blob: f80b0e7f8909584b00450142c223cbcab03dd531 [file] [log] [blame]
Lang Hames11c8dfa52019-04-20 17:10:34 +00001//===-------- JITLink_EHFrameSupport.cpp - JITLink eh-frame utils ---------===//
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
Lang Hames1233c152019-04-22 03:03:09 +000010#include "EHFrameSupportImpl.h"
Lang Hames11c8dfa52019-04-20 17:10:34 +000011
12#include "llvm/BinaryFormat/Dwarf.h"
Lang Hames68b0b8c2019-04-20 17:29:57 +000013#include "llvm/Support/DynamicLibrary.h"
Lang Hames11c8dfa52019-04-20 17:10:34 +000014
15#define DEBUG_TYPE "jitlink"
16
17namespace llvm {
18namespace jitlink {
19
Lang Hames4e920e52019-10-04 03:55:26 +000020EHFrameBinaryParser::EHFrameBinaryParser(JITTargetAddress EHFrameAddress,
21 StringRef EHFrameContent,
22 unsigned PointerSize,
23 support::endianness Endianness)
24 : EHFrameAddress(EHFrameAddress), EHFrameContent(EHFrameContent),
25 PointerSize(PointerSize), EHFrameReader(EHFrameContent, Endianness) {}
Lang Hames11c8dfa52019-04-20 17:10:34 +000026
Lang Hames4e920e52019-10-04 03:55:26 +000027Error EHFrameBinaryParser::addToGraph() {
Lang Hames11c8dfa52019-04-20 17:10:34 +000028 while (!EHFrameReader.empty()) {
29 size_t RecordOffset = EHFrameReader.getOffset();
30
31 LLVM_DEBUG({
32 dbgs() << "Processing eh-frame record at "
Lang Hames6fd91292019-10-04 05:24:39 +000033 << format("0x%016" PRIx64, EHFrameAddress + RecordOffset)
34 << " (offset " << RecordOffset << ")\n";
Lang Hames11c8dfa52019-04-20 17:10:34 +000035 });
36
Lang Hames4e920e52019-10-04 03:55:26 +000037 size_t RecordLength = 0;
38 uint32_t RecordLengthField;
39 if (auto Err = EHFrameReader.readInteger(RecordLengthField))
Lang Hames11c8dfa52019-04-20 17:10:34 +000040 return Err;
41
Lang Hames4e920e52019-10-04 03:55:26 +000042 // Process CIE/FDE length/extended-length fields to build the blocks.
Lang Hames11c8dfa52019-04-20 17:10:34 +000043 //
44 // The value of these fields describe the length of the *rest* of the CIE
45 // (not including data up to the end of the field itself) so we have to
Lang Hames4e920e52019-10-04 03:55:26 +000046 // bump RecordLength to include the data up to the end of the field: 4 bytes
Lang Hames11c8dfa52019-04-20 17:10:34 +000047 // for Length, or 12 bytes (4 bytes + 8 bytes) for ExtendedLength.
Lang Hames4e920e52019-10-04 03:55:26 +000048 if (RecordLengthField == 0) // Length 0 means end of __eh_frame section.
Lang Hames11c8dfa52019-04-20 17:10:34 +000049 break;
50
51 // If the regular length field's value is 0xffffffff, use extended length.
Lang Hames4e920e52019-10-04 03:55:26 +000052 if (RecordLengthField == 0xffffffff) {
53 uint64_t ExtendedLengthField;
54 if (auto Err = EHFrameReader.readInteger(ExtendedLengthField))
Lang Hames11c8dfa52019-04-20 17:10:34 +000055 return Err;
Lang Hames4e920e52019-10-04 03:55:26 +000056 if (ExtendedLengthField > EHFrameReader.bytesRemaining())
Lang Hames11c8dfa52019-04-20 17:10:34 +000057 return make_error<JITLinkError>("CIE record extends past the end of "
58 "the __eh_frame section");
Lang Hames4e920e52019-10-04 03:55:26 +000059 if (ExtendedLengthField + 12 > std::numeric_limits<size_t>::max())
Lang Hames11c8dfa52019-04-20 17:10:34 +000060 return make_error<JITLinkError>("CIE record too large to process");
Lang Hames4e920e52019-10-04 03:55:26 +000061 RecordLength = ExtendedLengthField + 12;
Lang Hames11c8dfa52019-04-20 17:10:34 +000062 } else {
Lang Hames4e920e52019-10-04 03:55:26 +000063 if (RecordLengthField > EHFrameReader.bytesRemaining())
Lang Hames11c8dfa52019-04-20 17:10:34 +000064 return make_error<JITLinkError>("CIE record extends past the end of "
65 "the __eh_frame section");
Lang Hames4e920e52019-10-04 03:55:26 +000066 RecordLength = RecordLengthField + 4;
Lang Hames11c8dfa52019-04-20 17:10:34 +000067 }
68
Lang Hames4e920e52019-10-04 03:55:26 +000069 LLVM_DEBUG(dbgs() << " length: " << RecordLength << "\n");
Lang Hames11c8dfa52019-04-20 17:10:34 +000070
71 // Read the CIE Pointer.
72 size_t CIEPointerAddress = EHFrameAddress + EHFrameReader.getOffset();
73 uint32_t CIEPointer;
74 if (auto Err = EHFrameReader.readInteger(CIEPointer))
75 return Err;
76
77 // Based on the CIE pointer value, parse this as a CIE or FDE record.
78 if (CIEPointer == 0) {
Lang Hames4e920e52019-10-04 03:55:26 +000079 if (auto Err = processCIE(RecordOffset, RecordLength))
Lang Hames11c8dfa52019-04-20 17:10:34 +000080 return Err;
81 } else {
Lang Hames4e920e52019-10-04 03:55:26 +000082 if (auto Err = processFDE(RecordOffset, RecordLength, CIEPointerAddress,
83 CIEPointer))
Lang Hames11c8dfa52019-04-20 17:10:34 +000084 return Err;
85 }
86
Lang Hames4e920e52019-10-04 03:55:26 +000087 EHFrameReader.setOffset(RecordOffset + RecordLength);
Lang Hames11c8dfa52019-04-20 17:10:34 +000088 }
89
90 return Error::success();
91}
92
Lang Hames4e920e52019-10-04 03:55:26 +000093void EHFrameBinaryParser::anchor() {}
94
95Expected<EHFrameBinaryParser::AugmentationInfo>
96EHFrameBinaryParser::parseAugmentationString() {
Lang Hames11c8dfa52019-04-20 17:10:34 +000097 AugmentationInfo AugInfo;
98 uint8_t NextChar;
99 uint8_t *NextField = &AugInfo.Fields[0];
100
101 if (auto Err = EHFrameReader.readInteger(NextChar))
102 return std::move(Err);
103
104 while (NextChar != 0) {
105 switch (NextChar) {
106 case 'z':
107 AugInfo.AugmentationDataPresent = true;
108 break;
109 case 'e':
110 if (auto Err = EHFrameReader.readInteger(NextChar))
111 return std::move(Err);
112 if (NextChar != 'h')
113 return make_error<JITLinkError>("Unrecognized substring e" +
114 Twine(NextChar) +
115 " in augmentation string");
116 AugInfo.EHDataFieldPresent = true;
117 break;
118 case 'L':
119 case 'P':
120 case 'R':
121 *NextField++ = NextChar;
122 break;
123 default:
124 return make_error<JITLinkError>("Unrecognized character " +
125 Twine(NextChar) +
126 " in augmentation string");
127 }
128
129 if (auto Err = EHFrameReader.readInteger(NextChar))
130 return std::move(Err);
131 }
132
133 return std::move(AugInfo);
134}
135
Lang Hames4e920e52019-10-04 03:55:26 +0000136Expected<JITTargetAddress> EHFrameBinaryParser::readAbsolutePointer() {
Lang Hames11c8dfa52019-04-20 17:10:34 +0000137 static_assert(sizeof(JITTargetAddress) == sizeof(uint64_t),
138 "Result must be able to hold a uint64_t");
139 JITTargetAddress Addr;
Lang Hames4e920e52019-10-04 03:55:26 +0000140 if (PointerSize == 8) {
Lang Hames11c8dfa52019-04-20 17:10:34 +0000141 if (auto Err = EHFrameReader.readInteger(Addr))
142 return std::move(Err);
Lang Hames4e920e52019-10-04 03:55:26 +0000143 } else if (PointerSize == 4) {
Lang Hames11c8dfa52019-04-20 17:10:34 +0000144 uint32_t Addr32;
145 if (auto Err = EHFrameReader.readInteger(Addr32))
146 return std::move(Err);
147 Addr = Addr32;
148 } else
149 llvm_unreachable("Pointer size is not 32-bit or 64-bit");
150 return Addr;
151}
152
Lang Hames4e920e52019-10-04 03:55:26 +0000153Error EHFrameBinaryParser::processCIE(size_t RecordOffset,
154 size_t RecordLength) {
Lang Hames11c8dfa52019-04-20 17:10:34 +0000155 // Use the dwarf namespace for convenient access to pointer encoding
156 // constants.
157 using namespace dwarf;
158
159 LLVM_DEBUG(dbgs() << " Record is CIE\n");
160
Lang Hames4e920e52019-10-04 03:55:26 +0000161 auto &CIESymbol =
162 createCIERecord(EHFrameAddress + RecordOffset,
163 EHFrameContent.substr(RecordOffset, RecordLength));
164
165 CIEInformation CIEInfo(CIESymbol);
Lang Hames11c8dfa52019-04-20 17:10:34 +0000166
167 uint8_t Version = 0;
168 if (auto Err = EHFrameReader.readInteger(Version))
169 return Err;
170
171 if (Version != 0x01)
172 return make_error<JITLinkError>("Bad CIE version " + Twine(Version) +
173 " (should be 0x01) in eh-frame");
174
175 auto AugInfo = parseAugmentationString();
176 if (!AugInfo)
177 return AugInfo.takeError();
178
179 // Skip the EH Data field if present.
180 if (AugInfo->EHDataFieldPresent)
Lang Hames4e920e52019-10-04 03:55:26 +0000181 if (auto Err = EHFrameReader.skip(PointerSize))
Lang Hames11c8dfa52019-04-20 17:10:34 +0000182 return Err;
183
184 // Read and sanity check the code alignment factor.
185 {
186 uint64_t CodeAlignmentFactor = 0;
187 if (auto Err = EHFrameReader.readULEB128(CodeAlignmentFactor))
188 return Err;
189 if (CodeAlignmentFactor != 1)
190 return make_error<JITLinkError>("Unsupported CIE code alignment factor " +
191 Twine(CodeAlignmentFactor) +
192 " (expected 1)");
193 }
194
195 // Read and sanity check the data alignment factor.
196 {
197 int64_t DataAlignmentFactor = 0;
198 if (auto Err = EHFrameReader.readSLEB128(DataAlignmentFactor))
199 return Err;
200 if (DataAlignmentFactor != -8)
201 return make_error<JITLinkError>("Unsupported CIE data alignment factor " +
202 Twine(DataAlignmentFactor) +
203 " (expected -8)");
204 }
205
206 // Skip the return address register field.
207 if (auto Err = EHFrameReader.skip(1))
208 return Err;
209
210 uint64_t AugmentationDataLength = 0;
211 if (auto Err = EHFrameReader.readULEB128(AugmentationDataLength))
212 return Err;
213
214 uint32_t AugmentationDataStartOffset = EHFrameReader.getOffset();
215
216 uint8_t *NextField = &AugInfo->Fields[0];
217 while (uint8_t Field = *NextField++) {
218 switch (Field) {
219 case 'L': {
Lang Hamesb1ba4d82019-04-24 15:15:55 +0000220 CIEInfo.FDEsHaveLSDAField = true;
Lang Hames11c8dfa52019-04-20 17:10:34 +0000221 uint8_t LSDAPointerEncoding;
222 if (auto Err = EHFrameReader.readInteger(LSDAPointerEncoding))
223 return Err;
224 if (LSDAPointerEncoding != (DW_EH_PE_pcrel | DW_EH_PE_absptr))
225 return make_error<JITLinkError>(
226 "Unsupported LSDA pointer encoding " +
227 formatv("{0:x2}", LSDAPointerEncoding) + " in CIE at " +
Lang Hames4e920e52019-10-04 03:55:26 +0000228 formatv("{0:x16}", CIESymbol.getAddress()));
Lang Hames11c8dfa52019-04-20 17:10:34 +0000229 break;
230 }
231 case 'P': {
232 uint8_t PersonalityPointerEncoding = 0;
233 if (auto Err = EHFrameReader.readInteger(PersonalityPointerEncoding))
234 return Err;
235 if (PersonalityPointerEncoding !=
236 (DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4))
237 return make_error<JITLinkError>(
238 "Unspported personality pointer "
239 "encoding " +
240 formatv("{0:x2}", PersonalityPointerEncoding) + " in CIE at " +
Lang Hames4e920e52019-10-04 03:55:26 +0000241 formatv("{0:x16}", CIESymbol.getAddress()));
Lang Hames11c8dfa52019-04-20 17:10:34 +0000242 uint32_t PersonalityPointerAddress;
243 if (auto Err = EHFrameReader.readInteger(PersonalityPointerAddress))
244 return Err;
245 break;
246 }
247 case 'R': {
248 uint8_t FDEPointerEncoding;
249 if (auto Err = EHFrameReader.readInteger(FDEPointerEncoding))
250 return Err;
251 if (FDEPointerEncoding != (DW_EH_PE_pcrel | DW_EH_PE_absptr))
252 return make_error<JITLinkError>(
253 "Unsupported FDE address pointer "
254 "encoding " +
255 formatv("{0:x2}", FDEPointerEncoding) + " in CIE at " +
Lang Hames4e920e52019-10-04 03:55:26 +0000256 formatv("{0:x16}", CIESymbol.getAddress()));
Lang Hames11c8dfa52019-04-20 17:10:34 +0000257 break;
258 }
259 default:
260 llvm_unreachable("Invalid augmentation string field");
261 }
262 }
263
264 if (EHFrameReader.getOffset() - AugmentationDataStartOffset >
265 AugmentationDataLength)
266 return make_error<JITLinkError>("Read past the end of the augmentation "
267 "data while parsing fields");
268
Lang Hames4e920e52019-10-04 03:55:26 +0000269 assert(!CIEInfos.count(CIESymbol.getAddress()) &&
Lang Hamesb1ba4d82019-04-24 15:15:55 +0000270 "Multiple CIEs recorded at the same address?");
Lang Hames4e920e52019-10-04 03:55:26 +0000271 CIEInfos[CIESymbol.getAddress()] = std::move(CIEInfo);
Lang Hamesb1ba4d82019-04-24 15:15:55 +0000272
Lang Hames11c8dfa52019-04-20 17:10:34 +0000273 return Error::success();
274}
275
Lang Hames4e920e52019-10-04 03:55:26 +0000276Error EHFrameBinaryParser::processFDE(size_t RecordOffset, size_t RecordLength,
277 JITTargetAddress CIEPointerAddress,
278 uint32_t CIEPointer) {
Lang Hames11c8dfa52019-04-20 17:10:34 +0000279 LLVM_DEBUG(dbgs() << " Record is FDE\n");
280
Lang Hames11c8dfa52019-04-20 17:10:34 +0000281 LLVM_DEBUG({
282 dbgs() << " CIE pointer: "
283 << format("0x%016" PRIx64, CIEPointerAddress - CIEPointer) << "\n";
284 });
285
Lang Hamesb1ba4d82019-04-24 15:15:55 +0000286 auto CIEInfoItr = CIEInfos.find(CIEPointerAddress - CIEPointer);
287 if (CIEInfoItr == CIEInfos.end())
288 return make_error<JITLinkError>(
Lang Hames4e920e52019-10-04 03:55:26 +0000289 "FDE at " + formatv("{0:x16}", EHFrameAddress + RecordOffset) +
Lang Hamesb1ba4d82019-04-24 15:15:55 +0000290 " points to non-existant CIE at " +
291 formatv("{0:x16}", CIEPointerAddress - CIEPointer));
292 auto &CIEInfo = CIEInfoItr->second;
Lang Hames11c8dfa52019-04-20 17:10:34 +0000293
Lang Hames11c8dfa52019-04-20 17:10:34 +0000294 // Read and sanity check the PC-start pointer and size.
295 JITTargetAddress PCBeginAddress = EHFrameAddress + EHFrameReader.getOffset();
296
297 auto PCBeginDelta = readAbsolutePointer();
298 if (!PCBeginDelta)
299 return PCBeginDelta.takeError();
300
301 JITTargetAddress PCBegin = PCBeginAddress + *PCBeginDelta;
302 LLVM_DEBUG({
Lang Hames4e920e52019-10-04 03:55:26 +0000303 dbgs() << " PC begin: " << format("0x%016" PRIx64, PCBegin) << "\n";
Lang Hames11c8dfa52019-04-20 17:10:34 +0000304 });
305
Lang Hames4e920e52019-10-04 03:55:26 +0000306 auto *TargetSymbol = getSymbolAtAddress(PCBegin);
Lang Hames11c8dfa52019-04-20 17:10:34 +0000307
Lang Hames4e920e52019-10-04 03:55:26 +0000308 if (!TargetSymbol)
Lang Hames11c8dfa52019-04-20 17:10:34 +0000309 return make_error<JITLinkError>("FDE PC-begin " +
310 formatv("{0:x16}", PCBegin) +
Lang Hames4e920e52019-10-04 03:55:26 +0000311 " does not point at symbol");
Lang Hames11c8dfa52019-04-20 17:10:34 +0000312
Lang Hames4e920e52019-10-04 03:55:26 +0000313 if (TargetSymbol->getAddress() != PCBegin)
Lang Hames11c8dfa52019-04-20 17:10:34 +0000314 return make_error<JITLinkError>(
315 "FDE PC-begin " + formatv("{0:x16}", PCBegin) +
Lang Hames4e920e52019-10-04 03:55:26 +0000316 " does not point to start of symbol at " +
317 formatv("{0:x16}", TargetSymbol->getAddress()));
Lang Hames11c8dfa52019-04-20 17:10:34 +0000318
Lang Hames4e920e52019-10-04 03:55:26 +0000319 LLVM_DEBUG(dbgs() << " FDE target: " << *TargetSymbol << "\n");
Lang Hames11c8dfa52019-04-20 17:10:34 +0000320
321 // Skip over the PC range size field.
Lang Hames4e920e52019-10-04 03:55:26 +0000322 if (auto Err = EHFrameReader.skip(PointerSize))
Lang Hames11c8dfa52019-04-20 17:10:34 +0000323 return Err;
324
Lang Hames4e920e52019-10-04 03:55:26 +0000325 Symbol *LSDASymbol = nullptr;
326 JITTargetAddress LSDAAddress = 0;
Lang Hamesb1ba4d82019-04-24 15:15:55 +0000327 if (CIEInfo.FDEsHaveLSDAField) {
Lang Hames11c8dfa52019-04-20 17:10:34 +0000328 uint64_t AugmentationDataSize;
329 if (auto Err = EHFrameReader.readULEB128(AugmentationDataSize))
330 return Err;
Lang Hames4e920e52019-10-04 03:55:26 +0000331 if (AugmentationDataSize != PointerSize)
Lang Hamesb1ba4d82019-04-24 15:15:55 +0000332 return make_error<JITLinkError>(
333 "Unexpected FDE augmentation data size (expected " +
Lang Hames4e920e52019-10-04 03:55:26 +0000334 Twine(PointerSize) + ", got " + Twine(AugmentationDataSize) +
335 ") for FDE at " + formatv("{0:x16}", EHFrameAddress + RecordOffset));
336 LSDAAddress = EHFrameAddress + EHFrameReader.getOffset();
Lang Hames11c8dfa52019-04-20 17:10:34 +0000337 auto LSDADelta = readAbsolutePointer();
338 if (!LSDADelta)
339 return LSDADelta.takeError();
340
341 JITTargetAddress LSDA = LSDAAddress + *LSDADelta;
342
Lang Hames4e920e52019-10-04 03:55:26 +0000343 LSDASymbol = getSymbolAtAddress(LSDA);
Lang Hames11c8dfa52019-04-20 17:10:34 +0000344
Lang Hames4e920e52019-10-04 03:55:26 +0000345 if (!LSDASymbol)
Lang Hames11c8dfa52019-04-20 17:10:34 +0000346 return make_error<JITLinkError>("FDE LSDA " + formatv("{0:x16}", LSDA) +
Lang Hames4e920e52019-10-04 03:55:26 +0000347 " does not point at symbol");
Lang Hames11c8dfa52019-04-20 17:10:34 +0000348
Lang Hames4e920e52019-10-04 03:55:26 +0000349 if (LSDASymbol->getAddress() != LSDA)
Lang Hames11c8dfa52019-04-20 17:10:34 +0000350 return make_error<JITLinkError>(
351 "FDE LSDA " + formatv("{0:x16}", LSDA) +
Lang Hames4e920e52019-10-04 03:55:26 +0000352 " does not point to start of symbol at " +
353 formatv("{0:x16}", LSDASymbol->getAddress()));
Lang Hames11c8dfa52019-04-20 17:10:34 +0000354
Lang Hames4e920e52019-10-04 03:55:26 +0000355 LLVM_DEBUG(dbgs() << " FDE LSDA: " << *LSDASymbol << "\n");
Lang Hames11c8dfa52019-04-20 17:10:34 +0000356 }
357
Lang Hames4e920e52019-10-04 03:55:26 +0000358 JITTargetAddress RecordAddress = EHFrameAddress + RecordOffset;
359 auto FDESymbol = createFDERecord(
360 RecordAddress, EHFrameContent.substr(RecordOffset, RecordLength),
361 *CIEInfo.CIESymbol, CIEPointerAddress - RecordAddress, *TargetSymbol,
362 PCBeginAddress - RecordAddress, LSDASymbol, LSDAAddress - RecordAddress);
Lang Hames11c8dfa52019-04-20 17:10:34 +0000363
Lang Hames4e920e52019-10-04 03:55:26 +0000364 return FDESymbol.takeError();
Lang Hames11c8dfa52019-04-20 17:10:34 +0000365}
366
367// Determine whether we can register EH tables.
368#if (defined(__GNUC__) && !defined(__ARM_EABI__) && !defined(__ia64__) && \
Xing Xue4246b752019-05-22 17:41:27 +0000369 !(defined(_AIX) && defined(__ibmxl__)) && !defined(__SEH__) && \
370 !defined(__USING_SJLJ_EXCEPTIONS__))
Lang Hames11c8dfa52019-04-20 17:10:34 +0000371#define HAVE_EHTABLE_SUPPORT 1
372#else
373#define HAVE_EHTABLE_SUPPORT 0
374#endif
375
376#if HAVE_EHTABLE_SUPPORT
377extern "C" void __register_frame(const void *);
378extern "C" void __deregister_frame(const void *);
379
380Error registerFrameWrapper(const void *P) {
381 __register_frame(P);
382 return Error::success();
383}
384
385Error deregisterFrameWrapper(const void *P) {
386 __deregister_frame(P);
387 return Error::success();
388}
389
390#else
391
392// The building compiler does not have __(de)register_frame but
393// it may be found at runtime in a dynamically-loaded library.
394// For example, this happens when building LLVM with Visual C++
395// but using the MingW runtime.
396static Error registerFrameWrapper(const void *P) {
397 static void((*RegisterFrame)(const void *)) = 0;
398
399 if (!RegisterFrame)
400 *(void **)&RegisterFrame =
401 llvm::sys::DynamicLibrary::SearchForAddressOfSymbol("__register_frame");
402
403 if (RegisterFrame) {
404 RegisterFrame(P);
405 return Error::success();
406 }
407
408 return make_error<JITLinkError>("could not register eh-frame: "
409 "__register_frame function not found");
410}
411
Lang Hames68b0b8c2019-04-20 17:29:57 +0000412static Error deregisterFrameWrapper(const void *P) {
Lang Hames11c8dfa52019-04-20 17:10:34 +0000413 static void((*DeregisterFrame)(const void *)) = 0;
414
415 if (!DeregisterFrame)
416 *(void **)&DeregisterFrame =
417 llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(
418 "__deregister_frame");
419
420 if (DeregisterFrame) {
421 DeregisterFrame(P);
422 return Error::success();
423 }
424
425 return make_error<JITLinkError>("could not deregister eh-frame: "
426 "__deregister_frame function not found");
427}
428#endif
429
430#ifdef __APPLE__
431
432template <typename HandleFDEFn>
433Error walkAppleEHFrameSection(const char *const SectionStart,
Lang Hamesc48f1f62019-08-27 15:50:32 +0000434 size_t SectionSize,
Lang Hames11c8dfa52019-04-20 17:10:34 +0000435 HandleFDEFn HandleFDE) {
436 const char *CurCFIRecord = SectionStart;
Lang Hamesc48f1f62019-08-27 15:50:32 +0000437 const char *End = SectionStart + SectionSize;
Lang Hames11c8dfa52019-04-20 17:10:34 +0000438 uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
439
Lang Hamesc48f1f62019-08-27 15:50:32 +0000440 while (CurCFIRecord != End && Size != 0) {
Lang Hames11c8dfa52019-04-20 17:10:34 +0000441 const char *OffsetField = CurCFIRecord + (Size == 0xffffffff ? 12 : 4);
442 if (Size == 0xffffffff)
443 Size = *reinterpret_cast<const uint64_t *>(CurCFIRecord + 4) + 12;
444 else
445 Size += 4;
446 uint32_t Offset = *reinterpret_cast<const uint32_t *>(OffsetField);
447 if (Offset != 0)
448 if (auto Err = HandleFDE(CurCFIRecord))
449 return Err;
450
451 LLVM_DEBUG({
452 dbgs() << "Registering eh-frame section:\n";
453 dbgs() << "Processing " << (Offset ? "FDE" : "CIE") << " @"
454 << (void *)CurCFIRecord << ": [";
455 for (unsigned I = 0; I < Size; ++I)
456 dbgs() << format(" 0x%02" PRIx8, *(CurCFIRecord + I));
457 dbgs() << " ]\n";
458 });
459 CurCFIRecord += Size;
460
461 Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
462 }
463
464 return Error::success();
465}
466
467#endif // __APPLE__
468
Lang Hamesc48f1f62019-08-27 15:50:32 +0000469Error registerEHFrameSection(const void *EHFrameSectionAddr,
470 size_t EHFrameSectionSize) {
Lang Hames11c8dfa52019-04-20 17:10:34 +0000471#ifdef __APPLE__
472 // On Darwin __register_frame has to be called for each FDE entry.
473 return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr),
Lang Hamesc48f1f62019-08-27 15:50:32 +0000474 EHFrameSectionSize,
Lang Hames11c8dfa52019-04-20 17:10:34 +0000475 registerFrameWrapper);
476#else
477 // On Linux __register_frame takes a single argument:
478 // a pointer to the start of the .eh_frame section.
479
480 // How can it find the end? Because crtendS.o is linked
481 // in and it has an .eh_frame section with four zero chars.
482 return registerFrameWrapper(EHFrameSectionAddr);
483#endif
484}
485
Lang Hamesc48f1f62019-08-27 15:50:32 +0000486Error deregisterEHFrameSection(const void *EHFrameSectionAddr,
487 size_t EHFrameSectionSize) {
Lang Hames11c8dfa52019-04-20 17:10:34 +0000488#ifdef __APPLE__
489 return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr),
Lang Hamesc48f1f62019-08-27 15:50:32 +0000490 EHFrameSectionSize,
Lang Hames11c8dfa52019-04-20 17:10:34 +0000491 deregisterFrameWrapper);
492#else
493 return deregisterFrameWrapper(EHFrameSectionAddr);
494#endif
495}
496
Lang Hamesf5a885f2019-07-04 00:05:12 +0000497EHFrameRegistrar::~EHFrameRegistrar() {}
498
499InProcessEHFrameRegistrar &InProcessEHFrameRegistrar::getInstance() {
500 static InProcessEHFrameRegistrar Instance;
501 return Instance;
502}
503
504InProcessEHFrameRegistrar::InProcessEHFrameRegistrar() {}
505
Lang Hames4e920e52019-10-04 03:55:26 +0000506LinkGraphPassFunction
Lang Hamesa9fdf372019-04-26 22:58:39 +0000507createEHFrameRecorderPass(const Triple &TT,
Lang Hamesc48f1f62019-08-27 15:50:32 +0000508 StoreFrameRangeFunction StoreRangeAddress) {
Lang Hames11c8dfa52019-04-20 17:10:34 +0000509 const char *EHFrameSectionName = nullptr;
510 if (TT.getObjectFormat() == Triple::MachO)
511 EHFrameSectionName = "__eh_frame";
512 else
513 EHFrameSectionName = ".eh_frame";
514
Lang Hamesc48f1f62019-08-27 15:50:32 +0000515 auto RecordEHFrame =
Lang Hames4e920e52019-10-04 03:55:26 +0000516 [EHFrameSectionName,
517 StoreFrameRange = std::move(StoreRangeAddress)](LinkGraph &G) -> Error {
518 // Search for a non-empty eh-frame and record the address of the first
519 // symbol in it.
Lang Hames11c8dfa52019-04-20 17:10:34 +0000520 JITTargetAddress Addr = 0;
Lang Hamesc48f1f62019-08-27 15:50:32 +0000521 size_t Size = 0;
522 if (auto *S = G.findSectionByName(EHFrameSectionName)) {
Lang Hames4e920e52019-10-04 03:55:26 +0000523 auto R = SectionRange(*S);
Lang Hamesc48f1f62019-08-27 15:50:32 +0000524 Addr = R.getStart();
525 Size = R.getSize();
526 }
527 if (Addr == 0 && Size != 0)
528 return make_error<JITLinkError>("__eh_frame section can not have zero "
529 "address with non-zero size");
530 StoreFrameRange(Addr, Size);
Lang Hames11c8dfa52019-04-20 17:10:34 +0000531 return Error::success();
532 };
533
534 return RecordEHFrame;
535}
536
537} // end namespace jitlink
538} // end namespace llvm