116 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"10#include "llvm/Support/BinaryStreamReader.h"11 12#define DEBUG_TYPE "jitlink"13 14namespace llvm {15namespace jitlink {16 17DWARFRecordSectionSplitter::DWARFRecordSectionSplitter(StringRef SectionName)18 : SectionName(SectionName) {}19 20Error DWARFRecordSectionSplitter::operator()(LinkGraph &G) {21 auto *Section = G.findSectionByName(SectionName);22 23 if (!Section) {24 LLVM_DEBUG({25 dbgs() << "DWARFRecordSectionSplitter: No " << SectionName26 << " section. Nothing to do\n";27 });28 return Error::success();29 }30 31 LLVM_DEBUG({32 dbgs() << "DWARFRecordSectionSplitter: Processing " << SectionName33 << "...\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 rather51 // 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 63Error 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 std::vector<Edge::OffsetT> SplitOffsets;82 while (true) {83 LLVM_DEBUG({84 dbgs() << " Processing CFI record at "85 << (B.getAddress() + BlockReader.getOffset()) << "\n";86 });87 88 uint32_t Length;89 if (auto Err = BlockReader.readInteger(Length))90 return Err;91 if (Length != 0xffffffff) {92 if (auto Err = BlockReader.skip(Length))93 return Err;94 } else {95 uint64_t ExtendedLength;96 if (auto Err = BlockReader.readInteger(ExtendedLength))97 return Err;98 if (auto Err = BlockReader.skip(ExtendedLength))99 return Err;100 }101 102 // If this was the last block then there's nothing more to split103 if (BlockReader.empty())104 break;105 106 SplitOffsets.push_back(BlockReader.getOffset());107 }108 109 G.splitBlock(B, SplitOffsets);110 111 return Error::success();112}113 114} // namespace jitlink115} // namespace llvm116