Relocations cleanup
This commit is contained in:
parent
4e13e84e56
commit
28af3d867c
3 changed files with 51 additions and 37 deletions
|
@ -23,17 +23,11 @@
|
|||
#include <grub/err.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/arm/reloc.h>
|
||||
|
||||
#ifdef GRUB_UTIL
|
||||
# include <grub/util/misc.h>
|
||||
#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<c>.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;
|
||||
}
|
||||
|
|
26
include/grub/arm/reloc.h
Normal file
26
include/grub/arm/reloc.h
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue