https://sourceware.org/bugzilla/show_bug.cgi?id=33710

            Bug ID: 33710
           Summary: -z combreloc does not sort relocations according to
                    dynamic symbol table index
           Product: binutils
           Version: 2.45.1
            Status: UNCONFIRMED
          Severity: minor
          Priority: P2
         Component: ld
          Assignee: unassigned at sourceware dot org
          Reporter: fabian.rast at tum dot de
  Target Milestone: ---

To reproduce:
$ gcc -shared -fpic test.c -o test.so -Wl,-z,combreloc -fuse-ld=bfd

test.c:
```
int ext_int = 1;
void f(void) { ext_int += 1; }
```

$ readelf -r test.so
Relocation section '.rela.dyn' at offset 0x478 contains 8 entries:
  Offset          Info           Type           Sym. Value    Sym. Name +
Addend
...
000000003fd0  000500000006 R_X86_64_GLOB_DAT 0000000000004008 ext_int + 0
000000003fd8  000300000006 R_X86_64_GLOB_DAT 0000000000000000
_ITM_registerTMCl[...] + 0
000000003fe0  000400000006 R_X86_64_GLOB_DAT 0000000000000000
__cxa_finalize@GLIBC_2.2.5 + 0

$ readelf --dyn-syms test.so
Symbol table '.dynsym' contains 7 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND
_ITM_deregisterT[...]
     2: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
     3: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND
_ITM_registerTMC[...]
     4: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND [...]@GLIBC_2.2.5
(2)
     5: 0000000000004008     4 OBJECT  GLOBAL DEFAULT   21 ext_int
     6: 00000000000010f9    28 FUNC    GLOBAL DEFAULT   12 f

In this example, the relocations against _ITM_register... and __cxa_finalize
are placed after the relocation against ext_int, even though ext_int has
a higher symbol index.
If combreloc is only used to group relocations to the same symbol together,
this is irrelevant, but if for example you would want to find the relocations
against a specific symbol using binary search this relocation table would need
to be sorted first.

What is interesting is that the ordering is actually correct when considering
the indices in .symtab:

Symbol table '.symtab' contains 26 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
...
    21: 00000000000010f9    28 FUNC    GLOBAL DEFAULT   12 f
    22: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
    23: 0000000000004008     4 OBJECT  GLOBAL DEFAULT   21 ext_int
    24: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND
_ITM_registerTMC[...]
    25: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND
__cxa_finalize@G[...]

here both _ITM_register... and cxa_finalize are after ext_int, but they have
been moved up in the dynamic symbol table, because they are undefined.

The llvm linker produces relocations sorted according to dynamic symbol table
index in this example:

$ gcc -shared -fpic test.c -o test.so -Wl,-z,combreloc -fuse-ld=lld
$ readelf --dyn-syms test.so

Symbol table '.dynsym' contains 7 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
...
     2: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND
_ITM_deregisterT[...]
     3: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND
_ITM_registerTMC[...]
     4: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND [...]@GLIBC_2.2.5
(2)
     5: 0000000000003830     4 OBJECT  GLOBAL DEFAULT   20 ext_int
     6: 00000000000015f9    28 FUNC    GLOBAL DEFAULT   11 f

$ readelf -r test.so
Relocation section '.rela.dyn' at offset 0x410 contains 8 entries:
  Offset          Info           Type           Sym. Value    Sym. Name +
Addend
...
000000002808  000200000006 R_X86_64_GLOB_DAT 0000000000000000
_ITM_deregisterTM[...] + 0
000000002810  000300000006 R_X86_64_GLOB_DAT 0000000000000000
_ITM_registerTMCl[...] + 0
000000002818  000400000006 R_X86_64_GLOB_DAT 0000000000000000
__cxa_finalize@GLIBC_2.2.5 + 0
000000002820  000500000006 R_X86_64_GLOB_DAT 0000000000003830 ext_int + 0

Version:
$ ld.bfd --version
GNU ld (GNU Binutils) 2.45.1
Copyright (C) 2025 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.

$ gcc --version                                                                
                                                                               
                 git@main
gcc (AerynOS) 15.2.1 20251024
Copyright (C) 2025 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Reply via email to