bug-binutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug ld/28218] New: ld: ifunc resolver calls a lazy PLT. When does it wo


From: i at maskray dot me
Subject: [Bug ld/28218] New: ld: ifunc resolver calls a lazy PLT. When does it work?
Date: Tue, 10 Aug 2021 17:36:59 +0000

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

            Bug ID: 28218
           Summary: ld: ifunc resolver calls a lazy PLT. When does it
                    work?
           Product: binutils
           Version: unspecified
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: ld
          Assignee: unassigned at sourceware dot org
          Reporter: i at maskray dot me
  Target Milestone: ---

If an ifunc resolver calls a PLT with lazy JUMP_SLOT, should it work?

My impression is that this does not necessarily need to work.

That said, the R_X86_64_IRELATIVE in .rela.plt is special.
PR ld/13302 patched GNU ld to place R_X86_64_IRELATIVE in .rela.plt after
JUMP_SLOT.
This allows lazy PLT calls.

I think if this case is to be supported, ld.so is to be patched instead.
IRELATIVE relocations are eagerly resolved.
.rela.dyn is conceptually a better place, similar to the .plt.got GLOB_DAT
optimization.
IRELATIVE relocations are not PLT.

FreeBSD rtld resolves non-IRELATIVE relocations in all modules, then IRELATIVE
relocations in all modules.
This allows flexibility on what can be used in ifunc resolvers, and
linkers don't need to place IRELATIVE in special places.

cat > a.c <<eof
  #include <stdio.h>

  int a_impl() { return 42; }
  void *a_resolver() {
    puts("a_resolver");
    return (void *)a_impl;
  }
  int a() __attribute__((ifunc("a_resolver")));

  // .rela.dyn.rel => R_X86_64_64 referencing STT_GNU_IFUNC in .rela.dyn
  int (*fptr_a)() = a;

  int main() { printf("%d\n", a()); }
eof

cc -fpie -c a.c
cc -fuse-ld=bfd -pie a.o -o a


% ./a
[1]    170657 segmentation fault  ./a
% readelf -Wr a

Relocation section '.rela.dyn' at offset 0x4b0 contains 9 entries:
    Offset             Info             Type               Symbol's Value 
Symbol's Name + Addend
0000000000003de8  0000000000000008 R_X86_64_RELATIVE                        
1150
0000000000003df0  0000000000000008 R_X86_64_RELATIVE                        
1110
0000000000004038  0000000000000008 R_X86_64_RELATIVE                        
4038
0000000000003fd8  0000000100000006 R_X86_64_GLOB_DAT      0000000000000000
_ITM_deregisterTMCloneTable + 0
0000000000003fe0  0000000400000006 R_X86_64_GLOB_DAT      0000000000000000
__libc_start_main@GLIBC_2.2.5 + 0
0000000000003fe8  0000000500000006 R_X86_64_GLOB_DAT      0000000000000000
__gmon_start__ + 0
0000000000003ff0  0000000600000006 R_X86_64_GLOB_DAT      0000000000000000
_ITM_registerTMCloneTable + 0
0000000000003ff8  0000000700000006 R_X86_64_GLOB_DAT      0000000000000000
__cxa_finalize@GLIBC_2.2.5 + 0
0000000000004040  0000000000000025 R_X86_64_IRELATIVE                       
1160

Relocation section '.rela.plt' at offset 0x588 contains 3 entries:
    Offset             Info             Type               Symbol's Value 
Symbol's Name + Addend
0000000000004018  0000000200000007 R_X86_64_JUMP_SLOT     0000000000000000
puts@GLIBC_2.2.5 + 0
0000000000004020  0000000300000007 R_X86_64_JUMP_SLOT     0000000000000000
printf@GLIBC_2.2.5 + 0
0000000000004028  0000000000000025 R_X86_64_IRELATIVE                       
1160



`int (*fptr_a)() = a;` leads to an R_X86_64_IRELATIVE in .rela.dyn .
If lazy binding is used, when the R_X86_64_IRELATIVE is resolved,
R_X86_64_JUMP_SLOT(puts) hasn't been resolved yet, and the program crashes.

R_X86_64_IRELATIVE can be seen as an optimization.
R_X86_64_64 referencing an STT_GNU_IFUNC symbol is a different representation.


---

cat > b.c <<eof
   #include <stdio.h>

   int b_impl() { return 42; }
   void *b_resolver() {
     puts("b resolver");
     return (void *)b_impl;
   }
   int b() __attribute__((ifunc("b_resolver")));

   int (*fptr_b)() = b;
eof
cc b.c -fpic -shared -o b.so

Make b.so a DT_NEEDED of the executable and see the crash again.
In this case, R_X86_64_64 is used instead of IRELATIVE.
(b is preemptible, so IRELATIVE cannot be used.)

https://sourceware.org/pipermail/libc-alpha/2021-August/129968.html says
"I don't believe this is the use case we want to support."

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


reply via email to

[Prev in Thread] Current Thread [Next in Thread]