[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / llvm / tools / dsymutil / MachODebugMapParser.cpp
blob955272b72f566b7cadaebe1cba7dc8b9bb4c41c0
1 //===- tools/dsymutil/MachODebugMapParser.cpp - Parse STABS debug maps ----===//
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 //===----------------------------------------------------------------------===//
9 #include "BinaryHolder.h"
10 #include "DebugMap.h"
11 #include "MachOUtils.h"
12 #include "llvm/ADT/Optional.h"
13 #include "llvm/ADT/SmallSet.h"
14 #include "llvm/Object/MachO.h"
15 #include "llvm/Support/Path.h"
16 #include "llvm/Support/WithColor.h"
17 #include "llvm/Support/raw_ostream.h"
18 #include <vector>
20 namespace {
21 using namespace llvm;
22 using namespace llvm::dsymutil;
23 using namespace llvm::object;
25 class MachODebugMapParser {
26 public:
27 MachODebugMapParser(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
28 StringRef BinaryPath, ArrayRef<std::string> Archs,
29 StringRef PathPrefix = "",
30 bool PaperTrailWarnings = false, bool Verbose = false)
31 : BinaryPath(std::string(BinaryPath)), Archs(Archs.begin(), Archs.end()),
32 PathPrefix(std::string(PathPrefix)),
33 PaperTrailWarnings(PaperTrailWarnings), BinHolder(VFS, Verbose),
34 CurrentDebugMapObject(nullptr) {}
36 /// Parses and returns the DebugMaps of the input binary. The binary contains
37 /// multiple maps in case it is a universal binary.
38 /// \returns an error in case the provided BinaryPath doesn't exist
39 /// or isn't of a supported type.
40 ErrorOr<std::vector<std::unique_ptr<DebugMap>>> parse();
42 /// Walk the symbol table and dump it.
43 bool dumpStab();
45 private:
46 std::string BinaryPath;
47 SmallVector<StringRef, 1> Archs;
48 std::string PathPrefix;
49 bool PaperTrailWarnings;
51 /// Owns the MemoryBuffer for the main binary.
52 BinaryHolder BinHolder;
53 /// Map of the binary symbol addresses.
54 StringMap<uint64_t> MainBinarySymbolAddresses;
55 StringRef MainBinaryStrings;
56 /// The constructed DebugMap.
57 std::unique_ptr<DebugMap> Result;
58 /// List of common symbols that need to be added to the debug map.
59 std::vector<std::string> CommonSymbols;
61 /// Map of the currently processed object file symbol addresses.
62 StringMap<Optional<uint64_t>> CurrentObjectAddresses;
64 /// Lazily computed map of symbols aliased to the processed object file.
65 StringMap<Optional<uint64_t>> CurrentObjectAliasMap;
67 /// If CurrentObjectAliasMap has been computed for a given address.
68 SmallSet<uint64_t, 4> SeenAliasValues;
70 /// Element of the debug map corresponding to the current object file.
71 DebugMapObject *CurrentDebugMapObject;
73 /// Holds function info while function scope processing.
74 const char *CurrentFunctionName;
75 uint64_t CurrentFunctionAddress;
77 std::unique_ptr<DebugMap> parseOneBinary(const MachOObjectFile &MainBinary,
78 StringRef BinaryPath);
80 void
81 switchToNewDebugMapObject(StringRef Filename,
82 sys::TimePoint<std::chrono::seconds> Timestamp);
83 void resetParserState();
84 uint64_t getMainBinarySymbolAddress(StringRef Name);
85 std::vector<StringRef> getMainBinarySymbolNames(uint64_t Value);
86 void loadMainBinarySymbols(const MachOObjectFile &MainBinary);
87 void loadCurrentObjectFileSymbols(const object::MachOObjectFile &Obj);
88 void handleStabSymbolTableEntry(uint32_t StringIndex, uint8_t Type,
89 uint8_t SectionIndex, uint16_t Flags,
90 uint64_t Value);
92 template <typename STEType> void handleStabDebugMapEntry(const STEType &STE) {
93 handleStabSymbolTableEntry(STE.n_strx, STE.n_type, STE.n_sect, STE.n_desc,
94 STE.n_value);
97 void addCommonSymbols();
99 /// Dump the symbol table output header.
100 void dumpSymTabHeader(raw_ostream &OS, StringRef Arch);
102 /// Dump the contents of nlist entries.
103 void dumpSymTabEntry(raw_ostream &OS, uint64_t Index, uint32_t StringIndex,
104 uint8_t Type, uint8_t SectionIndex, uint16_t Flags,
105 uint64_t Value);
107 template <typename STEType>
108 void dumpSymTabEntry(raw_ostream &OS, uint64_t Index, const STEType &STE) {
109 dumpSymTabEntry(OS, Index, STE.n_strx, STE.n_type, STE.n_sect, STE.n_desc,
110 STE.n_value);
112 void dumpOneBinaryStab(const MachOObjectFile &MainBinary,
113 StringRef BinaryPath);
115 void Warning(const Twine &Msg, StringRef File = StringRef()) {
116 WithColor::warning() << "("
117 << MachOUtils::getArchName(
118 Result->getTriple().getArchName())
119 << ") " << File << " " << Msg << "\n";
121 if (PaperTrailWarnings) {
122 if (!File.empty())
123 Result->addDebugMapObject(File, sys::TimePoint<std::chrono::seconds>());
124 if (Result->end() != Result->begin())
125 (*--Result->end())->addWarning(Msg.str());
130 } // anonymous namespace
132 /// Reset the parser state corresponding to the current object
133 /// file. This is to be called after an object file is finished
134 /// processing.
135 void MachODebugMapParser::resetParserState() {
136 CommonSymbols.clear();
137 CurrentObjectAddresses.clear();
138 CurrentObjectAliasMap.clear();
139 SeenAliasValues.clear();
140 CurrentDebugMapObject = nullptr;
143 /// Commons symbols won't show up in the symbol map but might need to be
144 /// relocated. We can add them to the symbol table ourselves by combining the
145 /// information in the object file (the symbol name) and the main binary (the
146 /// address).
147 void MachODebugMapParser::addCommonSymbols() {
148 for (auto &CommonSymbol : CommonSymbols) {
149 uint64_t CommonAddr = getMainBinarySymbolAddress(CommonSymbol);
150 if (CommonAddr == 0) {
151 // The main binary doesn't have an address for the given symbol.
152 continue;
154 if (!CurrentDebugMapObject->addSymbol(CommonSymbol, None /*ObjectAddress*/,
155 CommonAddr, 0 /*size*/)) {
156 // The symbol is already present.
157 continue;
162 /// Create a new DebugMapObject. This function resets the state of the
163 /// parser that was referring to the last object file and sets
164 /// everything up to add symbols to the new one.
165 void MachODebugMapParser::switchToNewDebugMapObject(
166 StringRef Filename, sys::TimePoint<std::chrono::seconds> Timestamp) {
167 addCommonSymbols();
168 resetParserState();
170 SmallString<80> Path(PathPrefix);
171 sys::path::append(Path, Filename);
173 auto ObjectEntry = BinHolder.getObjectEntry(Path, Timestamp);
174 if (!ObjectEntry) {
175 auto Err = ObjectEntry.takeError();
176 Warning("unable to open object file: " + toString(std::move(Err)),
177 Path.str());
178 return;
181 auto Object = ObjectEntry->getObjectAs<MachOObjectFile>(Result->getTriple());
182 if (!Object) {
183 auto Err = Object.takeError();
184 Warning("unable to open object file: " + toString(std::move(Err)),
185 Path.str());
186 return;
189 CurrentDebugMapObject =
190 &Result->addDebugMapObject(Path, Timestamp, MachO::N_OSO);
191 loadCurrentObjectFileSymbols(*Object);
194 static std::string getArchName(const object::MachOObjectFile &Obj) {
195 Triple T = Obj.getArchTriple();
196 return std::string(T.getArchName());
199 std::unique_ptr<DebugMap>
200 MachODebugMapParser::parseOneBinary(const MachOObjectFile &MainBinary,
201 StringRef BinaryPath) {
202 loadMainBinarySymbols(MainBinary);
203 ArrayRef<uint8_t> UUID = MainBinary.getUuid();
204 Result =
205 std::make_unique<DebugMap>(MainBinary.getArchTriple(), BinaryPath, UUID);
206 MainBinaryStrings = MainBinary.getStringTableData();
207 for (const SymbolRef &Symbol : MainBinary.symbols()) {
208 const DataRefImpl &DRI = Symbol.getRawDataRefImpl();
209 if (MainBinary.is64Bit())
210 handleStabDebugMapEntry(MainBinary.getSymbol64TableEntry(DRI));
211 else
212 handleStabDebugMapEntry(MainBinary.getSymbolTableEntry(DRI));
215 resetParserState();
216 return std::move(Result);
219 // Table that maps Darwin's Mach-O stab constants to strings to allow printing.
220 // llvm-nm has very similar code, the strings used here are however slightly
221 // different and part of the interface of dsymutil (some project's build-systems
222 // parse the ouptut of dsymutil -s), thus they shouldn't be changed.
223 struct DarwinStabName {
224 uint8_t NType;
225 const char *Name;
228 const struct DarwinStabName DarwinStabNames[] = {
229 {MachO::N_GSYM, "N_GSYM"}, {MachO::N_FNAME, "N_FNAME"},
230 {MachO::N_FUN, "N_FUN"}, {MachO::N_STSYM, "N_STSYM"},
231 {MachO::N_LCSYM, "N_LCSYM"}, {MachO::N_BNSYM, "N_BNSYM"},
232 {MachO::N_PC, "N_PC"}, {MachO::N_AST, "N_AST"},
233 {MachO::N_OPT, "N_OPT"}, {MachO::N_RSYM, "N_RSYM"},
234 {MachO::N_SLINE, "N_SLINE"}, {MachO::N_ENSYM, "N_ENSYM"},
235 {MachO::N_SSYM, "N_SSYM"}, {MachO::N_SO, "N_SO"},
236 {MachO::N_OSO, "N_OSO"}, {MachO::N_LSYM, "N_LSYM"},
237 {MachO::N_BINCL, "N_BINCL"}, {MachO::N_SOL, "N_SOL"},
238 {MachO::N_PARAMS, "N_PARAM"}, {MachO::N_VERSION, "N_VERS"},
239 {MachO::N_OLEVEL, "N_OLEV"}, {MachO::N_PSYM, "N_PSYM"},
240 {MachO::N_EINCL, "N_EINCL"}, {MachO::N_ENTRY, "N_ENTRY"},
241 {MachO::N_LBRAC, "N_LBRAC"}, {MachO::N_EXCL, "N_EXCL"},
242 {MachO::N_RBRAC, "N_RBRAC"}, {MachO::N_BCOMM, "N_BCOMM"},
243 {MachO::N_ECOMM, "N_ECOMM"}, {MachO::N_ECOML, "N_ECOML"},
244 {MachO::N_LENG, "N_LENG"}, {0, nullptr}};
246 static const char *getDarwinStabString(uint8_t NType) {
247 for (unsigned i = 0; DarwinStabNames[i].Name; i++) {
248 if (DarwinStabNames[i].NType == NType)
249 return DarwinStabNames[i].Name;
251 return nullptr;
254 void MachODebugMapParser::dumpSymTabHeader(raw_ostream &OS, StringRef Arch) {
255 OS << "-----------------------------------"
256 "-----------------------------------\n";
257 OS << "Symbol table for: '" << BinaryPath << "' (" << Arch.data() << ")\n";
258 OS << "-----------------------------------"
259 "-----------------------------------\n";
260 OS << "Index n_strx n_type n_sect n_desc n_value\n";
261 OS << "======== -------- ------------------ ------ ------ ----------------\n";
264 void MachODebugMapParser::dumpSymTabEntry(raw_ostream &OS, uint64_t Index,
265 uint32_t StringIndex, uint8_t Type,
266 uint8_t SectionIndex, uint16_t Flags,
267 uint64_t Value) {
268 // Index
269 OS << '[' << format_decimal(Index, 6)
270 << "] "
271 // n_strx
272 << format_hex_no_prefix(StringIndex, 8)
273 << ' '
274 // n_type...
275 << format_hex_no_prefix(Type, 2) << " (";
277 if (Type & MachO::N_STAB)
278 OS << left_justify(getDarwinStabString(Type), 13);
279 else {
280 if (Type & MachO::N_PEXT)
281 OS << "PEXT ";
282 else
283 OS << " ";
284 switch (Type & MachO::N_TYPE) {
285 case MachO::N_UNDF: // 0x0 undefined, n_sect == NO_SECT
286 OS << "UNDF";
287 break;
288 case MachO::N_ABS: // 0x2 absolute, n_sect == NO_SECT
289 OS << "ABS ";
290 break;
291 case MachO::N_SECT: // 0xe defined in section number n_sect
292 OS << "SECT";
293 break;
294 case MachO::N_PBUD: // 0xc prebound undefined (defined in a dylib)
295 OS << "PBUD";
296 break;
297 case MachO::N_INDR: // 0xa indirect
298 OS << "INDR";
299 break;
300 default:
301 OS << format_hex_no_prefix(Type, 2) << " ";
302 break;
304 if (Type & MachO::N_EXT)
305 OS << " EXT";
306 else
307 OS << " ";
310 OS << ") "
311 // n_sect
312 << format_hex_no_prefix(SectionIndex, 2)
313 << " "
314 // n_desc
315 << format_hex_no_prefix(Flags, 4)
316 << " "
317 // n_value
318 << format_hex_no_prefix(Value, 16);
320 const char *Name = &MainBinaryStrings.data()[StringIndex];
321 if (Name && Name[0])
322 OS << " '" << Name << "'";
324 OS << "\n";
327 void MachODebugMapParser::dumpOneBinaryStab(const MachOObjectFile &MainBinary,
328 StringRef BinaryPath) {
329 loadMainBinarySymbols(MainBinary);
330 MainBinaryStrings = MainBinary.getStringTableData();
331 raw_ostream &OS(llvm::outs());
333 dumpSymTabHeader(OS, getArchName(MainBinary));
334 uint64_t Idx = 0;
335 for (const SymbolRef &Symbol : MainBinary.symbols()) {
336 const DataRefImpl &DRI = Symbol.getRawDataRefImpl();
337 if (MainBinary.is64Bit())
338 dumpSymTabEntry(OS, Idx, MainBinary.getSymbol64TableEntry(DRI));
339 else
340 dumpSymTabEntry(OS, Idx, MainBinary.getSymbolTableEntry(DRI));
341 Idx++;
344 OS << "\n\n";
345 resetParserState();
348 static bool shouldLinkArch(SmallVectorImpl<StringRef> &Archs, StringRef Arch) {
349 if (Archs.empty() || is_contained(Archs, "all") || is_contained(Archs, "*"))
350 return true;
352 if (Arch.startswith("arm") && Arch != "arm64" && is_contained(Archs, "arm"))
353 return true;
355 SmallString<16> ArchName = Arch;
356 if (Arch.startswith("thumb"))
357 ArchName = ("arm" + Arch.substr(5)).str();
359 return is_contained(Archs, ArchName);
362 bool MachODebugMapParser::dumpStab() {
363 auto ObjectEntry = BinHolder.getObjectEntry(BinaryPath);
364 if (!ObjectEntry) {
365 auto Err = ObjectEntry.takeError();
366 WithColor::error() << "cannot load '" << BinaryPath
367 << "': " << toString(std::move(Err)) << '\n';
368 return false;
371 auto Objects = ObjectEntry->getObjectsAs<MachOObjectFile>();
372 if (!Objects) {
373 auto Err = Objects.takeError();
374 WithColor::error() << "cannot get '" << BinaryPath
375 << "' as MachO file: " << toString(std::move(Err))
376 << "\n";
377 return false;
380 for (const auto *Object : *Objects)
381 if (shouldLinkArch(Archs, Object->getArchTriple().getArchName()))
382 dumpOneBinaryStab(*Object, BinaryPath);
384 return true;
387 /// This main parsing routine tries to open the main binary and if
388 /// successful iterates over the STAB entries. The real parsing is
389 /// done in handleStabSymbolTableEntry.
390 ErrorOr<std::vector<std::unique_ptr<DebugMap>>> MachODebugMapParser::parse() {
391 auto ObjectEntry = BinHolder.getObjectEntry(BinaryPath);
392 if (!ObjectEntry) {
393 return errorToErrorCode(ObjectEntry.takeError());
396 auto Objects = ObjectEntry->getObjectsAs<MachOObjectFile>();
397 if (!Objects) {
398 return errorToErrorCode(Objects.takeError());
401 std::vector<std::unique_ptr<DebugMap>> Results;
402 for (const auto *Object : *Objects)
403 if (shouldLinkArch(Archs, Object->getArchTriple().getArchName()))
404 Results.push_back(parseOneBinary(*Object, BinaryPath));
406 return std::move(Results);
409 /// Interpret the STAB entries to fill the DebugMap.
410 void MachODebugMapParser::handleStabSymbolTableEntry(uint32_t StringIndex,
411 uint8_t Type,
412 uint8_t SectionIndex,
413 uint16_t Flags,
414 uint64_t Value) {
415 if (!(Type & MachO::N_STAB))
416 return;
418 const char *Name = &MainBinaryStrings.data()[StringIndex];
420 // An N_OSO entry represents the start of a new object file description.
421 if (Type == MachO::N_OSO)
422 return switchToNewDebugMapObject(Name, sys::toTimePoint(Value));
424 if (Type == MachO::N_AST) {
425 SmallString<80> Path(PathPrefix);
426 sys::path::append(Path, Name);
427 Result->addDebugMapObject(Path, sys::toTimePoint(Value), Type);
428 return;
431 // If the last N_OSO object file wasn't found, CurrentDebugMapObject will be
432 // null. Do not update anything until we find the next valid N_OSO entry.
433 if (!CurrentDebugMapObject)
434 return;
436 uint32_t Size = 0;
437 switch (Type) {
438 case MachO::N_GSYM:
439 // This is a global variable. We need to query the main binary
440 // symbol table to find its address as it might not be in the
441 // debug map (for common symbols).
442 Value = getMainBinarySymbolAddress(Name);
443 break;
444 case MachO::N_FUN:
445 // Functions are scopes in STABS. They have an end marker that
446 // contains the function size.
447 if (Name[0] == '\0') {
448 Size = Value;
449 Value = CurrentFunctionAddress;
450 Name = CurrentFunctionName;
451 break;
452 } else {
453 CurrentFunctionName = Name;
454 CurrentFunctionAddress = Value;
455 return;
457 case MachO::N_STSYM:
458 break;
459 default:
460 return;
463 auto ObjectSymIt = CurrentObjectAddresses.find(Name);
465 // If the name of a (non-static) symbol is not in the current object, we
466 // check all its aliases from the main binary.
467 if (ObjectSymIt == CurrentObjectAddresses.end() && Type != MachO::N_STSYM) {
468 if (SeenAliasValues.count(Value) == 0) {
469 auto Aliases = getMainBinarySymbolNames(Value);
470 for (const auto &Alias : Aliases) {
471 auto It = CurrentObjectAddresses.find(Alias);
472 if (It != CurrentObjectAddresses.end()) {
473 auto AliasValue = It->getValue();
474 for (const auto &Alias : Aliases)
475 CurrentObjectAliasMap[Alias] = AliasValue;
476 break;
479 SeenAliasValues.insert(Value);
482 auto AliasIt = CurrentObjectAliasMap.find(Name);
483 if (AliasIt != CurrentObjectAliasMap.end())
484 ObjectSymIt = AliasIt;
487 // ThinLTO adds a unique suffix to exported private symbols.
488 if (ObjectSymIt == CurrentObjectAddresses.end()) {
489 for (auto Iter = CurrentObjectAddresses.begin();
490 Iter != CurrentObjectAddresses.end(); ++Iter) {
491 llvm::StringRef SymbolName = Iter->getKey();
492 auto Pos = SymbolName.rfind(".llvm.");
493 if (Pos != llvm::StringRef::npos && SymbolName.substr(0, Pos) == Name) {
494 ObjectSymIt = Iter;
495 break;
500 if (ObjectSymIt == CurrentObjectAddresses.end()) {
501 Warning("could not find object file symbol for symbol " + Twine(Name));
502 return;
505 if (!CurrentDebugMapObject->addSymbol(Name, ObjectSymIt->getValue(), Value,
506 Size)) {
507 Warning(Twine("failed to insert symbol '") + Name + "' in the debug map.");
508 return;
512 /// Load the current object file symbols into CurrentObjectAddresses.
513 void MachODebugMapParser::loadCurrentObjectFileSymbols(
514 const object::MachOObjectFile &Obj) {
515 CurrentObjectAddresses.clear();
517 for (auto Sym : Obj.symbols()) {
518 uint64_t Addr = cantFail(Sym.getValue());
519 Expected<StringRef> Name = Sym.getName();
520 if (!Name) {
521 auto Err = Name.takeError();
522 Warning("failed to get symbol name: " + toString(std::move(Err)),
523 Obj.getFileName());
524 continue;
526 // The value of some categories of symbols isn't meaningful. For
527 // example common symbols store their size in the value field, not
528 // their address. Absolute symbols have a fixed address that can
529 // conflict with standard symbols. These symbols (especially the
530 // common ones), might still be referenced by relocations. These
531 // relocations will use the symbol itself, and won't need an
532 // object file address. The object file address field is optional
533 // in the DebugMap, leave it unassigned for these symbols.
534 uint32_t Flags = cantFail(Sym.getFlags());
535 if (Flags & SymbolRef::SF_Absolute) {
536 CurrentObjectAddresses[*Name] = None;
537 } else if (Flags & SymbolRef::SF_Common) {
538 CurrentObjectAddresses[*Name] = None;
539 CommonSymbols.push_back(std::string(*Name));
540 } else {
541 CurrentObjectAddresses[*Name] = Addr;
546 /// Lookup a symbol address in the main binary symbol table. The
547 /// parser only needs to query common symbols, thus not every symbol's
548 /// address is available through this function.
549 uint64_t MachODebugMapParser::getMainBinarySymbolAddress(StringRef Name) {
550 auto Sym = MainBinarySymbolAddresses.find(Name);
551 if (Sym == MainBinarySymbolAddresses.end())
552 return 0;
553 return Sym->second;
556 /// Get all symbol names in the main binary for the given value.
557 std::vector<StringRef>
558 MachODebugMapParser::getMainBinarySymbolNames(uint64_t Value) {
559 std::vector<StringRef> Names;
560 for (const auto &Entry : MainBinarySymbolAddresses) {
561 if (Entry.second == Value)
562 Names.push_back(Entry.first());
564 return Names;
567 /// Load the interesting main binary symbols' addresses into
568 /// MainBinarySymbolAddresses.
569 void MachODebugMapParser::loadMainBinarySymbols(
570 const MachOObjectFile &MainBinary) {
571 section_iterator Section = MainBinary.section_end();
572 MainBinarySymbolAddresses.clear();
573 for (const auto &Sym : MainBinary.symbols()) {
574 Expected<SymbolRef::Type> TypeOrErr = Sym.getType();
575 if (!TypeOrErr) {
576 auto Err = TypeOrErr.takeError();
577 Warning("failed to get symbol type: " + toString(std::move(Err)),
578 MainBinary.getFileName());
579 continue;
581 SymbolRef::Type Type = *TypeOrErr;
582 // Skip undefined and STAB entries.
583 if ((Type == SymbolRef::ST_Debug) || (Type == SymbolRef::ST_Unknown))
584 continue;
585 // In theory, the only symbols of interest are the global variables. These
586 // are the only ones that need to be queried because the address of common
587 // data won't be described in the debug map. All other addresses should be
588 // fetched for the debug map. In reality, by playing with 'ld -r' and
589 // export lists, you can get symbols described as N_GSYM in the debug map,
590 // but associated with a local symbol. Gather all the symbols, but prefer
591 // the global ones.
592 uint8_t SymType =
593 MainBinary.getSymbolTableEntry(Sym.getRawDataRefImpl()).n_type;
594 bool Extern = SymType & (MachO::N_EXT | MachO::N_PEXT);
595 Expected<section_iterator> SectionOrErr = Sym.getSection();
596 if (!SectionOrErr) {
597 auto Err = TypeOrErr.takeError();
598 Warning("failed to get symbol section: " + toString(std::move(Err)),
599 MainBinary.getFileName());
600 continue;
602 Section = *SectionOrErr;
603 if ((Section == MainBinary.section_end() || Section->isText()) && !Extern)
604 continue;
605 uint64_t Addr = cantFail(Sym.getValue());
606 Expected<StringRef> NameOrErr = Sym.getName();
607 if (!NameOrErr) {
608 auto Err = NameOrErr.takeError();
609 Warning("failed to get symbol name: " + toString(std::move(Err)),
610 MainBinary.getFileName());
611 continue;
613 StringRef Name = *NameOrErr;
614 if (Name.size() == 0 || Name[0] == '\0')
615 continue;
616 // Override only if the new key is global.
617 if (Extern)
618 MainBinarySymbolAddresses[Name] = Addr;
619 else
620 MainBinarySymbolAddresses.try_emplace(Name, Addr);
624 namespace llvm {
625 namespace dsymutil {
626 llvm::ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
627 parseDebugMap(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
628 StringRef InputFile, ArrayRef<std::string> Archs,
629 StringRef PrependPath, bool PaperTrailWarnings, bool Verbose,
630 bool InputIsYAML) {
631 if (InputIsYAML)
632 return DebugMap::parseYAMLDebugMap(InputFile, PrependPath, Verbose);
634 MachODebugMapParser Parser(VFS, InputFile, Archs, PrependPath,
635 PaperTrailWarnings, Verbose);
636 return Parser.parse();
639 bool dumpStab(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
640 StringRef InputFile, ArrayRef<std::string> Archs,
641 StringRef PrependPath) {
642 MachODebugMapParser Parser(VFS, InputFile, Archs, PrependPath, false);
643 return Parser.dumpStab();
645 } // namespace dsymutil
646 } // namespace llvm