[U-Boot] Relocation size penalty calculation
J. William Campbell
jwilliamcampbell at comcast.net
Wed Oct 14 18:45:06 CEST 2009
Joakim Tjernlund wrote:
> Graeme Russ <graeme.russ at gmail.com> wrote on 14/10/2009 13:48:27:
>
>> On Wed, Oct 14, 2009 at 6:25 PM, Joakim Tjernlund
>> <joakim.tjernlund at transmode.se> wrote:
>>
>>> "J. William Campbell" <jwilliamcampbell at comcast.net> wrote on 14/10/2009 01:48:52:
>>>
>>>> Joakim Tjernlund wrote:
>>>>
>>>>> Graeme Russ <graeme.russ at gmail.com> wrote on 13/10/2009 22:06:56:
>>>>>
>>>>>
>>>>>
>>>>>> On Tue, Oct 13, 2009 at 10:53 PM, Joakim Tjernlund
>>>>>> <joakim.tjernlund at transmode.se> wrote:
>>>>>>
>>>>>>
>>>>>>> Graeme Russ <graeme.russ at gmail.com> wrote on 13/10/2009 13:21:05:
>>>>>>>
>>>>>>>
>>>>>>>> On Sun, Oct 11, 2009 at 11:51 PM, Joakim Tjernlund
>>>>>>>> <joakim.tjernlund at transmode.se> wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>>> Graeme Russ <graeme.russ at gmail.com> wrote on 11/10/2009 12:47:19:
>>>>>>>>>
>>>>>>>>>
>>>>>>>> [Massive Snip :)]
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>>> So, all that is left are .dynsym and .dynamic ...
>>>>>>>>>> .dynsym
>>>>>>>>>> - Contains 70 entries (16 bytes each, 1120 bytes)
>>>>>>>>>> - 44 entries mimic those entries in .got which are not relocated
>>>>>>>>>> - 21 entries are the remaining symbols exported from the linker
>>>>>>>>>> script
>>>>>>>>>> - 4 entries are labels defined in inline asm and used in C
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>> Try adding proper asm declarations. Look at what gcc
>>>>>>>>> generates for a function/variable and mimic these.
>>>>>>>>>
>>>>>>>>>
>>>>>>>> Thanks - Now .dynsym contains only exports from the linker script
>>>>>>>>
>>>>>>>>
>>>>>>> :)
>>>>>>>
>>>>>>>
>>>>>>>>>> - 1 entry is a NULL entry
>>>>>>>>>>
>>>>>>>>>> .dynamic
>>>>>>>>>> - 88 bytes
>>>>>>>>>> - Array of Elf32_Dyn
>>>>>>>>>> - typedef struct {
>>>>>>>>>> Elf32_Sword d_tag;
>>>>>>>>>> union {
>>>>>>>>>> Elf32_Word d_val;
>>>>>>>>>> Elf32_Addr d_ptr;
>>>>>>>>>> } d_un;
>>>>>>>>>> } Elf32_Dyn;
>>>>>>>>>> - 0x11 entries
>>>>>>>>>> [00] 0x00000010, 0x00000000 DT_SYMBOLIC, (ignored)
>>>>>>>>>> [01] 0x00000004, 0x38059994 DT_HASH, points to .hash
>>>>>>>>>> [02] 0x00000005, 0x380595AB DT_STRTAB, points to .dynstr
>>>>>>>>>> [03] 0x00000006, 0x3805BDCC DT_SYMTAB, points to .dynsym
>>>>>>>>>> [04] 0x0000000A, 0x000003E6 DT_STRSZ, size of .dynstr
>>>>>>>>>> [05] 0x0000000B, 0x00000010 DT_SYMENT, ???
>>>>>>>>>> [06] 0x00000015, 0x00000000 DT_DEBUG, ???
>>>>>>>>>> [07] 0x00000011, 0x3805A8F4 DT_REL, points to .rel.text
>>>>>>>>>> [08] 0x00000012, 0x000014D8 DT_RELSZ, ???
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>> How big DT_REL is
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>> [09] 0x00000013, 0x00000008 DT_RELENT, ???
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>> hmm, cannot remeber :)
>>>>>>>>>
>>>>>>>>>
>>>>>>>> How big an entry in DT_REL is
>>>>>>>>
>>>>>>>>
>>>>>>> Right, how could I forget :)
>>>>>>>
>>>>>>>
>>>>>>>>>> [0a] 0x00000016, 0x00000000 DT_TEXTREL, ???
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>> Oops, you got text relocations. This is generally a bad thing.
>>>>>>>>> TEXTREL is commonly caused by asm code that arent truly pic so it needs
>>>>>>>>> to modify the .text segment to adjust for relocation.
>>>>>>>>> You should get rid of this one. Look for DT_TEXTREL in .o files to find
>>>>>>>>> the culprit.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>> Alas I cannot - The relocations are a result of loading a register with a
>>>>>>>> return address when calling show_boot_progress in the very early stages of
>>>>>>>> initialisation prior to the stack becoming available. The x86 does not
>>>>>>>> allow direct access to the IP so the only way to find the 'current
>>>>>>>> execution address' is to 'call' to the next instruction and pop the return
>>>>>>>> address off the stack
>>>>>>>>
>>>>>>>>
>>>>>>> hmm, same as ppc but that in it self should not cause a TEXREL, should it?
>>>>>>> Ahh, the 'call' is absolute, not relative? I guess there is some way around it
>>>>>>> but it is not important ATM I guess.
>>>>>>>
>>>>>>> Evil idea, skip -fpic et. all and add the full reloc procedure
>>>>>>> to relocate by rewriting directly in TEXT segment. Then you save space
>>>>>>> but you need more relocation code. Something like dl_do_reloc from
>>>>>>> uClibc. Wonder how much extra code that would be? Not too much I think.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>> With the following flags
>>>>>>
>>>>>> PLATFORM_RELFLAGS += -fvisibility=hidden
>>>>>> PLATFORM_CPPFLAGS += -fno-dwarf2-cfi-asm
>>>>>> PLATFORM_LDFLAGS += -pic --emit-relocs -Bsymbolic -Bsymbolic-functions
>>>>>>
>>>>>> I get no .got, but a lot of R_386_PC32 and R_386_32 relocations. I think
>>>>>> this might mean I need the symbol table in the binary in order to resolve
>>>>>> them
>>>>>>
>>>>>>
>>> BTW, how many relocs do you get compared with -fPIC? I suspect you more
>>> now but hopefully not that many more.
>>>
>>>
>>>>> Possibly, but I think you only need to add an offset to all those
>>>>> relocs.
>>>>>
>>>>>
>>>> Almost right. The relocations specify a symbol value that needs to be
>>>> added to the data in memory to relocate the reference. The symbol values
>>>> involved should be the start of the text section for program references,
>>>> the start of the uninitialized data section for bss references, and the
>>>> start of the data section for initialized data and constants. So there
>>>> are about four symbols whose value you need to keep. Take a look at
>>>> http://refspecs.freestandards.org/elf/elf.pdf (which you have probably
>>>> already looked at) and it tells you what to do with R_386_PC32 ad
>>>> R_386_32 relocations. Hopefully the objcopy with the --strip-unneeded
>>>> will remove all the symbols you don't actually need, but I don't know
>>>> that for sure. Note also that you can change the section flags of a
>>>> section marked noload to load.
>>>>
>>> Still think you can get away with just ADDING an offset. The image is linked to a
>>> specific address and then you move the whole image to a new address. Therefore
>>> you should be able to read the current address, add offset, write back the
>>>
>> new address.
>>
>> OK, I don't really get this at all....
>>
>> This code:
>>
>> printf ("\n\n%s\n\n", version_string);
>>
>> gets compiled into:
>>
>> 380403e7: 68 a4 18 05 38 push $0x380518a4
>> 380403ec: 68 de 2c 05 38 push $0x38052cde
>> 380403f1: e8 4f 84 00 00 call 38048845 <printf>
>>
>> With relocation entries in .rel.text of:
>>
>> Offset Info Type Sym.Value Sym. Name
>> 380403e8 00016201 R_386_32 380519f0 version_string
>> 380403ed 00000201 R_386_32 380519f0 .rodata
>> 380403f2 00016b02 R_386_PC32 38048991 printf
>>
>> Now I get the first two (R_386_32) entries - Relocation involves a simple
>> addition of an offset to the values at addresses 0x380403e8 and 0x380403ed
>> (of course, these addresses will be offset)
>>
>> However, the R_386_PC32 is an enigma - The call is already relative -
>> there is no need to relocate it at all (call is a position independent
>> opcode because it is a relative jump!)
>>
>
> Yes, but printf is defined in glibc så the app needs to relocate the call
> to glibc.
Actually, the reason the call is relocatable is that the compiler
DOESN'T KNOW where printf is at all. If it is in a library, it will not
be in the text segment and must be relocated accordingly. It may be in
a different segment for some reason. In any case, the compiler doesn't
know the address in the image where printf resides, so it needs a
relocation entry to get the value filled in at link time. After the
value is filled in, if the referenced symbol is in the same segment
(probably .text) as the point of reference, the relocation reference is
probably of no more use. However, there is no rule that says the linker
must delete the reference from the relocation list.
> U-boot has all it needs so there you should not have PC32 I think.
> Try defining a local static function. For non static functions
> you may need to define visibility=hidden and/or -Bsymbolic too.
>
Won't help. Any symbols referenced but not defined locally are
relocatable. After linking, they MAY, but need not, go away.
> You also need to look at the img after final linking.
>
After linking, if the symbol is defined, the R_386_PC32 is no longer
important UNLESS the symbol referenced is in a different segment AND the
segments are relocated with different offsets from each other than
originally linked. For this reason, I think the linker will not discard
these relocations. If we are not relocating the segments with different
relative offsets, we can ignore these relocations as the change in
offset will come out to be zero anyway. However, if you process them
normally, you will just add 0 and nothing will change.
>
>> Will all R_386_PC32 be like this? Can I simply ignore them all? If so, why
>> do they even need to be generated?
>>
>
> Hopefully you won't have any.
I think they may still be there, because we ask the linker to preserve
relocation information. However, if the entire image is being relocated,
not changing the order or relative offset of any segments, they can be
ignored, because the relative values will not change. It will be
interesting to know if they remain or if the linker drops them out. For
references in the same segment, we can hope that they get dropped. For
references across segments (if any), or any undefined symbols, they will
remain.
> Not sure about weak functions though. These might
> need PC32 relocs in some cases.
>
There can be PC32 relocs referencing the weak symbol, but that symbol
may be undefined.
> Also, if you look at _dl_do_reloc() in uClibc/ldso/ldso/i386/elfinterp.c I think
> you can replace symbol_addr with relocation offset.
>
I agree, in the case you a moving the entire image and ignoring PC32 relocs.
Best Regards,
Bill Campbell
> Jocke
>
>
>
>
>
More information about the U-Boot
mailing list