1 //===-- GsymContext.cpp ------------------------------------------------===// 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-exception 6 // 7 //===----------------------------------------------------------------------===/ 8 9 #include "llvm/DebugInfo/GSYM/GsymContext.h" 10 11 #include "llvm/DebugInfo/GSYM/GsymReader.h" 12 #include "llvm/Support/Path.h" 13 14 using namespace llvm; 15 using namespace llvm::gsym; 16 17 GsymContext::GsymContext(std::unique_ptr<GsymReader> Reader) 18 : DIContext(CK_GSYM), Reader(std::move(Reader)) {} 19 20 void GsymContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts) {} 21 22 static bool fillLineInfoFromLocation(const SourceLocation &Location, 23 DILineInfoSpecifier Specifier, 24 DILineInfo &LineInfo) { 25 // FIXME Demangle in case of DINameKind::ShortName 26 if (Specifier.FNKind != DINameKind::None) { 27 LineInfo.FunctionName = Location.Name.str(); 28 } 29 30 switch (Specifier.FLIKind) { 31 case DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath: 32 // We have no information to determine the relative path, so we fall back to 33 // returning the absolute path. 34 case DILineInfoSpecifier::FileLineInfoKind::RawValue: 35 case DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath: 36 if (Location.Dir.empty()) { 37 if (Location.Base.empty()) 38 LineInfo.FileName = DILineInfo::BadString; 39 else 40 LineInfo.FileName = Location.Base.str(); 41 } else { 42 SmallString<128> Path(Location.Dir); 43 sys::path::append(Path, Location.Base); 44 LineInfo.FileName = static_cast<std::string>(Path); 45 } 46 break; 47 48 case DILineInfoSpecifier::FileLineInfoKind::BaseNameOnly: 49 LineInfo.FileName = Location.Base.str(); 50 break; 51 52 default: 53 return false; 54 } 55 LineInfo.Line = Location.Line; 56 57 // We don't have information in GSYM to fill any of the Source, Column, 58 // StartFileName or StartLine attributes. 59 60 return true; 61 } 62 63 std::optional<DILineInfo> 64 GsymContext::getLineInfoForAddress(object::SectionedAddress Address, 65 DILineInfoSpecifier Specifier) { 66 if (Address.SectionIndex != object::SectionedAddress::UndefSection) 67 return {}; 68 69 auto ResultOrErr = Reader->lookup(Address.Address); 70 71 if (!ResultOrErr) { 72 consumeError(ResultOrErr.takeError()); 73 return {}; 74 } 75 76 const auto &Result = *ResultOrErr; 77 78 DILineInfo LineInfo; 79 80 if (Result.Locations.empty()) { 81 // No debug info for this, we just had a symbol from the symbol table. 82 83 // FIXME Demangle in case of DINameKind::ShortName 84 if (Specifier.FNKind != DINameKind::None) 85 LineInfo.FunctionName = Result.FuncName.str(); 86 } else if (!fillLineInfoFromLocation(Result.Locations.front(), Specifier, 87 LineInfo)) 88 return {}; 89 90 LineInfo.StartAddress = Result.FuncRange.start(); 91 92 return LineInfo; 93 } 94 95 std::optional<DILineInfo> 96 GsymContext::getLineInfoForDataAddress(object::SectionedAddress Address) { 97 // We can't implement this, there's no such information in the GSYM file. 98 99 return {}; 100 } 101 102 DILineInfoTable 103 GsymContext::getLineInfoForAddressRange(object::SectionedAddress Address, 104 uint64_t Size, 105 DILineInfoSpecifier Specifier) { 106 if (Size == 0) 107 return DILineInfoTable(); 108 109 if (Address.SectionIndex != llvm::object::SectionedAddress::UndefSection) 110 return DILineInfoTable(); 111 112 if (auto FuncInfoOrErr = Reader->getFunctionInfo(Address.Address)) { 113 DILineInfoTable Table; 114 if (FuncInfoOrErr->OptLineTable) { 115 const gsym::LineTable < = *FuncInfoOrErr->OptLineTable; 116 const uint64_t StartAddr = Address.Address; 117 const uint64_t EndAddr = Address.Address + Size; 118 for (const auto &LineEntry : LT) { 119 if (StartAddr <= LineEntry.Addr && LineEntry.Addr < EndAddr) { 120 // Use LineEntry.Addr, LineEntry.File (which is a file index into the 121 // files tables from the GsymReader), and LineEntry.Line (source line 122 // number) to add stuff to the DILineInfoTable 123 } 124 } 125 } 126 return Table; 127 } else { 128 consumeError(FuncInfoOrErr.takeError()); 129 return DILineInfoTable(); 130 } 131 } 132 133 DIInliningInfo 134 GsymContext::getInliningInfoForAddress(object::SectionedAddress Address, 135 DILineInfoSpecifier Specifier) { 136 auto ResultOrErr = Reader->lookup(Address.Address); 137 138 if (!ResultOrErr) 139 return {}; 140 141 const auto &Result = *ResultOrErr; 142 143 DIInliningInfo InlineInfo; 144 145 for (const auto &Location : Result.Locations) { 146 DILineInfo LineInfo; 147 148 if (!fillLineInfoFromLocation(Location, Specifier, LineInfo)) 149 return {}; 150 151 // Hm, that's probably something that should only be filled in the first or 152 // last frame? 153 LineInfo.StartAddress = Result.FuncRange.start(); 154 155 InlineInfo.addFrame(LineInfo); 156 } 157 158 return InlineInfo; 159 } 160 161 std::vector<DILocal> 162 GsymContext::getLocalsForAddress(object::SectionedAddress Address) { 163 // We can't implement this, there's no such information in the GSYM file. 164 165 return {}; 166 } 167