Remove 'using std::error_code' from tools.
[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/Object/ELFObjectFile.h"
18 #include "llvm/Object/MachO.h"
19 #include "llvm/Support/Casting.h"
20 #include "llvm/Support/Compression.h"
21 #include "llvm/Support/DataExtractor.h"
22 #include "llvm/Support/FileSystem.h"
23 #include "llvm/Support/MemoryBuffer.h"
24 #include "llvm/Support/Path.h"
25 #include <sstream>
26 #include <stdlib.h>
27
28 namespace llvm {
29 namespace symbolize {
30
31 static bool error(std::error_code ec) {
32   if (!ec)
33     return false;
34   errs() << "LLVMSymbolizer: error reading file: " << ec.message() << ".\n";
35   return true;
36 }
37
38 static DILineInfoSpecifier
39 getDILineInfoSpecifier(const LLVMSymbolizer::Options &Opts) {
40   return DILineInfoSpecifier(
41       DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
42       Opts.PrintFunctions);
43 }
44
45 ModuleInfo::ModuleInfo(ObjectFile *Obj, DIContext *DICtx)
46     : Module(Obj), DebugInfoContext(DICtx) {
47   for (const SymbolRef &Symbol : Module->symbols()) {
48     addSymbol(Symbol);
49   }
50   bool NoSymbolTable = (Module->symbol_begin() == Module->symbol_end());
51   if (NoSymbolTable && Module->isELF()) {
52     // Fallback to dynamic symbol table, if regular symbol table is stripped.
53     std::pair<symbol_iterator, symbol_iterator> IDyn =
54         getELFDynamicSymbolIterators(Module);
55     for (symbol_iterator si = IDyn.first, se = IDyn.second; si != se; ++si) {
56       addSymbol(*si);
57     }
58   }
59 }
60
61 void ModuleInfo::addSymbol(const SymbolRef &Symbol) {
62   SymbolRef::Type SymbolType;
63   if (error(Symbol.getType(SymbolType)))
64     return;
65   if (SymbolType != SymbolRef::ST_Function && SymbolType != SymbolRef::ST_Data)
66     return;
67   uint64_t SymbolAddress;
68   if (error(Symbol.getAddress(SymbolAddress)) ||
69       SymbolAddress == UnknownAddressOrSize)
70     return;
71   uint64_t SymbolSize;
72   // Getting symbol size is linear for Mach-O files, so assume that symbol
73   // occupies the memory range up to the following symbol.
74   if (isa<MachOObjectFile>(Module))
75     SymbolSize = 0;
76   else if (error(Symbol.getSize(SymbolSize)) ||
77            SymbolSize == UnknownAddressOrSize)
78     return;
79   StringRef SymbolName;
80   if (error(Symbol.getName(SymbolName)))
81     return;
82   // Mach-O symbol table names have leading underscore, skip it.
83   if (Module->isMachO() && SymbolName.size() > 0 && SymbolName[0] == '_')
84     SymbolName = SymbolName.drop_front();
85   // FIXME: If a function has alias, there are two entries in symbol table
86   // with same address size. Make sure we choose the correct one.
87   SymbolMapTy &M = SymbolType == SymbolRef::ST_Function ? Functions : Objects;
88   SymbolDesc SD = { SymbolAddress, SymbolSize };
89   M.insert(std::make_pair(SD, SymbolName));
90 }
91
92 bool ModuleInfo::getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address,
93                                         std::string &Name, uint64_t &Addr,
94                                         uint64_t &Size) const {
95   const SymbolMapTy &M = Type == SymbolRef::ST_Function ? Functions : Objects;
96   if (M.empty())
97     return false;
98   SymbolDesc SD = { Address, Address };
99   SymbolMapTy::const_iterator it = M.upper_bound(SD);
100   if (it == M.begin())
101     return false;
102   --it;
103   if (it->first.Size != 0 && it->first.Addr + it->first.Size <= Address)
104     return false;
105   Name = it->second.str();
106   Addr = it->first.Addr;
107   Size = it->first.Size;
108   return true;
109 }
110
111 DILineInfo ModuleInfo::symbolizeCode(
112     uint64_t ModuleOffset, const LLVMSymbolizer::Options &Opts) const {
113   DILineInfo LineInfo;
114   if (DebugInfoContext) {
115     LineInfo = DebugInfoContext->getLineInfoForAddress(
116         ModuleOffset, getDILineInfoSpecifier(Opts));
117   }
118   // Override function name from symbol table if necessary.
119   if (Opts.PrintFunctions != FunctionNameKind::None && Opts.UseSymbolTable) {
120     std::string FunctionName;
121     uint64_t Start, Size;
122     if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset,
123                                FunctionName, Start, Size)) {
124       LineInfo.FunctionName = FunctionName;
125     }
126   }
127   return LineInfo;
128 }
129
130 DIInliningInfo ModuleInfo::symbolizeInlinedCode(
131     uint64_t ModuleOffset, const LLVMSymbolizer::Options &Opts) const {
132   DIInliningInfo InlinedContext;
133   if (DebugInfoContext) {
134     InlinedContext = DebugInfoContext->getInliningInfoForAddress(
135         ModuleOffset, getDILineInfoSpecifier(Opts));
136   }
137   // Make sure there is at least one frame in context.
138   if (InlinedContext.getNumberOfFrames() == 0) {
139     InlinedContext.addFrame(DILineInfo());
140   }
141   // Override the function name in lower frame with name from symbol table.
142   if (Opts.PrintFunctions != FunctionNameKind::None && Opts.UseSymbolTable) {
143     DIInliningInfo PatchedInlinedContext;
144     for (uint32_t i = 0, n = InlinedContext.getNumberOfFrames(); i < n; i++) {
145       DILineInfo LineInfo = InlinedContext.getFrame(i);
146       if (i == n - 1) {
147         std::string FunctionName;
148         uint64_t Start, Size;
149         if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset,
150                                    FunctionName, Start, Size)) {
151           LineInfo.FunctionName = FunctionName;
152         }
153       }
154       PatchedInlinedContext.addFrame(LineInfo);
155     }
156     InlinedContext = PatchedInlinedContext;
157   }
158   return InlinedContext;
159 }
160
161 bool ModuleInfo::symbolizeData(uint64_t ModuleOffset, std::string &Name,
162                                uint64_t &Start, uint64_t &Size) const {
163   return getNameFromSymbolTable(SymbolRef::ST_Data, ModuleOffset, Name, Start,
164                                 Size);
165 }
166
167 const char LLVMSymbolizer::kBadString[] = "??";
168
169 std::string LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
170                                           uint64_t ModuleOffset) {
171   ModuleInfo *Info = getOrCreateModuleInfo(ModuleName);
172   if (!Info)
173     return printDILineInfo(DILineInfo());
174   if (Opts.PrintInlining) {
175     DIInliningInfo InlinedContext =
176         Info->symbolizeInlinedCode(ModuleOffset, Opts);
177     uint32_t FramesNum = InlinedContext.getNumberOfFrames();
178     assert(FramesNum > 0);
179     std::string Result;
180     for (uint32_t i = 0; i < FramesNum; i++) {
181       DILineInfo LineInfo = InlinedContext.getFrame(i);
182       Result += printDILineInfo(LineInfo);
183     }
184     return Result;
185   }
186   DILineInfo LineInfo = Info->symbolizeCode(ModuleOffset, Opts);
187   return printDILineInfo(LineInfo);
188 }
189
190 std::string LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
191                                           uint64_t ModuleOffset) {
192   std::string Name = kBadString;
193   uint64_t Start = 0;
194   uint64_t Size = 0;
195   if (Opts.UseSymbolTable) {
196     if (ModuleInfo *Info = getOrCreateModuleInfo(ModuleName)) {
197       if (Info->symbolizeData(ModuleOffset, Name, Start, Size) && Opts.Demangle)
198         Name = DemangleName(Name);
199     }
200   }
201   std::stringstream ss;
202   ss << Name << "\n" << Start << " " << Size << "\n";
203   return ss.str();
204 }
205
206 void LLVMSymbolizer::flush() {
207   DeleteContainerSeconds(Modules);
208   BinaryForPath.clear();
209   ObjectFileForArch.clear();
210 }
211
212 static std::string getDarwinDWARFResourceForPath(const std::string &Path) {
213   StringRef Basename = sys::path::filename(Path);
214   const std::string &DSymDirectory = Path + ".dSYM";
215   SmallString<16> ResourceName = StringRef(DSymDirectory);
216   sys::path::append(ResourceName, "Contents", "Resources", "DWARF");
217   sys::path::append(ResourceName, Basename);
218   return ResourceName.str();
219 }
220
221 static bool checkFileCRC(StringRef Path, uint32_t CRCHash) {
222   std::unique_ptr<MemoryBuffer> MB;
223   if (MemoryBuffer::getFileOrSTDIN(Path, MB))
224     return false;
225   return !zlib::isAvailable() || CRCHash == zlib::crc32(MB->getBuffer());
226 }
227
228 static bool findDebugBinary(const std::string &OrigPath,
229                             const std::string &DebuglinkName, uint32_t CRCHash,
230                             std::string &Result) {
231   std::string OrigRealPath = OrigPath;
232 #if defined(HAVE_REALPATH)
233   if (char *RP = realpath(OrigPath.c_str(), nullptr)) {
234     OrigRealPath = RP;
235     free(RP);
236   }
237 #endif
238   SmallString<16> OrigDir(OrigRealPath);
239   llvm::sys::path::remove_filename(OrigDir);
240   SmallString<16> DebugPath = OrigDir;
241   // Try /path/to/original_binary/debuglink_name
242   llvm::sys::path::append(DebugPath, DebuglinkName);
243   if (checkFileCRC(DebugPath, CRCHash)) {
244     Result = DebugPath.str();
245     return true;
246   }
247   // Try /path/to/original_binary/.debug/debuglink_name
248   DebugPath = OrigRealPath;
249   llvm::sys::path::append(DebugPath, ".debug", DebuglinkName);
250   if (checkFileCRC(DebugPath, CRCHash)) {
251     Result = DebugPath.str();
252     return true;
253   }
254   // Try /usr/lib/debug/path/to/original_binary/debuglink_name
255   DebugPath = "/usr/lib/debug";
256   llvm::sys::path::append(DebugPath, llvm::sys::path::relative_path(OrigDir),
257                           DebuglinkName);
258   if (checkFileCRC(DebugPath, CRCHash)) {
259     Result = DebugPath.str();
260     return true;
261   }
262   return false;
263 }
264
265 static bool getGNUDebuglinkContents(const Binary *Bin, std::string &DebugName,
266                                     uint32_t &CRCHash) {
267   const ObjectFile *Obj = dyn_cast<ObjectFile>(Bin);
268   if (!Obj)
269     return false;
270   for (const SectionRef &Section : Obj->sections()) {
271     StringRef Name;
272     Section.getName(Name);
273     Name = Name.substr(Name.find_first_not_of("._"));
274     if (Name == "gnu_debuglink") {
275       StringRef Data;
276       Section.getContents(Data);
277       DataExtractor DE(Data, Obj->isLittleEndian(), 0);
278       uint32_t Offset = 0;
279       if (const char *DebugNameStr = DE.getCStr(&Offset)) {
280         // 4-byte align the offset.
281         Offset = (Offset + 3) & ~0x3;
282         if (DE.isValidOffsetForDataOfSize(Offset, 4)) {
283           DebugName = DebugNameStr;
284           CRCHash = DE.getU32(&Offset);
285           return true;
286         }
287       }
288       break;
289     }
290   }
291   return false;
292 }
293
294 LLVMSymbolizer::BinaryPair
295 LLVMSymbolizer::getOrCreateBinary(const std::string &Path) {
296   BinaryMapTy::iterator I = BinaryForPath.find(Path);
297   if (I != BinaryForPath.end())
298     return I->second;
299   Binary *Bin = nullptr;
300   Binary *DbgBin = nullptr;
301   ErrorOr<Binary *> BinaryOrErr = createBinary(Path);
302   if (!error(BinaryOrErr.getError())) {
303     std::unique_ptr<Binary> ParsedBinary(BinaryOrErr.get());
304     // Check if it's a universal binary.
305     Bin = ParsedBinary.get();
306     ParsedBinariesAndObjects.push_back(std::move(ParsedBinary));
307     if (Bin->isMachO() || Bin->isMachOUniversalBinary()) {
308       // On Darwin we may find DWARF in separate object file in
309       // resource directory.
310       const std::string &ResourcePath =
311           getDarwinDWARFResourceForPath(Path);
312       BinaryOrErr = createBinary(ResourcePath);
313       std::error_code EC = BinaryOrErr.getError();
314       if (EC != std::errc::no_such_file_or_directory && !error(EC)) {
315         DbgBin = BinaryOrErr.get();
316         ParsedBinariesAndObjects.push_back(std::unique_ptr<Binary>(DbgBin));
317       }
318     }
319     // Try to locate the debug binary using .gnu_debuglink section.
320     if (!DbgBin) {
321       std::string DebuglinkName;
322       uint32_t CRCHash;
323       std::string DebugBinaryPath;
324       if (getGNUDebuglinkContents(Bin, DebuglinkName, CRCHash) &&
325           findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath)) {
326         BinaryOrErr = createBinary(DebugBinaryPath);
327         if (!error(BinaryOrErr.getError())) {
328           DbgBin = BinaryOrErr.get();
329           ParsedBinariesAndObjects.push_back(std::unique_ptr<Binary>(DbgBin));
330         }
331       }
332     }
333   }
334   if (!DbgBin)
335     DbgBin = Bin;
336   BinaryPair Res = std::make_pair(Bin, DbgBin);
337   BinaryForPath[Path] = Res;
338   return Res;
339 }
340
341 ObjectFile *
342 LLVMSymbolizer::getObjectFileFromBinary(Binary *Bin, const std::string &ArchName) {
343   if (!Bin)
344     return nullptr;
345   ObjectFile *Res = nullptr;
346   if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(Bin)) {
347     ObjectFileForArchMapTy::iterator I = ObjectFileForArch.find(
348         std::make_pair(UB, ArchName));
349     if (I != ObjectFileForArch.end())
350       return I->second;
351     std::unique_ptr<ObjectFile> ParsedObj;
352     if (!UB->getObjectForArch(Triple(ArchName).getArch(), ParsedObj)) {
353       Res = ParsedObj.get();
354       ParsedBinariesAndObjects.push_back(std::move(ParsedObj));
355     }
356     ObjectFileForArch[std::make_pair(UB, ArchName)] = Res;
357   } else if (Bin->isObject()) {
358     Res = cast<ObjectFile>(Bin);
359   }
360   return Res;
361 }
362
363 ModuleInfo *
364 LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
365   ModuleMapTy::iterator I = Modules.find(ModuleName);
366   if (I != Modules.end())
367     return I->second;
368   std::string BinaryName = ModuleName;
369   std::string ArchName = Opts.DefaultArch;
370   size_t ColonPos = ModuleName.find_last_of(':');
371   // Verify that substring after colon form a valid arch name.
372   if (ColonPos != std::string::npos) {
373     std::string ArchStr = ModuleName.substr(ColonPos + 1);
374     if (Triple(ArchStr).getArch() != Triple::UnknownArch) {
375       BinaryName = ModuleName.substr(0, ColonPos);
376       ArchName = ArchStr;
377     }
378   }
379   BinaryPair Binaries = getOrCreateBinary(BinaryName);
380   ObjectFile *Obj = getObjectFileFromBinary(Binaries.first, ArchName);
381   ObjectFile *DbgObj = getObjectFileFromBinary(Binaries.second, ArchName);
382
383   if (!Obj) {
384     // Failed to find valid object file.
385     Modules.insert(make_pair(ModuleName, (ModuleInfo *)nullptr));
386     return nullptr;
387   }
388   DIContext *Context = DIContext::getDWARFContext(DbgObj);
389   assert(Context);
390   ModuleInfo *Info = new ModuleInfo(Obj, Context);
391   Modules.insert(make_pair(ModuleName, Info));
392   return Info;
393 }
394
395 std::string LLVMSymbolizer::printDILineInfo(DILineInfo LineInfo) const {
396   // By default, DILineInfo contains "<invalid>" for function/filename it
397   // cannot fetch. We replace it to "??" to make our output closer to addr2line.
398   static const std::string kDILineInfoBadString = "<invalid>";
399   std::stringstream Result;
400   if (Opts.PrintFunctions != FunctionNameKind::None) {
401     std::string FunctionName = LineInfo.FunctionName;
402     if (FunctionName == kDILineInfoBadString)
403       FunctionName = kBadString;
404     else if (Opts.Demangle)
405       FunctionName = DemangleName(FunctionName);
406     Result << FunctionName << "\n";
407   }
408   std::string Filename = LineInfo.FileName;
409   if (Filename == kDILineInfoBadString)
410     Filename = kBadString;
411   Result << Filename << ":" << LineInfo.Line << ":" << LineInfo.Column << "\n";
412   return Result.str();
413 }
414
415 #if !defined(_MSC_VER)
416 // Assume that __cxa_demangle is provided by libcxxabi (except for Windows).
417 extern "C" char *__cxa_demangle(const char *mangled_name, char *output_buffer,
418                                 size_t *length, int *status);
419 #endif
420
421 std::string LLVMSymbolizer::DemangleName(const std::string &Name) {
422 #if !defined(_MSC_VER)
423   // We can spoil names of symbols with C linkage, so use an heuristic
424   // approach to check if the name should be demangled.
425   if (Name.substr(0, 2) != "_Z")
426     return Name;
427   int status = 0;
428   char *DemangledName = __cxa_demangle(Name.c_str(), nullptr, nullptr, &status);
429   if (status != 0)
430     return Name;
431   std::string Result = DemangledName;
432   free(DemangledName);
433   return Result;
434 #else
435   return Name;
436 #endif
437 }
438
439 } // namespace symbolize
440 } // namespace llvm