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