diff --git a/src/symbols/symbols.hpp b/src/symbols/symbols.hpp index 9078744..1750531 100644 --- a/src/symbols/symbols.hpp +++ b/src/symbols/symbols.hpp @@ -6,8 +6,19 @@ #include #include +#include "../platform/object.hpp" + namespace cpptrace { namespace detail { + using collated_vec = std::vector< + std::pair, std::reference_wrapper> + >; + + std::unordered_map collate_frames( + const std::vector& frames, + std::vector& trace + ); + #ifdef CPPTRACE_GET_SYMBOLS_WITH_LIBBACKTRACE namespace libbacktrace { std::vector resolve_frames(const std::vector& frames); @@ -38,6 +49,7 @@ namespace detail { std::vector resolve_frames(const std::vector& frames); } #endif + std::vector resolve_frames(const std::vector& frames); } } diff --git a/src/symbols/symbols_core.cpp b/src/symbols/symbols_core.cpp index 5737855..556f7a4 100644 --- a/src/symbols/symbols_core.cpp +++ b/src/symbols/symbols_core.cpp @@ -7,6 +7,25 @@ namespace cpptrace { namespace detail { + std::unordered_map collate_frames( + const std::vector& frames, + std::vector& trace + ) { + std::unordered_map entries; + for(std::size_t i = 0; i < frames.size(); i++) { + const auto& entry = frames[i]; + // If libdl fails to find the shared object for a frame, the path will be empty. I've observed this + // on macos when looking up the shared object containing `start`. + if(!entry.obj_path.empty()) { + entries[entry.obj_path].emplace_back( + entry, + trace[i] + ); + } + } + return entries; + } + void apply_trace( std::vector& result, std::vector&& trace diff --git a/src/symbols/symbols_with_addr2line.cpp b/src/symbols/symbols_with_addr2line.cpp index d345cbb..87590bc 100644 --- a/src/symbols/symbols_with_addr2line.cpp +++ b/src/symbols/symbols_with_addr2line.cpp @@ -190,45 +190,8 @@ namespace addr2line { } #endif - using target_vec = std::vector>>; - // NOLINTNEXTLINE(readability-convert-member-functions-to-static) - std::unordered_map get_addr2line_targets( - const std::vector& dlframes, - std::vector& trace - ) { - std::unordered_map entries; - for(std::size_t i = 0; i < dlframes.size(); i++) { - const auto& entry = dlframes[i]; - // If libdl fails to find the shared object for a frame, the path will be empty. I've observed this - // on macos when looking up the shared object containing `start`. - if(!entry.obj_path.empty()) { - ///fprintf( - /// stderr, - /// "%s %s\n", - /// to_hex(entry.raw_address).c_str(), - /// to_hex(entry.raw_address - entry.obj_base + base).c_str() - ///); - try { - entries[entry.obj_path].emplace_back( - to_hex(entry.obj_address), - trace[i] - ); - } catch(file_error&) { - // - } catch(...) { - throw; - } - // Set what is known for now, and resolutions from addr2line should overwrite - trace[i].filename = entry.obj_path; - trace[i].symbol = entry.symbol; - } - } - return entries; - } - - // NOLINTNEXTLINE(readability-convert-member-functions-to-static) - void update_trace(const std::string& line, size_t entry_index, const target_vec& entries_vec) { + void update_trace(const std::string& line, size_t entry_index, const collated_vec& entries_vec) { #if !IS_APPLE // Result will be of the form " at path:line" // The path may be ?? if addr2line cannot resolve, line may be ? @@ -311,12 +274,15 @@ namespace addr2line { std::vector resolve_frames(const std::vector& frames) { // TODO: Refactor better std::vector trace(frames.size(), stacktrace_frame { 0, 0, 0, "", "" }); - for(size_t i = 0; i < frames.size(); i++) { - trace[i].address = reinterpret_cast(frames[i]); + const std::vector dlframes = get_frames_object_info(frames); + for(size_t i = 0; i < dlframes.size(); i++) { + trace[i].address = dlframes[i].raw_address; + // Set what is known for now, and resolutions from addr2line should overwrite + trace[i].filename = dlframes[i].obj_path; + trace[i].symbol = dlframes[i].symbol; } if(has_addr2line()) { - const std::vector dlframes = get_frames_object_info(frames); - const auto entries = get_addr2line_targets(dlframes, trace); + const auto entries = collate_frames(dlframes, trace); for(const auto& entry : entries) { const auto& object_name = entry.first; const auto& entries_vec = entry.second; @@ -329,7 +295,7 @@ namespace addr2line { } std::string address_input; for(const auto& pair : entries_vec) { - address_input += pair.first; + address_input += to_hex(pair.first.get().obj_address); #if !IS_WINDOWS address_input += '\n'; #else