Search code examples
linuxbinaryelfstatic-analysisreadelf

readelf -R (--relocated-dump) option


Can anyone explain how the contents of a section are relocated using the -R option for readelf? I would like to see an example of this so I can understand how it works.

When I build an executable using g++ like this: g++ -o main main.cpp The output for -R and -x are the same.

When I create an object file like this: g++ -g -c -o main.o main.cpp I get some warnings when using -R option with readelf.

readelf -R .text main.o**
readelf: Warning: unable to apply unsupported reloc type 4 to section .text
readelf: Warning: unable to apply unsupported reloc type 42 to section .text
readelf: Warning: unable to apply unsupported reloc type 4 to section .text
readelf: Warning: unable to apply unsupported reloc type 42 to section .text
readelf: Warning: unable to apply unsupported reloc type 4 to section .text

What do these warnings mean and how is -R different from -x?

source: https://manpages.ubuntu.com/manpages/bionic/man1/readelf.1.html


Solution

  • Let's use the following main.cpp as our example:

    #include <iostream>
    
    int main()
    {
      std::cout << "Hellp" << std::endl;
    }
    

    After g++ -c main.cpp (using Debian 13.2.0-13), we have:

    readelf -Wr main.o
    
    Relocation section '.rela.text' at offset 0x398 contains 5 entries:
        Offset             Info             Type               Symbol's Value  Symbol's Name + Addend
    0000000000000007  0000000300000002 R_X86_64_PC32          0000000000000000 .rodata - 4
    0000000000000011  0000000900000002 R_X86_64_PC32          0000000000000000 _ZSt4cout - 4
    0000000000000019  0000000a00000004 R_X86_64_PLT32         0000000000000000 _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc - 4
    0000000000000020  0000000c0000002a R_X86_64_REX_GOTPCRELX 0000000000000000 _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_ - 4
    000000000000002b  0000000d00000004 R_X86_64_PLT32         0000000000000000 _ZNSolsEPFRSoS_E - 4
    

    What are numeric values of the different R_* relocations?

    egrep 'define R_X86_64_(PC32|PLT32|REX_GOTPCRELX)' /usr/include/elf.h
    
    #define R_X86_64_PC32           2       /* PC relative 32 bit signed */
    #define R_X86_64_PLT32          4       /* 32 bit PLT address */
    #define R_X86_64_REX_GOTPCRELX  42      /* Load from 32 bit signed pc relative
    

    So the warning about 4 and 42 corresponds to the R_X86_64_PLT32 and R_X86_64_REX_GOTPCRELX relocations respectively.

    Why couldn't readelf apply PLT32 and REX_GOTPCRELX relocations?

    Because main.o is a relocatable object -- unlike main executable, it hasn't yet been fully linked yet, and where its .text section will end up is yet to be determined.

    And thus the addresses to which .text will be relocated once main.o is fully linked aren't yet known, so readelf can't display them.