arch: m68k: Implement relocation

Implement relocation for M68K. Perform all the updates in start.S
relocate_code in assemby, since it is a simple matter of traversing
the dynsym table and adding relocation offset - MONITOR_BASE to all
the items in that table. The necessity to deal with MONITOR_BASE is
a specific of M68K, where the ELF entry point is at offset 0x400,
which is the MONITOR_BASE, while TEXT_BASE is at offset 0 .

This also removes the one last user of NEEDS_MANUAL_RELOC, so that
could be finally cleaned up .

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
This commit is contained in:
Marek Vasut 2023-08-27 00:25:36 +02:00 committed by Angelo Dureghello
parent bf10b9201c
commit 26af162ac8
9 changed files with 204 additions and 108 deletions

View file

@ -68,7 +68,6 @@ config M68K
bool "M68000 architecture"
select HAVE_PRIVATE_LIBGCC
select USE_PRIVATE_LIBGCC
select NEEDS_MANUAL_RELOC
select SYS_BOOT_GET_CMDLINE
select SYS_BOOT_GET_KBD
select SYS_CACHE_SHIFT_4

View file

@ -4,8 +4,8 @@ menu "M68000 architecture"
config SYS_ARCH
default "m68k"
config NEEDS_MANUAL_RELOC
def_bool y
config STATIC_RELA
default y
# processor family
config MCF520x

View file

@ -3,8 +3,8 @@
# (C) Copyright 2000-2002
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
PLATFORM_CPPFLAGS += -D__M68K__
KBUILD_LDFLAGS += -n
PLATFORM_CPPFLAGS += -D__M68K__ -fPIC
KBUILD_LDFLAGS += -n -pie
PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections
PLATFORM_RELFLAGS += -ffixed-d7 -msep-data
LDFLAGS_FINAL += --gc-sections
LDFLAGS_FINAL += --gc-sections -pie

View file

@ -177,6 +177,39 @@ relocate_code:
cmp.l %a1,%a2
bgt.s 1b
#define R_68K_32 1
#define R_68K_RELATIVE 22
move.l #(__rel_dyn_start), %a1
move.l #(__rel_dyn_end), %a2
fixloop:
move.l (%a1)+, %d1 /* Elf32_Rela r_offset */
move.l (%a1)+, %d2 /* Elf32_Rela r_info */
move.l (%a1)+, %d3 /* Elf32_Rela r_addend */
andi.l #0xff, %d2
cmp.l #R_68K_32, %d2
beq.s fixup
cmp.l #R_68K_RELATIVE, %d2
beq.s fixup
bra fixnext
fixup:
/* relative fix: store addend plus offset at dest location */
move.l %a0, %a3
add.l %d1, %a3
sub.l #CONFIG_SYS_MONITOR_BASE, %a3
move.l (%a3), %d4
add.l %a0, %d4
sub.l #CONFIG_SYS_MONITOR_BASE, %d4
move.l %d4, (%a3)
fixnext:
cmp.l %a1, %a2
bge.s fixloop
/*
* We are done. Do not return, instead branch to second part of board
* initialization, now running from RAM.
@ -191,10 +224,8 @@ clear_bss:
/*
* Now clear BSS segment
*/
move.l %a0, %a1
add.l #(_sbss - CONFIG_SYS_MONITOR_BASE),%a1
move.l %a0, %d1
add.l #(_ebss - CONFIG_SYS_MONITOR_BASE),%d1
move.l #(_sbss), %a1
move.l #(_ebss), %d1
6:
clr.l (%a1)+
cmp.l %a1,%d1
@ -203,24 +234,10 @@ clear_bss:
/*
* fix got table in RAM
*/
move.l %a0, %a1
add.l #(__got_start - CONFIG_SYS_MONITOR_BASE),%a1
move.l %a1,%a5 /* * fix got pointer register a5 */
move.l %a0, %a2
add.l #(__got_end - CONFIG_SYS_MONITOR_BASE),%a2
7:
move.l (%a1),%d1
sub.l #_start,%d1
add.l %a0,%d1
move.l %d1,(%a1)+
cmp.l %a2, %a1
bne 7b
move.l #(__got_start), %a5 /* fix got pointer register a5 */
/* calculate relative jump to board_init_r in ram */
move.l %a0, %a1
add.l #(board_init_r - CONFIG_SYS_MONITOR_BASE), %a1
move.l #(board_init_r), %a1
/* set parameters for board_init_r */
move.l %a0,-(%sp) /* dest_addr */

View file

@ -255,6 +255,39 @@ relocate_code:
cmp.l %a1,%a2
bgt.s 1b
#define R_68K_32 1
#define R_68K_RELATIVE 22
move.l #(__rel_dyn_start), %a1
move.l #(__rel_dyn_end), %a2
fixloop:
move.l (%a1)+, %d1 /* Elf32_Rela r_offset */
move.l (%a1)+, %d2 /* Elf32_Rela r_info */
move.l (%a1)+, %d3 /* Elf32_Rela r_addend */
andi.l #0xff, %d2
cmp.l #R_68K_32, %d2
beq.s fixup
cmp.l #R_68K_RELATIVE, %d2
beq.s fixup
bra fixnext
fixup:
/* relative fix: store addend plus offset at dest location */
move.l %a0, %a3
add.l %d1, %a3
sub.l #CONFIG_SYS_MONITOR_BASE, %a3
move.l (%a3), %d4
add.l %a0, %d4
sub.l #CONFIG_SYS_MONITOR_BASE, %d4
move.l %d4, (%a3)
fixnext:
cmp.l %a1, %a2
bge.s fixloop
/*
* We are done. Do not return, instead branch to second part of board
* initialization, now running from RAM.
@ -269,10 +302,8 @@ clear_bss:
/*
* Now clear BSS segment
*/
move.l %a0, %a1
add.l #(_sbss - CONFIG_SYS_MONITOR_BASE),%a1
move.l %a0, %d1
add.l #(_ebss - CONFIG_SYS_MONITOR_BASE),%d1
move.l #(_sbss), %a1
move.l #(_ebss), %d1
6:
clr.l (%a1)+
cmp.l %a1,%d1
@ -281,24 +312,10 @@ clear_bss:
/*
* fix got table in RAM
*/
move.l %a0, %a1
add.l #(__got_start - CONFIG_SYS_MONITOR_BASE),%a1
move.l %a1,%a5 /* fix got pointer register a5 */
move.l %a0, %a2
add.l #(__got_end - CONFIG_SYS_MONITOR_BASE),%a2
7:
move.l (%a1),%d1
sub.l #_start,%d1
add.l %a0,%d1
move.l %d1,(%a1)+
cmp.l %a2, %a1
bne 7b
move.l #(__got_start), %a5 /* fix got pointer register a5 */
/* calculate relative jump to board_init_r in ram */
move.l %a0, %a1
add.l #(board_init_r - CONFIG_SYS_MONITOR_BASE), %a1
move.l #(board_init_r), %a1
/* set parameters for board_init_r */
move.l %a0,-(%sp) /* dest_addr */

View file

@ -180,6 +180,39 @@ relocate_code:
cmp.l %a1,%a2
bgt.s 1b
#define R_68K_32 1
#define R_68K_RELATIVE 22
move.l #(__rel_dyn_start), %a1
move.l #(__rel_dyn_end), %a2
fixloop:
move.l (%a1)+, %d1 /* Elf32_Rela r_offset */
move.l (%a1)+, %d2 /* Elf32_Rela r_info */
move.l (%a1)+, %d3 /* Elf32_Rela r_addend */
andi.l #0xff, %d2
cmp.l #R_68K_32, %d2
beq.s fixup
cmp.l #R_68K_RELATIVE, %d2
beq.s fixup
bra fixnext
fixup:
/* relative fix: store addend plus offset at dest location */
move.l %a0, %a3
add.l %d1, %a3
sub.l #CONFIG_SYS_MONITOR_BASE, %a3
move.l (%a3), %d4
add.l %a0, %d4
sub.l #CONFIG_SYS_MONITOR_BASE, %d4
move.l %d4, (%a3)
fixnext:
cmp.l %a1, %a2
bge.s fixloop
/*
* We are done. Do not return, instead branch to second part of board
* initialization, now running from RAM.
@ -194,10 +227,8 @@ clear_bss:
/*
* Now clear BSS segment
*/
move.l %a0, %a1
add.l #(_sbss - CONFIG_SYS_MONITOR_BASE), %a1
move.l %a0, %d1
add.l #(_ebss - CONFIG_SYS_MONITOR_BASE), %d1
move.l #(_sbss), %a1
move.l #(_ebss), %d1
6:
clr.l (%a1)+
cmp.l %a1,%d1
@ -206,26 +237,10 @@ clear_bss:
/*
* fix got table in RAM
*/
move.l %a0, %a1
add.l #(__got_start - CONFIG_SYS_MONITOR_BASE), %a1
/* fix got pointer register a5 */
move.l %a1,%a5
move.l %a0, %a2
add.l #(__got_end - CONFIG_SYS_MONITOR_BASE), %a2
7:
move.l (%a1),%d1
sub.l #_start, %d1
add.l %a0,%d1
move.l %d1,(%a1)+
cmp.l %a2, %a1
bne 7b
move.l #(__got_start), %a5 /* fix got pointer register a5 */
/* calculate relative jump to board_init_r in ram */
move.l %a0, %a1
add.l #(board_init_r - CONFIG_SYS_MONITOR_BASE), %a1
move.l #(board_init_r), %a1
/* set parameters for board_init_r */
move.l %a0,-(%sp) /* dest_addr */

View file

@ -192,6 +192,39 @@ relocate_code:
cmp.l %a1,%a2
bgt.s 1b
#define R_68K_32 1
#define R_68K_RELATIVE 22
move.l #(__rel_dyn_start), %a1
move.l #(__rel_dyn_end), %a2
fixloop:
move.l (%a1)+, %d1 /* Elf32_Rela r_offset */
move.l (%a1)+, %d2 /* Elf32_Rela r_info */
move.l (%a1)+, %d3 /* Elf32_Rela r_addend */
andi.l #0xff, %d2
cmp.l #R_68K_32, %d2
beq.s fixup
cmp.l #R_68K_RELATIVE, %d2
beq.s fixup
bra fixnext
fixup:
/* relative fix: store addend plus offset at dest location */
move.l %a0, %a3
add.l %d1, %a3
sub.l #CONFIG_SYS_MONITOR_BASE, %a3
move.l (%a3), %d4
add.l %a0, %d4
sub.l #CONFIG_SYS_MONITOR_BASE, %d4
move.l %d4, (%a3)
fixnext:
cmp.l %a1, %a2
bge.s fixloop
/*
* We are done. Do not return, instead branch to second part of board
* initialization, now running from RAM.
@ -206,10 +239,8 @@ clear_bss:
/*
* Now clear BSS segment
*/
move.l %a0, %a1
add.l #(_sbss - CONFIG_SYS_MONITOR_BASE),%a1
move.l %a0, %d1
add.l #(_ebss - CONFIG_SYS_MONITOR_BASE),%d1
move.l #(_sbss), %a1
move.l #(_ebss), %d1
6:
clr.l (%a1)+
cmp.l %a1,%d1
@ -218,24 +249,10 @@ clear_bss:
/*
* fix got table in RAM
*/
move.l %a0, %a1
add.l #(__got_start - CONFIG_SYS_MONITOR_BASE),%a1
move.l %a1,%a5 /* fix got pointer register a5 */
move.l %a0, %a2
add.l #(__got_end - CONFIG_SYS_MONITOR_BASE),%a2
7:
move.l (%a1),%d1
sub.l #_start,%d1
add.l %a0,%d1
move.l %d1,(%a1)+
cmp.l %a2, %a1
bne 7b
move.l #(__got_start), %a5 /* fix got pointer register a5 */
/* calculate relative jump to board_init_r in ram */
move.l %a0, %a1
add.l #(board_init_r - CONFIG_SYS_MONITOR_BASE), %a1
move.l #(board_init_r), %a1
/* set parameters for board_init_r */
move.l %a0,-(%sp) /* dest_addr */

View file

@ -533,6 +533,39 @@ relocate_code:
cmp.l %a1,%a2
bgt.s 1b
#define R_68K_32 1
#define R_68K_RELATIVE 22
move.l #(__rel_dyn_start), %a1
move.l #(__rel_dyn_end), %a2
fixloop:
move.l (%a1)+, %d1 /* Elf32_Rela r_offset */
move.l (%a1)+, %d2 /* Elf32_Rela r_info */
move.l (%a1)+, %d3 /* Elf32_Rela r_addend */
andi.l #0xff, %d2
cmp.l #R_68K_32, %d2
beq.s fixup
cmp.l #R_68K_RELATIVE, %d2
beq.s fixup
bra fixnext
fixup:
/* relative fix: store addend plus offset at dest location */
move.l %a0, %a3
add.l %d1, %a3
sub.l #CONFIG_SYS_MONITOR_BASE, %a3
move.l (%a3), %d4
add.l %a0, %d4
sub.l #CONFIG_SYS_MONITOR_BASE, %d4
move.l %d4, (%a3)
fixnext:
cmp.l %a1, %a2
bge.s fixloop
/*
* We are done. Do not return, instead branch to second part of board
* initialization, now running from RAM.
@ -547,10 +580,8 @@ clear_bss:
/*
* Now clear BSS segment
*/
move.l %a0, %a1
add.l #(_sbss - CONFIG_SYS_MONITOR_BASE),%a1
move.l %a0, %d1
add.l #(_ebss - CONFIG_SYS_MONITOR_BASE),%d1
move.l #(_sbss), %a1
move.l #(_ebss), %d1
6:
clr.l (%a1)+
cmp.l %a1,%d1
@ -559,24 +590,10 @@ clear_bss:
/*
* fix got table in RAM
*/
move.l %a0, %a1
add.l #(__got_start - CONFIG_SYS_MONITOR_BASE),%a1
move.l %a1,%a5 /* fix got pointer register a5 */
move.l %a0, %a2
add.l #(__got_end - CONFIG_SYS_MONITOR_BASE),%a2
7:
move.l (%a1),%d1
sub.l #_start,%d1
add.l %a0,%d1
move.l %d1,(%a1)+
cmp.l %a2, %a1
bne 7b
move.l #(__got_start), %a5 /* fix got pointer register a5 */
/* calculate relative jump to board_init_r in ram */
move.l %a0, %a1
add.l #(board_init_r - CONFIG_SYS_MONITOR_BASE), %a1
move.l #(board_init_r), %a1
/* set parameters for board_init_r */
move.l %a0,-(%sp) /* dest_addr */

View file

@ -76,6 +76,20 @@ SECTIONS
. = ALIGN(4);
__init_end = .;
. = ALIGN(4);
__rel_dyn_start = .;
.rela.dyn : {
*(.rela.dyn)
}
__rel_dyn_end = .;
. = ALIGN(4);
__dyn_sym_start = .;
.dynsym : {
*(.dynsym)
}
__dyn_sym_end = .;
_end = .;
__bss_start = .;