
This does not actually change normal behaviour, but adds a check that should detect corruption of relocation data (e.g. by using BSS data prior to relocation).
Also add additional debugging output when enabled.
During this investigation, two situations have been seen: 1. calculate_relocation_address(): uintptr_t size = (uintptr_t)&__bss_end - (uintptr_t)&__text_start;
turns into 111166f: b8 83 c4 17 01 mov $0x117c483,%eax
whih is beyond the end of bss:
0117b484 g .bss 00000000 __bss_end
Somehow the __bss_end here is 255 bytes ahead.
2. do_elf_reloc_fixups():
uintptr_t size = (uintptr_t)&__bss_end - (uintptr_t)&__text_start;
Here the __text_start is 0 in the file:
1111d9f: bb a0 e0 13 01 mov $0x113e0a0,%ebx 1111da4: 81 ef 00 00 00 00 sub $0x0,%edi
As it happens, both of these are in pre-relocation code.
For these reasons we silent check and ignore bad relocations.
Signed-off-by: Simon Glass sjg@chromium.org --- Changes in v2: None
arch/x86/lib/relocate.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/arch/x86/lib/relocate.c b/arch/x86/lib/relocate.c index 3a38e52..3e370f2 100644 --- a/arch/x86/lib/relocate.c +++ b/arch/x86/lib/relocate.c @@ -73,12 +73,16 @@ int clear_bss(void) return 0; }
+/* + * This function has more error checking than you might expect. Please see + * the commit message for more informaiton. + */ int do_elf_reloc_fixups(void) { Elf32_Rel *re_src = (Elf32_Rel *)(&__rel_dyn_start); Elf32_Rel *re_end = (Elf32_Rel *)(&__rel_dyn_end);
- Elf32_Addr *offset_ptr_rom; + Elf32_Addr *offset_ptr_rom, *last_offset = NULL; Elf32_Addr *offset_ptr_ram;
/* The size of the region of u-boot that runs out of RAM. */ @@ -89,7 +93,8 @@ int do_elf_reloc_fixups(void) offset_ptr_rom = (Elf32_Addr *)re_src->r_offset;
/* Check that the location of the relocation is in .text */ - if (offset_ptr_rom >= (Elf32_Addr *)CONFIG_SYS_TEXT_BASE) { + if (offset_ptr_rom >= (Elf32_Addr *)CONFIG_SYS_TEXT_BASE && + offset_ptr_rom > last_offset) {
/* Switch to the in-RAM version */ offset_ptr_ram = (Elf32_Addr *)((ulong)offset_ptr_rom + @@ -100,8 +105,19 @@ int do_elf_reloc_fixups(void) *offset_ptr_ram <= (CONFIG_SYS_TEXT_BASE + size)) { *offset_ptr_ram += gd->reloc_off; + } else { + debug(" %p: rom reloc %x, ram %p, value %x," + " limit %lx\n", re_src, + re_src->r_offset, offset_ptr_ram, + *offset_ptr_ram, + CONFIG_SYS_TEXT_BASE + size); } + } else { + debug(" %p: rom reloc %x, last %p\n", re_src, + re_src->r_offset, last_offset); } + last_offset = offset_ptr_rom; + } while (++re_src < re_end);
return 0;