[PATCH] gas: add --reloc-use-section-sym={all, temporary, none} option for ELF
Fangrui Song
maskray@sourceware.org
Mon Feb 9 06:49:45 GMT 2026
On Sun, Feb 8, 2026 at 10:45 PM mengqinggang <mengqinggang@loongson.cn> wrote:
>
> Maybe need to change temporary to local-label in commit message?
Yes, I hit `git send-email` just before noticing the unchanged commit message.
I'll make sure to include the fix in the next revision after the review.
>
> 在 2026/2/9 05:03, maskray@sourceware.org 写道:
> > From: Fangrui Song <maskray@sourceware.org>
> >
> > When generating relocations for non-ifunc local symbols that satisfies
> > several conditions, GAS converts them to reference the section symbol
> > (STT_SECTION) instead, folding the original symbol's offset into the
> > addend. This allows the original local symbol to be omitted from
> > .symtab, but the STT_SECTION symbol itself must be present, so the
> > conversion saves .symtab entries only when a section has more than one
> > local symbol referenced by relocations.
> >
> > Add --reloc-use-section-sym to control this conversion:
> >
> > - all (default): convert all eligible local symbols
> > - temporary: only convert compiler-generated locals (.L prefix)
> > - none: never convert; keep all symbols as-is in relocations
> >
> > This is useful for debugging and for tools that benefit from preserve
> > symbol names.
> >
> > PR gas/33885
> > ---
> > gas/NEWS | 4 ++++
> > gas/as.c | 20 +++++++++++++++-
> > gas/as.h | 10 ++++++++
> > gas/doc/as.texi | 11 +++++++++
> > .../gas/i386/reloc-use-section-sym-all.d | 23 +++++++++++++++++++
> > .../i386/reloc-use-section-sym-local-label.d | 23 +++++++++++++++++++
> > .../gas/i386/reloc-use-section-sym-none.d | 23 +++++++++++++++++++
> > .../gas/i386/reloc-use-section-sym.s | 14 +++++++++++
> > gas/testsuite/gas/i386/x86-64.exp | 4 ++++
> > gas/write.c | 12 +++++++++-
> > 10 files changed, 142 insertions(+), 2 deletions(-)
> > create mode 100644 gas/testsuite/gas/i386/reloc-use-section-sym-all.d
> > create mode 100644 gas/testsuite/gas/i386/reloc-use-section-sym-local-label.d
> > create mode 100644 gas/testsuite/gas/i386/reloc-use-section-sym-none.d
> > create mode 100644 gas/testsuite/gas/i386/reloc-use-section-sym.s
> >
> > diff --git a/gas/NEWS b/gas/NEWS
> > index e384d1135c0..1d07f909b8f 100644
> > --- a/gas/NEWS
> > +++ b/gas/NEWS
> > @@ -1,5 +1,9 @@
> > -*- text -*-
> >
> > +* New command line option --reloc-use-section-sym=[all|local-label|none]
> > + controls whether relocations referencing local binding symbols are adjusted
> > + to use section symbols.
> > +
> > Changes in 2.46:
> >
> > * Add support for AMD Zen6 processor.
> > diff --git a/gas/as.c b/gas/as.c
> > index f08c7c71d73..e8c29c13f0f 100644
> > --- a/gas/as.c
> > +++ b/gas/as.c
> > @@ -326,6 +326,10 @@ Options:\n\
> > DEFAULT_SFRAME ? "yes" : "no");
> > fprintf (stream, _("\
> > --gsframe-<N> generate SFrame version <N> information. 3 == <N>\n"));
> > + fprintf (stream, _("\
> > + --reloc-use-section-sym=[all|local-label|none]\n\
> > + adjust eligible relocations to use section symbols\n\
> > + (default: all)\n"));
> > # if defined (TARGET_USE_SCFI) && defined (TARGET_USE_GINSN)
> > fprintf (stream, _("\
> > --scfi=experimental Synthesize DWARF CFI for hand-written asm\n\
> > @@ -523,7 +527,8 @@ parse_args (int * pargc, char *** pargv)
> > OPTION_SFRAME_3,
> > OPTION_SCFI,
> > OPTION_INFO,
> > - OPTION_NOINFO
> > + OPTION_NOINFO,
> > + OPTION_RELOC_USE_SECTION_SYM
> > /* When you add options here, check that they do
> > not collide with OPTION_MD_BASE. See as.h. */
> > };
> > @@ -556,6 +561,7 @@ parse_args (int * pargc, char *** pargv)
> > ,{"generate-missing-build-notes", required_argument, NULL, OPTION_ELF_BUILD_NOTES}
> > ,{"gsframe", optional_argument, NULL, OPTION_SFRAME}
> > ,{"gsframe-3", no_argument, NULL, OPTION_SFRAME_3}
> > + ,{"reloc-use-section-sym", required_argument, NULL, OPTION_RELOC_USE_SECTION_SYM}
> > # if defined (TARGET_USE_SCFI) && defined (TARGET_USE_GINSN)
> > ,{"scfi", required_argument, NULL, OPTION_SCFI}
> > # endif
> > @@ -1043,6 +1049,18 @@ This program has absolutely no warranty.\n"));
> > flag_sectname_subst = 1;
> > break;
> >
> > + case OPTION_RELOC_USE_SECTION_SYM:
> > + if (strcasecmp (optarg, "all") == 0)
> > + flag_reloc_use_section_sym = reloc_use_section_sym_all;
> > + else if (strcasecmp (optarg, "local-label") == 0)
> > + flag_reloc_use_section_sym = reloc_use_section_sym_local_label;
> > + else if (strcasecmp (optarg, "none") == 0)
> > + flag_reloc_use_section_sym = reloc_use_section_sym_none;
> > + else
> > + as_fatal (_("Invalid --reloc-use-section-sym= option: `%s'"),
> > + optarg);
> > + break;
> > +
> > case OPTION_ELF_BUILD_NOTES:
> > if (strcasecmp (optarg, "no") == 0)
> > flag_generate_build_notes = false;
> > diff --git a/gas/as.h b/gas/as.h
> > index 1c96a69ea09..24a8e521469 100644
> > --- a/gas/as.h
> > +++ b/gas/as.h
> > @@ -413,6 +413,16 @@ enum multibyte_input_handling
> > };
> > COMMON enum multibyte_input_handling multibyte_handling;
> >
> > +/* Controls whether relocations referencing local symbols are converted
> > + to use section symbols. */
> > +enum reloc_use_section_sym_type
> > +{
> > + reloc_use_section_sym_all = 0,
> > + reloc_use_section_sym_local_label,
> > + reloc_use_section_sym_none
> > +};
> > +COMMON enum reloc_use_section_sym_type flag_reloc_use_section_sym;
> > +
> > /* TRUE if we should produce a listing. */
> > extern int listing;
> >
> > diff --git a/gas/doc/as.texi b/gas/doc/as.texi
> > index 6114a178a0d..f2a8953504b 100644
> > --- a/gas/doc/as.texi
> > +++ b/gas/doc/as.texi
> > @@ -257,6 +257,7 @@ gcc(1), ld(1), and the Info entries for @file{binutils} and @file{ld}.
> > [@b{--multibyte-handling=[allow|warn|warn-sym-only]}]
> > [@b{--no-pad-sections}]
> > [@b{-o} @var{objfile}] [@b{-R}]
> > + [@b{--reloc-use-section-sym=[all|local-label|none]}]
> > [@b{--scfi=experimental}]
> > [@b{--sectname-subst}]
> > [@b{--size-check=[error|warning]}]
> > @@ -956,6 +957,16 @@ Ignored. Supported for compatibility with tools that pass the same option to
> > both the assembler and the linker.
> >
> > @ifset ELF
> > +@item --reloc-use-section-sym=all
> > +@itemx --reloc-use-section-sym=local-label
> > +@itemx --reloc-use-section-sym=none
> > +Control whether relocations referencing local binding symbols are adjusted to
> > +use section symbols instead. With @code{all} (the default), relocations
> > +against all eligible local binding symbols are converted. With
> > +@code{local-label}, only relocations against local labels (symbols matching the
> > +@code{.L} prefix) are converted. With @code{none}, no conversions are
> > +performed and all relocations retain their original symbols.
> > +
> > @item --scfi=experimental
> > This option controls whether the assembler should synthesize CFI for
> > hand-written input. If the input already contains some synthesizable CFI
> > diff --git a/gas/testsuite/gas/i386/reloc-use-section-sym-all.d b/gas/testsuite/gas/i386/reloc-use-section-sym-all.d
> > new file mode 100644
> > index 00000000000..4ff6bd86aea
> > --- /dev/null
> > +++ b/gas/testsuite/gas/i386/reloc-use-section-sym-all.d
> > @@ -0,0 +1,23 @@
> > +#source: reloc-use-section-sym.s
> > +#as: --reloc-use-section-sym=all
> > +#objdump: -rsj .data -j .text1
> > +#name: reloc-use-section-sym=all
> > +
> > +.*: file format .*
> > +
> > +RELOCATION RECORDS FOR \[\.data\]:
> > +OFFSET +TYPE +VALUE
> > +0+0 R_X86_64_64 +\.text\+0x0+11
> > +0+8 R_X86_64_64 +\.text\+0x0+12
> > +
> > +
> > +RELOCATION RECORDS FOR \[\.text1\]:
> > +OFFSET +TYPE +VALUE
> > +0+1 R_X86_64_PC32 +\.text-0x0+3
> > +0+6 R_X86_64_PC32 +\.text-0x0+2
> > +
> > +
> > +Contents of section \.data:
> > + 0000 00000000 00000000 00000000 00000000 \.+
> > +Contents of section \.text1:
> > + 0000 e8000000 00e80000 0000 +.*
> > diff --git a/gas/testsuite/gas/i386/reloc-use-section-sym-local-label.d b/gas/testsuite/gas/i386/reloc-use-section-sym-local-label.d
> > new file mode 100644
> > index 00000000000..2c56894fc63
> > --- /dev/null
> > +++ b/gas/testsuite/gas/i386/reloc-use-section-sym-local-label.d
> > @@ -0,0 +1,23 @@
> > +#source: reloc-use-section-sym.s
> > +#as: --reloc-use-section-sym=local-label
> > +#objdump: -rsj .data -j .text1
> > +#name: reloc-use-section-sym=local-label
> > +
> > +.*: file format .*
> > +
> > +RELOCATION RECORDS FOR \[\.data\]:
> > +OFFSET +TYPE +VALUE
> > +0+0 R_X86_64_64 +named_local\+0x0+10
> > +0+8 R_X86_64_64 +\.text\+0x0+12
> > +
> > +
> > +RELOCATION RECORDS FOR \[\.text1\]:
> > +OFFSET +TYPE +VALUE
> > +0+1 R_X86_64_PC32 +named_local-0x0+4
> > +0+6 R_X86_64_PC32 +\.text-0x0+2
> > +
> > +
> > +Contents of section \.data:
> > + 0000 00000000 00000000 00000000 00000000 \.+
> > +Contents of section \.text1:
> > + 0000 e8000000 00e80000 0000 +.*
> > diff --git a/gas/testsuite/gas/i386/reloc-use-section-sym-none.d b/gas/testsuite/gas/i386/reloc-use-section-sym-none.d
> > new file mode 100644
> > index 00000000000..1a3e290ef7b
> > --- /dev/null
> > +++ b/gas/testsuite/gas/i386/reloc-use-section-sym-none.d
> > @@ -0,0 +1,23 @@
> > +#source: reloc-use-section-sym.s
> > +#as: --reloc-use-section-sym=none
> > +#objdump: -rsj .data -j .text1
> > +#name: reloc-use-section-sym=none
> > +
> > +.*: file format .*
> > +
> > +RELOCATION RECORDS FOR \[\.data\]:
> > +OFFSET +TYPE +VALUE
> > +0+0 R_X86_64_64 +named_local\+0x0+10
> > +0+8 R_X86_64_64 +\.Ltemp\+0x0+10
> > +
> > +
> > +RELOCATION RECORDS FOR \[\.text1\]:
> > +OFFSET +TYPE +VALUE
> > +0+1 R_X86_64_PC32 +named_local-0x0+4
> > +0+6 R_X86_64_PC32 +\.Ltemp-0x0+4
> > +
> > +
> > +Contents of section \.data:
> > + 0000 00000000 00000000 00000000 00000000 \.+
> > +Contents of section \.text1:
> > + 0000 e8000000 00e80000 0000 +.*
> > diff --git a/gas/testsuite/gas/i386/reloc-use-section-sym.s b/gas/testsuite/gas/i386/reloc-use-section-sym.s
> > new file mode 100644
> > index 00000000000..7663ef71ce8
> > --- /dev/null
> > +++ b/gas/testsuite/gas/i386/reloc-use-section-sym.s
> > @@ -0,0 +1,14 @@
> > +.text
> > + nop
> > +named_local:
> > + nop
> > +.Ltemp:
> > + nop
> > +
> > +.section .text1,"ax"
> > + call named_local
> > + call .Ltemp
> > +
> > +.data
> > +.quad named_local + 16
> > +.quad .Ltemp + 16
> > diff --git a/gas/testsuite/gas/i386/x86-64.exp b/gas/testsuite/gas/i386/x86-64.exp
> > index 8ddf05481a5..1a3e16ef6e9 100644
> > --- a/gas/testsuite/gas/i386/x86-64.exp
> > +++ b/gas/testsuite/gas/i386/x86-64.exp
> > @@ -775,6 +775,10 @@ if [is_elf_format] then {
> > run_dump_test "x86-64-align-branch-3"
> > }
> > run_dump_test ehinterp
> > +
> > + run_dump_test "reloc-use-section-sym-all"
> > + run_dump_test "reloc-use-section-sym-local-label"
> > + run_dump_test "reloc-use-section-sym-none"
> > }
> > run_dump_test pr27198
> > run_dump_test pr29483
> > diff --git a/gas/write.c b/gas/write.c
> > index 3494871270a..81dcae765f7 100644
> > --- a/gas/write.c
> > +++ b/gas/write.c
> > @@ -804,6 +804,10 @@ adjust_reloc_syms (bfd *abfd ATTRIBUTE_UNUSED,
> >
> > dump_section_relocs (abfd, sec, stderr);
> >
> > + /* Disable all conversion for --reloc-use-section-sym=none. */
> > + if (flag_reloc_use_section_sym == reloc_use_section_sym_none)
> > + return;
> > +
> > for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
> > if (fixp->fx_done)
> > /* Ignore it. */
> > @@ -909,6 +913,12 @@ adjust_reloc_syms (bfd *abfd ATTRIBUTE_UNUSED,
> > if ((symsec->flags & SEC_THREAD_LOCAL) != 0)
> > continue;
> >
> > + /* If --reloc-use-section-sym=local-label, don't adjust a reloc against
> > + a local label. */
> > + if (flag_reloc_use_section_sym == reloc_use_section_sym_local_label
> > + && !bfd_is_local_label (stdoutput, symbol_get_bfdsym (sym)))
> > + continue;
> > +
> > val = S_GET_VALUE (sym);
> >
> > #if defined(TC_AARCH64) && defined(OBJ_COFF)
> > @@ -2043,7 +2053,7 @@ maybe_generate_build_notes (void)
> > else
> > desc_reloc = BFD_RELOC_64;
> > }
> > -
> > +
> > /* We have to create a note for *each* code section.
> > Linker garbage collection might discard some. */
> > total_size = 0;
>
More information about the Binutils
mailing list