1 //===-- RuntimeDyldELF.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Implementation of ELF support for the MC-JIT runtime dynamic linker.
12 //===----------------------------------------------------------------------===//
14 #define DEBUG_TYPE "dyld"
15 #include "llvm/ADT/OwningPtr.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/IntervalMap.h"
19 #include "RuntimeDyldELF.h"
20 #include "llvm/Object/ObjectFile.h"
21 #include "llvm/Support/ELF.h"
22 #include "llvm/ADT/Triple.h"
24 using namespace llvm::object;
29 void RuntimeDyldELF::resolveX86_64Relocation(uint8_t *LocalAddress,
30 uint64_t FinalAddress,
36 llvm_unreachable("Relocation type not implemented yet!");
38 case ELF::R_X86_64_64: {
39 uint64_t *Target = (uint64_t*)(LocalAddress);
40 *Target = Value + Addend;
43 case ELF::R_X86_64_32:
44 case ELF::R_X86_64_32S: {
46 // FIXME: Handle the possibility of this assertion failing
47 assert((Type == ELF::R_X86_64_32 && !(Value & 0xFFFFFFFF00000000ULL)) ||
48 (Type == ELF::R_X86_64_32S &&
49 (Value & 0xFFFFFFFF00000000ULL) == 0xFFFFFFFF00000000ULL));
50 uint32_t TruncatedAddr = (Value & 0xFFFFFFFF);
51 uint32_t *Target = reinterpret_cast<uint32_t*>(LocalAddress);
52 *Target = TruncatedAddr;
55 case ELF::R_X86_64_PC32: {
56 uint32_t *Placeholder = reinterpret_cast<uint32_t*>(LocalAddress);
57 int64_t RealOffset = *Placeholder + Value + Addend - FinalAddress;
58 assert(RealOffset <= 214783647 && RealOffset >= -214783648);
59 int32_t TruncOffset = (RealOffset & 0xFFFFFFFF);
60 *Placeholder = TruncOffset;
66 void RuntimeDyldELF::resolveX86Relocation(uint8_t *LocalAddress,
67 uint32_t FinalAddress,
73 uint32_t *Target = (uint32_t*)(LocalAddress);
74 *Target = Value + Addend;
77 case ELF::R_386_PC32: {
78 uint32_t *Placeholder = reinterpret_cast<uint32_t*>(LocalAddress);
79 uint32_t RealOffset = *Placeholder + Value + Addend - FinalAddress;
80 *Placeholder = RealOffset;
84 // There are other relocation types, but it appears these are the
85 // only ones currently used by the LLVM ELF object writer
86 llvm_unreachable("Relocation type not implemented yet!");
91 void RuntimeDyldELF::resolveARMRelocation(uint8_t *LocalAddress,
92 uint32_t FinalAddress,
96 // TODO: Add Thumb relocations.
97 uint32_t* TargetPtr = (uint32_t*)LocalAddress;
100 DEBUG(dbgs() << "resolveARMRelocation, LocalAddress: " << LocalAddress
101 << " FinalAddress: " << format("%p",FinalAddress)
102 << " Value: " << format("%x",Value)
103 << " Type: " << format("%x",Type)
104 << " Addend: " << format("%x",Addend)
109 llvm_unreachable("Not implemented relocation type!");
111 // Just write 32bit value to relocation address
112 case ELF::R_ARM_ABS32 :
116 // Write first 16 bit of 32 bit value to the mov instruction.
117 // Last 4 bit should be shifted.
118 case ELF::R_ARM_MOVW_ABS_NC :
119 Value = Value & 0xFFFF;
120 *TargetPtr |= Value & 0xFFF;
121 *TargetPtr |= ((Value >> 12) & 0xF) << 16;
124 // Write last 16 bit of 32 bit value to the mov instruction.
125 // Last 4 bit should be shifted.
126 case ELF::R_ARM_MOVT_ABS :
127 Value = (Value >> 16) & 0xFFFF;
128 *TargetPtr |= Value & 0xFFF;
129 *TargetPtr |= ((Value >> 12) & 0xF) << 16;
132 // Write 24 bit relative value to the branch instruction.
133 case ELF::R_ARM_PC24 : // Fall through.
134 case ELF::R_ARM_CALL : // Fall through.
135 case ELF::R_ARM_JUMP24 :
136 int32_t RelValue = static_cast<int32_t>(Value - FinalAddress - 8);
137 RelValue = (RelValue & 0x03FFFFFC) >> 2;
138 *TargetPtr &= 0xFF000000;
139 *TargetPtr |= RelValue;
144 void RuntimeDyldELF::resolveRelocation(uint8_t *LocalAddress,
145 uint64_t FinalAddress,
151 resolveX86_64Relocation(LocalAddress, FinalAddress, Value, Type, Addend);
154 resolveX86Relocation(LocalAddress, (uint32_t)(FinalAddress & 0xffffffffL),
155 (uint32_t)(Value & 0xffffffffL), Type,
156 (uint32_t)(Addend & 0xffffffffL));
158 case Triple::arm: // Fall through.
160 resolveARMRelocation(LocalAddress, (uint32_t)(FinalAddress & 0xffffffffL),
161 (uint32_t)(Value & 0xffffffffL), Type,
162 (uint32_t)(Addend & 0xffffffffL));
164 default: llvm_unreachable("Unsupported CPU type!");
168 void RuntimeDyldELF::
169 processRelocationRef(const ObjRelocationInfo &Rel, const ObjectFile &Obj,
170 ObjSectionToIDMap &ObjSectionToID,
171 LocalSymbolMap &Symbols, StubMap &Stubs) {
173 uint32_t RelType = (uint32_t)(Rel.Type & 0xffffffffL);
174 intptr_t Addend = (intptr_t)Rel.AdditionalInfo;
175 RelocationValueRef Value;
176 StringRef TargetName;
177 const SymbolRef &Symbol = Rel.Symbol;
178 Symbol.getName(TargetName);
179 DEBUG(dbgs() << "\t\tRelType: " << RelType
180 << " Addend: " << Addend
181 << " TargetName: " << TargetName
183 // First look the symbol in object file symbols.
184 LocalSymbolMap::iterator it = Symbols.find(TargetName.data());
185 if (it != Symbols.end()) {
186 Value.SectionID = it->second.first;
187 Value.Addend = it->second.second;
189 // Second look the symbol in global symbol table.
190 StringMap<SymbolLoc>::iterator itS = SymbolTable.find(TargetName.data());
191 if (itS != SymbolTable.end()) {
192 Value.SectionID = itS->second.first;
193 Value.Addend = itS->second.second;
195 SymbolRef::Type SymType;
196 Symbol.getType(SymType);
198 case SymbolRef::ST_Debug: {
199 // TODO: Now ELF SymbolRef::ST_Debug = STT_SECTION, it's not obviously
200 // and can be changed by another developers. Maybe best way is add
201 // a new symbol type ST_Section to SymbolRef and use it.
202 section_iterator sIt = Obj.end_sections();
203 Symbol.getSection(sIt);
204 if (sIt == Obj.end_sections())
205 llvm_unreachable("Symbol section not found, bad object file format!");
206 DEBUG(dbgs() << "\t\tThis is section symbol\n");
207 Value.SectionID = findOrEmitSection((*sIt), true, ObjSectionToID);
208 Value.Addend = Addend;
211 case SymbolRef::ST_Unknown: {
212 Value.SymbolName = TargetName.data();
213 Value.Addend = Addend;
217 llvm_unreachable("Unresolved symbol type!");
222 DEBUG(dbgs() << "\t\tRel.SectionID: " << Rel.SectionID
223 << " Rel.Offset: " << Rel.Offset
225 if (Arch == Triple::arm &&
226 (RelType == ELF::R_ARM_PC24 ||
227 RelType == ELF::R_ARM_CALL ||
228 RelType == ELF::R_ARM_JUMP24)) {
229 // This is an ARM branch relocation, need to use a stub function.
230 DEBUG(dbgs() << "\t\tThis is an ARM branch relocation.");
231 SectionEntry &Section = Sections[Rel.SectionID];
232 uint8_t *Target = Section.Address + Rel.Offset;
234 // Look up for existing stub.
235 StubMap::const_iterator stubIt = Stubs.find(Value);
236 if (stubIt != Stubs.end()) {
237 resolveRelocation(Target, Section.LoadAddress, (uint64_t)Section.Address +
238 stubIt->second, RelType, 0);
239 DEBUG(dbgs() << " Stub function found\n");
241 // Create a new stub function.
242 DEBUG(dbgs() << " Create a new stub function\n");
243 Stubs[Value] = Section.StubOffset;
244 uint8_t *StubTargetAddr = createStubFunction(Section.Address +
246 AddRelocation(Value, Rel.SectionID,
247 StubTargetAddr - Section.Address, ELF::R_ARM_ABS32);
248 resolveRelocation(Target, Section.LoadAddress, (uint64_t)Section.Address +
249 Section.StubOffset, RelType, 0);
250 Section.StubOffset += getMaxStubSize();
253 AddRelocation(Value, Rel.SectionID, Rel.Offset, RelType);
256 bool RuntimeDyldELF::isCompatibleFormat(const MemoryBuffer *InputBuffer) const {
257 StringRef Magic = InputBuffer->getBuffer().slice(0, ELF::EI_NIDENT);
258 return (memcmp(Magic.data(), ELF::ElfMagic, strlen(ELF::ElfMagic))) == 0;