diff --git a/cmake/FindDL.cmake b/cmake/FindDL.cmake index cc5167ac73..389d228a2f 100644 --- a/cmake/FindDL.cmake +++ b/cmake/FindDL.cmake @@ -10,11 +10,27 @@ check_cxx_source_compiles(" DL_FOUND ) +check_cxx_source_compiles(" + #include + #include + int main() { + Dl_info info; + struct link_map *lm = nullptr; + return dladdr1(0, &info, (void **)&lm, RTLD_DL_LINKMAP); + }" + DL_FOUND2 +) + if (DL_FOUND) add_compile_options( -DWITH_DL ) link_libraries(dl) + if (DL_FOUND2) + add_compile_options( + -DWITH_DL2 + ) + endif (DL_FOUND2) endif (DL_FOUND) set(CMAKE_REQUIRED_LIBRARIES "") diff --git a/src/os/unix/crashlog_unix.cpp b/src/os/unix/crashlog_unix.cpp index 6c63ef9e0d..3c2b056618 100644 --- a/src/os/unix/crashlog_unix.cpp +++ b/src/os/unix/crashlog_unix.cpp @@ -37,6 +37,9 @@ # include #if defined(WITH_DL) # include +#if defined(WITH_DL2) +# include +#endif #endif #if defined(WITH_DEMANGLE) # include @@ -535,16 +538,23 @@ class CrashLogUnix : public CrashLog { for (int i = 0; i < trace_size; i++) { #if defined(WITH_DL) Dl_info info; +#if defined(WITH_DL2) + struct link_map *dl_lm = nullptr; + int dladdr_result = dladdr1(trace[i], &info, (void **)&dl_lm, RTLD_DL_LINKMAP); +#else int dladdr_result = dladdr(trace[i], &info); +#endif /* WITH_DL2 */ const char *func_name = info.dli_sname; void *func_addr = info.dli_saddr; const char *file_name = nullptr; unsigned int line_num = 0; const int ptr_str_size = (2 + sizeof(void*) * 2); - if (dladdr_result && info.dli_fname) { +#if defined(WITH_DL2) + if (dladdr_result && info.dli_fname && dl_lm != nullptr) { char *saved_buffer = buffer; char addr_ptr_buffer[64]; - seprintf(addr_ptr_buffer, lastof(addr_ptr_buffer), PRINTF_SIZEX, (char *)trace[i] - (char *)info.dli_fbase); + /* subtract one to get the line before the return address, i.e. the function call line */ + seprintf(addr_ptr_buffer, lastof(addr_ptr_buffer), PRINTF_SIZEX, (char *)trace[i] - (char *)dl_lm->l_addr - 1); const char *args[] = { "addr2line", "-e", @@ -566,6 +576,7 @@ class CrashLogUnix : public CrashLog { buffer = saved_buffer; *buffer = 0; } +#endif /* WITH_DL2 */ #if defined(WITH_BFD) /* subtract one to get the line before the return address, i.e. the function call line */ sym_info_bfd bfd_info(reinterpret_cast(trace[i]) - reinterpret_cast(info.dli_fbase) - 1);