xref: /illumos-gate/usr/src/tools/elfextract/elfextract.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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