| //===-- GsymDIContext.cpp ------------------------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===/ |
| |
| #include "llvm/DebugInfo/GSYM/GsymDIContext.h" |
| |
| #include "llvm/DebugInfo/GSYM/GsymReader.h" |
| #include "llvm/Support/Path.h" |
| |
| using namespace llvm; |
| using namespace llvm::gsym; |
| |
| GsymDIContext::GsymDIContext(std::unique_ptr<GsymReader> Reader) |
| : DIContext(CK_GSYM), Reader(std::move(Reader)) {} |
| |
| void GsymDIContext::dump(raw_ostream &OS, DIDumpOptions DumpOpts) {} |
| |
| static bool fillLineInfoFromLocation(const SourceLocation &Location, |
| DILineInfoSpecifier Specifier, |
| DILineInfo &LineInfo) { |
| // FIXME Demangle in case of DINameKind::ShortName |
| if (Specifier.FNKind != DINameKind::None) { |
| LineInfo.FunctionName = Location.Name.str(); |
| } |
| |
| switch (Specifier.FLIKind) { |
| case DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath: |
| // We have no information to determine the relative path, so we fall back to |
| // returning the absolute path. |
| case DILineInfoSpecifier::FileLineInfoKind::RawValue: |
| case DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath: |
| if (Location.Dir.empty()) { |
| if (Location.Base.empty()) |
| LineInfo.FileName = DILineInfo::BadString; |
| else |
| LineInfo.FileName = Location.Base.str(); |
| } else { |
| SmallString<128> Path(Location.Dir); |
| sys::path::append(Path, Location.Base); |
| LineInfo.FileName = static_cast<std::string>(Path); |
| } |
| break; |
| |
| case DILineInfoSpecifier::FileLineInfoKind::BaseNameOnly: |
| LineInfo.FileName = Location.Base.str(); |
| break; |
| |
| default: |
| return false; |
| } |
| LineInfo.Line = Location.Line; |
| |
| // We don't have information in GSYM to fill any of the Source, Column, |
| // StartFileName or StartLine attributes. |
| |
| return true; |
| } |
| |
| std::optional<DILineInfo> |
| GsymDIContext::getLineInfoForAddress(object::SectionedAddress Address, |
| DILineInfoSpecifier Specifier) { |
| if (Address.SectionIndex != object::SectionedAddress::UndefSection) |
| return {}; |
| |
| auto ResultOrErr = Reader->lookup(Address.Address); |
| |
| if (!ResultOrErr) { |
| consumeError(ResultOrErr.takeError()); |
| return {}; |
| } |
| |
| const auto &Result = *ResultOrErr; |
| |
| DILineInfo LineInfo; |
| |
| if (Result.Locations.empty()) { |
| // No debug info for this, we just had a symbol from the symbol table. |
| |
| // FIXME Demangle in case of DINameKind::ShortName |
| if (Specifier.FNKind != DINameKind::None) |
| LineInfo.FunctionName = Result.FuncName.str(); |
| } else if (!fillLineInfoFromLocation(Result.Locations.front(), Specifier, |
| LineInfo)) |
| return {}; |
| |
| LineInfo.StartAddress = Result.FuncRange.start(); |
| |
| return LineInfo; |
| } |
| |
| std::optional<DILineInfo> |
| GsymDIContext::getLineInfoForDataAddress(object::SectionedAddress Address) { |
| // We can't implement this, there's no such information in the GSYM file. |
| |
| return {}; |
| } |
| |
| DILineInfoTable |
| GsymDIContext::getLineInfoForAddressRange(object::SectionedAddress Address, |
| uint64_t Size, |
| DILineInfoSpecifier Specifier) { |
| if (Size == 0) |
| return DILineInfoTable(); |
| |
| if (Address.SectionIndex != llvm::object::SectionedAddress::UndefSection) |
| return DILineInfoTable(); |
| |
| if (auto FuncInfoOrErr = Reader->getFunctionInfo(Address.Address)) { |
| DILineInfoTable Table; |
| if (FuncInfoOrErr->OptLineTable) { |
| const gsym::LineTable < = *FuncInfoOrErr->OptLineTable; |
| const uint64_t StartAddr = Address.Address; |
| const uint64_t EndAddr = Address.Address + Size; |
| for (const auto &LineEntry : LT) { |
| if (StartAddr <= LineEntry.Addr && LineEntry.Addr < EndAddr) { |
| // Use LineEntry.Addr, LineEntry.File (which is a file index into the |
| // files tables from the GsymReader), and LineEntry.Line (source line |
| // number) to add stuff to the DILineInfoTable |
| } |
| } |
| } |
| return Table; |
| } else { |
| consumeError(FuncInfoOrErr.takeError()); |
| return DILineInfoTable(); |
| } |
| } |
| |
| DIInliningInfo |
| GsymDIContext::getInliningInfoForAddress(object::SectionedAddress Address, |
| DILineInfoSpecifier Specifier) { |
| auto ResultOrErr = Reader->lookup(Address.Address); |
| |
| if (!ResultOrErr) |
| return {}; |
| |
| const auto &Result = *ResultOrErr; |
| |
| DIInliningInfo InlineInfo; |
| |
| for (const auto &Location : Result.Locations) { |
| DILineInfo LineInfo; |
| |
| if (!fillLineInfoFromLocation(Location, Specifier, LineInfo)) |
| return {}; |
| |
| // Hm, that's probably something that should only be filled in the first or |
| // last frame? |
| LineInfo.StartAddress = Result.FuncRange.start(); |
| |
| InlineInfo.addFrame(LineInfo); |
| } |
| |
| return InlineInfo; |
| } |
| |
| std::vector<DILocal> |
| GsymDIContext::getLocalsForAddress(object::SectionedAddress Address) { |
| // We can't implement this, there's no such information in the GSYM file. |
| |
| return {}; |
| } |