[U-Boot] [PATCH v1 0/7] MIPS: add dynamic relocation support

From: Daniel Schwierzeck daniel.schwierzeck@gmail.com
This series adds dynamic relocation support for MIPS. Furthermore the symbols in u-boot.lds are cleaned up and synchronized with ARM to prepare for future patches like generic board and initcall support.
Special thanks to Gabor Juhos for the initial patches.
This patch series is also available at: git://git.denx.de/u-boot-mips.git reloc
Daniel Schwierzeck (5): MIPS: u-boot.lds: merge all BSS sections and introduce symbols __bss_[start|end] MIPS: u-boot.lds: introduce symbol __image_copy_end MIPS: board.c: switch to new symbols __bss_end and __image_copy_end MIPS: start.S: optimize BSS initialization MIPS: start.S: use symbol __image_copy_end for U-Boot image relocation
Gabor Juhos (2): MIPS: u-boot.lds: add relocation specific sections MIPS: add dynamic relocation support
arch/mips/config.mk | 3 +- arch/mips/cpu/mips32/start.S | 55 ++++++++++++++++++++++++-------- arch/mips/cpu/mips64/start.S | 63 +++++++++++++++++++++++++++++-------- arch/mips/cpu/u-boot.lds | 35 ++++++++++++++++----- arch/mips/cpu/xburst/start.S | 56 +++++++++++++++++++++++++-------- arch/mips/include/asm/config.h | 2 -- arch/mips/include/asm/u-boot-mips.h | 19 +++++++++-- arch/mips/lib/board.c | 14 ++------- 8 files changed, 185 insertions(+), 62 deletions(-)

From: Daniel Schwierzeck daniel.schwierzeck@gmail.com
These symbols are used in later patches for as addresses for clearing the BSS area in the relocated U-Boot image.
Signed-off-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com --- arch/mips/cpu/u-boot.lds | 11 ++++++----- arch/mips/include/asm/u-boot-mips.h | 12 ++++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/arch/mips/cpu/u-boot.lds b/arch/mips/cpu/u-boot.lds index 58a49b2..6980b86 100644 --- a/arch/mips/cpu/u-boot.lds +++ b/arch/mips/cpu/u-boot.lds @@ -70,13 +70,14 @@ SECTIONS uboot_end_data = .;
. = ALIGN(4); - .sbss : { - *(.sbss*) - } - .bss : { - *(.bss*) + __bss_start = .; + *(.sbss.*) + *(.bss.*) + *(COMMON) . = ALIGN(4); + __bss_end = .; } + uboot_end = .; } diff --git a/arch/mips/include/asm/u-boot-mips.h b/arch/mips/include/asm/u-boot-mips.h index 6f26dfa..eda0498 100644 --- a/arch/mips/include/asm/u-boot-mips.h +++ b/arch/mips/include/asm/u-boot-mips.h @@ -8,4 +8,16 @@ extern ulong uboot_end_data; extern ulong uboot_end;
+static inline unsigned long bss_start(void) +{ + extern ulong __bss_start; + return (unsigned long) &__bss_start; +} + +static inline unsigned long bss_end(void) +{ + extern ulong __bss_end; + return (unsigned long) &__bss_end; +} + extern int incaip_set_cpuclk(void);

From: Daniel Schwierzeck daniel.schwierzeck@gmail.com
This symbol is used in later patches as end address for relocation of the U-Boot image into RAM.
Signed-off-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com --- arch/mips/cpu/u-boot.lds | 2 ++ arch/mips/include/asm/u-boot-mips.h | 6 ++++++ 2 files changed, 8 insertions(+)
diff --git a/arch/mips/cpu/u-boot.lds b/arch/mips/cpu/u-boot.lds index 6980b86..7b5fca0 100644 --- a/arch/mips/cpu/u-boot.lds +++ b/arch/mips/cpu/u-boot.lds @@ -70,6 +70,8 @@ SECTIONS uboot_end_data = .;
. = ALIGN(4); + __image_copy_end = .; + .bss : { __bss_start = .; *(.sbss.*) diff --git a/arch/mips/include/asm/u-boot-mips.h b/arch/mips/include/asm/u-boot-mips.h index eda0498..bfb6a4a 100644 --- a/arch/mips/include/asm/u-boot-mips.h +++ b/arch/mips/include/asm/u-boot-mips.h @@ -20,4 +20,10 @@ static inline unsigned long bss_end(void) return (unsigned long) &__bss_end; }
+static inline unsigned long image_copy_end(void) +{ + extern ulong __image_copy_end; + return (unsigned long) &__image_copy_end; +} + extern int incaip_set_cpuclk(void);

From: Daniel Schwierzeck daniel.schwierzeck@gmail.com
Use the newly introduced symbols __image_copy_end and __bss_end for setting up the memory area for the relocated U-Boot.
Signed-off-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com --- arch/mips/lib/board.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/mips/lib/board.c b/arch/mips/lib/board.c index d79e183..d494876 100644 --- a/arch/mips/lib/board.c +++ b/arch/mips/lib/board.c @@ -143,7 +143,7 @@ void board_init_f(ulong bootflag) gd_t gd_data, *id; bd_t *bd; init_fnc_t **init_fnc_ptr; - ulong addr, addr_sp, len = (ulong)&uboot_end - CONFIG_SYS_MONITOR_BASE; + ulong addr, addr_sp, len; ulong *s;
/* Pointer is writable since we allocated a register for it. @@ -176,6 +176,7 @@ void board_init_f(ulong bootflag) /* Reserve memory for U-Boot code, data & bss * round down to next 16 kB limit */ + len = bss_end() - CONFIG_SYS_MONITOR_BASE; addr -= len; addr &= ~(16 * 1024 - 1);
@@ -261,7 +262,7 @@ void board_init_r(gd_t *id, ulong dest_addr)
gd->reloc_off = dest_addr - CONFIG_SYS_MONITOR_BASE;
- monitor_flash_len = (ulong)&uboot_end_data - dest_addr; + monitor_flash_len = image_copy_end() - dest_addr;
serial_initialize();

From: Daniel Schwierzeck daniel.schwierzeck@gmail.com
Get the start and end address for clearing BSS from the newly introduced symbols __bss_start and __bss_end. After GOT is relocated, those symbols are already pointing to the correct addresses.
Also optimize the loop by moving the address incrementation to the delay slot to avoid the initial sub instruction.
Signed-off-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com --- arch/mips/cpu/mips32/start.S | 20 +++++++++++--------- arch/mips/cpu/mips64/start.S | 20 +++++++++++--------- arch/mips/cpu/xburst/start.S | 23 +++++++++++++---------- 3 files changed, 35 insertions(+), 28 deletions(-)
diff --git a/arch/mips/cpu/mips32/start.S b/arch/mips/cpu/mips32/start.S index 7373d4e..cd8b914 100644 --- a/arch/mips/cpu/mips32/start.S +++ b/arch/mips/cpu/mips32/start.S @@ -228,17 +228,19 @@ in_ram: blt t2, t3, 1b addi t4, 4
- /* Clear BSS */ - lw t1, -12(t0) # t1 <-- uboot_end_data - lw t2, -8(t0) # t2 <-- uboot_end - add t1, s1 # adjust pointers - add t2, s1 + /* + * Clear BSS + * + * GOT is now relocated. Thus __bss_start and __bss_end can be + * accessed directly via $gp. + */ + la t1, __bss_start # t1 <-- __bss_start + la t2, __bss_end # t2 <-- __bss_end
- sub t1, 4 1: - addi t1, 4 - bltl t1, t2, 1b - sw zero, 0(t1) + sw zero, 0(t1) + blt t1, t2, 1b + addi t1, 4
move a0, s0 # a0 <-- gd la t9, board_init_r diff --git a/arch/mips/cpu/mips64/start.S b/arch/mips/cpu/mips64/start.S index c0ae41a..ba4ca4d 100644 --- a/arch/mips/cpu/mips64/start.S +++ b/arch/mips/cpu/mips64/start.S @@ -220,17 +220,19 @@ in_ram: blt t2, t3, 1b daddi t8, 8
- /* Clear BSS */ - ld t1, -24(t0) # t1 <-- uboot_end_data - ld t2, -16(t0) # t2 <-- uboot_end - dadd t1, s1 # adjust pointers - dadd t2, s1 + /* + * Clear BSS + * + * GOT is now relocated. Thus __bss_start and __bss_end can be + * accessed directly via $gp. + */ + dla t1, __bss_start # t1 <-- __bss_start + dla t2, __bss_end # t2 <-- __bss_end
- dsub t1, 8 1: - daddi t1, 8 - bltl t1, t2, 1b - sd zero, 0(t1) + sd zero, 0(t1) + blt t1, t2, 1b + daddi t1, 8
move a0, s0 # a0 <-- gd dla t9, board_init_r diff --git a/arch/mips/cpu/xburst/start.S b/arch/mips/cpu/xburst/start.S index 50b7fb1..bd9390a 100644 --- a/arch/mips/cpu/xburst/start.S +++ b/arch/mips/cpu/xburst/start.S @@ -143,16 +143,19 @@ in_ram: blt t2, t3, 1b addi t4, 4
- /* Clear BSS */ - lw t1, -12(t0) # t1 <-- uboot_end_data - lw t2, -8(t0) # t2 <-- uboot_end - add t1, t6 # adjust pointers - add t2, t6 - - sub t1, 4 -1: addi t1, 4 - bltl t1, t2, 1b - sw zero, 0(t1) + /* + * Clear BSS + * + * GOT is now relocated. Thus __bss_start and __bss_end can be + * accessed directly via $gp. + */ + la t1, __bss_start # t1 <-- __bss_start + la t2, __bss_end # t2 <-- __bss_end + +1: + sw zero, 0(t1) + blt t1, t2, 1b + addi t1, 4
move a0, a1 # a0 <-- gd la t9, board_init_r

From: Daniel Schwierzeck daniel.schwierzeck@gmail.com
Use the newly introduced symbol __image_copy_end as end address for relocation of U-Boot image. This is needed for dynamic relocation added in later patches. This patch obsoletes the symbols uboot_end and uboot_end_data which are removed.
Signed-off-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com --- arch/mips/cpu/mips32/start.S | 7 +++---- arch/mips/cpu/mips64/start.S | 7 +++---- arch/mips/cpu/u-boot.lds | 4 ---- arch/mips/cpu/xburst/start.S | 7 +++---- arch/mips/include/asm/u-boot-mips.h | 3 --- 5 files changed, 9 insertions(+), 19 deletions(-)
diff --git a/arch/mips/cpu/mips32/start.S b/arch/mips/cpu/mips32/start.S index cd8b914..649c0bb 100644 --- a/arch/mips/cpu/mips32/start.S +++ b/arch/mips/cpu/mips32/start.S @@ -173,7 +173,7 @@ relocate_code: sub s1, s2, t0 # s1 <-- relocation offset
la t3, in_ram - lw t2, -12(t3) # t2 <-- uboot_end_data + lw t2, -12(t3) # t2 <-- __image_copy_end move t1, a2
add gp, s1 # adjust gp @@ -201,9 +201,8 @@ relocate_code: jr t0 nop
+ .word __image_copy_end .word _GLOBAL_OFFSET_TABLE_ - .word uboot_end_data - .word uboot_end .word num_got_entries
in_ram: @@ -214,7 +213,7 @@ in_ram: * generated by GNU ld. Skip these reserved entries from relocation. */ lw t3, -4(t0) # t3 <-- num_got_entries - lw t4, -16(t0) # t4 <-- _GLOBAL_OFFSET_TABLE_ + lw t4, -8(t0) # t4 <-- _GLOBAL_OFFSET_TABLE_ add t4, s1 # t4 now holds relocated _G_O_T_ addi t4, t4, 8 # skipping first two entries li t2, 2 diff --git a/arch/mips/cpu/mips64/start.S b/arch/mips/cpu/mips64/start.S index ba4ca4d..5c2c7b5 100644 --- a/arch/mips/cpu/mips64/start.S +++ b/arch/mips/cpu/mips64/start.S @@ -165,7 +165,7 @@ relocate_code: dsub s1, s2, t0 # s1 <-- relocation offset
dla t3, in_ram - ld t2, -24(t3) # t2 <-- uboot_end_data + ld t2, -24(t3) # t2 <-- __image_copy_end move t1, a2
dadd gp, s1 # adjust gp @@ -193,9 +193,8 @@ relocate_code: jr t0 nop
+ .dword __image_copy_end .dword _GLOBAL_OFFSET_TABLE_ - .dword uboot_end_data - .dword uboot_end .dword num_got_entries
in_ram: @@ -206,7 +205,7 @@ in_ram: * generated by GNU ld. Skip these reserved entries from relocation. */ ld t3, -8(t0) # t3 <-- num_got_entries - ld t8, -32(t0) # t8 <-- _GLOBAL_OFFSET_TABLE_ + ld t8, -16(t0) # t8 <-- _GLOBAL_OFFSET_TABLE_ dadd t8, s1 # t8 now holds relocated _G_O_T_ daddi t8, t8, 16 # skipping first two entries dli t2, 2 diff --git a/arch/mips/cpu/u-boot.lds b/arch/mips/cpu/u-boot.lds index 7b5fca0..4cd983a 100644 --- a/arch/mips/cpu/u-boot.lds +++ b/arch/mips/cpu/u-boot.lds @@ -67,8 +67,6 @@ SECTIONS #include <u-boot.lst> }
- uboot_end_data = .; - . = ALIGN(4); __image_copy_end = .;
@@ -80,6 +78,4 @@ SECTIONS . = ALIGN(4); __bss_end = .; } - - uboot_end = .; } diff --git a/arch/mips/cpu/xburst/start.S b/arch/mips/cpu/xburst/start.S index bd9390a..6b30d3e 100644 --- a/arch/mips/cpu/xburst/start.S +++ b/arch/mips/cpu/xburst/start.S @@ -67,7 +67,7 @@ relocate_code: sub t6, a2, t0 # t6 <-- relocation offset
la t3, in_ram - lw t2, -12(t3) # t2 <-- uboot_end_data + lw t2, -12(t3) # t2 <-- __image_copy_end move t1, a2
add gp, t6 # adjust gp @@ -116,9 +116,8 @@ relocate_code: jr t0 nop
+ .word __image_copy_end .word _GLOBAL_OFFSET_TABLE_ - .word uboot_end_data - .word uboot_end .word num_got_entries
in_ram: @@ -129,7 +128,7 @@ in_ram: * generated by GNU ld. Skip these reserved entries from relocation. */ lw t3, -4(t0) # t3 <-- num_got_entries - lw t4, -16(t0) # t4 <-- _GLOBAL_OFFSET_TABLE_ + lw t4, -8(t0) # t4 <-- _GLOBAL_OFFSET_TABLE_ add t4, t6 # t4 now holds relocated _G_O_T_ addi t4, t4, 8 # skipping first two entries li t2, 2 diff --git a/arch/mips/include/asm/u-boot-mips.h b/arch/mips/include/asm/u-boot-mips.h index bfb6a4a..a483166 100644 --- a/arch/mips/include/asm/u-boot-mips.h +++ b/arch/mips/include/asm/u-boot-mips.h @@ -5,9 +5,6 @@ * Copyright (C) 2003 Wolfgang Denk, DENX Software Engineering, wd@denx.de */
-extern ulong uboot_end_data; -extern ulong uboot_end; - static inline unsigned long bss_start(void) { extern ulong __bss_start;

From: Gabor Juhos juhosg@openwrt.org
This section contain the table needed for dynamic relocation. Also provide symbols for the relocation code to access the table.
Discard all sections which are not needed in the final ELF binary and U-Boot image. Section .dynsym cannot be discarded or GNU ld crashes otherwise. This section will be stripped by GNU objcpy in a later patch.
Signed-off-by: Gabor Juhos juhosg@openwrt.org Signed-off-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com --- arch/mips/cpu/u-boot.lds | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/arch/mips/cpu/u-boot.lds b/arch/mips/cpu/u-boot.lds index 4cd983a..cea9533 100644 --- a/arch/mips/cpu/u-boot.lds +++ b/arch/mips/cpu/u-boot.lds @@ -70,7 +70,17 @@ SECTIONS . = ALIGN(4); __image_copy_end = .;
- .bss : { + .rel.dyn : { + __rel_dyn_start = .; + *(.rel.dyn) + __rel_dyn_end = .; + } + + .dynsym : { + *(.dynsym) + } + + .bss __rel_dyn_start (OVERLAY) : { __bss_start = .; *(.sbss.*) *(.bss.*) @@ -78,4 +88,16 @@ SECTIONS . = ALIGN(4); __bss_end = .; } + + /DISCARD/ : { + *(.dynbss) + *(.dynstr) + *(.dynamic) + *(.interp) + *(.hash) + *(.gnu.*) + *(.plt) + *(.got.plt) + *(.rel.plt) + } }

2013.02.09. 21:33 keltezéssel, daniel.schwierzeck@gmail.com írta:
From: Gabor Juhos juhosg@openwrt.org
This section contain the table needed for dynamic relocation. Also provide symbols for the relocation code to access the table.
Discard all sections which are not needed in the final ELF binary and U-Boot image. Section .dynsym cannot be discarded or GNU ld crashes otherwise. This section will be stripped by GNU objcpy in a later patch.
Signed-off-by: Gabor Juhos juhosg@openwrt.org Signed-off-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com
arch/mips/cpu/u-boot.lds | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/arch/mips/cpu/u-boot.lds b/arch/mips/cpu/u-boot.lds index 4cd983a..cea9533 100644 --- a/arch/mips/cpu/u-boot.lds +++ b/arch/mips/cpu/u-boot.lds @@ -70,7 +70,17 @@ SECTIONS . = ALIGN(4); __image_copy_end = .;
- .bss : {
- .rel.dyn : {
__rel_dyn_start = .;
*(.rel.dyn)
__rel_dyn_end = .;
- }
- .dynsym : {
*(.dynsym)
- }
This is not enough to avoid the binutils issue I have mentioned in the original patch. The issue is present after applying this series.
The following example comes from the qemu_mips target compiled with the ELDK 5.3 toolchain:
$ mips-linux-objdump --disassemble u-boot | grep bfc005[67] bfc00560: 00000000 nop bfc00564: bfc31f74 cache 0x3,8052(s8) <--- __rel_dyn_end
The offset of __rel_dyn_end: 0x0bfc31f74 - 0xbfc00000 = 0x31f74 = 204660
bfc00568: bfc30804 cache 0x3,2052(s8) bfc0056c: bfc30804 cache 0x3,2052(s8) bfc00570: bfc2fa70 cache 0x2,-1424(s8) bfc00574: 000001df 0x1df bfc00578 <in_ram>: bfc00578: 8d0bfffc lw t3,-4(t0) bfc0057c: 8d0cfff8 lw t4,-8(t0)
$ ls -l u-boot.bin -rw-r--r-- 1 juhosg root 204284 Feb 11 11:29 u-boot.bin
204660 - 204284 = 376 bytes are missing from the final u-boot.bin.
-Gabor

2013/2/11 Gabor Juhos juhosg@openwrt.org:
2013.02.09. 21:33 keltezéssel, daniel.schwierzeck@gmail.com írta:
From: Gabor Juhos juhosg@openwrt.org
This section contain the table needed for dynamic relocation. Also provide symbols for the relocation code to access the table.
Discard all sections which are not needed in the final ELF binary and U-Boot image. Section .dynsym cannot be discarded or GNU ld crashes otherwise. This section will be stripped by GNU objcpy in a later patch.
Signed-off-by: Gabor Juhos juhosg@openwrt.org Signed-off-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com
arch/mips/cpu/u-boot.lds | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/arch/mips/cpu/u-boot.lds b/arch/mips/cpu/u-boot.lds index 4cd983a..cea9533 100644 --- a/arch/mips/cpu/u-boot.lds +++ b/arch/mips/cpu/u-boot.lds @@ -70,7 +70,17 @@ SECTIONS . = ALIGN(4); __image_copy_end = .;
.bss : {
.rel.dyn : {
__rel_dyn_start = .;
*(.rel.dyn)
__rel_dyn_end = .;
}
.dynsym : {
*(.dynsym)
}
This is not enough to avoid the binutils issue I have mentioned in the original patch. The issue is present after applying this series.
The following example comes from the qemu_mips target compiled with the ELDK 5.3 toolchain:
$ mips-linux-objdump --disassemble u-boot | grep bfc005[67] bfc00560: 00000000 nop bfc00564: bfc31f74 cache 0x3,8052(s8) <--- __rel_dyn_end
The offset of __rel_dyn_end: 0x0bfc31f74 - 0xbfc00000 = 0x31f74 = 204660
bfc00568: bfc30804 cache 0x3,2052(s8) bfc0056c: bfc30804 cache 0x3,2052(s8) bfc00570: bfc2fa70 cache 0x2,-1424(s8) bfc00574: 000001df 0x1df bfc00578 <in_ram>: bfc00578: 8d0bfffc lw t3,-4(t0) bfc0057c: 8d0cfff8 lw t4,-8(t0)
$ ls -l u-boot.bin -rw-r--r-- 1 juhosg root 204284 Feb 11 11:29 u-boot.bin
204660 - 204284 = 376 bytes are missing from the final u-boot.bin.
-Gabor
that's weird. Actually I checked after each patch if the *_end symbols match the U-Boot binary size. Now I checked again with different toolchains (gcc-4.[5,6,7], binutils-2.[21.53,22] and I have again that binutils issue.
But all toolchains have one in common (tested with qemu_mips): __rel_dyn_end - __rel_dyn_start = 0x1770 size from readelf = 0x15f8
Another problem is that your .deadcode workaround does not work anymore for me. It does not matter how I arrange or drop the unneeded sections, the size of .rel.dyn remains at 0x1770. I'll try to find another solution.

that's weird. Actually I checked after each patch if the *_end symbols match the U-Boot binary size. Now I checked again with different toolchains (gcc-4.[5,6,7], binutils-2.[21.53,22] and I have again that binutils issue.
But all toolchains have one in common (tested with qemu_mips): __rel_dyn_end - __rel_dyn_start = 0x1770 size from readelf = 0x15f8
Another problem is that your .deadcode workaround does not work anymore for me. It does not matter how I arrange or drop the unneeded sections, the size of .rel.dyn remains at 0x1770. I'll try to find another solution.
Erm, the presence of the .deadcode section does not change the size of the .rel.dyn section.
The ELF headers shows that there is a gap between the .rel.dyn and the .deadcode section:
[ 6] .rel.dyn REL bfc30804 030864 0015f8 08 A 8 0 4 [ 7] .deadcode PROGBITS bfc31f74 031fd4 000004 00 WA 0 0 1
However objcopy will copy the .deadcode section into the final binary because it is placed after the .rel.dyn section, and the gap will be filled with 0xff bytes.
As a result, the size of u-boot.bin will equal to (__rel_dyn_end - __start + 4), and this ensures that it will contain the full .rel.dyn section.
$ ls -l u-boot.bin -rw-r--r-- 1 juhosg root 204664 Feb 11 14:46 u-boot.bin
This is with the attached patch applied on top of the mips/reloc branch.
-Gabor

2013/2/11 Gabor Juhos juhosg@openwrt.org:
that's weird. Actually I checked after each patch if the *_end symbols match the U-Boot binary size. Now I checked again with different toolchains (gcc-4.[5,6,7], binutils-2.[21.53,22] and I have again that binutils issue.
But all toolchains have one in common (tested with qemu_mips): __rel_dyn_end - __rel_dyn_start = 0x1770 size from readelf = 0x15f8
Another problem is that your .deadcode workaround does not work anymore for me. It does not matter how I arrange or drop the unneeded sections, the size of .rel.dyn remains at 0x1770. I'll try to find another solution.
Erm, the presence of the .deadcode section does not change the size of the .rel.dyn section.
The ELF headers shows that there is a gap between the .rel.dyn and the .deadcode section:
[ 6] .rel.dyn REL bfc30804 030864 0015f8 08 A 8 0 4 [ 7] .deadcode PROGBITS bfc31f74 031fd4 000004 00 WA 0 0 1
However objcopy will copy the .deadcode section into the final binary because it is placed after the .rel.dyn section, and the gap will be filled with 0xff bytes.
As a result, the size of u-boot.bin will equal to (__rel_dyn_end - __start + 4), and this ensures that it will contain the full .rel.dyn section.
ok. I guess I misunderstood the intention of your workaround. My goal was to minimize the increase of image size caused by PIE.
I'll send a v2 of patch 6/7 with the .deadcode section.

From: Gabor Juhos juhosg@openwrt.org
This section contain the table needed for dynamic relocation. Also provide symbols for the relocation code to access the table.
Discard all sections which are not needed in the final ELF binary and U-Boot image. Section .dynsym cannot be discarded or GNU ld crashes otherwise. This section will be stripped by GNU objcpy in a later patch.
Signed-off-by: Gabor Juhos juhosg@openwrt.org Signed-off-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com --- Changes since v1: - add back the .deadcode section (see code comment for explanation)
arch/mips/cpu/u-boot.lds | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-)
diff --git a/arch/mips/cpu/u-boot.lds b/arch/mips/cpu/u-boot.lds index 4cd983a..10513ab 100644 --- a/arch/mips/cpu/u-boot.lds +++ b/arch/mips/cpu/u-boot.lds @@ -70,7 +70,35 @@ SECTIONS . = ALIGN(4); __image_copy_end = .;
- .bss : { + .rel.dyn : { + __rel_dyn_start = .; + *(.rel.dyn) + __rel_dyn_end = .; + } + + .deadcode : { + /* + * Workaround for a binutils feature (or bug?). + * + * The GNU ld from binutils puts the dynamic relocation + * entries into the .rel.dyn section. Sometimes it + * allocates more dynamic relocation entries than it needs + * and the unused slots are set to R_MIPS_NONE entries. + * + * However the size of the .rel.dyn section in the ELF + * section header does not cover the unused entries, so + * objcopy removes those during stripping. + * + * Create a small section here to avoid that. + */ + LONG(0xffffffff); + } + + .dynsym : { + *(.dynsym) + } + + .bss __rel_dyn_start (OVERLAY) : { __bss_start = .; *(.sbss.*) *(.bss.*) @@ -78,4 +106,16 @@ SECTIONS . = ALIGN(4); __bss_end = .; } + + /DISCARD/ : { + *(.dynbss) + *(.dynstr) + *(.dynamic) + *(.interp) + *(.hash) + *(.gnu.*) + *(.plt) + *(.got.plt) + *(.rel.plt) + } } -- 1.8.1.1

2013.02.11. 15:32 keltezéssel, Daniel Schwierzeck írta:
From: Gabor Juhos juhosg@openwrt.org
This section contain the table needed for dynamic relocation. Also provide symbols for the relocation code to access the table.
Discard all sections which are not needed in the final ELF binary and U-Boot image. Section .dynsym cannot be discarded or GNU ld crashes otherwise. This section will be stripped by GNU objcpy in a later patch.
Signed-off-by: Gabor Juhos juhosg@openwrt.org Signed-off-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com
Changes since v1:
- add back the .deadcode section (see code comment for explanation)
Thanks!
-Gabor
For the record: the qemu_mips{,el,64,64el} and the qi_lb60 images (compiled from the updated mips/reloc branch) are working under qemu:
U-Boot 2013.01-00178-gc27fe73 (Feb 11 2013 - 15:46:40)
Board: Qemu -M mips CPU: 24Kf proc_id=0x19300 DRAM: 128 MiB ## Unknown flash on Bank 1 - Size = 0x00000000 = 0 MB Flash: 0 Bytes *** Warning - bad CRC, using default environment
In: serial Out: serial Err: serial Net: NE2000 Hit any key to stop autoboot: 0 qemu-mips #
---
U-Boot 2013.01-00178-gc27fe73 (Feb 11 2013 - 15:47:29)
Board: Qemu -M mips CPU: 24Kf proc_id=0x19300 DRAM: 128 MiB ## Unknown flash on Bank 1 - Size = 0x00000000 = 0 MB Flash: 0 Bytes *** Warning - bad CRC, using default environment
In: serial Out: serial Err: serial Net: NE2000 Hit any key to stop autoboot: 0 qemu-mipsel #
---
U-Boot 2013.01-00178-gc27fe73 (Feb 11 2013 - 15:48:16)
Board: Qemu -M mips CPU: 20Kc proc_id=0x182a0 DRAM: 128 MiB ## Unknown flash on Bank 1 - Size = 0x00000000 = 0 MB Flash: 0 Bytes *** Warning - bad CRC, using default environment
In: serial Out: serial Err: serial Net: NE2000 Hit any key to stop autoboot: 0 qemu-mips64 #
---
U-Boot 2013.01-00178-gc27fe73 (Feb 11 2013 - 15:48:55)
Board: Qemu -M mips CPU: 20Kc proc_id=0x182a0 DRAM: 128 MiB ## Unknown flash on Bank 1 - Size = 0x00000000 = 0 MB Flash: 0 Bytes *** Warning - bad CRC, using default environment
In: serial Out: serial Err: serial Net: NE2000 Hit any key to stop autoboot: 0 qemu-mips64el #
---
U-Boot 2013.01-00178-gc27fe73 (Feb 11 2013 - 15:49:34)
Board: Qi LB60 (Ingenic XBurst Jz4740 SoC, Speed 336 MHz) DRAM: 32 MiB NAND: No NAND device found!!! 0 MiB No Valid Environment Area found No Valid Redundant Environment Area found *** Warning - bad CRC, using default environment
In: serial Out: serial Err: serial Hit any key to stop autoboot: 0
no devices available Wrong Image Format for bootm command ERROR: can't get kernel image! NanoNote#

From: Gabor Juhos juhosg@openwrt.org
The code handles relocation entries with the following relocation types only: mips32: R_MIPS_REL32 mips64: R_MIPS_REL+R_MIPS_64 xburst: R_MIPS_REL32
Other relocation entries are skipped without processing. The code must be extended if other relocation types must be supported.
Add -pie to LDFLAGS_FINAL to generate the .rel.dyn fixup table, which will be applied to the relocated image before transferring control to it.
The CONFIG_NEEDS_MANUAL_RELOC is not needed after the patch, so remove that as well.
Signed-off-by: Gabor Juhos juhosg@openwrt.org Signed-off-by: Daniel Schwierzeck daniel.schwierzeck@gmail.com
--- arch/mips/config.mk | 3 ++- arch/mips/cpu/mips32/start.S | 28 ++++++++++++++++++++++++++++ arch/mips/cpu/mips64/start.S | 36 ++++++++++++++++++++++++++++++++++++ arch/mips/cpu/xburst/start.S | 28 ++++++++++++++++++++++++++++ arch/mips/include/asm/config.h | 2 -- arch/mips/lib/board.c | 9 --------- 6 files changed, 94 insertions(+), 12 deletions(-)
diff --git a/arch/mips/config.mk b/arch/mips/config.mk index de9140b..aaa94e8 100644 --- a/arch/mips/config.mk +++ b/arch/mips/config.mk @@ -65,4 +65,5 @@ PLATFORM_CPPFLAGS += -G 0 -mabicalls -fpic $(ENDIANNESS) PLATFORM_CPPFLAGS += -msoft-float PLATFORM_LDFLAGS += -G 0 -static -n -nostdlib $(ENDIANNESS) PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections -LDFLAGS_FINAL += --gc-sections +LDFLAGS_FINAL += --gc-sections -pie +OBJCFLAGS += --remove-section=.dynsym diff --git a/arch/mips/cpu/mips32/start.S b/arch/mips/cpu/mips32/start.S index 649c0bb..76abbaa 100644 --- a/arch/mips/cpu/mips32/start.S +++ b/arch/mips/cpu/mips32/start.S @@ -201,6 +201,8 @@ relocate_code: jr t0 nop
+ .word __rel_dyn_end + .word __rel_dyn_start .word __image_copy_end .word _GLOBAL_OFFSET_TABLE_ .word num_got_entries @@ -227,6 +229,32 @@ in_ram: blt t2, t3, 1b addi t4, 4
+ /* Update dynamic relocations */ + lw t1, -16(t0) # t1 <-- __rel_dyn_start + lw t2, -20(t0) # t2 <-- __rel_dyn_end + + b 2f # skip first reserved entry + addi t1, 8 + +1: + lw t3, -4(t1) # t3 <-- relocation info + + sub t3, 3 + bnez t3, 2f # skip non R_MIPS_REL32 entries + nop + + lw t3, -8(t1) # t3 <-- location to fix up in FLASH + + lw t4, 0(t3) # t4 <-- original pointer + add t4, s1 # t4 <-- adjusted pointer + + add t3, s1 # t3 <-- location to fix up in RAM + sw t4, 0(t3) + +2: + blt t1, t2, 1b + addi t1, 8 # each rel.dyn entry is 8 bytes + /* * Clear BSS * diff --git a/arch/mips/cpu/mips64/start.S b/arch/mips/cpu/mips64/start.S index 5c2c7b5..dc7ce07 100644 --- a/arch/mips/cpu/mips64/start.S +++ b/arch/mips/cpu/mips64/start.S @@ -31,6 +31,14 @@ #define CONFIG_SYS_MIPS_CACHE_MODE CONF_CM_CACHABLE_NONCOHERENT #endif
+#ifdef CONFIG_SYS_LITTLE_ENDIAN +#define MIPS64_R_INFO(ssym, r_type3, r_type2, r_type) \ + (((r_type) << 24) | ((r_type2) << 16) | ((r_type3) << 8) | (ssym)) +#else +#define MIPS64_R_INFO(ssym, r_type3, r_type2, r_type) \ + ((r_type) | ((r_type2) << 8) | ((r_type3) << 16) | (ssym) << 24) +#endif + /* * For the moment disable interrupts, mark the kernel mode and * set ST0_KX so that the CPU does not spit fire when using @@ -193,6 +201,8 @@ relocate_code: jr t0 nop
+ .dword __rel_dyn_end + .dword __rel_dyn_start .dword __image_copy_end .dword _GLOBAL_OFFSET_TABLE_ .dword num_got_entries @@ -219,6 +229,32 @@ in_ram: blt t2, t3, 1b daddi t8, 8
+ /* Update dynamic relocations */ + ld t1, -32(t0) # t1 <-- __rel_dyn_start + ld t2, -40(t0) # t2 <-- __rel_dyn_end + + b 2f # skip first reserved entry + daddi t1, 16 + +1: + lw t8, -4(t1) # t8 <-- relocation info + + dli t3, MIPS64_R_INFO(0x00, 0x00, 0x12, 0x03) + bne t8, t3, 2f # skip non R_MIPS_REL32 entries + nop + + ld t3, -16(t1) # t3 <-- location to fix up in FLASH + + ld t8, 0(t3) # t8 <-- original pointer + dadd t8, s1 # t8 <-- adjusted pointer + + dadd t3, s1 # t3 <-- location to fix up in RAM + sd t8, 0(t3) + +2: + blt t1, t2, 1b + daddi t1, 16 # each rel.dyn entry is 16 bytes + /* * Clear BSS * diff --git a/arch/mips/cpu/xburst/start.S b/arch/mips/cpu/xburst/start.S index 6b30d3e..d2c064b 100644 --- a/arch/mips/cpu/xburst/start.S +++ b/arch/mips/cpu/xburst/start.S @@ -116,6 +116,8 @@ relocate_code: jr t0 nop
+ .word __rel_dyn_end + .word __rel_dyn_start .word __image_copy_end .word _GLOBAL_OFFSET_TABLE_ .word num_got_entries @@ -142,6 +144,32 @@ in_ram: blt t2, t3, 1b addi t4, 4
+ /* Update dynamic relocations */ + lw t1, -16(t0) # t1 <-- __rel_dyn_start + lw t2, -20(t0) # t2 <-- __rel_dyn_end + + b 2f # skip first reserved entry + addi t1, 8 + +1: + lw t3, -4(t1) # t3 <-- relocation info + + sub t3, 3 + bnez t3, 2f # skip non R_MIPS_REL32 entries + nop + + lw t3, -8(t1) # t3 <-- location to fix up in FLASH + + lw t4, 0(t3) # t4 <-- original pointer + add t4, t6 # t4 <-- adjusted pointer + + add t3, t6 # t3 <-- location to fix up in RAM + sw t4, 0(t3) + +2: + blt t1, t2, 1b + addi t1, 8 # each rel.dyn entry is 8 bytes + /* * Clear BSS * diff --git a/arch/mips/include/asm/config.h b/arch/mips/include/asm/config.h index 02fbfb3..049c44e 100644 --- a/arch/mips/include/asm/config.h +++ b/arch/mips/include/asm/config.h @@ -21,6 +21,4 @@ #ifndef _ASM_CONFIG_H_ #define _ASM_CONFIG_H_
-#define CONFIG_NEEDS_MANUAL_RELOC - #endif diff --git a/arch/mips/lib/board.c b/arch/mips/lib/board.c index d494876..2ec0f76 100644 --- a/arch/mips/lib/board.c +++ b/arch/mips/lib/board.c @@ -266,14 +266,6 @@ void board_init_r(gd_t *id, ulong dest_addr)
serial_initialize();
-#if defined(CONFIG_NEEDS_MANUAL_RELOC) - /* - * We have to relocate the command table manually - */ - fixup_cmdtable(ll_entry_start(cmd_tbl_t, cmd), - ll_entry_count(cmd_tbl_t, cmd)); -#endif /* defined(CONFIG_NEEDS_MANUAL_RELOC) */ - /* there are some other pointer constants we must deal with */ #ifndef CONFIG_ENV_IS_NOWHERE env_name_spec += gd->reloc_off; @@ -284,7 +276,6 @@ void board_init_r(gd_t *id, ulong dest_addr) /* The Malloc area is immediately below the monitor copy in DRAM */ mem_malloc_init(CONFIG_SYS_MONITOR_BASE + gd->reloc_off - TOTAL_MALLOC_LEN, TOTAL_MALLOC_LEN); - malloc_bin_reloc();
#ifndef CONFIG_SYS_NO_FLASH /* configure available FLASH banks */
participants (3)
-
Daniel Schwierzeck
-
daniel.schwierzeck@gmail.com
-
Gabor Juhos