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/err.h>
|
||||||
#include <grub/mm.h>
|
#include <grub/mm.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
|
#include <grub/arm/reloc.h>
|
||||||
|
|
||||||
#ifdef GRUB_UTIL
|
#ifdef GRUB_UTIL
|
||||||
# include <grub/util/misc.h>
|
# include <grub/util/misc.h>
|
||||||
#else
|
#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
|
#ifdef DL_DEBUG
|
||||||
static const char *symstrtab;
|
static const char *symstrtab;
|
||||||
|
@ -104,7 +98,7 @@ reloc_abs32 (Elf_Word *target, Elf_Addr sym_addr)
|
||||||
* B.W, BL and BLX
|
* B.W, BL and BLX
|
||||||
*/
|
*/
|
||||||
grub_err_t
|
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_int32_t offset, offset_low, offset_high;
|
||||||
grub_uint32_t sign, j1, j2, is_blx;
|
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 BLX, target symbol must be ARM (target address LSB == 0) */
|
||||||
if (is_blx && (sym_addr & 1))
|
if (is_blx && (sym_addr & 1))
|
||||||
{
|
return grub_error (GRUB_ERR_BUG,
|
||||||
#ifndef GRUB_UTIL
|
N_("Relocation targeting wrong execution state"));
|
||||||
return grub_error
|
|
||||||
(GRUB_ERR_BUG, N_("Relocation targeting wrong execution state"));
|
|
||||||
#else
|
|
||||||
grub_util_error ("Relocation targeting wrong execution state");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
offset_low = -16777216;
|
offset_low = -16777216;
|
||||||
offset_high = is_blx ? 16777212 : 16777214;
|
offset_high = is_blx ? 16777212 : 16777214;
|
||||||
|
@ -159,18 +147,12 @@ reloc_thm_call (grub_uint16_t *target, Elf32_Addr sym_addr)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((offset < offset_low) || (offset > offset_high))
|
if ((offset < offset_low) || (offset > offset_high))
|
||||||
{
|
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||||
#ifdef GRUB_UTIL
|
N_("THM_CALL Relocation out of range."));
|
||||||
grub_util_error ("Relocation out of range");
|
|
||||||
#else
|
|
||||||
return grub_error
|
|
||||||
(GRUB_ERR_OUT_OF_RANGE, N_("THM_CALL Relocation out of range."));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef GRUB_UTIL
|
#ifdef GRUB_UTIL
|
||||||
grub_util_info (" relative destination = 0x%08x",
|
grub_util_info (" relative destination = 0x%08lx",
|
||||||
(unsigned int)target + offset);
|
(unsigned long)target + offset);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Reassemble instruction word */
|
/* 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
|
* Relocate conditional Thumb (T32) B<c>.W
|
||||||
*/
|
*/
|
||||||
grub_err_t
|
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_int32_t offset;
|
||||||
grub_uint32_t insword, insmask;
|
grub_uint32_t insword, insmask;
|
||||||
|
@ -260,7 +242,7 @@ reloc_thm_jump19 (grub_uint16_t *addr, Elf32_Addr sym_addr)
|
||||||
* Relocate ARM (A32) B
|
* Relocate ARM (A32) B
|
||||||
*/
|
*/
|
||||||
grub_err_t
|
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_uint32_t insword;
|
||||||
grub_int32_t offset;
|
grub_int32_t offset;
|
||||||
|
@ -358,9 +340,10 @@ do_relocations (Elf_Shdr * relhdr, Elf_Ehdr * e, grub_dl_t mod)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case R_ARM_CALL:
|
||||||
case R_ARM_JUMP24:
|
case R_ARM_JUMP24:
|
||||||
{
|
{
|
||||||
retval = reloc_jump24 (target, sym_addr);
|
retval = grub_arm_reloc_jump24 (target, sym_addr);
|
||||||
if (retval != GRUB_ERR_NONE)
|
if (retval != GRUB_ERR_NONE)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -369,7 +352,7 @@ do_relocations (Elf_Shdr * relhdr, Elf_Ehdr * e, grub_dl_t mod)
|
||||||
case R_ARM_THM_JUMP24:
|
case R_ARM_THM_JUMP24:
|
||||||
{
|
{
|
||||||
/* Thumb instructions can be 16-bit aligned */
|
/* 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)
|
if (retval != GRUB_ERR_NONE)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -377,7 +360,7 @@ do_relocations (Elf_Shdr * relhdr, Elf_Ehdr * e, grub_dl_t mod)
|
||||||
case R_ARM_THM_JUMP19:
|
case R_ARM_THM_JUMP19:
|
||||||
{
|
{
|
||||||
/* Thumb instructions can be 16-bit aligned */
|
/* 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)
|
if (retval != GRUB_ERR_NONE)
|
||||||
return retval;
|
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);
|
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.
|
/* Relocate symbols; note that this function overwrites the symbol table.
|
||||||
Return the address of a start symbol. */
|
Return the address of a start symbol. */
|
||||||
static Elf_Addr
|
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_CALL:
|
||||||
case R_ARM_THM_JUMP24:
|
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;
|
sym_addr -= offset;
|
||||||
/* Thumb instructions can be 16-bit aligned */
|
/* 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;
|
break;
|
||||||
case R_ARM_THM_JUMP19:
|
case R_ARM_THM_JUMP19:
|
||||||
{
|
{
|
||||||
|
grub_err_t err;
|
||||||
grub_util_info (" THM_JUMP19:\toffset=%d\t(0x%08x)",
|
grub_util_info (" THM_JUMP19:\toffset=%d\t(0x%08x)",
|
||||||
sym_addr, sym_addr);
|
sym_addr, sym_addr);
|
||||||
sym_addr -= offset;
|
sym_addr -= offset;
|
||||||
/* Thumb instructions can be 16-bit aligned */
|
/* 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;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in a new issue