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

Generated by: LCOV version 1.13