diff options
author | Gabor Juhos <juhosg@openwrt.org> | 2013-02-12 22:22:13 +0100 |
---|---|---|
committer | Daniel Schwierzeck <daniel.schwierzeck@gmail.com> | 2013-02-12 22:22:13 +0100 |
commit | 04380c651a2ff0d1495822321d2b7668dcd02537 (patch) | |
tree | fd763e5b4f62d349cbcfde50e5e24292f9a1a18f | |
parent | 0ba8926e08bdabba681384ba3ea8476eda68c141 (diff) |
MIPS: add dynamic relocation support
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>
-rw-r--r-- | arch/mips/config.mk | 3 | ||||
-rw-r--r-- | arch/mips/cpu/mips32/start.S | 28 | ||||
-rw-r--r-- | arch/mips/cpu/mips64/start.S | 36 | ||||
-rw-r--r-- | arch/mips/cpu/xburst/start.S | 28 | ||||
-rw-r--r-- | arch/mips/include/asm/config.h | 2 | ||||
-rw-r--r-- | 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 de9140b67b5..aaa94e8be20 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 649c0bbf5ce..76abbaa2736 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 5c2c7b5bad6..dc7ce07ce78 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 6b30d3ee8a5..d2c064b0175 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 02fbfb3abfe..049c44eaf84 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 d494876b13e..2ec0f7638c5 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 */ |