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