diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp index e171155b9..9ece8479c 100644 --- a/libbacktrace/Android.bp +++ b/libbacktrace/Android.bp @@ -135,7 +135,6 @@ cc_test { defaults: ["libbacktrace_common"], host_supported: true, srcs: [ - "backtrace_offline_test.cpp", "backtrace_test.cpp", ], diff --git a/libbacktrace/UnwindStack.cpp b/libbacktrace/UnwindStack.cpp index 36640cdfa..a12862398 100644 --- a/libbacktrace/UnwindStack.cpp +++ b/libbacktrace/UnwindStack.cpp @@ -129,22 +129,6 @@ bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map, return true; } -bool Backtrace::UnwindOffline(unwindstack::Regs* regs, BacktraceMap* back_map, - const backtrace_stackinfo_t& stack, - std::vector* frames, - BacktraceUnwindError* error) { - UnwindStackOfflineMap* offline_map = reinterpret_cast(back_map); - // Create the process memory from the stack data since this will almost - // always be different each unwind. - if (!offline_map->CreateProcessMemory(stack)) { - if (error != nullptr) { - error->error_code = BACKTRACE_UNWIND_ERROR_SETUP_FAILED; - } - return false; - } - return Backtrace::Unwind(regs, back_map, frames, 0U, nullptr, error); -} - UnwindStackCurrent::UnwindStackCurrent(pid_t pid, pid_t tid, BacktraceMap* map) : BacktraceCurrent(pid, tid, map) {} @@ -171,7 +155,7 @@ bool UnwindStackCurrent::UnwindFromContext(size_t num_ignore_frames, void* ucont } UnwindStackPtrace::UnwindStackPtrace(pid_t pid, pid_t tid, BacktraceMap* map) - : BacktracePtrace(pid, tid, map), memory_(pid) {} + : BacktracePtrace(pid, tid, map), memory_(unwindstack::Memory::CreateProcessMemory(pid)) {} std::string UnwindStackPtrace::GetFunctionNameRaw(uint64_t pc, uint64_t* offset) { return GetMap()->GetFunctionName(pc, offset); @@ -189,73 +173,5 @@ bool UnwindStackPtrace::Unwind(size_t num_ignore_frames, void* context) { } size_t UnwindStackPtrace::Read(uint64_t addr, uint8_t* buffer, size_t bytes) { - return memory_.Read(addr, buffer, bytes); -} - -UnwindStackOffline::UnwindStackOffline(ArchEnum arch, pid_t pid, pid_t tid, BacktraceMap* map, - bool map_shared) - : Backtrace(pid, tid, map), arch_(arch) { - map_shared_ = map_shared; -} - -bool UnwindStackOffline::Unwind(size_t num_ignore_frames, void* ucontext) { - if (ucontext == nullptr) { - return false; - } - - unwindstack::ArchEnum arch; - switch (arch_) { - case ARCH_ARM: - arch = unwindstack::ARCH_ARM; - break; - case ARCH_ARM64: - arch = unwindstack::ARCH_ARM64; - break; - case ARCH_X86: - arch = unwindstack::ARCH_X86; - break; - case ARCH_X86_64: - arch = unwindstack::ARCH_X86_64; - break; - default: - return false; - } - - std::unique_ptr regs(unwindstack::Regs::CreateFromUcontext(arch, ucontext)); - - return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames, nullptr, &error_); -} - -std::string UnwindStackOffline::GetFunctionNameRaw(uint64_t, uint64_t*) { - return ""; -} - -size_t UnwindStackOffline::Read(uint64_t, uint8_t*, size_t) { - return 0; -} - -bool UnwindStackOffline::ReadWord(uint64_t, word_t*) { - return false; -} - -Backtrace* Backtrace::CreateOffline(ArchEnum arch, pid_t pid, pid_t tid, - const std::vector& maps, - const backtrace_stackinfo_t& stack) { - std::unique_ptr map( - reinterpret_cast(BacktraceMap::CreateOffline(pid, maps))); - if (map.get() == nullptr || !map->CreateProcessMemory(stack)) { - return nullptr; - } - return new UnwindStackOffline(arch, pid, tid, map.release(), false); -} - -Backtrace* Backtrace::CreateOffline(ArchEnum arch, pid_t pid, pid_t tid, BacktraceMap* map) { - if (map == nullptr) { - return nullptr; - } - return new UnwindStackOffline(arch, pid, tid, map, true); -} - -void Backtrace::SetGlobalElfCache(bool enable) { - unwindstack::Elf::SetCachingEnabled(enable); + return memory_->Read(addr, buffer, bytes); } diff --git a/libbacktrace/UnwindStack.h b/libbacktrace/UnwindStack.h index 4ec591d2f..47f6757d8 100644 --- a/libbacktrace/UnwindStack.h +++ b/libbacktrace/UnwindStack.h @@ -19,6 +19,7 @@ #include +#include #include #include @@ -49,23 +50,7 @@ class UnwindStackPtrace : public BacktracePtrace { size_t Read(uint64_t addr, uint8_t* buffer, size_t bytes) override; private: - unwindstack::MemoryRemote memory_; -}; - -class UnwindStackOffline : public Backtrace { - public: - UnwindStackOffline(ArchEnum arch, pid_t pid, pid_t tid, BacktraceMap* map, bool map_shared); - - bool Unwind(size_t num_ignore_frames, void* context) override; - - std::string GetFunctionNameRaw(uint64_t pc, uint64_t* offset) override; - - size_t Read(uint64_t addr, uint8_t* buffer, size_t bytes) override; - - bool ReadWord(uint64_t ptr, word_t* out_value) override; - - private: - ArchEnum arch_; + std::shared_ptr memory_; }; #endif // _LIBBACKTRACE_UNWIND_STACK_H diff --git a/libbacktrace/UnwindStackMap.cpp b/libbacktrace/UnwindStackMap.cpp index 4518891c3..aa0b17c99 100644 --- a/libbacktrace/UnwindStackMap.cpp +++ b/libbacktrace/UnwindStackMap.cpp @@ -132,43 +132,6 @@ std::shared_ptr UnwindStackMap::GetProcessMemory() { return process_memory_; } -UnwindStackOfflineMap::UnwindStackOfflineMap(pid_t pid) : UnwindStackMap(pid) {} - -bool UnwindStackOfflineMap::Build() { - return false; -} - -bool UnwindStackOfflineMap::Build(const std::vector& backtrace_maps) { - for (const backtrace_map_t& map : backtrace_maps) { - maps_.push_back(map); - } - - std::sort(maps_.begin(), maps_.end(), - [](const backtrace_map_t& a, const backtrace_map_t& b) { return a.start < b.start; }); - - unwindstack::Maps* maps = new unwindstack::Maps; - stack_maps_.reset(maps); - for (const backtrace_map_t& map : maps_) { - maps->Add(map.start, map.end, map.offset, map.flags, map.name, map.load_bias); - } - return true; -} - -bool UnwindStackOfflineMap::CreateProcessMemory(const backtrace_stackinfo_t& stack) { - if (stack.start >= stack.end) { - return false; - } - - // Create the process memory from the stack data. - if (memory_ == nullptr) { - memory_ = new unwindstack::MemoryOfflineBuffer(stack.data, stack.start, stack.end); - process_memory_.reset(memory_); - } else { - memory_->Reset(stack.data, stack.start, stack.end); - } - return true; -} - //------------------------------------------------------------------------- // BacktraceMap create function. //------------------------------------------------------------------------- @@ -189,15 +152,3 @@ BacktraceMap* BacktraceMap::Create(pid_t pid, bool uncached) { } return map; } - -//------------------------------------------------------------------------- -// BacktraceMap create offline function. -//------------------------------------------------------------------------- -BacktraceMap* BacktraceMap::CreateOffline(pid_t pid, const std::vector& maps) { - UnwindStackOfflineMap* map = new UnwindStackOfflineMap(pid); - if (!map->Build(maps)) { - delete map; - return nullptr; - } - return map; -} diff --git a/libbacktrace/UnwindStackMap.h b/libbacktrace/UnwindStackMap.h index e19b60565..f0e7d8b78 100644 --- a/libbacktrace/UnwindStackMap.h +++ b/libbacktrace/UnwindStackMap.h @@ -33,6 +33,7 @@ #include #include #include +#include // Forward declarations. class UnwindDexFile; @@ -74,19 +75,4 @@ class UnwindStackMap : public BacktraceMap { unwindstack::ArchEnum arch_ = unwindstack::ARCH_UNKNOWN; }; -class UnwindStackOfflineMap : public UnwindStackMap { - public: - UnwindStackOfflineMap(pid_t pid); - ~UnwindStackOfflineMap() = default; - - bool Build() override; - - bool Build(const std::vector& maps); - - bool CreateProcessMemory(const backtrace_stackinfo_t& stack); - - private: - unwindstack::MemoryOfflineBuffer* memory_ = nullptr; -}; - #endif // _LIBBACKTRACE_UNWINDSTACK_MAP_H diff --git a/libbacktrace/backtrace_offline_test.cpp b/libbacktrace/backtrace_offline_test.cpp deleted file mode 100644 index 662fb9977..000000000 --- a/libbacktrace/backtrace_offline_test.cpp +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "BacktraceTest.h" - -struct FunctionSymbol { - std::string name; - uint64_t start; - uint64_t end; -}; - -static std::vector GetFunctionSymbols() { - std::vector symbols = { - {"unknown_start", 0, 0}, - {"test_level_one", reinterpret_cast(&BacktraceTest::test_level_one_), 0}, - {"test_level_two", reinterpret_cast(&BacktraceTest::test_level_two_), 0}, - {"test_level_three", reinterpret_cast(&BacktraceTest::test_level_three_), 0}, - {"test_level_four", reinterpret_cast(&BacktraceTest::test_level_four_), 0}, - {"test_recursive_call", reinterpret_cast(&BacktraceTest::test_recursive_call_), 0}, - {"test_get_context_and_wait", - reinterpret_cast(&BacktraceTest::test_get_context_and_wait_), 0}, - {"unknown_end", static_cast(-1), static_cast(-1)}, - }; - std::sort( - symbols.begin(), symbols.end(), - [](const FunctionSymbol& s1, const FunctionSymbol& s2) { return s1.start < s2.start; }); - for (size_t i = 0; i + 1 < symbols.size(); ++i) { - symbols[i].end = symbols[i + 1].start; - } - return symbols; -} - -static std::string RawDataToHexString(const void* data, size_t size) { - const uint8_t* p = static_cast(data); - std::string s; - for (size_t i = 0; i < size; ++i) { - s += android::base::StringPrintf("%02x", p[i]); - } - return s; -} - -static void HexStringToRawData(const char* s, std::vector* data, size_t size) { - for (size_t i = 0; i < size; ++i) { - int value; - sscanf(s, "%02x", &value); - data->push_back(value); - s += 2; - } -} - -struct OfflineThreadArg { - std::vector ucontext; - pid_t tid; - volatile int exit_flag; -}; - -static void* OfflineThreadFunc(void* arg) { - OfflineThreadArg* fn_arg = reinterpret_cast(arg); - fn_arg->tid = android::base::GetThreadId(); - BacktraceTest::test_get_context_and_wait_(&fn_arg->ucontext, &fn_arg->exit_flag); - return nullptr; -} - -std::string GetTestPath(const std::string& arch, const std::string& path) { - return android::base::GetExecutableDirectory() + "/testdata/" + arch + '/' + path; -} - -// This test is disable because it is for generating test data. -TEST_F(BacktraceTest, DISABLED_generate_offline_testdata) { - // Create a thread to generate the needed stack and registers information. - const size_t stack_size = 16 * 1024; - void* stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - ASSERT_NE(MAP_FAILED, stack); - uint64_t stack_addr = reinterpret_cast(stack); - pthread_attr_t attr; - ASSERT_EQ(0, pthread_attr_init(&attr)); - ASSERT_EQ(0, pthread_attr_setstack(&attr, reinterpret_cast(stack), stack_size)); - pthread_t thread; - OfflineThreadArg arg; - arg.exit_flag = 0; - ASSERT_EQ(0, pthread_create(&thread, &attr, OfflineThreadFunc, &arg)); - // Wait for the offline thread to generate the stack and context information. - sleep(1); - // Copy the stack information. - std::vector stack_data(reinterpret_cast(stack), - reinterpret_cast(stack) + stack_size); - arg.exit_flag = 1; - ASSERT_EQ(0, pthread_join(thread, nullptr)); - ASSERT_EQ(0, munmap(stack, stack_size)); - - std::unique_ptr map(BacktraceMap::Create(getpid())); - ASSERT_TRUE(map != nullptr); - - backtrace_stackinfo_t stack_info; - stack_info.start = stack_addr; - stack_info.end = stack_addr + stack_size; - stack_info.data = stack_data.data(); - - // Generate offline testdata. - std::string testdata; - // 1. Dump pid, tid - testdata += android::base::StringPrintf("pid: %d tid: %d\n", getpid(), arg.tid); - // 2. Dump maps - for (auto it = map->begin(); it != map->end(); ++it) { - const backtrace_map_t* entry = *it; - testdata += - android::base::StringPrintf("map: start: %" PRIx64 " end: %" PRIx64 " offset: %" PRIx64 - " load_bias: %" PRIx64 " flags: %d name: %s\n", - entry->start, entry->end, entry->offset, entry->load_bias, - entry->flags, entry->name.c_str()); - } - // 3. Dump ucontext - testdata += android::base::StringPrintf("ucontext: %zu ", arg.ucontext.size()); - testdata += RawDataToHexString(arg.ucontext.data(), arg.ucontext.size()); - testdata.push_back('\n'); - - // 4. Dump stack - testdata += android::base::StringPrintf( - "stack: start: %" PRIx64 " end: %" PRIx64 " size: %zu ", - stack_info.start, stack_info.end, stack_data.size()); - testdata += RawDataToHexString(stack_data.data(), stack_data.size()); - testdata.push_back('\n'); - - // 5. Dump function symbols - std::vector function_symbols = GetFunctionSymbols(); - for (const auto& symbol : function_symbols) { - testdata += - android::base::StringPrintf("function: start: %" PRIx64 " end: %" PRIx64 " name: %s\n", - symbol.start, symbol.end, symbol.name.c_str()); - } - - ASSERT_TRUE(android::base::WriteStringToFile(testdata, "offline_testdata")); -} - -// Return the name of the function which matches the address. Although we don't know the -// exact end of each function, it is accurate enough for the tests. -static std::string FunctionNameForAddress(uint64_t addr, - const std::vector& symbols) { - for (auto& symbol : symbols) { - if (addr >= symbol.start && addr < symbol.end) { - return symbol.name; - } - } - return ""; -} - -struct OfflineTestData { - int pid; - int tid; - std::vector maps; - std::vector ucontext; - backtrace_stackinfo_t stack_info; - std::vector stack; - std::vector symbols; -}; - -bool ReadOfflineTestData(const std::string offline_testdata_path, OfflineTestData* testdata) { - std::string s; - if (!android::base::ReadFileToString(offline_testdata_path, &s)) { - return false; - } - // Parse offline_testdata. - std::vector lines = android::base::Split(s, "\n"); - for (const auto& line : lines) { - if (android::base::StartsWith(line, "pid:")) { - sscanf(line.c_str(), "pid: %d tid: %d", &testdata->pid, &testdata->tid); - } else if (android::base::StartsWith(line, "map:")) { - testdata->maps.resize(testdata->maps.size() + 1); - backtrace_map_t& map = testdata->maps.back(); - int pos; - sscanf(line.c_str(), - "map: start: %" SCNx64 " end: %" SCNx64 " offset: %" SCNx64 " load_bias: %" SCNx64 - " flags: %d name: %n", - &map.start, &map.end, &map.offset, &map.load_bias, &map.flags, &pos); - map.name = android::base::Trim(line.substr(pos)); - } else if (android::base::StartsWith(line, "ucontext:")) { - size_t size; - int pos; - testdata->ucontext.clear(); - sscanf(line.c_str(), "ucontext: %zu %n", &size, &pos); - HexStringToRawData(&line[pos], &testdata->ucontext, size); - } else if (android::base::StartsWith(line, "stack:")) { - size_t size; - int pos; - sscanf(line.c_str(), - "stack: start: %" SCNx64 " end: %" SCNx64 " size: %zu %n", - &testdata->stack_info.start, &testdata->stack_info.end, &size, &pos); - CHECK_EQ(testdata->stack_info.end - testdata->stack_info.start, size); - testdata->stack.clear(); - HexStringToRawData(&line[pos], &testdata->stack, size); - testdata->stack_info.data = testdata->stack.data(); - } else if (android::base::StartsWith(line, "function:")) { - testdata->symbols.resize(testdata->symbols.size() + 1); - FunctionSymbol& symbol = testdata->symbols.back(); - int pos; - sscanf(line.c_str(), "function: start: %" SCNx64 " end: %" SCNx64 " name: %n", &symbol.start, - &symbol.end, &pos); - symbol.name = line.substr(pos); - } - } - return true; -} - -static void BacktraceOfflineTest(std::string arch_str, const std::string& testlib_name) { - const std::string testlib_path(GetTestPath(arch_str, testlib_name)); - const std::string offline_testdata_path(GetTestPath(arch_str, "offline_testdata")); - OfflineTestData testdata; - ASSERT_TRUE(ReadOfflineTestData(offline_testdata_path, &testdata)) << "Failed " << arch_str; - - // Fix path of libbacktrace_testlib.so. - for (auto& map : testdata.maps) { - if (map.name.find("libbacktrace_test.so") != std::string::npos) { - map.name = testlib_path; - } - } - - Backtrace::ArchEnum arch; - if (arch_str == "arm") { - arch = Backtrace::ARCH_ARM; - } else if (arch_str == "arm64") { - arch = Backtrace::ARCH_ARM64; - } else if (arch_str == "x86") { - arch = Backtrace::ARCH_X86; - } else if (arch_str == "x86_64") { - arch = Backtrace::ARCH_X86_64; - } else { - abort(); - } - - std::unique_ptr backtrace(Backtrace::CreateOffline( - arch, testdata.pid, testdata.tid, testdata.maps, testdata.stack_info)); - ASSERT_TRUE(backtrace != nullptr) << "Failed " << arch_str; - - ASSERT_TRUE(backtrace->Unwind(0, testdata.ucontext.data())) << "Failed " << arch_str; - - // Collect pc values of the call stack frames. - std::vector pc_values; - for (size_t i = 0; i < backtrace->NumFrames(); ++i) { - pc_values.push_back(backtrace->GetFrame(i)->pc); - } - - size_t test_one_index = 0; - for (size_t i = 0; i < pc_values.size(); ++i) { - if (FunctionNameForAddress(pc_values[i], testdata.symbols) == "test_level_one") { - test_one_index = i; - break; - } - } - - ASSERT_GE(test_one_index, 3u) << "Failed " << arch_str; - ASSERT_EQ("test_level_one", FunctionNameForAddress(pc_values[test_one_index], testdata.symbols)) - << "Failed " << arch_str; - ASSERT_EQ("test_level_two", FunctionNameForAddress(pc_values[test_one_index - 1], testdata.symbols)) - << "Failed " << arch_str; - ASSERT_EQ("test_level_three", - FunctionNameForAddress(pc_values[test_one_index - 2], testdata.symbols)) - << "Failed " << arch_str; - ASSERT_EQ("test_level_four", - FunctionNameForAddress(pc_values[test_one_index - 3], testdata.symbols)) - << "Failed " << arch_str; -} - -// For now, these tests can only run on the given architectures. -TEST_F(BacktraceTest, offline_eh_frame) { - BacktraceOfflineTest("arm64", "libbacktrace_test_eh_frame.so"); - BacktraceOfflineTest("x86_64", "libbacktrace_test_eh_frame.so"); -} - -TEST_F(BacktraceTest, offline_debug_frame) { - BacktraceOfflineTest("arm", "libbacktrace_test_debug_frame.so"); - BacktraceOfflineTest("x86", "libbacktrace_test_debug_frame.so"); -} - -TEST_F(BacktraceTest, offline_gnu_debugdata) { - BacktraceOfflineTest("arm", "libbacktrace_test_gnu_debugdata.so"); - BacktraceOfflineTest("x86", "libbacktrace_test_gnu_debugdata.so"); -} - -TEST_F(BacktraceTest, offline_arm_exidx) { - BacktraceOfflineTest("arm", "libbacktrace_test_arm_exidx.so"); -} - -static void LibUnwindingTest(const std::string& arch_str, const std::string& testdata_name, - const std::string& testlib_name) { - const std::string testlib_path(GetTestPath(arch_str, testlib_name)); - struct stat st; - ASSERT_EQ(0, stat(testlib_path.c_str(), &st)) << "can't find testlib " << testlib_path; - - const std::string offline_testdata_path(GetTestPath(arch_str, testdata_name)); - OfflineTestData testdata; - ASSERT_TRUE(ReadOfflineTestData(offline_testdata_path, &testdata)); - - // Fix path of the testlib. - for (auto& map : testdata.maps) { - if (map.name.find(testlib_name) != std::string::npos) { - map.name = testlib_path; - } - } - - Backtrace::ArchEnum arch; - if (arch_str == "arm") { - arch = Backtrace::ARCH_ARM; - } else if (arch_str == "arm64") { - arch = Backtrace::ARCH_ARM64; - } else if (arch_str == "x86") { - arch = Backtrace::ARCH_X86; - } else if (arch_str == "x86_64") { - arch = Backtrace::ARCH_X86_64; - } else { - ASSERT_TRUE(false) << "Unsupported arch " << arch_str; - abort(); - } - - // Do offline backtrace. - std::unique_ptr backtrace(Backtrace::CreateOffline( - arch, testdata.pid, testdata.tid, testdata.maps, testdata.stack_info)); - ASSERT_TRUE(backtrace != nullptr); - - ASSERT_TRUE(backtrace->Unwind(0, testdata.ucontext.data())); - - ASSERT_EQ(testdata.symbols.size(), backtrace->NumFrames()); - for (size_t i = 0; i < backtrace->NumFrames(); ++i) { - std::string name = FunctionNameForAddress(backtrace->GetFrame(i)->rel_pc, testdata.symbols); - ASSERT_EQ(name, testdata.symbols[i].name); - } - ASSERT_TRUE(backtrace->GetError().error_code == BACKTRACE_UNWIND_ERROR_ACCESS_MEM_FAILED || - backtrace->GetError().error_code == BACKTRACE_UNWIND_ERROR_MAP_MISSING || - backtrace->GetError().error_code == BACKTRACE_UNWIND_ERROR_REPEATED_FRAME); -} - -// This test tests the situation that ranges of functions covered by .eh_frame and .ARM.exidx -// overlap with each other, which appears in /system/lib/libart.so. -TEST_F(BacktraceTest, offline_unwind_mix_eh_frame_and_arm_exidx) { - LibUnwindingTest("arm", "offline_testdata_for_libart", "libart.so"); -} - -TEST_F(BacktraceTest, offline_debug_frame_with_load_bias) { - LibUnwindingTest("arm", "offline_testdata_for_libandroid_runtime", "libandroid_runtime.so"); -} - -TEST_F(BacktraceTest, offline_try_armexidx_after_debug_frame) { - LibUnwindingTest("arm", "offline_testdata_for_libGLESv2_adreno", "libGLESv2_adreno.so"); -} - -TEST_F(BacktraceTest, offline_cie_with_P_augmentation) { - // Make sure we can unwind through functions with CIE entry containing P augmentation, which - // makes unwinding library reading personality handler from memory. One example is - // /system/lib64/libskia.so. - LibUnwindingTest("arm64", "offline_testdata_for_libskia", "libskia.so"); -} - -TEST_F(BacktraceTest, offline_empty_eh_frame_hdr) { - // Make sure we can unwind through libraries with empty .eh_frame_hdr section. One example is - // /vendor/lib64/egl/eglSubDriverAndroid.so. - LibUnwindingTest("arm64", "offline_testdata_for_eglSubDriverAndroid", "eglSubDriverAndroid.so"); -} - -TEST_F(BacktraceTest, offline_max_frames_limit) { - // The length of callchain can reach 256 when recording an application. - ASSERT_GE(MAX_BACKTRACE_FRAMES, 256); -} diff --git a/libbacktrace/include/backtrace/Backtrace.h b/libbacktrace/include/backtrace/Backtrace.h index 404e7e8ab..664b531fb 100644 --- a/libbacktrace/include/backtrace/Backtrace.h +++ b/libbacktrace/include/backtrace/Backtrace.h @@ -126,24 +126,6 @@ class Backtrace { // If map is not NULL, the map is still owned by the caller. static Backtrace* Create(pid_t pid, pid_t tid, BacktraceMap* map = nullptr); - // Create an offline Backtrace object that can be used to do an unwind without a process - // that is still running. By default, information is only cached in the map - // file. If the calling code creates the map, data can be cached between - // unwinds. If not, all cached data will be destroyed when the Backtrace - // object is destroyed. - static Backtrace* CreateOffline(ArchEnum arch, pid_t pid, pid_t tid, - const std::vector& maps, - const backtrace_stackinfo_t& stack); - static Backtrace* CreateOffline(ArchEnum arch, pid_t pid, pid_t tid, BacktraceMap* map); - - // Create an offline Backtrace object that can be used to do an unwind without a process - // that is still running. If cache_file is set to true, then elf information will be cached - // for this call. The cached information survives until the calling process ends. This means - // that subsequent calls to create offline Backtrace objects will continue to use the same - // cache. It also assumes that the elf files used for each offline unwind are the same. - static Backtrace* CreateOffline(pid_t pid, pid_t tid, BacktraceMap* map, - const backtrace_stackinfo_t& stack, bool cache_file = false); - virtual ~Backtrace(); // Get the current stack trace and store in the backtrace_ structure. @@ -153,11 +135,6 @@ class Backtrace { std::vector* frames, size_t num_ignore_frames, std::vector* skip_names, BacktraceUnwindError* error = nullptr); - static bool UnwindOffline(unwindstack::Regs* regs, BacktraceMap* back_map, - const backtrace_stackinfo_t& stack_info, - std::vector* frames, - BacktraceUnwindError* error = nullptr); - // Get the function name and offset into the function given the pc. // If the string is empty, then no valid function name was found, // or the pc is not in any valid map. diff --git a/libbacktrace/include/backtrace/BacktraceMap.h b/libbacktrace/include/backtrace/BacktraceMap.h index c564271b6..f8d5058c7 100644 --- a/libbacktrace/include/backtrace/BacktraceMap.h +++ b/libbacktrace/include/backtrace/BacktraceMap.h @@ -69,8 +69,6 @@ public: // is unsupported. static BacktraceMap* Create(pid_t pid, bool uncached = false); - static BacktraceMap* CreateOffline(pid_t pid, const std::vector& maps); - virtual ~BacktraceMap(); class iterator : public std::iterator { diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp index dee8eb36a..f0e413805 100644 --- a/libunwindstack/ElfInterface.cpp +++ b/libunwindstack/ElfInterface.cpp @@ -29,12 +29,12 @@ #include #include #include -#include #include #include "DwarfDebugFrame.h" #include "DwarfEhFrame.h" #include "DwarfEhFrameWithHdr.h" +#include "MemoryBuffer.h" #include "Symbols.h" namespace unwindstack { diff --git a/libunwindstack/JitDebug.cpp b/libunwindstack/JitDebug.cpp index 20bc4b902..8a85607cb 100644 --- a/libunwindstack/JitDebug.cpp +++ b/libunwindstack/JitDebug.cpp @@ -23,7 +23,8 @@ #include #include #include -#include + +#include "MemoryRange.h" // This implements the JIT Compilation Interface. // See https://sourceware.org/gdb/onlinedocs/gdb/JIT-Interface.html diff --git a/libunwindstack/MapInfo.cpp b/libunwindstack/MapInfo.cpp index d3cec069a..1c0f1e611 100644 --- a/libunwindstack/MapInfo.cpp +++ b/libunwindstack/MapInfo.cpp @@ -27,7 +27,9 @@ #include #include #include -#include + +#include "MemoryFileAtOffset.h" +#include "MemoryRange.h" namespace unwindstack { diff --git a/libunwindstack/Memory.cpp b/libunwindstack/Memory.cpp index 9904feff1..a66cd5b54 100644 --- a/libunwindstack/Memory.cpp +++ b/libunwindstack/Memory.cpp @@ -32,6 +32,14 @@ #include #include "Check.h" +#include "MemoryBuffer.h" +#include "MemoryCache.h" +#include "MemoryFileAtOffset.h" +#include "MemoryLocal.h" +#include "MemoryOffline.h" +#include "MemoryOfflineBuffer.h" +#include "MemoryRange.h" +#include "MemoryRemote.h" namespace unwindstack { @@ -168,6 +176,16 @@ bool Memory::ReadString(uint64_t addr, std::string* string, uint64_t max_read) { return false; } +std::unique_ptr Memory::CreateFileMemory(const std::string& path, uint64_t offset) { + auto memory = std::make_unique(); + + if (memory->Init(path, offset)) { + return memory; + } + + return nullptr; +} + std::shared_ptr Memory::CreateProcessMemory(pid_t pid) { if (pid == getpid()) { return std::shared_ptr(new MemoryLocal()); @@ -182,6 +200,11 @@ std::shared_ptr Memory::CreateProcessMemoryCached(pid_t pid) { return std::shared_ptr(new MemoryCache(new MemoryRemote(pid))); } +std::shared_ptr Memory::CreateOfflineMemory(const uint8_t* data, uint64_t start, + uint64_t end) { + return std::shared_ptr(new MemoryOfflineBuffer(data, start, end)); +} + size_t MemoryBuffer::Read(uint64_t addr, void* dst, size_t size) { if (addr >= raw_.size()) { return 0; diff --git a/libunwindstack/MemoryBuffer.h b/libunwindstack/MemoryBuffer.h new file mode 100644 index 000000000..3fe4bbbda --- /dev/null +++ b/libunwindstack/MemoryBuffer.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _LIBUNWINDSTACK_MEMORY_BUFFER_H +#define _LIBUNWINDSTACK_MEMORY_BUFFER_H + +#include + +#include +#include + +#include + +namespace unwindstack { + +class MemoryBuffer : public Memory { + public: + MemoryBuffer() = default; + virtual ~MemoryBuffer() = default; + + size_t Read(uint64_t addr, void* dst, size_t size) override; + + uint8_t* GetPtr(size_t offset); + + void Resize(size_t size) { raw_.resize(size); } + + uint64_t Size() { return raw_.size(); } + + private: + std::vector raw_; +}; + +} // namespace unwindstack + +#endif // _LIBUNWINDSTACK_MEMORY_BUFFER_H diff --git a/libunwindstack/MemoryCache.h b/libunwindstack/MemoryCache.h new file mode 100644 index 000000000..769d90746 --- /dev/null +++ b/libunwindstack/MemoryCache.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _LIBUNWINDSTACK_MEMORY_CACHE_H +#define _LIBUNWINDSTACK_MEMORY_CACHE_H + +#include + +#include +#include +#include + +#include + +namespace unwindstack { + +class MemoryCache : public Memory { + public: + MemoryCache(Memory* memory) : impl_(memory) {} + virtual ~MemoryCache() = default; + + size_t Read(uint64_t addr, void* dst, size_t size) override; + + void Clear() override { cache_.clear(); } + + private: + constexpr static size_t kCacheBits = 12; + constexpr static size_t kCacheMask = (1 << kCacheBits) - 1; + constexpr static size_t kCacheSize = 1 << kCacheBits; + std::unordered_map cache_; + + std::unique_ptr impl_; +}; + +} // namespace unwindstack + +#endif // _LIBUNWINDSTACK_MEMORY_CACHE_H diff --git a/libunwindstack/MemoryFileAtOffset.h b/libunwindstack/MemoryFileAtOffset.h new file mode 100644 index 000000000..d136eb44a --- /dev/null +++ b/libunwindstack/MemoryFileAtOffset.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _LIBUNWINDSTACK_MEMORY_FILE_AT_OFFSET_H +#define _LIBUNWINDSTACK_MEMORY_FILE_AT_OFFSET_H + +#include + +#include + +namespace unwindstack { + +class MemoryFileAtOffset : public Memory { + public: + MemoryFileAtOffset() = default; + virtual ~MemoryFileAtOffset(); + + bool Init(const std::string& file, uint64_t offset, uint64_t size = UINT64_MAX); + + size_t Read(uint64_t addr, void* dst, size_t size) override; + + size_t Size() { return size_; } + + void Clear() override; + + protected: + size_t size_ = 0; + size_t offset_ = 0; + uint8_t* data_ = nullptr; +}; + +} // namespace unwindstack + +#endif // _LIBUNWINDSTACK_MEMORY_FILE_AT_OFFSET_H diff --git a/libunwindstack/MemoryLocal.h b/libunwindstack/MemoryLocal.h new file mode 100644 index 000000000..29aaf128b --- /dev/null +++ b/libunwindstack/MemoryLocal.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _LIBUNWINDSTACK_MEMORY_LOCAL_H +#define _LIBUNWINDSTACK_MEMORY_LOCAL_H + +#include + +#include + +namespace unwindstack { + +class MemoryLocal : public Memory { + public: + MemoryLocal() = default; + virtual ~MemoryLocal() = default; + + size_t Read(uint64_t addr, void* dst, size_t size) override; +}; + +} // namespace unwindstack + +#endif // _LIBUNWINDSTACK_MEMORY_LOCAL_H diff --git a/libunwindstack/MemoryOffline.h b/libunwindstack/MemoryOffline.h new file mode 100644 index 000000000..789f1a268 --- /dev/null +++ b/libunwindstack/MemoryOffline.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _LIBUNWINDSTACK_MEMORY_OFFLINE_H +#define _LIBUNWINDSTACK_MEMORY_OFFLINE_H + +#include + +#include +#include +#include + +#include + +#include "MemoryRange.h" + +namespace unwindstack { + +class MemoryOffline : public Memory { + public: + MemoryOffline() = default; + virtual ~MemoryOffline() = default; + + bool Init(const std::string& file, uint64_t offset); + + size_t Read(uint64_t addr, void* dst, size_t size) override; + + private: + std::unique_ptr memory_; +}; + +class MemoryOfflineParts : public Memory { + public: + MemoryOfflineParts() = default; + virtual ~MemoryOfflineParts(); + + void Add(MemoryOffline* memory) { memories_.push_back(memory); } + + size_t Read(uint64_t addr, void* dst, size_t size) override; + + private: + std::vector memories_; +}; + +} // namespace unwindstack + +#endif // _LIBUNWINDSTACK_MEMORY_OFFLINE_H diff --git a/libunwindstack/MemoryOfflineBuffer.h b/libunwindstack/MemoryOfflineBuffer.h new file mode 100644 index 000000000..64c49a1ca --- /dev/null +++ b/libunwindstack/MemoryOfflineBuffer.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _LIBUNWINDSTACK_MEMORY_OFFLINE_BUFFER_H +#define _LIBUNWINDSTACK_MEMORY_OFFLINE_BUFFER_H + +#include + +#include + +namespace unwindstack { + +class MemoryOfflineBuffer : public Memory { + public: + MemoryOfflineBuffer(const uint8_t* data, uint64_t start, uint64_t end); + virtual ~MemoryOfflineBuffer() = default; + + void Reset(const uint8_t* data, uint64_t start, uint64_t end); + + size_t Read(uint64_t addr, void* dst, size_t size) override; + + private: + const uint8_t* data_; + uint64_t start_; + uint64_t end_; +}; + +} // namespace unwindstack + +#endif // _LIBUNWINDSTACK_MEMORY_OFFLINE_BUFFER_H diff --git a/libunwindstack/MemoryRange.h b/libunwindstack/MemoryRange.h new file mode 100644 index 000000000..3b4ab5c91 --- /dev/null +++ b/libunwindstack/MemoryRange.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _LIBUNWINDSTACK_MEMORY_RANGE_H +#define _LIBUNWINDSTACK_MEMORY_RANGE_H + +#include + +#include +#include +#include + +#include + +namespace unwindstack { + +// MemoryRange maps one address range onto another. +// The range [src_begin, src_begin + length) in the underlying Memory is mapped onto offset, +// such that range.read(offset) is equivalent to underlying.read(src_begin). +class MemoryRange : public Memory { + public: + MemoryRange(const std::shared_ptr& memory, uint64_t begin, uint64_t length, + uint64_t offset); + virtual ~MemoryRange() = default; + + size_t Read(uint64_t addr, void* dst, size_t size) override; + + uint64_t offset() { return offset_; } + uint64_t length() { return length_; } + + private: + std::shared_ptr memory_; + uint64_t begin_; + uint64_t length_; + uint64_t offset_; +}; + +class MemoryRanges : public Memory { + public: + MemoryRanges() = default; + virtual ~MemoryRanges() = default; + + void Insert(MemoryRange* memory); + + size_t Read(uint64_t addr, void* dst, size_t size) override; + + private: + std::map> maps_; +}; + +} // namespace unwindstack + +#endif // _LIBUNWINDSTACK_MEMORY_RANGE_H diff --git a/libunwindstack/MemoryRemote.h b/libunwindstack/MemoryRemote.h new file mode 100644 index 000000000..db367d649 --- /dev/null +++ b/libunwindstack/MemoryRemote.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _LIBUNWINDSTACK_MEMORY_REMOTE_H +#define _LIBUNWINDSTACK_MEMORY_REMOTE_H + +#include +#include + +#include + +#include + +namespace unwindstack { + +class MemoryRemote : public Memory { + public: + MemoryRemote(pid_t pid) : pid_(pid), read_redirect_func_(0) {} + virtual ~MemoryRemote() = default; + + size_t Read(uint64_t addr, void* dst, size_t size) override; + + pid_t pid() { return pid_; } + + private: + pid_t pid_; + std::atomic_uintptr_t read_redirect_func_; +}; + +} // namespace unwindstack + +#endif // _LIBUNWINDSTACK_MEMORY_REMOTE_H diff --git a/libunwindstack/include/unwindstack/MapInfo.h b/libunwindstack/include/unwindstack/MapInfo.h index 025fd98da..13ce10f00 100644 --- a/libunwindstack/include/unwindstack/MapInfo.h +++ b/libunwindstack/include/unwindstack/MapInfo.h @@ -25,10 +25,11 @@ #include #include -#include namespace unwindstack { +class MemoryFileAtOffset; + struct MapInfo { MapInfo(MapInfo* map_info, uint64_t start, uint64_t end, uint64_t offset, uint64_t flags, const char* name) diff --git a/libunwindstack/include/unwindstack/Memory.h b/libunwindstack/include/unwindstack/Memory.h index b3beb6eae..310656497 100644 --- a/libunwindstack/include/unwindstack/Memory.h +++ b/libunwindstack/include/unwindstack/Memory.h @@ -21,12 +21,8 @@ #include #include -#include -#include #include #include -#include -#include namespace unwindstack { @@ -37,6 +33,9 @@ class Memory { static std::shared_ptr CreateProcessMemory(pid_t pid); static std::shared_ptr CreateProcessMemoryCached(pid_t pid); + static std::shared_ptr CreateOfflineMemory(const uint8_t* data, uint64_t start, + uint64_t end); + static std::unique_ptr CreateFileMemory(const std::string& path, uint64_t offset); virtual bool ReadString(uint64_t addr, std::string* string, uint64_t max_read = UINT64_MAX); @@ -55,157 +54,6 @@ class Memory { } }; -class MemoryCache : public Memory { - public: - MemoryCache(Memory* memory) : impl_(memory) {} - virtual ~MemoryCache() = default; - - size_t Read(uint64_t addr, void* dst, size_t size) override; - - void Clear() override { cache_.clear(); } - - private: - constexpr static size_t kCacheBits = 12; - constexpr static size_t kCacheMask = (1 << kCacheBits) - 1; - constexpr static size_t kCacheSize = 1 << kCacheBits; - std::unordered_map cache_; - - std::unique_ptr impl_; -}; - -class MemoryBuffer : public Memory { - public: - MemoryBuffer() = default; - virtual ~MemoryBuffer() = default; - - size_t Read(uint64_t addr, void* dst, size_t size) override; - - uint8_t* GetPtr(size_t offset); - - void Resize(size_t size) { raw_.resize(size); } - - uint64_t Size() { return raw_.size(); } - - private: - std::vector raw_; -}; - -class MemoryFileAtOffset : public Memory { - public: - MemoryFileAtOffset() = default; - virtual ~MemoryFileAtOffset(); - - bool Init(const std::string& file, uint64_t offset, uint64_t size = UINT64_MAX); - - size_t Read(uint64_t addr, void* dst, size_t size) override; - - size_t Size() { return size_; } - - void Clear() override; - - protected: - size_t size_ = 0; - size_t offset_ = 0; - uint8_t* data_ = nullptr; -}; - -class MemoryRemote : public Memory { - public: - MemoryRemote(pid_t pid) : pid_(pid), read_redirect_func_(0) {} - virtual ~MemoryRemote() = default; - - size_t Read(uint64_t addr, void* dst, size_t size) override; - - pid_t pid() { return pid_; } - - private: - pid_t pid_; - std::atomic_uintptr_t read_redirect_func_; -}; - -class MemoryLocal : public Memory { - public: - MemoryLocal() = default; - virtual ~MemoryLocal() = default; - - size_t Read(uint64_t addr, void* dst, size_t size) override; -}; - -// MemoryRange maps one address range onto another. -// The range [src_begin, src_begin + length) in the underlying Memory is mapped onto offset, -// such that range.read(offset) is equivalent to underlying.read(src_begin). -class MemoryRange : public Memory { - public: - MemoryRange(const std::shared_ptr& memory, uint64_t begin, uint64_t length, - uint64_t offset); - virtual ~MemoryRange() = default; - - size_t Read(uint64_t addr, void* dst, size_t size) override; - - uint64_t offset() { return offset_; } - uint64_t length() { return length_; } - - private: - std::shared_ptr memory_; - uint64_t begin_; - uint64_t length_; - uint64_t offset_; -}; - -class MemoryRanges : public Memory { - public: - MemoryRanges() = default; - virtual ~MemoryRanges() = default; - - void Insert(MemoryRange* memory); - - size_t Read(uint64_t addr, void* dst, size_t size) override; - - private: - std::map> maps_; -}; - -class MemoryOffline : public Memory { - public: - MemoryOffline() = default; - virtual ~MemoryOffline() = default; - - bool Init(const std::string& file, uint64_t offset); - - size_t Read(uint64_t addr, void* dst, size_t size) override; - - private: - std::unique_ptr memory_; -}; - -class MemoryOfflineBuffer : public Memory { - public: - MemoryOfflineBuffer(const uint8_t* data, uint64_t start, uint64_t end); - virtual ~MemoryOfflineBuffer() = default; - - void Reset(const uint8_t* data, uint64_t start, uint64_t end); - - size_t Read(uint64_t addr, void* dst, size_t size) override; - - private: - const uint8_t* data_; - uint64_t start_; - uint64_t end_; -}; - -class MemoryOfflineParts : public Memory { - public: - MemoryOfflineParts() = default; - virtual ~MemoryOfflineParts(); - - void Add(MemoryOffline* memory) { memories_.push_back(memory); } - - size_t Read(uint64_t addr, void* dst, size_t size) override; - - private: - std::vector memories_; -}; - } // namespace unwindstack #endif // _LIBUNWINDSTACK_MEMORY_H diff --git a/libunwindstack/tests/MemoryBufferTest.cpp b/libunwindstack/tests/MemoryBufferTest.cpp index 28e0e76b9..a6c12aab0 100644 --- a/libunwindstack/tests/MemoryBufferTest.cpp +++ b/libunwindstack/tests/MemoryBufferTest.cpp @@ -18,9 +18,8 @@ #include -#include - #include "LogFake.h" +#include "MemoryBuffer.h" namespace unwindstack { diff --git a/libunwindstack/tests/MemoryCacheTest.cpp b/libunwindstack/tests/MemoryCacheTest.cpp index a3def206f..3bd3e4dbe 100644 --- a/libunwindstack/tests/MemoryCacheTest.cpp +++ b/libunwindstack/tests/MemoryCacheTest.cpp @@ -20,8 +20,7 @@ #include -#include - +#include "MemoryCache.h" #include "MemoryFake.h" namespace unwindstack { diff --git a/libunwindstack/tests/MemoryFileTest.cpp b/libunwindstack/tests/MemoryFileTest.cpp index d7d1ace64..4124a491c 100644 --- a/libunwindstack/tests/MemoryFileTest.cpp +++ b/libunwindstack/tests/MemoryFileTest.cpp @@ -21,7 +21,7 @@ #include #include -#include +#include "MemoryFileAtOffset.h" namespace unwindstack { diff --git a/libunwindstack/tests/MemoryLocalTest.cpp b/libunwindstack/tests/MemoryLocalTest.cpp index 5a389d0a9..c9e5dc0fd 100644 --- a/libunwindstack/tests/MemoryLocalTest.cpp +++ b/libunwindstack/tests/MemoryLocalTest.cpp @@ -22,7 +22,7 @@ #include -#include +#include "MemoryLocal.h" namespace unwindstack { diff --git a/libunwindstack/tests/MemoryOfflineBufferTest.cpp b/libunwindstack/tests/MemoryOfflineBufferTest.cpp index f022884cb..c62c53dae 100644 --- a/libunwindstack/tests/MemoryOfflineBufferTest.cpp +++ b/libunwindstack/tests/MemoryOfflineBufferTest.cpp @@ -18,9 +18,8 @@ #include -#include - #include "LogFake.h" +#include "MemoryOfflineBuffer.h" namespace unwindstack { diff --git a/libunwindstack/tests/MemoryOfflineTest.cpp b/libunwindstack/tests/MemoryOfflineTest.cpp index ab9aa9dc9..d0c441ba5 100644 --- a/libunwindstack/tests/MemoryOfflineTest.cpp +++ b/libunwindstack/tests/MemoryOfflineTest.cpp @@ -19,7 +19,8 @@ #include #include -#include + +#include "MemoryOffline.h" namespace unwindstack { diff --git a/libunwindstack/tests/MemoryRangeTest.cpp b/libunwindstack/tests/MemoryRangeTest.cpp index 2bac95b61..2d4f141ab 100644 --- a/libunwindstack/tests/MemoryRangeTest.cpp +++ b/libunwindstack/tests/MemoryRangeTest.cpp @@ -21,9 +21,8 @@ #include -#include - #include "MemoryFake.h" +#include "MemoryRange.h" namespace unwindstack { diff --git a/libunwindstack/tests/MemoryRangesTest.cpp b/libunwindstack/tests/MemoryRangesTest.cpp index d24fcd23f..e4e9fc4e9 100644 --- a/libunwindstack/tests/MemoryRangesTest.cpp +++ b/libunwindstack/tests/MemoryRangesTest.cpp @@ -20,9 +20,8 @@ #include -#include - #include "MemoryFake.h" +#include "MemoryRange.h" namespace unwindstack { diff --git a/libunwindstack/tests/MemoryRemoteTest.cpp b/libunwindstack/tests/MemoryRemoteTest.cpp index fb56e8afb..c90dedcec 100644 --- a/libunwindstack/tests/MemoryRemoteTest.cpp +++ b/libunwindstack/tests/MemoryRemoteTest.cpp @@ -30,7 +30,7 @@ #include #include -#include +#include "MemoryRemote.h" #include "MemoryFake.h" #include "TestUtils.h" diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp index 553b34406..baada8281 100644 --- a/libunwindstack/tests/UnwindOfflineTest.cpp +++ b/libunwindstack/tests/UnwindOfflineTest.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -43,6 +42,7 @@ #include #include "ElfTestUtils.h" +#include "MemoryOffline.h" #include "TestUtils.h" namespace unwindstack { diff --git a/libunwindstack/tests/UnwindTest.cpp b/libunwindstack/tests/UnwindTest.cpp index 4e3801511..f76a101df 100644 --- a/libunwindstack/tests/UnwindTest.cpp +++ b/libunwindstack/tests/UnwindTest.cpp @@ -35,11 +35,11 @@ #include #include -#include #include #include #include +#include "MemoryRemote.h" #include "TestUtils.h" namespace unwindstack { diff --git a/libunwindstack/tools/unwind_info.cpp b/libunwindstack/tools/unwind_info.cpp index 92e5c0af3..7a6d8ba46 100644 --- a/libunwindstack/tools/unwind_info.cpp +++ b/libunwindstack/tools/unwind_info.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include "ArmExidx.h" #include "ElfInterfaceArm.h" @@ -105,14 +106,7 @@ int GetElfInfo(const char* file, uint64_t offset) { // Send all log messages to stdout. log_to_stdout(true); - MemoryFileAtOffset* memory = new MemoryFileAtOffset; - if (!memory->Init(file, offset)) { - // Initializatation failed. - printf("Failed to init\n"); - return 1; - } - - Elf elf(memory); + Elf elf(Memory::CreateFileMemory(file, offset).release()); if (!elf.Init() || !elf.valid()) { printf("%s is not a valid elf file.\n", file); return 1; diff --git a/libunwindstack/tools/unwind_reg_info.cpp b/libunwindstack/tools/unwind_reg_info.cpp index b77a86bbf..d0562d9cf 100644 --- a/libunwindstack/tools/unwind_reg_info.cpp +++ b/libunwindstack/tools/unwind_reg_info.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include "ArmExidx.h" #include "DwarfOp.h" @@ -165,14 +166,7 @@ void PrintArmRegInformation(ElfInterfaceArm* interface, uint64_t pc) { } int GetInfo(const char* file, uint64_t pc) { - MemoryFileAtOffset* memory = new MemoryFileAtOffset; - if (!memory->Init(file, 0)) { - // Initializatation failed. - printf("Failed to init\n"); - return 1; - } - - Elf elf(memory); + Elf elf(Memory::CreateFileMemory(file, pc).release()); if (!elf.Init() || !elf.valid()) { printf("%s is not a valid elf file.\n", file); return 1; @@ -205,7 +199,7 @@ int GetInfo(const char* file, uint64_t pc) { DwarfSection* section = interface->eh_frame(); if (section != nullptr) { printf("\neh_frame:\n"); - PrintRegInformation(section, memory, pc, elf.class_type()); + PrintRegInformation(section, elf.memory(), pc, elf.class_type()); } else { printf("\nno eh_frame information\n"); } @@ -213,7 +207,7 @@ int GetInfo(const char* file, uint64_t pc) { section = interface->debug_frame(); if (section != nullptr) { printf("\ndebug_frame:\n"); - PrintRegInformation(section, memory, pc, elf.class_type()); + PrintRegInformation(section, elf.memory(), pc, elf.class_type()); printf("\n"); } else { printf("\nno debug_frame information\n"); diff --git a/libunwindstack/tools/unwind_symbols.cpp b/libunwindstack/tools/unwind_symbols.cpp index b0a4dd07a..8df228412 100644 --- a/libunwindstack/tools/unwind_symbols.cpp +++ b/libunwindstack/tools/unwind_symbols.cpp @@ -59,13 +59,7 @@ int main(int argc, char** argv) { // Send all log messages to stdout. unwindstack::log_to_stdout(true); - unwindstack::MemoryFileAtOffset* memory = new unwindstack::MemoryFileAtOffset; - if (!memory->Init(argv[1], 0)) { - printf("Failed to init\n"); - return 1; - } - - unwindstack::Elf elf(memory); + unwindstack::Elf elf(unwindstack::Memory::CreateFileMemory(argv[1], 0).release()); if (!elf.Init() || !elf.valid()) { printf("%s is not a valid elf file.\n", argv[1]); return 1;