|  | //===-------- JITLink_DWARFRecordSectionSplitter.cpp - JITLink-------------===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h" | 
|  | #include "llvm/Support/BinaryStreamReader.h" | 
|  |  | 
|  | #define DEBUG_TYPE "jitlink" | 
|  |  | 
|  | namespace llvm { | 
|  | namespace jitlink { | 
|  |  | 
|  | DWARFRecordSectionSplitter::DWARFRecordSectionSplitter(StringRef SectionName) | 
|  | : SectionName(SectionName) {} | 
|  |  | 
|  | Error DWARFRecordSectionSplitter::operator()(LinkGraph &G) { | 
|  | auto *Section = G.findSectionByName(SectionName); | 
|  |  | 
|  | if (!Section) { | 
|  | LLVM_DEBUG({ | 
|  | dbgs() << "DWARFRecordSectionSplitter: No " << SectionName | 
|  | << " section. Nothing to do\n"; | 
|  | }); | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | LLVM_DEBUG({ | 
|  | dbgs() << "DWARFRecordSectionSplitter: Processing " << SectionName | 
|  | << "...\n"; | 
|  | }); | 
|  |  | 
|  | DenseMap<Block *, LinkGraph::SplitBlockCache> Caches; | 
|  |  | 
|  | { | 
|  | // Pre-build the split caches. | 
|  | for (auto *B : Section->blocks()) | 
|  | Caches[B] = LinkGraph::SplitBlockCache::value_type(); | 
|  | for (auto *Sym : Section->symbols()) | 
|  | Caches[&Sym->getBlock()]->push_back(Sym); | 
|  | for (auto *B : Section->blocks()) | 
|  | llvm::sort(*Caches[B], [](const Symbol *LHS, const Symbol *RHS) { | 
|  | return LHS->getOffset() > RHS->getOffset(); | 
|  | }); | 
|  | } | 
|  |  | 
|  | // Iterate over blocks (we do this by iterating over Caches entries rather | 
|  | // than Section->blocks() as we will be inserting new blocks along the way, | 
|  | // which would invalidate iterators in the latter sequence. | 
|  | for (auto &KV : Caches) { | 
|  | auto &B = *KV.first; | 
|  | auto &BCache = KV.second; | 
|  | if (auto Err = processBlock(G, B, BCache)) | 
|  | return Err; | 
|  | } | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error DWARFRecordSectionSplitter::processBlock( | 
|  | LinkGraph &G, Block &B, LinkGraph::SplitBlockCache &Cache) { | 
|  | LLVM_DEBUG(dbgs() << "  Processing block at " << B.getAddress() << "\n"); | 
|  |  | 
|  | // Section should not contain zero-fill blocks. | 
|  | if (B.isZeroFill()) | 
|  | return make_error<JITLinkError>("Unexpected zero-fill block in " + | 
|  | SectionName + " section"); | 
|  |  | 
|  | if (B.getSize() == 0) { | 
|  | LLVM_DEBUG(dbgs() << "    Block is empty. Skipping.\n"); | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | BinaryStreamReader BlockReader( | 
|  | StringRef(B.getContent().data(), B.getContent().size()), | 
|  | G.getEndianness()); | 
|  |  | 
|  | std::vector<Edge::OffsetT> SplitOffsets; | 
|  | while (true) { | 
|  | LLVM_DEBUG({ | 
|  | dbgs() << "    Processing CFI record at " | 
|  | << (B.getAddress() + BlockReader.getOffset()) << "\n"; | 
|  | }); | 
|  |  | 
|  | uint32_t Length; | 
|  | if (auto Err = BlockReader.readInteger(Length)) | 
|  | return Err; | 
|  | if (Length != 0xffffffff) { | 
|  | if (auto Err = BlockReader.skip(Length)) | 
|  | return Err; | 
|  | } else { | 
|  | uint64_t ExtendedLength; | 
|  | if (auto Err = BlockReader.readInteger(ExtendedLength)) | 
|  | return Err; | 
|  | if (auto Err = BlockReader.skip(ExtendedLength)) | 
|  | return Err; | 
|  | } | 
|  |  | 
|  | // If this was the last block then there's nothing more to split | 
|  | if (BlockReader.empty()) | 
|  | break; | 
|  |  | 
|  | SplitOffsets.push_back(BlockReader.getOffset()); | 
|  | } | 
|  |  | 
|  | G.splitBlock(B, SplitOffsets); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | } // namespace jitlink | 
|  | } // namespace llvm |