xref: /aosp_15_r20/external/llvm/tools/dsymutil/MachODebugMapParser.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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