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
DWARFRecordSectionSplitter(StringRef SectionName)17 DWARFRecordSectionSplitter::DWARFRecordSectionSplitter(StringRef SectionName)
18 : SectionName(SectionName) {}
19
operator ()(LinkGraph & G)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
processBlock(LinkGraph & G,Block & B,LinkGraph::SplitBlockCache & Cache)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 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 split
103 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 jitlink
115 } // namespace llvm
116