*cough* With actual attachment.
On Mon, Dec 02, 2013 at 11:53:31AM +0100, Leif Lindholm wrote: > On Sun, Dec 01, 2013 at 07:06:32AM +0100, Vladimir 'φ-coder/phcoder' > Serbinenko wrote: > > Current ARM relocation doesn't handle the cases when the relocation cant > > be satisfied directly (like thumb call over 1M of distance or jump24 to > > thumb mode. Attached patch adds missing tampoline and missing relocation > > handling to EFI code (it didn't allow to use ARM (no-Thumb) binary with > > EFI). > > I couldn't test it on either arm-efi or ARM64 > > Amusingly, I wrote the attached on Saturday, based on a bug report > from Jon Masters @ Red Hat. Although an unlikely corner case, it does > probably need the addition of grub_arch_dl_get_tramp_got_size() from > your implementation in order to ensure the "veneers"[1] don't end up > in a heap region different to and too far away from the one the module > is loaded into. > > I'll have a look and a poke on both 32- and 64-bit stuff and respond.. > > I would say the modifications to grub-mkimage for arm64 are probably > unnessecary: AArch64 relative branch range is +-128MB, and I don't > think we'll see grub kernel images that big. > > / > Leif > > [1] > ARM terminology - "trampolines" for ARM refers to something generated > on the stack, which we don't see anymore since the nested functions were > removed.
>From 8d7948641b864168acc67cf0a4834585b3242748 Mon Sep 17 00:00:00 2001 From: Leif Lindholm <[email protected]> Date: Sat, 30 Nov 2013 13:05:34 +0000 Subject: [PATCH] arm64: dl: generate veneers for out-of-range relocations Signed-off-by: Leif Lindholm <[email protected]> --- grub-core/kern/arm64/dl_helper.c | 45 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/grub-core/kern/arm64/dl_helper.c b/grub-core/kern/arm64/dl_helper.c index ae4bce8..a473661 100644 --- a/grub-core/kern/arm64/dl_helper.c +++ b/grub-core/kern/arm64/dl_helper.c @@ -17,6 +17,7 @@ * along with GRUB. If not, see <http://www.gnu.org/licenses/>. */ +#include <grub/cache.h> #include <grub/dl.h> #include <grub/elf.h> #include <grub/misc.h> @@ -32,6 +33,46 @@ sign_compress_offset (grub_ssize_t offset, int bitpos) } /* + * AArch64 relative branch offset range is +-128MB. + * Modules are loaded onto the heap, which may be further away from the + * kernel than this. The workaround for this is in ARM-terminology called + * a "veneer" - a short sequence of a literal load, a branch to register + * and immediately following: the literal (64-bit aligned) 64-bit value. + */ +#ifndef GRUB_UTIL +#define VENEER_LOAD 0x58000050 /* LDR x16, [PC + 8] */ +#define VENEER_JUMP 0xd61f0200 /* BR x16 */ +struct veneer { + grub_uint32_t load; + grub_uint32_t jump; + Elf64_Addr target; +}; + +static grub_err_t +add_veneer (grub_uint32_t *place, Elf64_Addr adjust) +{ + struct veneer *current; + grub_err_t retval; + + current = grub_malloc (sizeof(struct veneer)); + if (!current) + return GRUB_ERR_OUT_OF_MEMORY; + + current->load = VENEER_LOAD; + current->jump = VENEER_JUMP; + current->target = adjust; + + retval = grub_arm64_reloc_xxxx26 (place, (Elf64_Addr) current); + if (retval == GRUB_ERR_NONE) + grub_arch_sync_caches (current, sizeof(struct veneer)); + else + grub_free (current); + + return retval; +} +#endif + +/* * grub_arm64_reloc_xxxx26(): * * JUMP26/CALL26 relocations for B and BL instructions. @@ -54,8 +95,12 @@ grub_arm64_reloc_xxxx26 (grub_uint32_t *place, Elf64_Addr adjust) if ((offset < offset_low) || (offset > offset_high)) { +#ifndef GRUB_UTIL + return add_veneer (place, adjust); +#else return grub_error (GRUB_ERR_BAD_MODULE, N_("CALL26 Relocation out of range")); +#endif } grub_dprintf ("dl", " reloc_xxxx64 %p %c= 0x%llx\n", -- 1.7.10.4
_______________________________________________ Grub-devel mailing list [email protected] https://lists.gnu.org/mailman/listinfo/grub-devel
