Meaning of ELF64_R_SYM(rela->r_info)
Fangrui Song
i@maskray.me
Wed Apr 21 23:08:59 GMT 2021
On 2021-04-21, Peng Yu via Binutils wrote:
>To put this into more complete context, here is the assembly code that
>the a.o file is generated from.
>
>Besides the questions that I asked in the previous email, I also have
>other questions.
>
>Why "call" is used here? Isn't it better to use "call" in both the
>assembly code and the objdump output to make the result consistent?
>
>Also, this assembly code is not very human writable. For example, "s"
>definition is split into 5 lines. I am more familiar with nasm syntax,
>in which, the code can be written much short. Is the as syntax this
>verbose? Or it is because it is machine generated assembly code, it is
>OK to be verbose? What the equivalent more writable code looks like?
>
>"leaq" becomes "lea" in the objdump output which is exactly the
>opposite of the "call" case (as "q" is added by objdump disassembly).
>This is again confusing. Why is so? How to know when the -q version
>should be used when the non-q version should be used? Isn't it better
>to make them consistent throughout?
>
> .file "a.c"
> .text
> .globl s
> .section .rodata
> .align 8
> .type s, @object
> .size s, 14
>s:
> .string "Hello World2!"
>.LC0:
> .string "Hello World!"
> .text
> .globl main
> .type main, @function
>main:
>.LFB0:
> .cfi_startproc
> pushq %rbp
> .cfi_def_cfa_offset 16
> .cfi_offset 6, -16
> movq %rsp, %rbp
> .cfi_def_cfa_register 6
> leaq .LC0(%rip), %rdi
> call puts@PLT
> leaq s(%rip), %rdi
> call puts@PLT
> movl $0, %eax
> popq %rbp
> .cfi_def_cfa 7, 8
> ret
> .cfi_endproc
>.LFE0:
> .size main, .-main
> .ident "GCC: (Debian 10.2.1-6) 10.2.1 20210110"
> .section .note.GNU-stack,"",@progbits
>
>
>On Wed, Apr 21, 2021 at 12:28 PM Peng Yu <pengyu.ut@gmail.com> wrote:
>>
>> On 4/21/21, Nick Clifton <nickc@redhat.com> wrote:
>> > 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 readelf -WS output should give the meaning of the symbol index 5.
It is a section symbol (STT_SECTION) whose st_shndx is the index into
the section header table. The section is .rodata
>> > 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.
>>
>> I don't understand the -4 part. Could you show me the definition of CALLQ?
>>
>> > 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
>>
>> Here is the `objdump -dr` output of a.o and a.out of the two-puts c file.
The relocation (r_offset: 0xa) modifies the bytes from 0xa to 0xd.
x86 lets a relocation start at the first byte the relocation applies.
On RISC architectures a common convention is to use the first byte of
the containing instruction.
As of `callq e`, objdump disassembles the instruction without taking
into consideration of potential linker effects wrt the relocation.
The raw e8 00 00 00 00 decodes to a call to the next instruction, which
is `callq 0xe` in this case. objdump on many architectures omit the 0x
prefix.
>> `# b <main+0xb>` and `# 17 <main+0x17>` add no information, as they
>> appear to be just the addresses of the next instructions? So I can
>> just ignore them?
>>
>> The numbers "10" and "1c" in "callq 10" and "callq 1c" just mean
>> that upon returning from callq, the next instruction to run is at
>> address 10 and 1c? They are derived by the disassembly (as in the
>> binary, the addresses are just zero)?
>>
>> "7: R_X86_64_PC32 .rodata+0xa" is just a reitteration of the entries
>> in .rela.text "000000000007 000500000002 R_X86_64_PC32
>> 0000000000000000 .rodata + a"? So that it brings the relocation to the
>> context of the assembly code for easier reading?
>>
>> How "a" is derived? "Hello World!" starts at the 15th character
>> (indexed at 14) in .rodata. I don't understand how "a" is computed
>> from 14?
>>
>> $ readelf -x .rodata a.o
>>
>> Hex dump of section '.rodata':
>> 0x00000000 48656c6c 6f20576f 726c6432 21004865 Hello World2!.He
>> 0x00000010 6c6c6f20 576f726c 642100 llo World!.
>>
>> How 0xed6 in the output of a.out is derived from that of a.o? Could
>> you show the exact arithmetics? Thanks.
>>
>> $ objdump -dr a.o
>> ....
>> 0000000000000000 <main>:
>> 0: 55 push %rbp
>> 1: 48 89 e5 mov %rsp,%rbp
>> 4: 48 8d 3d 00 00 00 00 lea 0x0(%rip),%rdi # b <main+0xb>
>> 7: R_X86_64_PC32 .rodata+0xa
>> b: e8 00 00 00 00 callq 10 <main+0x10>
>> c: R_X86_64_PLT32 puts-0x4
>> 10: 48 8d 3d 00 00 00 00 lea 0x0(%rip),%rdi # 17 <main+0x17>
>> 13: R_X86_64_PC32 s-0x4
>> 17: e8 00 00 00 00 callq 1c <main+0x1c>
>> 18: R_X86_64_PLT32 puts-0x4
>> 1c: b8 00 00 00 00 mov $0x0,%eax
>> 21: 5d pop %rbp
>> 22: c3 retq
>> $ objdump -dr a.out
>> ...
>> 0000000000001030 <puts@plt>:
>> 1030: ff 25 e2 2f 00 00 jmpq *0x2fe2(%rip) # 4018
>> <puts@GLIBC_2.2.5>
>> 1036: 68 00 00 00 00 pushq $0x0
>> 103b: e9 e0 ff ff ff jmpq 1020 <.plt>
>> ...
>> 0000000000001135 <main>:
>> 1135: 55 push %rbp
>> 1136: 48 89 e5 mov %rsp,%rbp
>> 1139: 48 8d 3d d6 0e 00 00 lea 0xed6(%rip),%rdi # 2016 <s+0xe>
>> 1140: e8 eb fe ff ff callq 1030 <puts@plt>
>> 1145: 48 8d 3d bc 0e 00 00 lea 0xebc(%rip),%rdi # 2008 <s>
>> 114c: e8 df fe ff ff callq 1030 <puts@plt>
>> 1151: b8 00 00 00 00 mov $0x0,%eax
>> 1156: 5d pop %rbp
>> 1157: c3 retq
>> 1158: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
>> 115f: 00
>>
>> --
>> Regards,
>> Peng
>
>
>
>--
>Regards,
>Peng
More information about the Binutils
mailing list