1 //===-------- JITLink_DWARFRecordSectionSplitter.cpp - JITLink-------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h" 10 #include "llvm/Support/BinaryStreamReader.h" 11 12 #define DEBUG_TYPE "jitlink" 13 14 namespace llvm { 15 namespace jitlink { 16 17 DWARFRecordSectionSplitter::DWARFRecordSectionSplitter(StringRef SectionName) 18 : SectionName(SectionName) {} 19 20 Error DWARFRecordSectionSplitter::operator()(LinkGraph &G) { 21 auto *Section = G.findSectionByName(SectionName); 22 23 if (!Section) { 24 LLVM_DEBUG({ 25 dbgs() << "DWARFRecordSectionSplitter: No " << SectionName 26 << " section. Nothing to do\n"; 27 }); 28 return Error::success(); 29 } 30 31 LLVM_DEBUG({ 32 dbgs() << "DWARFRecordSectionSplitter: Processing " << SectionName 33 << "...\n"; 34 }); 35 36 DenseMap<Block *, LinkGraph::SplitBlockCache> Caches; 37 38 { 39 // Pre-build the split caches. 40 for (auto *B : Section->blocks()) 41 Caches[B] = LinkGraph::SplitBlockCache::value_type(); 42 for (auto *Sym : Section->symbols()) 43 Caches[&Sym->getBlock()]->push_back(Sym); 44 for (auto *B : Section->blocks()) 45 llvm::sort(*Caches[B], [](const Symbol *LHS, const Symbol *RHS) { 46 return LHS->getOffset() > RHS->getOffset(); 47 }); 48 } 49 50 // Iterate over blocks (we do this by iterating over Caches entries rather 51 // than Section->blocks() as we will be inserting new blocks along the way, 52 // which would invalidate iterators in the latter sequence. 53 for (auto &KV : Caches) { 54 auto &B = *KV.first; 55 auto &BCache = KV.second; 56 if (auto Err = processBlock(G, B, BCache)) 57 return Err; 58 } 59 60 return Error::success(); 61 } 62 63 Error DWARFRecordSectionSplitter::processBlock( 64 LinkGraph &G, Block &B, LinkGraph::SplitBlockCache &Cache) { 65 LLVM_DEBUG(dbgs() << " Processing block at " << B.getAddress() << "\n"); 66 67 // Section should not contain zero-fill blocks. 68 if (B.isZeroFill()) 69 return make_error<JITLinkError>("Unexpected zero-fill block in " + 70 SectionName + " section"); 71 72 if (B.getSize() == 0) { 73 LLVM_DEBUG(dbgs() << " Block is empty. Skipping.\n"); 74 return Error::success(); 75 } 76 77 BinaryStreamReader BlockReader( 78 StringRef(B.getContent().data(), B.getContent().size()), 79 G.getEndianness()); 80 81 while (true) { 82 uint64_t RecordStartOffset = BlockReader.getOffset(); 83 84 LLVM_DEBUG({ 85 dbgs() << " Processing CFI record at " 86 << formatv("{0:x16}", B.getAddress()) << "\n"; 87 }); 88 89 uint32_t Length; 90 if (auto Err = BlockReader.readInteger(Length)) 91 return Err; 92 if (Length != 0xffffffff) { 93 if (auto Err = BlockReader.skip(Length)) 94 return Err; 95 } else { 96 uint64_t ExtendedLength; 97 if (auto Err = BlockReader.readInteger(ExtendedLength)) 98 return Err; 99 if (auto Err = BlockReader.skip(ExtendedLength)) 100 return Err; 101 } 102 103 // If this was the last block then there's nothing to split 104 if (BlockReader.empty()) { 105 LLVM_DEBUG(dbgs() << " Extracted " << B << "\n"); 106 return Error::success(); 107 } 108 109 uint64_t BlockSize = BlockReader.getOffset() - RecordStartOffset; 110 auto &NewBlock = G.splitBlock(B, BlockSize); 111 (void)NewBlock; 112 LLVM_DEBUG(dbgs() << " Extracted " << NewBlock << "\n"); 113 } 114 } 115 116 } // namespace jitlink 117 } // namespace llvm 118