ET_REL images contain lots of complicated relocations. One new relocation we need to support is R_LARCH_GOT_PC_HI20/LO12. Rather than the eternal chasing of complicated we can use linker to handle them and then only relatively simple dynamic relocs remain to handle.
This required small adjustments to the asm code to be compatible with -shared. Signed-off-by: Vladimir Serbinenko <phco...@gmail.com> --- conf/Makefile.common | 2 +- configure.ac | 6 +- grub-core/Makefile.core.def | 20 +- grub-core/kern/ia64/efi/startup.S | 7 +- grub-core/kern/mips/startup.S | 4 +- grub-core/kern/x86_64/efi/startup.S | 12 +- include/grub/util/mkimage.h | 4 +- util/grub-mkimagexx.c | 540 ++++++++++++++-------------- 8 files changed, 293 insertions(+), 302 deletions(-) diff --git a/conf/Makefile.common b/conf/Makefile.common index 8b1bd65bc..40b1609df 100644 --- a/conf/Makefile.common +++ b/conf/Makefile.common @@ -41,7 +41,7 @@ CFLAGS_KERNEL = $(CFLAGS_PLATFORM) -ffreestanding LDFLAGS_KERNEL = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) CPPFLAGS_KERNEL = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) -DGRUB_KERNEL=1 CCASFLAGS_KERNEL = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) -STRIPFLAGS_KERNEL = -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags -R .ARM.exidx +STRIPFLAGS_KERNEL = -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags -R .ARM.exidx if !COND_emu if COND_HAVE_ASM_USCORE LDFLAGS_KERNEL += -Wl,--defsym=_malloc=_grub_malloc -Wl,--defsym=_free=_grub_free diff --git a/configure.ac b/configure.ac index ff06752d0..fbeea0c70 100644 --- a/configure.ac +++ b/configure.ac @@ -877,9 +877,6 @@ if ( test "x$target_cpu" = xi386 || test "x$target_cpu" = xx86_64 ); then fi if test "x$target_cpu" = xloongarch64; then - TARGET_CFLAGS="$TARGET_CFLAGS -fno-plt" - TARGET_CCASFLAGS="$TARGET_CCASFLAGS -fno-plt" - AC_CACHE_CHECK([for no-relax options], grub_cv_target_cc_mno_relax, [ grub_cv_target_cc_mno_relax=no for cand in "-mno-relax" "-Wa,-mno-relax"; do @@ -1437,7 +1434,8 @@ case $target_cpu-$platform in TARGET_CFLAGS="$TARGET_CFLAGS -fPIC" fi ;; - riscv32-* | ia64-*) + # THose platforms require -fPIC in order to generate ET_DYN + riscv32-* | ia64-* | loongarch64-*) TARGET_CFLAGS="$TARGET_CFLAGS -fPIC" ;; *) diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index f70e02e69..9cc0a0ac3 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -51,34 +51,34 @@ kernel = { emu_ldflags = '-Wl,-r'; i386_efi_cflags = '-fshort-wchar'; - i386_efi_ldflags = '-Wl,-r'; + i386_efi_ldflags = '$(TARGET_RELOCATABLE)'; i386_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; x86_64_efi_cflags = '-fshort-wchar'; - x86_64_efi_ldflags = '-Wl,-r'; + x86_64_efi_ldflags = '$(TARGET_RELOCATABLE)'; x86_64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; ia64_efi_cflags = '-fshort-wchar -fno-builtin -fpic -minline-int-divide-max-throughput'; - ia64_efi_ldflags = '-Wl,-r'; + ia64_efi_ldflags = '-shared'; ia64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; arm_efi_cflags = '-fshort-wchar'; - arm_efi_ldflags = '-Wl,-r'; + arm_efi_ldflags = '-shared'; arm_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; arm64_efi_cflags = '-fshort-wchar'; - arm64_efi_ldflags = '-Wl,-r'; + arm64_efi_ldflags = '-shared'; arm64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame'; loongarch64_efi_cflags = '-fshort-wchar'; - loongarch64_efi_ldflags = '-Wl,-r'; + loongarch64_efi_ldflags = '-shared'; loongarch64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame'; riscv32_efi_cflags = '-fshort-wchar'; - riscv32_efi_ldflags = '-Wl,-r'; + riscv32_efi_ldflags = '-shared'; riscv32_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame'; riscv64_efi_cflags = '-fshort-wchar'; - riscv64_efi_ldflags = '-Wl,-r'; + riscv64_efi_ldflags = '-shared'; riscv64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame'; i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; @@ -108,9 +108,9 @@ kernel = { i386_qemu_cppflags = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)'; emu_cflags = '$(CFLAGS_GNULIB)'; emu_cppflags = '$(CPPFLAGS_GNULIB)'; - arm_uboot_ldflags = '-Wl,-r'; + arm_uboot_ldflags = '-shared'; arm_uboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; - arm_coreboot_ldflags = '-Wl,-r'; + arm_coreboot_ldflags = '-shared'; arm_coreboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; i386_pc_startup = kern/i386/pc/startup.S; diff --git a/grub-core/kern/ia64/efi/startup.S b/grub-core/kern/ia64/efi/startup.S index d75c6d7cc..e220cbf2d 100644 --- a/grub-core/kern/ia64/efi/startup.S +++ b/grub-core/kern/ia64/efi/startup.S @@ -29,8 +29,11 @@ _start: alloc loc0=ar.pfs,2,4,0,0 mov loc1=rp - addl loc2=@gprel(grub_efi_image_handle),gp - addl loc3=@gprel(grub_efi_system_table),gp + addl loc2=@ltoffx(grub_efi_image_handle),r1 + addl loc3=@ltoffx(grub_efi_system_table),r1 + ;; + ld8.mov loc2 = [loc2], grub_efi_image_handle + ld8.mov loc3 = [loc3], grub_efi_system_table ;; st8 [loc2]=in0 st8 [loc3]=in1 diff --git a/grub-core/kern/mips/startup.S b/grub-core/kern/mips/startup.S index 1fdb58aca..fde64358c 100644 --- a/grub-core/kern/mips/startup.S +++ b/grub-core/kern/mips/startup.S @@ -74,8 +74,8 @@ cont: #endif /* Move the modules out of BSS. */ - lui $t2, %hi(__bss_start) - addiu $t2, %lo(__bss_start) + lui $t2, %hi(_edata) + addiu $t2, %lo(_edata) lui $t1, %hi(_end) addiu $t1, %lo(_end) diff --git a/grub-core/kern/x86_64/efi/startup.S b/grub-core/kern/x86_64/efi/startup.S index 9357e5c5d..f93aae424 100644 --- a/grub-core/kern/x86_64/efi/startup.S +++ b/grub-core/kern/x86_64/efi/startup.S @@ -25,10 +25,18 @@ .globl start, _start .code64 +#if defined(__MINGW32__) || defined(__CYGWIN__) +#define EXT_GOT(x) .refptr. ## x +#else +#define EXT_GOT(x) x @ GOTPCREL +#endif + start: _start: - movq %rcx, EXT_C(grub_efi_image_handle)(%rip) - movq %rdx, EXT_C(grub_efi_system_table)(%rip) + movq EXT_GOT(grub_efi_image_handle) (%rip), %rax + movq %rcx, (%rax) + movq EXT_GOT(grub_efi_system_table)(%rip), %rax + movq %rdx, (%rax) andq $~0xf, %rsp call EXT_C(grub_main) diff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h index 9d74f82c5..72ac9758f 100644 --- a/include/grub/util/mkimage.h +++ b/include/grub/util/mkimage.h @@ -30,12 +30,14 @@ struct grub_mkimage_layout size_t reloc_size; size_t align; grub_size_t ia64jmp_off; - grub_size_t tramp_off; grub_size_t got_off; grub_size_t got_size; unsigned ia64jmpnum; grub_uint32_t bss_start; grub_uint32_t end; + grub_int64_t vaddr_diff; + grub_int64_t off_diff; + grub_size_t dyn_pltoff; }; /* Private header. Use only in mkimage-related sources. */ diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c index 97e83671a..a60f1730a 100644 --- a/util/grub-mkimagexx.c +++ b/util/grub-mkimagexx.c @@ -100,11 +100,13 @@ struct section_metadata { Elf_Half num_sections; Elf_Shdr *sections; - Elf_Addr *addrs; - Elf_Addr *vaddrs; Elf_Half section_entsize; Elf_Shdr *symtab; const char *strtab; + + Elf_Half num_phdrs; + Elf_Phdr *phdrs; + Elf_Half phdr_entsize; }; #define GRUB_SBAT_NOTE_NAME ".sbat" @@ -604,7 +606,7 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc static Elf_Addr SUFFIX (relocate_symbols) (Elf_Ehdr *e, struct section_metadata *smd, void *jumpers, Elf_Addr jumpers_addr, - Elf_Addr bss_start, Elf_Addr end, + struct grub_mkimage_layout *layout, const struct grub_install_image_target_desc *image_target) { Elf_Word symtab_size, sym_size, num_syms; @@ -642,11 +644,7 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, struct section_metadata *smd, } else if (cur_index == STN_UNDEF) { - if (sym->st_name && grub_strcmp (name, "__bss_start") == 0) - sym->st_value = bss_start; - else if (sym->st_name && grub_strcmp (name, "_end") == 0) - sym->st_value = end; - else if (sym->st_name) + if (sym->st_name) grub_util_error ("undefined symbol %s", name); else continue; @@ -656,7 +654,7 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, struct section_metadata *smd, else { sym->st_value = (grub_target_to_host (sym->st_value) - + smd->vaddrs[cur_index]); + + layout->vaddr_diff); } if (image_target->elf_target == EM_IA_64 && ELF_ST_TYPE (sym->st_info) @@ -665,13 +663,11 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, struct section_metadata *smd, *jptr = grub_host_to_target64 (sym->st_value); sym->st_value = (char *) jptr - (char *) jumpers + jumpers_addr; jptr++; - *jptr = 0; + *jptr = layout->vaddr_diff + layout->dyn_pltoff; jptr++; } - grub_util_info ("locating %s at 0x%" GRUB_HOST_PRIxLONG_LONG - " (0x%" GRUB_HOST_PRIxLONG_LONG ")", name, - (unsigned long long) sym->st_value, - (unsigned long long) smd->vaddrs[cur_index]); + grub_util_info ("locating %s at 0x%" GRUB_HOST_PRIxLONG_LONG, name, + (unsigned long long) sym->st_value); if (start_address == (Elf_Addr)-1) if (strcmp (name, "_start") == 0 || strcmp (name, "start") == 0) @@ -696,10 +692,10 @@ SUFFIX (get_symbol_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Word i, /* Return the address of a modified value. */ static Elf_Addr * -SUFFIX (get_target_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Addr offset, +SUFFIX (get_target_address) (char *e, struct grub_mkimage_layout *layout, Elf_Addr offset, const struct grub_install_image_target_desc *image_target) { - return (Elf_Addr *) ((char *) e + grub_target_to_host (s->sh_offset) + offset); + return (Elf_Addr *) ((char *) e + offset + layout->off_diff); } #ifdef MKIMAGE_ELF64 @@ -783,6 +779,8 @@ arm_get_trampoline_size (Elf_Ehdr *e, { case R_ARM_ABS32: case R_ARM_V4BX: + case R_ARM_JUMP_SLOT: + case R_ARM_RELATIVE: break; case R_ARM_THM_CALL: case R_ARM_THM_JUMP24: @@ -820,20 +818,17 @@ SUFFIX (is_kept_reloc_section) (Elf_Shdr *s, const struct grub_install_image_tar again by a PE32 relocator when loaded. */ static void SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, - char *pe_target, Elf_Addr tramp_off, Elf_Addr got_off, + char *pe_target, struct grub_mkimage_layout *layout, const struct grub_install_image_target_desc *image_target) { Elf_Half i; Elf_Shdr *s; #ifdef MKIMAGE_ELF64 - struct grub_ia64_trampoline *tr = (void *) (pe_target + tramp_off); - grub_uint64_t *gpptr = (void *) (pe_target + got_off); + grub_uint64_t *gpptr = (void *) (pe_target + layout->got_off); unsigned unmatched_adr_got_page = 0; struct grub_loongarch64_stack stack; grub_loongarch64_stack_init (&stack); #define MASK19 ((1 << 19) - 1) -#else - grub_uint32_t *tr = (void *) (pe_target + tramp_off); #endif for (i = 0, s = smd->sections; @@ -846,7 +841,7 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, Elf_Word rtab_size, r_size, num_rs; Elf_Off rtab_offset; Elf_Word target_section_index; - Elf_Addr target_section_addr; + Elf_Addr target_section_vaddr = layout->vaddr_diff; Elf_Shdr *target_section; Elf_Word j; @@ -859,7 +854,6 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, } target_section_index = grub_target_to_host32 (s->sh_info); - target_section_addr = smd->addrs[target_section_index]; target_section = (Elf_Shdr *) ((char *) smd->sections + (target_section_index * smd->section_entsize)); @@ -884,7 +878,7 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, Elf_Addr addend; offset = grub_target_to_host (r->r_offset); - target = SUFFIX (get_target_address) (e, target_section, + target = SUFFIX (get_target_address) (pe_target, layout, offset, image_target); info = grub_target_to_host (r->r_info); sym_addr = SUFFIX (get_symbol_address) (e, smd->symtab, @@ -901,6 +895,10 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, case R_386_NONE: break; + case R_386_RELATIVE: + *target = grub_host_to_target32 (grub_target_to_host32 (*target) + addend + layout->vaddr_diff); + break; + case R_386_32: /* This is absolute. */ *target = grub_host_to_target32 (grub_target_to_host32 (*target) @@ -916,8 +914,7 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, /* This is relative. */ *target = grub_host_to_target32 (grub_target_to_host32 (*target) + addend + sym_addr - - target_section_addr - offset - - image_target->vaddr_offset); + - target_section_vaddr - offset); grub_util_info ("relocating an R_386_PC32 entry to 0x%" GRUB_HOST_PRIxLONG_LONG " at the offset 0x%" GRUB_HOST_PRIxLONG_LONG, @@ -938,10 +935,25 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, case R_X86_64_NONE: break; + case R_X86_64_RELATIVE: + *target = grub_host_to_target64 (addend + layout->vaddr_diff); + break; + + case R_X86_64_GLOB_DAT: case R_X86_64_64: *target = grub_host_to_target64 (grub_target_to_host64 (*target) + addend + sym_addr); grub_util_info ("relocating an R_X86_64_64 entry to 0x%" + GRUB_HOST_PRIxLONG_LONG " at the offset 0x%" + GRUB_HOST_PRIxLONG_LONG " by 0x%" GRUB_HOST_PRIxLONG_LONG, + (unsigned long long) *target, + (unsigned long long) offset, + (unsigned long long) addend + sym_addr); + break; + + case R_X86_64_JUMP_SLOT: + *target = grub_host_to_target64 (addend + sym_addr); + grub_util_info ("relocating an R_X86_64_JUMP_SLOT entry to 0x%" GRUB_HOST_PRIxLONG_LONG " at the offset 0x%" GRUB_HOST_PRIxLONG_LONG, (unsigned long long) *target, @@ -954,8 +966,7 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, grub_uint32_t *t32 = (grub_uint32_t *) target; *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32) + addend + sym_addr - - target_section_addr - offset - - image_target->vaddr_offset); + - target_section_vaddr - offset); grub_util_info ("relocating an R_X86_64_PC32 entry to 0x%x at the offset 0x%" GRUB_HOST_PRIxLONG_LONG, *t32, (unsigned long long) offset); @@ -966,8 +977,7 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, { *target = grub_host_to_target64 (grub_target_to_host64 (*target) + addend + sym_addr - - target_section_addr - offset - - image_target->vaddr_offset); + - target_section_vaddr - offset); grub_util_info ("relocating an R_X86_64_PC64 entry to 0x%" GRUB_HOST_PRIxLONG_LONG " at the offset 0x%" GRUB_HOST_PRIxLONG_LONG, @@ -998,18 +1008,11 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, switch (ELF_R_TYPE (info)) { case R_IA64_PCREL21B: - { - grub_uint64_t noff; - grub_ia64_make_trampoline (tr, addend + sym_addr); - noff = ((char *) tr - (char *) pe_target - - target_section_addr - (offset & ~3)) >> 4; - tr++; - if (noff & ~MASK19) - grub_util_error ("trampoline offset too big (%" - GRUB_HOST_PRIxLONG_LONG ")", - (unsigned long long) noff); - grub_ia64_add_value_to_slot_20b ((grub_addr_t) target, noff); - } + grub_util_error("inserting trampolines is no longer supported"); + break; + + case R_IA64_REL64LSB: + *target = grub_host_to_target64 (addend + layout->vaddr_diff); break; case R_IA64_LTOFF22X: @@ -1045,18 +1048,21 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, case R_IA64_PCREL64LSB: *target = grub_host_to_target64 (grub_target_to_host64 (*target) + addend + sym_addr - - target_section_addr - offset - - image_target->vaddr_offset); + - target_section_vaddr - offset); break; - case R_IA64_SEGREL64LSB: - *target = grub_host_to_target64 (grub_target_to_host64 (*target) - + addend + sym_addr - target_section_addr); + case R_IA64_IPLTLSB: + memcpy(target, ((char *)pe_target + addend + sym_addr - image_target->vaddr_offset), 16); + grub_util_info ("relocating an IPLT entry to 0x%" + GRUB_HOST_PRIxLONG_LONG " at the offset 0x%" + GRUB_HOST_PRIxLONG_LONG, + (unsigned long long) + grub_target_to_host64 (*target), + (unsigned long long) offset); break; case R_IA64_DIR64LSB: case R_IA64_FPTR64LSB: - *target = grub_host_to_target64 (grub_target_to_host64 (*target) - + addend + sym_addr); + *target = grub_host_to_target64 (addend + sym_addr); grub_util_info ("relocating a direct entry to 0x%" GRUB_HOST_PRIxLONG_LONG " at the offset 0x%" GRUB_HOST_PRIxLONG_LONG, @@ -1080,18 +1086,23 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, sym_addr += addend; switch (ELF_R_TYPE (info)) { + case R_AARCH64_JUMP_SLOT: + *target = grub_host_to_target64 (sym_addr); + break; case R_AARCH64_ABS64: { *target = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr); } break; + case R_AARCH64_RELATIVE: + *target = grub_host_to_target64 (addend + layout->vaddr_diff); + break; case R_AARCH64_PREL32: { grub_uint32_t *t32 = (grub_uint32_t *) target; *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32) + sym_addr - - target_section_addr - offset - - image_target->vaddr_offset); + - target_section_vaddr - offset); grub_util_info ("relocating an R_AARCH64_PREL32 entry to 0x%x at the offset 0x%" GRUB_HOST_PRIxLONG_LONG, *t32, (unsigned long long) offset); @@ -1109,7 +1120,7 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, case R_AARCH64_CALL26: { sym_addr -= offset; - sym_addr -= target_section_addr + image_target->vaddr_offset; + sym_addr -= target_section_vaddr; if (!grub_arm_64_check_xxxx26_offset (sym_addr)) grub_util_error ("%s", "CALL26 Relocation out of range"); @@ -1121,7 +1132,7 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, { Elf64_Rela *rel2; grub_int64_t gpoffset = (((char *) gpptr - (char *) pe_target + image_target->vaddr_offset) & ~0xfffULL) - - ((offset + target_section_addr + image_target->vaddr_offset) & ~0xfffULL); + - ((offset + target_section_vaddr) & ~0xfffULL); unsigned k; *gpptr = grub_host_to_target64 (sym_addr); unmatched_adr_got_page++; @@ -1137,7 +1148,7 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, && r->r_addend == rel2->r_addend && ELF_R_TYPE (rel2->r_info) == R_AARCH64_LD64_GOT_LO12_NC) { - grub_arm64_set_abs_lo12_ldst64 ((grub_uint32_t *) SUFFIX (get_target_address) (e, target_section, + grub_arm64_set_abs_lo12_ldst64 ((grub_uint32_t *) SUFFIX (get_target_address) (pe_target, layout, grub_target_to_host (rel2->r_offset), image_target), ((char *) gpptr - (char *) pe_target + image_target->vaddr_offset)); break; @@ -1155,7 +1166,7 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, case R_AARCH64_ADR_PREL_PG_HI21: { sym_addr &= ~0xfffULL; - sym_addr -= (offset + target_section_addr + image_target->vaddr_offset) & ~0xfffULL; + sym_addr -= (offset + target_section_vaddr) & ~0xfffULL; if (!grub_arm64_check_hi21_signed (sym_addr)) grub_util_error ("%s", "CALL26 Relocation out of range"); @@ -1177,24 +1188,29 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, grub_uint32_t *t32 = (grub_uint32_t *) target; sym_addr += addend; - pc = offset + target_section_addr + image_target->vaddr_offset; + pc = offset + target_section_vaddr; switch (ELF_R_TYPE (info)) { case R_LARCH_64: { grub_uint64_t *t64 = (grub_uint64_t *) target; - *t64 = grub_host_to_target64 (grub_target_to_host64 (*t64) + sym_addr); + *t64 = grub_host_to_target64 (sym_addr); } break; + case R_LARCH_JUMP_SLOT: + *target = grub_host_to_target64 (sym_addr); + break; + case R_LARCH_RELATIVE: + *target = grub_host_to_target64 (addend + layout->vaddr_diff); + break; case R_LARCH_MARK_LA: break; case R_LARCH_SOP_PUSH_PCREL: case R_LARCH_SOP_PUSH_PLT_PCREL: grub_loongarch64_sop_push (&stack, sym_addr - -(target_section_addr - +offset - +image_target->vaddr_offset)); + -(target_section_vaddr + +offset)); break; case R_LARCH_B26: { @@ -1243,6 +1259,15 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, sym_addr -= image_target->vaddr_offset; switch (ELF_R_TYPE (info)) { + case R_ARM_JUMP_SLOT: + { + grub_util_info (" JUMP:\toffset=%d\t(0x%08x)", + (int) sym_addr, (int) sym_addr); + if (image_target->id == IMAGE_EFI) + sym_addr += GRUB_PE32_SECTION_ALIGNMENT; + *target = grub_host_to_target32 (sym_addr); + break; + } case R_ARM_ABS32: { grub_util_info (" ABS32:\toffset=%d\t(0x%08x)", @@ -1253,6 +1278,9 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, *target = grub_host_to_target32 (grub_target_to_host32 (*target) + sym_addr); } break; + case R_ARM_RELATIVE: + *target = grub_host_to_target32 (grub_target_to_host32 (*target) + addend + layout->vaddr_diff); + break; /* Happens when compiled with -march=armv4. Since currently we need at least armv5, keep bx as-is. */ @@ -1274,21 +1302,7 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, if (ELF_ST_TYPE (sym->st_info) != STT_FUNC) sym_addr |= 1; if (!(sym_addr & 1)) - { - grub_uint32_t tr_addr; - grub_int32_t new_offset; - tr_addr = (char *) tr - (char *) pe_target - - target_section_addr; - new_offset = sym_addr - tr_addr - 12; - - if (!grub_arm_jump24_check_offset (new_offset)) - return grub_util_error ("jump24 relocation out of range"); - - tr[0] = grub_host_to_target32 (0x46c04778); /* bx pc; nop */ - tr[1] = grub_host_to_target32 (((new_offset >> 2) & 0xffffff) | 0xea000000); /* b new_offset */ - tr += 2; - sym_addr = tr_addr | 1; - } + grub_util_error("inserting trampolines is no longer supported"); sym_addr -= offset; /* Thumb instructions can be 16-bit aligned */ if (ELF_R_TYPE (info) == R_ARM_THM_JUMP19) @@ -1307,21 +1321,7 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, grub_err_t err; grub_util_info (" JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)", (unsigned long) ((char *) target - (char *) e), sym_addr); if (sym_addr & 1) - { - grub_uint32_t tr_addr; - grub_int32_t new_offset; - tr_addr = (char *) tr - (char *) pe_target - - target_section_addr; - new_offset = sym_addr - tr_addr - 12; - - /* There is no immediate version of bx, only register one... */ - tr[0] = grub_host_to_target32 (0xe59fc004); /* ldr ip, [pc, #4] */ - tr[1] = grub_host_to_target32 (0xe08cc00f); /* add ip, ip, pc */ - tr[2] = grub_host_to_target32 (0xe12fff1c); /* bx ip */ - tr[3] = grub_host_to_target32 (new_offset | 1); - tr += 4; - sym_addr = tr_addr; - } + grub_util_error("inserting trampolines is no longer supported"); sym_addr -= offset; err = grub_arm_reloc_jump24 (target, sym_addr); @@ -1354,10 +1354,16 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, */ sym_addr += addend; - off = sym_addr - target_section_addr - offset - image_target->vaddr_offset; + off = sym_addr - target_section_vaddr - offset - image_target->vaddr_offset; switch (ELF_R_TYPE (info)) { + case R_RISCV_JUMP_SLOT: + *target = grub_host_to_target_addr (sym_addr); + break; + case R_RISCV_RELATIVE: + *target = grub_host_to_target_addr (addend + layout->vaddr_diff); + break; case R_RISCV_ADD8: *t8 = *t8 + sym_addr; break; @@ -1477,7 +1483,7 @@ SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd, rel2_offset = grub_target_to_host (rel2->r_offset); rel2_info = grub_target_to_host (rel2->r_info); - rel2_loc = target_section_addr + rel2_offset + image_target->vaddr_offset; + rel2_loc = target_section_vaddr + rel2_offset + image_target->vaddr_offset; if (ELF_R_TYPE (rel2_info) == R_RISCV_PCREL_HI20 && rel2_loc == sym_addr) @@ -1678,7 +1684,7 @@ translate_relocation_pe (struct translate_context *ctx, switch (image_target->elf_target) { case EM_386: - if (ELF_R_TYPE (info) == R_386_32) + if (ELF_R_TYPE (info) == R_386_32 || ELF_R_TYPE (info) == R_386_RELATIVE) { grub_util_info ("adding a relocation entry for 0x%" GRUB_HOST_PRIxLONG_LONG, @@ -1696,7 +1702,10 @@ translate_relocation_pe (struct translate_context *ctx, { grub_util_error ("can\'t add fixup entry for R_X86_64_32(S)"); } - else if (ELF_R_TYPE (info) == R_X86_64_64) + else if (ELF_R_TYPE (info) == R_X86_64_64 + || ELF_R_TYPE (info) == R_X86_64_RELATIVE + || ELF_R_TYPE (info) == R_X86_64_JUMP_SLOT + || ELF_R_TYPE (info) == R_X86_64_GLOB_DAT) { grub_util_info ("adding a relocation entry for 0x%" GRUB_HOST_PRIxLONG_LONG, @@ -1723,8 +1732,31 @@ translate_relocation_pe (struct translate_context *ctx, case R_IA64_SEGREL64LSB: break; + case R_IA64_IPLTLSB: +#if 1 + { + grub_util_info ("adding a relocation entry for 0x%" + GRUB_HOST_PRIxLONG_LONG, + (unsigned long long) addr); + ctx->current_address + = add_fixup_entry (&ctx->lst, + GRUB_PE32_REL_BASED_DIR64, + addr, + 0, ctx->current_address, + image_target); + ctx->current_address + = add_fixup_entry (&ctx->lst, + GRUB_PE32_REL_BASED_DIR64, + addr + 8, + 0, ctx->current_address, + image_target); + } +#endif + break; + case R_IA64_FPTR64LSB: case R_IA64_DIR64LSB: + case R_IA64_REL64LSB: #if 1 { grub_util_info ("adding a relocation entry for 0x%" @@ -1749,7 +1781,9 @@ translate_relocation_pe (struct translate_context *ctx, #if defined(MKIMAGE_ELF64) switch (ELF_R_TYPE (info)) { + case R_AARCH64_RELATIVE: case R_AARCH64_ABS64: + case R_AARCH64_JUMP_SLOT: { ctx->current_address = add_fixup_entry (&ctx->lst, @@ -1789,6 +1823,8 @@ translate_relocation_pe (struct translate_context *ctx, switch (ELF_R_TYPE (info)) { case R_LARCH_64: + case R_LARCH_RELATIVE: + case R_LARCH_JUMP_SLOT: { ctx->current_address = add_fixup_entry (&ctx->lst, GRUB_PE32_REL_BASED_DIR64, @@ -1859,6 +1895,8 @@ translate_relocation_pe (struct translate_context *ctx, break; /* Create fixup entry for PE/COFF loader */ case R_ARM_ABS32: + case R_ARM_JUMP_SLOT: + case R_ARM_RELATIVE: { ctx->current_address = add_fixup_entry (&ctx->lst, @@ -1877,6 +1915,10 @@ translate_relocation_pe (struct translate_context *ctx, case EM_RISCV: switch (ELF_R_TYPE (info)) { +#if defined(MKIMAGE_ELF32) + case R_RISCV_RELATIVE: + case R_RISCV_JUMP_SLOT: +#endif case R_RISCV_32: { ctx->current_address @@ -1886,6 +1928,10 @@ translate_relocation_pe (struct translate_context *ctx, image_target); } break; +#if defined(MKIMAGE_ELF64) + case R_RISCV_RELATIVE: + case R_RISCV_JUMP_SLOT: +#endif case R_RISCV_64: { ctx->current_address @@ -2147,7 +2193,6 @@ make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout, Elf_Rel *r; Elf_Word rtab_size, r_size, num_rs; Elf_Off rtab_offset; - Elf_Addr section_address; Elf_Word j; if (!SUFFIX (is_kept_reloc_section) (s, image_target, smd)) @@ -2165,8 +2210,6 @@ make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout, rtab_offset = grub_target_to_host (s->sh_offset); num_rs = rtab_size / r_size; - section_address = smd->vaddrs[grub_le_to_cpu32 (s->sh_info)]; - for (j = 0, r = (Elf_Rel *) ((char *) e + rtab_offset); j < num_rs; j++, r = (Elf_Rel *) ((char *) r + r_size)) @@ -2178,7 +2221,7 @@ make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout, offset = grub_target_to_host (r->r_offset); info = grub_target_to_host (r->r_info); - addr = section_address + offset; + addr = layout->vaddr_diff + offset; translate_relocation (&ctx, addr, info, image_target); } @@ -2262,6 +2305,9 @@ SUFFIX (is_kept_reloc_section) (Elf_Shdr *s, const struct grub_install_image_tar int r = 0; const char *name = smd->strtab + grub_host_to_target32 (s->sh_name); + if (strncmp (name, ".rela.dyn", 9) == 0 || strncmp (name, ".rel.dyn", 8) == 0) + return 1; + if (!strncmp (name, ".rela.", 6)) name += 5; else if (!strncmp (name, ".rel.", 5)) @@ -2299,31 +2345,6 @@ SUFFIX (check_elf_header) (Elf_Ehdr *e, size_t size, const struct grub_install_i return 1; } -static Elf_Addr -SUFFIX (put_section) (Elf_Shdr *s, int i, - Elf_Addr current_address, - struct section_metadata *smd, - const struct grub_install_image_target_desc *image_target) -{ - Elf_Word align = grub_host_to_target_addr (s->sh_addralign); - const char *name = smd->strtab + grub_host_to_target32 (s->sh_name); - - if (align) - current_address = ALIGN_UP (current_address + image_target->vaddr_offset, - align) - - image_target->vaddr_offset; - - grub_util_info ("locating the section %s at 0x%" - GRUB_HOST_PRIxLONG_LONG, - name, (unsigned long long) current_address); - if (!is_relocatable (image_target)) - current_address = grub_host_to_target_addr (s->sh_addr) - - image_target->link_addr; - smd->addrs[i] = current_address; - current_address += grub_host_to_target_addr (s->sh_size); - return current_address; -} - /* * Locate section addresses by merging code sections and data sections * into .text and .data, respectively. @@ -2335,97 +2356,105 @@ SUFFIX (locate_sections) (Elf_Ehdr *e, const char *kernel_path, const struct grub_install_image_target_desc *image_target) { int i; - Elf_Shdr *s; + Elf_Phdr *p; layout->align = 1; + layout->kernel_size = 0; + + Elf_Addr min_vaddr = ~(Elf_Addr)0; + Elf_Addr max_vaddr = 0; + Elf_Addr max_filled_vaddr = 0; + Elf_Addr max_align = 1; + Elf_Addr max_execvaddr = 0; + Elf_Addr min_wvaddr = ~(Elf_Addr)0; + /* Page-aligning simplifies relocation handling. */ if (image_target->elf_target == EM_AARCH64) - layout->align = 4096; + max_align = 4096; - layout->kernel_size = 0; + for (i = 0, p = smd->phdrs; + i < smd->num_phdrs; + i++, p = (Elf_Phdr *) ((char *) p + smd->phdr_entsize)) + { + if (grub_target_to_host32 (p->p_type) == PT_LOAD) + { + if (grub_target_to_host (p->p_vaddr) < min_vaddr) + min_vaddr = grub_target_to_host (p->p_vaddr); + if (grub_target_to_host (p->p_vaddr) + grub_target_to_host (p->p_memsz) > max_vaddr) + max_vaddr = grub_target_to_host (p->p_vaddr) + grub_target_to_host (p->p_memsz); + if (p->p_filesz != 0 && grub_target_to_host (p->p_vaddr) + grub_target_to_host (p->p_filesz) > max_filled_vaddr) + max_filled_vaddr = grub_target_to_host (p->p_vaddr) + grub_target_to_host (p->p_filesz); + if ((grub_target_to_host32 (p->p_flags) & PF_X) && grub_target_to_host (p->p_vaddr) + grub_target_to_host (p->p_memsz) > max_execvaddr) + max_execvaddr = grub_target_to_host (p->p_vaddr) + grub_target_to_host (p->p_memsz); + if ((grub_target_to_host32 (p->p_flags) & PF_W) && grub_target_to_host (p->p_vaddr) < min_wvaddr) + min_wvaddr = grub_target_to_host (p->p_vaddr); + if (grub_target_to_host (p->p_align) > max_align) + max_align = grub_target_to_host (p->p_align); + } + if (grub_target_to_host32 (p->p_type) == PT_DYNAMIC) + { + Elf64_Dyn *dyn = (Elf64_Dyn *) ((char *) e + grub_target_to_host (p->p_offset)); + grub_size_t sz = grub_target_to_host (p->p_filesz); + unsigned j; + for (j = 0; j < sz / sizeof(dyn[0]); j++) + switch (dyn[j].d_tag) + { + case DT_PLTGOT: + layout->dyn_pltoff = dyn[j].d_un.d_ptr; + break; + case DT_NULL: + goto end_dynamic; + } + end_dynamic:; + } + } - for (i = 0, s = smd->sections; - i < smd->num_sections; - i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize)) - if ((grub_target_to_host (s->sh_flags) & SHF_ALLOC) - && grub_host_to_target32 (s->sh_addralign) > layout->align) - layout->align = grub_host_to_target32 (s->sh_addralign); + if (image_target->id == IMAGE_EFI) + { + if (ALIGN_DOWN(min_wvaddr, 4096) < ALIGN_UP(max_execvaddr, 4096)) + grub_util_error("writable and executable overlap"); + max_execvaddr = ALIGN_UP(max_execvaddr, 4096); + } - /* .text */ - for (i = 0, s = smd->sections; - i < smd->num_sections; - i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize)) - if (SUFFIX (is_text_section) (s, image_target)) - { - layout->kernel_size = SUFFIX (put_section) (s, i, layout->kernel_size, - smd, image_target); - if (!is_relocatable (image_target) && - grub_host_to_target_addr (s->sh_addr) != image_target->link_addr) - { - char *msg - = grub_xasprintf (_("`%s' is miscompiled: its start address is 0x%llx" - " instead of 0x%llx: ld.gold bug?"), - kernel_path, - (unsigned long long) grub_host_to_target_addr (s->sh_addr), - (unsigned long long) image_target->link_addr); - grub_util_error ("%s", msg); - } - } + if (!is_relocatable (image_target) && + min_vaddr != image_target->link_addr) + { + char *msg + = grub_xasprintf (_("`%s' is miscompiled: its start address is 0x%llx" + " instead of 0x%llx: ld.gold bug?"), + kernel_path, + (unsigned long long) min_vaddr, + (unsigned long long) image_target->link_addr); + grub_util_error ("%s", msg); + } + + layout->vaddr_diff = image_target->vaddr_offset; + layout->off_diff = -(grub_int64_t)min_vaddr; + layout->kernel_size = max_filled_vaddr - min_vaddr; + layout->bss_size = max_vaddr - max_filled_vaddr; + layout->exec_size = max_execvaddr - min_vaddr; + layout->align = max_align; + + if (image_target->id == IMAGE_EFI) + { + layout->kernel_size += layout->bss_size; + layout->bss_size = 0; + } #ifdef MKIMAGE_ELF32 if (image_target->elf_target == EM_ARM) { grub_size_t tramp; - layout->kernel_size = ALIGN_UP (layout->kernel_size, 16); - tramp = arm_get_trampoline_size (e, smd->sections, smd->section_entsize, smd->num_sections, image_target); - - layout->tramp_off = layout->kernel_size; - layout->kernel_size += ALIGN_UP (tramp, 16); + if (tramp != 0) + grub_util_error("inserting trampolines is no longer supported"); } #endif - layout->kernel_size = ALIGN_UP (layout->kernel_size + image_target->vaddr_offset, - image_target->section_align) - - image_target->vaddr_offset; - layout->exec_size = layout->kernel_size; - - /* .data */ - for (i = 0, s = smd->sections; - i < smd->num_sections; - i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize)) - if (SUFFIX (is_data_section) (s, image_target)) - layout->kernel_size = SUFFIX (put_section) (s, i, layout->kernel_size, smd, - image_target); - - layout->bss_start = layout->kernel_size; - layout->end = layout->kernel_size; - - /* .bss */ - for (i = 0, s = smd->sections; - i < smd->num_sections; - i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize)) - { - if (SUFFIX (is_bss_section) (s, image_target)) - layout->end = SUFFIX (put_section) (s, i, layout->end, smd, image_target); - - /* - * This must to be in the last time this function passes through the loop. - */ - smd->vaddrs[i] = smd->addrs[i] + image_target->vaddr_offset; - } - - layout->end = ALIGN_UP (layout->end + image_target->vaddr_offset, + layout->end = ALIGN_UP (layout->kernel_size + image_target->vaddr_offset, image_target->section_align) - image_target->vaddr_offset; - /* Explicitly initialize BSS - when producing PE32 to avoid a bug in EFI implementations. - Platforms other than EFI and U-boot shouldn't have .bss in - their binaries as we build with -Wl,-Ttext. - */ - if (image_target->id == IMAGE_EFI || !is_relocatable (image_target)) - layout->kernel_size = layout->end; } char * @@ -2435,11 +2464,12 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path, const struct grub_install_image_target_desc *image_target) { char *kernel_img, *out_img; - struct section_metadata smd = { 0, 0, 0, 0, 0, 0, 0 }; + struct section_metadata smd = { 0, 0, 0, 0, 0, 0, 0, 0 }; Elf_Ehdr *e; int i; Elf_Shdr *s; - Elf_Off section_offset; + Elf_Phdr *p; + Elf_Off section_offset, phdr_offset; grub_size_t kernel_size; grub_memset (layout, 0, sizeof (*layout)); @@ -2464,71 +2494,23 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path, smd.sections = (Elf_Shdr *) (kernel_img + section_offset); + phdr_offset = grub_target_to_host (e->e_phoff); + smd.phdr_entsize = grub_target_to_host16 (e->e_phentsize); + smd.num_phdrs = grub_target_to_host16 (e->e_phnum); + + if (kernel_size < phdr_offset + + (grub_uint32_t) smd.phdr_entsize * smd.num_phdrs) + grub_util_error (_("premature end of file %s"), kernel_path); + + smd.phdrs = (Elf_Phdr *) (kernel_img + phdr_offset); + /* Relocate sections then symbols in the virtual address space. */ s = (Elf_Shdr *) ((char *) smd.sections + grub_host_to_target16 (e->e_shstrndx) * smd.section_entsize); smd.strtab = (char *) e + grub_host_to_target_addr (s->sh_offset); - smd.addrs = xcalloc (smd.num_sections, sizeof (*smd.addrs)); - smd.vaddrs = xcalloc (smd.num_sections, sizeof (*smd.vaddrs)); - SUFFIX (locate_sections) (e, kernel_path, &smd, layout, image_target); - if (!is_relocatable (image_target)) - { - Elf_Addr current_address = layout->kernel_size; - Elf_Addr bss_start = layout->kernel_size; - bool is_first = true; - - for (i = 0, s = smd.sections; - i < smd.num_sections; - i++, s = (Elf_Shdr *) ((char *) s + smd.section_entsize)) - if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS) - { - Elf_Word sec_align = grub_host_to_target_addr (s->sh_addralign); - const char *name = smd.strtab + grub_host_to_target32 (s->sh_name); - - if (sec_align) - current_address = ALIGN_UP (current_address - + image_target->vaddr_offset, - sec_align) - - image_target->vaddr_offset; - - grub_util_info ("locating the section %s at 0x%" - GRUB_HOST_PRIxLONG_LONG, - name, (unsigned long long) current_address); - if (!is_relocatable (image_target)) - current_address = grub_host_to_target_addr (s->sh_addr) - - image_target->link_addr; - - if (is_first == true) - { - bss_start = current_address; - is_first = false; - } - - smd.vaddrs[i] = current_address - + image_target->vaddr_offset; - current_address += grub_host_to_target_addr (s->sh_size); - } - current_address = ALIGN_UP (current_address + image_target->vaddr_offset, - image_target->section_align) - - image_target->vaddr_offset; - - if (image_target->id == IMAGE_YEELOONG_FLASH - || image_target->id == IMAGE_FULOONG2F_FLASH - || image_target->id == IMAGE_LOONGSON_ELF - || image_target->id == IMAGE_QEMU_MIPS_FLASH - || image_target->id == IMAGE_MIPS_ARC) - { - layout->kernel_size = bss_start; - } - - layout->bss_size = current_address - layout->kernel_size; - } - else - layout->bss_size = 0; - if (image_target->id == IMAGE_SPARC64_AOUT || image_target->id == IMAGE_SPARC64_RAW || image_target->id == IMAGE_UBOOT @@ -2542,7 +2524,7 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path, for (i = 0, s = smd.sections; i < smd.num_sections; i++, s = (Elf_Shdr *) ((char *) s + smd.section_entsize)) - if (s->sh_type == grub_host_to_target32 (SHT_SYMTAB)) + if (s->sh_type == grub_host_to_target32 (SHT_DYNSYM)) { smd.symtab = s; break; @@ -2558,8 +2540,8 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path, grub_ia64_dl_get_tramp_got_size (e, &tramp, &layout->got_size); - layout->tramp_off = layout->kernel_size; - layout->kernel_size += ALIGN_UP (tramp, 16); + if (tramp != 0) + grub_util_error("inserting trampolines is no longer supported"); layout->ia64jmp_off = layout->kernel_size; layout->ia64jmpnum = SUFFIX (count_funcs) (e, smd.symtab, @@ -2600,16 +2582,32 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path, layout->start_address = SUFFIX (relocate_symbols) (e, &smd, (char *) out_img + layout->ia64jmp_off, layout->ia64jmp_off + image_target->vaddr_offset, - layout->bss_start, layout->end, image_target); + layout, image_target); if (layout->start_address == (Elf_Addr) -1) grub_util_error ("start symbol is not defined"); + make_reloc_section (e, layout, &smd, image_target); + } + + for (i = 0, p = smd.phdrs; + i < smd.num_phdrs; + i++, p = (Elf_Phdr *) ((char *) p + smd.phdr_entsize)) + { + if (grub_target_to_host32 (p->p_type) != PT_LOAD) + continue; + memcpy (out_img + grub_target_to_host (p->p_vaddr) + layout->off_diff, + kernel_img + grub_target_to_host (p->p_offset), grub_target_to_host (p->p_filesz)); + if (image_target->id == IMAGE_EFI) + memset (out_img + grub_target_to_host (p->p_vaddr) + layout->off_diff + grub_target_to_host (p->p_filesz), + 0, grub_target_to_host (p->p_memsz) - grub_target_to_host (p->p_filesz)); + } + + if (is_relocatable (image_target)) + { /* Resolve addrs in the virtual address space. */ - SUFFIX (relocate_addrs) (e, &smd, out_img, layout->tramp_off, - layout->got_off, image_target); + SUFFIX (relocate_addrs) (e, &smd, out_img, layout, image_target); - make_reloc_section (e, layout, &smd, image_target); if (image_target->id != IMAGE_EFI) { out_img = xrealloc (out_img, layout->kernel_size + total_module_size @@ -2621,25 +2619,7 @@ SUFFIX (grub_mkimage_load_image) (const char *kernel_path, } } - for (i = 0, s = smd.sections; - i < smd.num_sections; - i++, s = (Elf_Shdr *) ((char *) s + smd.section_entsize)) - if (SUFFIX (is_kept_section) (s, image_target)) - { - if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS) - memset (out_img + smd.addrs[i], 0, - grub_host_to_target_addr (s->sh_size)); - else - memcpy (out_img + smd.addrs[i], - kernel_img + grub_host_to_target_addr (s->sh_offset), - grub_host_to_target_addr (s->sh_size)); - } free (kernel_img); - free (smd.vaddrs); - smd.vaddrs = NULL; - free (smd.addrs); - smd.addrs = NULL; - return out_img; } -- 2.49.0 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel