20#include "pedigree/kernel/Log.h"
21#include "pedigree/kernel/linker/Elf.h"
22#include "pedigree/kernel/linker/KernelElf.h"
24static constexpr bool VerboseElf =
false;
25#define VERBOSE_NOTICE(x) \
27 EMIT_IF(VerboseElf) { \
34#define R_X86_64_NONE 0
36#define R_X86_64_PC32 2
37#define R_X86_64_GOT32 3
38#define R_X86_64_PLT32 4
39#define R_X86_64_COPY 5
40#define R_X86_64_GLOB_DAT 6
41#define R_X86_64_JUMP_SLOT 7
42#define R_X86_64_RELATIVE 8
43#define R_X86_64_GOTPCREL 9
45#define R_X86_64_32S 11
46#define R_X86_64_PC64 24
47#define R_X86_64_GOTOFF64 25
48#define R_X86_64_GOTPC32 26
49#define R_X86_64_GOT64 27
50#define R_X86_64_GOTPCREL64 28
51#define R_X86_64_GOTPC64 29
52#define R_X86_64_GOTPLT64 30
53#define R_X86_64_PLTOFF64 31
57 uintptr_t destinationAddress, uintptr_t destinationEnd) {
58 ERROR(
"The X64 architecture does not use REL entries!");
64 uintptr_t destinationAddress, uintptr_t destinationEnd) {
66 if (pSh && pSh->addr == 0) {
71 if (R_TYPE(rel.info) == R_X86_64_NONE) {
76 loadBase = pSh ? pSh->addr - pSh->offset : 0;
78 ERROR(
"Cannot apply relocation, no load base given.");
85 uint64_t address = loadBase + rel.offset;
88 Elf_Sxword A = rel.addend;
96 if (!m_pDynamicSymbolTable) {
97 pSymbols = m_pSymbolTable;
99 pSymbols = m_pDynamicSymbolTable;
102 const char* pStringTable = 0;
103 if (!m_pDynamicStringTable) {
104 pStringTable =
reinterpret_cast<const char*
>(m_pStringTable);
106 pStringTable = m_pDynamicStringTable;
109 String symbolName(
"(unknown)");
111 size_t symbolSize = 0;
114 if (pSymbols && ST_TYPE(pSymbols[R_SYM(rel.info)].info) == 3) {
117 int shndx = pSymbols[R_SYM(rel.info)].shndx;
119 S = pReferencedSh->addr;
120 symbolSize = pSymbols[R_SYM(rel.info)].size;
121 }
else if (pSymbols && R_TYPE(rel.info) != R_X86_64_RELATIVE)
125 const char* pStr = pStringTable + pSymbols[R_SYM(rel.info)].name;
128 pSymtab = &m_SymbolTable;
130 if (R_TYPE(rel.info) == R_X86_64_COPY)
135 VERBOSE_NOTICE(
"Falling back to kernel symbol table for '" << pStr <<
"'");
139 if (S == 0 && ST_BIND(pSymbols[R_SYM(rel.info)].info) == 2) {
145 WARNING(
"Relocation failed for symbol \"" << pStr <<
"\" (relocation=" << R_TYPE(rel.info)
147 WARNING(
"Relocation at " <<
Hex << address <<
" (offset=" << rel.offset <<
")...");
150 symbolName.assign(pStr);
151 symbolSize = pSymbols[R_SYM(rel.info)].size;
154 if (S == 0 && (R_TYPE(rel.info) != R_X86_64_RELATIVE))
160 uint64_t B = loadBase;
162 uint8_t r_type = R_TYPE(rel.info);
163 const bool writes32 = r_type == R_X86_64_PC32 || r_type == R_X86_64_32 || r_type == R_X86_64_32S;
164 const size_t resultSize = writes32 ?
sizeof(uint32_t) : sizeof(uint64_t);
165 const uintptr_t resultAddress = destinationAddress ? destinationAddress : address;
166 if (destinationEnd &&
167 (resultAddress > destinationEnd || destinationEnd - resultAddress < resultSize)) {
168 ERROR(
"Relocation crosses the demand-page staging boundary");
172 uint64_t result = writes32 ? *
reinterpret_cast<uint32_t*
>(resultAddress)
173 : *reinterpret_cast<uint64_t*>(resultAddress);
177 VERBOSE_NOTICE(
"Relocation for " << symbolName);
178 VERBOSE_NOTICE(
"A=" <<
Hex << A <<
" B=" << B <<
" S=" << S <<
" P=" << P);
182 VERBOSE_NOTICE(
"R_X86_64_NONE");
185 VERBOSE_NOTICE(
"R_X86_64_64");
189 VERBOSE_NOTICE(
"R_X86_64_PC32");
190 result = (S + A - P) & 0xFFFFFFFF;
193 VERBOSE_NOTICE(
"R_X86_64_COPY");
196 "Cannot perform a R_X86_64_COPY relocation for a weak "
201 NOTICE(
"Copy needed, " << symbolSize <<
" bytes wanted");
202 result = *
reinterpret_cast<uintptr_t*
>(S);
204 case R_X86_64_JUMP_SLOT:
205 case R_X86_64_GLOB_DAT:
206 VERBOSE_NOTICE(
"R_X86_64_JUMP_SLOT/R_X86_64_GLOB_DAT");
210 case R_X86_64_RELATIVE:
211 VERBOSE_NOTICE(
"R_X86_64_RELATIVE");
216 VERBOSE_NOTICE(
"R_X86_64_32(S)");
219 if ((r_type == R_X86_64_32) && ((tmp & 0xFFFFFFFF00000000ULL) != 0)) {
220 ERROR(
"Relocation for symbol '" << symbolName <<
"' will be truncated to fit!");
221 }
else if (r_type == R_X86_64_32S) {
223 uint64_t sign = (tmp & 0x80000000ULL) >> 31ULL;
224 uint64_t top = (tmp & 0xFFFFFFFF00000000ULL) >> 32ULL;
225 if ((sign * 0xFFFFFFFFUL) != top) {
226 ERROR(
"Relocation for symbol '" << symbolName
227 <<
"' will be truncated to fit (sign-extension was "
232 result = tmp & 0xFFFFFFFFUL;
235 ERROR(
"Relocation not supported for symbol \"" << symbolName <<
"\": " <<
Dec
236 << R_TYPE(rel.info));
239 VERBOSE_NOTICE(
"result=" <<
Hex << result);
244 *
reinterpret_cast<uint32_t*
>(resultAddress) =
static_cast<uint32_t
>(result);
246 *
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)