From a7f971be76aaa7c7d5022964dcf92837644290ca Mon Sep 17 00:00:00 2001 From: Maciej Nowak Date: Mon, 4 Dec 2023 17:49:15 +0100 Subject: [PATCH] Accept input from stdin --- execs/addr2field/src/main.cpp | 204 ++++++++++++++++++++-------------- 1 file changed, 120 insertions(+), 84 deletions(-) diff --git a/execs/addr2field/src/main.cpp b/execs/addr2field/src/main.cpp index 8dc5e57..ae92719 100644 --- a/execs/addr2field/src/main.cpp +++ b/execs/addr2field/src/main.cpp @@ -12,6 +12,7 @@ #include "libdwarf/libdwarf.h" #include "spdlog/sinks/stdout_color_sinks.h" #include "spdlog/spdlog.h" +#include using namespace std::string_literals; @@ -279,128 +280,163 @@ static std::optional 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 0x
[0x
...]\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(variableDie)) + { + // iterate to the end of CU list + while(dwarf::NavigateToNextCompilationUnit(dbg)) + ; + break; + } } - for(auto arg = 2; arg < argc; arg++) + if(!static_cast(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(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 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(pathItem)) { - auto cuDie = dwarf::GetCompilationUnitTopDie(dbg, true); - spdlog::debug("CU: {}", dwarf::ReadDieName(cuDie).value_or("(unnamed)")); + auto& item = std::get(pathItem); - variableDie = FindVariableDie(dbg, cuDie, linkageName, lookupAddress - inVariableOffset); - if(static_cast(variableDie)) - { - // iterate to the end of CU list - while(dwarf::NavigateToNextCompilationUnit(dbg)) - ; - break; - } + printf("%s", item.name.c_str()); } + else if(std::holds_alternative(pathItem)) + { + auto& item = std::get(pathItem); - if(!static_cast(variableDie)) + printf(".%s", item.name.c_str()); + } + else if(std::holds_alternative(pathItem)) { - printf( - "0x%08X - DIE for variable not found. Symbol: %s+%lu\n", - lookupAddress, - linkageName.c_str(), - inVariableOffset); - continue; + auto& item = std::get(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 0x
[0x
...]\n", argv[0]); + fprintf(stderr, "\tResolve addresses given on command line\n"); + fprintf(stderr, "%s 0x
- \n", argv[0]); + fprintf(stderr, "\tAccept addresses one-by-one from standard input and resolve them\n"); + return 1; + } - if(!static_cast(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 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(pathItem)) + if (line.empty()) { - auto& item = std::get(pathItem); - - printf("%s", item.name.c_str()); + break; } - else if(std::holds_alternative(pathItem)) + std::uint32_t lookupAddress = 0; { - auto& item = std::get(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(pathItem)) + + LookupAddress(lookupAddress, argv[1], dbg, root); + } + } + else + { + for(auto arg = 2; arg < argc; arg++) + { + std::uint32_t lookupAddress = 0; { - auto& item = std::get(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"); } -} \ No newline at end of file +}