xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.cpp (revision fcaf7f8644a9988098ac6be2165bce3ea4786e91)
181ad6265SDimitry Andric //===-------- JITLink_DWARFRecordSectionSplitter.cpp - JITLink-------------===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric 
981ad6265SDimitry Andric #include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"
1081ad6265SDimitry Andric #include "llvm/Support/BinaryStreamReader.h"
1181ad6265SDimitry Andric 
1281ad6265SDimitry Andric #define DEBUG_TYPE "jitlink"
1381ad6265SDimitry Andric 
1481ad6265SDimitry Andric namespace llvm {
1581ad6265SDimitry Andric namespace jitlink {
1681ad6265SDimitry Andric 
DWARFRecordSectionSplitter(StringRef SectionName)1781ad6265SDimitry Andric DWARFRecordSectionSplitter::DWARFRecordSectionSplitter(StringRef SectionName)
1881ad6265SDimitry Andric     : SectionName(SectionName) {}
1981ad6265SDimitry Andric 
operator ()(LinkGraph & G)2081ad6265SDimitry Andric Error DWARFRecordSectionSplitter::operator()(LinkGraph &G) {
2181ad6265SDimitry Andric   auto *Section = G.findSectionByName(SectionName);
2281ad6265SDimitry Andric 
2381ad6265SDimitry Andric   if (!Section) {
2481ad6265SDimitry Andric     LLVM_DEBUG({
2581ad6265SDimitry Andric       dbgs() << "DWARFRecordSectionSplitter: No " << SectionName
2681ad6265SDimitry Andric              << " section. Nothing to do\n";
2781ad6265SDimitry Andric     });
2881ad6265SDimitry Andric     return Error::success();
2981ad6265SDimitry Andric   }
3081ad6265SDimitry Andric 
3181ad6265SDimitry Andric   LLVM_DEBUG({
3281ad6265SDimitry Andric     dbgs() << "DWARFRecordSectionSplitter: Processing " << SectionName
3381ad6265SDimitry Andric            << "...\n";
3481ad6265SDimitry Andric   });
3581ad6265SDimitry Andric 
3681ad6265SDimitry Andric   DenseMap<Block *, LinkGraph::SplitBlockCache> Caches;
3781ad6265SDimitry Andric 
3881ad6265SDimitry Andric   {
3981ad6265SDimitry Andric     // Pre-build the split caches.
4081ad6265SDimitry Andric     for (auto *B : Section->blocks())
4181ad6265SDimitry Andric       Caches[B] = LinkGraph::SplitBlockCache::value_type();
4281ad6265SDimitry Andric     for (auto *Sym : Section->symbols())
4381ad6265SDimitry Andric       Caches[&Sym->getBlock()]->push_back(Sym);
4481ad6265SDimitry Andric     for (auto *B : Section->blocks())
4581ad6265SDimitry Andric       llvm::sort(*Caches[B], [](const Symbol *LHS, const Symbol *RHS) {
4681ad6265SDimitry Andric         return LHS->getOffset() > RHS->getOffset();
4781ad6265SDimitry Andric       });
4881ad6265SDimitry Andric   }
4981ad6265SDimitry Andric 
5081ad6265SDimitry Andric   // Iterate over blocks (we do this by iterating over Caches entries rather
5181ad6265SDimitry Andric   // than Section->blocks() as we will be inserting new blocks along the way,
5281ad6265SDimitry Andric   // which would invalidate iterators in the latter sequence.
5381ad6265SDimitry Andric   for (auto &KV : Caches) {
5481ad6265SDimitry Andric     auto &B = *KV.first;
5581ad6265SDimitry Andric     auto &BCache = KV.second;
5681ad6265SDimitry Andric     if (auto Err = processBlock(G, B, BCache))
5781ad6265SDimitry Andric       return Err;
5881ad6265SDimitry Andric   }
5981ad6265SDimitry Andric 
6081ad6265SDimitry Andric   return Error::success();
6181ad6265SDimitry Andric }
6281ad6265SDimitry Andric 
processBlock(LinkGraph & G,Block & B,LinkGraph::SplitBlockCache & Cache)6381ad6265SDimitry Andric Error DWARFRecordSectionSplitter::processBlock(
6481ad6265SDimitry Andric     LinkGraph &G, Block &B, LinkGraph::SplitBlockCache &Cache) {
6581ad6265SDimitry Andric   LLVM_DEBUG(dbgs() << "  Processing block at " << B.getAddress() << "\n");
6681ad6265SDimitry Andric 
6781ad6265SDimitry Andric   // Section should not contain zero-fill blocks.
6881ad6265SDimitry Andric   if (B.isZeroFill())
6981ad6265SDimitry Andric     return make_error<JITLinkError>("Unexpected zero-fill block in " +
7081ad6265SDimitry Andric                                     SectionName + " section");
7181ad6265SDimitry Andric 
7281ad6265SDimitry Andric   if (B.getSize() == 0) {
7381ad6265SDimitry Andric     LLVM_DEBUG(dbgs() << "    Block is empty. Skipping.\n");
7481ad6265SDimitry Andric     return Error::success();
7581ad6265SDimitry Andric   }
7681ad6265SDimitry Andric 
7781ad6265SDimitry Andric   BinaryStreamReader BlockReader(
7881ad6265SDimitry Andric       StringRef(B.getContent().data(), B.getContent().size()),
7981ad6265SDimitry Andric       G.getEndianness());
8081ad6265SDimitry Andric 
8181ad6265SDimitry Andric   while (true) {
8281ad6265SDimitry Andric     uint64_t RecordStartOffset = BlockReader.getOffset();
8381ad6265SDimitry Andric 
8481ad6265SDimitry Andric     LLVM_DEBUG({
8581ad6265SDimitry Andric       dbgs() << "    Processing CFI record at "
8681ad6265SDimitry Andric              << formatv("{0:x16}", B.getAddress()) << "\n";
8781ad6265SDimitry Andric     });
8881ad6265SDimitry Andric 
8981ad6265SDimitry Andric     uint32_t Length;
9081ad6265SDimitry Andric     if (auto Err = BlockReader.readInteger(Length))
9181ad6265SDimitry Andric       return Err;
9281ad6265SDimitry Andric     if (Length != 0xffffffff) {
9381ad6265SDimitry Andric       if (auto Err = BlockReader.skip(Length))
9481ad6265SDimitry Andric         return Err;
9581ad6265SDimitry Andric     } else {
9681ad6265SDimitry Andric       uint64_t ExtendedLength;
9781ad6265SDimitry Andric       if (auto Err = BlockReader.readInteger(ExtendedLength))
9881ad6265SDimitry Andric         return Err;
9981ad6265SDimitry Andric       if (auto Err = BlockReader.skip(ExtendedLength))
10081ad6265SDimitry Andric         return Err;
10181ad6265SDimitry Andric     }
10281ad6265SDimitry Andric 
10381ad6265SDimitry Andric     // If this was the last block then there's nothing to split
10481ad6265SDimitry Andric     if (BlockReader.empty()) {
10581ad6265SDimitry Andric       LLVM_DEBUG(dbgs() << "      Extracted " << B << "\n");
10681ad6265SDimitry Andric       return Error::success();
10781ad6265SDimitry Andric     }
10881ad6265SDimitry Andric 
10981ad6265SDimitry Andric     uint64_t BlockSize = BlockReader.getOffset() - RecordStartOffset;
110*fcaf7f86SDimitry Andric     auto &NewBlock = G.splitBlock(B, BlockSize, &Cache);
11181ad6265SDimitry Andric     (void)NewBlock;
11281ad6265SDimitry Andric     LLVM_DEBUG(dbgs() << "      Extracted " << NewBlock << "\n");
11381ad6265SDimitry Andric   }
11481ad6265SDimitry Andric }
11581ad6265SDimitry Andric 
11681ad6265SDimitry Andric } // namespace jitlink
11781ad6265SDimitry Andric } // namespace llvm
118