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