Some refactoring, bring object_frame in line with safe_object_frame. Also renamed address_relative_to_object_base_in_memory.

This commit is contained in:
Jeremy 2023-11-20 23:13:21 -06:00
parent 2a4a8066d3
commit 9113cc5ffc
No known key found for this signature in database
GPG Key ID: B4C8300FEC395042
12 changed files with 109 additions and 109 deletions

View File

@ -185,9 +185,9 @@ is resolved), and the path to the object the instruction pointer is located in.
```cpp
namespace cpptrace {
struct object_frame {
std::string obj_path;
std::string object_path;
frame_ptr raw_address;
frame_ptr obj_address;
frame_ptr object_address;
};
struct object_trace {
@ -410,7 +410,7 @@ namespace cpptrace {
std::size_t safe_generate_raw_trace(frame_ptr* buffer, std::size_t size, std::size_t skip, std::size_t max_depth);
struct safe_object_frame {
frame_ptr raw_address;
frame_ptr address_relative_to_object_base_in_memory;
frame_ptr address_relative_to_object_start; // object base address must yet be added
char object_path[CPPTRACE_PATH_MAX + 1];
object_frame resolve() const; // To be called outside a signal handler. Not signal safe.
};

View File

@ -54,9 +54,9 @@ namespace cpptrace {
};
struct CPPTRACE_EXPORT object_frame {
std::string obj_path;
frame_ptr raw_address;
frame_ptr obj_address;
frame_ptr object_address;
std::string object_path;
};
struct CPPTRACE_EXPORT object_trace {
@ -195,7 +195,7 @@ namespace cpptrace {
);
struct CPPTRACE_EXPORT safe_object_frame {
frame_ptr raw_address;
frame_ptr address_relative_to_object_base_in_memory;
frame_ptr address_relative_to_object_start; // base must still be added
char object_path[CPPTRACE_PATH_MAX + 1];
// To be called outside a signal handler. Not signal safe.
object_frame resolve() const;

View File

@ -46,7 +46,7 @@ namespace cpptrace {
struct safe_object_frame {
frame_ptr raw_address;
frame_ptr address_relative_to_object_base_in_memory;
frame_ptr address_relative_to_object_start; // object base address must yet be added
char object_path[CPPTRACE_PATH_MAX + 1];
object_frame resolve() const; // To be called outside a signal handler. Not signal safe.
};

View File

@ -26,7 +26,7 @@ namespace detail {
template<std::size_t Bits>
static std::uintptr_t elf_get_module_image_base_from_program_table(
const std::string& obj_path,
const std::string& object_path,
std::FILE* file,
bool is_little_endian
) {
@ -34,7 +34,7 @@ namespace detail {
using Header = typename std::conditional<Bits == 32, Elf32_Ehdr, Elf64_Ehdr>::type;
using PHeader = typename std::conditional<Bits == 32, Elf32_Phdr, Elf64_Phdr>::type;
Header file_header = load_bytes<Header>(file, 0);
VERIFY(file_header.e_ehsize == sizeof(Header), "ELF file header size mismatch" + obj_path);
VERIFY(file_header.e_ehsize == sizeof(Header), "ELF file header size mismatch" + object_path);
// PT_PHDR will occur at most once
// Should be somewhat reliable https://stackoverflow.com/q/61568612/15675011
// It should occur at the beginning but may as well loop just in case
@ -49,22 +49,22 @@ namespace detail {
return 0;
}
static std::uintptr_t elf_get_module_image_base(const std::string& obj_path) {
auto file = raii_wrap(std::fopen(obj_path.c_str(), "rb"), file_deleter);
static std::uintptr_t elf_get_module_image_base(const std::string& object_path) {
auto file = raii_wrap(std::fopen(object_path.c_str(), "rb"), file_deleter);
if(file == nullptr) {
throw file_error("Unable to read object file " + obj_path);
throw file_error("Unable to read object file " + object_path);
}
// Initial checks/metadata
auto magic = load_bytes<std::array<char, 4>>(file, 0);
VERIFY(magic == (std::array<char, 4>{0x7F, 'E', 'L', 'F'}), "File is not ELF " + obj_path);
VERIFY(magic == (std::array<char, 4>{0x7F, 'E', 'L', 'F'}), "File is not ELF " + object_path);
bool is_64 = load_bytes<std::uint8_t>(file, 4) == 2;
bool is_little_endian = load_bytes<std::uint8_t>(file, 5) == 1;
VERIFY(load_bytes<std::uint8_t>(file, 6) == 1, "Unexpected ELF endianness " + obj_path);
VERIFY(load_bytes<std::uint8_t>(file, 6) == 1, "Unexpected ELF endianness " + object_path);
// get image base
if(is_64) {
return elf_get_module_image_base_from_program_table<64>(obj_path, file, is_little_endian);
return elf_get_module_image_base_from_program_table<64>(object_path, file, is_little_endian);
} else {
return elf_get_module_image_base_from_program_table<32>(obj_path, file, is_little_endian);
return elf_get_module_image_base_from_program_table<32>(object_path, file, is_little_endian);
}
}
}

View File

@ -75,8 +75,8 @@ namespace detail {
template<std::size_t Bits>
static optional<std::uintptr_t> macho_get_text_vmaddr_mach(
std::FILE* obj_file,
const std::string& obj_path,
std::FILE* object_file,
const std::string& object_path,
off_t offset,
bool should_swap,
bool allow_arch_mismatch
@ -87,7 +87,7 @@ namespace detail {
std::uint32_t ncmds;
off_t load_commands_offset = offset;
std::size_t header_size = sizeof(Mach_Header);
Mach_Header header = load_bytes<Mach_Header>(obj_file, offset);
Mach_Header header = load_bytes<Mach_Header>(object_file, offset);
if(should_swap) {
swap_mach_header(header);
}
@ -107,7 +107,7 @@ namespace detail {
if(allow_arch_mismatch) {
return nullopt;
} else {
PANIC("Mach-O file cpu type and subtype do not match current machine " + obj_path);
PANIC("Mach-O file cpu type and subtype do not match current machine " + object_path);
}
}
ncmds = header.ncmds;
@ -115,12 +115,12 @@ namespace detail {
// iterate load commands
off_t actual_offset = load_commands_offset;
for(std::uint32_t i = 0; i < ncmds; i++) {
load_command cmd = load_bytes<load_command>(obj_file, actual_offset);
load_command cmd = load_bytes<load_command>(object_file, actual_offset);
if(should_swap) {
swap_load_command(&cmd, NX_UnknownByteOrder);
}
// TODO: This is a mistake? Need to check cmd.cmd == LC_SEGMENT_64 / cmd.cmd == LC_SEGMENT
Segment_Command segment = load_bytes<Segment_Command>(obj_file, actual_offset);
Segment_Command segment = load_bytes<Segment_Command>(object_file, actual_offset);
if(should_swap) {
swap_segment_command(segment);
}
@ -135,38 +135,38 @@ namespace detail {
}
static std::uintptr_t macho_get_text_vmaddr_fat(
std::FILE* obj_file,
const std::string& obj_path,
std::FILE* object_file,
const std::string& object_path,
bool should_swap
) {
std::size_t header_size = sizeof(fat_header);
std::size_t arch_size = sizeof(fat_arch);
fat_header header = load_bytes<fat_header>(obj_file, 0);
fat_header header = load_bytes<fat_header>(object_file, 0);
if(should_swap) {
swap_fat_header(&header, NX_UnknownByteOrder);
}
off_t arch_offset = (off_t)header_size;
optional<std::uintptr_t> text_vmaddr;
for(std::uint32_t i = 0; i < header.nfat_arch; i++) {
fat_arch arch = load_bytes<fat_arch>(obj_file, arch_offset);
fat_arch arch = load_bytes<fat_arch>(object_file, arch_offset);
if(should_swap) {
swap_fat_arch(&arch, 1, NX_UnknownByteOrder);
}
off_t mach_header_offset = (off_t)arch.offset;
arch_offset += arch_size;
std::uint32_t magic = load_bytes<std::uint32_t>(obj_file, mach_header_offset);
std::uint32_t magic = load_bytes<std::uint32_t>(object_file, mach_header_offset);
if(is_magic_64(magic)) {
text_vmaddr = macho_get_text_vmaddr_mach<64>(
obj_file,
obj_path,
object_file,
object_path,
mach_header_offset,
should_swap_bytes(magic),
true
);
} else {
text_vmaddr = macho_get_text_vmaddr_mach<32>(
obj_file,
obj_path,
object_file,
object_path,
mach_header_offset,
should_swap_bytes(magic),
true
@ -181,31 +181,31 @@ namespace detail {
return 0;
}
static std::uintptr_t macho_get_text_vmaddr(const std::string& obj_path) {
//std::fprintf(stderr, "--%s--\n", obj_path.c_str());
auto file = raii_wrap(std::fopen(obj_path.c_str(), "rb"), file_deleter);
static std::uintptr_t macho_get_text_vmaddr(const std::string& object_path) {
//std::fprintf(stderr, "--%s--\n", object_path.c_str());
auto file = raii_wrap(std::fopen(object_path.c_str(), "rb"), file_deleter);
if(file == nullptr) {
throw file_error("Unable to read object file " + obj_path);
throw file_error("Unable to read object file " + object_path);
}
std::uint32_t magic = load_bytes<std::uint32_t>(file, 0);
VERIFY(is_mach_o(magic), "File is not Mach-O " + obj_path);
VERIFY(is_mach_o(magic), "File is not Mach-O " + object_path);
bool is_64 = is_magic_64(magic);
bool should_swap = should_swap_bytes(magic);
if(magic == FAT_MAGIC || magic == FAT_CIGAM) {
return macho_get_text_vmaddr_fat(file, obj_path, should_swap);
return macho_get_text_vmaddr_fat(file, object_path, should_swap);
} else {
if(is_64) {
return macho_get_text_vmaddr_mach<64>(file, obj_path, 0, should_swap, false).unwrap();
return macho_get_text_vmaddr_mach<64>(file, object_path, 0, should_swap, false).unwrap();
} else {
return macho_get_text_vmaddr_mach<32>(file, obj_path, 0, should_swap, false).unwrap();
return macho_get_text_vmaddr_mach<32>(file, object_path, 0, should_swap, false).unwrap();
}
}
}
inline bool macho_is_fat(const std::string& obj_path) {
auto file = raii_wrap(std::fopen(obj_path.c_str(), "rb"), file_deleter);
inline bool macho_is_fat(const std::string& object_path) {
auto file = raii_wrap(std::fopen(object_path.c_str(), "rb"), file_deleter);
if(file == nullptr) {
throw file_error("Unable to read object file " + obj_path);
throw file_error("Unable to read object file " + object_path);
}
std::uint32_t magic = load_bytes<std::uint32_t>(file, 0);
return is_fat_magic(magic);
@ -213,10 +213,10 @@ namespace detail {
// returns index of the appropriate mach-o binary in the universal binary
// TODO: Code duplication with macho_get_text_vmaddr_fat
inline unsigned get_fat_macho_index(const std::string& obj_path) {
auto file = raii_wrap(std::fopen(obj_path.c_str(), "rb"), file_deleter);
inline unsigned get_fat_macho_index(const std::string& object_path) {
auto file = raii_wrap(std::fopen(object_path.c_str(), "rb"), file_deleter);
if(file == nullptr) {
throw file_error("Unable to read object file " + obj_path);
throw file_error("Unable to read object file " + object_path);
}
std::uint32_t magic = load_bytes<std::uint32_t>(file, 0);
VERIFY(is_fat_magic(magic));

View File

@ -26,35 +26,35 @@ namespace cpptrace {
namespace detail {
#if IS_LINUX || IS_APPLE
#if !IS_APPLE
inline std::uintptr_t get_module_image_base(const std::string& obj_path) {
inline std::uintptr_t get_module_image_base(const std::string& object_path) {
static std::mutex mutex;
std::lock_guard<std::mutex> lock(mutex);
static std::unordered_map<std::string, std::uintptr_t> cache;
auto it = cache.find(obj_path);
auto it = cache.find(object_path);
if(it == cache.end()) {
// arguably it'd be better to release the lock while computing this, but also arguably it's good to not
// have two threads try to do the same computation
auto base = elf_get_module_image_base(obj_path);
cache.insert(it, {obj_path, base});
auto base = elf_get_module_image_base(object_path);
cache.insert(it, {object_path, base});
return base;
} else {
return it->second;
}
}
#else
inline std::uintptr_t get_module_image_base(const std::string& obj_path) {
inline std::uintptr_t get_module_image_base(const std::string& object_path) {
// We have to parse the Mach-O to find the offset of the text section.....
// I don't know how addresses are handled if there is more than one __TEXT load command. I'm assuming for
// now that there is only one, and I'm using only the first section entry within that load command.
static std::mutex mutex;
std::lock_guard<std::mutex> lock(mutex);
static std::unordered_map<std::string, std::uintptr_t> cache;
auto it = cache.find(obj_path);
auto it = cache.find(object_path);
if(it == cache.end()) {
// arguably it'd be better to release the lock while computing this, but also arguably it's good to not
// have two threads try to do the same computation
auto base = macho_get_text_vmaddr(obj_path);
cache.insert(it, {obj_path, base});
auto base = macho_get_text_vmaddr(object_path);
cache.insert(it, {object_path, base});
return base;
} else {
return it->second;
@ -70,12 +70,12 @@ namespace detail {
Dl_info info;
object_frame frame;
frame.raw_address = addr;
frame.obj_address = 0;
frame.object_address = 0;
if(dladdr(reinterpret_cast<void*>(addr), &info)) { // thread safe
// dli_sname and dli_saddr are only present with -rdynamic, sname will be included
// but we don't really need dli_saddr
frame.obj_path = info.dli_fname;
frame.obj_address = addr
frame.object_path = info.dli_fname;
frame.object_address = addr
- reinterpret_cast<std::uintptr_t>(info.dli_fbase)
+ get_module_image_base(info.dli_fname);
}
@ -105,16 +105,16 @@ namespace detail {
}
}
inline std::uintptr_t get_module_image_base(const std::string& obj_path) {
inline std::uintptr_t get_module_image_base(const std::string& object_path) {
static std::mutex mutex;
std::lock_guard<std::mutex> lock(mutex);
static std::unordered_map<std::string, std::uintptr_t> cache;
auto it = cache.find(obj_path);
auto it = cache.find(object_path);
if(it == cache.end()) {
// arguably it'd be better to release the lock while computing this, but also arguably it's good to not
// have two threads try to do the same computation
auto base = pe_get_module_image_base(obj_path);
cache.insert(it, {obj_path, base});
auto base = pe_get_module_image_base(object_path);
cache.insert(it, {object_path, base});
return base;
} else {
return it->second;
@ -129,7 +129,7 @@ namespace detail {
for(const frame_ptr addr : addrs) {
object_frame frame;
frame.raw_address = addr;
frame.obj_address = 0;
frame.object_address = 0;
HMODULE handle;
// Multithread safe as long as another thread doesn't come along and free the module
if(GetModuleHandleExA(
@ -137,10 +137,10 @@ namespace detail {
reinterpret_cast<const char*>(addr),
&handle
)) {
frame.obj_path = get_module_name(handle);
frame.obj_address = addr
frame.object_path = get_module_name(handle);
frame.object_address = addr
- reinterpret_cast<std::uintptr_t>(handle)
+ get_module_image_base(frame.obj_path);
+ get_module_image_base(frame.object_path);
} else {
std::fprintf(stderr, "%s\n", std::system_error(GetLastError(), std::system_category()).what());
}
@ -152,9 +152,9 @@ namespace detail {
inline object_frame resolve_safe_object_frame(const safe_object_frame& frame) {
return {
frame.object_path,
frame.raw_address,
frame.address_relative_to_object_base_in_memory + get_module_image_base(frame.object_path)
frame.address_relative_to_object_start + get_module_image_base(frame.object_path),
frame.object_path
};
}
}

View File

@ -26,22 +26,22 @@ namespace detail {
}
}
inline std::uintptr_t pe_get_module_image_base(const std::string& obj_path) {
inline std::uintptr_t pe_get_module_image_base(const std::string& object_path) {
// https://drive.google.com/file/d/0B3_wGJkuWLytbnIxY1J5WUs4MEk/view?pli=1&resourcekey=0-n5zZ2UW39xVTH8ZSu6C2aQ
// https://0xrick.github.io/win-internals/pe3/
// Endianness should always be little for dos and pe headers
std::FILE* file_ptr;
errno_t ret = fopen_s(&file_ptr, obj_path.c_str(), "rb");
errno_t ret = fopen_s(&file_ptr, object_path.c_str(), "rb");
auto file = raii_wrap(std::move(file_ptr), file_deleter);
if(ret != 0 || file == nullptr) {
throw file_error("Unable to read object file " + obj_path);
throw file_error("Unable to read object file " + object_path);
}
auto magic = load_bytes<std::array<char, 2>>(file, 0);
VERIFY(std::memcmp(magic.data(), "MZ", 2) == 0, "File is not a PE file " + obj_path);
VERIFY(std::memcmp(magic.data(), "MZ", 2) == 0, "File is not a PE file " + object_path);
DWORD e_lfanew = pe_byteswap_if_needed(load_bytes<DWORD>(file, 0x3c)); // dos header + 0x3c
DWORD nt_header_offset = e_lfanew;
auto signature = load_bytes<std::array<char, 4>>(file, nt_header_offset); // nt header + 0
VERIFY(std::memcmp(signature.data(), "PE\0\0", 4) == 0, "File is not a PE file " + obj_path);
VERIFY(std::memcmp(signature.data(), "PE\0\0", 4) == 0, "File is not a PE file " + object_path);
WORD size_of_optional_header = pe_byteswap_if_needed(
load_bytes<WORD>(file, nt_header_offset + 4 + 0x10) // file header + 0x10
);
@ -51,7 +51,7 @@ namespace detail {
);
VERIFY(
optional_header_magic == IMAGE_NT_OPTIONAL_HDR_MAGIC,
"PE file does not match expected bit-mode " + obj_path
"PE file does not match expected bit-mode " + object_path
);
// finally get image base
if(optional_header_magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {

View File

@ -25,7 +25,7 @@ namespace detail {
dl_find_object result;
if(_dl_find_object(reinterpret_cast<void*>(address), &result) == 0) {
out->raw_address = address;
out->address_relative_to_object_base_in_memory = address - reinterpret_cast<frame_ptr>(result.dlfo_map_start);
out->address_relative_to_object_start = address - reinterpret_cast<frame_ptr>(result.dlfo_map_start);
if(result.dlfo_link_map->l_name != nullptr && result.dlfo_link_map->l_name[0] != 0) {
std::size_t path_length = std::strlen(result.dlfo_link_map->l_name);
std::memcpy(
@ -45,7 +45,7 @@ namespace detail {
} else {
// std::cout<<"error"<<std::endl;
out->raw_address = address;
out->address_relative_to_object_base_in_memory = 0;
out->address_relative_to_object_start = 0;
out->object_path[0] = 0;
}
// TODO: Handle this part of the documentation?
@ -61,7 +61,7 @@ namespace cpptrace {
namespace detail {
inline void get_safe_object_frame(frame_ptr address, safe_object_frame* out) {
out->raw_address = address;
out->address_relative_to_object_base_in_memory = 0;
out->address_relative_to_object_start = 0;
out->object_path[0] = 0;
}
}

View File

@ -17,8 +17,8 @@ namespace detail {
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(
if(!entry.object_path.empty()) {
entries[entry.object_path].emplace_back(
entry,
trace[i]
);
@ -36,8 +36,8 @@ namespace detail {
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(
if(!entry.object_path.empty()) {
entries[entry.object_path].emplace_back(
entry,
trace[i]
);

View File

@ -236,12 +236,12 @@ namespace addr2line {
}
const std::size_t symbol_end = in_location;
entries_vec[entry_index].second.get().symbol = line.substr(0, symbol_end);
const std::size_t obj_end = line.find(")", in_location);
const std::size_t object_end = line.find(")", in_location);
VERIFY(
obj_end != std::string::npos,
object_end != std::string::npos,
"Unexpected edge case while processing addr2line/atos output"
);
const std::size_t filename_start = line.find(") (", obj_end);
const std::size_t filename_start = line.find(") (", object_end);
if(filename_start == std::string::npos) {
// presumably something like 0x100003b70 (in demo) or foo (in bar) + 14
return;
@ -271,7 +271,7 @@ namespace addr2line {
for(std::size_t i = 0; i < frames.size(); i++) {
trace[i].address = frames[i].raw_address;
// Set what is known for now, and resolutions from addr2line should overwrite
trace[i].filename = frames[i].obj_path;
trace[i].filename = frames[i].object_path;
}
if(has_addr2line()) {
const auto entries = collate_frames(frames, trace);
@ -288,7 +288,7 @@ namespace addr2line {
}
std::string address_input;
for(const auto& pair : entries_vec) {
address_input += to_hex(pair.first.get().obj_address);
address_input += to_hex(pair.first.get().object_address);
#if !IS_WINDOWS
address_input += '\n';
#else

View File

@ -83,7 +83,7 @@ namespace libdwarf {
};
struct dwarf_resolver {
std::string obj_path;
std::string object_path;
Dwarf_Debug dbg = nullptr;
bool ok = false;
// .debug_aranges cache
@ -124,16 +124,16 @@ namespace libdwarf {
}
CPPTRACE_FORCE_NO_INLINE_FOR_PROFILING
dwarf_resolver(const std::string& object_path) {
obj_path = object_path;
dwarf_resolver(const std::string& _object_path) {
object_path = _object_path;
// for universal / fat mach-o files
unsigned universal_number = 0;
#if IS_APPLE
if(directory_exists(obj_path + ".dSYM")) {
obj_path += ".dSYM/Contents/Resources/DWARF/" + basename(object_path);
if(directory_exists(object_path + ".dSYM")) {
object_path += ".dSYM/Contents/Resources/DWARF/" + basename(object_path);
}
if(macho_is_fat(obj_path)) {
universal_number = get_fat_macho_index(obj_path);
if(macho_is_fat(object_path)) {
universal_number = get_fat_macho_index(object_path);
}
#endif
@ -142,7 +142,7 @@ namespace libdwarf {
std::unique_ptr<char[]> buffer(new char[CPPTRACE_MAX_PATH]);
auto ret = wrap(
dwarf_init_path_a,
obj_path.c_str(),
object_path.c_str(),
buffer.get(),
CPPTRACE_MAX_PATH,
DW_GROUPNUMBER_ANY,
@ -205,7 +205,7 @@ namespace libdwarf {
dwarf_resolver& operator=(const dwarf_resolver&) = delete;
dwarf_resolver(dwarf_resolver&& other) noexcept :
obj_path(std::move(other.obj_path)),
object_path(std::move(other.object_path)),
dbg(other.dbg),
ok(other.ok),
aranges(other.aranges),
@ -220,7 +220,7 @@ namespace libdwarf {
}
dwarf_resolver& operator=(dwarf_resolver&& other) noexcept {
obj_path = std::move(other.obj_path);
object_path = std::move(other.object_path);
dbg = other.dbg;
ok = other.ok;
aranges = other.aranges;
@ -763,7 +763,7 @@ namespace libdwarf {
std::vector<stacktrace_frame>& inlines
) {
if(dump_dwarf) {
std::fprintf(stderr, "%s\n", obj_path.c_str());
std::fprintf(stderr, "%s\n", object_path.c_str());
std::fprintf(stderr, "%llx\n", to_ull(pc));
}
// Check for .debug_aranges for fast lookup
@ -849,19 +849,19 @@ namespace libdwarf {
CPPTRACE_FORCE_NO_INLINE_FOR_PROFILING
frame_with_inlines resolve_frame(const object_frame& frame_info) {
stacktrace_frame frame = null_frame;
frame.filename = frame_info.obj_path;
frame.filename = frame_info.object_path;
frame.address = frame_info.raw_address;
if(trace_dwarf) {
std::fprintf(
stderr,
"Starting resolution for %s %08llx\n",
obj_path.c_str(),
to_ull(frame_info.obj_address)
object_path.c_str(),
to_ull(frame_info.object_address)
);
}
std::vector<stacktrace_frame> inlines;
lookup_pc(
frame_info.obj_address,
frame_info.object_address,
frame,
inlines
);
@ -877,21 +877,21 @@ namespace libdwarf {
static std::unordered_map<std::string, dwarf_resolver> resolver_map;
// Locking around all libdwarf interaction per https://github.com/davea42/libdwarf-code/discussions/184
const std::lock_guard<std::mutex> lock(mutex);
for(const auto& obj_entry : collate_frames(frames, trace)) {
for(const auto& object_entry : collate_frames(frames, trace)) {
try {
const auto& obj_name = obj_entry.first;
const auto& object_name = object_entry.first;
optional<dwarf_resolver> resolver_object = nullopt;
dwarf_resolver* resolver = nullptr;
auto it = resolver_map.find(obj_name);
auto it = resolver_map.find(object_name);
if(it != resolver_map.end()) {
resolver = &it->second;
} else {
resolver_object = dwarf_resolver(obj_name);
resolver_object = dwarf_resolver(object_name);
resolver = &resolver_object.unwrap();
}
// If there's no debug information it'll mark itself as not ok
if(resolver->ok) {
for(const auto& entry : obj_entry.second) {
for(const auto& entry : object_entry.second) {
try {
const auto& dlframe = entry.first.get();
auto& frame = entry.second.get();
@ -904,7 +904,7 @@ namespace libdwarf {
}
} else {
// at least copy the addresses
for(const auto& entry : obj_entry.second) {
for(const auto& entry : object_entry.second) {
const auto& dlframe = entry.first.get();
auto& frame = entry.second.get();
frame.frame.address = dlframe.raw_address;
@ -912,7 +912,7 @@ namespace libdwarf {
}
if(resolver_object.has_value() && get_cache_mode() == cache_mode::prioritize_speed) {
// .emplace needed, for some reason .insert tries to copy <= gcc 7.2
resolver_map.emplace(obj_name, std::move(resolver_object).unwrap());
resolver_map.emplace(object_name, std::move(resolver_object).unwrap());
}
} catch(...) { // NOSONAR
if(!should_absorb_trace_exceptions()) {

View File

@ -170,10 +170,10 @@ namespace detail {
// TODO: Re-evaluate use of off_t
template<typename T, typename std::enable_if<std::is_trivial<T>::value, int>::type = 0>
T load_bytes(std::FILE* obj_file, off_t offset) {
T load_bytes(std::FILE* object_file, off_t offset) {
T object;
VERIFY(std::fseek(obj_file, offset, SEEK_SET) == 0, "fseek error");
VERIFY(std::fread(&object, sizeof(T), 1, obj_file) == 1, "fread error");
VERIFY(std::fseek(object_file, offset, SEEK_SET) == 0, "fseek error");
VERIFY(std::fread(&object, sizeof(T), 1, object_file) == 1, "fread error");
return object;
}