From: H.J. Lu Date: Sun, 11 Jan 2026 03:43:40 +0000 (+0800) Subject: elf: Handle the section flag 'o' linked to special sections X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2b17961bfb8b2b0d9701c9c0796a5f5749337fc7;p=thirdparty%2Fbinutils-gdb.git elf: Handle the section flag 'o' linked to special sections Call _bfd_elf_section_from_bfd_section to get the sh_link value from the section flag 'o' directive, which may point to special sections, like SHN_ABS or SHN_COMM. Update readelf to print the special section names in the sh_link field and replace "internal->sh_link > num" with "internal->sh_link >= num". bfd/ PR gas/33744 * elf.c (assign_section_numbers): Call _bfd_elf_section_from_bfd_section to get the sh_link value. binutils/ PR gas/33744 * readelf.c (special_defined_section_index): New. (get_32bit_section_headers): Don't warn special section indexes in the sh_link field. (get_64bit_section_headers): Likewise. (process_section_headers): Print special defined section names. gas/ PR gas/33744 * testsuite/gas/elf/elf.exp: Run PR gas/33744 tests. * testsuite/gas/elf/sh-link-abs-1.d: New file. * testsuite/gas/elf/sh-link-abs-2.d: Likewise. * testsuite/gas/elf/sh-link-abs-3-32.d: Likewise. * testsuite/gas/elf/sh-link-abs-3-64.d: Likewise. * testsuite/gas/elf/sh-link-abs-4-32.d: Likewise. * testsuite/gas/elf/sh-link-abs-4-64.d: Likewise. * testsuite/gas/elf/sh-link-abs.s: Likewise. * testsuite/gas/elf/sh-link-common-1.d: Likewise. * testsuite/gas/elf/sh-link-common-2.d: Likewise. * testsuite/gas/elf/sh-link-common-3-32.d: Likewise. * testsuite/gas/elf/sh-link-common-3-64.d: Likewise. * testsuite/gas/elf/sh-link-common-4-32.d: Likewise. * testsuite/gas/elf/sh-link-common-4-64.d: Likewise. * testsuite/gas/elf/sh-link-common.s: Likewise. * testsuite/gas/elf/sh-link-large-common-1.d: Likewise. * testsuite/gas/elf/sh-link-large-common-2.d: Likewise. * testsuite/gas/elf/sh-link-large-common-3.d: Likewise. * testsuite/gas/elf/sh-link-large-common-4.d: Likewise. * testsuite/gas/elf/sh-link-large-common.s: Likewise. Signed-off-by: H.J. Lu --- diff --git a/bfd/elf.c b/bfd/elf.c index 8b6dd3ce370..1177c3c3016 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -4333,7 +4333,8 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info) return false; } s = s->output_section; - d->this_hdr.sh_link = elf_section_data (s)->this_idx; + d->this_hdr.sh_link + = _bfd_elf_section_from_bfd_section (abfd, s); } } diff --git a/binutils/readelf.c b/binutils/readelf.c index d26e2bfa7b9..5b7fc0dc1de 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -1010,6 +1010,50 @@ is_ia64_vms (Filedata * filedata) && filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_OPENVMS; } +/* Return true if NDX is a special defined section index. */ + +static bool +special_defined_section_index (Filedata *filedata, size_t ndx) +{ + if (ndx == SHN_ABS || ndx == SHN_COMMON) + return true; + + if (filedata != NULL) + switch (filedata->file_header.e_machine) + { + case EM_MIPS: + if (ndx == SHN_MIPS_SCOMMON) + return true; + break; + + case EM_TI_C6000: + if (ndx == SHN_TIC6X_SCOMMON) + return true; + break; + + case EM_X86_64: + case EM_L1OM: + case EM_K1OM: + if (ndx == SHN_X86_64_LCOMMON) + return true; + break; + + case EM_IA_64: + if (filedata->file_header.e_ident[EI_OSABI] == ELFOSABI_HPUX + && ndx == SHN_IA_64_ANSI_COMMON) + return true; + + if (is_ia64_vms (filedata) && ndx == SHN_IA_64_VMS_SYMVEC) + return true; + break; + + default: + break; + } + + return false; +} + static const char * printable_section_name_from_index (Filedata * filedata, size_t ndx, @@ -7833,7 +7877,10 @@ get_32bit_section_headers (Filedata * filedata, bool probe) internal->sh_info = BYTE_GET (shdrs[i].sh_info); internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign); internal->sh_entsize = BYTE_GET (shdrs[i].sh_entsize); - if (!probe && internal->sh_link > num) + if (!probe + && internal->sh_link >= num + && !special_defined_section_index (filedata, + internal->sh_link)) warn (_("Section %u has an out of range sh_link value of %u\n"), i, internal->sh_link); if (!probe && internal->sh_flags & SHF_INFO_LINK && internal->sh_info > num) warn (_("Section %u has an out of range sh_info value of %u\n"), i, internal->sh_info); @@ -7905,7 +7952,10 @@ get_64bit_section_headers (Filedata * filedata, bool probe) internal->sh_info = BYTE_GET (shdrs[i].sh_info); internal->sh_offset = BYTE_GET (shdrs[i].sh_offset); internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign); - if (!probe && internal->sh_link > num) + if (!probe + && internal->sh_link >= num + && !special_defined_section_index (filedata, + internal->sh_link)) warn (_("Section %u has an out of range sh_link value of %u\n"), i, internal->sh_link); if (!probe && internal->sh_flags & SHF_INFO_LINK && internal->sh_info > num) warn (_("Section %u has an out of range sh_info value of %u\n"), i, internal->sh_info); @@ -9004,6 +9054,9 @@ process_section_headers (Filedata * filedata) printf (do_wide ? " %-15s " : " %-15.15s ", get_section_type_name (filedata, section->sh_type)); + bool special_defined_section + = special_defined_section_index (filedata, section->sh_link); + if (is_32bit_elf) { const char * link_too_big = NULL; @@ -9020,7 +9073,8 @@ process_section_headers (Filedata * filedata) else printf (" %3s ", get_elf_section_flags (filedata, section->sh_flags)); - if (section->sh_link >= filedata->file_header.e_shnum) + if (!special_defined_section + && section->sh_link >= filedata->file_header.e_shnum) { link_too_big = ""; /* The sh_link value is out of range. Normally this indicates @@ -9046,20 +9100,27 @@ process_section_headers (Filedata * filedata) } } + if (special_defined_section) + printf ("%2s ", + printable_section_name_from_index (filedata, + section->sh_link, + NULL)); + if (do_section_details) { - if (link_too_big != NULL && * link_too_big) - printf ("<%s> ", link_too_big); - else - printf ("%2u ", section->sh_link); - printf ("%3u %2lu\n", section->sh_info, - (unsigned long) section->sh_addralign); + if (!special_defined_section) + { + if (link_too_big != NULL && * link_too_big) + printf ("<%s> ", link_too_big); + else + printf ("%2u ", section->sh_link); + } } - else - printf ("%2u %3u %2lu\n", - section->sh_link, - section->sh_info, - (unsigned long) section->sh_addralign); + else if (!special_defined_section) + printf ("%2u ", section->sh_link); + + printf ("%3u %2lu\n", section->sh_info, + (unsigned long) section->sh_addralign); if (link_too_big && ! * link_too_big) warn (_("section %u: sh_link value of %u is larger than the number of sections\n"), @@ -9096,9 +9157,17 @@ process_section_headers (Filedata * filedata) if (do_section_details) fputs (" ", stdout); else - printf (" %3s ", get_elf_section_flags (filedata, section->sh_flags)); - - printf ("%2u %3u ", section->sh_link, section->sh_info); + printf (" %3s ", get_elf_section_flags (filedata, + section->sh_flags)); + + if (special_defined_section) + printf ("%2s ", + printable_section_name_from_index (filedata, + section->sh_link, + NULL)); + else + printf ("%2u ", section->sh_link); + printf ("%3u ", section->sh_info); if ((unsigned long) section->sh_addralign == section->sh_addralign) printf ("%2lu\n", (unsigned long) section->sh_addralign); @@ -9119,7 +9188,13 @@ process_section_headers (Filedata * filedata) printf (" "); print_vma (section->sh_offset, LONG_HEX); } - printf (" %u\n ", section->sh_link); + if (special_defined_section) + printf (" %s\n ", + printable_section_name_from_index (filedata, + section->sh_link, + NULL)); + else + printf (" %u\n ", section->sh_link); print_vma (section->sh_size, LONG_HEX); putchar (' '); print_vma (section->sh_entsize, LONG_HEX); @@ -9146,8 +9221,15 @@ process_section_headers (Filedata * filedata) printf (" %3s ", get_elf_section_flags (filedata, section->sh_flags)); - printf (" %2u %3u %lu\n", - section->sh_link, + if (special_defined_section) + printf (" %2s", + printable_section_name_from_index (filedata, + section->sh_link, + NULL)); + else + printf (" %2u", + section->sh_link); + printf (" %3u %lu\n", section->sh_info, (unsigned long) section->sh_addralign); } diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp index 35e06ce58b3..b4b4272ab9f 100644 --- a/gas/testsuite/gas/elf/elf.exp +++ b/gas/testsuite/gas/elf/elf.exp @@ -290,6 +290,25 @@ if { [is_elf_format] } then { run_dump_test "section28" run_dump_test "section29" run_dump_test "section30" $dump_opts + run_dump_test "sh-link-abs-1" + run_dump_test "sh-link-abs-2" + run_dump_test "sh-link-common-1" + run_dump_test "sh-link-common-2" + if [is_elf64 tmpdir/section30.o] { + run_dump_test "sh-link-abs-3-64" + run_dump_test "sh-link-abs-4-64" + run_dump_test "sh-link-common-3-64" + run_dump_test "sh-link-common-4-64" + run_dump_test "sh-link-large-common-1" + run_dump_test "sh-link-large-common-2" + run_dump_test "sh-link-large-common-3" + run_dump_test "sh-link-large-common-4" + } else { + run_dump_test "sh-link-abs-3-32" + run_dump_test "sh-link-abs-4-32" + run_dump_test "sh-link-common-3-32" + run_dump_test "sh-link-common-4-32" + } run_dump_test "sh-link-zero" run_dump_test "string" run_dump_test "size" diff --git a/gas/testsuite/gas/elf/sh-link-abs-1.d b/gas/testsuite/gas/elf/sh-link-abs-1.d new file mode 100644 index 00000000000..7010df0425f --- /dev/null +++ b/gas/testsuite/gas/elf/sh-link-abs-1.d @@ -0,0 +1,6 @@ +#source: sh-link-abs.s +#readelf: -SW + +#... + +\[ *[0-9]+\] +__patchable_function_entries +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+[248] +0+ +WAL +ABS +0 +1 +#pass diff --git a/gas/testsuite/gas/elf/sh-link-abs-2.d b/gas/testsuite/gas/elf/sh-link-abs-2.d new file mode 100644 index 00000000000..e3058a97288 --- /dev/null +++ b/gas/testsuite/gas/elf/sh-link-abs-2.d @@ -0,0 +1,8 @@ +#source: sh-link-abs.s +#readelf: -tW + +#... + +\[ *[0-9]+\] +__patchable_function_entries + +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+[248] +0+ +ABS +0 +1 + +\[0+83\]: WRITE, ALLOC, LINK ORDER +#pass diff --git a/gas/testsuite/gas/elf/sh-link-abs-3-32.d b/gas/testsuite/gas/elf/sh-link-abs-3-32.d new file mode 100644 index 00000000000..efac2f115fc --- /dev/null +++ b/gas/testsuite/gas/elf/sh-link-abs-3-32.d @@ -0,0 +1,6 @@ +#source: sh-link-abs.s +#readelf: -S + +#... + +\[ *[0-9]+\] +__patchable_\[\.\.\.\] +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+[248] +0+ +WAL +ABS +0 +1 +#pass diff --git a/gas/testsuite/gas/elf/sh-link-abs-3-64.d b/gas/testsuite/gas/elf/sh-link-abs-3-64.d new file mode 100644 index 00000000000..5724d27b2c9 --- /dev/null +++ b/gas/testsuite/gas/elf/sh-link-abs-3-64.d @@ -0,0 +1,7 @@ +#source: sh-link-abs.s +#readelf: -S + +#... + +\[ *[0-9]+\] +__patchable_\[\.\.\.\] +PROGBITS +[0-9a-f]+ +[0-9a-f]+ + +0+[248] +0+ +WAL +ABS +0 +1 +#pass diff --git a/gas/testsuite/gas/elf/sh-link-abs-4-32.d b/gas/testsuite/gas/elf/sh-link-abs-4-32.d new file mode 100644 index 00000000000..31387c4b7f2 --- /dev/null +++ b/gas/testsuite/gas/elf/sh-link-abs-4-32.d @@ -0,0 +1,8 @@ +#source: sh-link-abs.s +#readelf: -t + +#... + +\[ *[0-9]+\] +__patchable_function_entries + +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+[248] +0+ +ABS +0 +1 + +\[0+83\]: WRITE, ALLOC, LINK ORDER +#pass diff --git a/gas/testsuite/gas/elf/sh-link-abs-4-64.d b/gas/testsuite/gas/elf/sh-link-abs-4-64.d new file mode 100644 index 00000000000..d0ae74d01d5 --- /dev/null +++ b/gas/testsuite/gas/elf/sh-link-abs-4-64.d @@ -0,0 +1,9 @@ +#source: sh-link-abs.s +#readelf: -t + +#... + +\[ *[0-9]+\] +__patchable_function_entries + +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +ABS + +0+[248] +0+ +0 +1 + +\[0+83\]: WRITE, ALLOC, LINK ORDER +#pass diff --git a/gas/testsuite/gas/elf/sh-link-abs.s b/gas/testsuite/gas/elf/sh-link-abs.s new file mode 100644 index 00000000000..7094c770299 --- /dev/null +++ b/gas/testsuite/gas/elf/sh-link-abs.s @@ -0,0 +1,6 @@ + .section __patchable_function_entries,"awo",%progbits,foo + .dc.a .LPFE1 + .text +.LPFE1: + .byte 0 + .set foo,0x1000 diff --git a/gas/testsuite/gas/elf/sh-link-common-1.d b/gas/testsuite/gas/elf/sh-link-common-1.d new file mode 100644 index 00000000000..1e042efbc17 --- /dev/null +++ b/gas/testsuite/gas/elf/sh-link-common-1.d @@ -0,0 +1,6 @@ +#source: sh-link-common.s +#readelf: -SW + +#... + +\[ *[0-9]+\] +__patchable_function_entries +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+[248] +0+ +WAL +COM +0 +1 +#pass diff --git a/gas/testsuite/gas/elf/sh-link-common-2.d b/gas/testsuite/gas/elf/sh-link-common-2.d new file mode 100644 index 00000000000..aaed278bccf --- /dev/null +++ b/gas/testsuite/gas/elf/sh-link-common-2.d @@ -0,0 +1,8 @@ +#source: sh-link-common.s +#readelf: -tW + +#... + +\[ *[0-9]+\] +__patchable_function_entries + +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+[248] +0+ +COM +0 +1 + +\[0+83\]: WRITE, ALLOC, LINK ORDER +#pass diff --git a/gas/testsuite/gas/elf/sh-link-common-3-32.d b/gas/testsuite/gas/elf/sh-link-common-3-32.d new file mode 100644 index 00000000000..e2ca20f447f --- /dev/null +++ b/gas/testsuite/gas/elf/sh-link-common-3-32.d @@ -0,0 +1,6 @@ +#source: sh-link-common.s +#readelf: -S + +#... + +\[ *[0-9]+\] +__patchable_\[\.\.\.\] +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+[248] +0+ +WAL +COM +0 +1 +#pass diff --git a/gas/testsuite/gas/elf/sh-link-common-3-64.d b/gas/testsuite/gas/elf/sh-link-common-3-64.d new file mode 100644 index 00000000000..86a2b9f7f39 --- /dev/null +++ b/gas/testsuite/gas/elf/sh-link-common-3-64.d @@ -0,0 +1,7 @@ +#source: sh-link-common.s +#readelf: -S + +#... + +\[ *[0-9]+\] +__patchable_\[\.\.\.\] +PROGBITS +[0-9a-f]+ +[0-9a-f]+ + +0+[248] +0+ +WAL +COM +0 +1 +#pass diff --git a/gas/testsuite/gas/elf/sh-link-common-4-32.d b/gas/testsuite/gas/elf/sh-link-common-4-32.d new file mode 100644 index 00000000000..ad0bb1b8193 --- /dev/null +++ b/gas/testsuite/gas/elf/sh-link-common-4-32.d @@ -0,0 +1,8 @@ +#source: sh-link-common.s +#readelf: -t + +#... + +\[ *[0-9]+\] +__patchable_function_entries + +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+[248] +0+ +COM +0 +1 + +\[0+83\]: WRITE, ALLOC, LINK ORDER +#pass diff --git a/gas/testsuite/gas/elf/sh-link-common-4-64.d b/gas/testsuite/gas/elf/sh-link-common-4-64.d new file mode 100644 index 00000000000..4637b72883b --- /dev/null +++ b/gas/testsuite/gas/elf/sh-link-common-4-64.d @@ -0,0 +1,9 @@ +#source: sh-link-common.s +#readelf: -t + +#... + +\[ *[0-9]+\] +__patchable_function_entries + +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +COM + +0+[248] +0+ +0 +1 + +\[0+83\]: WRITE, ALLOC, LINK ORDER +#pass diff --git a/gas/testsuite/gas/elf/sh-link-common.s b/gas/testsuite/gas/elf/sh-link-common.s new file mode 100644 index 00000000000..84ec3e446df --- /dev/null +++ b/gas/testsuite/gas/elf/sh-link-common.s @@ -0,0 +1,6 @@ + .section __patchable_function_entries,"awo",%progbits,foo + .dc.a .LPFE1 + .text +.LPFE1: + .byte 0 + .comm foo,8 diff --git a/gas/testsuite/gas/elf/sh-link-large-common-1.d b/gas/testsuite/gas/elf/sh-link-large-common-1.d new file mode 100644 index 00000000000..acf238c8d1c --- /dev/null +++ b/gas/testsuite/gas/elf/sh-link-large-common-1.d @@ -0,0 +1,8 @@ +#source: sh-link-large-common.s +#readelf: -S +#target: x86_64-*-* + +#... + +\[ *[0-9]+\] +__patchable_\[\.\.\.\] +PROGBITS +[0-9a-f]+ +[0-9a-f]+ + +0+[248] +0+ +WAL +LARGE_COM +0 +1 +#pass diff --git a/gas/testsuite/gas/elf/sh-link-large-common-2.d b/gas/testsuite/gas/elf/sh-link-large-common-2.d new file mode 100644 index 00000000000..36d983761b7 --- /dev/null +++ b/gas/testsuite/gas/elf/sh-link-large-common-2.d @@ -0,0 +1,7 @@ +#source: sh-link-large-common.s +#readelf: -SW +#target: x86_64-*-* + +#... + +\[ *[0-9]+\] +__patchable_function_entries +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+[248] +0+ +WAL +LARGE_COM +0 +1 +#pass diff --git a/gas/testsuite/gas/elf/sh-link-large-common-3.d b/gas/testsuite/gas/elf/sh-link-large-common-3.d new file mode 100644 index 00000000000..d738a90482e --- /dev/null +++ b/gas/testsuite/gas/elf/sh-link-large-common-3.d @@ -0,0 +1,10 @@ +#source: sh-link-large-common.s +#readelf: -t +#target: x86_64-*-* + +#... + +\[ *[0-9]+\] +__patchable_function_entries + +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +LARGE_COM + +0+[248] +0+ +0 +1 + +\[0+83\]: WRITE, ALLOC, LINK ORDER +#pass diff --git a/gas/testsuite/gas/elf/sh-link-large-common-4.d b/gas/testsuite/gas/elf/sh-link-large-common-4.d new file mode 100644 index 00000000000..0101e54da7a --- /dev/null +++ b/gas/testsuite/gas/elf/sh-link-large-common-4.d @@ -0,0 +1,9 @@ +#source: sh-link-large-common.s +#readelf: -tW +#target: x86_64-*-* + +#... + +\[ *[0-9]+\] +__patchable_function_entries + +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+[248] +0+ +LARGE_COM +0 +1 + +\[0+83\]: WRITE, ALLOC, LINK ORDER +#pass diff --git a/gas/testsuite/gas/elf/sh-link-large-common.s b/gas/testsuite/gas/elf/sh-link-large-common.s new file mode 100644 index 00000000000..b2ef554dbc9 --- /dev/null +++ b/gas/testsuite/gas/elf/sh-link-large-common.s @@ -0,0 +1,6 @@ + .section __patchable_function_entries,"awo",%progbits,foo + .dc.a .LPFE1 + .text +.LPFE1: + .byte 0 + .largecomm foo,30,8