Home | History | Annotate | Download | only in elfextract
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28 
     29 #include <stdlib.h>
     30 #include <fcntl.h>
     31 #include <strings.h>
     32 #include <stdio.h>
     33 #include <errno.h>
     34 #include <sys/types.h>
     35 #include <sys/inttypes.h>
     36 #include <sys/elf.h>
     37 #include <sys/elf_notes.h>
     38 #include <sys/mman.h>
     39 #include <sys/stat.h>
     40 #include <sys/statvfs.h>
     41 
     42 static char *pname;
     43 static char *fname;
     44 static char *image;	/* pointer to the ELF file in memory */
     45 
     46 #define	ELFSEEK(offset) ((void *)(image + offset))
     47 
     48 /*
     49  * Extract the PT_LOAD bits and format them into a .s
     50  */
     51 static void
     52 extract32(Elf32_Ehdr *eh)
     53 {
     54 	Elf32_Phdr *phdr;
     55 	caddr_t allphdrs;
     56 	int i;
     57 	int c;
     58 	unsigned char *bytes;
     59 	uint_t cnt = 10;
     60 
     61 	allphdrs = NULL;
     62 
     63 	if (eh->e_type != ET_EXEC) {
     64 		(void) fprintf(stderr, "%s: not ET_EXEC, e_type = 0x%x\n",
     65 		    pname, eh->e_type);
     66 		exit(1);
     67 	}
     68 	if (eh->e_phnum == 0 || eh->e_phoff == 0) {
     69 		(void) fprintf(stderr, "%s: no program headers\n", pname);
     70 		exit(1);
     71 	}
     72 
     73 	/*
     74 	 * Get the program headers.
     75 	 */
     76 	allphdrs = ELFSEEK(eh->e_phoff);
     77 	if (allphdrs == NULL) {
     78 		(void) fprintf(stderr, "%s: Failed to get %d program hdrs\n",
     79 		    pname, eh->e_phnum);
     80 		exit(1);
     81 	}
     82 
     83 	/*
     84 	 * Find the PT_LOAD section
     85 	 */
     86 	for (i = 0; i < eh->e_phnum; i++) {
     87 		/*LINTED [ELF program header alignment]*/
     88 		phdr = (Elf32_Phdr *)(allphdrs + eh->e_phentsize * i);
     89 
     90 		if (phdr->p_type != PT_LOAD)
     91 			continue;
     92 
     93 		if (phdr->p_memsz == 0)
     94 			continue;
     95 
     96 		bytes = ELFSEEK(phdr->p_offset);
     97 		for (c = 0; c < phdr->p_filesz; ++c) {
     98 			if (c % cnt == 0)
     99 				(void) printf("\n	.byte	");
    100 			else
    101 				(void) printf(",");
    102 			(void) printf("0x%x", bytes[c]);
    103 		}
    104 		for (; c < phdr->p_memsz; ++c) {
    105 			if (c % cnt == 0) {
    106 				(void) printf("\n	.byte	");
    107 				cnt = 20;
    108 			} else {
    109 				(void) printf(", ");
    110 			}
    111 			(void) printf("0");
    112 		}
    113 		(void) printf("\n");
    114 		return;
    115 	}
    116 
    117 	(void) fprintf(stderr, "%s: Failed finding PT_LOAD section\n", pname);
    118 	exit(1);
    119 }
    120 
    121 static void
    122 extract64(Elf64_Ehdr *eh)
    123 {
    124 	Elf64_Phdr *phdr;
    125 	caddr_t allphdrs;
    126 	int i;
    127 	int c;
    128 	unsigned char *bytes;
    129 	uint_t cnt = 10;
    130 
    131 	allphdrs = NULL;
    132 
    133 	if (eh->e_type != ET_EXEC) {
    134 		(void) fprintf(stderr, "%s: not ET_EXEC, e_type = 0x%x\n",
    135 		    pname, eh->e_type);
    136 		exit(1);
    137 	}
    138 	if (eh->e_phnum == 0 || eh->e_phoff == 0) {
    139 		(void) fprintf(stderr, "%s: no program headers\n", pname);
    140 		exit(1);
    141 	}
    142 
    143 	/*
    144 	 * Get the program headers.
    145 	 */
    146 	allphdrs = ELFSEEK(eh->e_phoff);
    147 	if (allphdrs == NULL) {
    148 		(void) fprintf(stderr, "%s: Failed to get %d program hdrs\n",
    149 		    pname, eh->e_phnum);
    150 		exit(1);
    151 	}
    152 
    153 	/*
    154 	 * Find the PT_LOAD section
    155 	 */
    156 	for (i = 0; i < eh->e_phnum; i++) {
    157 		/*LINTED [ELF program header alignment]*/
    158 		phdr = (Elf64_Phdr *)(allphdrs + eh->e_phentsize * i);
    159 
    160 		if (phdr->p_type != PT_LOAD)
    161 			continue;
    162 
    163 		if (phdr->p_memsz == 0)
    164 			continue;
    165 
    166 		bytes = ELFSEEK(phdr->p_offset);
    167 		for (c = 0; c < phdr->p_filesz; ++c) {
    168 			if (c % cnt == 0)
    169 				(void) printf("\n	.byte	");
    170 			else
    171 				(void) printf(",");
    172 			(void) printf("0x%x", bytes[c]);
    173 		}
    174 		for (; c < phdr->p_memsz; ++c) {
    175 			if (c % cnt == 0) {
    176 				(void) printf("\n	.byte	");
    177 				cnt = 20;
    178 			} else {
    179 				(void) printf(", ");
    180 			}
    181 			(void) printf("0");
    182 		}
    183 		(void) printf("\n");
    184 		return;
    185 	}
    186 
    187 	(void) fprintf(stderr, "%s: Failed finding PT_LOAD section\n", pname);
    188 	exit(1);
    189 }
    190 
    191 int
    192 main(int argc, char **argv)
    193 {
    194 	int fd;
    195 	uchar_t *ident;
    196 	void *hdr = NULL;
    197 	struct stat stats;
    198 	ssize_t r;
    199 	size_t pgsz;
    200 	uint_t len;
    201 
    202 	/*
    203 	 * we expect one argument -- the elf file
    204 	 */
    205 	if (argc != 2) {
    206 		(void) fprintf(stderr, "usage: %s <unix-elf-file>\n", argv[0]);
    207 		exit(1);
    208 	}
    209 
    210 	pname = strrchr(argv[0], '/');
    211 	if (pname == NULL)
    212 		pname = argv[0];
    213 	else
    214 		++pname;
    215 
    216 	fname = argv[1];
    217 	fd = open(fname, O_RDONLY);
    218 	if (fd < 0) {
    219 		(void) fprintf(stderr, "%s: open(%s, O_RDONLY) failed, %s\n",
    220 		    pname, fname, strerror(errno));
    221 		exit(1);
    222 	}
    223 
    224 	if (stat(fname, &stats) < 0) {
    225 		(void) fprintf(stderr, "%s: stat(%s, ...) failed, %s\n",
    226 		    pname, fname, strerror(errno));
    227 		exit(1);
    228 	}
    229 
    230 	pgsz = getpagesize();
    231 	len = (stats.st_size + (pgsz - 1)) & (~(pgsz - 1));
    232 
    233 	/*
    234 	 * mmap the file
    235 	 */
    236 	image = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
    237 	if (image == MAP_FAILED) {
    238 		(void) fprintf(stderr, "%s: mmap() of %s failed, %s\n",
    239 		    pname, fname, strerror(errno));
    240 		exit(1);
    241 	}
    242 
    243 	ident = ELFSEEK(0);
    244 	if (ident[EI_MAG0] != ELFMAG0 || ident[EI_MAG1] != ELFMAG1 ||
    245 	    ident[EI_MAG2] != ELFMAG2 || ident[EI_MAG3] != ELFMAG3) {
    246 		(void) fprintf(stderr, "%s: not an ELF file!\n", pname);
    247 		exit(1);
    248 	}
    249 
    250 	if (ident[EI_CLASS] == ELFCLASS32) {
    251 		hdr = ELFSEEK(0);
    252 		extract32(hdr);
    253 	} else if (ident[EI_CLASS] == ELFCLASS64) {
    254 		hdr = ELFSEEK(0);
    255 		extract64(hdr);
    256 	} else {
    257 		(void) fprintf(stderr, "%s: Wrong ELF class 0x%x\n", pname,
    258 		    ident[EI_CLASS]);
    259 		exit(1);
    260 	}
    261 	return (0);
    262 }
    263