1 //===--- BinaryData.cpp - Representation of section data objects ----------===//
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 //===----------------------------------------------------------------------===//
10 
11 #include "bolt/Core/BinaryData.h"
12 #include "bolt/Core/BinarySection.h"
13 #include "llvm/Support/CommandLine.h"
14 #include "llvm/Support/Regex.h"
15 
16 using namespace llvm;
17 using namespace bolt;
18 
19 #define DEBUG_TYPE "bolt"
20 
21 namespace opts {
22 extern cl::OptionCategory BoltCategory;
23 extern cl::opt<unsigned> Verbosity;
24 
25 cl::opt<bool>
26 PrintSymbolAliases("print-aliases",
27   cl::desc("print aliases when printing objects"),
28   cl::Hidden,
29   cl::ZeroOrMore,
30   cl::cat(BoltCategory));
31 }
32 
33 bool BinaryData::isAbsolute() const { return Flags & SymbolRef::SF_Absolute; }
34 
35 bool BinaryData::isMoveable() const {
36   return (!isAbsolute() && (IsMoveable && (!Parent || isTopLevelJumpTable())));
37 }
38 
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 
51 bool BinaryData::hasName(StringRef Name) const {
52   for (const MCSymbol *Symbol : Symbols) {
53     if (Name == Symbol->getName())
54       return true;
55   }
56   return false;
57 }
58 
59 bool BinaryData::hasNameRegex(StringRef NameRegex) const {
60   Regex MatchName(NameRegex);
61   for (const MCSymbol *Symbol : Symbols) {
62     if (MatchName.match(Symbol->getName()))
63       return true;
64   }
65   return false;
66 }
67 
68 bool BinaryData::nameStartsWith(StringRef Prefix) const {
69   for (const MCSymbol *Symbol : Symbols) {
70     if (Symbol->getName().startswith(Prefix))
71       return true;
72   }
73   return false;
74 }
75 
76 StringRef BinaryData::getSectionName() const { return getSection().getName(); }
77 
78 StringRef BinaryData::getOutputSectionName() const {
79   return getOutputSection().getName();
80 }
81 
82 uint64_t BinaryData::getOutputAddress() const {
83   assert(OutputSection->getOutputAddress());
84   return OutputSection->getOutputAddress() + OutputOffset;
85 }
86 
87 uint64_t BinaryData::getOffset() const {
88   return Address - getSection().getAddress();
89 }
90 
91 void BinaryData::setSection(BinarySection &NewSection) {
92   if (OutputSection == Section)
93     OutputSection = &NewSection;
94   Section = &NewSection;
95 }
96 
97 bool BinaryData::isMoved() const {
98   return (getOffset() != OutputOffset || OutputSection != Section);
99 }
100 
101 void BinaryData::print(raw_ostream &OS) const { printBrief(OS); }
102 
103 void BinaryData::printBrief(raw_ostream &OS) const {
104   OS << "(";
105 
106   if (isJumpTable())
107     OS << "jump-table: ";
108   else
109     OS << "object: ";
110 
111   OS << getName();
112 
113   if ((opts::PrintSymbolAliases || opts::Verbosity > 1) && Symbols.size() > 1) {
114     OS << ", aliases:";
115     for (unsigned I = 1u; I < Symbols.size(); ++I) {
116       OS << (I == 1 ? " (" : ", ") << Symbols[I]->getName();
117     }
118     OS << ")";
119   }
120 
121   if (Parent) {
122     OS << " (parent: ";
123     Parent->printBrief(OS);
124     OS << ")";
125   }
126 
127   OS << ", 0x" << Twine::utohexstr(getAddress()) << ":0x"
128      << Twine::utohexstr(getEndAddress()) << "/" << getSize() << "/"
129      << getAlignment() << "/0x" << Twine::utohexstr(Flags);
130 
131   OS << ")";
132 }
133 
134 BinaryData::BinaryData(MCSymbol &Symbol, uint64_t Address, uint64_t Size,
135                        uint16_t Alignment, BinarySection &Section,
136                        unsigned Flags)
137     : Section(&Section), Address(Address), Size(Size), Alignment(Alignment),
138       Flags(Flags), OutputSection(&Section), OutputOffset(getOffset()) {
139   Symbols.push_back(&Symbol);
140 }
141