Skip to content

Commit

Permalink
x86: Add error checking to x86 relocation code
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
sjg20 committed Mar 4, 2013
1 parent f697d52 commit 62f7970
Showing 1 changed file with 18 additions and 2 deletions.
20 changes: 18 additions & 2 deletions arch/x86/lib/relocate.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand All @@ -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 +
Expand All @@ -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;
Expand Down

0 comments on commit 62f7970

Please sign in to comment.