113 lines · cpp
1//===- PDBSymbolCompiland.cpp - compiland details ---------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/DebugInfo/PDB/IPDBSession.h"10#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"11 12#include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h"13#include "llvm/DebugInfo/PDB/PDBSymDumper.h"14#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"15#include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h"16#include "llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h"17 18#include "llvm/ADT/StringSwitch.h"19#include "llvm/Support/Path.h"20 21using namespace llvm;22using namespace llvm::pdb;23 24void PDBSymbolCompiland::dump(PDBSymDumper &Dumper) const {25 Dumper.dump(*this);26}27 28std::string PDBSymbolCompiland::getSourceFileName() const {29 return sys::path::filename(getSourceFileFullPath()).str();30}31 32std::string PDBSymbolCompiland::getSourceFileFullPath() const {33 std::string SourceFileFullPath;34 35 // RecordedResult could be the basename, relative path or full path of the36 // source file. Usually it is retrieved and recorded from the command that37 // compiles this compiland.38 //39 // cmd FileName -> RecordedResult = .\\FileName40 // cmd (Path)\\FileName -> RecordedResult = (Path)\\FileName41 //42 std::string RecordedResult = RawSymbol->getSourceFileName();43 44 if (RecordedResult.empty()) {45 if (auto Envs = findAllChildren<PDBSymbolCompilandEnv>()) {46 std::string EnvWorkingDir, EnvSrc;47 48 while (auto Env = Envs->getNext()) {49 std::string Var = Env->getName();50 if (Var == "cwd") {51 EnvWorkingDir = Env->getValue();52 continue;53 }54 if (Var == "src") {55 EnvSrc = Env->getValue();56 if (sys::path::is_absolute(EnvSrc))57 return EnvSrc;58 RecordedResult = EnvSrc;59 continue;60 }61 }62 if (!EnvWorkingDir.empty() && !EnvSrc.empty()) {63 auto Len = EnvWorkingDir.length();64 if (EnvWorkingDir[Len - 1] != '/' && EnvWorkingDir[Len - 1] != '\\') {65 std::string Path = EnvWorkingDir + "\\" + EnvSrc;66 llvm::replace(Path, '/', '\\');67 // We will return it as full path if we can't find a better one.68 if (sys::path::is_absolute(Path))69 SourceFileFullPath = Path;70 }71 }72 }73 }74 75 if (!RecordedResult.empty()) {76 if (sys::path::is_absolute(RecordedResult))77 return RecordedResult;78 79 // This searches name that has same basename as the one in RecordedResult.80 auto OneSrcFile = Session.findOneSourceFile(81 this, RecordedResult, PDB_NameSearchFlags::NS_CaseInsensitive);82 if (OneSrcFile)83 return OneSrcFile->getFileName();84 }85 86 // At this point, we have to walk through all source files of this compiland,87 // and determine the right source file if any that is used to generate this88 // compiland based on language indicated in compilanddetails language field.89 auto Details = findOneChild<PDBSymbolCompilandDetails>();90 PDB_Lang Lang = Details ? Details->getLanguage() : PDB_Lang::Cpp;91 auto SrcFiles = Session.getSourceFilesForCompiland(*this);92 if (SrcFiles) {93 while (auto File = SrcFiles->getNext()) {94 std::string FileName = File->getFileName();95 auto file_extension = sys::path::extension(FileName);96 if (StringSwitch<bool>(file_extension.lower())97 .Case(".cpp", Lang == PDB_Lang::Cpp)98 .Case(".cc", Lang == PDB_Lang::Cpp)99 .Case(".cxx", Lang == PDB_Lang::Cpp)100 .Case(".c", Lang == PDB_Lang::C)101 .Case(".asm", Lang == PDB_Lang::Masm)102 .Case(".swift", Lang == PDB_Lang::Swift)103 .Case(".rs", Lang == PDB_Lang::Rust)104 .Case(".m", Lang == PDB_Lang::ObjC)105 .Case(".mm", Lang == PDB_Lang::ObjCpp)106 .Default(false))107 return File->getFileName();108 }109 }110 111 return SourceFileFullPath;112}113