Clang: Meaning of PLT32 in Godbolt

60 Views Asked by At

Consider the following program:

#include <stdio.h>

__attribute__((noinline)) 
int add(int a, int b)
{
        return a + b;
}

int add_external_def(int a, int b);

int main() 
{
        printf("5 + 5 = %d\n", add(5, 5));
        printf("5 + 5 = %d\n", add_external_def(5, 5));
        return 0;
}

Compiling this program with Clang 17.0.1, for x86-64 with -O3 will produce some assembly that is basically what I would expect. In this assembly, we call add, add_external_def and printf as follows (godbolt link):

call add
call printf@PLT
call add_external_def@PLT

My understanding here is that printf requires resolution by the dynamic linker/loader and add_external_def@PLT will probably just be replaced during link time optimization (please correct me if I am wrong).

However, if I check 'Compile to binary object' these calls are replaced respectively with the following

 call   20 <main+0x10>
    R_X86_64_PLT32 add-0x4
 call   33 <main+0x23>
    R_X86_64_PLT32 printf-0x4
 call   42 <main+0x32>
    R_X86_64_PLT32 add_external_def-0x4

What is the significance of this R_X86_64_PLT32 ...-0x4 part? Where has the information about 'whether this function is to be resolved through the PLT' gone?

1

There are 1 best solutions below

1
On

From here

On i386, there are 2 types of PLTs, PIC and non-PIC. PIE and shared objects must use PIC PLT. To use PIC PLT, you need to load GLOBAL_OFFSET_TABLE into EBX first. There is no need for that on x86-64 since x86-64 uses PC-relative PLT.

On x86-64, for 32-bit PC-relative branches, we can generate PLT32 relocation, instead of PC32 relocation, which can also be used as a marker for 32-bit PC-relative branches. Linker can always reduce PLT32 relocation to PC32 if function is defined locally. Local functions should use PC32 relocation. As far as Linux kernel is concerned, R_X86_64_PLT32 can be treated the same as R_X86_64_PC32 since Linux kernel doesn't use PLT.

is needed. It is available on hjl/plt32/master branch at