From 28af3d867c5212f9459c8c1a3a458bbbc847b532 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 12 Apr 2013 16:53:58 +0200 Subject: [PATCH] Relocations cleanup --- grub-core/kern/arm/dl.c | 45 +++++++++++++--------------------------- include/grub/arm/reloc.h | 26 +++++++++++++++++++++++ util/grub-mkimagexx.c | 17 +++++++++------ 3 files changed, 51 insertions(+), 37 deletions(-) create mode 100644 include/grub/arm/reloc.h diff --git a/grub-core/kern/arm/dl.c b/grub-core/kern/arm/dl.c index 39a34ca5b..74e6b96b5 100644 --- a/grub-core/kern/arm/dl.c +++ b/grub-core/kern/arm/dl.c @@ -23,17 +23,11 @@ #include #include #include +#include #ifdef GRUB_UTIL # include #else -# if !defined(__thumb2__) -# error "Relocations not implemented for A32 ("ARM") instruction set yet!" -# endif - -grub_err_t reloc_jump24 (grub_uint32_t *addr, Elf32_Addr sym_addr); -grub_err_t reloc_thm_call (grub_uint16_t *addr, Elf32_Addr sym_addr); -grub_err_t reloc_thm_jump19 (grub_uint16_t *addr, Elf32_Addr sym_addr); #ifdef DL_DEBUG static const char *symstrtab; @@ -104,7 +98,7 @@ reloc_abs32 (Elf_Word *target, Elf_Addr sym_addr) * B.W, BL and BLX */ grub_err_t -reloc_thm_call (grub_uint16_t *target, Elf32_Addr sym_addr) +grub_arm_reloc_thm_call (grub_uint16_t *target, Elf32_Addr sym_addr) { grub_int32_t offset, offset_low, offset_high; grub_uint32_t sign, j1, j2, is_blx; @@ -122,14 +116,8 @@ reloc_thm_call (grub_uint16_t *target, Elf32_Addr sym_addr) /* If BLX, target symbol must be ARM (target address LSB == 0) */ if (is_blx && (sym_addr & 1)) - { -#ifndef GRUB_UTIL - return grub_error - (GRUB_ERR_BUG, N_("Relocation targeting wrong execution state")); -#else - grub_util_error ("Relocation targeting wrong execution state"); -#endif - } + return grub_error (GRUB_ERR_BUG, + N_("Relocation targeting wrong execution state")); offset_low = -16777216; offset_high = is_blx ? 16777212 : 16777214; @@ -159,18 +147,12 @@ reloc_thm_call (grub_uint16_t *target, Elf32_Addr sym_addr) #endif if ((offset < offset_low) || (offset > offset_high)) - { -#ifdef GRUB_UTIL - grub_util_error ("Relocation out of range"); -#else - return grub_error - (GRUB_ERR_OUT_OF_RANGE, N_("THM_CALL Relocation out of range.")); -#endif - } + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("THM_CALL Relocation out of range.")); #ifdef GRUB_UTIL - grub_util_info (" relative destination = 0x%08x", - (unsigned int)target + offset); + grub_util_info (" relative destination = 0x%08lx", + (unsigned long)target + offset); #endif /* Reassemble instruction word */ @@ -200,7 +182,7 @@ reloc_thm_call (grub_uint16_t *target, Elf32_Addr sym_addr) * Relocate conditional Thumb (T32) B.W */ grub_err_t -reloc_thm_jump19 (grub_uint16_t *addr, Elf32_Addr sym_addr) +grub_arm_reloc_thm_jump19 (grub_uint16_t *addr, Elf32_Addr sym_addr) { grub_int32_t offset; grub_uint32_t insword, insmask; @@ -260,7 +242,7 @@ reloc_thm_jump19 (grub_uint16_t *addr, Elf32_Addr sym_addr) * Relocate ARM (A32) B */ grub_err_t -reloc_jump24 (grub_uint32_t *addr, Elf32_Addr sym_addr) +grub_arm_reloc_jump24 (grub_uint32_t *addr, Elf32_Addr sym_addr) { grub_uint32_t insword; grub_int32_t offset; @@ -358,9 +340,10 @@ do_relocations (Elf_Shdr * relhdr, Elf_Ehdr * e, grub_dl_t mod) return retval; } break; + case R_ARM_CALL: case R_ARM_JUMP24: { - retval = reloc_jump24 (target, sym_addr); + retval = grub_arm_reloc_jump24 (target, sym_addr); if (retval != GRUB_ERR_NONE) return retval; } @@ -369,7 +352,7 @@ do_relocations (Elf_Shdr * relhdr, Elf_Ehdr * e, grub_dl_t mod) case R_ARM_THM_JUMP24: { /* Thumb instructions can be 16-bit aligned */ - retval = reloc_thm_call ((grub_uint16_t *) target, sym_addr); + retval = grub_arm_reloc_thm_call ((grub_uint16_t *) target, sym_addr); if (retval != GRUB_ERR_NONE) return retval; } @@ -377,7 +360,7 @@ do_relocations (Elf_Shdr * relhdr, Elf_Ehdr * e, grub_dl_t mod) case R_ARM_THM_JUMP19: { /* Thumb instructions can be 16-bit aligned */ - retval = reloc_thm_jump19 ((grub_uint16_t *) target, sym_addr); + retval = grub_arm_reloc_thm_jump19 ((grub_uint16_t *) target, sym_addr); if (retval != GRUB_ERR_NONE) return retval; } diff --git a/include/grub/arm/reloc.h b/include/grub/arm/reloc.h new file mode 100644 index 000000000..b47792d95 --- /dev/null +++ b/include/grub/arm/reloc.h @@ -0,0 +1,26 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_ARM_RELOC_H +#define GRUB_ARM_RELOC_H 1 + +grub_err_t grub_arm_reloc_jump24 (grub_uint32_t *addr, Elf32_Addr sym_addr); +grub_err_t grub_arm_reloc_thm_call (grub_uint16_t *addr, Elf32_Addr sym_addr); +grub_err_t grub_arm_reloc_thm_jump19 (grub_uint16_t *addr, Elf32_Addr sym_addr); + +#endif diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c index 812db900a..b6a7dcbee 100644 --- a/util/grub-mkimagexx.c +++ b/util/grub-mkimagexx.c @@ -60,9 +60,6 @@ static Elf_Addr SUFFIX (entry_point); -grub_err_t reloc_thm_call (grub_uint16_t *addr, Elf32_Addr sym_addr); -grub_err_t reloc_thm_jump19 (grub_uint16_t *addr, Elf32_Addr sym_addr); - /* Relocate symbols; note that this function overwrites the symbol table. Return the address of a start symbol. */ static Elf_Addr @@ -553,19 +550,27 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, case R_ARM_THM_CALL: case R_ARM_THM_JUMP24: { - grub_util_info (" THM_JUMP24:\ttarget=0x%08x\toffset=(0x%08x)", (unsigned int) target, sym_addr); + grub_err_t err; + grub_util_info (" THM_JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)", (unsigned long) target, sym_addr); sym_addr -= offset; /* Thumb instructions can be 16-bit aligned */ - reloc_thm_call ((grub_uint16_t *) target, sym_addr); + err = grub_arm_reloc_thm_call ((grub_uint16_t *) target, + sym_addr); + if (err) + grub_util_error ("%s", grub_errmsg); } break; case R_ARM_THM_JUMP19: { + grub_err_t err; grub_util_info (" THM_JUMP19:\toffset=%d\t(0x%08x)", sym_addr, sym_addr); sym_addr -= offset; /* Thumb instructions can be 16-bit aligned */ - reloc_thm_jump19 ((grub_uint16_t *) target, sym_addr); + err = grub_arm_reloc_thm_jump19 ((grub_uint16_t *) target, + sym_addr); + if (err) + grub_util_error ("%s", grub_errmsg); } break; default: