xref: /illumos-gate/usr/src/tools/elfextract/elfextract.c (revision 34a0f871d192b33b865455a8812a3d34c1866315)
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 	uint_t len;
200 
201 	/*
202 	 * we expect one argument -- the elf file
203 	 */
204 	if (argc != 2) {
205 		(void) fprintf(stderr, "usage: %s <unix-elf-file>\n", argv[0]);
206 		exit(1);
207 	}
208 
209 	pname = strrchr(argv[0], '/');
210 	if (pname == NULL)
211 		pname = argv[0];
212 	else
213 		++pname;
214 
215 	fname = argv[1];
216 	fd = open(fname, O_RDONLY);
217 	if (fd < 0) {
218 		(void) fprintf(stderr, "%s: open(%s, O_RDONLY) failed, %s\n",
219 		    pname, fname, strerror(errno));
220 		exit(1);
221 	}
222 
223 	if (stat(fname, &stats) < 0) {
224 		(void) fprintf(stderr, "%s: stat(%s, ...) failed, %s\n",
225 		    pname, fname, strerror(errno));
226 		exit(1);
227 	}
228 
229 	len = stats.st_blocks * 512;
230 	len += 0xfff;
231 	len &= ~0xfff;
232 
233 #ifdef BUG_6491065_IS_FIXED
234 	/*
235 	 * mmap the file
236 	 */
237 	image = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
238 	if (image == MAP_FAILED) {
239 		(void) fprintf(stderr, "%s: mmap() of %s failed, %s\n",
240 			pname, fname, strerror(errno));
241 		exit(1);
242 	}
243 #else
244 	if ((image = malloc(stats.st_size)) == NULL) {
245 		(void) fprintf(stderr, "%s: out of memory\n", pname);
246 		exit(1);
247 	}
248 	if ((r = read(fd, image, stats.st_size)) != stats.st_size) {
249 		(void) fprintf(stderr, "%s: stat(%s, ...) failed, %s\n",
250 		    pname, fname, strerror(errno));
251 		exit(1);
252 	}
253 #endif
254 
255 	ident = ELFSEEK(0);
256 	if (ident[EI_MAG0] != ELFMAG0 || ident[EI_MAG1] != ELFMAG1 ||
257 	    ident[EI_MAG2] != ELFMAG2 || ident[EI_MAG3] != ELFMAG3) {
258 		(void) fprintf(stderr, "%s: not an ELF file!\n", pname);
259 		exit(1);
260 	}
261 
262 	if (ident[EI_CLASS] == ELFCLASS32) {
263 		hdr = ELFSEEK(0);
264 		extract32(hdr);
265 	} else if (ident[EI_CLASS] == ELFCLASS64) {
266 		hdr = ELFSEEK(0);
267 		extract64(hdr);
268 	} else {
269 		(void) fprintf(stderr, "%s: Wrong ELF class 0x%x\n", pname,
270 		    ident[EI_CLASS]);
271 		exit(1);
272 	}
273 	return (0);
274 }
275