| //===-------- 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 |