[PATCH 2/2] arch: m68k: Implement relocation

Marek Vasut marek.vasut+renesas at mailbox.org
Mon Jul 31 00:20:51 CEST 2023


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 .

Signed-off-by: Marek Vasut <marek.vasut+renesas at mailbox.org>
---
Cc: Angelo Dureghello <angelo at kernel-space.org>
Cc: Angelo Durgehello <angelo.dureghello at timesys.com>
Cc: Bin Meng <bmeng.cn at gmail.com>
Cc: Heinrich Schuchardt <xypron.glpk at gmx.de>
Cc: Huan Wang <alison.wang at nxp.com>
Cc: Marek Vasut <marek.vasut+renesas at mailbox.org>
Cc: Michal Simek <michal.simek at amd.com>
Cc: Ovidiu Panait <ovpanait at gmail.com>
Cc: Simon Glass <sjg at chromium.org>
Cc: Zong Li <zong.li at sifive.com>
---
 arch/Kconfig                   |  1 -
 arch/m68k/Kconfig              |  4 +--
 arch/m68k/config.mk            |  6 ++--
 arch/m68k/cpu/mcf523x/start.S  | 57 ++++++++++++++++++++------------
 arch/m68k/cpu/mcf52x2/start.S  | 57 ++++++++++++++++++++------------
 arch/m68k/cpu/mcf530x/start.S  | 59 +++++++++++++++++++++-------------
 arch/m68k/cpu/mcf532x/start.S  | 57 ++++++++++++++++++++------------
 arch/m68k/cpu/mcf5445x/start.S | 57 ++++++++++++++++++++------------
 arch/m68k/cpu/u-boot.lds       | 14 ++++++++
 9 files changed, 204 insertions(+), 108 deletions(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index c9a33592252..2e2cbdf37aa 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -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
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 1911563e540..587edd50d7e 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -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
diff --git a/arch/m68k/config.mk b/arch/m68k/config.mk
index 3ccbe492202..643b7d1d35d 100644
--- a/arch/m68k/config.mk
+++ b/arch/m68k/config.mk
@@ -3,8 +3,8 @@
 # (C) Copyright 2000-2002
 # Wolfgang Denk, DENX Software Engineering, wd at 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
diff --git a/arch/m68k/cpu/mcf523x/start.S b/arch/m68k/cpu/mcf523x/start.S
index d2a21c3279b..c609e82163c 100644
--- a/arch/m68k/cpu/mcf523x/start.S
+++ b/arch/m68k/cpu/mcf523x/start.S
@@ -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 */
diff --git a/arch/m68k/cpu/mcf52x2/start.S b/arch/m68k/cpu/mcf52x2/start.S
index 51d2e23df10..3a2760236ce 100644
--- a/arch/m68k/cpu/mcf52x2/start.S
+++ b/arch/m68k/cpu/mcf52x2/start.S
@@ -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 */
diff --git a/arch/m68k/cpu/mcf530x/start.S b/arch/m68k/cpu/mcf530x/start.S
index cef8d79aad1..552e0204b77 100644
--- a/arch/m68k/cpu/mcf530x/start.S
+++ b/arch/m68k/cpu/mcf530x/start.S
@@ -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 */
diff --git a/arch/m68k/cpu/mcf532x/start.S b/arch/m68k/cpu/mcf532x/start.S
index 72a2f99b7dd..c3eae73a9c0 100644
--- a/arch/m68k/cpu/mcf532x/start.S
+++ b/arch/m68k/cpu/mcf532x/start.S
@@ -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 */
diff --git a/arch/m68k/cpu/mcf5445x/start.S b/arch/m68k/cpu/mcf5445x/start.S
index a083c3d45d2..5c3bfff7918 100644
--- a/arch/m68k/cpu/mcf5445x/start.S
+++ b/arch/m68k/cpu/mcf5445x/start.S
@@ -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 */
diff --git a/arch/m68k/cpu/u-boot.lds b/arch/m68k/cpu/u-boot.lds
index 133f79150ba..03d427cd36c 100644
--- a/arch/m68k/cpu/u-boot.lds
+++ b/arch/m68k/cpu/u-boot.lds
@@ -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 = .;
-- 
2.40.1



More information about the U-Boot mailing list