Loading libbacktrace/Android.bp +2 −6 Original line number Diff line number Diff line Loading @@ -50,7 +50,6 @@ libbacktrace_sources = [ "BacktracePtrace.cpp", "thread_utils.c", "ThreadEntry.cpp", "UnwindDexFile.cpp", "UnwindStack.cpp", "UnwindStackMap.cpp", ] Loading Loading @@ -110,10 +109,9 @@ cc_library { static_libs: ["libasync_safe"], }, vendor: { cflags: ["-DNO_LIBDEXFILE"], exclude_srcs: ["UnwindDexFile.cpp"], cflags: ["-DNO_LIBDEXFILE_SUPPORT"], exclude_shared_libs: ["libdexfile"], }, } }, whole_static_libs: ["libdemangle"], } Loading Loading @@ -145,8 +143,6 @@ cc_test { "backtrace_test.cpp", "GetPss.cpp", "thread_utils.c", "unwind_dex_test.cpp", ], cflags: [ Loading libbacktrace/UnwindStack.cpp +9 −84 Original line number Diff line number Diff line Loading @@ -36,70 +36,15 @@ #include <unwindstack/Regs.h> #include <unwindstack/RegsGetLocal.h> #if !defined(NO_LIBDEXFILE_SUPPORT) #include <unwindstack/DexFiles.h> #endif #include <unwindstack/Unwinder.h> #include "BacktraceLog.h" #ifndef NO_LIBDEXFILE #include "UnwindDexFile.h" #endif #include "UnwindStack.h" #include "UnwindStackMap.h" static void FillInDexFrame(UnwindStackMap* stack_map, uint64_t dex_pc, backtrace_frame_data_t* frame) { // The DEX PC points into the .dex section within an ELF file. // However, this is a BBS section manually mmaped to a .vdex file, // so we need to get the following map to find the ELF data. unwindstack::Maps* maps = stack_map->stack_maps(); auto it = maps->begin(); uint64_t rel_dex_pc; unwindstack::MapInfo* info; for (; it != maps->end(); ++it) { auto entry = *it; if (dex_pc >= entry->start && dex_pc < entry->end) { info = entry; rel_dex_pc = dex_pc - entry->start; frame->map.start = entry->start; frame->map.end = entry->end; frame->map.offset = entry->offset; frame->map.load_bias = entry->load_bias; frame->map.flags = entry->flags; frame->map.name = entry->name; frame->rel_pc = rel_dex_pc; break; } } if (it == maps->end() || ++it == maps->end()) { return; } auto entry = *it; auto process_memory = stack_map->process_memory(); unwindstack::Elf* elf = entry->GetElf(process_memory, true); if (!elf->valid()) { return; } // Adjust the relative dex by the offset. rel_dex_pc += entry->elf_offset; uint64_t dex_offset; if (!elf->GetFunctionName(rel_dex_pc, &frame->func_name, &dex_offset)) { return; } frame->func_offset = dex_offset; if (frame->func_name != "$dexfile") { return; } #ifndef NO_LIBDEXFILE UnwindDexFile* dex_file = stack_map->GetDexFile(dex_pc - dex_offset, info); if (dex_file != nullptr) { dex_file->GetMethodInformation(dex_offset, &frame->func_name, &frame->func_offset); } #endif } bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map, std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames, std::vector<std::string>* skip_names, BacktraceUnwindError* error) { Loading @@ -110,6 +55,11 @@ bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map, if (stack_map->GetJitDebug() != nullptr) { unwinder.SetJitDebug(stack_map->GetJitDebug(), regs->Arch()); } #if !defined(NO_LIBDEXFILE_SUPPORT) if (stack_map->GetDexFiles() != nullptr) { unwinder.SetDexFiles(stack_map->GetDexFiles(), regs->Arch()); } #endif unwinder.Unwind(skip_names, &stack_map->GetSuffixesToIgnore()); if (error != nullptr) { switch (unwinder.LastErrorCode()) { Loading Loading @@ -150,36 +100,11 @@ bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map, } auto unwinder_frames = unwinder.frames(); // Get the real number of frames we'll need. size_t total_frames = 0; for (size_t i = num_ignore_frames; i < unwinder.NumFrames(); i++, total_frames++) { if (unwinder_frames[i].dex_pc != 0) { total_frames++; } } frames->resize(total_frames); frames->resize(unwinder.NumFrames() - num_ignore_frames); size_t cur_frame = 0; for (size_t i = num_ignore_frames; i < unwinder.NumFrames(); i++) { auto frame = &unwinder_frames[i]; // Inject extra 'virtual' frame that represents the dex pc data. // The dex pc is magic register defined in the Mterp interpreter, // and thus it will be restored/observed in the frame after it. // Adding the dex frame first here will create something like: // #7 pc 006b1ba1 libartd.so ExecuteMterpImpl+14625 // #8 pc 0015fa20 core.vdex java.util.Arrays.binarySearch+8 // #9 pc 0039a1ef libartd.so art::interpreter::Execute+719 if (frame->dex_pc != 0) { backtrace_frame_data_t* dex_frame = &frames->at(cur_frame); dex_frame->num = cur_frame++; dex_frame->pc = frame->dex_pc; dex_frame->rel_pc = frame->dex_pc; dex_frame->sp = frame->sp; dex_frame->stack_size = 0; dex_frame->func_offset = 0; FillInDexFrame(stack_map, frame->dex_pc, dex_frame); } backtrace_frame_data_t* back_frame = &frames->at(cur_frame); back_frame->num = cur_frame++; Loading libbacktrace/UnwindStackMap.cpp +3 −29 Original line number Diff line number Diff line Loading @@ -26,20 +26,11 @@ #include <unwindstack/MapInfo.h> #include <unwindstack/Maps.h> #include "UnwindDexFile.h" #include "UnwindStackMap.h" //------------------------------------------------------------------------- UnwindStackMap::UnwindStackMap(pid_t pid) : BacktraceMap(pid) {} UnwindStackMap::~UnwindStackMap() { #ifndef NO_LIBDEXFILE for (auto& entry : dex_files_) { delete entry.second; } #endif } bool UnwindStackMap::Build() { if (pid_ == 0) { pid_ = getpid(); Loading @@ -54,6 +45,9 @@ bool UnwindStackMap::Build() { // Create a JitDebug object for getting jit unwind information. std::vector<std::string> search_libs_{"libart.so", "libartd.so"}; jit_debug_.reset(new unwindstack::JitDebug(process_memory_, search_libs_)); #if !defined(NO_LIBDEXFILE_SUPPORT) dex_files_.reset(new unwindstack::DexFiles(process_memory_)); #endif if (!stack_maps_->Parse()) { return false; Loading Loading @@ -127,26 +121,6 @@ std::shared_ptr<unwindstack::Memory> UnwindStackMap::GetProcessMemory() { return process_memory_; } #ifdef NO_LIBDEXFILE UnwindDexFile* UnwindStackMap::GetDexFile(uint64_t, unwindstack::MapInfo*) { return nullptr; } #else UnwindDexFile* UnwindStackMap::GetDexFile(uint64_t dex_file_offset, unwindstack::MapInfo* info) { // Lock while we get the data. std::lock_guard<std::mutex> guard(dex_lock_); UnwindDexFile* dex_file; auto entry = dex_files_.find(dex_file_offset); if (entry == dex_files_.end()) { dex_file = UnwindDexFile::Create(dex_file_offset, process_memory_.get(), info); dex_files_[dex_file_offset] = dex_file; } else { dex_file = entry->second; } return dex_file; } #endif UnwindStackOfflineMap::UnwindStackOfflineMap(pid_t pid) : UnwindStackMap(pid) {} bool UnwindStackOfflineMap::Build() { Loading libbacktrace/UnwindStackMap.h +9 −5 Original line number Diff line number Diff line Loading @@ -27,6 +27,9 @@ #include <backtrace/Backtrace.h> #include <backtrace/BacktraceMap.h> #if !defined(NO_LIBDEXFILE_SUPPORT) #include <unwindstack/DexFiles.h> #endif #include <unwindstack/JitDebug.h> #include <unwindstack/Maps.h> Loading @@ -36,7 +39,7 @@ class UnwindDexFile; class UnwindStackMap : public BacktraceMap { public: explicit UnwindStackMap(pid_t pid); ~UnwindStackMap(); ~UnwindStackMap() = default; bool Build() override; Loading @@ -51,7 +54,9 @@ class UnwindStackMap : public BacktraceMap { unwindstack::JitDebug* GetJitDebug() { return jit_debug_.get(); } UnwindDexFile* GetDexFile(uint64_t dex_file_offset, unwindstack::MapInfo* info); #if !defined(NO_LIBDEXFILE_SUPPORT) unwindstack::DexFiles* GetDexFiles() { return dex_files_.get(); } #endif protected: uint64_t GetLoadBias(size_t index) override; Loading @@ -59,9 +64,8 @@ class UnwindStackMap : public BacktraceMap { std::unique_ptr<unwindstack::Maps> stack_maps_; std::shared_ptr<unwindstack::Memory> process_memory_; std::unique_ptr<unwindstack::JitDebug> jit_debug_; #ifndef NO_LIBDEXFILE std::mutex dex_lock_; std::unordered_map<uint64_t, UnwindDexFile*> dex_files_; #if !defined(NO_LIBDEXFILE_SUPPORT) std::unique_ptr<unwindstack::DexFiles> dex_files_; #endif }; Loading libunwindstack/Android.bp +64 −0 Original line number Diff line number Diff line Loading @@ -80,7 +80,13 @@ cc_library { host: { cflags: ["-O0", "-g"], }, vendor: { cflags: ["-DNO_LIBDEXFILE_SUPPORT"], exclude_static_libs: ["libunwindstack_dex"], exclude_shared_libs: ["libdexfile"], }, }, whole_static_libs: ["libunwindstack_dex"], arch: { x86: { Loading @@ -99,14 +105,70 @@ cc_library { shared_libs: [ "libbase", "libdexfile", "liblog", "liblzma", ], } // Isolate the dex file processing into a separate library. Currently, // it is necessary to add art include directories directly, which also // adds the art elf.h file in the include path, overriding the system one. // Work to isolate libdexfile is b/72216369. cc_library_static { name: "libunwindstack_dex", vendor_available: false, defaults: ["libunwindstack_flags"], cflags: [ "-Wexit-time-destructors", ], srcs: [ "DexFile.cpp", "DexFiles.cpp", ], shared_libs: [ "libbase", "libdexfile", ], local_include_dirs: ["include"], allow_undefined_symbols: true, // libdexfile will eventually properly export headers, for now include // these directly. include_dirs: [ "art/runtime", ], } //------------------------------------------------------------------------- // Unit Tests //------------------------------------------------------------------------- cc_test_library { name: "libunwindstack_dex_test", vendor_available: false, defaults: ["libunwindstack_flags"], srcs: [ "tests/DexFileTest.cpp", ], local_include_dirs: ["include"], allow_undefined_symbols: true, shared_libs: [ "libbase", "libunwindstack", ], // libdexfile will eventually properly export headers, for now include // these directly. include_dirs: [ "art/runtime", ], } cc_test { name: "libunwindstack_test", defaults: ["libunwindstack_flags"], Loading Loading @@ -168,6 +230,8 @@ cc_test { "libgmock", ], whole_static_libs: ["libunwindstack_dex_test"], data: [ "tests/files/elf32.xz", "tests/files/elf64.xz", Loading Loading
libbacktrace/Android.bp +2 −6 Original line number Diff line number Diff line Loading @@ -50,7 +50,6 @@ libbacktrace_sources = [ "BacktracePtrace.cpp", "thread_utils.c", "ThreadEntry.cpp", "UnwindDexFile.cpp", "UnwindStack.cpp", "UnwindStackMap.cpp", ] Loading Loading @@ -110,10 +109,9 @@ cc_library { static_libs: ["libasync_safe"], }, vendor: { cflags: ["-DNO_LIBDEXFILE"], exclude_srcs: ["UnwindDexFile.cpp"], cflags: ["-DNO_LIBDEXFILE_SUPPORT"], exclude_shared_libs: ["libdexfile"], }, } }, whole_static_libs: ["libdemangle"], } Loading Loading @@ -145,8 +143,6 @@ cc_test { "backtrace_test.cpp", "GetPss.cpp", "thread_utils.c", "unwind_dex_test.cpp", ], cflags: [ Loading
libbacktrace/UnwindStack.cpp +9 −84 Original line number Diff line number Diff line Loading @@ -36,70 +36,15 @@ #include <unwindstack/Regs.h> #include <unwindstack/RegsGetLocal.h> #if !defined(NO_LIBDEXFILE_SUPPORT) #include <unwindstack/DexFiles.h> #endif #include <unwindstack/Unwinder.h> #include "BacktraceLog.h" #ifndef NO_LIBDEXFILE #include "UnwindDexFile.h" #endif #include "UnwindStack.h" #include "UnwindStackMap.h" static void FillInDexFrame(UnwindStackMap* stack_map, uint64_t dex_pc, backtrace_frame_data_t* frame) { // The DEX PC points into the .dex section within an ELF file. // However, this is a BBS section manually mmaped to a .vdex file, // so we need to get the following map to find the ELF data. unwindstack::Maps* maps = stack_map->stack_maps(); auto it = maps->begin(); uint64_t rel_dex_pc; unwindstack::MapInfo* info; for (; it != maps->end(); ++it) { auto entry = *it; if (dex_pc >= entry->start && dex_pc < entry->end) { info = entry; rel_dex_pc = dex_pc - entry->start; frame->map.start = entry->start; frame->map.end = entry->end; frame->map.offset = entry->offset; frame->map.load_bias = entry->load_bias; frame->map.flags = entry->flags; frame->map.name = entry->name; frame->rel_pc = rel_dex_pc; break; } } if (it == maps->end() || ++it == maps->end()) { return; } auto entry = *it; auto process_memory = stack_map->process_memory(); unwindstack::Elf* elf = entry->GetElf(process_memory, true); if (!elf->valid()) { return; } // Adjust the relative dex by the offset. rel_dex_pc += entry->elf_offset; uint64_t dex_offset; if (!elf->GetFunctionName(rel_dex_pc, &frame->func_name, &dex_offset)) { return; } frame->func_offset = dex_offset; if (frame->func_name != "$dexfile") { return; } #ifndef NO_LIBDEXFILE UnwindDexFile* dex_file = stack_map->GetDexFile(dex_pc - dex_offset, info); if (dex_file != nullptr) { dex_file->GetMethodInformation(dex_offset, &frame->func_name, &frame->func_offset); } #endif } bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map, std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames, std::vector<std::string>* skip_names, BacktraceUnwindError* error) { Loading @@ -110,6 +55,11 @@ bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map, if (stack_map->GetJitDebug() != nullptr) { unwinder.SetJitDebug(stack_map->GetJitDebug(), regs->Arch()); } #if !defined(NO_LIBDEXFILE_SUPPORT) if (stack_map->GetDexFiles() != nullptr) { unwinder.SetDexFiles(stack_map->GetDexFiles(), regs->Arch()); } #endif unwinder.Unwind(skip_names, &stack_map->GetSuffixesToIgnore()); if (error != nullptr) { switch (unwinder.LastErrorCode()) { Loading Loading @@ -150,36 +100,11 @@ bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map, } auto unwinder_frames = unwinder.frames(); // Get the real number of frames we'll need. size_t total_frames = 0; for (size_t i = num_ignore_frames; i < unwinder.NumFrames(); i++, total_frames++) { if (unwinder_frames[i].dex_pc != 0) { total_frames++; } } frames->resize(total_frames); frames->resize(unwinder.NumFrames() - num_ignore_frames); size_t cur_frame = 0; for (size_t i = num_ignore_frames; i < unwinder.NumFrames(); i++) { auto frame = &unwinder_frames[i]; // Inject extra 'virtual' frame that represents the dex pc data. // The dex pc is magic register defined in the Mterp interpreter, // and thus it will be restored/observed in the frame after it. // Adding the dex frame first here will create something like: // #7 pc 006b1ba1 libartd.so ExecuteMterpImpl+14625 // #8 pc 0015fa20 core.vdex java.util.Arrays.binarySearch+8 // #9 pc 0039a1ef libartd.so art::interpreter::Execute+719 if (frame->dex_pc != 0) { backtrace_frame_data_t* dex_frame = &frames->at(cur_frame); dex_frame->num = cur_frame++; dex_frame->pc = frame->dex_pc; dex_frame->rel_pc = frame->dex_pc; dex_frame->sp = frame->sp; dex_frame->stack_size = 0; dex_frame->func_offset = 0; FillInDexFrame(stack_map, frame->dex_pc, dex_frame); } backtrace_frame_data_t* back_frame = &frames->at(cur_frame); back_frame->num = cur_frame++; Loading
libbacktrace/UnwindStackMap.cpp +3 −29 Original line number Diff line number Diff line Loading @@ -26,20 +26,11 @@ #include <unwindstack/MapInfo.h> #include <unwindstack/Maps.h> #include "UnwindDexFile.h" #include "UnwindStackMap.h" //------------------------------------------------------------------------- UnwindStackMap::UnwindStackMap(pid_t pid) : BacktraceMap(pid) {} UnwindStackMap::~UnwindStackMap() { #ifndef NO_LIBDEXFILE for (auto& entry : dex_files_) { delete entry.second; } #endif } bool UnwindStackMap::Build() { if (pid_ == 0) { pid_ = getpid(); Loading @@ -54,6 +45,9 @@ bool UnwindStackMap::Build() { // Create a JitDebug object for getting jit unwind information. std::vector<std::string> search_libs_{"libart.so", "libartd.so"}; jit_debug_.reset(new unwindstack::JitDebug(process_memory_, search_libs_)); #if !defined(NO_LIBDEXFILE_SUPPORT) dex_files_.reset(new unwindstack::DexFiles(process_memory_)); #endif if (!stack_maps_->Parse()) { return false; Loading Loading @@ -127,26 +121,6 @@ std::shared_ptr<unwindstack::Memory> UnwindStackMap::GetProcessMemory() { return process_memory_; } #ifdef NO_LIBDEXFILE UnwindDexFile* UnwindStackMap::GetDexFile(uint64_t, unwindstack::MapInfo*) { return nullptr; } #else UnwindDexFile* UnwindStackMap::GetDexFile(uint64_t dex_file_offset, unwindstack::MapInfo* info) { // Lock while we get the data. std::lock_guard<std::mutex> guard(dex_lock_); UnwindDexFile* dex_file; auto entry = dex_files_.find(dex_file_offset); if (entry == dex_files_.end()) { dex_file = UnwindDexFile::Create(dex_file_offset, process_memory_.get(), info); dex_files_[dex_file_offset] = dex_file; } else { dex_file = entry->second; } return dex_file; } #endif UnwindStackOfflineMap::UnwindStackOfflineMap(pid_t pid) : UnwindStackMap(pid) {} bool UnwindStackOfflineMap::Build() { Loading
libbacktrace/UnwindStackMap.h +9 −5 Original line number Diff line number Diff line Loading @@ -27,6 +27,9 @@ #include <backtrace/Backtrace.h> #include <backtrace/BacktraceMap.h> #if !defined(NO_LIBDEXFILE_SUPPORT) #include <unwindstack/DexFiles.h> #endif #include <unwindstack/JitDebug.h> #include <unwindstack/Maps.h> Loading @@ -36,7 +39,7 @@ class UnwindDexFile; class UnwindStackMap : public BacktraceMap { public: explicit UnwindStackMap(pid_t pid); ~UnwindStackMap(); ~UnwindStackMap() = default; bool Build() override; Loading @@ -51,7 +54,9 @@ class UnwindStackMap : public BacktraceMap { unwindstack::JitDebug* GetJitDebug() { return jit_debug_.get(); } UnwindDexFile* GetDexFile(uint64_t dex_file_offset, unwindstack::MapInfo* info); #if !defined(NO_LIBDEXFILE_SUPPORT) unwindstack::DexFiles* GetDexFiles() { return dex_files_.get(); } #endif protected: uint64_t GetLoadBias(size_t index) override; Loading @@ -59,9 +64,8 @@ class UnwindStackMap : public BacktraceMap { std::unique_ptr<unwindstack::Maps> stack_maps_; std::shared_ptr<unwindstack::Memory> process_memory_; std::unique_ptr<unwindstack::JitDebug> jit_debug_; #ifndef NO_LIBDEXFILE std::mutex dex_lock_; std::unordered_map<uint64_t, UnwindDexFile*> dex_files_; #if !defined(NO_LIBDEXFILE_SUPPORT) std::unique_ptr<unwindstack::DexFiles> dex_files_; #endif }; Loading
libunwindstack/Android.bp +64 −0 Original line number Diff line number Diff line Loading @@ -80,7 +80,13 @@ cc_library { host: { cflags: ["-O0", "-g"], }, vendor: { cflags: ["-DNO_LIBDEXFILE_SUPPORT"], exclude_static_libs: ["libunwindstack_dex"], exclude_shared_libs: ["libdexfile"], }, }, whole_static_libs: ["libunwindstack_dex"], arch: { x86: { Loading @@ -99,14 +105,70 @@ cc_library { shared_libs: [ "libbase", "libdexfile", "liblog", "liblzma", ], } // Isolate the dex file processing into a separate library. Currently, // it is necessary to add art include directories directly, which also // adds the art elf.h file in the include path, overriding the system one. // Work to isolate libdexfile is b/72216369. cc_library_static { name: "libunwindstack_dex", vendor_available: false, defaults: ["libunwindstack_flags"], cflags: [ "-Wexit-time-destructors", ], srcs: [ "DexFile.cpp", "DexFiles.cpp", ], shared_libs: [ "libbase", "libdexfile", ], local_include_dirs: ["include"], allow_undefined_symbols: true, // libdexfile will eventually properly export headers, for now include // these directly. include_dirs: [ "art/runtime", ], } //------------------------------------------------------------------------- // Unit Tests //------------------------------------------------------------------------- cc_test_library { name: "libunwindstack_dex_test", vendor_available: false, defaults: ["libunwindstack_flags"], srcs: [ "tests/DexFileTest.cpp", ], local_include_dirs: ["include"], allow_undefined_symbols: true, shared_libs: [ "libbase", "libunwindstack", ], // libdexfile will eventually properly export headers, for now include // these directly. include_dirs: [ "art/runtime", ], } cc_test { name: "libunwindstack_test", defaults: ["libunwindstack_flags"], Loading Loading @@ -168,6 +230,8 @@ cc_test { "libgmock", ], whole_static_libs: ["libunwindstack_dex_test"], data: [ "tests/files/elf32.xz", "tests/files/elf64.xz", Loading