diff options
Diffstat (limited to 'libfdtrack/fdtrack.cpp')
-rw-r--r-- | libfdtrack/fdtrack.cpp | 52 |
1 files changed, 34 insertions, 18 deletions
diff --git a/libfdtrack/fdtrack.cpp b/libfdtrack/fdtrack.cpp index 2e9cfbcd0..2d114f23e 100644 --- a/libfdtrack/fdtrack.cpp +++ b/libfdtrack/fdtrack.cpp @@ -31,6 +31,8 @@ #include <array> #include <mutex> +#include <string> +#include <string_view> #include <thread> #include <utility> #include <vector> @@ -43,11 +45,14 @@ #include <android-base/thread_annotations.h> #include <async_safe/log.h> #include <bionic/reserved_signals.h> -#include <unwindstack/LocalUnwinder.h> +#include <unwindstack/Maps.h> +#include <unwindstack/Regs.h> +#include <unwindstack/RegsGetLocal.h> +#include <unwindstack/Unwinder.h> struct FdEntry { std::mutex mutex; - std::vector<unwindstack::LocalFrameData> backtrace GUARDED_BY(mutex); + std::vector<unwindstack::FrameData> backtrace GUARDED_BY(mutex); }; extern "C" void fdtrack_dump(); @@ -62,15 +67,21 @@ static void fd_hook(android_fdtrack_event* event); // Backtraces for the first 4k file descriptors ought to be enough to diagnose an fd leak. static constexpr size_t kFdTableSize = 4096; -// 32 frames, plus two to skip from fdtrack itself. -static constexpr size_t kStackDepth = 34; -static constexpr size_t kStackFrameSkip = 2; +// Only unwind up to 32 frames outside of libfdtrack.so. +static constexpr size_t kStackDepth = 32; + +// Skip any initial frames from libfdtrack.so. +static std::vector<std::string> kSkipFdtrackLib [[clang::no_destroy]] = {"libfdtrack.so"}; static bool installed = false; static std::array<FdEntry, kFdTableSize> stack_traces [[clang::no_destroy]]; -static unwindstack::LocalUnwinder& Unwinder() { - static android::base::NoDestructor<unwindstack::LocalUnwinder> unwinder; - return *unwinder.get(); +static unwindstack::LocalUpdatableMaps& Maps() { + static android::base::NoDestructor<unwindstack::LocalUpdatableMaps> maps; + return *maps.get(); +} +static std::shared_ptr<unwindstack::Memory>& ProcessMemory() { + static android::base::NoDestructor<std::shared_ptr<unwindstack::Memory>> process_memory; + return *process_memory.get(); } __attribute__((constructor)) static void ctor() { @@ -89,7 +100,8 @@ __attribute__((constructor)) static void ctor() { sa.sa_flags = SA_SIGINFO | SA_ONSTACK; sigaction(BIONIC_SIGNAL_FDTRACK, &sa, nullptr); - if (Unwinder().Init()) { + if (Maps().Parse()) { + ProcessMemory() = unwindstack::Memory::CreateProcessMemoryThreadCached(getpid()); android_fdtrack_hook_t expected = nullptr; installed = android_fdtrack_compare_exchange_hook(&expected, &fd_hook); } @@ -116,7 +128,12 @@ static void fd_hook(android_fdtrack_event* event) { if (FdEntry* entry = GetFdEntry(event->fd); entry) { std::lock_guard<std::mutex> lock(entry->mutex); entry->backtrace.clear(); - Unwinder().Unwind(&entry->backtrace, kStackDepth); + + std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromLocal()); + unwindstack::RegsGetLocal(regs.get()); + unwindstack::Unwinder unwinder(kStackDepth, &Maps(), regs.get(), ProcessMemory()); + unwinder.Unwind(&kSkipFdtrackLib); + entry->backtrace = unwinder.ConsumeFrames(); } } else if (event->type == ANDROID_FDTRACK_EVENT_TYPE_CLOSE) { if (FdEntry* entry = GetFdEntry(event->fd); entry) { @@ -153,14 +170,13 @@ void fdtrack_iterate(fdtrack_callback_t callback, void* arg) { continue; } - for (size_t i = kStackFrameSkip; i < entry->backtrace.size(); ++i) { - size_t j = i - kStackFrameSkip; - function_names[j] = entry->backtrace[i].function_name.c_str(); - function_offsets[j] = entry->backtrace[i].function_offset; + for (size_t i = 0; i < entry->backtrace.size(); ++i) { + function_names[i] = entry->backtrace[i].function_name.c_str(); + function_offsets[i] = entry->backtrace[i].function_offset; } - bool should_continue = callback(fd, function_names, function_offsets, - entry->backtrace.size() - kStackFrameSkip, arg); + bool should_continue = + callback(fd, function_names, function_offsets, entry->backtrace.size(), arg); entry->mutex.unlock(); @@ -200,8 +216,8 @@ static void fdtrack_dump_impl(bool fatal) { size_t count = 0; size_t stack_depth = 0; - const char* function_names[kStackDepth - kStackFrameSkip]; - uint64_t function_offsets[kStackDepth - kStackFrameSkip]; + const char* function_names[kStackDepth]; + uint64_t function_offsets[kStackDepth]; }; struct StackList { size_t count = 0; |