Skip to content

Commit

Permalink
Accept input from stdin
Browse files Browse the repository at this point in the history
  • Loading branch information
Novakov committed Dec 4, 2023
1 parent 8de805f commit a7f971b
Showing 1 changed file with 120 additions and 84 deletions.
204 changes: 120 additions & 84 deletions execs/addr2field/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "libdwarf/libdwarf.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/spdlog.h"
#include <iostream>

using namespace std::string_literals;

Expand Down Expand Up @@ -279,128 +280,163 @@ static std::optional<std::string> GlobalVariableName(
return std::nullopt;
}

int main(int argc, char* argv[])
static void LookupAddress(std::uint32_t lookupAddress, const char* elfFile, dwarf::DebugInfo& dbg, Namespace& root)
{
if(argc < 3)
spdlog::info("Address for lookup: 0x{:08X}", lookupAddress);

auto containingSymbol = LookupSymbolByAddress(elfFile, lookupAddress);
if(!containingSymbol.has_value())
{
fprintf(stderr, "%s <elf file> 0x<address in hex> [0x<address in hex>...]\n", argv[0]);
return 1;
printf(
"0x%08X - Failed to match address to symbol\n",
lookupAddress);
}

auto logger = spdlog::stderr_color_st("root");
logger->set_level(spdlog::level::debug);
logger->set_pattern("[%-5l] %v");
spdlog::set_default_logger(logger);
auto [linkageName, inVariableOffset] = *containingSymbol;

spdlog::info("Analyzing ELF {}", argv[1]);
spdlog::info("Symbol name: {}+{}", linkageName, inVariableOffset);

auto dbg = dwarf::OpenDebugInfo(argv[1]);

Namespace root{""};

spdlog::info("Building type tree");
spdlog::info("Looking for DIE matching symbol");
dwarf::Die variableDie{};
while(dwarf::NavigateToNextCompilationUnit(dbg))
{
auto cuDie = dwarf::GetCompilationUnitTopDie(dbg, true);
spdlog::debug("CU: {}", dwarf::ReadDieName(cuDie).value_or("(unnamed)"));

BuildTypeTree(dbg, cuDie, root);
variableDie = FindVariableDie(dbg, cuDie, linkageName, lookupAddress - inVariableOffset);
if(static_cast<bool>(variableDie))
{
// iterate to the end of CU list
while(dwarf::NavigateToNextCompilationUnit(dbg))
;
break;
}
}

for(auto arg = 2; arg < argc; arg++)
if(!static_cast<bool>(variableDie))
{
std::uint32_t lookupAddress = 0;
{
std::string_view s{argv[arg]};
std::from_chars(s.data() + 2, s.data() + s.size(), lookupAddress, 16);
}
printf(
"0x%08X - DIE for variable not found. Symbol: %s+%lu\n",
lookupAddress,
linkageName.c_str(),
inVariableOffset);
return;
}

spdlog::info("Address for lookup: 0x{:08X}", lookupAddress);
spdlog::debug(
"Found variable die (offset=0x{:08X}) {}+{}", dwarf::GetDieOffset(variableDie), dwarf::ReadDieName(variableDie).value_or("(unnamed)"), inVariableOffset);

auto containingSymbol = LookupSymbolByAddress(argv[1], lookupAddress);
if(!containingSymbol.has_value())
{
spdlog::error("Failed to match address {} to symbol", lookupAddress);
return 2;
}
auto typeDie = ResolveTypeFromDie(dbg, root, variableDie);

if(!static_cast<bool>(typeDie))
{
printf("DIE offset: %llu\n", dwarf::GetDieOffset(variableDie));
printf(
"0x%08X - Failed to resolve type DIE for variable. Symbol: %s+%lu\n",
lookupAddress,
linkageName.c_str(),
inVariableOffset);
return;
}

std::vector<AccessPathItem> accessPath;

auto [linkageName, inVariableOffset] = *containingSymbol;
auto fullName = GlobalVariableName(
dbg, dwarf::GetCompilationUnitTopDie(dbg, true, variableDie), variableDie, "");

spdlog::info("Symbol name: {}+{}", linkageName, inVariableOffset);
accessPath.push_back(GlobalVariableAccess{fullName.value_or("(unnamed)"), inVariableOffset});

spdlog::info("Looking for DIE matching symbol");
dwarf::Die variableDie{};
while(dwarf::NavigateToNextCompilationUnit(dbg))
ResolveAddressToPath(dbg, root, typeDie, inVariableOffset, accessPath);

printf("0x%08X - ", lookupAddress);

for(const auto& pathItem: accessPath)
{
if(std::holds_alternative<GlobalVariableAccess>(pathItem))
{
auto cuDie = dwarf::GetCompilationUnitTopDie(dbg, true);
spdlog::debug("CU: {}", dwarf::ReadDieName(cuDie).value_or("(unnamed)"));
auto& item = std::get<GlobalVariableAccess>(pathItem);

variableDie = FindVariableDie(dbg, cuDie, linkageName, lookupAddress - inVariableOffset);
if(static_cast<bool>(variableDie))
{
// iterate to the end of CU list
while(dwarf::NavigateToNextCompilationUnit(dbg))
;
break;
}
printf("%s", item.name.c_str());
}
else if(std::holds_alternative<MemberAccess>(pathItem))
{
auto& item = std::get<MemberAccess>(pathItem);

if(!static_cast<bool>(variableDie))
printf(".%s", item.name.c_str());
}
else if(std::holds_alternative<ArrayAccess>(pathItem))
{
printf(
"0x%08X - DIE for variable not found. Symbol: %s+%lu\n",
lookupAddress,
linkageName.c_str(),
inVariableOffset);
continue;
auto& item = std::get<ArrayAccess>(pathItem);
printf("[%ld]", item.index);
}
}
printf("\n");
}

spdlog::debug(
"Found variable die (offset=0x{:08X}) {}+{}", dwarf::GetDieOffset(variableDie), dwarf::ReadDieName(variableDie).value_or("(unnamed)"), inVariableOffset);

auto typeDie = ResolveTypeFromDie(dbg, root, variableDie);
int main(int argc, char* argv[])
{
if(argc < 3)
{
fprintf(stderr, "%s <elf file> 0x<address in hex> [0x<address in hex>...]\n", argv[0]);
fprintf(stderr, "\tResolve addresses given on command line\n");
fprintf(stderr, "%s <elf file> 0x<address in hex> - \n", argv[0]);
fprintf(stderr, "\tAccept addresses one-by-one from standard input and resolve them\n");
return 1;
}

if(!static_cast<bool>(typeDie))
{
printf("DIE offset: %llu\n", dwarf::GetDieOffset(variableDie));
printf(
"0x%08X - Failed to resolve type DIE for variable. Symbol: %s+%lu\n",
lookupAddress,
linkageName.c_str(),
inVariableOffset);
continue;
}
auto logger = spdlog::stderr_color_st("root");
logger->set_level(spdlog::level::debug);
logger->set_pattern("[%-5l] %v");
spdlog::set_default_logger(logger);

std::vector<AccessPathItem> accessPath;
spdlog::info("Analyzing ELF {}", argv[1]);

auto fullName = GlobalVariableName(
dbg, dwarf::GetCompilationUnitTopDie(dbg, true, variableDie), variableDie, "");
auto dbg = dwarf::OpenDebugInfo(argv[1]);

accessPath.push_back(GlobalVariableAccess{fullName.value_or("(unnamed)"), inVariableOffset});
Namespace root{""};

ResolveAddressToPath(dbg, root, typeDie, inVariableOffset, accessPath);
spdlog::info("Building type tree");
while(dwarf::NavigateToNextCompilationUnit(dbg))
{
auto cuDie = dwarf::GetCompilationUnitTopDie(dbg, true);

printf("0x%08X - ", lookupAddress);
BuildTypeTree(dbg, cuDie, root);
}

for(const auto& pathItem: accessPath)
if (argc == 3 && std::string_view{argv[2]} == "-")
{
// Read from stdin
std::string line;
while(std::getline(std::cin, line))
{
if(std::holds_alternative<GlobalVariableAccess>(pathItem))
if (line.empty())
{
auto& item = std::get<GlobalVariableAccess>(pathItem);

printf("%s", item.name.c_str());
break;
}
else if(std::holds_alternative<MemberAccess>(pathItem))
std::uint32_t lookupAddress = 0;
{
auto& item = std::get<MemberAccess>(pathItem);

printf(".%s", item.name.c_str());
std::string_view s{line};
if(auto [_, ec] = std::from_chars(s.data() + 2, s.data() + s.size(), lookupAddress, 16); ec != std::errc{})
{
printf("Invalid address: %s\n", line.c_str());
continue;
}
}
else if(std::holds_alternative<ArrayAccess>(pathItem))

LookupAddress(lookupAddress, argv[1], dbg, root);
}
}
else
{
for(auto arg = 2; arg < argc; arg++)
{
std::uint32_t lookupAddress = 0;
{
auto& item = std::get<ArrayAccess>(pathItem);
printf("[%ld]", item.index);
std::string_view s{argv[arg]};
std::from_chars(s.data() + 2, s.data() + s.size(), lookupAddress, 16);
}

LookupAddress(lookupAddress, argv[1], dbg, root);
}
printf("\n");
}
}
}

0 comments on commit a7f971b

Please sign in to comment.