| 1 | /* |
1 | /* |
| 2 | * Copyright 2005 Gentoo Foundation |
2 | * Copyright 2005 Gentoo Foundation |
| 3 | * Distributed under the terms of the GNU General Public License v2 |
3 | * Distributed under the terms of the GNU General Public License v2 |
| 4 | * $Header: /var/cvsroot/gentoo-projects/pax-utils/dumpelf.c,v 1.8 2005/06/03 03:25:38 vapier Exp $ |
4 | * $Header: /var/cvsroot/gentoo-projects/pax-utils/dumpelf.c,v 1.9 2005/06/03 04:04:09 vapier Exp $ |
| 5 | */ |
5 | */ |
| 6 | |
6 | |
| 7 | #include <stdio.h> |
7 | #include <stdio.h> |
| 8 | #include <stdlib.h> |
8 | #include <stdlib.h> |
| 9 | #include <sys/types.h> |
9 | #include <sys/types.h> |
| … | |
… | |
| 13 | #include <unistd.h> |
13 | #include <unistd.h> |
| 14 | #include <sys/stat.h> |
14 | #include <sys/stat.h> |
| 15 | #include <dirent.h> |
15 | #include <dirent.h> |
| 16 | #include <getopt.h> |
16 | #include <getopt.h> |
| 17 | #include <assert.h> |
17 | #include <assert.h> |
|
|
18 | #include <ctype.h> |
| 18 | |
19 | |
| 19 | #include "paxelf.h" |
20 | #include "paxelf.h" |
| 20 | |
21 | |
| 21 | static const char *rcsid = "$Id: dumpelf.c,v 1.8 2005/06/03 03:25:38 vapier Exp $"; |
22 | static const char *rcsid = "$Id: dumpelf.c,v 1.9 2005/06/03 04:04:09 vapier Exp $"; |
| 22 | #define argv0 "dumpelf" |
23 | #define argv0 "dumpelf" |
| 23 | |
24 | |
| 24 | /* prototypes */ |
25 | /* prototypes */ |
| 25 | static void dumpelf(const char *filename, long file_cnt); |
26 | static void dumpelf(const char *filename, long file_cnt); |
| 26 | static void dump_ehdr(elfobj *elf, void *ehdr); |
27 | static void dump_ehdr(elfobj *elf, void *ehdr); |
| … | |
… | |
| 36 | static void parseargs(int argc, char *argv[]); |
37 | static void parseargs(int argc, char *argv[]); |
| 37 | |
38 | |
| 38 | |
39 | |
| 39 | |
40 | |
| 40 | /* variables to control behavior */ |
41 | /* variables to control behavior */ |
| 41 | /* none yet ! */ |
42 | static char be_verbose = 0; |
| 42 | |
43 | |
| 43 | |
44 | |
| 44 | |
45 | |
| 45 | /* dump all internal elf info */ |
46 | /* dump all internal elf info */ |
| 46 | static void dumpelf(const char *filename, long file_cnt) |
47 | static void dumpelf(const char *filename, long file_cnt) |
| … | |
… | |
| 184 | DUMP_PHDR(32) |
185 | DUMP_PHDR(32) |
| 185 | DUMP_PHDR(64) |
186 | DUMP_PHDR(64) |
| 186 | } |
187 | } |
| 187 | static void dump_shdr(elfobj *elf, void *shdr_void, long shdr_cnt, char *name) |
188 | static void dump_shdr(elfobj *elf, void *shdr_void, long shdr_cnt, char *name) |
| 188 | { |
189 | { |
|
|
190 | unsigned long i; |
| 189 | #define DUMP_SHDR(B) \ |
191 | #define DUMP_SHDR(B) \ |
| 190 | if (elf->elf_class == ELFCLASS ## B) { \ |
192 | if (elf->elf_class == ELFCLASS ## B) { \ |
| 191 | Elf ## B ## _Shdr *shdr = SHDR ## B (shdr_void); \ |
193 | Elf ## B ## _Shdr *shdr = SHDR ## B (shdr_void); \ |
|
|
194 | uint32_t type = EGET(shdr->sh_type); \ |
|
|
195 | uint ## B ## _t size = EGET(shdr->sh_size); \ |
| 192 | printf("/* Section Header #%li '%s' 0x%lX */\n{\n", \ |
196 | printf("/* Section Header #%li '%s' 0x%lX */\n{\n", \ |
| 193 | shdr_cnt, name, (unsigned long)shdr_void - (unsigned long)elf->data); \ |
197 | shdr_cnt, name, (unsigned long)shdr_void - (unsigned long)elf->data); \ |
| 194 | printf("\t.sh_name = %-10i ,\n", (int)EGET(shdr->sh_name)); \ |
198 | printf("\t.sh_name = %-10i ,\n", (int)EGET(shdr->sh_name)); \ |
| 195 | printf("\t.sh_type = %-10i ,\n", (int)EGET(shdr->sh_type)); \ |
199 | printf("\t.sh_type = %-10i , /* [%s] */\n", (int)EGET(shdr->sh_type), get_elfshttype(type)); \ |
| 196 | printf("\t.sh_flags = %-10li ,\n", (long)EGET(shdr->sh_flags)); \ |
200 | printf("\t.sh_flags = %-10li ,\n", (long)EGET(shdr->sh_flags)); \ |
| 197 | printf("\t.sh_addr = 0x%-8lX ,\n", (unsigned long)EGET(shdr->sh_addr)); \ |
201 | printf("\t.sh_addr = 0x%-8lX ,\n", (unsigned long)EGET(shdr->sh_addr)); \ |
| 198 | printf("\t.sh_offset = %-10i , /* (bytes) */\n", (int)EGET(shdr->sh_offset)); \ |
202 | printf("\t.sh_offset = %-10i , /* (bytes) */\n", (int)EGET(shdr->sh_offset)); \ |
| 199 | printf("\t.sh_size = %-10li , /* (bytes) */\n", (long)EGET(shdr->sh_size)); \ |
203 | printf("\t.sh_size = %-10li , /* (bytes) */\n", (long)EGET(shdr->sh_size)); \ |
| 200 | printf("\t.sh_link = %-10i ,\n", (int)EGET(shdr->sh_link)); \ |
204 | printf("\t.sh_link = %-10i ,\n", (int)EGET(shdr->sh_link)); \ |
| 201 | printf("\t.sh_info = %-10i ,\n", (int)EGET(shdr->sh_info)); \ |
205 | printf("\t.sh_info = %-10i ,\n", (int)EGET(shdr->sh_info)); \ |
| 202 | printf("\t.sh_addralign = %-10li ,\n", (long)EGET(shdr->sh_addralign)); \ |
206 | printf("\t.sh_addralign = %-10li ,\n", (long)EGET(shdr->sh_addralign)); \ |
| 203 | printf("\t.sh_entsize = %-10li\n", (long)EGET(shdr->sh_entsize)); \ |
207 | printf("\t.sh_entsize = %-10li\n", (long)EGET(shdr->sh_entsize)); \ |
|
|
208 | if (size && \ |
|
|
209 | ((be_verbose && type == SHT_STRTAB) || \ |
|
|
210 | (be_verbose > 1))) { \ |
|
|
211 | unsigned char *data = (unsigned char*)(elf->data + EGET(shdr->sh_offset)); \ |
|
|
212 | char bool; \ |
|
|
213 | printf("\n\t/* section dump:\n"); \ |
|
|
214 | if (type == SHT_STRTAB) { \ |
|
|
215 | bool = 1; \ |
|
|
216 | for (i = 0; i < size; ++i) { \ |
|
|
217 | ++data; \ |
|
|
218 | if (*data) { \ |
|
|
219 | if (bool) printf("\t * "); \ |
|
|
220 | printf("%c", *data); \ |
|
|
221 | bool = 0; \ |
|
|
222 | } else if (!bool) { \ |
|
|
223 | printf("\n"); \ |
|
|
224 | bool = 1; \ |
|
|
225 | } \ |
|
|
226 | } \ |
|
|
227 | } else { \ |
|
|
228 | for (i = 0; i < size; ++i) { \ |
|
|
229 | ++data; \ |
|
|
230 | if (i % 20 == 0) printf("\t * "); \ |
|
|
231 | printf("%.2X ", *data); \ |
|
|
232 | if (i % 20 == 19) printf("\n"); \ |
|
|
233 | } \ |
|
|
234 | if (i % 20) printf("\n"); \ |
|
|
235 | } \ |
|
|
236 | printf("\t */\n"); \ |
|
|
237 | } \ |
| 204 | printf("}"); \ |
238 | printf("}"); \ |
| 205 | } |
239 | } |
| 206 | DUMP_SHDR(32) |
240 | DUMP_SHDR(32) |
| 207 | DUMP_SHDR(64) |
241 | DUMP_SHDR(64) |
| 208 | } |
242 | } |
| 209 | |
243 | |
| 210 | |
244 | |
| 211 | |
245 | |
| 212 | /* usage / invocation handling functions */ |
246 | /* usage / invocation handling functions */ |
| 213 | #define PARSE_FLAGS "hV" |
247 | #define PARSE_FLAGS "vhV" |
| 214 | #define a_argument required_argument |
248 | #define a_argument required_argument |
| 215 | static struct option const long_opts[] = { |
249 | static struct option const long_opts[] = { |
|
|
250 | {"verbose", no_argument, NULL, 'v'}, |
| 216 | {"help", no_argument, NULL, 'h'}, |
251 | {"help", no_argument, NULL, 'h'}, |
| 217 | {"version", no_argument, NULL, 'V'}, |
252 | {"version", no_argument, NULL, 'V'}, |
| 218 | {NULL, no_argument, NULL, 0x0} |
253 | {NULL, no_argument, NULL, 0x0} |
| 219 | }; |
254 | }; |
| 220 | static char *opts_help[] = { |
255 | static char *opts_help[] = { |
|
|
256 | "Be verbose (can be specified more than once)", |
| 221 | "Print this help and exit", |
257 | "Print this help and exit", |
| 222 | "Print version and exit", |
258 | "Print version and exit", |
| 223 | NULL |
259 | NULL |
| 224 | }; |
260 | }; |
| 225 | |
261 | |
| … | |
… | |
| 255 | __FILE__, __DATE__, rcsid, argv0); |
291 | __FILE__, __DATE__, rcsid, argv0); |
| 256 | exit(EXIT_SUCCESS); |
292 | exit(EXIT_SUCCESS); |
| 257 | break; |
293 | break; |
| 258 | case 'h': usage(EXIT_SUCCESS); break; |
294 | case 'h': usage(EXIT_SUCCESS); break; |
| 259 | |
295 | |
|
|
296 | case 'v': be_verbose = (be_verbose % 20) + 1; break; |
|
|
297 | |
| 260 | case ':': |
298 | case ':': |
| 261 | warn("Option missing parameter"); |
299 | err("Option missing parameter"); |
| 262 | usage(EXIT_FAILURE); |
|
|
| 263 | break; |
|
|
| 264 | case '?': |
300 | case '?': |
| 265 | warn("Unknown option"); |
301 | err("Unknown option"); |
| 266 | usage(EXIT_FAILURE); |
|
|
| 267 | break; |
|
|
| 268 | default: |
302 | default: |
| 269 | err("Unhandled option '%c'", flag); |
303 | err("Unhandled option '%c'", flag); |
| 270 | break; |
|
|
| 271 | } |
304 | } |
| 272 | } |
305 | } |
| 273 | |
306 | |
| 274 | if (optind == argc) |
307 | if (optind == argc) |
| 275 | err("Nothing to dump !?"); |
308 | err("Nothing to dump !?"); |