1*9880d681SAndroid Build Coastguard Worker //===- tools/dsymutil/MachODebugMapParser.cpp - Parse STABS debug maps ----===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Linker
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker
10*9880d681SAndroid Build Coastguard Worker #include "BinaryHolder.h"
11*9880d681SAndroid Build Coastguard Worker #include "DebugMap.h"
12*9880d681SAndroid Build Coastguard Worker #include "dsymutil.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Optional.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/Object/MachO.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Path.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
17*9880d681SAndroid Build Coastguard Worker
18*9880d681SAndroid Build Coastguard Worker namespace {
19*9880d681SAndroid Build Coastguard Worker using namespace llvm;
20*9880d681SAndroid Build Coastguard Worker using namespace llvm::dsymutil;
21*9880d681SAndroid Build Coastguard Worker using namespace llvm::object;
22*9880d681SAndroid Build Coastguard Worker
23*9880d681SAndroid Build Coastguard Worker class MachODebugMapParser {
24*9880d681SAndroid Build Coastguard Worker public:
MachODebugMapParser(StringRef BinaryPath,ArrayRef<std::string> Archs,StringRef PathPrefix="",bool Verbose=false)25*9880d681SAndroid Build Coastguard Worker MachODebugMapParser(StringRef BinaryPath, ArrayRef<std::string> Archs,
26*9880d681SAndroid Build Coastguard Worker StringRef PathPrefix = "", bool Verbose = false)
27*9880d681SAndroid Build Coastguard Worker : BinaryPath(BinaryPath), Archs(Archs.begin(), Archs.end()),
28*9880d681SAndroid Build Coastguard Worker PathPrefix(PathPrefix), MainBinaryHolder(Verbose),
29*9880d681SAndroid Build Coastguard Worker CurrentObjectHolder(Verbose), CurrentDebugMapObject(nullptr) {}
30*9880d681SAndroid Build Coastguard Worker
31*9880d681SAndroid Build Coastguard Worker /// \brief Parses and returns the DebugMaps of the input binary.
32*9880d681SAndroid Build Coastguard Worker /// The binary contains multiple maps in case it is a universal
33*9880d681SAndroid Build Coastguard Worker /// binary.
34*9880d681SAndroid Build Coastguard Worker /// \returns an error in case the provided BinaryPath doesn't exist
35*9880d681SAndroid Build Coastguard Worker /// or isn't of a supported type.
36*9880d681SAndroid Build Coastguard Worker ErrorOr<std::vector<std::unique_ptr<DebugMap>>> parse();
37*9880d681SAndroid Build Coastguard Worker
38*9880d681SAndroid Build Coastguard Worker /// Walk the symbol table and dump it.
39*9880d681SAndroid Build Coastguard Worker bool dumpStab();
40*9880d681SAndroid Build Coastguard Worker
41*9880d681SAndroid Build Coastguard Worker private:
42*9880d681SAndroid Build Coastguard Worker std::string BinaryPath;
43*9880d681SAndroid Build Coastguard Worker SmallVector<StringRef, 1> Archs;
44*9880d681SAndroid Build Coastguard Worker std::string PathPrefix;
45*9880d681SAndroid Build Coastguard Worker
46*9880d681SAndroid Build Coastguard Worker /// Owns the MemoryBuffer for the main binary.
47*9880d681SAndroid Build Coastguard Worker BinaryHolder MainBinaryHolder;
48*9880d681SAndroid Build Coastguard Worker /// Map of the binary symbol addresses.
49*9880d681SAndroid Build Coastguard Worker StringMap<uint64_t> MainBinarySymbolAddresses;
50*9880d681SAndroid Build Coastguard Worker StringRef MainBinaryStrings;
51*9880d681SAndroid Build Coastguard Worker /// The constructed DebugMap.
52*9880d681SAndroid Build Coastguard Worker std::unique_ptr<DebugMap> Result;
53*9880d681SAndroid Build Coastguard Worker
54*9880d681SAndroid Build Coastguard Worker /// Owns the MemoryBuffer for the currently handled object file.
55*9880d681SAndroid Build Coastguard Worker BinaryHolder CurrentObjectHolder;
56*9880d681SAndroid Build Coastguard Worker /// Map of the currently processed object file symbol addresses.
57*9880d681SAndroid Build Coastguard Worker StringMap<Optional<uint64_t>> CurrentObjectAddresses;
58*9880d681SAndroid Build Coastguard Worker /// Element of the debug map corresponfing to the current object file.
59*9880d681SAndroid Build Coastguard Worker DebugMapObject *CurrentDebugMapObject;
60*9880d681SAndroid Build Coastguard Worker
61*9880d681SAndroid Build Coastguard Worker /// Holds function info while function scope processing.
62*9880d681SAndroid Build Coastguard Worker const char *CurrentFunctionName;
63*9880d681SAndroid Build Coastguard Worker uint64_t CurrentFunctionAddress;
64*9880d681SAndroid Build Coastguard Worker
65*9880d681SAndroid Build Coastguard Worker std::unique_ptr<DebugMap> parseOneBinary(const MachOObjectFile &MainBinary,
66*9880d681SAndroid Build Coastguard Worker StringRef BinaryPath);
67*9880d681SAndroid Build Coastguard Worker
68*9880d681SAndroid Build Coastguard Worker void switchToNewDebugMapObject(StringRef Filename, sys::TimeValue Timestamp);
69*9880d681SAndroid Build Coastguard Worker void resetParserState();
70*9880d681SAndroid Build Coastguard Worker uint64_t getMainBinarySymbolAddress(StringRef Name);
71*9880d681SAndroid Build Coastguard Worker void loadMainBinarySymbols(const MachOObjectFile &MainBinary);
72*9880d681SAndroid Build Coastguard Worker void loadCurrentObjectFileSymbols(const object::MachOObjectFile &Obj);
73*9880d681SAndroid Build Coastguard Worker void handleStabSymbolTableEntry(uint32_t StringIndex, uint8_t Type,
74*9880d681SAndroid Build Coastguard Worker uint8_t SectionIndex, uint16_t Flags,
75*9880d681SAndroid Build Coastguard Worker uint64_t Value);
76*9880d681SAndroid Build Coastguard Worker
handleStabDebugMapEntry(const STEType & STE)77*9880d681SAndroid Build Coastguard Worker template <typename STEType> void handleStabDebugMapEntry(const STEType &STE) {
78*9880d681SAndroid Build Coastguard Worker handleStabSymbolTableEntry(STE.n_strx, STE.n_type, STE.n_sect, STE.n_desc,
79*9880d681SAndroid Build Coastguard Worker STE.n_value);
80*9880d681SAndroid Build Coastguard Worker }
81*9880d681SAndroid Build Coastguard Worker
82*9880d681SAndroid Build Coastguard Worker /// Dump the symbol table output header.
83*9880d681SAndroid Build Coastguard Worker void dumpSymTabHeader(raw_ostream &OS, StringRef Arch);
84*9880d681SAndroid Build Coastguard Worker
85*9880d681SAndroid Build Coastguard Worker /// Dump the contents of nlist entries.
86*9880d681SAndroid Build Coastguard Worker void dumpSymTabEntry(raw_ostream &OS, uint64_t Index, uint32_t StringIndex,
87*9880d681SAndroid Build Coastguard Worker uint8_t Type, uint8_t SectionIndex, uint16_t Flags,
88*9880d681SAndroid Build Coastguard Worker uint64_t Value);
89*9880d681SAndroid Build Coastguard Worker
90*9880d681SAndroid Build Coastguard Worker template <typename STEType>
dumpSymTabEntry(raw_ostream & OS,uint64_t Index,const STEType & STE)91*9880d681SAndroid Build Coastguard Worker void dumpSymTabEntry(raw_ostream &OS, uint64_t Index, const STEType &STE) {
92*9880d681SAndroid Build Coastguard Worker dumpSymTabEntry(OS, Index, STE.n_strx, STE.n_type, STE.n_sect, STE.n_desc,
93*9880d681SAndroid Build Coastguard Worker STE.n_value);
94*9880d681SAndroid Build Coastguard Worker }
95*9880d681SAndroid Build Coastguard Worker void dumpOneBinaryStab(const MachOObjectFile &MainBinary,
96*9880d681SAndroid Build Coastguard Worker StringRef BinaryPath);
97*9880d681SAndroid Build Coastguard Worker };
98*9880d681SAndroid Build Coastguard Worker
Warning(const Twine & Msg)99*9880d681SAndroid Build Coastguard Worker static void Warning(const Twine &Msg) { errs() << "warning: " + Msg + "\n"; }
100*9880d681SAndroid Build Coastguard Worker } // anonymous namespace
101*9880d681SAndroid Build Coastguard Worker
102*9880d681SAndroid Build Coastguard Worker /// Reset the parser state coresponding to the current object
103*9880d681SAndroid Build Coastguard Worker /// file. This is to be called after an object file is finished
104*9880d681SAndroid Build Coastguard Worker /// processing.
resetParserState()105*9880d681SAndroid Build Coastguard Worker void MachODebugMapParser::resetParserState() {
106*9880d681SAndroid Build Coastguard Worker CurrentObjectAddresses.clear();
107*9880d681SAndroid Build Coastguard Worker CurrentDebugMapObject = nullptr;
108*9880d681SAndroid Build Coastguard Worker }
109*9880d681SAndroid Build Coastguard Worker
110*9880d681SAndroid Build Coastguard Worker /// Create a new DebugMapObject. This function resets the state of the
111*9880d681SAndroid Build Coastguard Worker /// parser that was referring to the last object file and sets
112*9880d681SAndroid Build Coastguard Worker /// everything up to add symbols to the new one.
switchToNewDebugMapObject(StringRef Filename,sys::TimeValue Timestamp)113*9880d681SAndroid Build Coastguard Worker void MachODebugMapParser::switchToNewDebugMapObject(StringRef Filename,
114*9880d681SAndroid Build Coastguard Worker sys::TimeValue Timestamp) {
115*9880d681SAndroid Build Coastguard Worker resetParserState();
116*9880d681SAndroid Build Coastguard Worker
117*9880d681SAndroid Build Coastguard Worker SmallString<80> Path(PathPrefix);
118*9880d681SAndroid Build Coastguard Worker sys::path::append(Path, Filename);
119*9880d681SAndroid Build Coastguard Worker
120*9880d681SAndroid Build Coastguard Worker auto MachOOrError =
121*9880d681SAndroid Build Coastguard Worker CurrentObjectHolder.GetFilesAs<MachOObjectFile>(Path, Timestamp);
122*9880d681SAndroid Build Coastguard Worker if (auto Error = MachOOrError.getError()) {
123*9880d681SAndroid Build Coastguard Worker Warning(Twine("cannot open debug object \"") + Path.str() + "\": " +
124*9880d681SAndroid Build Coastguard Worker Error.message() + "\n");
125*9880d681SAndroid Build Coastguard Worker return;
126*9880d681SAndroid Build Coastguard Worker }
127*9880d681SAndroid Build Coastguard Worker
128*9880d681SAndroid Build Coastguard Worker auto ErrOrAchObj =
129*9880d681SAndroid Build Coastguard Worker CurrentObjectHolder.GetAs<MachOObjectFile>(Result->getTriple());
130*9880d681SAndroid Build Coastguard Worker if (auto Err = ErrOrAchObj.getError()) {
131*9880d681SAndroid Build Coastguard Worker return Warning(Twine("cannot open debug object \"") + Path.str() + "\": " +
132*9880d681SAndroid Build Coastguard Worker Err.message() + "\n");
133*9880d681SAndroid Build Coastguard Worker }
134*9880d681SAndroid Build Coastguard Worker
135*9880d681SAndroid Build Coastguard Worker CurrentDebugMapObject = &Result->addDebugMapObject(Path, Timestamp);
136*9880d681SAndroid Build Coastguard Worker loadCurrentObjectFileSymbols(*ErrOrAchObj);
137*9880d681SAndroid Build Coastguard Worker }
138*9880d681SAndroid Build Coastguard Worker
getArchName(const object::MachOObjectFile & Obj)139*9880d681SAndroid Build Coastguard Worker static std::string getArchName(const object::MachOObjectFile &Obj) {
140*9880d681SAndroid Build Coastguard Worker Triple T = Obj.getArchTriple();
141*9880d681SAndroid Build Coastguard Worker return T.getArchName();
142*9880d681SAndroid Build Coastguard Worker }
143*9880d681SAndroid Build Coastguard Worker
144*9880d681SAndroid Build Coastguard Worker std::unique_ptr<DebugMap>
parseOneBinary(const MachOObjectFile & MainBinary,StringRef BinaryPath)145*9880d681SAndroid Build Coastguard Worker MachODebugMapParser::parseOneBinary(const MachOObjectFile &MainBinary,
146*9880d681SAndroid Build Coastguard Worker StringRef BinaryPath) {
147*9880d681SAndroid Build Coastguard Worker loadMainBinarySymbols(MainBinary);
148*9880d681SAndroid Build Coastguard Worker Result = make_unique<DebugMap>(MainBinary.getArchTriple(), BinaryPath);
149*9880d681SAndroid Build Coastguard Worker MainBinaryStrings = MainBinary.getStringTableData();
150*9880d681SAndroid Build Coastguard Worker for (const SymbolRef &Symbol : MainBinary.symbols()) {
151*9880d681SAndroid Build Coastguard Worker const DataRefImpl &DRI = Symbol.getRawDataRefImpl();
152*9880d681SAndroid Build Coastguard Worker if (MainBinary.is64Bit())
153*9880d681SAndroid Build Coastguard Worker handleStabDebugMapEntry(MainBinary.getSymbol64TableEntry(DRI));
154*9880d681SAndroid Build Coastguard Worker else
155*9880d681SAndroid Build Coastguard Worker handleStabDebugMapEntry(MainBinary.getSymbolTableEntry(DRI));
156*9880d681SAndroid Build Coastguard Worker }
157*9880d681SAndroid Build Coastguard Worker
158*9880d681SAndroid Build Coastguard Worker resetParserState();
159*9880d681SAndroid Build Coastguard Worker return std::move(Result);
160*9880d681SAndroid Build Coastguard Worker }
161*9880d681SAndroid Build Coastguard Worker
162*9880d681SAndroid Build Coastguard Worker // Table that maps Darwin's Mach-O stab constants to strings to allow printing.
163*9880d681SAndroid Build Coastguard Worker // llvm-nm has very similar code, the strings used here are however slightly
164*9880d681SAndroid Build Coastguard Worker // different and part of the interface of dsymutil (some project's build-systems
165*9880d681SAndroid Build Coastguard Worker // parse the ouptut of dsymutil -s), thus they shouldn't be changed.
166*9880d681SAndroid Build Coastguard Worker struct DarwinStabName {
167*9880d681SAndroid Build Coastguard Worker uint8_t NType;
168*9880d681SAndroid Build Coastguard Worker const char *Name;
169*9880d681SAndroid Build Coastguard Worker };
170*9880d681SAndroid Build Coastguard Worker
171*9880d681SAndroid Build Coastguard Worker static const struct DarwinStabName DarwinStabNames[] = {
172*9880d681SAndroid Build Coastguard Worker {MachO::N_GSYM, "N_GSYM"}, {MachO::N_FNAME, "N_FNAME"},
173*9880d681SAndroid Build Coastguard Worker {MachO::N_FUN, "N_FUN"}, {MachO::N_STSYM, "N_STSYM"},
174*9880d681SAndroid Build Coastguard Worker {MachO::N_LCSYM, "N_LCSYM"}, {MachO::N_BNSYM, "N_BNSYM"},
175*9880d681SAndroid Build Coastguard Worker {MachO::N_PC, "N_PC"}, {MachO::N_AST, "N_AST"},
176*9880d681SAndroid Build Coastguard Worker {MachO::N_OPT, "N_OPT"}, {MachO::N_RSYM, "N_RSYM"},
177*9880d681SAndroid Build Coastguard Worker {MachO::N_SLINE, "N_SLINE"}, {MachO::N_ENSYM, "N_ENSYM"},
178*9880d681SAndroid Build Coastguard Worker {MachO::N_SSYM, "N_SSYM"}, {MachO::N_SO, "N_SO"},
179*9880d681SAndroid Build Coastguard Worker {MachO::N_OSO, "N_OSO"}, {MachO::N_LSYM, "N_LSYM"},
180*9880d681SAndroid Build Coastguard Worker {MachO::N_BINCL, "N_BINCL"}, {MachO::N_SOL, "N_SOL"},
181*9880d681SAndroid Build Coastguard Worker {MachO::N_PARAMS, "N_PARAM"}, {MachO::N_VERSION, "N_VERS"},
182*9880d681SAndroid Build Coastguard Worker {MachO::N_OLEVEL, "N_OLEV"}, {MachO::N_PSYM, "N_PSYM"},
183*9880d681SAndroid Build Coastguard Worker {MachO::N_EINCL, "N_EINCL"}, {MachO::N_ENTRY, "N_ENTRY"},
184*9880d681SAndroid Build Coastguard Worker {MachO::N_LBRAC, "N_LBRAC"}, {MachO::N_EXCL, "N_EXCL"},
185*9880d681SAndroid Build Coastguard Worker {MachO::N_RBRAC, "N_RBRAC"}, {MachO::N_BCOMM, "N_BCOMM"},
186*9880d681SAndroid Build Coastguard Worker {MachO::N_ECOMM, "N_ECOMM"}, {MachO::N_ECOML, "N_ECOML"},
187*9880d681SAndroid Build Coastguard Worker {MachO::N_LENG, "N_LENG"}, {0, nullptr}};
188*9880d681SAndroid Build Coastguard Worker
getDarwinStabString(uint8_t NType)189*9880d681SAndroid Build Coastguard Worker static const char *getDarwinStabString(uint8_t NType) {
190*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; DarwinStabNames[i].Name; i++) {
191*9880d681SAndroid Build Coastguard Worker if (DarwinStabNames[i].NType == NType)
192*9880d681SAndroid Build Coastguard Worker return DarwinStabNames[i].Name;
193*9880d681SAndroid Build Coastguard Worker }
194*9880d681SAndroid Build Coastguard Worker return nullptr;
195*9880d681SAndroid Build Coastguard Worker }
196*9880d681SAndroid Build Coastguard Worker
dumpSymTabHeader(raw_ostream & OS,StringRef Arch)197*9880d681SAndroid Build Coastguard Worker void MachODebugMapParser::dumpSymTabHeader(raw_ostream &OS, StringRef Arch) {
198*9880d681SAndroid Build Coastguard Worker OS << "-----------------------------------"
199*9880d681SAndroid Build Coastguard Worker "-----------------------------------\n";
200*9880d681SAndroid Build Coastguard Worker OS << "Symbol table for: '" << BinaryPath << "' (" << Arch.data() << ")\n";
201*9880d681SAndroid Build Coastguard Worker OS << "-----------------------------------"
202*9880d681SAndroid Build Coastguard Worker "-----------------------------------\n";
203*9880d681SAndroid Build Coastguard Worker OS << "Index n_strx n_type n_sect n_desc n_value\n";
204*9880d681SAndroid Build Coastguard Worker OS << "======== -------- ------------------ ------ ------ ----------------\n";
205*9880d681SAndroid Build Coastguard Worker }
206*9880d681SAndroid Build Coastguard Worker
dumpSymTabEntry(raw_ostream & OS,uint64_t Index,uint32_t StringIndex,uint8_t Type,uint8_t SectionIndex,uint16_t Flags,uint64_t Value)207*9880d681SAndroid Build Coastguard Worker void MachODebugMapParser::dumpSymTabEntry(raw_ostream &OS, uint64_t Index,
208*9880d681SAndroid Build Coastguard Worker uint32_t StringIndex, uint8_t Type,
209*9880d681SAndroid Build Coastguard Worker uint8_t SectionIndex, uint16_t Flags,
210*9880d681SAndroid Build Coastguard Worker uint64_t Value) {
211*9880d681SAndroid Build Coastguard Worker // Index
212*9880d681SAndroid Build Coastguard Worker OS << '[' << format_decimal(Index, 6) << "] "
213*9880d681SAndroid Build Coastguard Worker // n_strx
214*9880d681SAndroid Build Coastguard Worker << format_hex_no_prefix(StringIndex, 8) << ' '
215*9880d681SAndroid Build Coastguard Worker // n_type...
216*9880d681SAndroid Build Coastguard Worker << format_hex_no_prefix(Type, 2) << " (";
217*9880d681SAndroid Build Coastguard Worker
218*9880d681SAndroid Build Coastguard Worker if (Type & MachO::N_STAB)
219*9880d681SAndroid Build Coastguard Worker OS << left_justify(getDarwinStabString(Type), 13);
220*9880d681SAndroid Build Coastguard Worker else {
221*9880d681SAndroid Build Coastguard Worker if (Type & MachO::N_PEXT)
222*9880d681SAndroid Build Coastguard Worker OS << "PEXT ";
223*9880d681SAndroid Build Coastguard Worker else
224*9880d681SAndroid Build Coastguard Worker OS << " ";
225*9880d681SAndroid Build Coastguard Worker switch (Type & MachO::N_TYPE) {
226*9880d681SAndroid Build Coastguard Worker case MachO::N_UNDF: // 0x0 undefined, n_sect == NO_SECT
227*9880d681SAndroid Build Coastguard Worker OS << "UNDF";
228*9880d681SAndroid Build Coastguard Worker break;
229*9880d681SAndroid Build Coastguard Worker case MachO::N_ABS: // 0x2 absolute, n_sect == NO_SECT
230*9880d681SAndroid Build Coastguard Worker OS << "ABS ";
231*9880d681SAndroid Build Coastguard Worker break;
232*9880d681SAndroid Build Coastguard Worker case MachO::N_SECT: // 0xe defined in section number n_sect
233*9880d681SAndroid Build Coastguard Worker OS << "SECT";
234*9880d681SAndroid Build Coastguard Worker break;
235*9880d681SAndroid Build Coastguard Worker case MachO::N_PBUD: // 0xc prebound undefined (defined in a dylib)
236*9880d681SAndroid Build Coastguard Worker OS << "PBUD";
237*9880d681SAndroid Build Coastguard Worker break;
238*9880d681SAndroid Build Coastguard Worker case MachO::N_INDR: // 0xa indirect
239*9880d681SAndroid Build Coastguard Worker OS << "INDR";
240*9880d681SAndroid Build Coastguard Worker break;
241*9880d681SAndroid Build Coastguard Worker default:
242*9880d681SAndroid Build Coastguard Worker OS << format_hex_no_prefix(Type, 2) << " ";
243*9880d681SAndroid Build Coastguard Worker break;
244*9880d681SAndroid Build Coastguard Worker }
245*9880d681SAndroid Build Coastguard Worker if (Type & MachO::N_EXT)
246*9880d681SAndroid Build Coastguard Worker OS << " EXT";
247*9880d681SAndroid Build Coastguard Worker else
248*9880d681SAndroid Build Coastguard Worker OS << " ";
249*9880d681SAndroid Build Coastguard Worker }
250*9880d681SAndroid Build Coastguard Worker
251*9880d681SAndroid Build Coastguard Worker OS << ") "
252*9880d681SAndroid Build Coastguard Worker // n_sect
253*9880d681SAndroid Build Coastguard Worker << format_hex_no_prefix(SectionIndex, 2) << " "
254*9880d681SAndroid Build Coastguard Worker // n_desc
255*9880d681SAndroid Build Coastguard Worker << format_hex_no_prefix(Flags, 4) << " "
256*9880d681SAndroid Build Coastguard Worker // n_value
257*9880d681SAndroid Build Coastguard Worker << format_hex_no_prefix(Value, 16);
258*9880d681SAndroid Build Coastguard Worker
259*9880d681SAndroid Build Coastguard Worker const char *Name = &MainBinaryStrings.data()[StringIndex];
260*9880d681SAndroid Build Coastguard Worker if (Name && Name[0])
261*9880d681SAndroid Build Coastguard Worker OS << " '" << Name << "'";
262*9880d681SAndroid Build Coastguard Worker
263*9880d681SAndroid Build Coastguard Worker OS << "\n";
264*9880d681SAndroid Build Coastguard Worker }
265*9880d681SAndroid Build Coastguard Worker
dumpOneBinaryStab(const MachOObjectFile & MainBinary,StringRef BinaryPath)266*9880d681SAndroid Build Coastguard Worker void MachODebugMapParser::dumpOneBinaryStab(const MachOObjectFile &MainBinary,
267*9880d681SAndroid Build Coastguard Worker StringRef BinaryPath) {
268*9880d681SAndroid Build Coastguard Worker loadMainBinarySymbols(MainBinary);
269*9880d681SAndroid Build Coastguard Worker MainBinaryStrings = MainBinary.getStringTableData();
270*9880d681SAndroid Build Coastguard Worker raw_ostream &OS(llvm::outs());
271*9880d681SAndroid Build Coastguard Worker
272*9880d681SAndroid Build Coastguard Worker dumpSymTabHeader(OS, getArchName(MainBinary));
273*9880d681SAndroid Build Coastguard Worker uint64_t Idx = 0;
274*9880d681SAndroid Build Coastguard Worker for (const SymbolRef &Symbol : MainBinary.symbols()) {
275*9880d681SAndroid Build Coastguard Worker const DataRefImpl &DRI = Symbol.getRawDataRefImpl();
276*9880d681SAndroid Build Coastguard Worker if (MainBinary.is64Bit())
277*9880d681SAndroid Build Coastguard Worker dumpSymTabEntry(OS, Idx, MainBinary.getSymbol64TableEntry(DRI));
278*9880d681SAndroid Build Coastguard Worker else
279*9880d681SAndroid Build Coastguard Worker dumpSymTabEntry(OS, Idx, MainBinary.getSymbolTableEntry(DRI));
280*9880d681SAndroid Build Coastguard Worker Idx++;
281*9880d681SAndroid Build Coastguard Worker }
282*9880d681SAndroid Build Coastguard Worker
283*9880d681SAndroid Build Coastguard Worker OS << "\n\n";
284*9880d681SAndroid Build Coastguard Worker resetParserState();
285*9880d681SAndroid Build Coastguard Worker }
286*9880d681SAndroid Build Coastguard Worker
shouldLinkArch(SmallVectorImpl<StringRef> & Archs,StringRef Arch)287*9880d681SAndroid Build Coastguard Worker static bool shouldLinkArch(SmallVectorImpl<StringRef> &Archs, StringRef Arch) {
288*9880d681SAndroid Build Coastguard Worker if (Archs.empty() ||
289*9880d681SAndroid Build Coastguard Worker std::find(Archs.begin(), Archs.end(), "all") != Archs.end() ||
290*9880d681SAndroid Build Coastguard Worker std::find(Archs.begin(), Archs.end(), "*") != Archs.end())
291*9880d681SAndroid Build Coastguard Worker return true;
292*9880d681SAndroid Build Coastguard Worker
293*9880d681SAndroid Build Coastguard Worker if (Arch.startswith("arm") && Arch != "arm64" &&
294*9880d681SAndroid Build Coastguard Worker std::find(Archs.begin(), Archs.end(), "arm") != Archs.end())
295*9880d681SAndroid Build Coastguard Worker return true;
296*9880d681SAndroid Build Coastguard Worker
297*9880d681SAndroid Build Coastguard Worker SmallString<16> ArchName = Arch;
298*9880d681SAndroid Build Coastguard Worker if (Arch.startswith("thumb"))
299*9880d681SAndroid Build Coastguard Worker ArchName = ("arm" + Arch.substr(5)).str();
300*9880d681SAndroid Build Coastguard Worker
301*9880d681SAndroid Build Coastguard Worker return std::find(Archs.begin(), Archs.end(), ArchName) != Archs.end();
302*9880d681SAndroid Build Coastguard Worker }
303*9880d681SAndroid Build Coastguard Worker
dumpStab()304*9880d681SAndroid Build Coastguard Worker bool MachODebugMapParser::dumpStab() {
305*9880d681SAndroid Build Coastguard Worker auto MainBinOrError =
306*9880d681SAndroid Build Coastguard Worker MainBinaryHolder.GetFilesAs<MachOObjectFile>(BinaryPath);
307*9880d681SAndroid Build Coastguard Worker if (auto Error = MainBinOrError.getError()) {
308*9880d681SAndroid Build Coastguard Worker llvm::errs() << "Cannot get '" << BinaryPath
309*9880d681SAndroid Build Coastguard Worker << "' as MachO file: " << Error.message() << "\n";
310*9880d681SAndroid Build Coastguard Worker return false;
311*9880d681SAndroid Build Coastguard Worker }
312*9880d681SAndroid Build Coastguard Worker
313*9880d681SAndroid Build Coastguard Worker for (const auto *Binary : *MainBinOrError)
314*9880d681SAndroid Build Coastguard Worker if (shouldLinkArch(Archs, Binary->getArchTriple().getArchName()))
315*9880d681SAndroid Build Coastguard Worker dumpOneBinaryStab(*Binary, BinaryPath);
316*9880d681SAndroid Build Coastguard Worker
317*9880d681SAndroid Build Coastguard Worker return true;
318*9880d681SAndroid Build Coastguard Worker }
319*9880d681SAndroid Build Coastguard Worker
320*9880d681SAndroid Build Coastguard Worker /// This main parsing routine tries to open the main binary and if
321*9880d681SAndroid Build Coastguard Worker /// successful iterates over the STAB entries. The real parsing is
322*9880d681SAndroid Build Coastguard Worker /// done in handleStabSymbolTableEntry.
parse()323*9880d681SAndroid Build Coastguard Worker ErrorOr<std::vector<std::unique_ptr<DebugMap>>> MachODebugMapParser::parse() {
324*9880d681SAndroid Build Coastguard Worker auto MainBinOrError =
325*9880d681SAndroid Build Coastguard Worker MainBinaryHolder.GetFilesAs<MachOObjectFile>(BinaryPath);
326*9880d681SAndroid Build Coastguard Worker if (auto Error = MainBinOrError.getError())
327*9880d681SAndroid Build Coastguard Worker return Error;
328*9880d681SAndroid Build Coastguard Worker
329*9880d681SAndroid Build Coastguard Worker std::vector<std::unique_ptr<DebugMap>> Results;
330*9880d681SAndroid Build Coastguard Worker for (const auto *Binary : *MainBinOrError)
331*9880d681SAndroid Build Coastguard Worker if (shouldLinkArch(Archs, Binary->getArchTriple().getArchName()))
332*9880d681SAndroid Build Coastguard Worker Results.push_back(parseOneBinary(*Binary, BinaryPath));
333*9880d681SAndroid Build Coastguard Worker
334*9880d681SAndroid Build Coastguard Worker return std::move(Results);
335*9880d681SAndroid Build Coastguard Worker }
336*9880d681SAndroid Build Coastguard Worker
337*9880d681SAndroid Build Coastguard Worker /// Interpret the STAB entries to fill the DebugMap.
handleStabSymbolTableEntry(uint32_t StringIndex,uint8_t Type,uint8_t SectionIndex,uint16_t Flags,uint64_t Value)338*9880d681SAndroid Build Coastguard Worker void MachODebugMapParser::handleStabSymbolTableEntry(uint32_t StringIndex,
339*9880d681SAndroid Build Coastguard Worker uint8_t Type,
340*9880d681SAndroid Build Coastguard Worker uint8_t SectionIndex,
341*9880d681SAndroid Build Coastguard Worker uint16_t Flags,
342*9880d681SAndroid Build Coastguard Worker uint64_t Value) {
343*9880d681SAndroid Build Coastguard Worker if (!(Type & MachO::N_STAB))
344*9880d681SAndroid Build Coastguard Worker return;
345*9880d681SAndroid Build Coastguard Worker
346*9880d681SAndroid Build Coastguard Worker const char *Name = &MainBinaryStrings.data()[StringIndex];
347*9880d681SAndroid Build Coastguard Worker
348*9880d681SAndroid Build Coastguard Worker // An N_OSO entry represents the start of a new object file description.
349*9880d681SAndroid Build Coastguard Worker if (Type == MachO::N_OSO) {
350*9880d681SAndroid Build Coastguard Worker sys::TimeValue Timestamp;
351*9880d681SAndroid Build Coastguard Worker Timestamp.fromEpochTime(Value);
352*9880d681SAndroid Build Coastguard Worker return switchToNewDebugMapObject(Name, Timestamp);
353*9880d681SAndroid Build Coastguard Worker }
354*9880d681SAndroid Build Coastguard Worker
355*9880d681SAndroid Build Coastguard Worker // If the last N_OSO object file wasn't found,
356*9880d681SAndroid Build Coastguard Worker // CurrentDebugMapObject will be null. Do not update anything
357*9880d681SAndroid Build Coastguard Worker // until we find the next valid N_OSO entry.
358*9880d681SAndroid Build Coastguard Worker if (!CurrentDebugMapObject)
359*9880d681SAndroid Build Coastguard Worker return;
360*9880d681SAndroid Build Coastguard Worker
361*9880d681SAndroid Build Coastguard Worker uint32_t Size = 0;
362*9880d681SAndroid Build Coastguard Worker switch (Type) {
363*9880d681SAndroid Build Coastguard Worker case MachO::N_GSYM:
364*9880d681SAndroid Build Coastguard Worker // This is a global variable. We need to query the main binary
365*9880d681SAndroid Build Coastguard Worker // symbol table to find its address as it might not be in the
366*9880d681SAndroid Build Coastguard Worker // debug map (for common symbols).
367*9880d681SAndroid Build Coastguard Worker Value = getMainBinarySymbolAddress(Name);
368*9880d681SAndroid Build Coastguard Worker break;
369*9880d681SAndroid Build Coastguard Worker case MachO::N_FUN:
370*9880d681SAndroid Build Coastguard Worker // Functions are scopes in STABS. They have an end marker that
371*9880d681SAndroid Build Coastguard Worker // contains the function size.
372*9880d681SAndroid Build Coastguard Worker if (Name[0] == '\0') {
373*9880d681SAndroid Build Coastguard Worker Size = Value;
374*9880d681SAndroid Build Coastguard Worker Value = CurrentFunctionAddress;
375*9880d681SAndroid Build Coastguard Worker Name = CurrentFunctionName;
376*9880d681SAndroid Build Coastguard Worker break;
377*9880d681SAndroid Build Coastguard Worker } else {
378*9880d681SAndroid Build Coastguard Worker CurrentFunctionName = Name;
379*9880d681SAndroid Build Coastguard Worker CurrentFunctionAddress = Value;
380*9880d681SAndroid Build Coastguard Worker return;
381*9880d681SAndroid Build Coastguard Worker }
382*9880d681SAndroid Build Coastguard Worker case MachO::N_STSYM:
383*9880d681SAndroid Build Coastguard Worker break;
384*9880d681SAndroid Build Coastguard Worker default:
385*9880d681SAndroid Build Coastguard Worker return;
386*9880d681SAndroid Build Coastguard Worker }
387*9880d681SAndroid Build Coastguard Worker
388*9880d681SAndroid Build Coastguard Worker auto ObjectSymIt = CurrentObjectAddresses.find(Name);
389*9880d681SAndroid Build Coastguard Worker if (ObjectSymIt == CurrentObjectAddresses.end())
390*9880d681SAndroid Build Coastguard Worker return Warning("could not find object file symbol for symbol " +
391*9880d681SAndroid Build Coastguard Worker Twine(Name));
392*9880d681SAndroid Build Coastguard Worker if (!CurrentDebugMapObject->addSymbol(Name, ObjectSymIt->getValue(), Value,
393*9880d681SAndroid Build Coastguard Worker Size))
394*9880d681SAndroid Build Coastguard Worker return Warning(Twine("failed to insert symbol '") + Name +
395*9880d681SAndroid Build Coastguard Worker "' in the debug map.");
396*9880d681SAndroid Build Coastguard Worker }
397*9880d681SAndroid Build Coastguard Worker
398*9880d681SAndroid Build Coastguard Worker /// Load the current object file symbols into CurrentObjectAddresses.
loadCurrentObjectFileSymbols(const object::MachOObjectFile & Obj)399*9880d681SAndroid Build Coastguard Worker void MachODebugMapParser::loadCurrentObjectFileSymbols(
400*9880d681SAndroid Build Coastguard Worker const object::MachOObjectFile &Obj) {
401*9880d681SAndroid Build Coastguard Worker CurrentObjectAddresses.clear();
402*9880d681SAndroid Build Coastguard Worker
403*9880d681SAndroid Build Coastguard Worker for (auto Sym : Obj.symbols()) {
404*9880d681SAndroid Build Coastguard Worker uint64_t Addr = Sym.getValue();
405*9880d681SAndroid Build Coastguard Worker Expected<StringRef> Name = Sym.getName();
406*9880d681SAndroid Build Coastguard Worker if (!Name) {
407*9880d681SAndroid Build Coastguard Worker // TODO: Actually report errors helpfully.
408*9880d681SAndroid Build Coastguard Worker consumeError(Name.takeError());
409*9880d681SAndroid Build Coastguard Worker continue;
410*9880d681SAndroid Build Coastguard Worker }
411*9880d681SAndroid Build Coastguard Worker // The value of some categories of symbols isn't meaningful. For
412*9880d681SAndroid Build Coastguard Worker // example common symbols store their size in the value field, not
413*9880d681SAndroid Build Coastguard Worker // their address. Absolute symbols have a fixed address that can
414*9880d681SAndroid Build Coastguard Worker // conflict with standard symbols. These symbols (especially the
415*9880d681SAndroid Build Coastguard Worker // common ones), might still be referenced by relocations. These
416*9880d681SAndroid Build Coastguard Worker // relocations will use the symbol itself, and won't need an
417*9880d681SAndroid Build Coastguard Worker // object file address. The object file address field is optional
418*9880d681SAndroid Build Coastguard Worker // in the DebugMap, leave it unassigned for these symbols.
419*9880d681SAndroid Build Coastguard Worker if (Sym.getFlags() & (SymbolRef::SF_Absolute | SymbolRef::SF_Common))
420*9880d681SAndroid Build Coastguard Worker CurrentObjectAddresses[*Name] = None;
421*9880d681SAndroid Build Coastguard Worker else
422*9880d681SAndroid Build Coastguard Worker CurrentObjectAddresses[*Name] = Addr;
423*9880d681SAndroid Build Coastguard Worker }
424*9880d681SAndroid Build Coastguard Worker }
425*9880d681SAndroid Build Coastguard Worker
426*9880d681SAndroid Build Coastguard Worker /// Lookup a symbol address in the main binary symbol table. The
427*9880d681SAndroid Build Coastguard Worker /// parser only needs to query common symbols, thus not every symbol's
428*9880d681SAndroid Build Coastguard Worker /// address is available through this function.
getMainBinarySymbolAddress(StringRef Name)429*9880d681SAndroid Build Coastguard Worker uint64_t MachODebugMapParser::getMainBinarySymbolAddress(StringRef Name) {
430*9880d681SAndroid Build Coastguard Worker auto Sym = MainBinarySymbolAddresses.find(Name);
431*9880d681SAndroid Build Coastguard Worker if (Sym == MainBinarySymbolAddresses.end())
432*9880d681SAndroid Build Coastguard Worker return 0;
433*9880d681SAndroid Build Coastguard Worker return Sym->second;
434*9880d681SAndroid Build Coastguard Worker }
435*9880d681SAndroid Build Coastguard Worker
436*9880d681SAndroid Build Coastguard Worker /// Load the interesting main binary symbols' addresses into
437*9880d681SAndroid Build Coastguard Worker /// MainBinarySymbolAddresses.
loadMainBinarySymbols(const MachOObjectFile & MainBinary)438*9880d681SAndroid Build Coastguard Worker void MachODebugMapParser::loadMainBinarySymbols(
439*9880d681SAndroid Build Coastguard Worker const MachOObjectFile &MainBinary) {
440*9880d681SAndroid Build Coastguard Worker section_iterator Section = MainBinary.section_end();
441*9880d681SAndroid Build Coastguard Worker MainBinarySymbolAddresses.clear();
442*9880d681SAndroid Build Coastguard Worker for (const auto &Sym : MainBinary.symbols()) {
443*9880d681SAndroid Build Coastguard Worker Expected<SymbolRef::Type> TypeOrErr = Sym.getType();
444*9880d681SAndroid Build Coastguard Worker if (!TypeOrErr) {
445*9880d681SAndroid Build Coastguard Worker // TODO: Actually report errors helpfully.
446*9880d681SAndroid Build Coastguard Worker consumeError(TypeOrErr.takeError());
447*9880d681SAndroid Build Coastguard Worker continue;
448*9880d681SAndroid Build Coastguard Worker }
449*9880d681SAndroid Build Coastguard Worker SymbolRef::Type Type = *TypeOrErr;
450*9880d681SAndroid Build Coastguard Worker // Skip undefined and STAB entries.
451*9880d681SAndroid Build Coastguard Worker if ((Type & SymbolRef::ST_Debug) || (Type & SymbolRef::ST_Unknown))
452*9880d681SAndroid Build Coastguard Worker continue;
453*9880d681SAndroid Build Coastguard Worker // The only symbols of interest are the global variables. These
454*9880d681SAndroid Build Coastguard Worker // are the only ones that need to be queried because the address
455*9880d681SAndroid Build Coastguard Worker // of common data won't be described in the debug map. All other
456*9880d681SAndroid Build Coastguard Worker // addresses should be fetched for the debug map.
457*9880d681SAndroid Build Coastguard Worker if (!(Sym.getFlags() & SymbolRef::SF_Global))
458*9880d681SAndroid Build Coastguard Worker continue;
459*9880d681SAndroid Build Coastguard Worker Expected<section_iterator> SectionOrErr = Sym.getSection();
460*9880d681SAndroid Build Coastguard Worker if (!SectionOrErr) {
461*9880d681SAndroid Build Coastguard Worker // TODO: Actually report errors helpfully.
462*9880d681SAndroid Build Coastguard Worker consumeError(SectionOrErr.takeError());
463*9880d681SAndroid Build Coastguard Worker continue;
464*9880d681SAndroid Build Coastguard Worker }
465*9880d681SAndroid Build Coastguard Worker Section = *SectionOrErr;
466*9880d681SAndroid Build Coastguard Worker if (Section == MainBinary.section_end() || Section->isText())
467*9880d681SAndroid Build Coastguard Worker continue;
468*9880d681SAndroid Build Coastguard Worker uint64_t Addr = Sym.getValue();
469*9880d681SAndroid Build Coastguard Worker Expected<StringRef> NameOrErr = Sym.getName();
470*9880d681SAndroid Build Coastguard Worker if (!NameOrErr) {
471*9880d681SAndroid Build Coastguard Worker // TODO: Actually report errors helpfully.
472*9880d681SAndroid Build Coastguard Worker consumeError(NameOrErr.takeError());
473*9880d681SAndroid Build Coastguard Worker continue;
474*9880d681SAndroid Build Coastguard Worker }
475*9880d681SAndroid Build Coastguard Worker StringRef Name = *NameOrErr;
476*9880d681SAndroid Build Coastguard Worker if (Name.size() == 0 || Name[0] == '\0')
477*9880d681SAndroid Build Coastguard Worker continue;
478*9880d681SAndroid Build Coastguard Worker MainBinarySymbolAddresses[Name] = Addr;
479*9880d681SAndroid Build Coastguard Worker }
480*9880d681SAndroid Build Coastguard Worker }
481*9880d681SAndroid Build Coastguard Worker
482*9880d681SAndroid Build Coastguard Worker namespace llvm {
483*9880d681SAndroid Build Coastguard Worker namespace dsymutil {
484*9880d681SAndroid Build Coastguard Worker llvm::ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
parseDebugMap(StringRef InputFile,ArrayRef<std::string> Archs,StringRef PrependPath,bool Verbose,bool InputIsYAML)485*9880d681SAndroid Build Coastguard Worker parseDebugMap(StringRef InputFile, ArrayRef<std::string> Archs,
486*9880d681SAndroid Build Coastguard Worker StringRef PrependPath, bool Verbose, bool InputIsYAML) {
487*9880d681SAndroid Build Coastguard Worker if (!InputIsYAML) {
488*9880d681SAndroid Build Coastguard Worker MachODebugMapParser Parser(InputFile, Archs, PrependPath, Verbose);
489*9880d681SAndroid Build Coastguard Worker return Parser.parse();
490*9880d681SAndroid Build Coastguard Worker } else {
491*9880d681SAndroid Build Coastguard Worker return DebugMap::parseYAMLDebugMap(InputFile, PrependPath, Verbose);
492*9880d681SAndroid Build Coastguard Worker }
493*9880d681SAndroid Build Coastguard Worker }
494*9880d681SAndroid Build Coastguard Worker
dumpStab(StringRef InputFile,ArrayRef<std::string> Archs,StringRef PrependPath)495*9880d681SAndroid Build Coastguard Worker bool dumpStab(StringRef InputFile, ArrayRef<std::string> Archs,
496*9880d681SAndroid Build Coastguard Worker StringRef PrependPath) {
497*9880d681SAndroid Build Coastguard Worker MachODebugMapParser Parser(InputFile, Archs, PrependPath, false);
498*9880d681SAndroid Build Coastguard Worker return Parser.dumpStab();
499*9880d681SAndroid Build Coastguard Worker }
500*9880d681SAndroid Build Coastguard Worker } // namespace dsymutil
501*9880d681SAndroid Build Coastguard Worker } // namespace llvm
502