diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 55d9ec08c9..47c8d0b3b4 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,13 @@ +2004-04-26 H.J. Lu + + * 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 * objdump.c (disassemble_section): Don't disassemble sections diff --git a/binutils/readelf.c b/binutils/readelf.c index 4db0a10f4d..29e1c8bc5b 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, _("[: 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); diff --git a/gas/ChangeLog b/gas/ChangeLog index 7a4f663570..08a47509a0 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,8 @@ +2004-04-26 H.J. Lu + + * config/obj-elf.c (obj_elf_change_section): Check if the old + group name is NULL before comparison. + 2004-04-23 Chris Demetriou * config/tc-mips.h (mips_dwarf2_addr_size): Prototype. diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index 14d48f2ee7..e5f3ce3e01 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -645,7 +645,8 @@ obj_elf_change_section (const char *name, if ((flags & SEC_MERGE) && old_sec->entsize != (unsigned) entsize) as_warn (_("ignoring changed section entity size for %s"), name); if ((attr & SHF_GROUP) != 0 - && strcmp (elf_group_name (old_sec), group_name) != 0) + && (elf_group_name (old_sec) == NULL + || strcmp (elf_group_name (old_sec), group_name) != 0)) as_warn (_("ignoring new section group for %s"), name); } diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 31e854d067..9ec1aff21f 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2004-04-26 H.J. Lu + + * gas/elf/elf.exp: Add group0a, group0b and group1 for section + group. + + * gas/elf/group0.s: New file. + * gas/elf/group0a.d: Likewise. + * gas/elf/group0b.d: Likewise. + * gas/elf/group1.e: Likewise. + * gas/elf/group1.s: Likewise. + 2004-04-23 Nick Clifton * gas/symver/symver1.d: Cope with extra symbols inserted by diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp index f4274822ac..e087fba0b4 100644 --- a/gas/testsuite/gas/elf/elf.exp +++ b/gas/testsuite/gas/elf/elf.exp @@ -48,6 +48,9 @@ if { ([istarget "*-*-elf*"] set target_machine -m32r } run_dump_test "ehopt0" + run_dump_test "group0a" + run_dump_test "group0b" + run_list_test "group1" "" "" "" run_dump_test "section0" run_dump_test "section1" run_list_test "section2" "$target_machine" "-al" "" diff --git a/gas/testsuite/gas/elf/group0.s b/gas/testsuite/gas/elf/group0.s new file mode 100644 index 0000000000..26bdda2bd1 --- /dev/null +++ b/gas/testsuite/gas/elf/group0.s @@ -0,0 +1,4 @@ + .section .foo,"axG",@progbits,.foo_group,comdat + .byte 1 + .section .bar,"aG",@progbits,.foo_group,comdat + .byte 1 diff --git a/gas/testsuite/gas/elf/group0a.d b/gas/testsuite/gas/elf/group0a.d new file mode 100644 index 0000000000..9b2b967bab --- /dev/null +++ b/gas/testsuite/gas/elf/group0a.d @@ -0,0 +1,9 @@ +#readelf: -SW +#name: group section +#source: group0.s + +#... +[ ]*\[.*\][ ]+\.foo[ ]+PROGBITS.*[ ]+AXG[ ]+.* +[ ]*\[.*\][ ]+\.bar[ ]+PROGBITS.*[ ]+AG[ ]+.* +[ ]*\[.*\][ ]+\.foo_group[ ]+GROUP.* +#pass diff --git a/gas/testsuite/gas/elf/group0b.d b/gas/testsuite/gas/elf/group0b.d new file mode 100644 index 0000000000..847a86b949 --- /dev/null +++ b/gas/testsuite/gas/elf/group0b.d @@ -0,0 +1,10 @@ +#readelf: -g +#name: group section +#source: group0.s + +#... +COMDAT group section `.foo_group' \[.foo_group\] contains 2 sections: +[ ]+\[Index\][ ]+Name +[ ]+\[.*\][ ]+.foo +[ ]+\[.*\][ ]+.bar +#pass diff --git a/gas/testsuite/gas/elf/group1.e b/gas/testsuite/gas/elf/group1.e new file mode 100644 index 0000000000..d4c40035e2 --- /dev/null +++ b/gas/testsuite/gas/elf/group1.e @@ -0,0 +1,7 @@ + +Symbol table '.symtab' contains 4 entries: + Num: Value[ ]* Size Type Bind Vis Ndx Name + 0: 0+0 0 NOTYPE LOCAL DEFAULT UND + 1: 0+0 0 SECTION LOCAL DEFAULT 1 + 2: 0+0 0 SECTION LOCAL DEFAULT 2 + 3: 0+0 0 SECTION LOCAL DEFAULT 3 diff --git a/gas/testsuite/gas/elf/group1.s b/gas/testsuite/gas/elf/group1.s new file mode 100644 index 0000000000..1645f0bf74 --- /dev/null +++ b/gas/testsuite/gas/elf/group1.s @@ -0,0 +1,2 @@ + .section .text,"axG",@progbits,.foo_group,comdat + .byte 1