https://sourceware.org/bugzilla/show_bug.cgi?id=29655
--- Comment #7 from Rui Ueyama <rui314 at gmail dot com> --- It's about pointer equality. C/C++ guarantees that two function pointers are equal if and only if they are for the same function. For example, an expression `&printf` in your main program code should yields the same address as an expression `&printf` in libc.so. That doesn't seem like a tricky requirement, but it actually is when dynamic linking is involved. When doing dynamic linking, there are more than one entry point for the same exported function. Your main program will call `printf` via the executable's PLT entry for `printf`; on the other hand, libc may call its own `printf` via its own PLT entry. libc.so can also call `printf` directly by jumping to the entry point of the function without PLT. `&printf` can be evaluated to any of these addresses, but the result must be consistent across all ELF modules for the same process throughout its lifetime. Otherwise, the pointer equality will not be guaranteed. For PIC, the linker creates a GOT entry for `printf`, and the code will read the entry value to obtain the address of `printf`. If all ELF modules are PIC (shared objects are always position-independent, so that means the main executable code was compiled with -fPIC), it's just as simple as the dynamic linker fills all GOT entries for `printf` with the same address, which is the real address of the `printf` function in memory. However, if the main executable wasn't compiled with -fPIC, the main executable assumes that all variables and functions exist at fixed locations in memory. That's a wrong assumption for imported functions such as `printf` though. So, in that case, the static linker makes the dynamic linker to use a main executable's PLT entry as an address of an imported function. The dynamic linker sets addresses of the main executable's PLT entries to shared libraries' GOT entries for pointer equality. A main executable's PLT entry that is used as a function address is often called a "canonical PLT". If the main executable isn't compiled as PIC, and if it takes a pointer of imported function `foo`, the linker has to make the main program's `foo`'s PLT entry canonical. If it's not canonical, the main executable would use its own PLT entry as `foo`'s address, while other shared object files in memory would use `foo`'s real address of its address, which breaks the pointer equality guarantee. Now, we can ask this question: is it safe to always make main executable's PLT entries canonical? I originally thought that the answer would be yes. Even if the main program is compiled with -fPIC, it seems that we can still make `foo`'s PLT entry canonical, so that the PLT entry's address will be used as `foo`'s address throughout the program execution. The above logic wasn't wrong, but in reality, there are libraries that assume the linker doesn't make PLT entries canonical unless necessary. Qt5 is one of such libraries. It's `connect` function takes a pointer to a callback function. Internally, it compares a given pointer value with a list of pointers. When doing so, it looks like Qt compares a given pointer with addresses of symbol aliases. It works as long as both pointers directly point to the address of a callback function. But it won't when a given pointer points to a PLT entry of the main executable. That caused a mysterious runtime issue. So I made a change to mold so that it makes PLT entries canonical only when needed (i.e. only when a function address is taken, as opposed to function is just called.) So, long story short, the linker has to distinguish address-taking relocations from non-address-taking relocations to properly make/not make PLT entries canonical. We assume that R_*_PLT* relocations are not address-taking (we assume such relocations are used for instructions such as x86's CALL, and despite its name, R_*_PLT* relocations don't request the linker to always generate PLT entries), and other relocations are address-taking. I want s390x to follow that convention. -- You are receiving this mail because: You are on the CC list for the bug.