MIPS: add dynamic relocation support
authorGabor Juhos <juhosg@openwrt.org>
Tue, 12 Feb 2013 21:22:13 +0000 (22:22 +0100)
committerDaniel Schwierzeck <daniel.schwierzeck@gmail.com>
Tue, 12 Feb 2013 21:22:13 +0000 (22:22 +0100)
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
arch/mips/cpu/mips32/start.S
arch/mips/cpu/mips64/start.S
arch/mips/cpu/xburst/start.S
arch/mips/include/asm/config.h
arch/mips/lib/board.c

index de9140b67b5258b9a4511bc0dbbdd913c00c525a..aaa94e8be203f7e1c0a1da17a240f0b7decc20cd 100644 (file)
@@ -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
index 649c0bbf5ce364193ea07abf07780769827a5181..76abbaa27368d5b14ebea23aeccd00d63004de52 100644 (file)
@@ -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
         *
index 5c2c7b5bad612eaeffaea4035260fb8fbff85924..dc7ce07ce78c8e416e8a7d359ef724c46592c517 100644 (file)
 #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
         *
index 6b30d3ee8a5d82310f38211b8a812fae4e72d3fe..d2c064b0175b0c5368e5a7d183c9192bc6340b8e 100644 (file)
@@ -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
         *
index 02fbfb3abfea8ae55e4aef175d3e4e525cef5a79..049c44eaf84de0ce67d86afcf0cd016d4bd6c407 100644 (file)
@@ -21,6 +21,4 @@
 #ifndef _ASM_CONFIG_H_
 #define _ASM_CONFIG_H_
 
-#define CONFIG_NEEDS_MANUAL_RELOC
-
 #endif
index d494876b13e29292cb346e2c1b72af9f5f637d7b..2ec0f7638c5d764b5546a26f1a2221df861a8a90 100644 (file)
@@ -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 */