]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / DebugInfo / Symbolize / Symbolize.cpp
1 //===-- LLVMSymbolize.cpp -------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Implementation for LLVM symbolization library.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "llvm/DebugInfo/Symbolize/Symbolize.h"
14
15 #include "SymbolizableObjectFile.h"
16
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/BinaryFormat/COFF.h"
19 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
20 #include "llvm/DebugInfo/PDB/PDB.h"
21 #include "llvm/DebugInfo/PDB/PDBContext.h"
22 #include "llvm/Demangle/Demangle.h"
23 #include "llvm/Object/COFF.h"
24 #include "llvm/Object/MachO.h"
25 #include "llvm/Object/MachOUniversal.h"
26 #include "llvm/Support/CRC.h"
27 #include "llvm/Support/Casting.h"
28 #include "llvm/Support/Compression.h"
29 #include "llvm/Support/DataExtractor.h"
30 #include "llvm/Support/Errc.h"
31 #include "llvm/Support/FileSystem.h"
32 #include "llvm/Support/MemoryBuffer.h"
33 #include "llvm/Support/Path.h"
34 #include <algorithm>
35 #include <cassert>
36 #include <cstring>
37
38 #if defined(_MSC_VER)
39 #include <Windows.h>
40
41 // This must be included after windows.h.
42 #include <DbgHelp.h>
43 #pragma comment(lib, "dbghelp.lib")
44
45 // Windows.h conflicts with our COFF header definitions.
46 #ifdef IMAGE_FILE_MACHINE_I386
47 #undef IMAGE_FILE_MACHINE_I386
48 #endif
49 #endif
50
51 namespace llvm {
52 namespace symbolize {
53
54 Expected<DILineInfo>
55 LLVMSymbolizer::symbolizeCodeCommon(SymbolizableModule *Info,
56                                     object::SectionedAddress ModuleOffset) {
57   // A null module means an error has already been reported. Return an empty
58   // result.
59   if (!Info)
60     return DILineInfo();
61
62   // If the user is giving us relative addresses, add the preferred base of the
63   // object to the offset before we do the query. It's what DIContext expects.
64   if (Opts.RelativeAddresses)
65     ModuleOffset.Address += Info->getModulePreferredBase();
66
67   DILineInfo LineInfo = Info->symbolizeCode(ModuleOffset, Opts.PrintFunctions,
68                                             Opts.UseSymbolTable);
69   if (Opts.Demangle)
70     LineInfo.FunctionName = DemangleName(LineInfo.FunctionName, Info);
71   return LineInfo;
72 }
73
74 Expected<DILineInfo>
75 LLVMSymbolizer::symbolizeCode(const ObjectFile &Obj,
76                               object::SectionedAddress ModuleOffset) {
77   StringRef ModuleName = Obj.getFileName();
78   auto I = Modules.find(ModuleName);
79   if (I != Modules.end())
80     return symbolizeCodeCommon(I->second.get(), ModuleOffset);
81
82   std::unique_ptr<DIContext> Context =
83         DWARFContext::create(Obj, nullptr, DWARFContext::defaultErrorHandler);
84   Expected<SymbolizableModule *> InfoOrErr =
85                      createModuleInfo(&Obj, std::move(Context), ModuleName);
86   if (!InfoOrErr)
87     return InfoOrErr.takeError();
88   return symbolizeCodeCommon(*InfoOrErr, ModuleOffset);
89 }
90
91 Expected<DILineInfo>
92 LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
93                               object::SectionedAddress ModuleOffset) {
94   Expected<SymbolizableModule *> InfoOrErr = getOrCreateModuleInfo(ModuleName);
95   if (!InfoOrErr)
96     return InfoOrErr.takeError();
97   return symbolizeCodeCommon(*InfoOrErr, ModuleOffset);
98 }
99
100 Expected<DIInliningInfo>
101 LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName,
102                                      object::SectionedAddress ModuleOffset) {
103   SymbolizableModule *Info;
104   if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName))
105     Info = InfoOrErr.get();
106   else
107     return InfoOrErr.takeError();
108
109   // A null module means an error has already been reported. Return an empty
110   // result.
111   if (!Info)
112     return DIInliningInfo();
113
114   // If the user is giving us relative addresses, add the preferred base of the
115   // object to the offset before we do the query. It's what DIContext expects.
116   if (Opts.RelativeAddresses)
117     ModuleOffset.Address += Info->getModulePreferredBase();
118
119   DIInliningInfo InlinedContext = Info->symbolizeInlinedCode(
120       ModuleOffset, Opts.PrintFunctions, Opts.UseSymbolTable);
121   if (Opts.Demangle) {
122     for (int i = 0, n = InlinedContext.getNumberOfFrames(); i < n; i++) {
123       auto *Frame = InlinedContext.getMutableFrame(i);
124       Frame->FunctionName = DemangleName(Frame->FunctionName, Info);
125     }
126   }
127   return InlinedContext;
128 }
129
130 Expected<DIGlobal>
131 LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
132                               object::SectionedAddress ModuleOffset) {
133   SymbolizableModule *Info;
134   if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName))
135     Info = InfoOrErr.get();
136   else
137     return InfoOrErr.takeError();
138
139   // A null module means an error has already been reported. Return an empty
140   // result.
141   if (!Info)
142     return DIGlobal();
143
144   // If the user is giving us relative addresses, add the preferred base of
145   // the object to the offset before we do the query. It's what DIContext
146   // expects.
147   if (Opts.RelativeAddresses)
148     ModuleOffset.Address += Info->getModulePreferredBase();
149
150   DIGlobal Global = Info->symbolizeData(ModuleOffset);
151   if (Opts.Demangle)
152     Global.Name = DemangleName(Global.Name, Info);
153   return Global;
154 }
155
156 Expected<std::vector<DILocal>>
157 LLVMSymbolizer::symbolizeFrame(const std::string &ModuleName,
158                                object::SectionedAddress ModuleOffset) {
159   SymbolizableModule *Info;
160   if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName))
161     Info = InfoOrErr.get();
162   else
163     return InfoOrErr.takeError();
164
165   // A null module means an error has already been reported. Return an empty
166   // result.
167   if (!Info)
168     return std::vector<DILocal>();
169
170   // If the user is giving us relative addresses, add the preferred base of
171   // the object to the offset before we do the query. It's what DIContext
172   // expects.
173   if (Opts.RelativeAddresses)
174     ModuleOffset.Address += Info->getModulePreferredBase();
175
176   return Info->symbolizeFrame(ModuleOffset);
177 }
178
179 void LLVMSymbolizer::flush() {
180   ObjectForUBPathAndArch.clear();
181   BinaryForPath.clear();
182   ObjectPairForPathArch.clear();
183   Modules.clear();
184 }
185
186 namespace {
187
188 // For Path="/path/to/foo" and Basename="foo" assume that debug info is in
189 // /path/to/foo.dSYM/Contents/Resources/DWARF/foo.
190 // For Path="/path/to/bar.dSYM" and Basename="foo" assume that debug info is in
191 // /path/to/bar.dSYM/Contents/Resources/DWARF/foo.
192 std::string getDarwinDWARFResourceForPath(
193     const std::string &Path, const std::string &Basename) {
194   SmallString<16> ResourceName = StringRef(Path);
195   if (sys::path::extension(Path) != ".dSYM") {
196     ResourceName += ".dSYM";
197   }
198   sys::path::append(ResourceName, "Contents", "Resources", "DWARF");
199   sys::path::append(ResourceName, Basename);
200   return ResourceName.str();
201 }
202
203 bool checkFileCRC(StringRef Path, uint32_t CRCHash) {
204   ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
205       MemoryBuffer::getFileOrSTDIN(Path);
206   if (!MB)
207     return false;
208   return CRCHash == llvm::crc32(0, MB.get()->getBuffer());
209 }
210
211 bool findDebugBinary(const std::string &OrigPath,
212                      const std::string &DebuglinkName, uint32_t CRCHash,
213                      const std::string &FallbackDebugPath,
214                      std::string &Result) {
215   SmallString<16> OrigDir(OrigPath);
216   llvm::sys::path::remove_filename(OrigDir);
217   SmallString<16> DebugPath = OrigDir;
218   // Try relative/path/to/original_binary/debuglink_name
219   llvm::sys::path::append(DebugPath, DebuglinkName);
220   if (checkFileCRC(DebugPath, CRCHash)) {
221     Result = DebugPath.str();
222     return true;
223   }
224   // Try relative/path/to/original_binary/.debug/debuglink_name
225   DebugPath = OrigDir;
226   llvm::sys::path::append(DebugPath, ".debug", DebuglinkName);
227   if (checkFileCRC(DebugPath, CRCHash)) {
228     Result = DebugPath.str();
229     return true;
230   }
231   // Make the path absolute so that lookups will go to
232   // "/usr/lib/debug/full/path/to/debug", not
233   // "/usr/lib/debug/to/debug"
234   llvm::sys::fs::make_absolute(OrigDir);
235   if (!FallbackDebugPath.empty()) {
236     // Try <FallbackDebugPath>/absolute/path/to/original_binary/debuglink_name
237     DebugPath = FallbackDebugPath;
238   } else {
239 #if defined(__NetBSD__)
240     // Try /usr/libdata/debug/absolute/path/to/original_binary/debuglink_name
241     DebugPath = "/usr/libdata/debug";
242 #else
243     // Try /usr/lib/debug/absolute/path/to/original_binary/debuglink_name
244     DebugPath = "/usr/lib/debug";
245 #endif
246   }
247   llvm::sys::path::append(DebugPath, llvm::sys::path::relative_path(OrigDir),
248                           DebuglinkName);
249   if (checkFileCRC(DebugPath, CRCHash)) {
250     Result = DebugPath.str();
251     return true;
252   }
253   return false;
254 }
255
256 bool getGNUDebuglinkContents(const ObjectFile *Obj, std::string &DebugName,
257                              uint32_t &CRCHash) {
258   if (!Obj)
259     return false;
260   for (const SectionRef &Section : Obj->sections()) {
261     StringRef Name;
262     Section.getName(Name);
263     Name = Name.substr(Name.find_first_not_of("._"));
264     if (Name == "gnu_debuglink") {
265       Expected<StringRef> ContentsOrErr = Section.getContents();
266       if (!ContentsOrErr) {
267         consumeError(ContentsOrErr.takeError());
268         return false;
269       }
270       DataExtractor DE(*ContentsOrErr, Obj->isLittleEndian(), 0);
271       uint32_t Offset = 0;
272       if (const char *DebugNameStr = DE.getCStr(&Offset)) {
273         // 4-byte align the offset.
274         Offset = (Offset + 3) & ~0x3;
275         if (DE.isValidOffsetForDataOfSize(Offset, 4)) {
276           DebugName = DebugNameStr;
277           CRCHash = DE.getU32(&Offset);
278           return true;
279         }
280       }
281       break;
282     }
283   }
284   return false;
285 }
286
287 bool darwinDsymMatchesBinary(const MachOObjectFile *DbgObj,
288                              const MachOObjectFile *Obj) {
289   ArrayRef<uint8_t> dbg_uuid = DbgObj->getUuid();
290   ArrayRef<uint8_t> bin_uuid = Obj->getUuid();
291   if (dbg_uuid.empty() || bin_uuid.empty())
292     return false;
293   return !memcmp(dbg_uuid.data(), bin_uuid.data(), dbg_uuid.size());
294 }
295
296 } // end anonymous namespace
297
298 ObjectFile *LLVMSymbolizer::lookUpDsymFile(const std::string &ExePath,
299     const MachOObjectFile *MachExeObj, const std::string &ArchName) {
300   // On Darwin we may find DWARF in separate object file in
301   // resource directory.
302   std::vector<std::string> DsymPaths;
303   StringRef Filename = sys::path::filename(ExePath);
304   DsymPaths.push_back(getDarwinDWARFResourceForPath(ExePath, Filename));
305   for (const auto &Path : Opts.DsymHints) {
306     DsymPaths.push_back(getDarwinDWARFResourceForPath(Path, Filename));
307   }
308   for (const auto &Path : DsymPaths) {
309     auto DbgObjOrErr = getOrCreateObject(Path, ArchName);
310     if (!DbgObjOrErr) {
311       // Ignore errors, the file might not exist.
312       consumeError(DbgObjOrErr.takeError());
313       continue;
314     }
315     ObjectFile *DbgObj = DbgObjOrErr.get();
316     if (!DbgObj)
317       continue;
318     const MachOObjectFile *MachDbgObj = dyn_cast<const MachOObjectFile>(DbgObj);
319     if (!MachDbgObj)
320       continue;
321     if (darwinDsymMatchesBinary(MachDbgObj, MachExeObj))
322       return DbgObj;
323   }
324   return nullptr;
325 }
326
327 ObjectFile *LLVMSymbolizer::lookUpDebuglinkObject(const std::string &Path,
328                                                   const ObjectFile *Obj,
329                                                   const std::string &ArchName) {
330   std::string DebuglinkName;
331   uint32_t CRCHash;
332   std::string DebugBinaryPath;
333   if (!getGNUDebuglinkContents(Obj, DebuglinkName, CRCHash))
334     return nullptr;
335   if (!findDebugBinary(Path, DebuglinkName, CRCHash, Opts.FallbackDebugPath,
336                        DebugBinaryPath))
337     return nullptr;
338   auto DbgObjOrErr = getOrCreateObject(DebugBinaryPath, ArchName);
339   if (!DbgObjOrErr) {
340     // Ignore errors, the file might not exist.
341     consumeError(DbgObjOrErr.takeError());
342     return nullptr;
343   }
344   return DbgObjOrErr.get();
345 }
346
347 Expected<LLVMSymbolizer::ObjectPair>
348 LLVMSymbolizer::getOrCreateObjectPair(const std::string &Path,
349                                       const std::string &ArchName) {
350   auto I = ObjectPairForPathArch.find(std::make_pair(Path, ArchName));
351   if (I != ObjectPairForPathArch.end())
352     return I->second;
353
354   auto ObjOrErr = getOrCreateObject(Path, ArchName);
355   if (!ObjOrErr) {
356     ObjectPairForPathArch.emplace(std::make_pair(Path, ArchName),
357                                   ObjectPair(nullptr, nullptr));
358     return ObjOrErr.takeError();
359   }
360
361   ObjectFile *Obj = ObjOrErr.get();
362   assert(Obj != nullptr);
363   ObjectFile *DbgObj = nullptr;
364
365   if (auto MachObj = dyn_cast<const MachOObjectFile>(Obj))
366     DbgObj = lookUpDsymFile(Path, MachObj, ArchName);
367   if (!DbgObj)
368     DbgObj = lookUpDebuglinkObject(Path, Obj, ArchName);
369   if (!DbgObj)
370     DbgObj = Obj;
371   ObjectPair Res = std::make_pair(Obj, DbgObj);
372   ObjectPairForPathArch.emplace(std::make_pair(Path, ArchName), Res);
373   return Res;
374 }
375
376 Expected<ObjectFile *>
377 LLVMSymbolizer::getOrCreateObject(const std::string &Path,
378                                   const std::string &ArchName) {
379   Binary *Bin;
380   auto Pair = BinaryForPath.emplace(Path, OwningBinary<Binary>());
381   if (!Pair.second) {
382     Bin = Pair.first->second.getBinary();
383   } else {
384     Expected<OwningBinary<Binary>> BinOrErr = createBinary(Path);
385     if (!BinOrErr)
386       return BinOrErr.takeError();
387     Pair.first->second = std::move(BinOrErr.get());
388     Bin = Pair.first->second.getBinary();
389   }
390
391   if (!Bin)
392     return static_cast<ObjectFile *>(nullptr);
393
394   if (MachOUniversalBinary *UB = dyn_cast_or_null<MachOUniversalBinary>(Bin)) {
395     auto I = ObjectForUBPathAndArch.find(std::make_pair(Path, ArchName));
396     if (I != ObjectForUBPathAndArch.end())
397       return I->second.get();
398
399     Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
400         UB->getObjectForArch(ArchName);
401     if (!ObjOrErr) {
402       ObjectForUBPathAndArch.emplace(std::make_pair(Path, ArchName),
403                                      std::unique_ptr<ObjectFile>());
404       return ObjOrErr.takeError();
405     }
406     ObjectFile *Res = ObjOrErr->get();
407     ObjectForUBPathAndArch.emplace(std::make_pair(Path, ArchName),
408                                    std::move(ObjOrErr.get()));
409     return Res;
410   }
411   if (Bin->isObject()) {
412     return cast<ObjectFile>(Bin);
413   }
414   return errorCodeToError(object_error::arch_not_found);
415 }
416
417 Expected<SymbolizableModule *>
418 LLVMSymbolizer::createModuleInfo(const ObjectFile *Obj,
419                                  std::unique_ptr<DIContext> Context,
420                                  StringRef ModuleName) {
421   auto InfoOrErr =
422       SymbolizableObjectFile::create(Obj, std::move(Context));
423   std::unique_ptr<SymbolizableModule> SymMod;
424   if (InfoOrErr)
425     SymMod = std::move(*InfoOrErr);
426   auto InsertResult =
427       Modules.insert(std::make_pair(ModuleName, std::move(SymMod)));
428   assert(InsertResult.second);
429   if (std::error_code EC = InfoOrErr.getError())
430     return errorCodeToError(EC);
431   return InsertResult.first->second.get();
432 }
433
434 Expected<SymbolizableModule *>
435 LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
436   auto I = Modules.find(ModuleName);
437   if (I != Modules.end())
438     return I->second.get();
439
440   std::string BinaryName = ModuleName;
441   std::string ArchName = Opts.DefaultArch;
442   size_t ColonPos = ModuleName.find_last_of(':');
443   // Verify that substring after colon form a valid arch name.
444   if (ColonPos != std::string::npos) {
445     std::string ArchStr = ModuleName.substr(ColonPos + 1);
446     if (Triple(ArchStr).getArch() != Triple::UnknownArch) {
447       BinaryName = ModuleName.substr(0, ColonPos);
448       ArchName = ArchStr;
449     }
450   }
451   auto ObjectsOrErr = getOrCreateObjectPair(BinaryName, ArchName);
452   if (!ObjectsOrErr) {
453     // Failed to find valid object file.
454     Modules.emplace(ModuleName, std::unique_ptr<SymbolizableModule>());
455     return ObjectsOrErr.takeError();
456   }
457   ObjectPair Objects = ObjectsOrErr.get();
458
459   std::unique_ptr<DIContext> Context;
460   // If this is a COFF object containing PDB info, use a PDBContext to
461   // symbolize. Otherwise, use DWARF.
462   if (auto CoffObject = dyn_cast<COFFObjectFile>(Objects.first)) {
463     const codeview::DebugInfo *DebugInfo;
464     StringRef PDBFileName;
465     auto EC = CoffObject->getDebugPDBInfo(DebugInfo, PDBFileName);
466     if (!EC && DebugInfo != nullptr && !PDBFileName.empty()) {
467 #if 0
468       using namespace pdb;
469       std::unique_ptr<IPDBSession> Session;
470       if (auto Err = loadDataForEXE(PDB_ReaderType::DIA,
471                                     Objects.first->getFileName(), Session)) {
472         Modules.emplace(ModuleName, std::unique_ptr<SymbolizableModule>());
473         // Return along the PDB filename to provide more context
474         return createFileError(PDBFileName, std::move(Err));
475       }
476       Context.reset(new PDBContext(*CoffObject, std::move(Session)));
477 #else
478       return make_error<StringError>(
479           "PDB support not compiled in",
480           std::make_error_code(std::errc::not_supported));
481 #endif
482     }
483   }
484   if (!Context)
485     Context =
486         DWARFContext::create(*Objects.second, nullptr,
487                              DWARFContext::defaultErrorHandler, Opts.DWPName);
488   return createModuleInfo(Objects.first, std::move(Context), ModuleName);
489 }
490
491 namespace {
492
493 // Undo these various manglings for Win32 extern "C" functions:
494 // cdecl       - _foo
495 // stdcall     - _foo@12
496 // fastcall    - @foo@12
497 // vectorcall  - foo@@12
498 // These are all different linkage names for 'foo'.
499 StringRef demanglePE32ExternCFunc(StringRef SymbolName) {
500   // Remove any '_' or '@' prefix.
501   char Front = SymbolName.empty() ? '\0' : SymbolName[0];
502   if (Front == '_' || Front == '@')
503     SymbolName = SymbolName.drop_front();
504
505   // Remove any '@[0-9]+' suffix.
506   if (Front != '?') {
507     size_t AtPos = SymbolName.rfind('@');
508     if (AtPos != StringRef::npos &&
509         std::all_of(SymbolName.begin() + AtPos + 1, SymbolName.end(),
510                     [](char C) { return C >= '0' && C <= '9'; })) {
511       SymbolName = SymbolName.substr(0, AtPos);
512     }
513   }
514
515   // Remove any ending '@' for vectorcall.
516   if (SymbolName.endswith("@"))
517     SymbolName = SymbolName.drop_back();
518
519   return SymbolName;
520 }
521
522 } // end anonymous namespace
523
524 std::string
525 LLVMSymbolizer::DemangleName(const std::string &Name,
526                              const SymbolizableModule *DbiModuleDescriptor) {
527   // We can spoil names of symbols with C linkage, so use an heuristic
528   // approach to check if the name should be demangled.
529   if (Name.substr(0, 2) == "_Z") {
530     int status = 0;
531     char *DemangledName = itaniumDemangle(Name.c_str(), nullptr, nullptr, &status);
532     if (status != 0)
533       return Name;
534     std::string Result = DemangledName;
535     free(DemangledName);
536     return Result;
537   }
538
539 #if defined(_MSC_VER)
540   if (!Name.empty() && Name.front() == '?') {
541     // Only do MSVC C++ demangling on symbols starting with '?'.
542     char DemangledName[1024] = {0};
543     DWORD result = ::UnDecorateSymbolName(
544         Name.c_str(), DemangledName, 1023,
545         UNDNAME_NO_ACCESS_SPECIFIERS |       // Strip public, private, protected
546             UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall, etc
547             UNDNAME_NO_THROW_SIGNATURES |    // Strip throw() specifications
548             UNDNAME_NO_MEMBER_TYPE | // Strip virtual, static, etc specifiers
549             UNDNAME_NO_MS_KEYWORDS | // Strip all MS extension keywords
550             UNDNAME_NO_FUNCTION_RETURNS); // Strip function return types
551     return (result == 0) ? Name : std::string(DemangledName);
552   }
553 #endif
554   if (DbiModuleDescriptor && DbiModuleDescriptor->isWin32Module())
555     return std::string(demanglePE32ExternCFunc(Name));
556   return Name;
557 }
558
559 } // namespace symbolize
560 } // namespace llvm