20#include "pedigree/kernel/Log.h"
21#include "pedigree/kernel/linker/Elf.h"
22#include "pedigree/kernel/linker/KernelElf.h"
23#include "pedigree/kernel/utilities/utility.h"
25namespace __pedigree_hosted {
29#define R_X86_64_NONE 0
31#define R_X86_64_PC32 2
32#define R_X86_64_GOT32 3
33#define R_X86_64_PLT32 4
34#define R_X86_64_COPY 5
35#define R_X86_64_GLOB_DAT 6
36#define R_X86_64_JUMP_SLOT 7
37#define R_X86_64_RELATIVE 8
38#define R_X86_64_GOTPCREL 9
40#define R_X86_64_32S 11
41#define R_X86_64_PC64 24
42#define R_X86_64_GOTOFF64 25
43#define R_X86_64_GOTPC32 26
44#define R_X86_64_GOT64 27
45#define R_X86_64_GOTPCREL64 28
46#define R_X86_64_GOTPC64 29
47#define R_X86_64_GOTPLT64 30
48#define R_X86_64_PLTOFF64 31
50#define TWO_GIGABYTES 0x80000000ULL
52static bool checkPc32Displacement(uint64_t S, uint64_t A, uint64_t P, uint64_t& diff) {
53 if (abs_difference(S + A, P) >= 0x80000000ULL) {
57 diff = (((S + A) - P) & 0xFFFFFFFFULL);
63 uintptr_t destinationAddress, uintptr_t destinationEnd) {
69 uintptr_t destinationAddress, uintptr_t destinationEnd) {
71 if (pSh && pSh->addr == 0)
75 if (R_TYPE(rel.info) == R_X86_64_NONE)
79 loadBase = pSh ? pSh->addr - pSh->offset : 0;
81 ERROR(
"Cannot apply relocation, no load base given.");
87 uint64_t address = loadBase + rel.offset;
90 Elf_Sxword A = rel.addend;
98 if (!m_pDynamicSymbolTable)
99 pSymbols = m_pSymbolTable;
101 pSymbols = m_pDynamicSymbolTable;
103 const char* pStringTable = 0;
104 if (!m_pDynamicStringTable)
105 pStringTable =
reinterpret_cast<const char*
>(m_pStringTable);
107 pStringTable = m_pDynamicStringTable;
109 String symbolName(
"(unknown)");
112 size_t symbolSize = 0;
113 if (pSymbols && ST_TYPE(pSymbols[R_SYM(rel.info)].info) == 3) {
116 int shndx = pSymbols[R_SYM(rel.info)].shndx;
119 symbolSize = pSymbols[R_SYM(rel.info)].size;
120 }
else if (R_TYPE(rel.info) != R_X86_64_RELATIVE)
123 if (!pStringTable || !pSymbols)
125 const char* pStr = pStringTable + pSymbols[R_SYM(rel.info)].name;
127 if (R_TYPE(rel.info) == R_X86_64_COPY)
133 if (S == 0 && pSymtab && pSymtab != &m_SymbolTable) {
140 void* pSym = __pedigree_hosted::dlsym(RTLD_DEFAULT, pStr);
142 S =
reinterpret_cast<uint64_t
>(pSym);
151 if (S == 0 && ST_BIND(pSymbols[R_SYM(rel.info)].info) == 2) {
157 WARNING(
"Relocation failed for symbol \"" << pStr <<
"\" (relocation=" << R_TYPE(rel.info)
159 WARNING(
"Relocation at " << address <<
" (offset=" << rel.offset <<
")...");
162 symbolName.assign(pStr);
163 symbolSize = pSymbols[R_SYM(rel.info)].size;
166 if (S == 0 && (R_TYPE(rel.info) != R_X86_64_RELATIVE))
172 uint64_t B = loadBase;
174 uint8_t r_type = R_TYPE(rel.info);
175 const bool writes32 = r_type == R_X86_64_PC32 || r_type == R_X86_64_32 || r_type == R_X86_64_32S;
176 const size_t resultSize = writes32 ?
sizeof(uint32_t) : sizeof(uint64_t);
177 const uintptr_t resultAddress = destinationAddress ? destinationAddress : address;
178 if (destinationEnd &&
179 (resultAddress > destinationEnd || destinationEnd - resultAddress < resultSize)) {
180 ERROR(
"Relocation crosses the demand-page staging boundary");
184 uint64_t result = writes32 ? *
reinterpret_cast<uint32_t*
>(resultAddress)
185 : *reinterpret_cast<uint64_t*>(resultAddress);
195 result = (S + A - P) & 0xFFFFFFFF;
198 result = (S + A) - P;
201 NOTICE(
"Copy needed, " << symbolSize <<
" bytes wanted");
204 result = *
reinterpret_cast<uintptr_t*
>(S);
206 case R_X86_64_JUMP_SLOT:
207 case R_X86_64_GLOB_DAT:
210 case R_X86_64_RELATIVE:
217 if ((r_type == R_X86_64_32) && ((tmp & 0xFFFFFFFF00000000ULL) != 0)) {
218 ERROR(
"Relocation for symbol '" << symbolName <<
"' will be truncated to fit!");
219 }
else if (r_type == R_X86_64_32S) {
221 uint64_t sign = (tmp & 0x80000000ULL) >> 31ULL;
222 uint64_t top = (tmp & 0xFFFFFFFF00000000ULL) >> 32ULL;
223 if ((sign * 0xFFFFFFFFUL) != top) {
224 ERROR(
"Relocation for symbol '" << symbolName
225 <<
"' will be truncated to fit (sign-extension was "
230 result = tmp & 0xFFFFFFFFUL;
234 ERROR(
"Relocation not supported for symbol \"" << symbolName <<
"\": " <<
Dec
235 << R_TYPE(rel.info));
240 *
reinterpret_cast<uint32_t*
>(resultAddress) =
static_cast<uint32_t
>(result);
242 *
reinterpret_cast<uint64_t*
>(resultAddress) = result;
bool applyRelocation(ElfRel_t rel, ElfSectionHeader_t *pSh, SymbolTable *pSymtab=0, uintptr_t loadBase=0, SymbolTable::Policy policy=SymbolTable::LocalFirst, uintptr_t destinationAddress=0, uintptr_t destinationEnd=0)
static KernelElf & instance()
uintptr_t EXPORTED_PUBLIC lookup(const HashedStringView &name, Elf *pElf, Policy policy=LocalFirst, Binding *pBinding=0)