Line data Source code
1 : //===---- RuntimeDyldMachOI386.h ---- MachO/I386 specific code. ---*- C++ -*-=//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOI386_H
11 : #define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOI386_H
12 :
13 : #include "../RuntimeDyldMachO.h"
14 : #include <string>
15 :
16 : #define DEBUG_TYPE "dyld"
17 :
18 : namespace llvm {
19 :
20 : class RuntimeDyldMachOI386
21 : : public RuntimeDyldMachOCRTPBase<RuntimeDyldMachOI386> {
22 : public:
23 :
24 : typedef uint32_t TargetPtrT;
25 :
26 : RuntimeDyldMachOI386(RuntimeDyld::MemoryManager &MM,
27 : JITSymbolResolver &Resolver)
28 2 : : RuntimeDyldMachOCRTPBase(MM, Resolver) {}
29 :
30 7 : unsigned getMaxStubSize() override { return 0; }
31 :
32 4 : unsigned getStubAlignment() override { return 1; }
33 :
34 : Expected<relocation_iterator>
35 5 : processRelocationRef(unsigned SectionID, relocation_iterator RelI,
36 : const ObjectFile &BaseObjT,
37 : ObjSectionToIDMap &ObjSectionToID,
38 : StubMap &Stubs) override {
39 : const MachOObjectFile &Obj =
40 : static_cast<const MachOObjectFile &>(BaseObjT);
41 : MachO::any_relocation_info RelInfo =
42 5 : Obj.getRelocation(RelI->getRawDataRefImpl());
43 5 : uint32_t RelType = Obj.getAnyRelocationType(RelInfo);
44 :
45 5 : if (Obj.isRelocationScattered(RelInfo)) {
46 4 : if (RelType == MachO::GENERIC_RELOC_SECTDIFF ||
47 2 : RelType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)
48 : return processSECTDIFFRelocation(SectionID, RelI, Obj,
49 1 : ObjSectionToID);
50 1 : else if (RelType == MachO::GENERIC_RELOC_VANILLA)
51 1 : return processScatteredVANILLA(SectionID, RelI, Obj, ObjSectionToID);
52 : return make_error<RuntimeDyldError>(("Unhandled I386 scattered relocation "
53 0 : "type: " + Twine(RelType)).str());
54 : }
55 :
56 3 : switch (RelType) {
57 : UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_PAIR);
58 : UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_PB_LA_PTR);
59 : UNIMPLEMENTED_RELOC(MachO::GENERIC_RELOC_TLV);
60 3 : default:
61 3 : if (RelType > MachO::GENERIC_RELOC_TLV)
62 0 : return make_error<RuntimeDyldError>(("MachO I386 relocation type " +
63 0 : Twine(RelType) +
64 0 : " is out of range").str());
65 : break;
66 : }
67 :
68 3 : RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI));
69 3 : RE.Addend = memcpyAddend(RE);
70 : RelocationValueRef Value;
71 3 : if (auto ValueOrErr = getRelocationValueRef(Obj, RelI, RE, ObjSectionToID))
72 3 : Value = *ValueOrErr;
73 : else
74 : return ValueOrErr.takeError();
75 :
76 : // Addends for external, PC-rel relocations on i386 point back to the zero
77 : // offset. Calculate the final offset from the relocation target instead.
78 : // This allows us to use the same logic for both external and internal
79 : // relocations in resolveI386RelocationRef.
80 : // bool IsExtern = Obj.getPlainRelocationExternal(RelInfo);
81 : // if (IsExtern && RE.IsPCRel) {
82 : // uint64_t RelocAddr = 0;
83 : // RelI->getAddress(RelocAddr);
84 : // Value.Addend += RelocAddr + 4;
85 : // }
86 3 : if (RE.IsPCRel)
87 3 : makeValueAddendPCRel(Value, RelI, 1 << RE.Size);
88 :
89 3 : RE.Addend = Value.Offset;
90 :
91 3 : if (Value.SymbolName)
92 0 : addRelocationForSymbol(RE, Value.SymbolName);
93 : else
94 3 : addRelocationForSection(RE, Value.SectionID);
95 :
96 : return ++RelI;
97 : }
98 :
99 7 : void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override {
100 : LLVM_DEBUG(dumpRelocationToResolve(RE, Value));
101 :
102 7 : const SectionEntry &Section = Sections[RE.SectionID];
103 7 : uint8_t *LocalAddress = Section.getAddressWithOffset(RE.Offset);
104 :
105 7 : if (RE.IsPCRel) {
106 4 : uint64_t FinalAddress = Section.getLoadAddressWithOffset(RE.Offset);
107 4 : Value -= FinalAddress + 4; // see MachOX86_64::resolveRelocation.
108 : }
109 :
110 7 : switch (RE.RelType) {
111 6 : case MachO::GENERIC_RELOC_VANILLA:
112 6 : writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size);
113 6 : break;
114 1 : case MachO::GENERIC_RELOC_SECTDIFF:
115 : case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {
116 1 : uint64_t SectionABase = Sections[RE.Sections.SectionA].getLoadAddress();
117 1 : uint64_t SectionBBase = Sections[RE.Sections.SectionB].getLoadAddress();
118 : assert((Value == SectionABase || Value == SectionBBase) &&
119 : "Unexpected SECTDIFF relocation value.");
120 1 : Value = SectionABase - SectionBBase + RE.Addend;
121 1 : writeBytesUnaligned(Value, LocalAddress, 1 << RE.Size);
122 1 : break;
123 : }
124 0 : default:
125 0 : llvm_unreachable("Invalid relocation type!");
126 : }
127 7 : }
128 :
129 4 : Error finalizeSection(const ObjectFile &Obj, unsigned SectionID,
130 : const SectionRef &Section) {
131 4 : StringRef Name;
132 4 : Section.getName(Name);
133 :
134 : if (Name == "__jump_table")
135 1 : return populateJumpTable(cast<MachOObjectFile>(Obj), Section, SectionID);
136 : else if (Name == "__pointers")
137 : return populateIndirectSymbolPointersSection(cast<MachOObjectFile>(Obj),
138 1 : Section, SectionID);
139 : return Error::success();
140 : }
141 :
142 : private:
143 : Expected<relocation_iterator>
144 1 : processSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI,
145 : const ObjectFile &BaseObjT,
146 : ObjSectionToIDMap &ObjSectionToID) {
147 : const MachOObjectFile &Obj =
148 : static_cast<const MachOObjectFile&>(BaseObjT);
149 : MachO::any_relocation_info RE =
150 1 : Obj.getRelocation(RelI->getRawDataRefImpl());
151 :
152 1 : SectionEntry &Section = Sections[SectionID];
153 1 : uint32_t RelocType = Obj.getAnyRelocationType(RE);
154 1 : bool IsPCRel = Obj.getAnyRelocationPCRel(RE);
155 1 : unsigned Size = Obj.getAnyRelocationLength(RE);
156 1 : uint64_t Offset = RelI->getOffset();
157 1 : uint8_t *LocalAddress = Section.getAddressWithOffset(Offset);
158 1 : unsigned NumBytes = 1 << Size;
159 1 : uint64_t Addend = readBytesUnaligned(LocalAddress, NumBytes);
160 :
161 : ++RelI;
162 : MachO::any_relocation_info RE2 =
163 1 : Obj.getRelocation(RelI->getRawDataRefImpl());
164 :
165 1 : uint32_t AddrA = Obj.getScatteredRelocationValue(RE);
166 1 : section_iterator SAI = getSectionByAddress(Obj, AddrA);
167 : assert(SAI != Obj.section_end() && "Can't find section for address A");
168 1 : uint64_t SectionABase = SAI->getAddress();
169 1 : uint64_t SectionAOffset = AddrA - SectionABase;
170 1 : SectionRef SectionA = *SAI;
171 1 : bool IsCode = SectionA.isText();
172 : uint32_t SectionAID = ~0U;
173 1 : if (auto SectionAIDOrErr =
174 1 : findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID))
175 1 : SectionAID = *SectionAIDOrErr;
176 : else
177 : return SectionAIDOrErr.takeError();
178 :
179 1 : uint32_t AddrB = Obj.getScatteredRelocationValue(RE2);
180 1 : section_iterator SBI = getSectionByAddress(Obj, AddrB);
181 : assert(SBI != Obj.section_end() && "Can't find section for address B");
182 1 : uint64_t SectionBBase = SBI->getAddress();
183 : uint64_t SectionBOffset = AddrB - SectionBBase;
184 1 : SectionRef SectionB = *SBI;
185 : uint32_t SectionBID = ~0U;
186 1 : if (auto SectionBIDOrErr =
187 1 : findOrEmitSection(Obj, SectionB, IsCode, ObjSectionToID))
188 1 : SectionBID = *SectionBIDOrErr;
189 : else
190 : return SectionBIDOrErr.takeError();
191 :
192 : // Compute the addend 'C' from the original expression 'A - B + C'.
193 1 : Addend -= AddrA - AddrB;
194 :
195 : LLVM_DEBUG(dbgs() << "Found SECTDIFF: AddrA: " << AddrA
196 : << ", AddrB: " << AddrB << ", Addend: " << Addend
197 : << ", SectionA ID: " << SectionAID << ", SectionAOffset: "
198 : << SectionAOffset << ", SectionB ID: " << SectionBID
199 : << ", SectionBOffset: " << SectionBOffset << "\n");
200 : RelocationEntry R(SectionID, Offset, RelocType, Addend, SectionAID,
201 : SectionAOffset, SectionBID, SectionBOffset,
202 : IsPCRel, Size);
203 :
204 1 : addRelocationForSection(R, SectionAID);
205 :
206 : return ++RelI;
207 : }
208 :
209 : // Populate stubs in __jump_table section.
210 1 : Error populateJumpTable(const MachOObjectFile &Obj,
211 : const SectionRef &JTSection,
212 : unsigned JTSectionID) {
213 1 : MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand();
214 1 : MachO::section Sec32 = Obj.getSection(JTSection.getRawDataRefImpl());
215 1 : uint32_t JTSectionSize = Sec32.size;
216 1 : unsigned FirstIndirectSymbol = Sec32.reserved1;
217 1 : unsigned JTEntrySize = Sec32.reserved2;
218 1 : unsigned NumJTEntries = JTSectionSize / JTEntrySize;
219 : uint8_t *JTSectionAddr = getSectionAddress(JTSectionID);
220 : unsigned JTEntryOffset = 0;
221 :
222 1 : if (JTSectionSize % JTEntrySize != 0)
223 : return make_error<RuntimeDyldError>("Jump-table section does not contain "
224 : "a whole number of stubs?");
225 :
226 2 : for (unsigned i = 0; i < NumJTEntries; ++i) {
227 : unsigned SymbolIndex =
228 1 : Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i);
229 1 : symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex);
230 : Expected<StringRef> IndirectSymbolName = SI->getName();
231 1 : if (!IndirectSymbolName)
232 : return IndirectSymbolName.takeError();
233 1 : uint8_t *JTEntryAddr = JTSectionAddr + JTEntryOffset;
234 1 : createStubFunction(JTEntryAddr);
235 1 : RelocationEntry RE(JTSectionID, JTEntryOffset + 1,
236 1 : MachO::GENERIC_RELOC_VANILLA, 0, true, 2);
237 1 : addRelocationForSymbol(RE, *IndirectSymbolName);
238 1 : JTEntryOffset += JTEntrySize;
239 : }
240 :
241 : return Error::success();
242 : }
243 :
244 : };
245 : }
246 :
247 : #undef DEBUG_TYPE
248 :
249 : #endif
|