diff options
Diffstat (limited to 'src/readelf.c')
| -rw-r--r-- | src/readelf.c | 167 |
1 files changed, 104 insertions, 63 deletions
diff --git a/src/readelf.c b/src/readelf.c index 74730959..bb79e28b 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -87,8 +87,9 @@ static const struct argp_option options[] = N_("Display architecture specific information (if any)"), 0 }, { "hex-dump", 'x', "SECTION", 0, N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 }, - { "strings", 'p', NULL, 0, - N_("Print contents of sections marked as containing only strings"), 0 }, + { "strings", 'p', "SECTION", OPTION_ARG_OPTIONAL, + N_("Print string contents of sections"), 0 }, + { "string-dump", 'p', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 }, { NULL, 0, NULL, 0, N_("Output control:"), 0 }, @@ -173,6 +174,10 @@ static enum section_e static struct section_argument *dump_data_sections; static struct section_argument **dump_data_sections_tail = &dump_data_sections; +/* Select string dumping of sections. */ +static struct section_argument *string_sections; +static struct section_argument **string_sections_tail = &string_sections; + struct section_argument { struct section_argument *next; @@ -208,6 +213,7 @@ static void handle_hash (Ebl *ebl); static void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr); static void print_liblist (Ebl *ebl); static void dump_data (Ebl *ebl); +static void dump_strings (Ebl *ebl); static void print_strings (Ebl *ebl); @@ -326,10 +332,6 @@ parse_opt (int key, char *arg, print_symbol_table = true; any_control_option = true; break; - case 'p': - print_string_sections = true; - any_control_option = true; - break; case 'V': print_version_info = true; any_control_option = true; @@ -367,13 +369,23 @@ parse_opt (int key, char *arg, } any_control_option = true; break; + case 'p': + any_control_option = true; + if (arg == NULL) + { + print_string_sections = true; + break; + } + /* Fall through. */ case 'x': { struct section_argument *a = xmalloc (sizeof *a); a->arg = arg; a->next = NULL; - *dump_data_sections_tail = a; - dump_data_sections_tail = &a->next; + struct section_argument ***tailp + = key == 'x' ? &dump_data_sections_tail : &string_sections_tail; + **tailp = a; + *tailp = &a->next; } any_control_option = true; break; @@ -542,6 +554,8 @@ process_elf_file (Elf *elf, const char *prefix, const char *fname, print_liblist (ebl); if (dump_data_sections != NULL) dump_data (ebl); + if (string_sections != NULL) + dump_strings (ebl); if (print_debug_sections != 0) print_debug (ebl, ehdr); if (print_notes) @@ -5694,15 +5708,76 @@ hex_dump (const uint8_t *data, size_t len) } static void -dump_data (Ebl *ebl) +dump_data_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name) +{ + if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS) + printf (gettext ("\nSection [%Zu] '%s' has no data to dump.\n"), + elf_ndxscn (scn), name); + else + { + Elf_Data *data = elf_rawdata (scn, NULL); + if (data == NULL) + error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"), + elf_ndxscn (scn), name, elf_errmsg (-1)); + else + { + printf (gettext ("\nHex dump of section [%Zu] '%s', %" PRIu64 + " bytes at offset %#0" PRIx64 ":\n"), + elf_ndxscn (scn), name, + shdr->sh_size, shdr->sh_offset); + hex_dump (data->d_buf, data->d_size); + } + } +} + +static void +print_string_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name) +{ + if (shdr->sh_size == 0) + printf (gettext ("\nSection [%Zu] '%s' is empty.\n"), + elf_ndxscn (scn), name); + + Elf_Data *data = elf_rawdata (scn, NULL); + if (data == NULL) + error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"), + elf_ndxscn (scn), name, elf_errmsg (-1)); + else + { + printf (gettext ("\nString section [%Zu] '%s' contains %" PRIu64 + " bytes at offset %#0" PRIx64 ":\n"), + elf_ndxscn (scn), name, + shdr->sh_size, shdr->sh_offset); + + const char *start = data->d_buf; + const char *const limit = start + data->d_size; + do + { + const char *end = memchr (start, '\0', limit - start); + const size_t pos = start - (const char *) data->d_buf; + if (unlikely (end == NULL)) + { + printf (" [%6Zx]- %.*s\n", + pos, (int) (limit - start), start); + break; + } + printf (" [%6Zx] %s\n", pos, start); + start = end + 1; + } while (start < limit); + } +} + +static void +for_each_section_argument (Elf *elf, const struct section_argument *list, + void (*dump) (Elf_Scn *scn, const GElf_Shdr *shdr, + const char *name)) { /* Get the section header string table index. */ size_t shstrndx; - if (elf_getshstrndx (ebl->elf, &shstrndx) < 0) + if (elf_getshstrndx (elf, &shstrndx) < 0) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); - for (struct section_argument *a = dump_data_sections; a != NULL; a = a->next) + for (const struct section_argument *a = list; a != NULL; a = a->next) { Elf_Scn *scn; GElf_Shdr shdr_mem; @@ -5712,7 +5787,7 @@ dump_data (Ebl *ebl) unsigned long int shndx = strtoul (a->arg, &endp, 0); if (endp != a->arg && *endp == '\0') { - scn = elf_getscn (ebl->elf, shndx); + scn = elf_getscn (elf, shndx); if (scn == NULL) { error (0, 0, gettext ("\nsection [%lu] does not exist"), shndx); @@ -5722,17 +5797,17 @@ dump_data (Ebl *ebl) if (gelf_getshdr (scn, &shdr_mem) == NULL) error (EXIT_FAILURE, 0, gettext ("cannot get section header: %s"), elf_errmsg (-1)); - name = elf_strptr (ebl->elf, shstrndx, shdr_mem.sh_name); + name = elf_strptr (elf, shstrndx, shdr_mem.sh_name); } else { /* Need to look up the section by name. */ scn = NULL; - while ((scn = elf_nextscn (ebl->elf, scn)) != NULL) + while ((scn = elf_nextscn (elf, scn)) != NULL) { if (gelf_getshdr (scn, &shdr_mem) == NULL) continue; - name = elf_strptr (ebl->elf, shstrndx, shdr_mem.sh_name); + name = elf_strptr (elf, shstrndx, shdr_mem.sh_name); if (name == NULL) continue; if (!strcmp (name, a->arg)) @@ -5746,28 +5821,23 @@ dump_data (Ebl *ebl) } } - if (shdr_mem.sh_size == 0 || shdr_mem.sh_type == SHT_NOBITS) - printf (gettext ("\nSection [%Zu] '%s' has no data to dump.\n"), - elf_ndxscn (scn), name); - else - { - Elf_Data *data = elf_rawdata (scn, NULL); - if (data == NULL) - error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"), - elf_ndxscn (scn), name, elf_errmsg (-1)); - else - { - printf (gettext ("\nHex dump of section [%Zu] '%s', %" PRIu64 - " bytes at offset %#0" PRIx64 ":\n"), - elf_ndxscn (scn), name, - shdr_mem.sh_size, shdr_mem.sh_offset); - hex_dump (data->d_buf, data->d_size); - } - } + (*dump) (scn, &shdr_mem, name); } } static void +dump_data (Ebl *ebl) +{ + for_each_section_argument (ebl->elf, dump_data_sections, &dump_data_section); +} + +static void +dump_strings (Ebl *ebl) +{ + for_each_section_argument (ebl->elf, string_sections, &print_string_section); +} + +static void print_strings (Ebl *ebl) { /* Get the section header string table index. */ @@ -5793,35 +5863,6 @@ print_strings (Ebl *ebl) if (name == NULL) continue; - if (shdr_mem.sh_size == 0) - printf (gettext ("\nSection [%Zu] '%s' is empty.\n"), - elf_ndxscn (scn), name); - - Elf_Data *data = elf_rawdata (scn, NULL); - if (data == NULL) - error (0, 0, gettext ("cannot get data for section [%Zu] '%s': %s"), - elf_ndxscn (scn), name, elf_errmsg (-1)); - else - { - printf (gettext ("\nString section [%Zu] '%s' contains %" PRIu64 - " bytes at offset %#0" PRIx64 ":\n"), - elf_ndxscn (scn), name, - shdr_mem.sh_size, shdr_mem.sh_offset); - - const char *start = data->d_buf; - const char *const limit = start + data->d_size; - do - { - const char *end = memchr (start, '\0', limit - start); - const size_t pos = start - (const char *) data->d_buf; - if (unlikely (end == NULL)) - { - printf (" [%6Zx]- %.*s\n", pos, (int) (end - start), start); - break; - } - printf (" [%6Zx] %s\n", pos, start); - start = end + 1; - } while (start < limit); - } + print_string_section (scn, &shdr_mem, name); } } |
