OSDN Git Service

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