1 //===- bolt/Core/BinaryData.cpp - Objects in a binary file ----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the BinaryData class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "bolt/Core/BinaryData.h"
14 #include "bolt/Core/BinarySection.h"
15 #include "llvm/Support/CommandLine.h"
16 #include "llvm/Support/Regex.h"
17 
18 using namespace llvm;
19 using namespace bolt;
20 
21 #define DEBUG_TYPE "bolt"
22 
23 namespace opts {
24 extern cl::OptionCategory BoltCategory;
25 extern cl::opt<unsigned> Verbosity;
26 
27 cl::opt<bool>
28     PrintSymbolAliases("print-aliases",
29                        cl::desc("print aliases when printing objects"),
30                        cl::Hidden, cl::cat(BoltCategory));
31 }
32 
isAbsolute() const33 bool BinaryData::isAbsolute() const { return Flags & SymbolRef::SF_Absolute; }
34 
isMoveable() const35 bool BinaryData::isMoveable() const {
36   return (!isAbsolute() && (IsMoveable && (!Parent || isTopLevelJumpTable())));
37 }
38 
merge(const BinaryData * Other)39 void BinaryData::merge(const BinaryData *Other) {
40   assert(!Size || !Other->Size || Size == Other->Size);
41   assert(Address == Other->Address);
42   assert(*Section == *Other->Section);
43   assert(OutputOffset == Other->OutputOffset);
44   assert(OutputSection == Other->OutputSection);
45   Symbols.insert(Symbols.end(), Other->Symbols.begin(), Other->Symbols.end());
46   Flags |= Other->Flags;
47   if (!Size)
48     Size = Other->Size;
49 }
50 
hasName(StringRef Name) const51 bool BinaryData::hasName(StringRef Name) const {
52   for (const MCSymbol *Symbol : Symbols)
53     if (Name == Symbol->getName())
54       return true;
55   return false;
56 }
57 
hasNameRegex(StringRef NameRegex) const58 bool BinaryData::hasNameRegex(StringRef NameRegex) const {
59   Regex MatchName(NameRegex);
60   for (const MCSymbol *Symbol : Symbols)
61     if (MatchName.match(Symbol->getName()))
62       return true;
63   return false;
64 }
65 
nameStartsWith(StringRef Prefix) const66 bool BinaryData::nameStartsWith(StringRef Prefix) const {
67   for (const MCSymbol *Symbol : Symbols)
68     if (Symbol->getName().startswith(Prefix))
69       return true;
70   return false;
71 }
72 
getSectionName() const73 StringRef BinaryData::getSectionName() const { return getSection().getName(); }
74 
getOutputSectionName() const75 StringRef BinaryData::getOutputSectionName() const {
76   return getOutputSection().getName();
77 }
78 
getOutputAddress() const79 uint64_t BinaryData::getOutputAddress() const {
80   assert(OutputSection->getOutputAddress());
81   return OutputSection->getOutputAddress() + OutputOffset;
82 }
83 
getOffset() const84 uint64_t BinaryData::getOffset() const {
85   return Address - getSection().getAddress();
86 }
87 
setSection(BinarySection & NewSection)88 void BinaryData::setSection(BinarySection &NewSection) {
89   if (OutputSection == Section)
90     OutputSection = &NewSection;
91   Section = &NewSection;
92 }
93 
isMoved() const94 bool BinaryData::isMoved() const {
95   return (getOffset() != OutputOffset || OutputSection != Section);
96 }
97 
print(raw_ostream & OS) const98 void BinaryData::print(raw_ostream &OS) const { printBrief(OS); }
99 
printBrief(raw_ostream & OS) const100 void BinaryData::printBrief(raw_ostream &OS) const {
101   OS << "(";
102 
103   if (isJumpTable())
104     OS << "jump-table: ";
105   else
106     OS << "object: ";
107 
108   OS << getName();
109 
110   if ((opts::PrintSymbolAliases || opts::Verbosity > 1) && Symbols.size() > 1) {
111     OS << ", aliases:";
112     for (unsigned I = 1u; I < Symbols.size(); ++I) {
113       OS << (I == 1 ? " (" : ", ") << Symbols[I]->getName();
114     }
115     OS << ")";
116   }
117 
118   if (Parent) {
119     OS << " (parent: ";
120     Parent->printBrief(OS);
121     OS << ")";
122   }
123 
124   OS << ", 0x" << Twine::utohexstr(getAddress()) << ":0x"
125      << Twine::utohexstr(getEndAddress()) << "/" << getSize() << "/"
126      << getAlignment() << "/0x" << Twine::utohexstr(Flags);
127 
128   OS << ")";
129 }
130 
BinaryData(MCSymbol & Symbol,uint64_t Address,uint64_t Size,uint16_t Alignment,BinarySection & Section,unsigned Flags)131 BinaryData::BinaryData(MCSymbol &Symbol, uint64_t Address, uint64_t Size,
132                        uint16_t Alignment, BinarySection &Section,
133                        unsigned Flags)
134     : Section(&Section), Address(Address), Size(Size), Alignment(Alignment),
135       Flags(Flags), OutputSection(&Section), OutputOffset(getOffset()) {
136   Symbols.push_back(&Symbol);
137 }
138