diff options
Diffstat (limited to 'binutils')
-rw-r--r-- | binutils/ChangeLog | 10 | ||||
-rw-r--r-- | binutils/readelf.c | 132 |
2 files changed, 140 insertions, 2 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 55d9ec0..47c8d0b 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,13 @@ +2004-04-26 H.J. Lu <hongjiu.lu@intel.com> + + * readelf.c (do_section_groups): New. + (options): Add --section-groups/-g. + (usage): Mention --section-groups/-g. + (parse_args): Support --section-groups/-g. + (get_group_flags): New. + (process_section_groups): New. + (process_object): Call process_section_groups. + 2004-04-24 Alan Modra <amodra@bigpond.net.au> * objdump.c (disassemble_section): Don't disassemble sections diff --git a/binutils/readelf.c b/binutils/readelf.c index 4db0a10..29e1c8b 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -140,6 +140,7 @@ int do_dynamic; int do_syms; int do_reloc; int do_sections; +int do_section_groups; int do_segments; int do_unwind; int do_using_dynamic; @@ -2393,6 +2394,7 @@ struct option options[] = {"segments", no_argument, 0, 'l'}, {"sections", no_argument, 0, 'S'}, {"section-headers", no_argument, 0, 'S'}, + {"section-groups", no_argument, 0, 'g'}, {"symbols", no_argument, 0, 's'}, {"syms", no_argument, 0, 's'}, {"relocs", no_argument, 0, 'r'}, @@ -2426,6 +2428,7 @@ usage (void) --segments An alias for --program-headers\n\ -S --section-headers Display the sections' header\n\ --sections An alias for --section-headers\n\ + -g --section-groups Display the section groups\n\ -e --headers Equivalent to: -h -l -S\n\ -s --syms Display the symbol table\n\ --symbols An alias for --syms\n\ @@ -2493,7 +2496,7 @@ parse_args (int argc, char **argv) usage (); while ((c = getopt_long - (argc, argv, "ersuahnldSDAIw::x:i:vVWH", options, NULL)) != EOF) + (argc, argv, "ersuahnldSDAIgw::x:i:vVWH", options, NULL)) != EOF) { char *cp; int section; @@ -2514,12 +2517,16 @@ parse_args (int argc, char **argv) do_dynamic++; do_header++; do_sections++; + do_section_groups++; do_segments++; do_version++; do_histogram++; do_arch++; do_notes++; break; + case 'g': + do_section_groups++; + break; case 'e': do_header++; do_sections++; @@ -2746,7 +2753,8 @@ parse_args (int argc, char **argv) if (!do_dynamic && !do_syms && !do_reloc && !do_unwind && !do_sections && !do_segments && !do_header && !do_dump && !do_version - && !do_histogram && !do_debugging && !do_arch && !do_notes) + && !do_histogram && !do_debugging && !do_arch && !do_notes + && !do_section_groups) usage (); else if (argc < 3) { @@ -3703,6 +3711,124 @@ process_section_headers (FILE *file) return 1; } +static const char * +get_group_flags (unsigned int flags) +{ + static char buff[32]; + switch (flags) + { + case GRP_COMDAT: + return "COMDAT"; + + default: + sprintf (buff, _("[<unknown>: 0x%x]"), flags); + break; + } + return buff; +} + +static int +process_section_groups (FILE *file) +{ + Elf_Internal_Shdr *section; + unsigned int i; + + if (!do_section_groups) + return 1; + + if (elf_header.e_shnum == 0) + { + if (do_section_groups) + printf (_("\nThere are no section groups in this file.\n")); + + return 1; + } + + if (section_headers == NULL) + { + error (_("Section headers are not available!\n")); + abort (); + } + + /* Scan the sections for the group section. */ + for (i = 0, section = section_headers; + i < elf_header.e_shnum; + i++, section++) + { + if (section->sh_type == SHT_GROUP) + { + char *name = SECTION_NAME (section); + char *group_name, *strtab, *start, *indices; + unsigned int entry, j, size; + Elf_Internal_Sym *sym; + Elf_Internal_Shdr *symtab_sec, *strtab_sec, *sec; + Elf_Internal_Sym *symtab; + + /* Get the symbol table. */ + symtab_sec = SECTION_HEADER (section->sh_link); + if (symtab_sec->sh_type != SHT_SYMTAB) + { + error (_("Bad sh_link in group section `%s'\n"), name); + continue; + } + symtab = GET_ELF_SYMBOLS (file, symtab_sec); + + sym = symtab + section->sh_info; + + if (ELF_ST_TYPE (sym->st_info) == STT_SECTION) + { + bfd_vma sec_index = SECTION_HEADER_INDEX (sym->st_shndx); + if (sec_index == 0) + { + error (_("Bad sh_info in group section `%s'\n"), name); + continue; + } + + group_name = SECTION_NAME (section_headers + sec_index); + strtab = NULL; + } + else + { + /* Get the string table. */ + strtab_sec = SECTION_HEADER (symtab_sec->sh_link); + strtab = get_data (NULL, file, strtab_sec->sh_offset, + strtab_sec->sh_size, + _("string table")); + + group_name = strtab + sym->st_name; + } + + start = get_data (NULL, file, section->sh_offset, + section->sh_size, _("section data")); + + indices = start; + size = (section->sh_size / section->sh_entsize) - 1; + entry = byte_get (indices, 4); + indices += 4; + printf ("\n%s group section `%s' [%s] contains %u sections:\n", + get_group_flags (entry), name, group_name, size); + + printf (_(" [Index] Name\n")); + for (j = 0; j < size; j++) + { + entry = byte_get (indices, 4); + indices += 4; + + sec = SECTION_HEADER (entry); + printf (" [%5u] %s\n", + entry, SECTION_NAME (sec)); + } + + if (strtab) + free (strtab); + if (start) + free (start); + } + } + + return 1; +} + struct { const char *name; @@ -10331,6 +10457,8 @@ process_object (char *file_name, FILE *file) process_section_contents (file); + process_section_groups (file); + process_corefile_contents (file); process_gnu_liblist (file); |