From 7ef7b5574618bbeb08c0a59ed6011cb72549c7fd Mon Sep 17 00:00:00 2001 From: Sergiu Moga Date: Wed, 22 Mar 2023 21:10:42 +0200 Subject: [PATCH] lib/ukreloc/arch/x86_64: Add `ur_mov` instruction macro Due to the high number of references to absolute symbol values in the 16-bit and 32-bit bootstrap code, a new macro, `ur_mov`, was introduced. The new macro creates a new type of `_uk_reloc_` symbol, with an `imm` suffix, to show that it is placed right after a `mov` instruction whose immediate value must be relocated/patched. Thus, update `mkukreloc.py` accordingly. Furthermore, although useless, for completeness's sake add a 64-bit variant. This variant does a `movabs` with the placeholder to guarantee that the size of the immediate is 8 bytes. Signed-off-by: Sergiu Moga Reviewed-by: Dragos Petre Reviewed-by: Michalis Pappas Reviewed-by: Razvan Deaconescu Approved-by: Razvan Deaconescu Tested-by: Unikraft CI GitHub-Closes: #772 --- .../arch/x86_64/include/uk/asm/reloc.h | 56 +++++++++++++++++++ support/scripts/mkukreloc.py | 1 + 2 files changed, 57 insertions(+) create mode 100644 lib/ukreloc/arch/x86_64/include/uk/asm/reloc.h diff --git a/lib/ukreloc/arch/x86_64/include/uk/asm/reloc.h b/lib/ukreloc/arch/x86_64/include/uk/asm/reloc.h new file mode 100644 index 000000000..a2925b0e5 --- /dev/null +++ b/lib/ukreloc/arch/x86_64/include/uk/asm/reloc.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright (c) 2023, Unikraft GmbH and The Unikraft Authors. + * Licensed under the BSD-3-Clause License (the "License"). + * You may not use this file except in compliance with the License. + */ + +#ifndef __UK_RELOC_H__ +#error Do not include this header directly +#endif + +#ifdef __ASSEMBLY__ + +/* Relocation-friendly ur_mov to replace mov instructions incompatible with + * a PIE binary. Usage example: + * ``` + * ur_mov gdt64_ptr, %eax, 4 + * ``` + * The above will get mkukreloc.py to process the symbol gdt64_ptr_ukeloc_imm4 + * representing in memory where this data is placed and the following entry: + * struct uk_reloc { + * __u64 r_mem_off = gdt64_ptr_ukeloc_imm4 - __BASE_ADDR + * __u64 r_addr = gdt64_ptr - __BASE_ADDR + * __u32 r_sz = 4 from gdt64_ptr_ukeloc_imm[4] + * __u32 flags = 0 + * } __packed; + * + * If CONFIG_LIBUKRELOC is not enabled then it will be simply resolved to + * ``` + * mov $gdt64_ptr, %eax + * ``` + * + * @param sym The symbol to relocate + * @param req The register into which to place the value + * @param bytes The size in bytes of the relocation + * @param flags Optional, if value is _phys, UKRELOC_FLAGS_PHYS_REL is set + */ +.macro ur_mov sym:req, reg:req, bytes:req, flags +#if CONFIG_LIBUKRELOC +/* UKRELOC_PLACEHODER is 16 bits, so in 64-bit code we must force a `movabs` + * to ensure that the last amount of opcodes are meant for the immediate + */ +.ifeq (8 - \bytes) + movabs $UKRELOC_PLACEHOLDER, \reg +.endif +.ifgt (8 - \bytes) + mov $UKRELOC_PLACEHOLDER, \reg +.endif + ur_sym \sym\()_uk_reloc_imm\bytes\()\flags\(), (. - \bytes) + nop + ur_sec_updt \sym +#else /* CONFIG_LIBUKRELOC */ + mov $\sym, \reg +#endif /* !CONFIG_LIBUKRELOC */ +.endm + +#endif /* __ASSEMBLY__ */ diff --git a/support/scripts/mkukreloc.py b/support/scripts/mkukreloc.py index 423d0526e..c955046e0 100755 --- a/support/scripts/mkukreloc.py +++ b/support/scripts/mkukreloc.py @@ -221,6 +221,7 @@ def uk_reloc_sym_to_struct(elf, uk_reloc_sym): def build_uk_relocs(elf, rela_dyn_secs, max_r_mem_off): uk_relocs = [rela_to_uk_reloc(r) for r in rela_dyn_secs] uk_reloc_syms = get_nm_syms(elf, get_uk_reloc_sym_exp(r'data')) + uk_reloc_syms += get_nm_syms(elf, get_uk_reloc_sym_exp(r'imm')) # Also gather all of the PTE uk_reloc's for use against relocatable # PTE's. -- 2.39.5