LCOV - code coverage report
Current view: top level - lib/DebugInfo/Symbolize - Symbolize.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 189 240 78.8 %
Date: 2017-09-14 15:23:50 Functions: 14 16 87.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13