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

Contents of /pax-utils/dumpelf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.29 - (hide annotations) (download) (as text)
Wed Dec 8 01:24:01 2010 UTC (3 years, 7 months ago) by vapier
Branch: MAIN
Changes since 1.28: +3 -3 lines
File MIME type: text/x-csrc
constify help string array

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

  ViewVC Help
Powered by ViewVC 1.1.20