[U-Boot] [PATCH] MIPS: make size of relocation table fixed but configurable

Daniel Schwierzeck daniel.schwierzeck at gmail.com
Thu Nov 1 01:02:21 UTC 2018


Currently the size of the relocation table will be shrunk
to the actual size needed. Although this gives a maximal
space saving, it messes up the _end symbol. This breaks
features like appended DTBs because the _end symbol doesn't
point to the real end of the U-Boot binary.

Remove the size shrinking and make the size of the relocation
table fixed but configurable. This follows the Linux approach
and the user can adjust the size to his needs.

Also rename the relocation table section from .rel to .data.reloc
to follow the Linux approach and to avoid ambiguities with the
.rel.* sections added by the linker.

Reported-by: Lars Povlsen <lars.povlsen at microsemi.com>
Signed-off-by: Daniel Schwierzeck <daniel.schwierzeck at gmail.com>

---
Lars, I couldn't find a working solution for fixing up the _end
symbol. Thus I decided to implement the Linux approach with a
configurable size for the relocation table. The _end symbol should
be now correct and aligned to 4 Bytes in all configurations.

 arch/mips/Kconfig        | 18 ++++++++++++++++++
 arch/mips/config.mk      |  2 +-
 arch/mips/cpu/u-boot.lds | 20 +++++++++++++-------
 tools/mips-relocs.c      | 30 ++++++++----------------------
 4 files changed, 40 insertions(+), 30 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 071dea04ec..6d646ef999 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -248,6 +248,24 @@ config MIPS_CACHE_INDEX_BASE
 	  Normally this is CKSEG0. If the MIPS system needs to move this block
 	  to some SRAM or ScratchPad RAM, adapt this option accordingly.
 
+config MIPS_RELOCATION_TABLE_SIZE
+	hex "Relocation table size"
+	range 0x100 0x10000
+	default "0x8000"
+	---help---
+	  A table of relocation data will be appended to the U-Boot binary
+	  and parsed in relocate_code() to fix up all offsets in the relocated
+	  U-Boot.
+
+	  This option allows the amount of space reserved for the table to be
+	  adjusted in a range from 256 up to 64k. The default is 32k and should
+	  be ok in most cases. Reduce this value to shrink the size of U-Boot
+	  binary.
+
+	  The build will fail and a valid size suggested if this is too small.
+
+	  If unsure, leave at the default value.
+
 endmenu
 
 menu "OS boot interface"
diff --git a/arch/mips/config.mk b/arch/mips/config.mk
index 8aa45fc45c..22223a0f3e 100644
--- a/arch/mips/config.mk
+++ b/arch/mips/config.mk
@@ -55,7 +55,7 @@ PLATFORM_ELFFLAGS += -B mips $(OBJCOPYFLAGS)
 # MODFLAGS			+= -mlong-calls
 #
 ifndef CONFIG_SPL_BUILD
-OBJCOPYFLAGS			+= -j .got -j .rel -j .padding -j .dtb.init.rodata
+OBJCOPYFLAGS			+= -j .data.reloc -j .dtb.init.rodata
 LDFLAGS_FINAL			+= --emit-relocs
 endif
 
diff --git a/arch/mips/cpu/u-boot.lds b/arch/mips/cpu/u-boot.lds
index c7b29068df..86496737d3 100644
--- a/arch/mips/cpu/u-boot.lds
+++ b/arch/mips/cpu/u-boot.lds
@@ -41,16 +41,22 @@ SECTIONS
 	__image_copy_end = .;
 	__init_end = .;
 
-	/*
-	 * .rel must come last so that the mips-relocs tool can shrink
-	 * the section size & the PT_LOAD program header filesz.
-	 */
-	.rel : {
+	.data.reloc : {
 		__rel_start = .;
-		BYTE(0x0)
-		. += (32 * 1024) - 1;
+		/*
+		 * Space for relocation table
+		 * This needs to be filled so that the
+		 * mips-reloc tool can overwrite the content.
+		 * An invalid value is left at the start of the
+		 * section to abort relocation if the table
+		 * has not been filled in.
+		 */
+		LONG(0xFFFFFFFF);
+		FILL(0);
+		. += CONFIG_MIPS_RELOCATION_TABLE_SIZE - 4;
 	}
 
+	. = ALIGN(4);
 	_end = .;
 
 	.bss __rel_start (OVERLAY) : {
diff --git a/tools/mips-relocs.c b/tools/mips-relocs.c
index 442cc8f6d2..625258085b 100644
--- a/tools/mips-relocs.c
+++ b/tools/mips-relocs.c
@@ -195,15 +195,13 @@ static int compare_relocs(const void *a, const void *b)
 int main(int argc, char *argv[])
 {
 	unsigned int i, j, i_rel_shdr, sh_type, sh_entsize, sh_entries;
-	size_t rel_size, rel_actual_size, load_sz;
+	size_t rel_size, rel_actual_size;
 	const char *shstrtab, *sh_name, *rel_pfx;
 	int (*parse_fn)(const void *rel);
 	uint8_t *buf_start, *buf;
 	const Elf32_Ehdr *ehdr32;
 	const Elf64_Ehdr *ehdr64;
 	uintptr_t sh_offset;
-	Elf32_Phdr *phdr32;
-	Elf64_Phdr *phdr64;
 	Elf32_Shdr *shdr32;
 	Elf64_Shdr *shdr64;
 	struct stat st;
@@ -285,8 +283,6 @@ int main(int argc, char *argv[])
 		goto out_free_relocs;
 	}
 
-	phdr32 = elf + ehdr_field(e_phoff);
-	phdr64 = elf + ehdr_field(e_phoff);
 	shdr32 = elf + ehdr_field(e_shoff);
 	shdr64 = elf + ehdr_field(e_shoff);
 	shstrtab = elf + shdr_field(ehdr_field(e_shstrndx), sh_offset);
@@ -295,7 +291,7 @@ int main(int argc, char *argv[])
 	for (i = 0; i < ehdr_field(e_shnum); i++) {
 		sh_name = shstr(shdr_field(i, sh_name));
 
-		if (!strcmp(sh_name, ".rel")) {
+		if (!strcmp(sh_name, ".data.reloc")) {
 			i_rel_shdr = i;
 			continue;
 		}
@@ -397,22 +393,12 @@ int main(int argc, char *argv[])
 	rel_size = shdr_field(i_rel_shdr, sh_size);
 	rel_actual_size = buf - buf_start;
 	if (rel_actual_size > rel_size) {
-		fprintf(stderr, "Relocs overflowed .rel section\n");
-		return -ENOMEM;
-	}
-
-	/* Update the .rel section's size */
-	set_shdr_field(i_rel_shdr, sh_size, rel_actual_size);
-
-	/* Shrink the PT_LOAD program header filesz (ie. shrink u-boot.bin) */
-	for (i = 0; i < ehdr_field(e_phnum); i++) {
-		if (phdr_field(i, p_type) != PT_LOAD)
-			continue;
-
-		load_sz = phdr_field(i, p_filesz);
-		load_sz -= rel_size - rel_actual_size;
-		set_phdr_field(i, p_filesz, load_sz);
-		break;
+		fprintf(stderr, "Relocations overflow available space of 0x%lx (required 0x%lx)!\n",
+			rel_size, rel_actual_size);
+		fprintf(stderr, "Please adjust CONFIG_MIPS_RELOCATION_TABLE_SIZE to at least 0x%lx\n",
+			(rel_actual_size + 0x100) & ~0xFF);
+		err = -ENOMEM;
+		goto out_free_relocs;
 	}
 
 	/* Make sure data is written back to the file */
-- 
2.19.1



More information about the U-Boot mailing list