summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sal/osl/unx/backtraceapi.cxx24
1 files changed, 21 insertions, 3 deletions
diff --git a/sal/osl/unx/backtraceapi.cxx b/sal/osl/unx/backtraceapi.cxx
index e24a9150c91d..8e55cc338020 100644
--- a/sal/osl/unx/backtraceapi.cxx
+++ b/sal/osl/unx/backtraceapi.cxx
@@ -52,6 +52,8 @@ std::unique_ptr<sal::BacktraceState> sal::backtrace_get(sal_uInt32 maxDepth)
#include <vector>
#include <osl/process.h>
#include <rtl/strbuf.hxx>
+#include <osl/mutex.hxx>
+#include <o3tl/lru_map.hxx>
#include "file_url.hxx"
namespace
@@ -59,11 +61,16 @@ namespace
struct FrameData
{
const char* file = nullptr;
+ void* addr;
ptrdiff_t offset;
OString info;
bool handled = false;
};
+typedef o3tl::lru_map<void*, OString> FrameCache;
+osl::Mutex frameCacheMutex;
+FrameCache frameCache( 256 );
+
void process_file_addr2line( const char* file, std::vector<FrameData>& frameData )
{
OUString binary("addr2line");
@@ -77,7 +84,7 @@ void process_file_addr2line( const char* file, std::vector<FrameData>& frameData
args.push_back( arg2.pData );
for( FrameData& frame : frameData )
{
- if( strcmp( file, frame.file ) == 0 )
+ if( frame.file != nullptr && strcmp( file, frame.file ) == 0 )
{
addrs.push_back("0x" + OUString::number(frame.offset, 16));
args.push_back(addrs.back().pData);
@@ -144,7 +151,7 @@ void process_file_addr2line( const char* file, std::vector<FrameData>& frameData
size_t linesPos = 0;
for( FrameData& frame : frameData )
{
- if( strcmp( file, frame.file ) == 0 )
+ if( frame.file != nullptr && strcmp( file, frame.file ) == 0 )
{
// There should be two lines, first function name and second source file information.
// If each of them starts with ??, it is invalid/unknown.
@@ -157,6 +164,8 @@ void process_file_addr2line( const char* file, std::vector<FrameData>& frameData
frame.info = function + " in " + file;
else
frame.info = function + " at " + source;
+ osl::MutexGuard guard(frameCacheMutex);
+ frameCache.insert( { frame.addr, frame.info } );
}
}
}
@@ -174,11 +183,20 @@ OUString sal::backtrace_to_string(BacktraceState* backtraceState)
{
Dl_info dli;
void* addr = backtraceState->buffer[i];
- if (dladdr(addr, &dli) != 0)
+ osl::ClearableMutexGuard guard(frameCacheMutex);
+ auto it = frameCache.find(addr);
+ guard.clear();
+ if( it != frameCache.end())
+ {
+ frameData[ i ].info = it->second;
+ frameData[ i ].handled = true;
+ }
+ else if (dladdr(addr, &dli) != 0)
{
if (dli.dli_fname && dli.dli_fbase)
{
frameData[ i ].file = dli.dli_fname;
+ frameData[ i ].addr = addr;
frameData[ i ].offset = reinterpret_cast<ptrdiff_t>(addr) - reinterpret_cast<ptrdiff_t>(dli.dli_fbase);
}
}