PR30592 objcopy: allow --set-section-flags to add or remove SHF_X86_64_LARGE

For example, objcopy --set-section-flags .data=alloc,large will add
SHF_X86_64_LARGE to the .data section.  Omitting "large" will drop the
SHF_X86_64_LARGE flag.

The bfd_section flag is named generically, SEC_ELF_LARGE, in case other
processors want to follow SHF_X86_64_LARGE.  SEC_ELF_LARGE has the same
value as SEC_TIC54X_BLOCK used by coff.

bfd/
    * section.c: Define SEC_ELF_LARGE.
    * bfd-in2.h: Regenerate.
    * elf64-x86-64.c (elf_x86_64_section_flags, elf_x86_64_fake_sections,
    elf_x86_64_copy_private_section_data): New.

binutils/
    * NEWS: Mention the new feature for objcopy.
    * doc/binutils.texi: Mention "large".
    * objcopy.c (parse_flags): Parse "large".
    (check_new_section_flags): Error if "large" is used with a
    non-x86-64 ELF target.
    * testsuite/binutils-all/x86-64/large-sections.d: New.
    * testsuite/binutils-all/x86-64/large-sections.s: New.
    * testsuite/binutils-all/x86-64/large-sections-i386.d: New.
    * testsuite/binutils-all/x86-64/large-sections-2.d: New.
    * testsuite/binutils-all/x86-64/large-sections-2-x32.d: New.
This commit is contained in:
Fangrui Song
2023-07-09 10:57:19 -07:00
committed by Fangrui Song
parent 4fb2abb59d
commit 5e24da908d
13 changed files with 155 additions and 10 deletions

View File

@@ -1,3 +1,11 @@
2023-07-09 Fangrui Song <maskray@google.com>
PR 30592
* section.c: Define SEC_ELF_LARGE.
* bfd-in2.h: Regenerate.
* elf64-x86-64.c (elf_x86_64_section_flags, elf_x86_64_fake_sections,
elf_x86_64_copy_private_section_data): New.
2023-07-03 Nick Clifton <nickc@redhat.com> 2023-07-03 Nick Clifton <nickc@redhat.com>
* version.m4: Update version number to 2.41.50. * version.m4: Update version number to 2.41.50.

View File

@@ -625,6 +625,9 @@ typedef struct bfd_section
TMS320C54X only. */ TMS320C54X only. */
#define SEC_TIC54X_BLOCK 0x10000000 #define SEC_TIC54X_BLOCK 0x10000000
/* This section has the SHF_X86_64_LARGE flag. This is ELF x86-64 only. */
#define SEC_ELF_LARGE 0x10000000
/* Conditionally link this section; do not link if there are no /* Conditionally link this section; do not link if there are no
references found to any symbol in the section. This is for TI references found to any symbol in the section. This is for TI
TMS320C54X only. */ TMS320C54X only. */

View File

@@ -5281,6 +5281,39 @@ elf_x86_64_merge_symbol (struct elf_link_hash_entry *h,
return true; return true;
} }
static bool
elf_x86_64_section_flags (const Elf_Internal_Shdr *hdr)
{
if ((hdr->sh_flags & SHF_X86_64_LARGE) != 0)
hdr->bfd_section->flags |= SEC_ELF_LARGE;
return true;
}
static bool
elf_x86_64_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
Elf_Internal_Shdr *hdr, asection *sec)
{
if (sec->flags & SEC_ELF_LARGE)
hdr->sh_flags |= SHF_X86_64_LARGE;
return true;
}
static bool
elf_x86_64_copy_private_section_data (bfd *ibfd, asection *isec,
bfd *obfd, asection *osec)
{
if (!_bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec))
return false;
/* objcopy --set-section-flags without "large" drops SHF_X86_64_LARGE. */
if (ibfd != obfd)
elf_section_flags (osec) &= ~SHF_X86_64_LARGE;
return true;
}
static int static int
elf_x86_64_additional_program_headers (bfd *abfd, elf_x86_64_additional_program_headers (bfd *abfd,
struct bfd_link_info *info ATTRIBUTE_UNUSED) struct bfd_link_info *info ATTRIBUTE_UNUSED)
@@ -5408,6 +5441,8 @@ elf_x86_64_special_sections[]=
#define elf_info_to_howto elf_x86_64_info_to_howto #define elf_info_to_howto elf_x86_64_info_to_howto
#define bfd_elf64_bfd_copy_private_section_data \
elf_x86_64_copy_private_section_data
#define bfd_elf64_bfd_reloc_type_lookup elf_x86_64_reloc_type_lookup #define bfd_elf64_bfd_reloc_type_lookup elf_x86_64_reloc_type_lookup
#define bfd_elf64_bfd_reloc_name_lookup \ #define bfd_elf64_bfd_reloc_name_lookup \
elf_x86_64_reloc_name_lookup elf_x86_64_reloc_name_lookup
@@ -5448,6 +5483,8 @@ elf_x86_64_special_sections[]=
elf_x86_64_merge_symbol elf_x86_64_merge_symbol
#define elf_backend_special_sections \ #define elf_backend_special_sections \
elf_x86_64_special_sections elf_x86_64_special_sections
#define elf_backend_section_flags elf_x86_64_section_flags
#define elf_backend_fake_sections elf_x86_64_fake_sections
#define elf_backend_additional_program_headers \ #define elf_backend_additional_program_headers \
elf_x86_64_additional_program_headers elf_x86_64_additional_program_headers
#define elf_backend_setup_gnu_properties \ #define elf_backend_setup_gnu_properties \
@@ -5564,6 +5601,8 @@ elf64_x86_64_copy_solaris_special_section_fields (const bfd *ibfd ATTRIBUTE_UNUS
#undef ELF_TARGET_OS #undef ELF_TARGET_OS
#undef ELF_OSABI #undef ELF_OSABI
#define bfd_elf32_bfd_copy_private_section_data \
elf_x86_64_copy_private_section_data
#define bfd_elf32_bfd_reloc_type_lookup \ #define bfd_elf32_bfd_reloc_type_lookup \
elf_x86_64_reloc_type_lookup elf_x86_64_reloc_type_lookup
#define bfd_elf32_bfd_reloc_name_lookup \ #define bfd_elf32_bfd_reloc_name_lookup \

View File

@@ -359,6 +359,9 @@ CODE_FRAGMENT
. TMS320C54X only. *} . TMS320C54X only. *}
.#define SEC_TIC54X_BLOCK 0x10000000 .#define SEC_TIC54X_BLOCK 0x10000000
. .
. {* This section has the SHF_X86_64_LARGE flag. This is ELF x86-64 only. *}
.#define SEC_ELF_LARGE 0x10000000
.
. {* Conditionally link this section; do not link if there are no . {* Conditionally link this section; do not link if there are no
. references found to any symbol in the section. This is for TI . references found to any symbol in the section. This is for TI
. TMS320C54X only. *} . TMS320C54X only. *}

View File

@@ -1,3 +1,17 @@
2023-07-09 Fangrui Song <maskray@google.com>
PR 30592
* NEWS: Mention the new feature for objcopy.
* doc/binutils.texi: Mention "large".
* objcopy.c (parse_flags): Parse "large".
(check_new_section_flags): Error if "large" is used with a
non-x86-64 ELF target.
* testsuite/binutils-all/x86-64/large-sections.d: New.
* testsuite/binutils-all/x86-64/large-sections.s: New.
* testsuite/binutils-all/x86-64/large-sections-i386.d: New.
* testsuite/binutils-all/x86-64/large-sections-2.d: New.
* testsuite/binutils-all/x86-64/large-sections-2-x32.d: New.
2023-07-03 Nick Clifton <nickc@redhat.com> 2023-07-03 Nick Clifton <nickc@redhat.com>
* README-how-to-make-a-release: Change some version numbers. * README-how-to-make-a-release: Change some version numbers.

View File

@@ -1,5 +1,8 @@
-*- text -*- -*- text -*-
* objcopy --set-section-flags now supports "large" to set SHF_X86_64_LARGE
for ELF x86-64 objects.
Changes in 2.41: Changes in 2.41:
* The MIPS port now supports the Sony Interactive Entertainment Allegrex * The MIPS port now supports the Sony Interactive Entertainment Allegrex

View File

@@ -1745,13 +1745,14 @@ Set the flags for any sections matching @var{sectionpattern}. The
@var{flags} argument is a comma separated string of flag names. The @var{flags} argument is a comma separated string of flag names. The
recognized names are @samp{alloc}, @samp{contents}, @samp{load}, recognized names are @samp{alloc}, @samp{contents}, @samp{load},
@samp{noload}, @samp{readonly}, @samp{code}, @samp{data}, @samp{rom}, @samp{noload}, @samp{readonly}, @samp{code}, @samp{data}, @samp{rom},
@samp{exclude}, @samp{share}, and @samp{debug}. You can set the @samp{exclude}, @samp{share}, @samp{debug}, and @samp{large}.
@samp{contents} flag for a section which does not have contents, but it You can set the @samp{contents} flag for a section which does not have
is not meaningful to clear the @samp{contents} flag of a section which contents, but it is not meaningful to clear the @samp{contents} flag of a
does have contents--just remove the section instead. Not all flags are section which does have contents--just remove the section instead. Not all
meaningful for all object file formats. In particular the flags are meaningful for all object file formats. In particular the
@samp{share} flag is only meaningful for COFF format files and not for @samp{share} flag is only meaningful for COFF format files and not for ELF
ELF format files. format files. The ELF x86-64 specific flag @samp{large} corresponds to
SHF_X86_64_LARGE.
@item --set-section-alignment @var{sectionpattern}=@var{align} @item --set-section-alignment @var{sectionpattern}=@var{align}
Set the alignment for any sections matching @var{sectionpattern}. Set the alignment for any sections matching @var{sectionpattern}.

View File

@@ -803,6 +803,7 @@ parse_flags (const char *s)
PARSE_FLAG ("contents", SEC_HAS_CONTENTS); PARSE_FLAG ("contents", SEC_HAS_CONTENTS);
PARSE_FLAG ("merge", SEC_MERGE); PARSE_FLAG ("merge", SEC_MERGE);
PARSE_FLAG ("strings", SEC_STRINGS); PARSE_FLAG ("strings", SEC_STRINGS);
PARSE_FLAG ("large", SEC_ELF_LARGE);
#undef PARSE_FLAG #undef PARSE_FLAG
else else
{ {
@@ -812,8 +813,10 @@ parse_flags (const char *s)
strncpy (copy, s, len); strncpy (copy, s, len);
copy[len] = '\0'; copy[len] = '\0';
non_fatal (_("unrecognized section flag `%s'"), copy); non_fatal (_("unrecognized section flag `%s'"), copy);
fatal (_("supported flags: %s"), fatal (_ ("supported flags: %s"),
"alloc, load, noload, readonly, debug, code, data, rom, exclude, share, contents, merge, strings"); "alloc, load, noload, readonly, debug, code, data, rom, "
"exclude, contents, merge, strings, (COFF specific) share, "
"(ELF x86-64 specific) large");
} }
s = snext; s = snext;
@@ -2618,7 +2621,7 @@ merge_gnu_build_notes (bfd * abfd,
} }
static flagword static flagword
check_new_section_flags (flagword flags, bfd * abfd, const char * secname) check_new_section_flags (flagword flags, bfd *abfd, const char * secname)
{ {
/* Only set the SEC_COFF_SHARED flag on COFF files. /* Only set the SEC_COFF_SHARED flag on COFF files.
The same bit value is used by ELF targets to indicate The same bit value is used by ELF targets to indicate
@@ -2631,6 +2634,19 @@ check_new_section_flags (flagword flags, bfd * abfd, const char * secname)
bfd_get_filename (abfd), secname); bfd_get_filename (abfd), secname);
flags &= ~ SEC_COFF_SHARED; flags &= ~ SEC_COFF_SHARED;
} }
/* Report a fatal error if 'large' is used with a non-x86-64 ELF target.
Suppress the error for non-ELF targets to allow -O binary and formats that
use the bit value SEC_ELF_LARGE for other purposes. */
if ((flags & SEC_ELF_LARGE) != 0
&& bfd_get_flavour (abfd) == bfd_target_elf_flavour
&& get_elf_backend_data (abfd)->elf_machine_code != EM_X86_64)
{
fatal (_ ("%s[%s]: 'large' flag is ELF x86-64 specific"),
bfd_get_filename (abfd), secname);
flags &= ~SEC_ELF_LARGE;
}
return flags; return flags;
} }

View File

@@ -0,0 +1,15 @@
#source: large-sections.s
#PROG: objcopy
#as: --x32
#objcopy: --set-section-flags .ldata=alloc
#readelf: -S -W
#...
\[[ 0-9]+\] \.text.*[ \t]+PROGBITS[ \t0-9a-f]+AX[ \t]+.*
#...
\[[ 0-9]+\] \.data.*[ \t]+PROGBITS[ \t0-9a-f]+WA[ \t]+.*
#...
\[[ 0-9]+\] \.ltext.*[ \t]+PROGBITS[ \t0-9a-f]+AXl[ \t]+.*
#...
\[[ 0-9]+\] \.ldata.*[ \t]+PROGBITS[ \t0-9a-f]+WA[ \t]+.*
#pass

View File

@@ -0,0 +1,15 @@
#source: large-sections.s
#PROG: objcopy
#as: --64
#objcopy: --set-section-flags .ldata=alloc
#readelf: -S -W
#...
\[[ 0-9]+\] \.text.*[ \t]+PROGBITS[ \t0-9a-f]+AX[ \t]+.*
#...
\[[ 0-9]+\] \.data.*[ \t]+PROGBITS[ \t0-9a-f]+WA[ \t]+.*
#...
\[[ 0-9]+\] \.ltext.*[ \t]+PROGBITS[ \t0-9a-f]+AXl[ \t]+.*
#...
\[[ 0-9]+\] \.ldata.*[ \t]+PROGBITS[ \t0-9a-f]+WA[ \t]+.*
#pass

View File

@@ -0,0 +1,6 @@
#source: large-sections.s
#PROG: objcopy
#as: --64
#objcopy: -O elf32-i386 --set-section-flags .data=alloc,large
#target: x86_64-*-linux*
#error: \A[^[]*\[.data\]: 'large' flag is ELF x86-64 specific

View File

@@ -0,0 +1,14 @@
#PROG: objcopy
#as: --64
#objcopy: --set-section-flags .text=alloc,readonly,code,large --set-section-flags .data=alloc,large
#readelf: -S -W
#...
\[[ 0-9]+\] \.text.*[ \t]+PROGBITS[ \t0-9a-f]+AXl[ \t]+.*
#...
\[[ 0-9]+\] \.data.*[ \t]+PROGBITS[ \t0-9a-f]+WAl[ \t]+.*
#...
\[[ 0-9]+\] \.ltext.*[ \t]+PROGBITS[ \t0-9a-f]+AXl[ \t]+.*
#...
\[[ 0-9]+\] \.ldata.*[ \t]+PROGBITS[ \t0-9a-f]+WAl[ \t]+.*
#pass

View File

@@ -0,0 +1,8 @@
.section .text, "ax"
nop
.section .data, "aw"
.byte 1
.section .ltext, "axl"
nop
.section .ldata, "awl"
.byte 1