
Renaming based on suggestion here: https://github.com/llvm/llvm-project/pull/139686#discussion_r2089538528
167 lines
5.1 KiB
C++
167 lines
5.1 KiB
C++
//===-- GsymContext.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/GsymContext.h"
|
|
|
|
#include "llvm/DebugInfo/GSYM/GsymReader.h"
|
|
#include "llvm/Support/Path.h"
|
|
|
|
using namespace llvm;
|
|
using namespace llvm::gsym;
|
|
|
|
GsymContext::GsymContext(std::unique_ptr<GsymReader> Reader)
|
|
: DIContext(CK_GSYM), Reader(std::move(Reader)) {}
|
|
|
|
void GsymContext::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>
|
|
GsymContext::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>
|
|
GsymContext::getLineInfoForDataAddress(object::SectionedAddress Address) {
|
|
// We can't implement this, there's no such information in the GSYM file.
|
|
|
|
return {};
|
|
}
|
|
|
|
DILineInfoTable
|
|
GsymContext::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
|
|
GsymContext::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>
|
|
GsymContext::getLocalsForAddress(object::SectionedAddress Address) {
|
|
// We can't implement this, there's no such information in the GSYM file.
|
|
|
|
return {};
|
|
}
|