12f09f445SMaksim Panchenko //===- bolt/Core/BinaryContext.cpp - Low-level context --------------------===//
2a34c753fSRafael Auler //
3a34c753fSRafael Auler // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a34c753fSRafael Auler // See https://llvm.org/LICENSE.txt for license information.
5a34c753fSRafael Auler // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a34c753fSRafael Auler //
7a34c753fSRafael Auler //===----------------------------------------------------------------------===//
8a34c753fSRafael Auler //
92f09f445SMaksim Panchenko // This file implements the BinaryContext class.
102f09f445SMaksim Panchenko //
11a34c753fSRafael Auler //===----------------------------------------------------------------------===//
12a34c753fSRafael Auler 
13a34c753fSRafael Auler #include "bolt/Core/BinaryContext.h"
14a34c753fSRafael Auler #include "bolt/Core/BinaryEmitter.h"
15a34c753fSRafael Auler #include "bolt/Core/BinaryFunction.h"
16a34c753fSRafael Auler #include "bolt/Utils/CommandLineOpts.h"
17a34c753fSRafael Auler #include "bolt/Utils/NameResolver.h"
18a34c753fSRafael Auler #include "bolt/Utils/Utils.h"
19a34c753fSRafael Auler #include "llvm/ADT/Twine.h"
20290e4823Sserge-sans-paille #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
21a34c753fSRafael Auler #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
22a34c753fSRafael Auler #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
23a34c753fSRafael Auler #include "llvm/MC/MCAsmLayout.h"
24a34c753fSRafael Auler #include "llvm/MC/MCAssembler.h"
25a34c753fSRafael Auler #include "llvm/MC/MCContext.h"
26a34c753fSRafael Auler #include "llvm/MC/MCDisassembler/MCDisassembler.h"
27a34c753fSRafael Auler #include "llvm/MC/MCInstPrinter.h"
28a34c753fSRafael Auler #include "llvm/MC/MCObjectStreamer.h"
29a34c753fSRafael Auler #include "llvm/MC/MCObjectWriter.h"
3057f7c7d9Sserge-sans-paille #include "llvm/MC/MCRegisterInfo.h"
31a34c753fSRafael Auler #include "llvm/MC/MCSectionELF.h"
32a34c753fSRafael Auler #include "llvm/MC/MCStreamer.h"
3357f7c7d9Sserge-sans-paille #include "llvm/MC/MCSubtargetInfo.h"
34a34c753fSRafael Auler #include "llvm/MC/MCSymbol.h"
35a34c753fSRafael Auler #include "llvm/Support/CommandLine.h"
3632d2473aSAmir Ayupov #include "llvm/Support/Error.h"
37a34c753fSRafael Auler #include "llvm/Support/Regex.h"
386aa735ceSAmir Ayupov #include <algorithm>
39a34c753fSRafael Auler #include <functional>
40a34c753fSRafael Auler #include <iterator>
416aa735ceSAmir Ayupov #include <unordered_set>
42a34c753fSRafael Auler 
43a34c753fSRafael Auler using namespace llvm;
44a34c753fSRafael Auler 
45a34c753fSRafael Auler #undef  DEBUG_TYPE
46a34c753fSRafael Auler #define DEBUG_TYPE "bolt"
47a34c753fSRafael Auler 
48a34c753fSRafael Auler namespace opts {
49a34c753fSRafael Auler 
50b92436efSFangrui Song cl::opt<bool> NoHugePages("no-huge-pages",
51a34c753fSRafael Auler                           cl::desc("use regular size pages for code alignment"),
52b92436efSFangrui Song                           cl::Hidden, cl::cat(BoltCategory));
53a34c753fSRafael Auler 
54a34c753fSRafael Auler static cl::opt<bool>
55a34c753fSRafael Auler PrintDebugInfo("print-debug-info",
56a34c753fSRafael Auler   cl::desc("print debug info when printing functions"),
57a34c753fSRafael Auler   cl::Hidden,
58a34c753fSRafael Auler   cl::ZeroOrMore,
59a34c753fSRafael Auler   cl::cat(BoltCategory));
60a34c753fSRafael Auler 
61b92436efSFangrui Song cl::opt<bool> PrintRelocations(
62b92436efSFangrui Song     "print-relocations",
63b92436efSFangrui Song     cl::desc("print relocations when printing functions/objects"), cl::Hidden,
64a34c753fSRafael Auler     cl::cat(BoltCategory));
65a34c753fSRafael Auler 
66a34c753fSRafael Auler static cl::opt<bool>
67a34c753fSRafael Auler PrintMemData("print-mem-data",
68a34c753fSRafael Auler   cl::desc("print memory data annotations when printing functions"),
69a34c753fSRafael Auler   cl::Hidden,
70a34c753fSRafael Auler   cl::ZeroOrMore,
71a34c753fSRafael Auler   cl::cat(BoltCategory));
72a34c753fSRafael Auler 
73a34c753fSRafael Auler } // namespace opts
74a34c753fSRafael Auler 
75a34c753fSRafael Auler namespace llvm {
76a34c753fSRafael Auler namespace bolt {
77a34c753fSRafael Auler 
BinaryContext(std::unique_ptr<MCContext> Ctx,std::unique_ptr<DWARFContext> DwCtx,std::unique_ptr<Triple> TheTriple,const Target * TheTarget,std::string TripleName,std::unique_ptr<MCCodeEmitter> MCE,std::unique_ptr<MCObjectFileInfo> MOFI,std::unique_ptr<const MCAsmInfo> AsmInfo,std::unique_ptr<const MCInstrInfo> MII,std::unique_ptr<const MCSubtargetInfo> STI,std::unique_ptr<MCInstPrinter> InstPrinter,std::unique_ptr<const MCInstrAnalysis> MIA,std::unique_ptr<MCPlusBuilder> MIB,std::unique_ptr<const MCRegisterInfo> MRI,std::unique_ptr<MCDisassembler> DisAsm)78a34c753fSRafael Auler BinaryContext::BinaryContext(std::unique_ptr<MCContext> Ctx,
79a34c753fSRafael Auler                              std::unique_ptr<DWARFContext> DwCtx,
80a34c753fSRafael Auler                              std::unique_ptr<Triple> TheTriple,
8140c2e0faSMaksim Panchenko                              const Target *TheTarget, std::string TripleName,
82a34c753fSRafael Auler                              std::unique_ptr<MCCodeEmitter> MCE,
83a34c753fSRafael Auler                              std::unique_ptr<MCObjectFileInfo> MOFI,
84a34c753fSRafael Auler                              std::unique_ptr<const MCAsmInfo> AsmInfo,
85a34c753fSRafael Auler                              std::unique_ptr<const MCInstrInfo> MII,
86a34c753fSRafael Auler                              std::unique_ptr<const MCSubtargetInfo> STI,
87a34c753fSRafael Auler                              std::unique_ptr<MCInstPrinter> InstPrinter,
88a34c753fSRafael Auler                              std::unique_ptr<const MCInstrAnalysis> MIA,
89a34c753fSRafael Auler                              std::unique_ptr<MCPlusBuilder> MIB,
90a34c753fSRafael Auler                              std::unique_ptr<const MCRegisterInfo> MRI,
91a34c753fSRafael Auler                              std::unique_ptr<MCDisassembler> DisAsm)
9240c2e0faSMaksim Panchenko     : Ctx(std::move(Ctx)), DwCtx(std::move(DwCtx)),
9340c2e0faSMaksim Panchenko       TheTriple(std::move(TheTriple)), TheTarget(TheTarget),
9440c2e0faSMaksim Panchenko       TripleName(TripleName), MCE(std::move(MCE)), MOFI(std::move(MOFI)),
9540c2e0faSMaksim Panchenko       AsmInfo(std::move(AsmInfo)), MII(std::move(MII)), STI(std::move(STI)),
9640c2e0faSMaksim Panchenko       InstPrinter(std::move(InstPrinter)), MIA(std::move(MIA)),
9740c2e0faSMaksim Panchenko       MIB(std::move(MIB)), MRI(std::move(MRI)), DisAsm(std::move(DisAsm)) {
98a34c753fSRafael Auler   Relocation::Arch = this->TheTriple->getArch();
99db65429dSElvina Yakubova   RegularPageSize = isAArch64() ? RegularPageSizeAArch64 : RegularPageSizeX86;
100a34c753fSRafael Auler   PageAlign = opts::NoHugePages ? RegularPageSize : HugePageSize;
101a34c753fSRafael Auler }
102a34c753fSRafael Auler 
~BinaryContext()103a34c753fSRafael Auler BinaryContext::~BinaryContext() {
1043652483cSRafael Auler   for (BinarySection *Section : Sections)
105a34c753fSRafael Auler     delete Section;
1063652483cSRafael Auler   for (BinaryFunction *InjectedFunction : InjectedBinaryFunctions)
107a34c753fSRafael Auler     delete InjectedFunction;
1083652483cSRafael Auler   for (std::pair<const uint64_t, JumpTable *> JTI : JumpTables)
109a34c753fSRafael Auler     delete JTI.second;
110a34c753fSRafael Auler   clearBinaryData();
111a34c753fSRafael Auler }
112a34c753fSRafael Auler 
113a34c753fSRafael Auler /// Create BinaryContext for a given architecture \p ArchName and
114a34c753fSRafael Auler /// triple \p TripleName.
11532d2473aSAmir Ayupov Expected<std::unique_ptr<BinaryContext>>
createBinaryContext(const ObjectFile * File,bool IsPIC,std::unique_ptr<DWARFContext> DwCtx)116a34c753fSRafael Auler BinaryContext::createBinaryContext(const ObjectFile *File, bool IsPIC,
117a34c753fSRafael Auler                                    std::unique_ptr<DWARFContext> DwCtx) {
118a34c753fSRafael Auler   StringRef ArchName = "";
119a34c753fSRafael Auler   StringRef FeaturesStr = "";
120a34c753fSRafael Auler   switch (File->getArch()) {
121a34c753fSRafael Auler   case llvm::Triple::x86_64:
122a34c753fSRafael Auler     ArchName = "x86-64";
123a34c753fSRafael Auler     FeaturesStr = "+nopl";
124a34c753fSRafael Auler     break;
125a34c753fSRafael Auler   case llvm::Triple::aarch64:
126a34c753fSRafael Auler     ArchName = "aarch64";
12775641678SDenis Revunov     FeaturesStr = "+all";
128a34c753fSRafael Auler     break;
129a34c753fSRafael Auler   default:
13032d2473aSAmir Ayupov     return createStringError(std::errc::not_supported,
13132d2473aSAmir Ayupov                              "BOLT-ERROR: Unrecognized machine in ELF file");
132a34c753fSRafael Auler   }
133a34c753fSRafael Auler 
134a34c753fSRafael Auler   auto TheTriple = std::make_unique<Triple>(File->makeTriple());
135a34c753fSRafael Auler   const std::string TripleName = TheTriple->str();
136a34c753fSRafael Auler 
137a34c753fSRafael Auler   std::string Error;
138a34c753fSRafael Auler   const Target *TheTarget =
139a34c753fSRafael Auler       TargetRegistry::lookupTarget(std::string(ArchName), *TheTriple, Error);
14032d2473aSAmir Ayupov   if (!TheTarget)
14132d2473aSAmir Ayupov     return createStringError(make_error_code(std::errc::not_supported),
14232d2473aSAmir Ayupov                              Twine("BOLT-ERROR: ", Error));
143a34c753fSRafael Auler 
144a34c753fSRafael Auler   std::unique_ptr<const MCRegisterInfo> MRI(
145a34c753fSRafael Auler       TheTarget->createMCRegInfo(TripleName));
14632d2473aSAmir Ayupov   if (!MRI)
14732d2473aSAmir Ayupov     return createStringError(
14832d2473aSAmir Ayupov         make_error_code(std::errc::not_supported),
14932d2473aSAmir Ayupov         Twine("BOLT-ERROR: no register info for target ", TripleName));
150a34c753fSRafael Auler 
151a34c753fSRafael Auler   // Set up disassembler.
152c31af7cfSAmir Ayupov   std::unique_ptr<MCAsmInfo> AsmInfo(
153a34c753fSRafael Auler       TheTarget->createMCAsmInfo(*MRI, TripleName, MCTargetOptions()));
15432d2473aSAmir Ayupov   if (!AsmInfo)
15532d2473aSAmir Ayupov     return createStringError(
15632d2473aSAmir Ayupov         make_error_code(std::errc::not_supported),
15732d2473aSAmir Ayupov         Twine("BOLT-ERROR: no assembly info for target ", TripleName));
158c31af7cfSAmir Ayupov   // BOLT creates "func@PLT" symbols for PLT entries. In function assembly dump
159c31af7cfSAmir Ayupov   // we want to emit such names as using @PLT without double quotes to convey
160c31af7cfSAmir Ayupov   // variant kind to the assembler. BOLT doesn't rely on the linker so we can
161c31af7cfSAmir Ayupov   // override the default AsmInfo behavior to emit names the way we want.
162c31af7cfSAmir Ayupov   AsmInfo->setAllowAtInName(true);
163a34c753fSRafael Auler 
164a34c753fSRafael Auler   std::unique_ptr<const MCSubtargetInfo> STI(
165a34c753fSRafael Auler       TheTarget->createMCSubtargetInfo(TripleName, "", FeaturesStr));
16632d2473aSAmir Ayupov   if (!STI)
16732d2473aSAmir Ayupov     return createStringError(
16832d2473aSAmir Ayupov         make_error_code(std::errc::not_supported),
16932d2473aSAmir Ayupov         Twine("BOLT-ERROR: no subtarget info for target ", TripleName));
170a34c753fSRafael Auler 
171a34c753fSRafael Auler   std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
17232d2473aSAmir Ayupov   if (!MII)
17332d2473aSAmir Ayupov     return createStringError(
17432d2473aSAmir Ayupov         make_error_code(std::errc::not_supported),
17532d2473aSAmir Ayupov         Twine("BOLT-ERROR: no instruction info for target ", TripleName));
176a34c753fSRafael Auler 
177a34c753fSRafael Auler   std::unique_ptr<MCContext> Ctx(
178a34c753fSRafael Auler       new MCContext(*TheTriple, AsmInfo.get(), MRI.get(), STI.get()));
179a34c753fSRafael Auler   std::unique_ptr<MCObjectFileInfo> MOFI(
180a34c753fSRafael Auler       TheTarget->createMCObjectFileInfo(*Ctx, IsPIC));
181a34c753fSRafael Auler   Ctx->setObjectFileInfo(MOFI.get());
182a34c753fSRafael Auler   // We do not support X86 Large code model. Change this in the future.
183a34c753fSRafael Auler   bool Large = false;
184a34c753fSRafael Auler   if (TheTriple->getArch() == llvm::Triple::aarch64)
185a34c753fSRafael Auler     Large = true;
186a34c753fSRafael Auler   unsigned LSDAEncoding =
187a34c753fSRafael Auler       Large ? dwarf::DW_EH_PE_absptr : dwarf::DW_EH_PE_udata4;
188a34c753fSRafael Auler   unsigned TTypeEncoding =
189a34c753fSRafael Auler       Large ? dwarf::DW_EH_PE_absptr : dwarf::DW_EH_PE_udata4;
190a34c753fSRafael Auler   if (IsPIC) {
191a34c753fSRafael Auler     LSDAEncoding = dwarf::DW_EH_PE_pcrel |
192a34c753fSRafael Auler                    (Large ? dwarf::DW_EH_PE_sdata8 : dwarf::DW_EH_PE_sdata4);
193a34c753fSRafael Auler     TTypeEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |
194a34c753fSRafael Auler                     (Large ? dwarf::DW_EH_PE_sdata8 : dwarf::DW_EH_PE_sdata4);
195a34c753fSRafael Auler   }
196a34c753fSRafael Auler 
197a34c753fSRafael Auler   std::unique_ptr<MCDisassembler> DisAsm(
198a34c753fSRafael Auler       TheTarget->createMCDisassembler(*STI, *Ctx));
199a34c753fSRafael Auler 
20032d2473aSAmir Ayupov   if (!DisAsm)
20132d2473aSAmir Ayupov     return createStringError(
20232d2473aSAmir Ayupov         make_error_code(std::errc::not_supported),
20332d2473aSAmir Ayupov         Twine("BOLT-ERROR: no disassembler info for target ", TripleName));
204a34c753fSRafael Auler 
205a34c753fSRafael Auler   std::unique_ptr<const MCInstrAnalysis> MIA(
206a34c753fSRafael Auler       TheTarget->createMCInstrAnalysis(MII.get()));
20732d2473aSAmir Ayupov   if (!MIA)
20832d2473aSAmir Ayupov     return createStringError(
20932d2473aSAmir Ayupov         make_error_code(std::errc::not_supported),
21032d2473aSAmir Ayupov         Twine("BOLT-ERROR: failed to create instruction analysis for target ",
21132d2473aSAmir Ayupov               TripleName));
212a34c753fSRafael Auler 
213a34c753fSRafael Auler   int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
214a34c753fSRafael Auler   std::unique_ptr<MCInstPrinter> InstructionPrinter(
215a34c753fSRafael Auler       TheTarget->createMCInstPrinter(*TheTriple, AsmPrinterVariant, *AsmInfo,
216a34c753fSRafael Auler                                      *MII, *MRI));
21732d2473aSAmir Ayupov   if (!InstructionPrinter)
21832d2473aSAmir Ayupov     return createStringError(
21932d2473aSAmir Ayupov         make_error_code(std::errc::not_supported),
22032d2473aSAmir Ayupov         Twine("BOLT-ERROR: no instruction printer for target ", TripleName));
221a34c753fSRafael Auler   InstructionPrinter->setPrintImmHex(true);
222a34c753fSRafael Auler 
223a34c753fSRafael Auler   std::unique_ptr<MCCodeEmitter> MCE(
2242aed07e9SShao-Ce SUN       TheTarget->createMCCodeEmitter(*MII, *Ctx));
225a34c753fSRafael Auler 
226a34c753fSRafael Auler   // Make sure we don't miss any output on core dumps.
227a34c753fSRafael Auler   outs().SetUnbuffered();
228a34c753fSRafael Auler   errs().SetUnbuffered();
229a34c753fSRafael Auler   dbgs().SetUnbuffered();
230a34c753fSRafael Auler 
231a34c753fSRafael Auler   auto BC = std::make_unique<BinaryContext>(
232a34c753fSRafael Auler       std::move(Ctx), std::move(DwCtx), std::move(TheTriple), TheTarget,
233a34c753fSRafael Auler       std::string(TripleName), std::move(MCE), std::move(MOFI),
234a34c753fSRafael Auler       std::move(AsmInfo), std::move(MII), std::move(STI),
23540c2e0faSMaksim Panchenko       std::move(InstructionPrinter), std::move(MIA), nullptr, std::move(MRI),
23640c2e0faSMaksim Panchenko       std::move(DisAsm));
237a34c753fSRafael Auler 
238a34c753fSRafael Auler   BC->TTypeEncoding = TTypeEncoding;
239a34c753fSRafael Auler   BC->LSDAEncoding = LSDAEncoding;
240a34c753fSRafael Auler 
241a34c753fSRafael Auler   BC->MAB = std::unique_ptr<MCAsmBackend>(
242a34c753fSRafael Auler       BC->TheTarget->createMCAsmBackend(*BC->STI, *BC->MRI, MCTargetOptions()));
243a34c753fSRafael Auler 
244a34c753fSRafael Auler   BC->setFilename(File->getFileName());
245a34c753fSRafael Auler 
246a34c753fSRafael Auler   BC->HasFixedLoadAddress = !IsPIC;
247a34c753fSRafael Auler 
248e290133cSMaksim Panchenko   BC->SymbolicDisAsm = std::unique_ptr<MCDisassembler>(
249e290133cSMaksim Panchenko       BC->TheTarget->createMCDisassembler(*BC->STI, *BC->Ctx));
250e290133cSMaksim Panchenko 
251e290133cSMaksim Panchenko   if (!BC->SymbolicDisAsm)
252e290133cSMaksim Panchenko     return createStringError(
253e290133cSMaksim Panchenko         make_error_code(std::errc::not_supported),
254e290133cSMaksim Panchenko         Twine("BOLT-ERROR: no disassembler info for target ", TripleName));
255e290133cSMaksim Panchenko 
25663686af1SVladislav Khmelevsky   return std::move(BC);
257a34c753fSRafael Auler }
258a34c753fSRafael Auler 
forceSymbolRelocations(StringRef SymbolName) const259a34c753fSRafael Auler bool BinaryContext::forceSymbolRelocations(StringRef SymbolName) const {
26040c2e0faSMaksim Panchenko   if (opts::HotText &&
26140c2e0faSMaksim Panchenko       (SymbolName == "__hot_start" || SymbolName == "__hot_end"))
262a34c753fSRafael Auler     return true;
263a34c753fSRafael Auler 
26440c2e0faSMaksim Panchenko   if (opts::HotData &&
26540c2e0faSMaksim Panchenko       (SymbolName == "__hot_data_start" || SymbolName == "__hot_data_end"))
266a34c753fSRafael Auler     return true;
267a34c753fSRafael Auler 
268a34c753fSRafael Auler   if (SymbolName == "_end")
269a34c753fSRafael Auler     return true;
270a34c753fSRafael Auler 
271a34c753fSRafael Auler   return false;
272a34c753fSRafael Auler }
273a34c753fSRafael Auler 
274a34c753fSRafael Auler std::unique_ptr<MCObjectWriter>
createObjectWriter(raw_pwrite_stream & OS)275a34c753fSRafael Auler BinaryContext::createObjectWriter(raw_pwrite_stream &OS) {
276a34c753fSRafael Auler   return MAB->createObjectWriter(OS);
277a34c753fSRafael Auler }
278a34c753fSRafael Auler 
validateObjectNesting() const279a34c753fSRafael Auler bool BinaryContext::validateObjectNesting() const {
280a34c753fSRafael Auler   auto Itr = BinaryDataMap.begin();
281a34c753fSRafael Auler   auto End = BinaryDataMap.end();
282a34c753fSRafael Auler   bool Valid = true;
283a34c753fSRafael Auler   while (Itr != End) {
284a34c753fSRafael Auler     auto Next = std::next(Itr);
285a34c753fSRafael Auler     while (Next != End &&
286a34c753fSRafael Auler            Itr->second->getSection() == Next->second->getSection() &&
287a34c753fSRafael Auler            Itr->second->containsRange(Next->second->getAddress(),
288a34c753fSRafael Auler                                       Next->second->getSize())) {
289a34c753fSRafael Auler       if (Next->second->Parent != Itr->second) {
290a34c753fSRafael Auler         errs() << "BOLT-WARNING: object nesting incorrect for:\n"
291a34c753fSRafael Auler                << "BOLT-WARNING:  " << *Itr->second << "\n"
292a34c753fSRafael Auler                << "BOLT-WARNING:  " << *Next->second << "\n";
293a34c753fSRafael Auler         Valid = false;
294a34c753fSRafael Auler       }
295a34c753fSRafael Auler       ++Next;
296a34c753fSRafael Auler     }
297a34c753fSRafael Auler     Itr = Next;
298a34c753fSRafael Auler   }
299a34c753fSRafael Auler   return Valid;
300a34c753fSRafael Auler }
301a34c753fSRafael Auler 
validateHoles() const302a34c753fSRafael Auler bool BinaryContext::validateHoles() const {
303a34c753fSRafael Auler   bool Valid = true;
304a34c753fSRafael Auler   for (BinarySection &Section : sections()) {
305a34c753fSRafael Auler     for (const Relocation &Rel : Section.relocations()) {
306a34c753fSRafael Auler       uint64_t RelAddr = Rel.Offset + Section.getAddress();
307a34c753fSRafael Auler       const BinaryData *BD = getBinaryDataContainingAddress(RelAddr);
308a34c753fSRafael Auler       if (!BD) {
309a34c753fSRafael Auler         errs() << "BOLT-WARNING: no BinaryData found for relocation at address"
310a34c753fSRafael Auler                << " 0x" << Twine::utohexstr(RelAddr) << " in "
311a34c753fSRafael Auler                << Section.getName() << "\n";
312a34c753fSRafael Auler         Valid = false;
313a34c753fSRafael Auler       } else if (!BD->getAtomicRoot()) {
314a34c753fSRafael Auler         errs() << "BOLT-WARNING: no atomic BinaryData found for relocation at "
315a34c753fSRafael Auler                << "address 0x" << Twine::utohexstr(RelAddr) << " in "
316a34c753fSRafael Auler                << Section.getName() << "\n";
317a34c753fSRafael Auler         Valid = false;
318a34c753fSRafael Auler       }
319a34c753fSRafael Auler     }
320a34c753fSRafael Auler   }
321a34c753fSRafael Auler   return Valid;
322a34c753fSRafael Auler }
323a34c753fSRafael Auler 
updateObjectNesting(BinaryDataMapType::iterator GAI)324a34c753fSRafael Auler void BinaryContext::updateObjectNesting(BinaryDataMapType::iterator GAI) {
325a34c753fSRafael Auler   const uint64_t Address = GAI->second->getAddress();
326a34c753fSRafael Auler   const uint64_t Size = GAI->second->getSize();
327a34c753fSRafael Auler 
32840c2e0faSMaksim Panchenko   auto fixParents = [&](BinaryDataMapType::iterator Itr,
32940c2e0faSMaksim Panchenko                         BinaryData *NewParent) {
330a34c753fSRafael Auler     BinaryData *OldParent = Itr->second->Parent;
331a34c753fSRafael Auler     Itr->second->Parent = NewParent;
332a34c753fSRafael Auler     ++Itr;
333a34c753fSRafael Auler     while (Itr != BinaryDataMap.end() && OldParent &&
334a34c753fSRafael Auler            Itr->second->Parent == OldParent) {
335a34c753fSRafael Auler       Itr->second->Parent = NewParent;
336a34c753fSRafael Auler       ++Itr;
337a34c753fSRafael Auler     }
338a34c753fSRafael Auler   };
339a34c753fSRafael Auler 
340a34c753fSRafael Auler   // Check if the previous symbol contains the newly added symbol.
341a34c753fSRafael Auler   if (GAI != BinaryDataMap.begin()) {
342a34c753fSRafael Auler     BinaryData *Prev = std::prev(GAI)->second;
343a34c753fSRafael Auler     while (Prev) {
344a34c753fSRafael Auler       if (Prev->getSection() == GAI->second->getSection() &&
345a34c753fSRafael Auler           Prev->containsRange(Address, Size)) {
346a34c753fSRafael Auler         fixParents(GAI, Prev);
347a34c753fSRafael Auler       } else {
348a34c753fSRafael Auler         fixParents(GAI, nullptr);
349a34c753fSRafael Auler       }
350a34c753fSRafael Auler       Prev = Prev->Parent;
351a34c753fSRafael Auler     }
352a34c753fSRafael Auler   }
353a34c753fSRafael Auler 
354a34c753fSRafael Auler   // Check if the newly added symbol contains any subsequent symbols.
355a34c753fSRafael Auler   if (Size != 0) {
356a34c753fSRafael Auler     BinaryData *BD = GAI->second->Parent ? GAI->second->Parent : GAI->second;
357a34c753fSRafael Auler     auto Itr = std::next(GAI);
35840c2e0faSMaksim Panchenko     while (
35940c2e0faSMaksim Panchenko         Itr != BinaryDataMap.end() &&
36040c2e0faSMaksim Panchenko         BD->containsRange(Itr->second->getAddress(), Itr->second->getSize())) {
361a34c753fSRafael Auler       Itr->second->Parent = BD;
362a34c753fSRafael Auler       ++Itr;
363a34c753fSRafael Auler     }
364a34c753fSRafael Auler   }
365a34c753fSRafael Auler }
366a34c753fSRafael Auler 
367a34c753fSRafael Auler iterator_range<BinaryContext::binary_data_iterator>
getSubBinaryData(BinaryData * BD)368a34c753fSRafael Auler BinaryContext::getSubBinaryData(BinaryData *BD) {
369a34c753fSRafael Auler   auto Start = std::next(BinaryDataMap.find(BD->getAddress()));
370a34c753fSRafael Auler   auto End = Start;
3713652483cSRafael Auler   while (End != BinaryDataMap.end() && BD->isAncestorOf(End->second))
372a34c753fSRafael Auler     ++End;
373a34c753fSRafael Auler   return make_range(Start, End);
374a34c753fSRafael Auler }
375a34c753fSRafael Auler 
376a34c753fSRafael Auler std::pair<const MCSymbol *, uint64_t>
handleAddressRef(uint64_t Address,BinaryFunction & BF,bool IsPCRel)377a34c753fSRafael Auler BinaryContext::handleAddressRef(uint64_t Address, BinaryFunction &BF,
378a34c753fSRafael Auler                                 bool IsPCRel) {
379a34c753fSRafael Auler   uint64_t Addend = 0;
380a34c753fSRafael Auler 
381a34c753fSRafael Auler   if (isAArch64()) {
382a34c753fSRafael Auler     // Check if this is an access to a constant island and create bookkeeping
383a34c753fSRafael Auler     // to keep track of it and emit it later as part of this function.
384a34c753fSRafael Auler     if (MCSymbol *IslandSym = BF.getOrCreateIslandAccess(Address))
385a34c753fSRafael Auler       return std::make_pair(IslandSym, Addend);
386a34c753fSRafael Auler 
387a34c753fSRafael Auler     // Detect custom code written in assembly that refers to arbitrary
388a34c753fSRafael Auler     // constant islands from other functions. Write this reference so we
389a34c753fSRafael Auler     // can pull this constant island and emit it as part of this function
390a34c753fSRafael Auler     // too.
391a34c753fSRafael Auler     auto IslandIter = AddressToConstantIslandMap.lower_bound(Address);
392a34c753fSRafael Auler     if (IslandIter != AddressToConstantIslandMap.end()) {
393a34c753fSRafael Auler       if (MCSymbol *IslandSym =
394a34c753fSRafael Auler               IslandIter->second->getOrCreateProxyIslandAccess(Address, BF)) {
395a34c753fSRafael Auler         BF.createIslandDependency(IslandSym, IslandIter->second);
396a34c753fSRafael Auler         return std::make_pair(IslandSym, Addend);
397a34c753fSRafael Auler       }
398a34c753fSRafael Auler     }
399a34c753fSRafael Auler   }
400a34c753fSRafael Auler 
401a34c753fSRafael Auler   // Note that the address does not necessarily have to reside inside
402a34c753fSRafael Auler   // a section, it could be an absolute address too.
403a34c753fSRafael Auler   ErrorOr<BinarySection &> Section = getSectionForAddress(Address);
404a34c753fSRafael Auler   if (Section && Section->isText()) {
405a34c753fSRafael Auler     if (BF.containsAddress(Address, /*UseMaxSize=*/isAArch64())) {
406a34c753fSRafael Auler       if (Address != BF.getAddress()) {
407a34c753fSRafael Auler         // The address could potentially escape. Mark it as another entry
408a34c753fSRafael Auler         // point into the function.
409a34c753fSRafael Auler         if (opts::Verbosity >= 1) {
410a34c753fSRafael Auler           outs() << "BOLT-INFO: potentially escaped address 0x"
41140c2e0faSMaksim Panchenko                  << Twine::utohexstr(Address) << " in function " << BF << '\n';
412a34c753fSRafael Auler         }
413a34c753fSRafael Auler         BF.HasInternalLabelReference = true;
414a34c753fSRafael Auler         return std::make_pair(
41540c2e0faSMaksim Panchenko             BF.addEntryPointAtOffset(Address - BF.getAddress()), Addend);
416a34c753fSRafael Auler       }
417a34c753fSRafael Auler     } else {
41835efe1d8SVladislav Khmelevsky       addInterproceduralReference(&BF, Address);
419a34c753fSRafael Auler     }
420a34c753fSRafael Auler   }
421a34c753fSRafael Auler 
422a34c753fSRafael Auler   // With relocations, catch jump table references outside of the basic block
423a34c753fSRafael Auler   // containing the indirect jump.
424a34c753fSRafael Auler   if (HasRelocations) {
425a34c753fSRafael Auler     const MemoryContentsType MemType = analyzeMemoryAt(Address, BF);
426a34c753fSRafael Auler     if (MemType == MemoryContentsType::POSSIBLE_PIC_JUMP_TABLE && IsPCRel) {
427a34c753fSRafael Auler       const MCSymbol *Symbol =
428a34c753fSRafael Auler           getOrCreateJumpTable(BF, Address, JumpTable::JTT_PIC);
429a34c753fSRafael Auler 
430a34c753fSRafael Auler       return std::make_pair(Symbol, Addend);
431a34c753fSRafael Auler     }
432a34c753fSRafael Auler   }
433a34c753fSRafael Auler 
4343652483cSRafael Auler   if (BinaryData *BD = getBinaryDataContainingAddress(Address))
435a34c753fSRafael Auler     return std::make_pair(BD->getSymbol(), Address - BD->getAddress());
436a34c753fSRafael Auler 
437a34c753fSRafael Auler   // TODO: use DWARF info to get size/alignment here?
438a34c753fSRafael Auler   MCSymbol *TargetSymbol = getOrCreateGlobalSymbol(Address, "DATAat");
439a34c753fSRafael Auler   LLVM_DEBUG(dbgs() << "Created symbol " << TargetSymbol->getName() << '\n');
440a34c753fSRafael Auler   return std::make_pair(TargetSymbol, Addend);
441a34c753fSRafael Auler }
442a34c753fSRafael Auler 
analyzeMemoryAt(uint64_t Address,BinaryFunction & BF)44340c2e0faSMaksim Panchenko MemoryContentsType BinaryContext::analyzeMemoryAt(uint64_t Address,
44440c2e0faSMaksim Panchenko                                                   BinaryFunction &BF) {
445a34c753fSRafael Auler   if (!isX86())
446a34c753fSRafael Auler     return MemoryContentsType::UNKNOWN;
447a34c753fSRafael Auler 
448a34c753fSRafael Auler   ErrorOr<BinarySection &> Section = getSectionForAddress(Address);
449a34c753fSRafael Auler   if (!Section) {
450a34c753fSRafael Auler     // No section - possibly an absolute address. Since we don't allow
451a34c753fSRafael Auler     // internal function addresses to escape the function scope - we
452a34c753fSRafael Auler     // consider it a tail call.
453a34c753fSRafael Auler     if (opts::Verbosity > 1) {
454a34c753fSRafael Auler       errs() << "BOLT-WARNING: no section for address 0x"
45540c2e0faSMaksim Panchenko              << Twine::utohexstr(Address) << " referenced from function " << BF
45640c2e0faSMaksim Panchenko              << '\n';
457a34c753fSRafael Auler     }
458a34c753fSRafael Auler     return MemoryContentsType::UNKNOWN;
459a34c753fSRafael Auler   }
460a34c753fSRafael Auler 
461a34c753fSRafael Auler   if (Section->isVirtual()) {
462a34c753fSRafael Auler     // The contents are filled at runtime.
463a34c753fSRafael Auler     return MemoryContentsType::UNKNOWN;
464a34c753fSRafael Auler   }
465a34c753fSRafael Auler 
466a34c753fSRafael Auler   // No support for jump tables in code yet.
467a34c753fSRafael Auler   if (Section->isText())
468a34c753fSRafael Auler     return MemoryContentsType::UNKNOWN;
469a34c753fSRafael Auler 
470a34c753fSRafael Auler   // Start with checking for PIC jump table. We expect non-PIC jump tables
471a34c753fSRafael Auler   // to have high 32 bits set to 0.
472a34c753fSRafael Auler   if (analyzeJumpTable(Address, JumpTable::JTT_PIC, BF))
473a34c753fSRafael Auler     return MemoryContentsType::POSSIBLE_PIC_JUMP_TABLE;
474a34c753fSRafael Auler 
475a34c753fSRafael Auler   if (analyzeJumpTable(Address, JumpTable::JTT_NORMAL, BF))
476a34c753fSRafael Auler     return MemoryContentsType::POSSIBLE_JUMP_TABLE;
477a34c753fSRafael Auler 
478a34c753fSRafael Auler   return MemoryContentsType::UNKNOWN;
479a34c753fSRafael Auler }
480a34c753fSRafael Auler 
4816aa735ceSAmir Ayupov /// Check if <fragment restored name> == <parent restored name>.cold(.\d+)?
isPotentialFragmentByName(BinaryFunction & Fragment,BinaryFunction & Parent)4826aa735ceSAmir Ayupov bool isPotentialFragmentByName(BinaryFunction &Fragment,
4836aa735ceSAmir Ayupov                                BinaryFunction &Parent) {
4846aa735ceSAmir Ayupov   for (StringRef Name : Parent.getNames()) {
4856aa735ceSAmir Ayupov     std::string NamePrefix = Regex::escape(NameResolver::restore(Name));
4866aa735ceSAmir Ayupov     std::string NameRegex = Twine(NamePrefix, "\\.cold(\\.[0-9]+)?").str();
4876aa735ceSAmir Ayupov     if (Fragment.hasRestoredNameRegex(NameRegex))
4886aa735ceSAmir Ayupov       return true;
4896aa735ceSAmir Ayupov   }
4906aa735ceSAmir Ayupov   return false;
4916aa735ceSAmir Ayupov }
4926aa735ceSAmir Ayupov 
analyzeJumpTable(const uint64_t Address,const JumpTable::JumpTableType Type,BinaryFunction & BF,const uint64_t NextJTAddress,JumpTable::AddressesType * EntriesAsAddress)493*05523dc3SHuan Nguyen bool BinaryContext::analyzeJumpTable(
494*05523dc3SHuan Nguyen     const uint64_t Address, const JumpTable::JumpTableType Type,
495*05523dc3SHuan Nguyen     BinaryFunction &BF, const uint64_t NextJTAddress,
496*05523dc3SHuan Nguyen     JumpTable::AddressesType *EntriesAsAddress) {
497a34c753fSRafael Auler   // Is one of the targets __builtin_unreachable?
498a34c753fSRafael Auler   bool HasUnreachable = false;
499a34c753fSRafael Auler 
500a34c753fSRafael Auler   // Number of targets other than __builtin_unreachable.
501a34c753fSRafael Auler   uint64_t NumRealEntries = 0;
502a34c753fSRafael Auler 
503*05523dc3SHuan Nguyen   auto addEntryAddress = [&](uint64_t EntryAddress) {
504*05523dc3SHuan Nguyen     if (EntriesAsAddress)
505*05523dc3SHuan Nguyen       EntriesAsAddress->emplace_back(EntryAddress);
506a34c753fSRafael Auler   };
507a34c753fSRafael Auler 
508a34c753fSRafael Auler   auto doesBelongToFunction = [&](const uint64_t Addr,
509a34c753fSRafael Auler                                   BinaryFunction *TargetBF) -> bool {
510a34c753fSRafael Auler     if (BF.containsAddress(Addr))
511a34c753fSRafael Auler       return true;
512a34c753fSRafael Auler     // Nothing to do if we failed to identify the containing function.
513a34c753fSRafael Auler     if (!TargetBF)
514a34c753fSRafael Auler       return false;
515a34c753fSRafael Auler     // Case 1: check if BF is a fragment and TargetBF is its parent.
516a34c753fSRafael Auler     if (BF.isFragment()) {
5176aa735ceSAmir Ayupov       // Parent function may or may not be already registered.
5186aa735ceSAmir Ayupov       // Set parent link based on function name matching heuristic.
5196aa735ceSAmir Ayupov       return registerFragment(BF, *TargetBF);
520a34c753fSRafael Auler     }
521a34c753fSRafael Auler     // Case 2: check if TargetBF is a fragment and BF is its parent.
5226aa735ceSAmir Ayupov     return TargetBF->isFragment() && registerFragment(*TargetBF, BF);
523a34c753fSRafael Auler   };
524a34c753fSRafael Auler 
525a34c753fSRafael Auler   ErrorOr<BinarySection &> Section = getSectionForAddress(Address);
526a34c753fSRafael Auler   if (!Section)
527a34c753fSRafael Auler     return false;
528a34c753fSRafael Auler 
529a34c753fSRafael Auler   // The upper bound is defined by containing object, section limits, and
530a34c753fSRafael Auler   // the next jump table in memory.
531a34c753fSRafael Auler   uint64_t UpperBound = Section->getEndAddress();
532a34c753fSRafael Auler   const BinaryData *JumpTableBD = getBinaryDataAtAddress(Address);
533a34c753fSRafael Auler   if (JumpTableBD && JumpTableBD->getSize()) {
534a34c753fSRafael Auler     assert(JumpTableBD->getEndAddress() <= UpperBound &&
535a34c753fSRafael Auler            "data object cannot cross a section boundary");
536a34c753fSRafael Auler     UpperBound = JumpTableBD->getEndAddress();
537a34c753fSRafael Auler   }
5383652483cSRafael Auler   if (NextJTAddress)
539a34c753fSRafael Auler     UpperBound = std::min(NextJTAddress, UpperBound);
540a34c753fSRafael Auler 
541a34c753fSRafael Auler   LLVM_DEBUG(dbgs() << "BOLT-DEBUG: analyzeJumpTable in " << BF.getPrintName()
542a34c753fSRafael Auler                     << '\n');
543a34c753fSRafael Auler   const uint64_t EntrySize = getJumpTableEntrySize(Type);
544a34c753fSRafael Auler   for (uint64_t EntryAddress = Address; EntryAddress <= UpperBound - EntrySize;
545a34c753fSRafael Auler        EntryAddress += EntrySize) {
546a34c753fSRafael Auler     LLVM_DEBUG(dbgs() << "  * Checking 0x" << Twine::utohexstr(EntryAddress)
547a34c753fSRafael Auler                       << " -> ");
548a34c753fSRafael Auler     // Check if there's a proper relocation against the jump table entry.
549a34c753fSRafael Auler     if (HasRelocations) {
550a34c753fSRafael Auler       if (Type == JumpTable::JTT_PIC &&
551a34c753fSRafael Auler           !DataPCRelocations.count(EntryAddress)) {
552a34c753fSRafael Auler         LLVM_DEBUG(
553a34c753fSRafael Auler             dbgs() << "FAIL: JTT_PIC table, no relocation for this address\n");
554a34c753fSRafael Auler         break;
555a34c753fSRafael Auler       }
556a34c753fSRafael Auler       if (Type == JumpTable::JTT_NORMAL && !getRelocationAt(EntryAddress)) {
557a34c753fSRafael Auler         LLVM_DEBUG(
558a34c753fSRafael Auler             dbgs()
559a34c753fSRafael Auler             << "FAIL: JTT_NORMAL table, no relocation for this address\n");
560a34c753fSRafael Auler         break;
561a34c753fSRafael Auler       }
562a34c753fSRafael Auler     }
563a34c753fSRafael Auler 
56440c2e0faSMaksim Panchenko     const uint64_t Value =
56540c2e0faSMaksim Panchenko         (Type == JumpTable::JTT_PIC)
566a34c753fSRafael Auler             ? Address + *getSignedValueAtAddress(EntryAddress, EntrySize)
567a34c753fSRafael Auler             : *getPointerAtAddress(EntryAddress);
568a34c753fSRafael Auler 
569a34c753fSRafael Auler     // __builtin_unreachable() case.
570a34c753fSRafael Auler     if (Value == BF.getAddress() + BF.getSize()) {
571*05523dc3SHuan Nguyen       addEntryAddress(Value);
572a34c753fSRafael Auler       HasUnreachable = true;
573a34c753fSRafael Auler       LLVM_DEBUG(dbgs() << "OK: __builtin_unreachable\n");
574a34c753fSRafael Auler       continue;
575a34c753fSRafael Auler     }
576a34c753fSRafael Auler 
577a34c753fSRafael Auler     // Function or one of its fragments.
578a34c753fSRafael Auler     BinaryFunction *TargetBF = getBinaryFunctionContainingAddress(Value);
579a34c753fSRafael Auler 
580a34c753fSRafael Auler     // We assume that a jump table cannot have function start as an entry.
581a34c753fSRafael Auler     if (!doesBelongToFunction(Value, TargetBF) || Value == BF.getAddress()) {
582a34c753fSRafael Auler       LLVM_DEBUG({
583a34c753fSRafael Auler         if (!BF.containsAddress(Value)) {
584a34c753fSRafael Auler           dbgs() << "FAIL: function doesn't contain this address\n";
585a34c753fSRafael Auler           if (TargetBF) {
586a34c753fSRafael Auler             dbgs() << "  ! function containing this address: "
587a34c753fSRafael Auler                    << TargetBF->getPrintName() << '\n';
588a34c753fSRafael Auler             if (TargetBF->isFragment())
589a34c753fSRafael Auler               dbgs() << "  ! is a fragment\n";
5906aa735ceSAmir Ayupov             for (BinaryFunction *TargetParent : TargetBF->ParentFragments)
591a34c753fSRafael Auler               dbgs() << "  ! its parent is "
592a34c753fSRafael Auler                      << (TargetParent ? TargetParent->getPrintName() : "(none)")
593a34c753fSRafael Auler                      << '\n';
594a34c753fSRafael Auler           }
595a34c753fSRafael Auler         }
596a34c753fSRafael Auler         if (Value == BF.getAddress())
597a34c753fSRafael Auler           dbgs() << "FAIL: jump table cannot have function start as an entry\n";
598a34c753fSRafael Auler       });
599a34c753fSRafael Auler       break;
600a34c753fSRafael Auler     }
601a34c753fSRafael Auler 
602a34c753fSRafael Auler     // Check there's an instruction at this offset.
603a34c753fSRafael Auler     if (TargetBF->getState() == BinaryFunction::State::Disassembled &&
604a34c753fSRafael Auler         !TargetBF->getInstructionAtOffset(Value - TargetBF->getAddress())) {
605a34c753fSRafael Auler       LLVM_DEBUG(dbgs() << "FAIL: no instruction at this offset\n");
606a34c753fSRafael Auler       break;
607a34c753fSRafael Auler     }
608a34c753fSRafael Auler 
609a34c753fSRafael Auler     ++NumRealEntries;
610a34c753fSRafael Auler 
611*05523dc3SHuan Nguyen     if (TargetBF != &BF)
612*05523dc3SHuan Nguyen       BF.setHasIndirectTargetToSplitFragment(true);
613*05523dc3SHuan Nguyen     addEntryAddress(Value);
614a34c753fSRafael Auler   }
615a34c753fSRafael Auler 
616a34c753fSRafael Auler   // It's a jump table if the number of real entries is more than 1, or there's
617a34c753fSRafael Auler   // one real entry and "unreachable" targets. If there are only multiple
618a34c753fSRafael Auler   // "unreachable" targets, then it's not a jump table.
619a34c753fSRafael Auler   return NumRealEntries + HasUnreachable >= 2;
620a34c753fSRafael Auler }
621a34c753fSRafael Auler 
populateJumpTables()622a34c753fSRafael Auler void BinaryContext::populateJumpTables() {
623a34c753fSRafael Auler   LLVM_DEBUG(dbgs() << "DataPCRelocations: " << DataPCRelocations.size()
624a34c753fSRafael Auler                     << '\n');
625a34c753fSRafael Auler   for (auto JTI = JumpTables.begin(), JTE = JumpTables.end(); JTI != JTE;
626a34c753fSRafael Auler        ++JTI) {
627a34c753fSRafael Auler     JumpTable *JT = JTI->second;
628a34c753fSRafael Auler 
629*05523dc3SHuan Nguyen     bool NonSimpleParent = false;
630*05523dc3SHuan Nguyen     for (BinaryFunction *BF : JT->Parents)
631*05523dc3SHuan Nguyen       NonSimpleParent |= !BF->isSimple();
632*05523dc3SHuan Nguyen     if (NonSimpleParent)
633a34c753fSRafael Auler       continue;
634a34c753fSRafael Auler 
635a34c753fSRafael Auler     uint64_t NextJTAddress = 0;
636a34c753fSRafael Auler     auto NextJTI = std::next(JTI);
6373652483cSRafael Auler     if (NextJTI != JTE)
638a34c753fSRafael Auler       NextJTAddress = NextJTI->second->getAddress();
639a34c753fSRafael Auler 
640*05523dc3SHuan Nguyen     const bool Success =
641*05523dc3SHuan Nguyen         analyzeJumpTable(JT->getAddress(), JT->Type, *(JT->Parents[0]),
642*05523dc3SHuan Nguyen                          NextJTAddress, &JT->EntriesAsAddress);
643a34c753fSRafael Auler     if (!Success) {
644*05523dc3SHuan Nguyen       LLVM_DEBUG(ListSeparator LS;
645*05523dc3SHuan Nguyen                  dbgs() << "failed to analyze jump table in function ";
646*05523dc3SHuan Nguyen                  for (BinaryFunction *Frag
647*05523dc3SHuan Nguyen                       : JT->Parents) dbgs()
648*05523dc3SHuan Nguyen                  << LS << *Frag;
649*05523dc3SHuan Nguyen                  dbgs() << '\n';);
650a34c753fSRafael Auler       JT->print(dbgs());
651a34c753fSRafael Auler       if (NextJTI != JTE) {
652*05523dc3SHuan Nguyen         LLVM_DEBUG(ListSeparator LS;
653a34c753fSRafael Auler                    dbgs() << "next jump table at 0x"
654a34c753fSRafael Auler                           << Twine::utohexstr(NextJTI->second->getAddress())
655*05523dc3SHuan Nguyen                           << " belongs to function ";
656*05523dc3SHuan Nguyen                    for (BinaryFunction *Frag
657*05523dc3SHuan Nguyen                         : NextJTI->second->Parents) dbgs()
658*05523dc3SHuan Nguyen                    << LS << *Frag;
659*05523dc3SHuan Nguyen                    dbgs() << "\n";);
660a34c753fSRafael Auler         NextJTI->second->print(dbgs());
661a34c753fSRafael Auler       }
662a34c753fSRafael Auler       llvm_unreachable("jump table heuristic failure");
663a34c753fSRafael Auler     }
664*05523dc3SHuan Nguyen     for (BinaryFunction *Frag : JT->Parents) {
665*05523dc3SHuan Nguyen       for (uint64_t EntryAddress : JT->EntriesAsAddress)
666*05523dc3SHuan Nguyen         // if target is builtin_unreachable
667*05523dc3SHuan Nguyen         if (EntryAddress == Frag->getAddress() + Frag->getSize()) {
668*05523dc3SHuan Nguyen           Frag->IgnoredBranches.emplace_back(EntryAddress - Frag->getAddress(),
669*05523dc3SHuan Nguyen                                              Frag->getSize());
670*05523dc3SHuan Nguyen         } else if (EntryAddress >= Frag->getAddress() &&
671*05523dc3SHuan Nguyen                    EntryAddress < Frag->getAddress() + Frag->getSize()) {
672*05523dc3SHuan Nguyen           Frag->registerReferencedOffset(EntryAddress - Frag->getAddress());
673*05523dc3SHuan Nguyen         }
674a34c753fSRafael Auler     }
675a34c753fSRafael Auler 
676a34c753fSRafael Auler     // In strict mode, erase PC-relative relocation record. Later we check that
677a34c753fSRafael Auler     // all such records are erased and thus have been accounted for.
678a34c753fSRafael Auler     if (opts::StrictMode && JT->Type == JumpTable::JTT_PIC) {
679a34c753fSRafael Auler       for (uint64_t Address = JT->getAddress();
680a34c753fSRafael Auler            Address < JT->getAddress() + JT->getSize();
681a34c753fSRafael Auler            Address += JT->EntrySize) {
682a34c753fSRafael Auler         DataPCRelocations.erase(DataPCRelocations.find(Address));
683a34c753fSRafael Auler       }
684a34c753fSRafael Auler     }
685a34c753fSRafael Auler 
686a34c753fSRafael Auler     // Mark to skip the function and all its fragments.
687*05523dc3SHuan Nguyen     for (BinaryFunction *Frag : JT->Parents)
688*05523dc3SHuan Nguyen       if (Frag->hasIndirectTargetToSplitFragment())
689*05523dc3SHuan Nguyen         addFragmentsToSkip(Frag);
690a34c753fSRafael Auler   }
691a34c753fSRafael Auler 
692a34c753fSRafael Auler   if (opts::StrictMode && DataPCRelocations.size()) {
693a34c753fSRafael Auler     LLVM_DEBUG({
694a34c753fSRafael Auler       dbgs() << DataPCRelocations.size()
695a34c753fSRafael Auler              << " unclaimed PC-relative relocations left in data:\n";
696a34c753fSRafael Auler       for (uint64_t Reloc : DataPCRelocations)
697a34c753fSRafael Auler         dbgs() << Twine::utohexstr(Reloc) << '\n';
698a34c753fSRafael Auler     });
699a34c753fSRafael Auler     assert(0 && "unclaimed PC-relative relocations left in data\n");
700a34c753fSRafael Auler   }
701a34c753fSRafael Auler   clearList(DataPCRelocations);
702a34c753fSRafael Auler }
7036aa735ceSAmir Ayupov 
skipMarkedFragments()7046aa735ceSAmir Ayupov void BinaryContext::skipMarkedFragments() {
705*05523dc3SHuan Nguyen   std::vector<BinaryFunction *> FragmentQueue;
706*05523dc3SHuan Nguyen   // Copy the functions to FragmentQueue.
707*05523dc3SHuan Nguyen   FragmentQueue.assign(FragmentsToSkip.begin(), FragmentsToSkip.end());
7086aa735ceSAmir Ayupov   auto addToWorklist = [&](BinaryFunction *Function) -> void {
709*05523dc3SHuan Nguyen     if (FragmentsToSkip.count(Function))
7106aa735ceSAmir Ayupov       return;
711*05523dc3SHuan Nguyen     FragmentQueue.push_back(Function);
712*05523dc3SHuan Nguyen     addFragmentsToSkip(Function);
7136aa735ceSAmir Ayupov   };
7146aa735ceSAmir Ayupov   // Functions containing split jump tables need to be skipped with all
7156aa735ceSAmir Ayupov   // fragments (transitively).
716*05523dc3SHuan Nguyen   for (size_t I = 0; I != FragmentQueue.size(); I++) {
717*05523dc3SHuan Nguyen     BinaryFunction *BF = FragmentQueue[I];
718*05523dc3SHuan Nguyen     assert(FragmentsToSkip.count(BF) &&
7196aa735ceSAmir Ayupov            "internal error in traversing function fragments");
7206aa735ceSAmir Ayupov     if (opts::Verbosity >= 1)
7216aa735ceSAmir Ayupov       errs() << "BOLT-WARNING: Ignoring " << BF->getPrintName() << '\n';
72282095bd5SHuan Nguyen     BF->setSimple(false);
723*05523dc3SHuan Nguyen     BF->setHasIndirectTargetToSplitFragment(true);
72482095bd5SHuan Nguyen 
725d2c87699SAmir Ayupov     llvm::for_each(BF->Fragments, addToWorklist);
726d2c87699SAmir Ayupov     llvm::for_each(BF->ParentFragments, addToWorklist);
7276aa735ceSAmir Ayupov   }
728641e92d4SMaksim Panchenko   if (!FragmentsToSkip.empty())
72982095bd5SHuan Nguyen     errs() << "BOLT-WARNING: skipped " << FragmentsToSkip.size() << " function"
730641e92d4SMaksim Panchenko            << (FragmentsToSkip.size() == 1 ? "" : "s")
731641e92d4SMaksim Panchenko            << " due to cold fragments\n";
732a34c753fSRafael Auler }
733a34c753fSRafael Auler 
getOrCreateGlobalSymbol(uint64_t Address,Twine Prefix,uint64_t Size,uint16_t Alignment,unsigned Flags)73440c2e0faSMaksim Panchenko MCSymbol *BinaryContext::getOrCreateGlobalSymbol(uint64_t Address, Twine Prefix,
735a34c753fSRafael Auler                                                  uint64_t Size,
736a34c753fSRafael Auler                                                  uint16_t Alignment,
737a34c753fSRafael Auler                                                  unsigned Flags) {
738a34c753fSRafael Auler   auto Itr = BinaryDataMap.find(Address);
739a34c753fSRafael Auler   if (Itr != BinaryDataMap.end()) {
740a34c753fSRafael Auler     assert(Itr->second->getSize() == Size || !Size);
741a34c753fSRafael Auler     return Itr->second->getSymbol();
742a34c753fSRafael Auler   }
743a34c753fSRafael Auler 
744a34c753fSRafael Auler   std::string Name = (Prefix + "0x" + Twine::utohexstr(Address)).str();
745a34c753fSRafael Auler   assert(!GlobalSymbols.count(Name) && "created name is not unique");
746a34c753fSRafael Auler   return registerNameAtAddress(Name, Address, Size, Alignment, Flags);
747a34c753fSRafael Auler }
748a34c753fSRafael Auler 
getOrCreateUndefinedGlobalSymbol(StringRef Name)749a34c753fSRafael Auler MCSymbol *BinaryContext::getOrCreateUndefinedGlobalSymbol(StringRef Name) {
750a34c753fSRafael Auler   return Ctx->getOrCreateSymbol(Name);
751a34c753fSRafael Auler }
752a34c753fSRafael Auler 
createBinaryFunction(const std::string & Name,BinarySection & Section,uint64_t Address,uint64_t Size,uint64_t SymbolSize,uint16_t Alignment)753a34c753fSRafael Auler BinaryFunction *BinaryContext::createBinaryFunction(
754a34c753fSRafael Auler     const std::string &Name, BinarySection &Section, uint64_t Address,
755a34c753fSRafael Auler     uint64_t Size, uint64_t SymbolSize, uint16_t Alignment) {
756a34c753fSRafael Auler   auto Result = BinaryFunctions.emplace(
757a34c753fSRafael Auler       Address, BinaryFunction(Name, Section, Address, Size, *this));
758a34c753fSRafael Auler   assert(Result.second == true && "unexpected duplicate function");
759a34c753fSRafael Auler   BinaryFunction *BF = &Result.first->second;
760a34c753fSRafael Auler   registerNameAtAddress(Name, Address, SymbolSize ? SymbolSize : Size,
761a34c753fSRafael Auler                         Alignment);
762a34c753fSRafael Auler   setSymbolToFunctionMap(BF->getSymbol(), BF);
763a34c753fSRafael Auler   return BF;
764a34c753fSRafael Auler }
765a34c753fSRafael Auler 
766a34c753fSRafael Auler const MCSymbol *
getOrCreateJumpTable(BinaryFunction & Function,uint64_t Address,JumpTable::JumpTableType Type)767a34c753fSRafael Auler BinaryContext::getOrCreateJumpTable(BinaryFunction &Function, uint64_t Address,
768a34c753fSRafael Auler                                     JumpTable::JumpTableType Type) {
76928b1dcb1SHuan Nguyen   auto isFragmentOf = [](BinaryFunction *Fragment, BinaryFunction *Parent) {
77028b1dcb1SHuan Nguyen     return (Fragment->isFragment() && Fragment->isParentFragment(Parent));
77128b1dcb1SHuan Nguyen   };
77228b1dcb1SHuan Nguyen 
773*05523dc3SHuan Nguyen   // Two fragments of same function access same jump table
774a34c753fSRafael Auler   if (JumpTable *JT = getJumpTableContainingAddress(Address)) {
775a34c753fSRafael Auler     assert(JT->Type == Type && "jump table types have to match");
776a34c753fSRafael Auler     assert(Address == JT->getAddress() && "unexpected non-empty jump table");
777a34c753fSRafael Auler 
778*05523dc3SHuan Nguyen     // Prevent associating a jump table to a specific fragment twice.
779*05523dc3SHuan Nguyen     // This simple check arises from the assumption: no more than 2 fragments.
780*05523dc3SHuan Nguyen     if (JT->Parents.size() == 1 && JT->Parents[0] != &Function) {
781*05523dc3SHuan Nguyen       bool SameFunction = isFragmentOf(JT->Parents[0], &Function) ||
782*05523dc3SHuan Nguyen                           isFragmentOf(&Function, JT->Parents[0]);
783*05523dc3SHuan Nguyen       assert(SameFunction &&
784*05523dc3SHuan Nguyen              "cannot re-use jump table of a different function");
78528b1dcb1SHuan Nguyen       // Duplicate the entry for the parent function for easy access
786*05523dc3SHuan Nguyen       JT->Parents.push_back(&Function);
78728b1dcb1SHuan Nguyen       if (opts::Verbosity > 2) {
788*05523dc3SHuan Nguyen         outs() << "BOLT-INFO: Multiple fragments access same jump table: "
789*05523dc3SHuan Nguyen                << JT->Parents[0]->getPrintName() << "; "
790*05523dc3SHuan Nguyen                << Function.getPrintName() << "\n";
791*05523dc3SHuan Nguyen         JT->print(outs());
79228b1dcb1SHuan Nguyen       }
79328b1dcb1SHuan Nguyen       Function.JumpTables.emplace(Address, JT);
794*05523dc3SHuan Nguyen       JT->Parents[0]->setHasIndirectTargetToSplitFragment(true);
795*05523dc3SHuan Nguyen       JT->Parents[1]->setHasIndirectTargetToSplitFragment(true);
79628b1dcb1SHuan Nguyen     }
797*05523dc3SHuan Nguyen 
798*05523dc3SHuan Nguyen     bool IsJumpTableParent = false;
799*05523dc3SHuan Nguyen     for (BinaryFunction *Frag : JT->Parents)
800*05523dc3SHuan Nguyen       if (Frag == &Function)
801*05523dc3SHuan Nguyen         IsJumpTableParent = true;
802*05523dc3SHuan Nguyen     assert(IsJumpTableParent &&
803*05523dc3SHuan Nguyen            "cannot re-use jump table of a different function");
804a34c753fSRafael Auler     return JT->getFirstLabel();
805a34c753fSRafael Auler   }
806a34c753fSRafael Auler 
807a34c753fSRafael Auler   // Re-use the existing symbol if possible.
808a34c753fSRafael Auler   MCSymbol *JTLabel = nullptr;
809a34c753fSRafael Auler   if (BinaryData *Object = getBinaryDataAtAddress(Address)) {
810a34c753fSRafael Auler     if (!isInternalSymbolName(Object->getSymbol()->getName()))
811a34c753fSRafael Auler       JTLabel = Object->getSymbol();
812a34c753fSRafael Auler   }
813a34c753fSRafael Auler 
814a34c753fSRafael Auler   const uint64_t EntrySize = getJumpTableEntrySize(Type);
815a34c753fSRafael Auler   if (!JTLabel) {
816a34c753fSRafael Auler     const std::string JumpTableName = generateJumpTableName(Function, Address);
817a34c753fSRafael Auler     JTLabel = registerNameAtAddress(JumpTableName, Address, 0, EntrySize);
818a34c753fSRafael Auler   }
819a34c753fSRafael Auler 
820a34c753fSRafael Auler   LLVM_DEBUG(dbgs() << "BOLT-DEBUG: creating jump table " << JTLabel->getName()
821a34c753fSRafael Auler                     << " in function " << Function << '\n');
822a34c753fSRafael Auler 
823a34c753fSRafael Auler   JumpTable *JT = new JumpTable(*JTLabel, Address, EntrySize, Type,
824*05523dc3SHuan Nguyen                                 JumpTable::LabelMapType{{0, JTLabel}},
825a34c753fSRafael Auler                                 *getSectionForAddress(Address));
826*05523dc3SHuan Nguyen   JT->Parents.push_back(&Function);
827*05523dc3SHuan Nguyen   if (opts::Verbosity > 2)
828*05523dc3SHuan Nguyen     JT->print(outs());
829a34c753fSRafael Auler   JumpTables.emplace(Address, JT);
830a34c753fSRafael Auler 
831a34c753fSRafael Auler   // Duplicate the entry for the parent function for easy access.
832a34c753fSRafael Auler   Function.JumpTables.emplace(Address, JT);
833a34c753fSRafael Auler   return JTLabel;
834a34c753fSRafael Auler }
835a34c753fSRafael Auler 
836a34c753fSRafael Auler std::pair<uint64_t, const MCSymbol *>
duplicateJumpTable(BinaryFunction & Function,JumpTable * JT,const MCSymbol * OldLabel)837a34c753fSRafael Auler BinaryContext::duplicateJumpTable(BinaryFunction &Function, JumpTable *JT,
838a34c753fSRafael Auler                                   const MCSymbol *OldLabel) {
839a34c753fSRafael Auler   auto L = scopeLock();
840a34c753fSRafael Auler   unsigned Offset = 0;
841a34c753fSRafael Auler   bool Found = false;
842a34c753fSRafael Auler   for (std::pair<const unsigned, MCSymbol *> Elmt : JT->Labels) {
843a34c753fSRafael Auler     if (Elmt.second != OldLabel)
844a34c753fSRafael Auler       continue;
845a34c753fSRafael Auler     Offset = Elmt.first;
846a34c753fSRafael Auler     Found = true;
847a34c753fSRafael Auler     break;
848a34c753fSRafael Auler   }
849a34c753fSRafael Auler   assert(Found && "Label not found");
850c907d6e0SAmir Ayupov   (void)Found;
851a34c753fSRafael Auler   MCSymbol *NewLabel = Ctx->createNamedTempSymbol("duplicatedJT");
852a34c753fSRafael Auler   JumpTable *NewJT =
853a34c753fSRafael Auler       new JumpTable(*NewLabel, JT->getAddress(), JT->EntrySize, JT->Type,
854*05523dc3SHuan Nguyen                     JumpTable::LabelMapType{{Offset, NewLabel}},
855a34c753fSRafael Auler                     *getSectionForAddress(JT->getAddress()));
856*05523dc3SHuan Nguyen   NewJT->Parents = JT->Parents;
857a34c753fSRafael Auler   NewJT->Entries = JT->Entries;
858a34c753fSRafael Auler   NewJT->Counts = JT->Counts;
859a34c753fSRafael Auler   uint64_t JumpTableID = ++DuplicatedJumpTables;
860a34c753fSRafael Auler   // Invert it to differentiate from regular jump tables whose IDs are their
861a34c753fSRafael Auler   // addresses in the input binary memory space
862a34c753fSRafael Auler   JumpTableID = ~JumpTableID;
863a34c753fSRafael Auler   JumpTables.emplace(JumpTableID, NewJT);
864a34c753fSRafael Auler   Function.JumpTables.emplace(JumpTableID, NewJT);
865a34c753fSRafael Auler   return std::make_pair(JumpTableID, NewLabel);
866a34c753fSRafael Auler }
867a34c753fSRafael Auler 
generateJumpTableName(const BinaryFunction & BF,uint64_t Address)868a34c753fSRafael Auler std::string BinaryContext::generateJumpTableName(const BinaryFunction &BF,
869a34c753fSRafael Auler                                                  uint64_t Address) {
870a34c753fSRafael Auler   size_t Id;
871a34c753fSRafael Auler   uint64_t Offset = 0;
872a34c753fSRafael Auler   if (const JumpTable *JT = BF.getJumpTableContainingAddress(Address)) {
873a34c753fSRafael Auler     Offset = Address - JT->getAddress();
874a34c753fSRafael Auler     auto Itr = JT->Labels.find(Offset);
8753652483cSRafael Auler     if (Itr != JT->Labels.end())
876a34c753fSRafael Auler       return std::string(Itr->second->getName());
877a34c753fSRafael Auler     Id = JumpTableIds.at(JT->getAddress());
878a34c753fSRafael Auler   } else {
879a34c753fSRafael Auler     Id = JumpTableIds[Address] = BF.JumpTables.size();
880a34c753fSRafael Auler   }
881a34c753fSRafael Auler   return ("JUMP_TABLE/" + BF.getOneName().str() + "." + std::to_string(Id) +
882a34c753fSRafael Auler           (Offset ? ("." + std::to_string(Offset)) : ""));
883a34c753fSRafael Auler }
884a34c753fSRafael Auler 
hasValidCodePadding(const BinaryFunction & BF)885a34c753fSRafael Auler bool BinaryContext::hasValidCodePadding(const BinaryFunction &BF) {
886a34c753fSRafael Auler   // FIXME: aarch64 support is missing.
887a34c753fSRafael Auler   if (!isX86())
888a34c753fSRafael Auler     return true;
889a34c753fSRafael Auler 
890a34c753fSRafael Auler   if (BF.getSize() == BF.getMaxSize())
891a34c753fSRafael Auler     return true;
892a34c753fSRafael Auler 
893a34c753fSRafael Auler   ErrorOr<ArrayRef<unsigned char>> FunctionData = BF.getData();
894a34c753fSRafael Auler   assert(FunctionData && "cannot get function as data");
895a34c753fSRafael Auler 
896a34c753fSRafael Auler   uint64_t Offset = BF.getSize();
897a34c753fSRafael Auler   MCInst Instr;
898a34c753fSRafael Auler   uint64_t InstrSize = 0;
899a34c753fSRafael Auler   uint64_t InstrAddress = BF.getAddress() + Offset;
900a34c753fSRafael Auler   using std::placeholders::_1;
901a34c753fSRafael Auler 
902a34c753fSRafael Auler   // Skip instructions that satisfy the predicate condition.
903a34c753fSRafael Auler   auto skipInstructions = [&](std::function<bool(const MCInst &)> Predicate) {
904a34c753fSRafael Auler     const uint64_t StartOffset = Offset;
905a34c753fSRafael Auler     for (; Offset < BF.getMaxSize();
906a34c753fSRafael Auler          Offset += InstrSize, InstrAddress += InstrSize) {
90740c2e0faSMaksim Panchenko       if (!DisAsm->getInstruction(Instr, InstrSize, FunctionData->slice(Offset),
90840c2e0faSMaksim Panchenko                                   InstrAddress, nulls()))
909a34c753fSRafael Auler         break;
910a34c753fSRafael Auler       if (!Predicate(Instr))
911a34c753fSRafael Auler         break;
912a34c753fSRafael Auler     }
913a34c753fSRafael Auler 
914a34c753fSRafael Auler     return Offset - StartOffset;
915a34c753fSRafael Auler   };
916a34c753fSRafael Auler 
917a34c753fSRafael Auler   // Skip a sequence of zero bytes.
918a34c753fSRafael Auler   auto skipZeros = [&]() {
919a34c753fSRafael Auler     const uint64_t StartOffset = Offset;
920a34c753fSRafael Auler     for (; Offset < BF.getMaxSize(); ++Offset)
921a34c753fSRafael Auler       if ((*FunctionData)[Offset] != 0)
922a34c753fSRafael Auler         break;
923a34c753fSRafael Auler 
924a34c753fSRafael Auler     return Offset - StartOffset;
925a34c753fSRafael Auler   };
926a34c753fSRafael Auler 
927a34c753fSRafael Auler   // Accept the whole padding area filled with breakpoints.
928a34c753fSRafael Auler   auto isBreakpoint = std::bind(&MCPlusBuilder::isBreakpoint, MIB.get(), _1);
929a34c753fSRafael Auler   if (skipInstructions(isBreakpoint) && Offset == BF.getMaxSize())
930a34c753fSRafael Auler     return true;
931a34c753fSRafael Auler 
932a34c753fSRafael Auler   auto isNoop = std::bind(&MCPlusBuilder::isNoop, MIB.get(), _1);
933a34c753fSRafael Auler 
934a34c753fSRafael Auler   // Some functions have a jump to the next function or to the padding area
935a34c753fSRafael Auler   // inserted after the body.
936a34c753fSRafael Auler   auto isSkipJump = [&](const MCInst &Instr) {
937a34c753fSRafael Auler     uint64_t TargetAddress = 0;
938a34c753fSRafael Auler     if (MIB->isUnconditionalBranch(Instr) &&
939a34c753fSRafael Auler         MIB->evaluateBranch(Instr, InstrAddress, InstrSize, TargetAddress)) {
940a34c753fSRafael Auler       if (TargetAddress >= InstrAddress + InstrSize &&
941a34c753fSRafael Auler           TargetAddress <= BF.getAddress() + BF.getMaxSize()) {
942a34c753fSRafael Auler         return true;
943a34c753fSRafael Auler       }
944a34c753fSRafael Auler     }
945a34c753fSRafael Auler     return false;
946a34c753fSRafael Auler   };
947a34c753fSRafael Auler 
948a34c753fSRafael Auler   // Skip over nops, jumps, and zero padding. Allow interleaving (this happens).
94940c2e0faSMaksim Panchenko   while (skipInstructions(isNoop) || skipInstructions(isSkipJump) ||
950a34c753fSRafael Auler          skipZeros())
951a34c753fSRafael Auler     ;
952a34c753fSRafael Auler 
953a34c753fSRafael Auler   if (Offset == BF.getMaxSize())
954a34c753fSRafael Auler     return true;
955a34c753fSRafael Auler 
956a34c753fSRafael Auler   if (opts::Verbosity >= 1) {
957a34c753fSRafael Auler     errs() << "BOLT-WARNING: bad padding at address 0x"
958a34c753fSRafael Auler            << Twine::utohexstr(BF.getAddress() + BF.getSize())
95940c2e0faSMaksim Panchenko            << " starting at offset " << (Offset - BF.getSize())
96040c2e0faSMaksim Panchenko            << " in function " << BF << '\n'
961a34c753fSRafael Auler            << FunctionData->slice(BF.getSize(), BF.getMaxSize() - BF.getSize())
962a34c753fSRafael Auler            << '\n';
963a34c753fSRafael Auler   }
964a34c753fSRafael Auler 
965a34c753fSRafael Auler   return false;
966a34c753fSRafael Auler }
967a34c753fSRafael Auler 
adjustCodePadding()968a34c753fSRafael Auler void BinaryContext::adjustCodePadding() {
969a34c753fSRafael Auler   for (auto &BFI : BinaryFunctions) {
970a34c753fSRafael Auler     BinaryFunction &BF = BFI.second;
971a34c753fSRafael Auler     if (!shouldEmit(BF))
972a34c753fSRafael Auler       continue;
973a34c753fSRafael Auler 
974a34c753fSRafael Auler     if (!hasValidCodePadding(BF)) {
975a34c753fSRafael Auler       if (HasRelocations) {
976a34c753fSRafael Auler         if (opts::Verbosity >= 1) {
977a34c753fSRafael Auler           outs() << "BOLT-INFO: function " << BF
978a34c753fSRafael Auler                  << " has invalid padding. Ignoring the function.\n";
979a34c753fSRafael Auler         }
980a34c753fSRafael Auler         BF.setIgnored();
981a34c753fSRafael Auler       } else {
982a34c753fSRafael Auler         BF.setMaxSize(BF.getSize());
983a34c753fSRafael Auler       }
984a34c753fSRafael Auler     }
985a34c753fSRafael Auler   }
986a34c753fSRafael Auler }
987a34c753fSRafael Auler 
registerNameAtAddress(StringRef Name,uint64_t Address,uint64_t Size,uint16_t Alignment,unsigned Flags)98840c2e0faSMaksim Panchenko MCSymbol *BinaryContext::registerNameAtAddress(StringRef Name, uint64_t Address,
989a34c753fSRafael Auler                                                uint64_t Size,
990a34c753fSRafael Auler                                                uint16_t Alignment,
991a34c753fSRafael Auler                                                unsigned Flags) {
992a34c753fSRafael Auler   // Register the name with MCContext.
993a34c753fSRafael Auler   MCSymbol *Symbol = Ctx->getOrCreateSymbol(Name);
994a34c753fSRafael Auler 
995a34c753fSRafael Auler   auto GAI = BinaryDataMap.find(Address);
996a34c753fSRafael Auler   BinaryData *BD;
997a34c753fSRafael Auler   if (GAI == BinaryDataMap.end()) {
998a34c753fSRafael Auler     ErrorOr<BinarySection &> SectionOrErr = getSectionForAddress(Address);
999a34c753fSRafael Auler     BinarySection &Section =
1000a34c753fSRafael Auler         SectionOrErr ? SectionOrErr.get() : absoluteSection();
100140c2e0faSMaksim Panchenko     BD = new BinaryData(*Symbol, Address, Size, Alignment ? Alignment : 1,
100240c2e0faSMaksim Panchenko                         Section, Flags);
1003a34c753fSRafael Auler     GAI = BinaryDataMap.emplace(Address, BD).first;
1004a34c753fSRafael Auler     GlobalSymbols[Name] = BD;
1005a34c753fSRafael Auler     updateObjectNesting(GAI);
1006a34c753fSRafael Auler   } else {
1007a34c753fSRafael Auler     BD = GAI->second;
1008a34c753fSRafael Auler     if (!BD->hasName(Name)) {
1009a34c753fSRafael Auler       GlobalSymbols[Name] = BD;
1010a34c753fSRafael Auler       BD->Symbols.push_back(Symbol);
1011a34c753fSRafael Auler     }
1012a34c753fSRafael Auler   }
1013a34c753fSRafael Auler 
1014a34c753fSRafael Auler   return Symbol;
1015a34c753fSRafael Auler }
1016a34c753fSRafael Auler 
1017a34c753fSRafael Auler const BinaryData *
getBinaryDataContainingAddressImpl(uint64_t Address) const1018a34c753fSRafael Auler BinaryContext::getBinaryDataContainingAddressImpl(uint64_t Address) const {
1019a34c753fSRafael Auler   auto NI = BinaryDataMap.lower_bound(Address);
1020a34c753fSRafael Auler   auto End = BinaryDataMap.end();
1021a34c753fSRafael Auler   if ((NI != End && Address == NI->first) ||
1022a34c753fSRafael Auler       ((NI != BinaryDataMap.begin()) && (NI-- != BinaryDataMap.begin()))) {
10233652483cSRafael Auler     if (NI->second->containsAddress(Address))
1024a34c753fSRafael Auler       return NI->second;
1025a34c753fSRafael Auler 
1026a34c753fSRafael Auler     // If this is a sub-symbol, see if a parent data contains the address.
1027a34c753fSRafael Auler     const BinaryData *BD = NI->second->getParent();
1028a34c753fSRafael Auler     while (BD) {
1029a34c753fSRafael Auler       if (BD->containsAddress(Address))
1030a34c753fSRafael Auler         return BD;
1031a34c753fSRafael Auler       BD = BD->getParent();
1032a34c753fSRafael Auler     }
1033a34c753fSRafael Auler   }
1034a34c753fSRafael Auler   return nullptr;
1035a34c753fSRafael Auler }
1036a34c753fSRafael Auler 
setBinaryDataSize(uint64_t Address,uint64_t Size)1037a34c753fSRafael Auler bool BinaryContext::setBinaryDataSize(uint64_t Address, uint64_t Size) {
1038a34c753fSRafael Auler   auto NI = BinaryDataMap.find(Address);
1039a34c753fSRafael Auler   assert(NI != BinaryDataMap.end());
1040a34c753fSRafael Auler   if (NI == BinaryDataMap.end())
1041a34c753fSRafael Auler     return false;
1042a34c753fSRafael Auler   // TODO: it's possible that a jump table starts at the same address
1043a34c753fSRafael Auler   // as a larger blob of private data.  When we set the size of the
1044a34c753fSRafael Auler   // jump table, it might be smaller than the total blob size.  In this
1045a34c753fSRafael Auler   // case we just leave the original size since (currently) it won't really
1046933df2a4SMaksim Panchenko   // affect anything.
1047a34c753fSRafael Auler   assert((!NI->second->Size || NI->second->Size == Size ||
1048a34c753fSRafael Auler           (NI->second->isJumpTable() && NI->second->Size > Size)) &&
1049a34c753fSRafael Auler          "can't change the size of a symbol that has already had its "
1050a34c753fSRafael Auler          "size set");
1051a34c753fSRafael Auler   if (!NI->second->Size) {
1052a34c753fSRafael Auler     NI->second->Size = Size;
1053a34c753fSRafael Auler     updateObjectNesting(NI);
1054a34c753fSRafael Auler     return true;
1055a34c753fSRafael Auler   }
1056a34c753fSRafael Auler   return false;
1057a34c753fSRafael Auler }
1058a34c753fSRafael Auler 
generateSymbolHashes()1059a34c753fSRafael Auler void BinaryContext::generateSymbolHashes() {
1060a34c753fSRafael Auler   auto isPadding = [](const BinaryData &BD) {
1061a34c753fSRafael Auler     StringRef Contents = BD.getSection().getContents();
1062a34c753fSRafael Auler     StringRef SymData = Contents.substr(BD.getOffset(), BD.getSize());
1063a34c753fSRafael Auler     return (BD.getName().startswith("HOLEat") ||
1064a34c753fSRafael Auler             SymData.find_first_not_of(0) == StringRef::npos);
1065a34c753fSRafael Auler   };
1066a34c753fSRafael Auler 
1067a34c753fSRafael Auler   uint64_t NumCollisions = 0;
1068a34c753fSRafael Auler   for (auto &Entry : BinaryDataMap) {
1069a34c753fSRafael Auler     BinaryData &BD = *Entry.second;
1070a34c753fSRafael Auler     StringRef Name = BD.getName();
1071a34c753fSRafael Auler 
1072a34c753fSRafael Auler     if (!isInternalSymbolName(Name))
1073a34c753fSRafael Auler       continue;
1074a34c753fSRafael Auler 
1075a34c753fSRafael Auler     // First check if a non-anonymous alias exists and move it to the front.
1076a34c753fSRafael Auler     if (BD.getSymbols().size() > 1) {
1077d2c87699SAmir Ayupov       auto Itr = llvm::find_if(BD.getSymbols(), [&](const MCSymbol *Symbol) {
1078a34c753fSRafael Auler         return !isInternalSymbolName(Symbol->getName());
1079a34c753fSRafael Auler       });
1080a34c753fSRafael Auler       if (Itr != BD.getSymbols().end()) {
1081a34c753fSRafael Auler         size_t Idx = std::distance(BD.getSymbols().begin(), Itr);
1082a34c753fSRafael Auler         std::swap(BD.getSymbols()[0], BD.getSymbols()[Idx]);
1083a34c753fSRafael Auler         continue;
1084a34c753fSRafael Auler       }
1085a34c753fSRafael Auler     }
1086a34c753fSRafael Auler 
1087a34c753fSRafael Auler     // We have to skip 0 size symbols since they will all collide.
1088a34c753fSRafael Auler     if (BD.getSize() == 0) {
1089a34c753fSRafael Auler       continue;
1090a34c753fSRafael Auler     }
1091a34c753fSRafael Auler 
1092a34c753fSRafael Auler     const uint64_t Hash = BD.getSection().hash(BD);
1093a34c753fSRafael Auler     const size_t Idx = Name.find("0x");
109440c2e0faSMaksim Panchenko     std::string NewName =
109540c2e0faSMaksim Panchenko         (Twine(Name.substr(0, Idx)) + "_" + Twine::utohexstr(Hash)).str();
1096a34c753fSRafael Auler     if (getBinaryDataByName(NewName)) {
1097a34c753fSRafael Auler       // Ignore collisions for symbols that appear to be padding
1098a34c753fSRafael Auler       // (i.e. all zeros or a "hole")
1099a34c753fSRafael Auler       if (!isPadding(BD)) {
1100a34c753fSRafael Auler         if (opts::Verbosity) {
1101a34c753fSRafael Auler           errs() << "BOLT-WARNING: collision detected when hashing " << BD
1102a34c753fSRafael Auler                  << " with new name (" << NewName << "), skipping.\n";
1103a34c753fSRafael Auler         }
1104a34c753fSRafael Auler         ++NumCollisions;
1105a34c753fSRafael Auler       }
1106a34c753fSRafael Auler       continue;
1107a34c753fSRafael Auler     }
110840c2e0faSMaksim Panchenko     BD.Symbols.insert(BD.Symbols.begin(), Ctx->getOrCreateSymbol(NewName));
1109a34c753fSRafael Auler     GlobalSymbols[NewName] = &BD;
1110a34c753fSRafael Auler   }
1111a34c753fSRafael Auler   if (NumCollisions) {
1112a34c753fSRafael Auler     errs() << "BOLT-WARNING: " << NumCollisions
1113a34c753fSRafael Auler            << " collisions detected while hashing binary objects";
1114a34c753fSRafael Auler     if (!opts::Verbosity)
1115a34c753fSRafael Auler       errs() << ". Use -v=1 to see the list.";
1116a34c753fSRafael Auler     errs() << '\n';
1117a34c753fSRafael Auler   }
1118a34c753fSRafael Auler }
1119a34c753fSRafael Auler 
registerFragment(BinaryFunction & TargetFunction,BinaryFunction & Function) const11206aa735ceSAmir Ayupov bool BinaryContext::registerFragment(BinaryFunction &TargetFunction,
1121a34c753fSRafael Auler                                      BinaryFunction &Function) const {
11226aa735ceSAmir Ayupov   if (!isPotentialFragmentByName(TargetFunction, Function))
11236aa735ceSAmir Ayupov     return false;
11246aa735ceSAmir Ayupov   assert(TargetFunction.isFragment() && "TargetFunction must be a fragment");
11256aa735ceSAmir Ayupov   if (TargetFunction.isParentFragment(&Function))
11266aa735ceSAmir Ayupov     return true;
11276aa735ceSAmir Ayupov   TargetFunction.addParentFragment(Function);
1128a34c753fSRafael Auler   Function.addFragment(TargetFunction);
1129a34c753fSRafael Auler   if (!HasRelocations) {
1130a34c753fSRafael Auler     TargetFunction.setSimple(false);
1131a34c753fSRafael Auler     Function.setSimple(false);
1132a34c753fSRafael Auler   }
1133a34c753fSRafael Auler   if (opts::Verbosity >= 1) {
113440c2e0faSMaksim Panchenko     outs() << "BOLT-INFO: marking " << TargetFunction << " as a fragment of "
113540c2e0faSMaksim Panchenko            << Function << '\n';
1136a34c753fSRafael Auler   }
11376aa735ceSAmir Ayupov   return true;
1138a34c753fSRafael Auler }
1139a34c753fSRafael Auler 
addAdrpAddRelocAArch64(BinaryFunction & BF,MCInst & LoadLowBits,MCInst & LoadHiBits,uint64_t Target)114035efe1d8SVladislav Khmelevsky void BinaryContext::addAdrpAddRelocAArch64(BinaryFunction &BF,
114135efe1d8SVladislav Khmelevsky                                            MCInst &LoadLowBits,
114235efe1d8SVladislav Khmelevsky                                            MCInst &LoadHiBits,
114335efe1d8SVladislav Khmelevsky                                            uint64_t Target) {
114435efe1d8SVladislav Khmelevsky   const MCSymbol *TargetSymbol;
114535efe1d8SVladislav Khmelevsky   uint64_t Addend = 0;
114635efe1d8SVladislav Khmelevsky   std::tie(TargetSymbol, Addend) = handleAddressRef(Target, BF,
114735efe1d8SVladislav Khmelevsky                                                     /*IsPCRel*/ true);
114835efe1d8SVladislav Khmelevsky   int64_t Val;
114935efe1d8SVladislav Khmelevsky   MIB->replaceImmWithSymbolRef(LoadHiBits, TargetSymbol, Addend, Ctx.get(), Val,
115035efe1d8SVladislav Khmelevsky                                ELF::R_AARCH64_ADR_PREL_PG_HI21);
115135efe1d8SVladislav Khmelevsky   MIB->replaceImmWithSymbolRef(LoadLowBits, TargetSymbol, Addend, Ctx.get(),
115235efe1d8SVladislav Khmelevsky                                Val, ELF::R_AARCH64_ADD_ABS_LO12_NC);
115335efe1d8SVladislav Khmelevsky }
115435efe1d8SVladislav Khmelevsky 
handleAArch64Veneer(uint64_t Address,bool MatchOnly)115535efe1d8SVladislav Khmelevsky bool BinaryContext::handleAArch64Veneer(uint64_t Address, bool MatchOnly) {
115635efe1d8SVladislav Khmelevsky   BinaryFunction *TargetFunction = getBinaryFunctionContainingAddress(Address);
115735efe1d8SVladislav Khmelevsky   if (TargetFunction)
115835efe1d8SVladislav Khmelevsky     return false;
115935efe1d8SVladislav Khmelevsky 
116035efe1d8SVladislav Khmelevsky   ErrorOr<BinarySection &> Section = getSectionForAddress(Address);
116135efe1d8SVladislav Khmelevsky   assert(Section && "cannot get section for referenced address");
116235efe1d8SVladislav Khmelevsky   if (!Section->isText())
116335efe1d8SVladislav Khmelevsky     return false;
116435efe1d8SVladislav Khmelevsky 
116535efe1d8SVladislav Khmelevsky   bool Ret = false;
116635efe1d8SVladislav Khmelevsky   StringRef SectionContents = Section->getContents();
116735efe1d8SVladislav Khmelevsky   uint64_t Offset = Address - Section->getAddress();
116835efe1d8SVladislav Khmelevsky   const uint64_t MaxSize = SectionContents.size() - Offset;
116935efe1d8SVladislav Khmelevsky   const uint8_t *Bytes =
117035efe1d8SVladislav Khmelevsky       reinterpret_cast<const uint8_t *>(SectionContents.data());
117135efe1d8SVladislav Khmelevsky   ArrayRef<uint8_t> Data(Bytes + Offset, MaxSize);
117235efe1d8SVladislav Khmelevsky 
117335efe1d8SVladislav Khmelevsky   auto matchVeneer = [&](BinaryFunction::InstrMapType &Instructions,
117435efe1d8SVladislav Khmelevsky                          MCInst &Instruction, uint64_t Offset,
117535efe1d8SVladislav Khmelevsky                          uint64_t AbsoluteInstrAddr,
117635efe1d8SVladislav Khmelevsky                          uint64_t TotalSize) -> bool {
117735efe1d8SVladislav Khmelevsky     MCInst *TargetHiBits, *TargetLowBits;
117835efe1d8SVladislav Khmelevsky     uint64_t TargetAddress, Count;
117935efe1d8SVladislav Khmelevsky     Count = MIB->matchLinkerVeneer(Instructions.begin(), Instructions.end(),
118035efe1d8SVladislav Khmelevsky                                    AbsoluteInstrAddr, Instruction, TargetHiBits,
118135efe1d8SVladislav Khmelevsky                                    TargetLowBits, TargetAddress);
118235efe1d8SVladislav Khmelevsky     if (!Count)
118335efe1d8SVladislav Khmelevsky       return false;
118435efe1d8SVladislav Khmelevsky 
118535efe1d8SVladislav Khmelevsky     if (MatchOnly)
118635efe1d8SVladislav Khmelevsky       return true;
118735efe1d8SVladislav Khmelevsky 
118835efe1d8SVladislav Khmelevsky     // NOTE The target symbol was created during disassemble's
118935efe1d8SVladislav Khmelevsky     // handleExternalReference
119035efe1d8SVladislav Khmelevsky     const MCSymbol *VeneerSymbol = getOrCreateGlobalSymbol(Address, "FUNCat");
119135efe1d8SVladislav Khmelevsky     BinaryFunction *Veneer = createBinaryFunction(VeneerSymbol->getName().str(),
119235efe1d8SVladislav Khmelevsky                                                   *Section, Address, TotalSize);
119335efe1d8SVladislav Khmelevsky     addAdrpAddRelocAArch64(*Veneer, *TargetLowBits, *TargetHiBits,
119435efe1d8SVladislav Khmelevsky                            TargetAddress);
119535efe1d8SVladislav Khmelevsky     MIB->addAnnotation(Instruction, "AArch64Veneer", true);
119635efe1d8SVladislav Khmelevsky     Veneer->addInstruction(Offset, std::move(Instruction));
119735efe1d8SVladislav Khmelevsky     --Count;
119835efe1d8SVladislav Khmelevsky     for (auto It = std::prev(Instructions.end()); Count != 0;
119935efe1d8SVladislav Khmelevsky          It = std::prev(It), --Count) {
120035efe1d8SVladislav Khmelevsky       MIB->addAnnotation(It->second, "AArch64Veneer", true);
120135efe1d8SVladislav Khmelevsky       Veneer->addInstruction(It->first, std::move(It->second));
120235efe1d8SVladislav Khmelevsky     }
120335efe1d8SVladislav Khmelevsky 
120435efe1d8SVladislav Khmelevsky     Veneer->getOrCreateLocalLabel(Address);
120535efe1d8SVladislav Khmelevsky     Veneer->setMaxSize(TotalSize);
120635efe1d8SVladislav Khmelevsky     Veneer->updateState(BinaryFunction::State::Disassembled);
120735efe1d8SVladislav Khmelevsky     LLVM_DEBUG(dbgs() << "BOLT-DEBUG: handling veneer function at 0x" << Address
120835efe1d8SVladislav Khmelevsky                       << "\n");
120935efe1d8SVladislav Khmelevsky     return true;
121035efe1d8SVladislav Khmelevsky   };
121135efe1d8SVladislav Khmelevsky 
121235efe1d8SVladislav Khmelevsky   uint64_t Size = 0, TotalSize = 0;
121335efe1d8SVladislav Khmelevsky   BinaryFunction::InstrMapType VeneerInstructions;
121435efe1d8SVladislav Khmelevsky   for (Offset = 0; Offset < MaxSize; Offset += Size) {
121535efe1d8SVladislav Khmelevsky     MCInst Instruction;
121635efe1d8SVladislav Khmelevsky     const uint64_t AbsoluteInstrAddr = Address + Offset;
121735efe1d8SVladislav Khmelevsky     if (!SymbolicDisAsm->getInstruction(Instruction, Size, Data.slice(Offset),
121835efe1d8SVladislav Khmelevsky                                         AbsoluteInstrAddr, nulls()))
121935efe1d8SVladislav Khmelevsky       break;
122035efe1d8SVladislav Khmelevsky 
122135efe1d8SVladislav Khmelevsky     TotalSize += Size;
122235efe1d8SVladislav Khmelevsky     if (MIB->isBranch(Instruction)) {
122335efe1d8SVladislav Khmelevsky       Ret = matchVeneer(VeneerInstructions, Instruction, Offset,
122435efe1d8SVladislav Khmelevsky                         AbsoluteInstrAddr, TotalSize);
122535efe1d8SVladislav Khmelevsky       break;
122635efe1d8SVladislav Khmelevsky     }
122735efe1d8SVladislav Khmelevsky 
122835efe1d8SVladislav Khmelevsky     VeneerInstructions.emplace(Offset, std::move(Instruction));
122935efe1d8SVladislav Khmelevsky   }
123035efe1d8SVladislav Khmelevsky 
123135efe1d8SVladislav Khmelevsky   return Ret;
123235efe1d8SVladislav Khmelevsky }
123335efe1d8SVladislav Khmelevsky 
processInterproceduralReferences()123435efe1d8SVladislav Khmelevsky void BinaryContext::processInterproceduralReferences() {
123535efe1d8SVladislav Khmelevsky   for (const std::pair<BinaryFunction *, uint64_t> &It :
123635efe1d8SVladislav Khmelevsky        InterproceduralReferences) {
123735efe1d8SVladislav Khmelevsky     BinaryFunction &Function = *It.first;
123835efe1d8SVladislav Khmelevsky     uint64_t Address = It.second;
123935efe1d8SVladislav Khmelevsky     if (!Address || Function.isIgnored())
1240a34c753fSRafael Auler       continue;
1241a34c753fSRafael Auler 
1242a34c753fSRafael Auler     BinaryFunction *TargetFunction =
1243a34c753fSRafael Auler         getBinaryFunctionContainingAddress(Address);
1244a34c753fSRafael Auler     if (&Function == TargetFunction)
1245a34c753fSRafael Auler       continue;
1246a34c753fSRafael Auler 
1247a34c753fSRafael Auler     if (TargetFunction) {
124835efe1d8SVladislav Khmelevsky       if (TargetFunction->isFragment() &&
12496aa735ceSAmir Ayupov           !registerFragment(*TargetFunction, Function)) {
12506aa735ceSAmir Ayupov         errs() << "BOLT-WARNING: interprocedural reference between unrelated "
12516aa735ceSAmir Ayupov                   "fragments: "
12526aa735ceSAmir Ayupov                << Function.getPrintName() << " and "
12536aa735ceSAmir Ayupov                << TargetFunction->getPrintName() << '\n';
12546aa735ceSAmir Ayupov       }
1255a34c753fSRafael Auler       if (uint64_t Offset = Address - TargetFunction->getAddress())
1256a34c753fSRafael Auler         TargetFunction->addEntryPointAtOffset(Offset);
1257a34c753fSRafael Auler 
1258a34c753fSRafael Auler       continue;
1259a34c753fSRafael Auler     }
1260a34c753fSRafael Auler 
1261a34c753fSRafael Auler     // Check if address falls in function padding space - this could be
1262a34c753fSRafael Auler     // unmarked data in code. In this case adjust the padding space size.
1263a34c753fSRafael Auler     ErrorOr<BinarySection &> Section = getSectionForAddress(Address);
1264a34c753fSRafael Auler     assert(Section && "cannot get section for referenced address");
1265a34c753fSRafael Auler 
1266a34c753fSRafael Auler     if (!Section->isText())
1267a34c753fSRafael Auler       continue;
1268a34c753fSRafael Auler 
1269a34c753fSRafael Auler     // PLT requires special handling and could be ignored in this context.
1270a34c753fSRafael Auler     StringRef SectionName = Section->getName();
1271a34c753fSRafael Auler     if (SectionName == ".plt" || SectionName == ".plt.got")
1272a34c753fSRafael Auler       continue;
1273a34c753fSRafael Auler 
127435efe1d8SVladislav Khmelevsky     // Check if it is aarch64 veneer written at Address
127535efe1d8SVladislav Khmelevsky     if (isAArch64() && handleAArch64Veneer(Address))
127635efe1d8SVladislav Khmelevsky       continue;
127735efe1d8SVladislav Khmelevsky 
1278a34c753fSRafael Auler     if (opts::processAllFunctions()) {
1279a34c753fSRafael Auler       errs() << "BOLT-ERROR: cannot process binaries with unmarked "
128040c2e0faSMaksim Panchenko              << "object in code at address 0x" << Twine::utohexstr(Address)
128140c2e0faSMaksim Panchenko              << " belonging to section " << SectionName << " in current mode\n";
1282a34c753fSRafael Auler       exit(1);
1283a34c753fSRafael Auler     }
1284a34c753fSRafael Auler 
128540c2e0faSMaksim Panchenko     TargetFunction = getBinaryFunctionContainingAddress(Address,
1286a34c753fSRafael Auler                                                         /*CheckPastEnd=*/false,
1287a34c753fSRafael Auler                                                         /*UseMaxSize=*/true);
1288a34c753fSRafael Auler     // We are not going to overwrite non-simple functions, but for simple
1289a34c753fSRafael Auler     // ones - adjust the padding size.
1290a34c753fSRafael Auler     if (TargetFunction && TargetFunction->isSimple()) {
1291a34c753fSRafael Auler       errs() << "BOLT-WARNING: function " << *TargetFunction
1292a34c753fSRafael Auler              << " has an object detected in a padding region at address 0x"
1293a34c753fSRafael Auler              << Twine::utohexstr(Address) << '\n';
1294a34c753fSRafael Auler       TargetFunction->setMaxSize(TargetFunction->getSize());
1295a34c753fSRafael Auler     }
1296a34c753fSRafael Auler   }
1297a34c753fSRafael Auler 
129835efe1d8SVladislav Khmelevsky   InterproceduralReferences.clear();
1299a34c753fSRafael Auler }
1300a34c753fSRafael Auler 
postProcessSymbolTable()1301a34c753fSRafael Auler void BinaryContext::postProcessSymbolTable() {
1302a34c753fSRafael Auler   fixBinaryDataHoles();
1303a34c753fSRafael Auler   bool Valid = true;
1304a34c753fSRafael Auler   for (auto &Entry : BinaryDataMap) {
1305a34c753fSRafael Auler     BinaryData *BD = Entry.second;
1306a34c753fSRafael Auler     if ((BD->getName().startswith("SYMBOLat") ||
1307a34c753fSRafael Auler          BD->getName().startswith("DATAat")) &&
130840c2e0faSMaksim Panchenko         !BD->getParent() && !BD->getSize() && !BD->isAbsolute() &&
1309a34c753fSRafael Auler         BD->getSection()) {
1310a34c753fSRafael Auler       errs() << "BOLT-WARNING: zero-sized top level symbol: " << *BD << "\n";
1311a34c753fSRafael Auler       Valid = false;
1312a34c753fSRafael Auler     }
1313a34c753fSRafael Auler   }
1314a34c753fSRafael Auler   assert(Valid);
1315c907d6e0SAmir Ayupov   (void)Valid;
1316a34c753fSRafael Auler   generateSymbolHashes();
1317a34c753fSRafael Auler }
1318a34c753fSRafael Auler 
foldFunction(BinaryFunction & ChildBF,BinaryFunction & ParentBF)1319a34c753fSRafael Auler void BinaryContext::foldFunction(BinaryFunction &ChildBF,
1320a34c753fSRafael Auler                                  BinaryFunction &ParentBF) {
1321a34c753fSRafael Auler   assert(!ChildBF.isMultiEntry() && !ParentBF.isMultiEntry() &&
1322a34c753fSRafael Auler          "cannot merge functions with multiple entry points");
1323a34c753fSRafael Auler 
1324a34c753fSRafael Auler   std::unique_lock<std::shared_timed_mutex> WriteCtxLock(CtxMutex,
1325a34c753fSRafael Auler                                                          std::defer_lock);
1326a34c753fSRafael Auler   std::unique_lock<std::shared_timed_mutex> WriteSymbolMapLock(
1327a34c753fSRafael Auler       SymbolToFunctionMapMutex, std::defer_lock);
1328a34c753fSRafael Auler 
1329a34c753fSRafael Auler   const StringRef ChildName = ChildBF.getOneName();
1330a34c753fSRafael Auler 
1331a34c753fSRafael Auler   // Move symbols over and update bookkeeping info.
1332a34c753fSRafael Auler   for (MCSymbol *Symbol : ChildBF.getSymbols()) {
1333a34c753fSRafael Auler     ParentBF.getSymbols().push_back(Symbol);
1334a34c753fSRafael Auler     WriteSymbolMapLock.lock();
1335a34c753fSRafael Auler     SymbolToFunctionMap[Symbol] = &ParentBF;
1336a34c753fSRafael Auler     WriteSymbolMapLock.unlock();
1337a34c753fSRafael Auler     // NB: there's no need to update BinaryDataMap and GlobalSymbols.
1338a34c753fSRafael Auler   }
1339a34c753fSRafael Auler   ChildBF.getSymbols().clear();
1340a34c753fSRafael Auler 
1341a34c753fSRafael Auler   // Move other names the child function is known under.
1342d2c87699SAmir Ayupov   llvm::move(ChildBF.Aliases, std::back_inserter(ParentBF.Aliases));
1343a34c753fSRafael Auler   ChildBF.Aliases.clear();
1344a34c753fSRafael Auler 
1345a34c753fSRafael Auler   if (HasRelocations) {
1346a34c753fSRafael Auler     // Merge execution counts of ChildBF into those of ParentBF.
1347a34c753fSRafael Auler     // Without relocations, we cannot reliably merge profiles as both functions
1348a34c753fSRafael Auler     // continue to exist and either one can be executed.
1349a34c753fSRafael Auler     ChildBF.mergeProfileDataInto(ParentBF);
1350a34c753fSRafael Auler 
1351a34c753fSRafael Auler     std::shared_lock<std::shared_timed_mutex> ReadBfsLock(BinaryFunctionsMutex,
1352a34c753fSRafael Auler                                                           std::defer_lock);
1353a34c753fSRafael Auler     std::unique_lock<std::shared_timed_mutex> WriteBfsLock(BinaryFunctionsMutex,
1354a34c753fSRafael Auler                                                            std::defer_lock);
1355a34c753fSRafael Auler     // Remove ChildBF from the global set of functions in relocs mode.
1356a34c753fSRafael Auler     ReadBfsLock.lock();
1357a34c753fSRafael Auler     auto FI = BinaryFunctions.find(ChildBF.getAddress());
1358a34c753fSRafael Auler     ReadBfsLock.unlock();
1359a34c753fSRafael Auler 
1360a34c753fSRafael Auler     assert(FI != BinaryFunctions.end() && "function not found");
1361a34c753fSRafael Auler     assert(&ChildBF == &FI->second && "function mismatch");
1362a34c753fSRafael Auler 
1363a34c753fSRafael Auler     WriteBfsLock.lock();
1364a34c753fSRafael Auler     ChildBF.clearDisasmState();
1365a34c753fSRafael Auler     FI = BinaryFunctions.erase(FI);
1366a34c753fSRafael Auler     WriteBfsLock.unlock();
1367a34c753fSRafael Auler 
1368a34c753fSRafael Auler   } else {
1369a34c753fSRafael Auler     // In non-relocation mode we keep the function, but rename it.
1370a34c753fSRafael Auler     std::string NewName = "__ICF_" + ChildName.str();
1371a34c753fSRafael Auler 
1372a34c753fSRafael Auler     WriteCtxLock.lock();
1373a34c753fSRafael Auler     ChildBF.getSymbols().push_back(Ctx->getOrCreateSymbol(NewName));
1374a34c753fSRafael Auler     WriteCtxLock.unlock();
1375a34c753fSRafael Auler 
1376a34c753fSRafael Auler     ChildBF.setFolded(&ParentBF);
1377a34c753fSRafael Auler   }
1378a34c753fSRafael Auler }
1379a34c753fSRafael Auler 
fixBinaryDataHoles()1380a34c753fSRafael Auler void BinaryContext::fixBinaryDataHoles() {
1381a34c753fSRafael Auler   assert(validateObjectNesting() && "object nesting inconsitency detected");
1382a34c753fSRafael Auler 
1383a34c753fSRafael Auler   for (BinarySection &Section : allocatableSections()) {
1384a34c753fSRafael Auler     std::vector<std::pair<uint64_t, uint64_t>> Holes;
1385a34c753fSRafael Auler 
1386a34c753fSRafael Auler     auto isNotHole = [&Section](const binary_data_iterator &Itr) {
1387a34c753fSRafael Auler       BinaryData *BD = Itr->second;
138840c2e0faSMaksim Panchenko       bool isHole = (!BD->getParent() && !BD->getSize() && BD->isObject() &&
1389a34c753fSRafael Auler                      (BD->getName().startswith("SYMBOLat0x") ||
1390a34c753fSRafael Auler                       BD->getName().startswith("DATAat0x") ||
1391a34c753fSRafael Auler                       BD->getName().startswith("ANONYMOUS")));
1392a34c753fSRafael Auler       return !isHole && BD->getSection() == Section && !BD->getParent();
1393a34c753fSRafael Auler     };
1394a34c753fSRafael Auler 
1395a34c753fSRafael Auler     auto BDStart = BinaryDataMap.begin();
1396a34c753fSRafael Auler     auto BDEnd = BinaryDataMap.end();
1397a34c753fSRafael Auler     auto Itr = FilteredBinaryDataIterator(isNotHole, BDStart, BDEnd);
1398a34c753fSRafael Auler     auto End = FilteredBinaryDataIterator(isNotHole, BDEnd, BDEnd);
1399a34c753fSRafael Auler 
1400a34c753fSRafael Auler     uint64_t EndAddress = Section.getAddress();
1401a34c753fSRafael Auler 
1402a34c753fSRafael Auler     while (Itr != End) {
1403a34c753fSRafael Auler       if (Itr->second->getAddress() > EndAddress) {
1404a34c753fSRafael Auler         uint64_t Gap = Itr->second->getAddress() - EndAddress;
1405a34c753fSRafael Auler         Holes.emplace_back(EndAddress, Gap);
1406a34c753fSRafael Auler       }
1407a34c753fSRafael Auler       EndAddress = Itr->second->getEndAddress();
1408a34c753fSRafael Auler       ++Itr;
1409a34c753fSRafael Auler     }
1410a34c753fSRafael Auler 
14113652483cSRafael Auler     if (EndAddress < Section.getEndAddress())
1412a34c753fSRafael Auler       Holes.emplace_back(EndAddress, Section.getEndAddress() - EndAddress);
1413a34c753fSRafael Auler 
1414a34c753fSRafael Auler     // If there is already a symbol at the start of the hole, grow that symbol
1415a34c753fSRafael Auler     // to cover the rest.  Otherwise, create a new symbol to cover the hole.
1416a34c753fSRafael Auler     for (std::pair<uint64_t, uint64_t> &Hole : Holes) {
1417a34c753fSRafael Auler       BinaryData *BD = getBinaryDataAtAddress(Hole.first);
1418a34c753fSRafael Auler       if (BD) {
1419a34c753fSRafael Auler         // BD->getSection() can be != Section if there are sections that
1420a34c753fSRafael Auler         // overlap.  In this case it is probably safe to just skip the holes
1421a34c753fSRafael Auler         // since the overlapping section will not(?) have any symbols in it.
1422a34c753fSRafael Auler         if (BD->getSection() == Section)
1423a34c753fSRafael Auler           setBinaryDataSize(Hole.first, Hole.second);
1424a34c753fSRafael Auler       } else {
1425a34c753fSRafael Auler         getOrCreateGlobalSymbol(Hole.first, "HOLEat", Hole.second, 1);
1426a34c753fSRafael Auler       }
1427a34c753fSRafael Auler     }
1428a34c753fSRafael Auler   }
1429a34c753fSRafael Auler 
1430a34c753fSRafael Auler   assert(validateObjectNesting() && "object nesting inconsitency detected");
1431a34c753fSRafael Auler   assert(validateHoles() && "top level hole detected in object map");
1432a34c753fSRafael Auler }
1433a34c753fSRafael Auler 
printGlobalSymbols(raw_ostream & OS) const1434a34c753fSRafael Auler void BinaryContext::printGlobalSymbols(raw_ostream &OS) const {
1435a34c753fSRafael Auler   const BinarySection *CurrentSection = nullptr;
1436a34c753fSRafael Auler   bool FirstSection = true;
1437a34c753fSRafael Auler 
1438a34c753fSRafael Auler   for (auto &Entry : BinaryDataMap) {
1439a34c753fSRafael Auler     const BinaryData *BD = Entry.second;
1440a34c753fSRafael Auler     const BinarySection &Section = BD->getSection();
1441a34c753fSRafael Auler     if (FirstSection || Section != *CurrentSection) {
1442a34c753fSRafael Auler       uint64_t Address, Size;
1443a34c753fSRafael Auler       StringRef Name = Section.getName();
1444a34c753fSRafael Auler       if (Section) {
1445a34c753fSRafael Auler         Address = Section.getAddress();
1446a34c753fSRafael Auler         Size = Section.getSize();
1447a34c753fSRafael Auler       } else {
1448a34c753fSRafael Auler         Address = BD->getAddress();
1449a34c753fSRafael Auler         Size = BD->getSize();
1450a34c753fSRafael Auler       }
1451a34c753fSRafael Auler       OS << "BOLT-INFO: Section " << Name << ", "
1452a34c753fSRafael Auler          << "0x" + Twine::utohexstr(Address) << ":"
145340c2e0faSMaksim Panchenko          << "0x" + Twine::utohexstr(Address + Size) << "/" << Size << "\n";
1454a34c753fSRafael Auler       CurrentSection = &Section;
1455a34c753fSRafael Auler       FirstSection = false;
1456a34c753fSRafael Auler     }
1457a34c753fSRafael Auler 
1458a34c753fSRafael Auler     OS << "BOLT-INFO: ";
1459a34c753fSRafael Auler     const BinaryData *P = BD->getParent();
1460a34c753fSRafael Auler     while (P) {
1461a34c753fSRafael Auler       OS << "  ";
1462a34c753fSRafael Auler       P = P->getParent();
1463a34c753fSRafael Auler     }
1464a34c753fSRafael Auler     OS << *BD << "\n";
1465a34c753fSRafael Auler   }
1466a34c753fSRafael Auler }
1467a34c753fSRafael Auler 
getDwarfFile(StringRef Directory,StringRef FileName,unsigned FileNumber,Optional<MD5::MD5Result> Checksum,Optional<StringRef> Source,unsigned CUID,unsigned DWARFVersion)1468014cd37fSAlexander Yermolovich Expected<unsigned> BinaryContext::getDwarfFile(
1469014cd37fSAlexander Yermolovich     StringRef Directory, StringRef FileName, unsigned FileNumber,
1470014cd37fSAlexander Yermolovich     Optional<MD5::MD5Result> Checksum, Optional<StringRef> Source,
1471014cd37fSAlexander Yermolovich     unsigned CUID, unsigned DWARFVersion) {
1472a34c753fSRafael Auler   DwarfLineTable &Table = DwarfLineTablesCUMap[CUID];
1473014cd37fSAlexander Yermolovich   return Table.tryGetFile(Directory, FileName, Checksum, Source, DWARFVersion,
1474014cd37fSAlexander Yermolovich                           FileNumber);
1475a34c753fSRafael Auler }
1476a34c753fSRafael Auler 
addDebugFilenameToUnit(const uint32_t DestCUID,const uint32_t SrcCUID,unsigned FileIndex)1477a34c753fSRafael Auler unsigned BinaryContext::addDebugFilenameToUnit(const uint32_t DestCUID,
1478a34c753fSRafael Auler                                                const uint32_t SrcCUID,
1479a34c753fSRafael Auler                                                unsigned FileIndex) {
1480a34c753fSRafael Auler   DWARFCompileUnit *SrcUnit = DwCtx->getCompileUnitForOffset(SrcCUID);
1481a34c753fSRafael Auler   const DWARFDebugLine::LineTable *LineTable =
1482a34c753fSRafael Auler       DwCtx->getLineTableForUnit(SrcUnit);
1483a34c753fSRafael Auler   const std::vector<DWARFDebugLine::FileNameEntry> &FileNames =
1484a34c753fSRafael Auler       LineTable->Prologue.FileNames;
1485a34c753fSRafael Auler   // Dir indexes start at 1, as DWARF file numbers, and a dir index 0
1486a34c753fSRafael Auler   // means empty dir.
1487a34c753fSRafael Auler   assert(FileIndex > 0 && FileIndex <= FileNames.size() &&
1488a34c753fSRafael Auler          "FileIndex out of range for the compilation unit.");
1489a34c753fSRafael Auler   StringRef Dir = "";
1490a34c753fSRafael Auler   if (FileNames[FileIndex - 1].DirIdx != 0) {
1491a34c753fSRafael Auler     if (Optional<const char *> DirName = dwarf::toString(
1492a34c753fSRafael Auler             LineTable->Prologue
1493a34c753fSRafael Auler                 .IncludeDirectories[FileNames[FileIndex - 1].DirIdx - 1])) {
1494a34c753fSRafael Auler       Dir = *DirName;
1495a34c753fSRafael Auler     }
1496a34c753fSRafael Auler   }
1497a34c753fSRafael Auler   StringRef FileName = "";
1498a34c753fSRafael Auler   if (Optional<const char *> FName =
1499a34c753fSRafael Auler           dwarf::toString(FileNames[FileIndex - 1].Name))
1500a34c753fSRafael Auler     FileName = *FName;
1501a34c753fSRafael Auler   assert(FileName != "");
1502014cd37fSAlexander Yermolovich   DWARFCompileUnit *DstUnit = DwCtx->getCompileUnitForOffset(DestCUID);
1503014cd37fSAlexander Yermolovich   return cantFail(getDwarfFile(Dir, FileName, 0, None, None, DestCUID,
1504014cd37fSAlexander Yermolovich                                DstUnit->getVersion()));
1505a34c753fSRafael Auler }
1506a34c753fSRafael Auler 
getSortedFunctions()1507a34c753fSRafael Auler std::vector<BinaryFunction *> BinaryContext::getSortedFunctions() {
1508a34c753fSRafael Auler   std::vector<BinaryFunction *> SortedFunctions(BinaryFunctions.size());
1509d2c87699SAmir Ayupov   llvm::transform(BinaryFunctions, SortedFunctions.begin(),
1510a34c753fSRafael Auler                   [](std::pair<const uint64_t, BinaryFunction> &BFI) {
1511a34c753fSRafael Auler                     return &BFI.second;
1512a34c753fSRafael Auler                   });
1513a34c753fSRafael Auler 
1514d2c87699SAmir Ayupov   llvm::stable_sort(SortedFunctions,
1515a34c753fSRafael Auler                     [](const BinaryFunction *A, const BinaryFunction *B) {
1516a34c753fSRafael Auler                       if (A->hasValidIndex() && B->hasValidIndex()) {
1517a34c753fSRafael Auler                         return A->getIndex() < B->getIndex();
1518a34c753fSRafael Auler                       }
1519a34c753fSRafael Auler                       return A->hasValidIndex();
1520a34c753fSRafael Auler                     });
1521a34c753fSRafael Auler   return SortedFunctions;
1522a34c753fSRafael Auler }
1523a34c753fSRafael Auler 
getAllBinaryFunctions()1524a34c753fSRafael Auler std::vector<BinaryFunction *> BinaryContext::getAllBinaryFunctions() {
1525a34c753fSRafael Auler   std::vector<BinaryFunction *> AllFunctions;
1526a34c753fSRafael Auler   AllFunctions.reserve(BinaryFunctions.size() + InjectedBinaryFunctions.size());
1527d2c87699SAmir Ayupov   llvm::transform(BinaryFunctions, std::back_inserter(AllFunctions),
1528a34c753fSRafael Auler                   [](std::pair<const uint64_t, BinaryFunction> &BFI) {
1529a34c753fSRafael Auler                     return &BFI.second;
1530a34c753fSRafael Auler                   });
1531d2c87699SAmir Ayupov   llvm::copy(InjectedBinaryFunctions, std::back_inserter(AllFunctions));
1532a34c753fSRafael Auler 
1533a34c753fSRafael Auler   return AllFunctions;
1534a34c753fSRafael Auler }
1535a34c753fSRafael Auler 
getDWOCU(uint64_t DWOId)1536a34c753fSRafael Auler Optional<DWARFUnit *> BinaryContext::getDWOCU(uint64_t DWOId) {
1537a34c753fSRafael Auler   auto Iter = DWOCUs.find(DWOId);
1538a34c753fSRafael Auler   if (Iter == DWOCUs.end())
1539a34c753fSRafael Auler     return None;
1540a34c753fSRafael Auler 
1541a34c753fSRafael Auler   return Iter->second;
1542a34c753fSRafael Auler }
1543a34c753fSRafael Auler 
getDWOContext() const15447dee646bSAmir Ayupov DWARFContext *BinaryContext::getDWOContext() const {
1545a34c753fSRafael Auler   if (DWOCUs.empty())
1546a34c753fSRafael Auler     return nullptr;
1547a34c753fSRafael Auler   return &DWOCUs.begin()->second->getContext();
1548a34c753fSRafael Auler }
1549a34c753fSRafael Auler 
1550a34c753fSRafael Auler /// Handles DWO sections that can either be in .o, .dwo or .dwp files.
preprocessDWODebugInfo()1551a34c753fSRafael Auler void BinaryContext::preprocessDWODebugInfo() {
1552a34c753fSRafael Auler   for (const std::unique_ptr<DWARFUnit> &CU : DwCtx->compile_units()) {
1553a34c753fSRafael Auler     DWARFUnit *const DwarfUnit = CU.get();
1554a34c753fSRafael Auler     if (llvm::Optional<uint64_t> DWOId = DwarfUnit->getDWOId()) {
1555a34c753fSRafael Auler       DWARFUnit *DWOCU = DwarfUnit->getNonSkeletonUnitDIE(false).getDwarfUnit();
1556a34c753fSRafael Auler       if (!DWOCU->isDWOUnit()) {
1557a34c753fSRafael Auler         std::string DWOName = dwarf::toString(
1558a34c753fSRafael Auler             DwarfUnit->getUnitDIE().find(
1559a34c753fSRafael Auler                 {dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}),
1560a34c753fSRafael Auler             "");
1561a34c753fSRafael Auler         outs() << "BOLT-WARNING: Debug Fission: DWO debug information for "
1562a34c753fSRafael Auler                << DWOName
1563a34c753fSRafael Auler                << " was not retrieved and won't be updated. Please check "
1564a34c753fSRafael Auler                   "relative path.\n";
1565a34c753fSRafael Auler         continue;
1566a34c753fSRafael Auler       }
1567a34c753fSRafael Auler       DWOCUs[*DWOId] = DWOCU;
1568a34c753fSRafael Auler     }
1569a34c753fSRafael Auler   }
1570a34c753fSRafael Auler }
1571a34c753fSRafael Auler 
preprocessDebugInfo()1572a34c753fSRafael Auler void BinaryContext::preprocessDebugInfo() {
1573a34c753fSRafael Auler   struct CURange {
1574a34c753fSRafael Auler     uint64_t LowPC;
1575a34c753fSRafael Auler     uint64_t HighPC;
1576a34c753fSRafael Auler     DWARFUnit *Unit;
1577a34c753fSRafael Auler 
157840c2e0faSMaksim Panchenko     bool operator<(const CURange &Other) const { return LowPC < Other.LowPC; }
1579a34c753fSRafael Auler   };
1580a34c753fSRafael Auler 
1581a34c753fSRafael Auler   // Building a map of address ranges to CUs similar to .debug_aranges and use
1582a34c753fSRafael Auler   // it to assign CU to functions.
1583a34c753fSRafael Auler   std::vector<CURange> AllRanges;
1584a34c753fSRafael Auler   AllRanges.reserve(DwCtx->getNumCompileUnits());
1585a34c753fSRafael Auler   for (const std::unique_ptr<DWARFUnit> &CU : DwCtx->compile_units()) {
1586a34c753fSRafael Auler     Expected<DWARFAddressRangesVector> RangesOrError =
1587a34c753fSRafael Auler         CU->getUnitDIE().getAddressRanges();
1588a34c753fSRafael Auler     if (!RangesOrError) {
1589a34c753fSRafael Auler       consumeError(RangesOrError.takeError());
1590a34c753fSRafael Auler       continue;
1591a34c753fSRafael Auler     }
1592a34c753fSRafael Auler     for (DWARFAddressRange &Range : *RangesOrError) {
1593a34c753fSRafael Auler       // Parts of the debug info could be invalidated due to corresponding code
1594a34c753fSRafael Auler       // being removed from the binary by the linker. Hence we check if the
1595a34c753fSRafael Auler       // address is a valid one.
1596a34c753fSRafael Auler       if (containsAddress(Range.LowPC))
1597a34c753fSRafael Auler         AllRanges.emplace_back(CURange{Range.LowPC, Range.HighPC, CU.get()});
1598a34c753fSRafael Auler     }
1599014cd37fSAlexander Yermolovich 
1600014cd37fSAlexander Yermolovich     ContainsDwarf5 |= CU->getVersion() >= 5;
1601014cd37fSAlexander Yermolovich     ContainsDwarfLegacy |= CU->getVersion() < 5;
1602a34c753fSRafael Auler   }
1603a34c753fSRafael Auler 
1604d2c87699SAmir Ayupov   llvm::sort(AllRanges);
1605a34c753fSRafael Auler   for (auto &KV : BinaryFunctions) {
1606a34c753fSRafael Auler     const uint64_t FunctionAddress = KV.first;
1607a34c753fSRafael Auler     BinaryFunction &Function = KV.second;
1608a34c753fSRafael Auler 
1609d2c87699SAmir Ayupov     auto It = llvm::partition_point(
1610d2c87699SAmir Ayupov         AllRanges, [=](CURange R) { return R.HighPC <= FunctionAddress; });
1611d2c87699SAmir Ayupov     if (It != AllRanges.end() && It->LowPC <= FunctionAddress)
1612a34c753fSRafael Auler       Function.setDWARFUnit(It->Unit);
1613a34c753fSRafael Auler   }
1614a34c753fSRafael Auler 
1615a34c753fSRafael Auler   // Discover units with debug info that needs to be updated.
1616a34c753fSRafael Auler   for (const auto &KV : BinaryFunctions) {
1617a34c753fSRafael Auler     const BinaryFunction &BF = KV.second;
1618a34c753fSRafael Auler     if (shouldEmit(BF) && BF.getDWARFUnit())
1619a34c753fSRafael Auler       ProcessedCUs.insert(BF.getDWARFUnit());
1620a34c753fSRafael Auler   }
1621a34c753fSRafael Auler 
1622a34c753fSRafael Auler   // Clear debug info for functions from units that we are not going to process.
1623a34c753fSRafael Auler   for (auto &KV : BinaryFunctions) {
1624a34c753fSRafael Auler     BinaryFunction &BF = KV.second;
1625a34c753fSRafael Auler     if (BF.getDWARFUnit() && !ProcessedCUs.count(BF.getDWARFUnit()))
1626a34c753fSRafael Auler       BF.setDWARFUnit(nullptr);
1627a34c753fSRafael Auler   }
1628a34c753fSRafael Auler 
1629a34c753fSRafael Auler   if (opts::Verbosity >= 1) {
1630a34c753fSRafael Auler     outs() << "BOLT-INFO: " << ProcessedCUs.size() << " out of "
1631a34c753fSRafael Auler            << DwCtx->getNumCompileUnits() << " CUs will be updated\n";
1632a34c753fSRafael Auler   }
1633a34c753fSRafael Auler 
1634ba1ac98cSAlexander Yermolovich   preprocessDWODebugInfo();
1635ba1ac98cSAlexander Yermolovich 
1636a34c753fSRafael Auler   // Populate MCContext with DWARF files from all units.
1637a34c753fSRafael Auler   StringRef GlobalPrefix = AsmInfo->getPrivateGlobalPrefix();
1638a34c753fSRafael Auler   for (const std::unique_ptr<DWARFUnit> &CU : DwCtx->compile_units()) {
1639a34c753fSRafael Auler     const uint64_t CUID = CU->getOffset();
1640014cd37fSAlexander Yermolovich     DwarfLineTable &BinaryLineTable = getDwarfLineTable(CUID);
1641014cd37fSAlexander Yermolovich     BinaryLineTable.setLabel(Ctx->getOrCreateSymbol(
1642a34c753fSRafael Auler         GlobalPrefix + "line_table_start" + Twine(CUID)));
1643a34c753fSRafael Auler 
1644a34c753fSRafael Auler     if (!ProcessedCUs.count(CU.get()))
1645a34c753fSRafael Auler       continue;
1646a34c753fSRafael Auler 
1647a34c753fSRafael Auler     const DWARFDebugLine::LineTable *LineTable =
1648a34c753fSRafael Auler         DwCtx->getLineTableForUnit(CU.get());
1649a34c753fSRafael Auler     const std::vector<DWARFDebugLine::FileNameEntry> &FileNames =
1650a34c753fSRafael Auler         LineTable->Prologue.FileNames;
1651a34c753fSRafael Auler 
1652014cd37fSAlexander Yermolovich     uint16_t DwarfVersion = LineTable->Prologue.getVersion();
1653014cd37fSAlexander Yermolovich     if (DwarfVersion >= 5) {
1654014cd37fSAlexander Yermolovich       Optional<MD5::MD5Result> Checksum = None;
1655014cd37fSAlexander Yermolovich       if (LineTable->Prologue.ContentTypes.HasMD5)
1656014cd37fSAlexander Yermolovich         Checksum = LineTable->Prologue.FileNames[0].Checksum;
1657ba1ac98cSAlexander Yermolovich       Optional<const char *> Name =
1658ba1ac98cSAlexander Yermolovich           dwarf::toString(CU->getUnitDIE().find(dwarf::DW_AT_name), nullptr);
1659ba1ac98cSAlexander Yermolovich       if (Optional<uint64_t> DWOID = CU->getDWOId()) {
1660ba1ac98cSAlexander Yermolovich         auto Iter = DWOCUs.find(*DWOID);
1661ba1ac98cSAlexander Yermolovich         assert(Iter != DWOCUs.end() && "DWO CU was not found.");
1662ba1ac98cSAlexander Yermolovich         Name = dwarf::toString(
1663ba1ac98cSAlexander Yermolovich             Iter->second->getUnitDIE().find(dwarf::DW_AT_name), nullptr);
1664ba1ac98cSAlexander Yermolovich       }
1665ba1ac98cSAlexander Yermolovich       BinaryLineTable.setRootFile(CU->getCompilationDir(), *Name, Checksum,
1666ba1ac98cSAlexander Yermolovich                                   None);
1667014cd37fSAlexander Yermolovich     }
1668014cd37fSAlexander Yermolovich 
1669014cd37fSAlexander Yermolovich     BinaryLineTable.setDwarfVersion(DwarfVersion);
1670014cd37fSAlexander Yermolovich 
1671a34c753fSRafael Auler     // Assign a unique label to every line table, one per CU.
1672a34c753fSRafael Auler     // Make sure empty debug line tables are registered too.
1673a34c753fSRafael Auler     if (FileNames.empty()) {
1674014cd37fSAlexander Yermolovich       cantFail(
1675014cd37fSAlexander Yermolovich           getDwarfFile("", "<unknown>", 0, None, None, CUID, DwarfVersion));
1676a34c753fSRafael Auler       continue;
1677a34c753fSRafael Auler     }
1678014cd37fSAlexander Yermolovich     const uint32_t Offset = DwarfVersion < 5 ? 1 : 0;
1679a34c753fSRafael Auler     for (size_t I = 0, Size = FileNames.size(); I != Size; ++I) {
1680a34c753fSRafael Auler       // Dir indexes start at 1, as DWARF file numbers, and a dir index 0
1681a34c753fSRafael Auler       // means empty dir.
1682a34c753fSRafael Auler       StringRef Dir = "";
1683014cd37fSAlexander Yermolovich       if (FileNames[I].DirIdx != 0 || DwarfVersion >= 5)
1684a34c753fSRafael Auler         if (Optional<const char *> DirName = dwarf::toString(
1685a34c753fSRafael Auler                 LineTable->Prologue
1686014cd37fSAlexander Yermolovich                     .IncludeDirectories[FileNames[I].DirIdx - Offset]))
1687a34c753fSRafael Auler           Dir = *DirName;
1688a34c753fSRafael Auler       StringRef FileName = "";
1689a34c753fSRafael Auler       if (Optional<const char *> FName = dwarf::toString(FileNames[I].Name))
1690a34c753fSRafael Auler         FileName = *FName;
1691a34c753fSRafael Auler       assert(FileName != "");
1692014cd37fSAlexander Yermolovich       Optional<MD5::MD5Result> Checksum = None;
1693014cd37fSAlexander Yermolovich       if (DwarfVersion >= 5 && LineTable->Prologue.ContentTypes.HasMD5)
1694014cd37fSAlexander Yermolovich         Checksum = LineTable->Prologue.FileNames[I].Checksum;
1695014cd37fSAlexander Yermolovich       cantFail(
1696014cd37fSAlexander Yermolovich           getDwarfFile(Dir, FileName, 0, Checksum, None, CUID, DwarfVersion));
1697a34c753fSRafael Auler     }
1698a34c753fSRafael Auler   }
1699a34c753fSRafael Auler }
1700a34c753fSRafael Auler 
shouldEmit(const BinaryFunction & Function) const1701a34c753fSRafael Auler bool BinaryContext::shouldEmit(const BinaryFunction &Function) const {
17024c14519eSVladislav Khmelevsky   if (Function.isPseudo())
17034c14519eSVladislav Khmelevsky     return false;
17044c14519eSVladislav Khmelevsky 
1705a34c753fSRafael Auler   if (opts::processAllFunctions())
1706a34c753fSRafael Auler     return true;
1707a34c753fSRafael Auler 
1708a34c753fSRafael Auler   if (Function.isIgnored())
1709a34c753fSRafael Auler     return false;
1710a34c753fSRafael Auler 
1711a34c753fSRafael Auler   // In relocation mode we will emit non-simple functions with CFG.
1712a34c753fSRafael Auler   // If the function does not have a CFG it should be marked as ignored.
1713a34c753fSRafael Auler   return HasRelocations || Function.isSimple();
1714a34c753fSRafael Auler }
1715a34c753fSRafael Auler 
printCFI(raw_ostream & OS,const MCCFIInstruction & Inst)1716a34c753fSRafael Auler void BinaryContext::printCFI(raw_ostream &OS, const MCCFIInstruction &Inst) {
1717a34c753fSRafael Auler   uint32_t Operation = Inst.getOperation();
1718a34c753fSRafael Auler   switch (Operation) {
1719a34c753fSRafael Auler   case MCCFIInstruction::OpSameValue:
1720a34c753fSRafael Auler     OS << "OpSameValue Reg" << Inst.getRegister();
1721a34c753fSRafael Auler     break;
1722a34c753fSRafael Auler   case MCCFIInstruction::OpRememberState:
1723a34c753fSRafael Auler     OS << "OpRememberState";
1724a34c753fSRafael Auler     break;
1725a34c753fSRafael Auler   case MCCFIInstruction::OpRestoreState:
1726a34c753fSRafael Auler     OS << "OpRestoreState";
1727a34c753fSRafael Auler     break;
1728a34c753fSRafael Auler   case MCCFIInstruction::OpOffset:
1729a34c753fSRafael Auler     OS << "OpOffset Reg" << Inst.getRegister() << " " << Inst.getOffset();
1730a34c753fSRafael Auler     break;
1731a34c753fSRafael Auler   case MCCFIInstruction::OpDefCfaRegister:
1732a34c753fSRafael Auler     OS << "OpDefCfaRegister Reg" << Inst.getRegister();
1733a34c753fSRafael Auler     break;
1734a34c753fSRafael Auler   case MCCFIInstruction::OpDefCfaOffset:
1735a34c753fSRafael Auler     OS << "OpDefCfaOffset " << Inst.getOffset();
1736a34c753fSRafael Auler     break;
1737a34c753fSRafael Auler   case MCCFIInstruction::OpDefCfa:
1738a34c753fSRafael Auler     OS << "OpDefCfa Reg" << Inst.getRegister() << " " << Inst.getOffset();
1739a34c753fSRafael Auler     break;
1740a34c753fSRafael Auler   case MCCFIInstruction::OpRelOffset:
1741a34c753fSRafael Auler     OS << "OpRelOffset Reg" << Inst.getRegister() << " " << Inst.getOffset();
1742a34c753fSRafael Auler     break;
1743a34c753fSRafael Auler   case MCCFIInstruction::OpAdjustCfaOffset:
1744a34c753fSRafael Auler     OS << "OfAdjustCfaOffset " << Inst.getOffset();
1745a34c753fSRafael Auler     break;
1746a34c753fSRafael Auler   case MCCFIInstruction::OpEscape:
1747a34c753fSRafael Auler     OS << "OpEscape";
1748a34c753fSRafael Auler     break;
1749a34c753fSRafael Auler   case MCCFIInstruction::OpRestore:
1750a34c753fSRafael Auler     OS << "OpRestore Reg" << Inst.getRegister();
1751a34c753fSRafael Auler     break;
1752a34c753fSRafael Auler   case MCCFIInstruction::OpUndefined:
1753a34c753fSRafael Auler     OS << "OpUndefined Reg" << Inst.getRegister();
1754a34c753fSRafael Auler     break;
1755a34c753fSRafael Auler   case MCCFIInstruction::OpRegister:
1756a34c753fSRafael Auler     OS << "OpRegister Reg" << Inst.getRegister() << " Reg"
1757a34c753fSRafael Auler        << Inst.getRegister2();
1758a34c753fSRafael Auler     break;
1759a34c753fSRafael Auler   case MCCFIInstruction::OpWindowSave:
1760a34c753fSRafael Auler     OS << "OpWindowSave";
1761a34c753fSRafael Auler     break;
1762a34c753fSRafael Auler   case MCCFIInstruction::OpGnuArgsSize:
1763a34c753fSRafael Auler     OS << "OpGnuArgsSize";
1764a34c753fSRafael Auler     break;
1765a34c753fSRafael Auler   default:
1766a34c753fSRafael Auler     OS << "Op#" << Operation;
1767a34c753fSRafael Auler     break;
1768a34c753fSRafael Auler   }
1769a34c753fSRafael Auler }
1770a34c753fSRafael Auler 
getMarkerType(const SymbolRef & Symbol) const17718579db96SDenis Revunov MarkerSymType BinaryContext::getMarkerType(const SymbolRef &Symbol) const {
17728579db96SDenis Revunov   // For aarch64, the ABI defines mapping symbols so we identify data in the
17738579db96SDenis Revunov   // code section (see IHI0056B). $x identifies a symbol starting code or the
17748579db96SDenis Revunov   // end of a data chunk inside code, $d indentifies start of data.
17758579db96SDenis Revunov   if (!isAArch64() || ELFSymbolRef(Symbol).getSize())
17768579db96SDenis Revunov     return MarkerSymType::NONE;
17778579db96SDenis Revunov 
17788579db96SDenis Revunov   Expected<StringRef> NameOrError = Symbol.getName();
17798579db96SDenis Revunov   Expected<object::SymbolRef::Type> TypeOrError = Symbol.getType();
17808579db96SDenis Revunov 
17818579db96SDenis Revunov   if (!TypeOrError || !NameOrError)
17828579db96SDenis Revunov     return MarkerSymType::NONE;
17838579db96SDenis Revunov 
17848579db96SDenis Revunov   if (*TypeOrError != SymbolRef::ST_Unknown)
17858579db96SDenis Revunov     return MarkerSymType::NONE;
17868579db96SDenis Revunov 
17878579db96SDenis Revunov   if (*NameOrError == "$x" || NameOrError->startswith("$x."))
17888579db96SDenis Revunov     return MarkerSymType::CODE;
17898579db96SDenis Revunov 
17908579db96SDenis Revunov   if (*NameOrError == "$d" || NameOrError->startswith("$d."))
17918579db96SDenis Revunov     return MarkerSymType::DATA;
17928579db96SDenis Revunov 
17938579db96SDenis Revunov   return MarkerSymType::NONE;
17948579db96SDenis Revunov }
17958579db96SDenis Revunov 
isMarker(const SymbolRef & Symbol) const17968579db96SDenis Revunov bool BinaryContext::isMarker(const SymbolRef &Symbol) const {
17978579db96SDenis Revunov   return getMarkerType(Symbol) != MarkerSymType::NONE;
17988579db96SDenis Revunov }
17998579db96SDenis Revunov 
printDebugInfo(raw_ostream & OS,const MCInst & Instruction,const BinaryFunction * Function,DWARFContext * DwCtx)18007dee646bSAmir Ayupov static void printDebugInfo(raw_ostream &OS, const MCInst &Instruction,
18017dee646bSAmir Ayupov                            const BinaryFunction *Function,
18027dee646bSAmir Ayupov                            DWARFContext *DwCtx) {
18037dee646bSAmir Ayupov   DebugLineTableRowRef RowRef =
18047dee646bSAmir Ayupov       DebugLineTableRowRef::fromSMLoc(Instruction.getLoc());
18057dee646bSAmir Ayupov   if (RowRef == DebugLineTableRowRef::NULL_ROW)
18067dee646bSAmir Ayupov     return;
18077dee646bSAmir Ayupov 
18087dee646bSAmir Ayupov   const DWARFDebugLine::LineTable *LineTable;
18097dee646bSAmir Ayupov   if (Function && Function->getDWARFUnit() &&
18107dee646bSAmir Ayupov       Function->getDWARFUnit()->getOffset() == RowRef.DwCompileUnitIndex) {
18117dee646bSAmir Ayupov     LineTable = Function->getDWARFLineTable();
18127dee646bSAmir Ayupov   } else {
18137dee646bSAmir Ayupov     LineTable = DwCtx->getLineTableForUnit(
18147dee646bSAmir Ayupov         DwCtx->getCompileUnitForOffset(RowRef.DwCompileUnitIndex));
18157dee646bSAmir Ayupov   }
18167dee646bSAmir Ayupov   assert(LineTable && "line table expected for instruction with debug info");
18177dee646bSAmir Ayupov 
18187dee646bSAmir Ayupov   const DWARFDebugLine::Row &Row = LineTable->Rows[RowRef.RowIndex - 1];
18197dee646bSAmir Ayupov   StringRef FileName = "";
18207dee646bSAmir Ayupov   if (Optional<const char *> FName =
18217dee646bSAmir Ayupov           dwarf::toString(LineTable->Prologue.FileNames[Row.File - 1].Name))
18227dee646bSAmir Ayupov     FileName = *FName;
18237dee646bSAmir Ayupov   OS << " # debug line " << FileName << ":" << Row.Line;
18247dee646bSAmir Ayupov   if (Row.Column)
18257dee646bSAmir Ayupov     OS << ":" << Row.Column;
18267dee646bSAmir Ayupov   if (Row.Discriminator)
18277dee646bSAmir Ayupov     OS << " discriminator:" << Row.Discriminator;
18287dee646bSAmir Ayupov }
18297dee646bSAmir Ayupov 
printInstruction(raw_ostream & OS,const MCInst & Instruction,uint64_t Offset,const BinaryFunction * Function,bool PrintMCInst,bool PrintMemData,bool PrintRelocations,StringRef Endl) const183040c2e0faSMaksim Panchenko void BinaryContext::printInstruction(raw_ostream &OS, const MCInst &Instruction,
1831a34c753fSRafael Auler                                      uint64_t Offset,
1832a34c753fSRafael Auler                                      const BinaryFunction *Function,
183340c2e0faSMaksim Panchenko                                      bool PrintMCInst, bool PrintMemData,
183469f87b6cSAmir Ayupov                                      bool PrintRelocations,
183569f87b6cSAmir Ayupov                                      StringRef Endl) const {
1836a34c753fSRafael Auler   if (MIB->isEHLabel(Instruction)) {
183769f87b6cSAmir Ayupov     OS << "  EH_LABEL: " << *MIB->getTargetSymbol(Instruction) << Endl;
1838a34c753fSRafael Auler     return;
1839a34c753fSRafael Auler   }
1840a34c753fSRafael Auler   OS << format("    %08" PRIx64 ": ", Offset);
1841a34c753fSRafael Auler   if (MIB->isCFI(Instruction)) {
1842a34c753fSRafael Auler     uint32_t Offset = Instruction.getOperand(0).getImm();
1843a34c753fSRafael Auler     OS << "\t!CFI\t$" << Offset << "\t; ";
1844a34c753fSRafael Auler     if (Function)
1845a34c753fSRafael Auler       printCFI(OS, *Function->getCFIFor(Instruction));
184669f87b6cSAmir Ayupov     OS << Endl;
1847a34c753fSRafael Auler     return;
1848a34c753fSRafael Auler   }
1849a34c753fSRafael Auler   InstPrinter->printInst(&Instruction, 0, "", *STI, OS);
1850a34c753fSRafael Auler   if (MIB->isCall(Instruction)) {
1851a34c753fSRafael Auler     if (MIB->isTailCall(Instruction))
1852a34c753fSRafael Auler       OS << " # TAILCALL ";
1853a34c753fSRafael Auler     if (MIB->isInvoke(Instruction)) {
1854a34c753fSRafael Auler       const Optional<MCPlus::MCLandingPad> EHInfo = MIB->getEHInfo(Instruction);
1855a34c753fSRafael Auler       OS << " # handler: ";
1856a34c753fSRafael Auler       if (EHInfo->first)
1857a34c753fSRafael Auler         OS << *EHInfo->first;
1858a34c753fSRafael Auler       else
1859a34c753fSRafael Auler         OS << '0';
1860a34c753fSRafael Auler       OS << "; action: " << EHInfo->second;
1861a34c753fSRafael Auler       const int64_t GnuArgsSize = MIB->getGnuArgsSize(Instruction);
1862a34c753fSRafael Auler       if (GnuArgsSize >= 0)
1863a34c753fSRafael Auler         OS << "; GNU_args_size = " << GnuArgsSize;
1864a34c753fSRafael Auler     }
1865a34c753fSRafael Auler   } else if (MIB->isIndirectBranch(Instruction)) {
1866a34c753fSRafael Auler     if (uint64_t JTAddress = MIB->getJumpTable(Instruction)) {
1867a34c753fSRafael Auler       OS << " # JUMPTABLE @0x" << Twine::utohexstr(JTAddress);
1868a34c753fSRafael Auler     } else {
1869a34c753fSRafael Auler       OS << " # UNKNOWN CONTROL FLOW";
1870a34c753fSRafael Auler     }
1871a34c753fSRafael Auler   }
1872a9cd49d5SAmir Ayupov   if (Optional<uint32_t> Offset = MIB->getOffset(Instruction))
1873a9cd49d5SAmir Ayupov     OS << " # Offset: " << *Offset;
1874a34c753fSRafael Auler 
1875a34c753fSRafael Auler   MIB->printAnnotations(Instruction, OS);
1876a34c753fSRafael Auler 
18777dee646bSAmir Ayupov   if (opts::PrintDebugInfo)
18787dee646bSAmir Ayupov     printDebugInfo(OS, Instruction, Function, DwCtx.get());
1879a34c753fSRafael Auler 
1880a34c753fSRafael Auler   if ((opts::PrintRelocations || PrintRelocations) && Function) {
1881a34c753fSRafael Auler     const uint64_t Size = computeCodeSize(&Instruction, &Instruction + 1);
1882a34c753fSRafael Auler     Function->printRelocations(OS, Offset, Size);
1883a34c753fSRafael Auler   }
1884a34c753fSRafael Auler 
188569f87b6cSAmir Ayupov   OS << Endl;
1886a34c753fSRafael Auler 
1887a34c753fSRafael Auler   if (PrintMCInst) {
1888a34c753fSRafael Auler     Instruction.dump_pretty(OS, InstPrinter.get());
188969f87b6cSAmir Ayupov     OS << Endl;
1890a34c753fSRafael Auler   }
1891a34c753fSRafael Auler }
1892a34c753fSRafael Auler 
189377b75ca5SMaksim Panchenko Optional<uint64_t>
getBaseAddressForMapping(uint64_t MMapAddress,uint64_t FileOffset) const189477b75ca5SMaksim Panchenko BinaryContext::getBaseAddressForMapping(uint64_t MMapAddress,
189577b75ca5SMaksim Panchenko                                         uint64_t FileOffset) const {
189677b75ca5SMaksim Panchenko   // Find a segment with a matching file offset.
189777b75ca5SMaksim Panchenko   for (auto &KV : SegmentMapInfo) {
189877b75ca5SMaksim Panchenko     const SegmentInfo &SegInfo = KV.second;
189977b75ca5SMaksim Panchenko     if (alignDown(SegInfo.FileOffset, SegInfo.Alignment) == FileOffset) {
190077b75ca5SMaksim Panchenko       // Use segment's aligned memory offset to calculate the base address.
190177b75ca5SMaksim Panchenko       const uint64_t MemOffset = alignDown(SegInfo.Address, SegInfo.Alignment);
190277b75ca5SMaksim Panchenko       return MMapAddress - MemOffset;
190377b75ca5SMaksim Panchenko     }
190477b75ca5SMaksim Panchenko   }
190577b75ca5SMaksim Panchenko 
190677b75ca5SMaksim Panchenko   return NoneType();
190777b75ca5SMaksim Panchenko }
190877b75ca5SMaksim Panchenko 
getSectionForAddress(uint64_t Address)1909a34c753fSRafael Auler ErrorOr<BinarySection &> BinaryContext::getSectionForAddress(uint64_t Address) {
1910a34c753fSRafael Auler   auto SI = AddressToSection.upper_bound(Address);
1911a34c753fSRafael Auler   if (SI != AddressToSection.begin()) {
1912a34c753fSRafael Auler     --SI;
1913a34c753fSRafael Auler     uint64_t UpperBound = SI->first + SI->second->getSize();
1914a34c753fSRafael Auler     if (!SI->second->getSize())
1915a34c753fSRafael Auler       UpperBound += 1;
1916a34c753fSRafael Auler     if (UpperBound > Address)
1917a34c753fSRafael Auler       return *SI->second;
1918a34c753fSRafael Auler   }
1919a34c753fSRafael Auler   return std::make_error_code(std::errc::bad_address);
1920a34c753fSRafael Auler }
1921a34c753fSRafael Auler 
1922a34c753fSRafael Auler ErrorOr<StringRef>
getSectionNameForAddress(uint64_t Address) const1923a34c753fSRafael Auler BinaryContext::getSectionNameForAddress(uint64_t Address) const {
19243652483cSRafael Auler   if (ErrorOr<const BinarySection &> Section = getSectionForAddress(Address))
1925a34c753fSRafael Auler     return Section->getName();
1926a34c753fSRafael Auler   return std::make_error_code(std::errc::bad_address);
1927a34c753fSRafael Auler }
1928a34c753fSRafael Auler 
registerSection(BinarySection * Section)1929a34c753fSRafael Auler BinarySection &BinaryContext::registerSection(BinarySection *Section) {
1930a34c753fSRafael Auler   auto Res = Sections.insert(Section);
1931a34c753fSRafael Auler   (void)Res;
1932a34c753fSRafael Auler   assert(Res.second && "can't register the same section twice.");
1933a34c753fSRafael Auler 
1934a34c753fSRafael Auler   // Only register allocatable sections in the AddressToSection map.
1935a34c753fSRafael Auler   if (Section->isAllocatable() && Section->getAddress())
1936a34c753fSRafael Auler     AddressToSection.insert(std::make_pair(Section->getAddress(), Section));
1937a34c753fSRafael Auler   NameToSection.insert(
1938a34c753fSRafael Auler       std::make_pair(std::string(Section->getName()), Section));
1939a34c753fSRafael Auler   LLVM_DEBUG(dbgs() << "BOLT-DEBUG: registering " << *Section << "\n");
1940a34c753fSRafael Auler   return *Section;
1941a34c753fSRafael Auler }
1942a34c753fSRafael Auler 
registerSection(SectionRef Section)1943a34c753fSRafael Auler BinarySection &BinaryContext::registerSection(SectionRef Section) {
1944a34c753fSRafael Auler   return registerSection(new BinarySection(*this, Section));
1945a34c753fSRafael Auler }
1946a34c753fSRafael Auler 
1947a34c753fSRafael Auler BinarySection &
registerSection(StringRef SectionName,const BinarySection & OriginalSection)1948a34c753fSRafael Auler BinaryContext::registerSection(StringRef SectionName,
1949a34c753fSRafael Auler                                const BinarySection &OriginalSection) {
195040c2e0faSMaksim Panchenko   return registerSection(
195140c2e0faSMaksim Panchenko       new BinarySection(*this, SectionName, OriginalSection));
1952a34c753fSRafael Auler }
1953a34c753fSRafael Auler 
195440c2e0faSMaksim Panchenko BinarySection &
registerOrUpdateSection(StringRef Name,unsigned ELFType,unsigned ELFFlags,uint8_t * Data,uint64_t Size,unsigned Alignment)195540c2e0faSMaksim Panchenko BinaryContext::registerOrUpdateSection(StringRef Name, unsigned ELFType,
195640c2e0faSMaksim Panchenko                                        unsigned ELFFlags, uint8_t *Data,
195740c2e0faSMaksim Panchenko                                        uint64_t Size, unsigned Alignment) {
1958a34c753fSRafael Auler   auto NamedSections = getSectionByName(Name);
1959a34c753fSRafael Auler   if (NamedSections.begin() != NamedSections.end()) {
1960a34c753fSRafael Auler     assert(std::next(NamedSections.begin()) == NamedSections.end() &&
1961a34c753fSRafael Auler            "can only update unique sections");
1962a34c753fSRafael Auler     BinarySection *Section = NamedSections.begin()->second;
1963a34c753fSRafael Auler 
1964a34c753fSRafael Auler     LLVM_DEBUG(dbgs() << "BOLT-DEBUG: updating " << *Section << " -> ");
1965a34c753fSRafael Auler     const bool Flag = Section->isAllocatable();
1966a34c753fSRafael Auler     (void)Flag;
1967a34c753fSRafael Auler     Section->update(Data, Size, Alignment, ELFType, ELFFlags);
1968a34c753fSRafael Auler     LLVM_DEBUG(dbgs() << *Section << "\n");
1969a34c753fSRafael Auler     // FIXME: Fix section flags/attributes for MachO.
1970a34c753fSRafael Auler     if (isELF())
1971a34c753fSRafael Auler       assert(Flag == Section->isAllocatable() &&
1972a34c753fSRafael Auler              "can't change section allocation status");
1973a34c753fSRafael Auler     return *Section;
1974a34c753fSRafael Auler   }
1975a34c753fSRafael Auler 
197640c2e0faSMaksim Panchenko   return registerSection(
197740c2e0faSMaksim Panchenko       new BinarySection(*this, Name, Data, Size, Alignment, ELFType, ELFFlags));
1978a34c753fSRafael Auler }
1979a34c753fSRafael Auler 
deregisterSection(BinarySection & Section)1980a34c753fSRafael Auler bool BinaryContext::deregisterSection(BinarySection &Section) {
1981a34c753fSRafael Auler   BinarySection *SectionPtr = &Section;
1982a34c753fSRafael Auler   auto Itr = Sections.find(SectionPtr);
1983a34c753fSRafael Auler   if (Itr != Sections.end()) {
1984a34c753fSRafael Auler     auto Range = AddressToSection.equal_range(SectionPtr->getAddress());
1985a34c753fSRafael Auler     while (Range.first != Range.second) {
1986a34c753fSRafael Auler       if (Range.first->second == SectionPtr) {
1987a34c753fSRafael Auler         AddressToSection.erase(Range.first);
1988a34c753fSRafael Auler         break;
1989a34c753fSRafael Auler       }
1990a34c753fSRafael Auler       ++Range.first;
1991a34c753fSRafael Auler     }
1992a34c753fSRafael Auler 
1993a34c753fSRafael Auler     auto NameRange =
1994a34c753fSRafael Auler         NameToSection.equal_range(std::string(SectionPtr->getName()));
1995a34c753fSRafael Auler     while (NameRange.first != NameRange.second) {
1996a34c753fSRafael Auler       if (NameRange.first->second == SectionPtr) {
1997a34c753fSRafael Auler         NameToSection.erase(NameRange.first);
1998a34c753fSRafael Auler         break;
1999a34c753fSRafael Auler       }
2000a34c753fSRafael Auler       ++NameRange.first;
2001a34c753fSRafael Auler     }
2002a34c753fSRafael Auler 
2003a34c753fSRafael Auler     Sections.erase(Itr);
2004a34c753fSRafael Auler     delete SectionPtr;
2005a34c753fSRafael Auler     return true;
2006a34c753fSRafael Auler   }
2007a34c753fSRafael Auler   return false;
2008a34c753fSRafael Auler }
2009a34c753fSRafael Auler 
printSections(raw_ostream & OS) const2010a34c753fSRafael Auler void BinaryContext::printSections(raw_ostream &OS) const {
20113652483cSRafael Auler   for (BinarySection *const &Section : Sections)
2012a34c753fSRafael Auler     OS << "BOLT-INFO: " << *Section << "\n";
2013a34c753fSRafael Auler }
2014a34c753fSRafael Auler 
absoluteSection()2015a34c753fSRafael Auler BinarySection &BinaryContext::absoluteSection() {
2016a34c753fSRafael Auler   if (ErrorOr<BinarySection &> Section = getUniqueSectionByName("<absolute>"))
2017a34c753fSRafael Auler     return *Section;
2018a34c753fSRafael Auler   return registerOrUpdateSection("<absolute>", ELF::SHT_NULL, 0u);
2019a34c753fSRafael Auler }
2020a34c753fSRafael Auler 
getUnsignedValueAtAddress(uint64_t Address,size_t Size) const202140c2e0faSMaksim Panchenko ErrorOr<uint64_t> BinaryContext::getUnsignedValueAtAddress(uint64_t Address,
2022a34c753fSRafael Auler                                                            size_t Size) const {
2023a34c753fSRafael Auler   const ErrorOr<const BinarySection &> Section = getSectionForAddress(Address);
2024a34c753fSRafael Auler   if (!Section)
2025a34c753fSRafael Auler     return std::make_error_code(std::errc::bad_address);
2026a34c753fSRafael Auler 
2027a34c753fSRafael Auler   if (Section->isVirtual())
2028a34c753fSRafael Auler     return 0;
2029a34c753fSRafael Auler 
2030a34c753fSRafael Auler   DataExtractor DE(Section->getContents(), AsmInfo->isLittleEndian(),
2031a34c753fSRafael Auler                    AsmInfo->getCodePointerSize());
2032a34c753fSRafael Auler   auto ValueOffset = static_cast<uint64_t>(Address - Section->getAddress());
2033a34c753fSRafael Auler   return DE.getUnsigned(&ValueOffset, Size);
2034a34c753fSRafael Auler }
2035a34c753fSRafael Auler 
getSignedValueAtAddress(uint64_t Address,size_t Size) const203640c2e0faSMaksim Panchenko ErrorOr<uint64_t> BinaryContext::getSignedValueAtAddress(uint64_t Address,
2037a34c753fSRafael Auler                                                          size_t Size) const {
2038a34c753fSRafael Auler   const ErrorOr<const BinarySection &> Section = getSectionForAddress(Address);
2039a34c753fSRafael Auler   if (!Section)
2040a34c753fSRafael Auler     return std::make_error_code(std::errc::bad_address);
2041a34c753fSRafael Auler 
2042a34c753fSRafael Auler   if (Section->isVirtual())
2043a34c753fSRafael Auler     return 0;
2044a34c753fSRafael Auler 
2045a34c753fSRafael Auler   DataExtractor DE(Section->getContents(), AsmInfo->isLittleEndian(),
2046a34c753fSRafael Auler                    AsmInfo->getCodePointerSize());
2047a34c753fSRafael Auler   auto ValueOffset = static_cast<uint64_t>(Address - Section->getAddress());
2048a34c753fSRafael Auler   return DE.getSigned(&ValueOffset, Size);
2049a34c753fSRafael Auler }
2050a34c753fSRafael Auler 
addRelocation(uint64_t Address,MCSymbol * Symbol,uint64_t Type,uint64_t Addend,uint64_t Value)205140c2e0faSMaksim Panchenko void BinaryContext::addRelocation(uint64_t Address, MCSymbol *Symbol,
205240c2e0faSMaksim Panchenko                                   uint64_t Type, uint64_t Addend,
2053a34c753fSRafael Auler                                   uint64_t Value) {
2054a34c753fSRafael Auler   ErrorOr<BinarySection &> Section = getSectionForAddress(Address);
2055a34c753fSRafael Auler   assert(Section && "cannot find section for address");
205640c2e0faSMaksim Panchenko   Section->addRelocation(Address - Section->getAddress(), Symbol, Type, Addend,
2057a34c753fSRafael Auler                          Value);
2058a34c753fSRafael Auler }
2059a34c753fSRafael Auler 
addDynamicRelocation(uint64_t Address,MCSymbol * Symbol,uint64_t Type,uint64_t Addend,uint64_t Value)206040c2e0faSMaksim Panchenko void BinaryContext::addDynamicRelocation(uint64_t Address, MCSymbol *Symbol,
206140c2e0faSMaksim Panchenko                                          uint64_t Type, uint64_t Addend,
2062a34c753fSRafael Auler                                          uint64_t Value) {
2063a34c753fSRafael Auler   ErrorOr<BinarySection &> Section = getSectionForAddress(Address);
2064a34c753fSRafael Auler   assert(Section && "cannot find section for address");
206540c2e0faSMaksim Panchenko   Section->addDynamicRelocation(Address - Section->getAddress(), Symbol, Type,
206640c2e0faSMaksim Panchenko                                 Addend, Value);
2067a34c753fSRafael Auler }
2068a34c753fSRafael Auler 
removeRelocationAt(uint64_t Address)2069a34c753fSRafael Auler bool BinaryContext::removeRelocationAt(uint64_t Address) {
2070a34c753fSRafael Auler   ErrorOr<BinarySection &> Section = getSectionForAddress(Address);
2071a34c753fSRafael Auler   assert(Section && "cannot find section for address");
2072a34c753fSRafael Auler   return Section->removeRelocationAt(Address - Section->getAddress());
2073a34c753fSRafael Auler }
2074a34c753fSRafael Auler 
getRelocationAt(uint64_t Address)2075a34c753fSRafael Auler const Relocation *BinaryContext::getRelocationAt(uint64_t Address) {
2076a34c753fSRafael Auler   ErrorOr<BinarySection &> Section = getSectionForAddress(Address);
2077a34c753fSRafael Auler   if (!Section)
2078a34c753fSRafael Auler     return nullptr;
2079a34c753fSRafael Auler 
2080a34c753fSRafael Auler   return Section->getRelocationAt(Address - Section->getAddress());
2081a34c753fSRafael Auler }
2082a34c753fSRafael Auler 
getDynamicRelocationAt(uint64_t Address)2083a34c753fSRafael Auler const Relocation *BinaryContext::getDynamicRelocationAt(uint64_t Address) {
2084a34c753fSRafael Auler   ErrorOr<BinarySection &> Section = getSectionForAddress(Address);
2085a34c753fSRafael Auler   if (!Section)
2086a34c753fSRafael Auler     return nullptr;
2087a34c753fSRafael Auler 
2088a34c753fSRafael Auler   return Section->getDynamicRelocationAt(Address - Section->getAddress());
2089a34c753fSRafael Auler }
2090a34c753fSRafael Auler 
markAmbiguousRelocations(BinaryData & BD,const uint64_t Address)2091a34c753fSRafael Auler void BinaryContext::markAmbiguousRelocations(BinaryData &BD,
2092a34c753fSRafael Auler                                              const uint64_t Address) {
2093a34c753fSRafael Auler   auto setImmovable = [&](BinaryData &BD) {
2094a34c753fSRafael Auler     BinaryData *Root = BD.getAtomicRoot();
2095a34c753fSRafael Auler     LLVM_DEBUG(if (Root->isMoveable()) {
2096a34c753fSRafael Auler       dbgs() << "BOLT-DEBUG: setting " << *Root << " as immovable "
2097a34c753fSRafael Auler              << "due to ambiguous relocation referencing 0x"
2098a34c753fSRafael Auler              << Twine::utohexstr(Address) << '\n';
2099a34c753fSRafael Auler     });
2100a34c753fSRafael Auler     Root->setIsMoveable(false);
2101a34c753fSRafael Auler   };
2102a34c753fSRafael Auler 
2103a34c753fSRafael Auler   if (Address == BD.getAddress()) {
2104a34c753fSRafael Auler     setImmovable(BD);
2105a34c753fSRafael Auler 
2106a34c753fSRafael Auler     // Set previous symbol as immovable
2107a34c753fSRafael Auler     BinaryData *Prev = getBinaryDataContainingAddress(Address - 1);
2108a34c753fSRafael Auler     if (Prev && Prev->getEndAddress() == BD.getAddress())
2109a34c753fSRafael Auler       setImmovable(*Prev);
2110a34c753fSRafael Auler   }
2111a34c753fSRafael Auler 
2112a34c753fSRafael Auler   if (Address == BD.getEndAddress()) {
2113a34c753fSRafael Auler     setImmovable(BD);
2114a34c753fSRafael Auler 
2115a34c753fSRafael Auler     // Set next symbol as immovable
2116a34c753fSRafael Auler     BinaryData *Next = getBinaryDataContainingAddress(BD.getEndAddress());
2117a34c753fSRafael Auler     if (Next && Next->getAddress() == BD.getEndAddress())
2118a34c753fSRafael Auler       setImmovable(*Next);
2119a34c753fSRafael Auler   }
2120a34c753fSRafael Auler }
2121a34c753fSRafael Auler 
getFunctionForSymbol(const MCSymbol * Symbol,uint64_t * EntryDesc)2122a34c753fSRafael Auler BinaryFunction *BinaryContext::getFunctionForSymbol(const MCSymbol *Symbol,
2123a34c753fSRafael Auler                                                     uint64_t *EntryDesc) {
2124a34c753fSRafael Auler   std::shared_lock<std::shared_timed_mutex> Lock(SymbolToFunctionMapMutex);
2125a34c753fSRafael Auler   auto BFI = SymbolToFunctionMap.find(Symbol);
2126a34c753fSRafael Auler   if (BFI == SymbolToFunctionMap.end())
2127a34c753fSRafael Auler     return nullptr;
2128a34c753fSRafael Auler 
2129a34c753fSRafael Auler   BinaryFunction *BF = BFI->second;
2130a34c753fSRafael Auler   if (EntryDesc)
2131a34c753fSRafael Auler     *EntryDesc = BF->getEntryIDForSymbol(Symbol);
2132a34c753fSRafael Auler 
2133a34c753fSRafael Auler   return BF;
2134a34c753fSRafael Auler }
2135a34c753fSRafael Auler 
exitWithBugReport(StringRef Message,const BinaryFunction & Function) const2136a34c753fSRafael Auler void BinaryContext::exitWithBugReport(StringRef Message,
2137a34c753fSRafael Auler                                       const BinaryFunction &Function) const {
2138a34c753fSRafael Auler   errs() << "=======================================\n";
2139a34c753fSRafael Auler   errs() << "BOLT is unable to proceed because it couldn't properly understand "
2140a34c753fSRafael Auler             "this function.\n";
2141a34c753fSRafael Auler   errs() << "If you are running the most recent version of BOLT, you may "
2142a34c753fSRafael Auler             "want to "
2143a34c753fSRafael Auler             "report this and paste this dump.\nPlease check that there is no "
2144a34c753fSRafael Auler             "sensitive contents being shared in this dump.\n";
2145a34c753fSRafael Auler   errs() << "\nOffending function: " << Function.getPrintName() << "\n\n";
2146a34c753fSRafael Auler   ScopedPrinter SP(errs());
2147a34c753fSRafael Auler   SP.printBinaryBlock("Function contents", *Function.getData());
2148a34c753fSRafael Auler   errs() << "\n";
2149a34c753fSRafael Auler   Function.dump();
2150a34c753fSRafael Auler   errs() << "ERROR: " << Message;
2151a34c753fSRafael Auler   errs() << "\n=======================================\n";
2152a34c753fSRafael Auler   exit(1);
2153a34c753fSRafael Auler }
2154a34c753fSRafael Auler 
2155a34c753fSRafael Auler BinaryFunction *
createInjectedBinaryFunction(const std::string & Name,bool IsSimple)2156a34c753fSRafael Auler BinaryContext::createInjectedBinaryFunction(const std::string &Name,
2157a34c753fSRafael Auler                                             bool IsSimple) {
2158a34c753fSRafael Auler   InjectedBinaryFunctions.push_back(new BinaryFunction(Name, *this, IsSimple));
2159a34c753fSRafael Auler   BinaryFunction *BF = InjectedBinaryFunctions.back();
2160a34c753fSRafael Auler   setSymbolToFunctionMap(BF->getSymbol(), BF);
2161a34c753fSRafael Auler   BF->CurrentState = BinaryFunction::State::CFG;
2162a34c753fSRafael Auler   return BF;
2163a34c753fSRafael Auler }
2164a34c753fSRafael Auler 
2165a34c753fSRafael Auler std::pair<size_t, size_t>
calculateEmittedSize(BinaryFunction & BF,bool FixBranches)2166a34c753fSRafael Auler BinaryContext::calculateEmittedSize(BinaryFunction &BF, bool FixBranches) {
2167a34c753fSRafael Auler   // Adjust branch instruction to match the current layout.
2168a34c753fSRafael Auler   if (FixBranches)
2169a34c753fSRafael Auler     BF.fixBranches();
2170a34c753fSRafael Auler 
2171a34c753fSRafael Auler   // Create local MC context to isolate the effect of ephemeral code emission.
2172a34c753fSRafael Auler   IndependentCodeEmitter MCEInstance = createIndependentMCCodeEmitter();
2173a34c753fSRafael Auler   MCContext *LocalCtx = MCEInstance.LocalCtx.get();
2174a34c753fSRafael Auler   MCAsmBackend *MAB =
2175a34c753fSRafael Auler       TheTarget->createMCAsmBackend(*STI, *MRI, MCTargetOptions());
2176a34c753fSRafael Auler 
2177a34c753fSRafael Auler   SmallString<256> Code;
2178a34c753fSRafael Auler   raw_svector_ostream VecOS(Code);
2179a34c753fSRafael Auler 
2180a34c753fSRafael Auler   std::unique_ptr<MCObjectWriter> OW = MAB->createObjectWriter(VecOS);
2181a34c753fSRafael Auler   std::unique_ptr<MCStreamer> Streamer(TheTarget->createMCObjectStreamer(
2182a34c753fSRafael Auler       *TheTriple, *LocalCtx, std::unique_ptr<MCAsmBackend>(MAB), std::move(OW),
2183a34c753fSRafael Auler       std::unique_ptr<MCCodeEmitter>(MCEInstance.MCE.release()), *STI,
2184a34c753fSRafael Auler       /*RelaxAll=*/false,
2185a34c753fSRafael Auler       /*IncrementalLinkerCompatible=*/false,
2186a34c753fSRafael Auler       /*DWARFMustBeAtTheEnd=*/false));
2187a34c753fSRafael Auler 
2188a34c753fSRafael Auler   Streamer->initSections(false, *STI);
2189a34c753fSRafael Auler 
2190a34c753fSRafael Auler   MCSection *Section = MCEInstance.LocalMOFI->getTextSection();
2191a34c753fSRafael Auler   Section->setHasInstructions(true);
2192a34c753fSRafael Auler 
2193a34c753fSRafael Auler   // Create symbols in the LocalCtx so that they get destroyed with it.
2194a34c753fSRafael Auler   MCSymbol *StartLabel = LocalCtx->createTempSymbol();
2195a34c753fSRafael Auler   MCSymbol *EndLabel = LocalCtx->createTempSymbol();
2196a34c753fSRafael Auler   MCSymbol *ColdStartLabel = LocalCtx->createTempSymbol();
2197a34c753fSRafael Auler   MCSymbol *ColdEndLabel = LocalCtx->createTempSymbol();
2198a34c753fSRafael Auler 
2199adf4142fSFangrui Song   Streamer->switchSection(Section);
2200a34c753fSRafael Auler   Streamer->emitLabel(StartLabel);
2201a34c753fSRafael Auler   emitFunctionBody(*Streamer, BF, /*EmitColdPart=*/false,
2202a34c753fSRafael Auler                    /*EmitCodeOnly=*/true);
2203a34c753fSRafael Auler   Streamer->emitLabel(EndLabel);
2204a34c753fSRafael Auler 
2205a34c753fSRafael Auler   if (BF.isSplit()) {
2206a34c753fSRafael Auler     MCSectionELF *ColdSection =
2207a34c753fSRafael Auler         LocalCtx->getELFSection(BF.getColdCodeSectionName(), ELF::SHT_PROGBITS,
2208a34c753fSRafael Auler                                 ELF::SHF_EXECINSTR | ELF::SHF_ALLOC);
2209a34c753fSRafael Auler     ColdSection->setHasInstructions(true);
2210a34c753fSRafael Auler 
2211adf4142fSFangrui Song     Streamer->switchSection(ColdSection);
2212a34c753fSRafael Auler     Streamer->emitLabel(ColdStartLabel);
2213a34c753fSRafael Auler     emitFunctionBody(*Streamer, BF, /*EmitColdPart=*/true,
2214a34c753fSRafael Auler                      /*EmitCodeOnly=*/true);
2215a34c753fSRafael Auler     Streamer->emitLabel(ColdEndLabel);
2216a34c753fSRafael Auler     // To avoid calling MCObjectStreamer::flushPendingLabels() which is private
2217a34c753fSRafael Auler     Streamer->emitBytes(StringRef(""));
2218adf4142fSFangrui Song     Streamer->switchSection(Section);
2219a34c753fSRafael Auler   }
2220a34c753fSRafael Auler 
2221a34c753fSRafael Auler   // To avoid calling MCObjectStreamer::flushPendingLabels() which is private or
2222a34c753fSRafael Auler   // MCStreamer::Finish(), which does more than we want
2223a34c753fSRafael Auler   Streamer->emitBytes(StringRef(""));
2224a34c753fSRafael Auler 
2225a34c753fSRafael Auler   MCAssembler &Assembler =
2226a34c753fSRafael Auler       static_cast<MCObjectStreamer *>(Streamer.get())->getAssembler();
2227a34c753fSRafael Auler   MCAsmLayout Layout(Assembler);
2228a34c753fSRafael Auler   Assembler.layout(Layout);
2229a34c753fSRafael Auler 
2230a34c753fSRafael Auler   const uint64_t HotSize =
2231a34c753fSRafael Auler       Layout.getSymbolOffset(*EndLabel) - Layout.getSymbolOffset(*StartLabel);
2232a34c753fSRafael Auler   const uint64_t ColdSize = BF.isSplit()
2233a34c753fSRafael Auler                                 ? Layout.getSymbolOffset(*ColdEndLabel) -
2234a34c753fSRafael Auler                                       Layout.getSymbolOffset(*ColdStartLabel)
2235a34c753fSRafael Auler                                 : 0ULL;
2236a34c753fSRafael Auler 
2237a34c753fSRafael Auler   // Clean-up the effect of the code emission.
2238a34c753fSRafael Auler   for (const MCSymbol &Symbol : Assembler.symbols()) {
2239a34c753fSRafael Auler     MCSymbol *MutableSymbol = const_cast<MCSymbol *>(&Symbol);
2240a34c753fSRafael Auler     MutableSymbol->setUndefined();
2241a34c753fSRafael Auler     MutableSymbol->setIsRegistered(false);
2242a34c753fSRafael Auler   }
2243a34c753fSRafael Auler 
2244a34c753fSRafael Auler   return std::make_pair(HotSize, ColdSize);
2245a34c753fSRafael Auler }
2246a34c753fSRafael Auler 
validateEncoding(const MCInst & Inst,ArrayRef<uint8_t> InputEncoding) const2247a34c753fSRafael Auler bool BinaryContext::validateEncoding(const MCInst &Inst,
2248a34c753fSRafael Auler                                      ArrayRef<uint8_t> InputEncoding) const {
2249a34c753fSRafael Auler   SmallString<256> Code;
2250a34c753fSRafael Auler   SmallVector<MCFixup, 4> Fixups;
2251a34c753fSRafael Auler   raw_svector_ostream VecOS(Code);
2252a34c753fSRafael Auler 
2253a34c753fSRafael Auler   MCE->encodeInstruction(Inst, VecOS, Fixups, *STI);
2254a34c753fSRafael Auler   auto EncodedData = ArrayRef<uint8_t>((uint8_t *)Code.data(), Code.size());
2255a34c753fSRafael Auler   if (InputEncoding != EncodedData) {
2256a34c753fSRafael Auler     if (opts::Verbosity > 1) {
2257a34c753fSRafael Auler       errs() << "BOLT-WARNING: mismatched encoding detected\n"
2258a34c753fSRafael Auler              << "      input: " << InputEncoding << '\n'
2259a34c753fSRafael Auler              << "     output: " << EncodedData << '\n';
2260a34c753fSRafael Auler     }
2261a34c753fSRafael Auler     return false;
2262a34c753fSRafael Auler   }
2263a34c753fSRafael Auler 
2264a34c753fSRafael Auler   return true;
2265a34c753fSRafael Auler }
2266a34c753fSRafael Auler 
getHotThreshold() const2267a34c753fSRafael Auler uint64_t BinaryContext::getHotThreshold() const {
2268a34c753fSRafael Auler   static uint64_t Threshold = 0;
2269a34c753fSRafael Auler   if (Threshold == 0) {
227040c2e0faSMaksim Panchenko     Threshold = std::max(
227140c2e0faSMaksim Panchenko         (uint64_t)opts::ExecutionCountThreshold,
2272a34c753fSRafael Auler         NumProfiledFuncs ? SumExecutionCount / (2 * NumProfiledFuncs) : 1);
2273a34c753fSRafael Auler   }
2274a34c753fSRafael Auler   return Threshold;
2275a34c753fSRafael Auler }
2276a34c753fSRafael Auler 
getBinaryFunctionContainingAddress(uint64_t Address,bool CheckPastEnd,bool UseMaxSize)227740c2e0faSMaksim Panchenko BinaryFunction *BinaryContext::getBinaryFunctionContainingAddress(
227840c2e0faSMaksim Panchenko     uint64_t Address, bool CheckPastEnd, bool UseMaxSize) {
2279a34c753fSRafael Auler   auto FI = BinaryFunctions.upper_bound(Address);
2280a34c753fSRafael Auler   if (FI == BinaryFunctions.begin())
2281a34c753fSRafael Auler     return nullptr;
2282a34c753fSRafael Auler   --FI;
2283a34c753fSRafael Auler 
2284a34c753fSRafael Auler   const uint64_t UsedSize =
2285a34c753fSRafael Auler       UseMaxSize ? FI->second.getMaxSize() : FI->second.getSize();
2286a34c753fSRafael Auler 
2287a34c753fSRafael Auler   if (Address >= FI->first + UsedSize + (CheckPastEnd ? 1 : 0))
2288a34c753fSRafael Auler     return nullptr;
2289a34c753fSRafael Auler 
2290a34c753fSRafael Auler   return &FI->second;
2291a34c753fSRafael Auler }
2292a34c753fSRafael Auler 
getBinaryFunctionAtAddress(uint64_t Address)229340c2e0faSMaksim Panchenko BinaryFunction *BinaryContext::getBinaryFunctionAtAddress(uint64_t Address) {
2294a34c753fSRafael Auler   // First, try to find a function starting at the given address. If the
2295a34c753fSRafael Auler   // function was folded, this will get us the original folded function if it
2296a34c753fSRafael Auler   // wasn't removed from the list, e.g. in non-relocation mode.
2297a34c753fSRafael Auler   auto BFI = BinaryFunctions.find(Address);
22983652483cSRafael Auler   if (BFI != BinaryFunctions.end())
2299a34c753fSRafael Auler     return &BFI->second;
2300a34c753fSRafael Auler 
2301a34c753fSRafael Auler   // We might have folded the function matching the object at the given
2302a34c753fSRafael Auler   // address. In such case, we look for a function matching the symbol
2303a34c753fSRafael Auler   // registered at the original address. The new function (the one that the
2304a34c753fSRafael Auler   // original was folded into) will hold the symbol.
2305a34c753fSRafael Auler   if (const BinaryData *BD = getBinaryDataAtAddress(Address)) {
2306a34c753fSRafael Auler     uint64_t EntryID = 0;
2307a34c753fSRafael Auler     BinaryFunction *BF = getFunctionForSymbol(BD->getSymbol(), &EntryID);
2308a34c753fSRafael Auler     if (BF && EntryID == 0)
2309a34c753fSRafael Auler       return BF;
2310a34c753fSRafael Auler   }
2311a34c753fSRafael Auler   return nullptr;
2312a34c753fSRafael Auler }
2313a34c753fSRafael Auler 
translateModuleAddressRanges(const DWARFAddressRangesVector & InputRanges) const2314a34c753fSRafael Auler DebugAddressRangesVector BinaryContext::translateModuleAddressRanges(
2315a34c753fSRafael Auler     const DWARFAddressRangesVector &InputRanges) const {
2316a34c753fSRafael Auler   DebugAddressRangesVector OutputRanges;
2317a34c753fSRafael Auler 
2318a34c753fSRafael Auler   for (const DWARFAddressRange Range : InputRanges) {
2319a34c753fSRafael Auler     auto BFI = BinaryFunctions.lower_bound(Range.LowPC);
2320a34c753fSRafael Auler     while (BFI != BinaryFunctions.end()) {
2321a34c753fSRafael Auler       const BinaryFunction &Function = BFI->second;
2322a34c753fSRafael Auler       if (Function.getAddress() >= Range.HighPC)
2323a34c753fSRafael Auler         break;
2324a34c753fSRafael Auler       const DebugAddressRangesVector FunctionRanges =
2325a34c753fSRafael Auler           Function.getOutputAddressRanges();
2326d2c87699SAmir Ayupov       llvm::move(FunctionRanges, std::back_inserter(OutputRanges));
2327a34c753fSRafael Auler       std::advance(BFI, 1);
2328a34c753fSRafael Auler     }
2329a34c753fSRafael Auler   }
2330a34c753fSRafael Auler 
2331a34c753fSRafael Auler   return OutputRanges;
2332a34c753fSRafael Auler }
2333a34c753fSRafael Auler 
2334a34c753fSRafael Auler } // namespace bolt
2335a34c753fSRafael Auler } // namespace llvm
2336