Simplify getSymbolType.
[oota-llvm.git] / tools / llvm-symbolizer / LLVMSymbolize.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 "LLVMSymbolize.h"
15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/Config/config.h"
17 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
18 #include "llvm/DebugInfo/PDB/PDB.h"
19 #include "llvm/DebugInfo/PDB/PDBContext.h"
20 #include "llvm/Object/ELFObjectFile.h"
21 #include "llvm/Object/MachO.h"
22 #include "llvm/Object/SymbolSize.h"
23 #include "llvm/Support/Casting.h"
24 #include "llvm/Support/Compression.h"
25 #include "llvm/Support/DataExtractor.h"
26 #include "llvm/Support/Errc.h"
27 #include "llvm/Support/FileSystem.h"
28 #include "llvm/Support/MemoryBuffer.h"
29 #include "llvm/Support/Path.h"
30 #include <sstream>
31 #include <stdlib.h>
32
33 #if defined(_MSC_VER)
34 #include <Windows.h>
35 #include <DbgHelp.h>
36 #endif
37
38 namespace llvm {
39 namespace symbolize {
40
41 static bool error(std::error_code ec) {
42   if (!ec)
43     return false;
44   errs() << "LLVMSymbolizer: error reading file: " << ec.message() << ".\n";
45   return true;
46 }
47
48 static DILineInfoSpecifier
49 getDILineInfoSpecifier(const LLVMSymbolizer::Options &Opts) {
50   return DILineInfoSpecifier(
51       DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
52       Opts.PrintFunctions);
53 }
54
55 ModuleInfo::ModuleInfo(ObjectFile *Obj, DIContext *DICtx)
56     : Module(Obj), DebugInfoContext(DICtx) {
57   std::unique_ptr<DataExtractor> OpdExtractor;
58   uint64_t OpdAddress = 0;
59   // Find the .opd (function descriptor) section if any, for big-endian
60   // PowerPC64 ELF.
61   if (Module->getArch() == Triple::ppc64) {
62     for (section_iterator Section : Module->sections()) {
63       StringRef Name;
64       if (!error(Section->getName(Name)) && Name == ".opd") {
65         StringRef Data;
66         if (!error(Section->getContents(Data))) {
67           OpdExtractor.reset(new DataExtractor(Data, Module->isLittleEndian(),
68                                                Module->getBytesInAddress()));
69           OpdAddress = Section->getAddress();
70         }
71         break;
72       }
73     }
74   }
75   std::vector<std::pair<SymbolRef, uint64_t>> Symbols =
76       computeSymbolSizes(*Module);
77   for (auto &P : Symbols)
78     addSymbol(P.first, P.second, OpdExtractor.get(), OpdAddress);
79 }
80
81 void ModuleInfo::addSymbol(const SymbolRef &Symbol, uint64_t SymbolSize,
82                            DataExtractor *OpdExtractor, uint64_t OpdAddress) {
83   SymbolRef::Type SymbolType = Symbol.getType();
84   if (SymbolType != SymbolRef::ST_Function && SymbolType != SymbolRef::ST_Data)
85     return;
86   uint64_t SymbolAddress;
87   if (error(Symbol.getAddress(SymbolAddress)) ||
88       SymbolAddress == UnknownAddress)
89     return;
90   if (OpdExtractor) {
91     // For big-endian PowerPC64 ELF, symbols in the .opd section refer to
92     // function descriptors. The first word of the descriptor is a pointer to
93     // the function's code.
94     // For the purposes of symbolization, pretend the symbol's address is that
95     // of the function's code, not the descriptor.
96     uint64_t OpdOffset = SymbolAddress - OpdAddress;
97     uint32_t OpdOffset32 = OpdOffset;
98     if (OpdOffset == OpdOffset32 && 
99         OpdExtractor->isValidOffsetForAddress(OpdOffset32))
100       SymbolAddress = OpdExtractor->getAddress(&OpdOffset32);
101   }
102   StringRef SymbolName;
103   if (error(Symbol.getName(SymbolName)))
104     return;
105   // Mach-O symbol table names have leading underscore, skip it.
106   if (Module->isMachO() && SymbolName.size() > 0 && SymbolName[0] == '_')
107     SymbolName = SymbolName.drop_front();
108   // FIXME: If a function has alias, there are two entries in symbol table
109   // with same address size. Make sure we choose the correct one.
110   auto &M = SymbolType == SymbolRef::ST_Function ? Functions : Objects;
111   SymbolDesc SD = { SymbolAddress, SymbolSize };
112   M.insert(std::make_pair(SD, SymbolName));
113 }
114
115 bool ModuleInfo::getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address,
116                                         std::string &Name, uint64_t &Addr,
117                                         uint64_t &Size) const {
118   const auto &SymbolMap = Type == SymbolRef::ST_Function ? Functions : Objects;
119   if (SymbolMap.empty())
120     return false;
121   SymbolDesc SD = { Address, Address };
122   auto SymbolIterator = SymbolMap.upper_bound(SD);
123   if (SymbolIterator == SymbolMap.begin())
124     return false;
125   --SymbolIterator;
126   if (SymbolIterator->first.Size != 0 &&
127       SymbolIterator->first.Addr + SymbolIterator->first.Size <= Address)
128     return false;
129   Name = SymbolIterator->second.str();
130   Addr = SymbolIterator->first.Addr;
131   Size = SymbolIterator->first.Size;
132   return true;
133 }
134
135 DILineInfo ModuleInfo::symbolizeCode(
136     uint64_t ModuleOffset, const LLVMSymbolizer::Options &Opts) const {
137   DILineInfo LineInfo;
138   if (DebugInfoContext) {
139     LineInfo = DebugInfoContext->getLineInfoForAddress(
140         ModuleOffset, getDILineInfoSpecifier(Opts));
141   }
142   // Override function name from symbol table if necessary.
143   if (Opts.PrintFunctions != FunctionNameKind::None && Opts.UseSymbolTable) {
144     std::string FunctionName;
145     uint64_t Start, Size;
146     if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset,
147                                FunctionName, Start, Size)) {
148       LineInfo.FunctionName = FunctionName;
149     }
150   }
151   return LineInfo;
152 }
153
154 DIInliningInfo ModuleInfo::symbolizeInlinedCode(
155     uint64_t ModuleOffset, const LLVMSymbolizer::Options &Opts) const {
156   DIInliningInfo InlinedContext;
157
158   if (DebugInfoContext) {
159     InlinedContext = DebugInfoContext->getInliningInfoForAddress(
160         ModuleOffset, getDILineInfoSpecifier(Opts));
161   }
162   // Make sure there is at least one frame in context.
163   if (InlinedContext.getNumberOfFrames() == 0) {
164     InlinedContext.addFrame(DILineInfo());
165   }
166   // Override the function name in lower frame with name from symbol table.
167   if (Opts.PrintFunctions != FunctionNameKind::None && Opts.UseSymbolTable) {
168     DIInliningInfo PatchedInlinedContext;
169     for (uint32_t i = 0, n = InlinedContext.getNumberOfFrames(); i < n; i++) {
170       DILineInfo LineInfo = InlinedContext.getFrame(i);
171       if (i == n - 1) {
172         std::string FunctionName;
173         uint64_t Start, Size;
174         if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset,
175                                    FunctionName, Start, Size)) {
176           LineInfo.FunctionName = FunctionName;
177         }
178       }
179       PatchedInlinedContext.addFrame(LineInfo);
180     }
181     InlinedContext = PatchedInlinedContext;
182   }
183   return InlinedContext;
184 }
185
186 bool ModuleInfo::symbolizeData(uint64_t ModuleOffset, std::string &Name,
187                                uint64_t &Start, uint64_t &Size) const {
188   return getNameFromSymbolTable(SymbolRef::ST_Data, ModuleOffset, Name, Start,
189                                 Size);
190 }
191
192 const char LLVMSymbolizer::kBadString[] = "??";
193
194 std::string LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
195                                           uint64_t ModuleOffset) {
196   ModuleInfo *Info = getOrCreateModuleInfo(ModuleName);
197   if (!Info)
198     return printDILineInfo(DILineInfo());
199   if (Opts.PrintInlining) {
200     DIInliningInfo InlinedContext =
201         Info->symbolizeInlinedCode(ModuleOffset, Opts);
202     uint32_t FramesNum = InlinedContext.getNumberOfFrames();
203     assert(FramesNum > 0);
204     std::string Result;
205     for (uint32_t i = 0; i < FramesNum; i++) {
206       DILineInfo LineInfo = InlinedContext.getFrame(i);
207       Result += printDILineInfo(LineInfo);
208     }
209     return Result;
210   }
211   DILineInfo LineInfo = Info->symbolizeCode(ModuleOffset, Opts);
212   return printDILineInfo(LineInfo);
213 }
214
215 std::string LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
216                                           uint64_t ModuleOffset) {
217   std::string Name = kBadString;
218   uint64_t Start = 0;
219   uint64_t Size = 0;
220   if (Opts.UseSymbolTable) {
221     if (ModuleInfo *Info = getOrCreateModuleInfo(ModuleName)) {
222       if (Info->symbolizeData(ModuleOffset, Name, Start, Size) && Opts.Demangle)
223         Name = DemangleName(Name);
224     }
225   }
226   std::stringstream ss;
227   ss << Name << "\n" << Start << " " << Size << "\n";
228   return ss.str();
229 }
230
231 void LLVMSymbolizer::flush() {
232   DeleteContainerSeconds(Modules);
233   ObjectPairForPathArch.clear();
234   ObjectFileForArch.clear();
235 }
236
237 // For Path="/path/to/foo" and Basename="foo" assume that debug info is in
238 // /path/to/foo.dSYM/Contents/Resources/DWARF/foo.
239 // For Path="/path/to/bar.dSYM" and Basename="foo" assume that debug info is in
240 // /path/to/bar.dSYM/Contents/Resources/DWARF/foo.
241 static
242 std::string getDarwinDWARFResourceForPath(
243     const std::string &Path, const std::string &Basename) {
244   SmallString<16> ResourceName = StringRef(Path);
245   if (sys::path::extension(Path) != ".dSYM") {
246     ResourceName += ".dSYM";
247   }
248   sys::path::append(ResourceName, "Contents", "Resources", "DWARF");
249   sys::path::append(ResourceName, Basename);
250   return ResourceName.str();
251 }
252
253 static bool checkFileCRC(StringRef Path, uint32_t CRCHash) {
254   ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
255       MemoryBuffer::getFileOrSTDIN(Path);
256   if (!MB)
257     return false;
258   return !zlib::isAvailable() || CRCHash == zlib::crc32(MB.get()->getBuffer());
259 }
260
261 static bool findDebugBinary(const std::string &OrigPath,
262                             const std::string &DebuglinkName, uint32_t CRCHash,
263                             std::string &Result) {
264   std::string OrigRealPath = OrigPath;
265 #if defined(HAVE_REALPATH)
266   if (char *RP = realpath(OrigPath.c_str(), nullptr)) {
267     OrigRealPath = RP;
268     free(RP);
269   }
270 #endif
271   SmallString<16> OrigDir(OrigRealPath);
272   llvm::sys::path::remove_filename(OrigDir);
273   SmallString<16> DebugPath = OrigDir;
274   // Try /path/to/original_binary/debuglink_name
275   llvm::sys::path::append(DebugPath, DebuglinkName);
276   if (checkFileCRC(DebugPath, CRCHash)) {
277     Result = DebugPath.str();
278     return true;
279   }
280   // Try /path/to/original_binary/.debug/debuglink_name
281   DebugPath = OrigRealPath;
282   llvm::sys::path::append(DebugPath, ".debug", DebuglinkName);
283   if (checkFileCRC(DebugPath, CRCHash)) {
284     Result = DebugPath.str();
285     return true;
286   }
287   // Try /usr/lib/debug/path/to/original_binary/debuglink_name
288   DebugPath = "/usr/lib/debug";
289   llvm::sys::path::append(DebugPath, llvm::sys::path::relative_path(OrigDir),
290                           DebuglinkName);
291   if (checkFileCRC(DebugPath, CRCHash)) {
292     Result = DebugPath.str();
293     return true;
294   }
295   return false;
296 }
297
298 static bool getGNUDebuglinkContents(const ObjectFile *Obj, std::string &DebugName,
299                                     uint32_t &CRCHash) {
300   if (!Obj)
301     return false;
302   for (const SectionRef &Section : Obj->sections()) {
303     StringRef Name;
304     Section.getName(Name);
305     Name = Name.substr(Name.find_first_not_of("._"));
306     if (Name == "gnu_debuglink") {
307       StringRef Data;
308       Section.getContents(Data);
309       DataExtractor DE(Data, Obj->isLittleEndian(), 0);
310       uint32_t Offset = 0;
311       if (const char *DebugNameStr = DE.getCStr(&Offset)) {
312         // 4-byte align the offset.
313         Offset = (Offset + 3) & ~0x3;
314         if (DE.isValidOffsetForDataOfSize(Offset, 4)) {
315           DebugName = DebugNameStr;
316           CRCHash = DE.getU32(&Offset);
317           return true;
318         }
319       }
320       break;
321     }
322   }
323   return false;
324 }
325
326 static
327 bool darwinDsymMatchesBinary(const MachOObjectFile *DbgObj,
328                              const MachOObjectFile *Obj) {
329   ArrayRef<uint8_t> dbg_uuid = DbgObj->getUuid();
330   ArrayRef<uint8_t> bin_uuid = Obj->getUuid();
331   if (dbg_uuid.empty() || bin_uuid.empty())
332     return false;
333   return !memcmp(dbg_uuid.data(), bin_uuid.data(), dbg_uuid.size());
334 }
335
336 ObjectFile *LLVMSymbolizer::lookUpDsymFile(const std::string &ExePath,
337     const MachOObjectFile *MachExeObj, const std::string &ArchName) {
338   // On Darwin we may find DWARF in separate object file in
339   // resource directory.
340   std::vector<std::string> DsymPaths;
341   StringRef Filename = sys::path::filename(ExePath);
342   DsymPaths.push_back(getDarwinDWARFResourceForPath(ExePath, Filename));
343   for (const auto &Path : Opts.DsymHints) {
344     DsymPaths.push_back(getDarwinDWARFResourceForPath(Path, Filename));
345   }
346   for (const auto &path : DsymPaths) {
347     ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(path);
348     std::error_code EC = BinaryOrErr.getError();
349     if (EC != errc::no_such_file_or_directory && !error(EC)) {
350       OwningBinary<Binary> B = std::move(BinaryOrErr.get());
351       ObjectFile *DbgObj =
352           getObjectFileFromBinary(B.getBinary(), ArchName);
353       const MachOObjectFile *MachDbgObj =
354           dyn_cast<const MachOObjectFile>(DbgObj);
355       if (!MachDbgObj) continue;
356       if (darwinDsymMatchesBinary(MachDbgObj, MachExeObj)) {
357         addOwningBinary(std::move(B));
358         return DbgObj; 
359       }
360     }
361   }
362   return nullptr;
363 }
364
365 LLVMSymbolizer::ObjectPair
366 LLVMSymbolizer::getOrCreateObjects(const std::string &Path,
367                                    const std::string &ArchName) {
368   const auto &I = ObjectPairForPathArch.find(std::make_pair(Path, ArchName));
369   if (I != ObjectPairForPathArch.end())
370     return I->second;
371   ObjectFile *Obj = nullptr;
372   ObjectFile *DbgObj = nullptr;
373   ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(Path);
374   if (!error(BinaryOrErr.getError())) {
375     OwningBinary<Binary> &B = BinaryOrErr.get();
376     Obj = getObjectFileFromBinary(B.getBinary(), ArchName);
377     if (!Obj) {
378       ObjectPair Res = std::make_pair(nullptr, nullptr);
379       ObjectPairForPathArch[std::make_pair(Path, ArchName)] = Res;
380       return Res;
381     }
382     addOwningBinary(std::move(B));
383     if (auto MachObj = dyn_cast<const MachOObjectFile>(Obj))
384       DbgObj = lookUpDsymFile(Path, MachObj, ArchName);
385     // Try to locate the debug binary using .gnu_debuglink section.
386     if (!DbgObj) {
387       std::string DebuglinkName;
388       uint32_t CRCHash;
389       std::string DebugBinaryPath;
390       if (getGNUDebuglinkContents(Obj, DebuglinkName, CRCHash) &&
391           findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath)) {
392         BinaryOrErr = createBinary(DebugBinaryPath);
393         if (!error(BinaryOrErr.getError())) {
394           OwningBinary<Binary> B = std::move(BinaryOrErr.get());
395           DbgObj = getObjectFileFromBinary(B.getBinary(), ArchName);
396           addOwningBinary(std::move(B));
397         }
398       }
399     }
400   }
401   if (!DbgObj)
402     DbgObj = Obj;
403   ObjectPair Res = std::make_pair(Obj, DbgObj);
404   ObjectPairForPathArch[std::make_pair(Path, ArchName)] = Res;
405   return Res;
406 }
407
408 ObjectFile *
409 LLVMSymbolizer::getObjectFileFromBinary(Binary *Bin,
410                                         const std::string &ArchName) {
411   if (!Bin)
412     return nullptr;
413   ObjectFile *Res = nullptr;
414   if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(Bin)) {
415     const auto &I = ObjectFileForArch.find(
416         std::make_pair(UB, ArchName));
417     if (I != ObjectFileForArch.end())
418       return I->second;
419     ErrorOr<std::unique_ptr<ObjectFile>> ParsedObj =
420         UB->getObjectForArch(ArchName);
421     if (ParsedObj) {
422       Res = ParsedObj.get().get();
423       ParsedBinariesAndObjects.push_back(std::move(ParsedObj.get()));
424     }
425     ObjectFileForArch[std::make_pair(UB, ArchName)] = Res;
426   } else if (Bin->isObject()) {
427     Res = cast<ObjectFile>(Bin);
428   }
429   return Res;
430 }
431
432 ModuleInfo *
433 LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
434   const auto &I = Modules.find(ModuleName);
435   if (I != Modules.end())
436     return I->second;
437   std::string BinaryName = ModuleName;
438   std::string ArchName = Opts.DefaultArch;
439   size_t ColonPos = ModuleName.find_last_of(':');
440   // Verify that substring after colon form a valid arch name.
441   if (ColonPos != std::string::npos) {
442     std::string ArchStr = ModuleName.substr(ColonPos + 1);
443     if (Triple(ArchStr).getArch() != Triple::UnknownArch) {
444       BinaryName = ModuleName.substr(0, ColonPos);
445       ArchName = ArchStr;
446     }
447   }
448   ObjectPair Objects = getOrCreateObjects(BinaryName, ArchName);
449
450   if (!Objects.first) {
451     // Failed to find valid object file.
452     Modules.insert(make_pair(ModuleName, (ModuleInfo *)nullptr));
453     return nullptr;
454   }
455   DIContext *Context = nullptr;
456   if (auto CoffObject = dyn_cast<COFFObjectFile>(Objects.first)) {
457     // If this is a COFF object, assume it contains PDB debug information.  If
458     // we don't find any we will fall back to the DWARF case.
459     std::unique_ptr<IPDBSession> Session;
460     PDB_ErrorCode Error = loadDataForEXE(PDB_ReaderType::DIA,
461                                          Objects.first->getFileName(), Session);
462     if (Error == PDB_ErrorCode::Success) {
463       Context = new PDBContext(*CoffObject, std::move(Session),
464                                Opts.RelativeAddresses);
465     }
466   }
467   if (!Context)
468     Context = new DWARFContextInMemory(*Objects.second);
469   assert(Context);
470   ModuleInfo *Info = new ModuleInfo(Objects.first, Context);
471   Modules.insert(make_pair(ModuleName, Info));
472   return Info;
473 }
474
475 std::string LLVMSymbolizer::printDILineInfo(DILineInfo LineInfo) const {
476   // By default, DILineInfo contains "<invalid>" for function/filename it
477   // cannot fetch. We replace it to "??" to make our output closer to addr2line.
478   static const std::string kDILineInfoBadString = "<invalid>";
479   std::stringstream Result;
480   if (Opts.PrintFunctions != FunctionNameKind::None) {
481     std::string FunctionName = LineInfo.FunctionName;
482     if (FunctionName == kDILineInfoBadString)
483       FunctionName = kBadString;
484     else if (Opts.Demangle)
485       FunctionName = DemangleName(FunctionName);
486     Result << FunctionName << "\n";
487   }
488   std::string Filename = LineInfo.FileName;
489   if (Filename == kDILineInfoBadString)
490     Filename = kBadString;
491   Result << Filename << ":" << LineInfo.Line << ":" << LineInfo.Column << "\n";
492   return Result.str();
493 }
494
495 #if !defined(_MSC_VER)
496 // Assume that __cxa_demangle is provided by libcxxabi (except for Windows).
497 extern "C" char *__cxa_demangle(const char *mangled_name, char *output_buffer,
498                                 size_t *length, int *status);
499 #endif
500
501 std::string LLVMSymbolizer::DemangleName(const std::string &Name) {
502 #if !defined(_MSC_VER)
503   // We can spoil names of symbols with C linkage, so use an heuristic
504   // approach to check if the name should be demangled.
505   if (Name.substr(0, 2) != "_Z")
506     return Name;
507   int status = 0;
508   char *DemangledName = __cxa_demangle(Name.c_str(), nullptr, nullptr, &status);
509   if (status != 0)
510     return Name;
511   std::string Result = DemangledName;
512   free(DemangledName);
513   return Result;
514 #else
515   char DemangledName[1024] = {0};
516   DWORD result = ::UnDecorateSymbolName(
517       Name.c_str(), DemangledName, 1023,
518       UNDNAME_NO_ACCESS_SPECIFIERS |       // Strip public, private, protected
519           UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall, etc
520           UNDNAME_NO_THROW_SIGNATURES |    // Strip throw() specifications
521           UNDNAME_NO_MEMBER_TYPE |      // Strip virtual, static, etc specifiers
522           UNDNAME_NO_MS_KEYWORDS |      // Strip all MS extension keywords
523           UNDNAME_NO_FUNCTION_RETURNS); // Strip function return types
524
525   return (result == 0) ? Name : std::string(DemangledName);
526 #endif
527 }
528
529 } // namespace symbolize
530 } // namespace llvm