[U-Boot] Relocation size penalty calculation

Joakim Tjernlund
2009-10-17T12:32:05Z

Graeme Russ <graeme.russ@gmail.com> wrote on 17/10/2009 07:17:04:
>

[SNIP]

>
> Apologies if this is getting way off-topic for a simple boot loader, but
> this is information I have gathered from far and wide over the net. I am
> surprised that there isn't a web site out there on 'How to create a
> relocatable boot loader'...

:), now you can write one :)

>
> OK, its all starting to come together now - It helps when you look at the
> right files ;)
>
> Firstly, u-boot.map
>
> 0x380589a0 __rel_dyn_start = .
>
> .rel.dyn 0x380589a0 0x42b0
> *(.rel.dyn)
> .rel.got 0x00000000 0x0 cpu/i386/start.o
> .rel.plt 0x00000000 0x0 cpu/i386/start.o
> .rel.text 0x380589a0 0x2e28 cpu/i386/start.o
> .rel.start16 0x3805b7c8 0x10 cpu/i386/start.o
> .rel.data 0x3805b7d8 0xc18 cpu/i386/start.o
> .rel.rodata 0x3805c3f0 0x360 cpu/i386/start.o
> .rel.u_boot_cmd
> 0x3805c750 0x500 cpu/i386/start.o
> 0x3805cc50 __rel_dyn_end = .
>
>
> And the output of readelf...
>
> Section Headers:
> [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
> [ 0] NULL 00000000 000000 000000 00 0 0 0
> [ 1] .text PROGBITS 38040000 001000 0118a4 00 AX 0 0 4
> [ 2] .rel.text REL 00000000 066c68 005d00 08 40 1 4
> [ 3] .rodata PROGBITS 380518a4 0128a4 005da5 00 A 0 0 4
> [ 4] .rel.rodata REL 00000000 06c968 000360 08 40 3 4
> [ 5] .interp PROGBITS 38057649 018649 000013 00 A 0 0 1
> [ 6] .dynstr STRTAB 3805765c 01865c 0001ee 00 A 0 0 1
> [ 7] .hash HASH 3805784c 01884c 0000cc 04 A 11 0 4
> [ 8] .data PROGBITS 38057918 018918 000a3c 00 WA 0 0 4
> [ 9] .rel.data REL 00000000 06ccc8 000c18 08 40 8 4
> [10] .got.plt PROGBITS 38058354 019354 00000c 04 WA 0 0 4
> [11] .dynsym DYNSYM 38058360 019360 000200 10 A 6 1 4
> [12] .dynamic DYNAMIC 38058560 019560 000080 08 WA 6 0 4
> [13] .u_boot_cmd PROGBITS 380585e0 0195e0 0003c0 00 WA 0 0 4
> [14] .rel.u_boot_cmd REL 00000000 06d8e0 000500 08 40 13 4
> [15] .bss NOBITS 3805cc50 01ec50 001a34 00 WA 0 0 4
> [16] .bios PROGBITS 00000000 01e000 00053e 00 AX 0 0 1
> [17] .rel.bios REL 00000000 06dde0 0000c0 08 40 16 4
> [18] .rel.dyn REL 380589a0 0199a0 0042b0 08 A 11 0 4
> [19] .start16 PROGBITS 0000f800 01e800 000110 00 AX 0 0 1
> [20] .rel.start16 REL 00000000 06dea0 000038 08 40 19 4
> [21] .resetvec PROGBITS 0000fff0 01eff0 000010 00 AX 0 0 1
> [22] .rel.resetvec REL 00000000 06ded8 000008 08 40 21 4
>
> ...
>
> Relocation section '.rel.text' at offset 0x66c68 contains 2976 entries:
> Offset Info Type Sym.Value Sym. Name
> 38040010 00000101 R_386_32 38040000 .text
> 3804001e 00000101 R_386_32 38040000 .text
> 38040028 00000101 R_386_32 38040000 .text
> 3804003f 00000101 R_386_32 38040000 .text
> 38040051 00000101 R_386_32 38040000 .text
> 38040075 00000101 R_386_32 38040000 .text
> 38040085 00000101 R_386_32 38040000 .text
> 3804009d 0003e602 R_386_PC32 380403fa load_uboot
> 380400a6 00000101 R_386_32 38040000 .text
> 38040015 00029f02 R_386_PC32 3804bdd8 early_board_init
> 38040023 0003f702 R_386_PC32 3804bdda show_boot_progress_asm
>
> ...
>
> Relocation section '.rel.rodata' at offset 0x6c968 contains 108 entries:
> Offset Info Type Sym.Value Sym. Name
> 38051908 00000201 R_386_32 380518a4 .rodata
> 38051938 00000201 R_386_32 380518a4 .rodata
> 38051968 00000201 R_386_32 380518a4 .rodata
> 38051998 00000201 R_386_32 380518a4 .rodata
> 380519c8 00000201 R_386_32 380518a4 .rodata
> 380519f8 00000201 R_386_32 380518a4 .rodata
>
> ...
>
> Relocation section '.rel.dyn' at offset 0x199a0 contains 2134 entries:
> Offset Info Type Sym.Value Sym. Name
> 0000f838 00000008 R_386_RELATIVE
> 0000f846 00000008 R_386_RELATIVE
> 38040010 00000008 R_386_RELATIVE
> 3804001e 00000008 R_386_RELATIVE
> 38040028 00000008 R_386_RELATIVE
> 3804003f 00000008 R_386_RELATIVE
> 38040051 00000008 R_386_RELATIVE
> 38040075 00000008 R_386_RELATIVE
> 38040085 00000008 R_386_RELATIVE
>
> Notice that, apart from .rel.dyn, non of the .rel.* sections have the
> A (Allocated) flag set - They do not end up in the stripped binary image.
> .rel.dyn is allocated in the binary image with all the R_386_PC32 entries
> from the other .rel section are discarded and the R_386_32 have been
> 'converted' to R_386_RELATIVE which are simple to adjust (locate in memory
> and adjust by the relocation offset)

Ah, they are converted to relative. Wonder if all archs do this?
If so one only will need two reloc functions, one for Rel and
one for Rela relocs.

>
> The relocation fixup is really easy:
>
> Elf32_Rel *rel_dyn_start = (Elf32_Rel *)&__rel_dyn_start;
> Elf32_Rel *rel_dyn_end = (Elf32_Rel *)&__rel_dyn_end;
> Elf32_Rel *re;
>
> for (re = rel_dyn_start; re < rel_dyn_end; re++)
> {
> if (re->r_offset >= TEXT_BASE)
> if (*(ulong *)re->r_offset >= TEXT_BASE)
> *(ulong *)(re->r_offset - rel_offset) -= (Elf32_Addr)rel_offset;
> }

Do you need the TEXT_BASE stuff or is it just a precaution?
Not sure if you need some test for NULL to handle weak undefined symbols though.

> The size penalty is ~17kB of extra data (which is not copied to RAM) and
> a tiny amount of relocation code (easily offset by removal of other fixups
> such as the command table fixup

17kB, how does that compare to the -fPIC version?

>
> Any without using the pic flag in gcc, there is no GOT and no associated
> performance penalty.

Yep :)

>
> Thanks for everyone's help (especially Jocke and Bill)

NP, will we see a patch soon?

Jocke