Meaning of ELF64_R_SYM(rela->r_info)

Nick Clifton nickc@redhat.com
Wed Apr 21 16:27:00 GMT 2021


Hi Peng,

> What is "a" in ".rodata + a"? 

It is an offset, in hexadecimal.  So in this case "a" is 0xa or 10.

> What the offset refers to? I don't quite follow the document.

The offset is part of the relocation.  So for example:

 > Relocation section '.rela.text' at offset 0x248 contains 4 entries:
 >      Offset             Info             Type               Symbol's
 > Value  Symbol's Name + Addend
 > 0000000000000007  0000000500000002 R_X86_64_PC32
 > 0000000000000000 .rodata + a

This first relocation says that the operation R_X86_64_PC32 should be 
applied to the sum of the value of symbol .rodata and the constant 0xa 
and the result stored at an offset of 0x0000000000000007 in the .text 
section.

The operation to be applied and the symbol it uses are extracted from 
the r_info field of the the relocation.  The value to be added to the 
symbol is extracted from the r_addend field of the relocation, and the 
offset in the .text section into which the result is applied is taken 
from the r_offset field.


> Of the two "puts - 4", could anybody explain how
> r_offset is computed?

The *r_offset* field is computed by whichever tool create the object 
file.  Typically either the assembler or the compiler.  When the 
instruction to be affected by the relocation is added to a given 
section, the tool computes the offset of that instruction from the start 
of the section and places it into the r_offset field of the relocation.

The *r_addend* field is also computed by the tool that creates the 
object file.  The value is architecture and relocation specific, and 
generally speaking you need to be familiar with the instruction set of 
the processor in order to be able to understand the addends.

In your example the -4 comes from the fact that the CALLQ instruction 
biases the constant part of its operand by +4.  So if you want to branch 
to the "puts" function you need to store "puts -4" in the CALLQ instruction.

As an aside you may find it helpful to use the objdump tool to see more 
about relocations.  If you combine its disassembly output with its 
relocation output you can see the instructions to which relocs refer:

   $ objdump -dr hello.o
   [...]
    9:	e8 00 00 00 00       	callq  e <main+0xe>
			a: R_X86_64_PLT32	puts-0x4

Cheers
   Nick









> "r_offset indicates the location at which the relocation should be
> applied. For a relocatable file, this is the offset, in bytes, from
> the beginning of the section to the beginning of the storage unit
> being relocated."
> 
> What is - 4 in "puts - 4" and "s - 4"? Why are they all "-4"?
> 
> $ cat a.c
> #include <stdio.h>
> const char s[] = "Hello World2!";
> int main() {
>    puts("Hello World!");
>    puts(s);
> }
> $ readelf -rW a.o
> 
> Relocation section '.rela.text' at offset 0x248 contains 4 entries:
>      Offset             Info             Type               Symbol's
> Value  Symbol's Name + Addend
> 0000000000000007  0000000500000002 R_X86_64_PC32
> 0000000000000000 .rodata + a
> 000000000000000c  0000000c00000004 R_X86_64_PLT32
> 0000000000000000 puts - 4
> 0000000000000013  0000000900000002 R_X86_64_PC32          0000000000000000 s - 4
> 0000000000000018  0000000c00000004 R_X86_64_PLT32
> 0000000000000000 puts - 4
> 
> Relocation section '.rela.eh_frame' at offset 0x2a8 contains 1 entry:
>      Offset             Info             Type               Symbol's
> Value  Symbol's Name + Addend
> 0000000000000020  0000000200000002 R_X86_64_PC32
> 0000000000000000 .text + 0
> $ readelf -s a.o
> 
> Symbol table '.symtab' contains 13 entries:
>     Num:    Value          Size Type    Bind   Vis      Ndx Name
>       0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
>       1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS a.c
>       2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1
>       3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3
>       4: 0000000000000000     0 SECTION LOCAL  DEFAULT    4
>       5: 0000000000000000     0 SECTION LOCAL  DEFAULT    5
>       6: 0000000000000000     0 SECTION LOCAL  DEFAULT    7
>       7: 0000000000000000     0 SECTION LOCAL  DEFAULT    8
>       8: 0000000000000000     0 SECTION LOCAL  DEFAULT    6
>       9: 0000000000000000    14 OBJECT  GLOBAL DEFAULT    5 s
>      10: 0000000000000000    35 FUNC    GLOBAL DEFAULT    1 main
>      11: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND _GLOBAL_OFFSET_TABLE_
>      12: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND puts
> 
> On 4/21/21, Nick Clifton <nickc@redhat.com> wrote:
>> Hi Peng,
>>
>>> I see ELF64_R_SYM(rela->r_info) are 00000005 and 0000000b
>>> respectively. I don't find what they refer to.
>>
>> You have already discovered this:
>>
>>> "r_info contains both a symbol table index and a relocation type. The
>>> symbol table index identifies the symbol whose value should be used in
>>> the relocation."
>>
>> So a value of 00000005 refers to the 5th entry in the symbol table
>> associated with the relocation section that contains the reloc.
>> Similarly 0000000b refers to the 11th entry in the symbol table.
>>
>>
>>>       Offset             Info             Type               Symbol's
>>> Value  Symbol's Name + Addend
>>> 0000000000000007  0000000500000002 R_X86_64_PC32
>>> 0000000000000000 .rodata - 4
>>> 000000000000000c  0000000b00000004 R_X86_64_PLT32
>>> 0000000000000000 puts - 4
>>
>> So readelf has decoded symbol index 5 and displayed ".rodata" and symbol
>> index 11 and displayed "puts".
>>
>>
>>> But I checked the symbol table and I don't think 00000005 and 0000000b
>>> have anything to do with this table.
>>
>> But they do:
>>
>>>        5: 0000000000000000     0 SECTION LOCAL  DEFAULT    5
>>
>> Symbol 5 is a section symbol, so its name is the section name, ie .rodata.
>>
>>>       11: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND puts
>>
>> And here is the "puts" symbol.
>>
>>
>>> Also for 00000002 and 00000004 (the lower half of Info), they just
>>> refer to R_X86_64_PC32 and R_X86_64_PLT32. Why showing the same info
>>> twice in the output of readelf -rW? Why not just show it once?
>>
>> It is done this way in order to help debug problems.  The raw value of
>> the info field is displayed so that users can see the actual value, and
>> then the decoded data (symbol name + relocation name + offset) is
>> displayed so that the value can be easily interpreted.  Users *could*
>> interpret the raw value themselves, but it can be a chore, and it is
>> simple for readelf to perform that task.
>>
>> Cheers
>>     Nick
>>
>> PS. A very recent update to readelf has changed the display of section
>> symbols in the symbol table. so that they now show the section name,
>> instead of just a blank space.
>>
>>
> 
> 



More information about the Binutils mailing list