/[gentoo-projects]/pax-utils/dumpelf.c
Gentoo

Contents of /pax-utils/dumpelf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.32 - (show annotations) (download) (as text)
Sun Nov 4 07:26:24 2012 UTC (20 months, 2 weeks ago) by vapier
Branch: MAIN
CVS Tags: HEAD
Changes since 1.31: +5 -5 lines
File MIME type: text/x-csrc
update copyright years

1 /*
2 * Copyright 2005-2012 Gentoo Foundation
3 * Distributed under the terms of the GNU General Public License v2
4 * $Header: /var/cvsroot/gentoo-projects/pax-utils/dumpelf.c,v 1.31 2011/10/13 04:48:44 vapier Exp $
5 *
6 * Copyright 2005-2012 Ned Ludd - <solar@gentoo.org>
7 * Copyright 2005-2012 Mike Frysinger - <vapier@gentoo.org>
8 */
9
10 static const char rcsid[] = "$Id: dumpelf.c,v 1.31 2011/10/13 04:48:44 vapier Exp $";
11 const char argv0[] = "dumpelf";
12
13 #include "paxinc.h"
14
15 /* prototypes */
16 static void dumpelf(const char *filename, long file_cnt);
17 static void dump_ehdr(elfobj *elf, void *ehdr);
18 static void dump_phdr(elfobj *elf, void *phdr, long phdr_cnt);
19 static void dump_shdr(elfobj *elf, void *shdr, long shdr_cnt, char *name);
20 static void dump_dyn(elfobj *elf, void *dyn, long dyn_cnt);
21 #if 0
22 static void dump_sym(elfobj *elf, void *sym);
23 static void dump_rel(elfobj *elf, void *rel);
24 static void dump_rela(elfobj *elf, void *rela);
25 #endif
26 static void usage(int status);
27 static void parseargs(int argc, char *argv[]);
28
29 /* variables to control behavior */
30 static char be_verbose = 0;
31
32 /* misc dynamic tag caches */
33 static void *phdr_dynamic_void = NULL;
34
35 /* dump all internal elf info */
36 static void dumpelf(const char *filename, long file_cnt)
37 {
38 elfobj *elf;
39 unsigned long i, b;
40
41 /* verify this is real ELF */
42 if ((elf = readelf(filename)) == NULL)
43 return;
44
45 printf("#include <elf.h>\n");
46
47 printf(
48 "\n"
49 "/*\n"
50 " * ELF dump of '%s'\n"
51 " * %li (0x%lX) bytes\n"
52 " */\n\n",
53 filename, (unsigned long)elf->len, (unsigned long)elf->len);
54
55 /* setup the struct to namespace this elf */
56 #define MAKE_STRUCT(B) \
57 if (elf->elf_class == ELFCLASS ## B) { \
58 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
59 b = B; \
60 printf( \
61 "Elf%1$i_Dyn dumpedelf_dyn_%2$li[];\n" \
62 "struct {\n" \
63 "\tElf%1$i_Ehdr ehdr;\n" \
64 "\tElf%1$i_Phdr phdrs[%3$li];\n" \
65 "\tElf%1$i_Shdr shdrs[%4$li];\n" \
66 "\tElf%1$i_Dyn *dyns;\n" \
67 "} dumpedelf_%2$li = {\n\n", \
68 B, file_cnt, \
69 (long)EGET(ehdr->e_phnum), \
70 (long)EGET(ehdr->e_shnum) \
71 ); \
72 }
73 MAKE_STRUCT(32)
74 MAKE_STRUCT(64)
75
76 /* dump the elf header */
77 dump_ehdr(elf, elf->ehdr);
78
79 /* dump the program headers */
80 printf("\n.phdrs = {\n");
81 if (elf->phdr) {
82 #define DUMP_PHDRS(B) \
83 if (elf->elf_class == ELFCLASS ## B) { \
84 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
85 Elf ## B ## _Phdr *phdr = PHDR ## B (elf->phdr); \
86 uint16_t phnum = EGET(ehdr->e_phnum); \
87 for (i = 0; i < phnum; ++i, ++phdr) \
88 dump_phdr(elf, phdr, i); \
89 }
90 DUMP_PHDRS(32)
91 DUMP_PHDRS(64)
92 } else {
93 printf(" /* no program headers ! */ ");
94 }
95 printf("},\n");
96
97 /* dump the section headers */
98 printf("\n.shdrs = {\n");
99 if (elf->shdr) {
100 #define DUMP_SHDRS(B) \
101 if (elf->elf_class == ELFCLASS ## B) { \
102 Elf ## B ## _Ehdr *ehdr = EHDR ## B (elf->ehdr); \
103 Elf ## B ## _Shdr *shdr = SHDR ## B (elf->shdr); \
104 uint16_t shstrndx = EGET(ehdr->e_shstrndx); \
105 Elf ## B ## _Off offset = EGET(shdr[shstrndx].sh_offset); \
106 uint16_t shnum = EGET(ehdr->e_shnum); \
107 for (i = 0; i < shnum; ++i, ++shdr) \
108 dump_shdr(elf, shdr, i, elf->vdata + offset + EGET(shdr->sh_name)); \
109 }
110 DUMP_SHDRS(32)
111 DUMP_SHDRS(64)
112 } else {
113 printf(" /* no section headers ! */ ");
114 }
115 printf("},\n");
116
117 /* finish the namespace struct and start the abitrary ones */
118 printf("\n.dyns = dumpedelf_dyn_%li,\n", file_cnt);
119 printf("};\n");
120
121 /* start the arbitrary structs */
122 printf("Elf%lu_Dyn dumpedelf_dyn_%li[] = {\n", b, file_cnt);
123 if (phdr_dynamic_void) {
124 #define DUMP_DYNS(B) \
125 if (elf->elf_class == ELFCLASS ## B) { \
126 Elf ## B ## _Phdr *phdr = phdr_dynamic_void; \
127 Elf ## B ## _Dyn *dyn = elf->vdata + EGET(phdr->p_offset); \
128 i = 0; \
129 do { \
130 dump_dyn(elf, dyn++, i++); \
131 } while (EGET(dyn->d_tag) != DT_NULL); \
132 }
133 DUMP_DYNS(32)
134 DUMP_DYNS(64)
135 } else {
136 printf(" /* no dynamic tags ! */ ");
137 }
138 printf("};\n");
139
140 /* get out of here */
141 unreadelf(elf);
142 }
143 static void dump_ehdr(elfobj *elf, void *ehdr_void)
144 {
145 #define DUMP_EHDR(B) \
146 if (elf->elf_class == ELFCLASS ## B) { \
147 Elf ## B ## _Ehdr *ehdr = EHDR ## B (ehdr_void); \
148 printf(".ehdr = {\n"); \
149 printf("\t.e_ident = { /* (EI_NIDENT bytes) */\n" \
150 "\t\t/* [%i] EI_MAG: */ 0x%X,'%c','%c','%c',\n" \
151 "\t\t/* [%i] EI_CLASS: */ %i , /* (%s) */\n" \
152 "\t\t/* [%i] EI_DATA: */ %i , /* (%s) */\n" \
153 "\t\t/* [%i] EI_VERSION: */ %i , /* (%s) */\n" \
154 "\t\t/* [%i] EI_OSABI: */ %i , /* (%s) */\n" \
155 "\t\t/* [%i] EI_ABIVERSION: */ %i ,\n" \
156 "\t\t/* [%i] EI_PAD: */ 0x%02X /* x %i bytes */\n" \
157 /* "\t\t/ [%i] EI_BRAND: / 0x%02X\n" */ \
158 "\t},\n", \
159 EI_MAG0, (unsigned int)ehdr->e_ident[EI_MAG0], ehdr->e_ident[EI_MAG1], ehdr->e_ident[EI_MAG2], ehdr->e_ident[EI_MAG3], \
160 EI_CLASS, (int)ehdr->e_ident[EI_CLASS], get_elfeitype(EI_CLASS, ehdr->e_ident[EI_CLASS]), \
161 EI_DATA, (int)ehdr->e_ident[EI_DATA], get_elfeitype(EI_DATA, ehdr->e_ident[EI_DATA]), \
162 EI_VERSION, (int)ehdr->e_ident[EI_VERSION], get_elfeitype(EI_VERSION, ehdr->e_ident[EI_VERSION]), \
163 EI_OSABI, (int)ehdr->e_ident[EI_OSABI], get_elfeitype(EI_OSABI, ehdr->e_ident[EI_OSABI]), \
164 EI_ABIVERSION, (int)ehdr->e_ident[EI_ABIVERSION], \
165 EI_PAD, (unsigned int)ehdr->e_ident[EI_PAD], EI_NIDENT - EI_PAD \
166 /* EI_BRAND, ehdr->e_ident[EI_BRAND] */ \
167 ); \
168 printf("\t.e_type = %-10i , /* (%s) */\n", (int)EGET(ehdr->e_type), get_elfetype(elf)); \
169 printf("\t.e_machine = %-10i , /* (%s) */\n", (int)EGET(ehdr->e_machine), get_elfemtype(elf)); \
170 printf("\t.e_version = %-10i ,\n", (int)EGET(ehdr->e_version)); \
171 printf("\t.e_entry = 0x%-8lX ,\n", (unsigned long)EGET(ehdr->e_entry)); \
172 printf("\t.e_phoff = %-10li , /* (bytes into file) */\n", (unsigned long)EGET(ehdr->e_phoff)); \
173 printf("\t.e_shoff = %-10li , /* (bytes into file) */\n", (unsigned long)EGET(ehdr->e_shoff)); \
174 printf("\t.e_flags = 0x%-8X ,\n", (unsigned int)EGET(ehdr->e_flags)); \
175 printf("\t.e_ehsize = %-10i , /* (bytes) */\n", (int)EGET(ehdr->e_ehsize)); \
176 printf("\t.e_phentsize = %-10i , /* (bytes) */\n", (int)EGET(ehdr->e_phentsize)); \
177 printf("\t.e_phnum = %-10i , /* (program headers) */\n", (int)EGET(ehdr->e_phnum)); \
178 printf("\t.e_shentsize = %-10i , /* (bytes) */\n", (int)EGET(ehdr->e_shentsize)); \
179 printf("\t.e_shnum = %-10i , /* (section headers) */\n", (int)EGET(ehdr->e_shnum)); \
180 printf("\t.e_shstrndx = %-10i\n", (int)EGET(ehdr->e_shstrndx)); \
181 printf("},\n"); \
182 }
183 DUMP_EHDR(32)
184 DUMP_EHDR(64)
185 }
186 static void dump_phdr(elfobj *elf, void *phdr_void, long phdr_cnt)
187 {
188 #define DUMP_PHDR(B) \
189 if (elf->elf_class == ELFCLASS ## B) { \
190 Elf ## B ## _Phdr *phdr = PHDR ## B (phdr_void); \
191 switch (EGET(phdr->p_type)) { \
192 case PT_DYNAMIC: phdr_dynamic_void = phdr_void; break; \
193 } \
194 printf("/* Program Header #%li 0x%lX */\n{\n", phdr_cnt, (unsigned long)phdr_void - (unsigned long)elf->data); \
195 printf("\t.p_type = %-10li , /* [%s] */\n", (long)EGET(phdr->p_type), get_elfptype(EGET(phdr->p_type))); \
196 printf("\t.p_offset = %-10li ,\n", (long)EGET(phdr->p_offset)); \
197 printf("\t.p_vaddr = 0x%-8lX ,\n", (unsigned long)EGET(phdr->p_vaddr)); \
198 printf("\t.p_paddr = 0x%-8lX ,\n", (unsigned long)EGET(phdr->p_paddr)); \
199 printf("\t.p_filesz = %-10li ,\n", (long)EGET(phdr->p_filesz)); \
200 printf("\t.p_memsz = %-10li ,\n", (long)EGET(phdr->p_memsz)); \
201 printf("\t.p_flags = %-10li ,\n", (long)EGET(phdr->p_flags)); \
202 printf("\t.p_align = %-10li\n", (long)EGET(phdr->p_align)); \
203 printf("},\n"); \
204 }
205 DUMP_PHDR(32)
206 DUMP_PHDR(64)
207 }
208 static void dump_shdr(elfobj *elf, void *shdr_void, long shdr_cnt, char *name)
209 {
210 unsigned long i;
211 #define DUMP_SHDR(B) \
212 if (elf->elf_class == ELFCLASS ## B) { \
213 Elf ## B ## _Shdr *shdr = SHDR ## B (shdr_void); \
214 uint32_t type = EGET(shdr->sh_type); \
215 uint ## B ## _t size = EGET(shdr->sh_size); \
216 printf("/* Section Header #%li '%s' 0x%lX */\n{\n", \
217 shdr_cnt, name, (unsigned long)shdr_void - (unsigned long)elf->data); \
218 printf("\t.sh_name = %-10i ,\n", (int)EGET(shdr->sh_name)); \
219 printf("\t.sh_type = %-10i , /* [%s] */\n", (int)EGET(shdr->sh_type), get_elfshttype(type)); \
220 printf("\t.sh_flags = %-10li ,\n", (long)EGET(shdr->sh_flags)); \
221 printf("\t.sh_addr = 0x%-8lX ,\n", (unsigned long)EGET(shdr->sh_addr)); \
222 printf("\t.sh_offset = %-10i , /* (bytes) */\n", (int)EGET(shdr->sh_offset)); \
223 printf("\t.sh_size = %-10li , /* (bytes) */\n", (long)EGET(shdr->sh_size)); \
224 printf("\t.sh_link = %-10i ,\n", (int)EGET(shdr->sh_link)); \
225 printf("\t.sh_info = %-10i ,\n", (int)EGET(shdr->sh_info)); \
226 printf("\t.sh_addralign = %-10li ,\n", (long)EGET(shdr->sh_addralign)); \
227 printf("\t.sh_entsize = %-10li\n", (long)EGET(shdr->sh_entsize)); \
228 if (size && be_verbose) { \
229 void *vdata = elf->vdata + EGET(shdr->sh_offset); \
230 unsigned char *data = vdata; \
231 switch (type) { \
232 case SHT_PROGBITS: { \
233 if (strcmp(name, ".interp") == 0) { \
234 printf("\n\t/* ELF interpreter: %s */\n", data); \
235 break; \
236 } \
237 if (strcmp(name, ".comment") != 0) \
238 break; \
239 } \
240 case SHT_STRTAB: { \
241 char b; \
242 printf("\n\t/%c section dump:\n", '*'); \
243 b = 1; \
244 if (type == SHT_PROGBITS) --data; \
245 for (i = 0; i < size; ++i) { \
246 ++data; \
247 if (*data) { \
248 if (b) printf("\t * "); \
249 printf("%c", *data); \
250 b = 0; \
251 } else if (!b) { \
252 printf("\n"); \
253 b = 1; \
254 } \
255 } \
256 printf("\t */\n"); \
257 break; \
258 } \
259 case SHT_DYNSYM: { \
260 Elf##B##_Sym *sym = vdata; \
261 printf("\n\t/%c section dump:\n", '*'); \
262 for (i = 0; i < EGET(shdr->sh_size) / EGET(shdr->sh_entsize); ++i) { \
263 printf("\t * Elf%i_Sym sym%li = {\n", B, (long)i); \
264 printf("\t * \t.st_name = %i,\n", (unsigned int)EGET(sym->st_name)); \
265 printf("\t * \t.st_value = 0x%lX,\n", (unsigned long)EGET(sym->st_value)); \
266 printf("\t * \t.st_size = %li, (bytes)\n", (unsigned long)EGET(sym->st_size)); \
267 printf("\t * \t.st_info = %i,\n", (unsigned int)EGET(sym->st_info)); \
268 printf("\t * \t.st_other = %i,\n", (unsigned int)EGET(sym->st_other)); \
269 printf("\t * \t.st_shndx = %li\n", (unsigned long)EGET(sym->st_shndx)); \
270 printf("\t * };\n"); \
271 ++sym; \
272 } \
273 printf("\t */\n"); \
274 break; \
275 } \
276 default: { \
277 if (be_verbose <= 1) \
278 break; \
279 printf("\n\t/%c section dump:\n", '*'); \
280 for (i = 0; i < size; ++i) { \
281 ++data; \
282 if (i % 20 == 0) printf("\t * "); \
283 printf("%.2X ", *data); /* this line can cause segfaults */ \
284 if (i % 20 == 19) printf("\n"); \
285 } \
286 if (i % 20) printf("\n"); \
287 printf("\t */\n"); \
288 } \
289 } \
290 } \
291 printf("},\n"); \
292 }
293 DUMP_SHDR(32)
294 DUMP_SHDR(64)
295 }
296 static void dump_dyn(elfobj *elf, void *dyn_void, long dyn_cnt)
297 {
298 #define DUMP_DYN(B) \
299 if (elf->elf_class == ELFCLASS ## B) { \
300 Elf ## B ## _Dyn *dyn = dyn_void; \
301 unsigned long tag = EGET(dyn->d_tag); \
302 printf("/* Dynamic tag #%li '%s' 0x%lX */\n{\n", \
303 dyn_cnt, get_elfdtype(tag), (unsigned long)dyn_void - (unsigned long)elf->data); \
304 printf("\t.d_tag = 0x%-8lX ,\n", tag); \
305 printf("\t.d_un = {\n"); \
306 printf("\t\t.d_val = 0x%-8lX ,\n", (unsigned long)EGET(dyn->d_un.d_val)); \
307 printf("\t\t.d_ptr = 0x%-8lX ,\n", (unsigned long)EGET(dyn->d_un.d_val)); \
308 printf("\t},\n"); \
309 printf("},\n"); \
310 }
311 DUMP_DYN(32)
312 DUMP_DYN(64)
313 }
314
315 /* usage / invocation handling functions */
316 #define PARSE_FLAGS "vhV"
317 #define a_argument required_argument
318 static struct option const long_opts[] = {
319 {"verbose", no_argument, NULL, 'v'},
320 {"help", no_argument, NULL, 'h'},
321 {"version", no_argument, NULL, 'V'},
322 {NULL, no_argument, NULL, 0x0}
323 };
324 static const char * const opts_help[] = {
325 "Be verbose (can be specified more than once)",
326 "Print this help and exit",
327 "Print version and exit",
328 NULL
329 };
330
331 /* display usage and exit */
332 static void usage(int status)
333 {
334 int i;
335 printf("* Dump internal ELF structure\n\n"
336 "Usage: %s <file1> [file2 fileN ...]\n\n", argv0);
337 printf("Options:\n");
338 for (i = 0; long_opts[i].name; ++i)
339 if (long_opts[i].has_arg == no_argument)
340 printf(" -%c, --%-13s* %s\n", long_opts[i].val,
341 long_opts[i].name, opts_help[i]);
342 else
343 printf(" -%c, --%-6s <arg> * %s\n", long_opts[i].val,
344 long_opts[i].name, opts_help[i]);
345 exit(status);
346 }
347
348 /* parse command line arguments and preform needed actions */
349 static void parseargs(int argc, char *argv[])
350 {
351 int flag;
352
353 opterr = 0;
354 while ((flag=getopt_long(argc, argv, PARSE_FLAGS, long_opts, NULL)) != -1) {
355 switch (flag) {
356
357 case 'V': /* version info */
358 printf("pax-utils-%s: %s compiled %s\n%s\n"
359 "%s written for Gentoo by <solar and vapier @ gentoo.org>\n",
360 VERSION, __FILE__, __DATE__, rcsid, argv0);
361 exit(EXIT_SUCCESS);
362 break;
363 case 'h': usage(EXIT_SUCCESS); break;
364
365 case 'v': be_verbose = (be_verbose % 20) + 1; break;
366
367 case ':':
368 err("Option missing parameter");
369 case '?':
370 err("Unknown option");
371 default:
372 err("Unhandled option '%c'", flag);
373 }
374 }
375
376 if (optind == argc)
377 err("Nothing to dump !?");
378
379 {
380 long file_cnt = 0;
381
382 while (optind < argc)
383 dumpelf(argv[optind++], file_cnt++);
384 }
385 }
386
387 int main(int argc, char *argv[])
388 {
389 if (argc < 2)
390 usage(EXIT_FAILURE);
391 parseargs(argc, argv);
392 return EXIT_SUCCESS;
393 }

  ViewVC Help
Powered by ViewVC 1.1.20