mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-11-17 07:04:10 +00:00
Move dynamic sections and relocation sections data structures to elf.h and enclose function relocate with CONFIG_RELOC. The input parameter struct Elf64_Dyn *dynamic is not used by x86-64 now because x86-64 can use pc-relative addressing to get the acutaly load address of _DYNAMIC in the C code. Tracked-On: #8825 Signed-off-by: Jian Jun Chen <jian.jun.chen@intel.com> Acked-by: Wang, Yu1 <yu1.wang@intel.com>
93 lines
2.4 KiB
C
93 lines
2.4 KiB
C
/*
|
|
* Copyright (C) 2018-2022 Intel Corporation.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <types.h>
|
|
#include <reloc.h>
|
|
#include <asm/boot/ld_sym.h>
|
|
|
|
/* get the delta between CONFIG_HV_RAM_START and the actual load address */
|
|
uint64_t arch_get_hv_image_delta(void)
|
|
{
|
|
uint64_t addr;
|
|
|
|
asm volatile (" call 0f\n"
|
|
"0: pop %%rax\n"
|
|
" sub $0b, %%rax\n"
|
|
" mov %%rax, %0\n"
|
|
: "=m" (addr)
|
|
:
|
|
: "%rax");
|
|
|
|
return addr;
|
|
}
|
|
|
|
#ifdef CONFIG_RELOC
|
|
void relocate(__unused struct Elf64_Dyn *dynamic)
|
|
{
|
|
struct Elf64_Dyn *dyn;
|
|
struct Elf64_Rel *entry = NULL;
|
|
uint8_t *rela_start = NULL, *rela_end = NULL;
|
|
uint64_t rela_size = 0;
|
|
uint64_t delta, entry_size = 0;
|
|
uint64_t trampoline_end;
|
|
uint64_t primary_entry_end;
|
|
uint64_t *addr;
|
|
|
|
/* get the delta that needs to be patched */
|
|
delta = get_hv_image_delta();
|
|
if (delta != 0U) {
|
|
|
|
/* Look for the descriptoin of relocation sections */
|
|
for (dyn = (struct Elf64_Dyn *)_DYNAMIC; dyn->d_tag != DT_NULL; dyn++) {
|
|
switch (dyn->d_tag) {
|
|
case DT_RELA:
|
|
rela_start = (uint8_t *)(dyn->d_ptr + delta);
|
|
break;
|
|
case DT_RELASZ:
|
|
rela_size = dyn->d_ptr;
|
|
break;
|
|
case DT_RELAENT:
|
|
entry_size = dyn->d_ptr;
|
|
break;
|
|
default:
|
|
/* if no RELA/RELASZ found, both start and end will be initialized to NULL, and later while loop won't be executed */
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Need to subtract the relocation delta to get the correct
|
|
* absolute addresses
|
|
*/
|
|
trampoline_end = (uint64_t)(&ld_trampoline_end) - delta;
|
|
primary_entry_end = (uint64_t)(&ld_entry_end) - delta;
|
|
|
|
rela_end = rela_start + rela_size;
|
|
while (rela_start < rela_end) {
|
|
entry = (struct Elf64_Rel *)rela_start;
|
|
if ((elf64_r_type(entry->r_info)) == R_X86_64_RELATIVE) {
|
|
addr = (uint64_t *)(delta + entry->r_offset);
|
|
|
|
/*
|
|
* we won't fixup any symbols from trampoline.S or cpu_primary.S
|
|
* for a number of reasons:
|
|
*
|
|
* - trampoline code itself takes another relocation,
|
|
* so any entries for trampoline symbols can't be fixed up
|
|
* through .rela sections
|
|
* - Linker option "-z noreloc-overflow" could force R_X86_32
|
|
* to R_X86_64 in the relocation sections, which could make
|
|
* the fixed up code dirty.
|
|
*/
|
|
if ((entry->r_offset > trampoline_end) && (entry->r_offset > primary_entry_end)) {
|
|
*addr += delta;
|
|
}
|
|
}
|
|
rela_start += entry_size;
|
|
}
|
|
}
|
|
}
|
|
#endif /* CONFIG_RELOC */ |