diff --git a/libbacktrace b/libbacktrace new file mode 120000 index 000000000..571194c26 --- /dev/null +++ b/libbacktrace @@ -0,0 +1 @@ +../unwinding/libbacktrace \ No newline at end of file diff --git a/libbacktrace/.clang-format b/libbacktrace/.clang-format deleted file mode 120000 index fd0645fdf..000000000 --- a/libbacktrace/.clang-format +++ /dev/null @@ -1 +0,0 @@ -../.clang-format-2 \ No newline at end of file diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp deleted file mode 100644 index c7969f24d..000000000 --- a/libbacktrace/Android.bp +++ /dev/null @@ -1,233 +0,0 @@ -// -// Copyright (C) 2014 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. -// - -cc_defaults { - name: "libbacktrace_common", - - cflags: [ - "-Wall", - "-Werror", - ], - - target: { - darwin: { - enabled: false, - }, - }, -} - -libbacktrace_sources = [ - "Backtrace.cpp", - "BacktraceCurrent.cpp", - "BacktracePtrace.cpp", - "ThreadEntry.cpp", - "UnwindStack.cpp", - "UnwindStackMap.cpp", -] - -cc_library_headers { - name: "libbacktrace_headers", - vendor_available: true, - recovery_available: true, - native_bridge_supported: true, - export_include_dirs: ["include"], - apex_available: [ - "//apex_available:platform", - "//apex_available:anyapex", - ], - min_sdk_version: "apex_inherit", -} - -cc_defaults { - name: "libbacktrace_defaults", - defaults: ["libbacktrace_common"], - - cflags: [ - "-Wexit-time-destructors", - ], - - srcs: [ - "BacktraceMap.cpp", - ], - - export_include_dirs: ["include"], - - target: { - darwin: { - enabled: true, - shared_libs: [ - "libbase", - ], - }, - linux: { - srcs: libbacktrace_sources, - - shared_libs: [ - "libbase", - "liblog", - ], - - static_libs: [ - "libprocinfo", - ], - }, - android: { - static_libs: ["libasync_safe"], - static: { - whole_static_libs: ["libasync_safe"], - }, - }, - }, -} - -cc_library { - name: "libbacktrace", - vendor_available: false, - // TODO(b/153609531): remove when no longer needed. - native_bridge_supported: true, - recovery_available: true, - apex_available: [ - "//apex_available:platform", - "//apex_available:anyapex", - ], - vndk: { - enabled: true, - support_system_process: true, - }, - host_supported: true, - defaults: ["libbacktrace_defaults"], - - target: { - linux: { - shared_libs: [ - "libunwindstack", - ], - }, - vendor: { - cflags: ["-DNO_LIBDEXFILE_SUPPORT"], - }, - recovery: { - cflags: ["-DNO_LIBDEXFILE_SUPPORT"], - }, - native_bridge: { - cflags: ["-DNO_LIBDEXFILE_SUPPORT"], - }, - }, -} - -// Static library without DEX support to avoid dependencies on the ART APEX. -cc_library_static { - name: "libbacktrace_no_dex", - visibility: [ - "//system/core/debuggerd", - "//system/core/init", - ], - defaults: ["libbacktrace_defaults"], - cflags: ["-DNO_LIBDEXFILE_SUPPORT"], - target: { - linux: { - static_libs: [ - "libunwindstack_no_dex", - ], - }, - }, -} - -cc_test_library { - name: "libbacktrace_test", - defaults: ["libbacktrace_common"], - host_supported: true, - strip: { - none: true, - }, - cflags: ["-O0"], - srcs: ["backtrace_testlib.cpp"], - - shared_libs: [ - "libunwindstack", - ], - relative_install_path: "backtrace_test_libs", - - target: { - linux_glibc: { - // This forces the creation of eh_frame with unwind information - // for host. - cflags: [ - "-fcxx-exceptions" - ], - }, - }, -} - -//------------------------------------------------------------------------- -// The backtrace_test executable. -//------------------------------------------------------------------------- -cc_test { - name: "backtrace_test", - isolated: true, - defaults: ["libbacktrace_common"], - host_supported: true, - srcs: [ - "backtrace_test.cpp", - ], - - cflags: [ - "-fno-builtin", - "-O0", - "-g", - ], - - shared_libs: [ - "libbacktrace", - "libbase", - "liblog", - "libunwindstack", - ], - - group_static_libs: true, - - // So that the dlopen can find the libbacktrace_test.so. - ldflags: [ - "-Wl,--rpath,${ORIGIN}/../backtrace_test_libs", - ], - - test_suites: ["device-tests"], - data: [ - "testdata/arm/*", - "testdata/arm64/*", - "testdata/x86/*", - "testdata/x86_64/*", - ], - required: [ - "libbacktrace_test", - ], -} - -cc_benchmark { - name: "backtrace_benchmarks", - defaults: ["libbacktrace_common"], - - srcs: [ - "backtrace_benchmarks.cpp", - "backtrace_read_benchmarks.cpp", - ], - - shared_libs: [ - "libbacktrace", - "libbase", - "libunwindstack", - ], -} diff --git a/libbacktrace/Backtrace.cpp b/libbacktrace/Backtrace.cpp deleted file mode 100644 index 3e050ab68..000000000 --- a/libbacktrace/Backtrace.cpp +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (C) 2013 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 "BacktraceLog.h" -#include "UnwindStack.h" - -using android::base::StringPrintf; - -extern "C" char* __cxa_demangle(const char*, char*, size_t*, int*); - -//------------------------------------------------------------------------- -// Backtrace functions. -//------------------------------------------------------------------------- -Backtrace::Backtrace(pid_t pid, pid_t tid, BacktraceMap* map) - : pid_(pid), tid_(tid), map_(map), map_shared_(true) { - if (map_ == nullptr) { - map_ = BacktraceMap::Create(pid); - map_shared_ = false; - } -} - -Backtrace::~Backtrace() { - if (map_ && !map_shared_) { - delete map_; - map_ = nullptr; - } -} - -std::string Backtrace::GetFunctionName(uint64_t pc, uint64_t* offset, const backtrace_map_t* map) { - backtrace_map_t map_value; - if (map == nullptr) { - FillInMap(pc, &map_value); - map = &map_value; - } - // If no map is found, or this map is backed by a device, then return nothing. - if (map->start == 0 || (map->flags & PROT_DEVICE_MAP)) { - return ""; - } - std::string name(GetFunctionNameRaw(pc, offset)); - char* demangled_name = __cxa_demangle(name.c_str(), nullptr, nullptr, nullptr); - if (demangled_name != nullptr) { - name = demangled_name; - free(demangled_name); - return name; - } - return name; -} - -bool Backtrace::VerifyReadWordArgs(uint64_t ptr, word_t* out_value) { - if (ptr & (sizeof(word_t)-1)) { - BACK_LOGW("invalid pointer %p", reinterpret_cast(ptr)); - *out_value = static_cast(-1); - return false; - } - return true; -} - -std::string Backtrace::FormatFrameData(size_t frame_num) { - if (frame_num >= frames_.size()) { - return ""; - } - return FormatFrameData(&frames_[frame_num]); -} - -std::string Backtrace::FormatFrameData(const backtrace_frame_data_t* frame) { - std::string map_name; - if (BacktraceMap::IsValid(frame->map)) { - map_name = frame->map.Name(); - if (!frame->map.name.empty()) { - if (map_name[0] == '[' && map_name[map_name.size() - 1] == ']') { - map_name.resize(map_name.size() - 1); - map_name += StringPrintf(":%" PRIPTR "]", frame->map.start); - } - } - } else { - map_name = ""; - } - - std::string line(StringPrintf("#%02zu pc %" PRIPTR " ", frame->num, frame->rel_pc)); - line += map_name; - // Special handling for non-zero offset maps, we need to print that - // information. - if (frame->map.offset != 0) { - line += " (offset " + StringPrintf("0x%" PRIx64, frame->map.offset) + ")"; - } - if (!frame->func_name.empty()) { - line += " (" + frame->func_name; - if (frame->func_offset) { - line += StringPrintf("+%" PRIu64, frame->func_offset); - } - line += ')'; - } - - return line; -} - -void Backtrace::FillInMap(uint64_t pc, backtrace_map_t* map) { - if (map_ != nullptr) { - map_->FillIn(pc, map); - } -} - -Backtrace* Backtrace::Create(pid_t pid, pid_t tid, BacktraceMap* map) { - if (pid == BACKTRACE_CURRENT_PROCESS) { - pid = getpid(); - if (tid == BACKTRACE_CURRENT_THREAD) { - tid = android::base::GetThreadId(); - } - } else if (tid == BACKTRACE_CURRENT_THREAD) { - tid = pid; - } - - if (pid == getpid()) { - return new UnwindStackCurrent(pid, tid, map); - } else { - return new UnwindStackPtrace(pid, tid, map); - } -} - -std::string Backtrace::GetErrorString(BacktraceUnwindError error) { - switch (error.error_code) { - case BACKTRACE_UNWIND_NO_ERROR: - return "No error"; - case BACKTRACE_UNWIND_ERROR_SETUP_FAILED: - return "Setup failed"; - case BACKTRACE_UNWIND_ERROR_MAP_MISSING: - return "No map found"; - case BACKTRACE_UNWIND_ERROR_INTERNAL: - return "Internal libbacktrace error, please submit a bugreport"; - case BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST: - return "Thread doesn't exist"; - case BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT: - return "Thread has not responded to signal in time"; - case BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION: - return "Attempt to use an unsupported feature"; - case BACKTRACE_UNWIND_ERROR_NO_CONTEXT: - return "Attempt to do an offline unwind without a context"; - case BACKTRACE_UNWIND_ERROR_EXCEED_MAX_FRAMES_LIMIT: - return "Exceed MAX_BACKTRACE_FRAMES limit"; - case BACKTRACE_UNWIND_ERROR_ACCESS_MEM_FAILED: - return android::base::StringPrintf("Failed to read memory at addr 0x%" PRIx64, - error.error_info.addr); - case BACKTRACE_UNWIND_ERROR_ACCESS_REG_FAILED: - return android::base::StringPrintf("Failed to read register %" PRIu64, error.error_info.regno); - case BACKTRACE_UNWIND_ERROR_FIND_PROC_INFO_FAILED: - return "Failed to find a function in debug sections"; - case BACKTRACE_UNWIND_ERROR_EXECUTE_DWARF_INSTRUCTION_FAILED: - return "Failed to execute dwarf instructions in debug sections"; - case BACKTRACE_UNWIND_ERROR_UNWIND_INFO: - return "Failed to unwind due to invalid unwind information"; - case BACKTRACE_UNWIND_ERROR_REPEATED_FRAME: - return "Failed to unwind due to same sp/pc repeating"; - case BACKTRACE_UNWIND_ERROR_INVALID_ELF: - return "Failed to unwind due to invalid elf"; - } -} diff --git a/libbacktrace/BacktraceAsyncSafeLog.h b/libbacktrace/BacktraceAsyncSafeLog.h deleted file mode 100644 index 14f51be24..000000000 --- a/libbacktrace/BacktraceAsyncSafeLog.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2014 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 _LIBBACKTRACE_BACKTRACE_ASYNC_SAFE_LOG_H -#define _LIBBACKTRACE_BACKTRACE_ASYNC_SAFE_LOG_H - -#if defined(__ANDROID__) - -#include - -// Logging macros for use in signal handler, only available on target. -#define BACK_ASYNC_SAFE_LOGW(format, ...) \ - async_safe_format_log(ANDROID_LOG_WARN, "libbacktrace", "%s: " format, __PRETTY_FUNCTION__, \ - ##__VA_ARGS__) - -#define BACK_ASYNC_SAFE_LOGE(format, ...) \ - async_safe_format_log(ANDROID_LOG_ERROR, "libbacktrace", "%s: " format, __PRETTY_FUNCTION__, \ - ##__VA_ARGS__) - -#else - -#define BACK_ASYNC_SAFE_LOGW(format, ...) - -#define BACK_ASYNC_SAFE_LOGE(format, ...) - -#endif - -#endif // _LIBBACKTRACE_BACKTRACE_ASYNC_SAFE_LOG_H diff --git a/libbacktrace/BacktraceCurrent.cpp b/libbacktrace/BacktraceCurrent.cpp deleted file mode 100644 index a5065752d..000000000 --- a/libbacktrace/BacktraceCurrent.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (C) 2013 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. - */ - -#define _GNU_SOURCE 1 -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include - -#include "BacktraceAsyncSafeLog.h" -#include "BacktraceCurrent.h" -#include "ThreadEntry.h" - -bool BacktraceCurrent::ReadWord(uint64_t ptr, word_t* out_value) { -#if defined(__aarch64__) - // Tagged pointer after Android R would lead top byte to have random values - // https://source.android.com/devices/tech/debug/tagged-pointers - ptr &= (1ULL << 56) - 1; -#endif - - if (!VerifyReadWordArgs(ptr, out_value)) { - return false; - } - - backtrace_map_t map; - FillInMap(ptr, &map); - if (BacktraceMap::IsValid(map) && map.flags & PROT_READ) { - *out_value = *reinterpret_cast(ptr); - return true; - } else { - BACK_ASYNC_SAFE_LOGW("pointer %p not in a readable map", reinterpret_cast(ptr)); - *out_value = static_cast(-1); - return false; - } -} - -size_t BacktraceCurrent::Read(uint64_t addr, uint8_t* buffer, size_t bytes) { -#if defined(__aarch64__) - // Tagged pointer after Android R would lead top byte to have random values - // https://source.android.com/devices/tech/debug/tagged-pointers - addr &= (1ULL << 56) - 1; -#endif - - backtrace_map_t map; - FillInMap(addr, &map); - if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) { - return 0; - } - bytes = MIN(map.end - addr, bytes); - memcpy(buffer, reinterpret_cast(addr), bytes); - return bytes; -} - -bool BacktraceCurrent::Unwind(size_t num_ignore_frames, void* ucontext) { - if (GetMap() == nullptr) { - // Without a map object, we can't do anything. - error_.error_code = BACKTRACE_UNWIND_ERROR_MAP_MISSING; - return false; - } - - error_.error_code = BACKTRACE_UNWIND_NO_ERROR; - if (ucontext) { - return UnwindFromContext(num_ignore_frames, ucontext); - } - - if (Tid() != static_cast(android::base::GetThreadId())) { - return UnwindThread(num_ignore_frames); - } - - return UnwindFromContext(num_ignore_frames, nullptr); -} - -bool BacktraceCurrent::DiscardFrame(const backtrace_frame_data_t& frame) { - if (BacktraceMap::IsValid(frame.map)) { - const std::string library = basename(frame.map.name.c_str()); - if (library == "libunwind.so" || library == "libbacktrace.so") { - return true; - } - } - return false; -} - -static pthread_mutex_t g_sigaction_mutex = PTHREAD_MUTEX_INITIALIZER; - -// Since errno is stored per thread, changing it in the signal handler -// modifies the value on the thread in which the signal handler executes. -// If a signal occurs between a call and an errno check, it's possible -// to get the errno set here. Always save and restore it just in case -// code would modify it. -class ErrnoRestorer { - public: - ErrnoRestorer() : saved_errno_(errno) {} - ~ErrnoRestorer() { - errno = saved_errno_; - } - - private: - int saved_errno_; -}; - -static void SignalLogOnly(int, siginfo_t*, void*) { - ErrnoRestorer restore; - - BACK_ASYNC_SAFE_LOGE("pid %d, tid %d: Received a spurious signal %d\n", getpid(), - static_cast(android::base::GetThreadId()), THREAD_SIGNAL); -} - -static void SignalHandler(int, siginfo_t*, void* sigcontext) { - ErrnoRestorer restore; - - ThreadEntry* entry = ThreadEntry::Get(getpid(), android::base::GetThreadId(), false); - if (!entry) { - BACK_ASYNC_SAFE_LOGE("pid %d, tid %d entry not found", getpid(), - static_cast(android::base::GetThreadId())); - return; - } - - entry->CopyUcontextFromSigcontext(sigcontext); - - // Indicate the ucontext is now valid. - entry->Wake(); - - // Pause the thread until the unwind is complete. This avoids having - // the thread run ahead causing problems. - // The number indicates that we are waiting for the second Wake() call - // overall which is made by the thread requesting an unwind. - if (entry->Wait(2)) { - // Do not remove the entry here because that can result in a deadlock - // if the code cannot properly send a signal to the thread under test. - entry->Wake(); - } else { - // At this point, it is possible that entry has been freed, so just exit. - BACK_ASYNC_SAFE_LOGE("Timed out waiting for unwind thread to indicate it completed."); - } -} - -bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) { - // Prevent multiple threads trying to set the trigger action on different - // threads at the same time. - pthread_mutex_lock(&g_sigaction_mutex); - - ThreadEntry* entry = ThreadEntry::Get(Pid(), Tid()); - entry->Lock(); - - struct sigaction act, oldact; - memset(&act, 0, sizeof(act)); - act.sa_sigaction = SignalHandler; - act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; - sigemptyset(&act.sa_mask); - if (sigaction(THREAD_SIGNAL, &act, &oldact) != 0) { - BACK_ASYNC_SAFE_LOGE("sigaction failed: %s", strerror(errno)); - ThreadEntry::Remove(entry); - pthread_mutex_unlock(&g_sigaction_mutex); - error_.error_code = BACKTRACE_UNWIND_ERROR_INTERNAL; - return false; - } - - if (tgkill(Pid(), Tid(), THREAD_SIGNAL) != 0) { - // Do not emit an error message, this might be expected. Set the - // error and let the caller decide. - if (errno == ESRCH) { - error_.error_code = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST; - } else { - error_.error_code = BACKTRACE_UNWIND_ERROR_INTERNAL; - } - - sigaction(THREAD_SIGNAL, &oldact, nullptr); - ThreadEntry::Remove(entry); - pthread_mutex_unlock(&g_sigaction_mutex); - return false; - } - - // Wait for the thread to get the ucontext. The number indicates - // that we are waiting for the first Wake() call made by the thread. - bool wait_completed = entry->Wait(1); - - if (!wait_completed && oldact.sa_sigaction == nullptr) { - // If the wait failed, it could be that the signal could not be delivered - // within the timeout. Add a signal handler that's simply going to log - // something so that we don't crash if the signal eventually gets - // delivered. Only do this if there isn't already an action set up. - memset(&act, 0, sizeof(act)); - act.sa_sigaction = SignalLogOnly; - act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; - sigemptyset(&act.sa_mask); - sigaction(THREAD_SIGNAL, &act, nullptr); - } else { - sigaction(THREAD_SIGNAL, &oldact, nullptr); - } - // After the thread has received the signal, allow other unwinders to - // continue. - pthread_mutex_unlock(&g_sigaction_mutex); - - bool unwind_done = false; - if (wait_completed) { - unwind_done = UnwindFromContext(num_ignore_frames, entry->GetUcontext()); - - // Tell the signal handler to exit and release the entry. - entry->Wake(); - - // Wait for the thread to indicate it is done with the ThreadEntry. - if (!entry->Wait(3)) { - // Send a warning, but do not mark as a failure to unwind. - BACK_ASYNC_SAFE_LOGW("Timed out waiting for signal handler to indicate it finished."); - } - } else { - // Check to see if the thread has disappeared. - if (tgkill(Pid(), Tid(), 0) == -1 && errno == ESRCH) { - error_.error_code = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST; - } else { - error_.error_code = BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT; - BACK_ASYNC_SAFE_LOGE("Timed out waiting for signal handler to get ucontext data."); - } - } - - ThreadEntry::Remove(entry); - - return unwind_done; -} diff --git a/libbacktrace/BacktraceCurrent.h b/libbacktrace/BacktraceCurrent.h deleted file mode 100644 index 48c14eaf3..000000000 --- a/libbacktrace/BacktraceCurrent.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2013 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 _LIBBACKTRACE_BACKTRACE_CURRENT_H -#define _LIBBACKTRACE_BACKTRACE_CURRENT_H - -#include -#include - -#include - -// The signal used to cause a thread to dump the stack. -#if defined(__GLIBC__) -// In order to run the backtrace_tests on the host, we can't use -// the internal real time signals used by GLIBC. To avoid this, -// use SIGRTMIN for the signal to dump the stack. -#define THREAD_SIGNAL SIGRTMIN -#else -#define THREAD_SIGNAL (__SIGRTMIN+1) -#endif - -class BacktraceMap; - -class BacktraceCurrent : public Backtrace { - public: - BacktraceCurrent(pid_t pid, pid_t tid, BacktraceMap* map) : Backtrace(pid, tid, map) {} - virtual ~BacktraceCurrent() {} - - size_t Read(uint64_t addr, uint8_t* buffer, size_t bytes) override; - - bool ReadWord(uint64_t ptr, word_t* out_value) override; - - bool Unwind(size_t num_ignore_frames, void* ucontext) override; - - protected: - bool DiscardFrame(const backtrace_frame_data_t& frame); - - private: - bool UnwindThread(size_t num_ignore_frames); - - virtual bool UnwindFromContext(size_t num_ignore_frames, void* ucontext) = 0; -}; - -#endif // _LIBBACKTRACE_BACKTRACE_CURRENT_H diff --git a/libbacktrace/BacktraceLog.h b/libbacktrace/BacktraceLog.h deleted file mode 100644 index 5c39f1c04..000000000 --- a/libbacktrace/BacktraceLog.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2014 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 _LIBBACKTRACE_BACKTRACE_LOG_H -#define _LIBBACKTRACE_BACKTRACE_LOG_H - -#define LOG_TAG "libbacktrace" - -#include - -// Macro to log the function name along with the warning message. -#define BACK_LOGW(format, ...) \ - ALOGW("%s: " format, __PRETTY_FUNCTION__, ##__VA_ARGS__) - -#define BACK_LOGE(format, ...) \ - ALOGE("%s: " format, __PRETTY_FUNCTION__, ##__VA_ARGS__) - -#endif // _LIBBACKTRACE_BACKTRACE_LOG_H diff --git a/libbacktrace/BacktraceMap.cpp b/libbacktrace/BacktraceMap.cpp deleted file mode 100644 index 781819af5..000000000 --- a/libbacktrace/BacktraceMap.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2014 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. - */ - -#define LOG_TAG "backtrace-map" - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#if defined(__linux__) -#include -#endif - -using android::base::StringPrintf; - -std::string backtrace_map_t::Name() const { - if (!name.empty()) return name; - if (start == 0 && end == 0) return ""; - return StringPrintf("", start); -} - -BacktraceMap::BacktraceMap(pid_t pid) : pid_(pid) { - if (pid_ < 0) { - pid_ = getpid(); - } -} - -BacktraceMap::~BacktraceMap() {} - -void BacktraceMap::FillIn(uint64_t addr, backtrace_map_t* map) { - ScopedBacktraceMapIteratorLock lock(this); - for (auto it = begin(); it != end(); ++it) { - const backtrace_map_t* entry = *it; - if (addr >= entry->start && addr < entry->end) { - *map = *entry; - return; - } - } - *map = {}; -} - -#if defined(__APPLE__) -static bool ParseLine(const char* line, backtrace_map_t* map) { - uint64_t start; - uint64_t end; - char permissions[5]; - int name_pos; - - // Mac OS vmmap(1) output: - // __TEXT 0009f000-000a1000 [ 8K 8K] r-x/rwx SM=COW - // /Volumes/android/dalvik-dev/out/host/darwin-x86/bin/libcorkscrew_test\n - // 012345678901234567890123456789012345678901234567890123456789 - // 0 1 2 3 4 5 - if (sscanf(line, "%*21c %" SCNx64 "-%" SCNx64 " [%*13c] %3c/%*3c SM=%*3c %n", &start, &end, - permissions, &name_pos) != 3) { - return false; - } - - map->start = start; - map->end = end; - map->flags = PROT_NONE; - if (permissions[0] == 'r') { - map->flags |= PROT_READ; - } - if (permissions[1] == 'w') { - map->flags |= PROT_WRITE; - } - if (permissions[2] == 'x') { - map->flags |= PROT_EXEC; - } - - map->name = line + name_pos; - if (!map->name.empty() && map->name[map->name.length() - 1] == '\n') { - map->name.erase(map->name.length() - 1); - } - - ALOGV("Parsed map: start=%p, end=%p, flags=%x, name=%s", reinterpret_cast(map->start), - reinterpret_cast(map->end), map->flags, map->name.c_str()); - return true; -} -#endif // defined(__APPLE__) - -bool BacktraceMap::Build() { -#if defined(__APPLE__) - char - cmd[sizeof(pid_t) * 3 + sizeof("vmmap -w -resident -submap -allSplitLibs -interleaved ") + 1]; - char line[1024]; - // cmd is guaranteed to always be big enough to hold this string. - snprintf(cmd, sizeof(cmd), "vmmap -w -resident -submap -allSplitLibs -interleaved %d", pid_); - FILE* fp = popen(cmd, "r"); - if (fp == nullptr) { - return false; - } - - while (fgets(line, sizeof(line), fp)) { - backtrace_map_t map; - if (ParseLine(line, &map)) { - maps_.push_back(map); - } - } - pclose(fp); - return true; -#else - return android::procinfo::ReadProcessMaps( - pid_, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t, ino_t, const char* name) { - maps_.resize(maps_.size() + 1); - backtrace_map_t& map = maps_.back(); - map.start = start; - map.end = end; - map.flags = flags; - map.name = name; - }); -#endif -} - -#if defined(__APPLE__) -// Corkscrew and libunwind don't compile on the mac, so create a generic -// map object. -BacktraceMap* BacktraceMap::Create(pid_t pid, bool /*uncached*/) { - BacktraceMap* map = new BacktraceMap(pid); - if (!map->Build()) { - delete map; - return nullptr; - } - return map; -} -#endif diff --git a/libbacktrace/BacktracePtrace.cpp b/libbacktrace/BacktracePtrace.cpp deleted file mode 100644 index 9da457d3d..000000000 --- a/libbacktrace/BacktracePtrace.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2013 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 "BacktraceLog.h" -#include "BacktracePtrace.h" - -#if !defined(__APPLE__) -static bool PtraceRead(pid_t tid, uint64_t addr, word_t* out_value) { - // ptrace() returns -1 and sets errno when the operation fails. - // To disambiguate -1 from a valid result, we clear errno beforehand. - errno = 0; - *out_value = ptrace(PTRACE_PEEKTEXT, tid, reinterpret_cast(addr), nullptr); - if (*out_value == static_cast(-1) && errno) { - return false; - } - return true; -} -#endif - -bool BacktracePtrace::ReadWord(uint64_t ptr, word_t* out_value) { -#if defined(__APPLE__) - BACK_LOGW("MacOS does not support reading from another pid."); - return false; -#else - if (!VerifyReadWordArgs(ptr, out_value)) { - return false; - } - - backtrace_map_t map; - FillInMap(ptr, &map); - if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) { - return false; - } - - return PtraceRead(Tid(), ptr, out_value); -#endif -} - -size_t BacktracePtrace::Read(uint64_t addr, uint8_t* buffer, size_t bytes) { -#if defined(__APPLE__) - BACK_LOGW("MacOS does not support reading from another pid."); - return 0; -#else - backtrace_map_t map; - FillInMap(addr, &map); - if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) { - return 0; - } - - bytes = MIN(map.end - addr, bytes); - size_t bytes_read = 0; - word_t data_word; - size_t align_bytes = addr & (sizeof(word_t) - 1); - if (align_bytes != 0) { - if (!PtraceRead(Tid(), addr & ~(sizeof(word_t) - 1), &data_word)) { - return 0; - } - size_t copy_bytes = MIN(sizeof(word_t) - align_bytes, bytes); - memcpy(buffer, reinterpret_cast(&data_word) + align_bytes, copy_bytes); - addr += copy_bytes; - buffer += copy_bytes; - bytes -= copy_bytes; - bytes_read += copy_bytes; - } - - size_t num_words = bytes / sizeof(word_t); - for (size_t i = 0; i < num_words; i++) { - if (!PtraceRead(Tid(), addr, &data_word)) { - return bytes_read; - } - memcpy(buffer, &data_word, sizeof(word_t)); - buffer += sizeof(word_t); - addr += sizeof(word_t); - bytes_read += sizeof(word_t); - } - - size_t left_over = bytes & (sizeof(word_t) - 1); - if (left_over) { - if (!PtraceRead(Tid(), addr, &data_word)) { - return bytes_read; - } - memcpy(buffer, &data_word, left_over); - bytes_read += left_over; - } - return bytes_read; -#endif -} diff --git a/libbacktrace/BacktracePtrace.h b/libbacktrace/BacktracePtrace.h deleted file mode 100644 index 1ae3adf55..000000000 --- a/libbacktrace/BacktracePtrace.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 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 _LIBBACKTRACE_BACKTRACE_PTRACE_H -#define _LIBBACKTRACE_BACKTRACE_PTRACE_H - -#include -#include - -#include - -class BacktraceMap; - -class BacktracePtrace : public Backtrace { - public: - BacktracePtrace(pid_t pid, pid_t tid, BacktraceMap* map) : Backtrace(pid, tid, map) {} - virtual ~BacktracePtrace() {} - - size_t Read(uint64_t addr, uint8_t* buffer, size_t bytes) override; - - bool ReadWord(uint64_t ptr, word_t* out_value) override; -}; - -#endif // _LIBBACKTRACE_BACKTRACE_PTRACE_H diff --git a/libbacktrace/BacktraceTest.h b/libbacktrace/BacktraceTest.h deleted file mode 100644 index c38af0498..000000000 --- a/libbacktrace/BacktraceTest.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2013 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 _LIBBACKTRACE_BACKTRACE_TEST_H -#define _LIBBACKTRACE_BACKTRACE_TEST_H - -#include - -#include - -class BacktraceTest : public ::testing::Test { - protected: - static void SetUpTestCase() { - dl_handle_ = dlopen("libbacktrace_test.so", RTLD_NOW | RTLD_LOCAL); - - test_level_one_ = reinterpret_cast( - dlsym(dl_handle_, "test_level_one")); - - test_level_two_ = reinterpret_cast( - dlsym(dl_handle_, "test_level_two")); - - test_level_three_ = reinterpret_cast( - dlsym(dl_handle_, "test_level_three")); - - test_level_four_ = reinterpret_cast( - dlsym(dl_handle_, "test_level_four")); - - test_recursive_call_ = reinterpret_cast( - dlsym(dl_handle_, "test_recursive_call")); - - test_get_context_and_wait_ = reinterpret_cast( - dlsym(dl_handle_, "test_get_context_and_wait")); - - test_signal_action_ = - reinterpret_cast(dlsym(dl_handle_, "test_signal_action")); - - test_signal_handler_ = - reinterpret_cast(dlsym(dl_handle_, "test_signal_handler")); - } - - void SetUp() override { - ASSERT_TRUE(dl_handle_ != nullptr); - ASSERT_TRUE(test_level_one_ != nullptr); - ASSERT_TRUE(test_level_two_ != nullptr); - ASSERT_TRUE(test_level_three_ != nullptr); - ASSERT_TRUE(test_level_four_ != nullptr); - ASSERT_TRUE(test_recursive_call_ != nullptr); - ASSERT_TRUE(test_get_context_and_wait_ != nullptr); - ASSERT_TRUE(test_signal_action_ != nullptr); - ASSERT_TRUE(test_signal_handler_ != nullptr); - } - - public: - static void* dl_handle_; - static int (*test_level_one_)(int, int, int, int, void (*)(void*), void*); - static int (*test_level_two_)(int, int, int, int, void (*)(void*), void*); - static int (*test_level_three_)(int, int, int, int, void (*)(void*), void*); - static int (*test_level_four_)(int, int, int, int, void (*)(void*), void*); - static int (*test_recursive_call_)(int, void (*)(void*), void*); - static void (*test_get_context_and_wait_)(void*, volatile int*); - static void (*test_signal_action_)(int, siginfo_t*, void*); - static void (*test_signal_handler_)(int); -}; - -#endif // _LIBBACKTRACE_BACKTRACE_TEST_H diff --git a/libbacktrace/OWNERS b/libbacktrace/OWNERS deleted file mode 100644 index bfeedca0e..000000000 --- a/libbacktrace/OWNERS +++ /dev/null @@ -1,2 +0,0 @@ -cferris@google.com -jmgao@google.com diff --git a/libbacktrace/ThreadEntry.cpp b/libbacktrace/ThreadEntry.cpp deleted file mode 100644 index 9bd59e4a2..000000000 --- a/libbacktrace/ThreadEntry.cpp +++ /dev/null @@ -1,131 +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 "BacktraceAsyncSafeLog.h" -#include "ThreadEntry.h" - -// Initialize static member variables. -ThreadEntry* ThreadEntry::list_ = nullptr; -pthread_mutex_t ThreadEntry::list_mutex_ = PTHREAD_MUTEX_INITIALIZER; - -// Assumes that ThreadEntry::list_mutex_ has already been locked before -// creating a ThreadEntry object. -ThreadEntry::ThreadEntry(pid_t pid, pid_t tid) - : pid_(pid), tid_(tid), ref_count_(1), mutex_(PTHREAD_MUTEX_INITIALIZER), - wait_mutex_(PTHREAD_MUTEX_INITIALIZER), wait_value_(0), - next_(ThreadEntry::list_), prev_(nullptr) { - pthread_condattr_t attr; - pthread_condattr_init(&attr); - pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); - pthread_cond_init(&wait_cond_, &attr); - - // Add ourselves to the list. - if (ThreadEntry::list_) { - ThreadEntry::list_->prev_ = this; - } - ThreadEntry::list_ = this; -} - -ThreadEntry* ThreadEntry::Get(pid_t pid, pid_t tid, bool create) { - pthread_mutex_lock(&ThreadEntry::list_mutex_); - ThreadEntry* entry = list_; - while (entry != nullptr) { - if (entry->Match(pid, tid)) { - break; - } - entry = entry->next_; - } - - if (!entry) { - if (create) { - entry = new ThreadEntry(pid, tid); - } - } else { - entry->ref_count_++; - } - pthread_mutex_unlock(&ThreadEntry::list_mutex_); - - return entry; -} - -void ThreadEntry::Remove(ThreadEntry* entry) { - entry->Unlock(); - - pthread_mutex_lock(&ThreadEntry::list_mutex_); - if (--entry->ref_count_ == 0) { - delete entry; - } - pthread_mutex_unlock(&ThreadEntry::list_mutex_); -} - -// Assumes that ThreadEntry::list_mutex_ has already been locked before -// deleting a ThreadEntry object. -ThreadEntry::~ThreadEntry() { - if (list_ == this) { - list_ = next_; - } else { - if (next_) { - next_->prev_ = prev_; - } - prev_->next_ = next_; - } - - next_ = nullptr; - prev_ = nullptr; - - pthread_cond_destroy(&wait_cond_); -} - -bool ThreadEntry::Wait(int value) { - timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - ts.tv_sec += 5; - - bool wait_completed = true; - pthread_mutex_lock(&wait_mutex_); - while (wait_value_ != value) { - int ret = pthread_cond_timedwait(&wait_cond_, &wait_mutex_, &ts); - if (ret != 0) { - BACK_ASYNC_SAFE_LOGW("pthread_cond_timedwait for value %d failed: %s", value, strerror(ret)); - wait_completed = false; - break; - } - } - pthread_mutex_unlock(&wait_mutex_); - - return wait_completed; -} - -void ThreadEntry::Wake() { - pthread_mutex_lock(&wait_mutex_); - wait_value_++; - pthread_mutex_unlock(&wait_mutex_); - - pthread_cond_signal(&wait_cond_); -} - -void ThreadEntry::CopyUcontextFromSigcontext(void* sigcontext) { - ucontext_t* ucontext = reinterpret_cast(sigcontext); - // The only thing the unwinder cares about is the mcontext data. - memcpy(&ucontext_.uc_mcontext, &ucontext->uc_mcontext, sizeof(ucontext->uc_mcontext)); -} diff --git a/libbacktrace/ThreadEntry.h b/libbacktrace/ThreadEntry.h deleted file mode 100644 index caa549715..000000000 --- a/libbacktrace/ThreadEntry.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2013 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 _LIBBACKTRACE_THREAD_ENTRY_H -#define _LIBBACKTRACE_THREAD_ENTRY_H - -#include -#include -#include - -class ThreadEntry { - public: - static ThreadEntry* Get(pid_t pid, pid_t tid, bool create = true); - - static void Remove(ThreadEntry* entry); - - void Wake(); - - bool Wait(int); - - void CopyUcontextFromSigcontext(void*); - - inline void Lock() { - pthread_mutex_lock(&mutex_); - - // Always reset the wait value since this could be the first or nth - // time this entry is locked. - wait_value_ = 0; - } - - inline void Unlock() { - pthread_mutex_unlock(&mutex_); - } - - inline ucontext_t* GetUcontext() { return &ucontext_; } - - private: - ThreadEntry(pid_t pid, pid_t tid); - ~ThreadEntry(); - - bool Match(pid_t chk_pid, pid_t chk_tid) { return (chk_pid == pid_ && chk_tid == tid_); } - - pid_t pid_; - pid_t tid_; - int ref_count_; - pthread_mutex_t mutex_; - pthread_mutex_t wait_mutex_; - pthread_cond_t wait_cond_; - int wait_value_; - ThreadEntry* next_; - ThreadEntry* prev_; - ucontext_t ucontext_; - - static ThreadEntry* list_; - static pthread_mutex_t list_mutex_; -}; - -#endif // _LIBBACKTRACE_THREAD_ENTRY_H diff --git a/libbacktrace/UnwindMap.cpp b/libbacktrace/UnwindMap.cpp deleted file mode 100644 index 798c769c8..000000000 --- a/libbacktrace/UnwindMap.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2014 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 "BacktraceLog.h" -#include "UnwindMap.h" - -//------------------------------------------------------------------------- -// libunwind has a single shared address space for the current process -// aka local. If multiple maps are created for the current pid, then -// only update the local address space once, and keep a reference count -// of maps using the same map cursor. -//------------------------------------------------------------------------- -UnwindMap::UnwindMap(pid_t pid) : BacktraceMap(pid) { - unw_map_cursor_clear(&map_cursor_); -} - -UnwindMapRemote::UnwindMapRemote(pid_t pid) : UnwindMap(pid) { -} - -UnwindMapRemote::~UnwindMapRemote() { - unw_map_cursor_destroy(&map_cursor_); - unw_map_cursor_clear(&map_cursor_); -} - -bool UnwindMapRemote::GenerateMap() { - // Use the map_cursor information to construct the BacktraceMap data - // rather than reparsing /proc/self/maps. - unw_map_cursor_reset(&map_cursor_); - - unw_map_t unw_map; - while (unw_map_cursor_get_next(&map_cursor_, &unw_map)) { - backtrace_map_t map; - - map.start = unw_map.start; - map.end = unw_map.end; - map.offset = unw_map.offset; - map.load_bias = unw_map.load_base; - map.flags = unw_map.flags; - map.name = unw_map.path; - - // The maps are in descending order, but we want them in ascending order. - maps_.push_front(map); - } - - return true; -} - -bool UnwindMapRemote::Build() { - return (unw_map_cursor_create(&map_cursor_, pid_) == 0) && GenerateMap(); -} - -UnwindMapLocal::UnwindMapLocal() : UnwindMap(getpid()), map_created_(false) { - pthread_rwlock_init(&map_lock_, nullptr); -} - -UnwindMapLocal::~UnwindMapLocal() { - if (map_created_) { - unw_map_local_destroy(); - unw_map_cursor_clear(&map_cursor_); - } -} - -bool UnwindMapLocal::GenerateMap() { - // Lock so that multiple threads cannot modify the maps data at the - // same time. - pthread_rwlock_wrlock(&map_lock_); - - // It's possible for the map to be regenerated while this loop is occurring. - // If that happens, get the map again, but only try at most three times - // before giving up. - bool generated = false; - for (int i = 0; i < 3; i++) { - maps_.clear(); - - // Save the map data retrieved so we can tell if it changes. - unw_map_local_cursor_get(&map_cursor_); - - unw_map_t unw_map; - int ret; - while ((ret = unw_map_local_cursor_get_next(&map_cursor_, &unw_map)) > 0) { - backtrace_map_t map; - - map.start = unw_map.start; - map.end = unw_map.end; - map.offset = unw_map.offset; - map.load_bias = unw_map.load_base; - map.flags = unw_map.flags; - map.name = unw_map.path; - - free(unw_map.path); - - // The maps are in descending order, but we want them in ascending order. - maps_.push_front(map); - } - // Check to see if the map changed while getting the data. - if (ret != -UNW_EINVAL) { - generated = true; - break; - } - } - - pthread_rwlock_unlock(&map_lock_); - - if (!generated) { - BACK_LOGW("Unable to generate the map."); - } - return generated; -} - -bool UnwindMapLocal::Build() { - return (map_created_ = (unw_map_local_create() == 0)) && GenerateMap();; -} - -void UnwindMapLocal::FillIn(uint64_t addr, backtrace_map_t* map) { - BacktraceMap::FillIn(addr, map); - if (!IsValid(*map)) { - // Check to see if the underlying map changed and regenerate the map - // if it did. - if (unw_map_local_cursor_valid(&map_cursor_) < 0) { - if (GenerateMap()) { - BacktraceMap::FillIn(addr, map); - } - } - } -} diff --git a/libbacktrace/UnwindMap.h b/libbacktrace/UnwindMap.h deleted file mode 100644 index 15544e82b..000000000 --- a/libbacktrace/UnwindMap.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2014 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 _LIBBACKTRACE_UNWIND_MAP_H -#define _LIBBACKTRACE_UNWIND_MAP_H - -#include -#include -#include - -#include - -// The unw_map_cursor_t structure is different depending on whether it is -// the local or remote version. In order to get the correct version, include -// libunwind.h first then this header. - -class UnwindMap : public BacktraceMap { - public: - explicit UnwindMap(pid_t pid); - - unw_map_cursor_t* GetMapCursor() { return &map_cursor_; } - - protected: - unw_map_cursor_t map_cursor_; -}; - -class UnwindMapRemote : public UnwindMap { - public: - explicit UnwindMapRemote(pid_t pid); - virtual ~UnwindMapRemote(); - - bool Build() override; - - private: - bool GenerateMap(); -}; - -class UnwindMapLocal : public UnwindMap { - public: - UnwindMapLocal(); - virtual ~UnwindMapLocal(); - - bool Build() override; - - void FillIn(uint64_t addr, backtrace_map_t* map) override; - - void LockIterator() override { pthread_rwlock_rdlock(&map_lock_); } - void UnlockIterator() override { pthread_rwlock_unlock(&map_lock_); } - - private: - bool GenerateMap(); - - bool map_created_; - - pthread_rwlock_t map_lock_; -}; - -#endif // _LIBBACKTRACE_UNWIND_MAP_H diff --git a/libbacktrace/UnwindStack.cpp b/libbacktrace/UnwindStack.cpp deleted file mode 100644 index 82ff21c09..000000000 --- a/libbacktrace/UnwindStack.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (C) 2017 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. - */ - -#define _GNU_SOURCE 1 -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#if !defined(NO_LIBDEXFILE_SUPPORT) -#include -#endif -#include - -#include "BacktraceLog.h" -#include "UnwindStack.h" -#include "UnwindStackMap.h" - -extern "C" char* __cxa_demangle(const char*, char*, size_t*, int*); - -bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map, - std::vector* frames, size_t num_ignore_frames, - std::vector* skip_names, BacktraceUnwindError* error) { - UnwindStackMap* stack_map = reinterpret_cast(back_map); - auto process_memory = stack_map->process_memory(); - unwindstack::Unwinder unwinder(MAX_BACKTRACE_FRAMES + num_ignore_frames, stack_map->stack_maps(), - regs, stack_map->process_memory()); - unwinder.SetResolveNames(stack_map->ResolveNames()); - stack_map->SetArch(regs->Arch()); - if (stack_map->GetJitDebug() != nullptr) { - unwinder.SetJitDebug(stack_map->GetJitDebug()); - } -#if !defined(NO_LIBDEXFILE_SUPPORT) - if (stack_map->GetDexFiles() != nullptr) { - unwinder.SetDexFiles(stack_map->GetDexFiles()); - } -#endif - unwinder.Unwind(skip_names, &stack_map->GetSuffixesToIgnore()); - if (error != nullptr) { - switch (unwinder.LastErrorCode()) { - case unwindstack::ERROR_NONE: - error->error_code = BACKTRACE_UNWIND_NO_ERROR; - break; - - case unwindstack::ERROR_MEMORY_INVALID: - error->error_code = BACKTRACE_UNWIND_ERROR_ACCESS_MEM_FAILED; - error->error_info.addr = unwinder.LastErrorAddress(); - break; - - case unwindstack::ERROR_UNWIND_INFO: - error->error_code = BACKTRACE_UNWIND_ERROR_UNWIND_INFO; - break; - - case unwindstack::ERROR_UNSUPPORTED: - error->error_code = BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION; - break; - - case unwindstack::ERROR_INVALID_MAP: - error->error_code = BACKTRACE_UNWIND_ERROR_MAP_MISSING; - break; - - case unwindstack::ERROR_MAX_FRAMES_EXCEEDED: - error->error_code = BACKTRACE_UNWIND_ERROR_EXCEED_MAX_FRAMES_LIMIT; - break; - - case unwindstack::ERROR_REPEATED_FRAME: - error->error_code = BACKTRACE_UNWIND_ERROR_REPEATED_FRAME; - break; - - case unwindstack::ERROR_INVALID_ELF: - error->error_code = BACKTRACE_UNWIND_ERROR_INVALID_ELF; - break; - } - } - - if (num_ignore_frames >= unwinder.NumFrames()) { - frames->resize(0); - return true; - } - - auto unwinder_frames = unwinder.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]; - - backtrace_frame_data_t* back_frame = &frames->at(cur_frame); - - back_frame->num = cur_frame++; - - back_frame->rel_pc = frame->rel_pc; - back_frame->pc = frame->pc; - back_frame->sp = frame->sp; - - char* demangled_name = __cxa_demangle(frame->function_name.c_str(), nullptr, nullptr, nullptr); - if (demangled_name != nullptr) { - back_frame->func_name = demangled_name; - free(demangled_name); - } else { - back_frame->func_name = frame->function_name; - } - back_frame->func_offset = frame->function_offset; - - back_frame->map.name = frame->map_name; - back_frame->map.start = frame->map_start; - back_frame->map.end = frame->map_end; - back_frame->map.offset = frame->map_elf_start_offset; - back_frame->map.load_bias = frame->map_load_bias; - back_frame->map.flags = frame->map_flags; - } - - return true; -} - -UnwindStackCurrent::UnwindStackCurrent(pid_t pid, pid_t tid, BacktraceMap* map) - : BacktraceCurrent(pid, tid, map) {} - -std::string UnwindStackCurrent::GetFunctionNameRaw(uint64_t pc, uint64_t* offset) { - return GetMap()->GetFunctionName(pc, offset); -} - -bool UnwindStackCurrent::UnwindFromContext(size_t num_ignore_frames, void* ucontext) { - std::unique_ptr regs; - if (ucontext == nullptr) { - regs.reset(unwindstack::Regs::CreateFromLocal()); - // Fill in the registers from this function. Do it here to avoid - // one extra function call appearing in the unwind. - unwindstack::RegsGetLocal(regs.get()); - } else { - regs.reset(unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(), ucontext)); - } - - std::vector skip_names{"libunwindstack.so", "libbacktrace.so"}; - if (!skip_frames_) { - skip_names.clear(); - } - return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames, &skip_names, &error_); -} - -UnwindStackPtrace::UnwindStackPtrace(pid_t pid, pid_t tid, BacktraceMap* map) - : BacktracePtrace(pid, tid, map), memory_(unwindstack::Memory::CreateProcessMemory(pid)) {} - -std::string UnwindStackPtrace::GetFunctionNameRaw(uint64_t pc, uint64_t* offset) { - return GetMap()->GetFunctionName(pc, offset); -} - -bool UnwindStackPtrace::Unwind(size_t num_ignore_frames, void* context) { - std::unique_ptr regs; - if (context == nullptr) { - regs.reset(unwindstack::Regs::RemoteGet(Tid())); - } else { - regs.reset(unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(), context)); - } - - return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames, nullptr, &error_); -} - -size_t UnwindStackPtrace::Read(uint64_t addr, uint8_t* buffer, size_t bytes) { -#if defined(__aarch64__) - // Tagged pointer after Android R would lead top byte to have random values - // https://source.android.com/devices/tech/debug/tagged-pointers - addr &= (1ULL << 56) - 1; -#endif - return memory_->Read(addr, buffer, bytes); -} diff --git a/libbacktrace/UnwindStack.h b/libbacktrace/UnwindStack.h deleted file mode 100644 index 47f6757d8..000000000 --- a/libbacktrace/UnwindStack.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2017 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 _LIBBACKTRACE_UNWIND_STACK_H -#define _LIBBACKTRACE_UNWIND_STACK_H - -#include - -#include -#include - -#include -#include - -#include "BacktraceCurrent.h" -#include "BacktracePtrace.h" - -class UnwindStackCurrent : public BacktraceCurrent { - public: - UnwindStackCurrent(pid_t pid, pid_t tid, BacktraceMap* map); - virtual ~UnwindStackCurrent() = default; - - std::string GetFunctionNameRaw(uint64_t pc, uint64_t* offset) override; - - bool UnwindFromContext(size_t num_ignore_frames, void* ucontext) override; -}; - -class UnwindStackPtrace : public BacktracePtrace { - public: - UnwindStackPtrace(pid_t pid, pid_t tid, BacktraceMap* map); - virtual ~UnwindStackPtrace() = default; - - 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; - - private: - std::shared_ptr memory_; -}; - -#endif // _LIBBACKTRACE_UNWIND_STACK_H diff --git a/libbacktrace/UnwindStackMap.cpp b/libbacktrace/UnwindStackMap.cpp deleted file mode 100644 index aa0b17c99..000000000 --- a/libbacktrace/UnwindStackMap.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2017 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 "UnwindStackMap.h" - -//------------------------------------------------------------------------- -UnwindStackMap::UnwindStackMap(pid_t pid) : BacktraceMap(pid) {} - -bool UnwindStackMap::Build() { - if (pid_ == 0) { - pid_ = getpid(); - stack_maps_.reset(new unwindstack::LocalMaps); - } else { - stack_maps_.reset(new unwindstack::RemoteMaps(pid_)); - } - - // Create the process memory object. - process_memory_ = unwindstack::Memory::CreateProcessMemory(pid_); - - // Create a JitDebug object for getting jit unwind information. - std::vector 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_, search_libs_)); -#endif - - if (!stack_maps_->Parse()) { - return false; - } - - // Iterate through the maps and fill in the backtrace_map_t structure. - for (const auto& map_info : *stack_maps_) { - backtrace_map_t map; - map.start = map_info->start; - map.end = map_info->end; - map.offset = map_info->offset; - // Set to -1 so that it is demand loaded. - map.load_bias = static_cast(-1); - map.flags = map_info->flags; - map.name = map_info->name; - - maps_.push_back(map); - } - - return true; -} - -void UnwindStackMap::FillIn(uint64_t addr, backtrace_map_t* map) { - BacktraceMap::FillIn(addr, map); - if (map->load_bias != static_cast(-1)) { - return; - } - - // Fill in the load_bias. - unwindstack::MapInfo* map_info = stack_maps_->Find(addr); - if (map_info == nullptr) { - return; - } - map->load_bias = map_info->GetLoadBias(process_memory_); -} - -uint64_t UnwindStackMap::GetLoadBias(size_t index) { - if (index >= stack_maps_->Total()) { - return 0; - } - - unwindstack::MapInfo* map_info = stack_maps_->Get(index); - if (map_info == nullptr) { - return 0; - } - return map_info->GetLoadBias(process_memory_); -} - -std::string UnwindStackMap::GetFunctionName(uint64_t pc, uint64_t* offset) { - *offset = 0; - unwindstack::Maps* maps = stack_maps(); - - // Get the map for this - unwindstack::MapInfo* map_info = maps->Find(pc); - if (map_info == nullptr || map_info->flags & PROT_DEVICE_MAP) { - return ""; - } - - if (arch_ == unwindstack::ARCH_UNKNOWN) { - if (pid_ == getpid()) { - arch_ = unwindstack::Regs::CurrentArch(); - } else { - // Create a remote regs, to figure out the architecture. - std::unique_ptr regs(unwindstack::Regs::RemoteGet(pid_)); - arch_ = regs->Arch(); - } - } - - unwindstack::Elf* elf = map_info->GetElf(process_memory(), arch_); - - std::string name; - uint64_t func_offset; - if (!elf->GetFunctionName(elf->GetRelPc(pc, map_info), &name, &func_offset)) { - return ""; - } - *offset = func_offset; - return name; -} - -std::shared_ptr UnwindStackMap::GetProcessMemory() { - return process_memory_; -} - -//------------------------------------------------------------------------- -// BacktraceMap create function. -//------------------------------------------------------------------------- -BacktraceMap* BacktraceMap::Create(pid_t pid, bool uncached) { - BacktraceMap* map; - - if (uncached) { - // Force use of the base class to parse the maps when this call is made. - map = new BacktraceMap(pid); - } else if (pid == getpid()) { - map = new UnwindStackMap(0); - } else { - map = new UnwindStackMap(pid); - } - if (!map->Build()) { - delete map; - return nullptr; - } - return map; -} diff --git a/libbacktrace/UnwindStackMap.h b/libbacktrace/UnwindStackMap.h deleted file mode 100644 index f0e7d8b78..000000000 --- a/libbacktrace/UnwindStackMap.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2017 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 _LIBBACKTRACE_UNWINDSTACK_MAP_H -#define _LIBBACKTRACE_UNWINDSTACK_MAP_H - -#include -#include - -#include -#include -#include -#include - -#include -#include -#if !defined(NO_LIBDEXFILE_SUPPORT) -#include -#endif -#include -#include -#include -#include - -// Forward declarations. -class UnwindDexFile; - -class UnwindStackMap : public BacktraceMap { - public: - explicit UnwindStackMap(pid_t pid); - ~UnwindStackMap() = default; - - bool Build() override; - - void FillIn(uint64_t addr, backtrace_map_t* map) override; - - virtual std::string GetFunctionName(uint64_t pc, uint64_t* offset) override; - virtual std::shared_ptr GetProcessMemory() override final; - - unwindstack::Maps* stack_maps() { return stack_maps_.get(); } - - const std::shared_ptr& process_memory() { return process_memory_; } - - unwindstack::JitDebug* GetJitDebug() { return jit_debug_.get(); } - -#if !defined(NO_LIBDEXFILE_SUPPORT) - unwindstack::DexFiles* GetDexFiles() { return dex_files_.get(); } -#endif - - void SetArch(unwindstack::ArchEnum arch) { arch_ = arch; } - - protected: - uint64_t GetLoadBias(size_t index) override; - - std::unique_ptr stack_maps_; - std::shared_ptr process_memory_; - std::unique_ptr jit_debug_; -#if !defined(NO_LIBDEXFILE_SUPPORT) - std::unique_ptr dex_files_; -#endif - - unwindstack::ArchEnum arch_ = unwindstack::ARCH_UNKNOWN; -}; - -#endif // _LIBBACKTRACE_UNWINDSTACK_MAP_H diff --git a/libbacktrace/backtrace_benchmarks.cpp b/libbacktrace/backtrace_benchmarks.cpp deleted file mode 100644 index a93a25e90..000000000 --- a/libbacktrace/backtrace_benchmarks.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2017 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 - -constexpr size_t kNumMaps = 2000; - -static bool CountMaps(pid_t pid, size_t* num_maps) { - // Minimize the calls that might allocate memory. If too much memory - // gets allocated, then this routine will add extra maps and the next - // call will fail to get the same number of maps as before. - int fd = - open((std::string("/proc/") + std::to_string(pid) + "/maps").c_str(), O_RDONLY | O_CLOEXEC); - if (fd == -1) { - fprintf(stderr, "Cannot open map file for pid %d: %s\n", pid, strerror(errno)); - return false; - } - *num_maps = 0; - while (true) { - char buffer[2048]; - ssize_t bytes = read(fd, buffer, sizeof(buffer)); - if (bytes <= 0) { - break; - } - // Count the '\n'. - for (size_t i = 0; i < static_cast(bytes); i++) { - if (buffer[i] == '\n') { - ++*num_maps; - } - } - } - - close(fd); - return true; -} - -static void CreateMap(benchmark::State& state, BacktraceMap* (*map_func)(pid_t, bool)) { - // Create a remote process so that the map data is exactly the same. - // Also, so that we can create a set number of maps. - pid_t pid; - if ((pid = fork()) == 0) { - size_t num_maps; - if (!CountMaps(getpid(), &num_maps)) { - exit(1); - } - // Create uniquely named maps. - std::vector maps; - for (size_t i = num_maps; i < kNumMaps; i++) { - int flags = PROT_READ | PROT_WRITE; - // Alternate page type to make sure a map entry is added for each call. - if ((i % 2) == 0) { - flags |= PROT_EXEC; - } - void* memory = mmap(nullptr, PAGE_SIZE, flags, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if (memory == MAP_FAILED) { - fprintf(stderr, "Failed to create map: %s\n", strerror(errno)); - exit(1); - } - memset(memory, 0x1, PAGE_SIZE); -#if defined(PR_SET_VMA) - if (prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, memory, PAGE_SIZE, "test_map") == -1) { - fprintf(stderr, "Failed: %s\n", strerror(errno)); - } -#endif - maps.push_back(memory); - } - - if (!CountMaps(getpid(), &num_maps)) { - exit(1); - } - - if (num_maps < kNumMaps) { - fprintf(stderr, "Maps set incorrectly: %zu found, %zu expected at least.\n", num_maps, - kNumMaps); - std::string str; - android::base::ReadFileToString("/proc/self/maps", &str); - fprintf(stderr, "%s\n", str.c_str()); - exit(1); - } - - // Wait for an hour at most. - sleep(3600); - exit(1); - } else if (pid < 0) { - fprintf(stderr, "Fork failed: %s\n", strerror(errno)); - return; - } - - size_t num_maps = 0; - for (size_t i = 0; i < 2000; i++) { - if (CountMaps(pid, &num_maps) && num_maps >= kNumMaps) { - break; - } - usleep(1000); - } - if (num_maps < kNumMaps) { - fprintf(stderr, "Timed out waiting for the number of maps available: %zu\n", num_maps); - return; - } - - while (state.KeepRunning()) { - BacktraceMap* map = map_func(pid, false); - if (map == nullptr) { - fprintf(stderr, "Failed to create map\n"); - return; - } - delete map; - } - - kill(pid, SIGKILL); - waitpid(pid, nullptr, 0); -} - -static void BM_create_map(benchmark::State& state) { - CreateMap(state, BacktraceMap::Create); -} -BENCHMARK(BM_create_map); - -using BacktraceCreateFn = decltype(Backtrace::Create); - -static void CreateBacktrace(benchmark::State& state, BacktraceMap* map, BacktraceCreateFn fn) { - while (state.KeepRunning()) { - std::unique_ptr backtrace(fn(getpid(), android::base::GetThreadId(), map)); - backtrace->Unwind(0); - } -} - -static void BM_create_backtrace(benchmark::State& state) { - std::unique_ptr backtrace_map(BacktraceMap::Create(getpid())); - CreateBacktrace(state, backtrace_map.get(), Backtrace::Create); -} -BENCHMARK(BM_create_backtrace); - -BENCHMARK_MAIN(); diff --git a/libbacktrace/backtrace_read_benchmarks.cpp b/libbacktrace/backtrace_read_benchmarks.cpp deleted file mode 100644 index 6a688b0c2..000000000 --- a/libbacktrace/backtrace_read_benchmarks.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2017 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 - -#define AT_COMMON_SIZES Arg(1)->Arg(4)->Arg(8)->Arg(16)->Arg(100)->Arg(200)->Arg(500)->Arg(1024) - -static void Attach(pid_t pid) { - if (ptrace(PTRACE_ATTACH, pid, 0, 0) == -1) { - perror("Failed to attach"); - abort(); - } - - siginfo_t si; - // Wait for up to 5 seconds. - for (size_t i = 0; i < 5000; i++) { - if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) { - return; - } - usleep(1000); - } - printf("Remote process failed to stop in five seconds.\n"); - abort(); -} - -class ScopedPidReaper { - public: - ScopedPidReaper(pid_t pid) : pid_(pid) {} - ~ScopedPidReaper() { - kill(pid_, SIGKILL); - waitpid(pid_, nullptr, 0); - } - - private: - pid_t pid_; -}; - -static size_t ProcessVmRead(pid_t pid, uint64_t remote_src, void* dst, size_t len) { - struct iovec dst_iov = { - .iov_base = dst, .iov_len = len, - }; - - struct iovec src_iov = { - .iov_base = reinterpret_cast(remote_src), .iov_len = len, - }; - - ssize_t rc = process_vm_readv(pid, &dst_iov, 1, &src_iov, 1, 0); - return rc == -1 ? 0 : rc; -} - -static bool PtraceReadLong(pid_t pid, uint64_t addr, long* value) { - // ptrace() returns -1 and sets errno when the operation fails. - // To disambiguate -1 from a valid result, we clear errno beforehand. - errno = 0; - *value = ptrace(PTRACE_PEEKTEXT, pid, reinterpret_cast(addr), nullptr); - if (*value == -1 && errno) { - return false; - } - return true; -} - -static size_t PtraceRead(pid_t pid, uint64_t addr, void* dst, size_t bytes) { - size_t bytes_read = 0; - long data; - for (size_t i = 0; i < bytes / sizeof(long); i++) { - if (!PtraceReadLong(pid, addr, &data)) { - return bytes_read; - } - memcpy(dst, &data, sizeof(long)); - dst = reinterpret_cast(reinterpret_cast(dst) + sizeof(long)); - addr += sizeof(long); - bytes_read += sizeof(long); - } - - size_t left_over = bytes & (sizeof(long) - 1); - if (left_over) { - if (!PtraceReadLong(pid, addr, &data)) { - return bytes_read; - } - memcpy(dst, &data, left_over); - bytes_read += left_over; - } - return bytes_read; -} - -static void CreateRemoteProcess(size_t size, void** map, pid_t* pid) { - *map = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if (*map == MAP_FAILED) { - perror("Can't allocate memory"); - abort(); - } - memset(*map, 0xaa, size); - - if ((*pid = fork()) == 0) { - for (volatile int i = 0;; i++) - ; - exit(1); - } - if (*pid < 0) { - perror("Failed to fork"); - abort(); - } - Attach(*pid); - // Don't need this map in the current process any more. - munmap(*map, size); -} - -static void BM_read_with_ptrace(benchmark::State& state) { - void* map; - pid_t pid; - CreateRemoteProcess(state.range(0), &map, &pid); - ScopedPidReaper reap(pid); - - std::vector read_buffer(state.range(0)); - uint64_t addr = reinterpret_cast(map); - while (state.KeepRunning()) { - if (PtraceRead(pid, addr, read_buffer.data(), read_buffer.size()) != read_buffer.size()) { - printf("Unexpected bad read.\n"); - abort(); - } - } - ptrace(PTRACE_DETACH, pid, 0, 0); -} -BENCHMARK(BM_read_with_ptrace)->AT_COMMON_SIZES; - -static void BM_read_with_process_vm_read(benchmark::State& state) { - void* map; - pid_t pid; - CreateRemoteProcess(state.range(0), &map, &pid); - ScopedPidReaper reap(pid); - - std::vector read_buffer(state.range(0)); - uint64_t addr = reinterpret_cast(map); - while (state.KeepRunning()) { - if (ProcessVmRead(pid, addr, read_buffer.data(), read_buffer.size()) != read_buffer.size()) { - printf("Unexpected bad read.\n"); - abort(); - } - } - ptrace(PTRACE_DETACH, pid, 0, 0); -} -BENCHMARK(BM_read_with_process_vm_read)->AT_COMMON_SIZES; - -static void BM_read_with_backtrace_object(benchmark::State& state) { - void* map; - pid_t pid; - CreateRemoteProcess(state.range(0), &map, &pid); - ScopedPidReaper reap(pid); - - std::unique_ptr backtrace(Backtrace::Create(pid, BACKTRACE_CURRENT_THREAD)); - if (backtrace.get() == nullptr) { - printf("Failed to create backtrace.\n"); - abort(); - } - - uint64_t addr = reinterpret_cast(map); - std::vector read_buffer(state.range(0)); - while (state.KeepRunning()) { - if (backtrace->Read(addr, read_buffer.data(), read_buffer.size()) != read_buffer.size()) { - printf("Unexpected bad read.\n"); - abort(); - } - } - ptrace(PTRACE_DETACH, pid, 0, 0); -} -BENCHMARK(BM_read_with_backtrace_object)->AT_COMMON_SIZES; diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp deleted file mode 100644 index cc32b6dc0..000000000 --- a/libbacktrace/backtrace_test.cpp +++ /dev/null @@ -1,1893 +0,0 @@ -/* - * Copyright (C) 2013 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. - */ - -#define _GNU_SOURCE 1 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -// For the THREAD_SIGNAL definition. -#include "BacktraceCurrent.h" -#include "BacktraceTest.h" -#include "backtrace_testlib.h" - -// Number of microseconds per milliseconds. -#define US_PER_MSEC 1000 - -// Number of nanoseconds in a second. -#define NS_PER_SEC 1000000000ULL - -// Number of simultaneous dumping operations to perform. -#define NUM_THREADS 40 - -// Number of simultaneous threads running in our forked process. -#define NUM_PTRACE_THREADS 5 - -// The list of shared libaries that make up the backtrace library. -static std::vector kBacktraceLibs{"libunwindstack.so", "libbacktrace.so"}; - -struct thread_t { - pid_t tid; - int32_t state; - pthread_t threadId; - void* data; -}; - -struct dump_thread_t { - thread_t thread; - BacktraceMap* map; - Backtrace* backtrace; - int32_t* now; - int32_t done; -}; - -typedef Backtrace* (*create_func_t)(pid_t, pid_t, BacktraceMap*); -typedef BacktraceMap* (*map_create_func_t)(pid_t, bool); - -static void VerifyLevelDump(Backtrace* backtrace, create_func_t create_func = nullptr, - map_create_func_t map_func = nullptr); -static void VerifyMaxDump(Backtrace* backtrace, create_func_t create_func = nullptr, - map_create_func_t map_func = nullptr); - -void* BacktraceTest::dl_handle_; -int (*BacktraceTest::test_level_one_)(int, int, int, int, void (*)(void*), void*); -int (*BacktraceTest::test_level_two_)(int, int, int, int, void (*)(void*), void*); -int (*BacktraceTest::test_level_three_)(int, int, int, int, void (*)(void*), void*); -int (*BacktraceTest::test_level_four_)(int, int, int, int, void (*)(void*), void*); -int (*BacktraceTest::test_recursive_call_)(int, void (*)(void*), void*); -void (*BacktraceTest::test_get_context_and_wait_)(void*, volatile int*); -void (*BacktraceTest::test_signal_action_)(int, siginfo_t*, void*); -void (*BacktraceTest::test_signal_handler_)(int); - -extern "C" bool GetInitialArgs(const char*** args, size_t* num_args) { - static const char* initial_args[] = {"--slow_threshold_ms=8000", "--deadline_threshold_ms=15000"}; - *args = initial_args; - *num_args = 2; - return true; -} - -static uint64_t NanoTime() { - struct timespec t = { 0, 0 }; - clock_gettime(CLOCK_MONOTONIC, &t); - return static_cast(t.tv_sec * NS_PER_SEC + t.tv_nsec); -} - -static std::string DumpFrames(Backtrace* backtrace) { - if (backtrace->NumFrames() == 0) { - return " No frames to dump.\n"; - } - - std::string frame; - for (size_t i = 0; i < backtrace->NumFrames(); i++) { - frame += " " + backtrace->FormatFrameData(i) + '\n'; - } - return frame; -} - -static void WaitForStop(pid_t pid) { - uint64_t start = NanoTime(); - - siginfo_t si; - while (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) < 0 && (errno == EINTR || errno == ESRCH)) { - if ((NanoTime() - start) > NS_PER_SEC) { - printf("The process did not get to a stopping point in 1 second.\n"); - break; - } - usleep(US_PER_MSEC); - } -} - -static void CreateRemoteProcess(pid_t* pid) { - if ((*pid = fork()) == 0) { - while (true) - ; - _exit(0); - } - ASSERT_NE(-1, *pid); - - ASSERT_TRUE(ptrace(PTRACE_ATTACH, *pid, 0, 0) == 0); - - // Wait for the process to get to a stopping point. - WaitForStop(*pid); -} - -static void FinishRemoteProcess(pid_t pid) { - ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0); - - kill(pid, SIGKILL); - ASSERT_EQ(waitpid(pid, nullptr, 0), pid); -} - -#if !defined(__ANDROID__) || defined(__arm__) -// On host and arm target we aren't guaranteed that we will terminate cleanly. -#define VERIFY_NO_ERROR(error_code) \ - ASSERT_TRUE(error_code == BACKTRACE_UNWIND_NO_ERROR || \ - error_code == BACKTRACE_UNWIND_ERROR_UNWIND_INFO || \ - error_code == BACKTRACE_UNWIND_ERROR_MAP_MISSING) \ - << "Unknown error code " << std::to_string(error_code); -#else -#define VERIFY_NO_ERROR(error_code) ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, error_code); -#endif - -static bool ReadyLevelBacktrace(Backtrace* backtrace) { - // See if test_level_four is in the backtrace. - bool found = false; - for (Backtrace::const_iterator it = backtrace->begin(); it != backtrace->end(); ++it) { - if (it->func_name == "test_level_four") { - found = true; - break; - } - } - - return found; -} - -static void VerifyLevelDump(Backtrace* backtrace, create_func_t, map_create_func_t) { - ASSERT_GT(backtrace->NumFrames(), static_cast(0)) - << DumpFrames(backtrace); - ASSERT_LT(backtrace->NumFrames(), static_cast(MAX_BACKTRACE_FRAMES)) - << DumpFrames(backtrace); - - // Look through the frames starting at the highest to find the - // frame we want. - size_t frame_num = 0; - for (size_t i = backtrace->NumFrames()-1; i > 2; i--) { - if (backtrace->GetFrame(i)->func_name == "test_level_one") { - frame_num = i; - break; - } - } - ASSERT_LT(static_cast(0), frame_num) << DumpFrames(backtrace); - ASSERT_LE(static_cast(3), frame_num) << DumpFrames(backtrace); - - ASSERT_EQ(backtrace->GetFrame(frame_num)->func_name, "test_level_one") - << DumpFrames(backtrace); - ASSERT_EQ(backtrace->GetFrame(frame_num-1)->func_name, "test_level_two") - << DumpFrames(backtrace); - ASSERT_EQ(backtrace->GetFrame(frame_num-2)->func_name, "test_level_three") - << DumpFrames(backtrace); - ASSERT_EQ(backtrace->GetFrame(frame_num-3)->func_name, "test_level_four") - << DumpFrames(backtrace); -} - -static void VerifyLevelBacktrace(void*) { - std::unique_ptr backtrace( - Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD)); - ASSERT_TRUE(backtrace.get() != nullptr); - ASSERT_TRUE(backtrace->Unwind(0)); - VERIFY_NO_ERROR(backtrace->GetError().error_code); - - VerifyLevelDump(backtrace.get()); -} - -static bool ReadyMaxBacktrace(Backtrace* backtrace) { - return (backtrace->NumFrames() == MAX_BACKTRACE_FRAMES); -} - -static void VerifyMaxDump(Backtrace* backtrace, create_func_t, map_create_func_t) { - ASSERT_EQ(backtrace->NumFrames(), static_cast(MAX_BACKTRACE_FRAMES)) - << DumpFrames(backtrace); - // Verify that the last frame is our recursive call. - ASSERT_EQ(backtrace->GetFrame(MAX_BACKTRACE_FRAMES-1)->func_name, "test_recursive_call") - << DumpFrames(backtrace); -} - -static void VerifyMaxBacktrace(void*) { - std::unique_ptr backtrace( - Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD)); - ASSERT_TRUE(backtrace.get() != nullptr); - ASSERT_TRUE(backtrace->Unwind(0)); - ASSERT_EQ(BACKTRACE_UNWIND_ERROR_EXCEED_MAX_FRAMES_LIMIT, backtrace->GetError().error_code); - - VerifyMaxDump(backtrace.get()); -} - -static void ThreadSetState(void* data) { - thread_t* thread = reinterpret_cast(data); - android_atomic_acquire_store(1, &thread->state); - volatile int i = 0; - while (thread->state) { - i++; - } -} - -static bool WaitForNonZero(int32_t* value, uint64_t seconds) { - uint64_t start = NanoTime(); - do { - if (android_atomic_acquire_load(value)) { - return true; - } - } while ((NanoTime() - start) < seconds * NS_PER_SEC); - return false; -} - -TEST_F(BacktraceTest, local_no_unwind_frames) { - // Verify that a local unwind does not include any frames within - // libunwind or libbacktrace. - std::unique_ptr backtrace(Backtrace::Create(getpid(), getpid())); - ASSERT_TRUE(backtrace.get() != nullptr); - ASSERT_TRUE(backtrace->Unwind(0)); - VERIFY_NO_ERROR(backtrace->GetError().error_code); - - ASSERT_TRUE(backtrace->NumFrames() != 0); - // None of the frames should be in the backtrace libraries. - for (const auto& frame : *backtrace ) { - if (BacktraceMap::IsValid(frame.map)) { - const std::string name = basename(frame.map.name.c_str()); - for (const auto& lib : kBacktraceLibs) { - ASSERT_TRUE(name != lib) << DumpFrames(backtrace.get()); - } - } - } -} - -TEST_F(BacktraceTest, local_unwind_frames) { - // Verify that a local unwind with the skip frames disabled does include - // frames within the backtrace libraries. - std::unique_ptr backtrace(Backtrace::Create(getpid(), getpid())); - ASSERT_TRUE(backtrace.get() != nullptr); - backtrace->SetSkipFrames(false); - ASSERT_TRUE(backtrace->Unwind(0)); - VERIFY_NO_ERROR(backtrace->GetError().error_code); - - ASSERT_TRUE(backtrace->NumFrames() != 0); - size_t first_frame_non_backtrace_lib = 0; - for (const auto& frame : *backtrace) { - if (BacktraceMap::IsValid(frame.map)) { - const std::string name = basename(frame.map.name.c_str()); - bool found = false; - for (const auto& lib : kBacktraceLibs) { - if (name == lib) { - found = true; - break; - } - } - if (!found) { - first_frame_non_backtrace_lib = frame.num; - break; - } - } - } - - ASSERT_NE(0U, first_frame_non_backtrace_lib) << "No frames found in backtrace libraries:\n" - << DumpFrames(backtrace.get()); -} - -TEST_F(BacktraceTest, local_trace) { - ASSERT_NE(test_level_one_(1, 2, 3, 4, VerifyLevelBacktrace, nullptr), 0); -} - -static void VerifyIgnoreFrames(Backtrace* bt_all, Backtrace* bt_ign1, Backtrace* bt_ign2, - const char* cur_proc) { - ASSERT_EQ(bt_all->NumFrames(), bt_ign1->NumFrames() + 1) << "All backtrace:\n" - << DumpFrames(bt_all) - << "Ignore 1 backtrace:\n" - << DumpFrames(bt_ign1); - ASSERT_EQ(bt_all->NumFrames(), bt_ign2->NumFrames() + 2) << "All backtrace:\n" - << DumpFrames(bt_all) - << "Ignore 2 backtrace:\n" - << DumpFrames(bt_ign2); - - // Check all of the frames are the same > the current frame. - bool check = (cur_proc == nullptr); - for (size_t i = 0; i < bt_ign2->NumFrames(); i++) { - if (check) { - EXPECT_EQ(bt_ign2->GetFrame(i)->pc, bt_ign1->GetFrame(i+1)->pc); - EXPECT_EQ(bt_ign2->GetFrame(i)->sp, bt_ign1->GetFrame(i+1)->sp); - EXPECT_EQ(bt_ign2->GetFrame(i)->stack_size, bt_ign1->GetFrame(i+1)->stack_size); - - EXPECT_EQ(bt_ign2->GetFrame(i)->pc, bt_all->GetFrame(i+2)->pc); - EXPECT_EQ(bt_ign2->GetFrame(i)->sp, bt_all->GetFrame(i+2)->sp); - EXPECT_EQ(bt_ign2->GetFrame(i)->stack_size, bt_all->GetFrame(i+2)->stack_size); - } - if (!check && bt_ign2->GetFrame(i)->func_name == cur_proc) { - check = true; - } - } -} - -static void VerifyLevelIgnoreFrames(void*) { - std::unique_ptr all( - Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD)); - ASSERT_TRUE(all.get() != nullptr); - ASSERT_TRUE(all->Unwind(0)); - VERIFY_NO_ERROR(all->GetError().error_code); - - std::unique_ptr ign1( - Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD)); - ASSERT_TRUE(ign1.get() != nullptr); - ASSERT_TRUE(ign1->Unwind(1)); - VERIFY_NO_ERROR(ign1->GetError().error_code); - - std::unique_ptr ign2( - Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD)); - ASSERT_TRUE(ign2.get() != nullptr); - ASSERT_TRUE(ign2->Unwind(2)); - VERIFY_NO_ERROR(ign2->GetError().error_code); - - VerifyIgnoreFrames(all.get(), ign1.get(), ign2.get(), "VerifyLevelIgnoreFrames"); -} - -TEST_F(BacktraceTest, local_trace_ignore_frames) { - ASSERT_NE(test_level_one_(1, 2, 3, 4, VerifyLevelIgnoreFrames, nullptr), 0); -} - -TEST_F(BacktraceTest, local_max_trace) { - ASSERT_NE(test_recursive_call_(MAX_BACKTRACE_FRAMES + 10, VerifyMaxBacktrace, nullptr), 0); -} - -static void VerifyProcTest(pid_t pid, pid_t tid, bool (*ReadyFunc)(Backtrace*), - void (*VerifyFunc)(Backtrace*, create_func_t, map_create_func_t), - create_func_t create_func, map_create_func_t map_create_func) { - pid_t ptrace_tid; - if (tid < 0) { - ptrace_tid = pid; - } else { - ptrace_tid = tid; - } - uint64_t start = NanoTime(); - bool verified = false; - std::string last_dump; - do { - usleep(US_PER_MSEC); - if (ptrace(PTRACE_ATTACH, ptrace_tid, 0, 0) == 0) { - // Wait for the process to get to a stopping point. - WaitForStop(ptrace_tid); - - std::unique_ptr map; - map.reset(map_create_func(pid, false)); - std::unique_ptr backtrace(create_func(pid, tid, map.get())); - ASSERT_TRUE(backtrace.get() != nullptr); - ASSERT_TRUE(backtrace->Unwind(0)); - if (ReadyFunc(backtrace.get())) { - VerifyFunc(backtrace.get(), create_func, map_create_func); - verified = true; - } else { - last_dump = DumpFrames(backtrace.get()); - } - - ASSERT_TRUE(ptrace(PTRACE_DETACH, ptrace_tid, 0, 0) == 0); - } - // If 5 seconds have passed, then we are done. - } while (!verified && (NanoTime() - start) <= 5 * NS_PER_SEC); - ASSERT_TRUE(verified) << "Last backtrace:\n" << last_dump; -} - -TEST_F(BacktraceTest, ptrace_trace) { - pid_t pid; - if ((pid = fork()) == 0) { - ASSERT_NE(test_level_one_(1, 2, 3, 4, nullptr, nullptr), 0); - _exit(1); - } - VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, ReadyLevelBacktrace, VerifyLevelDump, - Backtrace::Create, BacktraceMap::Create); - - kill(pid, SIGKILL); - int status; - ASSERT_EQ(waitpid(pid, &status, 0), pid); -} - -TEST_F(BacktraceTest, ptrace_max_trace) { - pid_t pid; - if ((pid = fork()) == 0) { - ASSERT_NE(test_recursive_call_(MAX_BACKTRACE_FRAMES + 10, nullptr, nullptr), 0); - _exit(1); - } - VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, ReadyMaxBacktrace, VerifyMaxDump, Backtrace::Create, - BacktraceMap::Create); - - kill(pid, SIGKILL); - int status; - ASSERT_EQ(waitpid(pid, &status, 0), pid); -} - -static void VerifyProcessIgnoreFrames(Backtrace* bt_all, create_func_t create_func, - map_create_func_t map_create_func) { - std::unique_ptr map(map_create_func(bt_all->Pid(), false)); - std::unique_ptr ign1(create_func(bt_all->Pid(), BACKTRACE_CURRENT_THREAD, map.get())); - ASSERT_TRUE(ign1.get() != nullptr); - ASSERT_TRUE(ign1->Unwind(1)); - VERIFY_NO_ERROR(ign1->GetError().error_code); - - std::unique_ptr ign2(create_func(bt_all->Pid(), BACKTRACE_CURRENT_THREAD, map.get())); - ASSERT_TRUE(ign2.get() != nullptr); - ASSERT_TRUE(ign2->Unwind(2)); - VERIFY_NO_ERROR(ign2->GetError().error_code); - - VerifyIgnoreFrames(bt_all, ign1.get(), ign2.get(), nullptr); -} - -TEST_F(BacktraceTest, ptrace_ignore_frames) { - pid_t pid; - if ((pid = fork()) == 0) { - ASSERT_NE(test_level_one_(1, 2, 3, 4, nullptr, nullptr), 0); - _exit(1); - } - VerifyProcTest(pid, BACKTRACE_CURRENT_THREAD, ReadyLevelBacktrace, VerifyProcessIgnoreFrames, - Backtrace::Create, BacktraceMap::Create); - - kill(pid, SIGKILL); - int status; - ASSERT_EQ(waitpid(pid, &status, 0), pid); -} - -// Create a process with multiple threads and dump all of the threads. -static void* PtraceThreadLevelRun(void*) { - EXPECT_NE(BacktraceTest::test_level_one_(1, 2, 3, 4, nullptr, nullptr), 0); - return nullptr; -} - -static void GetThreads(pid_t pid, std::vector* threads) { - // Get the list of tasks. - char task_path[128]; - snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid); - - std::unique_ptr tasks_dir(opendir(task_path), closedir); - ASSERT_TRUE(tasks_dir != nullptr); - struct dirent* entry; - while ((entry = readdir(tasks_dir.get())) != nullptr) { - char* end; - pid_t tid = strtoul(entry->d_name, &end, 10); - if (*end == '\0') { - threads->push_back(tid); - } - } -} - -TEST_F(BacktraceTest, ptrace_threads) { - pid_t pid; - if ((pid = fork()) == 0) { - for (size_t i = 0; i < NUM_PTRACE_THREADS; i++) { - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - - pthread_t thread; - ASSERT_TRUE(pthread_create(&thread, &attr, PtraceThreadLevelRun, nullptr) == 0); - } - ASSERT_NE(test_level_one_(1, 2, 3, 4, nullptr, nullptr), 0); - _exit(1); - } - - // Check to see that all of the threads are running before unwinding. - std::vector threads; - uint64_t start = NanoTime(); - do { - usleep(US_PER_MSEC); - threads.clear(); - GetThreads(pid, &threads); - } while ((threads.size() != NUM_PTRACE_THREADS + 1) && - ((NanoTime() - start) <= 5 * NS_PER_SEC)); - ASSERT_EQ(threads.size(), static_cast(NUM_PTRACE_THREADS + 1)); - - ASSERT_TRUE(ptrace(PTRACE_ATTACH, pid, 0, 0) == 0); - WaitForStop(pid); - for (std::vector::const_iterator it = threads.begin(); it != threads.end(); ++it) { - // Skip the current forked process, we only care about the threads. - if (pid == *it) { - continue; - } - VerifyProcTest(pid, *it, ReadyLevelBacktrace, VerifyLevelDump, Backtrace::Create, - BacktraceMap::Create); - } - - FinishRemoteProcess(pid); -} - -void VerifyLevelThread(void*) { - std::unique_ptr backtrace(Backtrace::Create(getpid(), android::base::GetThreadId())); - ASSERT_TRUE(backtrace.get() != nullptr); - ASSERT_TRUE(backtrace->Unwind(0)); - VERIFY_NO_ERROR(backtrace->GetError().error_code); - - VerifyLevelDump(backtrace.get()); -} - -TEST_F(BacktraceTest, thread_current_level) { - ASSERT_NE(test_level_one_(1, 2, 3, 4, VerifyLevelThread, nullptr), 0); -} - -static void VerifyMaxThread(void*) { - std::unique_ptr backtrace(Backtrace::Create(getpid(), android::base::GetThreadId())); - ASSERT_TRUE(backtrace.get() != nullptr); - ASSERT_TRUE(backtrace->Unwind(0)); - ASSERT_EQ(BACKTRACE_UNWIND_ERROR_EXCEED_MAX_FRAMES_LIMIT, backtrace->GetError().error_code); - - VerifyMaxDump(backtrace.get()); -} - -TEST_F(BacktraceTest, thread_current_max) { - ASSERT_NE(test_recursive_call_(MAX_BACKTRACE_FRAMES + 10, VerifyMaxThread, nullptr), 0); -} - -static void* ThreadLevelRun(void* data) { - thread_t* thread = reinterpret_cast(data); - - thread->tid = android::base::GetThreadId(); - EXPECT_NE(BacktraceTest::test_level_one_(1, 2, 3, 4, ThreadSetState, data), 0); - return nullptr; -} - -TEST_F(BacktraceTest, thread_level_trace) { - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - - thread_t thread_data = { 0, 0, 0, nullptr }; - pthread_t thread; - ASSERT_TRUE(pthread_create(&thread, &attr, ThreadLevelRun, &thread_data) == 0); - - // Wait up to 2 seconds for the tid to be set. - ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2)); - - // Make sure that the thread signal used is not visible when compiled for - // the target. -#if !defined(__GLIBC__) - ASSERT_LT(THREAD_SIGNAL, SIGRTMIN); -#endif - - // Save the current signal action and make sure it is restored afterwards. - struct sigaction cur_action; - ASSERT_TRUE(sigaction(THREAD_SIGNAL, nullptr, &cur_action) == 0); - - std::unique_ptr backtrace(Backtrace::Create(getpid(), thread_data.tid)); - ASSERT_TRUE(backtrace.get() != nullptr); - ASSERT_TRUE(backtrace->Unwind(0)); - VERIFY_NO_ERROR(backtrace->GetError().error_code); - - VerifyLevelDump(backtrace.get()); - - // Tell the thread to exit its infinite loop. - android_atomic_acquire_store(0, &thread_data.state); - - // Verify that the old action was restored. - struct sigaction new_action; - ASSERT_TRUE(sigaction(THREAD_SIGNAL, nullptr, &new_action) == 0); - EXPECT_EQ(cur_action.sa_sigaction, new_action.sa_sigaction); - // The SA_RESTORER flag gets set behind our back, so a direct comparison - // doesn't work unless we mask the value off. Mips doesn't have this - // flag, so skip this on that platform. -#if defined(SA_RESTORER) - cur_action.sa_flags &= ~SA_RESTORER; - new_action.sa_flags &= ~SA_RESTORER; -#elif defined(__GLIBC__) - // Our host compiler doesn't appear to define this flag for some reason. - cur_action.sa_flags &= ~0x04000000; - new_action.sa_flags &= ~0x04000000; -#endif - EXPECT_EQ(cur_action.sa_flags, new_action.sa_flags); -} - -TEST_F(BacktraceTest, thread_ignore_frames) { - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - - thread_t thread_data = { 0, 0, 0, nullptr }; - pthread_t thread; - ASSERT_TRUE(pthread_create(&thread, &attr, ThreadLevelRun, &thread_data) == 0); - - // Wait up to 2 seconds for the tid to be set. - ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2)); - - std::unique_ptr all(Backtrace::Create(getpid(), thread_data.tid)); - ASSERT_TRUE(all.get() != nullptr); - ASSERT_TRUE(all->Unwind(0)); - VERIFY_NO_ERROR(all->GetError().error_code); - - std::unique_ptr ign1(Backtrace::Create(getpid(), thread_data.tid)); - ASSERT_TRUE(ign1.get() != nullptr); - ASSERT_TRUE(ign1->Unwind(1)); - VERIFY_NO_ERROR(ign1->GetError().error_code); - - std::unique_ptr ign2(Backtrace::Create(getpid(), thread_data.tid)); - ASSERT_TRUE(ign2.get() != nullptr); - ASSERT_TRUE(ign2->Unwind(2)); - VERIFY_NO_ERROR(ign2->GetError().error_code); - - VerifyIgnoreFrames(all.get(), ign1.get(), ign2.get(), nullptr); - - // Tell the thread to exit its infinite loop. - android_atomic_acquire_store(0, &thread_data.state); -} - -static void* ThreadMaxRun(void* data) { - thread_t* thread = reinterpret_cast(data); - - thread->tid = android::base::GetThreadId(); - EXPECT_NE(BacktraceTest::test_recursive_call_(MAX_BACKTRACE_FRAMES + 10, ThreadSetState, data), - 0); - return nullptr; -} - -TEST_F(BacktraceTest, thread_max_trace) { - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - - thread_t thread_data = { 0, 0, 0, nullptr }; - pthread_t thread; - ASSERT_TRUE(pthread_create(&thread, &attr, ThreadMaxRun, &thread_data) == 0); - - // Wait for the tid to be set. - ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2)); - - std::unique_ptr backtrace(Backtrace::Create(getpid(), thread_data.tid)); - ASSERT_TRUE(backtrace.get() != nullptr); - ASSERT_TRUE(backtrace->Unwind(0)); - ASSERT_EQ(BACKTRACE_UNWIND_ERROR_EXCEED_MAX_FRAMES_LIMIT, backtrace->GetError().error_code); - - VerifyMaxDump(backtrace.get()); - - // Tell the thread to exit its infinite loop. - android_atomic_acquire_store(0, &thread_data.state); -} - -static void* ThreadDump(void* data) { - dump_thread_t* dump = reinterpret_cast(data); - while (true) { - if (android_atomic_acquire_load(dump->now)) { - break; - } - } - - // The status of the actual unwind will be checked elsewhere. - dump->backtrace = Backtrace::Create(getpid(), dump->thread.tid, dump->map); - dump->backtrace->Unwind(0); - - android_atomic_acquire_store(1, &dump->done); - - return nullptr; -} - -static void MultipleThreadDumpTest(bool share_map) { - // Dump NUM_THREADS simultaneously using the same map. - std::vector runners(NUM_THREADS); - std::vector dumpers(NUM_THREADS); - - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - for (size_t i = 0; i < NUM_THREADS; i++) { - // Launch the runners, they will spin in hard loops doing nothing. - runners[i].tid = 0; - runners[i].state = 0; - ASSERT_TRUE(pthread_create(&runners[i].threadId, &attr, ThreadMaxRun, &runners[i]) == 0); - } - - // Wait for tids to be set. - for (std::vector::iterator it = runners.begin(); it != runners.end(); ++it) { - ASSERT_TRUE(WaitForNonZero(&it->state, 30)); - } - - // Start all of the dumpers at once, they will spin until they are signalled - // to begin their dump run. - std::unique_ptr map; - if (share_map) { - map.reset(BacktraceMap::Create(getpid())); - } - int32_t dump_now = 0; - for (size_t i = 0; i < NUM_THREADS; i++) { - dumpers[i].thread.tid = runners[i].tid; - dumpers[i].thread.state = 0; - dumpers[i].done = 0; - dumpers[i].now = &dump_now; - dumpers[i].map = map.get(); - - ASSERT_TRUE(pthread_create(&dumpers[i].thread.threadId, &attr, ThreadDump, &dumpers[i]) == 0); - } - - // Start all of the dumpers going at once. - android_atomic_acquire_store(1, &dump_now); - - for (size_t i = 0; i < NUM_THREADS; i++) { - ASSERT_TRUE(WaitForNonZero(&dumpers[i].done, 30)); - - // Tell the runner thread to exit its infinite loop. - android_atomic_acquire_store(0, &runners[i].state); - - ASSERT_TRUE(dumpers[i].backtrace != nullptr); - VerifyMaxDump(dumpers[i].backtrace); - - delete dumpers[i].backtrace; - dumpers[i].backtrace = nullptr; - } -} - -TEST_F(BacktraceTest, thread_multiple_dump) { - MultipleThreadDumpTest(false); -} - -TEST_F(BacktraceTest, thread_multiple_dump_same_map) { - MultipleThreadDumpTest(true); -} - -// This test is for UnwindMaps that should share the same map cursor when -// multiple maps are created for the current process at the same time. -TEST_F(BacktraceTest, simultaneous_maps) { - BacktraceMap* map1 = BacktraceMap::Create(getpid()); - BacktraceMap* map2 = BacktraceMap::Create(getpid()); - BacktraceMap* map3 = BacktraceMap::Create(getpid()); - - Backtrace* back1 = Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD, map1); - ASSERT_TRUE(back1 != nullptr); - EXPECT_TRUE(back1->Unwind(0)); - VERIFY_NO_ERROR(back1->GetError().error_code); - delete back1; - delete map1; - - Backtrace* back2 = Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD, map2); - ASSERT_TRUE(back2 != nullptr); - EXPECT_TRUE(back2->Unwind(0)); - VERIFY_NO_ERROR(back2->GetError().error_code); - delete back2; - delete map2; - - Backtrace* back3 = Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD, map3); - ASSERT_TRUE(back3 != nullptr); - EXPECT_TRUE(back3->Unwind(0)); - VERIFY_NO_ERROR(back3->GetError().error_code); - delete back3; - delete map3; -} - -TEST_F(BacktraceTest, fillin_erases) { - BacktraceMap* back_map = BacktraceMap::Create(getpid()); - - backtrace_map_t map; - - map.start = 1; - map.end = 3; - map.flags = 1; - map.name = "Initialized"; - back_map->FillIn(0, &map); - delete back_map; - - ASSERT_FALSE(BacktraceMap::IsValid(map)); - ASSERT_EQ(static_cast(0), map.start); - ASSERT_EQ(static_cast(0), map.end); - ASSERT_EQ(0, map.flags); - ASSERT_EQ("", map.name); -} - -TEST_F(BacktraceTest, format_test) { - std::unique_ptr backtrace(Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD)); - ASSERT_TRUE(backtrace.get() != nullptr); - - backtrace_frame_data_t frame; - frame.num = 1; - frame.pc = 2; - frame.rel_pc = 2; - frame.sp = 0; - frame.stack_size = 0; - frame.func_offset = 0; - - // Check no map set. - frame.num = 1; -#if defined(__LP64__) - EXPECT_EQ("#01 pc 0000000000000002 ", -#else - EXPECT_EQ("#01 pc 00000002 ", -#endif - backtrace->FormatFrameData(&frame)); - - // Check map name empty, but exists. - frame.pc = 0xb0020; - frame.rel_pc = 0x20; - frame.map.start = 0xb0000; - frame.map.end = 0xbffff; - frame.map.load_bias = 0; -#if defined(__LP64__) - EXPECT_EQ("#01 pc 0000000000000020 ", -#else - EXPECT_EQ("#01 pc 00000020 ", -#endif - backtrace->FormatFrameData(&frame)); - - // Check map name begins with a [. - frame.pc = 0xc0020; - frame.map.start = 0xc0000; - frame.map.end = 0xcffff; - frame.map.load_bias = 0; - frame.map.name = "[anon:thread signal stack]"; -#if defined(__LP64__) - EXPECT_EQ("#01 pc 0000000000000020 [anon:thread signal stack:00000000000c0000]", -#else - EXPECT_EQ("#01 pc 00000020 [anon:thread signal stack:000c0000]", -#endif - backtrace->FormatFrameData(&frame)); - - // Check relative pc is set and map name is set. - frame.pc = 0x12345679; - frame.rel_pc = 0x12345678; - frame.map.name = "MapFake"; - frame.map.start = 1; - frame.map.end = 1; -#if defined(__LP64__) - EXPECT_EQ("#01 pc 0000000012345678 MapFake", -#else - EXPECT_EQ("#01 pc 12345678 MapFake", -#endif - backtrace->FormatFrameData(&frame)); - - // Check func_name is set, but no func offset. - frame.func_name = "ProcFake"; -#if defined(__LP64__) - EXPECT_EQ("#01 pc 0000000012345678 MapFake (ProcFake)", -#else - EXPECT_EQ("#01 pc 12345678 MapFake (ProcFake)", -#endif - backtrace->FormatFrameData(&frame)); - - // Check func_name is set, and func offset is non-zero. - frame.func_offset = 645; -#if defined(__LP64__) - EXPECT_EQ("#01 pc 0000000012345678 MapFake (ProcFake+645)", -#else - EXPECT_EQ("#01 pc 12345678 MapFake (ProcFake+645)", -#endif - backtrace->FormatFrameData(&frame)); - - // Check func_name is set, func offset is non-zero, and load_bias is non-zero. - frame.rel_pc = 0x123456dc; - frame.func_offset = 645; - frame.map.load_bias = 100; -#if defined(__LP64__) - EXPECT_EQ("#01 pc 00000000123456dc MapFake (ProcFake+645)", -#else - EXPECT_EQ("#01 pc 123456dc MapFake (ProcFake+645)", -#endif - backtrace->FormatFrameData(&frame)); - - // Check a non-zero map offset. - frame.map.offset = 0x1000; -#if defined(__LP64__) - EXPECT_EQ("#01 pc 00000000123456dc MapFake (offset 0x1000) (ProcFake+645)", -#else - EXPECT_EQ("#01 pc 123456dc MapFake (offset 0x1000) (ProcFake+645)", -#endif - backtrace->FormatFrameData(&frame)); -} - -struct map_test_t { - uint64_t start; - uint64_t end; -}; - -static bool map_sort(map_test_t i, map_test_t j) { return i.start < j.start; } - -static std::string GetTestMapsAsString(const std::vector& maps) { - if (maps.size() == 0) { - return "No test map entries\n"; - } - std::string map_txt; - for (auto map : maps) { - map_txt += android::base::StringPrintf("%" PRIx64 "-%" PRIx64 "\n", map.start, map.end); - } - return map_txt; -} - -static std::string GetMapsAsString(BacktraceMap* maps) { - if (maps->size() == 0) { - return "No map entries\n"; - } - std::string map_txt; - for (const backtrace_map_t* map : *maps) { - map_txt += android::base::StringPrintf( - "%" PRIx64 "-%" PRIx64 " flags: 0x%x offset: 0x%" PRIx64 " load_bias: 0x%" PRIx64, - map->start, map->end, map->flags, map->offset, map->load_bias); - if (!map->name.empty()) { - map_txt += ' ' + map->name; - } - map_txt += '\n'; - } - return map_txt; -} - -static void VerifyMap(pid_t pid) { - char buffer[4096]; - snprintf(buffer, sizeof(buffer), "/proc/%d/maps", pid); - - FILE* map_file = fopen(buffer, "r"); - ASSERT_TRUE(map_file != nullptr); - std::vector test_maps; - while (fgets(buffer, sizeof(buffer), map_file)) { - map_test_t map; - ASSERT_EQ(2, sscanf(buffer, "%" SCNx64 "-%" SCNx64 " ", &map.start, &map.end)); - test_maps.push_back(map); - } - fclose(map_file); - std::sort(test_maps.begin(), test_maps.end(), map_sort); - - std::unique_ptr map(BacktraceMap::Create(pid)); - - // Basic test that verifies that the map is in the expected order. - auto test_it = test_maps.begin(); - for (auto it = map->begin(); it != map->end(); ++it) { - ASSERT_TRUE(test_it != test_maps.end()) << "Mismatch in number of maps, expected test maps:\n" - << GetTestMapsAsString(test_maps) << "Actual maps:\n" - << GetMapsAsString(map.get()); - ASSERT_EQ(test_it->start, (*it)->start) << "Mismatch in map data, expected test maps:\n" - << GetTestMapsAsString(test_maps) << "Actual maps:\n" - << GetMapsAsString(map.get()); - ASSERT_EQ(test_it->end, (*it)->end) << "Mismatch maps in map data, expected test maps:\n" - << GetTestMapsAsString(test_maps) << "Actual maps:\n" - << GetMapsAsString(map.get()); - // Make sure the load bias get set to a value. - ASSERT_NE(static_cast(-1), (*it)->load_bias) << "Found uninitialized load_bias\n" - << GetMapsAsString(map.get()); - ++test_it; - } - ASSERT_TRUE(test_it == test_maps.end()); -} - -TEST_F(BacktraceTest, verify_map_remote) { - pid_t pid; - CreateRemoteProcess(&pid); - - // The maps should match exactly since the forked process has been paused. - VerifyMap(pid); - - FinishRemoteProcess(pid); -} - -static void InitMemory(uint8_t* memory, size_t bytes) { - for (size_t i = 0; i < bytes; i++) { - memory[i] = i; - if (memory[i] == '\0') { - // Don't use '\0' in our data so we can verify that an overread doesn't - // occur by using a '\0' as the character after the read data. - memory[i] = 23; - } - } -} - -static void* ThreadReadTest(void* data) { - thread_t* thread_data = reinterpret_cast(data); - - thread_data->tid = android::base::GetThreadId(); - - // Create two map pages. - // Mark the second page as not-readable. - size_t pagesize = static_cast(sysconf(_SC_PAGE_SIZE)); - uint8_t* memory; - if (posix_memalign(reinterpret_cast(&memory), pagesize, 2 * pagesize) != 0) { - return reinterpret_cast(-1); - } - - if (mprotect(&memory[pagesize], pagesize, PROT_NONE) != 0) { - return reinterpret_cast(-1); - } - - // Set up a simple pattern in memory. - InitMemory(memory, pagesize); - - thread_data->data = memory; - - // Tell the caller it's okay to start reading memory. - android_atomic_acquire_store(1, &thread_data->state); - - // Loop waiting for the caller to finish reading the memory. - while (thread_data->state) { - } - - // Re-enable read-write on the page so that we don't crash if we try - // and access data on this page when freeing the memory. - if (mprotect(&memory[pagesize], pagesize, PROT_READ | PROT_WRITE) != 0) { - return reinterpret_cast(-1); - } - free(memory); - - android_atomic_acquire_store(1, &thread_data->state); - - return nullptr; -} - -static void RunReadTest(Backtrace* backtrace, uint64_t read_addr) { - size_t pagesize = static_cast(sysconf(_SC_PAGE_SIZE)); - - // Create a page of data to use to do quick compares. - uint8_t* expected = new uint8_t[pagesize]; - InitMemory(expected, pagesize); - - uint8_t* data = new uint8_t[2 * pagesize]; - // Verify that we can only read one page worth of data. - size_t bytes_read = backtrace->Read(read_addr, data, 2 * pagesize); - ASSERT_EQ(pagesize, bytes_read); - ASSERT_TRUE(memcmp(data, expected, pagesize) == 0); - - // Verify unaligned reads. - for (size_t i = 1; i < sizeof(word_t); i++) { - bytes_read = backtrace->Read(read_addr + i, data, 2 * sizeof(word_t)); - ASSERT_EQ(2 * sizeof(word_t), bytes_read); - ASSERT_TRUE(memcmp(data, &expected[i], 2 * sizeof(word_t)) == 0) - << "Offset at " << i << " failed"; - } - - // Verify small unaligned reads. - for (size_t i = 1; i < sizeof(word_t); i++) { - for (size_t j = 1; j < sizeof(word_t); j++) { - // Set one byte past what we expect to read, to guarantee we don't overread. - data[j] = '\0'; - bytes_read = backtrace->Read(read_addr + i, data, j); - ASSERT_EQ(j, bytes_read); - ASSERT_TRUE(memcmp(data, &expected[i], j) == 0) - << "Offset at " << i << " length " << j << " miscompared"; - ASSERT_EQ('\0', data[j]) - << "Offset at " << i << " length " << j << " wrote too much data"; - } - } - delete[] data; - delete[] expected; -} - -TEST_F(BacktraceTest, thread_read) { - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_t thread; - thread_t thread_data = { 0, 0, 0, nullptr }; - ASSERT_TRUE(pthread_create(&thread, &attr, ThreadReadTest, &thread_data) == 0); - - ASSERT_TRUE(WaitForNonZero(&thread_data.state, 10)); - - std::unique_ptr backtrace(Backtrace::Create(getpid(), thread_data.tid)); - ASSERT_TRUE(backtrace.get() != nullptr); - - RunReadTest(backtrace.get(), reinterpret_cast(thread_data.data)); - - android_atomic_acquire_store(0, &thread_data.state); - - ASSERT_TRUE(WaitForNonZero(&thread_data.state, 10)); -} - -// The code requires these variables are the same size. -volatile uint64_t g_ready = 0; -volatile uint64_t g_addr = 0; -static_assert(sizeof(g_ready) == sizeof(g_addr), "g_ready/g_addr must be same size"); - -static void ForkedReadTest() { - // Create two map pages. - size_t pagesize = static_cast(sysconf(_SC_PAGE_SIZE)); - uint8_t* memory; - if (posix_memalign(reinterpret_cast(&memory), pagesize, 2 * pagesize) != 0) { - perror("Failed to allocate memory\n"); - exit(1); - } - - // Mark the second page as not-readable. - if (mprotect(&memory[pagesize], pagesize, PROT_NONE) != 0) { - perror("Failed to mprotect memory\n"); - exit(1); - } - - // Set up a simple pattern in memory. - InitMemory(memory, pagesize); - - g_addr = reinterpret_cast(memory); - g_ready = 1; - - while (1) { - usleep(US_PER_MSEC); - } -} - -TEST_F(BacktraceTest, process_read) { - g_ready = 0; - pid_t pid; - if ((pid = fork()) == 0) { - ForkedReadTest(); - exit(0); - } - ASSERT_NE(-1, pid); - - bool test_executed = false; - uint64_t start = NanoTime(); - while (1) { - if (ptrace(PTRACE_ATTACH, pid, 0, 0) == 0) { - WaitForStop(pid); - - std::unique_ptr backtrace(Backtrace::Create(pid, pid)); - ASSERT_TRUE(backtrace.get() != nullptr); - - uint64_t read_addr; - size_t bytes_read = backtrace->Read(reinterpret_cast(&g_ready), - reinterpret_cast(&read_addr), sizeof(g_ready)); - ASSERT_EQ(sizeof(g_ready), bytes_read); - if (read_addr) { - // The forked process is ready to be read. - bytes_read = backtrace->Read(reinterpret_cast(&g_addr), - reinterpret_cast(&read_addr), sizeof(g_addr)); - ASSERT_EQ(sizeof(g_addr), bytes_read); - - RunReadTest(backtrace.get(), read_addr); - - test_executed = true; - break; - } - ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0); - } - if ((NanoTime() - start) > 5 * NS_PER_SEC) { - break; - } - usleep(US_PER_MSEC); - } - kill(pid, SIGKILL); - ASSERT_EQ(waitpid(pid, nullptr, 0), pid); - - ASSERT_TRUE(test_executed); -} - -static void VerifyFunctionsFound(const std::vector& found_functions) { - // We expect to find these functions in libbacktrace_test. If we don't - // find them, that's a bug in the memory read handling code in libunwind. - std::list expected_functions; - expected_functions.push_back("test_recursive_call"); - expected_functions.push_back("test_level_one"); - expected_functions.push_back("test_level_two"); - expected_functions.push_back("test_level_three"); - expected_functions.push_back("test_level_four"); - for (const auto& found_function : found_functions) { - for (const auto& expected_function : expected_functions) { - if (found_function == expected_function) { - expected_functions.remove(found_function); - break; - } - } - } - ASSERT_TRUE(expected_functions.empty()) << "Not all functions found in shared library."; -} - -static void CopySharedLibrary(const char* tmp_dir, std::string* tmp_so_name) { - std::string test_lib(testing::internal::GetArgvs()[0]); - auto const value = test_lib.find_last_of('/'); - if (value == std::string::npos) { - test_lib = "../backtrace_test_libs/"; - } else { - test_lib = test_lib.substr(0, value + 1) + "../backtrace_test_libs/"; - } - test_lib += "libbacktrace_test.so"; - - *tmp_so_name = std::string(tmp_dir) + "/libbacktrace_test.so"; - std::string cp_cmd = android::base::StringPrintf("cp %s %s", test_lib.c_str(), tmp_dir); - - // Copy the shared so to a tempory directory. - ASSERT_EQ(0, system(cp_cmd.c_str())); -} - -TEST_F(BacktraceTest, check_unreadable_elf_local) { - TemporaryDir td; - std::string tmp_so_name; - ASSERT_NO_FATAL_FAILURE(CopySharedLibrary(td.path, &tmp_so_name)); - - struct stat buf; - ASSERT_TRUE(stat(tmp_so_name.c_str(), &buf) != -1); - uint64_t map_size = buf.st_size; - - int fd = open(tmp_so_name.c_str(), O_RDONLY); - ASSERT_TRUE(fd != -1); - - void* map = mmap(nullptr, map_size, PROT_READ | PROT_EXEC, MAP_PRIVATE, fd, 0); - ASSERT_TRUE(map != MAP_FAILED); - close(fd); - ASSERT_TRUE(unlink(tmp_so_name.c_str()) != -1); - - std::vector found_functions; - std::unique_ptr backtrace(Backtrace::Create(BACKTRACE_CURRENT_PROCESS, - BACKTRACE_CURRENT_THREAD)); - ASSERT_TRUE(backtrace.get() != nullptr); - - // Needed before GetFunctionName will work. - backtrace->Unwind(0); - - // Loop through the entire map, and get every function we can find. - map_size += reinterpret_cast(map); - std::string last_func; - for (uint64_t read_addr = reinterpret_cast(map); read_addr < map_size; read_addr += 4) { - uint64_t offset; - std::string func_name = backtrace->GetFunctionName(read_addr, &offset); - if (!func_name.empty() && last_func != func_name) { - found_functions.push_back(func_name); - } - last_func = func_name; - } - - ASSERT_TRUE(munmap(map, map_size - reinterpret_cast(map)) == 0); - - VerifyFunctionsFound(found_functions); -} - -TEST_F(BacktraceTest, check_unreadable_elf_remote) { - TemporaryDir td; - std::string tmp_so_name; - ASSERT_NO_FATAL_FAILURE(CopySharedLibrary(td.path, &tmp_so_name)); - - g_ready = 0; - - struct stat buf; - ASSERT_TRUE(stat(tmp_so_name.c_str(), &buf) != -1); - uint64_t map_size = buf.st_size; - - pid_t pid; - if ((pid = fork()) == 0) { - int fd = open(tmp_so_name.c_str(), O_RDONLY); - if (fd == -1) { - fprintf(stderr, "Failed to open file %s: %s\n", tmp_so_name.c_str(), strerror(errno)); - unlink(tmp_so_name.c_str()); - exit(0); - } - - void* map = mmap(nullptr, map_size, PROT_READ | PROT_EXEC, MAP_PRIVATE, fd, 0); - if (map == MAP_FAILED) { - fprintf(stderr, "Failed to map in memory: %s\n", strerror(errno)); - unlink(tmp_so_name.c_str()); - exit(0); - } - close(fd); - if (unlink(tmp_so_name.c_str()) == -1) { - fprintf(stderr, "Failed to unlink: %s\n", strerror(errno)); - exit(0); - } - - g_addr = reinterpret_cast(map); - g_ready = 1; - while (true) { - usleep(US_PER_MSEC); - } - exit(0); - } - ASSERT_TRUE(pid > 0); - - std::vector found_functions; - uint64_t start = NanoTime(); - while (true) { - ASSERT_TRUE(ptrace(PTRACE_ATTACH, pid, 0, 0) == 0); - - // Wait for the process to get to a stopping point. - WaitForStop(pid); - - std::unique_ptr backtrace(Backtrace::Create(pid, BACKTRACE_CURRENT_THREAD)); - ASSERT_TRUE(backtrace.get() != nullptr); - - uint64_t read_addr; - ASSERT_EQ(sizeof(g_ready), - backtrace->Read(reinterpret_cast(&g_ready), - reinterpret_cast(&read_addr), sizeof(g_ready))); - if (read_addr) { - ASSERT_EQ(sizeof(g_addr), - backtrace->Read(reinterpret_cast(&g_addr), - reinterpret_cast(&read_addr), sizeof(uint64_t))); - - // Needed before GetFunctionName will work. - backtrace->Unwind(0); - - // Loop through the entire map, and get every function we can find. - map_size += read_addr; - std::string last_func; - for (; read_addr < map_size; read_addr += 4) { - uint64_t offset; - std::string func_name = backtrace->GetFunctionName(read_addr, &offset); - if (!func_name.empty() && last_func != func_name) { - found_functions.push_back(func_name); - } - last_func = func_name; - } - break; - } - ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0); - - if ((NanoTime() - start) > 5 * NS_PER_SEC) { - break; - } - usleep(US_PER_MSEC); - } - - kill(pid, SIGKILL); - ASSERT_EQ(waitpid(pid, nullptr, 0), pid); - - VerifyFunctionsFound(found_functions); -} - -static bool FindFuncFrameInBacktrace(Backtrace* backtrace, uint64_t test_func, size_t* frame_num) { - backtrace_map_t map; - backtrace->FillInMap(test_func, &map); - if (!BacktraceMap::IsValid(map)) { - return false; - } - - // Loop through the frames, and find the one that is in the map. - *frame_num = 0; - for (Backtrace::const_iterator it = backtrace->begin(); it != backtrace->end(); ++it) { - if (BacktraceMap::IsValid(it->map) && map.start == it->map.start && - it->pc >= test_func) { - *frame_num = it->num; - return true; - } - } - return false; -} - -static void VerifyUnreadableElfFrame(Backtrace* backtrace, uint64_t test_func, size_t frame_num) { - ASSERT_LT(backtrace->NumFrames(), static_cast(MAX_BACKTRACE_FRAMES)) - << DumpFrames(backtrace); - - ASSERT_TRUE(frame_num != 0) << DumpFrames(backtrace); - // Make sure that there is at least one more frame above the test func call. - ASSERT_LT(frame_num, backtrace->NumFrames()) << DumpFrames(backtrace); - - uint64_t diff = backtrace->GetFrame(frame_num)->pc - test_func; - ASSERT_LT(diff, 200U) << DumpFrames(backtrace); -} - -static void VerifyUnreadableElfBacktrace(void* func) { - std::unique_ptr backtrace(Backtrace::Create(BACKTRACE_CURRENT_PROCESS, - BACKTRACE_CURRENT_THREAD)); - ASSERT_TRUE(backtrace.get() != nullptr); - ASSERT_TRUE(backtrace->Unwind(0)); - VERIFY_NO_ERROR(backtrace->GetError().error_code); - - size_t frame_num; - uint64_t test_func = reinterpret_cast(func); - ASSERT_TRUE(FindFuncFrameInBacktrace(backtrace.get(), test_func, &frame_num)) - << DumpFrames(backtrace.get()); - - VerifyUnreadableElfFrame(backtrace.get(), test_func, frame_num); -} - -typedef int (*test_func_t)(int, int, int, int, void (*)(void*), void*); - -TEST_F(BacktraceTest, unwind_through_unreadable_elf_local) { - TemporaryDir td; - std::string tmp_so_name; - ASSERT_NO_FATAL_FAILURE(CopySharedLibrary(td.path, &tmp_so_name)); - - void* lib_handle = dlopen(tmp_so_name.c_str(), RTLD_NOW); - ASSERT_TRUE(lib_handle != nullptr); - ASSERT_TRUE(unlink(tmp_so_name.c_str()) != -1); - - test_func_t test_func; - test_func = reinterpret_cast(dlsym(lib_handle, "test_level_one")); - ASSERT_TRUE(test_func != nullptr); - - ASSERT_NE(test_func(1, 2, 3, 4, VerifyUnreadableElfBacktrace, reinterpret_cast(test_func)), - 0); -} - -TEST_F(BacktraceTest, unwind_through_unreadable_elf_remote) { - TemporaryDir td; - std::string tmp_so_name; - ASSERT_NO_FATAL_FAILURE(CopySharedLibrary(td.path, &tmp_so_name)); - - void* lib_handle = dlopen(tmp_so_name.c_str(), RTLD_NOW); - ASSERT_TRUE(lib_handle != nullptr); - ASSERT_TRUE(unlink(tmp_so_name.c_str()) != -1); - - test_func_t test_func; - test_func = reinterpret_cast(dlsym(lib_handle, "test_level_one")); - ASSERT_TRUE(test_func != nullptr); - - pid_t pid; - if ((pid = fork()) == 0) { - test_func(1, 2, 3, 4, 0, 0); - exit(0); - } - ASSERT_TRUE(pid > 0); - - uint64_t start = NanoTime(); - bool done = false; - while (!done) { - ASSERT_TRUE(ptrace(PTRACE_ATTACH, pid, 0, 0) == 0); - - // Wait for the process to get to a stopping point. - WaitForStop(pid); - - std::unique_ptr backtrace(Backtrace::Create(pid, BACKTRACE_CURRENT_THREAD)); - ASSERT_TRUE(backtrace.get() != nullptr); - ASSERT_TRUE(backtrace->Unwind(0)); - VERIFY_NO_ERROR(backtrace->GetError().error_code); - - size_t frame_num; - if (FindFuncFrameInBacktrace(backtrace.get(), reinterpret_cast(test_func), - &frame_num) && - frame_num != 0) { - VerifyUnreadableElfFrame(backtrace.get(), reinterpret_cast(test_func), frame_num); - done = true; - } - - ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0); - - if ((NanoTime() - start) > 5 * NS_PER_SEC) { - break; - } - usleep(US_PER_MSEC); - } - - kill(pid, SIGKILL); - ASSERT_EQ(waitpid(pid, nullptr, 0), pid); - - ASSERT_TRUE(done) << "Test function never found in unwind."; -} - -TEST_F(BacktraceTest, unwind_thread_doesnt_exist) { - std::unique_ptr backtrace( - Backtrace::Create(BACKTRACE_CURRENT_PROCESS, 99999999)); - ASSERT_TRUE(backtrace.get() != nullptr); - ASSERT_FALSE(backtrace->Unwind(0)); - ASSERT_EQ(BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST, backtrace->GetError().error_code); -} - -TEST_F(BacktraceTest, local_get_function_name_before_unwind) { - std::unique_ptr backtrace( - Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD)); - ASSERT_TRUE(backtrace.get() != nullptr); - - // Verify that trying to get a function name before doing an unwind works. - uint64_t cur_func_offset = reinterpret_cast(test_level_one_) + 1; - uint64_t offset; - ASSERT_NE(std::string(""), backtrace->GetFunctionName(cur_func_offset, &offset)); -} - -TEST_F(BacktraceTest, remote_get_function_name_before_unwind) { - pid_t pid; - CreateRemoteProcess(&pid); - - // Now create an unwind object. - std::unique_ptr backtrace(Backtrace::Create(pid, pid)); - - // Verify that trying to get a function name before doing an unwind works. - uint64_t cur_func_offset = reinterpret_cast(test_level_one_) + 1; - uint64_t offset; - ASSERT_NE(std::string(""), backtrace->GetFunctionName(cur_func_offset, &offset)); - - FinishRemoteProcess(pid); -} - -static void SetUcontextSp(uint64_t sp, ucontext_t* ucontext) { -#if defined(__arm__) - ucontext->uc_mcontext.arm_sp = sp; -#elif defined(__aarch64__) - ucontext->uc_mcontext.sp = sp; -#elif defined(__i386__) - ucontext->uc_mcontext.gregs[REG_ESP] = sp; -#elif defined(__x86_64__) - ucontext->uc_mcontext.gregs[REG_RSP] = sp; -#else - UNUSED(sp); - UNUSED(ucontext); - ASSERT_TRUE(false) << "Unsupported architecture"; -#endif -} - -static void SetUcontextPc(uint64_t pc, ucontext_t* ucontext) { -#if defined(__arm__) - ucontext->uc_mcontext.arm_pc = pc; -#elif defined(__aarch64__) - ucontext->uc_mcontext.pc = pc; -#elif defined(__i386__) - ucontext->uc_mcontext.gregs[REG_EIP] = pc; -#elif defined(__x86_64__) - ucontext->uc_mcontext.gregs[REG_RIP] = pc; -#else - UNUSED(pc); - UNUSED(ucontext); - ASSERT_TRUE(false) << "Unsupported architecture"; -#endif -} - -static void SetUcontextLr(uint64_t lr, ucontext_t* ucontext) { -#if defined(__arm__) - ucontext->uc_mcontext.arm_lr = lr; -#elif defined(__aarch64__) - ucontext->uc_mcontext.regs[30] = lr; -#elif defined(__i386__) - // The lr is on the stack. - ASSERT_TRUE(lr != 0); - ASSERT_TRUE(ucontext != nullptr); -#elif defined(__x86_64__) - // The lr is on the stack. - ASSERT_TRUE(lr != 0); - ASSERT_TRUE(ucontext != nullptr); -#else - UNUSED(lr); - UNUSED(ucontext); - ASSERT_TRUE(false) << "Unsupported architecture"; -#endif -} - -static constexpr size_t DEVICE_MAP_SIZE = 1024; - -static void SetupDeviceMap(void** device_map) { - // Make sure that anything in a device map will result in fails - // to read. - android::base::unique_fd device_fd(open("/dev/zero", O_RDONLY | O_CLOEXEC)); - - *device_map = mmap(nullptr, 1024, PROT_READ, MAP_PRIVATE, device_fd, 0); - ASSERT_TRUE(*device_map != MAP_FAILED); - - // Make sure the map is readable. - ASSERT_EQ(0, reinterpret_cast(*device_map)[0]); -} - -static void UnwindFromDevice(Backtrace* backtrace, void* device_map) { - uint64_t device_map_uint = reinterpret_cast(device_map); - - backtrace_map_t map; - backtrace->FillInMap(device_map_uint, &map); - // Verify the flag is set. - ASSERT_EQ(PROT_DEVICE_MAP, map.flags & PROT_DEVICE_MAP); - - // Quick basic checks of functionality. - uint64_t offset; - ASSERT_EQ(std::string(""), backtrace->GetFunctionName(device_map_uint, &offset)); - ASSERT_EQ(std::string(""), backtrace->GetFunctionName(device_map_uint, &offset, &map)); - ASSERT_EQ(std::string(""), backtrace->GetFunctionName(0, &offset)); - - uint64_t cur_func_offset = reinterpret_cast(BacktraceTest::test_level_one_) + 1; - // Now verify the device map flag actually causes the function name to be empty. - backtrace->FillInMap(cur_func_offset, &map); - ASSERT_TRUE((map.flags & PROT_DEVICE_MAP) == 0); - ASSERT_NE(std::string(""), backtrace->GetFunctionName(cur_func_offset, &offset, &map)); - map.flags |= PROT_DEVICE_MAP; - ASSERT_EQ(std::string(""), backtrace->GetFunctionName(cur_func_offset, &offset, &map)); - - ucontext_t ucontext; - - // Create a context that has the pc in the device map, but the sp - // in a non-device map. - memset(&ucontext, 0, sizeof(ucontext)); - SetUcontextSp(reinterpret_cast(&ucontext), &ucontext); - SetUcontextPc(device_map_uint, &ucontext); - SetUcontextLr(cur_func_offset, &ucontext); - - ASSERT_TRUE(backtrace->Unwind(0, &ucontext)); - - // The buffer should only be a single element. - ASSERT_EQ(1U, backtrace->NumFrames()); - const backtrace_frame_data_t* frame = backtrace->GetFrame(0); - ASSERT_EQ(device_map_uint, frame->pc); - ASSERT_EQ(reinterpret_cast(&ucontext), frame->sp); - - // Check what happens when skipping the first frame. - ASSERT_TRUE(backtrace->Unwind(1, &ucontext)); - ASSERT_EQ(0U, backtrace->NumFrames()); - - // Create a context that has the sp in the device map, but the pc - // in a non-device map. - memset(&ucontext, 0, sizeof(ucontext)); - SetUcontextSp(device_map_uint, &ucontext); - SetUcontextPc(cur_func_offset, &ucontext); - SetUcontextLr(cur_func_offset, &ucontext); - - ASSERT_TRUE(backtrace->Unwind(0, &ucontext)); - - // The buffer should only be a single element. - ASSERT_EQ(1U, backtrace->NumFrames()); - frame = backtrace->GetFrame(0); - ASSERT_EQ(cur_func_offset, frame->pc); - ASSERT_EQ(device_map_uint, frame->sp); - - // Check what happens when skipping the first frame. - ASSERT_TRUE(backtrace->Unwind(1, &ucontext)); - ASSERT_EQ(0U, backtrace->NumFrames()); -} - -TEST_F(BacktraceTest, unwind_disallow_device_map_local) { - void* device_map; - SetupDeviceMap(&device_map); - - // Now create an unwind object. - std::unique_ptr backtrace( - Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD)); - ASSERT_TRUE(backtrace); - - UnwindFromDevice(backtrace.get(), device_map); - - munmap(device_map, DEVICE_MAP_SIZE); -} - -TEST_F(BacktraceTest, unwind_disallow_device_map_remote) { - void* device_map; - SetupDeviceMap(&device_map); - - // Fork a process to do a remote backtrace. - pid_t pid; - CreateRemoteProcess(&pid); - - // Now create an unwind object. - std::unique_ptr backtrace(Backtrace::Create(pid, pid)); - - UnwindFromDevice(backtrace.get(), device_map); - - FinishRemoteProcess(pid); - - munmap(device_map, DEVICE_MAP_SIZE); -} - -class ScopedSignalHandler { - public: - ScopedSignalHandler(int signal_number, void (*handler)(int)) : signal_number_(signal_number) { - memset(&action_, 0, sizeof(action_)); - action_.sa_handler = handler; - sigaction(signal_number_, &action_, &old_action_); - } - - ScopedSignalHandler(int signal_number, void (*action)(int, siginfo_t*, void*)) - : signal_number_(signal_number) { - memset(&action_, 0, sizeof(action_)); - action_.sa_flags = SA_SIGINFO; - action_.sa_sigaction = action; - sigaction(signal_number_, &action_, &old_action_); - } - - ~ScopedSignalHandler() { sigaction(signal_number_, &old_action_, nullptr); } - - private: - struct sigaction action_; - struct sigaction old_action_; - const int signal_number_; -}; - -static void SetValueAndLoop(void* data) { - volatile int* value = reinterpret_cast(data); - - *value = 1; - for (volatile int i = 0;; i++) - ; -} - -static void UnwindThroughSignal(bool use_action, create_func_t create_func, - map_create_func_t map_create_func) { - volatile int value = 0; - pid_t pid; - if ((pid = fork()) == 0) { - if (use_action) { - ScopedSignalHandler ssh(SIGUSR1, BacktraceTest::test_signal_action_); - - BacktraceTest::test_level_one_(1, 2, 3, 4, SetValueAndLoop, const_cast(&value)); - } else { - ScopedSignalHandler ssh(SIGUSR1, BacktraceTest::test_signal_handler_); - - BacktraceTest::test_level_one_(1, 2, 3, 4, SetValueAndLoop, const_cast(&value)); - } - } - ASSERT_NE(-1, pid); - - int read_value = 0; - uint64_t start = NanoTime(); - while (read_value == 0) { - usleep(1000); - - // Loop until the remote function gets into the final function. - ASSERT_TRUE(ptrace(PTRACE_ATTACH, pid, 0, 0) == 0); - - WaitForStop(pid); - - std::unique_ptr map(map_create_func(pid, false)); - std::unique_ptr backtrace(create_func(pid, pid, map.get())); - - size_t bytes_read = backtrace->Read(reinterpret_cast(const_cast(&value)), - reinterpret_cast(&read_value), sizeof(read_value)); - ASSERT_EQ(sizeof(read_value), bytes_read); - - ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0); - - ASSERT_TRUE(NanoTime() - start < 5 * NS_PER_SEC) - << "Remote process did not execute far enough in 5 seconds."; - } - - // Now need to send a signal to the remote process. - kill(pid, SIGUSR1); - - // Wait for the process to get to the signal handler loop. - Backtrace::const_iterator frame_iter; - start = NanoTime(); - std::unique_ptr map; - std::unique_ptr backtrace; - while (true) { - usleep(1000); - - ASSERT_TRUE(ptrace(PTRACE_ATTACH, pid, 0, 0) == 0); - - WaitForStop(pid); - - map.reset(map_create_func(pid, false)); - ASSERT_TRUE(map.get() != nullptr); - backtrace.reset(create_func(pid, pid, map.get())); - ASSERT_TRUE(backtrace->Unwind(0)); - bool found = false; - for (frame_iter = backtrace->begin(); frame_iter != backtrace->end(); ++frame_iter) { - if (frame_iter->func_name == "test_loop_forever") { - ++frame_iter; - found = true; - break; - } - } - if (found) { - break; - } - - ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0); - - ASSERT_TRUE(NanoTime() - start < 5 * NS_PER_SEC) - << "Remote process did not get in signal handler in 5 seconds." << std::endl - << DumpFrames(backtrace.get()); - } - - std::vector names; - // Loop through the frames, and save the function names. - size_t frame = 0; - for (; frame_iter != backtrace->end(); ++frame_iter) { - if (frame_iter->func_name == "test_level_four") { - frame = names.size() + 1; - } - names.push_back(frame_iter->func_name); - } - ASSERT_NE(0U, frame) << "Unable to find test_level_four in backtrace" << std::endl - << DumpFrames(backtrace.get()); - - // The expected order of the frames: - // test_loop_forever - // test_signal_handler|test_signal_action - // May or may not exist. - // SetValueAndLoop (but the function name might be empty) - // test_level_four - // test_level_three - // test_level_two - // test_level_one - ASSERT_LE(frame + 2, names.size()) << DumpFrames(backtrace.get()); - ASSERT_LE(2U, frame) << DumpFrames(backtrace.get()); - if (use_action) { - ASSERT_EQ("test_signal_action", names[0]) << DumpFrames(backtrace.get()); - } else { - ASSERT_EQ("test_signal_handler", names[0]) << DumpFrames(backtrace.get()); - } - ASSERT_EQ("test_level_three", names[frame]) << DumpFrames(backtrace.get()); - ASSERT_EQ("test_level_two", names[frame + 1]) << DumpFrames(backtrace.get()); - ASSERT_EQ("test_level_one", names[frame + 2]) << DumpFrames(backtrace.get()); - - FinishRemoteProcess(pid); -} - -TEST_F(BacktraceTest, unwind_remote_through_signal_using_handler) { - UnwindThroughSignal(false, Backtrace::Create, BacktraceMap::Create); -} - -TEST_F(BacktraceTest, unwind_remote_through_signal_using_action) { - UnwindThroughSignal(true, Backtrace::Create, BacktraceMap::Create); -} - -static void TestFrameSkipNumbering(create_func_t create_func, map_create_func_t map_create_func) { - std::unique_ptr map(map_create_func(getpid(), false)); - std::unique_ptr backtrace( - create_func(getpid(), android::base::GetThreadId(), map.get())); - backtrace->Unwind(1); - ASSERT_NE(0U, backtrace->NumFrames()); - ASSERT_EQ(0U, backtrace->GetFrame(0)->num); -} - -TEST_F(BacktraceTest, unwind_frame_skip_numbering) { - TestFrameSkipNumbering(Backtrace::Create, BacktraceMap::Create); -} - -#define MAX_LEAK_BYTES (32*1024UL) - -static void CheckForLeak(pid_t pid, pid_t tid) { - std::unique_ptr map(BacktraceMap::Create(pid)); - - // Loop enough that even a small leak should be detectable. - size_t first_allocated_bytes = 0; - size_t last_allocated_bytes = 0; - for (size_t i = 0; i < 4096; i++) { - Backtrace* backtrace = Backtrace::Create(pid, tid, map.get()); - ASSERT_TRUE(backtrace != nullptr); - ASSERT_TRUE(backtrace->Unwind(0)); - VERIFY_NO_ERROR(backtrace->GetError().error_code); - delete backtrace; - - size_t allocated_bytes = mallinfo().uordblks; - if (first_allocated_bytes == 0) { - first_allocated_bytes = allocated_bytes; - } else if (last_allocated_bytes > first_allocated_bytes) { - // Check that the memory did not increase too much over the first loop. - ASSERT_LE(last_allocated_bytes - first_allocated_bytes, MAX_LEAK_BYTES); - } - last_allocated_bytes = allocated_bytes; - } -} - -TEST_F(BacktraceTest, check_for_leak_local) { - CheckForLeak(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD); -} - -TEST_F(BacktraceTest, check_for_leak_local_thread) { - thread_t thread_data = { 0, 0, 0, nullptr }; - pthread_t thread; - ASSERT_TRUE(pthread_create(&thread, nullptr, ThreadLevelRun, &thread_data) == 0); - - // Wait up to 2 seconds for the tid to be set. - ASSERT_TRUE(WaitForNonZero(&thread_data.state, 2)); - - CheckForLeak(BACKTRACE_CURRENT_PROCESS, thread_data.tid); - - // Tell the thread to exit its infinite loop. - android_atomic_acquire_store(0, &thread_data.state); - - ASSERT_TRUE(pthread_join(thread, nullptr) == 0); -} - -TEST_F(BacktraceTest, check_for_leak_remote) { - pid_t pid; - CreateRemoteProcess(&pid); - - CheckForLeak(pid, BACKTRACE_CURRENT_THREAD); - - FinishRemoteProcess(pid); -} diff --git a/libbacktrace/backtrace_testlib.cpp b/libbacktrace/backtrace_testlib.cpp deleted file mode 100644 index fec7d985b..000000000 --- a/libbacktrace/backtrace_testlib.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2013 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 "backtrace_testlib.h" - -void test_loop_forever() { - while (1) - ; -} - -void test_signal_handler(int) { test_loop_forever(); } - -void test_signal_action(int, siginfo_t*, void*) { test_loop_forever(); } - -int test_level_four(int one, int two, int three, int four, void (*callback_func)(void*), - void* data) { - if (callback_func != NULL) { - callback_func(data); - } else { - while (1) - ; - } - return one + two + three + four; -} - -int test_level_three(int one, int two, int three, int four, void (*callback_func)(void*), - void* data) { - return test_level_four(one + 3, two + 6, three + 9, four + 12, callback_func, data) + 3; -} - -int test_level_two(int one, int two, int three, int four, void (*callback_func)(void*), void* data) { - return test_level_three(one + 2, two + 4, three + 6, four + 8, callback_func, data) + 2; -} - -int test_level_one(int one, int two, int three, int four, void (*callback_func)(void*), void* data) { - return test_level_two(one + 1, two + 2, three + 3, four + 4, callback_func, data) + 1; -} - -int test_recursive_call(int level, void (*callback_func)(void*), void* data) { - if (level > 0) { - return test_recursive_call(level - 1, callback_func, data) + level; - } else if (callback_func != NULL) { - callback_func(data); - } else { - while (1) { - } - } - return 0; -} - -typedef struct { - std::vector* ucontext; - volatile int* exit_flag; -} GetContextArg; - -static void GetContextAndExit(void* data) { - GetContextArg* arg = reinterpret_cast(data); - - std::unique_ptr regs(unwindstack::Regs::CreateFromLocal()); - unwindstack::RegsGetLocal(regs.get()); - - ucontext_t ucontext; - memset(&ucontext, 0, sizeof(ucontext)); -#if defined(__arm__) - memcpy(&ucontext.uc_mcontext, regs->RawData(), sizeof(uint32_t) * 16); -#elif defined(__aarch64__) - memcpy(&ucontext.uc_mcontext, regs->RawData(), sizeof(uint64_t) * 33); -#elif defined(__i386__) - uint32_t* reg_data = reinterpret_cast(regs->RawData()); - ucontext.uc_mcontext.gregs[0] = reg_data[15]; - ucontext.uc_mcontext.gregs[1] = reg_data[14]; - ucontext.uc_mcontext.gregs[2] = reg_data[13]; - ucontext.uc_mcontext.gregs[3] = reg_data[12]; - ucontext.uc_mcontext.gregs[4] = reg_data[7]; - ucontext.uc_mcontext.gregs[5] = reg_data[6]; - ucontext.uc_mcontext.gregs[6] = reg_data[5]; - ucontext.uc_mcontext.gregs[7] = reg_data[4]; - ucontext.uc_mcontext.gregs[8] = reg_data[3]; - ucontext.uc_mcontext.gregs[9] = reg_data[2]; - ucontext.uc_mcontext.gregs[10] = reg_data[1]; - ucontext.uc_mcontext.gregs[11] = reg_data[0]; - ucontext.uc_mcontext.gregs[14] = reg_data[8]; - ucontext.uc_mcontext.gregs[15] = reg_data[10]; -#elif defined(__x86_64__) - uint64_t* reg_data = reinterpret_cast(regs->RawData()); - ucontext.uc_mcontext.gregs[0] = reg_data[8]; - ucontext.uc_mcontext.gregs[1] = reg_data[9]; - ucontext.uc_mcontext.gregs[2] = reg_data[10]; - ucontext.uc_mcontext.gregs[3] = reg_data[11]; - ucontext.uc_mcontext.gregs[4] = reg_data[12]; - ucontext.uc_mcontext.gregs[5] = reg_data[13]; - ucontext.uc_mcontext.gregs[6] = reg_data[14]; - ucontext.uc_mcontext.gregs[7] = reg_data[15]; - ucontext.uc_mcontext.gregs[8] = reg_data[5]; - ucontext.uc_mcontext.gregs[9] = reg_data[4]; - ucontext.uc_mcontext.gregs[10] = reg_data[6]; - ucontext.uc_mcontext.gregs[11] = reg_data[3]; - ucontext.uc_mcontext.gregs[12] = reg_data[1]; - ucontext.uc_mcontext.gregs[13] = reg_data[0]; - ucontext.uc_mcontext.gregs[14] = reg_data[2]; - ucontext.uc_mcontext.gregs[15] = reg_data[7]; - ucontext.uc_mcontext.gregs[16] = reg_data[16]; -#endif - - arg->ucontext->resize(sizeof(ucontext)); - memcpy(arg->ucontext->data(), &ucontext, sizeof(ucontext)); - - // Don't touch the stack anymore. - while (*arg->exit_flag == 0) { - } -} - -void test_get_context_and_wait(void* ucontext, volatile int* exit_flag) { - GetContextArg arg; - arg.ucontext = reinterpret_cast*>(ucontext); - arg.exit_flag = exit_flag; - test_level_one(1, 2, 3, 4, GetContextAndExit, &arg); -} diff --git a/libbacktrace/backtrace_testlib.h b/libbacktrace/backtrace_testlib.h deleted file mode 100644 index 9b55e56d4..000000000 --- a/libbacktrace/backtrace_testlib.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2017 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 _LIBBACKTRACE_BACKTRACE_TESTLIB_H -#define _LIBBACKTRACE_BACKTRACE_TESTLIB_H - -#include - -__BEGIN_DECLS - -void test_loop_forever(); -void test_signal_handler(int); -void test_signal_action(int, siginfo_t*, void*); -int test_level_four(int, int, int, int, void (*)(void*), void*); -int test_level_three(int, int, int, int, void (*)(void*), void*); -int test_level_two(int, int, int, int, void (*)(void*), void*); -int test_level_one(int, int, int, int, void (*)(void*), void*); -int test_recursive_call(int, void (*)(void*), void*); -void test_get_context_and_wait(void*, volatile int*); - -__END_DECLS - -#endif // _LIBBACKTRACE_BACKTRACE_TESTLIB_H diff --git a/libbacktrace/include/backtrace/Backtrace.h b/libbacktrace/include/backtrace/Backtrace.h deleted file mode 100644 index 664b531fb..000000000 --- a/libbacktrace/include/backtrace/Backtrace.h +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (C) 2013 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 _BACKTRACE_BACKTRACE_H -#define _BACKTRACE_BACKTRACE_H - -#include -#include - -#include -#include - -#include -#include - -#if defined(__LP64__) -#define PRIPTR "016" PRIx64 -typedef uint64_t word_t; -#else -#define PRIPTR "08" PRIx64 -typedef uint32_t word_t; -#endif - -enum BacktraceUnwindErrorCode : uint32_t { - BACKTRACE_UNWIND_NO_ERROR, - // Something failed while trying to perform the setup to begin the unwind. - BACKTRACE_UNWIND_ERROR_SETUP_FAILED, - // There is no map information to use with the unwind. - BACKTRACE_UNWIND_ERROR_MAP_MISSING, - // An error occurred that indicates a programming error. - BACKTRACE_UNWIND_ERROR_INTERNAL, - // The thread to unwind has disappeared before the unwind can begin. - BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST, - // The thread to unwind has not responded to a signal in a timely manner. - BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT, - // Attempt to do an unsupported operation. - BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION, - // Attempt to do an offline unwind without a context. - BACKTRACE_UNWIND_ERROR_NO_CONTEXT, - // The count of frames exceed MAX_BACKTRACE_FRAMES. - BACKTRACE_UNWIND_ERROR_EXCEED_MAX_FRAMES_LIMIT, - // Failed to read memory. - BACKTRACE_UNWIND_ERROR_ACCESS_MEM_FAILED, - // Failed to read registers. - BACKTRACE_UNWIND_ERROR_ACCESS_REG_FAILED, - // Failed to find a function in debug sections. - BACKTRACE_UNWIND_ERROR_FIND_PROC_INFO_FAILED, - // Failed to execute dwarf instructions in debug sections. - BACKTRACE_UNWIND_ERROR_EXECUTE_DWARF_INSTRUCTION_FAILED, - // Unwind information is incorrect. - BACKTRACE_UNWIND_ERROR_UNWIND_INFO, - // Unwind information stopped due to sp/pc repeating. - BACKTRACE_UNWIND_ERROR_REPEATED_FRAME, - // Unwind information stopped due to invalid elf. - BACKTRACE_UNWIND_ERROR_INVALID_ELF, -}; - -struct BacktraceUnwindError { - enum BacktraceUnwindErrorCode error_code; - - union { - // for BACKTRACE_UNWIND_ERROR_ACCESS_MEM_FAILED - uint64_t addr; - // for BACKTRACE_UNWIND_ERROR_ACCESS_REG_FAILED - uint64_t regno; - } error_info; - - BacktraceUnwindError() : error_code(BACKTRACE_UNWIND_NO_ERROR) {} -}; - -struct backtrace_frame_data_t { - size_t num; // The current fame number. - uint64_t pc; // The absolute pc. - uint64_t rel_pc; // The relative pc. - uint64_t sp; // The top of the stack. - size_t stack_size; // The size of the stack, zero indicate an unknown stack size. - backtrace_map_t map; // The map associated with the given pc. - std::string func_name; // The function name associated with this pc, NULL if not found. - uint64_t func_offset; // pc relative to the start of the function, only valid if func_name is not - // NULL. -}; - -struct backtrace_stackinfo_t { - uint64_t start; - uint64_t end; - const uint8_t* data; -}; - -namespace unwindstack { -class Regs; -} - -class Backtrace { - public: - enum ArchEnum : uint8_t { - ARCH_ARM, - ARCH_ARM64, - ARCH_X86, - ARCH_X86_64, - }; - - static void SetGlobalElfCache(bool enable); - - // Create the correct Backtrace object based on what is to be unwound. - // If pid < 0 or equals the current pid, then the Backtrace object - // corresponds to the current process. - // If pid < 0 or equals the current pid and tid >= 0, then the Backtrace - // object corresponds to a thread in the current process. - // If pid >= 0 and tid < 0, then the Backtrace object corresponds to a - // different process. - // Tracing a thread in a different process is not supported. - // If map is NULL, then create the map and manage it internally. - // 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); - - virtual ~Backtrace(); - - // Get the current stack trace and store in the backtrace_ structure. - virtual bool Unwind(size_t num_ignore_frames, void* context = nullptr) = 0; - - static bool Unwind(unwindstack::Regs* regs, BacktraceMap* back_map, - std::vector* frames, size_t num_ignore_frames, - std::vector* skip_names, 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. - virtual std::string GetFunctionName(uint64_t pc, uint64_t* offset, - const backtrace_map_t* map = nullptr); - - // Fill in the map data associated with the given pc. - virtual void FillInMap(uint64_t pc, backtrace_map_t* map); - - // Read the data at a specific address. - virtual bool ReadWord(uint64_t ptr, word_t* out_value) = 0; - - // Read arbitrary data from a specific address. If a read request would - // span from one map to another, this call only reads up until the end - // of the current map. - // Returns the total number of bytes actually read. - virtual size_t Read(uint64_t addr, uint8_t* buffer, size_t bytes) = 0; - - // Create a string representing the formatted line of backtrace information - // for a single frame. - virtual std::string FormatFrameData(size_t frame_num); - static std::string FormatFrameData(const backtrace_frame_data_t* frame); - - pid_t Pid() const { return pid_; } - pid_t Tid() const { return tid_; } - size_t NumFrames() const { return frames_.size(); } - - const backtrace_frame_data_t* GetFrame(size_t frame_num) { - if (frame_num >= frames_.size()) { - return nullptr; - } - return &frames_[frame_num]; - } - - typedef std::vector::iterator iterator; - iterator begin() { return frames_.begin(); } - iterator end() { return frames_.end(); } - - typedef std::vector::const_iterator const_iterator; - const_iterator begin() const { return frames_.begin(); } - const_iterator end() const { return frames_.end(); } - - BacktraceMap* GetMap() { return map_; } - - BacktraceUnwindError GetError() { return error_; } - - std::string GetErrorString(BacktraceUnwindError error); - - // Set whether to skip frames in libbacktrace/libunwindstack when doing a local unwind. - void SetSkipFrames(bool skip_frames) { skip_frames_ = skip_frames; } - - protected: - Backtrace(pid_t pid, pid_t tid, BacktraceMap* map); - - // The name returned is not demangled, GetFunctionName() takes care of - // demangling the name. - virtual std::string GetFunctionNameRaw(uint64_t pc, uint64_t* offset) = 0; - - virtual bool VerifyReadWordArgs(uint64_t ptr, word_t* out_value); - - bool BuildMap(); - - pid_t pid_; - pid_t tid_; - - BacktraceMap* map_; - bool map_shared_; - - std::vector frames_; - - // Skip frames in libbacktrace/libunwindstack when doing a local unwind. - bool skip_frames_ = true; - - BacktraceUnwindError error_; -}; - -#endif // _BACKTRACE_BACKTRACE_H diff --git a/libbacktrace/include/backtrace/BacktraceMap.h b/libbacktrace/include/backtrace/BacktraceMap.h deleted file mode 100644 index e000a00e2..000000000 --- a/libbacktrace/include/backtrace/BacktraceMap.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (C) 2014 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 _BACKTRACE_BACKTRACE_MAP_H -#define _BACKTRACE_BACKTRACE_MAP_H - -#include -#include -#ifdef _WIN32 -// MINGW does not define these constants. -#define PROT_NONE 0 -#define PROT_READ 0x1 -#define PROT_WRITE 0x2 -#define PROT_EXEC 0x4 -#else -#include -#endif - -#include -#include -#include -#include -#include - -// Forward declaration. -struct backtrace_stackinfo_t; - -// Special flag to indicate a map is in /dev/. However, a map in -// /dev/ashmem/... does not set this flag. -static constexpr int PROT_DEVICE_MAP = 0x8000; -// Special flag to indicate that this map represents an elf file -// created by ART for use with the gdb jit debug interface. -// This should only ever appear in offline maps data. -static constexpr int PROT_JIT_SYMFILE_MAP = 0x4000; - -struct backtrace_map_t { - uint64_t start = 0; - uint64_t end = 0; - uint64_t offset = 0; - uint64_t load_bias = 0; - int flags = 0; - std::string name; - - // Returns `name` if non-empty, or `` otherwise. - std::string Name() const; -}; - -namespace unwindstack { -class Memory; -} - -class BacktraceMap { -public: - // If uncached is true, then parse the current process map as of the call. - // Passing a map created with uncached set to true to Backtrace::Create() - // is unsupported. - static BacktraceMap* Create(pid_t pid, bool uncached = false); - - virtual ~BacktraceMap(); - - class iterator : public std::iterator { - public: - iterator(BacktraceMap* map, size_t index) : map_(map), index_(index) {} - - iterator& operator++() { - index_++; - return *this; - } - const iterator operator++(int increment) { - index_ += increment; - return *this; - } - iterator& operator--() { - index_--; - return *this; - } - const iterator operator--(int decrement) { - index_ -= decrement; - return *this; - } - - bool operator==(const iterator& rhs) { return this->index_ == rhs.index_; } - bool operator!=(const iterator& rhs) { return this->index_ != rhs.index_; } - - const backtrace_map_t* operator*() { - if (index_ >= map_->size()) { - return nullptr; - } - backtrace_map_t* map = &map_->maps_[index_]; - if (map->load_bias == static_cast(-1)) { - map->load_bias = map_->GetLoadBias(index_); - } - return map; - } - - private: - BacktraceMap* map_ = nullptr; - size_t index_ = 0; - }; - - iterator begin() { return iterator(this, 0); } - iterator end() { return iterator(this, maps_.size()); } - - // Fill in the map data structure for the given address. - virtual void FillIn(uint64_t addr, backtrace_map_t* map); - - // Only supported with the new unwinder. - virtual std::string GetFunctionName(uint64_t /*pc*/, uint64_t* /*offset*/) { return ""; } - virtual std::shared_ptr GetProcessMemory() { return nullptr; } - - // The flags returned are the same flags as used by the mmap call. - // The values are PROT_*. - int GetFlags(uint64_t pc) { - backtrace_map_t map; - FillIn(pc, &map); - if (IsValid(map)) { - return map.flags; - } - return PROT_NONE; - } - - bool IsReadable(uint64_t pc) { return GetFlags(pc) & PROT_READ; } - bool IsWritable(uint64_t pc) { return GetFlags(pc) & PROT_WRITE; } - bool IsExecutable(uint64_t pc) { return GetFlags(pc) & PROT_EXEC; } - - // In order to use the iterators on this object, a caller must - // call the LockIterator and UnlockIterator function to guarantee - // that the data does not change while it's being used. - virtual void LockIterator() {} - virtual void UnlockIterator() {} - - size_t size() const { return maps_.size(); } - - virtual bool Build(); - - static inline bool IsValid(const backtrace_map_t& map) { - return map.end > 0; - } - - void SetSuffixesToIgnore(std::vector suffixes) { - suffixes_to_ignore_.insert(suffixes_to_ignore_.end(), suffixes.begin(), suffixes.end()); - } - - const std::vector& GetSuffixesToIgnore() { return suffixes_to_ignore_; } - - // Disabling the resolving of names results in the function name being - // set to an empty string and the function offset being set to zero - // in the frame data when unwinding. - void SetResolveNames(bool resolve) { resolve_names_ = resolve; } - - bool ResolveNames() { return resolve_names_; } - - protected: - BacktraceMap(pid_t pid); - - virtual uint64_t GetLoadBias(size_t /* index */) { return 0; } - - pid_t pid_; - std::deque maps_; - std::vector suffixes_to_ignore_; - bool resolve_names_ = true; -}; - -class ScopedBacktraceMapIteratorLock { -public: - explicit ScopedBacktraceMapIteratorLock(BacktraceMap* map) : map_(map) { - map->LockIterator(); - } - - ~ScopedBacktraceMapIteratorLock() { - map_->UnlockIterator(); - } - -private: - BacktraceMap* map_; -}; - -#endif // _BACKTRACE_BACKTRACE_MAP_H diff --git a/libbacktrace/include/backtrace/backtrace_constants.h b/libbacktrace/include/backtrace/backtrace_constants.h deleted file mode 100644 index 1a2da365a..000000000 --- a/libbacktrace/include/backtrace/backtrace_constants.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2014 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 _BACKTRACE_BACKTRACE_CONSTANTS_H -#define _BACKTRACE_BACKTRACE_CONSTANTS_H - -// When the pid to be traced is set to this value, then trace the current -// process. If the tid value is not BACKTRACE_NO_TID, then the specified -// thread from the current process will be traced. -#define BACKTRACE_CURRENT_PROCESS (-1) -// When the tid to be traced is set to this value, then trace the specified -// current thread of the specified pid. -#define BACKTRACE_CURRENT_THREAD (-1) - -#define MAX_BACKTRACE_FRAMES 256 - -#endif // _BACKTRACE_BACKTRACE_CONSTANTS_H diff --git a/libbacktrace/testdata/arm/libGLESv2_adreno.so b/libbacktrace/testdata/arm/libGLESv2_adreno.so deleted file mode 100644 index 871f6dc89..000000000 Binary files a/libbacktrace/testdata/arm/libGLESv2_adreno.so and /dev/null differ diff --git a/libbacktrace/testdata/arm/libandroid_runtime.so b/libbacktrace/testdata/arm/libandroid_runtime.so deleted file mode 100644 index e4283e63b..000000000 Binary files a/libbacktrace/testdata/arm/libandroid_runtime.so and /dev/null differ diff --git a/libbacktrace/testdata/arm/libart.so b/libbacktrace/testdata/arm/libart.so deleted file mode 100644 index bed8e3595..000000000 Binary files a/libbacktrace/testdata/arm/libart.so and /dev/null differ diff --git a/libbacktrace/testdata/arm/libbacktrace_test_arm_exidx.so b/libbacktrace/testdata/arm/libbacktrace_test_arm_exidx.so deleted file mode 100755 index 454b0320a..000000000 Binary files a/libbacktrace/testdata/arm/libbacktrace_test_arm_exidx.so and /dev/null differ diff --git a/libbacktrace/testdata/arm/libbacktrace_test_debug_frame.so b/libbacktrace/testdata/arm/libbacktrace_test_debug_frame.so deleted file mode 100755 index 787f2cb94..000000000 Binary files a/libbacktrace/testdata/arm/libbacktrace_test_debug_frame.so and /dev/null differ diff --git a/libbacktrace/testdata/arm/libbacktrace_test_gnu_debugdata.so b/libbacktrace/testdata/arm/libbacktrace_test_gnu_debugdata.so deleted file mode 100755 index 9340d9882..000000000 Binary files a/libbacktrace/testdata/arm/libbacktrace_test_gnu_debugdata.so and /dev/null differ diff --git a/libbacktrace/testdata/arm/offline_testdata b/libbacktrace/testdata/arm/offline_testdata deleted file mode 100644 index d5b8f4718..000000000 --- a/libbacktrace/testdata/arm/offline_testdata +++ /dev/null @@ -1,105 +0,0 @@ -pid: 32232 tid: 32233 -map: start: aad19000 end: aad6c000 offset: 0 load_bias: 0 flags: 5 name: /data/backtrace_test32 -map: start: aad6c000 end: aad6e000 offset: 52000 load_bias: 0 flags: 1 name: /data/backtrace_test32 -map: start: aad6e000 end: aad6f000 offset: 54000 load_bias: 0 flags: 3 name: /data/backtrace_test32 -map: start: e7380000 end: e7400000 offset: 0 load_bias: 0 flags: 3 name: [anon:libc_malloc] -map: start: e745f000 end: e7463000 offset: 0 load_bias: 0 flags: 5 name: /system/lib/libnetd_client.so -map: start: e7463000 end: e7464000 offset: 3000 load_bias: 0 flags: 1 name: /system/lib/libnetd_client.so -map: start: e7464000 end: e7465000 offset: 4000 load_bias: 0 flags: 3 name: /system/lib/libnetd_client.so -map: start: e7480000 end: e7500000 offset: 0 load_bias: 0 flags: 3 name: [anon:libc_malloc] -map: start: e7558000 end: e756c000 offset: 0 load_bias: 0 flags: 5 name: /system/lib/libunwind.so -map: start: e756c000 end: e756d000 offset: 0 load_bias: 0 flags: 0 name: -map: start: e756d000 end: e756e000 offset: 14000 load_bias: 0 flags: 1 name: /system/lib/libunwind.so -map: start: e756e000 end: e756f000 offset: 15000 load_bias: 0 flags: 3 name: /system/lib/libunwind.so -map: start: e756f000 end: e75b5000 offset: 0 load_bias: 0 flags: 3 name: [anon:.bss] -map: start: e75d4000 end: e75e1000 offset: 0 load_bias: 0 flags: 5 name: /system/lib/libbase.so -map: start: e75e1000 end: e75e2000 offset: c000 load_bias: 0 flags: 1 name: /system/lib/libbase.so -map: start: e75e2000 end: e75e3000 offset: d000 load_bias: 0 flags: 3 name: /system/lib/libbase.so -map: start: e7600000 end: e7616000 offset: 0 load_bias: 0 flags: 5 name: /system/lib/liblzma.so -map: start: e7616000 end: e7617000 offset: 15000 load_bias: 0 flags: 1 name: /system/lib/liblzma.so -map: start: e7617000 end: e7618000 offset: 16000 load_bias: 0 flags: 3 name: /system/lib/liblzma.so -map: start: e7618000 end: e761d000 offset: 0 load_bias: 0 flags: 3 name: [anon:.bss] -map: start: e7647000 end: e7656000 offset: 0 load_bias: 0 flags: 5 name: /system/lib/liblog.so -map: start: e7656000 end: e7657000 offset: e000 load_bias: 0 flags: 1 name: /system/lib/liblog.so -map: start: e7657000 end: e7658000 offset: f000 load_bias: 0 flags: 3 name: /system/lib/liblog.so -map: start: e7681000 end: e76a2000 offset: 0 load_bias: 0 flags: 5 name: /system/lib/libm.so -map: start: e76a2000 end: e76a3000 offset: 20000 load_bias: 0 flags: 1 name: /system/lib/libm.so -map: start: e76a3000 end: e76a4000 offset: 21000 load_bias: 0 flags: 3 name: /system/lib/libm.so -map: start: e76eb000 end: e76ee000 offset: 0 load_bias: 0 flags: 5 name: /data/libbacktrace_test.so -map: start: e76ee000 end: e76ef000 offset: 2000 load_bias: 0 flags: 1 name: /data/libbacktrace_test.so -map: start: e76ef000 end: e76f0000 offset: 3000 load_bias: 0 flags: 3 name: /data/libbacktrace_test.so -map: start: e7712000 end: e771f000 offset: 0 load_bias: 0 flags: 5 name: /system/lib/libbacktrace.so -map: start: e771f000 end: e7720000 offset: 0 load_bias: 0 flags: 0 name: -map: start: e7720000 end: e7721000 offset: d000 load_bias: 0 flags: 1 name: /system/lib/libbacktrace.so -map: start: e7721000 end: e7722000 offset: e000 load_bias: 0 flags: 3 name: /system/lib/libbacktrace.so -map: start: e7761000 end: e7778000 offset: 0 load_bias: 0 flags: 5 name: /system/lib/libutils.so -map: start: e7778000 end: e7779000 offset: 16000 load_bias: 0 flags: 1 name: /system/lib/libutils.so -map: start: e7779000 end: e777a000 offset: 17000 load_bias: 0 flags: 3 name: /system/lib/libutils.so -map: start: e77a5000 end: e782d000 offset: 0 load_bias: 0 flags: 5 name: /system/lib/libc.so -map: start: e782d000 end: e7831000 offset: 87000 load_bias: 0 flags: 1 name: /system/lib/libc.so -map: start: e7831000 end: e7833000 offset: 8b000 load_bias: 0 flags: 3 name: /system/lib/libc.so -map: start: e7833000 end: e7834000 offset: 0 load_bias: 0 flags: 3 name: [anon:.bss] -map: start: e7834000 end: e7835000 offset: 0 load_bias: 0 flags: 1 name: [anon:.bss] -map: start: e7835000 end: e783b000 offset: 0 load_bias: 0 flags: 3 name: [anon:.bss] -map: start: e7845000 end: e8437000 offset: 0 load_bias: 2b000 flags: 5 name: /system/lib/libLLVM.so -map: start: e8437000 end: e8438000 offset: 0 load_bias: 0 flags: 0 name: -map: start: e8438000 end: e848a000 offset: bf2000 load_bias: 0 flags: 1 name: /system/lib/libLLVM.so -map: start: e848a000 end: e848b000 offset: c44000 load_bias: 0 flags: 3 name: /system/lib/libLLVM.so -map: start: e848b000 end: e84a1000 offset: 0 load_bias: 0 flags: 3 name: [anon:.bss] -map: start: e84eb000 end: e84f7000 offset: 0 load_bias: 0 flags: 5 name: /system/lib/libcutils.so -map: start: e84f7000 end: e84f8000 offset: 0 load_bias: 0 flags: 0 name: -map: start: e84f8000 end: e84f9000 offset: c000 load_bias: 0 flags: 1 name: /system/lib/libcutils.so -map: start: e84f9000 end: e84fa000 offset: d000 load_bias: 0 flags: 3 name: /system/lib/libcutils.so -map: start: e852e000 end: e85b3000 offset: 0 load_bias: 2000 flags: 5 name: /system/lib/libc++.so -map: start: e85b3000 end: e85b4000 offset: 0 load_bias: 0 flags: 0 name: -map: start: e85b4000 end: e85b8000 offset: 85000 load_bias: 0 flags: 1 name: /system/lib/libc++.so -map: start: e85b8000 end: e85b9000 offset: 89000 load_bias: 0 flags: 3 name: /system/lib/libc++.so -map: start: e85b9000 end: e85ba000 offset: 0 load_bias: 0 flags: 3 name: [anon:.bss] -map: start: e85ce000 end: e85cf000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc] -map: start: e85e4000 end: e85e5000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_small_objects] -map: start: e8607000 end: e8608000 offset: 0 load_bias: 0 flags: 1 name: [anon:linker_alloc] -map: start: e8680000 end: e8700000 offset: 0 load_bias: 0 flags: 3 name: [anon:libc_malloc] -map: start: e870d000 end: e8719000 offset: 0 load_bias: 0 flags: 3 name: -map: start: e8719000 end: e871b000 offset: 0 load_bias: 0 flags: 1 name: [anon:atexit handlers] -map: start: e871b000 end: e873b000 offset: 0 load_bias: 0 flags: 32769 name: /dev/__properties__/u:object_r:default_prop:s0 -map: start: e873b000 end: e875b000 offset: 0 load_bias: 0 flags: 32769 name: /dev/__properties__/properties_serial -map: start: e875b000 end: e875c000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_vector] -map: start: e875c000 end: e875d000 offset: 0 load_bias: 0 flags: 3 name: [anon:arc4random data] -map: start: e875d000 end: e875e000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc] -map: start: e875e000 end: e875f000 offset: 0 load_bias: 0 flags: 1 name: [anon:linker_alloc] -map: start: e875f000 end: e877f000 offset: 0 load_bias: 0 flags: 32769 name: /dev/__properties__/u:object_r:debug_prop:s0 -map: start: e877f000 end: e879f000 offset: 0 load_bias: 0 flags: 32769 name: /dev/__properties__/properties_serial -map: start: e879f000 end: e87a0000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_vector] -map: start: e87a0000 end: e87a1000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_small_objects] -map: start: e87a1000 end: e87a2000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_vector] -map: start: e87a2000 end: e87a3000 offset: 0 load_bias: 0 flags: 0 name: -map: start: e87a3000 end: e87a4000 offset: 0 load_bias: 0 flags: 3 name: -map: start: e87a4000 end: e87a5000 offset: 0 load_bias: 0 flags: 0 name: -map: start: e87a5000 end: e87a6000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_lob] -map: start: e87a6000 end: e87a7000 offset: 0 load_bias: 0 flags: 1 name: [anon:linker_alloc] -map: start: e87a7000 end: e87a8000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_vector] -map: start: e87a8000 end: e87a9000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_small_objects] -map: start: e87a9000 end: e87aa000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_vector] -map: start: e87aa000 end: e87ab000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_small_objects] -map: start: e87ab000 end: e87ac000 offset: 0 load_bias: 0 flags: 1 name: [anon:atexit handlers] -map: start: e87ac000 end: e87ad000 offset: 0 load_bias: 0 flags: 0 name: [anon:thread signal stack guard page] -map: start: e87ad000 end: e87af000 offset: 0 load_bias: 0 flags: 3 name: [anon:thread signal stack] -map: start: e87af000 end: e87b0000 offset: 0 load_bias: 0 flags: 3 name: [anon:arc4random data] -map: start: e87b0000 end: e880d000 offset: 0 load_bias: 0 flags: 5 name: /system/bin/linker -map: start: e880d000 end: e880f000 offset: 5c000 load_bias: 0 flags: 1 name: /system/bin/linker -map: start: e880f000 end: e8810000 offset: 5e000 load_bias: 0 flags: 3 name: /system/bin/linker -map: start: e8810000 end: e8812000 offset: 0 load_bias: 0 flags: 3 name: -map: start: e8812000 end: e8813000 offset: 0 load_bias: 0 flags: 1 name: -map: start: e8813000 end: e8815000 offset: 0 load_bias: 0 flags: 3 name: -map: start: ff886000 end: ff8a9000 offset: 0 load_bias: 0 flags: 3 name: [stack] -map: start: ffff0000 end: ffff1000 offset: 0 load_bias: 0 flags: 5 name: [vectors] -ucontext: 104 000000000000000000000000000000000000000000000000000000000000000034868affdc8871e8150000001c0000001c000000150000000e00000007000000e08771e834868aff2354d2aa24f9ffffdc8871e88c8771e875b86ee778ba6ee70000000000000000 -stack: start: e8715000 end: e8719000 size: 16384 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dc8871e87dba6ee734868affdc8871e8dc8871e85dba6ee7070000000e000000150000001c000000dc8871e85dba6ee71c000000150000000e00000007000000100000000c0000000800000004000000ddb86ee75dba6ee7dc8871e804000000080000000c00000010000000dc8871e85dba6ee7100000000c000000080000000400000008000000060000000400000002000000288871e835b96ee75dba6ee7dc8871e802000000040000000600000008000000dc8871e85dba6ee70800000006000000040000000200000004000000030000000200000001000000708871e88db96ee75dba6ee7dc8871e801000000020000000300000004000000dc8871e85dba6ee70400000003000000020000000100000004000000208971e8208971e878000000e87d00003dba6ee75dba6ee7dc8871e878000000c5807ce7fc7183e734868aff78868aff78868aff34868aff34868aff78868affe0879437208971e84154d2aa0020000034868aff34868aff34868aff78000000c9b87ee7b1b87ee7a3f47be7288971e8b1b87ee7208971e800000000f83481e800000000e97d0000e87d000000000000005071e82039000000100000000000000000000000000000000000002354d2aa34868aff00000000002071e801000000000000000000000000000000708971e8208971e8000000000000000000000000e0879437000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -function: start: 0 end: e76eb835 name: unknown_start -function: start: e76eb835 end: e76eb88d name: test_level_four -function: start: e76eb88d end: e76eb8e5 name: test_level_three -function: start: e76eb8e5 end: e76eb93d name: test_level_two -function: start: e76eb93d end: e76eb995 name: test_level_one -function: start: e76eb995 end: e76eb9f1 name: test_recursive_call -function: start: e76eb9f1 end: ffffffff name: test_get_context_and_wait -function: start: ffffffff end: ffffffff name: unknown_end diff --git a/libbacktrace/testdata/arm/offline_testdata_for_libGLESv2_adreno b/libbacktrace/testdata/arm/offline_testdata_for_libGLESv2_adreno deleted file mode 100644 index d7c186e6f..000000000 --- a/libbacktrace/testdata/arm/offline_testdata_for_libGLESv2_adreno +++ /dev/null @@ -1,6 +0,0 @@ -pid: 7288 tid: 31656 -ucontext: 104 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f017cc00000000356241cc0000000000000000 -map: start: cc361000 end: cc758000 offset: 0 load_bias: 9000 flags: 5 name: /vendor/lib/egl/libGLESv2_adreno.so -stack: start: cc17f234 end: cc17f258 size: 36 0000000000000000000000000000000000000000000000000000000000000000b36141cc -function: start: be1f0 end: be304 name: EsxContext::Clear(unsigned int, unsigned int, unsigned int, EsxClearValues*) -function: start: be058 end: be1f0 name: EsxContext::ClearBuffersForDebug() diff --git a/libbacktrace/testdata/arm/offline_testdata_for_libandroid_runtime b/libbacktrace/testdata/arm/offline_testdata_for_libandroid_runtime deleted file mode 100644 index 54f352520..000000000 --- a/libbacktrace/testdata/arm/offline_testdata_for_libandroid_runtime +++ /dev/null @@ -1,6 +0,0 @@ -pid: 7288 tid: 31656 -ucontext: 104 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003069fed80000000049dcf6f10000000000000000 -map: start: f1f10000 end: f2049000 offset: 0 load_bias: 10000 flags: 5 name: /system/lib/libandroid_runtime.so -stack: start: d8fe6948 end: d8fe6958 size: 16 000000000000000000000000e7dcf6f1 -function: start: 6dbf9 end: 6dce5 name: android::AndroidRuntime::javaThreadShell -function: start: 6dce5 end: 6dd79 name: android::AndroidRuntime::javaCreateThreadEtc diff --git a/libbacktrace/testdata/arm/offline_testdata_for_libart b/libbacktrace/testdata/arm/offline_testdata_for_libart deleted file mode 100644 index c1369ff6c..000000000 --- a/libbacktrace/testdata/arm/offline_testdata_for_libart +++ /dev/null @@ -1,10 +0,0 @@ -pid: 32232 tid: 32233 -ucontext: 104 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006473602451b3e2e700000000d82fd1ff5600000000908eec00000000d42dd1ff00000000c02dd1ff617171e9617171e90000000000000000 -map: start: e9380000 end: e9766000 offset: 0 load_bias: b000 flags: 5 name: /system/lib/libart.so -stack: start: ffd12dc0 end: ffd1306c size: 684 00000000000c5024070000000300000005070a0a0100000051b3e2e700000000d82fd1ff560000004c2ed1ff000000000000000081b771e9d82fd1ff000000004c2ed1ff0c2ed1ff40a8d27024bf76e900908eec000000000834d1ff0000000000000000000000000d000000050000000000000000000000080000000101d1ff44b8bfeb4b0000000000000000000000e8b8952400000000fc2ed1ff4fb3e2e7bc49ac6f00908eecb02ed1ffd82fd1ff040000008c908eec942fd1ffd5c141e9d82fd1ff4fb3e2e7542fd1ff336c68e940000000400000007030d1fff031d1ff00000000bc49ac6f5c30d1ff942fd1ff842fd1ffd82fd1ff00000000b8f1786f4fb3e2e7610d67e9d82fd1ff4fb3e2e77880adeb7980adeb7a80adeb7b80adeb7c80adeb7d80adeb7e80adeb7f80adeb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007430d1ff02000000e8b89524e8d895240200000000908eec5c30d1ffbc49ac6f4fb3e2e74030d1ffe8d8952400000000b8f1786fbc49ac6f332367e94fb3e2e701000000637171e9637171e9000000005c30d1ff8430d1ffe0c08bec882fd1ff4fb3e2e70200000004000000942fd1ffe8b8952400908eec58d8952458d895247fbd69e90500000000400fe40100000000908eec58d89524060000009c86bd6f6b876fe900908eece0c08bec00008eec0000000000000000000000000000000044b8bfeb4b000000009be86f040000000038d1ff01000000c8e7446f060000000000000000908eec30d89524e8b895249c86bd6f7893476f00908eec00000000358c6fe970400fe4116e71e9a0285a6fa4d49c6f4489bd6f30d8952458d89524e8d8952400908eeca431d1ff2c31d1ffb75861e90100000000908eec30528bec409181e958d89524 -function: start: 3a2121 end: 3a217a name: art_quick_invoke_stub_internal -function: start: 3a66a5 end: 3a6787 name: art_quick_invoke_static_stub -function: start: a7129 end: a72f1 name: art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*) -function: start: 2fbd35 end: 2fc789 name: art::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, art::ArgArray*, art::JValue*, char const*) -function: start: 2fcf75 end: 2fd88d name: art::InvokeMethod(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jobject*, _jobject*, unsigned int) -function: start: 2a089d end: 2a08bb name: art::Method_invoke(_JNIEnv*, _jobject*, _jobject*, _jobject*) diff --git a/libbacktrace/testdata/arm64/eglSubDriverAndroid.so b/libbacktrace/testdata/arm64/eglSubDriverAndroid.so deleted file mode 100644 index 10ce06bfd..000000000 Binary files a/libbacktrace/testdata/arm64/eglSubDriverAndroid.so and /dev/null differ diff --git a/libbacktrace/testdata/arm64/libbacktrace_test_eh_frame.so b/libbacktrace/testdata/arm64/libbacktrace_test_eh_frame.so deleted file mode 100755 index 880f33796..000000000 Binary files a/libbacktrace/testdata/arm64/libbacktrace_test_eh_frame.so and /dev/null differ diff --git a/libbacktrace/testdata/arm64/libskia.so b/libbacktrace/testdata/arm64/libskia.so deleted file mode 100644 index ef1a6a185..000000000 Binary files a/libbacktrace/testdata/arm64/libskia.so and /dev/null differ diff --git a/libbacktrace/testdata/arm64/offline_testdata b/libbacktrace/testdata/arm64/offline_testdata deleted file mode 100644 index cee9f7202..000000000 --- a/libbacktrace/testdata/arm64/offline_testdata +++ /dev/null @@ -1,107 +0,0 @@ -pid: 32438 tid: 32439 -map: start: 557066e000 end: 55706ee000 offset: 0 load_bias: 0 flags: 5 name: /data/backtrace_test64 -map: start: 55706ef000 end: 55706f2000 offset: 80000 load_bias: 0 flags: 1 name: /data/backtrace_test64 -map: start: 55706f2000 end: 55706f3000 offset: 83000 load_bias: 0 flags: 3 name: /data/backtrace_test64 -map: start: 7014200000 end: 7014600000 offset: 0 load_bias: 0 flags: 3 name: [anon:libc_malloc] -map: start: 701464c000 end: 701465c000 offset: 0 load_bias: 0 flags: 5 name: /system/lib64/libcutils.so -map: start: 701465c000 end: 701465d000 offset: 0 load_bias: 0 flags: 0 name: -map: start: 701465d000 end: 701465e000 offset: 10000 load_bias: 0 flags: 1 name: /system/lib64/libcutils.so -map: start: 701465e000 end: 701465f000 offset: 11000 load_bias: 0 flags: 3 name: /system/lib64/libcutils.so -map: start: 7014691000 end: 70146b5000 offset: 0 load_bias: 0 flags: 5 name: /system/lib64/liblzma.so -map: start: 70146b5000 end: 70146b6000 offset: 23000 load_bias: 0 flags: 1 name: /system/lib64/liblzma.so -map: start: 70146b6000 end: 70146b7000 offset: 24000 load_bias: 0 flags: 3 name: /system/lib64/liblzma.so -map: start: 70146b7000 end: 70146bc000 offset: 0 load_bias: 0 flags: 3 name: [anon:.bss] -map: start: 70146c9000 end: 70158b5000 offset: 0 load_bias: af000 flags: 5 name: /system/lib64/libLLVM.so -map: start: 70158b5000 end: 701596b000 offset: 11eb000 load_bias: 0 flags: 1 name: /system/lib64/libLLVM.so -map: start: 701596b000 end: 701596c000 offset: 12a1000 load_bias: 0 flags: 3 name: /system/lib64/libLLVM.so -map: start: 701596c000 end: 701599f000 offset: 0 load_bias: 0 flags: 3 name: [anon:.bss] -map: start: 70159c2000 end: 70159f9000 offset: 0 load_bias: 0 flags: 5 name: /system/lib64/libm.so -map: start: 70159f9000 end: 70159fa000 offset: 36000 load_bias: 0 flags: 1 name: /system/lib64/libm.so -map: start: 70159fa000 end: 70159fb000 offset: 37000 load_bias: 0 flags: 3 name: /system/lib64/libm.so -map: start: 7015a1e000 end: 7015a2e000 offset: 0 load_bias: 0 flags: 5 name: /system/lib64/libbacktrace.so -map: start: 7015a2e000 end: 7015a2f000 offset: f000 load_bias: 0 flags: 1 name: /system/lib64/libbacktrace.so -map: start: 7015a2f000 end: 7015a30000 offset: 10000 load_bias: 0 flags: 3 name: /system/lib64/libbacktrace.so -map: start: 7015a5e000 end: 7015a7d000 offset: 0 load_bias: 1000 flags: 5 name: /system/lib64/libutils.so -map: start: 7015a7d000 end: 7015a7e000 offset: 0 load_bias: 0 flags: 0 name: -map: start: 7015a7e000 end: 7015a7f000 offset: 1f000 load_bias: 0 flags: 1 name: /system/lib64/libutils.so -map: start: 7015a7f000 end: 7015a80000 offset: 20000 load_bias: 0 flags: 3 name: /system/lib64/libutils.so -map: start: 7015a99000 end: 7015b6d000 offset: 0 load_bias: 9000 flags: 5 name: /system/lib64/libc++.so -map: start: 7015b6d000 end: 7015b6e000 offset: 0 load_bias: 0 flags: 0 name: -map: start: 7015b6e000 end: 7015b76000 offset: d4000 load_bias: 0 flags: 1 name: /system/lib64/libc++.so -map: start: 7015b76000 end: 7015b77000 offset: dc000 load_bias: 0 flags: 3 name: /system/lib64/libc++.so -map: start: 7015b77000 end: 7015b7a000 offset: 0 load_bias: 0 flags: 3 name: [anon:.bss] -map: start: 7015b81000 end: 7015b92000 offset: 0 load_bias: 0 flags: 5 name: /system/lib64/liblog.so -map: start: 7015b92000 end: 7015b93000 offset: 10000 load_bias: 0 flags: 1 name: /system/lib64/liblog.so -map: start: 7015b93000 end: 7015b94000 offset: 11000 load_bias: 0 flags: 3 name: /system/lib64/liblog.so -map: start: 7015be3000 end: 7015ca3000 offset: 0 load_bias: 0 flags: 5 name: /system/lib64/libc.so -map: start: 7015ca3000 end: 7015ca9000 offset: bf000 load_bias: 0 flags: 1 name: /system/lib64/libc.so -map: start: 7015ca9000 end: 7015cab000 offset: c5000 load_bias: 0 flags: 3 name: /system/lib64/libc.so -map: start: 7015cab000 end: 7015cac000 offset: 0 load_bias: 0 flags: 3 name: [anon:.bss] -map: start: 7015cac000 end: 7015cad000 offset: 0 load_bias: 0 flags: 1 name: [anon:.bss] -map: start: 7015cad000 end: 7015cb4000 offset: 0 load_bias: 0 flags: 3 name: [anon:.bss] -map: start: 7015cf5000 end: 7015cf6000 offset: 0 load_bias: 0 flags: 5 name: /data/libbacktrace_test.so -map: start: 7015cf6000 end: 7015cf7000 offset: 0 load_bias: 0 flags: 1 name: /data/libbacktrace_test.so -map: start: 7015cf7000 end: 7015cf8000 offset: 1000 load_bias: 0 flags: 3 name: /data/libbacktrace_test.so -map: start: 7015d1f000 end: 7015d39000 offset: 0 load_bias: 0 flags: 5 name: /system/lib64/libunwind.so -map: start: 7015d39000 end: 7015d3a000 offset: 19000 load_bias: 0 flags: 1 name: /system/lib64/libunwind.so -map: start: 7015d3a000 end: 7015d3b000 offset: 1a000 load_bias: 0 flags: 3 name: /system/lib64/libunwind.so -map: start: 7015d3b000 end: 7015da4000 offset: 0 load_bias: 0 flags: 3 name: [anon:.bss] -map: start: 7015de8000 end: 7015df7000 offset: 0 load_bias: 0 flags: 5 name: /system/lib64/libbase.so -map: start: 7015df7000 end: 7015df8000 offset: 0 load_bias: 0 flags: 0 name: -map: start: 7015df8000 end: 7015df9000 offset: f000 load_bias: 0 flags: 1 name: /system/lib64/libbase.so -map: start: 7015df9000 end: 7015dfa000 offset: 10000 load_bias: 0 flags: 3 name: /system/lib64/libbase.so -map: start: 7015e35000 end: 7015e36000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc] -map: start: 7015e4f000 end: 7015e50000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_small_objects] -map: start: 7015f11000 end: 7015f13000 offset: 0 load_bias: 0 flags: 5 name: /system/lib64/libnetd_client.so -map: start: 7015f13000 end: 7015f14000 offset: 1000 load_bias: 0 flags: 1 name: /system/lib64/libnetd_client.so -map: start: 7015f14000 end: 7015f15000 offset: 2000 load_bias: 0 flags: 3 name: /system/lib64/libnetd_client.so -map: start: 7015f6c000 end: 7015f79000 offset: 0 load_bias: 0 flags: 3 name: -map: start: 7015f79000 end: 7015f99000 offset: 0 load_bias: 0 flags: 32769 name: /dev/__properties__/u:object_r:default_prop:s0 -map: start: 7015f99000 end: 7015f9a000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_vector] -map: start: 7015f9a000 end: 7015f9b000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_small_objects] -map: start: 7015fa6000 end: 7015fa7000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_vector] -map: start: 7015fa8000 end: 7015fa9000 offset: 0 load_bias: 0 flags: 1 name: [anon:linker_alloc] -map: start: 7015faf000 end: 7015fcf000 offset: 0 load_bias: 0 flags: 32769 name: /dev/__properties__/properties_serial -map: start: 7015fcf000 end: 7015fd0000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_vector] -map: start: 7015fd0000 end: 7015fd1000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_small_objects] -map: start: 7015fd1000 end: 7015fd2000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_vector] -map: start: 7015fd4000 end: 7015fd7000 offset: 0 load_bias: 0 flags: 3 name: -map: start: 7015fd7000 end: 7015fdb000 offset: 0 load_bias: 0 flags: 1 name: [anon:atexit handlers] -map: start: 7015fdb000 end: 7015fdc000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc] -map: start: 7015fdc000 end: 7015fdd000 offset: 0 load_bias: 0 flags: 3 name: -map: start: 7015fdd000 end: 7015fde000 offset: 0 load_bias: 0 flags: 1 name: [anon:linker_alloc] -map: start: 7015fde000 end: 7015ffe000 offset: 0 load_bias: 0 flags: 32769 name: /dev/__properties__/u:object_r:debug_prop:s0 -map: start: 7015ffe000 end: 701601e000 offset: 0 load_bias: 0 flags: 32769 name: /dev/__properties__/properties_serial -map: start: 701601e000 end: 701601f000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_vector] -map: start: 701601f000 end: 7016020000 offset: 0 load_bias: 0 flags: 0 name: -map: start: 7016020000 end: 7016021000 offset: 0 load_bias: 0 flags: 3 name: -map: start: 7016021000 end: 7016022000 offset: 0 load_bias: 0 flags: 0 name: -map: start: 7016022000 end: 7016023000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_lob] -map: start: 7016023000 end: 7016025000 offset: 0 load_bias: 0 flags: 1 name: [anon:linker_alloc] -map: start: 7016025000 end: 7016026000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_small_objects] -map: start: 7016026000 end: 7016027000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_vector] -map: start: 7016027000 end: 7016028000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_small_objects] -map: start: 7016028000 end: 7016029000 offset: 0 load_bias: 0 flags: 3 name: [anon:arc4random data] -map: start: 7016029000 end: 701602a000 offset: 0 load_bias: 0 flags: 3 name: [anon:linker_alloc_small_objects] -map: start: 701602a000 end: 701602b000 offset: 0 load_bias: 0 flags: 1 name: [anon:atexit handlers] -map: start: 701602b000 end: 701602c000 offset: 0 load_bias: 0 flags: 0 name: [anon:thread signal stack guard page] -map: start: 701602c000 end: 7016030000 offset: 0 load_bias: 0 flags: 3 name: [anon:thread signal stack] -map: start: 7016030000 end: 7016031000 offset: 0 load_bias: 0 flags: 3 name: [anon:arc4random data] -map: start: 7016031000 end: 7016033000 offset: 0 load_bias: 0 flags: 5 name: [vdso] -map: start: 7016033000 end: 70160dd000 offset: 0 load_bias: 0 flags: 5 name: /system/bin/linker64 -map: start: 70160dd000 end: 70160e0000 offset: a9000 load_bias: 0 flags: 1 name: /system/bin/linker64 -map: start: 70160e0000 end: 70160e1000 offset: ac000 load_bias: 0 flags: 3 name: /system/bin/linker64 -map: start: 70160e1000 end: 70160e4000 offset: 0 load_bias: 0 flags: 3 name: -map: start: 70160e4000 end: 70160e5000 offset: 0 load_bias: 0 flags: 1 name: -map: start: 70160e5000 end: 70160e8000 offset: 0 load_bias: 0 flags: 3 name: -map: start: 7fd8baf000 end: 7fd8be6000 offset: 0 load_bias: 0 flags: 3 name: [stack] -ucontext: 464 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f838bed87f0000000e0000000000000015000000000000001c00000000000000ec59cf1570000000b863fd15700000005064fd15700000000000000000000000ec59cf15700000000200000000000000b863fd1570000000144abed87f0000006064fd15700000005064fd157000000000010000000000005826bed87f000000d86fcf15700000006057cf157000000000000000000000005064fd15700000005064fd15700000005064fd1570000000b67e00000000000040fd677055000000d064fd15700000000030fd157000000002000000000000000100000000000000fcb58a56000000000063fd15700000009857cf1570000000c062fd15700000001c5acf157000000000000000000000000000000000000000 -stack: start: 7015fd3000 end: 7015fd7000 size: 16384 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f838bed87f0000004038bed87f000000b863fd1570000000b863fd1570000000b863fd1570000000ec59cf15700000001c000000150000000e000000070000003063fd15700000001c58cf1570000000b863fd1570000000ec59cf1570000000100000000c00000008000000040000006063fd15700000007c58cf1570000000b863fd1570000000ec59cf1570000000080000000600000004000000020000009063fd1570000000dc58cf1570000000b863fd1570000000ec59cf157000000004000000030000000200000001000000d063fd1570000000c459cf15700000000100000000000000144abed87f0000004038bed87f0000004038bed87f000000144abed87f000000d3aec914588f4bcd1064fd157000000074fd6770550000004038bed87f0000004038bed87f000000ec84c41570000000e484c41570000000c484c4157000000000000000000000004064fd15700000004015c01570000000b67e0000000000000000000000000000705a0e1670000000185b0e167000000000000000000000000000000000000000705a0e16700000000000000000000000b77e0000b67e000000000000550000000030fd157000000050340000000000000010000000000000000000000000000000b222147000000000102a14700000000000000000000000000000000000000040fd6770550000004038bed87f000000000000000000000000a0fa1570000000010000000000000000000000000000000000000000000000e864fd15700000005064fd1570000000000000000000000000000000000000000000000000000000d3aec914588f4bcd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -function: start: 0 end: 7015cf5760 name: unknown_start -function: start: 7015cf5760 end: 7015cf57cc name: test_level_four -function: start: 7015cf57cc end: 7015cf582c name: test_level_three -function: start: 7015cf582c end: 7015cf588c name: test_level_two -function: start: 7015cf588c end: 7015cf58ec name: test_level_one -function: start: 7015cf58ec end: 7015cf5968 name: test_recursive_call -function: start: 7015cf5968 end: ffffffffffffffff name: test_get_context_and_wait -function: start: ffffffffffffffff end: ffffffffffffffff name: unknown_end diff --git a/libbacktrace/testdata/arm64/offline_testdata_for_eglSubDriverAndroid b/libbacktrace/testdata/arm64/offline_testdata_for_eglSubDriverAndroid deleted file mode 100644 index 673e30e1d..000000000 --- a/libbacktrace/testdata/arm64/offline_testdata_for_eglSubDriverAndroid +++ /dev/null @@ -1,6 +0,0 @@ -pid: 12276 tid: 12303 -map: start: 7b8c01e000 end: 7b8c030000 offset: 0 load_bias: 0 flags: 5 name: /vendor/lib64/egl/eglSubDriverAndroid.so -ucontext: 464 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004070158c7b00000000000000000000001070158c7b000000647f028c7b00000000000000000000000000000000000000 -stack: start: 7b8c157020 end: 7b8c157050 size: 48 00000000000000000000000000000000000000000000000000000000000000000000000000000000547e028c7b000000 -function: start: 9ed8 end: a1b0 name: EglAndroidWindowSurface::Initialize(EglAndroidConfig*, int const*) -function: start: 9dcc end: 9ed8 name: EglAndroidWindowSurface::Create(ANativeWindow*, EglAndroidConfig*, EglAndroidWindowSurface**, int const*) diff --git a/libbacktrace/testdata/arm64/offline_testdata_for_libskia b/libbacktrace/testdata/arm64/offline_testdata_for_libskia deleted file mode 100644 index da820c0bd..000000000 --- a/libbacktrace/testdata/arm64/offline_testdata_for_libskia +++ /dev/null @@ -1,6 +0,0 @@ -pid: 32232 tid: 32233 -map: start: 7c24c80000 end: 7c25413000 offset: 0 load_bias: 5f000 flags: 5 name: /system/lib64/libskia.so -ucontext: 464 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b04b158c7b0000000000000000000000504b158c7b0000000c9a18257c00000000000000000000000000000000000000 -stack: start: 7b8c154b80 end: 7b8c154bc0 size: 64 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ec43f2247c000000 -function: start: 568970 end: 568c08 name: SkScalerContext_FreeType::generateImage(SkGlyph const&) -function: start: 30330c end: 3044b0 name: SkScalerContext::getImage(SkGlyph const&) diff --git a/libbacktrace/testdata/x86/libbacktrace_test_debug_frame.so b/libbacktrace/testdata/x86/libbacktrace_test_debug_frame.so deleted file mode 100755 index a6f3b29f3..000000000 Binary files a/libbacktrace/testdata/x86/libbacktrace_test_debug_frame.so and /dev/null differ diff --git a/libbacktrace/testdata/x86/libbacktrace_test_gnu_debugdata.so b/libbacktrace/testdata/x86/libbacktrace_test_gnu_debugdata.so deleted file mode 100755 index ea58dfbe5..000000000 Binary files a/libbacktrace/testdata/x86/libbacktrace_test_gnu_debugdata.so and /dev/null differ diff --git a/libbacktrace/testdata/x86/offline_testdata b/libbacktrace/testdata/x86/offline_testdata deleted file mode 100644 index 920b3385b..000000000 --- a/libbacktrace/testdata/x86/offline_testdata +++ /dev/null @@ -1,82 +0,0 @@ -pid: 34545 tid: 34546 -map: start: f705a000 end: f705c000 offset: 0 load_bias: 0 flags: 3 name: -map: start: f705c000 end: f707f000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib/liblzma.so -map: start: f707f000 end: f7080000 offset: 22000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib/liblzma.so -map: start: f7080000 end: f7081000 offset: 23000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib/liblzma.so -map: start: f7081000 end: f7088000 offset: 0 load_bias: 0 flags: 3 name: -map: start: f7088000 end: f7230000 offset: 0 load_bias: 0 flags: 5 name: /lib/i386-linux-gnu/libc-2.19.so -map: start: f7230000 end: f7231000 offset: 1a8000 load_bias: 0 flags: 0 name: /lib/i386-linux-gnu/libc-2.19.so -map: start: f7231000 end: f7233000 offset: 1a8000 load_bias: 0 flags: 1 name: /lib/i386-linux-gnu/libc-2.19.so -map: start: f7233000 end: f7234000 offset: 1aa000 load_bias: 0 flags: 3 name: /lib/i386-linux-gnu/libc-2.19.so -map: start: f7234000 end: f7237000 offset: 0 load_bias: 0 flags: 3 name: -map: start: f7237000 end: f727b000 offset: 0 load_bias: 0 flags: 5 name: /lib/i386-linux-gnu/libm-2.19.so -map: start: f727b000 end: f727c000 offset: 43000 load_bias: 0 flags: 1 name: /lib/i386-linux-gnu/libm-2.19.so -map: start: f727c000 end: f727d000 offset: 44000 load_bias: 0 flags: 3 name: /lib/i386-linux-gnu/libm-2.19.so -map: start: f727d000 end: f7299000 offset: 0 load_bias: 0 flags: 5 name: /lib/i386-linux-gnu/libgcc_s.so.1 -map: start: f7299000 end: f729a000 offset: 1b000 load_bias: 0 flags: 3 name: /lib/i386-linux-gnu/libgcc_s.so.1 -map: start: f729a000 end: f72b8000 offset: 0 load_bias: 0 flags: 5 name: /lib/i386-linux-gnu/libtinfo.so.5.9 -map: start: f72b8000 end: f72b9000 offset: 1e000 load_bias: 0 flags: 0 name: /lib/i386-linux-gnu/libtinfo.so.5.9 -map: start: f72b9000 end: f72bb000 offset: 1e000 load_bias: 0 flags: 1 name: /lib/i386-linux-gnu/libtinfo.so.5.9 -map: start: f72bb000 end: f72bc000 offset: 20000 load_bias: 0 flags: 3 name: /lib/i386-linux-gnu/libtinfo.so.5.9 -map: start: f72bc000 end: f72bd000 offset: 0 load_bias: 0 flags: 3 name: -map: start: f72bd000 end: f72e0000 offset: 0 load_bias: 0 flags: 5 name: /lib/i386-linux-gnu/libncurses.so.5.9 -map: start: f72e0000 end: f72e1000 offset: 22000 load_bias: 0 flags: 1 name: /lib/i386-linux-gnu/libncurses.so.5.9 -map: start: f72e1000 end: f72e2000 offset: 23000 load_bias: 0 flags: 3 name: /lib/i386-linux-gnu/libncurses.so.5.9 -map: start: f72e2000 end: f72e5000 offset: 0 load_bias: 0 flags: 5 name: /lib/i386-linux-gnu/libdl-2.19.so -map: start: f72e5000 end: f72e6000 offset: 2000 load_bias: 0 flags: 1 name: /lib/i386-linux-gnu/libdl-2.19.so -map: start: f72e6000 end: f72e7000 offset: 3000 load_bias: 0 flags: 3 name: /lib/i386-linux-gnu/libdl-2.19.so -map: start: f72e7000 end: f72ee000 offset: 0 load_bias: 0 flags: 5 name: /lib/i386-linux-gnu/librt-2.19.so -map: start: f72ee000 end: f72ef000 offset: 6000 load_bias: 0 flags: 1 name: /lib/i386-linux-gnu/librt-2.19.so -map: start: f72ef000 end: f72f0000 offset: 7000 load_bias: 0 flags: 3 name: /lib/i386-linux-gnu/librt-2.19.so -map: start: f72f0000 end: f7308000 offset: 0 load_bias: 0 flags: 5 name: /lib/i386-linux-gnu/libpthread-2.19.so -map: start: f7308000 end: f7309000 offset: 18000 load_bias: 0 flags: 1 name: /lib/i386-linux-gnu/libpthread-2.19.so -map: start: f7309000 end: f730a000 offset: 19000 load_bias: 0 flags: 3 name: /lib/i386-linux-gnu/libpthread-2.19.so -map: start: f730a000 end: f730c000 offset: 0 load_bias: 0 flags: 3 name: -map: start: f732f000 end: f7331000 offset: 0 load_bias: 0 flags: 3 name: -map: start: f7331000 end: f7425000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libc++.so -map: start: f7425000 end: f7426000 offset: f4000 load_bias: 0 flags: 0 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libc++.so -map: start: f7426000 end: f742a000 offset: f4000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libc++.so -map: start: f742a000 end: f742b000 offset: f8000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libc++.so -map: start: f742b000 end: f742d000 offset: 0 load_bias: 0 flags: 3 name: -map: start: f742d000 end: f7446000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libunwind.so -map: start: f7446000 end: f7447000 offset: 18000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libunwind.so -map: start: f7447000 end: f7448000 offset: 19000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libunwind.so -map: start: f7448000 end: f7457000 offset: 0 load_bias: 0 flags: 3 name: -map: start: f7457000 end: f745c000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib/liblog.so -map: start: f745c000 end: f745d000 offset: 4000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib/liblog.so -map: start: f745d000 end: f745e000 offset: 5000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib/liblog.so -map: start: f745e000 end: f7467000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libcutils.so -map: start: f7467000 end: f7468000 offset: 9000 load_bias: 0 flags: 0 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libcutils.so -map: start: f7468000 end: f7469000 offset: 9000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libcutils.so -map: start: f7469000 end: f746a000 offset: a000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libcutils.so -map: start: f746a000 end: f7477000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbase.so -map: start: f7477000 end: f7478000 offset: c000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbase.so -map: start: f7478000 end: f7479000 offset: d000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbase.so -map: start: f7479000 end: f7489000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbacktrace.so -map: start: f7489000 end: f748a000 offset: f000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbacktrace.so -map: start: f748a000 end: f748b000 offset: 10000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbacktrace.so -map: start: f748b000 end: f748c000 offset: 0 load_bias: 0 flags: 3 name: -map: start: f748c000 end: f748d000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbacktrace_test.so -map: start: f748d000 end: f748e000 offset: 0 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbacktrace_test.so -map: start: f748e000 end: f748f000 offset: 1000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbacktrace_test.so -map: start: f748f000 end: f7491000 offset: 0 load_bias: 0 flags: 3 name: -map: start: f7491000 end: f74b1000 offset: 0 load_bias: 0 flags: 5 name: /lib/i386-linux-gnu/ld-2.19.so -map: start: f74b1000 end: f74b2000 offset: 1f000 load_bias: 0 flags: 1 name: /lib/i386-linux-gnu/ld-2.19.so -map: start: f74b2000 end: f74b3000 offset: 20000 load_bias: 0 flags: 3 name: /lib/i386-linux-gnu/ld-2.19.so -map: start: f74b3000 end: f77c6000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/nativetest/backtrace_test/backtrace_test32 -map: start: f77c6000 end: f77c7000 offset: 0 load_bias: ffffe000 flags: 5 name: [vdso] -map: start: f77c7000 end: f77d4000 offset: 313000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/nativetest/backtrace_test/backtrace_test32 -map: start: f77d4000 end: f77d5000 offset: 320000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/nativetest/backtrace_test/backtrace_test32 -map: start: f77d5000 end: f77d6000 offset: 0 load_bias: 0 flags: 3 name: -map: start: f7ec6000 end: f7ee7000 offset: 0 load_bias: 0 flags: 3 name: [heap] -map: start: ffe4e000 end: ffe70000 offset: 0 load_bias: 0 flags: 3 name: [stack] -ucontext: 96 0000000000000000000000000000000000000000abdae6ff00000000afdae6ff78dae6ff150000001c000000b8f132f7a0f132f7d0df48f7a0ca48f728d9e6ff000000000000000000000000ceca48f7a8dae6ff000000000000000000000000 -stack: start: f732c000 end: f7330000 size: 16384 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009d9d49f761b009f71e382ff7000000000000000000000000000000000000000002000000f6372ff704c82bf70000000000204bf7f0a908f7ceca48f728d9e6fff4a449f70000000020f332f720f332f7d0df48f7f8f132f794c748f720f332f70c144205978142a8d4be08f7d0df48f720f332f7a0ca48f71c000000150000000e000000070000001c000000a0ca48f7d0df48f748f232f739c848f7070000000e000000150000001c000000a0ca48f720f332f70000000000000000d0df48f720f332f7a0ca48f7100000000c000000080000000400000010000000a0ca48f7d0df48f798f232f7c9c848f704000000080000000c00000010000000a0ca48f720f332f70000000000000000d0df48f720f332f7a0ca48f70800000006000000040000000200000008000000a0ca48f7d0df48f7e8f232f759c948f702000000040000000600000008000000a0ca48f720f332f70000000000000000d0df48f720f332f7a0ca48f7040000000300000002000000010000000046bdaa00000000d0df48f738f332f77cca48f701000000020000000300000004000000a0ca48f720f332f700000000f83b7df7696d4df7d0df48f788dae6ff28d9e6ff28d9e6ff88dae6ff58f332f70046bdaa40fb32f7f83b7df758f332f78d6d4df728d9e6ff88dae6fff83b7df728d9e6ff28d9e6ff009030f728f432f7726f2ff728d9e6ff40fb32f740fb32f740fb32f790f332f700000000000000000000000000000000000000000000000000000000009030f740fb32f7000f3d0028f432f703b12c75032f144e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a06e2ff700000000000f3d00000000008e3f17f740fb32f7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a03823f7c4fd32f700000000e0341df7e02e1df7e03d1df70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040fb32f7188eecf740fb32f70100000030647cf70046bdaa28658876000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060a705f7a4b130f7f2860000f1860000b0fb32f7ecffffff000000000000000090f332f7000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ccfb32f70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000c2638cfa7f3e1d0000000000000000000000000000000000406d4df728d9e6ff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c032f7004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -function: start: 0 end: f748c740 name: unknown_start -function: start: f748c740 end: f748c7c0 name: test_level_four -function: start: f748c7c0 end: f748c850 name: test_level_three -function: start: f748c850 end: f748c8e0 name: test_level_two -function: start: f748c8e0 end: f748c970 name: test_level_one -function: start: f748c970 end: f748ca10 name: test_recursive_call -function: start: f748ca10 end: ffffffff name: test_get_context_and_wait -function: start: ffffffff end: ffffffff name: unknown_end diff --git a/libbacktrace/testdata/x86_64/libbacktrace_test_eh_frame.so b/libbacktrace/testdata/x86_64/libbacktrace_test_eh_frame.so deleted file mode 100755 index f11665830..000000000 Binary files a/libbacktrace/testdata/x86_64/libbacktrace_test_eh_frame.so and /dev/null differ diff --git a/libbacktrace/testdata/x86_64/offline_testdata b/libbacktrace/testdata/x86_64/offline_testdata deleted file mode 100644 index c6bb24161..000000000 --- a/libbacktrace/testdata/x86_64/offline_testdata +++ /dev/null @@ -1,93 +0,0 @@ -pid: 25683 tid: 25692 -map: start: 7fd5aa784000 end: 7fd5aa93e000 offset: 0 load_bias: 0 flags: 5 name: /lib/x86_64-linux-gnu/libc-2.19.so -map: start: 7fd5aa93e000 end: 7fd5aab3e000 offset: 1ba000 load_bias: 0 flags: 0 name: /lib/x86_64-linux-gnu/libc-2.19.so -map: start: 7fd5aab3e000 end: 7fd5aab42000 offset: 1ba000 load_bias: 0 flags: 1 name: /lib/x86_64-linux-gnu/libc-2.19.so -map: start: 7fd5aab42000 end: 7fd5aab44000 offset: 1be000 load_bias: 0 flags: 3 name: /lib/x86_64-linux-gnu/libc-2.19.so -map: start: 7fd5aab44000 end: 7fd5aab49000 offset: 0 load_bias: 0 flags: 3 name: -map: start: 7fd5aab49000 end: 7fd5aac4e000 offset: 0 load_bias: 0 flags: 5 name: /lib/x86_64-linux-gnu/libm-2.19.so -map: start: 7fd5aac4e000 end: 7fd5aae4d000 offset: 105000 load_bias: 0 flags: 0 name: /lib/x86_64-linux-gnu/libm-2.19.so -map: start: 7fd5aae4d000 end: 7fd5aae4e000 offset: 104000 load_bias: 0 flags: 1 name: /lib/x86_64-linux-gnu/libm-2.19.so -map: start: 7fd5aae4e000 end: 7fd5aae4f000 offset: 105000 load_bias: 0 flags: 3 name: /lib/x86_64-linux-gnu/libm-2.19.so -map: start: 7fd5aae4f000 end: 7fd5aae65000 offset: 0 load_bias: 0 flags: 5 name: /lib/x86_64-linux-gnu/libgcc_s.so.1 -map: start: 7fd5aae65000 end: 7fd5ab064000 offset: 16000 load_bias: 0 flags: 0 name: /lib/x86_64-linux-gnu/libgcc_s.so.1 -map: start: 7fd5ab064000 end: 7fd5ab065000 offset: 15000 load_bias: 0 flags: 3 name: /lib/x86_64-linux-gnu/libgcc_s.so.1 -map: start: 7fd5ab065000 end: 7fd5ab08a000 offset: 0 load_bias: 0 flags: 5 name: /lib/x86_64-linux-gnu/libtinfo.so.5.9 -map: start: 7fd5ab08a000 end: 7fd5ab289000 offset: 25000 load_bias: 0 flags: 0 name: /lib/x86_64-linux-gnu/libtinfo.so.5.9 -map: start: 7fd5ab289000 end: 7fd5ab28d000 offset: 24000 load_bias: 0 flags: 1 name: /lib/x86_64-linux-gnu/libtinfo.so.5.9 -map: start: 7fd5ab28d000 end: 7fd5ab28e000 offset: 28000 load_bias: 0 flags: 3 name: /lib/x86_64-linux-gnu/libtinfo.so.5.9 -map: start: 7fd5ab28e000 end: 7fd5ab2b0000 offset: 0 load_bias: 0 flags: 5 name: /lib/x86_64-linux-gnu/libncurses.so.5.9 -map: start: 7fd5ab2b0000 end: 7fd5ab4af000 offset: 22000 load_bias: 0 flags: 0 name: /lib/x86_64-linux-gnu/libncurses.so.5.9 -map: start: 7fd5ab4af000 end: 7fd5ab4b0000 offset: 21000 load_bias: 0 flags: 1 name: /lib/x86_64-linux-gnu/libncurses.so.5.9 -map: start: 7fd5ab4b0000 end: 7fd5ab4b1000 offset: 22000 load_bias: 0 flags: 3 name: /lib/x86_64-linux-gnu/libncurses.so.5.9 -map: start: 7fd5ab4b1000 end: 7fd5ab4b4000 offset: 0 load_bias: 0 flags: 5 name: /lib/x86_64-linux-gnu/libdl-2.19.so -map: start: 7fd5ab4b4000 end: 7fd5ab6b3000 offset: 3000 load_bias: 0 flags: 0 name: /lib/x86_64-linux-gnu/libdl-2.19.so -map: start: 7fd5ab6b3000 end: 7fd5ab6b4000 offset: 2000 load_bias: 0 flags: 1 name: /lib/x86_64-linux-gnu/libdl-2.19.so -map: start: 7fd5ab6b4000 end: 7fd5ab6b5000 offset: 3000 load_bias: 0 flags: 3 name: /lib/x86_64-linux-gnu/libdl-2.19.so -map: start: 7fd5ab6b5000 end: 7fd5ab6bc000 offset: 0 load_bias: 0 flags: 5 name: /lib/x86_64-linux-gnu/librt-2.19.so -map: start: 7fd5ab6bc000 end: 7fd5ab8bb000 offset: 7000 load_bias: 0 flags: 0 name: /lib/x86_64-linux-gnu/librt-2.19.so -map: start: 7fd5ab8bb000 end: 7fd5ab8bc000 offset: 6000 load_bias: 0 flags: 1 name: /lib/x86_64-linux-gnu/librt-2.19.so -map: start: 7fd5ab8bc000 end: 7fd5ab8bd000 offset: 7000 load_bias: 0 flags: 3 name: /lib/x86_64-linux-gnu/librt-2.19.so -map: start: 7fd5ab8bd000 end: 7fd5ab8d6000 offset: 0 load_bias: 0 flags: 5 name: /lib/x86_64-linux-gnu/libpthread-2.19.so -map: start: 7fd5ab8d6000 end: 7fd5abad5000 offset: 19000 load_bias: 0 flags: 0 name: /lib/x86_64-linux-gnu/libpthread-2.19.so -map: start: 7fd5abad5000 end: 7fd5abad6000 offset: 18000 load_bias: 0 flags: 1 name: /lib/x86_64-linux-gnu/libpthread-2.19.so -map: start: 7fd5abad6000 end: 7fd5abad7000 offset: 19000 load_bias: 0 flags: 3 name: /lib/x86_64-linux-gnu/libpthread-2.19.so -map: start: 7fd5abad7000 end: 7fd5abadb000 offset: 0 load_bias: 0 flags: 3 name: -map: start: 7fd5abadb000 end: 7fd5abafe000 offset: 0 load_bias: 0 flags: 5 name: /lib/x86_64-linux-gnu/ld-2.19.so -map: start: 7fd5abb17000 end: 7fd5abb1a000 offset: 0 load_bias: 0 flags: 3 name: -map: start: 7fd5abb1a000 end: 7fd5abb40000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/liblzma.so -map: start: 7fd5abb40000 end: 7fd5abb41000 offset: 25000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/liblzma.so -map: start: 7fd5abb41000 end: 7fd5abb42000 offset: 26000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/liblzma.so -map: start: 7fd5abb42000 end: 7fd5abb4b000 offset: 0 load_bias: 0 flags: 3 name: -map: start: 7fd5abb6a000 end: 7fd5abb70000 offset: 0 load_bias: 0 flags: 3 name: -map: start: 7fd5abb70000 end: 7fd5abc62000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libc++.so -map: start: 7fd5abc62000 end: 7fd5abc63000 offset: f2000 load_bias: 0 flags: 0 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libc++.so -map: start: 7fd5abc63000 end: 7fd5abc6b000 offset: f2000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libc++.so -map: start: 7fd5abc6b000 end: 7fd5abc6c000 offset: fa000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libc++.so -map: start: 7fd5abc6c000 end: 7fd5abc70000 offset: 0 load_bias: 0 flags: 3 name: -map: start: 7fd5abc70000 end: 7fd5abc8d000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libunwind.so -map: start: 7fd5abc8d000 end: 7fd5abc8e000 offset: 1c000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libunwind.so -map: start: 7fd5abc8e000 end: 7fd5abc8f000 offset: 1d000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libunwind.so -map: start: 7fd5abc8f000 end: 7fd5abcb8000 offset: 0 load_bias: 0 flags: 3 name: -map: start: 7fd5abcb8000 end: 7fd5abcbe000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/liblog.so -map: start: 7fd5abcbe000 end: 7fd5abcbf000 offset: 6000 load_bias: 0 flags: 0 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/liblog.so -map: start: 7fd5abcbf000 end: 7fd5abcc0000 offset: 6000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/liblog.so -map: start: 7fd5abcc0000 end: 7fd5abcc1000 offset: 7000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/liblog.so -map: start: 7fd5abcc1000 end: 7fd5abcc2000 offset: 0 load_bias: 0 flags: 3 name: -map: start: 7fd5abcc2000 end: 7fd5abccd000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libcutils.so -map: start: 7fd5abccd000 end: 7fd5abcce000 offset: b000 load_bias: 0 flags: 0 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libcutils.so -map: start: 7fd5abcce000 end: 7fd5abccf000 offset: b000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libcutils.so -map: start: 7fd5abccf000 end: 7fd5abcd0000 offset: c000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libcutils.so -map: start: 7fd5abcd0000 end: 7fd5abcdf000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbase.so -map: start: 7fd5abcdf000 end: 7fd5abce0000 offset: f000 load_bias: 0 flags: 0 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbase.so -map: start: 7fd5abce0000 end: 7fd5abce1000 offset: f000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbase.so -map: start: 7fd5abce1000 end: 7fd5abce2000 offset: 10000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbase.so -map: start: 7fd5abce2000 end: 7fd5abcf5000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbacktrace.so -map: start: 7fd5abcf5000 end: 7fd5abcf6000 offset: 12000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbacktrace.so -map: start: 7fd5abcf6000 end: 7fd5abcf7000 offset: 13000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbacktrace.so -map: start: 7fd5abcf7000 end: 7fd5abcf8000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbacktrace_test.so -map: start: 7fd5abcf8000 end: 7fd5abcf9000 offset: 1000 load_bias: 0 flags: 0 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbacktrace_test.so -map: start: 7fd5abcf9000 end: 7fd5abcfa000 offset: 1000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbacktrace_test.so -map: start: 7fd5abcfa000 end: 7fd5abcfb000 offset: 2000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbacktrace_test.so -map: start: 7fd5abcfb000 end: 7fd5abcfd000 offset: 0 load_bias: 0 flags: 3 name: -map: start: 7fd5abcfd000 end: 7fd5abcfe000 offset: 22000 load_bias: 0 flags: 1 name: /lib/x86_64-linux-gnu/ld-2.19.so -map: start: 7fd5abcfe000 end: 7fd5abcff000 offset: 23000 load_bias: 0 flags: 3 name: /lib/x86_64-linux-gnu/ld-2.19.so -map: start: 7fd5abcff000 end: 7fd5abd00000 offset: 0 load_bias: 0 flags: 3 name: -map: start: 7fd5abd00000 end: 7fd5ac053000 offset: 0 load_bias: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/nativetest64/backtrace_test/backtrace_test64 -map: start: 7fd5ac053000 end: 7fd5ac054000 offset: 0 load_bias: 0 flags: 3 name: -map: start: 7fd5ac054000 end: 7fd5ac06f000 offset: 353000 load_bias: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/nativetest64/backtrace_test/backtrace_test64 -map: start: 7fd5ac06f000 end: 7fd5ac070000 offset: 36e000 load_bias: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/nativetest64/backtrace_test/backtrace_test64 -map: start: 7fd5ac070000 end: 7fd5ac071000 offset: 0 load_bias: 0 flags: 3 name: -map: start: 7fd5ad54e000 end: 7fd5ad56f000 offset: 0 load_bias: 0 flags: 3 name: [heap] -map: start: 7ffcf47ed000 end: 7ffcf480f000 offset: 0 load_bias: 0 flags: 3 name: [stack] -map: start: 7ffcf48d5000 end: 7ffcf48d7000 offset: 0 load_bias: ffffffffff700000 flags: 5 name: [vdso] -map: start: ffffffffff600000 end: ffffffffff601000 offset: 0 load_bias: 0 flags: 5 name: [vsyscall] -ucontext: 224 00000000000000000000000000000000000000000000000000000000000000000000000000000000b07bcfabd57f000098deb6abd57f0000b82455add57f0000010000000000000000000000000000000000000000000000c0e354add57f000000e7b6abd57f0000c8b080f4fc7f00000e0000000000000080ddb6abd57f000000000000000000001500000000000000b07bcfabd57f00001c0000000000000060ddb6abd57f0000d07bcfabd57f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -stack: start: 7fd5abb6b000 end: 7fd5abb6f000 size: 16384 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c4eaeabd57f00000000000000000000978142a8000000000f0000000000000012000000000000003888b4abd57f0000e657aeabd57f00000000000000000000a0dcb6abd57f0000307d78aad57f0000b0ddb6abd57f000028d978aad57f0000060aa10200000000a0ddb6abd57f0000000000000000000000000000000000002091b1abd57f0000e094b4abd57f000017008cabd57f0000c84d79aad57f000028e28babd57f00000000000005000000d503000001000000000000000000000068deb6abd57f000040deb6abd57f00002091b1abd57f00000100000000000000e0f3c6abd57f000088f0c6abd57f00006159aeabd57f000000000000000000002091b1abd57f000005000000000000000000000000000000010000000000000088f0c6abd57f00000000000000000000d07bcfabd57f00000000000000000000000000000000000098deb6abd57f000098deb6abd57f0000b0ddb6abd57f00006179cfabd57f000098deb6abd57f0000b07bcfabd57f00001c000000150000000e00000007000000f0ddb6abd57f0000e179cfabd57f00000000000000000000150000001c00000098deb6abd57f0000b07bcfabd57f0000100000000c000000080000000400000030deb6abd57f0000417acfabd57f000000000000000000000c0000001000000098deb6abd57f0000b07bcfabd57f00000800000006000000040000000200000070deb6abd57f0000a17acfabd57f00000000000000000000060000000800000098deb6abd57f0000b07bcfabd57f000004000000030000000200000001000000b0deb6abd57f0000817bcfabd57f0000000000000000000074b480f4fc7f0000c8b080f4fc7f0000c8b080f4fc7f000074b480f4fc7f000000006a80f3f73cf1d0deb6abd57f00002a52d5abd57f0000c8b080f4fc7f0000c8b080f4fc7f0000000000000000000084518cabd57f0000000000000000000000e7b6abd57f000000e7b6abd57f00008f990b1e3bad5a6700000000000000000000000000000000c0e354add57f000000e7b6abd57f00008f99cba356faf1988f9991bc23faf1980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e7b6abd57f00007de387aad57f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006030b4aad57f0000b8edb6abd57f00000000000000000000000000000000000080b88eaad57f0000000000000000000080b28eaad57f0000000000000000000080c18eaad57f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e7b6abd57f0000402555add57f000000e7b6abd57f00000100000000000000000000000000000000006a80f3f73cf1058f9d56adb3c7cc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000407ab1abd57f000030a3adabd57f00005c64000053640000e0e9b6abd57f0000e0e9b6abd57f0000e0ffffffffffffff00000000000000000000000000000000f0deb6abd57f00000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010eab6abd57f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000c46ad90f52391d00000000000000000000000000000000000000000000000000f051d5abd57f0000c8b080f4fc7f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b0b6abd57f000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -function: start: 0 end: 7fd5abcf7930 name: unknown_start -function: start: 7fd5abcf7930 end: 7fd5abcf7990 name: test_level_four -function: start: 7fd5abcf7990 end: 7fd5abcf79f0 name: test_level_three -function: start: 7fd5abcf79f0 end: 7fd5abcf7a50 name: test_level_two -function: start: 7fd5abcf7a50 end: 7fd5abcf7ab0 name: test_level_one -function: start: 7fd5abcf7ab0 end: 7fd5abcf7b30 name: test_recursive_call -function: start: 7fd5abcf7b30 end: ffffffffffffffff name: test_get_context_and_wait -function: start: ffffffffffffffff end: ffffffffffffffff name: unknown_end diff --git a/libprocinfo b/libprocinfo new file mode 120000 index 000000000..dec8cf884 --- /dev/null +++ b/libprocinfo @@ -0,0 +1 @@ +../libprocinfo \ No newline at end of file diff --git a/libprocinfo/.clang-format b/libprocinfo/.clang-format deleted file mode 120000 index fd0645fdf..000000000 --- a/libprocinfo/.clang-format +++ /dev/null @@ -1 +0,0 @@ -../.clang-format-2 \ No newline at end of file diff --git a/libprocinfo/Android.bp b/libprocinfo/Android.bp deleted file mode 100644 index ae4574276..000000000 --- a/libprocinfo/Android.bp +++ /dev/null @@ -1,131 +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. -// - -cc_defaults { - name: "libprocinfo_defaults", - cflags: [ - "-Wall", - "-Werror", - "-Wextra", - ], -} - -cc_library { - name: "libprocinfo", - defaults: ["libprocinfo_defaults"], - vendor_available: true, - // TODO(b/153609531): remove when no longer needed. - native_bridge_supported: true, - recovery_available: true, - vndk: { - enabled: true, - }, - host_supported: true, - srcs: [ - "process.cpp", - "process_map.cpp", - ], - - local_include_dirs: ["include"], - export_include_dirs: ["include"], - shared_libs: ["libbase"], - target: { - darwin: { - enabled: false, - }, - linux_bionic: { - enabled: true, - }, - windows: { - enabled: false, - }, - }, - - apex_available: [ - "//apex_available:platform", - "com.android.art.debug", - "com.android.art.release", - ], -} - -// Tests -// ------------------------------------------------------------------------------ -cc_test { - name: "libprocinfo_test", - defaults: ["libprocinfo_defaults"], - host_supported: true, - isolated: true, - srcs: [ - "process_test.cpp", - "process_map_test.cpp", - ], - target: { - darwin: { - enabled: false, - }, - windows: { - enabled: false, - }, - }, - - shared_libs: [ - "libbase", - "libprocinfo", - ], - - compile_multilib: "both", - multilib: { - lib32: { - suffix: "32", - }, - lib64: { - suffix: "64", - }, - }, - - data: [ - "testdata/*", - ], - - test_suites: ["device-tests"], -} - -cc_benchmark { - name: "libprocinfo_benchmark", - defaults: ["libprocinfo_defaults"], - srcs: [ - "process_map_benchmark.cpp", - ], - shared_libs: [ - "libbacktrace", - "libbase", - "libprocinfo", - "libunwindstack", - ], - compile_multilib: "both", - multilib: { - lib32: { - suffix: "32", - }, - lib64: { - suffix: "64", - }, - }, - - data: [ - "testdata/*", - ], -} diff --git a/libprocinfo/OWNERS b/libprocinfo/OWNERS deleted file mode 100644 index a70cc57ef..000000000 --- a/libprocinfo/OWNERS +++ /dev/null @@ -1 +0,0 @@ -jmgao@google.com diff --git a/libprocinfo/include/procinfo/process.h b/libprocinfo/include/procinfo/process.h deleted file mode 100644 index 9278e1819..000000000 --- a/libprocinfo/include/procinfo/process.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2016 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. - */ - -#pragma once - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -namespace android { -namespace procinfo { - -#if defined(__linux__) - -enum ProcessState { - kProcessStateUnknown, - kProcessStateRunning, - kProcessStateSleeping, - kProcessStateUninterruptibleWait, - kProcessStateStopped, - kProcessStateZombie, -}; - -struct ProcessInfo { - std::string name; - ProcessState state; - pid_t tid; - pid_t pid; - pid_t ppid; - pid_t tracer; - uid_t uid; - uid_t gid; -}; - -// Parse the contents of /proc//status into |process_info|. -bool GetProcessInfo(pid_t tid, ProcessInfo* process_info, std::string* error = nullptr); - -// Parse the contents of /status into |process_info|. -// |fd| should be an fd pointing at a /proc/ directory. -bool GetProcessInfoFromProcPidFd(int fd, ProcessInfo* process_info, std::string* error = nullptr); - -// Fetch the list of threads from a given process's /proc/ directory. -// |fd| should be an fd pointing at a /proc/ directory. -template -auto GetProcessTidsFromProcPidFd(int fd, Collection* out, std::string* error = nullptr) -> - typename std::enable_if= sizeof(pid_t), bool>::type { - out->clear(); - - int task_fd = openat(fd, "task", O_DIRECTORY | O_RDONLY | O_CLOEXEC); - std::unique_ptr dir(fdopendir(task_fd), closedir); - if (!dir) { - if (error != nullptr) { - *error = "failed to open task directory"; - } - return false; - } - - struct dirent* dent; - while ((dent = readdir(dir.get()))) { - if (strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0) { - pid_t tid; - if (!android::base::ParseInt(dent->d_name, &tid, 1, std::numeric_limits::max())) { - if (error != nullptr) { - *error = std::string("failed to parse task id: ") + dent->d_name; - } - return false; - } - - out->insert(out->end(), tid); - } - } - - return true; -} - -template -auto GetProcessTids(pid_t pid, Collection* out, std::string* error = nullptr) -> - typename std::enable_if= sizeof(pid_t), bool>::type { - char task_path[PATH_MAX]; - if (snprintf(task_path, PATH_MAX, "/proc/%d", pid) >= PATH_MAX) { - if (error != nullptr) { - *error = "task path overflow (pid = " + std::to_string(pid) + ")"; - } - return false; - } - - android::base::unique_fd fd(open(task_path, O_DIRECTORY | O_RDONLY | O_CLOEXEC)); - if (fd == -1) { - if (error != nullptr) { - *error = std::string("failed to open ") + task_path; - } - return false; - } - - return GetProcessTidsFromProcPidFd(fd.get(), out, error); -} - -#endif - -} /* namespace procinfo */ -} /* namespace android */ diff --git a/libprocinfo/include/procinfo/process_map.h b/libprocinfo/include/procinfo/process_map.h deleted file mode 100644 index 569a02221..000000000 --- a/libprocinfo/include/procinfo/process_map.h +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (C) 2018 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. - */ - -#pragma once - -#include -#include -#include -#include - -#include -#include -#include - -#include - -namespace android { -namespace procinfo { - -template -bool ReadMapFileContent(char* content, const CallbackType& callback) { - uint64_t start_addr; - uint64_t end_addr; - uint16_t flags; - uint64_t pgoff; - ino_t inode; - char* next_line = content; - char* p; - - auto pass_space = [&]() { - if (*p != ' ') { - return false; - } - while (*p == ' ') { - p++; - } - return true; - }; - - auto pass_xdigit = [&]() { - if (!isxdigit(*p)) { - return false; - } - do { - p++; - } while (isxdigit(*p)); - return true; - }; - - while (next_line != nullptr && *next_line != '\0') { - p = next_line; - next_line = strchr(next_line, '\n'); - if (next_line != nullptr) { - *next_line = '\0'; - next_line++; - } - // Parse line like: 00400000-00409000 r-xp 00000000 fc:00 426998 /usr/lib/gvfs/gvfsd-http - char* end; - // start_addr - start_addr = strtoull(p, &end, 16); - if (end == p || *end != '-') { - return false; - } - p = end + 1; - // end_addr - end_addr = strtoull(p, &end, 16); - if (end == p) { - return false; - } - p = end; - if (!pass_space()) { - return false; - } - // flags - flags = 0; - if (*p == 'r') { - flags |= PROT_READ; - } else if (*p != '-') { - return false; - } - p++; - if (*p == 'w') { - flags |= PROT_WRITE; - } else if (*p != '-') { - return false; - } - p++; - if (*p == 'x') { - flags |= PROT_EXEC; - } else if (*p != '-') { - return false; - } - p++; - if (*p != 'p' && *p != 's') { - return false; - } - p++; - if (!pass_space()) { - return false; - } - // pgoff - pgoff = strtoull(p, &end, 16); - if (end == p) { - return false; - } - p = end; - if (!pass_space()) { - return false; - } - // major:minor - if (!pass_xdigit() || *p++ != ':' || !pass_xdigit() || !pass_space()) { - return false; - } - // inode - inode = strtoull(p, &end, 10); - if (end == p) { - return false; - } - p = end; - - if (*p != '\0' && !pass_space()) { - return false; - } - - // filename - callback(start_addr, end_addr, flags, pgoff, inode, p); - } - return true; -} - -inline bool ReadMapFile(const std::string& map_file, - const std::function& callback) { - std::string content; - if (!android::base::ReadFileToString(map_file, &content)) { - return false; - } - return ReadMapFileContent(&content[0], callback); -} - -inline bool ReadProcessMaps(pid_t pid, - const std::function& callback) { - return ReadMapFile("/proc/" + std::to_string(pid) + "/maps", callback); -} - -struct MapInfo { - uint64_t start; - uint64_t end; - uint16_t flags; - uint64_t pgoff; - ino_t inode; - std::string name; - - MapInfo(uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t inode, - const char* name) - : start(start), end(end), flags(flags), pgoff(pgoff), inode(inode), name(name) {} -}; - -inline bool ReadProcessMaps(pid_t pid, std::vector* maps) { - return ReadProcessMaps( - pid, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t inode, - const char* name) { maps->emplace_back(start, end, flags, pgoff, inode, name); }); -} - -bool ReadMapFileAsyncSafe(const char* map_file, void* buffer, size_t buffer_size, - const std::function& callback); - -} /* namespace procinfo */ -} /* namespace android */ diff --git a/libprocinfo/process.cpp b/libprocinfo/process.cpp deleted file mode 100644 index 2efd49c37..000000000 --- a/libprocinfo/process.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2016 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 - -using android::base::unique_fd; - -namespace android { -namespace procinfo { - -bool GetProcessInfo(pid_t tid, ProcessInfo* process_info, std::string* error) { - char path[PATH_MAX]; - snprintf(path, sizeof(path), "/proc/%d", tid); - - unique_fd dirfd(open(path, O_DIRECTORY | O_RDONLY)); - if (dirfd == -1) { - if (error != nullptr) { - *error = std::string("failed to open ") + path; - } - return false; - } - - return GetProcessInfoFromProcPidFd(dirfd.get(), process_info, error); -} - -static ProcessState parse_state(const char* state) { - switch (*state) { - case 'R': - return kProcessStateRunning; - case 'S': - return kProcessStateSleeping; - case 'D': - return kProcessStateUninterruptibleWait; - case 'T': - return kProcessStateStopped; - case 'Z': - return kProcessStateZombie; - default: - return kProcessStateUnknown; - } -} - -bool GetProcessInfoFromProcPidFd(int fd, ProcessInfo* process_info, std::string* error) { - int status_fd = openat(fd, "status", O_RDONLY | O_CLOEXEC); - - if (status_fd == -1) { - if (error != nullptr) { - *error = "failed to open status fd in GetProcessInfoFromProcPidFd"; - } - return false; - } - - std::unique_ptr fp(fdopen(status_fd, "r"), fclose); - if (!fp) { - if (error != nullptr) { - *error = "failed to open status file in GetProcessInfoFromProcPidFd"; - } - close(status_fd); - return false; - } - - int field_bitmap = 0; - static constexpr int finished_bitmap = 255; - char* line = nullptr; - size_t len = 0; - - while (getline(&line, &len, fp.get()) != -1 && field_bitmap != finished_bitmap) { - char* tab = strchr(line, '\t'); - if (tab == nullptr) { - continue; - } - - size_t header_len = tab - line; - std::string header = std::string(line, header_len); - if (header == "Name:") { - std::string name = line + header_len + 1; - - // line includes the trailing newline. - name.pop_back(); - process_info->name = std::move(name); - - field_bitmap |= 1; - } else if (header == "Pid:") { - process_info->tid = atoi(tab + 1); - field_bitmap |= 2; - } else if (header == "Tgid:") { - process_info->pid = atoi(tab + 1); - field_bitmap |= 4; - } else if (header == "PPid:") { - process_info->ppid = atoi(tab + 1); - field_bitmap |= 8; - } else if (header == "TracerPid:") { - process_info->tracer = atoi(tab + 1); - field_bitmap |= 16; - } else if (header == "Uid:") { - process_info->uid = atoi(tab + 1); - field_bitmap |= 32; - } else if (header == "Gid:") { - process_info->gid = atoi(tab + 1); - field_bitmap |= 64; - } else if (header == "State:") { - process_info->state = parse_state(tab + 1); - field_bitmap |= 128; - } - } - - free(line); - return field_bitmap == finished_bitmap; -} - -} /* namespace procinfo */ -} /* namespace android */ diff --git a/libprocinfo/process_map.cpp b/libprocinfo/process_map.cpp deleted file mode 100644 index 5e240b99f..000000000 --- a/libprocinfo/process_map.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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. - */ - -#include - -#include -#include -#include - -#include - -namespace android { -namespace procinfo { - -bool ReadMapFileAsyncSafe(const char* map_file, void* buffer, size_t buffer_size, - const std::function& callback) { - if (buffer == nullptr || buffer_size == 0) { - return false; - } - - int fd = open(map_file, O_RDONLY | O_CLOEXEC); - if (fd == -1) { - return false; - } - - char* char_buffer = reinterpret_cast(buffer); - size_t start = 0; - size_t read_bytes = 0; - char* line = nullptr; - bool read_complete = false; - while (true) { - ssize_t bytes = - TEMP_FAILURE_RETRY(read(fd, char_buffer + read_bytes, buffer_size - read_bytes - 1)); - if (bytes <= 0) { - if (read_bytes == 0) { - close(fd); - return bytes == 0; - } - // Treat the last piece of data as the last line. - char_buffer[start + read_bytes] = '\n'; - bytes = 1; - read_complete = true; - } - read_bytes += bytes; - - while (read_bytes > 0) { - char* newline = reinterpret_cast(memchr(&char_buffer[start], '\n', read_bytes)); - if (newline == nullptr) { - break; - } - *newline = '\0'; - line = &char_buffer[start]; - start = newline - char_buffer + 1; - read_bytes -= newline - line + 1; - - // Ignore the return code, errors are okay. - ReadMapFileContent(line, callback); - } - - if (read_complete) { - close(fd); - return true; - } - - if (start == 0 && read_bytes == buffer_size - 1) { - // The buffer provided is too small to contain this line, give up - // and indicate failure. - close(fd); - return false; - } - - // Copy any leftover data to the front of the buffer. - if (start > 0) { - if (read_bytes > 0) { - memmove(char_buffer, &char_buffer[start], read_bytes); - } - start = 0; - } - } -} - -} /* namespace procinfo */ -} /* namespace android */ diff --git a/libprocinfo/process_map_benchmark.cpp b/libprocinfo/process_map_benchmark.cpp deleted file mode 100644 index eba4fd0d8..000000000 --- a/libprocinfo/process_map_benchmark.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2018 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 - -static void BM_ReadMapFile(benchmark::State& state) { - std::string map_file = android::base::GetExecutableDirectory() + "/testdata/maps"; - for (auto _ : state) { - std::vector maps; - android::procinfo::ReadMapFile(map_file, [&](uint64_t start, uint64_t end, uint16_t flags, - uint64_t pgoff, ino_t inode, const char* name) { - maps.emplace_back(start, end, flags, pgoff, inode, name); - }); - CHECK_EQ(maps.size(), 2043u); - } -} -BENCHMARK(BM_ReadMapFile); - -static void BM_unwindstack_FileMaps(benchmark::State& state) { - std::string map_file = android::base::GetExecutableDirectory() + "/testdata/maps"; - for (auto _ : state) { - unwindstack::FileMaps maps(map_file); - maps.Parse(); - CHECK_EQ(maps.Total(), 2043u); - } -} -BENCHMARK(BM_unwindstack_FileMaps); - -static void BM_unwindstack_BufferMaps(benchmark::State& state) { - std::string map_file = android::base::GetExecutableDirectory() + "/testdata/maps"; - std::string content; - CHECK(android::base::ReadFileToString(map_file, &content)); - for (auto _ : state) { - unwindstack::BufferMaps maps(content.c_str()); - maps.Parse(); - CHECK_EQ(maps.Total(), 2043u); - } -} -BENCHMARK(BM_unwindstack_BufferMaps); - -static void BM_backtrace_BacktraceMap(benchmark::State& state) { - pid_t pid = getpid(); - for (auto _ : state) { - BacktraceMap* map = BacktraceMap::Create(pid, true); - CHECK(map != nullptr); - delete map; - } -} -BENCHMARK(BM_backtrace_BacktraceMap); - -BENCHMARK_MAIN(); diff --git a/libprocinfo/process_map_test.cpp b/libprocinfo/process_map_test.cpp deleted file mode 100644 index b1bdc08a5..000000000 --- a/libprocinfo/process_map_test.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright (C) 2018 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 - -TEST(process_map, ReadMapFile) { - std::string map_file = android::base::GetExecutableDirectory() + "/testdata/maps"; - std::vector maps; - ASSERT_TRUE(android::procinfo::ReadMapFile( - map_file, - [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t inode, - const char* name) { maps.emplace_back(start, end, flags, pgoff, inode, name); })); - ASSERT_EQ(2043u, maps.size()); - ASSERT_EQ(maps[0].start, 0x12c00000ULL); - ASSERT_EQ(maps[0].end, 0x2ac00000ULL); - ASSERT_EQ(maps[0].flags, PROT_READ | PROT_WRITE); - ASSERT_EQ(maps[0].pgoff, 0ULL); - ASSERT_EQ(maps[0].inode, 10267643UL); - ASSERT_EQ(maps[0].name, "[anon:dalvik-main space (region space)]"); - ASSERT_EQ(maps[876].start, 0x70e6c4f000ULL); - ASSERT_EQ(maps[876].end, 0x70e6c6b000ULL); - ASSERT_EQ(maps[876].flags, PROT_READ | PROT_EXEC); - ASSERT_EQ(maps[876].pgoff, 0ULL); - ASSERT_EQ(maps[876].inode, 2407UL); - ASSERT_EQ(maps[876].name, "/system/lib64/libutils.so"); - ASSERT_EQ(maps[1260].start, 0x70e96fa000ULL); - ASSERT_EQ(maps[1260].end, 0x70e96fb000ULL); - ASSERT_EQ(maps[1260].flags, PROT_READ); - ASSERT_EQ(maps[1260].pgoff, 0ULL); - ASSERT_EQ(maps[1260].inode, 10266154UL); - ASSERT_EQ(maps[1260].name, - "[anon:dalvik-classes.dex extracted in memory from " - "/data/app/com.google.sample.tunnel-HGGRU03Gu1Mwkf_-RnFmvw==/base.apk]"); -} - -TEST(process_map, ReadProcessMaps) { - std::vector maps; - ASSERT_TRUE(android::procinfo::ReadProcessMaps( - getpid(), - [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t inode, - const char* name) { maps.emplace_back(start, end, flags, pgoff, inode, name); })); - ASSERT_GT(maps.size(), 0u); - maps.clear(); - ASSERT_TRUE(android::procinfo::ReadProcessMaps(getpid(), &maps)); - ASSERT_GT(maps.size(), 0u); -} - -extern "C" void malloc_disable(); -extern "C" void malloc_enable(); - -struct TestMapInfo { - TestMapInfo() = default; - TestMapInfo(uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t inode, - const char* new_name) - : start(start), end(end), flags(flags), pgoff(pgoff), inode(inode) { - strcpy(name, new_name); - } - uint64_t start = 0; - uint64_t end = 0; - uint16_t flags = 0; - uint64_t pgoff = 0; - ino_t inode = 0; - char name[100] = {}; -}; - -void VerifyReadMapFileAsyncSafe(const char* maps_data, - const std::vector& expected_info) { - TemporaryFile tf; - ASSERT_TRUE(android::base::WriteStringToFd(maps_data, tf.fd)); - - std::vector saved_info(expected_info.size()); - size_t num_maps = 0; - - auto callback = [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t inode, - const char* name) { - if (num_maps != saved_info.size()) { - TestMapInfo& saved = saved_info[num_maps]; - saved.start = start; - saved.end = end; - saved.flags = flags; - saved.pgoff = pgoff; - saved.inode = inode; - strcpy(saved.name, name); - } - num_maps++; - }; - - std::vector buffer(64 * 1024); - -#if defined(__BIONIC__) - // Any allocations will block after this call. - malloc_disable(); -#endif - - bool parsed = - android::procinfo::ReadMapFileAsyncSafe(tf.path, buffer.data(), buffer.size(), callback); - -#if defined(__BIONIC__) - malloc_enable(); -#endif - - ASSERT_TRUE(parsed) << "Parsing of data failed:\n" << maps_data; - ASSERT_EQ(expected_info.size(), num_maps); - for (size_t i = 0; i < expected_info.size(); i++) { - const TestMapInfo& expected = expected_info[i]; - const TestMapInfo& saved = saved_info[i]; - EXPECT_EQ(expected.start, saved.start); - EXPECT_EQ(expected.end, saved.end); - EXPECT_EQ(expected.flags, saved.flags); - EXPECT_EQ(expected.pgoff, saved.pgoff); - EXPECT_EQ(expected.inode, saved.inode); - EXPECT_STREQ(expected.name, saved.name); - } -} - -TEST(process_map, ReadMapFileAsyncSafe_invalid) { - std::vector expected_info; - - VerifyReadMapFileAsyncSafe("12c00000-2ac00000", expected_info); -} - -TEST(process_map, ReadMapFileAsyncSafe_single) { - std::vector expected_info; - expected_info.emplace_back(0x12c00000, 0x2ac00000, PROT_READ | PROT_WRITE, 0x100, 10267643, - "/lib/fake.so"); - - VerifyReadMapFileAsyncSafe("12c00000-2ac00000 rw-p 00000100 00:05 10267643 /lib/fake.so", - expected_info); -} - -TEST(process_map, ReadMapFileAsyncSafe_single_with_newline) { - std::vector expected_info; - expected_info.emplace_back(0x12c00000, 0x2ac00000, PROT_READ | PROT_WRITE, 0x100, 10267643, - "/lib/fake.so"); - - VerifyReadMapFileAsyncSafe("12c00000-2ac00000 rw-p 00000100 00:05 10267643 /lib/fake.so\n", - expected_info); -} - -TEST(process_map, ReadMapFileAsyncSafe_single_no_library) { - std::vector expected_info; - expected_info.emplace_back(0xa0000, 0xc0000, PROT_READ | PROT_WRITE | PROT_EXEC, 0xb00, 101, ""); - - VerifyReadMapFileAsyncSafe("a0000-c0000 rwxp 00000b00 00:05 101", expected_info); -} - -TEST(process_map, ReadMapFileAsyncSafe_multiple) { - std::vector expected_info; - expected_info.emplace_back(0xa0000, 0xc0000, PROT_READ | PROT_WRITE | PROT_EXEC, 1, 100, ""); - expected_info.emplace_back(0xd0000, 0xe0000, PROT_READ, 2, 101, "/lib/libsomething1.so"); - expected_info.emplace_back(0xf0000, 0x100000, PROT_WRITE, 3, 102, "/lib/libsomething2.so"); - expected_info.emplace_back(0x110000, 0x120000, PROT_EXEC, 4, 103, "[anon:something or another]"); - - std::string map_data = - "0a0000-0c0000 rwxp 00000001 00:05 100\n" - "0d0000-0e0000 r--p 00000002 00:05 101 /lib/libsomething1.so\n" - "0f0000-100000 -w-p 00000003 00:05 102 /lib/libsomething2.so\n" - "110000-120000 --xp 00000004 00:05 103 [anon:something or another]\n"; - - VerifyReadMapFileAsyncSafe(map_data.c_str(), expected_info); -} - -TEST(process_map, ReadMapFileAsyncSafe_multiple_reads) { - std::vector expected_info; - std::string map_data; - uint64_t start = 0xa0000; - for (size_t i = 0; i < 10000; i++) { - map_data += android::base::StringPrintf("%" PRIx64 "-%" PRIx64 " r--p %zx 01:20 %zu fake.so\n", - start, start + 0x1000, i, 1000 + i); - expected_info.emplace_back(start, start + 0x1000, PROT_READ, i, 1000 + i, "fake.so"); - } - - VerifyReadMapFileAsyncSafe(map_data.c_str(), expected_info); -} - -TEST(process_map, ReadMapFileAsyncSafe_buffer_nullptr) { - size_t num_calls = 0; - auto callback = [&](uint64_t, uint64_t, uint16_t, uint64_t, ino_t, const char*) { num_calls++; }; - -#if defined(__BIONIC__) - // Any allocations will block after this call. - malloc_disable(); -#endif - - bool parsed = android::procinfo::ReadMapFileAsyncSafe("/proc/self/maps", nullptr, 10, callback); - -#if defined(__BIONIC__) - malloc_enable(); -#endif - - ASSERT_FALSE(parsed); - EXPECT_EQ(0UL, num_calls); -} - -TEST(process_map, ReadMapFileAsyncSafe_buffer_size_zero) { - size_t num_calls = 0; - auto callback = [&](uint64_t, uint64_t, uint16_t, uint64_t, ino_t, const char*) { num_calls++; }; - -#if defined(__BIONIC__) - // Any allocations will block after this call. - malloc_disable(); -#endif - - char buffer[10]; - bool parsed = android::procinfo::ReadMapFileAsyncSafe("/proc/self/maps", buffer, 0, callback); - -#if defined(__BIONIC__) - malloc_enable(); -#endif - - ASSERT_FALSE(parsed); - EXPECT_EQ(0UL, num_calls); -} - -TEST(process_map, ReadMapFileAsyncSafe_buffer_too_small_no_calls) { - size_t num_calls = 0; - auto callback = [&](uint64_t, uint64_t, uint16_t, uint64_t, ino_t, const char*) { num_calls++; }; - -#if defined(__BIONIC__) - // Any allocations will block after this call. - malloc_disable(); -#endif - - char buffer[10]; - bool parsed = - android::procinfo::ReadMapFileAsyncSafe("/proc/self/maps", buffer, sizeof(buffer), callback); - -#if defined(__BIONIC__) - malloc_enable(); -#endif - - ASSERT_FALSE(parsed); - EXPECT_EQ(0UL, num_calls); -} - -TEST(process_map, ReadMapFileAsyncSafe_buffer_too_small_could_parse) { - TemporaryFile tf; - ASSERT_TRUE(android::base::WriteStringToFd( - "0a0000-0c0000 rwxp 00000001 00:05 100 /fake/lib.so\n", tf.fd)); - - size_t num_calls = 0; - auto callback = [&](uint64_t, uint64_t, uint16_t, uint64_t, ino_t, const char*) { num_calls++; }; - -#if defined(__BIONIC__) - // Any allocations will block after this call. - malloc_disable(); -#endif - - char buffer[39]; - bool parsed = android::procinfo::ReadMapFileAsyncSafe(tf.path, buffer, sizeof(buffer), callback); - -#if defined(__BIONIC__) - malloc_enable(); -#endif - - ASSERT_FALSE(parsed); - EXPECT_EQ(0UL, num_calls); -} diff --git a/libprocinfo/process_test.cpp b/libprocinfo/process_test.cpp deleted file mode 100644 index 9da927899..000000000 --- a/libprocinfo/process_test.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2016 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 - -using namespace std::chrono_literals; - -#if !defined(__BIONIC__) -#include -static pid_t gettid() { - return syscall(__NR_gettid); -} -#endif - -TEST(process_info, process_info_smoke) { - android::procinfo::ProcessInfo self; - ASSERT_TRUE(android::procinfo::GetProcessInfo(gettid(), &self)); - ASSERT_EQ(gettid(), self.tid); - ASSERT_EQ(getpid(), self.pid); - ASSERT_EQ(getppid(), self.ppid); - ASSERT_EQ(getuid(), self.uid); - ASSERT_EQ(getgid(), self.gid); -} - -TEST(process_info, process_info_proc_pid_fd_smoke) { - android::procinfo::ProcessInfo self; - int fd = open(android::base::StringPrintf("/proc/%d", gettid()).c_str(), O_DIRECTORY | O_RDONLY); - ASSERT_NE(-1, fd); - ASSERT_TRUE(android::procinfo::GetProcessInfoFromProcPidFd(fd, &self)); - - // Process name is capped at 15 bytes. - ASSERT_EQ("libprocinfo_tes", self.name); - ASSERT_EQ(gettid(), self.tid); - ASSERT_EQ(getpid(), self.pid); - ASSERT_EQ(getppid(), self.ppid); - ASSERT_EQ(getuid(), self.uid); - ASSERT_EQ(getgid(), self.gid); - close(fd); -} - -TEST(process_info, process_tids_smoke) { - pid_t main_tid = gettid(); - std::thread([main_tid]() { - pid_t thread_tid = gettid(); - - { - std::vector vec; - ASSERT_TRUE(android::procinfo::GetProcessTids(getpid(), &vec)); - ASSERT_EQ(1, std::count(vec.begin(), vec.end(), main_tid)); - ASSERT_EQ(1, std::count(vec.begin(), vec.end(), thread_tid)); - } - - { - std::set set; - ASSERT_TRUE(android::procinfo::GetProcessTids(getpid(), &set)); - ASSERT_EQ(1, std::count(set.begin(), set.end(), main_tid)); - ASSERT_EQ(1, std::count(set.begin(), set.end(), thread_tid)); - } - }).join(); -} - -TEST(process_info, process_state) { - int pipefd[2]; - ASSERT_EQ(0, pipe2(pipefd, O_CLOEXEC)); - pid_t forkpid = fork(); - - ASSERT_NE(-1, forkpid); - if (forkpid == 0) { - close(pipefd[1]); - char buf; - TEMP_FAILURE_RETRY(read(pipefd[0], &buf, 1)); - _exit(0); - } - - // Give the child some time to get to the read. - std::this_thread::sleep_for(100ms); - - android::procinfo::ProcessInfo procinfo; - ASSERT_TRUE(android::procinfo::GetProcessInfo(forkpid, &procinfo)); - ASSERT_EQ(android::procinfo::kProcessStateSleeping, procinfo.state); - - ASSERT_EQ(0, kill(forkpid, SIGKILL)); - - // Give the kernel some time to kill the child. - std::this_thread::sleep_for(100ms); - - ASSERT_TRUE(android::procinfo::GetProcessInfo(forkpid, &procinfo)); - ASSERT_EQ(android::procinfo::kProcessStateZombie, procinfo.state); - - ASSERT_EQ(forkpid, waitpid(forkpid, nullptr, 0)); -} diff --git a/libprocinfo/testdata/maps b/libprocinfo/testdata/maps deleted file mode 100644 index 098cf257b..000000000 --- a/libprocinfo/testdata/maps +++ /dev/null @@ -1,2043 +0,0 @@ -12c00000-2ac00000 rw-p 00000000 00:05 10267643 [anon:dalvik-main space (region space)] -6fb5d000-6fd6e000 rw-p 00000000 103:1d 639511 /data/dalvik-cache/arm64/system@framework@boot.art -6fd6e000-6fd82000 r--p 00211000 103:1d 639511 /data/dalvik-cache/arm64/system@framework@boot.art -6fd82000-6fe47000 rw-p 00000000 103:1d 639514 /data/dalvik-cache/arm64/system@framework@boot-core-libart.art -6fe47000-6fe52000 r--p 000c5000 103:1d 639514 /data/dalvik-cache/arm64/system@framework@boot-core-libart.art -6fe52000-6fe84000 rw-p 00000000 103:1d 639517 /data/dalvik-cache/arm64/system@framework@boot-conscrypt.art -6fe84000-6fe87000 r--p 00032000 103:1d 639517 /data/dalvik-cache/arm64/system@framework@boot-conscrypt.art -6fe87000-6feb2000 rw-p 00000000 103:1d 639520 /data/dalvik-cache/arm64/system@framework@boot-okhttp.art -6feb2000-6feb5000 r--p 0002b000 103:1d 639520 /data/dalvik-cache/arm64/system@framework@boot-okhttp.art -6feb5000-6fef4000 rw-p 00000000 103:1d 639523 /data/dalvik-cache/arm64/system@framework@boot-bouncycastle.art -6fef4000-6fefb000 r--p 0003f000 103:1d 639523 /data/dalvik-cache/arm64/system@framework@boot-bouncycastle.art -6fefb000-6ff3f000 rw-p 00000000 103:1d 639526 /data/dalvik-cache/arm64/system@framework@boot-apache-xml.art -6ff3f000-6ff45000 r--p 00044000 103:1d 639526 /data/dalvik-cache/arm64/system@framework@boot-apache-xml.art -6ff45000-6ff7a000 rw-p 00000000 103:1d 639529 /data/dalvik-cache/arm64/system@framework@boot-ext.art -6ff7a000-6ff85000 r--p 00035000 103:1d 639529 /data/dalvik-cache/arm64/system@framework@boot-ext.art -6ff85000-70594000 rw-p 00000000 103:1d 639532 /data/dalvik-cache/arm64/system@framework@boot-framework.art -70594000-705cb000 r--p 0060f000 103:1d 639532 /data/dalvik-cache/arm64/system@framework@boot-framework.art -705cb000-7061f000 rw-p 00000000 103:1d 639535 /data/dalvik-cache/arm64/system@framework@boot-telephony-common.art -7061f000-70629000 r--p 00054000 103:1d 639535 /data/dalvik-cache/arm64/system@framework@boot-telephony-common.art -70629000-70635000 rw-p 00000000 103:1d 639538 /data/dalvik-cache/arm64/system@framework@boot-voip-common.art -70635000-70636000 r--p 0000c000 103:1d 639538 /data/dalvik-cache/arm64/system@framework@boot-voip-common.art -70636000-70644000 rw-p 00000000 103:1d 639541 /data/dalvik-cache/arm64/system@framework@boot-ims-common.art -70644000-70645000 r--p 0000e000 103:1d 639541 /data/dalvik-cache/arm64/system@framework@boot-ims-common.art -70645000-70648000 rw-p 00000000 103:1d 639544 /data/dalvik-cache/arm64/system@framework@boot-android.hidl.base-V1.0-java.art -70648000-7064c000 rw-p 00000000 103:1d 639547 /data/dalvik-cache/arm64/system@framework@boot-android.hidl.manager-V1.0-java.art -7064c000-7064d000 r--p 00004000 103:1d 639547 /data/dalvik-cache/arm64/system@framework@boot-android.hidl.manager-V1.0-java.art -7064d000-7064e000 rw-p 00000000 103:1d 639550 /data/dalvik-cache/arm64/system@framework@boot-framework-oahl-backward-compatibility.art -7064e000-70652000 rw-p 00000000 103:1d 639553 /data/dalvik-cache/arm64/system@framework@boot-android.test.base.art -70652000-70653000 r--p 00004000 103:1d 639553 /data/dalvik-cache/arm64/system@framework@boot-android.test.base.art -70653000-70654000 rw-p 00000000 103:1d 639556 /data/dalvik-cache/arm64/system@framework@boot-com.google.vr.platform.art -70654000-70655000 r--p 00001000 103:1d 639556 /data/dalvik-cache/arm64/system@framework@boot-com.google.vr.platform.art -70655000-70731000 r--p 00000000 fc:00 940 /system/framework/arm64/boot.oat -70731000-709ca000 r-xp 000dc000 fc:00 940 /system/framework/arm64/boot.oat -709ca000-709cb000 rw-p 00000000 00:00 0 [anon:.bss] -709cb000-70e4c000 r--s 00000000 fc:00 961 /system/framework/boot.vdex -70e4c000-70e4d000 r--p 00375000 fc:00 940 /system/framework/arm64/boot.oat -70e4d000-70e4e000 rw-p 00376000 fc:00 940 /system/framework/arm64/boot.oat -70e4e000-70eab000 r--p 00000000 fc:00 916 /system/framework/arm64/boot-core-libart.oat -70eab000-70fad000 r-xp 0005d000 fc:00 916 /system/framework/arm64/boot-core-libart.oat -70fad000-70fae000 rw-p 00000000 00:00 0 [anon:.bss] -70fae000-712a9000 r--s 00000000 fc:00 702 /system/framework/boot-core-libart.vdex -712a9000-712aa000 r--p 0015f000 fc:00 916 /system/framework/arm64/boot-core-libart.oat -712aa000-712ab000 rw-p 00160000 fc:00 916 /system/framework/arm64/boot-core-libart.oat -712ab000-712bb000 r--p 00000000 fc:00 941 /system/framework/arm64/boot-conscrypt.oat -712bb000-712e4000 r-xp 00010000 fc:00 941 /system/framework/arm64/boot-conscrypt.oat -712e4000-712e5000 rw-p 00000000 00:00 0 [anon:.bss] -712e5000-71346000 r--s 00000000 fc:00 970 /system/framework/boot-conscrypt.vdex -71346000-71347000 r--p 00039000 fc:00 941 /system/framework/arm64/boot-conscrypt.oat -71347000-71348000 rw-p 0003a000 fc:00 941 /system/framework/arm64/boot-conscrypt.oat -71348000-71361000 r--p 00000000 fc:00 908 /system/framework/arm64/boot-okhttp.oat -71361000-713a3000 r-xp 00019000 fc:00 908 /system/framework/arm64/boot-okhttp.oat -713a3000-713a4000 rw-p 00000000 00:00 0 [anon:.bss] -713a4000-71403000 r--s 00000000 fc:00 886 /system/framework/boot-okhttp.vdex -71403000-71404000 r--p 0005b000 fc:00 908 /system/framework/arm64/boot-okhttp.oat -71404000-71405000 rw-p 0005c000 fc:00 908 /system/framework/arm64/boot-okhttp.oat -71405000-71415000 r--p 00000000 fc:00 936 /system/framework/arm64/boot-bouncycastle.oat -71415000-71437000 r-xp 00010000 fc:00 936 /system/framework/arm64/boot-bouncycastle.oat -71437000-71438000 rw-p 00000000 00:00 0 [anon:.bss] -71438000-7157b000 r--s 00000000 fc:00 1006 /system/framework/boot-bouncycastle.vdex -7157b000-7157c000 r--p 00032000 fc:00 936 /system/framework/arm64/boot-bouncycastle.oat -7157c000-7157d000 rw-p 00033000 fc:00 936 /system/framework/arm64/boot-bouncycastle.oat -7157d000-71583000 r--p 00000000 fc:00 932 /system/framework/arm64/boot-apache-xml.oat -71583000-71584000 r-xp 00006000 fc:00 932 /system/framework/arm64/boot-apache-xml.oat -71584000-716a7000 r--s 00000000 fc:00 883 /system/framework/boot-apache-xml.vdex -716a7000-716a8000 r--p 00007000 fc:00 932 /system/framework/arm64/boot-apache-xml.oat -716a8000-716a9000 rw-p 00008000 fc:00 932 /system/framework/arm64/boot-apache-xml.oat -716a9000-716b5000 r--p 00000000 fc:00 891 /system/framework/arm64/boot-ext.oat -716b5000-716cc000 r-xp 0000c000 fc:00 891 /system/framework/arm64/boot-ext.oat -716cc000-716cd000 rw-p 00000000 00:00 0 [anon:.bss] -716cd000-717b8000 r--s 00000000 fc:00 879 /system/framework/boot-ext.vdex -717b8000-717b9000 r--p 00023000 fc:00 891 /system/framework/arm64/boot-ext.oat -717b9000-717ba000 rw-p 00024000 fc:00 891 /system/framework/arm64/boot-ext.oat -717ba000-71aeb000 r--p 00000000 fc:00 943 /system/framework/arm64/boot-framework.oat -71aeb000-72390000 r-xp 00331000 fc:00 943 /system/framework/arm64/boot-framework.oat -72390000-72396000 rw-p 00000000 00:00 0 [anon:.bss] -72396000-73746000 r--s 00000000 fc:00 985 /system/framework/boot-framework.vdex -73746000-73747000 r--p 00bd6000 fc:00 943 /system/framework/arm64/boot-framework.oat -73747000-73748000 rw-p 00bd7000 fc:00 943 /system/framework/arm64/boot-framework.oat -73748000-73780000 r--p 00000000 fc:00 893 /system/framework/arm64/boot-telephony-common.oat -73780000-73818000 r-xp 00038000 fc:00 893 /system/framework/arm64/boot-telephony-common.oat -73818000-7381a000 rw-p 00000000 00:00 0 [anon:.bss] -7381a000-73af0000 r--s 00000000 fc:00 697 /system/framework/boot-telephony-common.vdex -73af0000-73af1000 r--p 000d0000 fc:00 893 /system/framework/arm64/boot-telephony-common.oat -73af1000-73af2000 rw-p 000d1000 fc:00 893 /system/framework/arm64/boot-telephony-common.oat -73af2000-73af6000 r--p 00000000 fc:00 922 /system/framework/arm64/boot-voip-common.oat -73af6000-73af8000 r-xp 00004000 fc:00 922 /system/framework/arm64/boot-voip-common.oat -73af8000-73af9000 rw-p 00000000 00:00 0 [anon:.bss] -73af9000-73b1e000 r--s 00000000 fc:00 959 /system/framework/boot-voip-common.vdex -73b1e000-73b1f000 r--p 00006000 fc:00 922 /system/framework/arm64/boot-voip-common.oat -73b1f000-73b20000 rw-p 00007000 fc:00 922 /system/framework/arm64/boot-voip-common.oat -73b20000-73b23000 r--p 00000000 fc:00 918 /system/framework/arm64/boot-ims-common.oat -73b23000-73b25000 r-xp 00003000 fc:00 918 /system/framework/arm64/boot-ims-common.oat -73b25000-73b26000 rw-p 00000000 00:00 0 [anon:.bss] -73b26000-73b48000 r--s 00000000 fc:00 957 /system/framework/boot-ims-common.vdex -73b48000-73b49000 r--p 00005000 fc:00 918 /system/framework/arm64/boot-ims-common.oat -73b49000-73b4a000 rw-p 00006000 fc:00 918 /system/framework/arm64/boot-ims-common.oat -73b4a000-73b4d000 r--p 00000000 fc:00 909 /system/framework/arm64/boot-android.hidl.base-V1.0-java.oat -73b4d000-73b4e000 r-xp 00003000 fc:00 909 /system/framework/arm64/boot-android.hidl.base-V1.0-java.oat -73b4e000-73b55000 r--s 00000000 fc:00 972 /system/framework/boot-android.hidl.base-V1.0-java.vdex -73b55000-73b56000 r--p 00004000 fc:00 909 /system/framework/arm64/boot-android.hidl.base-V1.0-java.oat -73b56000-73b57000 rw-p 00005000 fc:00 909 /system/framework/arm64/boot-android.hidl.base-V1.0-java.oat -73b57000-73b5a000 r--p 00000000 fc:00 954 /system/framework/arm64/boot-android.hidl.manager-V1.0-java.oat -73b5a000-73b5c000 r-xp 00003000 fc:00 954 /system/framework/arm64/boot-android.hidl.manager-V1.0-java.oat -73b5c000-73b5d000 rw-p 00000000 00:00 0 [anon:.bss] -73b5d000-73b68000 r--s 00000000 fc:00 704 /system/framework/boot-android.hidl.manager-V1.0-java.vdex -73b68000-73b69000 r--p 00005000 fc:00 954 /system/framework/arm64/boot-android.hidl.manager-V1.0-java.oat -73b69000-73b6a000 rw-p 00006000 fc:00 954 /system/framework/arm64/boot-android.hidl.manager-V1.0-java.oat -73b6a000-73b6d000 r--p 00000000 fc:00 904 /system/framework/arm64/boot-framework-oahl-backward-compatibility.oat -73b6d000-73b6e000 r-xp 00003000 fc:00 904 /system/framework/arm64/boot-framework-oahl-backward-compatibility.oat -73b6e000-73b6f000 r--s 00000000 fc:00 994 /system/framework/boot-framework-oahl-backward-compatibility.vdex -73b6f000-73b70000 r--p 00004000 fc:00 904 /system/framework/arm64/boot-framework-oahl-backward-compatibility.oat -73b70000-73b71000 rw-p 00005000 fc:00 904 /system/framework/arm64/boot-framework-oahl-backward-compatibility.oat -73b71000-73b75000 r--p 00000000 fc:00 896 /system/framework/arm64/boot-android.test.base.oat -73b75000-73b79000 r-xp 00004000 fc:00 896 /system/framework/arm64/boot-android.test.base.oat -73b79000-73b7a000 rw-p 00000000 00:00 0 [anon:.bss] -73b7a000-73b82000 r--s 00000000 fc:00 706 /system/framework/boot-android.test.base.vdex -73b82000-73b83000 r--p 00008000 fc:00 896 /system/framework/arm64/boot-android.test.base.oat -73b83000-73b84000 rw-p 00009000 fc:00 896 /system/framework/arm64/boot-android.test.base.oat -73b84000-73b87000 r--p 00000000 fc:00 899 /system/framework/arm64/boot-com.google.vr.platform.oat -73b87000-73b88000 r-xp 00003000 fc:00 899 /system/framework/arm64/boot-com.google.vr.platform.oat -73b88000-73b89000 r--s 00000000 fc:00 884 /system/framework/boot-com.google.vr.platform.vdex -73b89000-73b8a000 r--p 00004000 fc:00 899 /system/framework/arm64/boot-com.google.vr.platform.oat -73b8a000-73b8b000 rw-p 00005000 fc:00 899 /system/framework/arm64/boot-com.google.vr.platform.oat -73b8b000-73b93000 rw-p 00000000 00:05 10267640 [anon:dalvik-non moving space] -73b93000-77b8b000 ---p 00008000 00:05 10267640 [anon:dalvik-non moving space] -77b8b000-97b8b000 rw-p 00000000 00:05 10267645 [anon:dalvik-free list large object space] -97b8b000-99b8b000 rw-p 00000000 00:05 10270989 [anon:dalvik-data-code-cache] -99b8b000-9bb8b000 r-xp 00000000 00:05 10270990 [anon:dalvik-jit-code-cache] -ebad6000-ebad7000 ---p 00000000 00:05 10269717 [anon:dalvik-Sentinel fault page] -7ffb6e000-7ffb76000 rw-s 000e5000 00:10 20630 /dev/kgsl-3d0 -7ffb76000-7ffb78000 rw-s 000e0000 00:10 20630 /dev/kgsl-3d0 -7ffbc3000-7ffbc4000 rw-s 000e8000 00:10 20630 /dev/kgsl-3d0 -7ffbc4000-7ffbc5000 rw-s 000e7000 00:10 20630 /dev/kgsl-3d0 -7ffbc6000-7ffbce000 rw-s 000e4000 00:10 20630 /dev/kgsl-3d0 -7ffbd0000-7ffbd2000 rw-s 000df000 00:10 20630 /dev/kgsl-3d0 -7ffbd2000-7ffbd4000 rw-s 000de000 00:10 20630 /dev/kgsl-3d0 -7ffbd4000-7ffbd6000 rw-s 000dd000 00:10 20630 /dev/kgsl-3d0 -7ffbd6000-7ffbd8000 rw-s 000dc000 00:10 20630 /dev/kgsl-3d0 -7ffbd8000-7ffbda000 rw-s 000db000 00:10 20630 /dev/kgsl-3d0 -7ffbda000-7ffbdc000 rw-s 000da000 00:10 20630 /dev/kgsl-3d0 -7ffbdd000-7ffbde000 rw-s 000ec000 00:10 20630 /dev/kgsl-3d0 -7ffbde000-7ffbe0000 rw-s 000d8000 00:10 20630 /dev/kgsl-3d0 -7ffce1000-7ffce2000 rw-s 000e6000 00:10 20630 /dev/kgsl-3d0 -7ffce2000-7ffce4000 rw-s 000d9000 00:10 20630 /dev/kgsl-3d0 -7ffce4000-7ffce8000 rw-s 000d4000 00:10 20630 /dev/kgsl-3d0 -7ffce8000-7ffcf8000 rw-s 000d2000 00:10 20630 /dev/kgsl-3d0 -7ffcf8000-7ffd08000 rw-s 000d1000 00:10 20630 /dev/kgsl-3d0 -7ffd08000-7ffd10000 rw-s 000d0000 00:10 20630 /dev/kgsl-3d0 -7ffd14000-7ffd18000 rw-s 000cd000 00:10 20630 /dev/kgsl-3d0 -7ffd18000-7ffd28000 rw-s 000cc000 00:10 20630 /dev/kgsl-3d0 -7ffd28000-7ffd38000 rw-s 000cb000 00:10 20630 /dev/kgsl-3d0 -7ffd38000-7ffd48000 rw-s 000ca000 00:10 20630 /dev/kgsl-3d0 -7ffd48000-7ffd58000 rw-s 000c9000 00:10 20630 /dev/kgsl-3d0 -7ffd58000-7ffd68000 rw-s 000c8000 00:10 20630 /dev/kgsl-3d0 -7ffd68000-7ffd6c000 rw-s 000c7000 00:10 20630 /dev/kgsl-3d0 -7ffdb1000-7ffdb2000 rw-s 000e3000 00:10 20630 /dev/kgsl-3d0 -7ffdb4000-7ffdb5000 rw-s 000e2000 00:10 20630 /dev/kgsl-3d0 -7ffdb5000-7ffdb7000 rw-s 000d7000 00:10 20630 /dev/kgsl-3d0 -7ffdb7000-7ffdb8000 rw-s 000c2000 00:10 20630 /dev/kgsl-3d0 -7ffdb8000-7ffdbc000 rw-s 000c0000 00:10 20630 /dev/kgsl-3d0 -7ffdbc000-7ffdc0000 rw-s 000be000 00:10 20630 /dev/kgsl-3d0 -7ffdc0000-7ffe00000 rw-s 000bb000 00:10 20630 /dev/kgsl-3d0 -7ffe00000-7ffe20000 rw-s 000ba000 00:10 20630 /dev/kgsl-3d0 -7ffe20000-7ffee0000 rw-s 000b9000 00:10 20630 /dev/kgsl-3d0 -7ffee1000-7ffee3000 rw-s 000c1000 00:10 20630 /dev/kgsl-3d0 -7ffee3000-7ffee4000 rw-s 000bf000 00:10 20630 /dev/kgsl-3d0 -7ffee4000-7ffee8000 rw-s 000bd000 00:10 20630 /dev/kgsl-3d0 -7ffee8000-7ffee9000 rw-s 000bc000 00:10 20630 /dev/kgsl-3d0 -7ffeea000-7ffeeb000 rw-s 000e1000 00:10 20630 /dev/kgsl-3d0 -7ffeeb000-7ffeec000 rw-s 000b6000 00:10 20630 /dev/kgsl-3d0 -7ffeec000-7ffeed000 rw-s 000b5000 00:10 20630 /dev/kgsl-3d0 -7ffeed000-7ffeee000 rw-s 000b4000 00:10 20630 /dev/kgsl-3d0 -7ffeee000-7ffeef000 rw-s 000b3000 00:10 20630 /dev/kgsl-3d0 -7ffeef000-7ffef0000 rw-s 000b2000 00:10 20630 /dev/kgsl-3d0 -7ffef0000-7ffef1000 rw-s 000b1000 00:10 20630 /dev/kgsl-3d0 -7ffef1000-7ffef2000 rw-s 000b0000 00:10 20630 /dev/kgsl-3d0 -7ffef2000-7ffef3000 rw-s 000af000 00:10 20630 /dev/kgsl-3d0 -7ffef3000-7ffef4000 rw-s 000ae000 00:10 20630 /dev/kgsl-3d0 -7ffef4000-7ffef5000 rw-s 000ad000 00:10 20630 /dev/kgsl-3d0 -7ffef5000-7ffef6000 rw-s 000ac000 00:10 20630 /dev/kgsl-3d0 -7ffef6000-7ffef7000 rw-s 000ab000 00:10 20630 /dev/kgsl-3d0 -7ffef7000-7ffef8000 rw-s 000aa000 00:10 20630 /dev/kgsl-3d0 -7ffef8000-7ffef9000 rw-s 000a9000 00:10 20630 /dev/kgsl-3d0 -7ffef9000-7ffefa000 rw-s 000a8000 00:10 20630 /dev/kgsl-3d0 -7ffefa000-7ffefb000 rw-s 000a7000 00:10 20630 /dev/kgsl-3d0 -7ffefb000-7ffefc000 rw-s 000a6000 00:10 20630 /dev/kgsl-3d0 -7ffefc000-7ffefd000 rw-s 000a5000 00:10 20630 /dev/kgsl-3d0 -7ffefd000-7ffefe000 rw-s 000a4000 00:10 20630 /dev/kgsl-3d0 -7ffefe000-7ffeff000 rw-s 000a3000 00:10 20630 /dev/kgsl-3d0 -7ffeff000-7fff00000 rw-s 000a2000 00:10 20630 /dev/kgsl-3d0 -7fff00000-7fff01000 rw-s 000a1000 00:10 20630 /dev/kgsl-3d0 -7fff01000-7fff02000 rw-s 000a0000 00:10 20630 /dev/kgsl-3d0 -7fff02000-7fff03000 rw-s 0009f000 00:10 20630 /dev/kgsl-3d0 -7fff03000-7fff04000 rw-s 0009e000 00:10 20630 /dev/kgsl-3d0 -7fff04000-7fff05000 rw-s 0009d000 00:10 20630 /dev/kgsl-3d0 -7fff05000-7fff06000 rw-s 0009c000 00:10 20630 /dev/kgsl-3d0 -7fff06000-7fff07000 rw-s 0009b000 00:10 20630 /dev/kgsl-3d0 -7fff07000-7fff08000 rw-s 0009a000 00:10 20630 /dev/kgsl-3d0 -7fff08000-7fff09000 rw-s 00099000 00:10 20630 /dev/kgsl-3d0 -7fff09000-7fff0a000 rw-s 00098000 00:10 20630 /dev/kgsl-3d0 -7fff0a000-7fff0b000 rw-s 00097000 00:10 20630 /dev/kgsl-3d0 -7fff0b000-7fff0c000 rw-s 00096000 00:10 20630 /dev/kgsl-3d0 -7fff0c000-7fff0d000 rw-s 00095000 00:10 20630 /dev/kgsl-3d0 -7fff0d000-7fff0e000 rw-s 00094000 00:10 20630 /dev/kgsl-3d0 -7fff0e000-7fff0f000 rw-s 00093000 00:10 20630 /dev/kgsl-3d0 -7fff0f000-7fff10000 rw-s 00092000 00:10 20630 /dev/kgsl-3d0 -7fff10000-7fff11000 rw-s 00091000 00:10 20630 /dev/kgsl-3d0 -7fff11000-7fff12000 rw-s 00090000 00:10 20630 /dev/kgsl-3d0 -7fff12000-7fff13000 rw-s 0008f000 00:10 20630 /dev/kgsl-3d0 -7fff13000-7fff14000 rw-s 0008e000 00:10 20630 /dev/kgsl-3d0 -7fff14000-7fff15000 rw-s 0008d000 00:10 20630 /dev/kgsl-3d0 -7fff15000-7fff16000 rw-s 0008c000 00:10 20630 /dev/kgsl-3d0 -7fff16000-7fff17000 rw-s 0008b000 00:10 20630 /dev/kgsl-3d0 -7fff17000-7fff18000 rw-s 0008a000 00:10 20630 /dev/kgsl-3d0 -7fff18000-7fff19000 rw-s 00089000 00:10 20630 /dev/kgsl-3d0 -7fff19000-7fff1a000 rw-s 00088000 00:10 20630 /dev/kgsl-3d0 -7fff1a000-7fff1b000 rw-s 00087000 00:10 20630 /dev/kgsl-3d0 -7fff1b000-7fff1c000 rw-s 00086000 00:10 20630 /dev/kgsl-3d0 -7fff1c000-7fff1d000 rw-s 00085000 00:10 20630 /dev/kgsl-3d0 -7fff1d000-7fff1e000 rw-s 00084000 00:10 20630 /dev/kgsl-3d0 -7fff1e000-7fff1f000 rw-s 00083000 00:10 20630 /dev/kgsl-3d0 -7fff1f000-7fff20000 rw-s 00082000 00:10 20630 /dev/kgsl-3d0 -7fff20000-7fff21000 rw-s 00081000 00:10 20630 /dev/kgsl-3d0 -7fff21000-7fff22000 rw-s 00080000 00:10 20630 /dev/kgsl-3d0 -7fff22000-7fff23000 rw-s 0007f000 00:10 20630 /dev/kgsl-3d0 -7fff23000-7fff24000 rw-s 0007e000 00:10 20630 /dev/kgsl-3d0 -7fff24000-7fff25000 rw-s 0007d000 00:10 20630 /dev/kgsl-3d0 -7fff25000-7fff26000 rw-s 0007c000 00:10 20630 /dev/kgsl-3d0 -7fff26000-7fff27000 rw-s 0007b000 00:10 20630 /dev/kgsl-3d0 -7fff27000-7fff28000 rw-s 0007a000 00:10 20630 /dev/kgsl-3d0 -7fff28000-7fff29000 rw-s 00079000 00:10 20630 /dev/kgsl-3d0 -7fff29000-7fff2a000 rw-s 00078000 00:10 20630 /dev/kgsl-3d0 -7fff2a000-7fff2b000 rw-s 00077000 00:10 20630 /dev/kgsl-3d0 -7fff2b000-7fff2c000 rw-s 00076000 00:10 20630 /dev/kgsl-3d0 -7fff2c000-7fff2d000 rw-s 00075000 00:10 20630 /dev/kgsl-3d0 -7fff2d000-7fff2e000 rw-s 00074000 00:10 20630 /dev/kgsl-3d0 -7fff2e000-7fff2f000 rw-s 00073000 00:10 20630 /dev/kgsl-3d0 -7fff2f000-7fff30000 rw-s 00072000 00:10 20630 /dev/kgsl-3d0 -7fff30000-7fff31000 rw-s 00071000 00:10 20630 /dev/kgsl-3d0 -7fff31000-7fff32000 rw-s 00070000 00:10 20630 /dev/kgsl-3d0 -7fff32000-7fff33000 rw-s 0006f000 00:10 20630 /dev/kgsl-3d0 -7fff33000-7fff34000 rw-s 0006e000 00:10 20630 /dev/kgsl-3d0 -7fff34000-7fff35000 rw-s 0006d000 00:10 20630 /dev/kgsl-3d0 -7fff35000-7fff36000 rw-s 0006c000 00:10 20630 /dev/kgsl-3d0 -7fff36000-7fff37000 rw-s 0006b000 00:10 20630 /dev/kgsl-3d0 -7fff37000-7fff38000 rw-s 0006a000 00:10 20630 /dev/kgsl-3d0 -7fff38000-7fff39000 rw-s 00069000 00:10 20630 /dev/kgsl-3d0 -7fff39000-7fff3a000 rw-s 00068000 00:10 20630 /dev/kgsl-3d0 -7fff3a000-7fff3b000 rw-s 00067000 00:10 20630 /dev/kgsl-3d0 -7fff3b000-7fff3c000 rw-s 00066000 00:10 20630 /dev/kgsl-3d0 -7fff3c000-7fff3d000 rw-s 00065000 00:10 20630 /dev/kgsl-3d0 -7fff3d000-7fff3e000 rw-s 00064000 00:10 20630 /dev/kgsl-3d0 -7fff3e000-7fff3f000 rw-s 00063000 00:10 20630 /dev/kgsl-3d0 -7fff3f000-7fff40000 rw-s 00062000 00:10 20630 /dev/kgsl-3d0 -7fff40000-7fff41000 rw-s 00061000 00:10 20630 /dev/kgsl-3d0 -7fff41000-7fff42000 rw-s 00060000 00:10 20630 /dev/kgsl-3d0 -7fff42000-7fff43000 rw-s 0005f000 00:10 20630 /dev/kgsl-3d0 -7fff43000-7fff44000 rw-s 0005e000 00:10 20630 /dev/kgsl-3d0 -7fff44000-7fff45000 rw-s 0005d000 00:10 20630 /dev/kgsl-3d0 -7fff45000-7fff46000 rw-s 0005c000 00:10 20630 /dev/kgsl-3d0 -7fff46000-7fff47000 rw-s 0005b000 00:10 20630 /dev/kgsl-3d0 -7fff47000-7fff48000 rw-s 0005a000 00:10 20630 /dev/kgsl-3d0 -7fff48000-7fff49000 rw-s 00059000 00:10 20630 /dev/kgsl-3d0 -7fff49000-7fff4a000 rw-s 00058000 00:10 20630 /dev/kgsl-3d0 -7fff4a000-7fff4b000 rw-s 00057000 00:10 20630 /dev/kgsl-3d0 -7fff4b000-7fff4c000 rw-s 00056000 00:10 20630 /dev/kgsl-3d0 -7fff4c000-7fff4d000 rw-s 00055000 00:10 20630 /dev/kgsl-3d0 -7fff4d000-7fff4e000 rw-s 00054000 00:10 20630 /dev/kgsl-3d0 -7fff4e000-7fff4f000 rw-s 00053000 00:10 20630 /dev/kgsl-3d0 -7fff4f000-7fff50000 rw-s 00052000 00:10 20630 /dev/kgsl-3d0 -7fff50000-7fff51000 rw-s 00051000 00:10 20630 /dev/kgsl-3d0 -7fff51000-7fff52000 rw-s 00050000 00:10 20630 /dev/kgsl-3d0 -7fff52000-7fff53000 rw-s 0004f000 00:10 20630 /dev/kgsl-3d0 -7fff53000-7fff54000 rw-s 0004e000 00:10 20630 /dev/kgsl-3d0 -7fff54000-7fff55000 rw-s 0004d000 00:10 20630 /dev/kgsl-3d0 -7fff55000-7fff56000 rw-s 0004c000 00:10 20630 /dev/kgsl-3d0 -7fff56000-7fff57000 rw-s 0004b000 00:10 20630 /dev/kgsl-3d0 -7fff57000-7fff58000 rw-s 0004a000 00:10 20630 /dev/kgsl-3d0 -7fff58000-7fff59000 rw-s 00049000 00:10 20630 /dev/kgsl-3d0 -7fff59000-7fff5a000 rw-s 00048000 00:10 20630 /dev/kgsl-3d0 -7fff5a000-7fff5b000 rw-s 00047000 00:10 20630 /dev/kgsl-3d0 -7fff5b000-7fff5c000 rw-s 00046000 00:10 20630 /dev/kgsl-3d0 -7fff5c000-7fff5d000 rw-s 00045000 00:10 20630 /dev/kgsl-3d0 -7fff5d000-7fff5e000 rw-s 00044000 00:10 20630 /dev/kgsl-3d0 -7fff5e000-7fff5f000 rw-s 00043000 00:10 20630 /dev/kgsl-3d0 -7fff5f000-7fff60000 rw-s 00042000 00:10 20630 /dev/kgsl-3d0 -7fff60000-7fff61000 rw-s 00041000 00:10 20630 /dev/kgsl-3d0 -7fff61000-7fff62000 rw-s 00040000 00:10 20630 /dev/kgsl-3d0 -7fff62000-7fff63000 rw-s 0003f000 00:10 20630 /dev/kgsl-3d0 -7fff63000-7fff64000 rw-s 0003e000 00:10 20630 /dev/kgsl-3d0 -7fff64000-7fff65000 rw-s 0003d000 00:10 20630 /dev/kgsl-3d0 -7fff65000-7fff66000 rw-s 0003c000 00:10 20630 /dev/kgsl-3d0 -7fff66000-7fff67000 rw-s 0003b000 00:10 20630 /dev/kgsl-3d0 -7fff67000-7fff68000 rw-s 0003a000 00:10 20630 /dev/kgsl-3d0 -7fff68000-7fff69000 rw-s 00039000 00:10 20630 /dev/kgsl-3d0 -7fff69000-7fff6a000 rw-s 00038000 00:10 20630 /dev/kgsl-3d0 -7fff6a000-7fff6b000 rw-s 00037000 00:10 20630 /dev/kgsl-3d0 -7fff6b000-7fff6c000 rw-s 00036000 00:10 20630 /dev/kgsl-3d0 -7fff6c000-7fff6d000 rw-s 00035000 00:10 20630 /dev/kgsl-3d0 -7fff6d000-7fff6e000 rw-s 00034000 00:10 20630 /dev/kgsl-3d0 -7fff6e000-7fff6f000 rw-s 00033000 00:10 20630 /dev/kgsl-3d0 -7fff6f000-7fff70000 rw-s 00032000 00:10 20630 /dev/kgsl-3d0 -7fff70000-7fff71000 rw-s 00031000 00:10 20630 /dev/kgsl-3d0 -7fff71000-7fff72000 rw-s 00030000 00:10 20630 /dev/kgsl-3d0 -7fff72000-7fff73000 rw-s 0002f000 00:10 20630 /dev/kgsl-3d0 -7fff73000-7fff74000 rw-s 0002e000 00:10 20630 /dev/kgsl-3d0 -7fff74000-7fff75000 rw-s 0002d000 00:10 20630 /dev/kgsl-3d0 -7fff75000-7fff76000 rw-s 0002c000 00:10 20630 /dev/kgsl-3d0 -7fff76000-7fff77000 rw-s 0002b000 00:10 20630 /dev/kgsl-3d0 -7fff77000-7fff78000 rw-s 0002a000 00:10 20630 /dev/kgsl-3d0 -7fff78000-7fff79000 rw-s 00029000 00:10 20630 /dev/kgsl-3d0 -7fff79000-7fff7a000 rw-s 00028000 00:10 20630 /dev/kgsl-3d0 -7fff7a000-7fff7b000 rw-s 00027000 00:10 20630 /dev/kgsl-3d0 -7fff7b000-7fff7c000 rw-s 00026000 00:10 20630 /dev/kgsl-3d0 -7fff7c000-7fff7d000 rw-s 00025000 00:10 20630 /dev/kgsl-3d0 -7fff7d000-7fff7e000 rw-s 00024000 00:10 20630 /dev/kgsl-3d0 -7fff7e000-7fff7f000 rw-s 00023000 00:10 20630 /dev/kgsl-3d0 -7fff7f000-7fff80000 rw-s 00022000 00:10 20630 /dev/kgsl-3d0 -7fff80000-7fff90000 rw-s 00019000 00:10 20630 /dev/kgsl-3d0 -7fff90000-7fffb0000 rw-s 00018000 00:10 20630 /dev/kgsl-3d0 -7fffb1000-7fffb2000 rw-s 00021000 00:10 20630 /dev/kgsl-3d0 -7fffb2000-7fffb3000 rw-s 00020000 00:10 20630 /dev/kgsl-3d0 -7fffb3000-7fffb4000 rw-s 0001f000 00:10 20630 /dev/kgsl-3d0 -7fffba000-7fffbe000 rw-s 0001b000 00:10 20630 /dev/kgsl-3d0 -7fffbe000-7fffbf000 rw-s 0001a000 00:10 20630 /dev/kgsl-3d0 -7fffbf000-7fffc0000 rw-s 00017000 00:10 20630 /dev/kgsl-3d0 -7fffc0000-7fffe0000 rw-s 00016000 00:10 20630 /dev/kgsl-3d0 -7fffe0000-7fffe1000 rw-s 00014000 00:10 20630 /dev/kgsl-3d0 -7fffe1000-7fffe5000 rw-s 00013000 00:10 20630 /dev/kgsl-3d0 -7fffe5000-7fffe6000 rw-s 00012000 00:10 20630 /dev/kgsl-3d0 -7fffe6000-7fffe7000 rw-s 00011000 00:10 20630 /dev/kgsl-3d0 -7fffe7000-7fffe8000 rw-s 00010000 00:10 20630 /dev/kgsl-3d0 -7fffe8000-7fffe9000 rw-s 0000f000 00:10 20630 /dev/kgsl-3d0 -7fffe9000-7fffea000 rw-s 0000e000 00:10 20630 /dev/kgsl-3d0 -7fffea000-7fffeb000 rw-s 0000d000 00:10 20630 /dev/kgsl-3d0 -7fffeb000-7fffec000 rw-s 0000c000 00:10 20630 /dev/kgsl-3d0 -7fffec000-7ffff0000 rw-s 0000b000 00:10 20630 /dev/kgsl-3d0 -7ffff0000-7ffff1000 rw-s 0000a000 00:10 20630 /dev/kgsl-3d0 -7ffff1000-7ffff5000 rw-s 00009000 00:10 20630 /dev/kgsl-3d0 -7ffff5000-7ffff6000 rw-s 00008000 00:10 20630 /dev/kgsl-3d0 -7ffff6000-7ffff7000 rw-s 00007000 00:10 20630 /dev/kgsl-3d0 -7ffff7000-7ffff8000 rw-s 00006000 00:10 20630 /dev/kgsl-3d0 -7ffff8000-7ffff9000 rw-s 00005000 00:10 20630 /dev/kgsl-3d0 -7ffff9000-7ffffa000 rw-s 00004000 00:10 20630 /dev/kgsl-3d0 -7ffffa000-7ffffb000 rw-s 00003000 00:10 20630 /dev/kgsl-3d0 -7ffffb000-7ffffc000 rw-s 00002000 00:10 20630 /dev/kgsl-3d0 -7ffffc000-800000000 rw-s 00001000 00:10 20630 /dev/kgsl-3d0 -5ff1d4f000-5ff1d54000 r-xp 00000000 fc:00 3419 /system/bin/app_process64 -5ff1d6e000-5ff1d6f000 r--p 0000f000 fc:00 3419 /system/bin/app_process64 -5ff1d6f000-5ff1d71000 rw-p 00000000 00:00 0 -704defa000-704defb000 ---p 00000000 00:00 0 [anon:thread stack guard] -704defb000-704defc000 ---p 00000000 00:00 0 -704defc000-704e000000 rw-p 00000000 00:00 0 -704e000000-704e400000 rw-p 00000000 00:00 0 [anon:libc_malloc] -704e455000-704e456000 ---p 00000000 00:00 0 [anon:thread stack guard] -704e456000-704e457000 ---p 00000000 00:00 0 -704e457000-704e553000 rw-p 00000000 00:00 0 -704e553000-704e651000 r--p 00000000 00:10 16029 /dev/hwbinder -704e651000-704e65f000 r-xp 00000000 fc:01 1040 /vendor/lib64/egl/eglSubDriverAndroid.so -704e65f000-704e660000 r--p 0000e000 fc:01 1040 /vendor/lib64/egl/eglSubDriverAndroid.so -704e660000-704e661000 rw-p 0000f000 fc:01 1040 /vendor/lib64/egl/eglSubDriverAndroid.so -704e69d000-704e69e000 ---p 00000000 00:00 0 [anon:thread stack guard] -704e69e000-704e79b000 rw-p 00000000 00:00 0 -704e79b000-704f79b000 rw-s 00000000 00:05 10271021 /dev/ashmem/AudioFlinger::Client(29312) (deleted) -704f79b000-704f79c000 ---p 00000000 00:00 0 [anon:thread stack guard] -704f79c000-704f899000 rw-p 00000000 00:00 0 -704f899000-704f89a000 ---p 00000000 00:00 0 [anon:thread stack guard] -704f89a000-704f89b000 ---p 00000000 00:00 0 -704f89b000-704f997000 rw-p 00000000 00:00 0 -704f997000-704f9ee000 r-xp 00000000 103:1d 1737338 /data/app/com.google.sample.tunnel-HGGRU03Gu1Mwkf_-RnFmvw==/lib/arm64/libgame.so -704f9ee000-704f9fd000 ---p 00000000 00:00 0 -704f9fd000-704fa00000 r--p 00056000 103:1d 1737338 /data/app/com.google.sample.tunnel-HGGRU03Gu1Mwkf_-RnFmvw==/lib/arm64/libgame.so -704fa00000-704fa01000 rw-p 00059000 103:1d 1737338 /data/app/com.google.sample.tunnel-HGGRU03Gu1Mwkf_-RnFmvw==/lib/arm64/libgame.so -704fa01000-704fa19000 rw-p 00000000 00:00 0 [anon:.bss] -704fa40000-70507e7000 r-xp 00000000 fc:01 1026 /vendor/lib64/libllvm-glnext.so -70507e7000-70507fc000 ---p 00000000 00:00 0 -70507fc000-7050835000 r--p 00da7000 fc:01 1026 /vendor/lib64/libllvm-glnext.so -7050835000-705083a000 rw-p 00de0000 fc:01 1026 /vendor/lib64/libllvm-glnext.so -705083a000-7050855000 rw-p 00000000 00:00 0 [anon:.bss] -705089b000-7050f19000 r-xp 00000000 fc:01 1039 /vendor/lib64/egl/libGLESv2_adreno.so -7050f19000-7050f22000 r--p 0067e000 fc:01 1039 /vendor/lib64/egl/libGLESv2_adreno.so -7050f22000-7050f29000 rw-p 00687000 fc:01 1039 /vendor/lib64/egl/libGLESv2_adreno.so -7050f29000-7050f2c000 rw-p 00000000 00:00 0 [anon:.bss] -7050f83000-7050fbc000 r-xp 00000000 fc:01 1041 /vendor/lib64/egl/libGLESv1_CM_adreno.so -7050fbc000-7050fbd000 r--p 00039000 fc:01 1041 /vendor/lib64/egl/libGLESv1_CM_adreno.so -7050fbd000-7050fbe000 rw-p 0003a000 fc:01 1041 /vendor/lib64/egl/libGLESv1_CM_adreno.so -7050fbe000-7050fbf000 rw-p 00000000 00:00 0 [anon:.bss] -7050fc6000-705111d000 r-xp 00000000 fc:01 865 /vendor/lib64/libgsl.so -705111d000-705111e000 r--p 00157000 fc:01 865 /vendor/lib64/libgsl.so -705111e000-705111f000 rw-p 00158000 fc:01 865 /vendor/lib64/libgsl.so -705111f000-7051120000 rw-p 00000000 00:00 0 [anon:.bss] -7051146000-705115d000 r-xp 00000000 fc:00 2587 /system/lib64/vndk-sp-28/libz.so -705115d000-7051175000 ---p 00000000 00:00 0 -7051175000-7051176000 r--p 0001f000 fc:00 2587 /system/lib64/vndk-sp-28/libz.so -7051176000-7051177000 rw-p 00020000 fc:00 2587 /system/lib64/vndk-sp-28/libz.so -705119f000-70511ac000 r-xp 00000000 fc:01 886 /vendor/lib64/libadreno_utils.so -70511ac000-70511ad000 r--p 0000d000 fc:01 886 /vendor/lib64/libadreno_utils.so -70511ad000-70511ae000 rw-p 0000e000 fc:01 886 /vendor/lib64/libadreno_utils.so -70511ae000-70511b0000 rw-p 00000000 00:00 0 [anon:.bss] -70511c0000-70511d7000 r-xp 00000000 fc:01 1044 /vendor/lib64/egl/libEGL_adreno.so -70511d7000-70511d8000 r--p 00017000 fc:01 1044 /vendor/lib64/egl/libEGL_adreno.so -70511d8000-70511d9000 rw-p 00018000 fc:01 1044 /vendor/lib64/egl/libEGL_adreno.so -70511d9000-70511da000 rw-p 00000000 00:00 0 [anon:.bss] -705120a000-705120d000 r-xp 00000000 fc:01 972 /vendor/lib64/libdrmutils.so -705120d000-7051229000 ---p 00000000 00:00 0 -7051229000-705122a000 r--p 0000f000 fc:01 972 /vendor/lib64/libdrmutils.so -705122a000-705122b000 rw-p 00010000 fc:01 972 /vendor/lib64/libdrmutils.so -705125a000-705125c000 r-xp 00000000 fc:01 1046 /vendor/lib64/libqdMetaData.so -705125c000-7051279000 ---p 00000000 00:00 0 -7051279000-705127a000 r--p 0000f000 fc:01 1046 /vendor/lib64/libqdMetaData.so -705127a000-705127b000 rw-p 00010000 fc:01 1046 /vendor/lib64/libqdMetaData.so -7051286000-7051297000 r-xp 00000000 fc:01 1024 /vendor/lib64/libdrm.so -7051297000-70512b5000 ---p 00000000 00:00 0 -70512b5000-70512b6000 r--p 0001f000 fc:01 1024 /vendor/lib64/libdrm.so -70512b6000-70512b7000 rw-p 00020000 fc:01 1024 /vendor/lib64/libdrm.so -70512cb000-70512de000 r-xp 00000000 fc:01 1008 /vendor/lib64/hw/gralloc.msm8998.so -70512de000-70512fa000 ---p 00000000 00:00 0 -70512fa000-70512fb000 r--p 0001f000 fc:01 1008 /vendor/lib64/hw/gralloc.msm8998.so -70512fb000-70512fc000 rw-p 00020000 fc:01 1008 /vendor/lib64/hw/gralloc.msm8998.so -7051326000-7051327000 ---p 00000000 00:00 0 [anon:thread stack guard] -7051327000-7051328000 ---p 00000000 00:00 0 -7051328000-7051424000 rw-p 00000000 00:00 0 -7051424000-705143d000 r--p 00000000 fc:00 739 /system/framework/oat/arm64/org.apache.http.legacy.boot.odex -705143d000-7051480000 r-xp 00019000 fc:00 739 /system/framework/oat/arm64/org.apache.http.legacy.boot.odex -7051480000-7051494000 r--p 00211000 103:1d 639511 /data/dalvik-cache/arm64/system@framework@boot.art -7051494000-705149f000 r--p 000c5000 103:1d 639514 /data/dalvik-cache/arm64/system@framework@boot-core-libart.art -705149f000-70514a2000 r--p 00032000 103:1d 639517 /data/dalvik-cache/arm64/system@framework@boot-conscrypt.art -70514a2000-70514a5000 r--p 0002b000 103:1d 639520 /data/dalvik-cache/arm64/system@framework@boot-okhttp.art -70514a5000-70514ac000 r--p 0003f000 103:1d 639523 /data/dalvik-cache/arm64/system@framework@boot-bouncycastle.art -70514ac000-70514b2000 r--p 00044000 103:1d 639526 /data/dalvik-cache/arm64/system@framework@boot-apache-xml.art -70514b2000-70514bd000 r--p 00035000 103:1d 639529 /data/dalvik-cache/arm64/system@framework@boot-ext.art -70514bd000-70514f4000 r--p 0060f000 103:1d 639532 /data/dalvik-cache/arm64/system@framework@boot-framework.art -70514f4000-70514fe000 r--p 00054000 103:1d 639535 /data/dalvik-cache/arm64/system@framework@boot-telephony-common.art -70514fe000-70514ff000 r--p 0000c000 103:1d 639538 /data/dalvik-cache/arm64/system@framework@boot-voip-common.art -70514ff000-7051500000 r--p 0000e000 103:1d 639541 /data/dalvik-cache/arm64/system@framework@boot-ims-common.art -7051500000-7051501000 r--p 00004000 103:1d 639547 /data/dalvik-cache/arm64/system@framework@boot-android.hidl.manager-V1.0-java.art -7051501000-7051502000 r--p 00004000 103:1d 639553 /data/dalvik-cache/arm64/system@framework@boot-android.test.base.art -7051502000-7051503000 r--p 00001000 103:1d 639556 /data/dalvik-cache/arm64/system@framework@boot-com.google.vr.platform.art -7051503000-7051504000 rw-p 00000000 00:00 0 [anon:.bss] -7051504000-7051579000 r--s 00000000 fc:00 790 /system/framework/oat/arm64/org.apache.http.legacy.boot.vdex -7051579000-705157a000 r--p 0005c000 fc:00 739 /system/framework/oat/arm64/org.apache.http.legacy.boot.odex -705157a000-705157b000 rw-p 0005d000 fc:00 739 /system/framework/oat/arm64/org.apache.http.legacy.boot.odex -705158b000-7057f4d000 ---p 00000000 00:00 0 -7057f4d000-7057f4f000 r-xp 00000000 fc:00 2646 /system/lib64/libwebviewchromium_loader.so -7057f4f000-7057f6c000 ---p 00000000 00:00 0 -7057f6c000-7057f6d000 r--p 0000f000 fc:00 2646 /system/lib64/libwebviewchromium_loader.so -7057f6d000-7057f6e000 rw-p 00010000 fc:00 2646 /system/lib64/libwebviewchromium_loader.so -7057f76000-7057f96000 r--s 00000000 00:10 16615 /dev/__properties__/u:object_r:hwservicemanager_prop:s0 -7057f96000-7057fb6000 r--s 00000000 00:10 16639 /dev/__properties__/u:object_r:public_vendor_default_prop:s0 -7057fb6000-7058004000 r--s 00000000 fc:00 1112 /system/usr/hyphen-data/hyph-hu.hyb -7058004000-7058024000 r-xp 00000000 fc:00 2354 /system/lib64/libcompiler_rt.so -7058024000-7058043000 ---p 00000000 00:00 0 -7058043000-7058044000 r--p 0002f000 fc:00 2354 /system/lib64/libcompiler_rt.so -7058044000-7058045000 rw-p 00030000 fc:00 2354 /system/lib64/libcompiler_rt.so -7058045000-70580b2000 rw-p 00000000 00:00 0 [anon:.bss] -70580bd000-70580dd000 rw-p 00000000 00:05 10265386 [anon:dalvik-LinearAlloc] -70580dd000-70580df000 r-xp 00000000 fc:00 2597 /system/lib64/vndk-sp-28/libhardware.so -70580df000-70580fc000 ---p 00000000 00:00 0 -70580fc000-70580fd000 r--p 0000f000 fc:00 2597 /system/lib64/vndk-sp-28/libhardware.so -70580fd000-70580fe000 rw-p 00010000 fc:00 2597 /system/lib64/vndk-sp-28/libhardware.so -705810e000-705811f000 r-xp 00000000 fc:00 2589 /system/lib64/vndk-sp-28/libbase.so -705811f000-705813d000 ---p 00000000 00:00 0 -705813d000-705813e000 r--p 0001f000 fc:00 2589 /system/lib64/vndk-sp-28/libbase.so -705813e000-705813f000 rw-p 00020000 fc:00 2589 /system/lib64/vndk-sp-28/libbase.so -7058140000-7058167000 r-xp 00000000 fc:00 2572 /system/lib64/vndk-sp-28/libhwbinder.so -7058167000-705817d000 ---p 00000000 00:00 0 -705817d000-705817f000 r--p 0002e000 fc:00 2572 /system/lib64/vndk-sp-28/libhwbinder.so -705817f000-7058180000 rw-p 00030000 fc:00 2572 /system/lib64/vndk-sp-28/libhwbinder.so -705818c000-705818d000 r-xp 00000000 fc:00 2584 /system/lib64/vndk-sp-28/android.hardware.graphics.common@1.0.so -705818d000-70581ab000 ---p 00000000 00:00 0 -70581ab000-70581ac000 r--p 0000f000 fc:00 2584 /system/lib64/vndk-sp-28/android.hardware.graphics.common@1.0.so -70581ac000-70581ad000 rw-p 00010000 fc:00 2584 /system/lib64/vndk-sp-28/android.hardware.graphics.common@1.0.so -70581b7000-70581d7000 r--s 00000000 00:10 16619 /dev/__properties__/u:object_r:log_prop:s0 -70581d7000-7058237000 r-xp 00000000 fc:00 2574 /system/lib64/vndk-sp-28/libhidltransport.so -7058237000-7058255000 ---p 00000000 00:00 0 -7058255000-705825d000 r--p 00068000 fc:00 2574 /system/lib64/vndk-sp-28/libhidltransport.so -705825d000-705825e000 rw-p 00070000 fc:00 2574 /system/lib64/vndk-sp-28/libhidltransport.so -7058260000-7058284000 r--s 00000000 fc:00 1138 /system/usr/hyphen-data/hyph-nn.hyb -7058284000-70582a0000 r-xp 00000000 fc:00 2576 /system/lib64/vndk-sp-28/libutils.so -70582a0000-70582b3000 ---p 00000000 00:00 0 -70582b3000-70582b4000 r--p 0001f000 fc:00 2576 /system/lib64/vndk-sp-28/libutils.so -70582b4000-70582b5000 rw-p 00020000 fc:00 2576 /system/lib64/vndk-sp-28/libutils.so -70582c4000-7058391000 r-xp 00000000 fc:00 2568 /system/lib64/vndk-sp-28/libc++.so -7058391000-70583ad000 ---p 00000000 00:00 0 -70583ad000-70583b7000 r--p 000d6000 fc:00 2568 /system/lib64/vndk-sp-28/libc++.so -70583b7000-70583b8000 rw-p 000e0000 fc:00 2568 /system/lib64/vndk-sp-28/libc++.so -70583b8000-70583bb000 rw-p 00000000 00:00 0 [anon:.bss] -70583cd000-70583e4000 r-xp 00000000 fc:00 2580 /system/lib64/vndk-sp-28/android.hardware.graphics.mapper@2.0.so -70583e4000-70583f9000 ---p 00000000 00:00 0 -70583f9000-70583fb000 r--p 0001e000 fc:00 2580 /system/lib64/vndk-sp-28/android.hardware.graphics.mapper@2.0.so -70583fb000-70583fc000 rw-p 00020000 fc:00 2580 /system/lib64/vndk-sp-28/android.hardware.graphics.mapper@2.0.so -705841b000-7058421000 r-xp 00000000 fc:01 1001 /vendor/lib64/hw/android.hardware.graphics.mapper@2.0-impl.so -7058421000-705843a000 ---p 00000000 00:00 0 -705843a000-705843b000 r--p 0000f000 fc:01 1001 /vendor/lib64/hw/android.hardware.graphics.mapper@2.0-impl.so -705843b000-705843c000 rw-p 00010000 fc:01 1001 /vendor/lib64/hw/android.hardware.graphics.mapper@2.0-impl.so -705844f000-7058473000 r--s 00000000 fc:00 1150 /system/usr/hyphen-data/hyph-nb.hyb -7058473000-7058495000 r-xp 00000000 fc:00 2582 /system/lib64/vndk-sp-28/libhidlbase.so -7058495000-70584b1000 ---p 00000000 00:00 0 -70584b1000-70584b3000 r--p 0002e000 fc:00 2582 /system/lib64/vndk-sp-28/libhidlbase.so -70584b3000-70584b4000 rw-p 00030000 fc:00 2582 /system/lib64/vndk-sp-28/libhidlbase.so -70584cd000-70584df000 r-xp 00000000 fc:00 2595 /system/lib64/vndk-sp-28/libcutils.so -70584df000-70584fb000 ---p 00000000 00:00 0 -70584fb000-70584fd000 r--p 0001e000 fc:00 2595 /system/lib64/vndk-sp-28/libcutils.so -70584fd000-70584fe000 rw-p 00020000 fc:00 2595 /system/lib64/vndk-sp-28/libcutils.so -7058519000-7058537000 r--s 00000000 fc:00 1124 /system/usr/hyphen-data/hyph-de-ch-1901.hyb -7058537000-7059fd1000 r--s 0070b000 fc:00 989 /system/framework/framework-res.apk -7059fd1000-705a013000 r-xp 00000000 fc:00 2610 /system/lib64/libjavacrypto.so -705a013000-705a02b000 ---p 00000000 00:00 0 -705a02b000-705a02d000 r--p 0004e000 fc:00 2610 /system/lib64/libjavacrypto.so -705a02d000-705a02f000 rw-p 00050000 fc:00 2610 /system/lib64/libjavacrypto.so -705a041000-705a05f000 r--s 00000000 fc:00 1128 /system/usr/hyphen-data/hyph-de-1996.hyb -705a05f000-705a06a000 r-xp 00000000 fc:00 2917 /system/lib64/libsoundpool.so -705a06a000-705a07e000 ---p 00000000 00:00 0 -705a07e000-705a07f000 r--p 0000f000 fc:00 2917 /system/lib64/libsoundpool.so -705a07f000-705a080000 rw-p 00010000 fc:00 2917 /system/lib64/libsoundpool.so -705a087000-705a102000 r--s 00000000 fc:00 1246 /system/usr/share/zoneinfo/tzdata -705a102000-705a863000 r--s 00000000 fc:00 101 /system/fonts/NotoColorEmoji.ttf -705a863000-705c000000 r--s 00000000 fc:00 251 /system/fonts/NotoSerifCJK-Regular.ttc -705c000000-705c200000 rw-p 00000000 00:00 0 [anon:libc_malloc] -705c209000-705c227000 r--s 00000000 fc:00 1077 /system/usr/hyphen-data/hyph-de-1901.hyb -705c227000-705c26e000 r--s 02284000 fc:00 989 /system/framework/framework-res.apk -705c26e000-705d43e000 r--s 00000000 fc:00 95 /system/fonts/NotoSansCJK-Regular.ttc -705d43e000-705d4ec000 r--s 00000000 fc:00 278 /system/fonts/NotoSansSymbols-Regular-Subsetted.ttf -705d4ec000-705d548000 r--s 00000000 fc:00 233 /system/fonts/NotoSansTibetan-Bold.ttf -705d548000-705d5ab000 r--s 00000000 fc:00 177 /system/fonts/NotoSansTibetan-Regular.ttf -705d5ab000-705d627000 r--s 00000000 fc:00 197 /system/fonts/NotoSansEgyptianHieroglyphs-Regular.ttf -705d627000-705d6a2000 r--s 00000000 fc:00 76 /system/fonts/NotoSansCuneiform-Regular.ttf -705d6a2000-705d6f3000 r--s 00000000 fc:00 67 /system/fonts/RobotoCondensed-BoldItalic.ttf -705d6f3000-705d73e000 r--s 00000000 fc:00 199 /system/fonts/RobotoCondensed-Bold.ttf -705d73e000-705d78f000 r--s 00000000 fc:00 230 /system/fonts/RobotoCondensed-MediumItalic.ttf -705d78f000-705d7da000 r--s 00000000 fc:00 92 /system/fonts/RobotoCondensed-Medium.ttf -705d7da000-705d82b000 r--s 00000000 fc:00 128 /system/fonts/RobotoCondensed-Italic.ttf -705d82b000-705d875000 r--s 00000000 fc:00 164 /system/fonts/RobotoCondensed-Regular.ttf -705d875000-705d8c7000 r--s 00000000 fc:00 292 /system/fonts/RobotoCondensed-LightItalic.ttf -705d8c7000-705d919000 r--s 00000000 fc:00 85 /system/fonts/Roboto-BoldItalic.ttf -705d919000-705d964000 r--s 00000000 fc:00 175 /system/fonts/Roboto-Bold.ttf -705d964000-705d9b5000 r--s 00000000 fc:00 266 /system/fonts/Roboto-BlackItalic.ttf -705d9b5000-705da00000 r--s 00000000 fc:00 187 /system/fonts/Roboto-Black.ttf -705da00000-705dc00000 rw-p 00000000 00:00 0 [anon:libc_malloc] -705dc1d000-705dc6e000 r--s 00000000 fc:00 148 /system/fonts/Roboto-MediumItalic.ttf -705dc6e000-705dcb9000 r--s 00000000 fc:00 284 /system/fonts/Roboto-Medium.ttf -705dcb9000-705dd0a000 r--s 00000000 fc:00 105 /system/fonts/Roboto-Italic.ttf -705dd0a000-705dd55000 r--s 00000000 fc:00 156 /system/fonts/Roboto-Regular.ttf -705dd55000-705dda7000 r--s 00000000 fc:00 217 /system/fonts/Roboto-LightItalic.ttf -705dda7000-705ddf8000 r--s 00000000 fc:00 166 /system/fonts/Roboto-ThinItalic.ttf -705ddf8000-705ddf9000 ---p 00000000 00:00 0 [anon:thread stack guard] -705ddf9000-705ddfa000 ---p 00000000 00:00 0 -705ddfa000-705def6000 rw-p 00000000 00:00 0 -705def6000-705f5ec000 r--s 00000000 fc:00 1350 /system/usr/icu/icudt60l.dat -705f5ec000-705f5ed000 ---p 00000000 00:00 0 [anon:thread stack guard] -705f5ed000-705f5ee000 ---p 00000000 00:00 0 -705f5ee000-705f6ea000 rw-p 00000000 00:00 0 -705f6ea000-705f7e8000 r--p 00000000 00:10 20636 /dev/binder -705f7e8000-705f7e9000 ---p 00000000 00:00 0 [anon:thread stack guard] -705f7e9000-705f7ea000 ---p 00000000 00:00 0 -705f7ea000-705f8ee000 rw-p 00000000 00:00 0 -705f8ee000-705f8ef000 ---p 00000000 00:00 0 [anon:thread stack guard] -705f8ef000-705f8f0000 ---p 00000000 00:00 0 -705f8f0000-705f9f4000 rw-p 00000000 00:00 0 -705f9f4000-705f9f5000 ---p 00000000 00:00 0 [anon:thread stack guard] -705f9f5000-705f9f6000 ---p 00000000 00:00 0 -705f9f6000-705fafa000 rw-p 00000000 00:00 0 -705fafa000-705fafb000 ---p 00000000 00:00 0 [anon:thread stack guard] -705fafb000-705fafc000 ---p 00000000 00:00 0 -705fafc000-705fc00000 rw-p 00000000 00:00 0 -705fc00000-705fe00000 rw-p 00000000 00:00 0 [anon:libc_malloc] -705fe01000-705fe4c000 r--s 00000000 fc:00 97 /system/fonts/Roboto-Light.ttf -705fe4c000-705fe4d000 ---p 00000000 00:00 0 [anon:thread stack guard] -705fe4d000-705fe4e000 ---p 00000000 00:00 0 -705fe4e000-705ff4a000 rw-p 00000000 00:00 0 -705ff4a000-705ff4b000 ---p 00000000 00:05 10270991 [anon:dalvik-Jit thread pool worker thread 0] -705ff4b000-705ff4c000 ---p 00001000 00:05 10270991 [anon:dalvik-Jit thread pool worker thread 0] -705ff4c000-706004b000 rw-p 00002000 00:05 10270991 [anon:dalvik-Jit thread pool worker thread 0] -706004b000-706010f000 r-xp 00000000 fc:00 2390 /system/lib64/libvixl-arm64.so -706010f000-7060120000 ---p 00000000 00:00 0 -7060120000-7060125000 r--p 000cb000 fc:00 2390 /system/lib64/libvixl-arm64.so -7060125000-7060126000 rw-p 000d0000 fc:00 2390 /system/lib64/libvixl-arm64.so -7060126000-706012d000 rw-p 00000000 00:00 0 [anon:.bss] -7060135000-7060151000 r--s 00000000 fc:01 1180 /vendor/overlay/framework-res__auto_generated_rro.apk -7060151000-7060263000 r-xp 00000000 fc:00 2669 /system/lib64/libvixl-arm.so -7060263000-7060275000 ---p 00000000 00:00 0 -7060275000-706027a000 r--p 0011b000 fc:00 2669 /system/lib64/libvixl-arm.so -706027a000-706027b000 rw-p 00120000 fc:00 2669 /system/lib64/libvixl-arm.so -706028b000-706056c000 r-xp 00000000 fc:00 2972 /system/lib64/libart-compiler.so -706056c000-7060580000 ---p 00000000 00:00 0 -7060580000-7060598000 r--p 002e8000 fc:00 2972 /system/lib64/libart-compiler.so -7060598000-7060599000 rw-p 00300000 fc:00 2972 /system/lib64/libart-compiler.so -7060599000-70605a0000 rw-p 00000000 00:00 0 [anon:.bss] -70605b0000-70605d0000 r--s 00000000 00:10 16571 /dev/__properties__/u:object_r:config_prop:s0 -70605d0000-7060619000 r-xp 00000000 fc:00 2702 /system/lib64/libssl.so -7060619000-706062d000 ---p 00000000 00:00 0 -706062d000-7060630000 r--p 0004d000 fc:00 2702 /system/lib64/libssl.so -7060630000-7060631000 rw-p 00050000 fc:00 2702 /system/lib64/libssl.so -7060647000-7060667000 r--s 00000000 00:10 16595 /dev/__properties__/u:object_r:exported3_radio_prop:s0 -7060667000-706069d000 r-xp 00000000 fc:00 2371 /system/lib64/libopenjdk.so -706069d000-70606b2000 ---p 00000000 00:00 0 -70606b2000-70606b4000 r--p 0003e000 fc:00 2371 /system/lib64/libopenjdk.so -70606b4000-70606b6000 rw-p 00040000 fc:00 2371 /system/lib64/libopenjdk.so -70606bb000-70606db000 r--s 00000000 00:10 16608 /dev/__properties__/u:object_r:exported_system_prop:s0 -70606db000-70606e3000 r-xp 00000000 fc:00 2538 /system/lib64/libopenjdkjvm.so -70606e3000-70606fa000 ---p 00000000 00:00 0 -70606fa000-70606fb000 r--p 0000f000 fc:00 2538 /system/lib64/libopenjdkjvm.so -70606fb000-70606fc000 rw-p 00010000 fc:00 2538 /system/lib64/libopenjdkjvm.so -7060701000-7060722000 r--s 00000000 fc:00 227 /system/fonts/NotoSansAnatolianHieroglyphs-Regular.otf -7060722000-7061e18000 r--s 00000000 fc:00 1350 /system/usr/icu/icudt60l.dat -7061e18000-7061e5d000 r-xp 00000000 fc:00 2368 /system/lib64/libjavacore.so -7061e5d000-7061e71000 ---p 00000000 00:00 0 -7061e71000-7061e73000 r--p 0004e000 fc:00 2368 /system/lib64/libjavacore.so -7061e73000-7061e75000 rw-p 00050000 fc:00 2368 /system/lib64/libjavacore.so -7061e75000-7061e76000 rw-p 00000000 00:00 0 [anon:.bss] -7061e77000-7061e96000 r--s 00000000 fc:00 186 /system/fonts/NotoSansYi-Regular.ttf -7061e96000-7061e99000 r-xp 00000000 fc:00 2953 /system/lib64/libwebviewchromium_plat_support.so -7061e99000-7061eb5000 ---p 00000000 00:00 0 -7061eb5000-7061eb6000 r--p 0000f000 fc:00 2953 /system/lib64/libwebviewchromium_plat_support.so -7061eb6000-7061eb7000 rw-p 00010000 fc:00 2953 /system/lib64/libwebviewchromium_plat_support.so -7061ebc000-7061edd000 r--s 00000000 fc:00 100 /system/fonts/NotoSansBamum-Regular.ttf -7061edd000-7061eed000 r-xp 00000000 fc:00 2945 /system/lib64/libRS.so -7061eed000-7061efc000 ---p 00000000 00:00 0 -7061efc000-7061efd000 r--p 0000f000 fc:00 2945 /system/lib64/libRS.so -7061efd000-7061efe000 rw-p 00010000 fc:00 2945 /system/lib64/libRS.so -7061f05000-7061f6b000 r-xp 00000000 fc:00 2423 /system/lib64/android.hardware.renderscript@1.0.so -7061f6b000-7061f7a000 ---p 00000000 00:00 0 -7061f7a000-7061f7f000 r--p 0006b000 fc:00 2423 /system/lib64/android.hardware.renderscript@1.0.so -7061f7f000-7061f80000 rw-p 00070000 fc:00 2423 /system/lib64/android.hardware.renderscript@1.0.so -7061f99000-7061f9b000 r-xp 00000000 fc:00 2614 /system/lib64/libOpenSLES.so -7061f9b000-7061fb8000 ---p 00000000 00:00 0 -7061fb8000-7061fb9000 r--p 0000f000 fc:00 2614 /system/lib64/libOpenSLES.so -7061fb9000-7061fba000 rw-p 00010000 fc:00 2614 /system/lib64/libOpenSLES.so -7061fc6000-7061fc8000 r-xp 00000000 fc:00 2963 /system/lib64/libOpenMAXAL.so -7061fc8000-7061fe5000 ---p 00000000 00:00 0 -7061fe5000-7061fe6000 r--p 0000f000 fc:00 2963 /system/lib64/libOpenMAXAL.so -7061fe6000-7061fe7000 rw-p 00010000 fc:00 2963 /system/lib64/libOpenMAXAL.so -7061fe7000-7062000000 r--s 00000000 fc:00 143 /system/fonts/NotoSansBhaiksuki-Regular.otf -7062000000-7062003000 r-xp 00000000 fc:00 2447 /system/lib64/libtextclassifier_hash.so -7062003000-706201f000 ---p 00000000 00:00 0 -706201f000-7062020000 r--p 0000f000 fc:00 2447 /system/lib64/libtextclassifier_hash.so -7062020000-7062021000 rw-p 00010000 fc:00 2447 /system/lib64/libtextclassifier_hash.so -7062022000-7062042000 rw-p 00000000 00:05 10269731 [anon:dalvik-CompilerMetadata] -7062042000-7062077000 r-xp 00000000 fc:00 2372 /system/lib64/android.hardware.neuralnetworks@1.0.so -7062077000-7062095000 ---p 00000000 00:00 0 -7062095000-706209b000 r--p 0003a000 fc:00 2372 /system/lib64/android.hardware.neuralnetworks@1.0.so -706209b000-706209c000 rw-p 00040000 fc:00 2372 /system/lib64/android.hardware.neuralnetworks@1.0.so -70620a9000-70620c9000 rw-p 00000000 00:05 10269730 [anon:dalvik-CompilerMetadata] -70620c9000-70620e3000 r-xp 00000000 fc:00 2956 /system/lib64/android.hardware.neuralnetworks@1.1.so -70620e3000-70620f4000 ---p 00000000 00:00 0 -70620f4000-70620f7000 r--p 0001d000 fc:00 2956 /system/lib64/android.hardware.neuralnetworks@1.1.so -70620f7000-70620f8000 rw-p 00020000 fc:00 2956 /system/lib64/android.hardware.neuralnetworks@1.1.so -706210b000-70621d0000 r-xp 00000000 fc:00 2387 /system/lib64/libneuralnetworks.so -70621d0000-70621e3000 ---p 00000000 00:00 0 -70621e3000-70621e5000 r--p 000ce000 fc:00 2387 /system/lib64/libneuralnetworks.so -70621e5000-70621e7000 rw-p 000d0000 fc:00 2387 /system/lib64/libneuralnetworks.so -70621e7000-7062372000 rw-p 00000000 00:00 0 [anon:.bss] -7062373000-7062395000 r--s 00000000 fc:00 274 /system/fonts/NotoSerifMyanmar-Bold.otf -7062395000-7062398000 r-xp 00000000 fc:00 2937 /system/lib64/libjnigraphics.so -7062398000-70623b4000 ---p 00000000 00:00 0 -70623b4000-70623b5000 r--p 0000f000 fc:00 2937 /system/lib64/libjnigraphics.so -70623b5000-70623b6000 rw-p 00010000 fc:00 2937 /system/lib64/libjnigraphics.so -70623c8000-70623e0000 r-xp 00000000 fc:00 2662 /system/lib64/libGLESv3.so -70623e0000-70623f7000 ---p 00000000 00:00 0 -70623f7000-70623f8000 r--p 0001f000 fc:00 2662 /system/lib64/libGLESv3.so -70623f8000-70623f9000 rw-p 00020000 fc:00 2662 /system/lib64/libGLESv3.so -70623fc000-706241c000 rw-p 00000000 00:05 10269729 [anon:dalvik-CompilerMetadata] -706241c000-7062444000 r-xp 00000000 fc:00 2603 /system/lib64/libexif.so -7062444000-706245f000 ---p 00000000 00:00 0 -706245f000-7062472000 r--p 0002d000 fc:00 2603 /system/lib64/libexif.so -7062472000-7062473000 rw-p 00040000 fc:00 2603 /system/lib64/libexif.so -7062474000-7062490000 r--s 00000000 fc:00 286 /system/fonts/NotoSansMongolian-Regular.ttf -7062490000-7062491000 r-xp 00000000 fc:00 2357 /system/lib64/libasyncio.so -7062491000-70624af000 ---p 00000000 00:00 0 -70624af000-70624b0000 r--p 0000f000 fc:00 2357 /system/lib64/libasyncio.so -70624b0000-70624b1000 rw-p 00010000 fc:00 2357 /system/lib64/libasyncio.so -70624b5000-70624cf000 r--s 00000000 fc:00 221 /system/fonts/NotoSansMyanmarUI-Bold.ttf -70624cf000-7062508000 r-xp 00000000 fc:00 2401 /system/lib64/libmtp.so -7062508000-7062522000 ---p 00000000 00:00 0 -7062522000-7062525000 r--p 0003d000 fc:00 2401 /system/lib64/libmtp.so -7062525000-706252c000 rw-p 00040000 fc:00 2401 /system/lib64/libmtp.so -7062530000-7062550000 rw-p 00000000 00:05 10269728 [anon:dalvik-CompilerMetadata] -7062550000-7062572000 r--s 00000000 fc:00 234 /system/fonts/NotoSerifMyanmar-Regular.otf -7062572000-706259e000 r-xp 00000000 fc:00 2620 /system/lib64/libmediandk.so -706259e000-70625b9000 ---p 00000000 00:00 0 -70625b9000-70625bc000 r--p 0002d000 fc:00 2620 /system/lib64/libmediandk.so -70625bc000-70625c0000 rw-p 00030000 fc:00 2620 /system/lib64/libmediandk.so -70625c2000-70625d1000 r-xp 00000000 fc:00 2613 /system/lib64/libmidi.so -70625d1000-70625ef000 ---p 00000000 00:00 0 -70625ef000-70625f1000 r--p 0000e000 fc:00 2613 /system/lib64/libmidi.so -70625f1000-70625f2000 rw-p 00010000 fc:00 2613 /system/lib64/libmidi.so -7062600000-7062621000 r-xp 00000000 fc:00 2366 /system/lib64/libmediadrmmetrics_lite.so -7062621000-706263d000 ---p 00000000 00:00 0 -706263d000-706263f000 r--p 0002e000 fc:00 2366 /system/lib64/libmediadrmmetrics_lite.so -706263f000-7062640000 rw-p 00030000 fc:00 2366 /system/lib64/libmediadrmmetrics_lite.so -706264b000-706266b000 rw-p 00000000 00:05 10269727 [anon:dalvik-CompilerMetadata] -706266b000-70626d4000 r-xp 00000000 fc:00 2727 /system/lib64/libmedia_jni.so -70626d4000-70626eb000 ---p 00000000 00:00 0 -70626eb000-70626f2000 r--p 00069000 fc:00 2727 /system/lib64/libmedia_jni.so -70626f2000-70626f3000 rw-p 00070000 fc:00 2727 /system/lib64/libmedia_jni.so -7062703000-7062732000 r-xp 00000000 fc:00 2399 /system/lib64/libcamera2ndk.so -7062732000-7062748000 ---p 00000000 00:00 0 -7062748000-706274b000 r--p 0003d000 fc:00 2399 /system/lib64/libcamera2ndk.so -706274b000-7062750000 rw-p 00040000 fc:00 2399 /system/lib64/libcamera2ndk.so -7062768000-7062788000 rw-p 00000000 00:05 10269726 [anon:dalvik-CompilerMetadata] -7062788000-70627ee000 r-xp 00000000 fc:00 2974 /system/lib64/android.hardware.drm@1.0.so -70627ee000-7062805000 ---p 00000000 00:00 0 -7062805000-706280d000 r--p 00068000 fc:00 2974 /system/lib64/android.hardware.drm@1.0.so -706280d000-706280e000 rw-p 00070000 fc:00 2974 /system/lib64/android.hardware.drm@1.0.so -706281a000-706281b000 ---p 00000000 00:00 0 [anon:thread signal stack guard] -706281b000-706281f000 rw-p 00000000 00:00 0 [anon:thread signal stack] -706281f000-7062843000 r--s 00000000 fc:00 142 /system/fonts/NotoSansKhmer-VF.ttf -7062843000-7062886000 r-xp 00000000 fc:00 2637 /system/lib64/android.hardware.drm@1.1.so -7062886000-70628a5000 ---p 00000000 00:00 0 -70628a5000-70628ab000 r--p 0004a000 fc:00 2637 /system/lib64/android.hardware.drm@1.1.so -70628ab000-70628ac000 rw-p 00050000 fc:00 2637 /system/lib64/android.hardware.drm@1.1.so -70628b0000-70628b1000 ---p 00000000 00:00 0 [anon:thread signal stack guard] -70628b1000-70628b5000 rw-p 00000000 00:00 0 [anon:thread signal stack] -70628b5000-70628db000 r--s 00000000 fc:00 137 /system/fonts/NotoSansSinhala-Bold.ttf -70628db000-7062907000 r-xp 00000000 fc:00 2478 /system/lib64/libmediadrm.so -7062907000-7062918000 ---p 00000000 00:00 0 -7062918000-7062920000 r--p 00038000 fc:00 2478 /system/lib64/libmediadrm.so -7062920000-7062921000 rw-p 00040000 fc:00 2478 /system/lib64/libmediadrm.so -7062922000-7062929000 rw-p 00000000 fc:00 583 /system/etc/event-log-tags -7062929000-7062951000 r--s 00000000 fc:00 296 /system/fonts/NotoSansSinhala-Regular.ttf -7062951000-7062997000 r-xp 00000000 fc:00 2448 /system/lib64/libaaudio.so -7062997000-70629ac000 ---p 00000000 00:00 0 -70629ac000-70629b2000 r--p 0004a000 fc:00 2448 /system/lib64/libaaudio.so -70629b2000-70629ba000 rw-p 00050000 fc:00 2448 /system/lib64/libaaudio.so -70629ba000-70629bb000 ---p 00000000 00:00 0 [anon:thread signal stack guard] -70629bb000-70629bf000 rw-p 00000000 00:00 0 [anon:thread signal stack] -70629bf000-70629c0000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70629c0000-70629c3000 rw-p 00000000 00:00 0 [anon:bionic TLS] -70629c3000-70629c4000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70629c4000-70629c5000 ---p 00000000 00:00 0 [anon:thread signal stack guard] -70629c5000-70629c9000 rw-p 00000000 00:00 0 [anon:thread signal stack] -70629c9000-70629e3000 r-xp 00000000 fc:00 2940 /system/lib64/libandroid.so -70629e3000-70629f3000 ---p 00000000 00:00 0 -70629f3000-70629f6000 r--p 0001d000 fc:00 2940 /system/lib64/libandroid.so -70629f6000-70629f7000 rw-p 00020000 fc:00 2940 /system/lib64/libandroid.so -70629f8000-70629f9000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70629f9000-70629fc000 rw-p 00000000 00:00 0 [anon:bionic TLS] -70629fc000-70629fd000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70629fd000-7062a3e000 r--s 00000000 fc:00 216 /system/fonts/NotoSerif-BoldItalic.ttf -7062a3e000-7062b06000 rw-p 00000000 00:05 10270984 [anon:dalvik-indirect ref table] -7062b06000-7062bce000 rw-p 00000000 00:05 10270983 [anon:dalvik-indirect ref table] -7062bce000-7062dce000 rw-p 00000000 00:05 10270726 [anon:dalvik-rb copying gc mark stack] -7062dce000-70635ce000 rw-p 00000000 00:05 10270725 [anon:dalvik-concurrent copying gc mark stack] -70635ce000-7063dcf000 rw-p 00000000 00:05 10270724 [anon:dalvik-live stack] -7063dcf000-70645d0000 rw-p 00000000 00:05 10270723 [anon:dalvik-allocation stack] -70645d0000-70649d1000 rw-p 00000000 00:05 10270721 [anon:dalvik-card table] -70649d1000-7064ad1000 rw-p 00000000 00:05 10267648 [anon:dalvik-large object free list space allocation info map] -7064ad1000-7065ad1000 rw-p 00000000 00:05 10267644 [anon:dalvik-region space live bitmap] -7065ad1000-7065bd1000 rw-p 00000000 00:05 10267642 [anon:dalvik-allocspace zygote / non moving space mark-bitmap 0] -7065bd1000-7065cd1000 rw-p 00000000 00:05 10267641 [anon:dalvik-allocspace zygote / non moving space live-bitmap 0] -7065cd1000-7065cd2000 r-xp 00000000 fc:00 2946 /system/lib64/libsigchain.so -7065cd2000-7065cf0000 ---p 00000000 00:00 0 -7065cf0000-7065cf1000 r--p 0000f000 fc:00 2946 /system/lib64/libsigchain.so -7065cf1000-7065cf2000 rw-p 00010000 fc:00 2946 /system/lib64/libsigchain.so -7065cf4000-7065d0f000 r--s 00000000 fc:00 190 /system/fonts/NotoSansMyanmar-Bold.ttf -7065d0f000-7065d22000 r-xp 00000000 fc:00 2405 /system/lib64/liblz4.so -7065d22000-7065d3e000 ---p 00000000 00:00 0 -7065d3e000-7065d3f000 r--p 0001f000 fc:00 2405 /system/lib64/liblz4.so -7065d3f000-7065d40000 rw-p 00020000 fc:00 2405 /system/lib64/liblz4.so -7065d40000-7065d5a000 r--s 00000000 fc:00 222 /system/fonts/NotoSansMyanmarUI-Regular.ttf -7065d5a000-7065d5e000 r-xp 00000000 fc:00 2609 /system/lib64/libtombstoned_client.so -7065d5e000-7065d79000 ---p 00000000 00:00 0 -7065d79000-7065d7a000 r--p 0000f000 fc:00 2609 /system/lib64/libtombstoned_client.so -7065d7a000-7065d7b000 rw-p 00010000 fc:00 2609 /system/lib64/libtombstoned_client.so -7065d7f000-7065d80000 ---p 00000000 00:00 0 [anon:thread signal stack guard] -7065d80000-7065d84000 rw-p 00000000 00:00 0 [anon:thread signal stack] -7065d84000-706636e000 r-xp 00000000 fc:00 2671 /system/lib64/libart.so -706636e000-706638d000 ---p 00000000 00:00 0 -706638d000-706639e000 r--p 005ef000 fc:00 2671 /system/lib64/libart.so -706639e000-70663a1000 rw-p 00600000 fc:00 2671 /system/lib64/libart.so -70663a1000-70663a4000 rw-p 00000000 00:00 0 [anon:.bss] -70663a6000-70663c6000 rw-p 00000000 00:05 10269725 [anon:dalvik-CompilerMetadata] -70663c6000-70663c8000 r-xp 00000000 fc:00 2673 /system/lib64/libmetricslogger.so -70663c8000-70663e5000 ---p 00000000 00:00 0 -70663e5000-70663e6000 r--p 0000f000 fc:00 2673 /system/lib64/libmetricslogger.so -70663e6000-70663e7000 rw-p 00010000 fc:00 2673 /system/lib64/libmetricslogger.so -70663e7000-7066400000 r--s 00000000 fc:00 110 /system/fonts/NotoSansLepcha-Regular.ttf -7066400000-7066800000 rw-p 00000000 00:00 0 [anon:libc_malloc] -7066803000-706681e000 r--s 00000000 fc:00 297 /system/fonts/NotoSansMyanmar-Regular.ttf -706681e000-7066821000 r--p 00000000 00:00 0 [anon:cfi shadow] -7066821000-7066822000 r--p 00000000 00:00 0 [anon:cfi shadow] -7066822000-7066b1d000 r--p 00000000 00:00 0 [anon:cfi shadow] -7066b1d000-7066b1e000 r--p 00000000 00:00 0 [anon:cfi shadow] -7066b1e000-7066ba0000 r--p 00000000 00:00 0 [anon:cfi shadow] -7066ba0000-7066ba1000 r--p 00000000 00:00 0 [anon:cfi shadow] -7066ba1000-7066ba2000 r--p 00000000 00:00 0 [anon:cfi shadow] -7066ba2000-7066ba5000 r--p 00000000 00:00 0 [anon:cfi shadow] -7066ba5000-7066ba6000 r--p 00000000 00:00 0 [anon:cfi shadow] -7066ba6000-70e681e000 r--p 00000000 00:00 0 [anon:cfi shadow] -70e681e000-70e6854000 r-xp 00000000 fc:00 2431 /system/lib64/libstagefright_foundation.so -70e6854000-70e6865000 ---p 00000000 00:00 0 -70e6865000-70e6867000 r--p 0003e000 fc:00 2431 /system/lib64/libstagefright_foundation.so -70e6867000-70e686c000 rw-p 00040000 fc:00 2431 /system/lib64/libstagefright_foundation.so -70e686d000-70e686e000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70e686e000-70e6871000 rw-p 00000000 00:00 0 [anon:bionic TLS] -70e6871000-70e6873000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70e6873000-70e6876000 rw-p 00000000 00:00 0 [anon:bionic TLS] -70e6876000-70e6877000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70e6877000-70e688c000 r--s 00000000 fc:00 301 /system/fonts/NotoSansSinhalaUI-Bold.otf -70e688c000-70e688e000 r-xp 00000000 fc:00 2943 /system/lib64/libion.so -70e688e000-70e68ab000 ---p 00000000 00:00 0 -70e68ab000-70e68ac000 r--p 0000f000 fc:00 2943 /system/lib64/libion.so -70e68ac000-70e68ad000 rw-p 00010000 fc:00 2943 /system/lib64/libion.so -70e68ad000-70e68af000 rw-p 00000000 00:05 10282496 [anon:dalvik-indirect ref table] -70e68af000-70e68b1000 rw-p 00000000 00:05 10282493 [anon:dalvik-indirect ref table] -70e68b1000-70e68ee000 r--s 00000000 fc:00 256 /system/fonts/NotoSerif-Italic.ttf -70e68ee000-70e6910000 r-xp 00000000 fc:00 2502 /system/lib64/libhidlbase.so -70e6910000-70e692c000 ---p 00000000 00:00 0 -70e692c000-70e692e000 r--p 0002e000 fc:00 2502 /system/lib64/libhidlbase.so -70e692e000-70e692f000 rw-p 00030000 fc:00 2502 /system/lib64/libhidlbase.so -70e6930000-70e693f000 r--s 00000000 fc:00 1082 /system/usr/hyphen-data/hyph-en-us.hyb -70e693f000-70e6954000 r--s 00000000 fc:00 138 /system/fonts/NotoSansSinhalaUI-Regular.otf -70e6954000-70e6978000 r-xp 00000000 fc:00 2482 /system/lib64/libui.so -70e6978000-70e6992000 ---p 00000000 00:00 0 -70e6992000-70e6994000 r--p 0002e000 fc:00 2482 /system/lib64/libui.so -70e6994000-70e6995000 rw-p 00030000 fc:00 2482 /system/lib64/libui.so -70e6996000-70e69a2000 r--s 00000000 fc:00 1117 /system/usr/hyphen-data/hyph-en-gb.hyb -70e69a2000-70e69b7000 r--s 00000000 fc:00 202 /system/fonts/NotoSerifSinhala-Bold.otf -70e69b7000-70e69cb000 r--s 00000000 fc:00 124 /system/fonts/NotoSansOriyaUI-Bold.ttf -70e69cb000-70e69e1000 r-xp 00000000 fc:00 2537 /system/lib64/liblog.so -70e69e1000-70e69fa000 ---p 00000000 00:00 0 -70e69fa000-70e69fb000 r--p 0001f000 fc:00 2537 /system/lib64/liblog.so -70e69fb000-70e69fc000 rw-p 00020000 fc:00 2537 /system/lib64/liblog.so -70e69fc000-70e69fe000 rw-p 00000000 00:05 10266158 [anon:dalvik-indirect ref table] -70e69fe000-70e69ff000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70e69ff000-70e6a02000 rw-p 00000000 00:00 0 [anon:bionic TLS] -70e6a02000-70e6a03000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70e6a03000-70e6a05000 r-xp 00000000 fc:00 2489 /system/lib64/android.hidl.token@1.0-utils.so -70e6a05000-70e6a22000 ---p 00000000 00:00 0 -70e6a22000-70e6a23000 r--p 0000f000 fc:00 2489 /system/lib64/android.hidl.token@1.0-utils.so -70e6a23000-70e6a24000 rw-p 00010000 fc:00 2489 /system/lib64/android.hidl.token@1.0-utils.so -70e6a25000-70e6a2e000 r--s 00000000 fc:00 1120 /system/usr/hyphen-data/hyph-ga.hyb -70e6a2e000-70e6a42000 r--s 00000000 fc:00 109 /system/fonts/NotoSansOriyaUI-Regular.ttf -70e6a42000-70e6a59000 r-xp 00000000 fc:00 2446 /system/lib64/android.hardware.graphics.mapper@2.0.so -70e6a59000-70e6a6e000 ---p 00000000 00:00 0 -70e6a6e000-70e6a70000 r--p 0001e000 fc:00 2446 /system/lib64/android.hardware.graphics.mapper@2.0.so -70e6a70000-70e6a71000 rw-p 00020000 fc:00 2446 /system/lib64/android.hardware.graphics.mapper@2.0.so -70e6a72000-70e6a78000 r--s 00000000 fc:00 1084 /system/usr/hyphen-data/hyph-et.hyb -70e6a78000-70e6a9d000 r--s 00000000 fc:00 207 /system/fonts/NotoSerifTelugu-Bold.ttf -70e6a9d000-70e6a9f000 r-xp 00000000 fc:00 2330 /system/lib64/android.hardware.configstore-utils.so -70e6a9f000-70e6abc000 ---p 00000000 00:00 0 -70e6abc000-70e6abd000 r--p 0000f000 fc:00 2330 /system/lib64/android.hardware.configstore-utils.so -70e6abd000-70e6abe000 rw-p 00010000 fc:00 2330 /system/lib64/android.hardware.configstore-utils.so -70e6abe000-70e6ac0000 r--s f8042000 00:10 20630 /dev/kgsl-3d0 -70e6ac0000-70e6adc000 r--s 00000000 fc:00 172 /system/fonts/NotoSansTeluguUI-Bold.ttf -70e6adc000-70e6ae0000 r-xp 00000000 fc:00 2555 /system/lib64/libstagefright_omx_utils.so -70e6ae0000-70e6afb000 ---p 00000000 00:00 0 -70e6afb000-70e6afc000 r--p 0000f000 fc:00 2555 /system/lib64/libstagefright_omx_utils.so -70e6afc000-70e6afd000 rw-p 00010000 fc:00 2555 /system/lib64/libstagefright_omx_utils.so -70e6afd000-70e6afe000 ---p 00000000 00:00 0 [anon:thread signal stack guard] -70e6afe000-70e6b02000 rw-p 00000000 00:00 0 [anon:thread signal stack] -70e6b02000-70e6b27000 r--s 00000000 fc:00 271 /system/fonts/NotoSerifTelugu-Regular.ttf -70e6b27000-70e6b61000 r-xp 00000000 fc:00 2695 /system/lib64/libdexfile.so -70e6b61000-70e6b73000 ---p 00000000 00:00 0 -70e6b73000-70e6b75000 r--p 0003e000 fc:00 2695 /system/lib64/libdexfile.so -70e6b75000-70e6b76000 rw-p 00040000 fc:00 2695 /system/lib64/libdexfile.so -70e6b76000-70e6b78000 rw-p 00000000 00:05 10253452 [anon:dalvik-indirect ref table] -70e6b78000-70e6b85000 r--s 00000000 fc:00 1080 /system/usr/hyphen-data/hyph-cu.hyb -70e6b85000-70e6b96000 r-xp 00000000 fc:00 2957 /system/lib64/libaudioutils.so -70e6b96000-70e6bb4000 ---p 00000000 00:00 0 -70e6bb4000-70e6bb5000 r--p 0001f000 fc:00 2957 /system/lib64/libaudioutils.so -70e6bb5000-70e6bb6000 rw-p 00020000 fc:00 2957 /system/lib64/libaudioutils.so -70e6bb6000-70e6bb7000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70e6bb7000-70e6bba000 rw-p 00000000 00:00 0 [anon:bionic TLS] -70e6bba000-70e6bbb000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70e6bbb000-70e6bd7000 r--s 00000000 fc:00 132 /system/fonts/NotoSansTeluguUI-Regular.ttf -70e6bd7000-70e6bdc000 r-xp 00000000 fc:00 2409 /system/lib64/libprocessgroup.so -70e6bdc000-70e6bf6000 ---p 00000000 00:00 0 -70e6bf6000-70e6bf7000 r--p 0000f000 fc:00 2409 /system/lib64/libprocessgroup.so -70e6bf7000-70e6bf8000 rw-p 00010000 fc:00 2409 /system/lib64/libprocessgroup.so -70e6bf8000-70e6c09000 r--s 00000000 fc:00 79 /system/fonts/NotoSansNewa-Regular.otf -70e6c09000-70e6c1c000 r-xp 00000000 fc:00 2329 /system/lib64/android.hidl.memory.token@1.0.so -70e6c1c000-70e6c36000 ---p 00000000 00:00 0 -70e6c36000-70e6c38000 r--p 0001e000 fc:00 2329 /system/lib64/android.hidl.memory.token@1.0.so -70e6c38000-70e6c39000 rw-p 00020000 fc:00 2329 /system/lib64/android.hidl.memory.token@1.0.so -70e6c3a000-70e6c4f000 r--s 00000000 fc:00 253 /system/fonts/NotoSansOriya-Bold.ttf -70e6c4f000-70e6c6b000 r-xp 00000000 fc:00 2407 /system/lib64/libutils.so -70e6c6b000-70e6c7e000 ---p 00000000 00:00 0 -70e6c7e000-70e6c7f000 r--p 0001f000 fc:00 2407 /system/lib64/libutils.so -70e6c7f000-70e6c80000 rw-p 00020000 fc:00 2407 /system/lib64/libutils.so -70e6c80000-70e6c9d000 r-xp 00000000 fc:00 2934 /system/lib64/libtinyxml2.so -70e6c9d000-70e6cba000 ---p 00000000 00:00 0 -70e6cba000-70e6cbc000 r--p 0001e000 fc:00 2934 /system/lib64/libtinyxml2.so -70e6cbc000-70e6cbf000 rw-p 00020000 fc:00 2934 /system/lib64/libtinyxml2.so -70e6cbf000-70e6ccf000 r--s 00000000 fc:00 80 /system/fonts/NotoSansMarchen-Regular.otf -70e6ccf000-70e6ce0000 r-xp 00000000 fc:00 2655 /system/lib64/libbase.so -70e6ce0000-70e6cfe000 ---p 00000000 00:00 0 -70e6cfe000-70e6cff000 r--p 0001f000 fc:00 2655 /system/lib64/libbase.so -70e6cff000-70e6d00000 rw-p 00020000 fc:00 2655 /system/lib64/libbase.so -70e6d00000-70e6d09000 r--s 00000000 fc:00 1113 /system/usr/hyphen-data/hyph-cy.hyb -70e6d09000-70e6d50000 r-xp 00000000 fc:00 2495 /system/lib64/libRScpp.so -70e6d50000-70e6d68000 ---p 00000000 00:00 0 -70e6d68000-70e6d69000 r--p 0004f000 fc:00 2495 /system/lib64/libRScpp.so -70e6d69000-70e6d6a000 rw-p 00050000 fc:00 2495 /system/lib64/libRScpp.so -70e6d6b000-70e6d6d000 r--s 00088000 103:1d 1736830 /data/app/com.google.sample.tunnel-HGGRU03Gu1Mwkf_-RnFmvw==/base.apk -70e6d6d000-70e6d7d000 r--s 00000000 fc:00 238 /system/fonts/NotoSansVai-Regular.ttf -70e6d7d000-70e6d98000 r--s 00000000 fc:00 276 /system/fonts/NotoSansTelugu-Bold.ttf -70e6d98000-70e6f2b000 r-xp 00000000 fc:00 2961 /system/lib64/libicuuc.so -70e6f2b000-70e6f47000 ---p 00000000 00:00 0 -70e6f47000-70e6f5c000 r--p 0019b000 fc:00 2961 /system/lib64/libicuuc.so -70e6f5c000-70e6f5d000 rw-p 001b0000 fc:00 2961 /system/lib64/libicuuc.so -70e6f5d000-70e6f5e000 rw-p 00000000 00:00 0 [anon:.bss] -70e6f5f000-70e6f68000 r--s 00000000 fc:00 159 /system/fonts/NotoSansLinearA-Regular.otf -70e6f68000-70e6f84000 r--s 00000000 fc:00 170 /system/fonts/NotoSansTelugu-Regular.ttf -70e6f84000-70e7058000 r-xp 00000000 fc:00 2356 /system/lib64/libc.so -70e7058000-70e706e000 ---p 00000000 00:00 0 -70e706e000-70e7074000 r--p 000da000 fc:00 2356 /system/lib64/libc.so -70e7074000-70e7076000 rw-p 000e0000 fc:00 2356 /system/lib64/libc.so -70e7076000-70e7077000 rw-p 00000000 00:00 0 [anon:.bss] -70e7077000-70e7078000 r--p 00000000 00:00 0 [anon:.bss] -70e7078000-70e7080000 rw-p 00000000 00:00 0 [anon:.bss] -70e7080000-70e7087000 r--s 00000000 fc:00 102 /system/fonts/NotoSansSharada-Regular.otf -70e7087000-70e708e000 r-xp 00000000 fc:00 2378 /system/lib64/libheif.so -70e708e000-70e70a4000 ---p 00000000 00:00 0 -70e70a4000-70e70a6000 r--p 0000e000 fc:00 2378 /system/lib64/libheif.so -70e70a6000-70e70a7000 rw-p 00010000 fc:00 2378 /system/lib64/libheif.so -70e70a7000-70e70a9000 r--s 00000000 fc:00 1116 /system/usr/hyphen-data/hyph-sl.hyb -70e70a9000-70e70ab000 r--s 00000000 fc:00 1147 /system/usr/hyphen-data/hyph-mn-cyrl.hyb -70e70ab000-70e70c5000 r--s 00000000 fc:00 291 /system/fonts/NotoSansBengaliUI-Bold.ttf -70e70c5000-70e70ea000 r-xp 00000000 fc:00 2545 /system/lib64/libEGL.so -70e70ea000-70e7109000 ---p 00000000 00:00 0 -70e7109000-70e710d000 r--p 0002c000 fc:00 2545 /system/lib64/libEGL.so -70e710d000-70e710e000 rw-p 00030000 fc:00 2545 /system/lib64/libEGL.so -70e710e000-70e7115000 rw-p 00000000 00:00 0 [anon:.bss] -70e7115000-70e7119000 r--s 00000000 fc:00 1143 /system/usr/hyphen-data/hyph-es.hyb -70e7119000-70e712e000 r--s 00000000 fc:00 71 /system/fonts/NotoSansOriya-Regular.ttf -70e712e000-70e717a000 r--s 00000000 fc:00 272 /system/fonts/Roboto-Thin.ttf -70e717a000-70e71db000 r-xp 00000000 fc:00 2393 /system/lib64/libpdx_default_transport.so -70e71db000-70e71f7000 ---p 00000000 00:00 0 -70e71f7000-70e71f9000 r--p 0006e000 fc:00 2393 /system/lib64/libpdx_default_transport.so -70e71f9000-70e71fa000 rw-p 00070000 fc:00 2393 /system/lib64/libpdx_default_transport.so -70e71fa000-70e71fb000 rw-p 00000000 00:00 0 [anon:.bss] -70e71fc000-70e71fe000 r--s 00000000 fc:00 1107 /system/usr/hyphen-data/hyph-fr.hyb -70e71fe000-70e7200000 r--s 00000000 fc:00 1097 /system/usr/hyphen-data/hyph-da.hyb -70e7200000-70e7223000 r-xp 00000000 fc:00 2380 /system/lib64/libminikin.so -70e7223000-70e723e000 ---p 00000000 00:00 0 -70e723e000-70e723f000 r--p 0002f000 fc:00 2380 /system/lib64/libminikin.so -70e723f000-70e7240000 rw-p 00030000 fc:00 2380 /system/lib64/libminikin.so -70e7241000-70e724d000 r--s 00000000 fc:00 179 /system/fonts/NotoSansTaiTham-Regular.ttf -70e724d000-70e725c000 r-xp 00000000 fc:00 2527 /system/lib64/libmediautils.so -70e725c000-70e7279000 ---p 00000000 00:00 0 -70e7279000-70e727b000 r--p 0001e000 fc:00 2527 /system/lib64/libmediautils.so -70e727b000-70e727c000 rw-p 00020000 fc:00 2527 /system/lib64/libmediautils.so -70e727d000-70e7283000 r--s 00000000 fc:00 136 /system/fonts/NotoSansMiao-Regular.otf -70e7283000-70e74d2000 r-xp 00000000 fc:00 2349 /system/lib64/libicui18n.so -70e74d2000-70e74e6000 ---p 00000000 00:00 0 -70e74e6000-70e74fa000 r--p 0025c000 fc:00 2349 /system/lib64/libicui18n.so -70e74fa000-70e74fb000 rw-p 00270000 fc:00 2349 /system/lib64/libicui18n.so -70e74fc000-70e74ff000 r--s 00000000 103:1d 1474562 /data/resource-cache/vendor@overlay@framework-res__auto_generated_rro.apk@idmap -70e74ff000-70e750c000 r--s 00000000 fc:00 126 /system/fonts/NotoSansSyriacWestern-Regular.ttf -70e750c000-70e751b000 r-xp 00000000 fc:00 2466 /system/lib64/libmediaextractor.so -70e751b000-70e753a000 ---p 00000000 00:00 0 -70e753a000-70e753b000 r--p 0000f000 fc:00 2466 /system/lib64/libmediaextractor.so -70e753b000-70e753c000 rw-p 00010000 fc:00 2466 /system/lib64/libmediaextractor.so -70e753d000-70e7540000 r--s 00000000 fc:00 107 /system/fonts/NotoSansPauCinHau-Regular.otf -70e7540000-70e7593000 r-xp 00000000 fc:00 2363 /system/lib64/libandroidfw.so -70e7593000-70e75ac000 ---p 00000000 00:00 0 -70e75ac000-70e75af000 r--p 0005d000 fc:00 2363 /system/lib64/libandroidfw.so -70e75af000-70e75b0000 rw-p 00060000 fc:00 2363 /system/lib64/libandroidfw.so -70e75b0000-70e75b2000 r--s 00000000 fc:00 1083 /system/usr/hyphen-data/hyph-be.hyb -70e75b2000-70e75cd000 r--s 00000000 fc:00 270 /system/fonts/NotoSansBengaliUI-Regular.ttf -70e75cd000-70e75cf000 r-xp 00000000 fc:00 2701 /system/lib64/libmemtrack.so -70e75cf000-70e75ec000 ---p 00000000 00:00 0 -70e75ec000-70e75ed000 r--p 0000f000 fc:00 2701 /system/lib64/libmemtrack.so -70e75ed000-70e75ee000 rw-p 00010000 fc:00 2701 /system/lib64/libmemtrack.so -70e75ee000-70e75f0000 r--s 00000000 fc:00 209 /system/fonts/NotoSansSoraSompeng-Regular.otf -70e75f0000-70e760d000 r--s 00000000 fc:00 243 /system/fonts/NotoSerifBengali-Bold.ttf -70e760d000-70e7613000 r-xp 00000000 fc:00 2667 /system/lib64/libutilscallstack.so -70e7613000-70e762c000 ---p 00000000 00:00 0 -70e762c000-70e762d000 r--p 0000f000 fc:00 2667 /system/lib64/libutilscallstack.so -70e762d000-70e762e000 rw-p 00010000 fc:00 2667 /system/lib64/libutilscallstack.so -70e762e000-70e7632000 r--s 00000000 fc:00 99 /system/fonts/NotoSansPahawhHmong-Regular.otf -70e7632000-70e764f000 r--s 00000000 fc:00 205 /system/fonts/NotoSerifBengali-Regular.ttf -70e764f000-70e7661000 r-xp 00000000 fc:00 2710 /system/lib64/libcutils.so -70e7661000-70e767d000 ---p 00000000 00:00 0 -70e767d000-70e767f000 r--p 0001e000 fc:00 2710 /system/lib64/libcutils.so -70e767f000-70e7680000 rw-p 00020000 fc:00 2710 /system/lib64/libcutils.so -70e7680000-70e7683000 r--s 00000000 fc:00 257 /system/fonts/NotoSansPalmyrene-Regular.otf -70e7683000-70e7697000 r--s 00000000 fc:00 78 /system/fonts/NotoSansKannadaUI-Bold.ttf -70e7697000-70e769a000 r-xp 00000000 fc:00 2362 /system/lib64/libstagefright_http_support.so -70e769a000-70e76b6000 ---p 00000000 00:00 0 -70e76b6000-70e76b7000 r--p 0000f000 fc:00 2362 /system/lib64/libstagefright_http_support.so -70e76b7000-70e76b8000 rw-p 00010000 fc:00 2362 /system/lib64/libstagefright_http_support.so -70e76b8000-70e76b9000 rw-p 00000000 00:00 0 [anon:linker_alloc_lob] -70e76b9000-70e76be000 r--s 00000000 fc:00 165 /system/fonts/NotoSansMeroitic-Regular.otf -70e76be000-70e76cb000 r--s 00000000 fc:00 112 /system/fonts/NotoSansSyriacEastern-Regular.ttf -70e76cb000-70e76de000 r-xp 00000000 fc:00 2343 /system/lib64/libsensor.so -70e76de000-70e76f5000 ---p 00000000 00:00 0 -70e76f5000-70e76f8000 r--p 0001d000 fc:00 2343 /system/lib64/libsensor.so -70e76f8000-70e76f9000 rw-p 00020000 fc:00 2343 /system/lib64/libsensor.so -70e76f9000-70e76fc000 r--s 00000000 fc:00 157 /system/fonts/NotoSansOldPermic-Regular.otf -70e76fc000-70e7708000 r--s 00000000 fc:00 189 /system/fonts/NotoSansSyriacEstrangela-Regular.ttf -70e7708000-70e771d000 r-xp 00000000 fc:00 2339 /system/lib64/android.hidl.token@1.0.so -70e771d000-70e7735000 ---p 00000000 00:00 0 -70e7735000-70e7737000 r--p 0001e000 fc:00 2339 /system/lib64/android.hidl.token@1.0.so -70e7737000-70e7738000 rw-p 00020000 fc:00 2339 /system/lib64/android.hidl.token@1.0.so -70e7738000-70e7739000 r--p 00000000 00:00 0 [anon:linker_alloc] -70e7739000-70e773b000 r--s 00000000 fc:00 267 /system/fonts/NotoSansOldNorthArabian-Regular.otf -70e773b000-70e7740000 r--s 00000000 fc:00 208 /system/fonts/NotoSansManichaean-Regular.otf -70e7740000-70e775c000 r--s 00000000 fc:00 118 /system/fonts/NotoSansGujaratiUI-Bold.ttf -70e775c000-70e7767000 r-xp 00000000 fc:00 2525 /system/lib64/libappfuse.so -70e7767000-70e777b000 ---p 00000000 00:00 0 -70e777b000-70e777c000 r--p 0000f000 fc:00 2525 /system/lib64/libappfuse.so -70e777c000-70e777d000 rw-p 00010000 fc:00 2525 /system/lib64/libappfuse.so -70e777e000-70e7795000 r--s 00000000 fc:00 250 /system/fonts/NotoSerifKannada-Bold.ttf -70e7795000-70e7798000 r-xp 00000000 fc:00 2413 /system/lib64/libpackagelistparser.so -70e7798000-70e77b4000 ---p 00000000 00:00 0 -70e77b4000-70e77b5000 r--p 0000f000 fc:00 2413 /system/lib64/libpackagelistparser.so -70e77b5000-70e77b6000 rw-p 00010000 fc:00 2413 /system/lib64/libpackagelistparser.so -70e77b6000-70e77b8000 r--s 00000000 fc:00 147 /system/fonts/NotoSansNabataean-Regular.otf -70e77b8000-70e77ba000 r--s 00000000 fc:00 146 /system/fonts/NotoSansMultani-Regular.otf -70e77ba000-70e77c1000 r--s 00000000 fc:00 214 /system/fonts/NotoSansPhagsPa-Regular.ttf -70e77c1000-70e77de000 r--s 00000000 fc:00 90 /system/fonts/NotoSansGujaratiUI-Regular.ttf -70e77de000-70e77e0000 r-xp 00000000 fc:00 2430 /system/lib64/libdl.so -70e77e0000-70e77fd000 ---p 00000000 00:00 0 -70e77fd000-70e77fe000 r--p 0000f000 fc:00 2430 /system/lib64/libdl.so -70e77fe000-70e77ff000 r--p 00000000 00:00 0 [anon:.bss] -70e7800000-70e7809000 r--s 00000000 fc:00 258 /system/fonts/NotoSansSymbols-Regular-Subsetted2.ttf -70e7809000-70e7857000 r-xp 00000000 fc:00 2560 /system/lib64/libjpeg.so -70e7857000-70e7868000 ---p 00000000 00:00 0 -70e7868000-70e7869000 r--p 0004f000 fc:00 2560 /system/lib64/libjpeg.so -70e7869000-70e786a000 rw-p 00050000 fc:00 2560 /system/lib64/libjpeg.so -70e786a000-70e7887000 r--s 00000000 fc:00 237 /system/fonts/NotoSansGujarati-Bold.ttf -70e7887000-70e788a000 r-xp 00000000 fc:00 2608 /system/lib64/libnetd_client.so -70e788a000-70e78a6000 ---p 00000000 00:00 0 -70e78a6000-70e78a7000 r--p 0000f000 fc:00 2608 /system/lib64/libnetd_client.so -70e78a7000-70e78a8000 rw-p 00010000 fc:00 2608 /system/lib64/libnetd_client.so -70e78a8000-70e78aa000 r--s 00000000 fc:00 290 /system/fonts/NotoSansMro-Regular.otf -70e78aa000-70e78b9000 r--s 00000000 fc:00 84 /system/fonts/NotoSansLinearB-Regular.ttf -70e78b9000-70e78d7000 r--s 00000000 fc:00 287 /system/fonts/NotoSansGujarati-Regular.ttf -70e78d7000-70e78d8000 r-xp 00000000 fc:00 2651 /system/lib64/libvndksupport.so -70e78d8000-70e78f6000 ---p 00000000 00:00 0 -70e78f6000-70e78f7000 r--p 0000f000 fc:00 2651 /system/lib64/libvndksupport.so -70e78f7000-70e78f8000 rw-p 00010000 fc:00 2651 /system/lib64/libvndksupport.so -70e78f9000-70e78fc000 r--s 00000000 fc:00 178 /system/fonts/NotoSansTaiLe-Regular.ttf -70e78fc000-70e7900000 r--s 00000000 fc:00 163 /system/fonts/NotoSansTifinagh-Regular.ttf -70e7900000-70e7906000 r-xp 00000000 fc:00 2659 /system/lib64/libnativeloader.so -70e7906000-70e791f000 ---p 00000000 00:00 0 -70e791f000-70e7920000 r--p 0000f000 fc:00 2659 /system/lib64/libnativeloader.so -70e7920000-70e7921000 rw-p 00010000 fc:00 2659 /system/lib64/libnativeloader.so -70e7921000-70e7923000 r--s 00000000 fc:00 268 /system/fonts/NotoSansHatran-Regular.otf -70e7923000-70e7927000 r--s 00000000 fc:00 195 /system/fonts/NotoSansTaiViet-Regular.ttf -70e7927000-70e7945000 r--s 00000000 fc:00 139 /system/fonts/NotoSansDevanagariUI-Bold.ttf -70e7945000-70e79a3000 r-xp 00000000 fc:00 2450 /system/lib64/libharfbuzz_ng.so -70e79a3000-70e79b3000 ---p 00000000 00:00 0 -70e79b3000-70e79b5000 r--p 0005e000 fc:00 2450 /system/lib64/libharfbuzz_ng.so -70e79b5000-70e79b6000 rw-p 00060000 fc:00 2450 /system/lib64/libharfbuzz_ng.so -70e79b6000-70e79c5000 r--s 00000000 fc:00 111 /system/fonts/NotoSansKaithi-Regular.ttf -70e79c5000-70e7a92000 r-xp 00000000 fc:00 2332 /system/lib64/libc++.so -70e7a92000-70e7aae000 ---p 00000000 00:00 0 -70e7aae000-70e7ab8000 r--p 000d6000 fc:00 2332 /system/lib64/libc++.so -70e7ab8000-70e7ab9000 rw-p 000e0000 fc:00 2332 /system/lib64/libc++.so -70e7ab9000-70e7abc000 rw-p 00000000 00:00 0 [anon:.bss] -70e7abc000-70e7abe000 r--s 00000000 fc:00 73 /system/fonts/NotoSansBassaVah-Regular.otf -70e7abe000-70e7ac8000 r--s 00000000 fc:00 254 /system/fonts/NotoSansJavanese-Regular.ttf -70e7ac8000-70e7acb000 r-xp 00000000 fc:00 2660 /system/lib64/libnativebridge.so -70e7acb000-70e7ae7000 ---p 00000000 00:00 0 -70e7ae7000-70e7ae8000 r--p 0000f000 fc:00 2660 /system/lib64/libnativebridge.so -70e7ae8000-70e7ae9000 rw-p 00010000 fc:00 2660 /system/lib64/libnativebridge.so -70e7ae9000-70e7aee000 r--s 00000000 fc:00 158 /system/fonts/NotoSansSaurashtra-Regular.ttf -70e7aee000-70e7b0f000 r--s 00000000 fc:00 82 /system/fonts/NotoSansDevanagari-Bold.ttf -70e7b0f000-70e7b2e000 r-xp 00000000 fc:00 2612 /system/lib64/libpcre2.so -70e7b2e000-70e7b3e000 ---p 00000000 00:00 0 -70e7b3e000-70e7b3f000 r--p 0001f000 fc:00 2612 /system/lib64/libpcre2.so -70e7b3f000-70e7b40000 rw-p 00020000 fc:00 2612 /system/lib64/libpcre2.so -70e7b40000-70e7bcc000 r-xp 00000000 fc:00 2975 /system/lib64/libgui.so -70e7bcc000-70e7be2000 ---p 00000000 00:00 0 -70e7be2000-70e7bf5000 r--p 0008d000 fc:00 2975 /system/lib64/libgui.so -70e7bf5000-70e7bf6000 rw-p 000a0000 fc:00 2975 /system/lib64/libgui.so -70e7bf6000-70e7bf7000 r--p 00000000 00:00 0 [anon:linker_alloc] -70e7bf7000-70e7bf9000 r--s 00000000 fc:00 228 /system/fonts/NotoSansUgaritic-Regular.ttf -70e7bf9000-70e7c08000 r--s 00000000 fc:00 89 /system/fonts/NotoSansCherokee-Regular.ttf -70e7c08000-70e7dea000 r-xp 00000000 fc:00 2441 /system/lib64/libandroid_runtime.so -70e7dea000-70e7e04000 ---p 00000000 00:00 0 -70e7e04000-70e7e23000 r--p 001e1000 fc:00 2441 /system/lib64/libandroid_runtime.so -70e7e23000-70e7e24000 rw-p 00200000 fc:00 2441 /system/lib64/libandroid_runtime.so -70e7e24000-70e7e28000 rw-p 00000000 00:00 0 [anon:.bss] -70e7e29000-70e7e66000 r--s 00000000 fc:00 74 /system/fonts/NotoSerif-Bold.ttf -70e7e66000-70e7ed0000 r-xp 00000000 fc:00 2547 /system/lib64/libclang_rt.ubsan_standalone-aarch64-android.so -70e7ed0000-70e7edf000 ---p 00000000 00:00 0 -70e7edf000-70e7ee1000 r--p 00069000 fc:00 2547 /system/lib64/libclang_rt.ubsan_standalone-aarch64-android.so -70e7ee1000-70e7ee4000 rw-p 0006b000 fc:00 2547 /system/lib64/libclang_rt.ubsan_standalone-aarch64-android.so -70e7ee4000-70e89f6000 rw-p 00000000 00:00 0 [anon:.bss] -70e89f6000-70e89fa000 r--s 00000000 fc:00 127 /system/fonts/NotoSansSylotiNagri-Regular.ttf -70e89fa000-70e8a06000 r--s 00000000 fc:00 93 /system/fonts/NotoSansCanadianAboriginal-Regular.ttf -70e8a06000-70e8a1b000 r-xp 00000000 fc:00 2460 /system/lib64/android.hardware.graphics.allocator@2.0.so -70e8a1b000-70e8a33000 ---p 00000000 00:00 0 -70e8a33000-70e8a35000 r--p 0001e000 fc:00 2460 /system/lib64/android.hardware.graphics.allocator@2.0.so -70e8a35000-70e8a36000 rw-p 00020000 fc:00 2460 /system/lib64/android.hardware.graphics.allocator@2.0.so -70e8a36000-70e8a55000 r--s 00000000 fc:00 145 /system/fonts/NotoSansDevanagariUI-Regular.ttf -70e8a55000-70e8a61000 r-xp 00000000 fc:00 2540 /system/lib64/libstagefright_xmlparser.so -70e8a61000-70e8a74000 ---p 00000000 00:00 0 -70e8a74000-70e8a75000 r--p 0000f000 fc:00 2540 /system/lib64/libstagefright_xmlparser.so -70e8a75000-70e8a76000 rw-p 00010000 fc:00 2540 /system/lib64/libstagefright_xmlparser.so -70e8a76000-70e8a78000 r--s 00000000 fc:00 293 /system/fonts/NotoSansTagbanwa-Regular.ttf -70e8a78000-70e8a8f000 r--s 00000000 fc:00 161 /system/fonts/NotoSerifKannada-Regular.ttf -70e8a8f000-70e8b23000 r-xp 00000000 fc:00 2633 /system/lib64/libaudioclient.so -70e8b23000-70e8b37000 ---p 00000000 00:00 0 -70e8b37000-70e8b49000 r--p 0009e000 fc:00 2633 /system/lib64/libaudioclient.so -70e8b49000-70e8b55000 rw-p 000b0000 fc:00 2633 /system/lib64/libaudioclient.so -70e8b55000-70e8b9f000 r--s 00000000 fc:00 83 /system/fonts/RobotoCondensed-Light.ttf -70e8b9f000-70e8ba1000 r-xp 00000000 fc:00 2520 /system/lib64/libhardware_legacy.so -70e8ba1000-70e8bbe000 ---p 00000000 00:00 0 -70e8bbe000-70e8bbf000 r--p 0000f000 fc:00 2520 /system/lib64/libhardware_legacy.so -70e8bbf000-70e8bc0000 rw-p 00010000 fc:00 2520 /system/lib64/libhardware_legacy.so -70e8bc0000-70e8be0000 r-xp 00000000 fc:00 2410 /system/lib64/android.hidl.memory@1.0.so -70e8be0000-70e8bfa000 ---p 00000000 00:00 0 -70e8bfa000-70e8bfd000 r--p 0002d000 fc:00 2410 /system/lib64/android.hidl.memory@1.0.so -70e8bfd000-70e8bfe000 rw-p 00030000 fc:00 2410 /system/lib64/android.hidl.memory@1.0.so -70e8bfe000-70e8bff000 r--p 00000000 00:00 0 [anon:linker_alloc] -70e8bff000-70e8c02000 r--s 00000000 fc:00 273 /system/fonts/NotoSansSundanese-Regular.ttf -70e8c02000-70e8c0f000 r--s 00000000 fc:00 115 /system/fonts/NotoSansAdlam-Regular.ttf -70e8c0f000-70e8c18000 r-xp 00000000 fc:00 2350 /system/lib64/libnetdutils.so -70e8c18000-70e8c2e000 ---p 00000000 00:00 0 -70e8c2e000-70e8c2f000 r--p 0000f000 fc:00 2350 /system/lib64/libnetdutils.so -70e8c2f000-70e8c30000 rw-p 00010000 fc:00 2350 /system/lib64/libnetdutils.so -70e8c30000-70e8c44000 r--s 00000000 fc:00 283 /system/fonts/NotoSansKannadaUI-Regular.ttf -70e8c44000-70e8c45000 r-xp 00000000 fc:00 2926 /system/lib64/libhidlallocatorutils.so -70e8c45000-70e8c63000 ---p 00000000 00:00 0 -70e8c63000-70e8c64000 r--p 0000f000 fc:00 2926 /system/lib64/libhidlallocatorutils.so -70e8c64000-70e8c65000 rw-p 00010000 fc:00 2926 /system/lib64/libhidlallocatorutils.so -70e8c65000-70e8c67000 r--s 00000000 fc:00 65 /system/fonts/NotoSansTagalog-Regular.ttf -70e8c67000-70e8c70000 r--s 00000000 fc:00 294 /system/fonts/NotoSansChakma-Regular.ttf -70e8c70000-70e8c92000 r--s 00000000 fc:00 116 /system/fonts/NotoSansDevanagari-Regular.ttf -70e8c92000-70e8c94000 r-xp 00000000 fc:00 2501 /system/lib64/libsync.so -70e8c94000-70e8cb1000 ---p 00000000 00:00 0 -70e8cb1000-70e8cb2000 r--p 0000f000 fc:00 2501 /system/lib64/libsync.so -70e8cb2000-70e8cb3000 rw-p 00010000 fc:00 2501 /system/lib64/libsync.so -70e8cb3000-70e8cc6000 r--s 00000000 fc:00 196 /system/fonts/NotoSerifSinhala-Regular.otf -70e8cc6000-70e8d5c000 r-xp 00000000 fc:00 2403 /system/lib64/libmedia.so -70e8d5c000-70e8d70000 ---p 00000000 00:00 0 -70e8d70000-70e8d88000 r--p 00098000 fc:00 2403 /system/lib64/libmedia.so -70e8d88000-70e8d95000 rw-p 000b0000 fc:00 2403 /system/lib64/libmedia.so -70e8d95000-70e8d96000 r--p 00000000 00:00 0 [anon:atexit handlers] -70e8d96000-70e8d99000 r--s 00000000 fc:00 247 /system/fonts/NotoSansSamaritan-Regular.ttf -70e8d99000-70e8dad000 r--s 00000000 fc:00 108 /system/fonts/NotoSansKannada-Bold.ttf -70e8dad000-70e8dcd000 r--s 00000000 fc:00 303 /system/fonts/NotoSerifEthiopic-Bold.otf -70e8dcd000-70e8de5000 r-xp 00000000 fc:00 2954 /system/lib64/libGLESv2.so -70e8de5000-70e8dfc000 ---p 00000000 00:00 0 -70e8dfc000-70e8dfd000 r--p 0001f000 fc:00 2954 /system/lib64/libGLESv2.so -70e8dfd000-70e8dfe000 rw-p 00020000 fc:00 2954 /system/lib64/libGLESv2.so -70e8dfe000-70e8e06000 r--s 00000000 fc:00 265 /system/fonts/NotoSansBalinese-Regular.ttf -70e8e06000-70e8e0e000 r--s 00000000 fc:00 219 /system/fonts/NotoSansLaoUI-Bold.ttf -70e8e0e000-70e8e12000 r-xp 00000000 fc:00 2617 /system/lib64/libdebuggerd_client.so -70e8e12000-70e8e2d000 ---p 00000000 00:00 0 -70e8e2d000-70e8e2e000 r--p 0000f000 fc:00 2617 /system/lib64/libdebuggerd_client.so -70e8e2e000-70e8e2f000 rw-p 00010000 fc:00 2617 /system/lib64/libdebuggerd_client.so -70e8e2f000-70e8e4b000 r--s 00000000 fc:00 211 /system/fonts/NotoSerifEthiopic-Regular.otf -70e8e4b000-70e8e5e000 r-xp 00000000 fc:00 2484 /system/lib64/android.hardware.memtrack@1.0.so -70e8e5e000-70e8e78000 ---p 00000000 00:00 0 -70e8e78000-70e8e7a000 r--p 0001e000 fc:00 2484 /system/lib64/android.hardware.memtrack@1.0.so -70e8e7a000-70e8e7b000 rw-p 00020000 fc:00 2484 /system/lib64/android.hardware.memtrack@1.0.so -70e8e7b000-70e8e7d000 r--s 00000000 fc:00 261 /system/fonts/NotoSansShavian-Regular.ttf -70e8e7d000-70e8e80000 r--s 00000000 fc:00 204 /system/fonts/NotoSansRunic-Regular.ttf -70e8e80000-70e8ea1000 r-xp 00000000 fc:00 2512 /system/lib64/android.hardware.configstore@1.0.so -70e8ea1000-70e8ebb000 ---p 00000000 00:00 0 -70e8ebb000-70e8ebe000 r--p 0002d000 fc:00 2512 /system/lib64/android.hardware.configstore@1.0.so -70e8ebe000-70e8ebf000 rw-p 00030000 fc:00 2512 /system/lib64/android.hardware.configstore@1.0.so -70e8ebf000-70e8ee3000 r--s 00000000 fc:00 226 /system/fonts/NotoSansEthiopic-Bold.ttf -70e8ee3000-70e8f1a000 r-xp 00000000 fc:00 2337 /system/lib64/libm.so -70e8f1a000-70e8f32000 ---p 00000000 00:00 0 -70e8f32000-70e8f33000 r--p 0003f000 fc:00 2337 /system/lib64/libm.so -70e8f33000-70e8f34000 rw-p 00040000 fc:00 2337 /system/lib64/libm.so -70e8f34000-70e8f36000 r--s 00000000 fc:00 133 /system/fonts/NotoSansRejang-Regular.ttf -70e8f36000-70e8f38000 r--s 00000000 fc:00 69 /system/fonts/NotoSansPhoenician-Regular.ttf -70e8f38000-70e8f40000 r--s 00000000 fc:00 245 /system/fonts/NotoSansLaoUI-Regular.ttf -70e8f40000-70e8f45000 r-xp 00000000 fc:00 2341 /system/lib64/libstagefright_codecbase.so -70e8f45000-70e8f5f000 ---p 00000000 00:00 0 -70e8f5f000-70e8f60000 r--p 0000f000 fc:00 2341 /system/lib64/libstagefright_codecbase.so -70e8f60000-70e8f61000 rw-p 00010000 fc:00 2341 /system/lib64/libstagefright_codecbase.so -70e8f61000-70e8f62000 r--p 00000000 00:00 0 [anon:atexit handlers] -70e8f62000-70e8f66000 r--s 00000000 fc:00 225 /system/fonts/NotoSansOldPersian-Regular.ttf -70e8f66000-70e8f89000 r--s 00000000 fc:00 167 /system/fonts/NotoSansEthiopic-Regular.ttf -70e8f89000-70e8f92000 r-xp 00000000 fc:00 2515 /system/lib64/libGLESv1_CM.so -70e8f92000-70e8fa8000 ---p 00000000 00:00 0 -70e8fa8000-70e8fa9000 r--p 0000f000 fc:00 2515 /system/lib64/libGLESv1_CM.so -70e8fa9000-70e8faa000 rw-p 00010000 fc:00 2515 /system/lib64/libGLESv1_CM.so -70e8faa000-70e8fad000 r--s 00000000 fc:00 206 /system/fonts/NotoSansOsage-Regular.ttf -70e8fad000-70e8fb5000 r--s 00000000 fc:00 121 /system/fonts/NotoSerifLao-Bold.ttf -70e8fb5000-70e8fd3000 r--s 00000000 fc:00 68 /system/fonts/NotoNaskhArabicUI-Bold.ttf -70e8fd3000-70e9010000 r-xp 00000000 fc:00 2600 /system/lib64/android.hardware.cas@1.0.so -70e9010000-70e9026000 ---p 00000000 00:00 0 -70e9026000-70e902c000 r--p 0004a000 fc:00 2600 /system/lib64/android.hardware.cas@1.0.so -70e902c000-70e902d000 rw-p 00050000 fc:00 2600 /system/lib64/android.hardware.cas@1.0.so -70e902d000-70e902e000 r--s 00000000 00:05 31475 /dev/ashmem/5c7d41a6-003d-45a5-9e3b-2d34c5829a2d (deleted) -70e902e000-70e9043000 r--s 00000000 fc:00 120 /system/fonts/NotoSansKannada-Regular.ttf -70e9043000-70e9067000 r-xp 00000000 fc:00 2729 /system/lib64/libexpat.so -70e9067000-70e9081000 ---p 00000000 00:00 0 -70e9081000-70e9083000 r--p 0002e000 fc:00 2729 /system/lib64/libexpat.so -70e9083000-70e9084000 rw-p 00030000 fc:00 2729 /system/lib64/libexpat.so -70e9084000-70e9086000 r--s 00000000 fc:00 155 /system/fonts/NotoSansOsmanya-Regular.ttf -70e9086000-70e90c3000 r--s 00000000 fc:00 91 /system/fonts/NotoSerif-Regular.ttf -70e90c3000-70e91ce000 r-xp 00000000 fc:00 2647 /system/lib64/libcrypto.so -70e91ce000-70e91e2000 ---p 00000000 00:00 0 -70e91e2000-70e91f3000 r--p 0010f000 fc:00 2647 /system/lib64/libcrypto.so -70e91f3000-70e91f4000 rw-p 00120000 fc:00 2647 /system/lib64/libcrypto.so -70e91f4000-70e91f5000 rw-p 00000000 00:00 0 [anon:.bss] -70e91f5000-70e91fa000 r--s 00000000 fc:00 149 /system/fonts/NotoSansNKo-Regular.ttf -70e91fa000-70e9202000 r--s 00000000 fc:00 198 /system/fonts/NotoSerifLao-Regular.ttf -70e9202000-70e921b000 r-xp 00000000 fc:00 2682 /system/lib64/libmedia_helper.so -70e921b000-70e922d000 ---p 00000000 00:00 0 -70e922d000-70e9230000 r--p 0001d000 fc:00 2682 /system/lib64/libmedia_helper.so -70e9230000-70e9231000 rw-p 00020000 fc:00 2682 /system/lib64/libmedia_helper.so -70e9231000-70e924a000 r--s 00000000 fc:00 232 /system/fonts/NotoSansBengali-Bold.ttf -70e924a000-70e9256000 r-xp 00000000 fc:00 2467 /system/lib64/libsoundtrigger.so -70e9256000-70e9272000 ---p 00000000 00:00 0 -70e9272000-70e9276000 r--p 0000c000 fc:00 2467 /system/lib64/libsoundtrigger.so -70e9276000-70e9277000 rw-p 00010000 fc:00 2467 /system/lib64/libsoundtrigger.so -70e9277000-70e9278000 r--s 00000000 fc:01 1177 /vendor/overlay/Pixel/PixelThemeOverlay.apk -70e9278000-70e927c000 r--s 00000000 fc:00 215 /system/fonts/NotoSansNewTaiLue-Regular.ttf -70e927c000-70e929a000 r--s 00000000 fc:00 235 /system/fonts/NotoNaskhArabicUI-Regular.ttf -70e929a000-70e929b000 r-xp 00000000 fc:00 2375 /system/lib64/android.hardware.graphics.common@1.1.so -70e929b000-70e92b9000 ---p 00000000 00:00 0 -70e92b9000-70e92ba000 r--p 0000f000 fc:00 2375 /system/lib64/android.hardware.graphics.common@1.1.so -70e92ba000-70e92bb000 rw-p 00010000 fc:00 2375 /system/lib64/android.hardware.graphics.common@1.1.so -70e92bb000-70e92da000 r--s 00000000 fc:00 281 /system/fonts/GoogleSans-BoldItalic.ttf -70e92da000-70e9302000 r-xp 00000000 fc:00 2529 /system/lib64/libinput.so -70e9302000-70e931b000 ---p 00000000 00:00 0 -70e931b000-70e9322000 r--p 00029000 fc:00 2529 /system/lib64/libinput.so -70e9322000-70e9323000 rw-p 00030000 fc:00 2529 /system/lib64/libinput.so -70e9323000-70e9340000 r--s 00000000 fc:00 130 /system/fonts/NotoNaskhArabic-Bold.ttf -70e9340000-70e934b000 r-xp 00000000 fc:00 2451 /system/lib64/libbpf.so -70e934b000-70e935f000 ---p 00000000 00:00 0 -70e935f000-70e9360000 r--p 0000f000 fc:00 2451 /system/lib64/libbpf.so -70e9360000-70e9361000 rw-p 00010000 fc:00 2451 /system/lib64/libbpf.so -70e9361000-70e9367000 r--s 00000000 fc:00 96 /system/fonts/NotoSansKharoshthi-Regular.ttf -70e9367000-70e9385000 r--s 00000000 fc:00 151 /system/fonts/GoogleSans-Bold.ttf -70e9385000-70e93b8000 r-xp 00000000 fc:00 2494 /system/lib64/libpng.so -70e93b8000-70e93d4000 ---p 00000000 00:00 0 -70e93d4000-70e93d5000 r--p 0003f000 fc:00 2494 /system/lib64/libpng.so -70e93d5000-70e93d6000 rw-p 00040000 fc:00 2494 /system/lib64/libpng.so -70e93d6000-70e93d7000 r--s 00004000 fc:01 1177 /vendor/overlay/Pixel/PixelThemeOverlay.apk -70e93d7000-70e93d9000 r--s 00000000 fc:00 295 /system/fonts/NotoSansOldTurkic-Regular.ttf -70e93d9000-70e93e5000 r--s 00000000 fc:00 86 /system/fonts/NotoSerifKhmer-Bold.otf -70e93e5000-70e9404000 r--s 00000000 fc:00 240 /system/fonts/GoogleSans-MediumItalic.ttf -70e9404000-70e9409000 r-xp 00000000 fc:00 2404 /system/lib64/libhidlmemory.so -70e9409000-70e9423000 ---p 00000000 00:00 0 -70e9423000-70e9424000 r--p 0000f000 fc:00 2404 /system/lib64/libhidlmemory.so -70e9424000-70e9425000 rw-p 00010000 fc:00 2404 /system/lib64/libhidlmemory.so -70e9425000-70e943e000 r--s 00000000 fc:00 185 /system/fonts/NotoSansBengali-Regular.ttf -70e943e000-70e945c000 r--s 00000000 fc:00 129 /system/fonts/GoogleSans-Medium.ttf -70e945c000-70e960c000 r-xp 00000000 fc:00 2398 /system/lib64/libstagefright.so -70e960c000-70e9625000 ---p 00000000 00:00 0 -70e9625000-70e9638000 r--p 001bd000 fc:00 2398 /system/lib64/libstagefright.so -70e9638000-70e966c000 rw-p 001d0000 fc:00 2398 /system/lib64/libstagefright.so -70e966c000-70e966d000 rw-p 00000000 00:00 0 [anon:.bss] -70e966d000-70e966e000 r--s 00000000 103:1d 1474566 /data/resource-cache/vendor@overlay@Pixel@PixelThemeOverlay.apk@idmap -70e966e000-70e9672000 r--s 00000000 fc:00 241 /system/fonts/NotoSansMeeteiMayek-Regular.ttf -70e9672000-70e9680000 r--s 00000000 fc:00 150 /system/fonts/NotoSansMalayalamUI-Bold.ttf -70e9680000-70e96a7000 r-xp 00000000 fc:00 2365 /system/lib64/libhwbinder.so -70e96a7000-70e96bd000 ---p 00000000 00:00 0 -70e96bd000-70e96bf000 r--p 0002e000 fc:00 2365 /system/lib64/libhwbinder.so -70e96bf000-70e96c0000 rw-p 00030000 fc:00 2365 /system/lib64/libhwbinder.so -70e96c0000-70e96c1000 r--s 00088000 103:1d 1736830 /data/app/com.google.sample.tunnel-HGGRU03Gu1Mwkf_-RnFmvw==/base.apk -70e96c1000-70e96cb000 r--s 00000000 fc:00 94 /system/fonts/NotoSansKhmerUI-Regular.ttf -70e96cb000-70e96d9000 r--s 00000000 fc:00 275 /system/fonts/NotoSansMalayalamUI-Regular.ttf -70e96d9000-70e96dd000 r-xp 00000000 fc:00 2386 /system/lib64/libusbhost.so -70e96dd000-70e96f8000 ---p 00000000 00:00 0 -70e96f8000-70e96f9000 r--p 0000f000 fc:00 2386 /system/lib64/libusbhost.so -70e96f9000-70e96fa000 rw-p 00010000 fc:00 2386 /system/lib64/libusbhost.so -70e96fa000-70e96fb000 r--p 00000000 00:05 10266154 [anon:dalvik-classes.dex extracted in memory from /data/app/com.google.sample.tunnel-HGGRU03Gu1Mwkf_-RnFmvw==/base.apk] -70e96fb000-70e9701000 r--s 00000000 fc:00 280 /system/fonts/NotoSansCoptic-Regular.ttf -70e9701000-70e9720000 r-xp 00000000 fc:00 2490 /system/lib64/libstagefright_bufferqueue_helper.so -70e9720000-70e973b000 ---p 00000000 00:00 0 -70e973b000-70e973e000 r--p 0002d000 fc:00 2490 /system/lib64/libstagefright_bufferqueue_helper.so -70e973e000-70e9740000 rw-p 00030000 fc:00 2490 /system/lib64/libstagefright_bufferqueue_helper.so -70e9740000-70e9742000 r--s 00000000 fc:00 141 /system/fonts/NotoSansOldSouthArabian-Regular.ttf -70e9742000-70e974c000 r--s 00000000 fc:00 229 /system/fonts/NotoSerifKhmer-Regular.otf -70e974c000-70e9759000 r--s 00000000 fc:00 260 /system/fonts/NotoSerifMalayalam-Bold.ttf -70e9759000-70e97c7000 r-xp 00000000 fc:00 2428 /system/lib64/libstagefright_omx.so -70e97c7000-70e97dc000 ---p 00000000 00:00 0 -70e97dc000-70e97e6000 r--p 00076000 fc:00 2428 /system/lib64/libstagefright_omx.so -70e97e6000-70e97ed000 rw-p 00080000 fc:00 2428 /system/lib64/libstagefright_omx.so -70e97ed000-70e97fa000 r--s 00000000 fc:00 66 /system/fonts/NotoSerifMalayalam-Regular.ttf -70e97fa000-70e9819000 r--s 00000000 fc:00 183 /system/fonts/GoogleSans-Italic.ttf -70e9819000-70e9856000 r-xp 00000000 fc:00 2434 /system/lib64/libprotobuf-cpp-lite.so -70e9856000-70e9867000 ---p 00000000 00:00 0 -70e9867000-70e9869000 r--p 0003e000 fc:00 2434 /system/lib64/libprotobuf-cpp-lite.so -70e9869000-70e986a000 rw-p 00040000 fc:00 2434 /system/lib64/libprotobuf-cpp-lite.so -70e986a000-70e9873000 r--s 00000000 fc:00 134 /system/fonts/NotoSansKhmerUI-Bold.ttf -70e9873000-70e9891000 r--s 00000000 fc:00 81 /system/fonts/GoogleSans-Regular.ttf -70e9891000-70e989e000 r-xp 00000000 fc:00 2377 /system/lib64/libmediametrics.so -70e989e000-70e98ae000 ---p 00000000 00:00 0 -70e98ae000-70e98b0000 r--p 0000e000 fc:00 2377 /system/lib64/libmediametrics.so -70e98b0000-70e98b1000 rw-p 00010000 fc:00 2377 /system/lib64/libmediametrics.so -70e98b1000-70e98b9000 r--s 00000000 fc:00 152 /system/fonts/NotoSansLao-Bold.ttf -70e98b9000-70e98c7000 r--s 00000000 fc:00 279 /system/fonts/NotoSansMalayalam-Bold.ttf -70e98c7000-70e98ca000 r-xp 00000000 fc:00 2952 /system/lib64/libETC1.so -70e98ca000-70e98e6000 ---p 00000000 00:00 0 -70e98e6000-70e98e7000 r--p 0000f000 fc:00 2952 /system/lib64/libETC1.so -70e98e7000-70e98e8000 rw-p 00010000 fc:00 2952 /system/lib64/libETC1.so -70e98e8000-70e98e9000 r--s 00000000 fc:00 1121 /system/usr/hyphen-data/hyph-und-ethi.hyb -70e98e9000-70e98ef000 r--s 00000000 fc:00 64 /system/fonts/NotoSansBrahmi-Regular.ttf -70e98ef000-70e990f000 rw-p 00000000 00:05 10271012 [anon:dalvik-CompilerMetadata] -70e990f000-70e9926000 r-xp 00000000 fc:00 2526 /system/lib64/libbacktrace.so -70e9926000-70e993e000 ---p 00000000 00:00 0 -70e993e000-70e993f000 r--p 0001f000 fc:00 2526 /system/lib64/libbacktrace.so -70e993f000-70e9940000 rw-p 00020000 fc:00 2526 /system/lib64/libbacktrace.so -70e9940000-70e9941000 r--s 00000000 fc:00 1129 /system/usr/hyphen-data/hyph-tk.hyb -70e9941000-70e99a4000 r-xp 00000000 fc:00 2528 /system/lib64/libcamera_client.so -70e99a4000-70e99bc000 ---p 00000000 00:00 0 -70e99bc000-70e99c9000 r--p 00063000 fc:00 2528 /system/lib64/libcamera_client.so -70e99c9000-70e99d0000 rw-p 00070000 fc:00 2528 /system/lib64/libcamera_client.so -70e99d0000-70e99d1000 r--p 00000000 00:00 0 [anon:linker_alloc] -70e99d1000-70e99d3000 r--s 00000000 fc:00 200 /system/fonts/NotoSansOldItalic-Regular.ttf -70e99d3000-70e99e1000 r--s 00000000 fc:00 153 /system/fonts/NotoSansMalayalam-Regular.ttf -70e99e1000-70e9a01000 rw-p 00000000 00:05 10271011 [anon:dalvik-CompilerMetadata] -70e9a01000-70e9a1e000 r-xp 00000000 fc:00 2542 /system/lib64/libimg_utils.so -70e9a1e000-70e9a39000 ---p 00000000 00:00 0 -70e9a39000-70e9a3c000 r--p 0001d000 fc:00 2542 /system/lib64/libimg_utils.so -70e9a3c000-70e9a3f000 rw-p 00020000 fc:00 2542 /system/lib64/libimg_utils.so -70e9a3f000-70e9a5c000 r--s 00000000 fc:00 262 /system/fonts/NotoNaskhArabic-Regular.ttf -70e9a5c000-70e9a69000 r-xp 00000000 fc:00 2706 /system/lib64/libziparchive.so -70e9a69000-70e9a7b000 ---p 00000000 00:00 0 -70e9a7b000-70e9a7c000 r--p 0000f000 fc:00 2706 /system/lib64/libziparchive.so -70e9a7c000-70e9a7d000 rw-p 00010000 fc:00 2706 /system/lib64/libziparchive.so -70e9a7d000-70e9a85000 r--s 00000000 fc:00 119 /system/fonts/NotoSansLao-Regular.ttf -70e9a85000-70e9a8e000 r--s 00000000 fc:00 77 /system/fonts/NotoSansTamilUI-Bold.ttf -70e9a8e000-70e9a97000 r--s 00000000 fc:00 160 /system/fonts/NotoSansTamilUI-Regular.ttf -70e9a97000-70e9a9d000 r-xp 00000000 fc:00 2536 /system/lib64/libnativehelper.so -70e9a9d000-70e9ab6000 ---p 00000000 00:00 0 -70e9ab6000-70e9ab7000 r--p 0000f000 fc:00 2536 /system/lib64/libnativehelper.so -70e9ab7000-70e9ab8000 rw-p 00010000 fc:00 2536 /system/lib64/libnativehelper.so -70e9ab8000-70e9ab9000 r--s 00000000 fc:00 1134 /system/usr/hyphen-data/hyph-te.hyb -70e9ab9000-70e9ac2000 r--s 00000000 fc:00 246 /system/fonts/NotoSerifTamil-Bold.ttf -70e9ac2000-70e9acb000 r--s 00000000 fc:00 302 /system/fonts/NotoSerifTamil-Regular.ttf -70e9acb000-70e9af4000 r-xp 00000000 fc:00 2950 /system/lib64/libmemunreachable.so -70e9af4000-70e9b09000 ---p 00000000 00:00 0 -70e9b09000-70e9b0b000 r--p 0002e000 fc:00 2950 /system/lib64/libmemunreachable.so -70e9b0b000-70e9b0c000 rw-p 00030000 fc:00 2950 /system/lib64/libmemunreachable.so -70e9b0c000-70e9b0d000 r--s 00000000 fc:00 1088 /system/usr/hyphen-data/hyph-ta.hyb -70e9b0d000-70e9b0f000 r--s 00000000 fc:00 72 /system/fonts/NotoSansOlChiki-Regular.ttf -70e9b0f000-70e9b2f000 rw-p 00000000 00:05 10271010 [anon:dalvik-CompilerMetadata] -70e9b2f000-70e9b4f000 r--s 00000000 00:10 16633 /dev/__properties__/u:object_r:persist_debug_prop:s0 -70e9b4f000-70e9b65000 r-xp 00000000 fc:00 2920 /system/lib64/android.hardware.cas.native@1.0.so -70e9b65000-70e9b7b000 ---p 00000000 00:00 0 -70e9b7b000-70e9b7d000 r--p 0001e000 fc:00 2920 /system/lib64/android.hardware.cas.native@1.0.so -70e9b7d000-70e9b7e000 rw-p 00020000 fc:00 2920 /system/lib64/android.hardware.cas.native@1.0.so -70e9b7e000-70e9b7f000 r--s 00000000 fc:00 1145 /system/usr/hyphen-data/hyph-pt.hyb -70e9b7f000-70e9b83000 r--s 00000000 fc:00 277 /system/fonts/NotoSansMandaic-Regular.ttf -70e9b83000-70e9bdb000 r-xp 00000000 fc:00 2334 /system/lib64/libsonivox.so -70e9bdb000-70e9bf2000 ---p 00000000 00:00 0 -70e9bf2000-70e9bf3000 r--p 0005f000 fc:00 2334 /system/lib64/libsonivox.so -70e9bf3000-70e9bf4000 rw-p 00060000 fc:00 2334 /system/lib64/libsonivox.so -70e9bf4000-70e9bfb000 rw-p 00000000 00:00 0 [anon:.bss] -70e9bfb000-70e9c01000 r--s 00000000 fc:00 123 /system/fonts/NotoSansCham-Bold.ttf -70e9c01000-70e9c0a000 r--s 00000000 fc:00 255 /system/fonts/NotoSansTamil-Bold.ttf -70e9c0a000-70e9c13000 r--s 00000000 fc:00 135 /system/fonts/NotoSansTamil-Regular.ttf -70e9c13000-70e9c15000 r-xp 00000000 fc:00 2519 /system/lib64/libgraphicsenv.so -70e9c15000-70e9c32000 ---p 00000000 00:00 0 -70e9c32000-70e9c33000 r--p 0000f000 fc:00 2519 /system/lib64/libgraphicsenv.so -70e9c33000-70e9c34000 rw-p 00010000 fc:00 2519 /system/lib64/libgraphicsenv.so -70e9c34000-70e9c3a000 r--s 00000000 fc:00 259 /system/fonts/NotoSansCham-Regular.ttf -70e9c3a000-70e9c42000 r--s 00000000 fc:00 114 /system/fonts/NotoSansGurmukhiUI-Bold.ttf -70e9c42000-70e9c4a000 r--s 00000000 fc:00 122 /system/fonts/NotoSansGurmukhiUI-Regular.ttf -70e9c4a000-70e9c5f000 r-xp 00000000 fc:00 2348 /system/lib64/android.hidl.allocator@1.0.so -70e9c5f000-70e9c77000 ---p 00000000 00:00 0 -70e9c77000-70e9c79000 r--p 0001e000 fc:00 2348 /system/lib64/android.hidl.allocator@1.0.so -70e9c79000-70e9c7a000 rw-p 00020000 fc:00 2348 /system/lib64/android.hidl.allocator@1.0.so -70e9c7a000-70e9c7b000 r--s 00000000 fc:00 1095 /system/usr/hyphen-data/hyph-pa.hyb -70e9c7b000-70e9c83000 r--s 00000000 fc:00 298 /system/fonts/NotoSerifGurmukhi-Bold.otf -70e9c83000-70e9d01000 r-xp 00000000 fc:00 2665 /system/lib64/libbinder.so -70e9d01000-70e9d1e000 ---p 00000000 00:00 0 -70e9d1e000-70e9d2e000 r--p 00080000 fc:00 2665 /system/lib64/libbinder.so -70e9d2e000-70e9d2f000 rw-p 00090000 fc:00 2665 /system/lib64/libbinder.so -70e9d2f000-70e9d4f000 rw-p 00000000 00:05 10271009 [anon:dalvik-CompilerMetadata] -70e9d4f000-70e9d53000 r-xp 00000000 fc:00 2454 /system/lib64/libaudiomanager.so -70e9d53000-70e9d6e000 ---p 00000000 00:00 0 -70e9d6e000-70e9d6f000 r--p 0000f000 fc:00 2454 /system/lib64/libaudiomanager.so -70e9d6f000-70e9d70000 rw-p 00010000 fc:00 2454 /system/lib64/libaudiomanager.so -70e9d70000-70e9d71000 r--s 00000000 fc:00 1087 /system/usr/hyphen-data/hyph-or.hyb -70e9d71000-70e9d91000 rw-p 00000000 00:05 10271008 [anon:dalvik-CompilerMetadata] -70e9d91000-70e9e21000 r-xp 00000000 fc:00 2627 /system/lib64/libft2.so -70e9e21000-70e9e37000 ---p 00000000 00:00 0 -70e9e37000-70e9e3c000 r--p 0009b000 fc:00 2627 /system/lib64/libft2.so -70e9e3c000-70e9e3d000 rw-p 000a0000 fc:00 2627 /system/lib64/libft2.so -70e9e3d000-70e9e3e000 r--s 00000000 fc:00 1142 /system/usr/hyphen-data/hyph-mr.hyb -70e9e3e000-70e9e45000 r--s 00000000 fc:00 88 /system/fonts/NotoSerifGurmukhi-Regular.otf -70e9e45000-70e9e65000 r--s 00000000 00:10 16594 /dev/__properties__/u:object_r:exported3_default_prop:s0 -70e9e65000-70e9e7f000 r-xp 00000000 fc:00 2643 /system/lib64/libunwind.so -70e9e7f000-70e9e94000 ---p 00000000 00:00 0 -70e9e94000-70e9e95000 r--p 0001f000 fc:00 2643 /system/lib64/libunwind.so -70e9e95000-70e9e96000 rw-p 00020000 fc:00 2643 /system/lib64/libunwind.so -70e9e96000-70e9eff000 rw-p 00000000 00:00 0 [anon:.bss] -70e9eff000-70e9f00000 r--s 00000000 fc:00 1130 /system/usr/hyphen-data/hyph-ml.hyb -70e9f00000-70e9f02000 r--s 00000000 fc:00 75 /system/fonts/NotoSansOgham-Regular.ttf -70e9f02000-70e9f0a000 r--s 00000000 fc:00 193 /system/fonts/NotoSansGurmukhi-Bold.ttf -70e9f0a000-70ea022000 r-xp 00000000 fc:00 2328 /system/lib64/libsqlite.so -70ea022000-70ea033000 ---p 00000000 00:00 0 -70ea033000-70ea036000 r--p 0011d000 fc:00 2328 /system/lib64/libsqlite.so -70ea036000-70ea038000 rw-p 00120000 fc:00 2328 /system/lib64/libsqlite.so -70ea038000-70ea03c000 r--s 00000000 fc:00 285 /system/fonts/NotoSansGlagolitic-Regular.ttf -70ea03c000-70ea04c000 r--s 00000000 fc:00 184 /system/fonts/NotoSerifGujarati-Bold.ttf -70ea04c000-70ea060000 r-xp 00000000 fc:00 2731 /system/lib64/libstatslog.so -70ea060000-70ea07b000 ---p 00000000 00:00 0 -70ea07b000-70ea07c000 r--p 0001f000 fc:00 2731 /system/lib64/libstatslog.so -70ea07c000-70ea07d000 rw-p 00020000 fc:00 2731 /system/lib64/libstatslog.so -70ea07d000-70ea081000 r--s 00000000 fc:00 182 /system/fonts/NotoSansBatak-Regular.ttf -70ea081000-70ea091000 r--s 00000000 fc:00 264 /system/fonts/NotoSerifGujarati-Regular.ttf -70ea091000-70ea160000 r-xp 00000000 fc:00 2728 /system/lib64/libdng_sdk.so -70ea160000-70ea173000 ---p 00000000 00:00 0 -70ea173000-70ea17a000 r--p 000d9000 fc:00 2728 /system/lib64/libdng_sdk.so -70ea17a000-70ea17b000 rw-p 000e0000 fc:00 2728 /system/lib64/libdng_sdk.so -70ea17b000-70ea198000 r--s 00000000 fc:00 223 /system/fonts/DancingScript-Bold.ttf -70ea198000-70ea19c000 r-xp 00000000 fc:00 2344 /system/lib64/libnativewindow.so -70ea19c000-70ea1b7000 ---p 00000000 00:00 0 -70ea1b7000-70ea1b8000 r--p 0000f000 fc:00 2344 /system/lib64/libnativewindow.so -70ea1b8000-70ea1b9000 rw-p 00010000 fc:00 2344 /system/lib64/libnativewindow.so -70ea1b9000-70ea1bd000 r--s 00000000 fc:00 98 /system/fonts/NotoSansAhom-Regular.otf -70ea1bd000-70ea1d1000 r--s 00000000 fc:00 104 /system/fonts/NotoSerifDevanagari-Bold.ttf -70ea1d1000-70ea1d4000 r-xp 00000000 fc:00 2923 /system/lib64/libstdc++.so -70ea1d4000-70ea1f0000 ---p 00000000 00:00 0 -70ea1f0000-70ea1f1000 r--p 0000f000 fc:00 2923 /system/lib64/libstdc++.so -70ea1f1000-70ea1f2000 rw-p 00010000 fc:00 2923 /system/lib64/libstdc++.so -70ea1f2000-70ea1f4000 r--s 00000000 fc:00 117 /system/fonts/NotoSansLydian-Regular.ttf -70ea1f4000-70ea211000 r--s 00000000 fc:00 239 /system/fonts/DancingScript-Regular.ttf -70ea211000-70ea24a000 r-xp 00000000 fc:00 2933 /system/lib64/android.hardware.graphics.bufferqueue@1.0.so -70ea24a000-70ea268000 ---p 00000000 00:00 0 -70ea268000-70ea26c000 r--p 0003c000 fc:00 2933 /system/lib64/android.hardware.graphics.bufferqueue@1.0.so -70ea26c000-70ea26d000 rw-p 00040000 fc:00 2933 /system/lib64/android.hardware.graphics.bufferqueue@1.0.so -70ea26d000-70ea26f000 r--s 00000000 fc:00 244 /system/fonts/NotoSansLycian-Regular.ttf -70ea26f000-70ea273000 r--s 00000000 fc:00 173 /system/fonts/NotoSansThaana-Bold.ttf -70ea273000-70ea287000 r--s 00000000 fc:00 106 /system/fonts/NotoSerifDevanagari-Regular.ttf -70ea287000-70ea29e000 r-xp 00000000 fc:00 2938 /system/lib64/libpiex.so -70ea29e000-70ea2b6000 ---p 00000000 00:00 0 -70ea2b6000-70ea2b7000 r--p 0001f000 fc:00 2938 /system/lib64/libpiex.so -70ea2b7000-70ea2b8000 rw-p 00020000 fc:00 2938 /system/lib64/libpiex.so -70ea2b8000-70ea2c0000 r--s 00000000 fc:00 113 /system/fonts/NotoSansGurmukhi-Regular.ttf -70ea2c0000-70ea2c6000 r--s 00000000 fc:00 263 /system/fonts/NotoSerifGeorgian-Bold.ttf -70ea2c6000-70ea2cc000 r--s 00000000 fc:00 249 /system/fonts/NotoSerifGeorgian-Regular.ttf -70ea2cc000-70ea9b4000 r-xp 00000000 fc:00 2532 /system/lib64/libhwui.so -70ea9b4000-70ea9d3000 ---p 00000000 00:00 0 -70ea9d3000-70eaa0b000 r--p 006e8000 fc:00 2532 /system/lib64/libhwui.so -70eaa0b000-70eaa0c000 rw-p 00720000 fc:00 2532 /system/lib64/libhwui.so -70eaa0c000-70eaa11000 rw-p 00000000 00:00 0 [anon:.bss] -70eaa11000-70eaa12000 r--s 00000000 fc:00 1110 /system/usr/hyphen-data/hyph-la.hyb -70eaa12000-70eaa16000 r--s 00000000 fc:00 87 /system/fonts/NotoSansThaana-Regular.ttf -70eaa16000-70eaa1b000 r--s 00000000 fc:00 218 /system/fonts/NotoSansGeorgian-Bold.ttf -70eaa1b000-70eaa20000 r--s 00000000 fc:00 125 /system/fonts/NotoSansGeorgian-Regular.ttf -70eaa20000-70eaa40000 rw-p 00000000 00:05 10271007 [anon:dalvik-CompilerMetadata] -70eaa40000-70eaaa0000 r-xp 00000000 fc:00 2384 /system/lib64/libhidltransport.so -70eaaa0000-70eaabe000 ---p 00000000 00:00 0 -70eaabe000-70eaac6000 r--p 00068000 fc:00 2384 /system/lib64/libhidltransport.so -70eaac6000-70eaac7000 rw-p 00070000 fc:00 2384 /system/lib64/libhidltransport.so -70eaac7000-70eaacb000 r--s 00000000 fc:00 192 /system/fonts/NotoSerifArmenian-Bold.ttf -70eaacb000-70eaad0000 r--s 00000000 fc:00 210 /system/fonts/NotoSansThaiUI-Bold.ttf -70eaad0000-70eaaf0000 rw-p 00000000 00:05 10271006 [anon:dalvik-CompilerMetadata] -70eaaf0000-70eab10000 rw-p 00000000 00:05 10271005 [anon:dalvik-CompilerMetadata] -70eab10000-70eab57000 r-xp 00000000 fc:00 2546 /system/lib64/libmedia_omx.so -70eab57000-70eab6d000 ---p 00000000 00:00 0 -70eab6d000-70eab7a000 r--p 00053000 fc:00 2546 /system/lib64/libmedia_omx.so -70eab7a000-70eab7f000 rw-p 00060000 fc:00 2546 /system/lib64/libmedia_omx.so -70eab7f000-70eab80000 r--s 00000000 fc:00 1119 /system/usr/hyphen-data/hyph-kn.hyb -70eab80000-70eab86000 r--s 00000000 fc:00 224 /system/fonts/NotoSansThaiUI-Regular.ttf -70eab86000-70eab8b000 r--s 00000000 fc:00 300 /system/fonts/NotoSerifThai-Bold.ttf -70eab8b000-70eabab000 rw-p 00000000 00:05 10271004 [anon:dalvik-CompilerMetadata] -70eabab000-70eac21000 r-xp 00000000 fc:00 2385 /system/lib64/libvintf.so -70eac21000-70eac31000 ---p 00000000 00:00 0 -70eac31000-70eac36000 r--p 0007b000 fc:00 2385 /system/lib64/libvintf.so -70eac36000-70eac37000 rw-p 00080000 fc:00 2385 /system/lib64/libvintf.so -70eac37000-70eac39000 rw-p 00000000 00:00 0 [anon:.bss] -70eac39000-70eac3a000 r--s 00000000 fc:00 1104 /system/usr/hyphen-data/hyph-hy.hyb -70eac3a000-70eac3f000 r--s 00000000 fc:00 212 /system/fonts/NotoSerifThai-Regular.ttf -70eac3f000-70eac44000 r--s 00000000 fc:00 220 /system/fonts/NotoSansThai-Bold.ttf -70eac44000-70eacb2000 r-xp 00000000 fc:00 2606 /system/lib64/android.hardware.media.omx@1.0.so -70eacb2000-70eaccf000 ---p 00000000 00:00 0 -70eaccf000-70eacd8000 r--p 00077000 fc:00 2606 /system/lib64/android.hardware.media.omx@1.0.so -70eacd8000-70eacd9000 rw-p 00080000 fc:00 2606 /system/lib64/android.hardware.media.omx@1.0.so -70eacd9000-70eacdf000 r--s 00000000 fc:00 169 /system/fonts/NotoSansThai-Regular.ttf -70eacdf000-70eace9000 r--s 00000000 fc:00 140 /system/fonts/CarroisGothicSC-Regular.ttf -70eace9000-70ead09000 rw-p 00000000 00:05 10271003 [anon:dalvik-CompilerMetadata] -70ead09000-70ead22000 r-xp 00000000 fc:00 2539 /system/lib64/android.hardware.graphics.mapper@2.1.so -70ead22000-70ead34000 ---p 00000000 00:00 0 -70ead34000-70ead37000 r--p 0001d000 fc:00 2539 /system/lib64/android.hardware.graphics.mapper@2.1.so -70ead37000-70ead38000 rw-p 00020000 fc:00 2539 /system/lib64/android.hardware.graphics.mapper@2.1.so -70ead38000-70ead47000 r--s 00000000 fc:00 188 /system/fonts/ComingSoon.ttf -70ead47000-70ead5d000 r-xp 00000000 fc:00 2379 /system/lib64/libselinux.so -70ead5d000-70ead76000 ---p 00000000 00:00 0 -70ead76000-70ead77000 r--p 0001f000 fc:00 2379 /system/lib64/libselinux.so -70ead77000-70ead78000 rw-p 00020000 fc:00 2379 /system/lib64/libselinux.so -70ead78000-70ead79000 rw-p 00000000 00:00 0 [anon:.bss] -70ead79000-70ead7d000 r--s 00000000 fc:00 282 /system/fonts/NotoSerifArmenian-Regular.ttf -70ead7d000-70ead82000 r--s 00000000 fc:00 288 /system/fonts/NotoSerifHebrew-Bold.ttf -70ead82000-70ead83000 r-xp 00000000 fc:00 2680 /system/lib64/android.hardware.media@1.0.so -70ead83000-70eada1000 ---p 00000000 00:00 0 -70eada1000-70eada2000 r--p 0000f000 fc:00 2680 /system/lib64/android.hardware.media@1.0.so -70eada2000-70eada3000 rw-p 00010000 fc:00 2680 /system/lib64/android.hardware.media@1.0.so -70eada3000-70eada8000 r--s 00000000 fc:00 248 /system/fonts/NotoSerifHebrew-Regular.ttf -70eada8000-70eadb9000 r--s 00000000 fc:00 252 /system/fonts/CutiveMono.ttf -70eadb9000-70eadd9000 r--s 00000000 00:10 16641 /dev/__properties__/u:object_r:radio_prop:s0 -70eadd9000-70eadda000 r-xp 00000000 fc:00 2533 /system/lib64/android.hardware.graphics.common@1.0.so -70eadda000-70eadf8000 ---p 00000000 00:00 0 -70eadf8000-70eadf9000 r--p 0000f000 fc:00 2533 /system/lib64/android.hardware.graphics.common@1.0.so -70eadf9000-70eadfa000 rw-p 00010000 fc:00 2533 /system/lib64/android.hardware.graphics.common@1.0.so -70eadfa000-70eadfb000 r--s 00000000 fc:00 1126 /system/usr/hyphen-data/hyph-hr.hyb -70eadfb000-70eadfd000 r--s 00000000 fc:00 194 /system/fonts/NotoSansLisu-Regular.ttf -70eadfd000-70eae18000 r--s 00000000 fc:00 201 /system/fonts/DroidSansMono.ttf -70eae18000-70eae3b000 r-xp 00000000 fc:00 2925 /system/lib64/liblzma.so -70eae3b000-70eae57000 ---p 00000000 00:00 0 -70eae57000-70eae58000 r--p 0002f000 fc:00 2925 /system/lib64/liblzma.so -70eae58000-70eae59000 rw-p 00030000 fc:00 2925 /system/lib64/liblzma.so -70eae59000-70eae5f000 rw-p 00000000 00:00 0 [anon:.bss] -70eae5f000-70eae62000 r--s 00000000 fc:00 103 /system/fonts/NotoSansLimbu-Regular.ttf -70eae62000-70eae67000 r--s 00000000 fc:00 236 /system/fonts/NotoSansHebrew-Bold.ttf -70eae67000-70eae84000 r--s 001c2000 fc:00 990 /system/framework/ext.jar -70eae84000-70eaea4000 rw-p 00000000 00:05 10269720 [anon:dalvik-LinearAlloc] -70eaea4000-70eaede000 r-xp 00000000 fc:00 2924 /system/lib64/libwilhelm.so -70eaede000-70eaefa000 ---p 00000000 00:00 0 -70eaefa000-70eaeff000 r--p 0003b000 fc:00 2924 /system/lib64/libwilhelm.so -70eaeff000-70eaf00000 rw-p 00040000 fc:00 2924 /system/lib64/libwilhelm.so -70eaf00000-70eaf03000 r--s 00000000 fc:00 242 /system/fonts/NotoSansElbasan-Regular.otf -70eaf03000-70eaf21000 r-xp 00000000 fc:00 2415 /system/lib64/libdrmframework.so -70eaf21000-70eaf38000 ---p 00000000 00:00 0 -70eaf38000-70eaf3d000 r--p 0002b000 fc:00 2415 /system/lib64/libdrmframework.so -70eaf3d000-70eaf3e000 rw-p 00030000 fc:00 2415 /system/lib64/libdrmframework.so -70eaf3e000-70eaf43000 r--s 00000000 fc:00 70 /system/fonts/NotoSansHebrew-Regular.ttf -70eaf43000-70eaf44000 ---p 00000000 00:00 0 [anon:thread signal stack guard] -70eaf44000-70eaf48000 rw-p 00000000 00:00 0 [anon:thread signal stack] -70eaf48000-70eaf49000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70eaf49000-70eaf4c000 rw-p 00000000 00:00 0 [anon:bionic TLS] -70eaf4c000-70eaf4d000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70eaf4d000-70eaf4e000 ---p 00000000 00:00 0 [anon:thread signal stack guard] -70eaf4e000-70eaf52000 rw-p 00000000 00:00 0 [anon:thread signal stack] -70eaf52000-70eaf98000 r-xp 00000000 fc:00 2426 /system/lib64/libunwindstack.so -70eaf98000-70eafb6000 ---p 00000000 00:00 0 -70eafb6000-70eafbd000 r--p 00049000 fc:00 2426 /system/lib64/libunwindstack.so -70eafbd000-70eafbe000 rw-p 00050000 fc:00 2426 /system/lib64/libunwindstack.so -70eafbe000-70eafc0000 r--s 00000000 fc:00 162 /system/fonts/NotoSansKayahLi-Regular.ttf -70eafc0000-70eafe4000 r-xp 00000000 fc:00 2944 /system/lib64/libvulkan.so -70eafe4000-70eaffc000 ---p 00000000 00:00 0 -70eaffc000-70eaffe000 r--p 0002e000 fc:00 2944 /system/lib64/libvulkan.so -70eaffe000-70eafff000 rw-p 00030000 fc:00 2944 /system/lib64/libvulkan.so -70eafff000-70eb001000 r--s 00000000 fc:00 180 /system/fonts/NotoSansInscriptionalParthian-Regular.ttf -70eb001000-70eb01d000 r-xp 00000000 fc:00 2400 /system/lib64/libbufferhubqueue.so -70eb01d000-70eb030000 ---p 00000000 00:00 0 -70eb030000-70eb031000 r--p 0001f000 fc:00 2400 /system/lib64/libbufferhubqueue.so -70eb031000-70eb032000 rw-p 00020000 fc:00 2400 /system/lib64/libbufferhubqueue.so -70eb032000-70eb036000 r--s 00000000 fc:00 269 /system/fonts/NotoSansArmenian-Bold.ttf -70eb036000-70eb037000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70eb037000-70eb03a000 rw-p 00000000 00:00 0 [anon:bionic TLS] -70eb03a000-70eb03b000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70eb03b000-70eb03c000 ---p 00000000 00:00 0 [anon:thread signal stack guard] -70eb03c000-70eb040000 rw-p 00000000 00:00 0 [anon:thread signal stack] -70eb040000-70eb042000 r-xp 00000000 fc:00 2935 /system/lib64/libhardware.so -70eb042000-70eb05f000 ---p 00000000 00:00 0 -70eb05f000-70eb060000 r--p 0000f000 fc:00 2935 /system/lib64/libhardware.so -70eb060000-70eb061000 rw-p 00010000 fc:00 2935 /system/lib64/libhardware.so -70eb061000-70eb063000 r--s 00000000 fc:00 171 /system/fonts/NotoSansInscriptionalPahlavi-Regular.ttf -70eb063000-70eb064000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70eb064000-70eb067000 rw-p 00000000 00:00 0 [anon:bionic TLS] -70eb067000-70eb068000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70eb068000-70eb069000 ---p 00000000 00:00 0 [anon:thread signal stack guard] -70eb069000-70eb06d000 rw-p 00000000 00:00 0 [anon:thread signal stack] -70eb06d000-70eb06e000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70eb06e000-70eb071000 rw-p 00000000 00:00 0 [anon:bionic TLS] -70eb071000-70eb072000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70eb072000-70eb073000 ---p 00000000 00:00 0 [anon:thread signal stack guard] -70eb073000-70eb077000 rw-p 00000000 00:00 0 [anon:thread signal stack] -70eb077000-70eb078000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70eb078000-70eb07b000 rw-p 00000000 00:00 0 [anon:bionic TLS] -70eb07b000-70eb07c000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70eb07c000-70eb07d000 ---p 00000000 00:00 0 [anon:thread signal stack guard] -70eb07d000-70eb081000 rw-p 00000000 00:00 0 [anon:thread signal stack] -70eb081000-70eb082000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70eb082000-70eb085000 rw-p 00000000 00:00 0 [anon:bionic TLS] -70eb085000-70eb086000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70eb086000-70eb09d000 r-xp 00000000 fc:00 2604 /system/lib64/libz.so -70eb09d000-70eb0b5000 ---p 00000000 00:00 0 -70eb0b5000-70eb0b6000 r--p 0001f000 fc:00 2604 /system/lib64/libz.so -70eb0b6000-70eb0b7000 rw-p 00020000 fc:00 2604 /system/lib64/libz.so -70eb0b7000-70eb0bb000 r--s 00000000 fc:00 289 /system/fonts/NotoSansArmenian-Regular.ttf -70eb0bb000-70eb0bc000 ---p 00000000 00:00 0 [anon:thread signal stack guard] -70eb0bc000-70eb0c0000 rw-p 00000000 00:00 0 [anon:thread signal stack] -70eb0c0000-70eb0c1000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70eb0c1000-70eb0c4000 rw-p 00000000 00:00 0 [anon:bionic TLS] -70eb0c4000-70eb0c5000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70eb0c5000-70eb0c6000 ---p 00000000 00:00 0 [anon:thread signal stack guard] -70eb0c6000-70eb0ca000 rw-p 00000000 00:00 0 [anon:thread signal stack] -70eb0ca000-70eb0cb000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70eb0cb000-70eb0ce000 rw-p 00000000 00:00 0 [anon:bionic TLS] -70eb0ce000-70eb0cf000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70eb0cf000-70eb0ef000 rw-p 00000000 00:05 10270988 [anon:dalvik-LinearAlloc] -70eb0ef000-70eb5bb000 r-xp 00000000 fc:00 2374 /system/lib64/libpdfium.so -70eb5bb000-70eb5cf000 ---p 00000000 00:00 0 -70eb5cf000-70eb5e6000 r--p 004d9000 fc:00 2374 /system/lib64/libpdfium.so -70eb5e6000-70eb5ea000 rw-p 004f0000 fc:00 2374 /system/lib64/libpdfium.so -70eb5ea000-70eb5f1000 rw-p 00000000 00:00 0 [anon:.bss] -70eb5f1000-70eb5f2000 r--s 00000000 fc:00 1094 /system/usr/hyphen-data/hyph-hi.hyb -70eb5f2000-70eb5f6000 rw-p 00000000 00:05 10270982 [anon:dalvik-thread local mark stack] -70eb5f6000-70eb5fa000 rw-p 00000000 00:05 10270981 [anon:dalvik-thread local mark stack] -70eb5fa000-70eb5fe000 rw-p 00000000 00:05 10270980 [anon:dalvik-thread local mark stack] -70eb5fe000-70eb602000 rw-p 00000000 00:05 10270979 [anon:dalvik-thread local mark stack] -70eb602000-70eb606000 rw-p 00000000 00:05 10270978 [anon:dalvik-thread local mark stack] -70eb606000-70eb60a000 rw-p 00000000 00:05 10270977 [anon:dalvik-thread local mark stack] -70eb60a000-70eb60e000 rw-p 00000000 00:05 10270976 [anon:dalvik-thread local mark stack] -70eb60e000-70eb612000 rw-p 00000000 00:05 10270975 [anon:dalvik-thread local mark stack] -70eb612000-70eb616000 rw-p 00000000 00:05 10270974 [anon:dalvik-thread local mark stack] -70eb616000-70eb61a000 r-xp 00000000 fc:00 2479 /system/lib64/libspeexresampler.so -70eb61a000-70eb635000 ---p 00000000 00:00 0 -70eb635000-70eb636000 r--p 0000f000 fc:00 2479 /system/lib64/libspeexresampler.so -70eb636000-70eb637000 rw-p 00010000 fc:00 2479 /system/lib64/libspeexresampler.so -70eb637000-70eb639000 r--s 00000000 fc:00 299 /system/fonts/NotoSansImperialAramaic-Regular.ttf -70eb639000-70eb63d000 rw-p 00000000 00:05 10270973 [anon:dalvik-thread local mark stack] -70eb63d000-70eb641000 rw-p 00000000 00:05 10270972 [anon:dalvik-thread local mark stack] -70eb641000-70eb645000 rw-p 00000000 00:05 10270971 [anon:dalvik-thread local mark stack] -70eb645000-70eb649000 rw-p 00000000 00:05 10270970 [anon:dalvik-thread local mark stack] -70eb649000-70eb64d000 rw-p 00000000 00:05 10270969 [anon:dalvik-thread local mark stack] -70eb64d000-70eb651000 rw-p 00000000 00:05 10270968 [anon:dalvik-thread local mark stack] -70eb651000-70eb655000 rw-p 00000000 00:05 10270967 [anon:dalvik-thread local mark stack] -70eb655000-70eb659000 rw-p 00000000 00:05 10270966 [anon:dalvik-thread local mark stack] -70eb659000-70eb65d000 rw-p 00000000 00:05 10270965 [anon:dalvik-thread local mark stack] -70eb65d000-70eb661000 rw-p 00000000 00:05 10270964 [anon:dalvik-thread local mark stack] -70eb661000-70eb6c5000 r-xp 00000000 fc:00 2461 /system/lib64/libhidl-gen-utils.so -70eb6c5000-70eb6df000 ---p 00000000 00:00 0 -70eb6df000-70eb6e1000 r--p 0006e000 fc:00 2461 /system/lib64/libhidl-gen-utils.so -70eb6e1000-70eb6e2000 rw-p 00070000 fc:00 2461 /system/lib64/libhidl-gen-utils.so -70eb6e2000-70eb6e6000 rw-p 00000000 00:05 10270963 [anon:dalvik-thread local mark stack] -70eb6e6000-70eb6ea000 rw-p 00000000 00:05 10270962 [anon:dalvik-thread local mark stack] -70eb6ea000-70eb6ee000 rw-p 00000000 00:05 10270961 [anon:dalvik-thread local mark stack] -70eb6ee000-70eb6f2000 rw-p 00000000 00:05 10270960 [anon:dalvik-thread local mark stack] -70eb6f2000-70eb6f6000 rw-p 00000000 00:05 10270959 [anon:dalvik-thread local mark stack] -70eb6f6000-70eb6fa000 rw-p 00000000 00:05 10270958 [anon:dalvik-thread local mark stack] -70eb6fa000-70eb6fe000 rw-p 00000000 00:05 10270957 [anon:dalvik-thread local mark stack] -70eb6fe000-70eb702000 rw-p 00000000 00:05 10270956 [anon:dalvik-thread local mark stack] -70eb702000-70eb706000 rw-p 00000000 00:05 10270955 [anon:dalvik-thread local mark stack] -70eb706000-70eb70a000 rw-p 00000000 00:05 10270954 [anon:dalvik-thread local mark stack] -70eb70a000-70eb70e000 rw-p 00000000 00:05 10270953 [anon:dalvik-thread local mark stack] -70eb70e000-70eb712000 rw-p 00000000 00:05 10270952 [anon:dalvik-thread local mark stack] -70eb712000-70eb71a000 r-xp 00000000 fc:00 2652 /system/lib64/libcamera_metadata.so -70eb71a000-70eb72f000 ---p 00000000 00:00 0 -70eb72f000-70eb730000 r--p 0000f000 fc:00 2652 /system/lib64/libcamera_metadata.so -70eb730000-70eb732000 rw-p 00010000 fc:00 2652 /system/lib64/libcamera_metadata.so -70eb732000-70eb734000 r--s 00000000 fc:00 131 /system/fonts/NotoSansHanunoo-Regular.ttf -70eb734000-70eb738000 rw-p 00000000 00:05 10270951 [anon:dalvik-thread local mark stack] -70eb738000-70eb73c000 rw-p 00000000 00:05 10270950 [anon:dalvik-thread local mark stack] -70eb73c000-70eb740000 rw-p 00000000 00:05 10270949 [anon:dalvik-thread local mark stack] -70eb740000-70eb744000 rw-p 00000000 00:05 10270948 [anon:dalvik-thread local mark stack] -70eb744000-70eb748000 rw-p 00000000 00:05 10270947 [anon:dalvik-thread local mark stack] -70eb748000-70eb74c000 rw-p 00000000 00:05 10270946 [anon:dalvik-thread local mark stack] -70eb74c000-70eb750000 rw-p 00000000 00:05 10270945 [anon:dalvik-thread local mark stack] -70eb750000-70eb754000 rw-p 00000000 00:05 10270944 [anon:dalvik-thread local mark stack] -70eb754000-70eb758000 rw-p 00000000 00:05 10270943 [anon:dalvik-thread local mark stack] -70eb758000-70eb75c000 rw-p 00000000 00:05 10270942 [anon:dalvik-thread local mark stack] -70eb75c000-70eb760000 rw-p 00000000 00:05 10270941 [anon:dalvik-thread local mark stack] -70eb760000-70eb764000 rw-p 00000000 00:05 10270940 [anon:dalvik-thread local mark stack] -70eb764000-70eb767000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70eb767000-70eb768000 r--p 00000000 00:00 0 [anon:linker_alloc] -70eb768000-70eb76c000 rw-p 00000000 00:05 10270939 [anon:dalvik-thread local mark stack] -70eb76c000-70eb770000 rw-p 00000000 00:05 10270938 [anon:dalvik-thread local mark stack] -70eb770000-70eb771000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70eb771000-70eb774000 r--s 00000000 fc:00 231 /system/fonts/NotoSansDeseret-Regular.ttf -70eb774000-70eb778000 rw-p 00000000 00:05 10270937 [anon:dalvik-thread local mark stack] -70eb778000-70eb77c000 rw-p 00000000 00:05 10270936 [anon:dalvik-thread local mark stack] -70eb77c000-70eb780000 rw-p 00000000 00:05 10270935 [anon:dalvik-thread local mark stack] -70eb780000-70eb784000 rw-p 00000000 00:05 10270934 [anon:dalvik-thread local mark stack] -70eb784000-70eb788000 rw-p 00000000 00:05 10270933 [anon:dalvik-thread local mark stack] -70eb788000-70eb78c000 rw-p 00000000 00:05 10270932 [anon:dalvik-thread local mark stack] -70eb78c000-70eb790000 rw-p 00000000 00:05 10270931 [anon:dalvik-thread local mark stack] -70eb790000-70eb794000 rw-p 00000000 00:05 10270930 [anon:dalvik-thread local mark stack] -70eb794000-70eb798000 rw-p 00000000 00:05 10270929 [anon:dalvik-thread local mark stack] -70eb798000-70eb79c000 rw-p 00000000 00:05 10270928 [anon:dalvik-thread local mark stack] -70eb79c000-70eb7a0000 rw-p 00000000 00:05 10270927 [anon:dalvik-thread local mark stack] -70eb7a0000-70eb7a1000 r--p 00000000 00:00 0 [anon:linker_alloc] -70eb7a1000-70eb7a3000 r--s 00000000 fc:00 176 /system/fonts/NotoSansGothic-Regular.ttf -70eb7a3000-70eb7a7000 rw-p 00000000 00:05 10270926 [anon:dalvik-thread local mark stack] -70eb7a7000-70eb7a8000 r--p 00000000 00:00 0 [anon:linker_alloc] -70eb7a8000-70eb7a9000 r--s 00000000 fc:00 1109 /system/usr/hyphen-data/hyph-gu.hyb -70eb7a9000-70eb7ad000 rw-p 00000000 00:05 10270925 [anon:dalvik-thread local mark stack] -70eb7ad000-70eb7ae000 r--p 00000000 00:00 0 [anon:linker_alloc] -70eb7ae000-70eb7af000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70eb7af000-70eb7b0000 r--p 00000000 00:00 0 [anon:linker_alloc] -70eb7b0000-70eb7b2000 r--s 00000000 fc:00 191 /system/fonts/NotoSansCypriot-Regular.ttf -70eb7b2000-70eb7b6000 rw-p 00000000 00:05 10270924 [anon:dalvik-thread local mark stack] -70eb7b6000-70eb7ba000 rw-p 00000000 00:05 10270923 [anon:dalvik-thread local mark stack] -70eb7ba000-70eb7be000 rw-p 00000000 00:05 10270922 [anon:dalvik-thread local mark stack] -70eb7be000-70eb7c2000 rw-p 00000000 00:05 10270921 [anon:dalvik-thread local mark stack] -70eb7c2000-70eb7c6000 rw-p 00000000 00:05 10270920 [anon:dalvik-thread local mark stack] -70eb7c6000-70eb7ca000 rw-p 00000000 00:05 10270919 [anon:dalvik-thread local mark stack] -70eb7ca000-70eb7ce000 rw-p 00000000 00:05 10270918 [anon:dalvik-thread local mark stack] -70eb7ce000-70eb7d2000 rw-p 00000000 00:05 10270917 [anon:dalvik-thread local mark stack] -70eb7d2000-70eb7d6000 rw-p 00000000 00:05 10270916 [anon:dalvik-thread local mark stack] -70eb7d6000-70eb7d7000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects] -70eb7d7000-70eb7db000 rw-p 00000000 00:05 10270915 [anon:dalvik-thread local mark stack] -70eb7db000-70eb7df000 rw-p 00000000 00:05 10270914 [anon:dalvik-thread local mark stack] -70eb7df000-70eb7e3000 rw-p 00000000 00:05 10270913 [anon:dalvik-thread local mark stack] -70eb7e3000-70eb7e7000 rw-p 00000000 00:05 10270912 [anon:dalvik-thread local mark stack] -70eb7e7000-70eb7e8000 r--p 00000000 00:00 0 [anon:linker_alloc] -70eb7e8000-70eb7ea000 r--s 00000000 fc:00 174 /system/fonts/NotoSansCarian-Regular.ttf -70eb7ea000-70eb7ee000 rw-p 00000000 00:05 10270911 [anon:dalvik-thread local mark stack] -70eb7ee000-70eb7f2000 rw-p 00000000 00:05 10270910 [anon:dalvik-thread local mark stack] -70eb7f2000-70eb7f6000 rw-p 00000000 00:05 10270909 [anon:dalvik-thread local mark stack] -70eb7f6000-70eb7f7000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70eb7f7000-70eb7f8000 r--s 00000000 fc:00 1096 /system/usr/hyphen-data/hyph-eu.hyb -70eb7f8000-70eb7fc000 rw-p 00000000 00:05 10270908 [anon:dalvik-thread local mark stack] -70eb7fc000-70eb800000 rw-p 00000000 00:05 10270907 [anon:dalvik-thread local mark stack] -70eb800000-70eb804000 rw-p 00000000 00:05 10270906 [anon:dalvik-thread local mark stack] -70eb804000-70eb808000 rw-p 00000000 00:05 10270905 [anon:dalvik-thread local mark stack] -70eb808000-70eb80c000 rw-p 00000000 00:05 10270904 [anon:dalvik-thread local mark stack] -70eb80c000-70eb810000 rw-p 00000000 00:05 10270903 [anon:dalvik-thread local mark stack] -70eb810000-70eb814000 rw-p 00000000 00:05 10270902 [anon:dalvik-thread local mark stack] -70eb814000-70eb815000 rw-p 00000000 00:00 0 [anon:linker_alloc_vector] -70eb815000-70eb819000 rw-p 00000000 00:05 10270901 [anon:dalvik-thread local mark stack] -70eb819000-70eb81d000 rw-p 00000000 00:05 10270900 [anon:dalvik-thread local mark stack] -70eb81d000-70eb81e000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70eb81e000-70eb822000 rw-p 00000000 00:05 10270899 [anon:dalvik-thread local mark stack] -70eb822000-70eb826000 rw-p 00000000 00:05 10270898 [anon:dalvik-thread local mark stack] -70eb826000-70eb82a000 rw-p 00000000 00:05 10270897 [anon:dalvik-thread local mark stack] -70eb82a000-70eb82e000 rw-p 00000000 00:05 10270896 [anon:dalvik-thread local mark stack] -70eb82e000-70eb832000 rw-p 00000000 00:05 10270895 [anon:dalvik-thread local mark stack] -70eb832000-70eb836000 rw-p 00000000 00:05 10270894 [anon:dalvik-thread local mark stack] -70eb836000-70eb837000 r--p 00000000 00:00 0 [anon:linker_alloc] -70eb837000-70eb83b000 rw-p 00000000 00:05 10270893 [anon:dalvik-thread local mark stack] -70eb83b000-70eb83f000 rw-p 00000000 00:05 10270892 [anon:dalvik-thread local mark stack] -70eb83f000-70eb843000 rw-p 00000000 00:05 10270891 [anon:dalvik-thread local mark stack] -70eb843000-70eb847000 rw-p 00000000 00:05 10270890 [anon:dalvik-thread local mark stack] -70eb847000-70eb84b000 rw-p 00000000 00:05 10270889 [anon:dalvik-thread local mark stack] -70eb84b000-70eb84f000 rw-p 00000000 00:05 10270888 [anon:dalvik-thread local mark stack] -70eb84f000-70eb850000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70eb850000-70eb854000 rw-p 00000000 00:05 10270887 [anon:dalvik-thread local mark stack] -70eb854000-70eb858000 rw-p 00000000 00:05 10270886 [anon:dalvik-thread local mark stack] -70eb858000-70eb85c000 rw-p 00000000 00:05 10270885 [anon:dalvik-thread local mark stack] -70eb85c000-70eb860000 rw-p 00000000 00:05 10270884 [anon:dalvik-thread local mark stack] -70eb860000-70eb864000 rw-p 00000000 00:05 10270883 [anon:dalvik-thread local mark stack] -70eb864000-70eb868000 rw-p 00000000 00:05 10270882 [anon:dalvik-thread local mark stack] -70eb868000-70eb869000 r--p 00000000 00:00 0 [anon:linker_alloc] -70eb869000-70eb86d000 rw-p 00000000 00:05 10270881 [anon:dalvik-thread local mark stack] -70eb86d000-70eb871000 rw-p 00000000 00:05 10270880 [anon:dalvik-thread local mark stack] -70eb871000-70eb875000 rw-p 00000000 00:05 10270879 [anon:dalvik-thread local mark stack] -70eb875000-70eb879000 rw-p 00000000 00:05 10270878 [anon:dalvik-thread local mark stack] -70eb879000-70eb87d000 rw-p 00000000 00:05 10270877 [anon:dalvik-thread local mark stack] -70eb87d000-70eb881000 rw-p 00000000 00:05 10270876 [anon:dalvik-thread local mark stack] -70eb881000-70eb885000 rw-p 00000000 00:05 10270875 [anon:dalvik-thread local mark stack] -70eb885000-70eb889000 rw-p 00000000 00:05 10270874 [anon:dalvik-thread local mark stack] -70eb889000-70eb88d000 rw-p 00000000 00:05 10270873 [anon:dalvik-thread local mark stack] -70eb88d000-70eb891000 rw-p 00000000 00:05 10270872 [anon:dalvik-thread local mark stack] -70eb891000-70eb892000 r--p 00000000 00:00 0 [anon:linker_alloc] -70eb892000-70eb896000 rw-p 00000000 00:05 10270871 [anon:dalvik-thread local mark stack] -70eb896000-70eb89a000 rw-p 00000000 00:05 10270870 [anon:dalvik-thread local mark stack] -70eb89a000-70eb89b000 rw-p 00000000 00:00 0 [anon:linker_alloc_vector] -70eb89b000-70eb89c000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects] -70eb89c000-70eb8a0000 rw-p 00000000 00:05 10270869 [anon:dalvik-thread local mark stack] -70eb8a0000-70eb8a4000 rw-p 00000000 00:05 10270868 [anon:dalvik-thread local mark stack] -70eb8a4000-70eb8a5000 r--p 00000000 00:00 0 [anon:atexit handlers] -70eb8a5000-70eb8a9000 rw-p 00000000 00:05 10270867 [anon:dalvik-thread local mark stack] -70eb8a9000-70eb8ad000 rw-p 00000000 00:05 10270866 [anon:dalvik-thread local mark stack] -70eb8ad000-70eb8b1000 rw-p 00000000 00:05 10270865 [anon:dalvik-thread local mark stack] -70eb8b1000-70eb8b5000 rw-p 00000000 00:05 10270864 [anon:dalvik-thread local mark stack] -70eb8b5000-70eb8b9000 rw-p 00000000 00:05 10270863 [anon:dalvik-thread local mark stack] -70eb8b9000-70eb8bd000 rw-p 00000000 00:05 10270862 [anon:dalvik-thread local mark stack] -70eb8bd000-70eb8be000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70eb8be000-70eb8c1000 r--s 00000000 fc:00 168 /system/fonts/NotoSansAvestan-Regular.ttf -70eb8c1000-70eb8c5000 rw-p 00000000 00:05 10270861 [anon:dalvik-thread local mark stack] -70eb8c5000-70eb8c9000 rw-p 00000000 00:05 10270860 [anon:dalvik-thread local mark stack] -70eb8c9000-70eb8cd000 rw-p 00000000 00:05 10270859 [anon:dalvik-thread local mark stack] -70eb8cd000-70eb8d1000 rw-p 00000000 00:05 10270858 [anon:dalvik-thread local mark stack] -70eb8d1000-70eb8d5000 rw-p 00000000 00:05 10270857 [anon:dalvik-thread local mark stack] -70eb8d5000-70eb8d7000 r--p 00000000 00:00 0 [anon:linker_alloc] -70eb8d7000-70eb8db000 rw-p 00000000 00:05 10270856 [anon:dalvik-thread local mark stack] -70eb8db000-70eb8df000 rw-p 00000000 00:05 10270855 [anon:dalvik-thread local mark stack] -70eb8df000-70eb8e3000 rw-p 00000000 00:05 10270854 [anon:dalvik-thread local mark stack] -70eb8e3000-70eb8e7000 rw-p 00000000 00:05 10270853 [anon:dalvik-thread local mark stack] -70eb8e7000-70eb8eb000 rw-p 00000000 00:05 10270852 [anon:dalvik-thread local mark stack] -70eb8eb000-70eb8ec000 r--p 00000000 00:00 0 [anon:linker_alloc] -70eb8ec000-70eb8ed000 r--s 00000000 fc:00 1099 /system/usr/hyphen-data/hyph-bn.hyb -70eb8ed000-70eb8f1000 rw-p 00000000 00:05 10270851 [anon:dalvik-thread local mark stack] -70eb8f1000-70eb8f5000 rw-p 00000000 00:05 10270850 [anon:dalvik-thread local mark stack] -70eb8f5000-70eb8f9000 rw-p 00000000 00:05 10270849 [anon:dalvik-thread local mark stack] -70eb8f9000-70eb8fd000 rw-p 00000000 00:05 10270848 [anon:dalvik-thread local mark stack] -70eb8fd000-70eb901000 rw-p 00000000 00:05 10270847 [anon:dalvik-thread local mark stack] -70eb901000-70eb905000 rw-p 00000000 00:05 10270846 [anon:dalvik-thread local mark stack] -70eb905000-70eb909000 rw-p 00000000 00:05 10270845 [anon:dalvik-thread local mark stack] -70eb909000-70eb90d000 rw-p 00000000 00:05 10270844 [anon:dalvik-thread local mark stack] -70eb90d000-70eb911000 rw-p 00000000 00:05 10270843 [anon:dalvik-thread local mark stack] -70eb911000-70eb915000 rw-p 00000000 00:05 10270842 [anon:dalvik-thread local mark stack] -70eb915000-70eb916000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70eb916000-70eb917000 r--s 00000000 fc:00 1114 /system/usr/hyphen-data/hyph-bg.hyb -70eb917000-70eb91b000 rw-p 00000000 00:05 10270841 [anon:dalvik-thread local mark stack] -70eb91b000-70eb91c000 r--p 00000000 00:00 0 [anon:linker_alloc] -70eb91c000-70eb91d000 r--s 00000000 fc:00 1133 /system/usr/hyphen-data/hyph-as.hyb -70eb91d000-70eb921000 rw-p 00000000 00:05 10270840 [anon:dalvik-thread local mark stack] -70eb921000-70eb925000 rw-p 00000000 00:05 10270839 [anon:dalvik-thread local mark stack] -70eb925000-70eb926000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects] -70eb926000-70eb927000 r--p 00000000 00:00 0 [anon:linker_alloc] -70eb927000-70eb929000 r--s 00000000 fc:00 203 /system/fonts/NotoSansBuhid-Regular.ttf -70eb929000-70eb92d000 rw-p 00000000 00:05 10270838 [anon:dalvik-thread local mark stack] -70eb92d000-70eb931000 rw-p 00000000 00:05 10270837 [anon:dalvik-thread local mark stack] -70eb931000-70eb935000 rw-p 00000000 00:05 10270836 [anon:dalvik-thread local mark stack] -70eb935000-70eb939000 rw-p 00000000 00:05 10270835 [anon:dalvik-thread local mark stack] -70eb939000-70eb93d000 rw-p 00000000 00:05 10270834 [anon:dalvik-thread local mark stack] -70eb93d000-70eb941000 rw-p 00000000 00:05 10270833 [anon:dalvik-thread local mark stack] -70eb941000-70eb945000 rw-p 00000000 00:05 10270832 [anon:dalvik-thread local mark stack] -70eb945000-70eb949000 rw-p 00000000 00:05 10270831 [anon:dalvik-thread local mark stack] -70eb949000-70eb94d000 rw-p 00000000 00:05 10270830 [anon:dalvik-thread local mark stack] -70eb94d000-70eb951000 rw-p 00000000 00:05 10270829 [anon:dalvik-thread local mark stack] -70eb951000-70eb991000 rw-p 00000000 00:05 10270722 [anon:dalvik-mark stack] -70eb991000-70eb992000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70eb992000-70eb996000 rw-p 00000000 00:05 10270828 [anon:dalvik-thread local mark stack] -70eb996000-70eb99a000 rw-p 00000000 00:05 10270827 [anon:dalvik-thread local mark stack] -70eb99a000-70eb99e000 rw-p 00000000 00:05 10270826 [anon:dalvik-thread local mark stack] -70eb99e000-70eb9a2000 rw-p 00000000 00:05 10270825 [anon:dalvik-thread local mark stack] -70eb9a2000-70eb9a4000 r--p 00000000 00:00 0 [anon:linker_alloc] -70eb9a4000-70eb9a8000 rw-p 00000000 00:05 10270824 [anon:dalvik-thread local mark stack] -70eb9a8000-70eb9ac000 rw-p 00000000 00:05 10270823 [anon:dalvik-thread local mark stack] -70eb9ac000-70eb9b0000 rw-p 00000000 00:05 10270822 [anon:dalvik-thread local mark stack] -70eb9b0000-70eb9b1000 r--p 00000000 00:00 0 [anon:linker_alloc] -70eb9b1000-70eb9b2000 r--s 00021000 fc:01 1180 /vendor/overlay/framework-res__auto_generated_rro.apk -70eb9b2000-70eb9b6000 rw-p 00000000 00:05 10270821 [anon:dalvik-thread local mark stack] -70eb9b6000-70eb9ba000 rw-p 00000000 00:05 10270820 [anon:dalvik-thread local mark stack] -70eb9ba000-70eb9be000 rw-p 00000000 00:05 10270819 [anon:dalvik-thread local mark stack] -70eb9be000-70eb9c2000 rw-p 00000000 00:05 10270818 [anon:dalvik-thread local mark stack] -70eb9c2000-70eb9c6000 rw-p 00000000 00:05 10270817 [anon:dalvik-thread local mark stack] -70eb9c6000-70eb9ca000 rw-p 00000000 00:05 10270816 [anon:dalvik-thread local mark stack] -70eb9ca000-70eb9ce000 rw-p 00000000 00:05 10270815 [anon:dalvik-thread local mark stack] -70eb9ce000-70eb9cf000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70eb9cf000-70eb9d1000 r--s 00000000 fc:00 213 /system/fonts/NotoSansBuginese-Regular.ttf -70eb9d1000-70eb9d5000 rw-p 00000000 00:05 10270814 [anon:dalvik-thread local mark stack] -70eb9d5000-70eb9d9000 rw-p 00000000 00:05 10270813 [anon:dalvik-thread local mark stack] -70eb9d9000-70eb9dd000 rw-p 00000000 00:05 10270812 [anon:dalvik-thread local mark stack] -70eb9dd000-70eb9e1000 rw-p 00000000 00:05 10270811 [anon:dalvik-thread local mark stack] -70eb9e1000-70eb9e5000 rw-p 00000000 00:05 10270810 [anon:dalvik-thread local mark stack] -70eb9e5000-70eb9e9000 rw-p 00000000 00:05 10270809 [anon:dalvik-thread local mark stack] -70eb9e9000-70eb9ed000 rw-p 00000000 00:05 10270808 [anon:dalvik-thread local mark stack] -70eb9ed000-70eb9f1000 rw-p 00000000 00:05 10270807 [anon:dalvik-thread local mark stack] -70eb9f1000-70eb9f5000 rw-p 00000000 00:05 10270806 [anon:dalvik-thread local mark stack] -70eb9f5000-70eb9f6000 r--p 00000000 00:00 0 [anon:linker_alloc] -70eb9f6000-70eb9f8000 rw-p 00000000 00:05 10271002 [anon:dalvik-indirect ref table] -70eb9f8000-70eb9fc000 rw-p 00000000 00:05 10270805 [anon:dalvik-thread local mark stack] -70eb9fc000-70eb9fd000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70eb9fd000-70eb9ff000 rw-p 00000000 00:05 10270999 [anon:dalvik-indirect ref table] -70eb9ff000-70eba00000 r--s 00000000 fc:00 983 /system/framework/com.google.vr.platform.jar -70eba00000-70eba04000 rw-p 00000000 00:05 10270804 [anon:dalvik-thread local mark stack] -70eba04000-70eba08000 rw-p 00000000 00:05 10270803 [anon:dalvik-thread local mark stack] -70eba08000-70eba0c000 rw-p 00000000 00:05 10270802 [anon:dalvik-thread local mark stack] -70eba0c000-70eba10000 rw-p 00000000 00:05 10270801 [anon:dalvik-thread local mark stack] -70eba10000-70eba14000 rw-p 00000000 00:05 10270800 [anon:dalvik-thread local mark stack] -70eba14000-70eba18000 rw-p 00000000 00:05 10270799 [anon:dalvik-thread local mark stack] -70eba18000-70eba1c000 rw-p 00000000 00:05 10270798 [anon:dalvik-thread local mark stack] -70eba1c000-70eba20000 rw-p 00000000 00:05 10270797 [anon:dalvik-thread local mark stack] -70eba20000-70eba24000 rw-p 00000000 00:05 10270796 [anon:dalvik-thread local mark stack] -70eba24000-70eba28000 rw-p 00000000 00:05 10270795 [anon:dalvik-thread local mark stack] -70eba28000-70eba2c000 rw-p 00000000 00:05 10270794 [anon:dalvik-thread local mark stack] -70eba2c000-70eba2d000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70eba2d000-70eba2e000 r--s 00000000 fc:00 881 /system/framework/android.test.base.jar -70eba2e000-70eba2f000 r--s 00000000 fc:00 707 /system/framework/framework-oahl-backward-compatibility.jar -70eba2f000-70eba30000 r--s 00000000 fc:00 705 /system/framework/android.hidl.manager-V1.0-java.jar -70eba30000-70eba34000 rw-p 00000000 00:05 10270793 [anon:dalvik-thread local mark stack] -70eba34000-70eba38000 rw-p 00000000 00:05 10270792 [anon:dalvik-thread local mark stack] -70eba38000-70eba3c000 rw-p 00000000 00:05 10270791 [anon:dalvik-thread local mark stack] -70eba3c000-70eba40000 rw-p 00000000 00:05 10270790 [anon:dalvik-thread local mark stack] -70eba40000-70eba44000 rw-p 00000000 00:05 10270789 [anon:dalvik-thread local mark stack] -70eba44000-70eba48000 rw-p 00000000 00:05 10270788 [anon:dalvik-thread local mark stack] -70eba48000-70eba4c000 rw-p 00000000 00:05 10270787 [anon:dalvik-thread local mark stack] -70eba4c000-70eba50000 rw-p 00000000 00:05 10270786 [anon:dalvik-thread local mark stack] -70eba50000-70eba52000 r--p 00000000 00:00 0 [anon:linker_alloc] -70eba52000-70eba53000 r--s 00000000 fc:00 971 /system/framework/android.hidl.base-V1.0-java.jar -70eba53000-70eba57000 rw-p 00000000 00:05 10270785 [anon:dalvik-thread local mark stack] -70eba57000-70eba5b000 rw-p 00000000 00:05 10270784 [anon:dalvik-thread local mark stack] -70eba5b000-70eba5f000 rw-p 00000000 00:05 10270783 [anon:dalvik-thread local mark stack] -70eba5f000-70eba63000 rw-p 00000000 00:05 10270782 [anon:dalvik-thread local mark stack] -70eba63000-70eba64000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70eba64000-70eba65000 r--s 00000000 fc:00 889 /system/framework/ims-common.jar -70eba65000-70eba69000 rw-p 00000000 00:05 10270781 [anon:dalvik-thread local mark stack] -70eba69000-70eba6d000 rw-p 00000000 00:05 10270780 [anon:dalvik-thread local mark stack] -70eba6d000-70eba71000 rw-p 00000000 00:05 10270779 [anon:dalvik-thread local mark stack] -70eba71000-70eba75000 rw-p 00000000 00:05 10270778 [anon:dalvik-thread local mark stack] -70eba75000-70eba95000 rw-p 00000000 00:05 10267647 [anon:dalvik-large marked objects] -70eba95000-70ebab5000 rw-p 00000000 00:05 10267646 [anon:dalvik-large live objects] -70ebab5000-70ebab6000 r--p 00000000 00:00 0 [anon:linker_alloc] -70ebab6000-70ebab7000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70ebab7000-70ebabb000 rw-p 00000000 00:05 10270777 [anon:dalvik-thread local mark stack] -70ebabb000-70ebadb000 r--s 00000000 00:10 16603 /dev/__properties__/u:object_r:exported_fingerprint_prop:s0 -70ebadb000-70ebadc000 r--p 00000000 00:00 0 [anon:linker_alloc] -70ebadc000-70ebadd000 r--s 00000000 fc:00 878 /system/framework/voip-common.jar -70ebadd000-70ebadf000 rw-p 00000000 00:05 10270995 [anon:dalvik-indirect ref table] -70ebadf000-70ebae3000 rw-p 00000000 00:05 10270776 [anon:dalvik-thread local mark stack] -70ebae3000-70ebae7000 rw-p 00000000 00:05 10270775 [anon:dalvik-thread local mark stack] -70ebae7000-70ebaeb000 rw-p 00000000 00:05 10270774 [anon:dalvik-thread local mark stack] -70ebaeb000-70ebaef000 rw-p 00000000 00:05 10270773 [anon:dalvik-thread local mark stack] -70ebaef000-70ebb0f000 r--s 00000000 00:10 16582 /dev/__properties__/u:object_r:debug_prop:s0 -70ebb0f000-70ebb10000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70ebb10000-70ebb11000 r--s 00000000 fc:00 703 /system/framework/telephony-common.jar -70ebb11000-70ebb13000 rw-p 00000000 00:05 10270994 [anon:dalvik-indirect ref table] -70ebb13000-70ebb17000 rw-p 00000000 00:05 10270772 [anon:dalvik-thread local mark stack] -70ebb17000-70ebb19000 r--p 00000000 00:00 0 [anon:linker_alloc] -70ebb19000-70ebb1d000 rw-p 00000000 00:05 10270771 [anon:dalvik-thread local mark stack] -70ebb1d000-70ebb3d000 r--s 00000000 00:10 16600 /dev/__properties__/u:object_r:exported_default_prop:s0 -70ebb3d000-70ebb5d000 r--s 00000000 00:10 16650 /dev/__properties__/u:object_r:system_prop:s0 -70ebb5d000-70ebb7d000 r--s 00000000 00:10 16610 /dev/__properties__/u:object_r:exported_vold_prop:s0 -70ebb7d000-70ebb9d000 r--s 00000000 00:10 16598 /dev/__properties__/u:object_r:exported_config_prop:s0 -70ebb9d000-70ebb9e000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70ebb9e000-70ebba2000 rw-p 00000000 00:05 10270770 [anon:dalvik-thread local mark stack] -70ebba2000-70ebba6000 rw-p 00000000 00:05 10270769 [anon:dalvik-thread local mark stack] -70ebba6000-70ebba7000 r--p 00000000 00:00 0 [anon:linker_alloc] -70ebba7000-70ebba8000 r--s 00000000 fc:00 1004 /system/framework/framework.jar -70ebba8000-70ebbac000 rw-p 00000000 00:05 10270768 [anon:dalvik-thread local mark stack] -70ebbac000-70ebbb0000 rw-p 00000000 00:05 10270767 [anon:dalvik-thread local mark stack] -70ebbb0000-70ebbb4000 rw-p 00000000 00:05 10270766 [anon:dalvik-thread local mark stack] -70ebbb4000-70ebbb8000 rw-p 00000000 00:05 10270765 [anon:dalvik-thread local mark stack] -70ebbb8000-70ebbbc000 rw-p 00000000 00:05 10270764 [anon:dalvik-thread local mark stack] -70ebbbc000-70ebbc0000 rw-p 00000000 00:05 10270763 [anon:dalvik-thread local mark stack] -70ebbc0000-70ebbc4000 rw-p 00000000 00:05 10270762 [anon:dalvik-thread local mark stack] -70ebbc4000-70ebbe4000 r--s 00000000 00:10 16581 /dev/__properties__/u:object_r:dalvik_prop:s0 -70ebbe4000-70ebbe5000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70ebbe5000-70ebbe6000 r--s 00004000 fc:00 877 /system/framework/apache-xml.jar -70ebbe6000-70ebbe8000 rw-p 00000000 00:05 10270993 [anon:dalvik-indirect ref table] -70ebbe8000-70ebbec000 rw-p 00000000 00:05 10270761 [anon:dalvik-thread local mark stack] -70ebbec000-70ebbf0000 rw-p 00000000 00:05 10270760 [anon:dalvik-thread local mark stack] -70ebbf0000-70ebbf4000 rw-p 00000000 00:05 10270759 [anon:dalvik-thread local mark stack] -70ebbf4000-70ebbf8000 rw-p 00000000 00:05 10270758 [anon:dalvik-thread local mark stack] -70ebbf8000-70ebbf9000 r--p 00000000 00:00 0 [anon:linker_alloc] -70ebbf9000-70ebbfa000 r--s 00000000 fc:00 968 /system/framework/bouncycastle.jar -70ebbfa000-70ebbfc000 rw-p 00000000 00:05 10270992 [anon:dalvik-indirect ref table] -70ebbfc000-70ebc00000 rw-p 00000000 00:05 10270757 [anon:dalvik-thread local mark stack] -70ebc00000-70ebc04000 rw-p 00000000 00:05 10270756 [anon:dalvik-thread local mark stack] -70ebc04000-70ebc08000 rw-p 00000000 00:05 10270755 [anon:dalvik-thread local mark stack] -70ebc08000-70ebc0c000 rw-p 00000000 00:05 10270754 [anon:dalvik-thread local mark stack] -70ebc0c000-70ebc10000 rw-p 00000000 00:05 10270753 [anon:dalvik-thread local mark stack] -70ebc10000-70ebc14000 rw-p 00000000 00:05 10270752 [anon:dalvik-thread local mark stack] -70ebc14000-70ebc15000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70ebc15000-70ebc16000 r--s 00000000 fc:00 960 /system/framework/okhttp.jar -70ebc16000-70ebc1a000 rw-p 00000000 00:05 10270751 [anon:dalvik-thread local mark stack] -70ebc1a000-70ebc1e000 rw-p 00000000 00:05 10270750 [anon:dalvik-thread local mark stack] -70ebc1e000-70ebc3e000 r--s 00000000 00:10 16584 /dev/__properties__/u:object_r:default_prop:s0 -70ebc3e000-70ebc3f000 r--p 00000000 00:00 0 [anon:linker_alloc] -70ebc3f000-70ebc40000 r--s 00000000 fc:00 974 /system/framework/conscrypt.jar -70ebc40000-70ebc42000 rw-p 00000000 00:05 10269719 [anon:dalvik-indirect ref table] -70ebc42000-70ebc46000 rw-p 00000000 00:05 10270749 [anon:dalvik-thread local mark stack] -70ebc46000-70ebc4a000 rw-p 00000000 00:05 10270748 [anon:dalvik-thread local mark stack] -70ebc4a000-70ebc4e000 rw-p 00000000 00:05 10270747 [anon:dalvik-thread local mark stack] -70ebc4e000-70ebc4f000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70ebc4f000-70ebc51000 rw-p 00000000 00:05 10269718 [anon:dalvik-indirect ref table] -70ebc51000-70ebc55000 rw-p 00000000 00:05 10270746 [anon:dalvik-thread local mark stack] -70ebc55000-70ebc59000 rw-p 00000000 00:05 10270745 [anon:dalvik-thread local mark stack] -70ebc59000-70ebc5d000 rw-p 00000000 00:05 10270744 [anon:dalvik-thread local mark stack] -70ebc5d000-70ebc7d000 r--s 00000000 00:10 16599 /dev/__properties__/u:object_r:exported_dalvik_prop:s0 -70ebc7d000-70ebc7e000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70ebc7e000-70ebc7f000 r--p 00000000 00:00 0 [anon:linker_alloc] -70ebc7f000-70ebc80000 r--s 00004000 fc:00 963 /system/framework/core-libart.jar -70ebc80000-70ebc81000 r--p 00000000 00:00 0 [anon:linker_alloc] -70ebc81000-70ebc85000 rw-p 00000000 00:05 10270743 [anon:dalvik-thread local mark stack] -70ebc85000-70ebc89000 rw-p 00000000 00:05 10270742 [anon:dalvik-thread local mark stack] -70ebc89000-70ebc8a000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects] -70ebc8a000-70ebc8c000 r--p 00000000 00:00 0 [anon:linker_alloc] -70ebc8c000-70ebc8d000 r--s 0001e000 fc:00 699 /system/framework/core-oj.jar -70ebc8d000-70ebc91000 rw-p 00000000 00:05 10270741 [anon:dalvik-thread local mark stack] -70ebc91000-70ebc95000 rw-p 00000000 00:05 10270740 [anon:dalvik-thread local mark stack] -70ebc95000-70ebc99000 rw-p 00000000 00:05 10270739 [anon:dalvik-thread local mark stack] -70ebc99000-70ebc9b000 r--p 00000000 00:00 0 [anon:linker_alloc] -70ebc9b000-70ebc9c000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70ebc9c000-70ebca0000 rw-p 00000000 00:05 10270738 [anon:dalvik-thread local mark stack] -70ebca0000-70ebca4000 rw-p 00000000 00:05 10270737 [anon:dalvik-thread local mark stack] -70ebca4000-70ebca8000 rw-p 00000000 00:05 10270736 [anon:dalvik-thread local mark stack] -70ebca8000-70ebcac000 rw-p 00000000 00:05 10270735 [anon:dalvik-thread local mark stack] -70ebcac000-70ebcb0000 rw-p 00000000 00:05 10270734 [anon:dalvik-thread local mark stack] -70ebcb0000-70ebcd0000 r--s 00000000 00:10 16592 /dev/__properties__/u:object_r:exported2_system_prop:s0 -70ebcd0000-70ebcd1000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70ebcd1000-70ebcd5000 rw-p 00000000 00:05 10270733 [anon:dalvik-thread local mark stack] -70ebcd5000-70ebcd9000 rw-p 00000000 00:05 10270732 [anon:dalvik-thread local mark stack] -70ebcd9000-70ebcdd000 rw-p 00000000 00:05 10270731 [anon:dalvik-thread local mark stack] -70ebcdd000-70ebce1000 rw-p 00000000 00:05 10270730 [anon:dalvik-thread local mark stack] -70ebce1000-70ebce5000 rw-p 00000000 00:05 10270729 [anon:dalvik-thread local mark stack] -70ebce5000-70ebce9000 rw-p 00000000 00:05 10270728 [anon:dalvik-thread local mark stack] -70ebce9000-70ebcea000 r--p 00000000 00:00 0 [anon:linker_alloc] -70ebcea000-70ebcec000 rw-p 00000000 00:05 10270987 [anon:dalvik-indirect ref table] -70ebcec000-70ebcf9000 r--p 00646000 103:1d 639532 /data/dalvik-cache/arm64/system@framework@boot-framework.art -70ebcf9000-70ebd19000 r--s 00000000 00:10 16620 /dev/__properties__/u:object_r:log_tag_prop:s0 -70ebd19000-70ebd39000 r--s 00000000 00:10 16621 /dev/__properties__/u:object_r:logd_prop:s0 -70ebd39000-70ebd3a000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70ebd3a000-70ebd3b000 r--p 00000000 00:00 0 [anon:linker_alloc] -70ebd3b000-70ebd3f000 rw-p 00000000 00:05 10270727 [anon:dalvik-thread local mark stack] -70ebd3f000-70ebd40000 r--p 00002000 103:1d 639556 /data/dalvik-cache/arm64/system@framework@boot-com.google.vr.platform.art -70ebd40000-70ebd41000 r--p 00005000 103:1d 639553 /data/dalvik-cache/arm64/system@framework@boot-android.test.base.art -70ebd41000-70ebd42000 r--p 00000000 00:00 0 [anon:linker_alloc] -70ebd42000-70ebd43000 r--p 00001000 103:1d 639550 /data/dalvik-cache/arm64/system@framework@boot-framework-oahl-backward-compatibility.art -70ebd43000-70ebd44000 r--p 00005000 103:1d 639547 /data/dalvik-cache/arm64/system@framework@boot-android.hidl.manager-V1.0-java.art -70ebd44000-70ebd45000 r--p 00003000 103:1d 639544 /data/dalvik-cache/arm64/system@framework@boot-android.hidl.base-V1.0-java.art -70ebd45000-70ebd46000 r--p 00000000 00:00 0 [anon:linker_alloc] -70ebd46000-70ebd47000 r--p 0000f000 103:1d 639541 /data/dalvik-cache/arm64/system@framework@boot-ims-common.art -70ebd47000-70ebd48000 r--p 0000d000 103:1d 639538 /data/dalvik-cache/arm64/system@framework@boot-voip-common.art -70ebd48000-70ebd4a000 r--p 0005e000 103:1d 639535 /data/dalvik-cache/arm64/system@framework@boot-telephony-common.art -70ebd4a000-70ebd4b000 r--p 00040000 103:1d 639529 /data/dalvik-cache/arm64/system@framework@boot-ext.art -70ebd4b000-70ebd4c000 r--p 0004a000 103:1d 639526 /data/dalvik-cache/arm64/system@framework@boot-apache-xml.art -70ebd4c000-70ebd4d000 r--p 00046000 103:1d 639523 /data/dalvik-cache/arm64/system@framework@boot-bouncycastle.art -70ebd4d000-70ebd4e000 r--p 00000000 00:00 0 [anon:linker_alloc] -70ebd4e000-70ebd53000 r--p 00225000 103:1d 639511 /data/dalvik-cache/arm64/system@framework@boot.art -70ebd53000-70ebd5a000 rw-p 00000000 fc:00 583 /system/etc/event-log-tags -70ebd5a000-70ebd5b000 r--p 00000000 00:00 0 [anon:linker_alloc] -70ebd5b000-70ebd5c000 r--p 0002e000 103:1d 639520 /data/dalvik-cache/arm64/system@framework@boot-okhttp.art -70ebd5c000-70ebd5d000 r--p 00035000 103:1d 639517 /data/dalvik-cache/arm64/system@framework@boot-conscrypt.art -70ebd5d000-70ebd5f000 r--p 000d0000 103:1d 639514 /data/dalvik-cache/arm64/system@framework@boot-core-libart.art -70ebd5f000-70ebd62000 r--p 00000000 00:00 0 [anon:atexit handlers] -70ebd62000-70ebd63000 rw-p 00000000 00:00 0 -70ebd63000-70ebd83000 r--s 00000000 00:10 16590 /dev/__properties__/u:object_r:exported2_default_prop:s0 -70ebd83000-70ebd84000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70ebd84000-70ebd89000 rw-p 00000000 00:00 0 -70ebd89000-70ebda9000 r--s 00000000 00:10 16669 /dev/__properties__/properties_serial -70ebda9000-70ebdb3000 r--s 00000000 00:10 16560 /dev/__properties__/property_info -70ebdb3000-70ebdb4000 rw-p 00000000 00:00 0 [anon:linker_alloc_vector] -70ebdb4000-70ebdb5000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects] -70ebdb5000-70ebdb7000 rw-p 00000000 00:00 0 [anon:System property context nodes] -70ebdb7000-70ebdb8000 rw-p 00000000 00:00 0 [anon:linker_alloc_vector] -70ebdb8000-70ebdba000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects] -70ebdba000-70ebdbb000 rw-p 00000000 00:00 0 [anon:linker_alloc] -70ebdbb000-70ebdbd000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects] -70ebdbd000-70ebdbe000 r--p 00000000 00:00 0 [anon:atexit handlers] -70ebdbe000-70ebdbf000 r--p 00000000 00:00 0 [anon:linker_alloc] -70ebdbf000-70ebdc0000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects] -70ebdc0000-70ebdc1000 rw-p 00000000 00:00 0 [anon:linker_alloc_vector] -70ebdc1000-70ebdc2000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects] -70ebdc2000-70ebdc3000 rw-p 00000000 00:00 0 [anon:linker_alloc_vector] -70ebdc3000-70ebdc5000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects] -70ebdc5000-70ebde5000 r--s 00000000 00:10 16600 /dev/__properties__/u:object_r:exported_default_prop:s0 -70ebde5000-70ebde6000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects] -70ebde6000-70ebde8000 r--p 00000000 00:00 0 [anon:linker_alloc] -70ebde8000-70ebe08000 r--s 00000000 00:10 16582 /dev/__properties__/u:object_r:debug_prop:s0 -70ebe08000-70ebe09000 ---p 00000000 00:00 0 -70ebe09000-70ebe0a000 rw-p 00000000 00:00 0 -70ebe0a000-70ebe0b000 ---p 00000000 00:00 0 -70ebe0b000-70ebe2b000 r--s 00000000 00:10 16669 /dev/__properties__/properties_serial -70ebe2b000-70ebe2d000 rw-p 00000000 00:00 0 [anon:System property context nodes] -70ebe2d000-70ebf55000 r-xp 00000000 fc:00 3184 /system/bin/linker64 -70ebf55000-70ebf5f000 r--s 00000000 00:10 16560 /dev/__properties__/property_info -70ebf5f000-70ebf60000 r--p 00000000 00:00 0 [anon:linker_alloc] -70ebf60000-70ebf61000 rw-p 00000000 00:00 0 [anon:linker_alloc_vector] -70ebf61000-70ebf62000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects] -70ebf62000-70ebf63000 rw-p 00000000 00:00 0 [anon:arc4random data] -70ebf63000-70ebf64000 rw-p 00000000 00:00 0 [anon:linker_alloc_small_objects] -70ebf64000-70ebf65000 r--p 00000000 00:00 0 [anon:atexit handlers] -70ebf65000-70ebf66000 ---p 00000000 00:00 0 [anon:thread signal stack guard] -70ebf66000-70ebf6a000 rw-p 00000000 00:00 0 [anon:thread signal stack] -70ebf6a000-70ebf6b000 rw-p 00000000 00:00 0 [anon:arc4random data] -70ebf6b000-70ebf6c000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70ebf6c000-70ebf6f000 rw-p 00000000 00:00 0 [anon:bionic TLS] -70ebf6f000-70ebf70000 ---p 00000000 00:00 0 [anon:bionic TLS guard] -70ebf70000-70ebf71000 r--p 00000000 00:00 0 [vvar] -70ebf71000-70ebf72000 r-xp 00000000 00:00 0 [vdso] -70ebf72000-70ebf7d000 r--p 00135000 fc:00 3184 /system/bin/linker64 -70ebf7d000-70ebf7e000 rw-p 00140000 fc:00 3184 /system/bin/linker64 -70ebf7e000-70ebf81000 rw-p 00000000 00:00 0 -70ebf81000-70ebf82000 r--p 00000000 00:00 0 -70ebf82000-70ebf89000 rw-p 00000000 00:00 0 -7fc7df1000-7fc7df2000 ---p 00000000 00:00 0 -7fc7df2000-7fc85f1000 rw-p 00000000 00:00 0 [stack] diff --git a/libunwindstack b/libunwindstack new file mode 120000 index 000000000..9a1240379 --- /dev/null +++ b/libunwindstack @@ -0,0 +1 @@ +../unwinding/libunwindstack \ No newline at end of file diff --git a/libunwindstack/.clang-format b/libunwindstack/.clang-format deleted file mode 120000 index fd0645fdf..000000000 --- a/libunwindstack/.clang-format +++ /dev/null @@ -1 +0,0 @@ -../.clang-format-2 \ No newline at end of file diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp deleted file mode 100644 index 8ea286eab..000000000 --- a/libunwindstack/Android.bp +++ /dev/null @@ -1,496 +0,0 @@ -// -// Copyright (C) 2017 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. -// - -cc_defaults { - name: "libunwindstack_flags", - - host_supported: true, - - cflags: [ - "-Wall", - "-Werror", - "-Wextra", - ], - - target: { - darwin: { - enabled: false, - }, - linux_bionic: { - enabled: true, - }, - }, -} - -cc_defaults { - name: "libunwindstack_defaults", - defaults: ["libunwindstack_flags"], - export_include_dirs: ["include"], - - srcs: [ - "ArmExidx.cpp", - "DexFiles.cpp", - "DwarfCfa.cpp", - "DwarfEhFrameWithHdr.cpp", - "DwarfMemory.cpp", - "DwarfOp.cpp", - "DwarfSection.cpp", - "Elf.cpp", - "ElfInterface.cpp", - "ElfInterfaceArm.cpp", - "Global.cpp", - "JitDebug.cpp", - "Log.cpp", - "MapInfo.cpp", - "Maps.cpp", - "Memory.cpp", - "MemoryMte.cpp", - "LocalUnwinder.cpp", - "Regs.cpp", - "RegsArm.cpp", - "RegsArm64.cpp", - "RegsX86.cpp", - "RegsX86_64.cpp", - "RegsMips.cpp", - "RegsMips64.cpp", - "Unwinder.cpp", - "Symbols.cpp", - ], - - cflags: [ - "-Wexit-time-destructors", - ], - - target: { - host: { - // Always disable optimizations for host to make it easier to debug. - cflags: [ - "-O0", - "-g", - ], - }, - android: { - header_libs: ["bionic_libc_platform_headers"], - product_variables: { - experimental_mte: { - cflags: ["-DANDROID_EXPERIMENTAL_MTE"], - }, - }, - }, - linux_bionic: { - header_libs: ["bionic_libc_platform_headers"], - product_variables: { - experimental_mte: { - cflags: ["-DANDROID_EXPERIMENTAL_MTE"], - }, - }, - }, - }, - - arch: { - x86: { - srcs: ["AsmGetRegsX86.S"], - }, - x86_64: { - srcs: ["AsmGetRegsX86_64.S"], - }, - }, - - static_libs: [ - "libprocinfo", - ], - - shared_libs: [ - "libbase", - "liblog", - "liblzma", - ], -} - -cc_library { - name: "libunwindstack", - vendor_available: true, - recovery_available: true, - // TODO(b/153609531): remove when no longer needed. - native_bridge_supported: true, - vndk: { - enabled: true, - support_system_process: true, - }, - defaults: ["libunwindstack_defaults"], - srcs: ["DexFile.cpp"], - cflags: ["-DDEXFILE_SUPPORT"], - shared_libs: ["libdexfile_support"], - - target: { - vendor: { - cflags: ["-UDEXFILE_SUPPORT"], - exclude_srcs: ["DexFile.cpp"], - exclude_shared_libs: ["libdexfile_support"], - }, - recovery: { - cflags: ["-UDEXFILE_SUPPORT"], - exclude_srcs: ["DexFile.cpp"], - exclude_shared_libs: ["libdexfile_support"], - }, - native_bridge: { - cflags: ["-UDEXFILE_SUPPORT"], - exclude_srcs: ["DexFile.cpp"], - exclude_shared_libs: ["libdexfile_support"], - }, - }, - - apex_available: [ - "//apex_available:platform", - "com.android.art.debug", - "com.android.art.release", - ], -} - -// Static library without DEX support to avoid dependencies on the ART APEX. -cc_library_static { - name: "libunwindstack_no_dex", - recovery_available: true, - defaults: ["libunwindstack_defaults"], - - visibility: [ - "//external/gwp_asan", - "//system/core/debuggerd", - "//system/core/init", - "//system/core/libbacktrace", - // Temporary add the new path in preparation for migration. - "//system/unwinding/libbacktrace", - ], - apex_available: [ - "//apex_available:platform", - "com.android.runtime", - ], -} - -//------------------------------------------------------------------------- -// Unit Tests -//------------------------------------------------------------------------- -cc_test_library { - name: "libunwindstack_local", - defaults: ["libunwindstack_flags"], - srcs: ["tests/TestLocal.cpp"], - - cflags: [ - "-O0", - "-g", - ], - - shared_libs: [ - "libunwindstack", - ], - relative_install_path: "libunwindstack_test", -} - -cc_defaults { - name: "libunwindstack_testlib_flags", - defaults: ["libunwindstack_flags"], - - srcs: [ - "tests/ArmExidxDecodeTest.cpp", - "tests/ArmExidxExtractTest.cpp", - "tests/DexFileTest.cpp", - "tests/DexFilesTest.cpp", - "tests/DwarfCfaLogTest.cpp", - "tests/DwarfCfaTest.cpp", - "tests/DwarfDebugFrameTest.cpp", - "tests/DwarfEhFrameTest.cpp", - "tests/DwarfEhFrameWithHdrTest.cpp", - "tests/DwarfMemoryTest.cpp", - "tests/DwarfOpLogTest.cpp", - "tests/DwarfOpTest.cpp", - "tests/DwarfSectionTest.cpp", - "tests/DwarfSectionImplTest.cpp", - "tests/ElfCacheTest.cpp", - "tests/ElfFake.cpp", - "tests/ElfInterfaceArmTest.cpp", - "tests/ElfInterfaceTest.cpp", - "tests/ElfTest.cpp", - "tests/ElfTestUtils.cpp", - "tests/IsolatedSettings.cpp", - "tests/JitDebugTest.cpp", - "tests/LocalUpdatableMapsTest.cpp", - "tests/LogFake.cpp", - "tests/MapInfoCreateMemoryTest.cpp", - "tests/MapInfoGetBuildIDTest.cpp", - "tests/MapInfoGetElfTest.cpp", - "tests/MapInfoGetLoadBiasTest.cpp", - "tests/MapInfoTest.cpp", - "tests/MapsTest.cpp", - "tests/MemoryBufferTest.cpp", - "tests/MemoryCacheTest.cpp", - "tests/MemoryFake.cpp", - "tests/MemoryFileTest.cpp", - "tests/MemoryLocalTest.cpp", - "tests/MemoryOfflineBufferTest.cpp", - "tests/MemoryOfflineTest.cpp", - "tests/MemoryRangeTest.cpp", - "tests/MemoryRangesTest.cpp", - "tests/MemoryRemoteTest.cpp", - "tests/MemoryTest.cpp", - "tests/MemoryMteTest.cpp", - "tests/RegsInfoTest.cpp", - "tests/RegsIterateTest.cpp", - "tests/RegsStepIfSignalHandlerTest.cpp", - "tests/RegsTest.cpp", - "tests/SymbolsTest.cpp", - "tests/TestUtils.cpp", - "tests/UnwindOfflineTest.cpp", - "tests/UnwindTest.cpp", - "tests/UnwinderTest.cpp", - "tests/VerifyBionicTerminationTest.cpp", - ], - - cflags: [ - "-O0", - "-g", - ], - - shared_libs: [ - "libbase", - "liblog", - "liblzma", - "libunwindstack", - "libdexfile_support", - ], - - static_libs: [ - "libgmock", - ], - - test_suites: ["device-tests"], - data: [ - "tests/files/elf32.xz", - "tests/files/elf64.xz", - "tests/files/offline/art_quick_osr_stub_arm/*", - "tests/files/offline/bad_eh_frame_hdr_arm64/*", - "tests/files/offline/debug_frame_first_x86/*", - "tests/files/offline/debug_frame_load_bias_arm/*", - "tests/files/offline/eh_frame_bias_x86/*", - "tests/files/offline/eh_frame_hdr_begin_x86_64/*", - "tests/files/offline/empty_arm64/*", - "tests/files/offline/invalid_elf_offset_arm/*", - "tests/files/offline/jit_debug_arm/*", - "tests/files/offline/jit_debug_x86/*", - "tests/files/offline/jit_map_arm/*", - "tests/files/offline/gnu_debugdata_arm/*", - "tests/files/offline/load_bias_different_section_bias_arm64/*", - "tests/files/offline/load_bias_ro_rx_x86_64/*", - "tests/files/offline/offset_arm/*", - "tests/files/offline/shared_lib_in_apk_arm64/*", - "tests/files/offline/shared_lib_in_apk_memory_only_arm64/*", - "tests/files/offline/shared_lib_in_apk_single_map_arm64/*", - "tests/files/offline/signal_load_bias_arm/*", - "tests/files/offline/signal_fde_x86/*", - "tests/files/offline/signal_fde_x86_64/*", - "tests/files/offline/straddle_arm/*", - "tests/files/offline/straddle_arm64/*", - ], - - target: { - android: { - header_libs: ["bionic_libc_platform_headers"], - product_variables: { - experimental_mte: { - cflags: ["-DANDROID_EXPERIMENTAL_MTE"], - }, - }, - }, - linux_bionic: { - header_libs: ["bionic_libc_platform_headers"], - product_variables: { - experimental_mte: { - cflags: ["-DANDROID_EXPERIMENTAL_MTE"], - }, - }, - }, - }, -} - -cc_test { - name: "libunwindstack_test", - defaults: ["libunwindstack_testlib_flags"], - isolated: true, - - srcs: [ - "tests/LocalUnwinderTest.cpp", - ], - required: [ - "libunwindstack_local", - ], -} - -// Skip LocalUnwinderTest until atest understands required properly. -cc_test { - name: "libunwindstack_unit_test", - defaults: ["libunwindstack_testlib_flags"], - isolated: true, -} - -//------------------------------------------------------------------------- -// Fuzzers -//------------------------------------------------------------------------- -cc_defaults { - name: "libunwindstack_fuzz_defaults", - host_supported: true, - defaults: ["libunwindstack_flags"], - cflags: [ - "-Wno-exit-time-destructors", - "-g", - ], - shared_libs: [ - "libbase", - "liblog", - "liblzma", - "libunwindstack", - "libdexfile_support", - ], -} - -cc_fuzz { - name: "libunwindstack_fuzz_unwinder", - defaults: ["libunwindstack_fuzz_defaults"], - srcs: [ - "tests/MemoryFake.cpp", - "tests/ElfFake.cpp", - "tests/fuzz/UnwinderComponentCreator.cpp", - "tests/fuzz/UnwinderFuzz.cpp", - ], -} - -//------------------------------------------------------------------------- -// Tools -//------------------------------------------------------------------------- -cc_defaults { - name: "libunwindstack_tools", - defaults: ["libunwindstack_flags"], - - shared_libs: [ - "libunwindstack", - "libbase", - "liblzma", - ], - target: { - // Always disable optimizations for host to make it easier to debug. - host: { - cflags: [ - "-O0", - "-g", - ], - }, - }, -} - -cc_binary { - name: "unwind", - defaults: ["libunwindstack_tools"], - - srcs: [ - "tools/unwind.cpp", - ], -} - -cc_binary { - name: "unwind_info", - defaults: ["libunwindstack_tools"], - - srcs: [ - "tools/unwind_info.cpp", - ], -} - -cc_binary { - name: "unwind_symbols", - defaults: ["libunwindstack_tools"], - - srcs: [ - "tools/unwind_symbols.cpp", - ], -} - -cc_binary { - name: "unwind_for_offline", - defaults: ["libunwindstack_tools"], - - srcs: [ - "tools/unwind_for_offline.cpp", - ], -} - -cc_binary { - name: "unwind_reg_info", - defaults: ["libunwindstack_tools"], - - srcs: [ - "tools/unwind_reg_info.cpp", - ], -} - -//------------------------------------------------------------------------- -// Benchmarks -//------------------------------------------------------------------------- -cc_benchmark { - name: "unwind_benchmarks", - host_supported: true, - defaults: ["libunwindstack_flags"], - - // Disable optimizations so that all of the calls are not optimized away. - cflags: [ - "-O0", - ], - - srcs: [ - "benchmarks/unwind_benchmarks.cpp", - "benchmarks/ElfBenchmark.cpp", - "benchmarks/MapsBenchmark.cpp", - "benchmarks/SymbolBenchmark.cpp", - "benchmarks/Utils.cpp", - ], - - data: [ - "benchmarks/files/*", - ], - - shared_libs: [ - "libbase", - "libunwindstack", - ], - - target: { - android: { - static_libs: [ - "libmeminfo", - "libprocinfo", - ], - }, - }, -} - -// Generates the elf data for use in the tests for .gnu_debugdata frames. -// Once these files are generated, use the xz command to compress the data. -cc_binary_host { - name: "gen_gnudebugdata", - defaults: ["libunwindstack_flags"], - - srcs: [ - "tests/GenGnuDebugdata.cpp", - ], -} - diff --git a/libunwindstack/AndroidVersions.md b/libunwindstack/AndroidVersions.md deleted file mode 100644 index 234f6391b..000000000 --- a/libunwindstack/AndroidVersions.md +++ /dev/null @@ -1,116 +0,0 @@ -# Unwinder Support Per Android Release -This document describes the changes in the way the libunwindstack -unwinder works on different Android versions. It does not describe -every change in the code made between different versions, but is -meant to allow an app developer to know what might be supported -on different versions. It also describes the different way an unwind -will display on different versions of Android. - -## Android P -libunwindstack was first introduced in Android P. - -* Supports up to and including Dwarf 4 unwinding information. - See http://dwarfstd.org/ for Dwarf standards. -* Supports Arm exidx unwinding. -* Supports the gdb JIT unwinding interface, which is how ART creates unwinding - information for the JIT'd Java frames. -* Supports special frames added to represent an ART Java interpreter frame. - ART has marked the dex pc using cfi information that the unwinder - understands and handles by adding a new frame in the stacktrace. - -## Note -By default, lld creates two separate maps of the elf in memory, one read-only -and one read/executable. The libunwindstack on P and the unwinder on older -versions of Android will not unwind properly in this case. For apps that -target Android P or older, make sure that `-Wl,--no-rosegment` is -included in linker arguments when using lld. - -## Android Q -* Fix bug (b/109824792) that handled load bias data incorrectly when - FDEs use pc relative addressing in the eh\_frame\_hdr. - Unfortunately, this wasn't fixed correctly in Q since it assumes - that the bias is coming from the program header for the executable - load. The real fix was to use the bias from the actual section data and - is not completely fixed until Android R. For apps targeting Android Q, - if it is being compiled with the llvm linker lld, it might be necessary - to add the linker option `-Wl,-zseparate-code` to avoid creating an elf - created this way. -* Change the way the exidx section offset is found (b/110704153). Before - the p\_vaddr value from the program header minus the load bias was used - to find the start of the exidx data. Changed to use the p\_offset since - it doesn't require any load bias manipulations. -* Fix bug handling of dwarf sections without any header (b/110235461). - Previously, the code assumed that FDEs are non-overlapping, and the FDEs - are always in sorted order from low pc to high pc. Thus the code would - read the entire set of CIEs/FDEs and then do a binary search to find - the appropriate FDE for a given pc. Now the code does a sequential read - and stops when it finds the FDE for a pc. It also understands the - overlapping FDEs, so find the first FDE that matches a pc. In practice, - elf files with this format only ever occurs if the file was generated - without an eh\_frame/eh\_frame\_hdr section and only a debug\_frame. The - other way this has been observed is when running simpleperf to unwind since - sometimes there is not enough information in the eh\_frame for all points - in the executable. On Android P, this would result in some incorrect - unwinds coming from simpleperf. Nearly all crashes from Android P should - be correct since the eh\_frame information was enough to do the unwind - properly. -* Be permissive of badly formed elf files. Previously, any detected error - would result in unwinds stopping even if there is enough valid information - to do an unwind. - * The code now allows program header/section header offsets to point - to unreadable memory. As long as the code can find the unwind tables, - that is good enough. - * The code allows program headers/section headers to be missing. - * Allow a symbol table section header to point to invalid symbol table - values. -* Support for the linker read-only segment option (b/109657296). - This is a feature of lld whereby there are two sections that - contain elf data. The first is read-only and contains the elf header data, - and the second is read-execute or execute only that - contains the executable code from the elf. Before this, the unwinder - always assumed that there was only a single read-execute section that - contained the elf header data and the executable code. -* Build ID information for elf objects added. This will display the - NT\_GNU\_BUILD\_ID note found in elf files. This information can be used - to identify the exact version of a shared library to help get symbol - information when looking at a crash. -* Add support for displaying the soname from an apk frame. Previously, - a frame map name would be only the apk, but now if the shared library - in the apk has set a soname, the map name will be `app.apk!libexample.so` - instead of only `app.apk`. -* Minimal support for Dwarf 5. This merely treats a Dwarf 5 version - elf file as Dwarf 4. It does not support the new dwarf ops in Dwarf 5. - Since the new ops are not likely to be used very often, this allows - continuing to unwind even when encountering Dwarf 5 elf files. -* Fix bug in pc handling of signal frames (b/130302288). In the previous - version, the pc would be wrong in the signal frame. The rest of the - unwind was correct, only the frame in the signal handler was incorrect - in Android P. -* Detect when an elf file is not readable so that a message can be - displayed indicating that. This can happen when an app puts the shared - libraries in non-standard locations that are not readable due to - security restrictions (selinux rules). - -## Android R -* Display the offsets for Java interpreter frames. If this frame came - from a non-zero offset map, no offset is printed. Previously, the - line would look like: - - #17 pc 00500d7a GoogleCamera.apk (com.google.camera.AndroidPriorityThread.run+10) - - to: - - #17 pc 00500d7a GoogleCamera.apk (offset 0x11d0000) (com.google.camera.AndroidPriorityThread.run+10) -* Fix bug where the load bias was set from the first PT\_LOAD program - header that has a zero p\_offset value. Now it is set from the first - executable PT\_LOAD program header. This has only ever been a problem - for host executables compiled for the x86\_64 architecture. -* Switched to the libc++ demangler for function names. Previously, the - demangler used was not complete, so some less common demangled function - names would not be properly demangled or the function name would not be - demangled at all. -* Fix bug in load bias handling. If the unwind information in the eh\_frame - or eh\_frame\_hdr does not have the same bias as the executable section, - and uses pc relative FDEs, the unwind will be incorrect. This tends - to truncate unwinds since the unwinder could not find the correct unwind - information for a given pc. diff --git a/libunwindstack/ArmExidx.cpp b/libunwindstack/ArmExidx.cpp deleted file mode 100644 index 818f5d16a..000000000 --- a/libunwindstack/ArmExidx.cpp +++ /dev/null @@ -1,862 +0,0 @@ -/* - * Copyright (C) 2016 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 "ArmExidx.h" -#include "Check.h" - -namespace unwindstack { - -static constexpr uint8_t LOG_CFA_REG = 64; - -void ArmExidx::LogRawData() { - std::string log_str("Raw Data:"); - for (const uint8_t data : data_) { - log_str += android::base::StringPrintf(" 0x%02x", data); - } - log(log_indent_, log_str.c_str()); -} - -bool ArmExidx::ExtractEntryData(uint32_t entry_offset) { - data_.clear(); - status_ = ARM_STATUS_NONE; - - if (entry_offset & 1) { - // The offset needs to be at least two byte aligned. - status_ = ARM_STATUS_INVALID_ALIGNMENT; - return false; - } - - // Each entry is a 32 bit prel31 offset followed by 32 bits - // of unwind information. If bit 31 of the unwind data is zero, - // then this is a prel31 offset to the start of the unwind data. - // If the unwind data is 1, then this is a cant unwind entry. - // Otherwise, this data is the compact form of the unwind information. - uint32_t data; - if (!elf_memory_->Read32(entry_offset + 4, &data)) { - status_ = ARM_STATUS_READ_FAILED; - status_address_ = entry_offset + 4; - return false; - } - if (data == 1) { - // This is a CANT UNWIND entry. - status_ = ARM_STATUS_NO_UNWIND; - if (log_type_ != ARM_LOG_NONE) { - if (log_type_ == ARM_LOG_FULL) { - log(log_indent_, "Raw Data: 0x00 0x00 0x00 0x01"); - } - log(log_indent_, "[cantunwind]"); - } - return false; - } - - if (data & (1UL << 31)) { - // This is a compact table entry. - if ((data >> 24) & 0xf) { - // This is a non-zero index, this code doesn't support - // other formats. - status_ = ARM_STATUS_INVALID_PERSONALITY; - return false; - } - data_.push_back((data >> 16) & 0xff); - data_.push_back((data >> 8) & 0xff); - uint8_t last_op = data & 0xff; - data_.push_back(last_op); - if (last_op != ARM_OP_FINISH) { - // If this didn't end with a finish op, add one. - data_.push_back(ARM_OP_FINISH); - } - if (log_type_ == ARM_LOG_FULL) { - LogRawData(); - } - return true; - } - - // Get the address of the ops. - // Sign extend the data value if necessary. - int32_t signed_data = static_cast(data << 1) >> 1; - uint32_t addr = (entry_offset + 4) + signed_data; - if (!elf_memory_->Read32(addr, &data)) { - status_ = ARM_STATUS_READ_FAILED; - status_address_ = addr; - return false; - } - - size_t num_table_words; - if (data & (1UL << 31)) { - // Compact model. - switch ((data >> 24) & 0xf) { - case 0: - num_table_words = 0; - data_.push_back((data >> 16) & 0xff); - break; - case 1: - case 2: - num_table_words = (data >> 16) & 0xff; - addr += 4; - break; - default: - // Only a personality of 0, 1, 2 is valid. - status_ = ARM_STATUS_INVALID_PERSONALITY; - return false; - } - data_.push_back((data >> 8) & 0xff); - data_.push_back(data & 0xff); - } else { - // Generic model. - - // Skip the personality routine data, it doesn't contain any data - // needed to decode the unwind information. - addr += 4; - if (!elf_memory_->Read32(addr, &data)) { - status_ = ARM_STATUS_READ_FAILED; - status_address_ = addr; - return false; - } - num_table_words = (data >> 24) & 0xff; - data_.push_back((data >> 16) & 0xff); - data_.push_back((data >> 8) & 0xff); - data_.push_back(data & 0xff); - addr += 4; - } - - if (num_table_words > 5) { - status_ = ARM_STATUS_MALFORMED; - return false; - } - - for (size_t i = 0; i < num_table_words; i++) { - if (!elf_memory_->Read32(addr, &data)) { - status_ = ARM_STATUS_READ_FAILED; - status_address_ = addr; - return false; - } - data_.push_back((data >> 24) & 0xff); - data_.push_back((data >> 16) & 0xff); - data_.push_back((data >> 8) & 0xff); - data_.push_back(data & 0xff); - addr += 4; - } - - if (data_.back() != ARM_OP_FINISH) { - // If this didn't end with a finish op, add one. - data_.push_back(ARM_OP_FINISH); - } - - if (log_type_ == ARM_LOG_FULL) { - LogRawData(); - } - return true; -} - -inline bool ArmExidx::GetByte(uint8_t* byte) { - if (data_.empty()) { - status_ = ARM_STATUS_TRUNCATED; - return false; - } - *byte = data_.front(); - data_.pop_front(); - return true; -} - -inline bool ArmExidx::DecodePrefix_10_00(uint8_t byte) { - CHECK((byte >> 4) == 0x8); - - uint16_t registers = (byte & 0xf) << 8; - if (!GetByte(&byte)) { - return false; - } - - registers |= byte; - if (registers == 0) { - // 10000000 00000000: Refuse to unwind - if (log_type_ != ARM_LOG_NONE) { - log(log_indent_, "Refuse to unwind"); - } - status_ = ARM_STATUS_NO_UNWIND; - return false; - } - // 1000iiii iiiiiiii: Pop up to 12 integer registers under masks {r15-r12}, {r11-r4} - registers <<= 4; - - if (log_type_ != ARM_LOG_NONE) { - if (log_type_ == ARM_LOG_FULL) { - bool add_comma = false; - std::string msg = "pop {"; - for (size_t reg = 4; reg < 16; reg++) { - if (registers & (1 << reg)) { - if (add_comma) { - msg += ", "; - } - msg += android::base::StringPrintf("r%zu", reg); - add_comma = true; - } - } - log(log_indent_, "%s}", msg.c_str()); - } else { - uint32_t cfa_offset = __builtin_popcount(registers) * 4; - log_cfa_offset_ += cfa_offset; - for (size_t reg = 4; reg < 16; reg++) { - if (registers & (1 << reg)) { - log_regs_[reg] = cfa_offset; - cfa_offset -= 4; - } - } - } - - if (log_skip_execution_) { - return true; - } - } - - for (size_t reg = 4; reg < 16; reg++) { - if (registers & (1 << reg)) { - if (!process_memory_->Read32(cfa_, &(*regs_)[reg])) { - status_ = ARM_STATUS_READ_FAILED; - status_address_ = cfa_; - return false; - } - cfa_ += 4; - } - } - - // If the sp register is modified, change the cfa value. - if (registers & (1 << ARM_REG_SP)) { - cfa_ = (*regs_)[ARM_REG_SP]; - } - - // Indicate if the pc register was set. - if (registers & (1 << ARM_REG_PC)) { - pc_set_ = true; - } - return true; -} - -inline bool ArmExidx::DecodePrefix_10_01(uint8_t byte) { - CHECK((byte >> 4) == 0x9); - - uint8_t bits = byte & 0xf; - if (bits == 13 || bits == 15) { - // 10011101: Reserved as prefix for ARM register to register moves - // 10011111: Reserved as prefix for Intel Wireless MMX register to register moves - if (log_type_ != ARM_LOG_NONE) { - log(log_indent_, "[Reserved]"); - } - status_ = ARM_STATUS_RESERVED; - return false; - } - // 1001nnnn: Set vsp = r[nnnn] (nnnn != 13, 15) - if (log_type_ != ARM_LOG_NONE) { - if (log_type_ == ARM_LOG_FULL) { - log(log_indent_, "vsp = r%d", bits); - } else { - log_regs_[LOG_CFA_REG] = bits; - } - - if (log_skip_execution_) { - return true; - } - } - // It is impossible for bits to be larger than the total number of - // arm registers, so don't bother checking if bits is a valid register. - cfa_ = (*regs_)[bits]; - return true; -} - -inline bool ArmExidx::DecodePrefix_10_10(uint8_t byte) { - CHECK((byte >> 4) == 0xa); - - // 10100nnn: Pop r4-r[4+nnn] - // 10101nnn: Pop r4-r[4+nnn], r14 - if (log_type_ != ARM_LOG_NONE) { - uint8_t end_reg = byte & 0x7; - if (log_type_ == ARM_LOG_FULL) { - std::string msg = "pop {r4"; - if (end_reg) { - msg += android::base::StringPrintf("-r%d", 4 + end_reg); - } - if (byte & 0x8) { - log(log_indent_, "%s, r14}", msg.c_str()); - } else { - log(log_indent_, "%s}", msg.c_str()); - } - } else { - end_reg += 4; - uint32_t cfa_offset = (end_reg - 3) * 4; - if (byte & 0x8) { - cfa_offset += 4; - } - log_cfa_offset_ += cfa_offset; - - for (uint8_t reg = 4; reg <= end_reg; reg++) { - log_regs_[reg] = cfa_offset; - cfa_offset -= 4; - } - - if (byte & 0x8) { - log_regs_[14] = cfa_offset; - } - } - - if (log_skip_execution_) { - return true; - } - } - - for (size_t i = 4; i <= 4 + (byte & 0x7); i++) { - if (!process_memory_->Read32(cfa_, &(*regs_)[i])) { - status_ = ARM_STATUS_READ_FAILED; - status_address_ = cfa_; - return false; - } - cfa_ += 4; - } - if (byte & 0x8) { - if (!process_memory_->Read32(cfa_, &(*regs_)[ARM_REG_R14])) { - status_ = ARM_STATUS_READ_FAILED; - status_address_ = cfa_; - return false; - } - cfa_ += 4; - } - return true; -} - -inline bool ArmExidx::DecodePrefix_10_11_0000() { - // 10110000: Finish - if (log_type_ != ARM_LOG_NONE) { - if (log_type_ == ARM_LOG_FULL) { - log(log_indent_, "finish"); - } - - if (log_skip_execution_) { - status_ = ARM_STATUS_FINISH; - return false; - } - } - status_ = ARM_STATUS_FINISH; - return false; -} - -inline bool ArmExidx::DecodePrefix_10_11_0001() { - uint8_t byte; - if (!GetByte(&byte)) { - return false; - } - - if (byte == 0) { - // 10110001 00000000: Spare - if (log_type_ != ARM_LOG_NONE) { - log(log_indent_, "Spare"); - } - status_ = ARM_STATUS_SPARE; - return false; - } - if (byte >> 4) { - // 10110001 xxxxyyyy: Spare (xxxx != 0000) - if (log_type_ != ARM_LOG_NONE) { - log(log_indent_, "Spare"); - } - status_ = ARM_STATUS_SPARE; - return false; - } - - // 10110001 0000iiii: Pop integer registers under mask {r3, r2, r1, r0} - if (log_type_ != ARM_LOG_NONE) { - if (log_type_ == ARM_LOG_FULL) { - bool add_comma = false; - std::string msg = "pop {"; - for (size_t i = 0; i < 4; i++) { - if (byte & (1 << i)) { - if (add_comma) { - msg += ", "; - } - msg += android::base::StringPrintf("r%zu", i); - add_comma = true; - } - } - log(log_indent_, "%s}", msg.c_str()); - } else { - byte &= 0xf; - uint32_t cfa_offset = __builtin_popcount(byte) * 4; - log_cfa_offset_ += cfa_offset; - for (size_t reg = 0; reg < 4; reg++) { - if (byte & (1 << reg)) { - log_regs_[reg] = cfa_offset; - cfa_offset -= 4; - } - } - } - - if (log_skip_execution_) { - return true; - } - } - - for (size_t reg = 0; reg < 4; reg++) { - if (byte & (1 << reg)) { - if (!process_memory_->Read32(cfa_, &(*regs_)[reg])) { - status_ = ARM_STATUS_READ_FAILED; - status_address_ = cfa_; - return false; - } - cfa_ += 4; - } - } - return true; -} - -inline void ArmExidx::AdjustRegisters(int32_t offset) { - for (auto& entry : log_regs_) { - if (entry.first >= LOG_CFA_REG) { - break; - } - entry.second += offset; - } -} - -inline bool ArmExidx::DecodePrefix_10_11_0010() { - // 10110010 uleb128: vsp = vsp + 0x204 + (uleb128 << 2) - uint32_t result = 0; - uint32_t shift = 0; - uint8_t byte; - do { - if (!GetByte(&byte)) { - return false; - } - - result |= (byte & 0x7f) << shift; - shift += 7; - } while (byte & 0x80); - result <<= 2; - if (log_type_ != ARM_LOG_NONE) { - int32_t cfa_offset = 0x204 + result; - if (log_type_ == ARM_LOG_FULL) { - log(log_indent_, "vsp = vsp + %d", cfa_offset); - } else { - log_cfa_offset_ += cfa_offset; - } - AdjustRegisters(cfa_offset); - - if (log_skip_execution_) { - return true; - } - } - cfa_ += 0x204 + result; - return true; -} - -inline bool ArmExidx::DecodePrefix_10_11_0011() { - // 10110011 sssscccc: Pop VFP double precision registers D[ssss]-D[ssss+cccc] by FSTMFDX - uint8_t byte; - if (!GetByte(&byte)) { - return false; - } - - if (log_type_ != ARM_LOG_NONE) { - uint8_t start_reg = byte >> 4; - uint8_t end_reg = start_reg + (byte & 0xf); - - if (log_type_ == ARM_LOG_FULL) { - std::string msg = android::base::StringPrintf("pop {d%d", start_reg); - if (end_reg) { - msg += android::base::StringPrintf("-d%d", end_reg); - } - log(log_indent_, "%s}", msg.c_str()); - } else { - log(log_indent_, "Unsupported DX register display"); - } - - if (log_skip_execution_) { - return true; - } - } - cfa_ += (byte & 0xf) * 8 + 12; - return true; -} - -inline bool ArmExidx::DecodePrefix_10_11_01nn() { - // 101101nn: Spare - if (log_type_ != ARM_LOG_NONE) { - log(log_indent_, "Spare"); - } - status_ = ARM_STATUS_SPARE; - return false; -} - -inline bool ArmExidx::DecodePrefix_10_11_1nnn(uint8_t byte) { - CHECK((byte & ~0x07) == 0xb8); - - // 10111nnn: Pop VFP double-precision registers D[8]-D[8+nnn] by FSTMFDX - if (log_type_ != ARM_LOG_NONE) { - if (log_type_ == ARM_LOG_FULL) { - uint8_t last_reg = (byte & 0x7); - std::string msg = "pop {d8"; - if (last_reg) { - msg += android::base::StringPrintf("-d%d", last_reg + 8); - } - log(log_indent_, "%s}", msg.c_str()); - } else { - log(log_indent_, "Unsupported DX register display"); - } - - if (log_skip_execution_) { - return true; - } - } - // Only update the cfa. - cfa_ += (byte & 0x7) * 8 + 12; - return true; -} - -inline bool ArmExidx::DecodePrefix_10(uint8_t byte) { - CHECK((byte >> 6) == 0x2); - - switch ((byte >> 4) & 0x3) { - case 0: - return DecodePrefix_10_00(byte); - case 1: - return DecodePrefix_10_01(byte); - case 2: - return DecodePrefix_10_10(byte); - default: - switch (byte & 0xf) { - case 0: - return DecodePrefix_10_11_0000(); - case 1: - return DecodePrefix_10_11_0001(); - case 2: - return DecodePrefix_10_11_0010(); - case 3: - return DecodePrefix_10_11_0011(); - default: - if (byte & 0x8) { - return DecodePrefix_10_11_1nnn(byte); - } else { - return DecodePrefix_10_11_01nn(); - } - } - } -} - -inline bool ArmExidx::DecodePrefix_11_000(uint8_t byte) { - CHECK((byte & ~0x07) == 0xc0); - - uint8_t bits = byte & 0x7; - if (bits == 6) { - if (!GetByte(&byte)) { - return false; - } - - // 11000110 sssscccc: Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc] - if (log_type_ != ARM_LOG_NONE) { - if (log_type_ == ARM_LOG_FULL) { - uint8_t start_reg = byte >> 4; - std::string msg = android::base::StringPrintf("pop {wR%d", start_reg); - uint8_t end_reg = byte & 0xf; - if (end_reg) { - msg += android::base::StringPrintf("-wR%d", start_reg + end_reg); - } - log(log_indent_, "%s}", msg.c_str()); - } else { - log(log_indent_, "Unsupported wRX register display"); - } - - if (log_skip_execution_) { - return true; - } - } - // Only update the cfa. - cfa_ += (byte & 0xf) * 8 + 8; - } else if (bits == 7) { - if (!GetByte(&byte)) { - return false; - } - - if (byte == 0) { - // 11000111 00000000: Spare - if (log_type_ != ARM_LOG_NONE) { - log(log_indent_, "Spare"); - } - status_ = ARM_STATUS_SPARE; - return false; - } else if ((byte >> 4) == 0) { - // 11000111 0000iiii: Intel Wireless MMX pop wCGR registers {wCGR0,1,2,3} - if (log_type_ != ARM_LOG_NONE) { - if (log_type_ == ARM_LOG_FULL) { - bool add_comma = false; - std::string msg = "pop {"; - for (size_t i = 0; i < 4; i++) { - if (byte & (1 << i)) { - if (add_comma) { - msg += ", "; - } - msg += android::base::StringPrintf("wCGR%zu", i); - add_comma = true; - } - } - log(log_indent_, "%s}", msg.c_str()); - } else { - log(log_indent_, "Unsupported wCGR register display"); - } - - if (log_skip_execution_) { - return true; - } - } - // Only update the cfa. - cfa_ += __builtin_popcount(byte) * 4; - } else { - // 11000111 xxxxyyyy: Spare (xxxx != 0000) - if (log_type_ != ARM_LOG_NONE) { - log(log_indent_, "Spare"); - } - status_ = ARM_STATUS_SPARE; - return false; - } - } else { - // 11000nnn: Intel Wireless MMX pop wR[10]-wR[10+nnn] (nnn != 6, 7) - if (log_type_ != ARM_LOG_NONE) { - if (log_type_ == ARM_LOG_FULL) { - std::string msg = "pop {wR10"; - uint8_t nnn = byte & 0x7; - if (nnn) { - msg += android::base::StringPrintf("-wR%d", 10 + nnn); - } - log(log_indent_, "%s}", msg.c_str()); - } else { - log(log_indent_, "Unsupported wRX register display"); - } - - if (log_skip_execution_) { - return true; - } - } - // Only update the cfa. - cfa_ += (byte & 0x7) * 8 + 8; - } - return true; -} - -inline bool ArmExidx::DecodePrefix_11_001(uint8_t byte) { - CHECK((byte & ~0x07) == 0xc8); - - uint8_t bits = byte & 0x7; - if (bits == 0) { - // 11001000 sssscccc: Pop VFP double precision registers D[16+ssss]-D[16+ssss+cccc] by VPUSH - if (!GetByte(&byte)) { - return false; - } - - if (log_type_ != ARM_LOG_NONE) { - if (log_type_ == ARM_LOG_FULL) { - uint8_t start_reg = byte >> 4; - std::string msg = android::base::StringPrintf("pop {d%d", 16 + start_reg); - uint8_t end_reg = byte & 0xf; - if (end_reg) { - msg += android::base::StringPrintf("-d%d", 16 + start_reg + end_reg); - } - log(log_indent_, "%s}", msg.c_str()); - } else { - log(log_indent_, "Unsupported DX register display"); - } - - if (log_skip_execution_) { - return true; - } - } - // Only update the cfa. - cfa_ += (byte & 0xf) * 8 + 8; - } else if (bits == 1) { - // 11001001 sssscccc: Pop VFP double precision registers D[ssss]-D[ssss+cccc] by VPUSH - if (!GetByte(&byte)) { - return false; - } - - if (log_type_ != ARM_LOG_NONE) { - if (log_type_ == ARM_LOG_FULL) { - uint8_t start_reg = byte >> 4; - std::string msg = android::base::StringPrintf("pop {d%d", start_reg); - uint8_t end_reg = byte & 0xf; - if (end_reg) { - msg += android::base::StringPrintf("-d%d", start_reg + end_reg); - } - log(log_indent_, "%s}", msg.c_str()); - } else { - log(log_indent_, "Unsupported DX register display"); - } - - if (log_skip_execution_) { - return true; - } - } - // Only update the cfa. - cfa_ += (byte & 0xf) * 8 + 8; - } else { - // 11001yyy: Spare (yyy != 000, 001) - if (log_type_ != ARM_LOG_NONE) { - log(log_indent_, "Spare"); - } - status_ = ARM_STATUS_SPARE; - return false; - } - return true; -} - -inline bool ArmExidx::DecodePrefix_11_010(uint8_t byte) { - CHECK((byte & ~0x07) == 0xd0); - - // 11010nnn: Pop VFP double precision registers D[8]-D[8+nnn] by VPUSH - if (log_type_ != ARM_LOG_NONE) { - if (log_type_ == ARM_LOG_FULL) { - std::string msg = "pop {d8"; - uint8_t end_reg = byte & 0x7; - if (end_reg) { - msg += android::base::StringPrintf("-d%d", 8 + end_reg); - } - log(log_indent_, "%s}", msg.c_str()); - } else { - log(log_indent_, "Unsupported DX register display"); - } - - if (log_skip_execution_) { - return true; - } - } - cfa_ += (byte & 0x7) * 8 + 8; - return true; -} - -inline bool ArmExidx::DecodePrefix_11(uint8_t byte) { - CHECK((byte >> 6) == 0x3); - - switch ((byte >> 3) & 0x7) { - case 0: - return DecodePrefix_11_000(byte); - case 1: - return DecodePrefix_11_001(byte); - case 2: - return DecodePrefix_11_010(byte); - default: - // 11xxxyyy: Spare (xxx != 000, 001, 010) - if (log_type_ != ARM_LOG_NONE) { - log(log_indent_, "Spare"); - } - status_ = ARM_STATUS_SPARE; - return false; - } -} - -bool ArmExidx::Decode() { - status_ = ARM_STATUS_NONE; - uint8_t byte; - if (!GetByte(&byte)) { - return false; - } - - switch (byte >> 6) { - case 0: - // 00xxxxxx: vsp = vsp + (xxxxxxx << 2) + 4 - if (log_type_ != ARM_LOG_NONE) { - int32_t cfa_offset = ((byte & 0x3f) << 2) + 4; - if (log_type_ == ARM_LOG_FULL) { - log(log_indent_, "vsp = vsp + %d", cfa_offset); - } else { - log_cfa_offset_ += cfa_offset; - } - AdjustRegisters(cfa_offset); - - if (log_skip_execution_) { - break; - } - } - cfa_ += ((byte & 0x3f) << 2) + 4; - break; - case 1: - // 01xxxxxx: vsp = vsp - (xxxxxxx << 2) + 4 - if (log_type_ != ARM_LOG_NONE) { - uint32_t cfa_offset = ((byte & 0x3f) << 2) + 4; - if (log_type_ == ARM_LOG_FULL) { - log(log_indent_, "vsp = vsp - %d", cfa_offset); - } else { - log_cfa_offset_ -= cfa_offset; - } - AdjustRegisters(-cfa_offset); - - if (log_skip_execution_) { - break; - } - } - cfa_ -= ((byte & 0x3f) << 2) + 4; - break; - case 2: - return DecodePrefix_10(byte); - default: - return DecodePrefix_11(byte); - } - return true; -} - -bool ArmExidx::Eval() { - pc_set_ = false; - while (Decode()); - return status_ == ARM_STATUS_FINISH; -} - -void ArmExidx::LogByReg() { - if (log_type_ != ARM_LOG_BY_REG) { - return; - } - - uint8_t cfa_reg; - if (log_regs_.count(LOG_CFA_REG) == 0) { - cfa_reg = 13; - } else { - cfa_reg = log_regs_[LOG_CFA_REG]; - } - - if (log_cfa_offset_ != 0) { - char sign = (log_cfa_offset_ > 0) ? '+' : '-'; - log(log_indent_, "cfa = r%zu %c %d", cfa_reg, sign, abs(log_cfa_offset_)); - } else { - log(log_indent_, "cfa = r%zu", cfa_reg); - } - - for (const auto& entry : log_regs_) { - if (entry.first >= LOG_CFA_REG) { - break; - } - if (entry.second == 0) { - log(log_indent_, "r%zu = [cfa]", entry.first); - } else { - char sign = (entry.second > 0) ? '-' : '+'; - log(log_indent_, "r%zu = [cfa %c %d]", entry.first, sign, abs(entry.second)); - } - } -} - -} // namespace unwindstack diff --git a/libunwindstack/ArmExidx.h b/libunwindstack/ArmExidx.h deleted file mode 100644 index d9fc371c3..000000000 --- a/libunwindstack/ArmExidx.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2016 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_ARM_EXIDX_H -#define _LIBUNWINDSTACK_ARM_EXIDX_H - -#include - -#include -#include - -namespace unwindstack { - -// Forward declarations. -class Memory; -class RegsArm; - -enum ArmStatus : size_t { - ARM_STATUS_NONE = 0, - ARM_STATUS_NO_UNWIND, - ARM_STATUS_FINISH, - ARM_STATUS_RESERVED, - ARM_STATUS_SPARE, - ARM_STATUS_TRUNCATED, - ARM_STATUS_READ_FAILED, - ARM_STATUS_MALFORMED, - ARM_STATUS_INVALID_ALIGNMENT, - ARM_STATUS_INVALID_PERSONALITY, -}; - -enum ArmOp : uint8_t { - ARM_OP_FINISH = 0xb0, -}; - -enum ArmLogType : uint8_t { - ARM_LOG_NONE, - ARM_LOG_FULL, - ARM_LOG_BY_REG, -}; - -class ArmExidx { - public: - ArmExidx(RegsArm* regs, Memory* elf_memory, Memory* process_memory) - : regs_(regs), elf_memory_(elf_memory), process_memory_(process_memory) {} - virtual ~ArmExidx() {} - - void LogRawData(); - - void LogByReg(); - - bool ExtractEntryData(uint32_t entry_offset); - - bool Eval(); - - bool Decode(); - - std::deque* data() { return &data_; } - - ArmStatus status() { return status_; } - uint64_t status_address() { return status_address_; } - - RegsArm* regs() { return regs_; } - - uint32_t cfa() { return cfa_; } - void set_cfa(uint32_t cfa) { cfa_ = cfa; } - - bool pc_set() { return pc_set_; } - void set_pc_set(bool pc_set) { pc_set_ = pc_set; } - - void set_log(ArmLogType log_type) { log_type_ = log_type; } - void set_log_skip_execution(bool skip_execution) { log_skip_execution_ = skip_execution; } - void set_log_indent(uint8_t indent) { log_indent_ = indent; } - - private: - bool GetByte(uint8_t* byte); - void AdjustRegisters(int32_t offset); - - bool DecodePrefix_10_00(uint8_t byte); - bool DecodePrefix_10_01(uint8_t byte); - bool DecodePrefix_10_10(uint8_t byte); - bool DecodePrefix_10_11_0000(); - bool DecodePrefix_10_11_0001(); - bool DecodePrefix_10_11_0010(); - bool DecodePrefix_10_11_0011(); - bool DecodePrefix_10_11_01nn(); - bool DecodePrefix_10_11_1nnn(uint8_t byte); - bool DecodePrefix_10(uint8_t byte); - - bool DecodePrefix_11_000(uint8_t byte); - bool DecodePrefix_11_001(uint8_t byte); - bool DecodePrefix_11_010(uint8_t byte); - bool DecodePrefix_11(uint8_t byte); - - RegsArm* regs_ = nullptr; - uint32_t cfa_ = 0; - std::deque data_; - ArmStatus status_ = ARM_STATUS_NONE; - uint64_t status_address_ = 0; - - Memory* elf_memory_; - Memory* process_memory_; - - ArmLogType log_type_ = ARM_LOG_NONE; - uint8_t log_indent_ = 0; - bool log_skip_execution_ = false; - bool pc_set_ = false; - int32_t log_cfa_offset_ = 0; - std::map log_regs_; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_ARM_EXIDX_H diff --git a/libunwindstack/AsmGetRegsX86.S b/libunwindstack/AsmGetRegsX86.S deleted file mode 100644 index 021e6286c..000000000 --- a/libunwindstack/AsmGetRegsX86.S +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - - .text - .global AsmGetRegs - .balign 16 - .type AsmGetRegs, @function -AsmGetRegs: - .cfi_startproc - mov 4(%esp), %eax - movl $0, (%eax) - movl %ecx, 4(%eax) - movl %edx, 8(%eax) - movl %ebx, 12(%eax) - - /* ESP */ - leal 4(%esp), %ecx - movl %ecx, 16(%eax) - - movl %ebp, 20(%eax) - movl %esi, 24(%eax) - movl %edi, 28(%eax) - - /* EIP */ - movl (%esp), %ecx - movl %ecx, 32(%eax) - - mov %cs, 36(%eax) - mov %ss, 40(%eax) - mov %ds, 44(%eax) - mov %es, 48(%eax) - mov %fs, 52(%eax) - mov %gs, 56(%eax) - ret - - .cfi_endproc - .size AsmGetRegs, .-AsmGetRegs diff --git a/libunwindstack/AsmGetRegsX86_64.S b/libunwindstack/AsmGetRegsX86_64.S deleted file mode 100644 index 4cd3b6fb6..000000000 --- a/libunwindstack/AsmGetRegsX86_64.S +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - - .text - .global AsmGetRegs - .balign 16 - .type AsmGetRegs, @function -AsmGetRegs: - .cfi_startproc - movq %rax, (%rdi) - movq %rdx, 8(%rdi) - movq %rcx, 16(%rdi) - movq %rbx, 24(%rdi) - movq %rsi, 32(%rdi) - movq %rdi, 40(%rdi) - movq %rbp, 48(%rdi) - - /* RSP */ - lea 8(%rsp), %rax - movq %rax, 56(%rdi) - - movq %r8, 64(%rdi) - movq %r9, 72(%rdi) - movq %r10, 80(%rdi) - movq %r11, 88(%rdi) - movq %r12, 96(%rdi) - movq %r13, 104(%rdi) - movq %r14, 112(%rdi) - movq %r15, 120(%rdi) - - /* RIP */ - movq (%rsp), %rax - movq %rax, 128(%rdi) - ret - - .cfi_endproc - .size AsmGetRegs, .-AsmGetRegs diff --git a/libunwindstack/Check.h b/libunwindstack/Check.h deleted file mode 100644 index 9643d7670..000000000 --- a/libunwindstack/Check.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2017 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_CHECK_H -#define _LIBUNWINDSTACK_CHECK_H - -#include - -#include - -namespace unwindstack { - -#define CHECK(assertion) \ - if (__builtin_expect(!(assertion), false)) { \ - log(0, "%s:%d: %s\n", __FILE__, __LINE__, #assertion); \ - abort(); \ - } - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_CHECK_H diff --git a/libunwindstack/DexFile.cpp b/libunwindstack/DexFile.cpp deleted file mode 100644 index 8fc3d23ec..000000000 --- a/libunwindstack/DexFile.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2018 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 - -#define LOG_TAG "unwind" -#include - -#include -#include - -#include -#include - -#include "DexFile.h" - -namespace unwindstack { - -static bool CheckDexSupport() { - if (std::string err_msg; !art_api::dex::TryLoadLibdexfileExternal(&err_msg)) { - ALOGW("Failed to initialize DEX file support: %s", err_msg.c_str()); - return false; - } - return true; -} - -static bool HasDexSupport() { - static bool has_dex_support = CheckDexSupport(); - return has_dex_support; -} - -std::unique_ptr DexFile::Create(uint64_t dex_file_offset_in_memory, Memory* memory, - MapInfo* info) { - if (UNLIKELY(!HasDexSupport())) { - return nullptr; - } - - size_t max_size = info->end - dex_file_offset_in_memory; - if (memory->IsLocal()) { - size_t size = max_size; - - std::string err_msg; - std::unique_ptr art_dex_file = DexFile::OpenFromMemory( - reinterpret_cast(dex_file_offset_in_memory), &size, info->name, &err_msg); - if (art_dex_file != nullptr && size <= max_size) { - return std::unique_ptr(new DexFile(art_dex_file)); - } - } - - if (!info->name.empty()) { - std::unique_ptr dex_file = - DexFileFromFile::Create(dex_file_offset_in_memory - info->start + info->offset, info->name); - if (dex_file) { - return dex_file; - } - } - return DexFileFromMemory::Create(dex_file_offset_in_memory, memory, info->name, max_size); -} - -bool DexFile::GetMethodInformation(uint64_t dex_offset, std::string* method_name, - uint64_t* method_offset) { - art_api::dex::MethodInfo method_info = GetMethodInfoForOffset(dex_offset, false); - if (method_info.offset == 0) { - return false; - } - *method_name = method_info.name; - *method_offset = dex_offset - method_info.offset; - return true; -} - -std::unique_ptr DexFileFromFile::Create(uint64_t dex_file_offset_in_file, - const std::string& file) { - if (UNLIKELY(!HasDexSupport())) { - return nullptr; - } - - android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(file.c_str(), O_RDONLY | O_CLOEXEC))); - if (fd == -1) { - return nullptr; - } - - std::string error_msg; - std::unique_ptr art_dex_file = - OpenFromFd(fd, dex_file_offset_in_file, file, &error_msg); - if (art_dex_file == nullptr) { - return nullptr; - } - - return std::unique_ptr(new DexFileFromFile(art_dex_file)); -} - -std::unique_ptr DexFileFromMemory::Create(uint64_t dex_file_offset_in_memory, - Memory* memory, - const std::string& name, - size_t max_size) { - if (UNLIKELY(!HasDexSupport())) { - return nullptr; - } - - std::vector backing_memory; - - for (size_t size = 0;;) { - std::string error_msg; - std::unique_ptr art_dex_file = - OpenFromMemory(backing_memory.data(), &size, name, &error_msg); - if (size > max_size) { - return nullptr; - } - - if (art_dex_file != nullptr) { - return std::unique_ptr( - new DexFileFromMemory(art_dex_file, std::move(backing_memory))); - } - - if (!error_msg.empty()) { - return nullptr; - } - - backing_memory.resize(size); - if (!memory->ReadFully(dex_file_offset_in_memory, backing_memory.data(), - backing_memory.size())) { - return nullptr; - } - } -} - -} // namespace unwindstack diff --git a/libunwindstack/DexFile.h b/libunwindstack/DexFile.h deleted file mode 100644 index fe185dae0..000000000 --- a/libunwindstack/DexFile.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2018 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_DEX_FILE_H -#define _LIBUNWINDSTACK_DEX_FILE_H - -#include - -#include -#include -#include -#include -#include - -#include - -namespace unwindstack { - -class DexFile : protected art_api::dex::DexFile { - public: - virtual ~DexFile() = default; - - bool GetMethodInformation(uint64_t dex_offset, std::string* method_name, uint64_t* method_offset); - - static std::unique_ptr Create(uint64_t dex_file_offset_in_memory, Memory* memory, - MapInfo* info); - - protected: - DexFile(std::unique_ptr& art_dex_file) - : art_api::dex::DexFile(art_dex_file) {} -}; - -class DexFileFromFile : public DexFile { - public: - static std::unique_ptr Create(uint64_t dex_file_offset_in_file, - const std::string& file); - - private: - DexFileFromFile(std::unique_ptr& art_dex_file) : DexFile(art_dex_file) {} -}; - -class DexFileFromMemory : public DexFile { - public: - static std::unique_ptr Create(uint64_t dex_file_offset_in_memory, - Memory* memory, const std::string& name, - size_t max_size); - - private: - DexFileFromMemory(std::unique_ptr& art_dex_file, - std::vector&& memory) - : DexFile(art_dex_file), memory_(std::move(memory)) {} - - std::vector memory_; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_DEX_FILE_H diff --git a/libunwindstack/DexFiles.cpp b/libunwindstack/DexFiles.cpp deleted file mode 100644 index 2057fad19..000000000 --- a/libunwindstack/DexFiles.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2018 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 - -#if defined(DEXFILE_SUPPORT) -#include "DexFile.h" -#endif - -namespace unwindstack { - -#if !defined(DEXFILE_SUPPORT) -// Empty class definition. -class DexFile { - public: - DexFile() = default; - virtual ~DexFile() = default; -}; -#endif - -struct DEXFileEntry32 { - uint32_t next; - uint32_t prev; - uint32_t dex_file; -}; - -struct DEXFileEntry64 { - uint64_t next; - uint64_t prev; - uint64_t dex_file; -}; - -DexFiles::DexFiles(std::shared_ptr& memory) : Global(memory) {} - -DexFiles::DexFiles(std::shared_ptr& memory, std::vector& search_libs) - : Global(memory, search_libs) {} - -DexFiles::~DexFiles() {} - -void DexFiles::ProcessArch() { - switch (arch()) { - case ARCH_ARM: - case ARCH_MIPS: - case ARCH_X86: - read_entry_ptr_func_ = &DexFiles::ReadEntryPtr32; - read_entry_func_ = &DexFiles::ReadEntry32; - break; - - case ARCH_ARM64: - case ARCH_MIPS64: - case ARCH_X86_64: - read_entry_ptr_func_ = &DexFiles::ReadEntryPtr64; - read_entry_func_ = &DexFiles::ReadEntry64; - break; - - case ARCH_UNKNOWN: - abort(); - } -} - -uint64_t DexFiles::ReadEntryPtr32(uint64_t addr) { - uint32_t entry; - const uint32_t field_offset = 12; // offset of first_entry_ in the descriptor struct. - if (!memory_->ReadFully(addr + field_offset, &entry, sizeof(entry))) { - return 0; - } - return entry; -} - -uint64_t DexFiles::ReadEntryPtr64(uint64_t addr) { - uint64_t entry; - const uint32_t field_offset = 16; // offset of first_entry_ in the descriptor struct. - if (!memory_->ReadFully(addr + field_offset, &entry, sizeof(entry))) { - return 0; - } - return entry; -} - -bool DexFiles::ReadEntry32() { - DEXFileEntry32 entry; - if (!memory_->ReadFully(entry_addr_, &entry, sizeof(entry)) || entry.dex_file == 0) { - entry_addr_ = 0; - return false; - } - - addrs_.push_back(entry.dex_file); - entry_addr_ = entry.next; - return true; -} - -bool DexFiles::ReadEntry64() { - DEXFileEntry64 entry; - if (!memory_->ReadFully(entry_addr_, &entry, sizeof(entry)) || entry.dex_file == 0) { - entry_addr_ = 0; - return false; - } - - addrs_.push_back(entry.dex_file); - entry_addr_ = entry.next; - return true; -} - -bool DexFiles::ReadVariableData(uint64_t ptr_offset) { - entry_addr_ = (this->*read_entry_ptr_func_)(ptr_offset); - return entry_addr_ != 0; -} - -void DexFiles::Init(Maps* maps) { - if (initialized_) { - return; - } - initialized_ = true; - entry_addr_ = 0; - - FindAndReadVariable(maps, "__dex_debug_descriptor"); -} - -#if defined(DEXFILE_SUPPORT) -DexFile* DexFiles::GetDexFile(uint64_t dex_file_offset, MapInfo* info) { - // Lock while processing the data. - DexFile* dex_file; - auto entry = files_.find(dex_file_offset); - if (entry == files_.end()) { - std::unique_ptr new_dex_file = DexFile::Create(dex_file_offset, memory_.get(), info); - dex_file = new_dex_file.get(); - files_[dex_file_offset] = std::move(new_dex_file); - } else { - dex_file = entry->second.get(); - } - return dex_file; -} -#else -DexFile* DexFiles::GetDexFile(uint64_t, MapInfo*) { - return nullptr; -} -#endif - -bool DexFiles::GetAddr(size_t index, uint64_t* addr) { - if (index < addrs_.size()) { - *addr = addrs_[index]; - return true; - } - if (entry_addr_ != 0 && (this->*read_entry_func_)()) { - *addr = addrs_.back(); - return true; - } - return false; -} - -#if defined(DEXFILE_SUPPORT) -void DexFiles::GetMethodInformation(Maps* maps, MapInfo* info, uint64_t dex_pc, - std::string* method_name, uint64_t* method_offset) { - std::lock_guard guard(lock_); - if (!initialized_) { - Init(maps); - } - - size_t index = 0; - uint64_t addr; - while (GetAddr(index++, &addr)) { - if (addr < info->start || addr >= info->end) { - continue; - } - - DexFile* dex_file = GetDexFile(addr, info); - if (dex_file != nullptr && - dex_file->GetMethodInformation(dex_pc - addr, method_name, method_offset)) { - break; - } - } -} -#else -void DexFiles::GetMethodInformation(Maps*, MapInfo*, uint64_t, std::string*, uint64_t*) {} -#endif - -} // namespace unwindstack diff --git a/libunwindstack/DwarfCfa.cpp b/libunwindstack/DwarfCfa.cpp deleted file mode 100644 index c6db209db..000000000 --- a/libunwindstack/DwarfCfa.cpp +++ /dev/null @@ -1,768 +0,0 @@ -/* - * Copyright (C) 2016 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 "DwarfCfa.h" -#include "DwarfEncoding.h" -#include "DwarfOp.h" - -namespace unwindstack { - -template -constexpr typename DwarfCfa::process_func DwarfCfa::kCallbackTable[64]; - -template -bool DwarfCfa::GetLocationInfo(uint64_t pc, uint64_t start_offset, uint64_t end_offset, - dwarf_loc_regs_t* loc_regs) { - if (cie_loc_regs_ != nullptr) { - for (const auto& entry : *cie_loc_regs_) { - (*loc_regs)[entry.first] = entry.second; - } - } - last_error_.code = DWARF_ERROR_NONE; - last_error_.address = 0; - - memory_->set_cur_offset(start_offset); - uint64_t cfa_offset; - cur_pc_ = fde_->pc_start; - loc_regs->pc_start = cur_pc_; - while (true) { - if (cur_pc_ > pc) { - loc_regs->pc_end = cur_pc_; - return true; - } - if ((cfa_offset = memory_->cur_offset()) >= end_offset) { - loc_regs->pc_end = fde_->pc_end; - return true; - } - loc_regs->pc_start = cur_pc_; - operands_.clear(); - // Read the cfa information. - uint8_t cfa_value; - if (!memory_->ReadBytes(&cfa_value, 1)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_->cur_offset(); - return false; - } - uint8_t cfa_low = cfa_value & 0x3f; - // Check the 2 high bits. - switch (cfa_value >> 6) { - case 1: - cur_pc_ += cfa_low * fde_->cie->code_alignment_factor; - break; - case 2: { - uint64_t offset; - if (!memory_->ReadULEB128(&offset)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_->cur_offset(); - return false; - } - SignedType signed_offset = - static_cast(offset) * fde_->cie->data_alignment_factor; - (*loc_regs)[cfa_low] = {.type = DWARF_LOCATION_OFFSET, - .values = {static_cast(signed_offset)}}; - break; - } - case 3: { - if (cie_loc_regs_ == nullptr) { - log(0, "restore while processing cie"); - last_error_.code = DWARF_ERROR_ILLEGAL_STATE; - return false; - } - - auto reg_entry = cie_loc_regs_->find(cfa_low); - if (reg_entry == cie_loc_regs_->end()) { - loc_regs->erase(cfa_low); - } else { - (*loc_regs)[cfa_low] = reg_entry->second; - } - break; - } - case 0: { - const auto handle_func = DwarfCfa::kCallbackTable[cfa_low]; - if (handle_func == nullptr) { - last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; - return false; - } - - const auto cfa = &DwarfCfaInfo::kTable[cfa_low]; - for (size_t i = 0; i < cfa->num_operands; i++) { - if (cfa->operands[i] == DW_EH_PE_block) { - uint64_t block_length; - if (!memory_->ReadULEB128(&block_length)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_->cur_offset(); - return false; - } - operands_.push_back(block_length); - memory_->set_cur_offset(memory_->cur_offset() + block_length); - continue; - } - uint64_t value; - if (!memory_->ReadEncodedValue(cfa->operands[i], &value)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_->cur_offset(); - return false; - } - operands_.push_back(value); - } - - if (!(this->*handle_func)(loc_regs)) { - return false; - } - break; - } - } - } -} - -template -std::string DwarfCfa::GetOperandString(uint8_t operand, uint64_t value, - uint64_t* cur_pc) { - std::string string; - switch (operand) { - case DwarfCfaInfo::DWARF_DISPLAY_REGISTER: - string = " register(" + std::to_string(value) + ")"; - break; - case DwarfCfaInfo::DWARF_DISPLAY_SIGNED_NUMBER: - string += " " + std::to_string(static_cast(value)); - break; - case DwarfCfaInfo::DWARF_DISPLAY_ADVANCE_LOC: - *cur_pc += value; - FALLTHROUGH_INTENDED; - // Fall through to log the value. - case DwarfCfaInfo::DWARF_DISPLAY_NUMBER: - string += " " + std::to_string(value); - break; - case DwarfCfaInfo::DWARF_DISPLAY_SET_LOC: - *cur_pc = value; - FALLTHROUGH_INTENDED; - // Fall through to log the value. - case DwarfCfaInfo::DWARF_DISPLAY_ADDRESS: - if (std::is_same::value) { - string += android::base::StringPrintf(" 0x%" PRIx32, static_cast(value)); - } else { - string += android::base::StringPrintf(" 0x%" PRIx64, static_cast(value)); - } - break; - default: - string = " unknown"; - } - return string; -} - -template -bool DwarfCfa::LogOffsetRegisterString(uint32_t indent, uint64_t cfa_offset, - uint8_t reg) { - uint64_t offset; - if (!memory_->ReadULEB128(&offset)) { - return false; - } - uint64_t end_offset = memory_->cur_offset(); - memory_->set_cur_offset(cfa_offset); - - std::string raw_data = "Raw Data:"; - for (uint64_t i = cfa_offset; i < end_offset; i++) { - uint8_t value; - if (!memory_->ReadBytes(&value, 1)) { - return false; - } - raw_data += android::base::StringPrintf(" 0x%02x", value); - } - log(indent, "DW_CFA_offset register(%d) %" PRId64, reg, offset); - log(indent, "%s", raw_data.c_str()); - return true; -} - -template -bool DwarfCfa::LogInstruction(uint32_t indent, uint64_t cfa_offset, uint8_t op, - uint64_t* cur_pc) { - const auto* cfa = &DwarfCfaInfo::kTable[op]; - if (cfa->name[0] == '\0' || (arch_ != ARCH_ARM64 && op == 0x2d)) { - if (op == 0x2d) { - log(indent, "Illegal (Only valid on aarch64)"); - } else { - log(indent, "Illegal"); - } - log(indent, "Raw Data: 0x%02x", op); - return true; - } - - std::string log_string(cfa->name); - std::vector expression_lines; - for (size_t i = 0; i < cfa->num_operands; i++) { - if (cfa->operands[i] == DW_EH_PE_block) { - // This is a Dwarf Expression. - uint64_t end_offset; - if (!memory_->ReadULEB128(&end_offset)) { - return false; - } - log_string += " " + std::to_string(end_offset); - end_offset += memory_->cur_offset(); - - DwarfOp op(memory_, nullptr); - op.GetLogInfo(memory_->cur_offset(), end_offset, &expression_lines); - memory_->set_cur_offset(end_offset); - } else { - uint64_t value; - if (!memory_->ReadEncodedValue(cfa->operands[i], &value)) { - return false; - } - log_string += GetOperandString(cfa->display_operands[i], value, cur_pc); - } - } - log(indent, "%s", log_string.c_str()); - - // Get the raw bytes of the data. - uint64_t end_offset = memory_->cur_offset(); - memory_->set_cur_offset(cfa_offset); - std::string raw_data("Raw Data:"); - for (uint64_t i = 0; i < end_offset - cfa_offset; i++) { - uint8_t value; - if (!memory_->ReadBytes(&value, 1)) { - return false; - } - - // Only show 10 raw bytes per line. - if ((i % 10) == 0 && i != 0) { - log(indent, "%s", raw_data.c_str()); - raw_data.clear(); - } - if (raw_data.empty()) { - raw_data = "Raw Data:"; - } - raw_data += android::base::StringPrintf(" 0x%02x", value); - } - if (!raw_data.empty()) { - log(indent, "%s", raw_data.c_str()); - } - - // Log any of the expression data. - for (const auto& line : expression_lines) { - log(indent + 1, "%s", line.c_str()); - } - return true; -} - -template -bool DwarfCfa::Log(uint32_t indent, uint64_t pc, uint64_t start_offset, - uint64_t end_offset) { - memory_->set_cur_offset(start_offset); - uint64_t cfa_offset; - uint64_t cur_pc = fde_->pc_start; - uint64_t old_pc = cur_pc; - while ((cfa_offset = memory_->cur_offset()) < end_offset && cur_pc <= pc) { - // Read the cfa information. - uint8_t cfa_value; - if (!memory_->ReadBytes(&cfa_value, 1)) { - return false; - } - - // Check the 2 high bits. - uint8_t cfa_low = cfa_value & 0x3f; - switch (cfa_value >> 6) { - case 0: - if (!LogInstruction(indent, cfa_offset, cfa_low, &cur_pc)) { - return false; - } - break; - case 1: - log(indent, "DW_CFA_advance_loc %d", cfa_low); - log(indent, "Raw Data: 0x%02x", cfa_value); - cur_pc += cfa_low * fde_->cie->code_alignment_factor; - break; - case 2: - if (!LogOffsetRegisterString(indent, cfa_offset, cfa_low)) { - return false; - } - break; - case 3: - log(indent, "DW_CFA_restore register(%d)", cfa_low); - log(indent, "Raw Data: 0x%02x", cfa_value); - break; - } - if (cur_pc != old_pc) { - log(0, ""); - log(indent, "PC 0x%" PRIx64, cur_pc); - } - old_pc = cur_pc; - } - return true; -} - -// Static data. -template -bool DwarfCfa::cfa_nop(dwarf_loc_regs_t*) { - return true; -} - -template -bool DwarfCfa::cfa_set_loc(dwarf_loc_regs_t*) { - AddressType cur_pc = cur_pc_; - AddressType new_pc = operands_[0]; - if (new_pc < cur_pc) { - if (std::is_same::value) { - log(0, "Warning: PC is moving backwards: old 0x%" PRIx32 " new 0x%" PRIx32, cur_pc, new_pc); - } else { - log(0, "Warning: PC is moving backwards: old 0x%" PRIx64 " new 0x%" PRIx64, cur_pc, new_pc); - } - } - cur_pc_ = new_pc; - return true; -} - -template -bool DwarfCfa::cfa_advance_loc(dwarf_loc_regs_t*) { - cur_pc_ += operands_[0] * fde_->cie->code_alignment_factor; - return true; -} - -template -bool DwarfCfa::cfa_offset(dwarf_loc_regs_t* loc_regs) { - AddressType reg = operands_[0]; - (*loc_regs)[reg] = {.type = DWARF_LOCATION_OFFSET, .values = {operands_[1]}}; - return true; -} - -template -bool DwarfCfa::cfa_restore(dwarf_loc_regs_t* loc_regs) { - AddressType reg = operands_[0]; - if (cie_loc_regs_ == nullptr) { - log(0, "restore while processing cie"); - last_error_.code = DWARF_ERROR_ILLEGAL_STATE; - return false; - } - auto reg_entry = cie_loc_regs_->find(reg); - if (reg_entry == cie_loc_regs_->end()) { - loc_regs->erase(reg); - } else { - (*loc_regs)[reg] = reg_entry->second; - } - return true; -} - -template -bool DwarfCfa::cfa_undefined(dwarf_loc_regs_t* loc_regs) { - AddressType reg = operands_[0]; - (*loc_regs)[reg] = {.type = DWARF_LOCATION_UNDEFINED}; - return true; -} - -template -bool DwarfCfa::cfa_same_value(dwarf_loc_regs_t* loc_regs) { - AddressType reg = operands_[0]; - loc_regs->erase(reg); - return true; -} - -template -bool DwarfCfa::cfa_register(dwarf_loc_regs_t* loc_regs) { - AddressType reg = operands_[0]; - AddressType reg_dst = operands_[1]; - (*loc_regs)[reg] = {.type = DWARF_LOCATION_REGISTER, .values = {reg_dst}}; - return true; -} - -template -bool DwarfCfa::cfa_remember_state(dwarf_loc_regs_t* loc_regs) { - loc_reg_state_.push(*loc_regs); - return true; -} - -template -bool DwarfCfa::cfa_restore_state(dwarf_loc_regs_t* loc_regs) { - if (loc_reg_state_.size() == 0) { - log(0, "Warning: Attempt to restore without remember."); - return true; - } - *loc_regs = loc_reg_state_.top(); - loc_reg_state_.pop(); - return true; -} - -template -bool DwarfCfa::cfa_def_cfa(dwarf_loc_regs_t* loc_regs) { - (*loc_regs)[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {operands_[0], operands_[1]}}; - return true; -} - -template -bool DwarfCfa::cfa_def_cfa_register(dwarf_loc_regs_t* loc_regs) { - auto cfa_location = loc_regs->find(CFA_REG); - if (cfa_location == loc_regs->end() || cfa_location->second.type != DWARF_LOCATION_REGISTER) { - log(0, "Attempt to set new register, but cfa is not already set to a register."); - last_error_.code = DWARF_ERROR_ILLEGAL_STATE; - return false; - } - - cfa_location->second.values[0] = operands_[0]; - return true; -} - -template -bool DwarfCfa::cfa_def_cfa_offset(dwarf_loc_regs_t* loc_regs) { - // Changing the offset if this is not a register is illegal. - auto cfa_location = loc_regs->find(CFA_REG); - if (cfa_location == loc_regs->end() || cfa_location->second.type != DWARF_LOCATION_REGISTER) { - log(0, "Attempt to set offset, but cfa is not set to a register."); - last_error_.code = DWARF_ERROR_ILLEGAL_STATE; - return false; - } - cfa_location->second.values[1] = operands_[0]; - return true; -} - -template -bool DwarfCfa::cfa_def_cfa_expression(dwarf_loc_regs_t* loc_regs) { - // There is only one type of expression for CFA evaluation and the DWARF - // specification is unclear whether it returns the address or the - // dereferenced value. GDB expects the value, so will we. - (*loc_regs)[CFA_REG] = {.type = DWARF_LOCATION_VAL_EXPRESSION, - .values = {operands_[0], memory_->cur_offset()}}; - return true; -} - -template -bool DwarfCfa::cfa_expression(dwarf_loc_regs_t* loc_regs) { - AddressType reg = operands_[0]; - (*loc_regs)[reg] = {.type = DWARF_LOCATION_EXPRESSION, - .values = {operands_[1], memory_->cur_offset()}}; - return true; -} - -template -bool DwarfCfa::cfa_offset_extended_sf(dwarf_loc_regs_t* loc_regs) { - AddressType reg = operands_[0]; - SignedType value = static_cast(operands_[1]) * fde_->cie->data_alignment_factor; - (*loc_regs)[reg] = {.type = DWARF_LOCATION_OFFSET, .values = {static_cast(value)}}; - return true; -} - -template -bool DwarfCfa::cfa_def_cfa_sf(dwarf_loc_regs_t* loc_regs) { - SignedType offset = static_cast(operands_[1]) * fde_->cie->data_alignment_factor; - (*loc_regs)[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, - .values = {operands_[0], static_cast(offset)}}; - return true; -} - -template -bool DwarfCfa::cfa_def_cfa_offset_sf(dwarf_loc_regs_t* loc_regs) { - // Changing the offset if this is not a register is illegal. - auto cfa_location = loc_regs->find(CFA_REG); - if (cfa_location == loc_regs->end() || cfa_location->second.type != DWARF_LOCATION_REGISTER) { - log(0, "Attempt to set offset, but cfa is not set to a register."); - last_error_.code = DWARF_ERROR_ILLEGAL_STATE; - return false; - } - SignedType offset = static_cast(operands_[0]) * fde_->cie->data_alignment_factor; - cfa_location->second.values[1] = static_cast(offset); - return true; -} - -template -bool DwarfCfa::cfa_val_offset(dwarf_loc_regs_t* loc_regs) { - AddressType reg = operands_[0]; - SignedType offset = static_cast(operands_[1]) * fde_->cie->data_alignment_factor; - (*loc_regs)[reg] = {.type = DWARF_LOCATION_VAL_OFFSET, .values = {static_cast(offset)}}; - return true; -} - -template -bool DwarfCfa::cfa_val_offset_sf(dwarf_loc_regs_t* loc_regs) { - AddressType reg = operands_[0]; - SignedType offset = static_cast(operands_[1]) * fde_->cie->data_alignment_factor; - (*loc_regs)[reg] = {.type = DWARF_LOCATION_VAL_OFFSET, .values = {static_cast(offset)}}; - return true; -} - -template -bool DwarfCfa::cfa_val_expression(dwarf_loc_regs_t* loc_regs) { - AddressType reg = operands_[0]; - (*loc_regs)[reg] = {.type = DWARF_LOCATION_VAL_EXPRESSION, - .values = {operands_[1], memory_->cur_offset()}}; - return true; -} - -template -bool DwarfCfa::cfa_gnu_negative_offset_extended(dwarf_loc_regs_t* loc_regs) { - AddressType reg = operands_[0]; - SignedType offset = -static_cast(operands_[1]); - (*loc_regs)[reg] = {.type = DWARF_LOCATION_OFFSET, .values = {static_cast(offset)}}; - return true; -} - -template -bool DwarfCfa::cfa_aarch64_negate_ra_state(dwarf_loc_regs_t* loc_regs) { - // Only supported on aarch64. - if (arch_ != ARCH_ARM64) { - last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; - return false; - } - - auto cfa_location = loc_regs->find(Arm64Reg::ARM64_PREG_RA_SIGN_STATE); - if (cfa_location == loc_regs->end()) { - (*loc_regs)[Arm64Reg::ARM64_PREG_RA_SIGN_STATE] = {.type = DWARF_LOCATION_PSEUDO_REGISTER, - .values = {1}}; - } else { - cfa_location->second.values[0] ^= 1; - } - return true; -} - -const DwarfCfaInfo::Info DwarfCfaInfo::kTable[64] = { - { - // 0x00 DW_CFA_nop - "DW_CFA_nop", - 2, - 0, - {}, - {}, - }, - { - "DW_CFA_set_loc", // 0x01 DW_CFA_set_loc - 2, - 1, - {DW_EH_PE_absptr}, - {DWARF_DISPLAY_SET_LOC}, - }, - { - "DW_CFA_advance_loc1", // 0x02 DW_CFA_advance_loc1 - 2, - 1, - {DW_EH_PE_udata1}, - {DWARF_DISPLAY_ADVANCE_LOC}, - }, - { - "DW_CFA_advance_loc2", // 0x03 DW_CFA_advance_loc2 - 2, - 1, - {DW_EH_PE_udata2}, - {DWARF_DISPLAY_ADVANCE_LOC}, - }, - { - "DW_CFA_advance_loc4", // 0x04 DW_CFA_advance_loc4 - 2, - 1, - {DW_EH_PE_udata4}, - {DWARF_DISPLAY_ADVANCE_LOC}, - }, - { - "DW_CFA_offset_extended", // 0x05 DW_CFA_offset_extended - 2, - 2, - {DW_EH_PE_uleb128, DW_EH_PE_uleb128}, - {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_NUMBER}, - }, - { - "DW_CFA_restore_extended", // 0x06 DW_CFA_restore_extended - 2, - 1, - {DW_EH_PE_uleb128}, - {DWARF_DISPLAY_REGISTER}, - }, - { - "DW_CFA_undefined", // 0x07 DW_CFA_undefined - 2, - 1, - {DW_EH_PE_uleb128}, - {DWARF_DISPLAY_REGISTER}, - }, - { - "DW_CFA_same_value", // 0x08 DW_CFA_same_value - 2, - 1, - {DW_EH_PE_uleb128}, - {DWARF_DISPLAY_REGISTER}, - }, - { - "DW_CFA_register", // 0x09 DW_CFA_register - 2, - 2, - {DW_EH_PE_uleb128, DW_EH_PE_uleb128}, - {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_REGISTER}, - }, - { - "DW_CFA_remember_state", // 0x0a DW_CFA_remember_state - 2, - 0, - {}, - {}, - }, - { - "DW_CFA_restore_state", // 0x0b DW_CFA_restore_state - 2, - 0, - {}, - {}, - }, - { - "DW_CFA_def_cfa", // 0x0c DW_CFA_def_cfa - 2, - 2, - {DW_EH_PE_uleb128, DW_EH_PE_uleb128}, - {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_NUMBER}, - }, - { - "DW_CFA_def_cfa_register", // 0x0d DW_CFA_def_cfa_register - 2, - 1, - {DW_EH_PE_uleb128}, - {DWARF_DISPLAY_REGISTER}, - }, - { - "DW_CFA_def_cfa_offset", // 0x0e DW_CFA_def_cfa_offset - 2, - 1, - {DW_EH_PE_uleb128}, - {DWARF_DISPLAY_NUMBER}, - }, - { - "DW_CFA_def_cfa_expression", // 0x0f DW_CFA_def_cfa_expression - 2, - 1, - {DW_EH_PE_block}, - {DWARF_DISPLAY_EVAL_BLOCK}, - }, - { - "DW_CFA_expression", // 0x10 DW_CFA_expression - 2, - 2, - {DW_EH_PE_uleb128, DW_EH_PE_block}, - {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_EVAL_BLOCK}, - }, - { - "DW_CFA_offset_extended_sf", // 0x11 DW_CFA_offset_extend_sf - 2, - 2, - {DW_EH_PE_uleb128, DW_EH_PE_sleb128}, - {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_SIGNED_NUMBER}, - }, - { - "DW_CFA_def_cfa_sf", // 0x12 DW_CFA_def_cfa_sf - 2, - 2, - {DW_EH_PE_uleb128, DW_EH_PE_sleb128}, - {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_SIGNED_NUMBER}, - }, - { - "DW_CFA_def_cfa_offset_sf", // 0x13 DW_CFA_def_cfa_offset_sf - 2, - 1, - {DW_EH_PE_sleb128}, - {DWARF_DISPLAY_SIGNED_NUMBER}, - }, - { - "DW_CFA_val_offset", // 0x14 DW_CFA_val_offset - 2, - 2, - {DW_EH_PE_uleb128, DW_EH_PE_uleb128}, - {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_NUMBER}, - }, - { - "DW_CFA_val_offset_sf", // 0x15 DW_CFA_val_offset_sf - 2, - 2, - {DW_EH_PE_uleb128, DW_EH_PE_sleb128}, - {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_SIGNED_NUMBER}, - }, - { - "DW_CFA_val_expression", // 0x16 DW_CFA_val_expression - 2, - 2, - {DW_EH_PE_uleb128, DW_EH_PE_block}, - {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_EVAL_BLOCK}, - }, - {"", 0, 0, {}, {}}, // 0x17 illegal cfa - {"", 0, 0, {}, {}}, // 0x18 illegal cfa - {"", 0, 0, {}, {}}, // 0x19 illegal cfa - {"", 0, 0, {}, {}}, // 0x1a illegal cfa - {"", 0, 0, {}, {}}, // 0x1b illegal cfa - {"", 0, 0, {}, {}}, // 0x1c DW_CFA_lo_user (Treat as illegal) - {"", 0, 0, {}, {}}, // 0x1d illegal cfa - {"", 0, 0, {}, {}}, // 0x1e illegal cfa - {"", 0, 0, {}, {}}, // 0x1f illegal cfa - {"", 0, 0, {}, {}}, // 0x20 illegal cfa - {"", 0, 0, {}, {}}, // 0x21 illegal cfa - {"", 0, 0, {}, {}}, // 0x22 illegal cfa - {"", 0, 0, {}, {}}, // 0x23 illegal cfa - {"", 0, 0, {}, {}}, // 0x24 illegal cfa - {"", 0, 0, {}, {}}, // 0x25 illegal cfa - {"", 0, 0, {}, {}}, // 0x26 illegal cfa - {"", 0, 0, {}, {}}, // 0x27 illegal cfa - {"", 0, 0, {}, {}}, // 0x28 illegal cfa - {"", 0, 0, {}, {}}, // 0x29 illegal cfa - {"", 0, 0, {}, {}}, // 0x2a illegal cfa - {"", 0, 0, {}, {}}, // 0x2b illegal cfa - {"", 0, 0, {}, {}}, // 0x2c illegal cfa - { - "DW_CFA_AARCH64_negate_ra_state", // 0x2d DW_CFA_AARCH64_negate_ra_state - 3, - 0, - {}, - {}, - }, - { - "DW_CFA_GNU_args_size", // 0x2e DW_CFA_GNU_args_size - 2, - 1, - {DW_EH_PE_uleb128}, - {DWARF_DISPLAY_NUMBER}, - }, - { - "DW_CFA_GNU_negative_offset_extended", // 0x2f DW_CFA_GNU_negative_offset_extended - 2, - 2, - {DW_EH_PE_uleb128, DW_EH_PE_uleb128}, - {DWARF_DISPLAY_REGISTER, DWARF_DISPLAY_NUMBER}, - }, - {"", 0, 0, {}, {}}, // 0x31 illegal cfa - {"", 0, 0, {}, {}}, // 0x32 illegal cfa - {"", 0, 0, {}, {}}, // 0x33 illegal cfa - {"", 0, 0, {}, {}}, // 0x34 illegal cfa - {"", 0, 0, {}, {}}, // 0x35 illegal cfa - {"", 0, 0, {}, {}}, // 0x36 illegal cfa - {"", 0, 0, {}, {}}, // 0x37 illegal cfa - {"", 0, 0, {}, {}}, // 0x38 illegal cfa - {"", 0, 0, {}, {}}, // 0x39 illegal cfa - {"", 0, 0, {}, {}}, // 0x3a illegal cfa - {"", 0, 0, {}, {}}, // 0x3b illegal cfa - {"", 0, 0, {}, {}}, // 0x3c illegal cfa - {"", 0, 0, {}, {}}, // 0x3d illegal cfa - {"", 0, 0, {}, {}}, // 0x3e illegal cfa - {"", 0, 0, {}, {}}, // 0x3f DW_CFA_hi_user (Treat as illegal) -}; - -// Explicitly instantiate DwarfCfa. -template class DwarfCfa; -template class DwarfCfa; - -} // namespace unwindstack diff --git a/libunwindstack/DwarfCfa.h b/libunwindstack/DwarfCfa.h deleted file mode 100644 index d627e156b..000000000 --- a/libunwindstack/DwarfCfa.h +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (C) 2016 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_DWARF_CFA_H -#define _LIBUNWINDSTACK_DWARF_CFA_H - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -namespace unwindstack { - -// Forward declarations. -enum ArchEnum : uint8_t; - -// DWARF Standard home: http://dwarfstd.org/ -// This code is based on DWARF 4: http://http://dwarfstd.org/doc/DWARF4.pdf -// See section 6.4.2.1 for a description of the DW_CFA_xxx values. - -class DwarfCfaInfo { - public: - enum DisplayType : uint8_t { - DWARF_DISPLAY_NONE = 0, - DWARF_DISPLAY_REGISTER, - DWARF_DISPLAY_NUMBER, - DWARF_DISPLAY_SIGNED_NUMBER, - DWARF_DISPLAY_EVAL_BLOCK, - DWARF_DISPLAY_ADDRESS, - DWARF_DISPLAY_SET_LOC, - DWARF_DISPLAY_ADVANCE_LOC, - }; - - struct Info { - // It may seem cleaner to just change the type of 'name' to 'const char *'. - // However, having a pointer here would require relocation at runtime, - // causing 'kTable' to be placed in data.rel.ro section instead of rodata - // section, adding memory pressure to the system. Note that this is only - // safe because this is only used in C++ code. C++ standard, unlike C - // standard, mandates the array size to be large enough to hold the NULL - // terminator when initialized with a string literal. - const char name[36]; - uint8_t supported_version; - uint8_t num_operands; - uint8_t operands[2]; - uint8_t display_operands[2]; - }; - - const static Info kTable[64]; -}; - -template -class DwarfCfa { - // Signed version of AddressType - typedef typename std::make_signed::type SignedType; - - public: - DwarfCfa(DwarfMemory* memory, const DwarfFde* fde, ArchEnum arch) - : memory_(memory), fde_(fde), arch_(arch) {} - virtual ~DwarfCfa() = default; - - bool GetLocationInfo(uint64_t pc, uint64_t start_offset, uint64_t end_offset, - dwarf_loc_regs_t* loc_regs); - - bool Log(uint32_t indent, uint64_t pc, uint64_t start_offset, uint64_t end_offset); - - const DwarfErrorData& last_error() { return last_error_; } - DwarfErrorCode LastErrorCode() { return last_error_.code; } - uint64_t LastErrorAddress() { return last_error_.address; } - - AddressType cur_pc() { return cur_pc_; } - - void set_cie_loc_regs(const dwarf_loc_regs_t* cie_loc_regs) { cie_loc_regs_ = cie_loc_regs; } - - protected: - std::string GetOperandString(uint8_t operand, uint64_t value, uint64_t* cur_pc); - - bool LogOffsetRegisterString(uint32_t indent, uint64_t cfa_offset, uint8_t reg); - - bool LogInstruction(uint32_t indent, uint64_t cfa_offset, uint8_t op, uint64_t* cur_pc); - - private: - DwarfErrorData last_error_; - DwarfMemory* memory_; - const DwarfFde* fde_; - ArchEnum arch_; - - AddressType cur_pc_; - const dwarf_loc_regs_t* cie_loc_regs_ = nullptr; - std::vector operands_; - std::stack loc_reg_state_; - - // CFA processing functions. - bool cfa_nop(dwarf_loc_regs_t*); - bool cfa_set_loc(dwarf_loc_regs_t*); - bool cfa_advance_loc(dwarf_loc_regs_t*); - bool cfa_offset(dwarf_loc_regs_t*); - bool cfa_restore(dwarf_loc_regs_t*); - bool cfa_undefined(dwarf_loc_regs_t*); - bool cfa_same_value(dwarf_loc_regs_t*); - bool cfa_register(dwarf_loc_regs_t*); - bool cfa_remember_state(dwarf_loc_regs_t*); - bool cfa_restore_state(dwarf_loc_regs_t*); - bool cfa_def_cfa(dwarf_loc_regs_t*); - bool cfa_def_cfa_register(dwarf_loc_regs_t*); - bool cfa_def_cfa_offset(dwarf_loc_regs_t*); - bool cfa_def_cfa_expression(dwarf_loc_regs_t*); - bool cfa_expression(dwarf_loc_regs_t*); - bool cfa_offset_extended_sf(dwarf_loc_regs_t*); - bool cfa_def_cfa_sf(dwarf_loc_regs_t*); - bool cfa_def_cfa_offset_sf(dwarf_loc_regs_t*); - bool cfa_val_offset(dwarf_loc_regs_t*); - bool cfa_val_offset_sf(dwarf_loc_regs_t*); - bool cfa_val_expression(dwarf_loc_regs_t*); - bool cfa_gnu_negative_offset_extended(dwarf_loc_regs_t*); - bool cfa_aarch64_negate_ra_state(dwarf_loc_regs_t*); - - using process_func = bool (DwarfCfa::*)(dwarf_loc_regs_t*); - constexpr static process_func kCallbackTable[64] = { - // 0x00 DW_CFA_nop - &DwarfCfa::cfa_nop, - // 0x01 DW_CFA_set_loc - &DwarfCfa::cfa_set_loc, - // 0x02 DW_CFA_advance_loc1 - &DwarfCfa::cfa_advance_loc, - // 0x03 DW_CFA_advance_loc2 - &DwarfCfa::cfa_advance_loc, - // 0x04 DW_CFA_advance_loc4 - &DwarfCfa::cfa_advance_loc, - // 0x05 DW_CFA_offset_extended - &DwarfCfa::cfa_offset, - // 0x06 DW_CFA_restore_extended - &DwarfCfa::cfa_restore, - // 0x07 DW_CFA_undefined - &DwarfCfa::cfa_undefined, - // 0x08 DW_CFA_same_value - &DwarfCfa::cfa_same_value, - // 0x09 DW_CFA_register - &DwarfCfa::cfa_register, - // 0x0a DW_CFA_remember_state - &DwarfCfa::cfa_remember_state, - // 0x0b DW_CFA_restore_state - &DwarfCfa::cfa_restore_state, - // 0x0c DW_CFA_def_cfa - &DwarfCfa::cfa_def_cfa, - // 0x0d DW_CFA_def_cfa_register - &DwarfCfa::cfa_def_cfa_register, - // 0x0e DW_CFA_def_cfa_offset - &DwarfCfa::cfa_def_cfa_offset, - // 0x0f DW_CFA_def_cfa_expression - &DwarfCfa::cfa_def_cfa_expression, - // 0x10 DW_CFA_expression - &DwarfCfa::cfa_expression, - // 0x11 DW_CFA_offset_extended_sf - &DwarfCfa::cfa_offset_extended_sf, - // 0x12 DW_CFA_def_cfa_sf - &DwarfCfa::cfa_def_cfa_sf, - // 0x13 DW_CFA_def_cfa_offset_sf - &DwarfCfa::cfa_def_cfa_offset_sf, - // 0x14 DW_CFA_val_offset - &DwarfCfa::cfa_val_offset, - // 0x15 DW_CFA_val_offset_sf - &DwarfCfa::cfa_val_offset_sf, - // 0x16 DW_CFA_val_expression - &DwarfCfa::cfa_val_expression, - // 0x17 illegal cfa - nullptr, - // 0x18 illegal cfa - nullptr, - // 0x19 illegal cfa - nullptr, - // 0x1a illegal cfa - nullptr, - // 0x1b illegal cfa - nullptr, - // 0x1c DW_CFA_lo_user (Treat this as illegal) - nullptr, - // 0x1d illegal cfa - nullptr, - // 0x1e illegal cfa - nullptr, - // 0x1f illegal cfa - nullptr, - // 0x20 illegal cfa - nullptr, - // 0x21 illegal cfa - nullptr, - // 0x22 illegal cfa - nullptr, - // 0x23 illegal cfa - nullptr, - // 0x24 illegal cfa - nullptr, - // 0x25 illegal cfa - nullptr, - // 0x26 illegal cfa - nullptr, - // 0x27 illegal cfa - nullptr, - // 0x28 illegal cfa - nullptr, - // 0x29 illegal cfa - nullptr, - // 0x2a illegal cfa - nullptr, - // 0x2b illegal cfa - nullptr, - // 0x2c illegal cfa - nullptr, - // 0x2d DW_CFA_AARCH64_negate_ra_state (aarch64 only) - // DW_CFA_GNU_window_save on other architectures. - &DwarfCfa::cfa_aarch64_negate_ra_state, - // 0x2e DW_CFA_GNU_args_size - &DwarfCfa::cfa_nop, - // 0x2f DW_CFA_GNU_negative_offset_extended - &DwarfCfa::cfa_gnu_negative_offset_extended, - // 0x30 illegal cfa - nullptr, - // 0x31 illegal cfa - nullptr, - // 0x32 illegal cfa - nullptr, - // 0x33 illegal cfa - nullptr, - // 0x34 illegal cfa - nullptr, - // 0x35 illegal cfa - nullptr, - // 0x36 illegal cfa - nullptr, - // 0x37 illegal cfa - nullptr, - // 0x38 illegal cfa - nullptr, - // 0x39 illegal cfa - nullptr, - // 0x3a illegal cfa - nullptr, - // 0x3b illegal cfa - nullptr, - // 0x3c illegal cfa - nullptr, - // 0x3d illegal cfa - nullptr, - // 0x3e illegal cfa - nullptr, - // 0x3f DW_CFA_hi_user (Treat this as illegal) - nullptr, - }; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_DWARF_CFA_H diff --git a/libunwindstack/DwarfDebugFrame.h b/libunwindstack/DwarfDebugFrame.h deleted file mode 100644 index 635cefdf2..000000000 --- a/libunwindstack/DwarfDebugFrame.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2017 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_DWARF_DEBUG_FRAME_H -#define _LIBUNWINDSTACK_DWARF_DEBUG_FRAME_H - -#include - -#include - -#include - -namespace unwindstack { - -template -class DwarfDebugFrame : public DwarfSectionImpl { - public: - DwarfDebugFrame(Memory* memory) : DwarfSectionImpl(memory) { - this->cie32_value_ = static_cast(-1); - this->cie64_value_ = static_cast(-1); - } - virtual ~DwarfDebugFrame() = default; - - uint64_t GetCieOffsetFromFde32(uint32_t pointer) override { - return this->entries_offset_ + pointer; - } - - uint64_t GetCieOffsetFromFde64(uint64_t pointer) override { - return this->entries_offset_ + pointer; - } - - uint64_t AdjustPcFromFde(uint64_t pc) override { return pc; } -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_DWARF_DEBUG_FRAME_H diff --git a/libunwindstack/DwarfEhFrame.h b/libunwindstack/DwarfEhFrame.h deleted file mode 100644 index 7a41e4550..000000000 --- a/libunwindstack/DwarfEhFrame.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2016 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_DWARF_EH_FRAME_H -#define _LIBUNWINDSTACK_DWARF_EH_FRAME_H - -#include - -#include -#include - -namespace unwindstack { - -template -class DwarfEhFrame : public DwarfSectionImpl { - public: - DwarfEhFrame(Memory* memory) : DwarfSectionImpl(memory) {} - virtual ~DwarfEhFrame() = default; - - uint64_t GetCieOffsetFromFde32(uint32_t pointer) override { - return this->memory_.cur_offset() - pointer - 4; - } - - uint64_t GetCieOffsetFromFde64(uint64_t pointer) override { - return this->memory_.cur_offset() - pointer - 8; - } - - uint64_t AdjustPcFromFde(uint64_t pc) override { - // The eh_frame uses relative pcs. - return pc + this->memory_.cur_offset() - 4; - } -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_DWARF_EH_FRAME_H diff --git a/libunwindstack/DwarfEhFrameWithHdr.cpp b/libunwindstack/DwarfEhFrameWithHdr.cpp deleted file mode 100644 index 1358e51de..000000000 --- a/libunwindstack/DwarfEhFrameWithHdr.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (C) 2017 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 "Check.h" -#include "DwarfEhFrameWithHdr.h" -#include "DwarfEncoding.h" - -namespace unwindstack { - -static inline bool IsEncodingRelative(uint8_t encoding) { - encoding >>= 4; - return encoding > 0 && encoding <= DW_EH_PE_funcrel; -} - -template -bool DwarfEhFrameWithHdr::EhFrameInit(uint64_t offset, uint64_t size, - int64_t section_bias) { - return DwarfSectionImpl::Init(offset, size, section_bias); -} - -template -bool DwarfEhFrameWithHdr::Init(uint64_t offset, uint64_t, int64_t section_bias) { - memory_.clear_func_offset(); - memory_.clear_text_offset(); - memory_.set_data_offset(offset); - memory_.set_cur_offset(offset); - - hdr_section_bias_ = section_bias; - - // Read the first four bytes all at once. - uint8_t data[4]; - if (!memory_.ReadBytes(data, 4)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - - version_ = data[0]; - if (version_ != 1) { - // Unknown version. - last_error_.code = DWARF_ERROR_UNSUPPORTED_VERSION; - return false; - } - - uint8_t ptr_encoding = data[1]; - uint8_t fde_count_encoding = data[2]; - table_encoding_ = data[3]; - table_entry_size_ = memory_.template GetEncodedSize(table_encoding_); - - // If we can't perform a binary search on the entries, it's not worth - // using this object. The calling code will fall back to the DwarfEhFrame - // object in this case. - if (table_entry_size_ == 0) { - last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; - return false; - } - - memory_.set_pc_offset(memory_.cur_offset()); - uint64_t ptr_offset; - if (!memory_.template ReadEncodedValue(ptr_encoding, &ptr_offset)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - - memory_.set_pc_offset(memory_.cur_offset()); - if (!memory_.template ReadEncodedValue(fde_count_encoding, &fde_count_)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - - if (fde_count_ == 0) { - last_error_.code = DWARF_ERROR_NO_FDES; - return false; - } - - hdr_entries_offset_ = memory_.cur_offset(); - hdr_entries_data_offset_ = offset; - - return true; -} - -template -const DwarfFde* DwarfEhFrameWithHdr::GetFdeFromPc(uint64_t pc) { - uint64_t fde_offset; - if (!GetFdeOffsetFromPc(pc, &fde_offset)) { - return nullptr; - } - const DwarfFde* fde = this->GetFdeFromOffset(fde_offset); - if (fde == nullptr) { - return nullptr; - } - - // There is a possibility that this entry points to a zero length FDE - // due to a bug. If this happens, try and find the non-zero length FDE - // from eh_frame directly. See b/142483624. - if (fde->pc_start == fde->pc_end) { - fde = DwarfSectionImpl::GetFdeFromPc(pc); - if (fde == nullptr) { - return nullptr; - } - } - - // Guaranteed pc >= pc_start, need to check pc in the fde range. - if (pc < fde->pc_end) { - return fde; - } - last_error_.code = DWARF_ERROR_ILLEGAL_STATE; - return nullptr; -} - -template -const typename DwarfEhFrameWithHdr::FdeInfo* -DwarfEhFrameWithHdr::GetFdeInfoFromIndex(size_t index) { - auto entry = fde_info_.find(index); - if (entry != fde_info_.end()) { - return &fde_info_[index]; - } - FdeInfo* info = &fde_info_[index]; - - memory_.set_data_offset(hdr_entries_data_offset_); - memory_.set_cur_offset(hdr_entries_offset_ + 2 * index * table_entry_size_); - memory_.set_pc_offset(0); - uint64_t value; - if (!memory_.template ReadEncodedValue(table_encoding_, &value) || - !memory_.template ReadEncodedValue(table_encoding_, &info->offset)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - fde_info_.erase(index); - return nullptr; - } - - // Relative encodings require adding in the load bias. - if (IsEncodingRelative(table_encoding_)) { - value += hdr_section_bias_; - } - info->pc = value; - return info; -} - -template -bool DwarfEhFrameWithHdr::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) { - if (fde_count_ == 0) { - return false; - } - - size_t first = 0; - size_t last = fde_count_; - while (first < last) { - size_t current = (first + last) / 2; - const FdeInfo* info = GetFdeInfoFromIndex(current); - if (info == nullptr) { - return false; - } - if (pc == info->pc) { - *fde_offset = info->offset; - return true; - } - if (pc < info->pc) { - last = current; - } else { - first = current + 1; - } - } - if (last != 0) { - const FdeInfo* info = GetFdeInfoFromIndex(last - 1); - if (info == nullptr) { - return false; - } - *fde_offset = info->offset; - return true; - } - return false; -} - -template -void DwarfEhFrameWithHdr::GetFdes(std::vector* fdes) { - for (size_t i = 0; i < fde_count_; i++) { - const FdeInfo* info = GetFdeInfoFromIndex(i); - if (info == nullptr) { - break; - } - const DwarfFde* fde = this->GetFdeFromOffset(info->offset); - if (fde == nullptr) { - break; - } - - // There is a possibility that this entry points to a zero length FDE - // due to a bug. If this happens, try and find the non-zero length FDE - // from eh_frame directly. See b/142483624. - if (fde->pc_start == fde->pc_end) { - const DwarfFde* fde_real = DwarfSectionImpl::GetFdeFromPc(fde->pc_start); - if (fde_real != nullptr) { - fde = fde_real; - } - } - fdes->push_back(fde); - } -} - -// Explicitly instantiate DwarfEhFrameWithHdr -template class DwarfEhFrameWithHdr; -template class DwarfEhFrameWithHdr; - -} // namespace unwindstack diff --git a/libunwindstack/DwarfEhFrameWithHdr.h b/libunwindstack/DwarfEhFrameWithHdr.h deleted file mode 100644 index f7c010ce4..000000000 --- a/libunwindstack/DwarfEhFrameWithHdr.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2016 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_DWARF_EH_FRAME_WITH_HDR_H -#define _LIBUNWINDSTACK_DWARF_EH_FRAME_WITH_HDR_H - -#include - -#include - -#include - -namespace unwindstack { - -// Forward declarations. -class Memory; - -template -class DwarfEhFrameWithHdr : public DwarfSectionImpl { - public: - // Add these so that the protected members of DwarfSectionImpl - // can be accessed without needing a this->. - using DwarfSectionImpl::memory_; - using DwarfSectionImpl::last_error_; - - struct FdeInfo { - AddressType pc; - uint64_t offset; - }; - - DwarfEhFrameWithHdr(Memory* memory) : DwarfSectionImpl(memory) {} - virtual ~DwarfEhFrameWithHdr() = default; - - uint64_t GetCieOffsetFromFde32(uint32_t pointer) override { - return memory_.cur_offset() - pointer - 4; - } - - uint64_t GetCieOffsetFromFde64(uint64_t pointer) override { - return memory_.cur_offset() - pointer - 8; - } - - uint64_t AdjustPcFromFde(uint64_t pc) override { - // The eh_frame uses relative pcs. - return pc + memory_.cur_offset() - 4; - } - - bool EhFrameInit(uint64_t offset, uint64_t size, int64_t section_bias); - bool Init(uint64_t offset, uint64_t size, int64_t section_bias) override; - - const DwarfFde* GetFdeFromPc(uint64_t pc) override; - - bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset); - - const FdeInfo* GetFdeInfoFromIndex(size_t index); - - void GetFdes(std::vector* fdes) override; - - protected: - uint8_t version_ = 0; - uint8_t table_encoding_ = 0; - size_t table_entry_size_ = 0; - - uint64_t hdr_entries_offset_ = 0; - uint64_t hdr_entries_data_offset_ = 0; - uint64_t hdr_section_bias_ = 0; - - uint64_t fde_count_ = 0; - std::unordered_map fde_info_; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_DWARF_EH_FRAME_WITH_HDR_H diff --git a/libunwindstack/DwarfEncoding.h b/libunwindstack/DwarfEncoding.h deleted file mode 100644 index 20db2221f..000000000 --- a/libunwindstack/DwarfEncoding.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2016 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_DWARF_ENCODING_H -#define _LIBUNWINDSTACK_DWARF_ENCODING_H - -#include - -namespace unwindstack { - -enum DwarfEncoding : uint8_t { - DW_EH_PE_omit = 0xff, - - DW_EH_PE_absptr = 0x00, - DW_EH_PE_uleb128 = 0x01, - DW_EH_PE_udata2 = 0x02, - DW_EH_PE_udata4 = 0x03, - DW_EH_PE_udata8 = 0x04, - DW_EH_PE_sleb128 = 0x09, - DW_EH_PE_sdata2 = 0x0a, - DW_EH_PE_sdata4 = 0x0b, - DW_EH_PE_sdata8 = 0x0c, - - DW_EH_PE_pcrel = 0x10, - DW_EH_PE_textrel = 0x20, - DW_EH_PE_datarel = 0x30, - DW_EH_PE_funcrel = 0x40, - DW_EH_PE_aligned = 0x50, - - // The following are special values used to encode CFA and OP operands. - DW_EH_PE_udata1 = 0x0d, - DW_EH_PE_sdata1 = 0x0e, - DW_EH_PE_block = 0x0f, -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_DWARF_ENCODING_H diff --git a/libunwindstack/DwarfMemory.cpp b/libunwindstack/DwarfMemory.cpp deleted file mode 100644 index 2e388c689..000000000 --- a/libunwindstack/DwarfMemory.cpp +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright (C) 2017 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 "Check.h" -#include "DwarfEncoding.h" - -namespace unwindstack { - -bool DwarfMemory::ReadBytes(void* dst, size_t num_bytes) { - if (!memory_->ReadFully(cur_offset_, dst, num_bytes)) { - return false; - } - cur_offset_ += num_bytes; - return true; -} - -template -bool DwarfMemory::ReadSigned(uint64_t* value) { - SignedType signed_value; - if (!ReadBytes(&signed_value, sizeof(SignedType))) { - return false; - } - *value = static_cast(signed_value); - return true; -} - -bool DwarfMemory::ReadULEB128(uint64_t* value) { - uint64_t cur_value = 0; - uint64_t shift = 0; - uint8_t byte; - do { - if (!ReadBytes(&byte, 1)) { - return false; - } - cur_value += static_cast(byte & 0x7f) << shift; - shift += 7; - } while (byte & 0x80); - *value = cur_value; - return true; -} - -bool DwarfMemory::ReadSLEB128(int64_t* value) { - uint64_t cur_value = 0; - uint64_t shift = 0; - uint8_t byte; - do { - if (!ReadBytes(&byte, 1)) { - return false; - } - cur_value += static_cast(byte & 0x7f) << shift; - shift += 7; - } while (byte & 0x80); - if (byte & 0x40) { - // Negative value, need to sign extend. - cur_value |= static_cast(-1) << shift; - } - *value = static_cast(cur_value); - return true; -} - -template -size_t DwarfMemory::GetEncodedSize(uint8_t encoding) { - switch (encoding & 0x0f) { - case DW_EH_PE_absptr: - return sizeof(AddressType); - case DW_EH_PE_udata1: - case DW_EH_PE_sdata1: - return 1; - case DW_EH_PE_udata2: - case DW_EH_PE_sdata2: - return 2; - case DW_EH_PE_udata4: - case DW_EH_PE_sdata4: - return 4; - case DW_EH_PE_udata8: - case DW_EH_PE_sdata8: - return 8; - case DW_EH_PE_uleb128: - case DW_EH_PE_sleb128: - default: - return 0; - } -} - -bool DwarfMemory::AdjustEncodedValue(uint8_t encoding, uint64_t* value) { - CHECK((encoding & 0x0f) == 0); - - // Handle the encoding. - switch (encoding) { - case DW_EH_PE_absptr: - // Nothing to do. - break; - case DW_EH_PE_pcrel: - if (pc_offset_ == INT64_MAX) { - // Unsupported encoding. - return false; - } - *value += pc_offset_; - break; - case DW_EH_PE_textrel: - if (text_offset_ == static_cast(-1)) { - // Unsupported encoding. - return false; - } - *value += text_offset_; - break; - case DW_EH_PE_datarel: - if (data_offset_ == static_cast(-1)) { - // Unsupported encoding. - return false; - } - *value += data_offset_; - break; - case DW_EH_PE_funcrel: - if (func_offset_ == static_cast(-1)) { - // Unsupported encoding. - return false; - } - *value += func_offset_; - break; - default: - return false; - } - - return true; -} - -template -bool DwarfMemory::ReadEncodedValue(uint8_t encoding, uint64_t* value) { - if (encoding == DW_EH_PE_omit) { - *value = 0; - return true; - } else if (encoding == DW_EH_PE_aligned) { - if (__builtin_add_overflow(cur_offset_, sizeof(AddressType) - 1, &cur_offset_)) { - return false; - } - cur_offset_ &= -sizeof(AddressType); - - if (sizeof(AddressType) != sizeof(uint64_t)) { - *value = 0; - } - return ReadBytes(value, sizeof(AddressType)); - } - - // Get the data. - switch (encoding & 0x0f) { - case DW_EH_PE_absptr: - if (sizeof(AddressType) != sizeof(uint64_t)) { - *value = 0; - } - if (!ReadBytes(value, sizeof(AddressType))) { - return false; - } - break; - case DW_EH_PE_uleb128: - if (!ReadULEB128(value)) { - return false; - } - break; - case DW_EH_PE_sleb128: - int64_t signed_value; - if (!ReadSLEB128(&signed_value)) { - return false; - } - *value = static_cast(signed_value); - break; - case DW_EH_PE_udata1: { - uint8_t value8; - if (!ReadBytes(&value8, 1)) { - return false; - } - *value = value8; - } break; - case DW_EH_PE_sdata1: - if (!ReadSigned(value)) { - return false; - } - break; - case DW_EH_PE_udata2: { - uint16_t value16; - if (!ReadBytes(&value16, 2)) { - return false; - } - *value = value16; - } break; - case DW_EH_PE_sdata2: - if (!ReadSigned(value)) { - return false; - } - break; - case DW_EH_PE_udata4: { - uint32_t value32; - if (!ReadBytes(&value32, 4)) { - return false; - } - *value = value32; - } break; - case DW_EH_PE_sdata4: - if (!ReadSigned(value)) { - return false; - } - break; - case DW_EH_PE_udata8: - if (!ReadBytes(value, sizeof(uint64_t))) { - return false; - } - break; - case DW_EH_PE_sdata8: - if (!ReadSigned(value)) { - return false; - } - break; - default: - return false; - } - - return AdjustEncodedValue(encoding & 0x70, value); -} - -// Instantiate all of the needed template functions. -template bool DwarfMemory::ReadSigned(uint64_t*); -template bool DwarfMemory::ReadSigned(uint64_t*); -template bool DwarfMemory::ReadSigned(uint64_t*); -template bool DwarfMemory::ReadSigned(uint64_t*); - -template size_t DwarfMemory::GetEncodedSize(uint8_t); -template size_t DwarfMemory::GetEncodedSize(uint8_t); - -template bool DwarfMemory::ReadEncodedValue(uint8_t, uint64_t*); -template bool DwarfMemory::ReadEncodedValue(uint8_t, uint64_t*); - -} // namespace unwindstack diff --git a/libunwindstack/DwarfOp.cpp b/libunwindstack/DwarfOp.cpp deleted file mode 100644 index 393eb3efc..000000000 --- a/libunwindstack/DwarfOp.cpp +++ /dev/null @@ -1,1941 +0,0 @@ -/* - * Copyright (C) 2017 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 "DwarfOp.h" - -namespace unwindstack { - -enum DwarfOpHandleFunc : uint8_t { - OP_ILLEGAL = 0, - OP_DEREF, - OP_DEREF_SIZE, - OP_PUSH, - OP_DUP, - OP_DROP, - OP_OVER, - OP_PICK, - OP_SWAP, - OP_ROT, - OP_ABS, - OP_AND, - OP_DIV, - OP_MINUS, - OP_MOD, - OP_MUL, - OP_NEG, - OP_NOT, - OP_OR, - OP_PLUS, - OP_PLUS_UCONST, - OP_SHL, - OP_SHR, - OP_SHRA, - OP_XOR, - OP_BRA, - OP_EQ, - OP_GE, - OP_GT, - OP_LE, - OP_LT, - OP_NE, - OP_SKIP, - OP_LIT, - OP_REG, - OP_REGX, - OP_BREG, - OP_BREGX, - OP_NOP, - OP_NOT_IMPLEMENTED, -}; - -struct OpCallback { - // It may seem tempting to "clean this up" by replacing "const char[26]" with - // "const char*", but doing so would place the entire callback table in - // .data.rel.ro section, instead of .rodata section, and thus increase - // dirty memory usage. Libunwindstack is used by the linker and therefore - // loaded for every running process, so every bit of memory counts. - // Unlike C standard, C++ standard guarantees this array is big enough to - // store the names, or else we would get a compilation error. - const char name[26]; - - // Similarily for this field, we do NOT want to directly store function - // pointers here. Not only would that cause the callback table to be placed - // in .data.rel.ro section, but it would be duplicated for each AddressType. - // Instead, we use DwarfOpHandleFunc enum to decouple the callback table from - // the function pointers. - DwarfOpHandleFunc handle_func; - - uint8_t num_required_stack_values; - uint8_t num_operands; - uint8_t operands[2]; -}; - -constexpr static OpCallback kCallbackTable[256] = { - {"", OP_ILLEGAL, 0, 0, {}}, // 0x00 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0x01 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0x02 illegal op - { - // 0x03 DW_OP_addr - "DW_OP_addr", - OP_PUSH, - 0, - 1, - {DW_EH_PE_absptr}, - }, - {"", OP_ILLEGAL, 0, 0, {}}, // 0x04 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0x05 illegal op - { - // 0x06 DW_OP_deref - "DW_OP_deref", - OP_DEREF, - 1, - 0, - {}, - }, - {"", OP_ILLEGAL, 0, 0, {}}, // 0x07 illegal op - { - // 0x08 DW_OP_const1u - "DW_OP_const1u", - OP_PUSH, - 0, - 1, - {DW_EH_PE_udata1}, - }, - { - // 0x09 DW_OP_const1s - "DW_OP_const1s", - OP_PUSH, - 0, - 1, - {DW_EH_PE_sdata1}, - }, - { - // 0x0a DW_OP_const2u - "DW_OP_const2u", - OP_PUSH, - 0, - 1, - {DW_EH_PE_udata2}, - }, - { - // 0x0b DW_OP_const2s - "DW_OP_const2s", - OP_PUSH, - 0, - 1, - {DW_EH_PE_sdata2}, - }, - { - // 0x0c DW_OP_const4u - "DW_OP_const4u", - OP_PUSH, - 0, - 1, - {DW_EH_PE_udata4}, - }, - { - // 0x0d DW_OP_const4s - "DW_OP_const4s", - OP_PUSH, - 0, - 1, - {DW_EH_PE_sdata4}, - }, - { - // 0x0e DW_OP_const8u - "DW_OP_const8u", - OP_PUSH, - 0, - 1, - {DW_EH_PE_udata8}, - }, - { - // 0x0f DW_OP_const8s - "DW_OP_const8s", - OP_PUSH, - 0, - 1, - {DW_EH_PE_sdata8}, - }, - { - // 0x10 DW_OP_constu - "DW_OP_constu", - OP_PUSH, - 0, - 1, - {DW_EH_PE_uleb128}, - }, - { - // 0x11 DW_OP_consts - "DW_OP_consts", - OP_PUSH, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x12 DW_OP_dup - "DW_OP_dup", - OP_DUP, - 1, - 0, - {}, - }, - { - // 0x13 DW_OP_drop - "DW_OP_drop", - OP_DROP, - 1, - 0, - {}, - }, - { - // 0x14 DW_OP_over - "DW_OP_over", - OP_OVER, - 2, - 0, - {}, - }, - { - // 0x15 DW_OP_pick - "DW_OP_pick", - OP_PICK, - 0, - 1, - {DW_EH_PE_udata1}, - }, - { - // 0x16 DW_OP_swap - "DW_OP_swap", - OP_SWAP, - 2, - 0, - {}, - }, - { - // 0x17 DW_OP_rot - "DW_OP_rot", - OP_ROT, - 3, - 0, - {}, - }, - { - // 0x18 DW_OP_xderef - "DW_OP_xderef", - OP_NOT_IMPLEMENTED, - 2, - 0, - {}, - }, - { - // 0x19 DW_OP_abs - "DW_OP_abs", - OP_ABS, - 1, - 0, - {}, - }, - { - // 0x1a DW_OP_and - "DW_OP_and", - OP_AND, - 2, - 0, - {}, - }, - { - // 0x1b DW_OP_div - "DW_OP_div", - OP_DIV, - 2, - 0, - {}, - }, - { - // 0x1c DW_OP_minus - "DW_OP_minus", - OP_MINUS, - 2, - 0, - {}, - }, - { - // 0x1d DW_OP_mod - "DW_OP_mod", - OP_MOD, - 2, - 0, - {}, - }, - { - // 0x1e DW_OP_mul - "DW_OP_mul", - OP_MUL, - 2, - 0, - {}, - }, - { - // 0x1f DW_OP_neg - "DW_OP_neg", - OP_NEG, - 1, - 0, - {}, - }, - { - // 0x20 DW_OP_not - "DW_OP_not", - OP_NOT, - 1, - 0, - {}, - }, - { - // 0x21 DW_OP_or - "DW_OP_or", - OP_OR, - 2, - 0, - {}, - }, - { - // 0x22 DW_OP_plus - "DW_OP_plus", - OP_PLUS, - 2, - 0, - {}, - }, - { - // 0x23 DW_OP_plus_uconst - "DW_OP_plus_uconst", - OP_PLUS_UCONST, - 1, - 1, - {DW_EH_PE_uleb128}, - }, - { - // 0x24 DW_OP_shl - "DW_OP_shl", - OP_SHL, - 2, - 0, - {}, - }, - { - // 0x25 DW_OP_shr - "DW_OP_shr", - OP_SHR, - 2, - 0, - {}, - }, - { - // 0x26 DW_OP_shra - "DW_OP_shra", - OP_SHRA, - 2, - 0, - {}, - }, - { - // 0x27 DW_OP_xor - "DW_OP_xor", - OP_XOR, - 2, - 0, - {}, - }, - { - // 0x28 DW_OP_bra - "DW_OP_bra", - OP_BRA, - 1, - 1, - {DW_EH_PE_sdata2}, - }, - { - // 0x29 DW_OP_eq - "DW_OP_eq", - OP_EQ, - 2, - 0, - {}, - }, - { - // 0x2a DW_OP_ge - "DW_OP_ge", - OP_GE, - 2, - 0, - {}, - }, - { - // 0x2b DW_OP_gt - "DW_OP_gt", - OP_GT, - 2, - 0, - {}, - }, - { - // 0x2c DW_OP_le - "DW_OP_le", - OP_LE, - 2, - 0, - {}, - }, - { - // 0x2d DW_OP_lt - "DW_OP_lt", - OP_LT, - 2, - 0, - {}, - }, - { - // 0x2e DW_OP_ne - "DW_OP_ne", - OP_NE, - 2, - 0, - {}, - }, - { - // 0x2f DW_OP_skip - "DW_OP_skip", - OP_SKIP, - 0, - 1, - {DW_EH_PE_sdata2}, - }, - { - // 0x30 DW_OP_lit0 - "DW_OP_lit0", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x31 DW_OP_lit1 - "DW_OP_lit1", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x32 DW_OP_lit2 - "DW_OP_lit2", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x33 DW_OP_lit3 - "DW_OP_lit3", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x34 DW_OP_lit4 - "DW_OP_lit4", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x35 DW_OP_lit5 - "DW_OP_lit5", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x36 DW_OP_lit6 - "DW_OP_lit6", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x37 DW_OP_lit7 - "DW_OP_lit7", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x38 DW_OP_lit8 - "DW_OP_lit8", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x39 DW_OP_lit9 - "DW_OP_lit9", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x3a DW_OP_lit10 - "DW_OP_lit10", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x3b DW_OP_lit11 - "DW_OP_lit11", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x3c DW_OP_lit12 - "DW_OP_lit12", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x3d DW_OP_lit13 - "DW_OP_lit13", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x3e DW_OP_lit14 - "DW_OP_lit14", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x3f DW_OP_lit15 - "DW_OP_lit15", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x40 DW_OP_lit16 - "DW_OP_lit16", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x41 DW_OP_lit17 - "DW_OP_lit17", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x42 DW_OP_lit18 - "DW_OP_lit18", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x43 DW_OP_lit19 - "DW_OP_lit19", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x44 DW_OP_lit20 - "DW_OP_lit20", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x45 DW_OP_lit21 - "DW_OP_lit21", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x46 DW_OP_lit22 - "DW_OP_lit22", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x47 DW_OP_lit23 - "DW_OP_lit23", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x48 DW_OP_lit24 - "DW_OP_lit24", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x49 DW_OP_lit25 - "DW_OP_lit25", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x4a DW_OP_lit26 - "DW_OP_lit26", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x4b DW_OP_lit27 - "DW_OP_lit27", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x4c DW_OP_lit28 - "DW_OP_lit28", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x4d DW_OP_lit29 - "DW_OP_lit29", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x4e DW_OP_lit30 - "DW_OP_lit30", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x4f DW_OP_lit31 - "DW_OP_lit31", - OP_LIT, - 0, - 0, - {}, - }, - { - // 0x50 DW_OP_reg0 - "DW_OP_reg0", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x51 DW_OP_reg1 - "DW_OP_reg1", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x52 DW_OP_reg2 - "DW_OP_reg2", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x53 DW_OP_reg3 - "DW_OP_reg3", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x54 DW_OP_reg4 - "DW_OP_reg4", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x55 DW_OP_reg5 - "DW_OP_reg5", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x56 DW_OP_reg6 - "DW_OP_reg6", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x57 DW_OP_reg7 - "DW_OP_reg7", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x58 DW_OP_reg8 - "DW_OP_reg8", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x59 DW_OP_reg9 - "DW_OP_reg9", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x5a DW_OP_reg10 - "DW_OP_reg10", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x5b DW_OP_reg11 - "DW_OP_reg11", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x5c DW_OP_reg12 - "DW_OP_reg12", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x5d DW_OP_reg13 - "DW_OP_reg13", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x5e DW_OP_reg14 - "DW_OP_reg14", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x5f DW_OP_reg15 - "DW_OP_reg15", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x60 DW_OP_reg16 - "DW_OP_reg16", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x61 DW_OP_reg17 - "DW_OP_reg17", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x62 DW_OP_reg18 - "DW_OP_reg18", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x63 DW_OP_reg19 - "DW_OP_reg19", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x64 DW_OP_reg20 - "DW_OP_reg20", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x65 DW_OP_reg21 - "DW_OP_reg21", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x66 DW_OP_reg22 - "DW_OP_reg22", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x67 DW_OP_reg23 - "DW_OP_reg23", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x68 DW_OP_reg24 - "DW_OP_reg24", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x69 DW_OP_reg25 - "DW_OP_reg25", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x6a DW_OP_reg26 - "DW_OP_reg26", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x6b DW_OP_reg27 - "DW_OP_reg27", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x6c DW_OP_reg28 - "DW_OP_reg28", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x6d DW_OP_reg29 - "DW_OP_reg29", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x6e DW_OP_reg30 - "DW_OP_reg30", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x6f DW_OP_reg31 - "DW_OP_reg31", - OP_REG, - 0, - 0, - {}, - }, - { - // 0x70 DW_OP_breg0 - "DW_OP_breg0", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x71 DW_OP_breg1 - "DW_OP_breg1", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x72 DW_OP_breg2 - "DW_OP_breg2", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x73 DW_OP_breg3 - "DW_OP_breg3", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x74 DW_OP_breg4 - "DW_OP_breg4", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x75 DW_OP_breg5 - "DW_OP_breg5", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x76 DW_OP_breg6 - "DW_OP_breg6", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x77 DW_OP_breg7 - "DW_OP_breg7", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x78 DW_OP_breg8 - "DW_OP_breg8", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x79 DW_OP_breg9 - "DW_OP_breg9", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x7a DW_OP_breg10 - "DW_OP_breg10", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x7b DW_OP_breg11 - "DW_OP_breg11", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x7c DW_OP_breg12 - "DW_OP_breg12", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x7d DW_OP_breg13 - "DW_OP_breg13", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x7e DW_OP_breg14 - "DW_OP_breg14", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x7f DW_OP_breg15 - "DW_OP_breg15", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x80 DW_OP_breg16 - "DW_OP_breg16", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x81 DW_OP_breg17 - "DW_OP_breg17", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x82 DW_OP_breg18 - "DW_OP_breg18", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x83 DW_OP_breg19 - "DW_OP_breg19", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x84 DW_OP_breg20 - "DW_OP_breg20", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x85 DW_OP_breg21 - "DW_OP_breg21", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x86 DW_OP_breg22 - "DW_OP_breg22", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x87 DW_OP_breg23 - "DW_OP_breg23", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x88 DW_OP_breg24 - "DW_OP_breg24", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x89 DW_OP_breg25 - "DW_OP_breg25", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x8a DW_OP_breg26 - "DW_OP_breg26", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x8b DW_OP_breg27 - "DW_OP_breg27", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x8c DW_OP_breg28 - "DW_OP_breg28", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x8d DW_OP_breg29 - "DW_OP_breg29", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x8e DW_OP_breg30 - "DW_OP_breg30", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x8f DW_OP_breg31 - "DW_OP_breg31", - OP_BREG, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x90 DW_OP_regx - "DW_OP_regx", - OP_REGX, - 0, - 1, - {DW_EH_PE_uleb128}, - }, - { - // 0x91 DW_OP_fbreg - "DW_OP_fbreg", - OP_NOT_IMPLEMENTED, - 0, - 1, - {DW_EH_PE_sleb128}, - }, - { - // 0x92 DW_OP_bregx - "DW_OP_bregx", - OP_BREGX, - 0, - 2, - {DW_EH_PE_uleb128, DW_EH_PE_sleb128}, - }, - { - // 0x93 DW_OP_piece - "DW_OP_piece", - OP_NOT_IMPLEMENTED, - 0, - 1, - {DW_EH_PE_uleb128}, - }, - { - // 0x94 DW_OP_deref_size - "DW_OP_deref_size", - OP_DEREF_SIZE, - 1, - 1, - {DW_EH_PE_udata1}, - }, - { - // 0x95 DW_OP_xderef_size - "DW_OP_xderef_size", - OP_NOT_IMPLEMENTED, - 0, - 1, - {DW_EH_PE_udata1}, - }, - { - // 0x96 DW_OP_nop - "DW_OP_nop", - OP_NOP, - 0, - 0, - {}, - }, - { - // 0x97 DW_OP_push_object_address - "DW_OP_push_object_address", - OP_NOT_IMPLEMENTED, - 0, - 0, - {}, - }, - { - // 0x98 DW_OP_call2 - "DW_OP_call2", - OP_NOT_IMPLEMENTED, - 0, - 1, - {DW_EH_PE_udata2}, - }, - { - // 0x99 DW_OP_call4 - "DW_OP_call4", - OP_NOT_IMPLEMENTED, - 0, - 1, - {DW_EH_PE_udata4}, - }, - { - // 0x9a DW_OP_call_ref - "DW_OP_call_ref", - OP_NOT_IMPLEMENTED, - 0, - 0, // Has a different sized operand (4 bytes or 8 bytes). - {}, - }, - { - // 0x9b DW_OP_form_tls_address - "DW_OP_form_tls_address", - OP_NOT_IMPLEMENTED, - 0, - 0, - {}, - }, - { - // 0x9c DW_OP_call_frame_cfa - "DW_OP_call_frame_cfa", - OP_NOT_IMPLEMENTED, - 0, - 0, - {}, - }, - { - // 0x9d DW_OP_bit_piece - "DW_OP_bit_piece", - OP_NOT_IMPLEMENTED, - 0, - 2, - {DW_EH_PE_uleb128, DW_EH_PE_uleb128}, - }, - { - // 0x9e DW_OP_implicit_value - "DW_OP_implicit_value", - OP_NOT_IMPLEMENTED, - 0, - 1, - {DW_EH_PE_uleb128}, - }, - { - // 0x9f DW_OP_stack_value - "DW_OP_stack_value", - OP_NOT_IMPLEMENTED, - 1, - 0, - {}, - }, - {"", OP_ILLEGAL, 0, 0, {}}, // 0xa0 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xa1 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xa2 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xa3 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xa4 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xa5 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xa6 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xa7 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xa8 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xa9 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xaa illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xab illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xac illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xad illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xae illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xaf illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xb0 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xb1 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xb2 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xb3 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xb4 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xb5 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xb6 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xb7 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xb8 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xb9 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xba illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xbb illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xbc illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xbd illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xbe illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xbf illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xc0 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xc1 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xc2 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xc3 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xc4 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xc5 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xc6 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xc7 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xc8 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xc9 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xca illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xcb illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xcc illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xcd illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xce illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xcf illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xd0 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xd1 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xd2 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xd3 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xd4 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xd5 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xd6 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xd7 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xd8 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xd9 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xda illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xdb illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xdc illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xdd illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xde illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xdf illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xe0 DW_OP_lo_user - {"", OP_ILLEGAL, 0, 0, {}}, // 0xe1 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xe2 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xe3 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xe4 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xe5 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xe6 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xe7 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xe8 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xe9 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xea illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xeb illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xec illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xed illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xee illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xef illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xf0 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xf1 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xf2 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xf3 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xf4 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xf5 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xf6 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xf7 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xf8 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xf9 illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xfa illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xfb illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xfc illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xfd illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xfe illegal op - {"", OP_ILLEGAL, 0, 0, {}}, // 0xff DW_OP_hi_user -}; - -template -const typename DwarfOp::OpHandleFuncPtr DwarfOp::kOpHandleFuncList[] = { - [OP_ILLEGAL] = nullptr, - [OP_DEREF] = &DwarfOp::op_deref, - [OP_DEREF_SIZE] = &DwarfOp::op_deref_size, - [OP_PUSH] = &DwarfOp::op_push, - [OP_DUP] = &DwarfOp::op_dup, - [OP_DROP] = &DwarfOp::op_drop, - [OP_OVER] = &DwarfOp::op_over, - [OP_PICK] = &DwarfOp::op_pick, - [OP_SWAP] = &DwarfOp::op_swap, - [OP_ROT] = &DwarfOp::op_rot, - [OP_ABS] = &DwarfOp::op_abs, - [OP_AND] = &DwarfOp::op_and, - [OP_DIV] = &DwarfOp::op_div, - [OP_MINUS] = &DwarfOp::op_minus, - [OP_MOD] = &DwarfOp::op_mod, - [OP_MUL] = &DwarfOp::op_mul, - [OP_NEG] = &DwarfOp::op_neg, - [OP_NOT] = &DwarfOp::op_not, - [OP_OR] = &DwarfOp::op_or, - [OP_PLUS] = &DwarfOp::op_plus, - [OP_PLUS_UCONST] = &DwarfOp::op_plus_uconst, - [OP_SHL] = &DwarfOp::op_shl, - [OP_SHR] = &DwarfOp::op_shr, - [OP_SHRA] = &DwarfOp::op_shra, - [OP_XOR] = &DwarfOp::op_xor, - [OP_BRA] = &DwarfOp::op_bra, - [OP_EQ] = &DwarfOp::op_eq, - [OP_GE] = &DwarfOp::op_ge, - [OP_GT] = &DwarfOp::op_gt, - [OP_LE] = &DwarfOp::op_le, - [OP_LT] = &DwarfOp::op_lt, - [OP_NE] = &DwarfOp::op_ne, - [OP_SKIP] = &DwarfOp::op_skip, - [OP_LIT] = &DwarfOp::op_lit, - [OP_REG] = &DwarfOp::op_reg, - [OP_REGX] = &DwarfOp::op_regx, - [OP_BREG] = &DwarfOp::op_breg, - [OP_BREGX] = &DwarfOp::op_bregx, - [OP_NOP] = &DwarfOp::op_nop, - [OP_NOT_IMPLEMENTED] = &DwarfOp::op_not_implemented, -}; - -template -bool DwarfOp::Eval(uint64_t start, uint64_t end) { - is_register_ = false; - stack_.clear(); - memory_->set_cur_offset(start); - dex_pc_set_ = false; - - // Unroll the first Decode calls to be able to check for a special - // sequence of ops and values that indicate this is the dex pc. - // The pattern is: - // OP_const4u (0x0c) 'D' 'E' 'X' '1' - // OP_drop (0x13) - if (memory_->cur_offset() < end) { - if (!Decode()) { - return false; - } - } else { - return true; - } - bool check_for_drop; - if (cur_op_ == 0x0c && operands_.back() == 0x31584544) { - check_for_drop = true; - } else { - check_for_drop = false; - } - if (memory_->cur_offset() < end) { - if (!Decode()) { - return false; - } - } else { - return true; - } - - if (check_for_drop && cur_op_ == 0x13) { - dex_pc_set_ = true; - } - - uint32_t iterations = 2; - while (memory_->cur_offset() < end) { - if (!Decode()) { - return false; - } - // To protect against a branch that creates an infinite loop, - // terminate if the number of iterations gets too high. - if (iterations++ == 1000) { - last_error_.code = DWARF_ERROR_TOO_MANY_ITERATIONS; - return false; - } - } - return true; -} - -template -bool DwarfOp::Decode() { - last_error_.code = DWARF_ERROR_NONE; - if (!memory_->ReadBytes(&cur_op_, 1)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_->cur_offset(); - return false; - } - - const auto* op = &kCallbackTable[cur_op_]; - if (op->handle_func == OP_ILLEGAL) { - last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; - return false; - } - - const auto handle_func = kOpHandleFuncList[op->handle_func]; - - // Make sure that the required number of stack elements is available. - if (stack_.size() < op->num_required_stack_values) { - last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID; - return false; - } - - operands_.clear(); - for (size_t i = 0; i < op->num_operands; i++) { - uint64_t value; - if (!memory_->ReadEncodedValue(op->operands[i], &value)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_->cur_offset(); - return false; - } - operands_.push_back(value); - } - return (this->*handle_func)(); -} - -template -void DwarfOp::GetLogInfo(uint64_t start, uint64_t end, - std::vector* lines) { - memory_->set_cur_offset(start); - while (memory_->cur_offset() < end) { - uint8_t cur_op; - if (!memory_->ReadBytes(&cur_op, 1)) { - return; - } - - std::string raw_string(android::base::StringPrintf("Raw Data: 0x%02x", cur_op)); - std::string log_string; - const auto* op = &kCallbackTable[cur_op]; - if (op->handle_func == OP_ILLEGAL) { - log_string = "Illegal"; - } else { - log_string = op->name; - uint64_t start_offset = memory_->cur_offset(); - for (size_t i = 0; i < op->num_operands; i++) { - uint64_t value; - if (!memory_->ReadEncodedValue(op->operands[i], &value)) { - return; - } - log_string += ' ' + std::to_string(value); - } - uint64_t end_offset = memory_->cur_offset(); - - memory_->set_cur_offset(start_offset); - for (size_t i = start_offset; i < end_offset; i++) { - uint8_t byte; - if (!memory_->ReadBytes(&byte, 1)) { - return; - } - raw_string += android::base::StringPrintf(" 0x%02x", byte); - } - memory_->set_cur_offset(end_offset); - } - lines->push_back(std::move(log_string)); - lines->push_back(std::move(raw_string)); - } -} - -template -bool DwarfOp::op_deref() { - // Read the address and dereference it. - AddressType addr = StackPop(); - AddressType value; - if (!regular_memory()->ReadFully(addr, &value, sizeof(value))) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = addr; - return false; - } - stack_.push_front(value); - return true; -} - -template -bool DwarfOp::op_deref_size() { - AddressType bytes_to_read = OperandAt(0); - if (bytes_to_read > sizeof(AddressType) || bytes_to_read == 0) { - last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; - return false; - } - // Read the address and dereference it. - AddressType addr = StackPop(); - AddressType value = 0; - if (!regular_memory()->ReadFully(addr, &value, bytes_to_read)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = addr; - return false; - } - stack_.push_front(value); - return true; -} - -template -bool DwarfOp::op_push() { - // Push all of the operands. - for (auto operand : operands_) { - stack_.push_front(operand); - } - return true; -} - -template -bool DwarfOp::op_dup() { - stack_.push_front(StackAt(0)); - return true; -} - -template -bool DwarfOp::op_drop() { - StackPop(); - return true; -} - -template -bool DwarfOp::op_over() { - stack_.push_front(StackAt(1)); - return true; -} - -template -bool DwarfOp::op_pick() { - AddressType index = OperandAt(0); - if (index > StackSize()) { - last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID; - return false; - } - stack_.push_front(StackAt(index)); - return true; -} - -template -bool DwarfOp::op_swap() { - AddressType old_value = stack_[0]; - stack_[0] = stack_[1]; - stack_[1] = old_value; - return true; -} - -template -bool DwarfOp::op_rot() { - AddressType top = stack_[0]; - stack_[0] = stack_[1]; - stack_[1] = stack_[2]; - stack_[2] = top; - return true; -} - -template -bool DwarfOp::op_abs() { - SignedType signed_value = static_cast(stack_[0]); - if (signed_value < 0) { - signed_value = -signed_value; - } - stack_[0] = static_cast(signed_value); - return true; -} - -template -bool DwarfOp::op_and() { - AddressType top = StackPop(); - stack_[0] &= top; - return true; -} - -template -bool DwarfOp::op_div() { - AddressType top = StackPop(); - if (top == 0) { - last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; - return false; - } - SignedType signed_divisor = static_cast(top); - SignedType signed_dividend = static_cast(stack_[0]); - stack_[0] = static_cast(signed_dividend / signed_divisor); - return true; -} - -template -bool DwarfOp::op_minus() { - AddressType top = StackPop(); - stack_[0] -= top; - return true; -} - -template -bool DwarfOp::op_mod() { - AddressType top = StackPop(); - if (top == 0) { - last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; - return false; - } - stack_[0] %= top; - return true; -} - -template -bool DwarfOp::op_mul() { - AddressType top = StackPop(); - stack_[0] *= top; - return true; -} - -template -bool DwarfOp::op_neg() { - SignedType signed_value = static_cast(stack_[0]); - stack_[0] = static_cast(-signed_value); - return true; -} - -template -bool DwarfOp::op_not() { - stack_[0] = ~stack_[0]; - return true; -} - -template -bool DwarfOp::op_or() { - AddressType top = StackPop(); - stack_[0] |= top; - return true; -} - -template -bool DwarfOp::op_plus() { - AddressType top = StackPop(); - stack_[0] += top; - return true; -} - -template -bool DwarfOp::op_plus_uconst() { - stack_[0] += OperandAt(0); - return true; -} - -template -bool DwarfOp::op_shl() { - AddressType top = StackPop(); - stack_[0] <<= top; - return true; -} - -template -bool DwarfOp::op_shr() { - AddressType top = StackPop(); - stack_[0] >>= top; - return true; -} - -template -bool DwarfOp::op_shra() { - AddressType top = StackPop(); - SignedType signed_value = static_cast(stack_[0]) >> top; - stack_[0] = static_cast(signed_value); - return true; -} - -template -bool DwarfOp::op_xor() { - AddressType top = StackPop(); - stack_[0] ^= top; - return true; -} - -template -bool DwarfOp::op_bra() { - // Requires one stack element. - AddressType top = StackPop(); - int16_t offset = static_cast(OperandAt(0)); - uint64_t cur_offset; - if (top != 0) { - cur_offset = memory_->cur_offset() + offset; - } else { - cur_offset = memory_->cur_offset() - offset; - } - memory_->set_cur_offset(cur_offset); - return true; -} - -template -bool DwarfOp::op_eq() { - AddressType top = StackPop(); - stack_[0] = bool_to_dwarf_bool(stack_[0] == top); - return true; -} - -template -bool DwarfOp::op_ge() { - AddressType top = StackPop(); - stack_[0] = bool_to_dwarf_bool(stack_[0] >= top); - return true; -} - -template -bool DwarfOp::op_gt() { - AddressType top = StackPop(); - stack_[0] = bool_to_dwarf_bool(stack_[0] > top); - return true; -} - -template -bool DwarfOp::op_le() { - AddressType top = StackPop(); - stack_[0] = bool_to_dwarf_bool(stack_[0] <= top); - return true; -} - -template -bool DwarfOp::op_lt() { - AddressType top = StackPop(); - stack_[0] = bool_to_dwarf_bool(stack_[0] < top); - return true; -} - -template -bool DwarfOp::op_ne() { - AddressType top = StackPop(); - stack_[0] = bool_to_dwarf_bool(stack_[0] != top); - return true; -} - -template -bool DwarfOp::op_skip() { - int16_t offset = static_cast(OperandAt(0)); - uint64_t cur_offset = memory_->cur_offset() + offset; - memory_->set_cur_offset(cur_offset); - return true; -} - -template -bool DwarfOp::op_lit() { - stack_.push_front(cur_op() - 0x30); - return true; -} - -template -bool DwarfOp::op_reg() { - is_register_ = true; - stack_.push_front(cur_op() - 0x50); - return true; -} - -template -bool DwarfOp::op_regx() { - is_register_ = true; - stack_.push_front(OperandAt(0)); - return true; -} - -// It's not clear for breg/bregx, if this op should read the current -// value of the register, or where we think that register is located. -// For simplicity, the code will read the value before doing the unwind. -template -bool DwarfOp::op_breg() { - uint16_t reg = cur_op() - 0x70; - if (reg >= regs_info_->Total()) { - last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; - return false; - } - stack_.push_front(regs_info_->Get(reg) + OperandAt(0)); - return true; -} - -template -bool DwarfOp::op_bregx() { - AddressType reg = OperandAt(0); - if (reg >= regs_info_->Total()) { - last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; - return false; - } - stack_.push_front(regs_info_->Get(reg) + OperandAt(1)); - return true; -} - -template -bool DwarfOp::op_nop() { - return true; -} - -template -bool DwarfOp::op_not_implemented() { - last_error_.code = DWARF_ERROR_NOT_IMPLEMENTED; - return false; -} - -// Explicitly instantiate DwarfOp. -template class DwarfOp; -template class DwarfOp; - -} // namespace unwindstack diff --git a/libunwindstack/DwarfOp.h b/libunwindstack/DwarfOp.h deleted file mode 100644 index ac9fd2d16..000000000 --- a/libunwindstack/DwarfOp.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2016 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_DWARF_OP_H -#define _LIBUNWINDSTACK_DWARF_OP_H - -#include - -#include -#include -#include -#include - -#include - -#include "DwarfEncoding.h" -#include "RegsInfo.h" - -namespace unwindstack { - -// Forward declarations. -class DwarfMemory; -class Memory; -template -class RegsImpl; - -template -class DwarfOp { - // Signed version of AddressType - typedef typename std::make_signed::type SignedType; - - public: - DwarfOp(DwarfMemory* memory, Memory* regular_memory) - : memory_(memory), regular_memory_(regular_memory) {} - virtual ~DwarfOp() = default; - - bool Decode(); - - bool Eval(uint64_t start, uint64_t end); - - void GetLogInfo(uint64_t start, uint64_t end, std::vector* lines); - - AddressType StackAt(size_t index) { return stack_[index]; } - size_t StackSize() { return stack_.size(); } - - void set_regs_info(RegsInfo* regs_info) { regs_info_ = regs_info; } - - const DwarfErrorData& last_error() { return last_error_; } - DwarfErrorCode LastErrorCode() { return last_error_.code; } - uint64_t LastErrorAddress() { return last_error_.address; } - - bool dex_pc_set() { return dex_pc_set_; } - - bool is_register() { return is_register_; } - - uint8_t cur_op() { return cur_op_; } - - Memory* regular_memory() { return regular_memory_; } - - protected: - AddressType OperandAt(size_t index) { return operands_[index]; } - size_t OperandsSize() { return operands_.size(); } - - AddressType StackPop() { - AddressType value = stack_.front(); - stack_.pop_front(); - return value; - } - - private: - DwarfMemory* memory_; - Memory* regular_memory_; - - RegsInfo* regs_info_; - bool dex_pc_set_ = false; - bool is_register_ = false; - DwarfErrorData last_error_{DWARF_ERROR_NONE, 0}; - uint8_t cur_op_; - std::vector operands_; - std::deque stack_; - - inline AddressType bool_to_dwarf_bool(bool value) { return value ? 1 : 0; } - - // Op processing functions. - bool op_deref(); - bool op_deref_size(); - bool op_push(); - bool op_dup(); - bool op_drop(); - bool op_over(); - bool op_pick(); - bool op_swap(); - bool op_rot(); - bool op_abs(); - bool op_and(); - bool op_div(); - bool op_minus(); - bool op_mod(); - bool op_mul(); - bool op_neg(); - bool op_not(); - bool op_or(); - bool op_plus(); - bool op_plus_uconst(); - bool op_shl(); - bool op_shr(); - bool op_shra(); - bool op_xor(); - bool op_bra(); - bool op_eq(); - bool op_ge(); - bool op_gt(); - bool op_le(); - bool op_lt(); - bool op_ne(); - bool op_skip(); - bool op_lit(); - bool op_reg(); - bool op_regx(); - bool op_breg(); - bool op_bregx(); - bool op_nop(); - bool op_not_implemented(); - - using OpHandleFuncPtr = bool (DwarfOp::*)(); - static const OpHandleFuncPtr kOpHandleFuncList[]; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_DWARF_OP_H diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp deleted file mode 100644 index ad25e809a..000000000 --- a/libunwindstack/DwarfSection.cpp +++ /dev/null @@ -1,830 +0,0 @@ -/* - * Copyright (C) 2017 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 "DwarfCfa.h" -#include "DwarfDebugFrame.h" -#include "DwarfEhFrame.h" -#include "DwarfEncoding.h" -#include "DwarfOp.h" -#include "RegsInfo.h" - -namespace unwindstack { - -DwarfSection::DwarfSection(Memory* memory) : memory_(memory) {} - -bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished, - bool* is_signal_frame) { - // Lookup the pc in the cache. - auto it = loc_regs_.upper_bound(pc); - if (it == loc_regs_.end() || pc < it->second.pc_start) { - last_error_.code = DWARF_ERROR_NONE; - const DwarfFde* fde = GetFdeFromPc(pc); - if (fde == nullptr || fde->cie == nullptr) { - last_error_.code = DWARF_ERROR_ILLEGAL_STATE; - return false; - } - - // Now get the location information for this pc. - dwarf_loc_regs_t loc_regs; - if (!GetCfaLocationInfo(pc, fde, &loc_regs, regs->Arch())) { - return false; - } - loc_regs.cie = fde->cie; - - // Store it in the cache. - it = loc_regs_.emplace(loc_regs.pc_end, std::move(loc_regs)).first; - } - - *is_signal_frame = it->second.cie->is_signal_frame; - - // Now eval the actual registers. - return Eval(it->second.cie, process_memory, it->second, regs, finished); -} - -template -const DwarfCie* DwarfSectionImpl::GetCieFromOffset(uint64_t offset) { - auto cie_entry = cie_entries_.find(offset); - if (cie_entry != cie_entries_.end()) { - return &cie_entry->second; - } - DwarfCie* cie = &cie_entries_[offset]; - memory_.set_data_offset(entries_offset_); - memory_.set_cur_offset(offset); - if (!FillInCieHeader(cie) || !FillInCie(cie)) { - // Erase the cached entry. - cie_entries_.erase(offset); - return nullptr; - } - return cie; -} - -template -bool DwarfSectionImpl::FillInCieHeader(DwarfCie* cie) { - cie->lsda_encoding = DW_EH_PE_omit; - uint32_t length32; - if (!memory_.ReadBytes(&length32, sizeof(length32))) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - if (length32 == static_cast(-1)) { - // 64 bit Cie - uint64_t length64; - if (!memory_.ReadBytes(&length64, sizeof(length64))) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - - cie->cfa_instructions_end = memory_.cur_offset() + length64; - cie->fde_address_encoding = DW_EH_PE_sdata8; - - uint64_t cie_id; - if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - if (cie_id != cie64_value_) { - // This is not a Cie, something has gone horribly wrong. - last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; - return false; - } - } else { - // 32 bit Cie - cie->cfa_instructions_end = memory_.cur_offset() + length32; - cie->fde_address_encoding = DW_EH_PE_sdata4; - - uint32_t cie_id; - if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - if (cie_id != cie32_value_) { - // This is not a Cie, something has gone horribly wrong. - last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; - return false; - } - } - return true; -} - -template -bool DwarfSectionImpl::FillInCie(DwarfCie* cie) { - if (!memory_.ReadBytes(&cie->version, sizeof(cie->version))) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - - if (cie->version != 1 && cie->version != 3 && cie->version != 4 && cie->version != 5) { - // Unrecognized version. - last_error_.code = DWARF_ERROR_UNSUPPORTED_VERSION; - return false; - } - - // Read the augmentation string. - char aug_value; - do { - if (!memory_.ReadBytes(&aug_value, 1)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - cie->augmentation_string.push_back(aug_value); - } while (aug_value != '\0'); - - if (cie->version == 4 || cie->version == 5) { - // Skip the Address Size field since we only use it for validation. - memory_.set_cur_offset(memory_.cur_offset() + 1); - - // Segment Size - if (!memory_.ReadBytes(&cie->segment_size, 1)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - } - - // Code Alignment Factor - if (!memory_.ReadULEB128(&cie->code_alignment_factor)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - - // Data Alignment Factor - if (!memory_.ReadSLEB128(&cie->data_alignment_factor)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - - if (cie->version == 1) { - // Return Address is a single byte. - uint8_t return_address_register; - if (!memory_.ReadBytes(&return_address_register, 1)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - cie->return_address_register = return_address_register; - } else if (!memory_.ReadULEB128(&cie->return_address_register)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - - if (cie->augmentation_string[0] != 'z') { - cie->cfa_instructions_offset = memory_.cur_offset(); - return true; - } - - uint64_t aug_length; - if (!memory_.ReadULEB128(&aug_length)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - cie->cfa_instructions_offset = memory_.cur_offset() + aug_length; - - for (size_t i = 1; i < cie->augmentation_string.size(); i++) { - switch (cie->augmentation_string[i]) { - case 'L': - if (!memory_.ReadBytes(&cie->lsda_encoding, 1)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - break; - case 'P': { - uint8_t encoding; - if (!memory_.ReadBytes(&encoding, 1)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - memory_.set_pc_offset(pc_offset_); - if (!memory_.ReadEncodedValue(encoding, &cie->personality_handler)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - } break; - case 'R': - if (!memory_.ReadBytes(&cie->fde_address_encoding, 1)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - break; - case 'S': - cie->is_signal_frame = true; - break; - } - } - return true; -} - -template -const DwarfFde* DwarfSectionImpl::GetFdeFromOffset(uint64_t offset) { - auto fde_entry = fde_entries_.find(offset); - if (fde_entry != fde_entries_.end()) { - return &fde_entry->second; - } - DwarfFde* fde = &fde_entries_[offset]; - memory_.set_data_offset(entries_offset_); - memory_.set_cur_offset(offset); - if (!FillInFdeHeader(fde) || !FillInFde(fde)) { - fde_entries_.erase(offset); - return nullptr; - } - return fde; -} - -template -bool DwarfSectionImpl::FillInFdeHeader(DwarfFde* fde) { - uint32_t length32; - if (!memory_.ReadBytes(&length32, sizeof(length32))) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - - if (length32 == static_cast(-1)) { - // 64 bit Fde. - uint64_t length64; - if (!memory_.ReadBytes(&length64, sizeof(length64))) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - fde->cfa_instructions_end = memory_.cur_offset() + length64; - - uint64_t value64; - if (!memory_.ReadBytes(&value64, sizeof(value64))) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - if (value64 == cie64_value_) { - // This is a Cie, this means something has gone wrong. - last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; - return false; - } - - // Get the Cie pointer, which is necessary to properly read the rest of - // of the Fde information. - fde->cie_offset = GetCieOffsetFromFde64(value64); - } else { - // 32 bit Fde. - fde->cfa_instructions_end = memory_.cur_offset() + length32; - - uint32_t value32; - if (!memory_.ReadBytes(&value32, sizeof(value32))) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - if (value32 == cie32_value_) { - // This is a Cie, this means something has gone wrong. - last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; - return false; - } - - // Get the Cie pointer, which is necessary to properly read the rest of - // of the Fde information. - fde->cie_offset = GetCieOffsetFromFde32(value32); - } - return true; -} - -template -bool DwarfSectionImpl::FillInFde(DwarfFde* fde) { - uint64_t cur_offset = memory_.cur_offset(); - - const DwarfCie* cie = GetCieFromOffset(fde->cie_offset); - if (cie == nullptr) { - return false; - } - fde->cie = cie; - - if (cie->segment_size != 0) { - // Skip over the segment selector for now. - cur_offset += cie->segment_size; - } - memory_.set_cur_offset(cur_offset); - - // The load bias only applies to the start. - memory_.set_pc_offset(section_bias_); - bool valid = memory_.ReadEncodedValue(cie->fde_address_encoding, &fde->pc_start); - fde->pc_start = AdjustPcFromFde(fde->pc_start); - - memory_.set_pc_offset(0); - if (!valid || !memory_.ReadEncodedValue(cie->fde_address_encoding, &fde->pc_end)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - fde->pc_end += fde->pc_start; - - if (cie->augmentation_string.size() > 0 && cie->augmentation_string[0] == 'z') { - // Augmentation Size - uint64_t aug_length; - if (!memory_.ReadULEB128(&aug_length)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - uint64_t cur_offset = memory_.cur_offset(); - - memory_.set_pc_offset(pc_offset_); - if (!memory_.ReadEncodedValue(cie->lsda_encoding, &fde->lsda_address)) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - - // Set our position to after all of the augmentation data. - memory_.set_cur_offset(cur_offset + aug_length); - } - fde->cfa_instructions_offset = memory_.cur_offset(); - - return true; -} - -template -bool DwarfSectionImpl::EvalExpression(const DwarfLocation& loc, Memory* regular_memory, - AddressType* value, - RegsInfo* regs_info, - bool* is_dex_pc) { - DwarfOp op(&memory_, regular_memory); - op.set_regs_info(regs_info); - - // Need to evaluate the op data. - uint64_t end = loc.values[1]; - uint64_t start = end - loc.values[0]; - if (!op.Eval(start, end)) { - last_error_ = op.last_error(); - return false; - } - if (op.StackSize() == 0) { - last_error_.code = DWARF_ERROR_ILLEGAL_STATE; - return false; - } - // We don't support an expression that evaluates to a register number. - if (op.is_register()) { - last_error_.code = DWARF_ERROR_NOT_IMPLEMENTED; - return false; - } - *value = op.StackAt(0); - if (is_dex_pc != nullptr && op.dex_pc_set()) { - *is_dex_pc = true; - } - return true; -} - -template -struct EvalInfo { - const dwarf_loc_regs_t* loc_regs; - const DwarfCie* cie; - Memory* regular_memory; - AddressType cfa; - bool return_address_undefined = false; - RegsInfo regs_info; -}; - -template -bool DwarfSectionImpl::EvalRegister(const DwarfLocation* loc, uint32_t reg, - AddressType* reg_ptr, void* info) { - EvalInfo* eval_info = reinterpret_cast*>(info); - Memory* regular_memory = eval_info->regular_memory; - switch (loc->type) { - case DWARF_LOCATION_OFFSET: - if (!regular_memory->ReadFully(eval_info->cfa + loc->values[0], reg_ptr, sizeof(AddressType))) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = eval_info->cfa + loc->values[0]; - return false; - } - break; - case DWARF_LOCATION_VAL_OFFSET: - *reg_ptr = eval_info->cfa + loc->values[0]; - break; - case DWARF_LOCATION_REGISTER: { - uint32_t cur_reg = loc->values[0]; - if (cur_reg >= eval_info->regs_info.Total()) { - last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; - return false; - } - *reg_ptr = eval_info->regs_info.Get(cur_reg) + loc->values[1]; - break; - } - case DWARF_LOCATION_EXPRESSION: - case DWARF_LOCATION_VAL_EXPRESSION: { - AddressType value; - bool is_dex_pc = false; - if (!EvalExpression(*loc, regular_memory, &value, &eval_info->regs_info, &is_dex_pc)) { - return false; - } - if (loc->type == DWARF_LOCATION_EXPRESSION) { - if (!regular_memory->ReadFully(value, reg_ptr, sizeof(AddressType))) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = value; - return false; - } - } else { - *reg_ptr = value; - if (is_dex_pc) { - eval_info->regs_info.regs->set_dex_pc(value); - } - } - break; - } - case DWARF_LOCATION_UNDEFINED: - if (reg == eval_info->cie->return_address_register) { - eval_info->return_address_undefined = true; - } - break; - case DWARF_LOCATION_PSEUDO_REGISTER: - last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; - return false; - default: - break; - } - - return true; -} - -template -bool DwarfSectionImpl::Eval(const DwarfCie* cie, Memory* regular_memory, - const dwarf_loc_regs_t& loc_regs, Regs* regs, - bool* finished) { - RegsImpl* cur_regs = reinterpret_cast*>(regs); - if (cie->return_address_register >= cur_regs->total_regs()) { - last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; - return false; - } - - // Get the cfa value; - auto cfa_entry = loc_regs.find(CFA_REG); - if (cfa_entry == loc_regs.end()) { - last_error_.code = DWARF_ERROR_CFA_NOT_DEFINED; - return false; - } - - // Always set the dex pc to zero when evaluating. - cur_regs->set_dex_pc(0); - - // Reset necessary pseudo registers before evaluation. - // This is needed for ARM64, for example. - regs->ResetPseudoRegisters(); - - EvalInfo eval_info{.loc_regs = &loc_regs, - .cie = cie, - .regular_memory = regular_memory, - .regs_info = RegsInfo(cur_regs)}; - const DwarfLocation* loc = &cfa_entry->second; - // Only a few location types are valid for the cfa. - switch (loc->type) { - case DWARF_LOCATION_REGISTER: - if (loc->values[0] >= cur_regs->total_regs()) { - last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; - return false; - } - eval_info.cfa = (*cur_regs)[loc->values[0]]; - eval_info.cfa += loc->values[1]; - break; - case DWARF_LOCATION_VAL_EXPRESSION: { - AddressType value; - if (!EvalExpression(*loc, regular_memory, &value, &eval_info.regs_info, nullptr)) { - return false; - } - // There is only one type of valid expression for CFA evaluation. - eval_info.cfa = value; - break; - } - default: - last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; - return false; - } - - for (const auto& entry : loc_regs) { - uint32_t reg = entry.first; - // Already handled the CFA register. - if (reg == CFA_REG) continue; - - AddressType* reg_ptr; - if (reg >= cur_regs->total_regs()) { - if (entry.second.type != DWARF_LOCATION_PSEUDO_REGISTER) { - // Skip this unknown register. - continue; - } - if (!eval_info.regs_info.regs->SetPseudoRegister(reg, entry.second.values[0])) { - last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; - return false; - } - } else { - reg_ptr = eval_info.regs_info.Save(reg); - if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) { - return false; - } - } - } - - // Find the return address location. - if (eval_info.return_address_undefined) { - cur_regs->set_pc(0); - } else { - cur_regs->set_pc((*cur_regs)[cie->return_address_register]); - } - - // If the pc was set to zero, consider this the final frame. Exception: if - // this is the sigreturn frame, then we want to try to recover the real PC - // using the return address (from LR or the stack), so keep going. - *finished = (cur_regs->pc() == 0 && !cie->is_signal_frame) ? true : false; - - cur_regs->set_sp(eval_info.cfa); - - return true; -} - -template -bool DwarfSectionImpl::GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, - dwarf_loc_regs_t* loc_regs, ArchEnum arch) { - DwarfCfa cfa(&memory_, fde, arch); - - // Look for the cached copy of the cie data. - auto reg_entry = cie_loc_regs_.find(fde->cie_offset); - if (reg_entry == cie_loc_regs_.end()) { - if (!cfa.GetLocationInfo(pc, fde->cie->cfa_instructions_offset, fde->cie->cfa_instructions_end, - loc_regs)) { - last_error_ = cfa.last_error(); - return false; - } - cie_loc_regs_[fde->cie_offset] = *loc_regs; - } - cfa.set_cie_loc_regs(&cie_loc_regs_[fde->cie_offset]); - if (!cfa.GetLocationInfo(pc, fde->cfa_instructions_offset, fde->cfa_instructions_end, loc_regs)) { - last_error_ = cfa.last_error(); - return false; - } - return true; -} - -template -bool DwarfSectionImpl::Log(uint8_t indent, uint64_t pc, const DwarfFde* fde, - ArchEnum arch) { - DwarfCfa cfa(&memory_, fde, arch); - - // Always print the cie information. - const DwarfCie* cie = fde->cie; - if (!cfa.Log(indent, pc, cie->cfa_instructions_offset, cie->cfa_instructions_end)) { - last_error_ = cfa.last_error(); - return false; - } - if (!cfa.Log(indent, pc, fde->cfa_instructions_offset, fde->cfa_instructions_end)) { - last_error_ = cfa.last_error(); - return false; - } - return true; -} - -template -bool DwarfSectionImpl::Init(uint64_t offset, uint64_t size, int64_t section_bias) { - section_bias_ = section_bias; - entries_offset_ = offset; - next_entries_offset_ = offset; - entries_end_ = offset + size; - - memory_.clear_func_offset(); - memory_.clear_text_offset(); - memory_.set_cur_offset(offset); - pc_offset_ = offset; - - return true; -} - -// Create a cached version of the fde information such that it is a std::map -// that is indexed by end pc and contains a pair that represents the start pc -// followed by the fde object. The fde pointers are owned by fde_entries_ -// and not by the map object. -// It is possible for an fde to be represented by multiple entries in -// the map. This can happen if the the start pc and end pc overlap already -// existing entries. For example, if there is already an entry of 0x400, 0x200, -// and an fde has a start pc of 0x100 and end pc of 0x500, two new entries -// will be added: 0x200, 0x100 and 0x500, 0x400. -template -void DwarfSectionImpl::InsertFde(const DwarfFde* fde) { - uint64_t start = fde->pc_start; - uint64_t end = fde->pc_end; - auto it = fdes_.upper_bound(start); - while (it != fdes_.end() && start < end && it->second.first < end) { - if (start < it->second.first) { - fdes_[it->second.first] = std::make_pair(start, fde); - } - start = it->first; - ++it; - } - if (start < end) { - fdes_[end] = std::make_pair(start, fde); - } -} - -template -bool DwarfSectionImpl::GetNextCieOrFde(const DwarfFde** fde_entry) { - uint64_t start_offset = next_entries_offset_; - - memory_.set_data_offset(entries_offset_); - memory_.set_cur_offset(next_entries_offset_); - uint32_t value32; - if (!memory_.ReadBytes(&value32, sizeof(value32))) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - - uint64_t cie_offset; - uint8_t cie_fde_encoding; - bool entry_is_cie = false; - if (value32 == static_cast(-1)) { - // 64 bit entry. - uint64_t value64; - if (!memory_.ReadBytes(&value64, sizeof(value64))) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - - next_entries_offset_ = memory_.cur_offset() + value64; - // Read the Cie Id of a Cie or the pointer of the Fde. - if (!memory_.ReadBytes(&value64, sizeof(value64))) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - - if (value64 == cie64_value_) { - entry_is_cie = true; - cie_fde_encoding = DW_EH_PE_sdata8; - } else { - cie_offset = GetCieOffsetFromFde64(value64); - } - } else { - next_entries_offset_ = memory_.cur_offset() + value32; - - // 32 bit Cie - if (!memory_.ReadBytes(&value32, sizeof(value32))) { - last_error_.code = DWARF_ERROR_MEMORY_INVALID; - last_error_.address = memory_.cur_offset(); - return false; - } - - if (value32 == cie32_value_) { - entry_is_cie = true; - cie_fde_encoding = DW_EH_PE_sdata4; - } else { - cie_offset = GetCieOffsetFromFde32(value32); - } - } - - if (entry_is_cie) { - auto entry = cie_entries_.find(start_offset); - if (entry == cie_entries_.end()) { - DwarfCie* cie = &cie_entries_[start_offset]; - cie->lsda_encoding = DW_EH_PE_omit; - cie->cfa_instructions_end = next_entries_offset_; - cie->fde_address_encoding = cie_fde_encoding; - - if (!FillInCie(cie)) { - cie_entries_.erase(start_offset); - return false; - } - } - *fde_entry = nullptr; - } else { - auto entry = fde_entries_.find(start_offset); - if (entry != fde_entries_.end()) { - *fde_entry = &entry->second; - } else { - DwarfFde* fde = &fde_entries_[start_offset]; - fde->cfa_instructions_end = next_entries_offset_; - fde->cie_offset = cie_offset; - - if (!FillInFde(fde)) { - fde_entries_.erase(start_offset); - return false; - } - *fde_entry = fde; - } - } - return true; -} - -template -void DwarfSectionImpl::GetFdes(std::vector* fdes) { - // Loop through the already cached entries. - uint64_t entry_offset = entries_offset_; - while (entry_offset < next_entries_offset_) { - auto cie_it = cie_entries_.find(entry_offset); - if (cie_it != cie_entries_.end()) { - entry_offset = cie_it->second.cfa_instructions_end; - } else { - auto fde_it = fde_entries_.find(entry_offset); - if (fde_it == fde_entries_.end()) { - // No fde or cie at this entry, should not be possible. - return; - } - entry_offset = fde_it->second.cfa_instructions_end; - fdes->push_back(&fde_it->second); - } - } - - while (next_entries_offset_ < entries_end_) { - const DwarfFde* fde; - if (!GetNextCieOrFde(&fde)) { - break; - } - if (fde != nullptr) { - InsertFde(fde); - fdes->push_back(fde); - } - - if (next_entries_offset_ < memory_.cur_offset()) { - // Simply consider the processing done in this case. - break; - } - } -} - -template -const DwarfFde* DwarfSectionImpl::GetFdeFromPc(uint64_t pc) { - // Search in the list of fdes we already have. - auto it = fdes_.upper_bound(pc); - if (it != fdes_.end()) { - if (pc >= it->second.first) { - return it->second.second; - } - } - - // The section might have overlapping pcs in fdes, so it is necessary - // to do a linear search of the fdes by pc. As fdes are read, a cached - // search map is created. - while (next_entries_offset_ < entries_end_) { - const DwarfFde* fde; - if (!GetNextCieOrFde(&fde)) { - return nullptr; - } - if (fde != nullptr) { - InsertFde(fde); - if (pc >= fde->pc_start && pc < fde->pc_end) { - return fde; - } - } - - if (next_entries_offset_ < memory_.cur_offset()) { - // Simply consider the processing done in this case. - break; - } - } - return nullptr; -} - -// Explicitly instantiate DwarfSectionImpl -template class DwarfSectionImpl; -template class DwarfSectionImpl; - -// Explicitly instantiate DwarfDebugFrame -template class DwarfDebugFrame; -template class DwarfDebugFrame; - -// Explicitly instantiate DwarfEhFrame -template class DwarfEhFrame; -template class DwarfEhFrame; - -} // namespace unwindstack diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp deleted file mode 100644 index e098a583a..000000000 --- a/libunwindstack/Elf.cpp +++ /dev/null @@ -1,422 +0,0 @@ -/* - * Copyright (C) 2016 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 - -#define LOG_TAG "unwind" -#include - -#include -#include -#include -#include -#include - -#include "ElfInterfaceArm.h" -#include "Symbols.h" - -namespace unwindstack { - -bool Elf::cache_enabled_; -std::unordered_map, bool>>* Elf::cache_; -std::mutex* Elf::cache_lock_; - -bool Elf::Init() { - load_bias_ = 0; - if (!memory_) { - return false; - } - - interface_.reset(CreateInterfaceFromMemory(memory_.get())); - if (!interface_) { - return false; - } - - valid_ = interface_->Init(&load_bias_); - if (valid_) { - interface_->InitHeaders(); - InitGnuDebugdata(); - } else { - interface_.reset(nullptr); - } - return valid_; -} - -// It is expensive to initialize the .gnu_debugdata section. Provide a method -// to initialize this data separately. -void Elf::InitGnuDebugdata() { - if (!valid_ || interface_->gnu_debugdata_offset() == 0) { - return; - } - - gnu_debugdata_memory_.reset(interface_->CreateGnuDebugdataMemory()); - gnu_debugdata_interface_.reset(CreateInterfaceFromMemory(gnu_debugdata_memory_.get())); - ElfInterface* gnu = gnu_debugdata_interface_.get(); - if (gnu == nullptr) { - return; - } - - // Ignore the load_bias from the compressed section, the correct load bias - // is in the uncompressed data. - int64_t load_bias; - if (gnu->Init(&load_bias)) { - gnu->InitHeaders(); - interface_->SetGnuDebugdataInterface(gnu); - } else { - // Free all of the memory associated with the gnu_debugdata section. - gnu_debugdata_memory_.reset(nullptr); - gnu_debugdata_interface_.reset(nullptr); - } -} - -void Elf::Invalidate() { - interface_.reset(nullptr); - valid_ = false; -} - -std::string Elf::GetSoname() { - std::lock_guard guard(lock_); - if (!valid_) { - return ""; - } - return interface_->GetSoname(); -} - -uint64_t Elf::GetRelPc(uint64_t pc, const MapInfo* map_info) { - return pc - map_info->start + load_bias_ + map_info->elf_offset; -} - -bool Elf::GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) { - std::lock_guard guard(lock_); - return valid_ && (interface_->GetFunctionName(addr, name, func_offset) || - (gnu_debugdata_interface_ && - gnu_debugdata_interface_->GetFunctionName(addr, name, func_offset))); -} - -bool Elf::GetGlobalVariableOffset(const std::string& name, uint64_t* memory_offset) { - if (!valid_) { - return false; - } - - uint64_t vaddr; - if (!interface_->GetGlobalVariable(name, &vaddr) && - (gnu_debugdata_interface_ == nullptr || - !gnu_debugdata_interface_->GetGlobalVariable(name, &vaddr))) { - return false; - } - - if (arch() == ARCH_ARM64) { - // Tagged pointer after Android R would lead top byte to have random values - // https://source.android.com/devices/tech/debug/tagged-pointers - vaddr &= (1ULL << 56) - 1; - } - - // Check the .data section. - uint64_t vaddr_start = interface_->data_vaddr_start(); - if (vaddr >= vaddr_start && vaddr < interface_->data_vaddr_end()) { - *memory_offset = vaddr - vaddr_start + interface_->data_offset(); - return true; - } - - // Check the .dynamic section. - vaddr_start = interface_->dynamic_vaddr_start(); - if (vaddr >= vaddr_start && vaddr < interface_->dynamic_vaddr_end()) { - *memory_offset = vaddr - vaddr_start + interface_->dynamic_offset(); - return true; - } - - return false; -} - -std::string Elf::GetBuildID() { - if (!valid_) { - return ""; - } - return interface_->GetBuildID(); -} - -void Elf::GetLastError(ErrorData* data) { - if (valid_) { - *data = interface_->last_error(); - } -} - -ErrorCode Elf::GetLastErrorCode() { - if (valid_) { - return interface_->LastErrorCode(); - } - return ERROR_INVALID_ELF; -} - -uint64_t Elf::GetLastErrorAddress() { - if (valid_) { - return interface_->LastErrorAddress(); - } - return 0; -} - -// The relative pc expectd by this function is relative to the start of the elf. -bool Elf::StepIfSignalHandler(uint64_t rel_pc, Regs* regs, Memory* process_memory) { - if (!valid_) { - return false; - } - - // Convert the rel_pc to an elf_offset. - if (rel_pc < static_cast(load_bias_)) { - return false; - } - return regs->StepIfSignalHandler(rel_pc - load_bias_, this, process_memory); -} - -// The relative pc is always relative to the start of the map from which it comes. -bool Elf::Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished, - bool* is_signal_frame) { - if (!valid_) { - return false; - } - - // Lock during the step which can update information in the object. - std::lock_guard guard(lock_); - return interface_->Step(rel_pc, regs, process_memory, finished, is_signal_frame); -} - -bool Elf::IsValidElf(Memory* memory) { - if (memory == nullptr) { - return false; - } - - // Verify that this is a valid elf file. - uint8_t e_ident[SELFMAG + 1]; - if (!memory->ReadFully(0, e_ident, SELFMAG)) { - return false; - } - - if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) { - return false; - } - return true; -} - -bool Elf::GetInfo(Memory* memory, uint64_t* size) { - if (!IsValidElf(memory)) { - return false; - } - *size = 0; - - uint8_t class_type; - if (!memory->ReadFully(EI_CLASS, &class_type, 1)) { - return false; - } - - // Get the maximum size of the elf data from the header. - if (class_type == ELFCLASS32) { - ElfInterface32::GetMaxSize(memory, size); - } else if (class_type == ELFCLASS64) { - ElfInterface64::GetMaxSize(memory, size); - } else { - return false; - } - return true; -} - -bool Elf::IsValidPc(uint64_t pc) { - if (!valid_ || (load_bias_ > 0 && pc < static_cast(load_bias_))) { - return false; - } - - if (interface_->IsValidPc(pc)) { - return true; - } - - if (gnu_debugdata_interface_ != nullptr && gnu_debugdata_interface_->IsValidPc(pc)) { - return true; - } - - return false; -} - -ElfInterface* Elf::CreateInterfaceFromMemory(Memory* memory) { - if (!IsValidElf(memory)) { - return nullptr; - } - - std::unique_ptr interface; - if (!memory->ReadFully(EI_CLASS, &class_type_, 1)) { - return nullptr; - } - if (class_type_ == ELFCLASS32) { - Elf32_Half e_machine; - if (!memory->ReadFully(EI_NIDENT + sizeof(Elf32_Half), &e_machine, sizeof(e_machine))) { - return nullptr; - } - - machine_type_ = e_machine; - if (e_machine == EM_ARM) { - arch_ = ARCH_ARM; - interface.reset(new ElfInterfaceArm(memory)); - } else if (e_machine == EM_386) { - arch_ = ARCH_X86; - interface.reset(new ElfInterface32(memory)); - } else if (e_machine == EM_MIPS) { - arch_ = ARCH_MIPS; - interface.reset(new ElfInterface32(memory)); - } else { - // Unsupported. - ALOGI("32 bit elf that is neither arm nor x86 nor mips: e_machine = %d\n", e_machine); - return nullptr; - } - } else if (class_type_ == ELFCLASS64) { - Elf64_Half e_machine; - if (!memory->ReadFully(EI_NIDENT + sizeof(Elf64_Half), &e_machine, sizeof(e_machine))) { - return nullptr; - } - - machine_type_ = e_machine; - if (e_machine == EM_AARCH64) { - arch_ = ARCH_ARM64; - } else if (e_machine == EM_X86_64) { - arch_ = ARCH_X86_64; - } else if (e_machine == EM_MIPS) { - arch_ = ARCH_MIPS64; - } else { - // Unsupported. - ALOGI("64 bit elf that is neither aarch64 nor x86_64 nor mips64: e_machine = %d\n", - e_machine); - return nullptr; - } - interface.reset(new ElfInterface64(memory)); - } - - return interface.release(); -} - -int64_t Elf::GetLoadBias(Memory* memory) { - if (!IsValidElf(memory)) { - return 0; - } - - uint8_t class_type; - if (!memory->Read(EI_CLASS, &class_type, 1)) { - return 0; - } - - if (class_type == ELFCLASS32) { - return ElfInterface::GetLoadBias(memory); - } else if (class_type == ELFCLASS64) { - return ElfInterface::GetLoadBias(memory); - } - return 0; -} - -void Elf::SetCachingEnabled(bool enable) { - if (!cache_enabled_ && enable) { - cache_enabled_ = true; - cache_ = new std::unordered_map, bool>>; - cache_lock_ = new std::mutex; - } else if (cache_enabled_ && !enable) { - cache_enabled_ = false; - delete cache_; - delete cache_lock_; - } -} - -void Elf::CacheLock() { - cache_lock_->lock(); -} - -void Elf::CacheUnlock() { - cache_lock_->unlock(); -} - -void Elf::CacheAdd(MapInfo* info) { - // If elf_offset != 0, then cache both name:offset and name. - // The cached name is used to do lookups if multiple maps for the same - // named elf file exist. - // For example, if there are two maps boot.odex:1000 and boot.odex:2000 - // where each reference the entire boot.odex, the cache will properly - // use the same cached elf object. - - if (info->offset == 0 || info->elf_offset != 0) { - (*cache_)[info->name] = std::make_pair(info->elf, true); - } - - if (info->offset != 0) { - // The second element in the pair indicates whether elf_offset should - // be set to offset when getting out of the cache. - (*cache_)[info->name + ':' + std::to_string(info->offset)] = - std::make_pair(info->elf, info->elf_offset != 0); - } -} - -bool Elf::CacheAfterCreateMemory(MapInfo* info) { - if (info->name.empty() || info->offset == 0 || info->elf_offset == 0) { - return false; - } - - auto entry = cache_->find(info->name); - if (entry == cache_->end()) { - return false; - } - - // In this case, the whole file is the elf, and the name has already - // been cached. Add an entry at name:offset to get this directly out - // of the cache next time. - info->elf = entry->second.first; - (*cache_)[info->name + ':' + std::to_string(info->offset)] = std::make_pair(info->elf, true); - return true; -} - -bool Elf::CacheGet(MapInfo* info) { - std::string name(info->name); - if (info->offset != 0) { - name += ':' + std::to_string(info->offset); - } - auto entry = cache_->find(name); - if (entry != cache_->end()) { - info->elf = entry->second.first; - if (entry->second.second) { - info->elf_offset = info->offset; - } - return true; - } - return false; -} - -std::string Elf::GetBuildID(Memory* memory) { - if (!IsValidElf(memory)) { - return ""; - } - - uint8_t class_type; - if (!memory->Read(EI_CLASS, &class_type, 1)) { - return ""; - } - - if (class_type == ELFCLASS32) { - return ElfInterface::ReadBuildIDFromMemory(memory); - } else if (class_type == ELFCLASS64) { - return ElfInterface::ReadBuildIDFromMemory(memory); - } - return ""; -} - -} // namespace unwindstack diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp deleted file mode 100644 index 0188def4e..000000000 --- a/libunwindstack/ElfInterface.cpp +++ /dev/null @@ -1,720 +0,0 @@ -/* - * Copyright (C) 2017 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 <7zCrc.h> -#include -#include - -#include -#include -#include -#include -#include - -#include "DwarfDebugFrame.h" -#include "DwarfEhFrame.h" -#include "DwarfEhFrameWithHdr.h" -#include "MemoryBuffer.h" -#include "Symbols.h" - -namespace unwindstack { - -ElfInterface::~ElfInterface() { - for (auto symbol : symbols_) { - delete symbol; - } -} - -bool ElfInterface::IsValidPc(uint64_t pc) { - if (!pt_loads_.empty()) { - for (auto& entry : pt_loads_) { - uint64_t start = entry.second.table_offset; - uint64_t end = start + entry.second.table_size; - if (pc >= start && pc < end) { - return true; - } - } - return false; - } - - // No PT_LOAD data, look for a fde for this pc in the section data. - if (debug_frame_ != nullptr && debug_frame_->GetFdeFromPc(pc) != nullptr) { - return true; - } - - if (eh_frame_ != nullptr && eh_frame_->GetFdeFromPc(pc) != nullptr) { - return true; - } - - return false; -} - -Memory* ElfInterface::CreateGnuDebugdataMemory() { - if (gnu_debugdata_offset_ == 0 || gnu_debugdata_size_ == 0) { - return nullptr; - } - - // TODO: Only call these initialization functions once. - CrcGenerateTable(); - Crc64GenerateTable(); - - // Verify the request is not larger than the max size_t value. - if (gnu_debugdata_size_ > SIZE_MAX) { - return nullptr; - } - size_t initial_buffer_size; - if (__builtin_mul_overflow(5, gnu_debugdata_size_, &initial_buffer_size)) { - return nullptr; - } - - size_t buffer_increment; - if (__builtin_mul_overflow(2, gnu_debugdata_size_, &buffer_increment)) { - return nullptr; - } - - std::unique_ptr src(new (std::nothrow) uint8_t[gnu_debugdata_size_]); - if (src.get() == nullptr) { - return nullptr; - } - - std::unique_ptr dst(new MemoryBuffer); - if (!dst->Resize(initial_buffer_size)) { - return nullptr; - } - - if (!memory_->ReadFully(gnu_debugdata_offset_, src.get(), gnu_debugdata_size_)) { - return nullptr; - } - - ISzAlloc alloc; - CXzUnpacker state; - alloc.Alloc = [](ISzAllocPtr, size_t size) { return malloc(size); }; - alloc.Free = [](ISzAllocPtr, void* ptr) { return free(ptr); }; - XzUnpacker_Construct(&state, &alloc); - - int return_val; - size_t src_offset = 0; - size_t dst_offset = 0; - ECoderStatus status; - do { - size_t src_remaining = gnu_debugdata_size_ - src_offset; - size_t dst_remaining = dst->Size() - dst_offset; - if (dst_remaining < buffer_increment) { - size_t new_size; - if (__builtin_add_overflow(dst->Size(), buffer_increment, &new_size) || - !dst->Resize(new_size)) { - XzUnpacker_Free(&state); - return nullptr; - } - dst_remaining += buffer_increment; - } - return_val = XzUnpacker_Code(&state, dst->GetPtr(dst_offset), &dst_remaining, &src[src_offset], - &src_remaining, true, CODER_FINISH_ANY, &status); - src_offset += src_remaining; - dst_offset += dst_remaining; - } while (return_val == SZ_OK && status == CODER_STATUS_NOT_FINISHED); - XzUnpacker_Free(&state); - if (return_val != SZ_OK || !XzUnpacker_IsStreamWasFinished(&state)) { - return nullptr; - } - - // Shrink back down to the exact size. - if (!dst->Resize(dst_offset)) { - return nullptr; - } - - return dst.release(); -} - -template -void ElfInterface::InitHeadersWithTemplate() { - if (eh_frame_hdr_offset_ != 0) { - DwarfEhFrameWithHdr* eh_frame_hdr = new DwarfEhFrameWithHdr(memory_); - eh_frame_.reset(eh_frame_hdr); - if (!eh_frame_hdr->EhFrameInit(eh_frame_offset_, eh_frame_size_, eh_frame_section_bias_) || - !eh_frame_->Init(eh_frame_hdr_offset_, eh_frame_hdr_size_, eh_frame_hdr_section_bias_)) { - eh_frame_.reset(nullptr); - } - } - - if (eh_frame_.get() == nullptr && eh_frame_offset_ != 0) { - // If there is an eh_frame section without an eh_frame_hdr section, - // or using the frame hdr object failed to init. - eh_frame_.reset(new DwarfEhFrame(memory_)); - if (!eh_frame_->Init(eh_frame_offset_, eh_frame_size_, eh_frame_section_bias_)) { - eh_frame_.reset(nullptr); - } - } - - if (eh_frame_.get() == nullptr) { - eh_frame_hdr_offset_ = 0; - eh_frame_hdr_section_bias_ = 0; - eh_frame_hdr_size_ = static_cast(-1); - eh_frame_offset_ = 0; - eh_frame_section_bias_ = 0; - eh_frame_size_ = static_cast(-1); - } - - if (debug_frame_offset_ != 0) { - debug_frame_.reset(new DwarfDebugFrame(memory_)); - if (!debug_frame_->Init(debug_frame_offset_, debug_frame_size_, debug_frame_section_bias_)) { - debug_frame_.reset(nullptr); - debug_frame_offset_ = 0; - debug_frame_size_ = static_cast(-1); - } - } -} - -template -bool ElfInterface::ReadAllHeaders(int64_t* load_bias) { - EhdrType ehdr; - if (!memory_->ReadFully(0, &ehdr, sizeof(ehdr))) { - last_error_.code = ERROR_MEMORY_INVALID; - last_error_.address = 0; - return false; - } - - // If we have enough information that this is an elf file, then allow - // malformed program and section headers. - ReadProgramHeaders(ehdr, load_bias); - ReadSectionHeaders(ehdr); - return true; -} - -template -int64_t ElfInterface::GetLoadBias(Memory* memory) { - EhdrType ehdr; - if (!memory->ReadFully(0, &ehdr, sizeof(ehdr))) { - return false; - } - - uint64_t offset = ehdr.e_phoff; - for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) { - PhdrType phdr; - if (!memory->ReadFully(offset, &phdr, sizeof(phdr))) { - return 0; - } - - // Find the first executable load when looking for the load bias. - if (phdr.p_type == PT_LOAD && (phdr.p_flags & PF_X)) { - return static_cast(phdr.p_vaddr) - phdr.p_offset; - } - } - return 0; -} - -template -void ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, int64_t* load_bias) { - uint64_t offset = ehdr.e_phoff; - bool first_exec_load_header = true; - for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) { - PhdrType phdr; - if (!memory_->ReadFully(offset, &phdr, sizeof(phdr))) { - return; - } - - switch (phdr.p_type) { - case PT_LOAD: - { - if ((phdr.p_flags & PF_X) == 0) { - continue; - } - - pt_loads_[phdr.p_offset] = LoadInfo{phdr.p_offset, phdr.p_vaddr, - static_cast(phdr.p_memsz)}; - // Only set the load bias from the first executable load header. - if (first_exec_load_header) { - *load_bias = static_cast(phdr.p_vaddr) - phdr.p_offset; - } - first_exec_load_header = false; - break; - } - - case PT_GNU_EH_FRAME: - // This is really the pointer to the .eh_frame_hdr section. - eh_frame_hdr_offset_ = phdr.p_offset; - eh_frame_hdr_section_bias_ = static_cast(phdr.p_vaddr) - phdr.p_offset; - eh_frame_hdr_size_ = phdr.p_memsz; - break; - - case PT_DYNAMIC: - dynamic_offset_ = phdr.p_offset; - dynamic_vaddr_start_ = phdr.p_vaddr; - if (__builtin_add_overflow(dynamic_vaddr_start_, phdr.p_memsz, &dynamic_vaddr_end_)) { - dynamic_offset_ = 0; - dynamic_vaddr_start_ = 0; - dynamic_vaddr_end_ = 0; - } - break; - - default: - HandleUnknownType(phdr.p_type, phdr.p_offset, phdr.p_filesz); - break; - } - } -} - -template -std::string ElfInterface::ReadBuildID() { - // Ensure there is no overflow in any of the calulations below. - uint64_t tmp; - if (__builtin_add_overflow(gnu_build_id_offset_, gnu_build_id_size_, &tmp)) { - return ""; - } - - uint64_t offset = 0; - while (offset < gnu_build_id_size_) { - if (gnu_build_id_size_ - offset < sizeof(NhdrType)) { - return ""; - } - NhdrType hdr; - if (!memory_->ReadFully(gnu_build_id_offset_ + offset, &hdr, sizeof(hdr))) { - return ""; - } - offset += sizeof(hdr); - - if (gnu_build_id_size_ - offset < hdr.n_namesz) { - return ""; - } - if (hdr.n_namesz > 0) { - std::string name(hdr.n_namesz, '\0'); - if (!memory_->ReadFully(gnu_build_id_offset_ + offset, &(name[0]), hdr.n_namesz)) { - return ""; - } - - // Trim trailing \0 as GNU is stored as a C string in the ELF file. - if (name.back() == '\0') - name.resize(name.size() - 1); - - // Align hdr.n_namesz to next power multiple of 4. See man 5 elf. - offset += (hdr.n_namesz + 3) & ~3; - - if (name == "GNU" && hdr.n_type == NT_GNU_BUILD_ID) { - if (gnu_build_id_size_ - offset < hdr.n_descsz || hdr.n_descsz == 0) { - return ""; - } - std::string build_id(hdr.n_descsz, '\0'); - if (memory_->ReadFully(gnu_build_id_offset_ + offset, &build_id[0], hdr.n_descsz)) { - return build_id; - } - return ""; - } - } - // Align hdr.n_descsz to next power multiple of 4. See man 5 elf. - offset += (hdr.n_descsz + 3) & ~3; - } - return ""; -} - -template -void ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) { - uint64_t offset = ehdr.e_shoff; - uint64_t sec_offset = 0; - uint64_t sec_size = 0; - - // Get the location of the section header names. - // If something is malformed in the header table data, we aren't going - // to terminate, we'll simply ignore this part. - ShdrType shdr; - if (ehdr.e_shstrndx < ehdr.e_shnum) { - uint64_t sh_offset = offset + ehdr.e_shstrndx * ehdr.e_shentsize; - if (memory_->ReadFully(sh_offset, &shdr, sizeof(shdr))) { - sec_offset = shdr.sh_offset; - sec_size = shdr.sh_size; - } - } - - // Skip the first header, it's always going to be NULL. - offset += ehdr.e_shentsize; - for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) { - if (!memory_->ReadFully(offset, &shdr, sizeof(shdr))) { - return; - } - - if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) { - // Need to go get the information about the section that contains - // the string terminated names. - ShdrType str_shdr; - if (shdr.sh_link >= ehdr.e_shnum) { - continue; - } - uint64_t str_offset = ehdr.e_shoff + shdr.sh_link * ehdr.e_shentsize; - if (!memory_->ReadFully(str_offset, &str_shdr, sizeof(str_shdr))) { - continue; - } - if (str_shdr.sh_type != SHT_STRTAB) { - continue; - } - symbols_.push_back(new Symbols(shdr.sh_offset, shdr.sh_size, shdr.sh_entsize, - str_shdr.sh_offset, str_shdr.sh_size)); - } else if (shdr.sh_type == SHT_PROGBITS && sec_size != 0) { - // Look for the .debug_frame and .gnu_debugdata. - if (shdr.sh_name < sec_size) { - std::string name; - if (memory_->ReadString(sec_offset + shdr.sh_name, &name, sec_size - shdr.sh_name)) { - if (name == ".debug_frame") { - debug_frame_offset_ = shdr.sh_offset; - debug_frame_size_ = shdr.sh_size; - debug_frame_section_bias_ = static_cast(shdr.sh_addr) - shdr.sh_offset; - } else if (name == ".gnu_debugdata") { - gnu_debugdata_offset_ = shdr.sh_offset; - gnu_debugdata_size_ = shdr.sh_size; - } else if (name == ".eh_frame") { - eh_frame_offset_ = shdr.sh_offset; - eh_frame_section_bias_ = static_cast(shdr.sh_addr) - shdr.sh_offset; - eh_frame_size_ = shdr.sh_size; - } else if (eh_frame_hdr_offset_ == 0 && name == ".eh_frame_hdr") { - eh_frame_hdr_offset_ = shdr.sh_offset; - eh_frame_hdr_section_bias_ = static_cast(shdr.sh_addr) - shdr.sh_offset; - eh_frame_hdr_size_ = shdr.sh_size; - } else if (name == ".data") { - data_offset_ = shdr.sh_offset; - data_vaddr_start_ = shdr.sh_addr; - if (__builtin_add_overflow(data_vaddr_start_, shdr.sh_size, &data_vaddr_end_)) { - data_offset_ = 0; - data_vaddr_start_ = 0; - data_vaddr_end_ = 0; - } - } - } - } - } else if (shdr.sh_type == SHT_STRTAB) { - // In order to read soname, keep track of address to offset mapping. - strtabs_.push_back(std::make_pair(static_cast(shdr.sh_addr), - static_cast(shdr.sh_offset))); - } else if (shdr.sh_type == SHT_NOTE) { - if (shdr.sh_name < sec_size) { - std::string name; - if (memory_->ReadString(sec_offset + shdr.sh_name, &name, sec_size - shdr.sh_name) && - name == ".note.gnu.build-id") { - gnu_build_id_offset_ = shdr.sh_offset; - gnu_build_id_size_ = shdr.sh_size; - } - } - } - } -} - -template -std::string ElfInterface::GetSonameWithTemplate() { - if (soname_type_ == SONAME_INVALID) { - return ""; - } - if (soname_type_ == SONAME_VALID) { - return soname_; - } - - soname_type_ = SONAME_INVALID; - - uint64_t soname_offset = 0; - uint64_t strtab_addr = 0; - uint64_t strtab_size = 0; - - // Find the soname location from the dynamic headers section. - DynType dyn; - uint64_t offset = dynamic_offset_; - uint64_t max_offset = offset + dynamic_vaddr_end_ - dynamic_vaddr_start_; - for (uint64_t offset = dynamic_offset_; offset < max_offset; offset += sizeof(DynType)) { - if (!memory_->ReadFully(offset, &dyn, sizeof(dyn))) { - last_error_.code = ERROR_MEMORY_INVALID; - last_error_.address = offset; - return ""; - } - - if (dyn.d_tag == DT_STRTAB) { - strtab_addr = dyn.d_un.d_ptr; - } else if (dyn.d_tag == DT_STRSZ) { - strtab_size = dyn.d_un.d_val; - } else if (dyn.d_tag == DT_SONAME) { - soname_offset = dyn.d_un.d_val; - } else if (dyn.d_tag == DT_NULL) { - break; - } - } - - // Need to map the strtab address to the real offset. - for (const auto& entry : strtabs_) { - if (entry.first == strtab_addr) { - soname_offset = entry.second + soname_offset; - uint64_t soname_max = entry.second + strtab_size; - if (soname_offset >= soname_max) { - return ""; - } - if (!memory_->ReadString(soname_offset, &soname_, soname_max - soname_offset)) { - return ""; - } - soname_type_ = SONAME_VALID; - return soname_; - } - } - return ""; -} - -template -bool ElfInterface::GetFunctionNameWithTemplate(uint64_t addr, std::string* name, - uint64_t* func_offset) { - if (symbols_.empty()) { - return false; - } - - for (const auto symbol : symbols_) { - if (symbol->GetName(addr, memory_, name, func_offset)) { - return true; - } - } - return false; -} - -template -bool ElfInterface::GetGlobalVariableWithTemplate(const std::string& name, uint64_t* memory_address) { - if (symbols_.empty()) { - return false; - } - - for (const auto symbol : symbols_) { - if (symbol->GetGlobal(memory_, name, memory_address)) { - return true; - } - } - return false; -} - -bool ElfInterface::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished, - bool* is_signal_frame) { - last_error_.code = ERROR_NONE; - last_error_.address = 0; - - // Try the debug_frame first since it contains the most specific unwind - // information. - DwarfSection* debug_frame = debug_frame_.get(); - if (debug_frame != nullptr && - debug_frame->Step(pc, regs, process_memory, finished, is_signal_frame)) { - return true; - } - - // Try the eh_frame next. - DwarfSection* eh_frame = eh_frame_.get(); - if (eh_frame != nullptr && eh_frame->Step(pc, regs, process_memory, finished, is_signal_frame)) { - return true; - } - - if (gnu_debugdata_interface_ != nullptr && - gnu_debugdata_interface_->Step(pc, regs, process_memory, finished, is_signal_frame)) { - return true; - } - - // Set the error code based on the first error encountered. - DwarfSection* section = nullptr; - if (debug_frame_ != nullptr) { - section = debug_frame_.get(); - } else if (eh_frame_ != nullptr) { - section = eh_frame_.get(); - } else if (gnu_debugdata_interface_ != nullptr) { - last_error_ = gnu_debugdata_interface_->last_error(); - return false; - } else { - return false; - } - - // Convert the DWARF ERROR to an external error. - DwarfErrorCode code = section->LastErrorCode(); - switch (code) { - case DWARF_ERROR_NONE: - last_error_.code = ERROR_NONE; - break; - - case DWARF_ERROR_MEMORY_INVALID: - last_error_.code = ERROR_MEMORY_INVALID; - last_error_.address = section->LastErrorAddress(); - break; - - case DWARF_ERROR_ILLEGAL_VALUE: - case DWARF_ERROR_ILLEGAL_STATE: - case DWARF_ERROR_STACK_INDEX_NOT_VALID: - case DWARF_ERROR_TOO_MANY_ITERATIONS: - case DWARF_ERROR_CFA_NOT_DEFINED: - case DWARF_ERROR_NO_FDES: - last_error_.code = ERROR_UNWIND_INFO; - break; - - case DWARF_ERROR_NOT_IMPLEMENTED: - case DWARF_ERROR_UNSUPPORTED_VERSION: - last_error_.code = ERROR_UNSUPPORTED; - break; - } - return false; -} - -// This is an estimation of the size of the elf file using the location -// of the section headers and size. This assumes that the section headers -// are at the end of the elf file. If the elf has a load bias, the size -// will be too large, but this is acceptable. -template -void ElfInterface::GetMaxSizeWithTemplate(Memory* memory, uint64_t* size) { - EhdrType ehdr; - if (!memory->ReadFully(0, &ehdr, sizeof(ehdr))) { - return; - } - if (ehdr.e_shnum == 0) { - return; - } - *size = ehdr.e_shoff + ehdr.e_shentsize * ehdr.e_shnum; -} - -template -bool GetBuildIDInfo(Memory* memory, uint64_t* build_id_offset, uint64_t* build_id_size) { - EhdrType ehdr; - if (!memory->ReadFully(0, &ehdr, sizeof(ehdr))) { - return false; - } - - uint64_t offset = ehdr.e_shoff; - uint64_t sec_offset; - uint64_t sec_size; - ShdrType shdr; - if (ehdr.e_shstrndx >= ehdr.e_shnum) { - return false; - } - - uint64_t sh_offset = offset + ehdr.e_shstrndx * ehdr.e_shentsize; - if (!memory->ReadFully(sh_offset, &shdr, sizeof(shdr))) { - return false; - } - sec_offset = shdr.sh_offset; - sec_size = shdr.sh_size; - - // Skip the first header, it's always going to be NULL. - offset += ehdr.e_shentsize; - for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) { - if (!memory->ReadFully(offset, &shdr, sizeof(shdr))) { - return false; - } - std::string name; - if (shdr.sh_type == SHT_NOTE && shdr.sh_name < sec_size && - memory->ReadString(sec_offset + shdr.sh_name, &name, sec_size - shdr.sh_name) && - name == ".note.gnu.build-id") { - *build_id_offset = shdr.sh_offset; - *build_id_size = shdr.sh_size; - return true; - } - } - - return false; -} - -template -std::string ElfInterface::ReadBuildIDFromMemory(Memory* memory) { - uint64_t note_offset; - uint64_t note_size; - if (!GetBuildIDInfo(memory, ¬e_offset, ¬e_size)) { - return ""; - } - - // Ensure there is no overflow in any of the calculations below. - uint64_t tmp; - if (__builtin_add_overflow(note_offset, note_size, &tmp)) { - return ""; - } - - uint64_t offset = 0; - while (offset < note_size) { - if (note_size - offset < sizeof(NhdrType)) { - return ""; - } - NhdrType hdr; - if (!memory->ReadFully(note_offset + offset, &hdr, sizeof(hdr))) { - return ""; - } - offset += sizeof(hdr); - - if (note_size - offset < hdr.n_namesz) { - return ""; - } - if (hdr.n_namesz > 0) { - std::string name(hdr.n_namesz, '\0'); - if (!memory->ReadFully(note_offset + offset, &(name[0]), hdr.n_namesz)) { - return ""; - } - - // Trim trailing \0 as GNU is stored as a C string in the ELF file. - if (name.back() == '\0') name.resize(name.size() - 1); - - // Align hdr.n_namesz to next power multiple of 4. See man 5 elf. - offset += (hdr.n_namesz + 3) & ~3; - - if (name == "GNU" && hdr.n_type == NT_GNU_BUILD_ID) { - if (note_size - offset < hdr.n_descsz || hdr.n_descsz == 0) { - return ""; - } - std::string build_id(hdr.n_descsz, '\0'); - if (memory->ReadFully(note_offset + offset, &build_id[0], hdr.n_descsz)) { - return build_id; - } - return ""; - } - } - // Align hdr.n_descsz to next power multiple of 4. See man 5 elf. - offset += (hdr.n_descsz + 3) & ~3; - } - return ""; -} - -// Instantiate all of the needed template functions. -template void ElfInterface::InitHeadersWithTemplate(); -template void ElfInterface::InitHeadersWithTemplate(); - -template bool ElfInterface::ReadAllHeaders(int64_t*); -template bool ElfInterface::ReadAllHeaders(int64_t*); - -template void ElfInterface::ReadProgramHeaders(const Elf32_Ehdr&, int64_t*); -template void ElfInterface::ReadProgramHeaders(const Elf64_Ehdr&, int64_t*); - -template void ElfInterface::ReadSectionHeaders(const Elf32_Ehdr&); -template void ElfInterface::ReadSectionHeaders(const Elf64_Ehdr&); - -template std::string ElfInterface::ReadBuildID(); -template std::string ElfInterface::ReadBuildID(); - -template std::string ElfInterface::GetSonameWithTemplate(); -template std::string ElfInterface::GetSonameWithTemplate(); - -template bool ElfInterface::GetFunctionNameWithTemplate(uint64_t, std::string*, - uint64_t*); -template bool ElfInterface::GetFunctionNameWithTemplate(uint64_t, std::string*, - uint64_t*); - -template bool ElfInterface::GetGlobalVariableWithTemplate(const std::string&, uint64_t*); -template bool ElfInterface::GetGlobalVariableWithTemplate(const std::string&, uint64_t*); - -template void ElfInterface::GetMaxSizeWithTemplate(Memory*, uint64_t*); -template void ElfInterface::GetMaxSizeWithTemplate(Memory*, uint64_t*); - -template int64_t ElfInterface::GetLoadBias(Memory*); -template int64_t ElfInterface::GetLoadBias(Memory*); - -template std::string ElfInterface::ReadBuildIDFromMemory( - Memory*); -template std::string ElfInterface::ReadBuildIDFromMemory( - Memory*); - -} // namespace unwindstack diff --git a/libunwindstack/ElfInterfaceArm.cpp b/libunwindstack/ElfInterfaceArm.cpp deleted file mode 100644 index 9352a5dec..000000000 --- a/libunwindstack/ElfInterfaceArm.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2016 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 "ArmExidx.h" -#include "ElfInterfaceArm.h" - -namespace unwindstack { - -bool ElfInterfaceArm::Init(int64_t* load_bias) { - if (!ElfInterface32::Init(load_bias)) { - return false; - } - load_bias_ = *load_bias; - return true; -} - -bool ElfInterfaceArm::FindEntry(uint32_t pc, uint64_t* entry_offset) { - if (start_offset_ == 0 || total_entries_ == 0) { - last_error_.code = ERROR_UNWIND_INFO; - return false; - } - - size_t first = 0; - size_t last = total_entries_; - while (first < last) { - size_t current = (first + last) / 2; - uint32_t addr = addrs_[current]; - if (addr == 0) { - if (!GetPrel31Addr(start_offset_ + current * 8, &addr)) { - return false; - } - addrs_[current] = addr; - } - if (pc == addr) { - *entry_offset = start_offset_ + current * 8; - return true; - } - if (pc < addr) { - last = current; - } else { - first = current + 1; - } - } - if (last != 0) { - *entry_offset = start_offset_ + (last - 1) * 8; - return true; - } - last_error_.code = ERROR_UNWIND_INFO; - return false; -} - -bool ElfInterfaceArm::GetPrel31Addr(uint32_t offset, uint32_t* addr) { - uint32_t data; - if (!memory_->Read32(offset, &data)) { - last_error_.code = ERROR_MEMORY_INVALID; - last_error_.address = offset; - return false; - } - - // Sign extend the value if necessary. - int32_t value = (static_cast(data) << 1) >> 1; - *addr = offset + value; - return true; -} - -#if !defined(PT_ARM_EXIDX) -#define PT_ARM_EXIDX 0x70000001 -#endif - -void ElfInterfaceArm::HandleUnknownType(uint32_t type, uint64_t ph_offset, uint64_t ph_filesz) { - if (type != PT_ARM_EXIDX) { - return; - } - - // The offset already takes into account the load bias. - start_offset_ = ph_offset; - - // Always use filesz instead of memsz. In most cases they are the same, - // but some shared libraries wind up setting one correctly and not the other. - total_entries_ = ph_filesz / 8; -} - -bool ElfInterfaceArm::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished, - bool* is_signal_frame) { - // Dwarf unwind information is precise about whether a pc is covered or not, - // but arm unwind information only has ranges of pc. In order to avoid - // incorrectly doing a bad unwind using arm unwind information for a - // different function, always try and unwind with the dwarf information first. - return ElfInterface32::Step(pc, regs, process_memory, finished, is_signal_frame) || - StepExidx(pc, regs, process_memory, finished); -} - -bool ElfInterfaceArm::StepExidx(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) { - // Adjust the load bias to get the real relative pc. - if (pc < load_bias_) { - last_error_.code = ERROR_UNWIND_INFO; - return false; - } - pc -= load_bias_; - - RegsArm* regs_arm = reinterpret_cast(regs); - uint64_t entry_offset; - if (!FindEntry(pc, &entry_offset)) { - return false; - } - - ArmExidx arm(regs_arm, memory_, process_memory); - arm.set_cfa(regs_arm->sp()); - bool return_value = false; - if (arm.ExtractEntryData(entry_offset) && arm.Eval()) { - // If the pc was not set, then use the LR registers for the PC. - if (!arm.pc_set()) { - (*regs_arm)[ARM_REG_PC] = (*regs_arm)[ARM_REG_LR]; - } - (*regs_arm)[ARM_REG_SP] = arm.cfa(); - return_value = true; - - // If the pc was set to zero, consider this the final frame. - *finished = (regs_arm->pc() == 0) ? true : false; - } - - if (arm.status() == ARM_STATUS_NO_UNWIND) { - *finished = true; - return true; - } - - if (!return_value) { - switch (arm.status()) { - case ARM_STATUS_NONE: - case ARM_STATUS_NO_UNWIND: - case ARM_STATUS_FINISH: - last_error_.code = ERROR_NONE; - break; - - case ARM_STATUS_RESERVED: - case ARM_STATUS_SPARE: - case ARM_STATUS_TRUNCATED: - case ARM_STATUS_MALFORMED: - case ARM_STATUS_INVALID_ALIGNMENT: - case ARM_STATUS_INVALID_PERSONALITY: - last_error_.code = ERROR_UNWIND_INFO; - break; - - case ARM_STATUS_READ_FAILED: - last_error_.code = ERROR_MEMORY_INVALID; - last_error_.address = arm.status_address(); - break; - } - } - return return_value; -} - -bool ElfInterfaceArm::GetFunctionName(uint64_t addr, std::string* name, uint64_t* offset) { - // For ARM, thumb function symbols have bit 0 set, but the address passed - // in here might not have this bit set and result in a failure to find - // the thumb function names. Adjust the address and offset to account - // for this possible case. - if (ElfInterface32::GetFunctionName(addr | 1, name, offset)) { - *offset &= ~1; - return true; - } - return false; -} - -} // namespace unwindstack diff --git a/libunwindstack/ElfInterfaceArm.h b/libunwindstack/ElfInterfaceArm.h deleted file mode 100644 index fd824f88b..000000000 --- a/libunwindstack/ElfInterfaceArm.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2016 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_ELF_INTERFACE_ARM_H -#define _LIBUNWINDSTACK_ELF_INTERFACE_ARM_H - -#include -#include - -#include -#include - -#include -#include - -namespace unwindstack { - -class ElfInterfaceArm : public ElfInterface32 { - public: - ElfInterfaceArm(Memory* memory) : ElfInterface32(memory) {} - virtual ~ElfInterfaceArm() = default; - - class iterator : public std::iterator { - public: - iterator(ElfInterfaceArm* interface, size_t index) : interface_(interface), index_(index) { } - - iterator& operator++() { index_++; return *this; } - iterator& operator++(int increment) { index_ += increment; return *this; } - iterator& operator--() { index_--; return *this; } - iterator& operator--(int decrement) { index_ -= decrement; return *this; } - - bool operator==(const iterator& rhs) { return this->index_ == rhs.index_; } - bool operator!=(const iterator& rhs) { return this->index_ != rhs.index_; } - - uint32_t operator*() { - uint32_t addr = interface_->addrs_[index_]; - if (addr == 0) { - if (!interface_->GetPrel31Addr(interface_->start_offset_ + index_ * 8, &addr)) { - return 0; - } - interface_->addrs_[index_] = addr; - } - return addr; - } - - private: - ElfInterfaceArm* interface_ = nullptr; - size_t index_ = 0; - }; - - iterator begin() { return iterator(this, 0); } - iterator end() { return iterator(this, total_entries_); } - - bool Init(int64_t* section_bias) override; - - bool GetPrel31Addr(uint32_t offset, uint32_t* addr); - - bool FindEntry(uint32_t pc, uint64_t* entry_offset); - - void HandleUnknownType(uint32_t type, uint64_t ph_offset, uint64_t ph_filesz) override; - - bool Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished, - bool* is_signal_frame) override; - - bool StepExidx(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished); - - bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* offset) override; - - uint64_t start_offset() { return start_offset_; } - - size_t total_entries() { return total_entries_; } - - void set_load_bias(uint64_t load_bias) { load_bias_ = load_bias; } - - protected: - uint64_t start_offset_ = 0; - size_t total_entries_ = 0; - uint64_t load_bias_ = 0; - - std::unordered_map addrs_; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_ELF_INTERFACE_ARM_H diff --git a/libunwindstack/Global.cpp b/libunwindstack/Global.cpp deleted file mode 100644 index ee6c8a593..000000000 --- a/libunwindstack/Global.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2018 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 - -namespace unwindstack { - -Global::Global(std::shared_ptr& memory) : memory_(memory) {} -Global::Global(std::shared_ptr& memory, std::vector& search_libs) - : memory_(memory), search_libs_(search_libs) {} - -void Global::SetArch(ArchEnum arch) { - if (arch_ == ARCH_UNKNOWN) { - arch_ = arch; - ProcessArch(); - } -} - -bool Global::Searchable(const std::string& name) { - if (search_libs_.empty()) { - return true; - } - - if (name.empty()) { - return false; - } - - const char* base_name = basename(name.c_str()); - for (const std::string& lib : search_libs_) { - if (base_name == lib) { - return true; - } - } - return false; -} - -void Global::FindAndReadVariable(Maps* maps, const char* var_str) { - std::string variable(var_str); - // When looking for global variables, do not arbitrarily search every - // readable map. Instead look for a specific pattern that must exist. - // The pattern should be a readable map, followed by a read-write - // map with a non-zero offset. - // For example: - // f0000-f1000 0 r-- /system/lib/libc.so - // f1000-f2000 1000 r-x /system/lib/libc.so - // f2000-f3000 2000 rw- /system/lib/libc.so - // This also works: - // f0000-f2000 0 r-- /system/lib/libc.so - // f2000-f3000 2000 rw- /system/lib/libc.so - // It is also possible to see empty maps after the read-only like so: - // f0000-f1000 0 r-- /system/lib/libc.so - // f1000-f2000 0 --- - // f2000-f3000 1000 r-x /system/lib/libc.so - // f3000-f4000 2000 rw- /system/lib/libc.so - MapInfo* map_zero = nullptr; - for (const auto& info : *maps) { - if (info->offset != 0 && (info->flags & (PROT_READ | PROT_WRITE)) == (PROT_READ | PROT_WRITE) && - map_zero != nullptr && Searchable(info->name) && info->name == map_zero->name) { - Elf* elf = map_zero->GetElf(memory_, arch()); - uint64_t ptr; - if (elf->GetGlobalVariableOffset(variable, &ptr) && ptr != 0) { - uint64_t offset_end = info->offset + info->end - info->start; - if (ptr >= info->offset && ptr < offset_end) { - ptr = info->start + ptr - info->offset; - if (ReadVariableData(ptr)) { - break; - } - } - } - } else if (info->offset == 0 && !info->name.empty()) { - map_zero = info.get(); - } - } -} - -} // namespace unwindstack diff --git a/libunwindstack/JitDebug.cpp b/libunwindstack/JitDebug.cpp deleted file mode 100644 index 8a85607cb..000000000 --- a/libunwindstack/JitDebug.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (C) 2017 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 "MemoryRange.h" - -// This implements the JIT Compilation Interface. -// See https://sourceware.org/gdb/onlinedocs/gdb/JIT-Interface.html - -namespace unwindstack { - -struct JITCodeEntry32Pack { - uint32_t next; - uint32_t prev; - uint32_t symfile_addr; - uint64_t symfile_size; -} __attribute__((packed)); - -struct JITCodeEntry32Pad { - uint32_t next; - uint32_t prev; - uint32_t symfile_addr; - uint32_t pad; - uint64_t symfile_size; -}; - -struct JITCodeEntry64 { - uint64_t next; - uint64_t prev; - uint64_t symfile_addr; - uint64_t symfile_size; -}; - -struct JITDescriptorHeader { - uint32_t version; - uint32_t action_flag; -}; - -struct JITDescriptor32 { - JITDescriptorHeader header; - uint32_t relevant_entry; - uint32_t first_entry; -}; - -struct JITDescriptor64 { - JITDescriptorHeader header; - uint64_t relevant_entry; - uint64_t first_entry; -}; - -JitDebug::JitDebug(std::shared_ptr& memory) : Global(memory) {} - -JitDebug::JitDebug(std::shared_ptr& memory, std::vector& search_libs) - : Global(memory, search_libs) {} - -JitDebug::~JitDebug() { - for (auto* elf : elf_list_) { - delete elf; - } -} - -uint64_t JitDebug::ReadDescriptor32(uint64_t addr) { - JITDescriptor32 desc; - if (!memory_->ReadFully(addr, &desc, sizeof(desc))) { - return 0; - } - - if (desc.header.version != 1 || desc.first_entry == 0) { - // Either unknown version, or no jit entries. - return 0; - } - - return desc.first_entry; -} - -uint64_t JitDebug::ReadDescriptor64(uint64_t addr) { - JITDescriptor64 desc; - if (!memory_->ReadFully(addr, &desc, sizeof(desc))) { - return 0; - } - - if (desc.header.version != 1 || desc.first_entry == 0) { - // Either unknown version, or no jit entries. - return 0; - } - - return desc.first_entry; -} - -uint64_t JitDebug::ReadEntry32Pack(uint64_t* start, uint64_t* size) { - JITCodeEntry32Pack code; - if (!memory_->ReadFully(entry_addr_, &code, sizeof(code))) { - return 0; - } - - *start = code.symfile_addr; - *size = code.symfile_size; - return code.next; -} - -uint64_t JitDebug::ReadEntry32Pad(uint64_t* start, uint64_t* size) { - JITCodeEntry32Pad code; - if (!memory_->ReadFully(entry_addr_, &code, sizeof(code))) { - return 0; - } - - *start = code.symfile_addr; - *size = code.symfile_size; - return code.next; -} - -uint64_t JitDebug::ReadEntry64(uint64_t* start, uint64_t* size) { - JITCodeEntry64 code; - if (!memory_->ReadFully(entry_addr_, &code, sizeof(code))) { - return 0; - } - - *start = code.symfile_addr; - *size = code.symfile_size; - return code.next; -} - -void JitDebug::ProcessArch() { - switch (arch()) { - case ARCH_X86: - read_descriptor_func_ = &JitDebug::ReadDescriptor32; - read_entry_func_ = &JitDebug::ReadEntry32Pack; - break; - - case ARCH_ARM: - case ARCH_MIPS: - read_descriptor_func_ = &JitDebug::ReadDescriptor32; - read_entry_func_ = &JitDebug::ReadEntry32Pad; - break; - - case ARCH_ARM64: - case ARCH_X86_64: - case ARCH_MIPS64: - read_descriptor_func_ = &JitDebug::ReadDescriptor64; - read_entry_func_ = &JitDebug::ReadEntry64; - break; - case ARCH_UNKNOWN: - abort(); - } -} - -bool JitDebug::ReadVariableData(uint64_t ptr) { - entry_addr_ = (this->*read_descriptor_func_)(ptr); - return entry_addr_ != 0; -} - -void JitDebug::Init(Maps* maps) { - if (initialized_) { - return; - } - // Regardless of what happens below, consider the init finished. - initialized_ = true; - - FindAndReadVariable(maps, "__jit_debug_descriptor"); -} - -Elf* JitDebug::GetElf(Maps* maps, uint64_t pc) { - // Use a single lock, this object should be used so infrequently that - // a fine grain lock is unnecessary. - std::lock_guard guard(lock_); - if (!initialized_) { - Init(maps); - } - - // Search the existing elf object first. - for (Elf* elf : elf_list_) { - if (elf->IsValidPc(pc)) { - return elf; - } - } - - while (entry_addr_ != 0) { - uint64_t start; - uint64_t size; - entry_addr_ = (this->*read_entry_func_)(&start, &size); - - Elf* elf = new Elf(new MemoryRange(memory_, start, size, 0)); - elf->Init(); - if (!elf->valid()) { - // The data is not formatted in a way we understand, do not attempt - // to process any other entries. - entry_addr_ = 0; - delete elf; - return nullptr; - } - elf_list_.push_back(elf); - - if (elf->IsValidPc(pc)) { - return elf; - } - } - return nullptr; -} - -} // namespace unwindstack diff --git a/libunwindstack/LocalUnwinder.cpp b/libunwindstack/LocalUnwinder.cpp deleted file mode 100644 index 5f51a73c6..000000000 --- a/libunwindstack/LocalUnwinder.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace unwindstack { - -bool LocalUnwinder::Init() { - pthread_rwlock_init(&maps_rwlock_, nullptr); - - // Create the maps. - maps_.reset(new unwindstack::LocalUpdatableMaps()); - if (!maps_->Parse()) { - maps_.reset(); - return false; - } - - process_memory_ = unwindstack::Memory::CreateProcessMemory(getpid()); - - return true; -} - -bool LocalUnwinder::ShouldSkipLibrary(const std::string& map_name) { - for (const std::string& skip_library : skip_libraries_) { - if (skip_library == map_name) { - return true; - } - } - return false; -} - -MapInfo* LocalUnwinder::GetMapInfo(uint64_t pc) { - pthread_rwlock_rdlock(&maps_rwlock_); - MapInfo* map_info = maps_->Find(pc); - pthread_rwlock_unlock(&maps_rwlock_); - - if (map_info == nullptr) { - pthread_rwlock_wrlock(&maps_rwlock_); - // This is guaranteed not to invalidate any previous MapInfo objects so - // we don't need to worry about any MapInfo* values already in use. - if (maps_->Reparse()) { - map_info = maps_->Find(pc); - } - pthread_rwlock_unlock(&maps_rwlock_); - } - - return map_info; -} - -bool LocalUnwinder::Unwind(std::vector* frame_info, size_t max_frames) { - std::unique_ptr regs(unwindstack::Regs::CreateFromLocal()); - unwindstack::RegsGetLocal(regs.get()); - ArchEnum arch = regs->Arch(); - - size_t num_frames = 0; - bool adjust_pc = false; - while (true) { - uint64_t cur_pc = regs->pc(); - uint64_t cur_sp = regs->sp(); - - MapInfo* map_info = GetMapInfo(cur_pc); - if (map_info == nullptr) { - break; - } - - Elf* elf = map_info->GetElf(process_memory_, arch); - uint64_t rel_pc = elf->GetRelPc(cur_pc, map_info); - uint64_t step_pc = rel_pc; - uint64_t pc_adjustment; - if (adjust_pc) { - pc_adjustment = GetPcAdjustment(rel_pc, elf, arch); - } else { - pc_adjustment = 0; - } - step_pc -= pc_adjustment; - - bool finished = false; - bool is_signal_frame = false; - if (elf->StepIfSignalHandler(rel_pc, regs.get(), process_memory_.get())) { - step_pc = rel_pc; - } else if (!elf->Step(step_pc, regs.get(), process_memory_.get(), &finished, - &is_signal_frame)) { - finished = true; - } - - // Skip any locations that are within this library. - if (num_frames != 0 || !ShouldSkipLibrary(map_info->name)) { - // Add frame information. - std::string func_name; - uint64_t func_offset; - if (elf->GetFunctionName(rel_pc, &func_name, &func_offset)) { - frame_info->emplace_back(map_info, cur_pc - pc_adjustment, rel_pc - pc_adjustment, - func_name, func_offset); - } else { - frame_info->emplace_back(map_info, cur_pc - pc_adjustment, rel_pc - pc_adjustment, "", 0); - } - num_frames++; - } - - if (finished || frame_info->size() == max_frames || - (cur_pc == regs->pc() && cur_sp == regs->sp())) { - break; - } - adjust_pc = true; - } - return num_frames != 0; -} - -} // namespace unwindstack diff --git a/libunwindstack/Log.cpp b/libunwindstack/Log.cpp deleted file mode 100644 index 436e23c28..000000000 --- a/libunwindstack/Log.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2016 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 - -#define LOG_TAG "unwind" -#include - -#include - -#include - -namespace unwindstack { - -static bool g_print_to_stdout = false; - -void log_to_stdout(bool enable) { - g_print_to_stdout = enable; -} - -// Send the data to the log. -void log(uint8_t indent, const char* format, ...) { - std::string real_format; - if (indent > 0) { - real_format = android::base::StringPrintf("%*s%s", 2 * indent, " ", format); - } else { - real_format = format; - } - va_list args; - va_start(args, format); - if (g_print_to_stdout) { - real_format += '\n'; - vprintf(real_format.c_str(), args); - } else { - LOG_PRI_VA(ANDROID_LOG_INFO, LOG_TAG, real_format.c_str(), args); - } - va_end(args); -} - -} // namespace unwindstack diff --git a/libunwindstack/MapInfo.cpp b/libunwindstack/MapInfo.cpp deleted file mode 100644 index 31f314434..000000000 --- a/libunwindstack/MapInfo.cpp +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright (C) 2017 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 "MemoryFileAtOffset.h" -#include "MemoryRange.h" - -namespace unwindstack { - -bool MapInfo::InitFileMemoryFromPreviousReadOnlyMap(MemoryFileAtOffset* memory) { - // One last attempt, see if the previous map is read-only with the - // same name and stretches across this map. - if (prev_real_map == nullptr || prev_real_map->flags != PROT_READ) { - return false; - } - - uint64_t map_size = end - prev_real_map->end; - if (!memory->Init(name, prev_real_map->offset, map_size)) { - return false; - } - - uint64_t max_size; - if (!Elf::GetInfo(memory, &max_size) || max_size < map_size) { - return false; - } - - if (!memory->Init(name, prev_real_map->offset, max_size)) { - return false; - } - - elf_offset = offset - prev_real_map->offset; - elf_start_offset = prev_real_map->offset; - return true; -} - -Memory* MapInfo::GetFileMemory() { - std::unique_ptr memory(new MemoryFileAtOffset); - if (offset == 0) { - if (memory->Init(name, 0)) { - return memory.release(); - } - return nullptr; - } - - // These are the possibilities when the offset is non-zero. - // - There is an elf file embedded in a file, and the offset is the - // the start of the elf in the file. - // - There is an elf file embedded in a file, and the offset is the - // the start of the executable part of the file. The actual start - // of the elf is in the read-only segment preceeding this map. - // - The whole file is an elf file, and the offset needs to be saved. - // - // Map in just the part of the file for the map. If this is not - // a valid elf, then reinit as if the whole file is an elf file. - // If the offset is a valid elf, then determine the size of the map - // and reinit to that size. This is needed because the dynamic linker - // only maps in a portion of the original elf, and never the symbol - // file data. - uint64_t map_size = end - start; - if (!memory->Init(name, offset, map_size)) { - return nullptr; - } - - // Check if the start of this map is an embedded elf. - uint64_t max_size = 0; - if (Elf::GetInfo(memory.get(), &max_size)) { - elf_start_offset = offset; - if (max_size > map_size) { - if (memory->Init(name, offset, max_size)) { - return memory.release(); - } - // Try to reinit using the default map_size. - if (memory->Init(name, offset, map_size)) { - return memory.release(); - } - elf_start_offset = 0; - return nullptr; - } - return memory.release(); - } - - // No elf at offset, try to init as if the whole file is an elf. - if (memory->Init(name, 0) && Elf::IsValidElf(memory.get())) { - elf_offset = offset; - // Need to check how to set the elf start offset. If this map is not - // the r-x map of a r-- map, then use the real offset value. Otherwise, - // use 0. - if (prev_real_map == nullptr || prev_real_map->offset != 0 || - prev_real_map->flags != PROT_READ || prev_real_map->name != name) { - elf_start_offset = offset; - } - return memory.release(); - } - - // See if the map previous to this one contains a read-only map - // that represents the real start of the elf data. - if (InitFileMemoryFromPreviousReadOnlyMap(memory.get())) { - return memory.release(); - } - - // Failed to find elf at start of file or at read-only map, return - // file object from the current map. - if (memory->Init(name, offset, map_size)) { - return memory.release(); - } - return nullptr; -} - -Memory* MapInfo::CreateMemory(const std::shared_ptr& process_memory) { - if (end <= start) { - return nullptr; - } - - elf_offset = 0; - - // Fail on device maps. - if (flags & MAPS_FLAGS_DEVICE_MAP) { - return nullptr; - } - - // First try and use the file associated with the info. - if (!name.empty()) { - Memory* memory = GetFileMemory(); - if (memory != nullptr) { - return memory; - } - } - - if (process_memory == nullptr) { - return nullptr; - } - - // Need to verify that this elf is valid. It's possible that - // only part of the elf file to be mapped into memory is in the executable - // map. In this case, there will be another read-only map that includes the - // first part of the elf file. This is done if the linker rosegment - // option is used. - std::unique_ptr memory(new MemoryRange(process_memory, start, end - start, 0)); - if (Elf::IsValidElf(memory.get())) { - memory_backed_elf = true; - return memory.release(); - } - - // Find the read-only map by looking at the previous map. The linker - // doesn't guarantee that this invariant will always be true. However, - // if that changes, there is likely something else that will change and - // break something. - if (offset == 0 || name.empty() || prev_real_map == nullptr || prev_real_map->name != name || - prev_real_map->offset >= offset) { - return nullptr; - } - - // Make sure that relative pc values are corrected properly. - elf_offset = offset - prev_real_map->offset; - // Use this as the elf start offset, otherwise, you always get offsets into - // the r-x section, which is not quite the right information. - elf_start_offset = prev_real_map->offset; - - MemoryRanges* ranges = new MemoryRanges; - ranges->Insert(new MemoryRange(process_memory, prev_real_map->start, - prev_real_map->end - prev_real_map->start, 0)); - ranges->Insert(new MemoryRange(process_memory, start, end - start, elf_offset)); - - memory_backed_elf = true; - return ranges; -} - -Elf* MapInfo::GetElf(const std::shared_ptr& process_memory, ArchEnum expected_arch) { - { - // Make sure no other thread is trying to add the elf to this map. - std::lock_guard guard(mutex_); - - if (elf.get() != nullptr) { - return elf.get(); - } - - bool locked = false; - if (Elf::CachingEnabled() && !name.empty()) { - Elf::CacheLock(); - locked = true; - if (Elf::CacheGet(this)) { - Elf::CacheUnlock(); - return elf.get(); - } - } - - Memory* memory = CreateMemory(process_memory); - if (locked) { - if (Elf::CacheAfterCreateMemory(this)) { - delete memory; - Elf::CacheUnlock(); - return elf.get(); - } - } - elf.reset(new Elf(memory)); - // If the init fails, keep the elf around as an invalid object so we - // don't try to reinit the object. - elf->Init(); - if (elf->valid() && expected_arch != elf->arch()) { - // Make the elf invalid, mismatch between arch and expected arch. - elf->Invalidate(); - } - - if (locked) { - Elf::CacheAdd(this); - Elf::CacheUnlock(); - } - } - - if (!elf->valid()) { - elf_start_offset = offset; - } else if (prev_real_map != nullptr && elf_start_offset != offset && - prev_real_map->offset == elf_start_offset && prev_real_map->name == name) { - // If there is a read-only map then a read-execute map that represents the - // same elf object, make sure the previous map is using the same elf - // object if it hasn't already been set. - std::lock_guard guard(prev_real_map->mutex_); - if (prev_real_map->elf.get() == nullptr) { - prev_real_map->elf = elf; - prev_real_map->memory_backed_elf = memory_backed_elf; - } - } - return elf.get(); -} - -bool MapInfo::GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) { - { - // Make sure no other thread is trying to update this elf object. - std::lock_guard guard(mutex_); - if (elf == nullptr) { - return false; - } - } - // No longer need the lock, once the elf object is created, it is not deleted - // until this object is deleted. - return elf->GetFunctionName(addr, name, func_offset); -} - -uint64_t MapInfo::GetLoadBias(const std::shared_ptr& process_memory) { - int64_t cur_load_bias = load_bias.load(); - if (cur_load_bias != INT64_MAX) { - return cur_load_bias; - } - - { - // Make sure no other thread is trying to add the elf to this map. - std::lock_guard guard(mutex_); - if (elf != nullptr) { - if (elf->valid()) { - cur_load_bias = elf->GetLoadBias(); - load_bias = cur_load_bias; - return cur_load_bias; - } else { - load_bias = 0; - return 0; - } - } - } - - // Call lightweight static function that will only read enough of the - // elf data to get the load bias. - std::unique_ptr memory(CreateMemory(process_memory)); - cur_load_bias = Elf::GetLoadBias(memory.get()); - load_bias = cur_load_bias; - return cur_load_bias; -} - -MapInfo::~MapInfo() { - uintptr_t id = build_id.load(); - if (id != 0) { - delete reinterpret_cast(id); - } -} - -std::string MapInfo::GetBuildID() { - uintptr_t id = build_id.load(); - if (id != 0) { - return *reinterpret_cast(id); - } - - // No need to lock, at worst if multiple threads do this at the same - // time it should be detected and only one thread should win and - // save the data. - std::unique_ptr cur_build_id(new std::string); - - // Now need to see if the elf object exists. - // Make sure no other thread is trying to add the elf to this map. - mutex_.lock(); - Elf* elf_obj = elf.get(); - mutex_.unlock(); - if (elf_obj != nullptr) { - *cur_build_id = elf_obj->GetBuildID(); - } else { - // This will only work if we can get the file associated with this memory. - // If this is only available in memory, then the section name information - // is not present and we will not be able to find the build id info. - std::unique_ptr memory(GetFileMemory()); - if (memory != nullptr) { - *cur_build_id = Elf::GetBuildID(memory.get()); - } - } - - id = reinterpret_cast(cur_build_id.get()); - uintptr_t expected_id = 0; - if (build_id.compare_exchange_weak(expected_id, id)) { - // Value saved, so make sure the memory is not freed. - cur_build_id.release(); - } - return *reinterpret_cast(id); -} - -std::string MapInfo::GetPrintableBuildID() { - std::string raw_build_id = GetBuildID(); - if (raw_build_id.empty()) { - return ""; - } - std::string printable_build_id; - for (const char& c : raw_build_id) { - // Use %hhx to avoid sign extension on abis that have signed chars. - printable_build_id += android::base::StringPrintf("%02hhx", c); - } - return printable_build_id; -} - -} // namespace unwindstack diff --git a/libunwindstack/Maps.cpp b/libunwindstack/Maps.cpp deleted file mode 100644 index 670d9046f..000000000 --- a/libunwindstack/Maps.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (C) 2016 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 - -namespace unwindstack { - -MapInfo* Maps::Find(uint64_t pc) { - if (maps_.empty()) { - return nullptr; - } - size_t first = 0; - size_t last = maps_.size(); - while (first < last) { - size_t index = (first + last) / 2; - const auto& cur = maps_[index]; - if (pc >= cur->start && pc < cur->end) { - return cur.get(); - } else if (pc < cur->start) { - last = index; - } else { - first = index + 1; - } - } - return nullptr; -} - -bool Maps::Parse() { - MapInfo* prev_map = nullptr; - MapInfo* prev_real_map = nullptr; - return android::procinfo::ReadMapFile( - GetMapsFile(), - [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t, const char* name) { - // Mark a device map in /dev/ and not in /dev/ashmem/ specially. - if (strncmp(name, "/dev/", 5) == 0 && strncmp(name + 5, "ashmem/", 7) != 0) { - flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP; - } - maps_.emplace_back(new MapInfo(prev_map, prev_real_map, start, end, pgoff, flags, name)); - prev_map = maps_.back().get(); - if (!prev_map->IsBlank()) { - prev_real_map = prev_map; - } - }); -} - -void Maps::Add(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags, - const std::string& name, uint64_t load_bias) { - MapInfo* prev_map = maps_.empty() ? nullptr : maps_.back().get(); - MapInfo* prev_real_map = prev_map; - while (prev_real_map != nullptr && prev_real_map->IsBlank()) { - prev_real_map = prev_real_map->prev_map; - } - - auto map_info = - std::make_unique(prev_map, prev_real_map, start, end, offset, flags, name); - map_info->load_bias = load_bias; - maps_.emplace_back(std::move(map_info)); -} - -void Maps::Sort() { - std::sort(maps_.begin(), maps_.end(), - [](const std::unique_ptr& a, const std::unique_ptr& b) { - return a->start < b->start; }); - - // Set the prev_map values on the info objects. - MapInfo* prev_map = nullptr; - MapInfo* prev_real_map = nullptr; - for (const auto& map_info : maps_) { - map_info->prev_map = prev_map; - map_info->prev_real_map = prev_real_map; - prev_map = map_info.get(); - if (!prev_map->IsBlank()) { - prev_real_map = prev_map; - } - } -} - -bool BufferMaps::Parse() { - std::string content(buffer_); - MapInfo* prev_map = nullptr; - MapInfo* prev_real_map = nullptr; - return android::procinfo::ReadMapFileContent( - &content[0], - [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t, const char* name) { - // Mark a device map in /dev/ and not in /dev/ashmem/ specially. - if (strncmp(name, "/dev/", 5) == 0 && strncmp(name + 5, "ashmem/", 7) != 0) { - flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP; - } - maps_.emplace_back(new MapInfo(prev_map, prev_real_map, start, end, pgoff, flags, name)); - prev_map = maps_.back().get(); - if (!prev_map->IsBlank()) { - prev_real_map = prev_map; - } - }); -} - -const std::string RemoteMaps::GetMapsFile() const { - return "/proc/" + std::to_string(pid_) + "/maps"; -} - -const std::string LocalUpdatableMaps::GetMapsFile() const { - return "/proc/self/maps"; -} - -bool LocalUpdatableMaps::Reparse() { - // New maps will be added at the end without deleting the old ones. - size_t last_map_idx = maps_.size(); - if (!Parse()) { - maps_.resize(last_map_idx); - return false; - } - - size_t total_entries = maps_.size(); - size_t search_map_idx = 0; - for (size_t new_map_idx = last_map_idx; new_map_idx < maps_.size(); new_map_idx++) { - auto& new_map_info = maps_[new_map_idx]; - uint64_t start = new_map_info->start; - uint64_t end = new_map_info->end; - uint64_t flags = new_map_info->flags; - std::string* name = &new_map_info->name; - for (size_t old_map_idx = search_map_idx; old_map_idx < last_map_idx; old_map_idx++) { - auto& info = maps_[old_map_idx]; - if (start == info->start && end == info->end && flags == info->flags && *name == info->name) { - // No need to check - search_map_idx = old_map_idx + 1; - if (new_map_idx + 1 < maps_.size()) { - maps_[new_map_idx + 1]->prev_map = info.get(); - maps_[new_map_idx + 1]->prev_real_map = - info->IsBlank() ? info->prev_real_map : info.get(); - } - maps_[new_map_idx] = nullptr; - total_entries--; - break; - } else if (info->start > start) { - // Stop, there isn't going to be a match. - search_map_idx = old_map_idx; - break; - } - - // Never delete these maps, they may be in use. The assumption is - // that there will only every be a handful of these so waiting - // to destroy them is not too expensive. - saved_maps_.emplace_back(std::move(info)); - search_map_idx = old_map_idx + 1; - maps_[old_map_idx] = nullptr; - total_entries--; - } - if (search_map_idx >= last_map_idx) { - break; - } - } - - // Now move out any of the maps that never were found. - for (size_t i = search_map_idx; i < last_map_idx; i++) { - saved_maps_.emplace_back(std::move(maps_[i])); - maps_[i] = nullptr; - total_entries--; - } - - // Sort all of the values such that the nullptrs wind up at the end, then - // resize them away. - std::sort(maps_.begin(), maps_.end(), [](const auto& a, const auto& b) { - if (a == nullptr) { - return false; - } else if (b == nullptr) { - return true; - } - return a->start < b->start; - }); - maps_.resize(total_entries); - - return true; -} - -} // namespace unwindstack diff --git a/libunwindstack/Memory.cpp b/libunwindstack/Memory.cpp deleted file mode 100644 index b4623faac..000000000 --- a/libunwindstack/Memory.cpp +++ /dev/null @@ -1,498 +0,0 @@ -/* - * Copyright (C) 2016 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 "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 { - -static size_t ProcessVmRead(pid_t pid, uint64_t remote_src, void* dst, size_t len) { - - // Split up the remote read across page boundaries. - // From the manpage: - // A partial read/write may result if one of the remote_iov elements points to an invalid - // memory region in the remote process. - // - // Partial transfers apply at the granularity of iovec elements. These system calls won't - // perform a partial transfer that splits a single iovec element. - constexpr size_t kMaxIovecs = 64; - struct iovec src_iovs[kMaxIovecs]; - - uint64_t cur = remote_src; - size_t total_read = 0; - while (len > 0) { - struct iovec dst_iov = { - .iov_base = &reinterpret_cast(dst)[total_read], .iov_len = len, - }; - - size_t iovecs_used = 0; - while (len > 0) { - if (iovecs_used == kMaxIovecs) { - break; - } - - // struct iovec uses void* for iov_base. - if (cur >= UINTPTR_MAX) { - errno = EFAULT; - return total_read; - } - - src_iovs[iovecs_used].iov_base = reinterpret_cast(cur); - - uintptr_t misalignment = cur & (getpagesize() - 1); - size_t iov_len = getpagesize() - misalignment; - iov_len = std::min(iov_len, len); - - len -= iov_len; - if (__builtin_add_overflow(cur, iov_len, &cur)) { - errno = EFAULT; - return total_read; - } - - src_iovs[iovecs_used].iov_len = iov_len; - ++iovecs_used; - } - - ssize_t rc = process_vm_readv(pid, &dst_iov, 1, src_iovs, iovecs_used, 0); - if (rc == -1) { - return total_read; - } - total_read += rc; - } - return total_read; -} - -static bool PtraceReadLong(pid_t pid, uint64_t addr, long* value) { - // ptrace() returns -1 and sets errno when the operation fails. - // To disambiguate -1 from a valid result, we clear errno beforehand. - errno = 0; - *value = ptrace(PTRACE_PEEKTEXT, pid, reinterpret_cast(addr), nullptr); - if (*value == -1 && errno) { - return false; - } - return true; -} - -static size_t PtraceRead(pid_t pid, uint64_t addr, void* dst, size_t bytes) { - // Make sure that there is no overflow. - uint64_t max_size; - if (__builtin_add_overflow(addr, bytes, &max_size)) { - return 0; - } - - size_t bytes_read = 0; - long data; - size_t align_bytes = addr & (sizeof(long) - 1); - if (align_bytes != 0) { - if (!PtraceReadLong(pid, addr & ~(sizeof(long) - 1), &data)) { - return 0; - } - size_t copy_bytes = std::min(sizeof(long) - align_bytes, bytes); - memcpy(dst, reinterpret_cast(&data) + align_bytes, copy_bytes); - addr += copy_bytes; - dst = reinterpret_cast(reinterpret_cast(dst) + copy_bytes); - bytes -= copy_bytes; - bytes_read += copy_bytes; - } - - for (size_t i = 0; i < bytes / sizeof(long); i++) { - if (!PtraceReadLong(pid, addr, &data)) { - return bytes_read; - } - memcpy(dst, &data, sizeof(long)); - dst = reinterpret_cast(reinterpret_cast(dst) + sizeof(long)); - addr += sizeof(long); - bytes_read += sizeof(long); - } - - size_t left_over = bytes & (sizeof(long) - 1); - if (left_over) { - if (!PtraceReadLong(pid, addr, &data)) { - return bytes_read; - } - memcpy(dst, &data, left_over); - bytes_read += left_over; - } - return bytes_read; -} - -bool Memory::ReadFully(uint64_t addr, void* dst, size_t size) { - size_t rc = Read(addr, dst, size); - return rc == size; -} - -bool Memory::ReadString(uint64_t addr, std::string* dst, size_t max_read) { - char buffer[256]; // Large enough for 99% of symbol names. - size_t size = 0; // Number of bytes which were read into the buffer. - for (size_t offset = 0; offset < max_read; offset += size) { - // Look for null-terminator first, so we can allocate string of exact size. - // If we know the end of valid memory range, do the reads in larger blocks. - size_t read = std::min(sizeof(buffer), max_read - offset); - size = Read(addr + offset, buffer, read); - if (size == 0) { - return false; // We have not found end of string yet and we can not read more data. - } - size_t length = strnlen(buffer, size); // Index of the null-terminator. - if (length < size) { - // We found the null-terminator. Allocate the string and set its content. - if (offset == 0) { - // We did just single read, so the buffer already contains the whole string. - dst->assign(buffer, length); - return true; - } else { - // The buffer contains only the last block. Read the whole string again. - dst->assign(offset + length, '\0'); - return ReadFully(addr, dst->data(), dst->size()); - } - } - } - 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()); - } - return std::shared_ptr(new MemoryRemote(pid)); -} - -std::shared_ptr Memory::CreateProcessMemoryCached(pid_t pid) { - if (pid == getpid()) { - return std::shared_ptr(new MemoryCache(new MemoryLocal())); - } - 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 >= size_) { - return 0; - } - - size_t bytes_left = size_ - static_cast(addr); - const unsigned char* actual_base = static_cast(raw_) + addr; - size_t actual_len = std::min(bytes_left, size); - - memcpy(dst, actual_base, actual_len); - return actual_len; -} - -uint8_t* MemoryBuffer::GetPtr(size_t offset) { - if (offset < size_) { - return &raw_[offset]; - } - return nullptr; -} - -MemoryFileAtOffset::~MemoryFileAtOffset() { - Clear(); -} - -void MemoryFileAtOffset::Clear() { - if (data_) { - munmap(&data_[-offset_], size_ + offset_); - data_ = nullptr; - } -} - -bool MemoryFileAtOffset::Init(const std::string& file, uint64_t offset, uint64_t size) { - // Clear out any previous data if it exists. - Clear(); - - android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(file.c_str(), O_RDONLY | O_CLOEXEC))); - if (fd == -1) { - return false; - } - struct stat buf; - if (fstat(fd, &buf) == -1) { - return false; - } - if (offset >= static_cast(buf.st_size)) { - return false; - } - - offset_ = offset & (getpagesize() - 1); - uint64_t aligned_offset = offset & ~(getpagesize() - 1); - if (aligned_offset > static_cast(buf.st_size) || - offset > static_cast(buf.st_size)) { - return false; - } - - size_ = buf.st_size - aligned_offset; - uint64_t max_size; - if (!__builtin_add_overflow(size, offset_, &max_size) && max_size < size_) { - // Truncate the mapped size. - size_ = max_size; - } - void* map = mmap(nullptr, size_, PROT_READ, MAP_PRIVATE, fd, aligned_offset); - if (map == MAP_FAILED) { - return false; - } - - data_ = &reinterpret_cast(map)[offset_]; - size_ -= offset_; - - return true; -} - -size_t MemoryFileAtOffset::Read(uint64_t addr, void* dst, size_t size) { - if (addr >= size_) { - return 0; - } - - size_t bytes_left = size_ - static_cast(addr); - const unsigned char* actual_base = static_cast(data_) + addr; - size_t actual_len = std::min(bytes_left, size); - - memcpy(dst, actual_base, actual_len); - return actual_len; -} - -size_t MemoryRemote::Read(uint64_t addr, void* dst, size_t size) { -#if !defined(__LP64__) - // Cannot read an address greater than 32 bits in a 32 bit context. - if (addr > UINT32_MAX) { - return 0; - } -#endif - - size_t (*read_func)(pid_t, uint64_t, void*, size_t) = - reinterpret_cast(read_redirect_func_.load()); - if (read_func != nullptr) { - return read_func(pid_, addr, dst, size); - } else { - // Prefer process_vm_read, try it first. If it doesn't work, use the - // ptrace function. If at least one of them returns at least some data, - // set that as the permanent function to use. - // This assumes that if process_vm_read works once, it will continue - // to work. - size_t bytes = ProcessVmRead(pid_, addr, dst, size); - if (bytes > 0) { - read_redirect_func_ = reinterpret_cast(ProcessVmRead); - return bytes; - } - bytes = PtraceRead(pid_, addr, dst, size); - if (bytes > 0) { - read_redirect_func_ = reinterpret_cast(PtraceRead); - } - return bytes; - } -} - -size_t MemoryLocal::Read(uint64_t addr, void* dst, size_t size) { - return ProcessVmRead(getpid(), addr, dst, size); -} - -#if !defined(ANDROID_EXPERIMENTAL_MTE) -long MemoryRemote::ReadTag(uint64_t) { - return -1; -} - -long MemoryLocal::ReadTag(uint64_t) { - return -1; -} -#endif - -MemoryRange::MemoryRange(const std::shared_ptr& memory, uint64_t begin, uint64_t length, - uint64_t offset) - : memory_(memory), begin_(begin), length_(length), offset_(offset) {} - -size_t MemoryRange::Read(uint64_t addr, void* dst, size_t size) { - if (addr < offset_) { - return 0; - } - - uint64_t read_offset = addr - offset_; - if (read_offset >= length_) { - return 0; - } - - uint64_t read_length = std::min(static_cast(size), length_ - read_offset); - uint64_t read_addr; - if (__builtin_add_overflow(read_offset, begin_, &read_addr)) { - return 0; - } - - return memory_->Read(read_addr, dst, read_length); -} - -void MemoryRanges::Insert(MemoryRange* memory) { - maps_.emplace(memory->offset() + memory->length(), memory); -} - -size_t MemoryRanges::Read(uint64_t addr, void* dst, size_t size) { - auto entry = maps_.upper_bound(addr); - if (entry != maps_.end()) { - return entry->second->Read(addr, dst, size); - } - return 0; -} - -bool MemoryOffline::Init(const std::string& file, uint64_t offset) { - auto memory_file = std::make_shared(); - if (!memory_file->Init(file, offset)) { - return false; - } - - // The first uint64_t value is the start of memory. - uint64_t start; - if (!memory_file->ReadFully(0, &start, sizeof(start))) { - return false; - } - - uint64_t size = memory_file->Size(); - if (__builtin_sub_overflow(size, sizeof(start), &size)) { - return false; - } - - memory_ = std::make_unique(memory_file, sizeof(start), size, start); - return true; -} - -size_t MemoryOffline::Read(uint64_t addr, void* dst, size_t size) { - if (!memory_) { - return 0; - } - - return memory_->Read(addr, dst, size); -} - -MemoryOfflineBuffer::MemoryOfflineBuffer(const uint8_t* data, uint64_t start, uint64_t end) - : data_(data), start_(start), end_(end) {} - -void MemoryOfflineBuffer::Reset(const uint8_t* data, uint64_t start, uint64_t end) { - data_ = data; - start_ = start; - end_ = end; -} - -size_t MemoryOfflineBuffer::Read(uint64_t addr, void* dst, size_t size) { - if (addr < start_ || addr >= end_) { - return 0; - } - - size_t read_length = std::min(size, static_cast(end_ - addr)); - memcpy(dst, &data_[addr - start_], read_length); - return read_length; -} - -MemoryOfflineParts::~MemoryOfflineParts() { - for (auto memory : memories_) { - delete memory; - } -} - -size_t MemoryOfflineParts::Read(uint64_t addr, void* dst, size_t size) { - if (memories_.empty()) { - return 0; - } - - // Do a read on each memory object, no support for reading across the - // different memory objects. - for (MemoryOffline* memory : memories_) { - size_t bytes = memory->Read(addr, dst, size); - if (bytes != 0) { - return bytes; - } - } - return 0; -} - -size_t MemoryCache::Read(uint64_t addr, void* dst, size_t size) { - // Only bother caching and looking at the cache if this is a small read for now. - if (size > 64) { - return impl_->Read(addr, dst, size); - } - - uint64_t addr_page = addr >> kCacheBits; - auto entry = cache_.find(addr_page); - uint8_t* cache_dst; - if (entry != cache_.end()) { - cache_dst = entry->second; - } else { - cache_dst = cache_[addr_page]; - if (!impl_->ReadFully(addr_page << kCacheBits, cache_dst, kCacheSize)) { - // Erase the entry. - cache_.erase(addr_page); - return impl_->Read(addr, dst, size); - } - } - size_t max_read = ((addr_page + 1) << kCacheBits) - addr; - if (size <= max_read) { - memcpy(dst, &cache_dst[addr & kCacheMask], size); - return size; - } - - // The read crossed into another cached entry, since a read can only cross - // into one extra cached page, duplicate the code rather than looping. - memcpy(dst, &cache_dst[addr & kCacheMask], max_read); - dst = &reinterpret_cast(dst)[max_read]; - addr_page++; - - entry = cache_.find(addr_page); - if (entry != cache_.end()) { - cache_dst = entry->second; - } else { - cache_dst = cache_[addr_page]; - if (!impl_->ReadFully(addr_page << kCacheBits, cache_dst, kCacheSize)) { - // Erase the entry. - cache_.erase(addr_page); - return impl_->Read(addr_page << kCacheBits, dst, size - max_read) + max_read; - } - } - memcpy(dst, cache_dst, size - max_read); - return size; -} - -} // namespace unwindstack diff --git a/libunwindstack/MemoryBuffer.h b/libunwindstack/MemoryBuffer.h deleted file mode 100644 index a91e59f1e..000000000 --- a/libunwindstack/MemoryBuffer.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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() { free(raw_); } - - size_t Read(uint64_t addr, void* dst, size_t size) override; - - uint8_t* GetPtr(size_t offset); - - bool Resize(size_t size) { - raw_ = reinterpret_cast(realloc(raw_, size)); - if (raw_ == nullptr) { - size_ = 0; - return false; - } - size_ = size; - return true; - } - - uint64_t Size() { return size_; } - - private: - uint8_t* raw_ = nullptr; - size_t size_ = 0; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_MEMORY_BUFFER_H diff --git a/libunwindstack/MemoryCache.h b/libunwindstack/MemoryCache.h deleted file mode 100644 index d97640d8b..000000000 --- a/libunwindstack/MemoryCache.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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; - long ReadTag(uint64_t addr) override { return impl_->ReadTag(addr); } - - 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 deleted file mode 100644 index d136eb44a..000000000 --- a/libunwindstack/MemoryFileAtOffset.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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 deleted file mode 100644 index 741f1077c..000000000 --- a/libunwindstack/MemoryLocal.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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; - - bool IsLocal() const override { return true; } - - size_t Read(uint64_t addr, void* dst, size_t size) override; - long ReadTag(uint64_t addr) override; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_MEMORY_LOCAL_H diff --git a/libunwindstack/MemoryMte.cpp b/libunwindstack/MemoryMte.cpp deleted file mode 100644 index 46a546e1c..000000000 --- a/libunwindstack/MemoryMte.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2020 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. - */ - -#if defined(ANDROID_EXPERIMENTAL_MTE) - -#include -#include - -#include -#include - -#include "MemoryLocal.h" -#include "MemoryRemote.h" - -namespace unwindstack { - -long MemoryRemote::ReadTag(uint64_t addr) { -#if defined(__aarch64__) - char tag; - iovec iov = {&tag, 1}; - if (ptrace(PTRACE_PEEKMTETAGS, pid_, reinterpret_cast(addr), &iov) != 0 || - iov.iov_len != 1) { - return -1; - } - return tag; -#else - (void)addr; - return -1; -#endif -} - -long MemoryLocal::ReadTag(uint64_t addr) { -#if defined(__aarch64__) - // Check that the memory is readable first. This is racy with the ldg but there's not much - // we can do about it. - char data; - if (!mte_supported() || !Read(addr, &data, 1)) { - return -1; - } - - __asm__ __volatile__(".arch_extension mte; ldg %0, [%0]" : "+r"(addr) : : "memory"); - return (addr >> 56) & 0xf; -#else - (void)addr; - return -1; -#endif -} - -} // namespace unwindstack - -#endif diff --git a/libunwindstack/MemoryOffline.h b/libunwindstack/MemoryOffline.h deleted file mode 100644 index 789f1a268..000000000 --- a/libunwindstack/MemoryOffline.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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 deleted file mode 100644 index 64c49a1ca..000000000 --- a/libunwindstack/MemoryOfflineBuffer.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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 deleted file mode 100644 index 3b4ab5c91..000000000 --- a/libunwindstack/MemoryRange.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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 deleted file mode 100644 index dd09c8838..000000000 --- a/libunwindstack/MemoryRemote.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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; - long ReadTag(uint64_t addr) 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/OWNERS b/libunwindstack/OWNERS deleted file mode 100644 index 6f7e4a3c4..000000000 --- a/libunwindstack/OWNERS +++ /dev/null @@ -1 +0,0 @@ -cferris@google.com diff --git a/libunwindstack/Regs.cpp b/libunwindstack/Regs.cpp deleted file mode 100644 index 03aa6c205..000000000 --- a/libunwindstack/Regs.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2016 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 - -namespace unwindstack { - -// The largest user structure. -constexpr size_t MAX_USER_REGS_SIZE = sizeof(mips64_user_regs) + 10; - -// This function assumes that reg_data is already aligned to a 64 bit value. -// If not this could crash with an unaligned access. -Regs* Regs::RemoteGet(pid_t pid) { - // Make the buffer large enough to contain the largest registers type. - std::vector buffer(MAX_USER_REGS_SIZE / sizeof(uint64_t)); - struct iovec io; - io.iov_base = buffer.data(); - io.iov_len = buffer.size() * sizeof(uint64_t); - - if (ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, reinterpret_cast(&io)) == -1) { - return nullptr; - } - - switch (io.iov_len) { - case sizeof(x86_user_regs): - return RegsX86::Read(buffer.data()); - case sizeof(x86_64_user_regs): - return RegsX86_64::Read(buffer.data()); - case sizeof(arm_user_regs): - return RegsArm::Read(buffer.data()); - case sizeof(arm64_user_regs): - return RegsArm64::Read(buffer.data()); - case sizeof(mips_user_regs): - return RegsMips::Read(buffer.data()); - case sizeof(mips64_user_regs): - return RegsMips64::Read(buffer.data()); - } - return nullptr; -} - -Regs* Regs::CreateFromUcontext(ArchEnum arch, void* ucontext) { - switch (arch) { - case ARCH_X86: - return RegsX86::CreateFromUcontext(ucontext); - case ARCH_X86_64: - return RegsX86_64::CreateFromUcontext(ucontext); - case ARCH_ARM: - return RegsArm::CreateFromUcontext(ucontext); - case ARCH_ARM64: - return RegsArm64::CreateFromUcontext(ucontext); - case ARCH_MIPS: - return RegsMips::CreateFromUcontext(ucontext); - case ARCH_MIPS64: - return RegsMips64::CreateFromUcontext(ucontext); - case ARCH_UNKNOWN: - default: - return nullptr; - } -} - -ArchEnum Regs::CurrentArch() { -#if defined(__arm__) - return ARCH_ARM; -#elif defined(__aarch64__) - return ARCH_ARM64; -#elif defined(__i386__) - return ARCH_X86; -#elif defined(__x86_64__) - return ARCH_X86_64; -#else - abort(); -#endif -} - -Regs* Regs::CreateFromLocal() { - Regs* regs; -#if defined(__arm__) - regs = new RegsArm(); -#elif defined(__aarch64__) - regs = new RegsArm64(); -#elif defined(__i386__) - regs = new RegsX86(); -#elif defined(__x86_64__) - regs = new RegsX86_64(); -#else - abort(); -#endif - return regs; -} - -uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf, ArchEnum arch) { - switch (arch) { - case ARCH_ARM: { - if (!elf->valid()) { - return 2; - } - - uint64_t load_bias = elf->GetLoadBias(); - if (rel_pc < load_bias) { - if (rel_pc < 2) { - return 0; - } - return 2; - } - uint64_t adjusted_rel_pc = rel_pc - load_bias; - if (adjusted_rel_pc < 5) { - if (adjusted_rel_pc < 2) { - return 0; - } - return 2; - } - - if (adjusted_rel_pc & 1) { - // This is a thumb instruction, it could be 2 or 4 bytes. - uint32_t value; - if (!elf->memory()->ReadFully(adjusted_rel_pc - 5, &value, sizeof(value)) || - (value & 0xe000f000) != 0xe000f000) { - return 2; - } - } - return 4; - } - case ARCH_ARM64: { - if (rel_pc < 4) { - return 0; - } - return 4; - } - case ARCH_MIPS: - case ARCH_MIPS64: { - if (rel_pc < 8) { - return 0; - } - // For now, just assume no compact branches - return 8; - } - case ARCH_X86: - case ARCH_X86_64: { - if (rel_pc == 0) { - return 0; - } - return 1; - } - case ARCH_UNKNOWN: - return 0; - } -} - -} // namespace unwindstack diff --git a/libunwindstack/RegsArm.cpp b/libunwindstack/RegsArm.cpp deleted file mode 100644 index 1aaa08f56..000000000 --- a/libunwindstack/RegsArm.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2016 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 - -namespace unwindstack { - -RegsArm::RegsArm() : RegsImpl(ARM_REG_LAST, Location(LOCATION_REGISTER, ARM_REG_LR)) {} - -ArchEnum RegsArm::Arch() { - return ARCH_ARM; -} - -uint64_t RegsArm::pc() { - return regs_[ARM_REG_PC]; -} - -uint64_t RegsArm::sp() { - return regs_[ARM_REG_SP]; -} - -void RegsArm::set_pc(uint64_t pc) { - regs_[ARM_REG_PC] = pc; -} - -void RegsArm::set_sp(uint64_t sp) { - regs_[ARM_REG_SP] = sp; -} - -bool RegsArm::SetPcFromReturnAddress(Memory*) { - uint32_t lr = regs_[ARM_REG_LR]; - if (regs_[ARM_REG_PC] == lr) { - return false; - } - - regs_[ARM_REG_PC] = lr; - return true; -} - -void RegsArm::IterateRegisters(std::function fn) { - fn("r0", regs_[ARM_REG_R0]); - fn("r1", regs_[ARM_REG_R1]); - fn("r2", regs_[ARM_REG_R2]); - fn("r3", regs_[ARM_REG_R3]); - fn("r4", regs_[ARM_REG_R4]); - fn("r5", regs_[ARM_REG_R5]); - fn("r6", regs_[ARM_REG_R6]); - fn("r7", regs_[ARM_REG_R7]); - fn("r8", regs_[ARM_REG_R8]); - fn("r9", regs_[ARM_REG_R9]); - fn("r10", regs_[ARM_REG_R10]); - fn("r11", regs_[ARM_REG_R11]); - fn("ip", regs_[ARM_REG_R12]); - fn("sp", regs_[ARM_REG_SP]); - fn("lr", regs_[ARM_REG_LR]); - fn("pc", regs_[ARM_REG_PC]); -} - -Regs* RegsArm::Read(void* remote_data) { - arm_user_regs* user = reinterpret_cast(remote_data); - - RegsArm* regs = new RegsArm(); - memcpy(regs->RawData(), &user->regs[0], ARM_REG_LAST * sizeof(uint32_t)); - return regs; -} - -Regs* RegsArm::CreateFromUcontext(void* ucontext) { - arm_ucontext_t* arm_ucontext = reinterpret_cast(ucontext); - - RegsArm* regs = new RegsArm(); - memcpy(regs->RawData(), &arm_ucontext->uc_mcontext.regs[0], ARM_REG_LAST * sizeof(uint32_t)); - return regs; -} - -bool RegsArm::StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) { - uint32_t data; - Memory* elf_memory = elf->memory(); - // Read from elf memory since it is usually more expensive to read from - // process memory. - if (!elf_memory->ReadFully(elf_offset, &data, sizeof(data))) { - return false; - } - - uint64_t offset = 0; - if (data == 0xe3a07077 || data == 0xef900077 || data == 0xdf002777) { - uint64_t sp = regs_[ARM_REG_SP]; - // non-RT sigreturn call. - // __restore: - // - // Form 1 (arm): - // 0x77 0x70 mov r7, #0x77 - // 0xa0 0xe3 svc 0x00000000 - // - // Form 2 (arm): - // 0x77 0x00 0x90 0xef svc 0x00900077 - // - // Form 3 (thumb): - // 0x77 0x27 movs r7, #77 - // 0x00 0xdf svc 0 - if (!process_memory->ReadFully(sp, &data, sizeof(data))) { - return false; - } - if (data == 0x5ac3c35a) { - // SP + uc_mcontext offset + r0 offset. - offset = sp + 0x14 + 0xc; - } else { - // SP + r0 offset - offset = sp + 0xc; - } - } else if (data == 0xe3a070ad || data == 0xef9000ad || data == 0xdf0027ad) { - uint64_t sp = regs_[ARM_REG_SP]; - // RT sigreturn call. - // __restore_rt: - // - // Form 1 (arm): - // 0xad 0x70 mov r7, #0xad - // 0xa0 0xe3 svc 0x00000000 - // - // Form 2 (arm): - // 0xad 0x00 0x90 0xef svc 0x009000ad - // - // Form 3 (thumb): - // 0xad 0x27 movs r7, #ad - // 0x00 0xdf svc 0 - if (!process_memory->ReadFully(sp, &data, sizeof(data))) { - return false; - } - if (data == sp + 8) { - // SP + 8 + sizeof(siginfo_t) + uc_mcontext_offset + r0 offset - offset = sp + 8 + 0x80 + 0x14 + 0xc; - } else { - // SP + sizeof(siginfo_t) + uc_mcontext_offset + r0 offset - offset = sp + 0x80 + 0x14 + 0xc; - } - } - if (offset == 0) { - return false; - } - - if (!process_memory->ReadFully(offset, regs_.data(), sizeof(uint32_t) * ARM_REG_LAST)) { - return false; - } - return true; -} - -Regs* RegsArm::Clone() { - return new RegsArm(*this); -} - -} // namespace unwindstack diff --git a/libunwindstack/RegsArm64.cpp b/libunwindstack/RegsArm64.cpp deleted file mode 100644 index b496187cb..000000000 --- a/libunwindstack/RegsArm64.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (C) 2016 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 - -namespace unwindstack { - -RegsArm64::RegsArm64() - : RegsImpl(ARM64_REG_LAST, Location(LOCATION_REGISTER, ARM64_REG_LR)) { - ResetPseudoRegisters(); - pac_mask_ = 0; -} - -ArchEnum RegsArm64::Arch() { - return ARCH_ARM64; -} - -uint64_t RegsArm64::pc() { - return regs_[ARM64_REG_PC]; -} - -uint64_t RegsArm64::sp() { - return regs_[ARM64_REG_SP]; -} - -void RegsArm64::set_pc(uint64_t pc) { - // If the target is aarch64 then the return address may have been - // signed using the Armv8.3-A Pointer Authentication extension. The - // original return address can be restored by stripping out the - // authentication code using a mask or xpaclri. xpaclri is a NOP on - // pre-Armv8.3-A architectures. - if ((0 != pc) && IsRASigned()) { - if (pac_mask_) { - pc &= ~pac_mask_; -#if defined(__aarch64__) - } else { - register uint64_t x30 __asm("x30") = pc; - // This is XPACLRI. - asm("hint 0x7" : "+r"(x30)); - pc = x30; -#endif - } - } - regs_[ARM64_REG_PC] = pc; -} - -void RegsArm64::set_sp(uint64_t sp) { - regs_[ARM64_REG_SP] = sp; -} - -bool RegsArm64::SetPcFromReturnAddress(Memory*) { - uint64_t lr = regs_[ARM64_REG_LR]; - if (regs_[ARM64_REG_PC] == lr) { - return false; - } - - regs_[ARM64_REG_PC] = lr; - return true; -} - -void RegsArm64::IterateRegisters(std::function fn) { - fn("x0", regs_[ARM64_REG_R0]); - fn("x1", regs_[ARM64_REG_R1]); - fn("x2", regs_[ARM64_REG_R2]); - fn("x3", regs_[ARM64_REG_R3]); - fn("x4", regs_[ARM64_REG_R4]); - fn("x5", regs_[ARM64_REG_R5]); - fn("x6", regs_[ARM64_REG_R6]); - fn("x7", regs_[ARM64_REG_R7]); - fn("x8", regs_[ARM64_REG_R8]); - fn("x9", regs_[ARM64_REG_R9]); - fn("x10", regs_[ARM64_REG_R10]); - fn("x11", regs_[ARM64_REG_R11]); - fn("x12", regs_[ARM64_REG_R12]); - fn("x13", regs_[ARM64_REG_R13]); - fn("x14", regs_[ARM64_REG_R14]); - fn("x15", regs_[ARM64_REG_R15]); - fn("x16", regs_[ARM64_REG_R16]); - fn("x17", regs_[ARM64_REG_R17]); - fn("x18", regs_[ARM64_REG_R18]); - fn("x19", regs_[ARM64_REG_R19]); - fn("x20", regs_[ARM64_REG_R20]); - fn("x21", regs_[ARM64_REG_R21]); - fn("x22", regs_[ARM64_REG_R22]); - fn("x23", regs_[ARM64_REG_R23]); - fn("x24", regs_[ARM64_REG_R24]); - fn("x25", regs_[ARM64_REG_R25]); - fn("x26", regs_[ARM64_REG_R26]); - fn("x27", regs_[ARM64_REG_R27]); - fn("x28", regs_[ARM64_REG_R28]); - fn("x29", regs_[ARM64_REG_R29]); - fn("lr", regs_[ARM64_REG_LR]); - fn("sp", regs_[ARM64_REG_SP]); - fn("pc", regs_[ARM64_REG_PC]); - fn("pst", regs_[ARM64_REG_PSTATE]); -} - -Regs* RegsArm64::Read(void* remote_data) { - arm64_user_regs* user = reinterpret_cast(remote_data); - - RegsArm64* regs = new RegsArm64(); - memcpy(regs->RawData(), &user->regs[0], (ARM64_REG_R30 + 1) * sizeof(uint64_t)); - uint64_t* reg_data = reinterpret_cast(regs->RawData()); - reg_data[ARM64_REG_SP] = user->sp; - reg_data[ARM64_REG_PC] = user->pc; - reg_data[ARM64_REG_PSTATE] = user->pstate; - return regs; -} - -Regs* RegsArm64::CreateFromUcontext(void* ucontext) { - arm64_ucontext_t* arm64_ucontext = reinterpret_cast(ucontext); - - RegsArm64* regs = new RegsArm64(); - memcpy(regs->RawData(), &arm64_ucontext->uc_mcontext.regs[0], ARM64_REG_LAST * sizeof(uint64_t)); - return regs; -} - -bool RegsArm64::StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) { - uint64_t data; - Memory* elf_memory = elf->memory(); - // Read from elf memory since it is usually more expensive to read from - // process memory. - if (!elf_memory->ReadFully(elf_offset, &data, sizeof(data))) { - return false; - } - - // Look for the kernel sigreturn function. - // __kernel_rt_sigreturn: - // 0xd2801168 mov x8, #0x8b - // 0xd4000001 svc #0x0 - if (data != 0xd4000001d2801168ULL) { - return false; - } - - // SP + sizeof(siginfo_t) + uc_mcontext offset + X0 offset. - if (!process_memory->ReadFully(regs_[ARM64_REG_SP] + 0x80 + 0xb0 + 0x08, regs_.data(), - sizeof(uint64_t) * ARM64_REG_LAST)) { - return false; - } - return true; -} - -void RegsArm64::ResetPseudoRegisters(void) { - // DWARF for AArch64 says RA_SIGN_STATE should be initialized to 0. - this->SetPseudoRegister(Arm64Reg::ARM64_PREG_RA_SIGN_STATE, 0); -} - -bool RegsArm64::SetPseudoRegister(uint16_t id, uint64_t value) { - if ((id >= Arm64Reg::ARM64_PREG_FIRST) && (id < Arm64Reg::ARM64_PREG_LAST)) { - pseudo_regs_[id - Arm64Reg::ARM64_PREG_FIRST] = value; - return true; - } - return false; -} - -bool RegsArm64::GetPseudoRegister(uint16_t id, uint64_t* value) { - if ((id >= Arm64Reg::ARM64_PREG_FIRST) && (id < Arm64Reg::ARM64_PREG_LAST)) { - *value = pseudo_regs_[id - Arm64Reg::ARM64_PREG_FIRST]; - return true; - } - return false; -} - -bool RegsArm64::IsRASigned() { - uint64_t value; - auto result = this->GetPseudoRegister(Arm64Reg::ARM64_PREG_RA_SIGN_STATE, &value); - return (result && (value != 0)); -} - -void RegsArm64::SetPACMask(uint64_t mask) { - pac_mask_ = mask; -} - -Regs* RegsArm64::Clone() { - return new RegsArm64(*this); -} - -} // namespace unwindstack diff --git a/libunwindstack/RegsInfo.h b/libunwindstack/RegsInfo.h deleted file mode 100644 index e445a9170..000000000 --- a/libunwindstack/RegsInfo.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2018 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_REGS_INFO_H -#define _LIBUNWINDSTACK_REGS_INFO_H - -#include - -#include - -namespace unwindstack { - -template -struct RegsInfo { - static constexpr size_t MAX_REGISTERS = 64; - - RegsInfo(RegsImpl* regs) : regs(regs) {} - - RegsImpl* regs = nullptr; - uint64_t saved_reg_map = 0; - AddressType saved_regs[MAX_REGISTERS]; - - inline AddressType Get(uint32_t reg) { - if (IsSaved(reg)) { - return saved_regs[reg]; - } - return (*regs)[reg]; - } - - inline AddressType* Save(uint32_t reg) { - if (reg >= MAX_REGISTERS) { - // This should never happen since all currently supported - // architectures have < 64 total registers. - abort(); - } - saved_reg_map |= 1ULL << reg; - saved_regs[reg] = (*regs)[reg]; - return &(*regs)[reg]; - } - - inline bool IsSaved(uint32_t reg) { - if (reg > MAX_REGISTERS) { - // This should never happen since all currently supported - // architectures have < 64 total registers. - abort(); - } - return saved_reg_map & (1ULL << reg); - } - - inline uint16_t Total() { return regs->total_regs(); } -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_REGS_INFO_H diff --git a/libunwindstack/RegsMips.cpp b/libunwindstack/RegsMips.cpp deleted file mode 100644 index ab8469114..000000000 --- a/libunwindstack/RegsMips.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 2017 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 - -namespace unwindstack { - -RegsMips::RegsMips() - : RegsImpl(MIPS_REG_LAST, Location(LOCATION_REGISTER, MIPS_REG_RA)) {} - -ArchEnum RegsMips::Arch() { - return ARCH_MIPS; -} - -uint64_t RegsMips::pc() { - return regs_[MIPS_REG_PC]; -} - -uint64_t RegsMips::sp() { - return regs_[MIPS_REG_SP]; -} - -void RegsMips::set_pc(uint64_t pc) { - regs_[MIPS_REG_PC] = static_cast(pc); -} - -void RegsMips::set_sp(uint64_t sp) { - regs_[MIPS_REG_SP] = static_cast(sp); -} - -bool RegsMips::SetPcFromReturnAddress(Memory*) { - uint32_t ra = regs_[MIPS_REG_RA]; - if (regs_[MIPS_REG_PC] == ra) { - return false; - } - - regs_[MIPS_REG_PC] = ra; - return true; -} - -void RegsMips::IterateRegisters(std::function fn) { - fn("r0", regs_[MIPS_REG_R0]); - fn("r1", regs_[MIPS_REG_R1]); - fn("r2", regs_[MIPS_REG_R2]); - fn("r3", regs_[MIPS_REG_R3]); - fn("r4", regs_[MIPS_REG_R4]); - fn("r5", regs_[MIPS_REG_R5]); - fn("r6", regs_[MIPS_REG_R6]); - fn("r7", regs_[MIPS_REG_R7]); - fn("r8", regs_[MIPS_REG_R8]); - fn("r9", regs_[MIPS_REG_R9]); - fn("r10", regs_[MIPS_REG_R10]); - fn("r11", regs_[MIPS_REG_R11]); - fn("r12", regs_[MIPS_REG_R12]); - fn("r13", regs_[MIPS_REG_R13]); - fn("r14", regs_[MIPS_REG_R14]); - fn("r15", regs_[MIPS_REG_R15]); - fn("r16", regs_[MIPS_REG_R16]); - fn("r17", regs_[MIPS_REG_R17]); - fn("r18", regs_[MIPS_REG_R18]); - fn("r19", regs_[MIPS_REG_R19]); - fn("r20", regs_[MIPS_REG_R20]); - fn("r21", regs_[MIPS_REG_R21]); - fn("r22", regs_[MIPS_REG_R22]); - fn("r23", regs_[MIPS_REG_R23]); - fn("r24", regs_[MIPS_REG_R24]); - fn("r25", regs_[MIPS_REG_R25]); - fn("r26", regs_[MIPS_REG_R26]); - fn("r27", regs_[MIPS_REG_R27]); - fn("r28", regs_[MIPS_REG_R28]); - fn("sp", regs_[MIPS_REG_SP]); - fn("r30", regs_[MIPS_REG_R30]); - fn("ra", regs_[MIPS_REG_RA]); - fn("pc", regs_[MIPS_REG_PC]); -} - -Regs* RegsMips::Read(void* remote_data) { - mips_user_regs* user = reinterpret_cast(remote_data); - RegsMips* regs = new RegsMips(); - uint32_t* reg_data = reinterpret_cast(regs->RawData()); - - memcpy(regs->RawData(), &user->regs[MIPS32_EF_R0], (MIPS_REG_R31 + 1) * sizeof(uint32_t)); - - reg_data[MIPS_REG_PC] = user->regs[MIPS32_EF_CP0_EPC]; - return regs; -} - -Regs* RegsMips::CreateFromUcontext(void* ucontext) { - mips_ucontext_t* mips_ucontext = reinterpret_cast(ucontext); - - RegsMips* regs = new RegsMips(); - // Copy 64 bit sc_regs over to 32 bit regs - for (int i = 0; i < 32; i++) { - (*regs)[MIPS_REG_R0 + i] = mips_ucontext->uc_mcontext.sc_regs[i]; - } - (*regs)[MIPS_REG_PC] = mips_ucontext->uc_mcontext.sc_pc; - return regs; -} - -bool RegsMips::StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) { - uint64_t data; - uint64_t offset = 0; - Memory* elf_memory = elf->memory(); - // Read from elf memory since it is usually more expensive to read from - // process memory. - if (!elf_memory->ReadFully(elf_offset, &data, sizeof(data))) { - return false; - } - - // Look for the kernel sigreturn functions. - // __vdso_rt_sigreturn: - // 0x24021061 li v0, 0x1061 - // 0x0000000c syscall - // __vdso_sigreturn: - // 0x24021017 li v0, 0x1017 - // 0x0000000c syscall - if (data == 0x0000000c24021061ULL) { - // vdso_rt_sigreturn => read rt_sigframe - // offset = siginfo offset + sizeof(siginfo) + uc_mcontext offset + sc_pc offset - offset = 24 + 128 + 24 + 8; - } else if (data == 0x0000000c24021017LL) { - // vdso_sigreturn => read sigframe - // offset = sigcontext offset + sc_pc offset - offset = 24 + 8; - } else { - return false; - } - - // read sc_pc and sc_regs[32] from stack - uint64_t values[MIPS_REG_LAST]; - if (!process_memory->ReadFully(regs_[MIPS_REG_SP] + offset, values, sizeof(values))) { - return false; - } - - // Copy 64 bit sc_pc over to 32 bit regs_[MIPS_REG_PC] - regs_[MIPS_REG_PC] = values[0]; - - // Copy 64 bit sc_regs over to 32 bit regs - for (int i = 0; i < 32; i++) { - regs_[MIPS_REG_R0 + i] = values[1 + i]; - } - return true; -} - -Regs* RegsMips::Clone() { - return new RegsMips(*this); -} - -} // namespace unwindstack diff --git a/libunwindstack/RegsMips64.cpp b/libunwindstack/RegsMips64.cpp deleted file mode 100644 index 7f600d362..000000000 --- a/libunwindstack/RegsMips64.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (C) 2017 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 - -namespace unwindstack { - -RegsMips64::RegsMips64() - : RegsImpl(MIPS64_REG_LAST, Location(LOCATION_REGISTER, MIPS64_REG_RA)) {} - -ArchEnum RegsMips64::Arch() { - return ARCH_MIPS64; -} - -uint64_t RegsMips64::pc() { - return regs_[MIPS64_REG_PC]; -} - -uint64_t RegsMips64::sp() { - return regs_[MIPS64_REG_SP]; -} - -void RegsMips64::set_pc(uint64_t pc) { - regs_[MIPS64_REG_PC] = pc; -} - -void RegsMips64::set_sp(uint64_t sp) { - regs_[MIPS64_REG_SP] = sp; -} - -bool RegsMips64::SetPcFromReturnAddress(Memory*) { - uint64_t ra = regs_[MIPS64_REG_RA]; - if (regs_[MIPS64_REG_PC] == ra) { - return false; - } - - regs_[MIPS64_REG_PC] = ra; - return true; -} - -void RegsMips64::IterateRegisters(std::function fn) { - fn("r0", regs_[MIPS64_REG_R0]); - fn("r1", regs_[MIPS64_REG_R1]); - fn("r2", regs_[MIPS64_REG_R2]); - fn("r3", regs_[MIPS64_REG_R3]); - fn("r4", regs_[MIPS64_REG_R4]); - fn("r5", regs_[MIPS64_REG_R5]); - fn("r6", regs_[MIPS64_REG_R6]); - fn("r7", regs_[MIPS64_REG_R7]); - fn("r8", regs_[MIPS64_REG_R8]); - fn("r9", regs_[MIPS64_REG_R9]); - fn("r10", regs_[MIPS64_REG_R10]); - fn("r11", regs_[MIPS64_REG_R11]); - fn("r12", regs_[MIPS64_REG_R12]); - fn("r13", regs_[MIPS64_REG_R13]); - fn("r14", regs_[MIPS64_REG_R14]); - fn("r15", regs_[MIPS64_REG_R15]); - fn("r16", regs_[MIPS64_REG_R16]); - fn("r17", regs_[MIPS64_REG_R17]); - fn("r18", regs_[MIPS64_REG_R18]); - fn("r19", regs_[MIPS64_REG_R19]); - fn("r20", regs_[MIPS64_REG_R20]); - fn("r21", regs_[MIPS64_REG_R21]); - fn("r22", regs_[MIPS64_REG_R22]); - fn("r23", regs_[MIPS64_REG_R23]); - fn("r24", regs_[MIPS64_REG_R24]); - fn("r25", regs_[MIPS64_REG_R25]); - fn("r26", regs_[MIPS64_REG_R26]); - fn("r27", regs_[MIPS64_REG_R27]); - fn("r28", regs_[MIPS64_REG_R28]); - fn("sp", regs_[MIPS64_REG_SP]); - fn("r30", regs_[MIPS64_REG_R30]); - fn("ra", regs_[MIPS64_REG_RA]); - fn("pc", regs_[MIPS64_REG_PC]); -} - -Regs* RegsMips64::Read(void* remote_data) { - mips64_user_regs* user = reinterpret_cast(remote_data); - RegsMips64* regs = new RegsMips64(); - uint64_t* reg_data = reinterpret_cast(regs->RawData()); - - memcpy(regs->RawData(), &user->regs[MIPS64_EF_R0], (MIPS64_REG_R31 + 1) * sizeof(uint64_t)); - - reg_data[MIPS64_REG_PC] = user->regs[MIPS64_EF_CP0_EPC]; - return regs; -} - -Regs* RegsMips64::CreateFromUcontext(void* ucontext) { - mips64_ucontext_t* mips64_ucontext = reinterpret_cast(ucontext); - - RegsMips64* regs = new RegsMips64(); - // Copy 64 bit sc_regs over to 64 bit regs - memcpy(regs->RawData(), &mips64_ucontext->uc_mcontext.sc_regs[0], 32 * sizeof(uint64_t)); - (*regs)[MIPS64_REG_PC] = mips64_ucontext->uc_mcontext.sc_pc; - return regs; -} - -bool RegsMips64::StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) { - uint64_t data; - Memory* elf_memory = elf->memory(); - // Read from elf memory since it is usually more expensive to read from - // process memory. - if (!elf_memory->Read(elf_offset, &data, sizeof(data))) { - return false; - } - - // Look for the kernel sigreturn function. - // __vdso_rt_sigreturn: - // 0x2402145b li v0, 0x145b - // 0x0000000c syscall - if (data != 0x0000000c2402145bULL) { - return false; - } - - // vdso_rt_sigreturn => read rt_sigframe - // offset = siginfo offset + sizeof(siginfo) + uc_mcontext offset - // read 64 bit sc_regs[32] from stack into 64 bit regs_ - uint64_t sp = regs_[MIPS64_REG_SP]; - if (!process_memory->Read(sp + 24 + 128 + 40, regs_.data(), - sizeof(uint64_t) * (MIPS64_REG_LAST - 1))) { - return false; - } - - // offset = siginfo offset + sizeof(siginfo) + uc_mcontext offset + sc_pc offset - // read 64 bit sc_pc from stack into 64 bit regs_[MIPS64_REG_PC] - if (!process_memory->Read(sp + 24 + 128 + 40 + 576, ®s_[MIPS64_REG_PC], sizeof(uint64_t))) { - return false; - } - return true; -} - -Regs* RegsMips64::Clone() { - return new RegsMips64(*this); -} - -} // namespace unwindstack diff --git a/libunwindstack/RegsX86.cpp b/libunwindstack/RegsX86.cpp deleted file mode 100644 index 4d3c246a4..000000000 --- a/libunwindstack/RegsX86.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2016 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 - -namespace unwindstack { - -RegsX86::RegsX86() : RegsImpl(X86_REG_LAST, Location(LOCATION_SP_OFFSET, -4)) {} - -ArchEnum RegsX86::Arch() { - return ARCH_X86; -} - -uint64_t RegsX86::pc() { - return regs_[X86_REG_PC]; -} - -uint64_t RegsX86::sp() { - return regs_[X86_REG_SP]; -} - -void RegsX86::set_pc(uint64_t pc) { - regs_[X86_REG_PC] = static_cast(pc); -} - -void RegsX86::set_sp(uint64_t sp) { - regs_[X86_REG_SP] = static_cast(sp); -} - -bool RegsX86::SetPcFromReturnAddress(Memory* process_memory) { - // Attempt to get the return address from the top of the stack. - uint32_t new_pc; - if (!process_memory->ReadFully(regs_[X86_REG_SP], &new_pc, sizeof(new_pc)) || - new_pc == regs_[X86_REG_PC]) { - return false; - } - - regs_[X86_REG_PC] = new_pc; - return true; -} - -void RegsX86::IterateRegisters(std::function fn) { - fn("eax", regs_[X86_REG_EAX]); - fn("ebx", regs_[X86_REG_EBX]); - fn("ecx", regs_[X86_REG_ECX]); - fn("edx", regs_[X86_REG_EDX]); - fn("ebp", regs_[X86_REG_EBP]); - fn("edi", regs_[X86_REG_EDI]); - fn("esi", regs_[X86_REG_ESI]); - fn("esp", regs_[X86_REG_ESP]); - fn("eip", regs_[X86_REG_EIP]); -} - -Regs* RegsX86::Read(void* user_data) { - x86_user_regs* user = reinterpret_cast(user_data); - - RegsX86* regs = new RegsX86(); - (*regs)[X86_REG_EAX] = user->eax; - (*regs)[X86_REG_EBX] = user->ebx; - (*regs)[X86_REG_ECX] = user->ecx; - (*regs)[X86_REG_EDX] = user->edx; - (*regs)[X86_REG_EBP] = user->ebp; - (*regs)[X86_REG_EDI] = user->edi; - (*regs)[X86_REG_ESI] = user->esi; - (*regs)[X86_REG_ESP] = user->esp; - (*regs)[X86_REG_EIP] = user->eip; - - return regs; -} - -void RegsX86::SetFromUcontext(x86_ucontext_t* ucontext) { - // Put the registers in the expected order. - regs_[X86_REG_EDI] = ucontext->uc_mcontext.edi; - regs_[X86_REG_ESI] = ucontext->uc_mcontext.esi; - regs_[X86_REG_EBP] = ucontext->uc_mcontext.ebp; - regs_[X86_REG_ESP] = ucontext->uc_mcontext.esp; - regs_[X86_REG_EBX] = ucontext->uc_mcontext.ebx; - regs_[X86_REG_EDX] = ucontext->uc_mcontext.edx; - regs_[X86_REG_ECX] = ucontext->uc_mcontext.ecx; - regs_[X86_REG_EAX] = ucontext->uc_mcontext.eax; - regs_[X86_REG_EIP] = ucontext->uc_mcontext.eip; -} - -Regs* RegsX86::CreateFromUcontext(void* ucontext) { - x86_ucontext_t* x86_ucontext = reinterpret_cast(ucontext); - - RegsX86* regs = new RegsX86(); - regs->SetFromUcontext(x86_ucontext); - return regs; -} - -bool RegsX86::StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) { - uint64_t data; - Memory* elf_memory = elf->memory(); - // Read from elf memory since it is usually more expensive to read from - // process memory. - if (!elf_memory->ReadFully(elf_offset, &data, sizeof(data))) { - return false; - } - - if (data == 0x80cd00000077b858ULL) { - // Without SA_SIGINFO set, the return sequence is: - // - // __restore: - // 0x58 pop %eax - // 0xb8 0x77 0x00 0x00 0x00 movl 0x77,%eax - // 0xcd 0x80 int 0x80 - // - // SP points at arguments: - // int signum - // struct sigcontext (same format as mcontext) - struct x86_mcontext_t context; - if (!process_memory->ReadFully(regs_[X86_REG_SP] + 4, &context, sizeof(context))) { - return false; - } - regs_[X86_REG_EBP] = context.ebp; - regs_[X86_REG_ESP] = context.esp; - regs_[X86_REG_EBX] = context.ebx; - regs_[X86_REG_EDX] = context.edx; - regs_[X86_REG_ECX] = context.ecx; - regs_[X86_REG_EAX] = context.eax; - regs_[X86_REG_EIP] = context.eip; - return true; - } else if ((data & 0x00ffffffffffffffULL) == 0x0080cd000000adb8ULL) { - // With SA_SIGINFO set, the return sequence is: - // - // __restore_rt: - // 0xb8 0xad 0x00 0x00 0x00 movl 0xad,%eax - // 0xcd 0x80 int 0x80 - // - // SP points at arguments: - // int signum - // siginfo* - // ucontext* - - // Get the location of the sigcontext data. - uint32_t ptr; - if (!process_memory->ReadFully(regs_[X86_REG_SP] + 8, &ptr, sizeof(ptr))) { - return false; - } - // Only read the portion of the data structure we care about. - x86_ucontext_t x86_ucontext; - if (!process_memory->ReadFully(ptr + 0x14, &x86_ucontext.uc_mcontext, sizeof(x86_mcontext_t))) { - return false; - } - SetFromUcontext(&x86_ucontext); - return true; - } - return false; -} - -Regs* RegsX86::Clone() { - return new RegsX86(*this); -} - -} // namespace unwindstack diff --git a/libunwindstack/RegsX86_64.cpp b/libunwindstack/RegsX86_64.cpp deleted file mode 100644 index 26d9f6578..000000000 --- a/libunwindstack/RegsX86_64.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (C) 2016 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 - -namespace unwindstack { - -RegsX86_64::RegsX86_64() : RegsImpl(X86_64_REG_LAST, Location(LOCATION_SP_OFFSET, -8)) {} - -ArchEnum RegsX86_64::Arch() { - return ARCH_X86_64; -} - -uint64_t RegsX86_64::pc() { - return regs_[X86_64_REG_PC]; -} - -uint64_t RegsX86_64::sp() { - return regs_[X86_64_REG_SP]; -} - -void RegsX86_64::set_pc(uint64_t pc) { - regs_[X86_64_REG_PC] = pc; -} - -void RegsX86_64::set_sp(uint64_t sp) { - regs_[X86_64_REG_SP] = sp; -} - -bool RegsX86_64::SetPcFromReturnAddress(Memory* process_memory) { - // Attempt to get the return address from the top of the stack. - uint64_t new_pc; - if (!process_memory->ReadFully(regs_[X86_64_REG_SP], &new_pc, sizeof(new_pc)) || - new_pc == regs_[X86_64_REG_PC]) { - return false; - } - - regs_[X86_64_REG_PC] = new_pc; - return true; -} - -void RegsX86_64::IterateRegisters(std::function fn) { - fn("rax", regs_[X86_64_REG_RAX]); - fn("rbx", regs_[X86_64_REG_RBX]); - fn("rcx", regs_[X86_64_REG_RCX]); - fn("rdx", regs_[X86_64_REG_RDX]); - fn("r8", regs_[X86_64_REG_R8]); - fn("r9", regs_[X86_64_REG_R9]); - fn("r10", regs_[X86_64_REG_R10]); - fn("r11", regs_[X86_64_REG_R11]); - fn("r12", regs_[X86_64_REG_R12]); - fn("r13", regs_[X86_64_REG_R13]); - fn("r14", regs_[X86_64_REG_R14]); - fn("r15", regs_[X86_64_REG_R15]); - fn("rdi", regs_[X86_64_REG_RDI]); - fn("rsi", regs_[X86_64_REG_RSI]); - fn("rbp", regs_[X86_64_REG_RBP]); - fn("rsp", regs_[X86_64_REG_RSP]); - fn("rip", regs_[X86_64_REG_RIP]); -} - -Regs* RegsX86_64::Read(void* remote_data) { - x86_64_user_regs* user = reinterpret_cast(remote_data); - - RegsX86_64* regs = new RegsX86_64(); - (*regs)[X86_64_REG_RAX] = user->rax; - (*regs)[X86_64_REG_RBX] = user->rbx; - (*regs)[X86_64_REG_RCX] = user->rcx; - (*regs)[X86_64_REG_RDX] = user->rdx; - (*regs)[X86_64_REG_R8] = user->r8; - (*regs)[X86_64_REG_R9] = user->r9; - (*regs)[X86_64_REG_R10] = user->r10; - (*regs)[X86_64_REG_R11] = user->r11; - (*regs)[X86_64_REG_R12] = user->r12; - (*regs)[X86_64_REG_R13] = user->r13; - (*regs)[X86_64_REG_R14] = user->r14; - (*regs)[X86_64_REG_R15] = user->r15; - (*regs)[X86_64_REG_RDI] = user->rdi; - (*regs)[X86_64_REG_RSI] = user->rsi; - (*regs)[X86_64_REG_RBP] = user->rbp; - (*regs)[X86_64_REG_RSP] = user->rsp; - (*regs)[X86_64_REG_RIP] = user->rip; - - return regs; -} - -void RegsX86_64::SetFromUcontext(x86_64_ucontext_t* ucontext) { - // R8-R15 - memcpy(®s_[X86_64_REG_R8], &ucontext->uc_mcontext.r8, 8 * sizeof(uint64_t)); - - // Rest of the registers. - regs_[X86_64_REG_RDI] = ucontext->uc_mcontext.rdi; - regs_[X86_64_REG_RSI] = ucontext->uc_mcontext.rsi; - regs_[X86_64_REG_RBP] = ucontext->uc_mcontext.rbp; - regs_[X86_64_REG_RBX] = ucontext->uc_mcontext.rbx; - regs_[X86_64_REG_RDX] = ucontext->uc_mcontext.rdx; - regs_[X86_64_REG_RAX] = ucontext->uc_mcontext.rax; - regs_[X86_64_REG_RCX] = ucontext->uc_mcontext.rcx; - regs_[X86_64_REG_RSP] = ucontext->uc_mcontext.rsp; - regs_[X86_64_REG_RIP] = ucontext->uc_mcontext.rip; -} - -Regs* RegsX86_64::CreateFromUcontext(void* ucontext) { - x86_64_ucontext_t* x86_64_ucontext = reinterpret_cast(ucontext); - - RegsX86_64* regs = new RegsX86_64(); - regs->SetFromUcontext(x86_64_ucontext); - return regs; -} - -bool RegsX86_64::StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) { - uint64_t data; - Memory* elf_memory = elf->memory(); - // Read from elf memory since it is usually more expensive to read from - // process memory. - if (!elf_memory->ReadFully(elf_offset, &data, sizeof(data)) || data != 0x0f0000000fc0c748) { - return false; - } - - uint8_t data2; - if (!elf_memory->ReadFully(elf_offset + 8, &data2, sizeof(data2)) || data2 != 0x05) { - return false; - } - - // __restore_rt: - // 0x48 0xc7 0xc0 0x0f 0x00 0x00 0x00 mov $0xf,%rax - // 0x0f 0x05 syscall - - // Read the mcontext data from the stack. - // sp points to the ucontext data structure, read only the mcontext part. - x86_64_ucontext_t x86_64_ucontext; - if (!process_memory->ReadFully(regs_[X86_64_REG_SP] + 0x28, &x86_64_ucontext.uc_mcontext, - sizeof(x86_64_mcontext_t))) { - return false; - } - SetFromUcontext(&x86_64_ucontext); - return true; -} - -Regs* RegsX86_64::Clone() { - return new RegsX86_64(*this); -} - -} // namespace unwindstack diff --git a/libunwindstack/Symbols.cpp b/libunwindstack/Symbols.cpp deleted file mode 100644 index 2117ebd3e..000000000 --- a/libunwindstack/Symbols.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2017 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 "Check.h" -#include "Symbols.h" - -namespace unwindstack { - -Symbols::Symbols(uint64_t offset, uint64_t size, uint64_t entry_size, uint64_t str_offset, - uint64_t str_size) - : offset_(offset), - count_(entry_size != 0 ? size / entry_size : 0), - entry_size_(entry_size), - str_offset_(str_offset), - str_end_(str_offset_ + str_size) {} - -template -static bool IsFunc(const SymType* entry) { - return entry->st_shndx != SHN_UNDEF && ELF32_ST_TYPE(entry->st_info) == STT_FUNC; -} - -// Read symbol entry from memory and cache it so we don't have to read it again. -template -inline __attribute__((__always_inline__)) const Symbols::Info* Symbols::ReadFuncInfo( - uint32_t symbol_index, Memory* elf_memory) { - auto it = symbols_.find(symbol_index); - if (it != symbols_.end()) { - return &it->second; - } - SymType sym; - if (!elf_memory->ReadFully(offset_ + symbol_index * entry_size_, &sym, sizeof(sym))) { - return nullptr; - } - if (!IsFunc(&sym)) { - // We need the address for binary search, but we don't want it to be matched. - sym.st_size = 0; - } - Info info{.addr = sym.st_value, .size = static_cast(sym.st_size), .name = sym.st_name}; - return &symbols_.emplace(symbol_index, info).first->second; -} - -// Binary search the symbol table to find function containing the given address. -// Without remap, the symbol table is assumed to be sorted and accessed directly. -// If the symbol table is not sorted this method might fail but should not crash. -// When the indices are remapped, they are guaranteed to be sorted by address. -template -const Symbols::Info* Symbols::BinarySearch(uint64_t addr, Memory* elf_memory) { - size_t first = 0; - size_t last = RemapIndices ? remap_->size() : count_; - while (first < last) { - size_t current = first + (last - first) / 2; - size_t symbol_index = RemapIndices ? remap_.value()[current] : current; - const Info* info = ReadFuncInfo(symbol_index, elf_memory); - if (info == nullptr) { - return nullptr; - } - if (addr < info->addr) { - last = current; - } else if (addr < info->addr + info->size) { - return info; - } else { - first = current + 1; - } - } - return nullptr; -} - -// Create remapping table which allows us to access symbols as if they were sorted by address. -template -void Symbols::BuildRemapTable(Memory* elf_memory) { - std::vector addrs; // Addresses of all symbols (addrs[i] == symbols[i].st_value). - addrs.reserve(count_); - remap_.emplace(); // Construct the optional remap table. - remap_->reserve(count_); - for (size_t symbol_idx = 0; symbol_idx < count_;) { - // Read symbols from memory. We intentionally bypass the cache to save memory. - // Do the reads in batches so that we minimize the number of memory read calls. - uint8_t buffer[1024]; - size_t read = std::min(sizeof(buffer), (count_ - symbol_idx) * entry_size_); - size_t size = elf_memory->Read(offset_ + symbol_idx * entry_size_, buffer, read); - if (size < sizeof(SymType)) { - break; // Stop processing, something looks like it is corrupted. - } - for (size_t offset = 0; offset + sizeof(SymType) <= size; offset += entry_size_, symbol_idx++) { - SymType sym; - memcpy(&sym, &buffer[offset], sizeof(SymType)); // Copy to ensure alignment. - addrs.push_back(sym.st_value); // Always insert so it is indexable by symbol index. - if (IsFunc(&sym)) { - remap_->push_back(symbol_idx); // Indices of function symbols only. - } - } - } - // Sort by address to make the remap list binary searchable (stable due to the abegin(), remap_->end(), comp); - // Remove duplicate entries (methods de-duplicated by the linker). - auto pred = [&addrs](auto a, auto b) { return addrs[a] == addrs[b]; }; - remap_->erase(std::unique(remap_->begin(), remap_->end(), pred), remap_->end()); - remap_->shrink_to_fit(); -} - -template -bool Symbols::GetName(uint64_t addr, Memory* elf_memory, std::string* name, uint64_t* func_offset) { - const Info* info; - if (!remap_.has_value()) { - // Assume the symbol table is sorted. If it is not, this will gracefully fail. - info = BinarySearch(addr, elf_memory); - if (info == nullptr) { - // Create the remapping table and retry the search. - BuildRemapTable(elf_memory); - symbols_.clear(); // Remove cached symbols since the access pattern will be different. - info = BinarySearch(addr, elf_memory); - } - } else { - // Fast search using the previously created remap table. - info = BinarySearch(addr, elf_memory); - } - if (info == nullptr) { - return false; - } - // Read the function name from the string table. - *func_offset = addr - info->addr; - uint64_t str = str_offset_ + info->name; - return str < str_end_ && elf_memory->ReadString(str, name, str_end_ - str); -} - -template -bool Symbols::GetGlobal(Memory* elf_memory, const std::string& name, uint64_t* memory_address) { - for (uint32_t i = 0; i < count_; i++) { - SymType entry; - if (!elf_memory->ReadFully(offset_ + i * entry_size_, &entry, sizeof(entry))) { - return false; - } - - if (entry.st_shndx != SHN_UNDEF && ELF32_ST_TYPE(entry.st_info) == STT_OBJECT && - ELF32_ST_BIND(entry.st_info) == STB_GLOBAL) { - uint64_t str_offset = str_offset_ + entry.st_name; - if (str_offset < str_end_) { - std::string symbol; - if (elf_memory->ReadString(str_offset, &symbol, str_end_ - str_offset) && symbol == name) { - *memory_address = entry.st_value; - return true; - } - } - } - } - return false; -} - -// Instantiate all of the needed template functions. -template bool Symbols::GetName(uint64_t, Memory*, std::string*, uint64_t*); -template bool Symbols::GetName(uint64_t, Memory*, std::string*, uint64_t*); - -template bool Symbols::GetGlobal(Memory*, const std::string&, uint64_t*); -template bool Symbols::GetGlobal(Memory*, const std::string&, uint64_t*); -} // namespace unwindstack diff --git a/libunwindstack/Symbols.h b/libunwindstack/Symbols.h deleted file mode 100644 index 3b3f20b1c..000000000 --- a/libunwindstack/Symbols.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2016 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_SYMBOLS_H -#define _LIBUNWINDSTACK_SYMBOLS_H - -#include - -#include -#include -#include - -namespace unwindstack { - -// Forward declaration. -class Memory; - -class Symbols { - struct Info { - uint64_t addr; // Symbol address. - uint32_t size; // Symbol size in bytes. Zero if not a function. - uint32_t name; // Offset in .strtab. - }; - - public: - Symbols(uint64_t offset, uint64_t size, uint64_t entry_size, uint64_t str_offset, - uint64_t str_size); - virtual ~Symbols() = default; - - template - bool GetName(uint64_t addr, Memory* elf_memory, std::string* name, uint64_t* func_offset); - - template - bool GetGlobal(Memory* elf_memory, const std::string& name, uint64_t* memory_address); - - void ClearCache() { - symbols_.clear(); - remap_.reset(); - } - - private: - template - const Info* ReadFuncInfo(uint32_t symbol_index, Memory* elf_memory); - - template - const Info* BinarySearch(uint64_t addr, Memory* elf_memory); - - template - void BuildRemapTable(Memory* elf_memory); - - const uint64_t offset_; - const uint64_t count_; - const uint64_t entry_size_; - const uint64_t str_offset_; - const uint64_t str_end_; - - std::unordered_map symbols_; // Cache of read symbols (keyed by symbol index). - std::optional> remap_; // Indices of function symbols sorted by address. -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_SYMBOLS_H diff --git a/libunwindstack/TEST_MAPPING b/libunwindstack/TEST_MAPPING deleted file mode 100644 index 909f8976c..000000000 --- a/libunwindstack/TEST_MAPPING +++ /dev/null @@ -1,10 +0,0 @@ -{ - "presubmit": [ - { - "name": "libunwindstack_unit_test" - }, - { - "name": "CtsSimpleperfTestCases" - } - ] -} diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp deleted file mode 100644 index 9ffc0f738..000000000 --- a/libunwindstack/Unwinder.cpp +++ /dev/null @@ -1,475 +0,0 @@ -/* - * Copyright (C) 2017 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. - */ - -#define _GNU_SOURCE 1 -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "Check.h" - -// Use the demangler from libc++. -extern "C" char* __cxa_demangle(const char*, char*, size_t*, int* status); - -namespace unwindstack { - -// Inject extra 'virtual' frame that represents the dex pc data. -// The dex pc is a 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 0015fa20 core.vdex java.util.Arrays.binarySearch+8 -// #8 pc 006b1ba1 libartd.so ExecuteMterpImpl+14625 -// #9 pc 0039a1ef libartd.so art::interpreter::Execute+719 -void Unwinder::FillInDexFrame() { - size_t frame_num = frames_.size(); - frames_.resize(frame_num + 1); - FrameData* frame = &frames_.at(frame_num); - frame->num = frame_num; - - uint64_t dex_pc = regs_->dex_pc(); - frame->pc = dex_pc; - frame->sp = regs_->sp(); - - MapInfo* info = maps_->Find(dex_pc); - if (info != nullptr) { - frame->map_start = info->start; - frame->map_end = info->end; - // Since this is a dex file frame, the elf_start_offset is not set - // by any of the normal code paths. Use the offset of the map since - // that matches the actual offset. - frame->map_elf_start_offset = info->offset; - frame->map_exact_offset = info->offset; - frame->map_load_bias = info->load_bias; - frame->map_flags = info->flags; - if (resolve_names_) { - frame->map_name = info->name; - } - frame->rel_pc = dex_pc - info->start; - } else { - frame->rel_pc = dex_pc; - warnings_ |= WARNING_DEX_PC_NOT_IN_MAP; - return; - } - - if (!resolve_names_) { - return; - } - -#if defined(DEXFILE_SUPPORT) - if (dex_files_ == nullptr) { - return; - } - - dex_files_->GetMethodInformation(maps_, info, dex_pc, &frame->function_name, - &frame->function_offset); -#endif -} - -FrameData* Unwinder::FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, - uint64_t pc_adjustment) { - size_t frame_num = frames_.size(); - frames_.resize(frame_num + 1); - FrameData* frame = &frames_.at(frame_num); - frame->num = frame_num; - frame->sp = regs_->sp(); - frame->rel_pc = rel_pc - pc_adjustment; - frame->pc = regs_->pc() - pc_adjustment; - - if (map_info == nullptr) { - // Nothing else to update. - return nullptr; - } - - if (resolve_names_) { - frame->map_name = map_info->name; - if (embedded_soname_ && map_info->elf_start_offset != 0 && !frame->map_name.empty()) { - std::string soname = elf->GetSoname(); - if (!soname.empty()) { - frame->map_name += '!' + soname; - } - } - } - frame->map_elf_start_offset = map_info->elf_start_offset; - frame->map_exact_offset = map_info->offset; - frame->map_start = map_info->start; - frame->map_end = map_info->end; - frame->map_flags = map_info->flags; - frame->map_load_bias = elf->GetLoadBias(); - return frame; -} - -static bool ShouldStop(const std::vector* map_suffixes_to_ignore, - std::string& map_name) { - if (map_suffixes_to_ignore == nullptr) { - return false; - } - auto pos = map_name.find_last_of('.'); - if (pos == std::string::npos) { - return false; - } - - return std::find(map_suffixes_to_ignore->begin(), map_suffixes_to_ignore->end(), - map_name.substr(pos + 1)) != map_suffixes_to_ignore->end(); -} - -void Unwinder::Unwind(const std::vector* initial_map_names_to_skip, - const std::vector* map_suffixes_to_ignore) { - CHECK(arch_ != ARCH_UNKNOWN); - ClearErrors(); - - frames_.clear(); - elf_from_memory_not_file_ = false; - - bool return_address_attempt = false; - bool adjust_pc = false; - for (; frames_.size() < max_frames_;) { - uint64_t cur_pc = regs_->pc(); - uint64_t cur_sp = regs_->sp(); - - MapInfo* map_info = maps_->Find(regs_->pc()); - uint64_t pc_adjustment = 0; - uint64_t step_pc; - uint64_t rel_pc; - Elf* elf; - if (map_info == nullptr) { - step_pc = regs_->pc(); - rel_pc = step_pc; - last_error_.code = ERROR_INVALID_MAP; - } else { - if (ShouldStop(map_suffixes_to_ignore, map_info->name)) { - break; - } - elf = map_info->GetElf(process_memory_, arch_); - // If this elf is memory backed, and there is a valid file, then set - // an indicator that we couldn't open the file. - if (!elf_from_memory_not_file_ && map_info->memory_backed_elf && !map_info->name.empty() && - map_info->name[0] != '[' && !android::base::StartsWith(map_info->name, "/memfd:")) { - elf_from_memory_not_file_ = true; - } - step_pc = regs_->pc(); - rel_pc = elf->GetRelPc(step_pc, map_info); - // Everyone except elf data in gdb jit debug maps uses the relative pc. - if (!(map_info->flags & MAPS_FLAGS_JIT_SYMFILE_MAP)) { - step_pc = rel_pc; - } - if (adjust_pc) { - pc_adjustment = GetPcAdjustment(rel_pc, elf, arch_); - } else { - pc_adjustment = 0; - } - step_pc -= pc_adjustment; - - // If the pc is in an invalid elf file, try and get an Elf object - // using the jit debug information. - if (!elf->valid() && jit_debug_ != nullptr) { - uint64_t adjusted_jit_pc = regs_->pc() - pc_adjustment; - Elf* jit_elf = jit_debug_->GetElf(maps_, adjusted_jit_pc); - if (jit_elf != nullptr) { - // The jit debug information requires a non relative adjusted pc. - step_pc = adjusted_jit_pc; - elf = jit_elf; - } - } - } - - FrameData* frame = nullptr; - if (map_info == nullptr || initial_map_names_to_skip == nullptr || - std::find(initial_map_names_to_skip->begin(), initial_map_names_to_skip->end(), - basename(map_info->name.c_str())) == initial_map_names_to_skip->end()) { - if (regs_->dex_pc() != 0) { - // Add a frame to represent the dex file. - FillInDexFrame(); - // Clear the dex pc so that we don't repeat this frame later. - regs_->set_dex_pc(0); - - // Make sure there is enough room for the real frame. - if (frames_.size() == max_frames_) { - last_error_.code = ERROR_MAX_FRAMES_EXCEEDED; - break; - } - } - - frame = FillInFrame(map_info, elf, rel_pc, pc_adjustment); - - // Once a frame is added, stop skipping frames. - initial_map_names_to_skip = nullptr; - } - adjust_pc = true; - - bool stepped = false; - bool in_device_map = false; - bool finished = false; - if (map_info != nullptr) { - if (map_info->flags & MAPS_FLAGS_DEVICE_MAP) { - // Do not stop here, fall through in case we are - // in the speculative unwind path and need to remove - // some of the speculative frames. - in_device_map = true; - } else { - MapInfo* sp_info = maps_->Find(regs_->sp()); - if (sp_info != nullptr && sp_info->flags & MAPS_FLAGS_DEVICE_MAP) { - // Do not stop here, fall through in case we are - // in the speculative unwind path and need to remove - // some of the speculative frames. - in_device_map = true; - } else { - bool is_signal_frame = false; - if (elf->StepIfSignalHandler(rel_pc, regs_, process_memory_.get())) { - stepped = true; - is_signal_frame = true; - } else if (elf->Step(step_pc, regs_, process_memory_.get(), &finished, - &is_signal_frame)) { - stepped = true; - } - if (is_signal_frame && frame != nullptr) { - // Need to adjust the relative pc because the signal handler - // pc should not be adjusted. - frame->rel_pc = rel_pc; - frame->pc += pc_adjustment; - step_pc = rel_pc; - } - elf->GetLastError(&last_error_); - } - } - } - - if (frame != nullptr) { - if (!resolve_names_ || - !elf->GetFunctionName(step_pc, &frame->function_name, &frame->function_offset)) { - frame->function_name = ""; - frame->function_offset = 0; - } - } - - if (finished) { - break; - } - - if (!stepped) { - if (return_address_attempt) { - // Only remove the speculative frame if there are more than two frames - // or the pc in the first frame is in a valid map. - // This allows for a case where the code jumps into the middle of - // nowhere, but there is no other unwind information after that. - if (frames_.size() > 2 || (frames_.size() > 0 && maps_->Find(frames_[0].pc) != nullptr)) { - // Remove the speculative frame. - frames_.pop_back(); - } - break; - } else if (in_device_map) { - // Do not attempt any other unwinding, pc or sp is in a device - // map. - break; - } else { - // Steping didn't work, try this secondary method. - if (!regs_->SetPcFromReturnAddress(process_memory_.get())) { - break; - } - return_address_attempt = true; - } - } else { - return_address_attempt = false; - if (max_frames_ == frames_.size()) { - last_error_.code = ERROR_MAX_FRAMES_EXCEEDED; - } - } - - // If the pc and sp didn't change, then consider everything stopped. - if (cur_pc == regs_->pc() && cur_sp == regs_->sp()) { - last_error_.code = ERROR_REPEATED_FRAME; - break; - } - } -} - -std::string Unwinder::FormatFrame(const FrameData& frame) const { - std::string data; - if (ArchIs32Bit(arch_)) { - data += android::base::StringPrintf(" #%02zu pc %08" PRIx64, frame.num, frame.rel_pc); - } else { - data += android::base::StringPrintf(" #%02zu pc %016" PRIx64, frame.num, frame.rel_pc); - } - - if (frame.map_start == frame.map_end) { - // No valid map associated with this frame. - data += " "; - } else if (!frame.map_name.empty()) { - data += " " + frame.map_name; - } else { - data += android::base::StringPrintf(" ", frame.map_start); - } - - if (frame.map_elf_start_offset != 0) { - data += android::base::StringPrintf(" (offset 0x%" PRIx64 ")", frame.map_elf_start_offset); - } - - if (!frame.function_name.empty()) { - char* demangled_name = __cxa_demangle(frame.function_name.c_str(), nullptr, nullptr, nullptr); - if (demangled_name == nullptr) { - data += " (" + frame.function_name; - } else { - data += " ("; - data += demangled_name; - free(demangled_name); - } - if (frame.function_offset != 0) { - data += android::base::StringPrintf("+%" PRId64, frame.function_offset); - } - data += ')'; - } - - MapInfo* map_info = maps_->Find(frame.map_start); - if (map_info != nullptr && display_build_id_) { - std::string build_id = map_info->GetPrintableBuildID(); - if (!build_id.empty()) { - data += " (BuildId: " + build_id + ')'; - } - } - return data; -} - -std::string Unwinder::FormatFrame(size_t frame_num) const { - if (frame_num >= frames_.size()) { - return ""; - } - return FormatFrame(frames_[frame_num]); -} - -void Unwinder::SetJitDebug(JitDebug* jit_debug) { - CHECK(arch_ != ARCH_UNKNOWN); - jit_debug->SetArch(arch_); - jit_debug_ = jit_debug; -} - -void Unwinder::SetDexFiles(DexFiles* dex_files) { - CHECK(arch_ != ARCH_UNKNOWN); - dex_files->SetArch(arch_); - dex_files_ = dex_files; -} - -bool UnwinderFromPid::Init() { - CHECK(arch_ != ARCH_UNKNOWN); - if (initted_) { - return true; - } - initted_ = true; - - if (pid_ == getpid()) { - maps_ptr_.reset(new LocalMaps()); - } else { - maps_ptr_.reset(new RemoteMaps(pid_)); - } - if (!maps_ptr_->Parse()) { - ClearErrors(); - last_error_.code = ERROR_INVALID_MAP; - return false; - } - maps_ = maps_ptr_.get(); - - process_memory_ = Memory::CreateProcessMemoryCached(pid_); - - jit_debug_ptr_.reset(new JitDebug(process_memory_)); - jit_debug_ = jit_debug_ptr_.get(); - SetJitDebug(jit_debug_); -#if defined(DEXFILE_SUPPORT) - dex_files_ptr_.reset(new DexFiles(process_memory_)); - dex_files_ = dex_files_ptr_.get(); - SetDexFiles(dex_files_); -#endif - - return true; -} - -void UnwinderFromPid::Unwind(const std::vector* initial_map_names_to_skip, - const std::vector* map_suffixes_to_ignore) { - if (!Init()) { - return; - } - Unwinder::Unwind(initial_map_names_to_skip, map_suffixes_to_ignore); -} - -FrameData Unwinder::BuildFrameFromPcOnly(uint64_t pc, ArchEnum arch, Maps* maps, - JitDebug* jit_debug, - std::shared_ptr process_memory, - bool resolve_names) { - FrameData frame; - - MapInfo* map_info = maps->Find(pc); - if (map_info == nullptr || arch == ARCH_UNKNOWN) { - frame.pc = pc; - frame.rel_pc = pc; - return frame; - } - - Elf* elf = map_info->GetElf(process_memory, arch); - - uint64_t relative_pc = elf->GetRelPc(pc, map_info); - - uint64_t pc_adjustment = GetPcAdjustment(relative_pc, elf, arch); - relative_pc -= pc_adjustment; - // The debug PC may be different if the PC comes from the JIT. - uint64_t debug_pc = relative_pc; - - // If we don't have a valid ELF file, check the JIT. - if (!elf->valid() && jit_debug != nullptr) { - uint64_t jit_pc = pc - pc_adjustment; - Elf* jit_elf = jit_debug->GetElf(maps, jit_pc); - if (jit_elf != nullptr) { - debug_pc = jit_pc; - elf = jit_elf; - } - } - - // Copy all the things we need into the frame for symbolization. - frame.rel_pc = relative_pc; - frame.pc = pc - pc_adjustment; - frame.map_name = map_info->name; - frame.map_elf_start_offset = map_info->elf_start_offset; - frame.map_exact_offset = map_info->offset; - frame.map_start = map_info->start; - frame.map_end = map_info->end; - frame.map_flags = map_info->flags; - frame.map_load_bias = elf->GetLoadBias(); - - if (!resolve_names || - !elf->GetFunctionName(debug_pc, &frame.function_name, &frame.function_offset)) { - frame.function_name = ""; - frame.function_offset = 0; - } - return frame; -} - -FrameData Unwinder::BuildFrameFromPcOnly(uint64_t pc) { - return BuildFrameFromPcOnly(pc, arch_, maps_, jit_debug_, process_memory_, resolve_names_); -} - -} // namespace unwindstack diff --git a/libunwindstack/benchmarks/ElfBenchmark.cpp b/libunwindstack/benchmarks/ElfBenchmark.cpp deleted file mode 100644 index a46bd7a24..000000000 --- a/libunwindstack/benchmarks/ElfBenchmark.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2020 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 "Utils.h" - -static void BenchmarkElfCreate(benchmark::State& state, const std::string& elf_file) { -#if defined(__BIONIC__) - uint64_t rss_bytes = 0; -#endif - uint64_t alloc_bytes = 0; - for (auto _ : state) { - state.PauseTiming(); -#if defined(__BIONIC__) - mallopt(M_PURGE, 0); - uint64_t rss_bytes_before = 0; - GatherRss(&rss_bytes_before); -#endif - uint64_t alloc_bytes_before = mallinfo().uordblks; - auto file_memory = unwindstack::Memory::CreateFileMemory(elf_file, 0); - state.ResumeTiming(); - - unwindstack::Elf elf(file_memory.release()); - if (!elf.Init() || !elf.valid()) { - errx(1, "Internal Error: Cannot open elf."); - } - - state.PauseTiming(); -#if defined(__BIONIC__) - mallopt(M_PURGE, 0); -#endif - alloc_bytes += mallinfo().uordblks - alloc_bytes_before; -#if defined(__BIONIC__) - GatherRss(&rss_bytes); - rss_bytes -= rss_bytes_before; -#endif - state.ResumeTiming(); - } - -#if defined(__BIONIC__) - state.counters["RSS_BYTES"] = rss_bytes / static_cast(state.iterations()); -#endif - state.counters["ALLOCATED_BYTES"] = alloc_bytes / static_cast(state.iterations()); -} - -void BM_elf_create(benchmark::State& state) { - BenchmarkElfCreate(state, GetElfFile()); -} -BENCHMARK(BM_elf_create); - -void BM_elf_create_compressed(benchmark::State& state) { - BenchmarkElfCreate(state, GetCompressedElfFile()); -} -BENCHMARK(BM_elf_create_compressed); - -static void InitializeBuildId(benchmark::State& state, unwindstack::Maps& maps, - unwindstack::MapInfo** build_id_map_info) { - if (!maps.Parse()) { - state.SkipWithError("Failed to parse local maps."); - return; - } - - // Find the libc.so share library and use that for benchmark purposes. - *build_id_map_info = nullptr; - for (auto& map_info : maps) { - if (map_info->offset == 0 && map_info->GetBuildID() != "") { - *build_id_map_info = map_info.get(); - break; - } - } - - if (*build_id_map_info == nullptr) { - state.SkipWithError("Failed to find a map with a BuildID."); - } -} - -static void BM_elf_get_build_id_from_object(benchmark::State& state) { - unwindstack::LocalMaps maps; - unwindstack::MapInfo* build_id_map_info; - InitializeBuildId(state, maps, &build_id_map_info); - - unwindstack::Elf* elf = build_id_map_info->GetElf(std::shared_ptr(), - unwindstack::Regs::CurrentArch()); - if (!elf->valid()) { - state.SkipWithError("Cannot get valid elf from map."); - } - - for (auto _ : state) { - state.PauseTiming(); - uintptr_t id = build_id_map_info->build_id; - if (id != 0) { - delete reinterpret_cast(id); - build_id_map_info->build_id = 0; - } - state.ResumeTiming(); - benchmark::DoNotOptimize(build_id_map_info->GetBuildID()); - } -} -BENCHMARK(BM_elf_get_build_id_from_object); - -static void BM_elf_get_build_id_from_file(benchmark::State& state) { - unwindstack::LocalMaps maps; - unwindstack::MapInfo* build_id_map_info; - InitializeBuildId(state, maps, &build_id_map_info); - - for (auto _ : state) { - state.PauseTiming(); - uintptr_t id = build_id_map_info->build_id; - if (id != 0) { - delete reinterpret_cast(id); - build_id_map_info->build_id = 0; - } - state.ResumeTiming(); - benchmark::DoNotOptimize(build_id_map_info->GetBuildID()); - } -} -BENCHMARK(BM_elf_get_build_id_from_file); diff --git a/libunwindstack/benchmarks/MapsBenchmark.cpp b/libunwindstack/benchmarks/MapsBenchmark.cpp deleted file mode 100644 index 5df149168..000000000 --- a/libunwindstack/benchmarks/MapsBenchmark.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (C) 2020 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 - -class BenchmarkLocalUpdatableMaps : public unwindstack::LocalUpdatableMaps { - public: - BenchmarkLocalUpdatableMaps() : unwindstack::LocalUpdatableMaps() {} - virtual ~BenchmarkLocalUpdatableMaps() = default; - - const std::string GetMapsFile() const override { return maps_file_; } - - void BenchmarkSetMapsFile(const std::string& maps_file) { maps_file_ = maps_file; } - - private: - std::string maps_file_; -}; - -static constexpr size_t kNumSmallMaps = 100; -static constexpr size_t kNumLargeMaps = 10000; - -static void CreateMap(const char* filename, size_t num_maps, size_t increment = 1) { - std::string maps; - for (size_t i = 0; i < num_maps; i += increment) { - maps += android::base::StringPrintf("%zu-%zu r-xp 0000 00:00 0 name%zu\n", i * 1000, - (i + 1) * 1000 * increment, i * increment); - } - if (!android::base::WriteStringToFile(maps, filename)) { - errx(1, "WriteStringToFile failed"); - } -} - -static void ReparseBenchmark(benchmark::State& state, const char* maps1, size_t maps1_total, - const char* maps2, size_t maps2_total) { - for (auto _ : state) { - BenchmarkLocalUpdatableMaps maps; - maps.BenchmarkSetMapsFile(maps1); - if (!maps.Reparse()) { - errx(1, "Internal Error: reparse of initial maps filed."); - } - if (maps.Total() != maps1_total) { - errx(1, "Internal Error: Incorrect total number of maps %zu, expected %zu.", maps.Total(), - maps1_total); - } - maps.BenchmarkSetMapsFile(maps2); - if (!maps.Reparse()) { - errx(1, "Internal Error: reparse of second set of maps filed."); - } - if (maps.Total() != maps2_total) { - errx(1, "Internal Error: Incorrect total number of maps %zu, expected %zu.", maps.Total(), - maps2_total); - } - } -} - -void BM_local_updatable_maps_reparse_double_initial_small(benchmark::State& state) { - TemporaryFile initial_maps; - CreateMap(initial_maps.path, kNumSmallMaps, 2); - - TemporaryFile reparse_maps; - CreateMap(reparse_maps.path, kNumSmallMaps); - - ReparseBenchmark(state, initial_maps.path, kNumSmallMaps / 2, reparse_maps.path, kNumSmallMaps); -} -BENCHMARK(BM_local_updatable_maps_reparse_double_initial_small); - -void BM_local_updatable_maps_reparse_double_initial_large(benchmark::State& state) { - TemporaryFile initial_maps; - CreateMap(initial_maps.path, kNumLargeMaps, 2); - - TemporaryFile reparse_maps; - CreateMap(reparse_maps.path, kNumLargeMaps); - - ReparseBenchmark(state, initial_maps.path, kNumLargeMaps / 2, reparse_maps.path, kNumLargeMaps); -} -BENCHMARK(BM_local_updatable_maps_reparse_double_initial_large); - -void BM_local_updatable_maps_reparse_same_maps_small(benchmark::State& state) { - static constexpr size_t kNumSmallMaps = 100; - TemporaryFile maps; - CreateMap(maps.path, kNumSmallMaps); - - ReparseBenchmark(state, maps.path, kNumSmallMaps, maps.path, kNumSmallMaps); -} -BENCHMARK(BM_local_updatable_maps_reparse_same_maps_small); - -void BM_local_updatable_maps_reparse_same_maps_large(benchmark::State& state) { - TemporaryFile maps; - CreateMap(maps.path, kNumLargeMaps); - - ReparseBenchmark(state, maps.path, kNumLargeMaps, maps.path, kNumLargeMaps); -} -BENCHMARK(BM_local_updatable_maps_reparse_same_maps_large); - -void BM_local_updatable_maps_reparse_few_extra_small(benchmark::State& state) { - TemporaryFile maps1; - CreateMap(maps1.path, kNumSmallMaps - 4); - - TemporaryFile maps2; - CreateMap(maps2.path, kNumSmallMaps); - - ReparseBenchmark(state, maps1.path, kNumSmallMaps - 4, maps2.path, kNumSmallMaps); -} -BENCHMARK(BM_local_updatable_maps_reparse_few_extra_small); - -void BM_local_updatable_maps_reparse_few_extra_large(benchmark::State& state) { - TemporaryFile maps1; - CreateMap(maps1.path, kNumLargeMaps - 4); - - TemporaryFile maps2; - CreateMap(maps2.path, kNumLargeMaps); - - ReparseBenchmark(state, maps1.path, kNumLargeMaps - 4, maps2.path, kNumLargeMaps); -} -BENCHMARK(BM_local_updatable_maps_reparse_few_extra_large); - -void BM_local_updatable_maps_reparse_few_less_small(benchmark::State& state) { - TemporaryFile maps1; - CreateMap(maps1.path, kNumSmallMaps); - - TemporaryFile maps2; - CreateMap(maps2.path, kNumSmallMaps - 4); - - ReparseBenchmark(state, maps1.path, kNumSmallMaps, maps2.path, kNumSmallMaps - 4); -} -BENCHMARK(BM_local_updatable_maps_reparse_few_less_small); - -void BM_local_updatable_maps_reparse_few_less_large(benchmark::State& state) { - TemporaryFile maps1; - CreateMap(maps1.path, kNumLargeMaps); - - TemporaryFile maps2; - CreateMap(maps2.path, kNumLargeMaps - 4); - - ReparseBenchmark(state, maps1.path, kNumLargeMaps, maps2.path, kNumLargeMaps - 4); -} -BENCHMARK(BM_local_updatable_maps_reparse_few_less_large); diff --git a/libunwindstack/benchmarks/SymbolBenchmark.cpp b/libunwindstack/benchmarks/SymbolBenchmark.cpp deleted file mode 100644 index 73088dab0..000000000 --- a/libunwindstack/benchmarks/SymbolBenchmark.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2020 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 "Utils.h" - -static void BenchmarkSymbolLookup(benchmark::State& state, std::vector offsets, - std::string elf_file, bool expect_found) { -#if defined(__BIONIC__) - uint64_t rss_bytes = 0; -#endif - uint64_t alloc_bytes = 0; - for (auto _ : state) { - state.PauseTiming(); - unwindstack::Elf elf(unwindstack::Memory::CreateFileMemory(elf_file, 0).release()); - if (!elf.Init() || !elf.valid()) { - errx(1, "Internal Error: Cannot open elf."); - } - -#if defined(__BIONIC__) - mallopt(M_PURGE, 0); - uint64_t rss_bytes_before = 0; - GatherRss(&rss_bytes_before); -#endif - uint64_t alloc_bytes_before = mallinfo().uordblks; - state.ResumeTiming(); - - for (auto pc : offsets) { - std::string name; - uint64_t offset; - bool found = elf.GetFunctionName(pc, &name, &offset); - if (expect_found && !found) { - errx(1, "expected pc 0x%" PRIx64 " present, but not found.", pc); - } else if (!expect_found && found) { - errx(1, "expected pc 0x%" PRIx64 " not present, but found.", pc); - } - } - - state.PauseTiming(); -#if defined(__BIONIC__) - mallopt(M_PURGE, 0); -#endif - alloc_bytes += mallinfo().uordblks - alloc_bytes_before; -#if defined(__BIONIC__) - GatherRss(&rss_bytes); - rss_bytes -= rss_bytes_before; -#endif - state.ResumeTiming(); - } - -#if defined(__BIONIC__) - state.counters["RSS_BYTES"] = rss_bytes / static_cast(state.iterations()); -#endif - state.counters["ALLOCATED_BYTES"] = alloc_bytes / static_cast(state.iterations()); -} - -static void BenchmarkSymbolLookup(benchmark::State& state, uint64_t pc, std::string elf_file, - bool expect_found) { - BenchmarkSymbolLookup(state, std::vector{pc}, elf_file, expect_found); -} - -void BM_symbol_not_present(benchmark::State& state) { - BenchmarkSymbolLookup(state, 0, GetElfFile(), false); -} -BENCHMARK(BM_symbol_not_present); - -void BM_symbol_find_single(benchmark::State& state) { - BenchmarkSymbolLookup(state, 0x22b2bc, GetElfFile(), true); -} -BENCHMARK(BM_symbol_find_single); - -void BM_symbol_find_single_many_times(benchmark::State& state) { - BenchmarkSymbolLookup(state, std::vector(15, 0x22b2bc), GetElfFile(), true); -} -BENCHMARK(BM_symbol_find_single_many_times); - -void BM_symbol_find_multiple(benchmark::State& state) { - BenchmarkSymbolLookup(state, - std::vector{0x22b2bc, 0xd5d30, 0x1312e8, 0x13582e, 0x1389c8}, - GetElfFile(), true); -} -BENCHMARK(BM_symbol_find_multiple); - -void BM_symbol_not_present_from_sorted(benchmark::State& state) { - BenchmarkSymbolLookup(state, 0, GetSymbolSortedElfFile(), false); -} -BENCHMARK(BM_symbol_not_present_from_sorted); - -void BM_symbol_find_single_from_sorted(benchmark::State& state) { - BenchmarkSymbolLookup(state, 0x138638, GetSymbolSortedElfFile(), true); -} -BENCHMARK(BM_symbol_find_single_from_sorted); - -void BM_symbol_find_single_many_times_from_sorted(benchmark::State& state) { - BenchmarkSymbolLookup(state, std::vector(15, 0x138638), GetSymbolSortedElfFile(), true); -} -BENCHMARK(BM_symbol_find_single_many_times_from_sorted); - -void BM_symbol_find_multiple_from_sorted(benchmark::State& state) { - BenchmarkSymbolLookup(state, - std::vector{0x138638, 0x84350, 0x14df18, 0x1f3a38, 0x1f3ca8}, - GetSymbolSortedElfFile(), true); -} -BENCHMARK(BM_symbol_find_multiple_from_sorted); diff --git a/libunwindstack/benchmarks/Utils.cpp b/libunwindstack/benchmarks/Utils.cpp deleted file mode 100644 index c92f1099d..000000000 --- a/libunwindstack/benchmarks/Utils.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2020 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 - -std::string GetElfFile() { - return android::base::GetExecutableDirectory() + "/benchmarks/files/libart_arm.so"; -} - -std::string GetSymbolSortedElfFile() { - return android::base::GetExecutableDirectory() + "/benchmarks/files/boot_arm.oat"; -} - -std::string GetCompressedElfFile() { - // Both are the same right now. - return GetSymbolSortedElfFile(); -} - -#if defined(__BIONIC__) - -#include -#include - -void GatherRss(uint64_t* rss_bytes) { - android::meminfo::ProcMemInfo proc_mem(getpid()); - const std::vector& maps = proc_mem.MapsWithoutUsageStats(); - for (auto& vma : maps) { - if (vma.name == "[anon:libc_malloc]" || android::base::StartsWith(vma.name, "[anon:scudo:") || - android::base::StartsWith(vma.name, "[anon:GWP-ASan")) { - android::meminfo::Vma update_vma(vma); - if (!proc_mem.FillInVmaStats(update_vma)) { - err(1, "FillInVmaStats failed\n"); - } - *rss_bytes += update_vma.usage.rss; - } - } -} -#endif diff --git a/libunwindstack/benchmarks/Utils.h b/libunwindstack/benchmarks/Utils.h deleted file mode 100644 index bee6efcad..000000000 --- a/libunwindstack/benchmarks/Utils.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2020 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_UTILS_H -#define _LIBUNWINDSTACK_UTILS_H - -#include - -#include - -std::string GetElfFile(); - -std::string GetSymbolSortedElfFile(); - -std::string GetCompressedElfFile(); - -#if defined(__BIONIC__) - -#include -#include - -void GatherRss(uint64_t* rss_bytes); - -#endif - -#endif // _LIBUNWINDSTACK_UTILS_h diff --git a/libunwindstack/benchmarks/files/boot_arm.oat b/libunwindstack/benchmarks/files/boot_arm.oat deleted file mode 100644 index 51188ebd3..000000000 Binary files a/libunwindstack/benchmarks/files/boot_arm.oat and /dev/null differ diff --git a/libunwindstack/benchmarks/files/libart_arm.so b/libunwindstack/benchmarks/files/libart_arm.so deleted file mode 100644 index 2201faf8f..000000000 Binary files a/libunwindstack/benchmarks/files/libart_arm.so and /dev/null differ diff --git a/libunwindstack/benchmarks/unwind_benchmarks.cpp b/libunwindstack/benchmarks/unwind_benchmarks.cpp deleted file mode 100644 index 0bee6ef78..000000000 --- a/libunwindstack/benchmarks/unwind_benchmarks.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2018 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 - -size_t Call6(std::shared_ptr& process_memory, unwindstack::Maps* maps) { - std::unique_ptr regs(unwindstack::Regs::CreateFromLocal()); - unwindstack::RegsGetLocal(regs.get()); - unwindstack::Unwinder unwinder(32, maps, regs.get(), process_memory); - unwinder.Unwind(); - return unwinder.NumFrames(); -} - -size_t Call5(std::shared_ptr& process_memory, unwindstack::Maps* maps) { - return Call6(process_memory, maps); -} - -size_t Call4(std::shared_ptr& process_memory, unwindstack::Maps* maps) { - return Call5(process_memory, maps); -} - -size_t Call3(std::shared_ptr& process_memory, unwindstack::Maps* maps) { - return Call4(process_memory, maps); -} - -size_t Call2(std::shared_ptr& process_memory, unwindstack::Maps* maps) { - return Call3(process_memory, maps); -} - -size_t Call1(std::shared_ptr& process_memory, unwindstack::Maps* maps) { - return Call2(process_memory, maps); -} - -static void BM_uncached_unwind(benchmark::State& state) { - auto process_memory = unwindstack::Memory::CreateProcessMemory(getpid()); - unwindstack::LocalMaps maps; - if (!maps.Parse()) { - state.SkipWithError("Failed to parse local maps."); - } - - for (auto _ : state) { - benchmark::DoNotOptimize(Call1(process_memory, &maps)); - } -} -BENCHMARK(BM_uncached_unwind); - -static void BM_cached_unwind(benchmark::State& state) { - auto process_memory = unwindstack::Memory::CreateProcessMemoryCached(getpid()); - unwindstack::LocalMaps maps; - if (!maps.Parse()) { - state.SkipWithError("Failed to parse local maps."); - } - - for (auto _ : state) { - benchmark::DoNotOptimize(Call1(process_memory, &maps)); - } -} -BENCHMARK(BM_cached_unwind); - -BENCHMARK_MAIN(); diff --git a/libunwindstack/include/unwindstack/Arch.h b/libunwindstack/include/unwindstack/Arch.h deleted file mode 100644 index 706000419..000000000 --- a/libunwindstack/include/unwindstack/Arch.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2020 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_ARCH_H -#define _LIBUNWINDSTACK_ARCH_H - -#include - -namespace unwindstack { - -enum ArchEnum : uint8_t { - ARCH_UNKNOWN = 0, - ARCH_ARM, - ARCH_ARM64, - ARCH_X86, - ARCH_X86_64, - ARCH_MIPS, - ARCH_MIPS64, -}; - -static inline bool ArchIs32Bit(ArchEnum arch) { - switch (arch) { - case ARCH_ARM: - case ARCH_X86: - case ARCH_MIPS: - return true; - default: - return false; - } -} - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_ARCH_H diff --git a/libunwindstack/include/unwindstack/DexFiles.h b/libunwindstack/include/unwindstack/DexFiles.h deleted file mode 100644 index 67a9640d6..000000000 --- a/libunwindstack/include/unwindstack/DexFiles.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2018 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_DEX_FILES_H -#define _LIBUNWINDSTACK_DEX_FILES_H - -#include - -#include -#include -#include -#include -#include - -#include -#include - -namespace unwindstack { - -// Forward declarations. -class DexFile; -class Maps; -struct MapInfo; -enum ArchEnum : uint8_t; - -class DexFiles : public Global { - public: - explicit DexFiles(std::shared_ptr& memory); - DexFiles(std::shared_ptr& memory, std::vector& search_libs); - virtual ~DexFiles(); - - DexFile* GetDexFile(uint64_t dex_file_offset, MapInfo* info); - - void GetMethodInformation(Maps* maps, MapInfo* info, uint64_t dex_pc, std::string* method_name, - uint64_t* method_offset); - - private: - void Init(Maps* maps); - - bool GetAddr(size_t index, uint64_t* addr); - - uint64_t ReadEntryPtr32(uint64_t addr); - - uint64_t ReadEntryPtr64(uint64_t addr); - - bool ReadEntry32(); - - bool ReadEntry64(); - - bool ReadVariableData(uint64_t ptr_offset) override; - - void ProcessArch() override; - - std::mutex lock_; - bool initialized_ = false; - std::unordered_map> files_; - - uint64_t entry_addr_ = 0; - uint64_t (DexFiles::*read_entry_ptr_func_)(uint64_t) = nullptr; - bool (DexFiles::*read_entry_func_)() = nullptr; - std::vector addrs_; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_DEX_FILES_H diff --git a/libunwindstack/include/unwindstack/DwarfError.h b/libunwindstack/include/unwindstack/DwarfError.h deleted file mode 100644 index 763e2cbfe..000000000 --- a/libunwindstack/include/unwindstack/DwarfError.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2016 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_DWARF_ERROR_H -#define _LIBUNWINDSTACK_DWARF_ERROR_H - -#include - -namespace unwindstack { - -enum DwarfErrorCode : uint8_t { - DWARF_ERROR_NONE, - DWARF_ERROR_MEMORY_INVALID, - DWARF_ERROR_ILLEGAL_VALUE, - DWARF_ERROR_ILLEGAL_STATE, - DWARF_ERROR_STACK_INDEX_NOT_VALID, - DWARF_ERROR_NOT_IMPLEMENTED, - DWARF_ERROR_TOO_MANY_ITERATIONS, - DWARF_ERROR_CFA_NOT_DEFINED, - DWARF_ERROR_UNSUPPORTED_VERSION, - DWARF_ERROR_NO_FDES, -}; - -struct DwarfErrorData { - DwarfErrorCode code; - uint64_t address; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_DWARF_ERROR_H diff --git a/libunwindstack/include/unwindstack/DwarfLocation.h b/libunwindstack/include/unwindstack/DwarfLocation.h deleted file mode 100644 index bf45bc752..000000000 --- a/libunwindstack/include/unwindstack/DwarfLocation.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2016 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_DWARF_LOCATION_H -#define _LIBUNWINDSTACK_DWARF_LOCATION_H - -#include - -#include - -namespace unwindstack { - -struct DwarfCie; - -enum DwarfLocationEnum : uint8_t { - DWARF_LOCATION_INVALID = 0, - DWARF_LOCATION_UNDEFINED, - DWARF_LOCATION_OFFSET, - DWARF_LOCATION_VAL_OFFSET, - DWARF_LOCATION_REGISTER, - DWARF_LOCATION_EXPRESSION, - DWARF_LOCATION_VAL_EXPRESSION, - DWARF_LOCATION_PSEUDO_REGISTER, -}; - -struct DwarfLocation { - DwarfLocationEnum type; - uint64_t values[2]; -}; - -struct DwarfLocations : public std::unordered_map { - const DwarfCie* cie; - // The range of PCs where the locations are valid (end is exclusive). - uint64_t pc_start = 0; - uint64_t pc_end = 0; -}; -typedef DwarfLocations dwarf_loc_regs_t; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_DWARF_LOCATION_H diff --git a/libunwindstack/include/unwindstack/DwarfMemory.h b/libunwindstack/include/unwindstack/DwarfMemory.h deleted file mode 100644 index c45699a9e..000000000 --- a/libunwindstack/include/unwindstack/DwarfMemory.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2016 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_DWARF_MEMORY_H -#define _LIBUNWINDSTACK_DWARF_MEMORY_H - -#include - -namespace unwindstack { - -// Forward declarations. -class Memory; - -class DwarfMemory { - public: - DwarfMemory(Memory* memory) : memory_(memory) {} - virtual ~DwarfMemory() = default; - - bool ReadBytes(void* dst, size_t num_bytes); - - template - bool ReadSigned(uint64_t* value); - - bool ReadULEB128(uint64_t* value); - - bool ReadSLEB128(int64_t* value); - - template - size_t GetEncodedSize(uint8_t encoding); - - bool AdjustEncodedValue(uint8_t encoding, uint64_t* value); - - template - bool ReadEncodedValue(uint8_t encoding, uint64_t* value); - - uint64_t cur_offset() { return cur_offset_; } - void set_cur_offset(uint64_t cur_offset) { cur_offset_ = cur_offset; } - - void set_pc_offset(int64_t offset) { pc_offset_ = offset; } - void clear_pc_offset() { pc_offset_ = INT64_MAX; } - - void set_data_offset(uint64_t offset) { data_offset_ = offset; } - void clear_data_offset() { data_offset_ = static_cast(-1); } - - void set_func_offset(uint64_t offset) { func_offset_ = offset; } - void clear_func_offset() { func_offset_ = static_cast(-1); } - - void set_text_offset(uint64_t offset) { text_offset_ = offset; } - void clear_text_offset() { text_offset_ = static_cast(-1); } - - private: - Memory* memory_; - uint64_t cur_offset_ = 0; - - int64_t pc_offset_ = INT64_MAX; - uint64_t data_offset_ = static_cast(-1); - uint64_t func_offset_ = static_cast(-1); - uint64_t text_offset_ = static_cast(-1); -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_DWARF_MEMORY_H diff --git a/libunwindstack/include/unwindstack/DwarfSection.h b/libunwindstack/include/unwindstack/DwarfSection.h deleted file mode 100644 index f28cf25f7..000000000 --- a/libunwindstack/include/unwindstack/DwarfSection.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (C) 2016 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_DWARF_SECTION_H -#define _LIBUNWINDSTACK_DWARF_SECTION_H - -#include - -#include -#include -#include - -#include -#include -#include -#include - -namespace unwindstack { - -// Forward declarations. -enum ArchEnum : uint8_t; -class Memory; -class Regs; -template -struct RegsInfo; - -class DwarfSection { - public: - DwarfSection(Memory* memory); - virtual ~DwarfSection() = default; - - class iterator : public std::iterator { - public: - iterator(DwarfSection* section, size_t index) : index_(index) { - section->GetFdes(&fdes_); - if (index_ == static_cast(-1)) { - index_ = fdes_.size(); - } - } - - iterator& operator++() { - index_++; - return *this; - } - iterator& operator++(int increment) { - index_ += increment; - return *this; - } - iterator& operator--() { - index_--; - return *this; - } - iterator& operator--(int decrement) { - index_ -= decrement; - return *this; - } - - bool operator==(const iterator& rhs) { return this->index_ == rhs.index_; } - bool operator!=(const iterator& rhs) { return this->index_ != rhs.index_; } - - const DwarfFde* operator*() { - if (index_ > fdes_.size()) return nullptr; - return fdes_[index_]; - } - - private: - std::vector fdes_; - size_t index_ = 0; - }; - - iterator begin() { return iterator(this, 0); } - iterator end() { return iterator(this, static_cast(-1)); } - - DwarfErrorCode LastErrorCode() { return last_error_.code; } - uint64_t LastErrorAddress() { return last_error_.address; } - - virtual bool Init(uint64_t offset, uint64_t size, int64_t section_bias) = 0; - - virtual bool Eval(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*) = 0; - - virtual bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde, ArchEnum arch) = 0; - - virtual void GetFdes(std::vector* fdes) = 0; - - virtual const DwarfFde* GetFdeFromPc(uint64_t pc) = 0; - - virtual bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs, - ArchEnum arch) = 0; - - virtual uint64_t GetCieOffsetFromFde32(uint32_t pointer) = 0; - - virtual uint64_t GetCieOffsetFromFde64(uint64_t pointer) = 0; - - virtual uint64_t AdjustPcFromFde(uint64_t pc) = 0; - - bool Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished, bool* is_signal_frame); - - protected: - DwarfMemory memory_; - DwarfErrorData last_error_{DWARF_ERROR_NONE, 0}; - - uint32_t cie32_value_ = 0; - uint64_t cie64_value_ = 0; - - std::unordered_map fde_entries_; - std::unordered_map cie_entries_; - std::unordered_map cie_loc_regs_; - std::map loc_regs_; // Single row indexed by pc_end. -}; - -template -class DwarfSectionImpl : public DwarfSection { - public: - DwarfSectionImpl(Memory* memory) : DwarfSection(memory) {} - virtual ~DwarfSectionImpl() = default; - - bool Init(uint64_t offset, uint64_t size, int64_t section_bias) override; - - const DwarfCie* GetCieFromOffset(uint64_t offset); - - const DwarfFde* GetFdeFromOffset(uint64_t offset); - - const DwarfFde* GetFdeFromPc(uint64_t pc) override; - - void GetFdes(std::vector* fdes) override; - - bool EvalRegister(const DwarfLocation* loc, uint32_t reg, AddressType* reg_ptr, void* info); - - bool Eval(const DwarfCie* cie, Memory* regular_memory, const dwarf_loc_regs_t& loc_regs, - Regs* regs, bool* finished) override; - - bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs, - ArchEnum arch) override; - - bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde, ArchEnum arch) override; - - protected: - bool GetNextCieOrFde(const DwarfFde** fde_entry); - - bool FillInCieHeader(DwarfCie* cie); - - bool FillInCie(DwarfCie* cie); - - bool FillInFdeHeader(DwarfFde* fde); - - bool FillInFde(DwarfFde* fde); - - bool EvalExpression(const DwarfLocation& loc, Memory* regular_memory, AddressType* value, - RegsInfo* regs_info, bool* is_dex_pc); - - void InsertFde(const DwarfFde* fde); - - int64_t section_bias_ = 0; - uint64_t entries_offset_ = 0; - uint64_t entries_end_ = 0; - uint64_t next_entries_offset_ = 0; - uint64_t pc_offset_ = 0; - - std::map> fdes_; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_DWARF_SECTION_H diff --git a/libunwindstack/include/unwindstack/DwarfStructs.h b/libunwindstack/include/unwindstack/DwarfStructs.h deleted file mode 100644 index 3d8c2dbfc..000000000 --- a/libunwindstack/include/unwindstack/DwarfStructs.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2016 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_DWARF_STRUCTS_H -#define _LIBUNWINDSTACK_DWARF_STRUCTS_H - -#include - -#include - -namespace unwindstack { - -struct DwarfCie { - uint8_t version = 0; - uint8_t fde_address_encoding = 0; - uint8_t lsda_encoding = 0; - uint8_t segment_size = 0; - std::vector augmentation_string; - uint64_t personality_handler = 0; - uint64_t cfa_instructions_offset = 0; - uint64_t cfa_instructions_end = 0; - uint64_t code_alignment_factor = 0; - int64_t data_alignment_factor = 0; - uint64_t return_address_register = 0; - bool is_signal_frame = false; -}; - -struct DwarfFde { - uint64_t cie_offset = 0; - uint64_t cfa_instructions_offset = 0; - uint64_t cfa_instructions_end = 0; - uint64_t pc_start = 0; - uint64_t pc_end = 0; - uint64_t lsda_address = 0; - const DwarfCie* cie = nullptr; -}; - -constexpr uint16_t CFA_REG = static_cast(-1); - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_DWARF_STRUCTS_H diff --git a/libunwindstack/include/unwindstack/Elf.h b/libunwindstack/include/unwindstack/Elf.h deleted file mode 100644 index e15b221a9..000000000 --- a/libunwindstack/include/unwindstack/Elf.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2016 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_ELF_H -#define _LIBUNWINDSTACK_ELF_H - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#if !defined(EM_AARCH64) -#define EM_AARCH64 183 -#endif - -namespace unwindstack { - -// Forward declaration. -struct MapInfo; -class Regs; - -class Elf { - public: - Elf(Memory* memory) : memory_(memory) {} - virtual ~Elf() = default; - - bool Init(); - - void InitGnuDebugdata(); - - void Invalidate(); - - std::string GetSoname(); - - bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset); - - bool GetGlobalVariableOffset(const std::string& name, uint64_t* memory_offset); - - uint64_t GetRelPc(uint64_t pc, const MapInfo* map_info); - - bool StepIfSignalHandler(uint64_t rel_pc, Regs* regs, Memory* process_memory); - - bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished, - bool* is_signal_frame); - - ElfInterface* CreateInterfaceFromMemory(Memory* memory); - - std::string GetBuildID(); - - int64_t GetLoadBias() { return load_bias_; } - - bool IsValidPc(uint64_t pc); - - void GetLastError(ErrorData* data); - ErrorCode GetLastErrorCode(); - uint64_t GetLastErrorAddress(); - - bool valid() { return valid_; } - - uint32_t machine_type() { return machine_type_; } - - uint8_t class_type() { return class_type_; } - - ArchEnum arch() { return arch_; } - - Memory* memory() { return memory_.get(); } - - ElfInterface* interface() { return interface_.get(); } - - ElfInterface* gnu_debugdata_interface() { return gnu_debugdata_interface_.get(); } - - static bool IsValidElf(Memory* memory); - - static bool GetInfo(Memory* memory, uint64_t* size); - - static int64_t GetLoadBias(Memory* memory); - - static std::string GetBuildID(Memory* memory); - - static void SetCachingEnabled(bool enable); - static bool CachingEnabled() { return cache_enabled_; } - - static void CacheLock(); - static void CacheUnlock(); - static void CacheAdd(MapInfo* info); - static bool CacheGet(MapInfo* info); - static bool CacheAfterCreateMemory(MapInfo* info); - - protected: - bool valid_ = false; - int64_t load_bias_ = 0; - std::unique_ptr interface_; - std::unique_ptr memory_; - uint32_t machine_type_; - uint8_t class_type_; - ArchEnum arch_; - // Protect calls that can modify internal state of the interface object. - std::mutex lock_; - - std::unique_ptr gnu_debugdata_memory_; - std::unique_ptr gnu_debugdata_interface_; - - static bool cache_enabled_; - static std::unordered_map, bool>>* cache_; - static std::mutex* cache_lock_; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_ELF_H diff --git a/libunwindstack/include/unwindstack/ElfInterface.h b/libunwindstack/include/unwindstack/ElfInterface.h deleted file mode 100644 index 5df7ddf41..000000000 --- a/libunwindstack/include/unwindstack/ElfInterface.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (C) 2016 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_ELF_INTERFACE_H -#define _LIBUNWINDSTACK_ELF_INTERFACE_H - -#include -#include - -#include -#include -#include -#include - -#include -#include - -namespace unwindstack { - -// Forward declarations. -class Memory; -class Regs; -class Symbols; - -struct LoadInfo { - uint64_t offset; - uint64_t table_offset; - size_t table_size; -}; - -enum : uint8_t { - SONAME_UNKNOWN = 0, - SONAME_VALID, - SONAME_INVALID, -}; - -class ElfInterface { - public: - ElfInterface(Memory* memory) : memory_(memory) {} - virtual ~ElfInterface(); - - virtual bool Init(int64_t* load_bias) = 0; - - virtual void InitHeaders() = 0; - - virtual std::string GetSoname() = 0; - - virtual bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* offset) = 0; - - virtual bool GetGlobalVariable(const std::string& name, uint64_t* memory_address) = 0; - - virtual std::string GetBuildID() = 0; - - virtual bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished, - bool* is_signal_frame); - - virtual bool IsValidPc(uint64_t pc); - - Memory* CreateGnuDebugdataMemory(); - - Memory* memory() { return memory_; } - - const std::unordered_map& pt_loads() { return pt_loads_; } - - void SetGnuDebugdataInterface(ElfInterface* interface) { gnu_debugdata_interface_ = interface; } - - uint64_t dynamic_offset() { return dynamic_offset_; } - uint64_t dynamic_vaddr_start() { return dynamic_vaddr_start_; } - uint64_t dynamic_vaddr_end() { return dynamic_vaddr_end_; } - uint64_t data_offset() { return data_offset_; } - uint64_t data_vaddr_start() { return data_vaddr_start_; } - uint64_t data_vaddr_end() { return data_vaddr_end_; } - uint64_t eh_frame_hdr_offset() { return eh_frame_hdr_offset_; } - int64_t eh_frame_hdr_section_bias() { return eh_frame_hdr_section_bias_; } - uint64_t eh_frame_hdr_size() { return eh_frame_hdr_size_; } - uint64_t eh_frame_offset() { return eh_frame_offset_; } - int64_t eh_frame_section_bias() { return eh_frame_section_bias_; } - uint64_t eh_frame_size() { return eh_frame_size_; } - uint64_t debug_frame_offset() { return debug_frame_offset_; } - int64_t debug_frame_section_bias() { return debug_frame_section_bias_; } - uint64_t debug_frame_size() { return debug_frame_size_; } - uint64_t gnu_debugdata_offset() { return gnu_debugdata_offset_; } - uint64_t gnu_debugdata_size() { return gnu_debugdata_size_; } - uint64_t gnu_build_id_offset() { return gnu_build_id_offset_; } - uint64_t gnu_build_id_size() { return gnu_build_id_size_; } - - DwarfSection* eh_frame() { return eh_frame_.get(); } - DwarfSection* debug_frame() { return debug_frame_.get(); } - - const ErrorData& last_error() { return last_error_; } - ErrorCode LastErrorCode() { return last_error_.code; } - uint64_t LastErrorAddress() { return last_error_.address; } - - template - static int64_t GetLoadBias(Memory* memory); - - template - static std::string ReadBuildIDFromMemory(Memory* memory); - - protected: - template - void InitHeadersWithTemplate(); - - template - bool ReadAllHeaders(int64_t* load_bias); - - template - void ReadProgramHeaders(const EhdrType& ehdr, int64_t* load_bias); - - template - void ReadSectionHeaders(const EhdrType& ehdr); - - template - std::string GetSonameWithTemplate(); - - template - bool GetFunctionNameWithTemplate(uint64_t addr, std::string* name, uint64_t* func_offset); - - template - bool GetGlobalVariableWithTemplate(const std::string& name, uint64_t* memory_address); - - virtual void HandleUnknownType(uint32_t, uint64_t, uint64_t) {} - - template - static void GetMaxSizeWithTemplate(Memory* memory, uint64_t* size); - - template - std::string ReadBuildID(); - - Memory* memory_; - std::unordered_map pt_loads_; - - // Stored elf data. - uint64_t dynamic_offset_ = 0; - uint64_t dynamic_vaddr_start_ = 0; - uint64_t dynamic_vaddr_end_ = 0; - - uint64_t data_offset_ = 0; - uint64_t data_vaddr_start_ = 0; - uint64_t data_vaddr_end_ = 0; - - uint64_t eh_frame_hdr_offset_ = 0; - int64_t eh_frame_hdr_section_bias_ = 0; - uint64_t eh_frame_hdr_size_ = 0; - - uint64_t eh_frame_offset_ = 0; - int64_t eh_frame_section_bias_ = 0; - uint64_t eh_frame_size_ = 0; - - uint64_t debug_frame_offset_ = 0; - int64_t debug_frame_section_bias_ = 0; - uint64_t debug_frame_size_ = 0; - - uint64_t gnu_debugdata_offset_ = 0; - uint64_t gnu_debugdata_size_ = 0; - - uint64_t gnu_build_id_offset_ = 0; - uint64_t gnu_build_id_size_ = 0; - - uint8_t soname_type_ = SONAME_UNKNOWN; - std::string soname_; - - ErrorData last_error_{ERROR_NONE, 0}; - - std::unique_ptr eh_frame_; - std::unique_ptr debug_frame_; - // The Elf object owns the gnu_debugdata interface object. - ElfInterface* gnu_debugdata_interface_ = nullptr; - - std::vector symbols_; - std::vector> strtabs_; -}; - -class ElfInterface32 : public ElfInterface { - public: - ElfInterface32(Memory* memory) : ElfInterface(memory) {} - virtual ~ElfInterface32() = default; - - bool Init(int64_t* load_bias) override { - return ElfInterface::ReadAllHeaders(load_bias); - } - - void InitHeaders() override { ElfInterface::InitHeadersWithTemplate(); } - - std::string GetSoname() override { return ElfInterface::GetSonameWithTemplate(); } - - bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) override { - return ElfInterface::GetFunctionNameWithTemplate(addr, name, func_offset); - } - - bool GetGlobalVariable(const std::string& name, uint64_t* memory_address) override { - return ElfInterface::GetGlobalVariableWithTemplate(name, memory_address); - } - - std::string GetBuildID() override { return ElfInterface::ReadBuildID(); } - - static void GetMaxSize(Memory* memory, uint64_t* size) { - GetMaxSizeWithTemplate(memory, size); - } -}; - -class ElfInterface64 : public ElfInterface { - public: - ElfInterface64(Memory* memory) : ElfInterface(memory) {} - virtual ~ElfInterface64() = default; - - bool Init(int64_t* load_bias) override { - return ElfInterface::ReadAllHeaders(load_bias); - } - - void InitHeaders() override { ElfInterface::InitHeadersWithTemplate(); } - - std::string GetSoname() override { return ElfInterface::GetSonameWithTemplate(); } - - bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) override { - return ElfInterface::GetFunctionNameWithTemplate(addr, name, func_offset); - } - - bool GetGlobalVariable(const std::string& name, uint64_t* memory_address) override { - return ElfInterface::GetGlobalVariableWithTemplate(name, memory_address); - } - - std::string GetBuildID() override { return ElfInterface::ReadBuildID(); } - - static void GetMaxSize(Memory* memory, uint64_t* size) { - GetMaxSizeWithTemplate(memory, size); - } -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_ELF_INTERFACE_H diff --git a/libunwindstack/include/unwindstack/Error.h b/libunwindstack/include/unwindstack/Error.h deleted file mode 100644 index 0be4572f4..000000000 --- a/libunwindstack/include/unwindstack/Error.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2018 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_ERROR_H -#define _LIBUNWINDSTACK_ERROR_H - -#include - -namespace unwindstack { - -// A bit map of warnings, multiple warnings can be set at the same time. -enum WarningCode : uint64_t { - WARNING_NONE = 0, - WARNING_DEX_PC_NOT_IN_MAP = 0x1, // A dex pc was found, but it doesn't exist - // in any valid map. -}; - -enum ErrorCode : uint8_t { - ERROR_NONE, // No error. - ERROR_MEMORY_INVALID, // Memory read failed. - ERROR_UNWIND_INFO, // Unable to use unwind information to unwind. - ERROR_UNSUPPORTED, // Encountered unsupported feature. - ERROR_INVALID_MAP, // Unwind in an invalid map. - ERROR_MAX_FRAMES_EXCEEDED, // The number of frames exceed the total allowed. - ERROR_REPEATED_FRAME, // The last frame has the same pc/sp as the next. - ERROR_INVALID_ELF, // Unwind in an invalid elf. -}; - -static inline const char* GetErrorCodeString(ErrorCode error) { - switch (error) { - case ERROR_NONE: - return "None"; - case ERROR_MEMORY_INVALID: - return "Memory Invalid"; - case ERROR_UNWIND_INFO: - return "Unwind Info"; - case ERROR_UNSUPPORTED: - return "Unsupported"; - case ERROR_INVALID_MAP: - return "Invalid Map"; - case ERROR_MAX_FRAMES_EXCEEDED: - return "Maximum Frames Exceeded"; - case ERROR_REPEATED_FRAME: - return "Repeated Frame"; - case ERROR_INVALID_ELF: - return "Invalid Elf"; - } -} - -struct ErrorData { - ErrorCode code; - uint64_t address; // Only valid when code is ERROR_MEMORY_INVALID. - // Indicates the failing address. -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_ERROR_H diff --git a/libunwindstack/include/unwindstack/Global.h b/libunwindstack/include/unwindstack/Global.h deleted file mode 100644 index b9bb141b1..000000000 --- a/libunwindstack/include/unwindstack/Global.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2018 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_GLOBAL_H -#define _LIBUNWINDSTACK_GLOBAL_H - -#include - -#include -#include -#include -#include -#include - -#include -#include - -namespace unwindstack { - -// Forward declarations. -class Maps; -struct MapInfo; - -class Global { - public: - explicit Global(std::shared_ptr& memory); - Global(std::shared_ptr& memory, std::vector& search_libs); - virtual ~Global() = default; - - void SetArch(ArchEnum arch); - - ArchEnum arch() { return arch_; } - - protected: - bool Searchable(const std::string& name); - void FindAndReadVariable(Maps* maps, const char* variable); - - virtual bool ReadVariableData(uint64_t offset) = 0; - - virtual void ProcessArch() = 0; - - ArchEnum arch_ = ARCH_UNKNOWN; - - std::shared_ptr memory_; - std::vector search_libs_; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_GLOBAL_H diff --git a/libunwindstack/include/unwindstack/JitDebug.h b/libunwindstack/include/unwindstack/JitDebug.h deleted file mode 100644 index 8b7b4b590..000000000 --- a/libunwindstack/include/unwindstack/JitDebug.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2017 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_JIT_DEBUG_H -#define _LIBUNWINDSTACK_JIT_DEBUG_H - -#include - -#include -#include -#include -#include - -#include -#include - -namespace unwindstack { - -// Forward declarations. -class Elf; -class Maps; -enum ArchEnum : uint8_t; - -class JitDebug : public Global { - public: - explicit JitDebug(std::shared_ptr& memory); - JitDebug(std::shared_ptr& memory, std::vector& search_libs); - virtual ~JitDebug(); - - Elf* GetElf(Maps* maps, uint64_t pc); - - private: - void Init(Maps* maps); - - uint64_t (JitDebug::*read_descriptor_func_)(uint64_t) = nullptr; - uint64_t (JitDebug::*read_entry_func_)(uint64_t*, uint64_t*) = nullptr; - - uint64_t ReadDescriptor32(uint64_t); - uint64_t ReadDescriptor64(uint64_t); - - uint64_t ReadEntry32Pack(uint64_t* start, uint64_t* size); - uint64_t ReadEntry32Pad(uint64_t* start, uint64_t* size); - uint64_t ReadEntry64(uint64_t* start, uint64_t* size); - - bool ReadVariableData(uint64_t ptr_offset) override; - - void ProcessArch() override; - - uint64_t entry_addr_ = 0; - bool initialized_ = false; - std::vector elf_list_; - - std::mutex lock_; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_JIT_DEBUG_H diff --git a/libunwindstack/include/unwindstack/LocalUnwinder.h b/libunwindstack/include/unwindstack/LocalUnwinder.h deleted file mode 100644 index 80bb53ec1..000000000 --- a/libunwindstack/include/unwindstack/LocalUnwinder.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2018 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_LOCAL_UNWINDER_H -#define _LIBUNWINDSTACK_LOCAL_UNWINDER_H - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -namespace unwindstack { - -// Forward declarations. -class Elf; -struct MapInfo; - -struct LocalFrameData { - LocalFrameData(MapInfo* map_info, uint64_t pc, uint64_t rel_pc, const std::string& function_name, - uint64_t function_offset) - : map_info(map_info), - pc(pc), - rel_pc(rel_pc), - function_name(function_name), - function_offset(function_offset) {} - - MapInfo* map_info; - uint64_t pc; - uint64_t rel_pc; - std::string function_name; - uint64_t function_offset; -}; - -// This is a specialized class that should only be used for doing local unwinds. -// The Unwind call can be made as multiple times on the same object, and it can -// be called by multiple threads at the same time. -// It is designed to be used in debugging circumstances to get a stack trace -// as fast as possible. -class LocalUnwinder { - public: - LocalUnwinder() = default; - LocalUnwinder(const std::vector& skip_libraries) : skip_libraries_(skip_libraries) {} - ~LocalUnwinder() = default; - - bool Init(); - - bool Unwind(std::vector* frame_info, size_t max_frames); - - bool ShouldSkipLibrary(const std::string& map_name); - - MapInfo* GetMapInfo(uint64_t pc); - - ErrorCode LastErrorCode() { return last_error_.code; } - uint64_t LastErrorAddress() { return last_error_.address; } - - private: - pthread_rwlock_t maps_rwlock_; - std::unique_ptr maps_ = nullptr; - std::shared_ptr process_memory_; - std::vector skip_libraries_; - ErrorData last_error_; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_LOCAL_UNWINDER_H diff --git a/libunwindstack/include/unwindstack/Log.h b/libunwindstack/include/unwindstack/Log.h deleted file mode 100644 index aa1219c26..000000000 --- a/libunwindstack/include/unwindstack/Log.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2016 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_LOG_H -#define _LIBUNWINDSTACK_LOG_H - -#include - -namespace unwindstack { - -void log_to_stdout(bool enable); -void log(uint8_t indent, const char* format, ...); - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_LOG_H diff --git a/libunwindstack/include/unwindstack/MachineArm.h b/libunwindstack/include/unwindstack/MachineArm.h deleted file mode 100644 index 3f902b194..000000000 --- a/libunwindstack/include/unwindstack/MachineArm.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2017 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_MACHINE_ARM_H -#define _LIBUNWINDSTACK_MACHINE_ARM_H - -#include - -namespace unwindstack { - -enum ArmReg : uint16_t { - ARM_REG_R0 = 0, - ARM_REG_R1, - ARM_REG_R2, - ARM_REG_R3, - ARM_REG_R4, - ARM_REG_R5, - ARM_REG_R6, - ARM_REG_R7, - ARM_REG_R8, - ARM_REG_R9, - ARM_REG_R10, - ARM_REG_R11, - ARM_REG_R12, - ARM_REG_R13, - ARM_REG_R14, - ARM_REG_R15, - ARM_REG_LAST, - - ARM_REG_SP = ARM_REG_R13, - ARM_REG_LR = ARM_REG_R14, - ARM_REG_PC = ARM_REG_R15, -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_MACHINE_ARM_H diff --git a/libunwindstack/include/unwindstack/MachineArm64.h b/libunwindstack/include/unwindstack/MachineArm64.h deleted file mode 100644 index 358e3d989..000000000 --- a/libunwindstack/include/unwindstack/MachineArm64.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2017 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_MACHINE_ARM64_H -#define _LIBUNWINDSTACK_MACHINE_ARM64_H - -#include - -namespace unwindstack { - -enum Arm64Reg : uint16_t { - ARM64_REG_R0 = 0, - ARM64_REG_R1, - ARM64_REG_R2, - ARM64_REG_R3, - ARM64_REG_R4, - ARM64_REG_R5, - ARM64_REG_R6, - ARM64_REG_R7, - ARM64_REG_R8, - ARM64_REG_R9, - ARM64_REG_R10, - ARM64_REG_R11, - ARM64_REG_R12, - ARM64_REG_R13, - ARM64_REG_R14, - ARM64_REG_R15, - ARM64_REG_R16, - ARM64_REG_R17, - ARM64_REG_R18, - ARM64_REG_R19, - ARM64_REG_R20, - ARM64_REG_R21, - ARM64_REG_R22, - ARM64_REG_R23, - ARM64_REG_R24, - ARM64_REG_R25, - ARM64_REG_R26, - ARM64_REG_R27, - ARM64_REG_R28, - ARM64_REG_R29, - ARM64_REG_R30, - ARM64_REG_R31, - ARM64_REG_PC, - ARM64_REG_PSTATE, - ARM64_REG_LAST, - - ARM64_REG_SP = ARM64_REG_R31, - ARM64_REG_LR = ARM64_REG_R30, - - // Pseudo registers. These are not machine registers. - - // AARCH64 Return address signed state pseudo-register - ARM64_PREG_RA_SIGN_STATE = 34, - ARM64_PREG_FIRST = ARM64_PREG_RA_SIGN_STATE, - ARM64_PREG_LAST, -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_MACHINE_ARM64_H diff --git a/libunwindstack/include/unwindstack/MachineMips.h b/libunwindstack/include/unwindstack/MachineMips.h deleted file mode 100644 index 2dfb1e940..000000000 --- a/libunwindstack/include/unwindstack/MachineMips.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2017 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_MACHINE_MIPS_H -#define _LIBUNWINDSTACK_MACHINE_MIPS_H - -#include - -namespace unwindstack { - -enum MipsReg : uint16_t { - MIPS_REG_R0 = 0, - MIPS_REG_R1, - MIPS_REG_R2, - MIPS_REG_R3, - MIPS_REG_R4, - MIPS_REG_R5, - MIPS_REG_R6, - MIPS_REG_R7, - MIPS_REG_R8, - MIPS_REG_R9, - MIPS_REG_R10, - MIPS_REG_R11, - MIPS_REG_R12, - MIPS_REG_R13, - MIPS_REG_R14, - MIPS_REG_R15, - MIPS_REG_R16, - MIPS_REG_R17, - MIPS_REG_R18, - MIPS_REG_R19, - MIPS_REG_R20, - MIPS_REG_R21, - MIPS_REG_R22, - MIPS_REG_R23, - MIPS_REG_R24, - MIPS_REG_R25, - MIPS_REG_R26, - MIPS_REG_R27, - MIPS_REG_R28, - MIPS_REG_R29, - MIPS_REG_R30, - MIPS_REG_R31, - MIPS_REG_PC, - MIPS_REG_LAST, - - MIPS_REG_SP = MIPS_REG_R29, - MIPS_REG_RA = MIPS_REG_R31, -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_MACHINE_MIPS_H \ No newline at end of file diff --git a/libunwindstack/include/unwindstack/MachineMips64.h b/libunwindstack/include/unwindstack/MachineMips64.h deleted file mode 100644 index 34addf24d..000000000 --- a/libunwindstack/include/unwindstack/MachineMips64.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2017 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_MACHINE_MIPS64_H -#define _LIBUNWINDSTACK_MACHINE_MIPS64_H - -#include - -namespace unwindstack { - -enum Mips64Reg : uint16_t { - MIPS64_REG_R0 = 0, - MIPS64_REG_R1, - MIPS64_REG_R2, - MIPS64_REG_R3, - MIPS64_REG_R4, - MIPS64_REG_R5, - MIPS64_REG_R6, - MIPS64_REG_R7, - MIPS64_REG_R8, - MIPS64_REG_R9, - MIPS64_REG_R10, - MIPS64_REG_R11, - MIPS64_REG_R12, - MIPS64_REG_R13, - MIPS64_REG_R14, - MIPS64_REG_R15, - MIPS64_REG_R16, - MIPS64_REG_R17, - MIPS64_REG_R18, - MIPS64_REG_R19, - MIPS64_REG_R20, - MIPS64_REG_R21, - MIPS64_REG_R22, - MIPS64_REG_R23, - MIPS64_REG_R24, - MIPS64_REG_R25, - MIPS64_REG_R26, - MIPS64_REG_R27, - MIPS64_REG_R28, - MIPS64_REG_R29, - MIPS64_REG_R30, - MIPS64_REG_R31, - MIPS64_REG_PC, - MIPS64_REG_LAST, - - MIPS64_REG_SP = MIPS64_REG_R29, - MIPS64_REG_RA = MIPS64_REG_R31, -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_MACHINE_MIPS64_H \ No newline at end of file diff --git a/libunwindstack/include/unwindstack/MachineX86.h b/libunwindstack/include/unwindstack/MachineX86.h deleted file mode 100644 index 02adb98c3..000000000 --- a/libunwindstack/include/unwindstack/MachineX86.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2017 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_MACHINE_X86_H -#define _LIBUNWINDSTACK_MACHINE_X86_H - -#include - -namespace unwindstack { - -// Matches the numbers for the registers as generated by compilers. -// If this is changed, then unwinding will fail. -enum X86Reg : uint16_t { - X86_REG_EAX = 0, - X86_REG_ECX = 1, - X86_REG_EDX = 2, - X86_REG_EBX = 3, - X86_REG_ESP = 4, - X86_REG_EBP = 5, - X86_REG_ESI = 6, - X86_REG_EDI = 7, - X86_REG_EIP = 8, - X86_REG_EFL = 9, - X86_REG_CS = 10, - X86_REG_SS = 11, - X86_REG_DS = 12, - X86_REG_ES = 13, - X86_REG_FS = 14, - X86_REG_GS = 15, - X86_REG_LAST, - - X86_REG_SP = X86_REG_ESP, - X86_REG_PC = X86_REG_EIP, -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_MACHINE_X86_H diff --git a/libunwindstack/include/unwindstack/MachineX86_64.h b/libunwindstack/include/unwindstack/MachineX86_64.h deleted file mode 100644 index af33fea80..000000000 --- a/libunwindstack/include/unwindstack/MachineX86_64.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2017 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_MACHINE_X86_64_H -#define _LIBUNWINDSTACK_MACHINE_X86_64_H - -#include - -namespace unwindstack { - -// Matches the numbers for the registers as generated by compilers. -// If this is changed, then unwinding will fail. -enum X86_64Reg : uint16_t { - X86_64_REG_RAX = 0, - X86_64_REG_RDX = 1, - X86_64_REG_RCX = 2, - X86_64_REG_RBX = 3, - X86_64_REG_RSI = 4, - X86_64_REG_RDI = 5, - X86_64_REG_RBP = 6, - X86_64_REG_RSP = 7, - X86_64_REG_R8 = 8, - X86_64_REG_R9 = 9, - X86_64_REG_R10 = 10, - X86_64_REG_R11 = 11, - X86_64_REG_R12 = 12, - X86_64_REG_R13 = 13, - X86_64_REG_R14 = 14, - X86_64_REG_R15 = 15, - X86_64_REG_RIP = 16, - X86_64_REG_LAST, - - X86_64_REG_SP = X86_64_REG_RSP, - X86_64_REG_PC = X86_64_REG_RIP, -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_MACHINE_X86_64_H diff --git a/libunwindstack/include/unwindstack/MapInfo.h b/libunwindstack/include/unwindstack/MapInfo.h deleted file mode 100644 index 052e79fe1..000000000 --- a/libunwindstack/include/unwindstack/MapInfo.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2016 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_MAP_INFO_H -#define _LIBUNWINDSTACK_MAP_INFO_H - -#include - -#include -#include -#include -#include - -#include - -namespace unwindstack { - -class MemoryFileAtOffset; - -struct MapInfo { - MapInfo(MapInfo* prev_map, MapInfo* prev_real_map, uint64_t start, uint64_t end, uint64_t offset, - uint64_t flags, const char* name) - : start(start), - end(end), - offset(offset), - flags(flags), - name(name), - prev_map(prev_map), - prev_real_map(prev_real_map), - load_bias(INT64_MAX), - build_id(0) {} - MapInfo(MapInfo* prev_map, MapInfo* prev_real_map, uint64_t start, uint64_t end, uint64_t offset, - uint64_t flags, const std::string& name) - : start(start), - end(end), - offset(offset), - flags(flags), - name(name), - prev_map(prev_map), - prev_real_map(prev_real_map), - load_bias(INT64_MAX), - build_id(0) {} - ~MapInfo(); - - uint64_t start = 0; - uint64_t end = 0; - uint64_t offset = 0; - uint16_t flags = 0; - std::string name; - std::shared_ptr elf; - // The offset of the beginning of this mapping to the beginning of the - // ELF file. - // elf_offset == offset - elf_start_offset. - // This value is only non-zero if the offset is non-zero but there is - // no elf signature found at that offset. - uint64_t elf_offset = 0; - // This value is the offset into the file of the map in memory that is the - // start of the elf. This is not equal to offset when the linker splits - // shared libraries into a read-only and read-execute map. - uint64_t elf_start_offset = 0; - - MapInfo* prev_map = nullptr; - // This is the previous map that is not empty with a 0 offset. For - // example, this set of maps: - // 1000-2000 r--p 000000 00:00 0 libc.so - // 2000-3000 ---p 000000 00:00 0 libc.so - // 3000-4000 r-xp 003000 00:00 0 libc.so - // The last map's prev_map would point to the 2000-3000 map, while the - // prev_real_map would point to the 1000-2000 map. - MapInfo* prev_real_map = nullptr; - - std::atomic_int64_t load_bias; - - // This is a pointer to a new'd std::string. - // Using an atomic value means that we don't need to lock and will - // make it easier to move to a fine grained lock in the future. - std::atomic_uintptr_t build_id; - - // Set to true if the elf file data is coming from memory. - bool memory_backed_elf = false; - - // This function guarantees it will never return nullptr. - Elf* GetElf(const std::shared_ptr& process_memory, ArchEnum expected_arch); - - uint64_t GetLoadBias(const std::shared_ptr& process_memory); - - Memory* CreateMemory(const std::shared_ptr& process_memory); - - bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset); - - // Returns the raw build id read from the elf data. - std::string GetBuildID(); - - // Returns the printable version of the build id (hex dump of raw data). - std::string GetPrintableBuildID(); - - inline bool IsBlank() { return offset == 0 && flags == 0 && name.empty(); } - - private: - MapInfo(const MapInfo&) = delete; - void operator=(const MapInfo&) = delete; - - Memory* GetFileMemory(); - bool InitFileMemoryFromPreviousReadOnlyMap(MemoryFileAtOffset* memory); - - // Protect the creation of the elf object. - std::mutex mutex_; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_MAP_INFO_H diff --git a/libunwindstack/include/unwindstack/Maps.h b/libunwindstack/include/unwindstack/Maps.h deleted file mode 100644 index e53f367d4..000000000 --- a/libunwindstack/include/unwindstack/Maps.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2016 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_MAPS_H -#define _LIBUNWINDSTACK_MAPS_H - -#include -#include - -#include -#include -#include - -#include - -namespace unwindstack { - -// Special flag to indicate a map is in /dev/. However, a map in -// /dev/ashmem/... does not set this flag. -static constexpr int MAPS_FLAGS_DEVICE_MAP = 0x8000; -// Special flag to indicate that this map represents an elf file -// created by ART for use with the gdb jit debug interface. -// This should only ever appear in offline maps data. -static constexpr int MAPS_FLAGS_JIT_SYMFILE_MAP = 0x4000; - -class Maps { - public: - virtual ~Maps() = default; - - Maps() = default; - - // Maps are not copyable but movable, because they own pointers to MapInfo - // objects. - Maps(const Maps&) = delete; - Maps& operator=(const Maps&) = delete; - Maps(Maps&&) = default; - Maps& operator=(Maps&&) = default; - - MapInfo* Find(uint64_t pc); - - virtual bool Parse(); - - virtual const std::string GetMapsFile() const { return ""; } - - void Add(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags, const std::string& name, - uint64_t load_bias); - - void Sort(); - - typedef std::vector>::iterator iterator; - iterator begin() { return maps_.begin(); } - iterator end() { return maps_.end(); } - - typedef std::vector>::const_iterator const_iterator; - const_iterator begin() const { return maps_.begin(); } - const_iterator end() const { return maps_.end(); } - - size_t Total() { return maps_.size(); } - - MapInfo* Get(size_t index) { - if (index >= maps_.size()) return nullptr; - return maps_[index].get(); - } - - protected: - std::vector> maps_; -}; - -class RemoteMaps : public Maps { - public: - RemoteMaps(pid_t pid) : pid_(pid) {} - virtual ~RemoteMaps() = default; - - virtual const std::string GetMapsFile() const override; - - private: - pid_t pid_; -}; - -class LocalMaps : public RemoteMaps { - public: - LocalMaps() : RemoteMaps(getpid()) {} - virtual ~LocalMaps() = default; -}; - -class LocalUpdatableMaps : public Maps { - public: - LocalUpdatableMaps() : Maps() {} - virtual ~LocalUpdatableMaps() = default; - - bool Reparse(); - - const std::string GetMapsFile() const override; - - protected: - std::vector> saved_maps_; -}; - -class BufferMaps : public Maps { - public: - BufferMaps(const char* buffer) : buffer_(buffer) {} - virtual ~BufferMaps() = default; - - bool Parse() override; - - private: - const char* buffer_; -}; - -class FileMaps : public Maps { - public: - FileMaps(const std::string& file) : file_(file) {} - virtual ~FileMaps() = default; - - const std::string GetMapsFile() const override { return file_; } - - protected: - const std::string file_; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_MAPS_H diff --git a/libunwindstack/include/unwindstack/Memory.h b/libunwindstack/include/unwindstack/Memory.h deleted file mode 100644 index 3d8187856..000000000 --- a/libunwindstack/include/unwindstack/Memory.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2016 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_H -#define _LIBUNWINDSTACK_MEMORY_H - -#include -#include -#include - -#include -#include - -namespace unwindstack { - -class Memory { - public: - Memory() = default; - virtual ~Memory() = default; - - 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* dst, size_t max_read); - - virtual void Clear() {} - - virtual bool IsLocal() const { return false; } - - virtual size_t Read(uint64_t addr, void* dst, size_t size) = 0; - virtual long ReadTag(uint64_t) { return -1; } - - bool ReadFully(uint64_t addr, void* dst, size_t size); - - inline bool Read32(uint64_t addr, uint32_t* dst) { - return ReadFully(addr, dst, sizeof(uint32_t)); - } - - inline bool Read64(uint64_t addr, uint64_t* dst) { - return ReadFully(addr, dst, sizeof(uint64_t)); - } -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_MEMORY_H diff --git a/libunwindstack/include/unwindstack/Regs.h b/libunwindstack/include/unwindstack/Regs.h deleted file mode 100644 index 1a2a70440..000000000 --- a/libunwindstack/include/unwindstack/Regs.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2016 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_REGS_H -#define _LIBUNWINDSTACK_REGS_H - -#include -#include - -#include -#include -#include - -#include - -namespace unwindstack { - -// Forward declarations. -class Elf; -class Memory; - -class Regs { - public: - enum LocationEnum : uint8_t { - LOCATION_UNKNOWN = 0, - LOCATION_REGISTER, - LOCATION_SP_OFFSET, - }; - - struct Location { - Location(LocationEnum type, int16_t value) : type(type), value(value) {} - - LocationEnum type; - int16_t value; - }; - - Regs(uint16_t total_regs, const Location& return_loc) - : total_regs_(total_regs), return_loc_(return_loc) {} - virtual ~Regs() = default; - - virtual ArchEnum Arch() = 0; - - bool Is32Bit() { return ArchIs32Bit(Arch()); } - - virtual void* RawData() = 0; - virtual uint64_t pc() = 0; - virtual uint64_t sp() = 0; - - virtual void set_pc(uint64_t pc) = 0; - virtual void set_sp(uint64_t sp) = 0; - - uint64_t dex_pc() { return dex_pc_; } - void set_dex_pc(uint64_t dex_pc) { dex_pc_ = dex_pc; } - - virtual void ResetPseudoRegisters() {} - virtual bool SetPseudoRegister(uint16_t, uint64_t) { return false; } - virtual bool GetPseudoRegister(uint16_t, uint64_t*) { return false; } - - virtual bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) = 0; - - virtual bool SetPcFromReturnAddress(Memory* process_memory) = 0; - - virtual void IterateRegisters(std::function) = 0; - - uint16_t total_regs() { return total_regs_; } - - virtual Regs* Clone() = 0; - - static ArchEnum CurrentArch(); - static Regs* RemoteGet(pid_t pid); - static Regs* CreateFromUcontext(ArchEnum arch, void* ucontext); - static Regs* CreateFromLocal(); - - protected: - uint16_t total_regs_; - Location return_loc_; - uint64_t dex_pc_ = 0; -}; - -template -class RegsImpl : public Regs { - public: - RegsImpl(uint16_t total_regs, Location return_loc) - : Regs(total_regs, return_loc), regs_(total_regs) {} - virtual ~RegsImpl() = default; - - inline AddressType& operator[](size_t reg) { return regs_[reg]; } - - void* RawData() override { return regs_.data(); } - - virtual void IterateRegisters(std::function fn) override { - for (size_t i = 0; i < regs_.size(); ++i) { - fn(std::to_string(i).c_str(), regs_[i]); - } - } - - protected: - std::vector regs_; -}; - -uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf, ArchEnum arch); - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_REGS_H diff --git a/libunwindstack/include/unwindstack/RegsArm.h b/libunwindstack/include/unwindstack/RegsArm.h deleted file mode 100644 index fbb34e7f8..000000000 --- a/libunwindstack/include/unwindstack/RegsArm.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2016 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_REGS_ARM_H -#define _LIBUNWINDSTACK_REGS_ARM_H - -#include - -#include - -#include -#include - -namespace unwindstack { - -// Forward declarations. -class Memory; - -class RegsArm : public RegsImpl { - public: - RegsArm(); - virtual ~RegsArm() = default; - - ArchEnum Arch() override final; - - bool SetPcFromReturnAddress(Memory* process_memory) override; - - bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override; - - void IterateRegisters(std::function) override final; - - uint64_t pc() override; - uint64_t sp() override; - - void set_pc(uint64_t pc) override; - void set_sp(uint64_t sp) override; - - Regs* Clone() override final; - - static Regs* Read(void* data); - - static Regs* CreateFromUcontext(void* ucontext); -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_REGS_ARM_H diff --git a/libunwindstack/include/unwindstack/RegsArm64.h b/libunwindstack/include/unwindstack/RegsArm64.h deleted file mode 100644 index bf7ab1527..000000000 --- a/libunwindstack/include/unwindstack/RegsArm64.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2016 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_REGS_ARM64_H -#define _LIBUNWINDSTACK_REGS_ARM64_H - -#include - -#include - -#include -#include -#include - -namespace unwindstack { - -// Forward declarations. -class Memory; - -class RegsArm64 : public RegsImpl { - public: - RegsArm64(); - virtual ~RegsArm64() = default; - - ArchEnum Arch() override final; - - bool SetPcFromReturnAddress(Memory* process_memory) override; - - bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override; - - void IterateRegisters(std::function) override final; - - uint64_t pc() override; - uint64_t sp() override; - - void set_pc(uint64_t pc) override; - void set_sp(uint64_t sp) override; - - void ResetPseudoRegisters() override; - - bool SetPseudoRegister(uint16_t id, uint64_t value) override; - - bool GetPseudoRegister(uint16_t id, uint64_t* value) override; - - bool IsRASigned(); - - void SetPACMask(uint64_t mask); - - Regs* Clone() override final; - - static Regs* Read(void* data); - - static Regs* CreateFromUcontext(void* ucontext); - - protected: - uint64_t pseudo_regs_[Arm64Reg::ARM64_PREG_LAST - Arm64Reg::ARM64_PREG_FIRST]; - uint64_t pac_mask_; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_REGS_ARM64_H diff --git a/libunwindstack/include/unwindstack/RegsGetLocal.h b/libunwindstack/include/unwindstack/RegsGetLocal.h deleted file mode 100644 index 300a3ecc5..000000000 --- a/libunwindstack/include/unwindstack/RegsGetLocal.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _LIBUNWINDSTACK_REGS_GET_LOCAL_H -#define _LIBUNWINDSTACK_REGS_GET_LOCAL_H - -namespace unwindstack { - -#if defined(__arm__) - -inline __attribute__((__always_inline__)) void AsmGetRegs(void* reg_data) { - asm volatile( - ".align 2\n" - "bx pc\n" - "nop\n" - ".code 32\n" - "stmia %[base], {r0-r12}\n" - "add %[base], #52\n" - "mov r1, r13\n" - "mov r2, r14\n" - "mov r3, r15\n" - "stmia %[base], {r1-r3}\n" - "orr %[base], pc, #1\n" - "bx %[base]\n" - : [base] "+r"(reg_data) - : - : "memory"); -} - -#elif defined(__aarch64__) - -inline __attribute__((__always_inline__)) void AsmGetRegs(void* reg_data) { - asm volatile( - "1:\n" - "stp x0, x1, [%[base], #0]\n" - "stp x2, x3, [%[base], #16]\n" - "stp x4, x5, [%[base], #32]\n" - "stp x6, x7, [%[base], #48]\n" - "stp x8, x9, [%[base], #64]\n" - "stp x10, x11, [%[base], #80]\n" - "stp x12, x13, [%[base], #96]\n" - "stp x14, x15, [%[base], #112]\n" - "stp x16, x17, [%[base], #128]\n" - "stp x18, x19, [%[base], #144]\n" - "stp x20, x21, [%[base], #160]\n" - "stp x22, x23, [%[base], #176]\n" - "stp x24, x25, [%[base], #192]\n" - "stp x26, x27, [%[base], #208]\n" - "stp x28, x29, [%[base], #224]\n" - "str x30, [%[base], #240]\n" - "mov x12, sp\n" - "adr x13, 1b\n" - "stp x12, x13, [%[base], #248]\n" - : [base] "+r"(reg_data) - : - : "x12", "x13", "memory"); -} - -#elif defined(__i386__) || defined(__x86_64__) - -extern "C" void AsmGetRegs(void* regs); - -#endif - -inline __attribute__((__always_inline__)) void RegsGetLocal(Regs* regs) { - AsmGetRegs(regs->RawData()); -} - - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_REGS_GET_LOCAL_H diff --git a/libunwindstack/include/unwindstack/RegsMips.h b/libunwindstack/include/unwindstack/RegsMips.h deleted file mode 100644 index dc09b83b8..000000000 --- a/libunwindstack/include/unwindstack/RegsMips.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2017 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_REGS_MIPS_H -#define _LIBUNWINDSTACK_REGS_MIPS_H - -#include - -#include - -#include -#include - -namespace unwindstack { - -// Forward declarations. -class Memory; - -class RegsMips : public RegsImpl { - public: - RegsMips(); - virtual ~RegsMips() = default; - - ArchEnum Arch() override final; - - bool SetPcFromReturnAddress(Memory* process_memory) override; - - bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override; - - void IterateRegisters(std::function) override final; - - uint64_t pc() override; - uint64_t sp() override; - - void set_pc(uint64_t pc) override; - void set_sp(uint64_t sp) override; - - Regs* Clone() override final; - - static Regs* Read(void* data); - - static Regs* CreateFromUcontext(void* ucontext); -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_REGS_MIPS_H diff --git a/libunwindstack/include/unwindstack/RegsMips64.h b/libunwindstack/include/unwindstack/RegsMips64.h deleted file mode 100644 index 64a80dc0b..000000000 --- a/libunwindstack/include/unwindstack/RegsMips64.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2017 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_REGS_MIPS64_H -#define _LIBUNWINDSTACK_REGS_MIPS64_H - -#include - -#include - -#include -#include - -namespace unwindstack { - -// Forward declarations. -class Memory; - -class RegsMips64 : public RegsImpl { - public: - RegsMips64(); - virtual ~RegsMips64() = default; - - ArchEnum Arch() override final; - - bool SetPcFromReturnAddress(Memory* process_memory) override; - - bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override; - - void IterateRegisters(std::function) override final; - - uint64_t pc() override; - uint64_t sp() override; - - void set_pc(uint64_t pc) override; - void set_sp(uint64_t sp) override; - - Regs* Clone() override final; - - static Regs* Read(void* data); - - static Regs* CreateFromUcontext(void* ucontext); -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_REGS_MIPS64_H diff --git a/libunwindstack/include/unwindstack/RegsX86.h b/libunwindstack/include/unwindstack/RegsX86.h deleted file mode 100644 index cfbdda661..000000000 --- a/libunwindstack/include/unwindstack/RegsX86.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2016 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_REGS_X86_H -#define _LIBUNWINDSTACK_REGS_X86_H - -#include - -#include - -#include -#include - -namespace unwindstack { - -// Forward declarations. -class Memory; -struct x86_ucontext_t; - -class RegsX86 : public RegsImpl { - public: - RegsX86(); - virtual ~RegsX86() = default; - - ArchEnum Arch() override final; - - bool SetPcFromReturnAddress(Memory* process_memory) override; - - bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override; - - void SetFromUcontext(x86_ucontext_t* ucontext); - - void IterateRegisters(std::function) override final; - - uint64_t pc() override; - uint64_t sp() override; - - void set_pc(uint64_t pc) override; - void set_sp(uint64_t sp) override; - - Regs* Clone() override final; - - static Regs* Read(void* data); - - static Regs* CreateFromUcontext(void* ucontext); -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_REGS_X86_H diff --git a/libunwindstack/include/unwindstack/RegsX86_64.h b/libunwindstack/include/unwindstack/RegsX86_64.h deleted file mode 100644 index a11aef09f..000000000 --- a/libunwindstack/include/unwindstack/RegsX86_64.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2016 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_REGS_X86_64_H -#define _LIBUNWINDSTACK_REGS_X86_64_H - -#include - -#include - -#include -#include - -namespace unwindstack { - -// Forward declarations. -class Memory; -struct x86_64_ucontext_t; - -class RegsX86_64 : public RegsImpl { - public: - RegsX86_64(); - virtual ~RegsX86_64() = default; - - ArchEnum Arch() override final; - - bool SetPcFromReturnAddress(Memory* process_memory) override; - - bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) override; - - void SetFromUcontext(x86_64_ucontext_t* ucontext); - - void IterateRegisters(std::function) override final; - - uint64_t pc() override; - uint64_t sp() override; - - void set_pc(uint64_t pc) override; - void set_sp(uint64_t sp) override; - - Regs* Clone() override final; - - static Regs* Read(void* data); - - static Regs* CreateFromUcontext(void* ucontext); -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_REGS_X86_64_H diff --git a/libunwindstack/include/unwindstack/UcontextArm.h b/libunwindstack/include/unwindstack/UcontextArm.h deleted file mode 100644 index 7d1ec3b9a..000000000 --- a/libunwindstack/include/unwindstack/UcontextArm.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _LIBUNWINDSTACK_UCONTEXT_ARM_H -#define _LIBUNWINDSTACK_UCONTEXT_ARM_H - -#include - -#include - -namespace unwindstack { - -struct arm_stack_t { - uint32_t ss_sp; // void __user* - int32_t ss_flags; // int - uint32_t ss_size; // size_t -}; - -struct arm_mcontext_t { - uint32_t trap_no; // unsigned long - uint32_t error_code; // unsigned long - uint32_t oldmask; // unsigned long - uint32_t regs[ARM_REG_LAST]; // unsigned long - uint32_t cpsr; // unsigned long - uint32_t fault_address; // unsigned long -}; - -struct arm_ucontext_t { - uint32_t uc_flags; // unsigned long - uint32_t uc_link; // struct ucontext* - arm_stack_t uc_stack; - arm_mcontext_t uc_mcontext; - // Nothing else is used, so don't define it. -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_UCONTEXT_ARM_H diff --git a/libunwindstack/include/unwindstack/UcontextArm64.h b/libunwindstack/include/unwindstack/UcontextArm64.h deleted file mode 100644 index a68be3b64..000000000 --- a/libunwindstack/include/unwindstack/UcontextArm64.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _LIBUNWINDSTACK_UCONTEXT_ARM64_H -#define _LIBUNWINDSTACK_UCONTEXT_ARM64_H - -#include - -#include - -namespace unwindstack { - -struct arm64_stack_t { - uint64_t ss_sp; // void __user* - int32_t ss_flags; // int - uint64_t ss_size; // size_t -}; - -struct arm64_sigset_t { - uint64_t sig; // unsigned long -}; - -struct arm64_mcontext_t { - uint64_t fault_address; // __u64 - uint64_t regs[ARM64_REG_LAST]; // __u64 - uint64_t pstate; // __u64 - // Nothing else is used, so don't define it. -}; - -struct arm64_ucontext_t { - uint64_t uc_flags; // unsigned long - uint64_t uc_link; // struct ucontext* - arm64_stack_t uc_stack; - arm64_sigset_t uc_sigmask; - // The kernel adds extra padding after uc_sigmask to match glibc sigset_t on ARM64. - char __padding[128 - sizeof(arm64_sigset_t)]; - // The full structure requires 16 byte alignment, but our partial structure - // doesn't, so force the alignment. - arm64_mcontext_t uc_mcontext __attribute__((aligned(16))); -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_UCONTEXT_ARM64_H diff --git a/libunwindstack/include/unwindstack/UcontextMips.h b/libunwindstack/include/unwindstack/UcontextMips.h deleted file mode 100644 index 02e33b64e..000000000 --- a/libunwindstack/include/unwindstack/UcontextMips.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _LIBUNWINDSTACK_UCONTEXT_MIPS_H -#define _LIBUNWINDSTACK_UCONTEXT_MIPS_H - -#include - -#include - -namespace unwindstack { - -struct mips_stack_t { - uint32_t ss_sp; // void __user* - uint32_t ss_size; // size_t - int32_t ss_flags; // int -}; - -struct mips_mcontext_t { - uint32_t sc_regmask; - uint32_t sc_status; - uint64_t sc_pc; - uint64_t sc_regs[32]; - // Nothing else is used, so don't define it. -}; - -struct mips_ucontext_t { - uint32_t uc_flags; // unsigned long - uint32_t uc_link; // struct ucontext* - mips_stack_t uc_stack; - mips_mcontext_t uc_mcontext; - // Nothing else is used, so don't define it. -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_UCONTEXT_MIPS_H diff --git a/libunwindstack/include/unwindstack/UcontextMips64.h b/libunwindstack/include/unwindstack/UcontextMips64.h deleted file mode 100644 index 5b92a55ae..000000000 --- a/libunwindstack/include/unwindstack/UcontextMips64.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _LIBUNWINDSTACK_UCONTEXT_MIPS64_H -#define _LIBUNWINDSTACK_UCONTEXT_MIPS64_H - -#include - -#include - -namespace unwindstack { - -struct mips64_stack_t { - uint64_t ss_sp; // void __user* - uint64_t ss_size; // size_t - int32_t ss_flags; // int -}; - -struct mips64_mcontext_t { - uint64_t sc_regs[32]; - uint64_t sc_fpregs[32]; - uint64_t sc_mdhi; - uint64_t sc_hi1; - uint64_t sc_hi2; - uint64_t sc_hi3; - uint64_t sc_mdlo; - uint64_t sc_lo1; - uint64_t sc_lo2; - uint64_t sc_lo3; - uint64_t sc_pc; - // Nothing else is used, so don't define it. -}; - -struct mips64_ucontext_t { - uint64_t uc_flags; // unsigned long - uint64_t uc_link; // struct ucontext* - mips64_stack_t uc_stack; - mips64_mcontext_t uc_mcontext; - // Nothing else is used, so don't define it. -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_UCONTEXT_MIPS64_H diff --git a/libunwindstack/include/unwindstack/UcontextX86.h b/libunwindstack/include/unwindstack/UcontextX86.h deleted file mode 100644 index c96ebb70b..000000000 --- a/libunwindstack/include/unwindstack/UcontextX86.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _LIBUNWINDSTACK_UCONTEXT_X86_H -#define _LIBUNWINDSTACK_UCONTEXT_X86_H - -#include - -#include - -namespace unwindstack { - -struct x86_stack_t { - uint32_t ss_sp; // void __user* - int32_t ss_flags; // int - uint32_t ss_size; // size_t -}; - -struct x86_mcontext_t { - uint32_t gs; - uint32_t fs; - uint32_t es; - uint32_t ds; - uint32_t edi; - uint32_t esi; - uint32_t ebp; - uint32_t esp; - uint32_t ebx; - uint32_t edx; - uint32_t ecx; - uint32_t eax; - uint32_t trapno; - uint32_t err; - uint32_t eip; - uint32_t cs; - uint32_t efl; - uint32_t uesp; - uint32_t ss; - // Only care about the registers, skip everything else. -}; - -struct x86_ucontext_t { - uint32_t uc_flags; // unsigned long - uint32_t uc_link; // struct ucontext* - x86_stack_t uc_stack; - x86_mcontext_t uc_mcontext; - // Nothing else is used, so don't define it. -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_UCONTEXT_X86_H diff --git a/libunwindstack/include/unwindstack/UcontextX86_64.h b/libunwindstack/include/unwindstack/UcontextX86_64.h deleted file mode 100644 index 4e163e5d4..000000000 --- a/libunwindstack/include/unwindstack/UcontextX86_64.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _LIBUNWINDSTACK_UCONTEXT_X86_64_H -#define _LIBUNWINDSTACK_UCONTEXT_X86_64_H - -#include - -#include - -namespace unwindstack { - -struct x86_64_stack_t { - uint64_t ss_sp; // void __user* - int32_t ss_flags; // int - int32_t pad; - uint64_t ss_size; // size_t -}; - -struct x86_64_mcontext_t { - uint64_t r8; - uint64_t r9; - uint64_t r10; - uint64_t r11; - uint64_t r12; - uint64_t r13; - uint64_t r14; - uint64_t r15; - uint64_t rdi; - uint64_t rsi; - uint64_t rbp; - uint64_t rbx; - uint64_t rdx; - uint64_t rax; - uint64_t rcx; - uint64_t rsp; - uint64_t rip; - uint64_t efl; - uint64_t csgsfs; - uint64_t err; - uint64_t trapno; - uint64_t oldmask; - uint64_t cr2; - // Only care about the registers, skip everything else. -}; - -struct x86_64_ucontext_t { - uint64_t uc_flags; // unsigned long - uint64_t uc_link; // struct ucontext* - x86_64_stack_t uc_stack; - x86_64_mcontext_t uc_mcontext; - // Nothing else is used, so don't define it. -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_UCONTEXT_X86_64_H diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h deleted file mode 100644 index b274c4c13..000000000 --- a/libunwindstack/include/unwindstack/Unwinder.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (C) 2017 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_UNWINDER_H -#define _LIBUNWINDSTACK_UNWINDER_H - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace unwindstack { - -// Forward declarations. -class Elf; - -struct FrameData { - size_t num; - - uint64_t rel_pc; - uint64_t pc; - uint64_t sp; - - std::string function_name; - uint64_t function_offset = 0; - - std::string map_name; - // The offset from the first map representing the frame. When there are - // two maps (read-only and read-execute) this will be the offset from - // the read-only map. When there is only one map, this will be the - // same as the actual offset of the map and match map_exact_offset. - uint64_t map_elf_start_offset = 0; - // The actual offset from the map where the pc lies. - uint64_t map_exact_offset = 0; - uint64_t map_start = 0; - uint64_t map_end = 0; - uint64_t map_load_bias = 0; - int map_flags = 0; -}; - -class Unwinder { - public: - Unwinder(size_t max_frames, Maps* maps, Regs* regs, std::shared_ptr process_memory) - : max_frames_(max_frames), - maps_(maps), - regs_(regs), - process_memory_(process_memory), - arch_(regs->Arch()) { - frames_.reserve(max_frames); - } - Unwinder(size_t max_frames, Maps* maps, std::shared_ptr process_memory) - : max_frames_(max_frames), maps_(maps), process_memory_(process_memory) { - frames_.reserve(max_frames); - } - - virtual ~Unwinder() = default; - - virtual void Unwind(const std::vector* initial_map_names_to_skip = nullptr, - const std::vector* map_suffixes_to_ignore = nullptr); - - size_t NumFrames() const { return frames_.size(); } - - const std::vector& frames() { return frames_; } - - std::vector ConsumeFrames() { - std::vector frames = std::move(frames_); - frames_.clear(); - return frames; - } - - std::string FormatFrame(size_t frame_num) const; - std::string FormatFrame(const FrameData& frame) const; - - void SetArch(ArchEnum arch) { arch_ = arch; }; - - void SetJitDebug(JitDebug* jit_debug); - - void SetRegs(Regs* regs) { - regs_ = regs; - arch_ = regs_ != nullptr ? regs->Arch() : ARCH_UNKNOWN; - } - Maps* GetMaps() { return maps_; } - std::shared_ptr& GetProcessMemory() { return process_memory_; } - - // Disabling the resolving of names results in the function name being - // set to an empty string and the function offset being set to zero. - void SetResolveNames(bool resolve) { resolve_names_ = resolve; } - - // Enable/disable soname printing the soname for a map name if the elf is - // embedded in a file. This is enabled by default. - // NOTE: This does nothing unless resolving names is enabled. - void SetEmbeddedSoname(bool embedded_soname) { embedded_soname_ = embedded_soname; } - - void SetDisplayBuildID(bool display_build_id) { display_build_id_ = display_build_id; } - - void SetDexFiles(DexFiles* dex_files); - - bool elf_from_memory_not_file() { return elf_from_memory_not_file_; } - - ErrorCode LastErrorCode() { return last_error_.code; } - const char* LastErrorCodeString() { return GetErrorCodeString(last_error_.code); } - uint64_t LastErrorAddress() { return last_error_.address; } - uint64_t warnings() { return warnings_; } - - // Builds a frame for symbolization using the maps from this unwinder. The - // constructed frame contains just enough information to be used to symbolize - // frames collected by frame-pointer unwinding that's done outside of - // libunwindstack. This is used by tombstoned to symbolize frame pointer-based - // stack traces that are collected by tools such as GWP-ASan and MTE. - static FrameData BuildFrameFromPcOnly(uint64_t pc, ArchEnum arch, Maps* maps, JitDebug* jit_debug, - std::shared_ptr process_memory, bool resolve_names); - FrameData BuildFrameFromPcOnly(uint64_t pc); - - protected: - Unwinder(size_t max_frames) : max_frames_(max_frames) { frames_.reserve(max_frames); } - Unwinder(size_t max_frames, ArchEnum arch) : max_frames_(max_frames), arch_(arch) { - frames_.reserve(max_frames); - } - - void ClearErrors() { - warnings_ = WARNING_NONE; - last_error_.code = ERROR_NONE; - last_error_.address = 0; - } - - void FillInDexFrame(); - FrameData* FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, uint64_t pc_adjustment); - - size_t max_frames_; - Maps* maps_; - Regs* regs_; - std::vector frames_; - std::shared_ptr process_memory_; - JitDebug* jit_debug_ = nullptr; - DexFiles* dex_files_ = nullptr; - bool resolve_names_ = true; - bool embedded_soname_ = true; - bool display_build_id_ = false; - // True if at least one elf file is coming from memory and not the related - // file. This is only true if there is an actual file backing up the elf. - bool elf_from_memory_not_file_ = false; - ErrorData last_error_; - uint64_t warnings_; - ArchEnum arch_ = ARCH_UNKNOWN; -}; - -class UnwinderFromPid : public Unwinder { - public: - UnwinderFromPid(size_t max_frames, pid_t pid) : Unwinder(max_frames), pid_(pid) {} - UnwinderFromPid(size_t max_frames, pid_t pid, ArchEnum arch) - : Unwinder(max_frames, arch), pid_(pid) {} - virtual ~UnwinderFromPid() = default; - - bool Init(); - - void Unwind(const std::vector* initial_map_names_to_skip = nullptr, - const std::vector* map_suffixes_to_ignore = nullptr) override; - - private: - pid_t pid_; - std::unique_ptr maps_ptr_; - std::unique_ptr jit_debug_ptr_; - std::unique_ptr dex_files_ptr_; - bool initted_ = false; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_UNWINDER_H diff --git a/libunwindstack/include/unwindstack/UserArm.h b/libunwindstack/include/unwindstack/UserArm.h deleted file mode 100644 index 7388c03e4..000000000 --- a/libunwindstack/include/unwindstack/UserArm.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _LIBUNWINDSTACK_USER_ARM_H -#define _LIBUNWINDSTACK_USER_ARM_H - -namespace unwindstack { - -struct arm_user_regs { - uint32_t regs[18]; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_USER_ARM_H diff --git a/libunwindstack/include/unwindstack/UserArm64.h b/libunwindstack/include/unwindstack/UserArm64.h deleted file mode 100644 index d74983fec..000000000 --- a/libunwindstack/include/unwindstack/UserArm64.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _LIBUNWINDSTACK_USER_ARM64_H -#define _LIBUNWINDSTACK_USER_ARM64_H - -namespace unwindstack { - -struct arm64_user_regs { - uint64_t regs[31]; - uint64_t sp; - uint64_t pc; - uint64_t pstate; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_USER_ARM64_H diff --git a/libunwindstack/include/unwindstack/UserMips.h b/libunwindstack/include/unwindstack/UserMips.h deleted file mode 100644 index 184be4f39..000000000 --- a/libunwindstack/include/unwindstack/UserMips.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _LIBUNWINDSTACK_USER_MIPS_H -#define _LIBUNWINDSTACK_USER_MIPS_H - -namespace unwindstack { - -enum Mips32UserReg : uint16_t { - MIPS32_EF_R0 = 6, - MIPS32_EF_CP0_EPC = 40, -}; - -struct mips_user_regs { - uint32_t regs[45]; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_USER_MIPS_H diff --git a/libunwindstack/include/unwindstack/UserMips64.h b/libunwindstack/include/unwindstack/UserMips64.h deleted file mode 100644 index c46befd4f..000000000 --- a/libunwindstack/include/unwindstack/UserMips64.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _LIBUNWINDSTACK_USER_MIPS64_H -#define _LIBUNWINDSTACK_USER_MIPS64_H - -namespace unwindstack { - -enum Mips64UserReg : uint16_t { - MIPS64_EF_R0 = 0, - MIPS64_EF_CP0_EPC = 34, -}; - -struct mips64_user_regs { - uint64_t regs[45]; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_USER_MIPS64_H diff --git a/libunwindstack/include/unwindstack/UserX86.h b/libunwindstack/include/unwindstack/UserX86.h deleted file mode 100644 index a040560c7..000000000 --- a/libunwindstack/include/unwindstack/UserX86.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _LIBUNWINDSTACK_USER_X86_H -#define _LIBUNWINDSTACK_USER_X86_H - -namespace unwindstack { - -struct x86_user_regs { - uint32_t ebx; - uint32_t ecx; - uint32_t edx; - uint32_t esi; - uint32_t edi; - uint32_t ebp; - uint32_t eax; - uint32_t xds; - uint32_t xes; - uint32_t xfs; - uint32_t xgs; - uint32_t orig_eax; - uint32_t eip; - uint32_t xcs; - uint32_t eflags; - uint32_t esp; - uint32_t xss; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_USER_X86_H diff --git a/libunwindstack/include/unwindstack/UserX86_64.h b/libunwindstack/include/unwindstack/UserX86_64.h deleted file mode 100644 index b80d201d5..000000000 --- a/libunwindstack/include/unwindstack/UserX86_64.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _LIBUNWINDSTACK_USER_X86_64_H -#define _LIBUNWINDSTACK_USER_X86_64_H - -namespace unwindstack { - -struct x86_64_user_regs { - uint64_t r15; - uint64_t r14; - uint64_t r13; - uint64_t r12; - uint64_t rbp; - uint64_t rbx; - uint64_t r11; - uint64_t r10; - uint64_t r9; - uint64_t r8; - uint64_t rax; - uint64_t rcx; - uint64_t rdx; - uint64_t rsi; - uint64_t rdi; - uint64_t orig_rax; - uint64_t rip; - uint64_t cs; - uint64_t eflags; - uint64_t rsp; - uint64_t ss; - uint64_t fs_base; - uint64_t gs_base; - uint64_t ds; - uint64_t es; - uint64_t fs; - uint64_t gs; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_USER_X86_64_H diff --git a/libunwindstack/tests/ArmExidxDecodeTest.cpp b/libunwindstack/tests/ArmExidxDecodeTest.cpp deleted file mode 100644 index 69a781641..000000000 --- a/libunwindstack/tests/ArmExidxDecodeTest.cpp +++ /dev/null @@ -1,1668 +0,0 @@ -/* - * Copyright (C) 2016 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 "ArmExidx.h" - -#include "LogFake.h" -#include "MemoryFake.h" - -namespace unwindstack { - -class ArmExidxDecodeTest : public ::testing::TestWithParam { - protected: - void Init(Memory* process_memory = nullptr) { - if (process_memory == nullptr) { - process_memory = &process_memory_; - } - - regs_arm_.reset(new RegsArm()); - for (size_t i = 0; i < regs_arm_->total_regs(); i++) { - (*regs_arm_)[i] = 0; - } - regs_arm_->set_pc(0); - regs_arm_->set_sp(0); - - exidx_.reset(new ArmExidx(regs_arm_.get(), &elf_memory_, process_memory)); - if (log_ != ARM_LOG_NONE) { - exidx_->set_log(log_); - exidx_->set_log_indent(0); - exidx_->set_log_skip_execution(false); - } - data_ = exidx_->data(); - exidx_->set_cfa(0x10000); - } - - void SetUp() override { - if (GetParam() == "no_logging") { - log_ = ARM_LOG_NONE; - } else if (GetParam() == "register_logging") { - log_ = ARM_LOG_BY_REG; - } else { - log_ = ARM_LOG_FULL; - } - elf_memory_.Clear(); - process_memory_.Clear(); - ResetExidx(); - } - - void ResetExidx() { - ResetLogs(); - Init(); - } - - std::unique_ptr exidx_; - std::unique_ptr regs_arm_; - std::deque* data_; - - MemoryFake elf_memory_; - MemoryFake process_memory_; - ArmLogType log_; -}; - -TEST_P(ArmExidxDecodeTest, vsp_incr) { - // 00xxxxxx: vsp = vsp + (xxxxxx << 2) + 4 - data_->push_back(0x00); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind vsp = vsp + 4\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ("4 unwind cfa = r13 + 4\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10004U, exidx_->cfa()); - - ResetExidx(); - data_->clear(); - data_->push_back(0x01); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind vsp = vsp + 8\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ("4 unwind cfa = r13 + 8\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10008U, exidx_->cfa()); - - ResetExidx(); - data_->clear(); - data_->push_back(0x3f); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind vsp = vsp + 256\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ("4 unwind cfa = r13 + 256\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10100U, exidx_->cfa()); -} - -TEST_P(ArmExidxDecodeTest, vsp_decr) { - // 01xxxxxx: vsp = vsp - (xxxxxx << 2) + 4 - data_->push_back(0x40); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind vsp = vsp - 4\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ("4 unwind cfa = r13 - 4\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0xfffcU, exidx_->cfa()); - - ResetExidx(); - data_->clear(); - data_->push_back(0x41); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind vsp = vsp - 8\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ("4 unwind cfa = r13 - 8\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0xfff8U, exidx_->cfa()); - - ResetExidx(); - data_->clear(); - data_->push_back(0x7f); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind vsp = vsp - 256\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ("4 unwind cfa = r13 - 256\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0xff00U, exidx_->cfa()); -} - -TEST_P(ArmExidxDecodeTest, refuse_unwind) { - // 10000000 00000000: Refuse to unwind - data_->push_back(0x80); - data_->push_back(0x00); - ASSERT_FALSE(exidx_->Decode()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Refuse to unwind\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(ARM_STATUS_NO_UNWIND, exidx_->status()); -} - -TEST_P(ArmExidxDecodeTest, pop_up_to_12) { - // 1000iiii iiiiiiii: Pop up to 12 integer registers - data_->push_back(0x88); - data_->push_back(0x00); - process_memory_.SetData32(0x10000, 0x10); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_TRUE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {r15}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ( - "4 unwind cfa = r13 + 4\n" - "4 unwind r15 = [cfa - 4]\n", - GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10004U, exidx_->cfa()); - ASSERT_EQ(0x10U, (*exidx_->regs())[15]); - - ResetExidx(); - data_->push_back(0x8f); - data_->push_back(0xff); - for (size_t i = 0; i < 12; i++) { - process_memory_.SetData32(0x10000 + i * 4, i + 0x20); - } - exidx_->set_pc_set(false); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_TRUE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15}\n", - GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ( - "4 unwind cfa = r13 + 48\n" - "4 unwind r4 = [cfa - 48]\n" - "4 unwind r5 = [cfa - 44]\n" - "4 unwind r6 = [cfa - 40]\n" - "4 unwind r7 = [cfa - 36]\n" - "4 unwind r8 = [cfa - 32]\n" - "4 unwind r9 = [cfa - 28]\n" - "4 unwind r10 = [cfa - 24]\n" - "4 unwind r11 = [cfa - 20]\n" - "4 unwind r12 = [cfa - 16]\n" - "4 unwind r13 = [cfa - 12]\n" - "4 unwind r14 = [cfa - 8]\n" - "4 unwind r15 = [cfa - 4]\n", - GetFakeLogPrint()); - break; - } - // Popping r13 results in a modified cfa. - ASSERT_EQ(0x29U, exidx_->cfa()); - - ASSERT_EQ(0x20U, (*exidx_->regs())[4]); - ASSERT_EQ(0x21U, (*exidx_->regs())[5]); - ASSERT_EQ(0x22U, (*exidx_->regs())[6]); - ASSERT_EQ(0x23U, (*exidx_->regs())[7]); - ASSERT_EQ(0x24U, (*exidx_->regs())[8]); - ASSERT_EQ(0x25U, (*exidx_->regs())[9]); - ASSERT_EQ(0x26U, (*exidx_->regs())[10]); - ASSERT_EQ(0x27U, (*exidx_->regs())[11]); - ASSERT_EQ(0x28U, (*exidx_->regs())[12]); - ASSERT_EQ(0x29U, (*exidx_->regs())[13]); - ASSERT_EQ(0x2aU, (*exidx_->regs())[14]); - ASSERT_EQ(0x2bU, (*exidx_->regs())[15]); - - ResetExidx(); - exidx_->set_cfa(0x10034); - data_->push_back(0x81); - data_->push_back(0x28); - process_memory_.SetData32(0x10034, 0x11); - process_memory_.SetData32(0x10038, 0x22); - process_memory_.SetData32(0x1003c, 0x33); - exidx_->set_pc_set(false); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {r7, r9, r12}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ( - "4 unwind cfa = r13 + 12\n" - "4 unwind r7 = [cfa - 12]\n" - "4 unwind r9 = [cfa - 8]\n" - "4 unwind r12 = [cfa - 4]\n", - GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10040U, exidx_->cfa()); - ASSERT_EQ(0x11U, (*exidx_->regs())[7]); - ASSERT_EQ(0x22U, (*exidx_->regs())[9]); - ASSERT_EQ(0x33U, (*exidx_->regs())[12]); -} - -TEST_P(ArmExidxDecodeTest, set_vsp_from_register) { - // 1001nnnn: Set vsp = r[nnnn] (nnnn != 13, 15) - exidx_->set_cfa(0x100); - for (size_t i = 0; i < 15; i++) { - (*regs_arm_)[i] = i + 1; - } - - data_->push_back(0x90); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind vsp = r0\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ("4 unwind cfa = r0\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(1U, exidx_->cfa()); - - ResetExidx(); - exidx_->set_cfa(0x100); - for (size_t i = 0; i < 15; i++) { - (*regs_arm_)[i] = i + 1; - } - data_->push_back(0x93); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind vsp = r3\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ("4 unwind cfa = r3\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(4U, exidx_->cfa()); - - ResetExidx(); - exidx_->set_cfa(0x100); - for (size_t i = 0; i < 15; i++) { - (*regs_arm_)[i] = i + 1; - } - data_->push_back(0x9e); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind vsp = r14\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ("4 unwind cfa = r14\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(15U, exidx_->cfa()); -} - -TEST_P(ArmExidxDecodeTest, reserved_prefix) { - // 10011101: Reserved as prefix for ARM register to register moves - data_->push_back(0x9d); - ASSERT_FALSE(exidx_->Decode()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind [Reserved]\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(ARM_STATUS_RESERVED, exidx_->status()); - - // 10011111: Reserved as prefix for Intel Wireless MMX register to register moves - ResetExidx(); - data_->push_back(0x9f); - ASSERT_FALSE(exidx_->Decode()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind [Reserved]\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(ARM_STATUS_RESERVED, exidx_->status()); -} - -TEST_P(ArmExidxDecodeTest, pop_registers) { - // 10100nnn: Pop r4-r[4+nnn] - data_->push_back(0xa0); - process_memory_.SetData32(0x10000, 0x14); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {r4}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ( - "4 unwind cfa = r13 + 4\n" - "4 unwind r4 = [cfa - 4]\n", - GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10004U, exidx_->cfa()); - ASSERT_EQ(0x14U, (*exidx_->regs())[4]); - - ResetExidx(); - data_->push_back(0xa3); - process_memory_.SetData32(0x10000, 0x20); - process_memory_.SetData32(0x10004, 0x30); - process_memory_.SetData32(0x10008, 0x40); - process_memory_.SetData32(0x1000c, 0x50); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {r4-r7}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ( - "4 unwind cfa = r13 + 16\n" - "4 unwind r4 = [cfa - 16]\n" - "4 unwind r5 = [cfa - 12]\n" - "4 unwind r6 = [cfa - 8]\n" - "4 unwind r7 = [cfa - 4]\n", - GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10010U, exidx_->cfa()); - ASSERT_EQ(0x20U, (*exidx_->regs())[4]); - ASSERT_EQ(0x30U, (*exidx_->regs())[5]); - ASSERT_EQ(0x40U, (*exidx_->regs())[6]); - ASSERT_EQ(0x50U, (*exidx_->regs())[7]); - - ResetExidx(); - data_->push_back(0xa7); - process_memory_.SetData32(0x10000, 0x41); - process_memory_.SetData32(0x10004, 0x51); - process_memory_.SetData32(0x10008, 0x61); - process_memory_.SetData32(0x1000c, 0x71); - process_memory_.SetData32(0x10010, 0x81); - process_memory_.SetData32(0x10014, 0x91); - process_memory_.SetData32(0x10018, 0xa1); - process_memory_.SetData32(0x1001c, 0xb1); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {r4-r11}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ( - "4 unwind cfa = r13 + 32\n" - "4 unwind r4 = [cfa - 32]\n" - "4 unwind r5 = [cfa - 28]\n" - "4 unwind r6 = [cfa - 24]\n" - "4 unwind r7 = [cfa - 20]\n" - "4 unwind r8 = [cfa - 16]\n" - "4 unwind r9 = [cfa - 12]\n" - "4 unwind r10 = [cfa - 8]\n" - "4 unwind r11 = [cfa - 4]\n", - GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10020U, exidx_->cfa()); - ASSERT_EQ(0x41U, (*exidx_->regs())[4]); - ASSERT_EQ(0x51U, (*exidx_->regs())[5]); - ASSERT_EQ(0x61U, (*exidx_->regs())[6]); - ASSERT_EQ(0x71U, (*exidx_->regs())[7]); - ASSERT_EQ(0x81U, (*exidx_->regs())[8]); - ASSERT_EQ(0x91U, (*exidx_->regs())[9]); - ASSERT_EQ(0xa1U, (*exidx_->regs())[10]); - ASSERT_EQ(0xb1U, (*exidx_->regs())[11]); -} - -TEST_P(ArmExidxDecodeTest, pop_registers_with_r14) { - // 10101nnn: Pop r4-r[4+nnn], r14 - data_->push_back(0xa8); - process_memory_.SetData32(0x10000, 0x12); - process_memory_.SetData32(0x10004, 0x22); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {r4, r14}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ( - "4 unwind cfa = r13 + 8\n" - "4 unwind r4 = [cfa - 8]\n" - "4 unwind r14 = [cfa - 4]\n", - GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10008U, exidx_->cfa()); - ASSERT_EQ(0x12U, (*exidx_->regs())[4]); - ASSERT_EQ(0x22U, (*exidx_->regs())[14]); - - ResetExidx(); - data_->push_back(0xab); - process_memory_.SetData32(0x10000, 0x1); - process_memory_.SetData32(0x10004, 0x2); - process_memory_.SetData32(0x10008, 0x3); - process_memory_.SetData32(0x1000c, 0x4); - process_memory_.SetData32(0x10010, 0x5); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {r4-r7, r14}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ( - "4 unwind cfa = r13 + 20\n" - "4 unwind r4 = [cfa - 20]\n" - "4 unwind r5 = [cfa - 16]\n" - "4 unwind r6 = [cfa - 12]\n" - "4 unwind r7 = [cfa - 8]\n" - "4 unwind r14 = [cfa - 4]\n", - GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10014U, exidx_->cfa()); - ASSERT_EQ(0x1U, (*exidx_->regs())[4]); - ASSERT_EQ(0x2U, (*exidx_->regs())[5]); - ASSERT_EQ(0x3U, (*exidx_->regs())[6]); - ASSERT_EQ(0x4U, (*exidx_->regs())[7]); - ASSERT_EQ(0x5U, (*exidx_->regs())[14]); - - ResetExidx(); - data_->push_back(0xaf); - process_memory_.SetData32(0x10000, 0x1a); - process_memory_.SetData32(0x10004, 0x2a); - process_memory_.SetData32(0x10008, 0x3a); - process_memory_.SetData32(0x1000c, 0x4a); - process_memory_.SetData32(0x10010, 0x5a); - process_memory_.SetData32(0x10014, 0x6a); - process_memory_.SetData32(0x10018, 0x7a); - process_memory_.SetData32(0x1001c, 0x8a); - process_memory_.SetData32(0x10020, 0x9a); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {r4-r11, r14}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ( - "4 unwind cfa = r13 + 36\n" - "4 unwind r4 = [cfa - 36]\n" - "4 unwind r5 = [cfa - 32]\n" - "4 unwind r6 = [cfa - 28]\n" - "4 unwind r7 = [cfa - 24]\n" - "4 unwind r8 = [cfa - 20]\n" - "4 unwind r9 = [cfa - 16]\n" - "4 unwind r10 = [cfa - 12]\n" - "4 unwind r11 = [cfa - 8]\n" - "4 unwind r14 = [cfa - 4]\n", - GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10024U, exidx_->cfa()); - ASSERT_EQ(0x1aU, (*exidx_->regs())[4]); - ASSERT_EQ(0x2aU, (*exidx_->regs())[5]); - ASSERT_EQ(0x3aU, (*exidx_->regs())[6]); - ASSERT_EQ(0x4aU, (*exidx_->regs())[7]); - ASSERT_EQ(0x5aU, (*exidx_->regs())[8]); - ASSERT_EQ(0x6aU, (*exidx_->regs())[9]); - ASSERT_EQ(0x7aU, (*exidx_->regs())[10]); - ASSERT_EQ(0x8aU, (*exidx_->regs())[11]); - ASSERT_EQ(0x9aU, (*exidx_->regs())[14]); -} - -TEST_P(ArmExidxDecodeTest, finish) { - // 10110000: Finish - data_->push_back(0xb0); - ASSERT_FALSE(exidx_->Decode()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind finish\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ("4 unwind cfa = r13\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10000U, exidx_->cfa()); - ASSERT_EQ(ARM_STATUS_FINISH, exidx_->status()); -} - -TEST_P(ArmExidxDecodeTest, spare) { - // 10110001 00000000: Spare - data_->push_back(0xb1); - data_->push_back(0x00); - ASSERT_FALSE(exidx_->Decode()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10000U, exidx_->cfa()); - ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status()); - - // 10110001 xxxxyyyy: Spare (xxxx != 0000) - for (size_t x = 1; x < 16; x++) { - for (size_t y = 0; y < 16; y++) { - ResetExidx(); - data_->push_back(0xb1); - data_->push_back((x << 4) | y); - ASSERT_FALSE(exidx_->Decode()) << "x, y = " << x << ", " << y; - ASSERT_EQ("", GetFakeLogBuf()) << "x, y = " << x << ", " << y; - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "x, y = " << x << ", " << y; - break; - } - ASSERT_EQ(0x10000U, exidx_->cfa()) << "x, y = " << x << ", " << y; - ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status()); - } - } - - // 101101nn: Spare - for (size_t n = 0; n < 4; n++) { - ResetExidx(); - data_->push_back(0xb4 | n); - ASSERT_FALSE(exidx_->Decode()) << "n = " << n; - ASSERT_EQ("", GetFakeLogBuf()) << "n = " << n; - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "n = " << n; - break; - } - ASSERT_EQ(0x10000U, exidx_->cfa()) << "n = " << n; - ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status()); - } - - // 11000111 00000000: Spare - ResetExidx(); - data_->push_back(0xc7); - data_->push_back(0x00); - ASSERT_FALSE(exidx_->Decode()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10000U, exidx_->cfa()); - ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status()); - - // 11000111 xxxxyyyy: Spare (xxxx != 0000) - for (size_t x = 1; x < 16; x++) { - for (size_t y = 0; y < 16; y++) { - ResetExidx(); - data_->push_back(0xc7); - data_->push_back(0x10); - ASSERT_FALSE(exidx_->Decode()) << "x, y = " << x << ", " << y; - ASSERT_EQ("", GetFakeLogBuf()) << "x, y = " << x << ", " << y; - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "x, y = " << x << ", " << y; - break; - } - ASSERT_EQ(0x10000U, exidx_->cfa()) << "x, y = " << x << ", " << y; - ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status()); - } - } - - // 11001yyy: Spare (yyy != 000, 001) - for (size_t y = 2; y < 8; y++) { - ResetExidx(); - data_->push_back(0xc8 | y); - ASSERT_FALSE(exidx_->Decode()) << "y = " << y; - ASSERT_EQ("", GetFakeLogBuf()) << "y = " << y; - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "y = " << y; - break; - } - ASSERT_EQ(0x10000U, exidx_->cfa()) << "y = " << y; - ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status()); - } - - // 11xxxyyy: Spare (xxx != 000, 001, 010) - for (size_t x = 3; x < 8; x++) { - for (size_t y = 0; y < 8; y++) { - ResetExidx(); - data_->push_back(0xc0 | (x << 3) | y); - ASSERT_FALSE(exidx_->Decode()) << "x, y = " << x << ", " << y; - ASSERT_EQ("", GetFakeLogBuf()) << "x, y = " << x << ", " << y; - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "x, y = " << x << ", " << y; - break; - } - ASSERT_EQ(0x10000U, exidx_->cfa()) << "x, y = " << x << ", " << y; - ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status()); - } - } -} - -TEST_P(ArmExidxDecodeTest, pop_registers_under_mask) { - // 10110001 0000iiii: Pop integer registers {r0, r1, r2, r3} - data_->push_back(0xb1); - data_->push_back(0x01); - process_memory_.SetData32(0x10000, 0x45); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {r0}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ( - "4 unwind cfa = r13 + 4\n" - "4 unwind r0 = [cfa - 4]\n", - GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10004U, exidx_->cfa()); - ASSERT_EQ(0x45U, (*exidx_->regs())[0]); - - ResetExidx(); - data_->push_back(0xb1); - data_->push_back(0x0a); - process_memory_.SetData32(0x10000, 0x23); - process_memory_.SetData32(0x10004, 0x24); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {r1, r3}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ( - "4 unwind cfa = r13 + 8\n" - "4 unwind r1 = [cfa - 8]\n" - "4 unwind r3 = [cfa - 4]\n", - GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10008U, exidx_->cfa()); - ASSERT_EQ(0x23U, (*exidx_->regs())[1]); - ASSERT_EQ(0x24U, (*exidx_->regs())[3]); - - ResetExidx(); - data_->push_back(0xb1); - data_->push_back(0x0f); - process_memory_.SetData32(0x10000, 0x65); - process_memory_.SetData32(0x10004, 0x54); - process_memory_.SetData32(0x10008, 0x43); - process_memory_.SetData32(0x1000c, 0x32); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {r0, r1, r2, r3}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ( - "4 unwind cfa = r13 + 16\n" - "4 unwind r0 = [cfa - 16]\n" - "4 unwind r1 = [cfa - 12]\n" - "4 unwind r2 = [cfa - 8]\n" - "4 unwind r3 = [cfa - 4]\n", - GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10010U, exidx_->cfa()); - ASSERT_EQ(0x65U, (*exidx_->regs())[0]); - ASSERT_EQ(0x54U, (*exidx_->regs())[1]); - ASSERT_EQ(0x43U, (*exidx_->regs())[2]); - ASSERT_EQ(0x32U, (*exidx_->regs())[3]); -} - -TEST_P(ArmExidxDecodeTest, vsp_large_incr) { - // 10110010 uleb128: vsp = vsp + 0x204 + (uleb128 << 2) - data_->push_back(0xb2); - data_->push_back(0x7f); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind vsp = vsp + 1024\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ("4 unwind cfa = r13 + 1024\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10400U, exidx_->cfa()); - - ResetExidx(); - data_->push_back(0xb2); - data_->push_back(0xff); - data_->push_back(0x02); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind vsp = vsp + 2048\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ("4 unwind cfa = r13 + 2048\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10800U, exidx_->cfa()); - - ResetExidx(); - data_->push_back(0xb2); - data_->push_back(0xff); - data_->push_back(0x82); - data_->push_back(0x30); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind vsp = vsp + 3147776\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ("4 unwind cfa = r13 + 3147776\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x310800U, exidx_->cfa()); -} - -TEST_P(ArmExidxDecodeTest, pop_vfp_fstmfdx) { - // 10110011 sssscccc: Pop VFP double precision registers D[ssss]-D[ssss+cccc] by FSTMFDX - data_->push_back(0xb3); - data_->push_back(0x00); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {d0}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x1000cU, exidx_->cfa()); - - ResetExidx(); - data_->push_back(0xb3); - data_->push_back(0x48); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {d4-d12}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x1004cU, exidx_->cfa()); -} - -TEST_P(ArmExidxDecodeTest, pop_vfp8_fstmfdx) { - // 10111nnn: Pop VFP double precision registers D[8]-D[8+nnn] by FSTMFDX - data_->push_back(0xb8); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {d8}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x1000cU, exidx_->cfa()); - - ResetExidx(); - data_->push_back(0xbb); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {d8-d11}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10024U, exidx_->cfa()); - - ResetExidx(); - data_->push_back(0xbf); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {d8-d15}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10044U, exidx_->cfa()); -} - -TEST_P(ArmExidxDecodeTest, pop_mmx_wr10) { - // 11000nnn: Intel Wireless MMX pop wR[10]-wR[10+nnn] (nnn != 6, 7) - data_->push_back(0xc0); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {wR10}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Unsupported wRX register display\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10008U, exidx_->cfa()); - - ResetExidx(); - data_->push_back(0xc2); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {wR10-wR12}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Unsupported wRX register display\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10018U, exidx_->cfa()); - - ResetExidx(); - data_->push_back(0xc5); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {wR10-wR15}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Unsupported wRX register display\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10030U, exidx_->cfa()); -} - -TEST_P(ArmExidxDecodeTest, pop_mmx_wr) { - // 11000110 sssscccc: Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc] - data_->push_back(0xc6); - data_->push_back(0x00); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {wR0}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Unsupported wRX register display\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10008U, exidx_->cfa()); - - ResetExidx(); - data_->push_back(0xc6); - data_->push_back(0x25); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {wR2-wR7}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Unsupported wRX register display\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10030U, exidx_->cfa()); - - ResetExidx(); - data_->push_back(0xc6); - data_->push_back(0xff); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {wR15-wR30}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Unsupported wRX register display\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10080U, exidx_->cfa()); -} - -TEST_P(ArmExidxDecodeTest, pop_mmx_wcgr) { - // 11000111 0000iiii: Intel Wireless MMX pop wCGR registes {wCGR0,1,2,3} - data_->push_back(0xc7); - data_->push_back(0x01); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {wCGR0}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Unsupported wCGR register display\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10004U, exidx_->cfa()); - - ResetExidx(); - data_->push_back(0xc7); - data_->push_back(0x0a); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {wCGR1, wCGR3}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Unsupported wCGR register display\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10008U, exidx_->cfa()); - - ResetExidx(); - data_->push_back(0xc7); - data_->push_back(0x0f); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {wCGR0, wCGR1, wCGR2, wCGR3}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Unsupported wCGR register display\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10010U, exidx_->cfa()); -} - -TEST_P(ArmExidxDecodeTest, pop_vfp16_vpush) { - // 11001000 sssscccc: Pop VFP double precision registers d[16+ssss]-D[16+ssss+cccc] by VPUSH - data_->push_back(0xc8); - data_->push_back(0x00); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {d16}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10008U, exidx_->cfa()); - - ResetExidx(); - data_->push_back(0xc8); - data_->push_back(0x14); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {d17-d21}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10028U, exidx_->cfa()); - - ResetExidx(); - data_->push_back(0xc8); - data_->push_back(0xff); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {d31-d46}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10080U, exidx_->cfa()); -} - -TEST_P(ArmExidxDecodeTest, pop_vfp_vpush) { - // 11001001 sssscccc: Pop VFP double precision registers d[ssss]-D[ssss+cccc] by VPUSH - data_->push_back(0xc9); - data_->push_back(0x00); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {d0}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10008U, exidx_->cfa()); - - ResetExidx(); - data_->push_back(0xc9); - data_->push_back(0x23); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {d2-d5}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10020U, exidx_->cfa()); - - ResetExidx(); - data_->push_back(0xc9); - data_->push_back(0xff); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {d15-d30}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10080U, exidx_->cfa()); -} - -TEST_P(ArmExidxDecodeTest, pop_vfp8_vpush) { - // 11010nnn: Pop VFP double precision registers D[8]-D[8+nnn] by VPUSH - data_->push_back(0xd0); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {d8}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10008U, exidx_->cfa()); - - ResetExidx(); - data_->push_back(0xd2); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {d8-d10}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10018U, exidx_->cfa()); - - ResetExidx(); - data_->push_back(0xd7); - ASSERT_TRUE(exidx_->Decode()); - ASSERT_FALSE(exidx_->pc_set()); - ASSERT_EQ("", GetFakeLogBuf()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ("4 unwind pop {d8-d15}\n", GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10040U, exidx_->cfa()); -} - -TEST_P(ArmExidxDecodeTest, expect_truncated) { - // This test verifies that any op that requires extra ops will - // fail if the data is not present. - data_->push_back(0x80); - ASSERT_FALSE(exidx_->Decode()); - ASSERT_EQ(ARM_STATUS_TRUNCATED, exidx_->status()); - - data_->clear(); - data_->push_back(0xb1); - ASSERT_FALSE(exidx_->Decode()); - ASSERT_EQ(ARM_STATUS_TRUNCATED, exidx_->status()); - - data_->clear(); - data_->push_back(0xb2); - ASSERT_FALSE(exidx_->Decode()); - ASSERT_EQ(ARM_STATUS_TRUNCATED, exidx_->status()); - - data_->clear(); - data_->push_back(0xb3); - ASSERT_FALSE(exidx_->Decode()); - ASSERT_EQ(ARM_STATUS_TRUNCATED, exidx_->status()); - - data_->clear(); - data_->push_back(0xc6); - ASSERT_FALSE(exidx_->Decode()); - ASSERT_EQ(ARM_STATUS_TRUNCATED, exidx_->status()); - - data_->clear(); - data_->push_back(0xc7); - ASSERT_FALSE(exidx_->Decode()); - ASSERT_EQ(ARM_STATUS_TRUNCATED, exidx_->status()); - - data_->clear(); - data_->push_back(0xc8); - ASSERT_FALSE(exidx_->Decode()); - ASSERT_EQ(ARM_STATUS_TRUNCATED, exidx_->status()); - - data_->clear(); - data_->push_back(0xc9); - ASSERT_FALSE(exidx_->Decode()); - ASSERT_EQ(ARM_STATUS_TRUNCATED, exidx_->status()); -} - -TEST_P(ArmExidxDecodeTest, verify_no_truncated) { - // This test verifies that no pattern results in a crash or truncation. - MemoryFakeAlwaysReadZero memory_zero; - Init(&memory_zero); - - for (size_t x = 0; x < 256; x++) { - if (x == 0xb2) { - // This opcode is followed by an uleb128, so just skip this one. - continue; - } - for (size_t y = 0; y < 256; y++) { - data_->clear(); - data_->push_back(x); - data_->push_back(y); - if (!exidx_->Decode()) { - ASSERT_NE(ARM_STATUS_TRUNCATED, exidx_->status()) - << "x y = 0x" << std::hex << x << " 0x" << y; - ASSERT_NE(ARM_STATUS_READ_FAILED, exidx_->status()) - << "x y = 0x" << std::hex << x << " 0x" << y; - } - } - } -} - -TEST_P(ArmExidxDecodeTest, eval_multiple_decodes) { - // vsp = vsp + 4 - data_->push_back(0x00); - // vsp = vsp + 12 - data_->push_back(0x02); - // Finish - data_->push_back(0xb0); - - ASSERT_TRUE(exidx_->Eval()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ( - "4 unwind vsp = vsp + 4\n" - "4 unwind vsp = vsp + 12\n" - "4 unwind finish\n", - GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ("4 unwind cfa = r13 + 16\n", GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10010U, exidx_->cfa()); - ASSERT_FALSE(exidx_->pc_set()); -} - -TEST_P(ArmExidxDecodeTest, eval_vsp_add_after_pop) { - // Pop {r15} - data_->push_back(0x88); - data_->push_back(0x00); - // vsp = vsp + 12 - data_->push_back(0x02); - // Finish - data_->push_back(0xb0); - process_memory_.SetData32(0x10000, 0x10); - - ASSERT_TRUE(exidx_->Eval()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ( - "4 unwind pop {r15}\n" - "4 unwind vsp = vsp + 12\n" - "4 unwind finish\n", - GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ( - "4 unwind cfa = r13 + 16\n" - "4 unwind r15 = [cfa - 16]\n", - GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10010U, exidx_->cfa()); - ASSERT_TRUE(exidx_->pc_set()); - ASSERT_EQ(0x10U, (*exidx_->regs())[15]); -} - -TEST_P(ArmExidxDecodeTest, eval_vsp_add_large_after_pop) { - // Pop {r15} - data_->push_back(0x88); - data_->push_back(0x00); - // vsp = vsp + 1024 - data_->push_back(0xb2); - data_->push_back(0x7f); - // Finish - data_->push_back(0xb0); - process_memory_.SetData32(0x10000, 0x10); - - ASSERT_TRUE(exidx_->Eval()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ( - "4 unwind pop {r15}\n" - "4 unwind vsp = vsp + 1024\n" - "4 unwind finish\n", - GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ( - "4 unwind cfa = r13 + 1028\n" - "4 unwind r15 = [cfa - 1028]\n", - GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10404U, exidx_->cfa()); - ASSERT_TRUE(exidx_->pc_set()); - ASSERT_EQ(0x10U, (*exidx_->regs())[15]); -} - -TEST_P(ArmExidxDecodeTest, eval_vsp_sub_after_pop) { - // Pop {r15} - data_->push_back(0x88); - data_->push_back(0x00); - // vsp = vsp - 4 - data_->push_back(0x41); - // Finish - data_->push_back(0xb0); - process_memory_.SetData32(0x10000, 0x10); - - ASSERT_TRUE(exidx_->Eval()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ( - "4 unwind pop {r15}\n" - "4 unwind vsp = vsp - 8\n" - "4 unwind finish\n", - GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ( - "4 unwind cfa = r13 - 4\n" - "4 unwind r15 = [cfa + 4]\n", - GetFakeLogPrint()); - break; - } - ASSERT_EQ(0xfffcU, exidx_->cfa()); - ASSERT_TRUE(exidx_->pc_set()); - ASSERT_EQ(0x10U, (*exidx_->regs())[15]); -} - -TEST_P(ArmExidxDecodeTest, eval_pc_set) { - // vsp = vsp + 4 - data_->push_back(0x00); - // vsp = vsp + 12 - data_->push_back(0x02); - // Pop {r15} - data_->push_back(0x88); - data_->push_back(0x00); - // vsp = vsp + 12 - data_->push_back(0x02); - // Finish - data_->push_back(0xb0); - - process_memory_.SetData32(0x10010, 0x10); - - ASSERT_TRUE(exidx_->Eval()); - switch (log_) { - case ARM_LOG_NONE: - ASSERT_EQ("", GetFakeLogPrint()); - break; - case ARM_LOG_FULL: - ASSERT_EQ( - "4 unwind vsp = vsp + 4\n" - "4 unwind vsp = vsp + 12\n" - "4 unwind pop {r15}\n" - "4 unwind vsp = vsp + 12\n" - "4 unwind finish\n", - GetFakeLogPrint()); - break; - case ARM_LOG_BY_REG: - exidx_->LogByReg(); - ASSERT_EQ( - "4 unwind cfa = r13 + 32\n" - "4 unwind r15 = [cfa - 16]\n", - GetFakeLogPrint()); - break; - } - ASSERT_EQ(0x10020U, exidx_->cfa()); - ASSERT_TRUE(exidx_->pc_set()); - ASSERT_EQ(0x10U, (*exidx_->regs())[15]); -} - -INSTANTIATE_TEST_SUITE_P(Unwindstack, ArmExidxDecodeTest, - ::testing::Values("logging", "register_logging", "no_logging")); - -} // namespace unwindstack diff --git a/libunwindstack/tests/ArmExidxExtractTest.cpp b/libunwindstack/tests/ArmExidxExtractTest.cpp deleted file mode 100644 index 79c799c3a..000000000 --- a/libunwindstack/tests/ArmExidxExtractTest.cpp +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (C) 2016 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 "ArmExidx.h" - -#include "LogFake.h" -#include "MemoryFake.h" - -namespace unwindstack { - -class ArmExidxExtractTest : public ::testing::Test { - protected: - void SetUp() override { - ResetLogs(); - elf_memory_.Clear(); - exidx_ = new ArmExidx(nullptr, &elf_memory_, nullptr); - data_ = exidx_->data(); - data_->clear(); - } - - void TearDown() override { - delete exidx_; - } - - ArmExidx* exidx_ = nullptr; - std::deque* data_; - MemoryFake elf_memory_; -}; - -TEST_F(ArmExidxExtractTest, bad_alignment) { - ASSERT_FALSE(exidx_->ExtractEntryData(0x1001)); - ASSERT_EQ(ARM_STATUS_INVALID_ALIGNMENT, exidx_->status()); - ASSERT_TRUE(data_->empty()); -} - -TEST_F(ArmExidxExtractTest, cant_unwind) { - elf_memory_.SetData32(0x1000, 0x7fff2340); - elf_memory_.SetData32(0x1004, 1); - ASSERT_FALSE(exidx_->ExtractEntryData(0x1000)); - ASSERT_EQ(ARM_STATUS_NO_UNWIND, exidx_->status()); - ASSERT_TRUE(data_->empty()); -} - -TEST_F(ArmExidxExtractTest, compact) { - elf_memory_.SetData32(0x4000, 0x7ffa3000); - elf_memory_.SetData32(0x4004, 0x80a8b0b0); - ASSERT_TRUE(exidx_->ExtractEntryData(0x4000)); - ASSERT_EQ(3U, data_->size()); - ASSERT_EQ(0xa8, data_->at(0)); - ASSERT_EQ(0xb0, data_->at(1)); - ASSERT_EQ(0xb0, data_->at(2)); - - // Missing finish gets added. - elf_memory_.Clear(); - elf_memory_.SetData32(0x534, 0x7ffa3000); - elf_memory_.SetData32(0x538, 0x80a1a2a3); - ASSERT_TRUE(exidx_->ExtractEntryData(0x534)); - ASSERT_EQ(4U, data_->size()); - ASSERT_EQ(0xa1, data_->at(0)); - ASSERT_EQ(0xa2, data_->at(1)); - ASSERT_EQ(0xa3, data_->at(2)); - ASSERT_EQ(0xb0, data_->at(3)); -} - -TEST_F(ArmExidxExtractTest, compact_non_zero_personality) { - elf_memory_.SetData32(0x4000, 0x7ffa3000); - - uint32_t compact_value = 0x80a8b0b0; - for (size_t i = 1; i < 16; i++) { - elf_memory_.SetData32(0x4004, compact_value | (i << 24)); - ASSERT_FALSE(exidx_->ExtractEntryData(0x4000)); - ASSERT_EQ(ARM_STATUS_INVALID_PERSONALITY, exidx_->status()); - } -} - -TEST_F(ArmExidxExtractTest, second_read_compact_personality_1_2) { - elf_memory_.SetData32(0x5000, 0x1234); - elf_memory_.SetData32(0x5004, 0x00001230); - elf_memory_.SetData32(0x6234, 0x8100f3b0); - ASSERT_TRUE(exidx_->ExtractEntryData(0x5000)); - ASSERT_EQ(2U, data_->size()); - ASSERT_EQ(0xf3, data_->at(0)); - ASSERT_EQ(0xb0, data_->at(1)); - - elf_memory_.Clear(); - elf_memory_.SetData32(0x5000, 0x1234); - elf_memory_.SetData32(0x5004, 0x00001230); - elf_memory_.SetData32(0x6234, 0x8200f3f4); - ASSERT_TRUE(exidx_->ExtractEntryData(0x5000)); - ASSERT_EQ(3U, data_->size()); - ASSERT_EQ(0xf3, data_->at(0)); - ASSERT_EQ(0xf4, data_->at(1)); - ASSERT_EQ(0xb0, data_->at(2)); - - elf_memory_.Clear(); - elf_memory_.SetData32(0x5000, 0x1234); - elf_memory_.SetData32(0x5004, 0x00001230); - elf_memory_.SetData32(0x6234, 0x8201f3f4); - elf_memory_.SetData32(0x6238, 0x102030b0); - ASSERT_TRUE(exidx_->ExtractEntryData(0x5000)); - ASSERT_EQ(6U, data_->size()); - ASSERT_EQ(0xf3, data_->at(0)); - ASSERT_EQ(0xf4, data_->at(1)); - ASSERT_EQ(0x10, data_->at(2)); - ASSERT_EQ(0x20, data_->at(3)); - ASSERT_EQ(0x30, data_->at(4)); - ASSERT_EQ(0xb0, data_->at(5)); - - elf_memory_.Clear(); - elf_memory_.SetData32(0x5000, 0x1234); - elf_memory_.SetData32(0x5004, 0x00001230); - elf_memory_.SetData32(0x6234, 0x8103f3f4); - elf_memory_.SetData32(0x6238, 0x10203040); - elf_memory_.SetData32(0x623c, 0x50607080); - elf_memory_.SetData32(0x6240, 0x90a0c0d0); - ASSERT_TRUE(exidx_->ExtractEntryData(0x5000)); - ASSERT_EQ(15U, data_->size()); - ASSERT_EQ(0xf3, data_->at(0)); - ASSERT_EQ(0xf4, data_->at(1)); - ASSERT_EQ(0x10, data_->at(2)); - ASSERT_EQ(0x20, data_->at(3)); - ASSERT_EQ(0x30, data_->at(4)); - ASSERT_EQ(0x40, data_->at(5)); - ASSERT_EQ(0x50, data_->at(6)); - ASSERT_EQ(0x60, data_->at(7)); - ASSERT_EQ(0x70, data_->at(8)); - ASSERT_EQ(0x80, data_->at(9)); - ASSERT_EQ(0x90, data_->at(10)); - ASSERT_EQ(0xa0, data_->at(11)); - ASSERT_EQ(0xc0, data_->at(12)); - ASSERT_EQ(0xd0, data_->at(13)); - ASSERT_EQ(0xb0, data_->at(14)); -} - -TEST_F(ArmExidxExtractTest, second_read_compact_personality_illegal) { - elf_memory_.SetData32(0x5000, 0x7ffa1e48); - elf_memory_.SetData32(0x5004, 0x1230); - elf_memory_.SetData32(0x6234, 0x832132b0); - ASSERT_FALSE(exidx_->ExtractEntryData(0x5000)); - ASSERT_EQ(ARM_STATUS_INVALID_PERSONALITY, exidx_->status()); - - elf_memory_.Clear(); - elf_memory_.SetData32(0x5000, 0x7ffa1e48); - elf_memory_.SetData32(0x5004, 0x1230); - elf_memory_.SetData32(0x6234, 0x842132b0); - ASSERT_FALSE(exidx_->ExtractEntryData(0x5000)); - ASSERT_EQ(ARM_STATUS_INVALID_PERSONALITY, exidx_->status()); -} - -TEST_F(ArmExidxExtractTest, second_read_offset_is_negative) { - elf_memory_.SetData32(0x5000, 0x7ffa1e48); - elf_memory_.SetData32(0x5004, 0x7fffb1e0); - elf_memory_.SetData32(0x1e4, 0x842132b0); - ASSERT_FALSE(exidx_->ExtractEntryData(0x5000)); - ASSERT_EQ(ARM_STATUS_INVALID_PERSONALITY, exidx_->status()); -} - -TEST_F(ArmExidxExtractTest, second_read_not_compact) { - elf_memory_.SetData32(0x5000, 0x1234); - elf_memory_.SetData32(0x5004, 0x00001230); - elf_memory_.SetData32(0x6234, 0x1); - elf_memory_.SetData32(0x6238, 0x001122b0); - ASSERT_TRUE(exidx_->ExtractEntryData(0x5000)); - ASSERT_EQ(3U, data_->size()); - ASSERT_EQ(0x11, data_->at(0)); - ASSERT_EQ(0x22, data_->at(1)); - ASSERT_EQ(0xb0, data_->at(2)); - - elf_memory_.Clear(); - elf_memory_.SetData32(0x5000, 0x1234); - elf_memory_.SetData32(0x5004, 0x00001230); - elf_memory_.SetData32(0x6234, 0x2); - elf_memory_.SetData32(0x6238, 0x00112233); - ASSERT_TRUE(exidx_->ExtractEntryData(0x5000)); - ASSERT_EQ(4U, data_->size()); - ASSERT_EQ(0x11, data_->at(0)); - ASSERT_EQ(0x22, data_->at(1)); - ASSERT_EQ(0x33, data_->at(2)); - ASSERT_EQ(0xb0, data_->at(3)); - - elf_memory_.Clear(); - elf_memory_.SetData32(0x5000, 0x1234); - elf_memory_.SetData32(0x5004, 0x00001230); - elf_memory_.SetData32(0x6234, 0x3); - elf_memory_.SetData32(0x6238, 0x01112233); - elf_memory_.SetData32(0x623c, 0x445566b0); - ASSERT_TRUE(exidx_->ExtractEntryData(0x5000)); - ASSERT_EQ(7U, data_->size()); - ASSERT_EQ(0x11, data_->at(0)); - ASSERT_EQ(0x22, data_->at(1)); - ASSERT_EQ(0x33, data_->at(2)); - ASSERT_EQ(0x44, data_->at(3)); - ASSERT_EQ(0x55, data_->at(4)); - ASSERT_EQ(0x66, data_->at(5)); - ASSERT_EQ(0xb0, data_->at(6)); - - elf_memory_.Clear(); - elf_memory_.SetData32(0x5000, 0x1234); - elf_memory_.SetData32(0x5004, 0x00001230); - elf_memory_.SetData32(0x6234, 0x3); - elf_memory_.SetData32(0x6238, 0x05112233); - elf_memory_.SetData32(0x623c, 0x01020304); - elf_memory_.SetData32(0x6240, 0x05060708); - elf_memory_.SetData32(0x6244, 0x090a0b0c); - elf_memory_.SetData32(0x6248, 0x0d0e0f10); - elf_memory_.SetData32(0x624c, 0x11121314); - ASSERT_TRUE(exidx_->ExtractEntryData(0x5000)); - ASSERT_EQ(24U, data_->size()); - ASSERT_EQ(0x11, data_->at(0)); - ASSERT_EQ(0x22, data_->at(1)); - ASSERT_EQ(0x33, data_->at(2)); - ASSERT_EQ(0x01, data_->at(3)); - ASSERT_EQ(0x02, data_->at(4)); - ASSERT_EQ(0x03, data_->at(5)); - ASSERT_EQ(0x04, data_->at(6)); - ASSERT_EQ(0x05, data_->at(7)); - ASSERT_EQ(0x06, data_->at(8)); - ASSERT_EQ(0x07, data_->at(9)); - ASSERT_EQ(0x08, data_->at(10)); - ASSERT_EQ(0x09, data_->at(11)); - ASSERT_EQ(0x0a, data_->at(12)); - ASSERT_EQ(0x0b, data_->at(13)); - ASSERT_EQ(0x0c, data_->at(14)); - ASSERT_EQ(0x0d, data_->at(15)); - ASSERT_EQ(0x0e, data_->at(16)); - ASSERT_EQ(0x0f, data_->at(17)); - ASSERT_EQ(0x10, data_->at(18)); - ASSERT_EQ(0x11, data_->at(19)); - ASSERT_EQ(0x12, data_->at(20)); - ASSERT_EQ(0x13, data_->at(21)); - ASSERT_EQ(0x14, data_->at(22)); - ASSERT_EQ(0xb0, data_->at(23)); -} - -TEST_F(ArmExidxExtractTest, read_failures) { - ASSERT_FALSE(exidx_->ExtractEntryData(0x5000)); - ASSERT_EQ(ARM_STATUS_READ_FAILED, exidx_->status()); - EXPECT_EQ(0x5004U, exidx_->status_address()); - - elf_memory_.SetData32(0x5000, 0x100); - ASSERT_FALSE(exidx_->ExtractEntryData(0x5000)); - ASSERT_EQ(ARM_STATUS_READ_FAILED, exidx_->status()); - EXPECT_EQ(0x5004U, exidx_->status_address()); - - elf_memory_.SetData32(0x5004, 0x100); - ASSERT_FALSE(exidx_->ExtractEntryData(0x5000)); - ASSERT_EQ(ARM_STATUS_READ_FAILED, exidx_->status()); - EXPECT_EQ(0x5104U, exidx_->status_address()); - - elf_memory_.SetData32(0x5104, 0x1); - ASSERT_FALSE(exidx_->ExtractEntryData(0x5000)); - ASSERT_EQ(ARM_STATUS_READ_FAILED, exidx_->status()); - EXPECT_EQ(0x5108U, exidx_->status_address()); - - elf_memory_.SetData32(0x5108, 0x01010203); - ASSERT_FALSE(exidx_->ExtractEntryData(0x5000)); - ASSERT_EQ(ARM_STATUS_READ_FAILED, exidx_->status()); - EXPECT_EQ(0x510cU, exidx_->status_address()); -} - -TEST_F(ArmExidxExtractTest, malformed) { - elf_memory_.SetData32(0x5000, 0x100); - elf_memory_.SetData32(0x5004, 0x100); - elf_memory_.SetData32(0x5104, 0x1); - elf_memory_.SetData32(0x5108, 0x06010203); - ASSERT_FALSE(exidx_->ExtractEntryData(0x5000)); - ASSERT_EQ(ARM_STATUS_MALFORMED, exidx_->status()); - - elf_memory_.Clear(); - elf_memory_.SetData32(0x5000, 0x100); - elf_memory_.SetData32(0x5004, 0x100); - elf_memory_.SetData32(0x5104, 0x1); - elf_memory_.SetData32(0x5108, 0x81060203); - ASSERT_FALSE(exidx_->ExtractEntryData(0x5000)); - ASSERT_EQ(ARM_STATUS_MALFORMED, exidx_->status()); -} - -TEST_F(ArmExidxExtractTest, cant_unwind_log) { - elf_memory_.SetData32(0x1000, 0x7fff2340); - elf_memory_.SetData32(0x1004, 1); - - exidx_->set_log(ARM_LOG_FULL); - exidx_->set_log_indent(0); - exidx_->set_log_skip_execution(false); - - ASSERT_FALSE(exidx_->ExtractEntryData(0x1000)); - ASSERT_EQ(ARM_STATUS_NO_UNWIND, exidx_->status()); - - ASSERT_EQ("4 unwind Raw Data: 0x00 0x00 0x00 0x01\n" - "4 unwind [cantunwind]\n", GetFakeLogPrint()); -} - -TEST_F(ArmExidxExtractTest, raw_data_compact) { - elf_memory_.SetData32(0x4000, 0x7ffa3000); - elf_memory_.SetData32(0x4004, 0x80a8b0b0); - - exidx_->set_log(ARM_LOG_FULL); - exidx_->set_log_indent(0); - exidx_->set_log_skip_execution(false); - - ASSERT_TRUE(exidx_->ExtractEntryData(0x4000)); - ASSERT_EQ("4 unwind Raw Data: 0xa8 0xb0 0xb0\n", GetFakeLogPrint()); -} - -TEST_F(ArmExidxExtractTest, raw_data_non_compact) { - elf_memory_.SetData32(0x5000, 0x1234); - elf_memory_.SetData32(0x5004, 0x00001230); - elf_memory_.SetData32(0x6234, 0x2); - elf_memory_.SetData32(0x6238, 0x00112233); - - exidx_->set_log(ARM_LOG_FULL); - exidx_->set_log_indent(0); - exidx_->set_log_skip_execution(false); - - ASSERT_TRUE(exidx_->ExtractEntryData(0x5000)); - ASSERT_EQ("4 unwind Raw Data: 0x11 0x22 0x33 0xb0\n", GetFakeLogPrint()); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/DexFileData.h b/libunwindstack/tests/DexFileData.h deleted file mode 100644 index 6975c688b..000000000 --- a/libunwindstack/tests/DexFileData.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2018 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_DEXFILESDATA_H -#define _LIBUNWINDSTACK_DEXFILESDATA_H - -namespace unwindstack { - -// Borrowed from art/dex/dex_file_test.cc. -static constexpr uint32_t kDexData[] = { - 0x0a786564, 0x00383330, 0xc98b3ab8, 0xf3749d94, 0xaecca4d8, 0xffc7b09a, 0xdca9ca7f, 0x5be5deab, - 0x00000220, 0x00000070, 0x12345678, 0x00000000, 0x00000000, 0x0000018c, 0x00000008, 0x00000070, - 0x00000004, 0x00000090, 0x00000002, 0x000000a0, 0x00000000, 0x00000000, 0x00000003, 0x000000b8, - 0x00000001, 0x000000d0, 0x00000130, 0x000000f0, 0x00000122, 0x0000012a, 0x00000132, 0x00000146, - 0x00000151, 0x00000154, 0x00000158, 0x0000016d, 0x00000001, 0x00000002, 0x00000004, 0x00000006, - 0x00000004, 0x00000002, 0x00000000, 0x00000005, 0x00000002, 0x0000011c, 0x00000000, 0x00000000, - 0x00010000, 0x00000007, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, - 0x00000003, 0x00000000, 0x0000017e, 0x00000000, 0x00010001, 0x00000001, 0x00000173, 0x00000004, - 0x00021070, 0x000e0000, 0x00010001, 0x00000000, 0x00000178, 0x00000001, 0x0000000e, 0x00000001, - 0x3c060003, 0x74696e69, 0x4c06003e, 0x6e69614d, 0x4c12003b, 0x6176616a, 0x6e616c2f, 0x624f2f67, - 0x7463656a, 0x4d09003b, 0x2e6e6961, 0x6176616a, 0x00560100, 0x004c5602, 0x6a4c5b13, 0x2f617661, - 0x676e616c, 0x7274532f, 0x3b676e69, 0x616d0400, 0x01006e69, 0x000e0700, 0x07000103, 0x0000000e, - 0x81000002, 0x01f00480, 0x02880901, 0x0000000c, 0x00000000, 0x00000001, 0x00000000, 0x00000001, - 0x00000008, 0x00000070, 0x00000002, 0x00000004, 0x00000090, 0x00000003, 0x00000002, 0x000000a0, - 0x00000005, 0x00000003, 0x000000b8, 0x00000006, 0x00000001, 0x000000d0, 0x00002001, 0x00000002, - 0x000000f0, 0x00001001, 0x00000001, 0x0000011c, 0x00002002, 0x00000008, 0x00000122, 0x00002003, - 0x00000002, 0x00000173, 0x00002000, 0x00000001, 0x0000017e, 0x00001000, 0x00000001, 0x0000018c, -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_DEXFILESDATA_H diff --git a/libunwindstack/tests/DexFileTest.cpp b/libunwindstack/tests/DexFileTest.cpp deleted file mode 100644 index 1deba0145..000000000 --- a/libunwindstack/tests/DexFileTest.cpp +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (C) 2018 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 "DexFile.h" -#include "DexFileData.h" -#include "MemoryFake.h" - -namespace unwindstack { - -TEST(DexFileTest, from_file_open_non_exist) { - EXPECT_TRUE(DexFileFromFile::Create(0, "/file/does/not/exist") == nullptr); -} - -TEST(DexFileTest, from_file_open_too_small) { - TemporaryFile tf; - ASSERT_TRUE(tf.fd != -1); - - ASSERT_EQ(size_t{10}, static_cast(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, 10)))); - - // Header too small. - EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) == nullptr); - - // Header correct, file too small. - ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET)); - ASSERT_EQ(sizeof(kDexData) - 1, - static_cast(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData) - 1)))); - EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) == nullptr); -} - -TEST(DexFileTest, from_file_open) { - TemporaryFile tf; - ASSERT_TRUE(tf.fd != -1); - - ASSERT_EQ(sizeof(kDexData), - static_cast(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData))))); - - EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) != nullptr); -} - -TEST(DexFileTest, from_file_open_non_zero_offset) { - TemporaryFile tf; - ASSERT_TRUE(tf.fd != -1); - - ASSERT_EQ(0x100, lseek(tf.fd, 0x100, SEEK_SET)); - ASSERT_EQ(sizeof(kDexData), - static_cast(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData))))); - - EXPECT_TRUE(DexFileFromFile::Create(0x100, tf.path) != nullptr); -} - -static constexpr size_t kNumLeakLoops = 5000; -static constexpr size_t kMaxAllowedLeakBytes = 1024; - -static void CheckForLeak(size_t loop, size_t* first_allocated_bytes, size_t* last_allocated_bytes) { - size_t allocated_bytes = mallinfo().uordblks; - if (*first_allocated_bytes == 0) { - *first_allocated_bytes = allocated_bytes; - } else if (*last_allocated_bytes > *first_allocated_bytes) { - // Check that the total memory did not increase too much over the first loop. - ASSERT_LE(*last_allocated_bytes - *first_allocated_bytes, kMaxAllowedLeakBytes) - << "Failed in loop " << loop << " first_allocated_bytes " << *first_allocated_bytes - << " last_allocated_bytes " << *last_allocated_bytes; - } - *last_allocated_bytes = allocated_bytes; -} - -TEST(DexFileTest, from_file_no_leak) { - TemporaryFile tf; - ASSERT_TRUE(tf.fd != -1); - - ASSERT_EQ(sizeof(kDexData), - static_cast(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData))))); - - size_t first_allocated_bytes = 0; - size_t last_allocated_bytes = 0; - for (size_t i = 0; i < kNumLeakLoops; i++) { - EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) != nullptr); - ASSERT_NO_FATAL_FAILURE(CheckForLeak(i, &first_allocated_bytes, &last_allocated_bytes)); - } -} - -TEST(DexFileTest, from_memory_fail_too_small_for_header) { - MemoryFake memory; - - memory.SetMemory(0x1000, kDexData, 10); - - EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) == nullptr); -} - -TEST(DexFileTest, from_memory_fail_too_small_for_data) { - MemoryFake memory; - - memory.SetMemory(0x1000, kDexData, sizeof(kDexData) - 2); - - EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) == nullptr); -} - -TEST(DexFileTest, from_memory_open) { - MemoryFake memory; - - memory.SetMemory(0x1000, kDexData, sizeof(kDexData)); - - EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) != nullptr); -} - -TEST(DexFileTest, from_memory_no_leak) { - MemoryFake memory; - - memory.SetMemory(0x1000, kDexData, sizeof(kDexData)); - - size_t first_allocated_bytes = 0; - size_t last_allocated_bytes = 0; - for (size_t i = 0; i < kNumLeakLoops; i++) { - EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "", sizeof(kDexData)) != nullptr); - ASSERT_NO_FATAL_FAILURE(CheckForLeak(i, &first_allocated_bytes, &last_allocated_bytes)); - } -} - -TEST(DexFileTest, create_using_file) { - TemporaryFile tf; - ASSERT_TRUE(tf.fd != -1); - - ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET)); - ASSERT_EQ(sizeof(kDexData), - static_cast(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData))))); - - MemoryFake memory; - MapInfo info(nullptr, nullptr, 0, 0x10000, 0, 0x5, tf.path); - EXPECT_TRUE(DexFile::Create(0x500, &memory, &info) != nullptr); -} - -TEST(DexFileTest, create_using_file_non_zero_start) { - TemporaryFile tf; - ASSERT_TRUE(tf.fd != -1); - - ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET)); - ASSERT_EQ(sizeof(kDexData), - static_cast(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData))))); - - MemoryFake memory; - MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0, 0x5, tf.path); - EXPECT_TRUE(DexFile::Create(0x600, &memory, &info) != nullptr); -} - -TEST(DexFileTest, create_using_file_non_zero_offset) { - TemporaryFile tf; - ASSERT_TRUE(tf.fd != -1); - - ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET)); - ASSERT_EQ(sizeof(kDexData), - static_cast(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData))))); - - MemoryFake memory; - MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, tf.path); - EXPECT_TRUE(DexFile::Create(0x400, &memory, &info) != nullptr); -} - -TEST(DexFileTest, create_using_memory_empty_file) { - MemoryFake memory; - memory.SetMemory(0x4000, kDexData, sizeof(kDexData)); - MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, ""); - EXPECT_TRUE(DexFile::Create(0x4000, &memory, &info) != nullptr); -} - -TEST(DexFileTest, create_using_memory_file_does_not_exist) { - MemoryFake memory; - memory.SetMemory(0x4000, kDexData, sizeof(kDexData)); - MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, "/does/not/exist"); - EXPECT_TRUE(DexFile::Create(0x4000, &memory, &info) != nullptr); -} - -TEST(DexFileTest, create_using_memory_file_is_malformed) { - TemporaryFile tf; - ASSERT_TRUE(tf.fd != -1); - - ASSERT_EQ(sizeof(kDexData) - 10, - static_cast(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData) - 10)))); - - MemoryFake memory; - memory.SetMemory(0x4000, kDexData, sizeof(kDexData)); - MapInfo info(nullptr, nullptr, 0x4000, 0x10000, 0x200, 0x5, "/does/not/exist"); - std::unique_ptr dex_file = DexFile::Create(0x4000, &memory, &info); - ASSERT_TRUE(dex_file != nullptr); - - // Check it came from memory by clearing memory and verifying it fails. - memory.Clear(); - dex_file = DexFile::Create(0x4000, &memory, &info); - EXPECT_TRUE(dex_file == nullptr); -} - -TEST(DexFileTest, create_using_memory_size_too_small) { - MemoryFake memory; - memory.SetMemory(0x4000, kDexData, sizeof(kDexData)); - MapInfo info(nullptr, nullptr, 0x100, sizeof(kDexData) - 2, 0x200, 0x5, "/does/not/exist"); - EXPECT_TRUE(DexFile::Create(0x4000, &memory, &info) != nullptr); -} - -class MemoryLocalFake : public MemoryLocal { - public: - MemoryLocalFake(size_t memory_size) : backing_(memory_size) {} - virtual ~MemoryLocalFake() = default; - - void* Data() { return backing_.data(); } - - private: - std::vector backing_; -}; - -TEST(DexFileTest, create_using_local_memory) { - MemoryLocalFake memory(sizeof(kDexData)); - - memcpy(memory.Data(), kDexData, sizeof(kDexData)); - uint64_t start = reinterpret_cast(memory.Data()); - MapInfo info(nullptr, nullptr, start, start + 0x1000, 0x200, 0x5, "/does/not/exist"); - EXPECT_TRUE(DexFile::Create(start, &memory, &info) != nullptr); -} - -TEST(DexFileTest, create_using_local_memory_size_too_small) { - MemoryLocalFake memory(sizeof(kDexData)); - - memcpy(memory.Data(), kDexData, sizeof(kDexData)); - uint64_t start = reinterpret_cast(memory.Data()); - MapInfo info(nullptr, nullptr, start, start + sizeof(kDexData) - 2, 0x200, 0x5, - "/does/not/exist"); - EXPECT_TRUE(DexFile::Create(start, &memory, &info) == nullptr); -} - -TEST(DexFileTest, get_method) { - MemoryFake memory; - memory.SetMemory(0x4000, kDexData, sizeof(kDexData)); - MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, ""); - std::unique_ptr dex_file(DexFile::Create(0x4000, &memory, &info)); - ASSERT_TRUE(dex_file != nullptr); - - std::string method; - uint64_t method_offset; - ASSERT_TRUE(dex_file->GetMethodInformation(0x102, &method, &method_offset)); - EXPECT_EQ("Main.", method); - EXPECT_EQ(2U, method_offset); - - ASSERT_TRUE(dex_file->GetMethodInformation(0x118, &method, &method_offset)); - EXPECT_EQ("Main.main", method); - EXPECT_EQ(0U, method_offset); -} - -TEST(DexFileTest, get_method_empty) { - MemoryFake memory; - memory.SetMemory(0x4000, kDexData, sizeof(kDexData)); - MapInfo info(nullptr, nullptr, 0x100, 0x10000, 0x200, 0x5, ""); - std::unique_ptr dex_file(DexFile::Create(0x4000, &memory, &info)); - ASSERT_TRUE(dex_file != nullptr); - - std::string method; - uint64_t method_offset; - EXPECT_FALSE(dex_file->GetMethodInformation(0x100000, &method, &method_offset)); - - EXPECT_FALSE(dex_file->GetMethodInformation(0x98, &method, &method_offset)); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/DexFilesTest.cpp b/libunwindstack/tests/DexFilesTest.cpp deleted file mode 100644 index 477cf8efe..000000000 --- a/libunwindstack/tests/DexFilesTest.cpp +++ /dev/null @@ -1,356 +0,0 @@ -/* - * Copyright (C) 2018 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 "DexFileData.h" -#include "ElfFake.h" -#include "MemoryFake.h" - -namespace unwindstack { - -class DexFilesTest : public ::testing::Test { - protected: - void CreateFakeElf(MapInfo* map_info, uint64_t global_offset, uint64_t data_offset, - uint64_t data_vaddr, uint64_t data_size) { - MemoryFake* memory = new MemoryFake; - ElfFake* elf = new ElfFake(memory); - elf->FakeSetValid(true); - ElfInterfaceFake* interface = new ElfInterfaceFake(memory); - elf->FakeSetInterface(interface); - - interface->FakeSetGlobalVariable("__dex_debug_descriptor", global_offset); - interface->FakeSetDataOffset(data_offset); - interface->FakeSetDataVaddrStart(data_vaddr); - interface->FakeSetDataVaddrEnd(data_vaddr + data_size); - map_info->elf.reset(elf); - } - - void Init(ArchEnum arch) { - dex_files_.reset(new DexFiles(process_memory_)); - dex_files_->SetArch(arch); - - maps_.reset( - new BufferMaps("1000-4000 ---s 00000000 00:00 0 /fake/elf\n" - "4000-6000 r--s 00000000 00:00 0 /fake/elf\n" - "6000-8000 -wxs 00002000 00:00 0 /fake/elf\n" - "a000-c000 r--p 00000000 00:00 0 /fake/elf2\n" - "c000-f000 rw-p 00002000 00:00 0 /fake/elf2\n" - "f000-11000 r--p 00000000 00:00 0 /fake/elf3\n" - "100000-110000 rw-p 00f1000 00:00 0 /fake/elf3\n" - "200000-210000 rw-p 0002000 00:00 0 /fake/elf3\n" - "300000-400000 rw-p 0003000 00:00 0 /fake/elf3\n" - "500000-501000 r--p 0000000 00:00 0 /fake/elf4\n" - "501000-502000 ---p 0000000 00:00 0\n" - "503000-510000 rw-p 0003000 00:00 0 /fake/elf4\n" - "510000-520000 rw-p 0010000 00:00 0 /fake/elf4\n")); - ASSERT_TRUE(maps_->Parse()); - - // Global variable in a section that is not readable. - MapInfo* map_info = maps_->Get(kMapGlobalNonReadable); - ASSERT_TRUE(map_info != nullptr); - CreateFakeElf(map_info, 0x2800, 0x2000, 0x2000, 0x3000); - - // Global variable not set by default. - map_info = maps_->Get(kMapGlobalSetToZero); - ASSERT_TRUE(map_info != nullptr); - CreateFakeElf(map_info, 0x2800, 0x2000, 0x2000, 0x3000); - - // Global variable set in this map. - map_info = maps_->Get(kMapGlobal); - ASSERT_TRUE(map_info != nullptr); - CreateFakeElf(map_info, 0xf1800, 0xf1000, 0xf1000, 0x10000); - - // Global variable set in this map, but there is an empty map before rw map. - map_info = maps_->Get(kMapGlobalAfterEmpty); - ASSERT_TRUE(map_info != nullptr); - CreateFakeElf(map_info, 0x3800, 0x3000, 0x3000, 0xd000); - } - - void SetUp() override { - memory_ = new MemoryFake; - process_memory_.reset(memory_); - - Init(ARCH_ARM); - } - - void WriteDescriptor32(uint64_t addr, uint32_t head); - void WriteDescriptor64(uint64_t addr, uint64_t head); - void WriteEntry32(uint64_t entry_addr, uint32_t next, uint32_t prev, uint32_t dex_file); - void WriteEntry64(uint64_t entry_addr, uint64_t next, uint64_t prev, uint64_t dex_file); - void WriteDex(uint64_t dex_file); - - static constexpr size_t kMapGlobalNonReadable = 2; - static constexpr size_t kMapGlobalSetToZero = 3; - static constexpr size_t kMapGlobal = 5; - static constexpr size_t kMapGlobalRw = 6; - static constexpr size_t kMapDexFileEntries = 7; - static constexpr size_t kMapDexFiles = 8; - static constexpr size_t kMapGlobalAfterEmpty = 9; - static constexpr size_t kMapDexFilesAfterEmpty = 12; - - std::shared_ptr process_memory_; - MemoryFake* memory_; - std::unique_ptr dex_files_; - std::unique_ptr maps_; -}; - -void DexFilesTest::WriteDescriptor32(uint64_t addr, uint32_t head) { - // void* first_entry_ - memory_->SetData32(addr + 12, head); -} - -void DexFilesTest::WriteDescriptor64(uint64_t addr, uint64_t head) { - // void* first_entry_ - memory_->SetData64(addr + 16, head); -} - -void DexFilesTest::WriteEntry32(uint64_t entry_addr, uint32_t next, uint32_t prev, - uint32_t dex_file) { - // Format of the 32 bit DEXFileEntry structure: - // uint32_t next - memory_->SetData32(entry_addr, next); - // uint32_t prev - memory_->SetData32(entry_addr + 4, prev); - // uint32_t dex_file - memory_->SetData32(entry_addr + 8, dex_file); -} - -void DexFilesTest::WriteEntry64(uint64_t entry_addr, uint64_t next, uint64_t prev, - uint64_t dex_file) { - // Format of the 64 bit DEXFileEntry structure: - // uint64_t next - memory_->SetData64(entry_addr, next); - // uint64_t prev - memory_->SetData64(entry_addr + 8, prev); - // uint64_t dex_file - memory_->SetData64(entry_addr + 16, dex_file); -} - -void DexFilesTest::WriteDex(uint64_t dex_file) { - memory_->SetMemory(dex_file, kDexData, sizeof(kDexData) * sizeof(uint32_t)); -} - -TEST_F(DexFilesTest, get_method_information_invalid) { - std::string method_name = "nothing"; - uint64_t method_offset = 0x124; - MapInfo* info = maps_->Get(kMapDexFileEntries); - - dex_files_->GetMethodInformation(maps_.get(), info, 0, &method_name, &method_offset); - EXPECT_EQ("nothing", method_name); - EXPECT_EQ(0x124U, method_offset); -} - -TEST_F(DexFilesTest, get_method_information_32) { - std::string method_name = "nothing"; - uint64_t method_offset = 0x124; - MapInfo* info = maps_->Get(kMapDexFiles); - - WriteDescriptor32(0x100800, 0x200000); - WriteEntry32(0x200000, 0, 0, 0x300000); - WriteDex(0x300000); - - dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset); - EXPECT_EQ("Main.", method_name); - EXPECT_EQ(0U, method_offset); -} - -TEST_F(DexFilesTest, get_method_information_64) { - Init(ARCH_ARM64); - - std::string method_name = "nothing"; - uint64_t method_offset = 0x124; - MapInfo* info = maps_->Get(kMapDexFiles); - - WriteDescriptor64(0x100800, 0x200000); - WriteEntry64(0x200000, 0, 0, 0x301000); - WriteDex(0x301000); - - dex_files_->GetMethodInformation(maps_.get(), info, 0x301102, &method_name, &method_offset); - EXPECT_EQ("Main.", method_name); - EXPECT_EQ(2U, method_offset); -} - -TEST_F(DexFilesTest, get_method_information_not_first_entry_32) { - std::string method_name = "nothing"; - uint64_t method_offset = 0x124; - MapInfo* info = maps_->Get(kMapDexFiles); - - WriteDescriptor32(0x100800, 0x200000); - WriteEntry32(0x200000, 0x200100, 0, 0x100000); - WriteEntry32(0x200100, 0, 0x200000, 0x300000); - WriteDex(0x300000); - - dex_files_->GetMethodInformation(maps_.get(), info, 0x300104, &method_name, &method_offset); - EXPECT_EQ("Main.", method_name); - EXPECT_EQ(4U, method_offset); -} - -TEST_F(DexFilesTest, get_method_information_not_first_entry_64) { - Init(ARCH_ARM64); - - std::string method_name = "nothing"; - uint64_t method_offset = 0x124; - MapInfo* info = maps_->Get(kMapDexFiles); - - WriteDescriptor64(0x100800, 0x200000); - WriteEntry64(0x200000, 0x200100, 0, 0x100000); - WriteEntry64(0x200100, 0, 0x200000, 0x300000); - WriteDex(0x300000); - - dex_files_->GetMethodInformation(maps_.get(), info, 0x300106, &method_name, &method_offset); - EXPECT_EQ("Main.", method_name); - EXPECT_EQ(6U, method_offset); -} - -TEST_F(DexFilesTest, get_method_information_cached) { - std::string method_name = "nothing"; - uint64_t method_offset = 0x124; - MapInfo* info = maps_->Get(kMapDexFiles); - - WriteDescriptor32(0x100800, 0x200000); - WriteEntry32(0x200000, 0, 0, 0x300000); - WriteDex(0x300000); - - dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset); - EXPECT_EQ("Main.", method_name); - EXPECT_EQ(0U, method_offset); - - // Clear all memory and make sure that data is acquired from the cache. - memory_->Clear(); - dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset); - EXPECT_EQ("Main.", method_name); - EXPECT_EQ(0U, method_offset); -} - -TEST_F(DexFilesTest, get_method_information_search_libs) { - std::string method_name = "nothing"; - uint64_t method_offset = 0x124; - MapInfo* info = maps_->Get(kMapDexFiles); - - WriteDescriptor32(0x100800, 0x200000); - WriteEntry32(0x200000, 0x200100, 0, 0x100000); - WriteEntry32(0x200100, 0, 0x200000, 0x300000); - WriteDex(0x300000); - - // Only search a given named list of libs. - std::vector libs{"libart.so"}; - dex_files_.reset(new DexFiles(process_memory_, libs)); - dex_files_->SetArch(ARCH_ARM); - - dex_files_->GetMethodInformation(maps_.get(), info, 0x300104, &method_name, &method_offset); - EXPECT_EQ("nothing", method_name); - EXPECT_EQ(0x124U, method_offset); - - MapInfo* map_info = maps_->Get(kMapGlobal); - map_info->name = "/system/lib/libart.so"; - dex_files_.reset(new DexFiles(process_memory_, libs)); - dex_files_->SetArch(ARCH_ARM); - // Set the rw map to the same name or this will not scan this entry. - map_info = maps_->Get(kMapGlobalRw); - map_info->name = "/system/lib/libart.so"; - // Make sure that clearing out copy of the libs doesn't affect the - // DexFiles object. - libs.clear(); - - dex_files_->GetMethodInformation(maps_.get(), info, 0x300104, &method_name, &method_offset); - EXPECT_EQ("Main.", method_name); - EXPECT_EQ(4U, method_offset); -} - -TEST_F(DexFilesTest, get_method_information_global_skip_zero_32) { - std::string method_name = "nothing"; - uint64_t method_offset = 0x124; - MapInfo* info = maps_->Get(kMapDexFiles); - - // First global variable found, but value is zero. - WriteDescriptor32(0xc800, 0); - - WriteDescriptor32(0x100800, 0x200000); - WriteEntry32(0x200000, 0, 0, 0x300000); - WriteDex(0x300000); - - dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset); - EXPECT_EQ("Main.", method_name); - EXPECT_EQ(0U, method_offset); - - // Verify that second is ignored when first is set to non-zero - dex_files_.reset(new DexFiles(process_memory_)); - dex_files_->SetArch(ARCH_ARM); - method_name = "fail"; - method_offset = 0x123; - WriteDescriptor32(0xc800, 0x100000); - dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset); - EXPECT_EQ("fail", method_name); - EXPECT_EQ(0x123U, method_offset); -} - -TEST_F(DexFilesTest, get_method_information_global_skip_zero_64) { - Init(ARCH_ARM64); - - std::string method_name = "nothing"; - uint64_t method_offset = 0x124; - MapInfo* info = maps_->Get(kMapDexFiles); - - // First global variable found, but value is zero. - WriteDescriptor64(0xc800, 0); - - WriteDescriptor64(0x100800, 0x200000); - WriteEntry64(0x200000, 0, 0, 0x300000); - WriteDex(0x300000); - - dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset); - EXPECT_EQ("Main.", method_name); - EXPECT_EQ(0U, method_offset); - - // Verify that second is ignored when first is set to non-zero - dex_files_.reset(new DexFiles(process_memory_)); - dex_files_->SetArch(ARCH_ARM64); - method_name = "fail"; - method_offset = 0x123; - WriteDescriptor64(0xc800, 0x100000); - dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset); - EXPECT_EQ("fail", method_name); - EXPECT_EQ(0x123U, method_offset); -} - -TEST_F(DexFilesTest, get_method_information_with_empty_map) { - std::string method_name = "nothing"; - uint64_t method_offset = 0x124; - MapInfo* info = maps_->Get(kMapDexFilesAfterEmpty); - - WriteDescriptor32(0x503800, 0x506000); - WriteEntry32(0x506000, 0, 0, 0x510000); - WriteDex(0x510000); - - dex_files_->GetMethodInformation(maps_.get(), info, 0x510100, &method_name, &method_offset); - EXPECT_EQ("Main.", method_name); - EXPECT_EQ(0U, method_offset); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/DwarfCfaLogTest.cpp b/libunwindstack/tests/DwarfCfaLogTest.cpp deleted file mode 100644 index 2b5a8dc83..000000000 --- a/libunwindstack/tests/DwarfCfaLogTest.cpp +++ /dev/null @@ -1,801 +0,0 @@ -/* - * Copyright (C) 2016 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 "DwarfCfa.h" - -#include "LogFake.h" -#include "MemoryFake.h" - -namespace unwindstack { - -template -class DwarfCfaLogTest : public ::testing::Test { - protected: - void SetUp() override { - ResetLogs(); - memory_.Clear(); - - dmem_.reset(new DwarfMemory(&memory_)); - - cie_.cfa_instructions_offset = 0x1000; - cie_.cfa_instructions_end = 0x1030; - // These two values should be different to distinguish between - // operations that deal with code versus data. - cie_.code_alignment_factor = 4; - cie_.data_alignment_factor = 8; - - fde_.cfa_instructions_offset = 0x2000; - fde_.cfa_instructions_end = 0x2030; - fde_.pc_start = 0x2000; - fde_.pc_end = 0x2000; - fde_.pc_end = 0x10000; - fde_.cie = &cie_; - cfa_.reset(new DwarfCfa(dmem_.get(), &fde_, ARCH_UNKNOWN)); - } - - MemoryFake memory_; - std::unique_ptr dmem_; - std::unique_ptr> cfa_; - DwarfCie cie_; - DwarfFde fde_; -}; -TYPED_TEST_SUITE_P(DwarfCfaLogTest); - -// NOTE: All class variable references have to be prefaced with this->. - -TYPED_TEST_P(DwarfCfaLogTest, cfa_illegal) { - for (uint8_t i = 0x17; i < 0x3f; i++) { - if (i == 0x2d || i == 0x2e || i == 0x2f) { - // Skip gnu extension ops and aarch64 specialized op. - continue; - } - this->memory_.SetMemory(0x2000, std::vector{i}); - - ResetLogs(); - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2000, 0x2001)); - std::string expected = "4 unwind Illegal\n"; - expected += android::base::StringPrintf("4 unwind Raw Data: 0x%02x\n", i); - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - } -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_nop) { - this->memory_.SetMemory(0x2000, std::vector{0x00}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2000, 0x2001)); - std::string expected = - "4 unwind DW_CFA_nop\n" - "4 unwind Raw Data: 0x00\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_offset) { - this->memory_.SetMemory(0x2000, std::vector{0x83, 0x04}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2000, 0x2002)); - std::string expected = - "4 unwind DW_CFA_offset register(3) 4\n" - "4 unwind Raw Data: 0x83 0x04\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - this->memory_.SetMemory(0x2100, std::vector{0x83, 0x84, 0x01}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2100, 0x2103)); - expected = - "4 unwind DW_CFA_offset register(3) 132\n" - "4 unwind Raw Data: 0x83 0x84 0x01\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_offset_extended) { - this->memory_.SetMemory(0x500, std::vector{0x05, 0x03, 0x02}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x500, 0x503)); - std::string expected = - "4 unwind DW_CFA_offset_extended register(3) 2\n" - "4 unwind Raw Data: 0x05 0x03 0x02\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - this->memory_.SetMemory(0x1500, std::vector{0x05, 0x81, 0x01, 0x82, 0x12}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x1500, 0x1505)); - expected = - "4 unwind DW_CFA_offset_extended register(129) 2306\n" - "4 unwind Raw Data: 0x05 0x81 0x01 0x82 0x12\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_offset_extended_sf) { - this->memory_.SetMemory(0x500, std::vector{0x11, 0x05, 0x10}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x500, 0x503)); - std::string expected = - "4 unwind DW_CFA_offset_extended_sf register(5) 16\n" - "4 unwind Raw Data: 0x11 0x05 0x10\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - // Check a negative value for the offset. - ResetLogs(); - this->memory_.SetMemory(0x1500, std::vector{0x11, 0x86, 0x01, 0xff, 0x7f}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x1500, 0x1505)); - expected = - "4 unwind DW_CFA_offset_extended_sf register(134) -1\n" - "4 unwind Raw Data: 0x11 0x86 0x01 0xff 0x7f\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_restore) { - this->memory_.SetMemory(0x2000, std::vector{0xc2}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2000, 0x2001)); - std::string expected = - "4 unwind DW_CFA_restore register(2)\n" - "4 unwind Raw Data: 0xc2\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - this->memory_.SetMemory(0x3000, std::vector{0x82, 0x04, 0xc2}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x3000, 0x3003)); - expected = - "4 unwind DW_CFA_offset register(2) 4\n" - "4 unwind Raw Data: 0x82 0x04\n" - "4 unwind DW_CFA_restore register(2)\n" - "4 unwind Raw Data: 0xc2\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_restore_extended) { - this->memory_.SetMemory(0x4000, std::vector{0x06, 0x08}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x4000, 0x4002)); - std::string expected = - "4 unwind DW_CFA_restore_extended register(8)\n" - "4 unwind Raw Data: 0x06 0x08\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - this->memory_.SetMemory(0x5000, std::vector{0x05, 0x82, 0x02, 0x04, 0x06, 0x82, 0x02}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x5000, 0x5007)); - expected = - "4 unwind DW_CFA_offset_extended register(258) 4\n" - "4 unwind Raw Data: 0x05 0x82 0x02 0x04\n" - "4 unwind DW_CFA_restore_extended register(258)\n" - "4 unwind Raw Data: 0x06 0x82 0x02\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_set_loc) { - uint8_t buffer[1 + sizeof(TypeParam)]; - buffer[0] = 0x1; - TypeParam address; - std::string raw_data("Raw Data: 0x01 "); - std::string address_str; - if (std::is_same::value) { - address = 0x81234578U; - address_str = "0x81234578"; - raw_data += "0x78 0x45 0x23 0x81"; - } else { - address = 0x8123456712345678ULL; - address_str = "0x8123456712345678"; - raw_data += "0x78 0x56 0x34 0x12 0x67 0x45 0x23 0x81"; - } - memcpy(&buffer[1], &address, sizeof(address)); - - this->memory_.SetMemory(0x50, buffer, sizeof(buffer)); - ResetLogs(); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x50, 0x51 + sizeof(TypeParam))); - std::string expected = "4 unwind DW_CFA_set_loc " + address_str + "\n"; - expected += "4 unwind " + raw_data + "\n"; - expected += "4 unwind \n"; - expected += "4 unwind PC " + address_str + "\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - // Check for a set going back. - ResetLogs(); - this->fde_.pc_start = address + 0x10; - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x50, 0x51 + sizeof(TypeParam))); - expected = "4 unwind DW_CFA_set_loc " + address_str + "\n"; - expected += "4 unwind " + raw_data + "\n"; - expected += "4 unwind \n"; - expected += "4 unwind PC " + address_str + "\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_advance_loc) { - this->memory_.SetMemory(0x200, std::vector{0x44}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x201)); - std::string expected = - "4 unwind DW_CFA_advance_loc 4\n" - "4 unwind Raw Data: 0x44\n" - "4 unwind \n" - "4 unwind PC 0x2010\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_advance_loc1) { - this->memory_.SetMemory(0x200, std::vector{0x02, 0x04}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x202)); - std::string expected = - "4 unwind DW_CFA_advance_loc1 4\n" - "4 unwind Raw Data: 0x02 0x04\n" - "4 unwind \n" - "4 unwind PC 0x2004\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_advance_loc2) { - this->memory_.SetMemory(0x600, std::vector{0x03, 0x04, 0x03}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x600, 0x603)); - std::string expected = - "4 unwind DW_CFA_advance_loc2 772\n" - "4 unwind Raw Data: 0x03 0x04 0x03\n" - "4 unwind \n" - "4 unwind PC 0x2304\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_advance_loc4) { - this->memory_.SetMemory(0x500, std::vector{0x04, 0x04, 0x03, 0x02, 0x01}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x500, 0x505)); - std::string expected = - "4 unwind DW_CFA_advance_loc4 16909060\n" - "4 unwind Raw Data: 0x04 0x04 0x03 0x02 0x01\n" - "4 unwind \n" - "4 unwind PC 0x1022304\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_undefined) { - this->memory_.SetMemory(0xa00, std::vector{0x07, 0x09}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0xa00, 0xa02)); - std::string expected = - "4 unwind DW_CFA_undefined register(9)\n" - "4 unwind Raw Data: 0x07 0x09\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - dwarf_loc_regs_t cie_loc_regs; - this->memory_.SetMemory(0x1a00, std::vector{0x07, 0x81, 0x01}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x1a00, 0x1a03)); - expected = - "4 unwind DW_CFA_undefined register(129)\n" - "4 unwind Raw Data: 0x07 0x81 0x01\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_same) { - this->memory_.SetMemory(0x100, std::vector{0x08, 0x7f}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x102)); - std::string expected = - "4 unwind DW_CFA_same_value register(127)\n" - "4 unwind Raw Data: 0x08 0x7f\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - this->memory_.SetMemory(0x2100, std::vector{0x08, 0xff, 0x01}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2100, 0x2103)); - expected = - "4 unwind DW_CFA_same_value register(255)\n" - "4 unwind Raw Data: 0x08 0xff 0x01\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_register) { - this->memory_.SetMemory(0x300, std::vector{0x09, 0x02, 0x01}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x300, 0x303)); - std::string expected = - "4 unwind DW_CFA_register register(2) register(1)\n" - "4 unwind Raw Data: 0x09 0x02 0x01\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - this->memory_.SetMemory(0x4300, std::vector{0x09, 0xff, 0x01, 0xff, 0x03}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x4300, 0x4305)); - expected = - "4 unwind DW_CFA_register register(255) register(511)\n" - "4 unwind Raw Data: 0x09 0xff 0x01 0xff 0x03\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_state) { - this->memory_.SetMemory(0x300, std::vector{0x0a}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x300, 0x301)); - - std::string expected = - "4 unwind DW_CFA_remember_state\n" - "4 unwind Raw Data: 0x0a\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - this->memory_.SetMemory(0x4300, std::vector{0x0b}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x4300, 0x4301)); - - expected = - "4 unwind DW_CFA_restore_state\n" - "4 unwind Raw Data: 0x0b\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_state_cfa_offset_restore) { - this->memory_.SetMemory(0x3000, std::vector{0x0a, 0x0e, 0x40, 0x0b}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x3000, 0x3004)); - - std::string expected = - "4 unwind DW_CFA_remember_state\n" - "4 unwind Raw Data: 0x0a\n" - "4 unwind DW_CFA_def_cfa_offset 64\n" - "4 unwind Raw Data: 0x0e 0x40\n" - "4 unwind DW_CFA_restore_state\n" - "4 unwind Raw Data: 0x0b\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa) { - this->memory_.SetMemory(0x100, std::vector{0x0c, 0x7f, 0x74}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x103)); - - std::string expected = - "4 unwind DW_CFA_def_cfa register(127) 116\n" - "4 unwind Raw Data: 0x0c 0x7f 0x74\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - this->memory_.SetMemory(0x200, std::vector{0x0c, 0xff, 0x02, 0xf4, 0x04}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x205)); - - expected = - "4 unwind DW_CFA_def_cfa register(383) 628\n" - "4 unwind Raw Data: 0x0c 0xff 0x02 0xf4 0x04\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_sf) { - this->memory_.SetMemory(0x100, std::vector{0x12, 0x30, 0x25}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x103)); - - std::string expected = - "4 unwind DW_CFA_def_cfa_sf register(48) 37\n" - "4 unwind Raw Data: 0x12 0x30 0x25\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - // Test a negative value. - ResetLogs(); - this->memory_.SetMemory(0x200, std::vector{0x12, 0xa3, 0x01, 0xfa, 0x7f}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x205)); - - expected = - "4 unwind DW_CFA_def_cfa_sf register(163) -6\n" - "4 unwind Raw Data: 0x12 0xa3 0x01 0xfa 0x7f\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_register) { - this->memory_.SetMemory(0x100, std::vector{0x0d, 0x72}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x102)); - - std::string expected = - "4 unwind DW_CFA_def_cfa_register register(114)\n" - "4 unwind Raw Data: 0x0d 0x72\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - this->memory_.SetMemory(0x200, std::vector{0x0d, 0xf9, 0x20}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x203)); - - expected = - "4 unwind DW_CFA_def_cfa_register register(4217)\n" - "4 unwind Raw Data: 0x0d 0xf9 0x20\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_offset) { - this->memory_.SetMemory(0x100, std::vector{0x0e, 0x59}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x102)); - - std::string expected = - "4 unwind DW_CFA_def_cfa_offset 89\n" - "4 unwind Raw Data: 0x0e 0x59\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x102)); - - expected = - "4 unwind DW_CFA_def_cfa_offset 89\n" - "4 unwind Raw Data: 0x0e 0x59\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - this->memory_.SetMemory(0x200, std::vector{0x0e, 0xd4, 0x0a}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x203)); - - expected = - "4 unwind DW_CFA_def_cfa_offset 1364\n" - "4 unwind Raw Data: 0x0e 0xd4 0x0a\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_offset_sf) { - this->memory_.SetMemory(0x100, std::vector{0x13, 0x23}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x102)); - - std::string expected = - "4 unwind DW_CFA_def_cfa_offset_sf 35\n" - "4 unwind Raw Data: 0x13 0x23\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x102)); - - expected = - "4 unwind DW_CFA_def_cfa_offset_sf 35\n" - "4 unwind Raw Data: 0x13 0x23\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - // Negative offset. - ResetLogs(); - this->memory_.SetMemory(0x200, std::vector{0x13, 0xf6, 0x7f}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x203)); - - expected = - "4 unwind DW_CFA_def_cfa_offset_sf -10\n" - "4 unwind Raw Data: 0x13 0xf6 0x7f\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_expression) { - this->memory_.SetMemory(0x100, std::vector{0x0f, 0x04, 0x01, 0x02, 0x04, 0x05}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x106)); - - std::string expected = - "4 unwind DW_CFA_def_cfa_expression 4\n" - "4 unwind Raw Data: 0x0f 0x04 0x01 0x02 0x04 0x05\n" - "4 unwind Illegal\n" - "4 unwind Raw Data: 0x01\n" - "4 unwind Illegal\n" - "4 unwind Raw Data: 0x02\n" - "4 unwind Illegal\n" - "4 unwind Raw Data: 0x04\n" - "4 unwind Illegal\n" - "4 unwind Raw Data: 0x05\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - std::vector ops{0x0f, 0x81, 0x01}; - expected = "4 unwind Raw Data: 0x0f 0x81 0x01"; - std::string op_string; - for (uint8_t i = 3; i < 132; i++) { - ops.push_back(0x05); - op_string += - "4 unwind Illegal\n" - "4 unwind Raw Data: 0x05\n"; - expected += " 0x05"; - if (((i + 1) % 10) == 0) { - expected += "\n4 unwind Raw Data:"; - } - } - expected += '\n'; - this->memory_.SetMemory(0x200, ops); - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x284)); - - expected = "4 unwind DW_CFA_def_cfa_expression 129\n" + expected; - ASSERT_EQ(expected + op_string, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_expression) { - this->memory_.SetMemory(0x100, std::vector{0x10, 0x04, 0x02, 0xc0, 0xc1}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x105)); - - std::string expected = - "4 unwind DW_CFA_expression register(4) 2\n" - "4 unwind Raw Data: 0x10 0x04 0x02 0xc0 0xc1\n" - "4 unwind Illegal\n" - "4 unwind Raw Data: 0xc0\n" - "4 unwind Illegal\n" - "4 unwind Raw Data: 0xc1\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - std::vector ops{0x10, 0xff, 0x01, 0x82, 0x01}; - expected = "4 unwind Raw Data: 0x10 0xff 0x01 0x82 0x01"; - std::string op_string; - for (uint8_t i = 5; i < 135; i++) { - ops.push_back(0xa0 + (i - 5) % 96); - op_string += "4 unwind Illegal\n"; - op_string += android::base::StringPrintf("4 unwind Raw Data: 0x%02x\n", ops.back()); - expected += android::base::StringPrintf(" 0x%02x", ops.back()); - if (((i + 1) % 10) == 0) { - expected += "\n4 unwind Raw Data:"; - } - } - expected = "4 unwind DW_CFA_expression register(255) 130\n" + expected + "\n"; - - this->memory_.SetMemory(0x200, ops); - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x287)); - - ASSERT_EQ(expected + op_string, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_val_offset) { - this->memory_.SetMemory(0x100, std::vector{0x14, 0x45, 0x54}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x103)); - - std::string expected = - "4 unwind DW_CFA_val_offset register(69) 84\n" - "4 unwind Raw Data: 0x14 0x45 0x54\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - this->memory_.SetMemory(0x400, std::vector{0x14, 0xa2, 0x02, 0xb4, 0x05}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x400, 0x405)); - - expected = - "4 unwind DW_CFA_val_offset register(290) 692\n" - "4 unwind Raw Data: 0x14 0xa2 0x02 0xb4 0x05\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_val_offset_sf) { - this->memory_.SetMemory(0x100, std::vector{0x15, 0x56, 0x12}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x103)); - - std::string expected = - "4 unwind DW_CFA_val_offset_sf register(86) 18\n" - "4 unwind Raw Data: 0x15 0x56 0x12\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - // Negative value. - ResetLogs(); - this->memory_.SetMemory(0xa00, std::vector{0x15, 0xff, 0x01, 0xc0, 0x7f}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0xa00, 0xa05)); - - expected = - "4 unwind DW_CFA_val_offset_sf register(255) -64\n" - "4 unwind Raw Data: 0x15 0xff 0x01 0xc0 0x7f\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_val_expression) { - this->memory_.SetMemory(0x100, std::vector{0x16, 0x05, 0x02, 0xb0, 0xb1}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x105)); - - std::string expected = - "4 unwind DW_CFA_val_expression register(5) 2\n" - "4 unwind Raw Data: 0x16 0x05 0x02 0xb0 0xb1\n" - "4 unwind Illegal\n" - "4 unwind Raw Data: 0xb0\n" - "4 unwind Illegal\n" - "4 unwind Raw Data: 0xb1\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - std::vector ops{0x16, 0x83, 0x10, 0xa8, 0x01}; - expected = "4 unwind Raw Data: 0x16 0x83 0x10 0xa8 0x01"; - std::string op_string; - for (uint8_t i = 0; i < 168; i++) { - ops.push_back(0xa0 + (i % 96)); - op_string += "4 unwind Illegal\n"; - op_string += android::base::StringPrintf("4 unwind Raw Data: 0x%02x\n", ops.back()); - expected += android::base::StringPrintf(" 0x%02x", ops.back()); - if (((i + 6) % 10) == 0) { - expected += "\n4 unwind Raw Data:"; - } - } - expected = "4 unwind DW_CFA_val_expression register(2051) 168\n" + expected + "\n"; - - this->memory_.SetMemory(0xa00, ops); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0xa00, 0xaad)); - - ASSERT_EQ(expected + op_string, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_gnu_args_size) { - this->memory_.SetMemory(0x2000, std::vector{0x2e, 0x04}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2000, 0x2002)); - - std::string expected = - "4 unwind DW_CFA_GNU_args_size 4\n" - "4 unwind Raw Data: 0x2e 0x04\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - this->memory_.SetMemory(0x5000, std::vector{0x2e, 0xa4, 0x80, 0x04}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x5000, 0x5004)); - - expected = - "4 unwind DW_CFA_GNU_args_size 65572\n" - "4 unwind Raw Data: 0x2e 0xa4 0x80 0x04\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_gnu_negative_offset_extended) { - this->memory_.SetMemory(0x500, std::vector{0x2f, 0x08, 0x10}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x500, 0x503)); - - std::string expected = - "4 unwind DW_CFA_GNU_negative_offset_extended register(8) 16\n" - "4 unwind Raw Data: 0x2f 0x08 0x10\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - this->memory_.SetMemory(0x1500, std::vector{0x2f, 0x81, 0x02, 0xff, 0x01}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x1500, 0x1505)); - - expected = - "4 unwind DW_CFA_GNU_negative_offset_extended register(257) 255\n" - "4 unwind Raw Data: 0x2f 0x81 0x02 0xff 0x01\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_register_override) { - this->memory_.SetMemory(0x300, std::vector{0x09, 0x02, 0x01, 0x09, 0x02, 0x04}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x300, 0x306)); - - std::string expected = - "4 unwind DW_CFA_register register(2) register(1)\n" - "4 unwind Raw Data: 0x09 0x02 0x01\n" - "4 unwind DW_CFA_register register(2) register(4)\n" - "4 unwind Raw Data: 0x09 0x02 0x04\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaLogTest, cfa_aarch64_negate_ra_state) { - // Verify that if the cfa op is handled properly depending on aarch. - this->memory_.SetMemory(0x2000, std::vector{0x2d}); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2000, 0x2001)); - std::string expected = "4 unwind Illegal (Only valid on aarch64)\n"; - expected += "4 unwind Raw Data: 0x2d\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - this->cfa_.reset(new DwarfCfa(this->dmem_.get(), &this->fde_, ARCH_ARM64)); - - ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2000, 0x2001)); - expected = "4 unwind DW_CFA_AARCH64_negate_ra_state\n"; - expected += "4 unwind Raw Data: 0x2d\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -REGISTER_TYPED_TEST_SUITE_P(DwarfCfaLogTest, cfa_illegal, cfa_nop, cfa_offset, cfa_offset_extended, - cfa_offset_extended_sf, cfa_restore, cfa_restore_extended, cfa_set_loc, - cfa_advance_loc, cfa_advance_loc1, cfa_advance_loc2, cfa_advance_loc4, - cfa_undefined, cfa_same, cfa_register, cfa_state, - cfa_state_cfa_offset_restore, cfa_def_cfa, cfa_def_cfa_sf, - cfa_def_cfa_register, cfa_def_cfa_offset, cfa_def_cfa_offset_sf, - cfa_def_cfa_expression, cfa_expression, cfa_val_offset, - cfa_val_offset_sf, cfa_val_expression, cfa_gnu_args_size, - cfa_gnu_negative_offset_extended, cfa_register_override, - cfa_aarch64_negate_ra_state); - -typedef ::testing::Types DwarfCfaLogTestTypes; -INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfCfaLogTest, DwarfCfaLogTestTypes); - -} // namespace unwindstack diff --git a/libunwindstack/tests/DwarfCfaTest.cpp b/libunwindstack/tests/DwarfCfaTest.cpp deleted file mode 100644 index ea7e70807..000000000 --- a/libunwindstack/tests/DwarfCfaTest.cpp +++ /dev/null @@ -1,1021 +0,0 @@ -/* - * Copyright (C) 2016 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 "DwarfCfa.h" - -#include "LogFake.h" -#include "MemoryFake.h" - -namespace unwindstack { - -template -class DwarfCfaTest : public ::testing::Test { - protected: - void SetUp() override { - ResetLogs(); - memory_.Clear(); - - dmem_.reset(new DwarfMemory(&memory_)); - - cie_.cfa_instructions_offset = 0x1000; - cie_.cfa_instructions_end = 0x1030; - // These two values should be different to distinguish between - // operations that deal with code versus data. - cie_.code_alignment_factor = 4; - cie_.data_alignment_factor = 8; - - fde_.cfa_instructions_offset = 0x2000; - fde_.cfa_instructions_end = 0x2030; - fde_.pc_start = 0x2000; - fde_.cie = &cie_; - - cfa_.reset(new DwarfCfa(dmem_.get(), &fde_, ARCH_UNKNOWN)); - } - - MemoryFake memory_; - std::unique_ptr dmem_; - std::unique_ptr> cfa_; - DwarfCie cie_; - DwarfFde fde_; -}; -TYPED_TEST_SUITE_P(DwarfCfaTest); - -// NOTE: All test class variables need to be referenced as this->. - -TYPED_TEST_P(DwarfCfaTest, cfa_illegal) { - for (uint8_t i = 0x17; i < 0x3f; i++) { - if (i == 0x2d || i == 0x2e || i == 0x2f) { - // Skip gnu extension ops and aarch64 specialized op. - continue; - } - this->memory_.SetMemory(0x2000, std::vector{i}); - dwarf_loc_regs_t loc_regs; - - ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs)); - ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->cfa_->LastErrorCode()); - ASSERT_EQ(0x2001U, this->dmem_->cur_offset()); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - } -} - -TYPED_TEST_P(DwarfCfaTest, cfa_nop) { - this->memory_.SetMemory(0x2000, std::vector{0x00}); - dwarf_loc_regs_t loc_regs; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs)); - ASSERT_EQ(0x2001U, this->dmem_->cur_offset()); - ASSERT_EQ(0U, loc_regs.size()); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -// This test needs to be examined. -TYPED_TEST_P(DwarfCfaTest, cfa_offset) { - this->memory_.SetMemory(0x2000, std::vector{0x83, 0x04}); - dwarf_loc_regs_t loc_regs; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2002, &loc_regs)); - ASSERT_EQ(0x2002U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - auto location = loc_regs.find(3); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type); - ASSERT_EQ(32U, location->second.values[0]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - this->memory_.SetMemory(0x2100, std::vector{0x83, 0x84, 0x01}); - loc_regs.clear(); - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2100, 0x2103, &loc_regs)); - ASSERT_EQ(0x2103U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - location = loc_regs.find(3); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type); - ASSERT_EQ(1056U, location->second.values[0]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_offset_extended) { - this->memory_.SetMemory(0x500, std::vector{0x05, 0x03, 0x02}); - dwarf_loc_regs_t loc_regs; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x500, 0x503, &loc_regs)); - ASSERT_EQ(0x503U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - auto location = loc_regs.find(3); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type); - ASSERT_EQ(2U, location->second.values[0]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - loc_regs.clear(); - this->memory_.SetMemory(0x1500, std::vector{0x05, 0x81, 0x01, 0x82, 0x12}); - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x1500, 0x1505, &loc_regs)); - ASSERT_EQ(0x1505U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - location = loc_regs.find(129); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type); - ASSERT_EQ(2306U, location->second.values[0]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_offset_extended_sf) { - this->memory_.SetMemory(0x500, std::vector{0x11, 0x05, 0x10}); - dwarf_loc_regs_t loc_regs; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x500, 0x503, &loc_regs)); - ASSERT_EQ(0x503U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - auto location = loc_regs.find(5); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type); - ASSERT_EQ(0x80U, location->second.values[0]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - // Check a negative value for the offset. - ResetLogs(); - loc_regs.clear(); - this->memory_.SetMemory(0x1500, std::vector{0x11, 0x86, 0x01, 0xff, 0x7f}); - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x1500, 0x1505, &loc_regs)); - ASSERT_EQ(0x1505U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - location = loc_regs.find(134); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type); - ASSERT_EQ(static_cast(-8), location->second.values[0]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_restore) { - this->memory_.SetMemory(0x2000, std::vector{0xc2}); - dwarf_loc_regs_t loc_regs; - - ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs)); - ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode()); - ASSERT_EQ(0x2001U, this->dmem_->cur_offset()); - ASSERT_EQ(0U, loc_regs.size()); - - ASSERT_EQ("4 unwind restore while processing cie\n", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - dwarf_loc_regs_t cie_loc_regs; - cie_loc_regs[2] = {.type = DWARF_LOCATION_REGISTER, .values = {0, 0}}; - this->cfa_->set_cie_loc_regs(&cie_loc_regs); - this->memory_.SetMemory(0x3000, std::vector{0x82, 0x04, 0xc2}); - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x3000, 0x3003, &loc_regs)); - ASSERT_EQ(0x3003U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - auto location = loc_regs.find(2); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_REGISTER, location->second.type); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_restore_extended) { - this->memory_.SetMemory(0x4000, std::vector{0x06, 0x08}); - dwarf_loc_regs_t loc_regs; - - ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x4000, 0x4002, &loc_regs)); - ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode()); - ASSERT_EQ(0x4002U, this->dmem_->cur_offset()); - ASSERT_EQ(0U, loc_regs.size()); - - ASSERT_EQ("4 unwind restore while processing cie\n", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - loc_regs.clear(); - this->memory_.SetMemory(0x5000, std::vector{0x05, 0x82, 0x02, 0x04, 0x06, 0x82, 0x02}); - dwarf_loc_regs_t cie_loc_regs; - cie_loc_regs[258] = {.type = DWARF_LOCATION_REGISTER, .values = {0, 0}}; - this->cfa_->set_cie_loc_regs(&cie_loc_regs); - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x5000, 0x5007, &loc_regs)); - ASSERT_EQ(0x5007U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - auto location = loc_regs.find(258); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_REGISTER, location->second.type); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_set_loc) { - uint8_t buffer[1 + sizeof(TypeParam)]; - buffer[0] = 0x1; - TypeParam address; - std::string raw_data("Raw Data: 0x01 "); - std::string address_str; - if (sizeof(TypeParam) == 4) { - address = 0x81234578U; - address_str = "0x81234578"; - raw_data += "0x78 0x45 0x23 0x81"; - } else { - address = 0x8123456712345678ULL; - address_str = "0x8123456712345678"; - raw_data += "0x78 0x56 0x34 0x12 0x67 0x45 0x23 0x81"; - } - memcpy(&buffer[1], &address, sizeof(address)); - - this->memory_.SetMemory(0x50, buffer, sizeof(buffer)); - ResetLogs(); - dwarf_loc_regs_t loc_regs; - ASSERT_TRUE( - this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x50, 0x51 + sizeof(TypeParam), &loc_regs)); - ASSERT_EQ(0x51 + sizeof(TypeParam), this->dmem_->cur_offset()); - ASSERT_EQ(address, this->cfa_->cur_pc()); - ASSERT_EQ(0U, loc_regs.size()); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - // Check for a set going back. - ResetLogs(); - loc_regs.clear(); - this->fde_.pc_start = address + 0x10; - ASSERT_TRUE( - this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x50, 0x51 + sizeof(TypeParam), &loc_regs)); - ASSERT_EQ(0x51 + sizeof(TypeParam), this->dmem_->cur_offset()); - ASSERT_EQ(address, this->cfa_->cur_pc()); - ASSERT_EQ(0U, loc_regs.size()); - - std::string cur_address_str(address_str); - cur_address_str[cur_address_str.size() - 2] = '8'; - std::string expected = "4 unwind Warning: PC is moving backwards: old " + cur_address_str + - " new " + address_str + "\n"; - ASSERT_EQ(expected, GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_advance_loc1) { - this->memory_.SetMemory(0x200, std::vector{0x02, 0x04}); - dwarf_loc_regs_t loc_regs; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x202, &loc_regs)); - ASSERT_EQ(0x202U, this->dmem_->cur_offset()); - ASSERT_EQ(this->fde_.pc_start + 0x10, this->cfa_->cur_pc()); - ASSERT_EQ(0U, loc_regs.size()); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_advance_loc2) { - this->memory_.SetMemory(0x600, std::vector{0x03, 0x04, 0x03}); - dwarf_loc_regs_t loc_regs; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x600, 0x603, &loc_regs)); - ASSERT_EQ(0x603U, this->dmem_->cur_offset()); - ASSERT_EQ(this->fde_.pc_start + 0xc10U, this->cfa_->cur_pc()); - ASSERT_EQ(0U, loc_regs.size()); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_advance_loc4) { - this->memory_.SetMemory(0x500, std::vector{0x04, 0x04, 0x03, 0x02, 0x01}); - dwarf_loc_regs_t loc_regs; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x500, 0x505, &loc_regs)); - ASSERT_EQ(0x505U, this->dmem_->cur_offset()); - ASSERT_EQ(this->fde_.pc_start + 0x4080c10, this->cfa_->cur_pc()); - ASSERT_EQ(0U, loc_regs.size()); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_undefined) { - this->memory_.SetMemory(0xa00, std::vector{0x07, 0x09}); - dwarf_loc_regs_t loc_regs; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0xa00, 0xa02, &loc_regs)); - ASSERT_EQ(0xa02U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - auto location = loc_regs.find(9); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_UNDEFINED, location->second.type); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - loc_regs.clear(); - this->memory_.SetMemory(0x1a00, std::vector{0x07, 0x81, 0x01}); - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x1a00, 0x1a03, &loc_regs)); - ASSERT_EQ(0x1a03U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - location = loc_regs.find(129); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_UNDEFINED, location->second.type); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_same) { - this->memory_.SetMemory(0x100, std::vector{0x08, 0x7f}); - dwarf_loc_regs_t loc_regs; - - loc_regs[127] = {.type = DWARF_LOCATION_REGISTER, .values = {0, 0}}; - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs)); - ASSERT_EQ(0x102U, this->dmem_->cur_offset()); - ASSERT_EQ(0U, loc_regs.size()); - ASSERT_EQ(0U, loc_regs.count(127)); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - loc_regs.clear(); - this->memory_.SetMemory(0x2100, std::vector{0x08, 0xff, 0x01}); - - loc_regs[255] = {.type = DWARF_LOCATION_REGISTER, .values = {0, 0}}; - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2100, 0x2103, &loc_regs)); - ASSERT_EQ(0x2103U, this->dmem_->cur_offset()); - ASSERT_EQ(0U, loc_regs.size()); - ASSERT_EQ(0U, loc_regs.count(255)); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_register) { - this->memory_.SetMemory(0x300, std::vector{0x09, 0x02, 0x01}); - dwarf_loc_regs_t loc_regs; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x300, 0x303, &loc_regs)); - ASSERT_EQ(0x303U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - auto location = loc_regs.find(2); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_REGISTER, location->second.type); - ASSERT_EQ(1U, location->second.values[0]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - loc_regs.clear(); - this->memory_.SetMemory(0x4300, std::vector{0x09, 0xff, 0x01, 0xff, 0x03}); - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x4300, 0x4305, &loc_regs)); - ASSERT_EQ(0x4305U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - location = loc_regs.find(255); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_REGISTER, location->second.type); - ASSERT_EQ(511U, location->second.values[0]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_state) { - this->memory_.SetMemory(0x300, std::vector{0x0a}); - dwarf_loc_regs_t loc_regs; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x300, 0x301, &loc_regs)); - ASSERT_EQ(0x301U, this->dmem_->cur_offset()); - ASSERT_EQ(0U, loc_regs.size()); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - this->memory_.SetMemory(0x4300, std::vector{0x0b}); - - loc_regs.clear(); - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x4300, 0x4301, &loc_regs)); - ASSERT_EQ(0x4301U, this->dmem_->cur_offset()); - ASSERT_EQ(0U, loc_regs.size()); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - this->memory_.SetMemory(0x2000, std::vector{0x85, 0x02, 0x0a, 0x86, 0x04, 0x0b}); - - loc_regs.clear(); - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2005, &loc_regs)); - ASSERT_EQ(0x2005U, this->dmem_->cur_offset()); - ASSERT_EQ(2U, loc_regs.size()); - ASSERT_NE(loc_regs.end(), loc_regs.find(5)); - ASSERT_NE(loc_regs.end(), loc_regs.find(6)); - - loc_regs.clear(); - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2006, &loc_regs)); - ASSERT_EQ(0x2006U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - ASSERT_NE(loc_regs.end(), loc_regs.find(5)); - - ResetLogs(); - this->memory_.SetMemory( - 0x6000, std::vector{0x0a, 0x85, 0x02, 0x0a, 0x86, 0x04, 0x0a, 0x87, 0x01, 0x0a, 0x89, - 0x05, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}); - - loc_regs.clear(); - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x6000, 0x600c, &loc_regs)); - ASSERT_EQ(0x600cU, this->dmem_->cur_offset()); - ASSERT_EQ(4U, loc_regs.size()); - ASSERT_NE(loc_regs.end(), loc_regs.find(5)); - ASSERT_NE(loc_regs.end(), loc_regs.find(6)); - ASSERT_NE(loc_regs.end(), loc_regs.find(7)); - ASSERT_NE(loc_regs.end(), loc_regs.find(9)); - - loc_regs.clear(); - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x6000, 0x600d, &loc_regs)); - ASSERT_EQ(0x600dU, this->dmem_->cur_offset()); - ASSERT_EQ(3U, loc_regs.size()); - ASSERT_NE(loc_regs.end(), loc_regs.find(5)); - ASSERT_NE(loc_regs.end(), loc_regs.find(6)); - ASSERT_NE(loc_regs.end(), loc_regs.find(7)); - - loc_regs.clear(); - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x6000, 0x600e, &loc_regs)); - ASSERT_EQ(0x600eU, this->dmem_->cur_offset()); - ASSERT_EQ(2U, loc_regs.size()); - ASSERT_NE(loc_regs.end(), loc_regs.find(5)); - ASSERT_NE(loc_regs.end(), loc_regs.find(6)); - - loc_regs.clear(); - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x6000, 0x600f, &loc_regs)); - ASSERT_EQ(0x600fU, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - ASSERT_NE(loc_regs.end(), loc_regs.find(5)); - - loc_regs.clear(); - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x6000, 0x6010, &loc_regs)); - ASSERT_EQ(0x6010U, this->dmem_->cur_offset()); - ASSERT_EQ(0U, loc_regs.size()); - - loc_regs.clear(); - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x6000, 0x6011, &loc_regs)); - ASSERT_EQ(0x6011U, this->dmem_->cur_offset()); - ASSERT_EQ(0U, loc_regs.size()); -} - -// This test verifies that the cfa offset is saved and restored properly. -// Even though the spec is not clear about whether the offset is also -// restored, the gcc unwinder does, and libunwind does too. -TYPED_TEST_P(DwarfCfaTest, cfa_state_cfa_offset_restore) { - this->memory_.SetMemory(0x3000, std::vector{0x0a, 0x0e, 0x40, 0x0b}); - dwarf_loc_regs_t loc_regs; - loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {5, 100}}; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x3000, 0x3004, &loc_regs)); - ASSERT_EQ(0x3004U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type); - ASSERT_EQ(5U, loc_regs[CFA_REG].values[0]); - ASSERT_EQ(100U, loc_regs[CFA_REG].values[1]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa) { - this->memory_.SetMemory(0x100, std::vector{0x0c, 0x7f, 0x74}); - dwarf_loc_regs_t loc_regs; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x103, &loc_regs)); - ASSERT_EQ(0x103U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type); - ASSERT_EQ(0x7fU, loc_regs[CFA_REG].values[0]); - ASSERT_EQ(0x74U, loc_regs[CFA_REG].values[1]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - loc_regs.clear(); - this->memory_.SetMemory(0x200, std::vector{0x0c, 0xff, 0x02, 0xf4, 0x04}); - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x205, &loc_regs)); - ASSERT_EQ(0x205U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type); - ASSERT_EQ(0x17fU, loc_regs[CFA_REG].values[0]); - ASSERT_EQ(0x274U, loc_regs[CFA_REG].values[1]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa_sf) { - this->memory_.SetMemory(0x100, std::vector{0x12, 0x30, 0x25}); - dwarf_loc_regs_t loc_regs; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x103, &loc_regs)); - ASSERT_EQ(0x103U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type); - ASSERT_EQ(0x30U, loc_regs[CFA_REG].values[0]); - ASSERT_EQ(0x128U, loc_regs[CFA_REG].values[1]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - // Test a negative value. - ResetLogs(); - loc_regs.clear(); - this->memory_.SetMemory(0x200, std::vector{0x12, 0xa3, 0x01, 0xfa, 0x7f}); - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x205, &loc_regs)); - ASSERT_EQ(0x205U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type); - ASSERT_EQ(0xa3U, loc_regs[CFA_REG].values[0]); - ASSERT_EQ(static_cast(-48), loc_regs[CFA_REG].values[1]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa_register) { - this->memory_.SetMemory(0x100, std::vector{0x0d, 0x72}); - dwarf_loc_regs_t loc_regs; - - // This fails because the cfa is not defined as a register. - ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs)); - ASSERT_EQ(0U, loc_regs.size()); - ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode()); - - ASSERT_EQ("4 unwind Attempt to set new register, but cfa is not already set to a register.\n", - GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - loc_regs.clear(); - loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {3, 20}}; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs)); - ASSERT_EQ(0x102U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type); - ASSERT_EQ(0x72U, loc_regs[CFA_REG].values[0]); - ASSERT_EQ(20U, loc_regs[CFA_REG].values[1]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - this->memory_.SetMemory(0x200, std::vector{0x0d, 0xf9, 0x20}); - loc_regs.clear(); - loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {3, 60}}; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x203, &loc_regs)); - ASSERT_EQ(0x203U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type); - ASSERT_EQ(0x1079U, loc_regs[CFA_REG].values[0]); - ASSERT_EQ(60U, loc_regs[CFA_REG].values[1]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa_offset) { - this->memory_.SetMemory(0x100, std::vector{0x0e, 0x59}); - dwarf_loc_regs_t loc_regs; - - // This fails because the cfa is not defined as a register. - ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs)); - ASSERT_EQ(0U, loc_regs.size()); - ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode()); - - ASSERT_EQ("4 unwind Attempt to set offset, but cfa is not set to a register.\n", - GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - loc_regs.clear(); - loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {3}}; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs)); - ASSERT_EQ(0x102U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type); - ASSERT_EQ(3U, loc_regs[CFA_REG].values[0]); - ASSERT_EQ(0x59U, loc_regs[CFA_REG].values[1]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - this->memory_.SetMemory(0x200, std::vector{0x0e, 0xd4, 0x0a}); - loc_regs.clear(); - loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {3}}; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x203, &loc_regs)); - ASSERT_EQ(0x203U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type); - ASSERT_EQ(3U, loc_regs[CFA_REG].values[0]); - ASSERT_EQ(0x554U, loc_regs[CFA_REG].values[1]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa_offset_sf) { - this->memory_.SetMemory(0x100, std::vector{0x13, 0x23}); - dwarf_loc_regs_t loc_regs; - - // This fails because the cfa is not defined as a register. - ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs)); - ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode()); - - ASSERT_EQ("4 unwind Attempt to set offset, but cfa is not set to a register.\n", - GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - loc_regs.clear(); - loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {3}}; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs)); - ASSERT_EQ(0x102U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type); - ASSERT_EQ(3U, loc_regs[CFA_REG].values[0]); - ASSERT_EQ(0x118U, loc_regs[CFA_REG].values[1]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - // Negative offset. - ResetLogs(); - this->memory_.SetMemory(0x200, std::vector{0x13, 0xf6, 0x7f}); - loc_regs.clear(); - loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {3}}; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x203, &loc_regs)); - ASSERT_EQ(0x203U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type); - ASSERT_EQ(3U, loc_regs[CFA_REG].values[0]); - ASSERT_EQ(static_cast(-80), static_cast(loc_regs[CFA_REG].values[1])); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa_expression) { - this->memory_.SetMemory(0x100, std::vector{0x0f, 0x04, 0x01, 0x02, 0x03, 0x04}); - dwarf_loc_regs_t loc_regs; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x106, &loc_regs)); - ASSERT_EQ(0x106U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - std::vector ops{0x0f, 0x81, 0x01}; - for (uint8_t i = 3; i < 132; i++) { - ops.push_back(i - 1); - } - this->memory_.SetMemory(0x200, ops); - loc_regs.clear(); - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x284, &loc_regs)); - ASSERT_EQ(0x284U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - ASSERT_EQ(DWARF_LOCATION_VAL_EXPRESSION, loc_regs[CFA_REG].type); - ASSERT_EQ(0x81U, loc_regs[CFA_REG].values[0]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_expression) { - this->memory_.SetMemory(0x100, std::vector{0x10, 0x04, 0x02, 0x40, 0x20}); - dwarf_loc_regs_t loc_regs; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x105, &loc_regs)); - ASSERT_EQ(0x105U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - auto location = loc_regs.find(4); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_EXPRESSION, location->second.type); - ASSERT_EQ(2U, location->second.values[0]); - ASSERT_EQ(0x105U, location->second.values[1]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - std::vector ops{0x10, 0xff, 0x01, 0x82, 0x01}; - for (uint8_t i = 5; i < 135; i++) { - ops.push_back(i - 4); - } - - this->memory_.SetMemory(0x200, ops); - loc_regs.clear(); - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x287, &loc_regs)); - ASSERT_EQ(0x287U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - location = loc_regs.find(255); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_EXPRESSION, location->second.type); - ASSERT_EQ(130U, location->second.values[0]); - ASSERT_EQ(0x287U, location->second.values[1]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_val_offset) { - this->memory_.SetMemory(0x100, std::vector{0x14, 0x45, 0x54}); - dwarf_loc_regs_t loc_regs; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x103, &loc_regs)); - ASSERT_EQ(0x103U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - auto location = loc_regs.find(69); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_VAL_OFFSET, location->second.type); - ASSERT_EQ(0x2a0U, location->second.values[0]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - loc_regs.clear(); - this->memory_.SetMemory(0x400, std::vector{0x14, 0xa2, 0x02, 0xb4, 0x05}); - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x400, 0x405, &loc_regs)); - ASSERT_EQ(0x405U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - location = loc_regs.find(290); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_VAL_OFFSET, location->second.type); - ASSERT_EQ(0x15a0U, location->second.values[0]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_val_offset_sf) { - this->memory_.SetMemory(0x100, std::vector{0x15, 0x56, 0x12}); - dwarf_loc_regs_t loc_regs; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x103, &loc_regs)); - ASSERT_EQ(0x103U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - auto location = loc_regs.find(86); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_VAL_OFFSET, location->second.type); - ASSERT_EQ(0x90U, location->second.values[0]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - // Negative value. - ResetLogs(); - loc_regs.clear(); - this->memory_.SetMemory(0xa00, std::vector{0x15, 0xff, 0x01, 0xc0, 0x7f}); - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0xa00, 0xa05, &loc_regs)); - ASSERT_EQ(0xa05U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - location = loc_regs.find(255); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_VAL_OFFSET, location->second.type); - ASSERT_EQ(static_cast(-512), location->second.values[0]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_val_expression) { - this->memory_.SetMemory(0x100, std::vector{0x16, 0x05, 0x02, 0x10, 0x20}); - dwarf_loc_regs_t loc_regs; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x105, &loc_regs)); - ASSERT_EQ(0x105U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - auto location = loc_regs.find(5); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_VAL_EXPRESSION, location->second.type); - ASSERT_EQ(2U, location->second.values[0]); - ASSERT_EQ(0x105U, location->second.values[1]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - std::vector ops{0x16, 0x83, 0x10, 0xa8, 0x01}; - for (uint8_t i = 0; i < 168; i++) { - ops.push_back(i); - } - - this->memory_.SetMemory(0xa00, ops); - loc_regs.clear(); - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0xa00, 0xaad, &loc_regs)); - ASSERT_EQ(0xaadU, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - location = loc_regs.find(2051); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_VAL_EXPRESSION, location->second.type); - ASSERT_EQ(168U, location->second.values[0]); - ASSERT_EQ(0xaadU, location->second.values[1]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_gnu_args_size) { - this->memory_.SetMemory(0x2000, std::vector{0x2e, 0x04}); - dwarf_loc_regs_t loc_regs; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2002, &loc_regs)); - ASSERT_EQ(0x2002U, this->dmem_->cur_offset()); - ASSERT_EQ(0U, loc_regs.size()); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - loc_regs.clear(); - this->memory_.SetMemory(0x5000, std::vector{0x2e, 0xa4, 0x80, 0x04}); - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x5000, 0x5004, &loc_regs)); - ASSERT_EQ(0x5004U, this->dmem_->cur_offset()); - ASSERT_EQ(0U, loc_regs.size()); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_gnu_negative_offset_extended) { - this->memory_.SetMemory(0x500, std::vector{0x2f, 0x08, 0x10}); - dwarf_loc_regs_t loc_regs; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x500, 0x503, &loc_regs)); - ASSERT_EQ(0x503U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - auto location = loc_regs.find(8); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type); - ASSERT_EQ(static_cast(-16), location->second.values[0]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - loc_regs.clear(); - this->memory_.SetMemory(0x1500, std::vector{0x2f, 0x81, 0x02, 0xff, 0x01}); - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x1500, 0x1505, &loc_regs)); - ASSERT_EQ(0x1505U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - location = loc_regs.find(257); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type); - ASSERT_EQ(static_cast(-255), location->second.values[0]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_register_override) { - this->memory_.SetMemory(0x300, std::vector{0x09, 0x02, 0x01, 0x09, 0x02, 0x04}); - dwarf_loc_regs_t loc_regs; - - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x300, 0x306, &loc_regs)); - ASSERT_EQ(0x306U, this->dmem_->cur_offset()); - ASSERT_EQ(1U, loc_regs.size()); - auto location = loc_regs.find(2); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_REGISTER, location->second.type); - ASSERT_EQ(4U, location->second.values[0]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -TYPED_TEST_P(DwarfCfaTest, cfa_aarch64_negate_ra_state) { - this->memory_.SetMemory(0x2000, std::vector{0x2d}); - dwarf_loc_regs_t loc_regs; - - ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs)); - ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->cfa_->LastErrorCode()); - ASSERT_EQ(0x2001U, this->dmem_->cur_offset()); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - ResetLogs(); - this->cfa_.reset(new DwarfCfa(this->dmem_.get(), &this->fde_, ARCH_ARM64)); - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs)); - ASSERT_EQ(0x2001U, this->dmem_->cur_offset()); - - auto location = loc_regs.find(Arm64Reg::ARM64_PREG_RA_SIGN_STATE); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_PSEUDO_REGISTER, location->second.type); - ASSERT_EQ(1U, location->second.values[0]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - // Verify that the value is set to 0 after another evaluation. - ResetLogs(); - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs)); - ASSERT_EQ(0x2001U, this->dmem_->cur_offset()); - - location = loc_regs.find(Arm64Reg::ARM64_PREG_RA_SIGN_STATE); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_PSEUDO_REGISTER, location->second.type); - ASSERT_EQ(0U, location->second.values[0]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); - - // Verify that the value is set to 1 again after a third op. - ResetLogs(); - ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs)); - ASSERT_EQ(0x2001U, this->dmem_->cur_offset()); - - location = loc_regs.find(Arm64Reg::ARM64_PREG_RA_SIGN_STATE); - ASSERT_NE(loc_regs.end(), location); - ASSERT_EQ(DWARF_LOCATION_PSEUDO_REGISTER, location->second.type); - ASSERT_EQ(1U, location->second.values[0]); - - ASSERT_EQ("", GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -REGISTER_TYPED_TEST_SUITE_P(DwarfCfaTest, cfa_illegal, cfa_nop, cfa_offset, cfa_offset_extended, - cfa_offset_extended_sf, cfa_restore, cfa_restore_extended, cfa_set_loc, - cfa_advance_loc1, cfa_advance_loc2, cfa_advance_loc4, cfa_undefined, - cfa_same, cfa_register, cfa_state, cfa_state_cfa_offset_restore, - cfa_def_cfa, cfa_def_cfa_sf, cfa_def_cfa_register, cfa_def_cfa_offset, - cfa_def_cfa_offset_sf, cfa_def_cfa_expression, cfa_expression, - cfa_val_offset, cfa_val_offset_sf, cfa_val_expression, - cfa_gnu_args_size, cfa_gnu_negative_offset_extended, - cfa_register_override, cfa_aarch64_negate_ra_state); - -typedef ::testing::Types DwarfCfaTestTypes; -INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfCfaTest, DwarfCfaTestTypes); - -} // namespace unwindstack diff --git a/libunwindstack/tests/DwarfDebugFrameTest.cpp b/libunwindstack/tests/DwarfDebugFrameTest.cpp deleted file mode 100644 index fac8a0e3f..000000000 --- a/libunwindstack/tests/DwarfDebugFrameTest.cpp +++ /dev/null @@ -1,888 +0,0 @@ -/* - * Copyright (C) 2016 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 "DwarfDebugFrame.h" -#include "DwarfEncoding.h" - -#include "LogFake.h" -#include "MemoryFake.h" - -namespace unwindstack { - -template -class DwarfDebugFrameTest : public ::testing::Test { - protected: - void SetUp() override { - memory_.Clear(); - debug_frame_ = new DwarfDebugFrame(&memory_); - ResetLogs(); - } - - void TearDown() override { delete debug_frame_; } - - MemoryFake memory_; - DwarfDebugFrame* debug_frame_ = nullptr; -}; -TYPED_TEST_SUITE_P(DwarfDebugFrameTest); - -// NOTE: All test class variables need to be referenced as this->. - -static void SetCie32(MemoryFake* memory, uint64_t offset, uint32_t length, - std::vector data) { - memory->SetData32(offset, length); - offset += 4; - // Indicates this is a cie. - memory->SetData32(offset, 0xffffffff); - offset += 4; - memory->SetMemory(offset, data); -} - -static void SetCie64(MemoryFake* memory, uint64_t offset, uint64_t length, - std::vector data) { - memory->SetData32(offset, 0xffffffff); - offset += 4; - memory->SetData64(offset, length); - offset += 8; - // Indicates this is a cie. - memory->SetData64(offset, 0xffffffffffffffffUL); - offset += 8; - memory->SetMemory(offset, data); -} - -static void SetFde32(MemoryFake* memory, uint64_t offset, uint32_t length, uint64_t cie_offset, - uint32_t pc_start, uint32_t pc_length, uint64_t segment_length = 0, - std::vector* data = nullptr) { - memory->SetData32(offset, length); - offset += 4; - memory->SetData32(offset, cie_offset); - offset += 4 + segment_length; - memory->SetData32(offset, pc_start); - offset += 4; - memory->SetData32(offset, pc_length); - if (data != nullptr) { - offset += 4; - memory->SetMemory(offset, *data); - } -} - -static void SetFde64(MemoryFake* memory, uint64_t offset, uint64_t length, uint64_t cie_offset, - uint64_t pc_start, uint64_t pc_length, uint64_t segment_length = 0, - std::vector* data = nullptr) { - memory->SetData32(offset, 0xffffffff); - offset += 4; - memory->SetData64(offset, length); - offset += 8; - memory->SetData64(offset, cie_offset); - offset += 8 + segment_length; - memory->SetData64(offset, pc_start); - offset += 8; - memory->SetData64(offset, pc_length); - if (data != nullptr) { - offset += 8; - memory->SetMemory(offset, *data); - } -} - -static void SetFourFdes32(MemoryFake* memory) { - SetCie32(memory, 0x5000, 0xfc, std::vector{1, '\0', 0, 0, 1}); - - // FDE 32 information. - SetFde32(memory, 0x5100, 0xfc, 0, 0x1500, 0x200); - SetFde32(memory, 0x5200, 0xfc, 0, 0x2500, 0x300); - - // CIE 32 information. - SetCie32(memory, 0x5300, 0xfc, std::vector{1, '\0', 0, 0, 1}); - - // FDE 32 information. - SetFde32(memory, 0x5400, 0xfc, 0x300, 0x3500, 0x400); - SetFde32(memory, 0x5500, 0xfc, 0x300, 0x4500, 0x500); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetFdes32) { - SetFourFdes32(&this->memory_); - ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0)); - - std::vector fdes; - this->debug_frame_->GetFdes(&fdes); - - ASSERT_EQ(4U, fdes.size()); - - EXPECT_EQ(0x5000U, fdes[0]->cie_offset); - EXPECT_EQ(0x5110U, fdes[0]->cfa_instructions_offset); - EXPECT_EQ(0x5200U, fdes[0]->cfa_instructions_end); - EXPECT_EQ(0x1500U, fdes[0]->pc_start); - EXPECT_EQ(0x1700U, fdes[0]->pc_end); - EXPECT_EQ(0U, fdes[0]->lsda_address); - EXPECT_TRUE(fdes[0]->cie != nullptr); - - EXPECT_EQ(0x5000U, fdes[1]->cie_offset); - EXPECT_EQ(0x5210U, fdes[1]->cfa_instructions_offset); - EXPECT_EQ(0x5300U, fdes[1]->cfa_instructions_end); - EXPECT_EQ(0x2500U, fdes[1]->pc_start); - EXPECT_EQ(0x2800U, fdes[1]->pc_end); - EXPECT_EQ(0U, fdes[1]->lsda_address); - EXPECT_TRUE(fdes[1]->cie != nullptr); - - EXPECT_EQ(0x5300U, fdes[2]->cie_offset); - EXPECT_EQ(0x5410U, fdes[2]->cfa_instructions_offset); - EXPECT_EQ(0x5500U, fdes[2]->cfa_instructions_end); - EXPECT_EQ(0x3500U, fdes[2]->pc_start); - EXPECT_EQ(0x3900U, fdes[2]->pc_end); - EXPECT_EQ(0U, fdes[2]->lsda_address); - EXPECT_TRUE(fdes[2]->cie != nullptr); - - EXPECT_EQ(0x5300U, fdes[3]->cie_offset); - EXPECT_EQ(0x5510U, fdes[3]->cfa_instructions_offset); - EXPECT_EQ(0x5600U, fdes[3]->cfa_instructions_end); - EXPECT_EQ(0x4500U, fdes[3]->pc_start); - EXPECT_EQ(0x4a00U, fdes[3]->pc_end); - EXPECT_EQ(0U, fdes[3]->lsda_address); - EXPECT_TRUE(fdes[3]->cie != nullptr); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetFdes32_after_GetFdeFromPc) { - SetFourFdes32(&this->memory_); - ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0)); - - const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x3600); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x3500U, fde->pc_start); - EXPECT_EQ(0x3900U, fde->pc_end); - - std::vector fdes; - this->debug_frame_->GetFdes(&fdes); - ASSERT_EQ(4U, fdes.size()); - - // Verify that they got added in the correct order. - EXPECT_EQ(0x1500U, fdes[0]->pc_start); - EXPECT_EQ(0x1700U, fdes[0]->pc_end); - EXPECT_EQ(0x2500U, fdes[1]->pc_start); - EXPECT_EQ(0x2800U, fdes[1]->pc_end); - EXPECT_EQ(0x3500U, fdes[2]->pc_start); - EXPECT_EQ(0x3900U, fdes[2]->pc_end); - EXPECT_EQ(0x4500U, fdes[3]->pc_start); - EXPECT_EQ(0x4a00U, fdes[3]->pc_end); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetFdes32_not_in_section) { - SetFourFdes32(&this->memory_); - ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x500, 0)); - - std::vector fdes; - this->debug_frame_->GetFdes(&fdes); - - ASSERT_EQ(3U, fdes.size()); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromPc32) { - SetFourFdes32(&this->memory_); - ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0)); - - const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x1600); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x1500U, fde->pc_start); - - fde = this->debug_frame_->GetFdeFromPc(0x2600); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x2500U, fde->pc_start); - - fde = this->debug_frame_->GetFdeFromPc(0x3600); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x3500U, fde->pc_start); - - fde = this->debug_frame_->GetFdeFromPc(0x4600); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x4500U, fde->pc_start); - - fde = this->debug_frame_->GetFdeFromPc(0); - ASSERT_TRUE(fde == nullptr); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromPc32_reverse) { - SetFourFdes32(&this->memory_); - ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0)); - - const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x4600); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x4500U, fde->pc_start); - - fde = this->debug_frame_->GetFdeFromPc(0x3600); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x3500U, fde->pc_start); - - fde = this->debug_frame_->GetFdeFromPc(0x2600); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x2500U, fde->pc_start); - - fde = this->debug_frame_->GetFdeFromPc(0x1600); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x1500U, fde->pc_start); - - fde = this->debug_frame_->GetFdeFromPc(0); - ASSERT_TRUE(fde == nullptr); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromPc32_not_in_section) { - SetFourFdes32(&this->memory_); - ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x500, 0)); - - const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x4600); - ASSERT_TRUE(fde == nullptr); -} - -static void SetFourFdes64(MemoryFake* memory) { - // CIE 64 information. - SetCie64(memory, 0x5000, 0xf4, std::vector{1, '\0', 0, 0, 1}); - - // FDE 64 information. - SetFde64(memory, 0x5100, 0xf4, 0, 0x1500, 0x200); - SetFde64(memory, 0x5200, 0xf4, 0, 0x2500, 0x300); - - // CIE 64 information. - SetCie64(memory, 0x5300, 0xf4, std::vector{1, '\0', 0, 0, 1}); - - // FDE 64 information. - SetFde64(memory, 0x5400, 0xf4, 0x300, 0x3500, 0x400); - SetFde64(memory, 0x5500, 0xf4, 0x300, 0x4500, 0x500); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetFdes64) { - SetFourFdes64(&this->memory_); - ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0)); - - std::vector fdes; - this->debug_frame_->GetFdes(&fdes); - - ASSERT_EQ(4U, fdes.size()); - - EXPECT_EQ(0x5000U, fdes[0]->cie_offset); - EXPECT_EQ(0x5124U, fdes[0]->cfa_instructions_offset); - EXPECT_EQ(0x5200U, fdes[0]->cfa_instructions_end); - EXPECT_EQ(0x1500U, fdes[0]->pc_start); - EXPECT_EQ(0x1700U, fdes[0]->pc_end); - EXPECT_EQ(0U, fdes[0]->lsda_address); - EXPECT_TRUE(fdes[0]->cie != nullptr); - - EXPECT_EQ(0x5000U, fdes[1]->cie_offset); - EXPECT_EQ(0x5224U, fdes[1]->cfa_instructions_offset); - EXPECT_EQ(0x5300U, fdes[1]->cfa_instructions_end); - EXPECT_EQ(0x2500U, fdes[1]->pc_start); - EXPECT_EQ(0x2800U, fdes[1]->pc_end); - EXPECT_EQ(0U, fdes[1]->lsda_address); - EXPECT_TRUE(fdes[1]->cie != nullptr); - - EXPECT_EQ(0x5300U, fdes[2]->cie_offset); - EXPECT_EQ(0x5424U, fdes[2]->cfa_instructions_offset); - EXPECT_EQ(0x5500U, fdes[2]->cfa_instructions_end); - EXPECT_EQ(0x3500U, fdes[2]->pc_start); - EXPECT_EQ(0x3900U, fdes[2]->pc_end); - EXPECT_EQ(0U, fdes[2]->lsda_address); - EXPECT_TRUE(fdes[2]->cie != nullptr); - - EXPECT_EQ(0x5300U, fdes[3]->cie_offset); - EXPECT_EQ(0x5524U, fdes[3]->cfa_instructions_offset); - EXPECT_EQ(0x5600U, fdes[3]->cfa_instructions_end); - EXPECT_EQ(0x4500U, fdes[3]->pc_start); - EXPECT_EQ(0x4a00U, fdes[3]->pc_end); - EXPECT_EQ(0U, fdes[3]->lsda_address); - EXPECT_TRUE(fdes[3]->cie != nullptr); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetFdes64_after_GetFdeFromPc) { - SetFourFdes64(&this->memory_); - ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0)); - - const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x2600); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x2500U, fde->pc_start); - EXPECT_EQ(0x2800U, fde->pc_end); - - std::vector fdes; - this->debug_frame_->GetFdes(&fdes); - ASSERT_EQ(4U, fdes.size()); - - // Verify that they got added in the correct order. - EXPECT_EQ(0x1500U, fdes[0]->pc_start); - EXPECT_EQ(0x1700U, fdes[0]->pc_end); - EXPECT_EQ(0x2500U, fdes[1]->pc_start); - EXPECT_EQ(0x2800U, fdes[1]->pc_end); - EXPECT_EQ(0x3500U, fdes[2]->pc_start); - EXPECT_EQ(0x3900U, fdes[2]->pc_end); - EXPECT_EQ(0x4500U, fdes[3]->pc_start); - EXPECT_EQ(0x4a00U, fdes[3]->pc_end); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetFdes64_not_in_section) { - SetFourFdes64(&this->memory_); - ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x500, 0)); - - std::vector fdes; - this->debug_frame_->GetFdes(&fdes); - - ASSERT_EQ(3U, fdes.size()); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromPc64) { - SetFourFdes64(&this->memory_); - ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0)); - - const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x1600); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x1500U, fde->pc_start); - - fde = this->debug_frame_->GetFdeFromPc(0x2600); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x2500U, fde->pc_start); - - fde = this->debug_frame_->GetFdeFromPc(0x3600); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x3500U, fde->pc_start); - - fde = this->debug_frame_->GetFdeFromPc(0x4600); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x4500U, fde->pc_start); - - fde = this->debug_frame_->GetFdeFromPc(0); - ASSERT_TRUE(fde == nullptr); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromPc64_reverse) { - SetFourFdes64(&this->memory_); - ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0)); - - const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x4600); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x4500U, fde->pc_start); - - fde = this->debug_frame_->GetFdeFromPc(0x3600); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x3500U, fde->pc_start); - - fde = this->debug_frame_->GetFdeFromPc(0x2600); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x2500U, fde->pc_start); - - fde = this->debug_frame_->GetFdeFromPc(0x1600); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x1500U, fde->pc_start); - - fde = this->debug_frame_->GetFdeFromPc(0); - ASSERT_TRUE(fde == nullptr); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromPc64_not_in_section) { - SetFourFdes64(&this->memory_); - ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x500, 0)); - - const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x4600); - ASSERT_TRUE(fde == nullptr); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetCieFde32) { - SetCie32(&this->memory_, 0xf000, 0x100, std::vector{1, '\0', 4, 8, 0x20}); - SetFde32(&this->memory_, 0x14000, 0x20, 0xf000, 0x9000, 0x100); - - const DwarfFde* fde = this->debug_frame_->GetFdeFromOffset(0x14000); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x14010U, fde->cfa_instructions_offset); - EXPECT_EQ(0x14024U, fde->cfa_instructions_end); - EXPECT_EQ(0x9000U, fde->pc_start); - EXPECT_EQ(0x9100U, fde->pc_end); - EXPECT_EQ(0xf000U, fde->cie_offset); - EXPECT_EQ(0U, fde->lsda_address); - - ASSERT_TRUE(fde->cie != nullptr); - EXPECT_EQ(1U, fde->cie->version); - EXPECT_EQ(DW_EH_PE_sdata4, fde->cie->fde_address_encoding); - EXPECT_EQ(DW_EH_PE_omit, fde->cie->lsda_encoding); - EXPECT_EQ(0U, fde->cie->segment_size); - EXPECT_EQ(1U, fde->cie->augmentation_string.size()); - EXPECT_EQ('\0', fde->cie->augmentation_string[0]); - EXPECT_EQ(0U, fde->cie->personality_handler); - EXPECT_EQ(0xf00dU, fde->cie->cfa_instructions_offset); - EXPECT_EQ(0xf104U, fde->cie->cfa_instructions_end); - EXPECT_EQ(4U, fde->cie->code_alignment_factor); - EXPECT_EQ(8, fde->cie->data_alignment_factor); - EXPECT_EQ(0x20U, fde->cie->return_address_register); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetCieFde64) { - SetCie64(&this->memory_, 0x6000, 0x100, std::vector{1, '\0', 4, 8, 0x20}); - SetFde64(&this->memory_, 0x8000, 0x200, 0x6000, 0x5000, 0x300); - - const DwarfFde* fde = this->debug_frame_->GetFdeFromOffset(0x8000); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x8024U, fde->cfa_instructions_offset); - EXPECT_EQ(0x820cU, fde->cfa_instructions_end); - EXPECT_EQ(0x5000U, fde->pc_start); - EXPECT_EQ(0x5300U, fde->pc_end); - EXPECT_EQ(0x6000U, fde->cie_offset); - EXPECT_EQ(0U, fde->lsda_address); - - ASSERT_TRUE(fde->cie != nullptr); - EXPECT_EQ(1U, fde->cie->version); - EXPECT_EQ(DW_EH_PE_sdata8, fde->cie->fde_address_encoding); - EXPECT_EQ(DW_EH_PE_omit, fde->cie->lsda_encoding); - EXPECT_EQ(0U, fde->cie->segment_size); - EXPECT_EQ(1U, fde->cie->augmentation_string.size()); - EXPECT_EQ('\0', fde->cie->augmentation_string[0]); - EXPECT_EQ(0U, fde->cie->personality_handler); - EXPECT_EQ(0x6019U, fde->cie->cfa_instructions_offset); - EXPECT_EQ(0x610cU, fde->cie->cfa_instructions_end); - EXPECT_EQ(4U, fde->cie->code_alignment_factor); - EXPECT_EQ(8, fde->cie->data_alignment_factor); - EXPECT_EQ(0x20U, fde->cie->return_address_register); -} - -static void VerifyCieVersion(const DwarfCie* cie, uint8_t version, uint8_t segment_size, - uint8_t fde_encoding, uint64_t return_address, uint64_t start_offset, - uint64_t end_offset) { - EXPECT_EQ(version, cie->version); - EXPECT_EQ(fde_encoding, cie->fde_address_encoding); - EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding); - EXPECT_EQ(segment_size, cie->segment_size); - EXPECT_EQ(1U, cie->augmentation_string.size()); - EXPECT_EQ('\0', cie->augmentation_string[0]); - EXPECT_EQ(0U, cie->personality_handler); - EXPECT_EQ(4U, cie->code_alignment_factor); - EXPECT_EQ(8, cie->data_alignment_factor); - EXPECT_EQ(return_address, cie->return_address_register); - EXPECT_EQ(0x5000U + start_offset, cie->cfa_instructions_offset); - EXPECT_EQ(0x5000U + end_offset, cie->cfa_instructions_end); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset32_cie_cached) { - SetCie32(&this->memory_, 0x5000, 0x100, std::vector{1, '\0', 4, 8, 0x20}); - const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000); - EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode()); - ASSERT_TRUE(cie != nullptr); - VerifyCieVersion(cie, 1, 0, DW_EH_PE_sdata4, 0x20, 0xd, 0x104); - - std::vector zero(0x100, 0); - this->memory_.SetMemory(0x5000, zero); - cie = this->debug_frame_->GetCieFromOffset(0x5000); - EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode()); - ASSERT_TRUE(cie != nullptr); - VerifyCieVersion(cie, 1, 0, DW_EH_PE_sdata4, 0x20, 0xd, 0x104); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset64_cie_cached) { - SetCie64(&this->memory_, 0x5000, 0x100, std::vector{1, '\0', 4, 8, 0x20}); - const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000); - EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode()); - ASSERT_TRUE(cie != nullptr); - VerifyCieVersion(cie, 1, 0, DW_EH_PE_sdata8, 0x20, 0x19, 0x10c); - - std::vector zero(0x100, 0); - this->memory_.SetMemory(0x5000, zero); - cie = this->debug_frame_->GetCieFromOffset(0x5000); - EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode()); - ASSERT_TRUE(cie != nullptr); - VerifyCieVersion(cie, 1, 0, DW_EH_PE_sdata8, 0x20, 0x19, 0x10c); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset32_version1) { - SetCie32(&this->memory_, 0x5000, 0x100, std::vector{1, '\0', 4, 8, 0x20}); - const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000); - EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode()); - ASSERT_TRUE(cie != nullptr); - VerifyCieVersion(cie, 1, 0, DW_EH_PE_sdata4, 0x20, 0xd, 0x104); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset64_version1) { - SetCie64(&this->memory_, 0x5000, 0x100, std::vector{1, '\0', 4, 8, 0x20}); - const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000); - EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode()); - ASSERT_TRUE(cie != nullptr); - VerifyCieVersion(cie, 1, 0, DW_EH_PE_sdata8, 0x20, 0x19, 0x10c); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset32_version3) { - SetCie32(&this->memory_, 0x5000, 0x100, std::vector{3, '\0', 4, 8, 0x81, 3}); - const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000); - EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode()); - ASSERT_TRUE(cie != nullptr); - VerifyCieVersion(cie, 3, 0, DW_EH_PE_sdata4, 0x181, 0xe, 0x104); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset64_version3) { - SetCie64(&this->memory_, 0x5000, 0x100, std::vector{3, '\0', 4, 8, 0x81, 3}); - const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000); - EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode()); - ASSERT_TRUE(cie != nullptr); - VerifyCieVersion(cie, 3, 0, DW_EH_PE_sdata8, 0x181, 0x1a, 0x10c); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset32_version4) { - SetCie32(&this->memory_, 0x5000, 0x100, std::vector{4, '\0', 0, 10, 4, 8, 0x81, 3}); - const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000); - EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode()); - ASSERT_TRUE(cie != nullptr); - VerifyCieVersion(cie, 4, 10, DW_EH_PE_sdata4, 0x181, 0x10, 0x104); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset64_version4) { - SetCie64(&this->memory_, 0x5000, 0x100, std::vector{4, '\0', 0, 10, 4, 8, 0x81, 3}); - const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000); - EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode()); - ASSERT_TRUE(cie != nullptr); - VerifyCieVersion(cie, 4, 10, DW_EH_PE_sdata8, 0x181, 0x1c, 0x10c); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset32_version5) { - SetCie32(&this->memory_, 0x5000, 0x100, std::vector{5, '\0', 0, 10, 4, 8, 0x81, 3}); - const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000); - EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode()); - ASSERT_TRUE(cie != nullptr); - VerifyCieVersion(cie, 5, 10, DW_EH_PE_sdata4, 0x181, 0x10, 0x104); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset64_version5) { - SetCie64(&this->memory_, 0x5000, 0x100, std::vector{5, '\0', 0, 10, 4, 8, 0x81, 3}); - const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000); - EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode()); - ASSERT_TRUE(cie != nullptr); - VerifyCieVersion(cie, 5, 10, DW_EH_PE_sdata8, 0x181, 0x1c, 0x10c); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset_version_invalid) { - SetCie32(&this->memory_, 0x5000, 0x100, std::vector{0, '\0', 1, 2, 3, 4, 5, 6, 7}); - ASSERT_TRUE(this->debug_frame_->GetCieFromOffset(0x5000) == nullptr); - EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->debug_frame_->LastErrorCode()); - SetCie64(&this->memory_, 0x6000, 0x100, std::vector{0, '\0', 1, 2, 3, 4, 5, 6, 7}); - ASSERT_TRUE(this->debug_frame_->GetCieFromOffset(0x6000) == nullptr); - EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->debug_frame_->LastErrorCode()); - - SetCie32(&this->memory_, 0x7000, 0x100, std::vector{6, '\0', 1, 2, 3, 4, 5, 6, 7}); - ASSERT_TRUE(this->debug_frame_->GetCieFromOffset(0x7000) == nullptr); - EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->debug_frame_->LastErrorCode()); - SetCie64(&this->memory_, 0x8000, 0x100, std::vector{6, '\0', 1, 2, 3, 4, 5, 6, 7}); - ASSERT_TRUE(this->debug_frame_->GetCieFromOffset(0x8000) == nullptr); - EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->debug_frame_->LastErrorCode()); -} - -static void VerifyCieAugment(const DwarfCie* cie, uint64_t inst_offset, uint64_t inst_end) { - EXPECT_EQ(1U, cie->version); - EXPECT_EQ(DW_EH_PE_udata2, cie->fde_address_encoding); - EXPECT_EQ(DW_EH_PE_textrel | DW_EH_PE_udata2, cie->lsda_encoding); - EXPECT_EQ(0U, cie->segment_size); - EXPECT_EQ(5U, cie->augmentation_string.size()); - EXPECT_EQ('z', cie->augmentation_string[0]); - EXPECT_EQ('L', cie->augmentation_string[1]); - EXPECT_EQ('P', cie->augmentation_string[2]); - EXPECT_EQ('R', cie->augmentation_string[3]); - EXPECT_EQ('\0', cie->augmentation_string[4]); - EXPECT_EQ(0x12345678U, cie->personality_handler); - EXPECT_EQ(4U, cie->code_alignment_factor); - EXPECT_EQ(8, cie->data_alignment_factor); - EXPECT_EQ(0x10U, cie->return_address_register); - EXPECT_EQ(inst_offset, cie->cfa_instructions_offset); - EXPECT_EQ(inst_end, cie->cfa_instructions_end); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset32_augment) { - SetCie32(&this->memory_, 0x5000, 0x100, - std::vector{/* version */ 1, - /* augment string */ 'z', 'L', 'P', 'R', '\0', - /* code alignment factor */ 4, - /* data alignment factor */ 8, - /* return address register */ 0x10, - /* augment length */ 0xf, - /* L data */ DW_EH_PE_textrel | DW_EH_PE_udata2, - /* P data */ DW_EH_PE_udata4, 0x78, 0x56, 0x34, 0x12, - /* R data */ DW_EH_PE_udata2}); - - const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000); - ASSERT_TRUE(cie != nullptr); - VerifyCieAugment(cie, 0x5021, 0x5104); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset64_augment) { - SetCie64(&this->memory_, 0x5000, 0x100, - std::vector{/* version */ 1, - /* augment string */ 'z', 'L', 'P', 'R', '\0', - /* code alignment factor */ 4, - /* data alignment factor */ 8, - /* return address register */ 0x10, - /* augment length */ 0xf, - /* L data */ DW_EH_PE_textrel | DW_EH_PE_udata2, - /* P data */ DW_EH_PE_udata4, 0x78, 0x56, 0x34, 0x12, - /* R data */ DW_EH_PE_udata2}); - - const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000); - ASSERT_TRUE(cie != nullptr); - VerifyCieAugment(cie, 0x502d, 0x510c); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromOffset32_augment) { - SetCie32(&this->memory_, 0x5000, 0xfc, - std::vector{/* version */ 4, - /* augment string */ 'z', '\0', - /* address size */ 8, - /* segment size */ 0x10, - /* code alignment factor */ 16, - /* data alignment factor */ 32, - /* return address register */ 10, - /* augment length */ 0x0}); - - std::vector data{/* augment length */ 0x80, 0x3}; - SetFde32(&this->memory_, 0x5200, 0x300, 0x5000, 0x4300, 0x300, 0x10, &data); - - const DwarfFde* fde = this->debug_frame_->GetFdeFromOffset(0x5200); - ASSERT_TRUE(fde != nullptr); - ASSERT_TRUE(fde->cie != nullptr); - EXPECT_EQ(4U, fde->cie->version); - EXPECT_EQ(0x5000U, fde->cie_offset); - EXPECT_EQ(0x53a2U, fde->cfa_instructions_offset); - EXPECT_EQ(0x5504U, fde->cfa_instructions_end); - EXPECT_EQ(0x4300U, fde->pc_start); - EXPECT_EQ(0x4600U, fde->pc_end); - EXPECT_EQ(0U, fde->lsda_address); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromOffset64_augment) { - SetCie64(&this->memory_, 0x5000, 0xfc, - std::vector{/* version */ 4, - /* augment string */ 'z', '\0', - /* address size */ 8, - /* segment size */ 0x10, - /* code alignment factor */ 16, - /* data alignment factor */ 32, - /* return address register */ 10, - /* augment length */ 0x0}); - - std::vector data{/* augment length */ 0x80, 0x3}; - SetFde64(&this->memory_, 0x5200, 0x300, 0x5000, 0x4300, 0x300, 0x10, &data); - - const DwarfFde* fde = this->debug_frame_->GetFdeFromOffset(0x5200); - ASSERT_TRUE(fde != nullptr); - ASSERT_TRUE(fde->cie != nullptr); - EXPECT_EQ(4U, fde->cie->version); - EXPECT_EQ(0x5000U, fde->cie_offset); - EXPECT_EQ(0x53b6U, fde->cfa_instructions_offset); - EXPECT_EQ(0x550cU, fde->cfa_instructions_end); - EXPECT_EQ(0x4300U, fde->pc_start); - EXPECT_EQ(0x4600U, fde->pc_end); - EXPECT_EQ(0U, fde->lsda_address); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromOffset32_lsda_address) { - SetCie32(&this->memory_, 0x5000, 0xfc, - std::vector{/* version */ 1, - /* augment string */ 'z', 'L', '\0', - /* address size */ 8, - /* code alignment factor */ 16, - /* data alignment factor */ 32, - /* return address register */ 10, - /* augment length */ 0x2, - /* L data */ DW_EH_PE_udata2}); - - std::vector data{/* augment length */ 0x80, 0x3, - /* lsda address */ 0x20, 0x45}; - SetFde32(&this->memory_, 0x5200, 0x300, 0x5000, 0x4300, 0x300, 0, &data); - - const DwarfFde* fde = this->debug_frame_->GetFdeFromOffset(0x5200); - ASSERT_TRUE(fde != nullptr); - ASSERT_TRUE(fde->cie != nullptr); - EXPECT_EQ(1U, fde->cie->version); - EXPECT_EQ(0x5000U, fde->cie_offset); - EXPECT_EQ(0x5392U, fde->cfa_instructions_offset); - EXPECT_EQ(0x5504U, fde->cfa_instructions_end); - EXPECT_EQ(0x4300U, fde->pc_start); - EXPECT_EQ(0x4600U, fde->pc_end); - EXPECT_EQ(0x4520U, fde->lsda_address); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromOffset64_lsda_address) { - SetCie64(&this->memory_, 0x5000, 0xfc, - std::vector{/* version */ 1, - /* augment string */ 'z', 'L', '\0', - /* address size */ 8, - /* code alignment factor */ 16, - /* data alignment factor */ 32, - /* return address register */ 10, - /* augment length */ 0x2, - /* L data */ DW_EH_PE_udata2}); - - std::vector data{/* augment length */ 0x80, 0x3, - /* lsda address */ 0x20, 0x45}; - SetFde64(&this->memory_, 0x5200, 0x300, 0x5000, 0x4300, 0x300, 0, &data); - - const DwarfFde* fde = this->debug_frame_->GetFdeFromOffset(0x5200); - ASSERT_TRUE(fde != nullptr); - ASSERT_TRUE(fde->cie != nullptr); - EXPECT_EQ(1U, fde->cie->version); - EXPECT_EQ(0x5000U, fde->cie_offset); - EXPECT_EQ(0x53a6U, fde->cfa_instructions_offset); - EXPECT_EQ(0x550cU, fde->cfa_instructions_end); - EXPECT_EQ(0x4300U, fde->pc_start); - EXPECT_EQ(0x4600U, fde->pc_end); - EXPECT_EQ(0x4520U, fde->lsda_address); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromPc_interleaved) { - SetCie32(&this->memory_, 0x5000, 0xfc, std::vector{1, '\0', 0, 0, 1}); - - // FDE 0 (0x100 - 0x200) - SetFde32(&this->memory_, 0x5100, 0xfc, 0, 0x100, 0x100); - // FDE 1 (0x300 - 0x500) - SetFde32(&this->memory_, 0x5200, 0xfc, 0, 0x300, 0x200); - // FDE 2 (0x700 - 0x800) - SetFde32(&this->memory_, 0x5300, 0xfc, 0, 0x700, 0x100); - // FDE 3 (0xa00 - 0xb00) - SetFde32(&this->memory_, 0x5400, 0xfc, 0, 0xa00, 0x100); - // FDE 4 (0x100 - 0xb00) - SetFde32(&this->memory_, 0x5500, 0xfc, 0, 0x150, 0xa00); - // FDE 5 (0x50 - 0xa0) - SetFde32(&this->memory_, 0x5600, 0xfc, 0, 0x50, 0x50); - // FDE 6 (0x0 - 0x50) - SetFde32(&this->memory_, 0x5700, 0xfc, 0, 0, 0x50); - - this->debug_frame_->Init(0x5000, 0x800, 0); - - // Force reading all entries so no entries are found. - const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0xfffff); - ASSERT_TRUE(fde == nullptr); - - // 0x50 - 0xa0 FDE 5 - fde = this->debug_frame_->GetFdeFromPc(0x60); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x50U, fde->pc_start); - EXPECT_EQ(0xa0U, fde->pc_end); - - // 0x0 - 0x50 FDE 6 - fde = this->debug_frame_->GetFdeFromPc(0x10); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0U, fde->pc_start); - EXPECT_EQ(0x50U, fde->pc_end); - - // 0x100 - 0x200 FDE 0 - fde = this->debug_frame_->GetFdeFromPc(0x170); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x100U, fde->pc_start); - EXPECT_EQ(0x200U, fde->pc_end); - - // 0x200 - 0x300 FDE 4 - fde = this->debug_frame_->GetFdeFromPc(0x210); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x150U, fde->pc_start); - EXPECT_EQ(0xb50U, fde->pc_end); - - // 0x300 - 0x500 FDE 1 - fde = this->debug_frame_->GetFdeFromPc(0x310); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x300U, fde->pc_start); - EXPECT_EQ(0x500U, fde->pc_end); - - // 0x700 - 0x800 FDE 2 - fde = this->debug_frame_->GetFdeFromPc(0x790); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x700U, fde->pc_start); - EXPECT_EQ(0x800U, fde->pc_end); - - // 0x800 - 0x900 FDE 4 - fde = this->debug_frame_->GetFdeFromPc(0x850); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x150U, fde->pc_start); - EXPECT_EQ(0xb50U, fde->pc_end); - - // 0xa00 - 0xb00 FDE 3 - fde = this->debug_frame_->GetFdeFromPc(0xa35); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0xa00U, fde->pc_start); - EXPECT_EQ(0xb00U, fde->pc_end); - - // 0xb00 - 0xb50 FDE 4 - fde = this->debug_frame_->GetFdeFromPc(0xb20); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x150U, fde->pc_start); - EXPECT_EQ(0xb50U, fde->pc_end); -} - -TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromPc_overlap) { - SetCie32(&this->memory_, 0x5000, 0xfc, std::vector{1, '\0', 0, 0, 1}); - - // FDE 0 (0x100 - 0x200) - SetFde32(&this->memory_, 0x5100, 0xfc, 0, 0x100, 0x100); - // FDE 1 (0x50 - 0x550) - SetFde32(&this->memory_, 0x5200, 0xfc, 0, 0x50, 0x500); - // FDE 2 (0x00 - 0x800) - SetFde32(&this->memory_, 0x5300, 0xfc, 0, 0x0, 0x800); - - this->debug_frame_->Init(0x5000, 0x400, 0); - - // Force reading all entries so no entries are found. - const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0xfffff); - ASSERT_TRUE(fde == nullptr); - - // 0x0 - 0x50 FDE 2 - fde = this->debug_frame_->GetFdeFromPc(0x10); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x0U, fde->pc_start); - EXPECT_EQ(0x800U, fde->pc_end); - - // 0x50 - 0x100 FDE 1 - fde = this->debug_frame_->GetFdeFromPc(0x60); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x50U, fde->pc_start); - EXPECT_EQ(0x550U, fde->pc_end); - - // 0x100 - 0x200 FDE 0 - fde = this->debug_frame_->GetFdeFromPc(0x170); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x100U, fde->pc_start); - EXPECT_EQ(0x200U, fde->pc_end); - - // 0x200 - 0x550 FDE 1 - fde = this->debug_frame_->GetFdeFromPc(0x210); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x50U, fde->pc_start); - EXPECT_EQ(0x550U, fde->pc_end); - - // 0x550 - 0x800 FDE 2 - fde = this->debug_frame_->GetFdeFromPc(0x580); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x0U, fde->pc_start); - EXPECT_EQ(0x800U, fde->pc_end); - - fde = this->debug_frame_->GetFdeFromPc(0x810); - ASSERT_TRUE(fde == nullptr); -} - -REGISTER_TYPED_TEST_SUITE_P( - DwarfDebugFrameTest, GetFdes32, GetFdes32_after_GetFdeFromPc, GetFdes32_not_in_section, - GetFdeFromPc32, GetFdeFromPc32_reverse, GetFdeFromPc32_not_in_section, GetFdes64, - GetFdes64_after_GetFdeFromPc, GetFdes64_not_in_section, GetFdeFromPc64, GetFdeFromPc64_reverse, - GetFdeFromPc64_not_in_section, GetCieFde32, GetCieFde64, GetCieFromOffset32_cie_cached, - GetCieFromOffset64_cie_cached, GetCieFromOffset32_version1, GetCieFromOffset64_version1, - GetCieFromOffset32_version3, GetCieFromOffset64_version3, GetCieFromOffset32_version4, - GetCieFromOffset64_version4, GetCieFromOffset32_version5, GetCieFromOffset64_version5, - GetCieFromOffset_version_invalid, GetCieFromOffset32_augment, GetCieFromOffset64_augment, - GetFdeFromOffset32_augment, GetFdeFromOffset64_augment, GetFdeFromOffset32_lsda_address, - GetFdeFromOffset64_lsda_address, GetFdeFromPc_interleaved, GetFdeFromPc_overlap); - -typedef ::testing::Types DwarfDebugFrameTestTypes; -INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfDebugFrameTest, DwarfDebugFrameTestTypes); - -} // namespace unwindstack diff --git a/libunwindstack/tests/DwarfEhFrameTest.cpp b/libunwindstack/tests/DwarfEhFrameTest.cpp deleted file mode 100644 index 46a25a480..000000000 --- a/libunwindstack/tests/DwarfEhFrameTest.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2016 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 "DwarfEhFrame.h" -#include "DwarfEncoding.h" - -#include "LogFake.h" -#include "MemoryFake.h" - -namespace unwindstack { - -template -class DwarfEhFrameTest : public ::testing::Test { - protected: - void SetUp() override { - memory_.Clear(); - eh_frame_ = new DwarfEhFrame(&memory_); - ResetLogs(); - } - - void TearDown() override { delete eh_frame_; } - - MemoryFake memory_; - DwarfEhFrame* eh_frame_ = nullptr; -}; -TYPED_TEST_SUITE_P(DwarfEhFrameTest); - -// NOTE: All test class variables need to be referenced as this->. - -// Only verify different cie/fde format. All other DwarfSection corner -// cases are tested in DwarfDebugFrameTest.cpp. - -TYPED_TEST_P(DwarfEhFrameTest, GetFdeCieFromOffset32) { - // CIE 32 information. - this->memory_.SetData32(0x5000, 0xfc); - // Indicates this is a cie for eh_frame. - this->memory_.SetData32(0x5004, 0); - this->memory_.SetMemory(0x5008, std::vector{1, '\0', 16, 32, 1}); - - // FDE 32 information. - this->memory_.SetData32(0x5100, 0xfc); - this->memory_.SetData32(0x5104, 0x104); - this->memory_.SetData32(0x5108, 0x1500); - this->memory_.SetData32(0x510c, 0x200); - - const DwarfFde* fde = this->eh_frame_->GetFdeFromOffset(0x5100); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x5000U, fde->cie_offset); - EXPECT_EQ(0x5110U, fde->cfa_instructions_offset); - EXPECT_EQ(0x5200U, fde->cfa_instructions_end); - EXPECT_EQ(0x6608U, fde->pc_start); - EXPECT_EQ(0x6808U, fde->pc_end); - EXPECT_EQ(0U, fde->lsda_address); - - const DwarfCie* cie = fde->cie; - ASSERT_TRUE(cie != nullptr); - EXPECT_EQ(1U, cie->version); - EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding); - EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding); - EXPECT_EQ(0U, cie->segment_size); - EXPECT_EQ('\0', cie->augmentation_string[0]); - EXPECT_EQ(0U, cie->personality_handler); - EXPECT_EQ(0x500dU, cie->cfa_instructions_offset); - EXPECT_EQ(0x5100U, cie->cfa_instructions_end); - EXPECT_EQ(16U, cie->code_alignment_factor); - EXPECT_EQ(32U, cie->data_alignment_factor); - EXPECT_EQ(1U, cie->return_address_register); -} - -TYPED_TEST_P(DwarfEhFrameTest, GetFdeCieFromOffset64) { - // CIE 64 information. - this->memory_.SetData32(0x5000, 0xffffffff); - this->memory_.SetData64(0x5004, 0xfc); - // Indicates this is a cie for eh_frame. - this->memory_.SetData64(0x500c, 0); - this->memory_.SetMemory(0x5014, std::vector{1, '\0', 16, 32, 1}); - - // FDE 64 information. - this->memory_.SetData32(0x5100, 0xffffffff); - this->memory_.SetData64(0x5104, 0xfc); - this->memory_.SetData64(0x510c, 0x10c); - this->memory_.SetData64(0x5114, 0x1500); - this->memory_.SetData64(0x511c, 0x200); - - const DwarfFde* fde = this->eh_frame_->GetFdeFromOffset(0x5100); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x5000U, fde->cie_offset); - EXPECT_EQ(0x5124U, fde->cfa_instructions_offset); - EXPECT_EQ(0x5208U, fde->cfa_instructions_end); - EXPECT_EQ(0x6618U, fde->pc_start); - EXPECT_EQ(0x6818U, fde->pc_end); - EXPECT_EQ(0U, fde->lsda_address); - - const DwarfCie* cie = fde->cie; - ASSERT_TRUE(cie != nullptr); - EXPECT_EQ(1U, cie->version); - EXPECT_EQ(DW_EH_PE_sdata8, cie->fde_address_encoding); - EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding); - EXPECT_EQ(0U, cie->segment_size); - EXPECT_EQ('\0', cie->augmentation_string[0]); - EXPECT_EQ(0U, cie->personality_handler); - EXPECT_EQ(0x5019U, cie->cfa_instructions_offset); - EXPECT_EQ(0x5108U, cie->cfa_instructions_end); - EXPECT_EQ(16U, cie->code_alignment_factor); - EXPECT_EQ(32U, cie->data_alignment_factor); - EXPECT_EQ(1U, cie->return_address_register); -} - -REGISTER_TYPED_TEST_SUITE_P(DwarfEhFrameTest, GetFdeCieFromOffset32, GetFdeCieFromOffset64); - -typedef ::testing::Types DwarfEhFrameTestTypes; -INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfEhFrameTest, DwarfEhFrameTestTypes); - -} // namespace unwindstack diff --git a/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp b/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp deleted file mode 100644 index 6aa386764..000000000 --- a/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp +++ /dev/null @@ -1,557 +0,0 @@ -/* - * Copyright (C) 2016 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 "DwarfEhFrameWithHdr.h" -#include "DwarfEncoding.h" - -#include "LogFake.h" -#include "MemoryFake.h" - -namespace unwindstack { - -template -class TestDwarfEhFrameWithHdr : public DwarfEhFrameWithHdr { - public: - TestDwarfEhFrameWithHdr(Memory* memory) : DwarfEhFrameWithHdr(memory) {} - ~TestDwarfEhFrameWithHdr() = default; - - void TestSetTableEncoding(uint8_t encoding) { this->table_encoding_ = encoding; } - void TestSetHdrEntriesOffset(uint64_t offset) { this->hdr_entries_offset_ = offset; } - void TestSetHdrEntriesDataOffset(uint64_t offset) { this->hdr_entries_data_offset_ = offset; } - void TestSetTableEntrySize(size_t size) { this->table_entry_size_ = size; } - - void TestSetFdeCount(uint64_t count) { this->fde_count_ = count; } - void TestSetFdeInfo(uint64_t index, const typename DwarfEhFrameWithHdr::FdeInfo& info) { - this->fde_info_[index] = info; - } - - uint8_t TestGetVersion() { return this->version_; } - uint8_t TestGetTableEncoding() { return this->table_encoding_; } - uint64_t TestGetTableEntrySize() { return this->table_entry_size_; } - uint64_t TestGetFdeCount() { return this->fde_count_; } - uint64_t TestGetHdrEntriesOffset() { return this->hdr_entries_offset_; } - uint64_t TestGetHdrEntriesDataOffset() { return this->hdr_entries_data_offset_; } -}; - -template -class DwarfEhFrameWithHdrTest : public ::testing::Test { - protected: - void SetUp() override { - memory_.Clear(); - eh_frame_ = new TestDwarfEhFrameWithHdr(&memory_); - ResetLogs(); - } - - void TearDown() override { delete eh_frame_; } - - MemoryFake memory_; - TestDwarfEhFrameWithHdr* eh_frame_ = nullptr; -}; -TYPED_TEST_SUITE_P(DwarfEhFrameWithHdrTest); - -// NOTE: All test class variables need to be referenced as this->. - -TYPED_TEST_P(DwarfEhFrameWithHdrTest, Init) { - this->memory_.SetMemory( - 0x1000, std::vector{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4, DW_EH_PE_sdata4}); - this->memory_.SetData16(0x1004, 0x500); - this->memory_.SetData32(0x1006, 126); - - ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0)); - EXPECT_EQ(1U, this->eh_frame_->TestGetVersion()); - EXPECT_EQ(DW_EH_PE_sdata4, this->eh_frame_->TestGetTableEncoding()); - EXPECT_EQ(4U, this->eh_frame_->TestGetTableEntrySize()); - EXPECT_EQ(126U, this->eh_frame_->TestGetFdeCount()); - EXPECT_EQ(0x100aU, this->eh_frame_->TestGetHdrEntriesOffset()); - EXPECT_EQ(0x1000U, this->eh_frame_->TestGetHdrEntriesDataOffset()); - - // Verify a zero table entry size fails to init. - this->memory_.SetData8(0x1003, 0x1); - ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100, 0)); - ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->LastErrorCode()); - // Reset the value back to the original. - this->memory_.SetData8(0x1003, DW_EH_PE_sdata4); - - // Verify a zero fde count fails to init. - this->memory_.SetData32(0x1006, 0); - ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100, 0)); - ASSERT_EQ(DWARF_ERROR_NO_FDES, this->eh_frame_->LastErrorCode()); - - // Verify an unexpected version will cause a fail. - this->memory_.SetData32(0x1006, 126); - this->memory_.SetData8(0x1000, 0); - ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100, 0)); - ASSERT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->eh_frame_->LastErrorCode()); - this->memory_.SetData8(0x1000, 2); - ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100, 0)); - ASSERT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->eh_frame_->LastErrorCode()); -} - -TYPED_TEST_P(DwarfEhFrameWithHdrTest, Init_non_zero_load_bias) { - this->memory_.SetMemory(0x1000, std::vector{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4, - DW_EH_PE_pcrel | DW_EH_PE_sdata4}); - this->memory_.SetData16(0x1004, 0x500); - this->memory_.SetData32(0x1006, 1); - this->memory_.SetData32(0x100a, 0x2500); - this->memory_.SetData32(0x100e, 0x1400); - - // CIE 32 information. - this->memory_.SetData32(0x1300, 0xfc); - this->memory_.SetData32(0x1304, 0); - this->memory_.SetMemory(0x1308, std::vector{1, 'z', 'R', '\0', 0, 0, 0, 0, 0x1b}); - - // FDE 32 information. - this->memory_.SetData32(0x1400, 0xfc); - this->memory_.SetData32(0x1404, 0x104); - this->memory_.SetData32(0x1408, 0x10f8); - this->memory_.SetData32(0x140c, 0x200); - this->memory_.SetData16(0x1410, 0); - - ASSERT_TRUE(this->eh_frame_->EhFrameInit(0x1300, 0x200, 0x2000)); - ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0x2000)); - EXPECT_EQ(1U, this->eh_frame_->TestGetVersion()); - EXPECT_EQ(0x1b, this->eh_frame_->TestGetTableEncoding()); - EXPECT_EQ(4U, this->eh_frame_->TestGetTableEntrySize()); - EXPECT_EQ(1U, this->eh_frame_->TestGetFdeCount()); - EXPECT_EQ(0x100aU, this->eh_frame_->TestGetHdrEntriesOffset()); - EXPECT_EQ(0x1000U, this->eh_frame_->TestGetHdrEntriesDataOffset()); - - const DwarfFde* fde = this->eh_frame_->GetFdeFromPc(0x4600); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x4500U, fde->pc_start); - EXPECT_EQ(0x4700U, fde->pc_end); -} - -TYPED_TEST_P(DwarfEhFrameWithHdrTest, Init_non_zero_load_bias_different_from_eh_frame_bias) { - this->memory_.SetMemory(0x1000, std::vector{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4, - DW_EH_PE_pcrel | DW_EH_PE_sdata4}); - this->memory_.SetData16(0x1004, 0x500); - this->memory_.SetData32(0x1006, 1); - this->memory_.SetData32(0x100a, 0x2500); - this->memory_.SetData32(0x100e, 0x1400); - - // CIE 32 information. - this->memory_.SetData32(0x1300, 0xfc); - this->memory_.SetData32(0x1304, 0); - this->memory_.SetMemory(0x1308, std::vector{1, 'z', 'R', '\0', 0, 0, 0, 0, 0x1b}); - - // FDE 32 information. - this->memory_.SetData32(0x1400, 0xfc); - this->memory_.SetData32(0x1404, 0x104); - this->memory_.SetData32(0x1408, 0x20f8); - this->memory_.SetData32(0x140c, 0x200); - this->memory_.SetData16(0x1410, 0); - - ASSERT_TRUE(this->eh_frame_->EhFrameInit(0x1300, 0x200, 0x1000)); - ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0x2000)); - EXPECT_EQ(1U, this->eh_frame_->TestGetVersion()); - EXPECT_EQ(0x1b, this->eh_frame_->TestGetTableEncoding()); - EXPECT_EQ(4U, this->eh_frame_->TestGetTableEntrySize()); - EXPECT_EQ(1U, this->eh_frame_->TestGetFdeCount()); - EXPECT_EQ(0x100aU, this->eh_frame_->TestGetHdrEntriesOffset()); - EXPECT_EQ(0x1000U, this->eh_frame_->TestGetHdrEntriesDataOffset()); - - const DwarfFde* fde = this->eh_frame_->GetFdeFromPc(0x4600); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x4500U, fde->pc_start); - EXPECT_EQ(0x4700U, fde->pc_end); -} - -TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeFromPc_wtih_empty_fde) { - this->memory_.SetMemory(0x1000, std::vector{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4, - DW_EH_PE_pcrel | DW_EH_PE_sdata4}); - this->memory_.SetData16(0x1004, 0x500); - this->memory_.SetData32(0x1006, 1); - this->memory_.SetData32(0x100a, 0x2500); - this->memory_.SetData32(0x100e, 0x1400); - - // CIE 32 information. - this->memory_.SetData32(0x1300, 0xfc); - this->memory_.SetData32(0x1304, 0); - this->memory_.SetMemory(0x1308, std::vector{1, 'z', 'R', '\0', 0, 0, 0, 0, 0x1b}); - - // FDE 32 information. - this->memory_.SetData32(0x1400, 0xfc); - this->memory_.SetData32(0x1404, 0x104); - this->memory_.SetData32(0x1408, 0x30f8); - this->memory_.SetData32(0x140c, 0); - this->memory_.SetData16(0x1410, 0); - - // FDE 32 information. - this->memory_.SetData32(0x1500, 0xfc); - this->memory_.SetData32(0x1504, 0x204); - this->memory_.SetData32(0x1508, 0x2ff8); - this->memory_.SetData32(0x150c, 0x200); - this->memory_.SetData16(0x1510, 0); - - ASSERT_TRUE(this->eh_frame_->EhFrameInit(0x1300, 0x300, 0)); - ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0)); - - const DwarfFde* fde = this->eh_frame_->GetFdeFromPc(0x4600); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x4500U, fde->pc_start); - EXPECT_EQ(0x4700U, fde->pc_end); -} - -TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdes_with_empty_fde) { - this->memory_.SetMemory(0x1000, std::vector{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4, - DW_EH_PE_pcrel | DW_EH_PE_sdata4}); - this->memory_.SetData16(0x1004, 0x500); - this->memory_.SetData32(0x1006, 1); - this->memory_.SetData32(0x100a, 0x2500); - this->memory_.SetData32(0x100e, 0x1400); - - // CIE 32 information. - this->memory_.SetData32(0x1300, 0xfc); - this->memory_.SetData32(0x1304, 0); - this->memory_.SetMemory(0x1308, std::vector{1, 'z', 'R', '\0', 0, 0, 0, 0, 0x1b}); - - // FDE 32 information. - this->memory_.SetData32(0x1400, 0xfc); - this->memory_.SetData32(0x1404, 0x104); - this->memory_.SetData32(0x1408, 0x30f8); - this->memory_.SetData32(0x140c, 0); - this->memory_.SetData16(0x1410, 0); - - // FDE 32 information. - this->memory_.SetData32(0x1500, 0xfc); - this->memory_.SetData32(0x1504, 0x204); - this->memory_.SetData32(0x1508, 0x2ff8); - this->memory_.SetData32(0x150c, 0x200); - this->memory_.SetData16(0x1510, 0); - - ASSERT_TRUE(this->eh_frame_->EhFrameInit(0x1300, 0x300, 0)); - ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0)); - - std::vector fdes; - this->eh_frame_->GetFdes(&fdes); - ASSERT_FALSE(fdes.empty()); - ASSERT_EQ(1U, fdes.size()); - EXPECT_EQ(0x4500U, fdes[0]->pc_start); - EXPECT_EQ(0x4700U, fdes[0]->pc_end); -} - -TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdes) { - this->memory_.SetMemory( - 0x1000, std::vector{1, DW_EH_PE_udata2, DW_EH_PE_udata4, DW_EH_PE_sdata4}); - this->memory_.SetData16(0x1004, 0x500); - this->memory_.SetData32(0x1006, 4); - - // Header information. - this->memory_.SetData32(0x100a, 0x4600); - this->memory_.SetData32(0x100e, 0x1500); - this->memory_.SetData32(0x1012, 0x5500); - this->memory_.SetData32(0x1016, 0x1400); - this->memory_.SetData32(0x101a, 0x6800); - this->memory_.SetData32(0x101e, 0x1700); - this->memory_.SetData32(0x1022, 0x7700); - this->memory_.SetData32(0x1026, 0x1600); - - // CIE 32 information. - this->memory_.SetData32(0x1300, 0xfc); - this->memory_.SetData32(0x1304, 0); - this->memory_.SetMemory(0x1308, std::vector{1, '\0', 0, 0, 0}); - - // FDE 32 information. - // pc 0x5500 - 0x5700 - this->memory_.SetData32(0x1400, 0xfc); - this->memory_.SetData32(0x1404, 0x104); - this->memory_.SetData32(0x1408, 0x40f8); - this->memory_.SetData32(0x140c, 0x200); - - // pc 0x4600 - 0x4800 - this->memory_.SetData32(0x1500, 0xfc); - this->memory_.SetData32(0x1504, 0x204); - this->memory_.SetData32(0x1508, 0x30f8); - this->memory_.SetData32(0x150c, 0x200); - - // pc 0x7700 - 0x7900 - this->memory_.SetData32(0x1600, 0xfc); - this->memory_.SetData32(0x1604, 0x304); - this->memory_.SetData32(0x1608, 0x60f8); - this->memory_.SetData32(0x160c, 0x200); - - // pc 0x6800 - 0x6a00 - this->memory_.SetData32(0x1700, 0xfc); - this->memory_.SetData32(0x1704, 0x404); - this->memory_.SetData32(0x1708, 0x50f8); - this->memory_.SetData32(0x170c, 0x200); - - ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0)); - - std::vector fdes; - this->eh_frame_->GetFdes(&fdes); - ASSERT_EQ(4U, fdes.size()); - - EXPECT_EQ(0x4600U, fdes[0]->pc_start); - EXPECT_EQ(0x4800U, fdes[0]->pc_end); - EXPECT_EQ(0x5500U, fdes[1]->pc_start); - EXPECT_EQ(0x5700U, fdes[1]->pc_end); - EXPECT_EQ(0x6800U, fdes[2]->pc_start); - EXPECT_EQ(0x6a00U, fdes[2]->pc_end); - EXPECT_EQ(0x7700U, fdes[3]->pc_start); - EXPECT_EQ(0x7900U, fdes[3]->pc_end); -} - -TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_expect_cache_fail) { - this->eh_frame_->TestSetTableEntrySize(0x10); - this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); - this->eh_frame_->TestSetHdrEntriesOffset(0x1000); - - ASSERT_TRUE(this->eh_frame_->GetFdeInfoFromIndex(0) == nullptr); - ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->eh_frame_->LastErrorCode()); - EXPECT_EQ(0x1000U, this->eh_frame_->LastErrorAddress()); - ASSERT_TRUE(this->eh_frame_->GetFdeInfoFromIndex(0) == nullptr); - ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->eh_frame_->LastErrorCode()); - EXPECT_EQ(0x1000U, this->eh_frame_->LastErrorAddress()); -} - -// We are assuming that pc rel, is really relative to the load_bias. -TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_read_pcrel) { - this->eh_frame_->TestSetTableEncoding(DW_EH_PE_pcrel | DW_EH_PE_udata4); - this->eh_frame_->TestSetHdrEntriesOffset(0x1000); - this->eh_frame_->TestSetHdrEntriesDataOffset(0x3000); - this->eh_frame_->TestSetTableEntrySize(0x10); - - this->memory_.SetData32(0x1040, 0x340); - this->memory_.SetData32(0x1044, 0x500); - - auto info = this->eh_frame_->GetFdeInfoFromIndex(2); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(0x340U, info->pc); - EXPECT_EQ(0x500U, info->offset); -} - -TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_read_datarel) { - this->eh_frame_->TestSetTableEncoding(DW_EH_PE_datarel | DW_EH_PE_udata4); - this->eh_frame_->TestSetHdrEntriesOffset(0x1000); - this->eh_frame_->TestSetHdrEntriesDataOffset(0x3000); - this->eh_frame_->TestSetTableEntrySize(0x10); - - this->memory_.SetData32(0x1040, 0x340); - this->memory_.SetData32(0x1044, 0x500); - - auto info = this->eh_frame_->GetFdeInfoFromIndex(2); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(0x3340U, info->pc); - EXPECT_EQ(0x3500U, info->offset); -} - -TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_cached) { - this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); - this->eh_frame_->TestSetHdrEntriesOffset(0x1000); - this->eh_frame_->TestSetTableEntrySize(0x10); - - this->memory_.SetData32(0x1040, 0x340); - this->memory_.SetData32(0x1044, 0x500); - - auto info = this->eh_frame_->GetFdeInfoFromIndex(2); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(0x340U, info->pc); - EXPECT_EQ(0x500U, info->offset); - - // Clear the memory so that this will fail if it doesn't read cached data. - this->memory_.Clear(); - - info = this->eh_frame_->GetFdeInfoFromIndex(2); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(0x340U, info->pc); - EXPECT_EQ(0x500U, info->offset); -} - -TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_verify) { - this->eh_frame_->TestSetTableEntrySize(0x10); - - typename DwarfEhFrameWithHdr::FdeInfo info; - for (size_t i = 0; i < 10; i++) { - info.pc = 0x1000 * (i + 1); - info.offset = 0x5000 + i * 0x20; - this->eh_frame_->TestSetFdeInfo(i, info); - } - - uint64_t fde_offset; - this->eh_frame_->TestSetFdeCount(10); - EXPECT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x100, &fde_offset)); - // Not an error, just not found. - ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode()); - // Even number of elements. - for (size_t i = 0; i < 10; i++) { - SCOPED_TRACE(testing::Message() << "Failed at index " << i); - TypeParam pc = 0x1000 * (i + 1); - EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc, &fde_offset)); - EXPECT_EQ(0x5000 + i * 0x20, fde_offset); - EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset)); - EXPECT_EQ(0x5000 + i * 0x20, fde_offset); - EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset)); - EXPECT_EQ(0x5000 + i * 0x20, fde_offset); - } - - // Odd number of elements. - this->eh_frame_->TestSetFdeCount(9); - for (size_t i = 0; i < 9; i++) { - SCOPED_TRACE(testing::Message() << "Failed at index " << i); - TypeParam pc = 0x1000 * (i + 1); - EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc, &fde_offset)); - EXPECT_EQ(0x5000 + i * 0x20, fde_offset); - EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset)); - EXPECT_EQ(0x5000 + i * 0x20, fde_offset); - EXPECT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset)); - EXPECT_EQ(0x5000 + i * 0x20, fde_offset); - } -} - -TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_index_fail) { - this->eh_frame_->TestSetTableEntrySize(0x10); - this->eh_frame_->TestSetFdeCount(10); - - uint64_t fde_offset; - EXPECT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x1000, &fde_offset)); -} - -TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_fail_fde_count) { - this->eh_frame_->TestSetFdeCount(0); - - uint64_t fde_offset; - ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x100, &fde_offset)); - ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode()); -} - -TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_search) { - this->eh_frame_->TestSetTableEntrySize(16); - this->eh_frame_->TestSetFdeCount(10); - - typename DwarfEhFrameWithHdr::FdeInfo info; - info.pc = 0x550; - info.offset = 0x10500; - this->eh_frame_->TestSetFdeInfo(5, info); - info.pc = 0x750; - info.offset = 0x10700; - this->eh_frame_->TestSetFdeInfo(7, info); - info.pc = 0x850; - info.offset = 0x10800; - this->eh_frame_->TestSetFdeInfo(8, info); - - uint64_t fde_offset; - ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(0x800, &fde_offset)); - EXPECT_EQ(0x10700U, fde_offset); -} - -TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetCieFde32) { - // CIE 32 information. - this->memory_.SetData32(0xf000, 0x100); - this->memory_.SetData32(0xf004, 0); - this->memory_.SetMemory(0xf008, std::vector{1, '\0', 4, 8, 0x20}); - - // FDE 32 information. - this->memory_.SetData32(0x14000, 0x20); - this->memory_.SetData32(0x14004, 0x5004); - this->memory_.SetData32(0x14008, 0x9000); - this->memory_.SetData32(0x1400c, 0x100); - - const DwarfFde* fde = this->eh_frame_->GetFdeFromOffset(0x14000); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x14010U, fde->cfa_instructions_offset); - EXPECT_EQ(0x14024U, fde->cfa_instructions_end); - EXPECT_EQ(0x1d008U, fde->pc_start); - EXPECT_EQ(0x1d108U, fde->pc_end); - EXPECT_EQ(0xf000U, fde->cie_offset); - EXPECT_EQ(0U, fde->lsda_address); - - ASSERT_TRUE(fde->cie != nullptr); - EXPECT_EQ(1U, fde->cie->version); - EXPECT_EQ(DW_EH_PE_sdata4, fde->cie->fde_address_encoding); - EXPECT_EQ(DW_EH_PE_omit, fde->cie->lsda_encoding); - EXPECT_EQ(0U, fde->cie->segment_size); - EXPECT_EQ(1U, fde->cie->augmentation_string.size()); - EXPECT_EQ('\0', fde->cie->augmentation_string[0]); - EXPECT_EQ(0U, fde->cie->personality_handler); - EXPECT_EQ(0xf00dU, fde->cie->cfa_instructions_offset); - EXPECT_EQ(0xf104U, fde->cie->cfa_instructions_end); - EXPECT_EQ(4U, fde->cie->code_alignment_factor); - EXPECT_EQ(8, fde->cie->data_alignment_factor); - EXPECT_EQ(0x20U, fde->cie->return_address_register); -} - -TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetCieFde64) { - // CIE 64 information. - this->memory_.SetData32(0x6000, 0xffffffff); - this->memory_.SetData64(0x6004, 0x100); - this->memory_.SetData64(0x600c, 0); - this->memory_.SetMemory(0x6014, std::vector{1, '\0', 4, 8, 0x20}); - - // FDE 64 information. - this->memory_.SetData32(0x8000, 0xffffffff); - this->memory_.SetData64(0x8004, 0x200); - this->memory_.SetData64(0x800c, 0x200c); - this->memory_.SetData64(0x8014, 0x5000); - this->memory_.SetData64(0x801c, 0x300); - - const DwarfFde* fde = this->eh_frame_->GetFdeFromOffset(0x8000); - ASSERT_TRUE(fde != nullptr); - EXPECT_EQ(0x8024U, fde->cfa_instructions_offset); - EXPECT_EQ(0x820cU, fde->cfa_instructions_end); - EXPECT_EQ(0xd018U, fde->pc_start); - EXPECT_EQ(0xd318U, fde->pc_end); - EXPECT_EQ(0x6000U, fde->cie_offset); - EXPECT_EQ(0U, fde->lsda_address); - - ASSERT_TRUE(fde->cie != nullptr); - EXPECT_EQ(1U, fde->cie->version); - EXPECT_EQ(DW_EH_PE_sdata8, fde->cie->fde_address_encoding); - EXPECT_EQ(DW_EH_PE_omit, fde->cie->lsda_encoding); - EXPECT_EQ(0U, fde->cie->segment_size); - EXPECT_EQ(1U, fde->cie->augmentation_string.size()); - EXPECT_EQ('\0', fde->cie->augmentation_string[0]); - EXPECT_EQ(0U, fde->cie->personality_handler); - EXPECT_EQ(0x6019U, fde->cie->cfa_instructions_offset); - EXPECT_EQ(0x610cU, fde->cie->cfa_instructions_end); - EXPECT_EQ(4U, fde->cie->code_alignment_factor); - EXPECT_EQ(8, fde->cie->data_alignment_factor); - EXPECT_EQ(0x20U, fde->cie->return_address_register); -} - -TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeFromPc_fde_not_found) { - this->eh_frame_->TestSetTableEntrySize(16); - this->eh_frame_->TestSetFdeCount(1); - - typename DwarfEhFrameWithHdr::FdeInfo info; - info.pc = 0x550; - info.offset = 0x10500; - this->eh_frame_->TestSetFdeInfo(0, info); - - ASSERT_EQ(nullptr, this->eh_frame_->GetFdeFromPc(0x800)); -} - -REGISTER_TYPED_TEST_SUITE_P(DwarfEhFrameWithHdrTest, Init, Init_non_zero_load_bias, - Init_non_zero_load_bias_different_from_eh_frame_bias, - GetFdeFromPc_wtih_empty_fde, GetFdes_with_empty_fde, GetFdes, - GetFdeInfoFromIndex_expect_cache_fail, GetFdeInfoFromIndex_read_pcrel, - GetFdeInfoFromIndex_read_datarel, GetFdeInfoFromIndex_cached, - GetFdeOffsetFromPc_verify, GetFdeOffsetFromPc_index_fail, - GetFdeOffsetFromPc_fail_fde_count, GetFdeOffsetFromPc_search, - GetCieFde32, GetCieFde64, GetFdeFromPc_fde_not_found); - -typedef ::testing::Types DwarfEhFrameWithHdrTestTypes; -INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfEhFrameWithHdrTest, DwarfEhFrameWithHdrTestTypes); - -} // namespace unwindstack diff --git a/libunwindstack/tests/DwarfMemoryTest.cpp b/libunwindstack/tests/DwarfMemoryTest.cpp deleted file mode 100644 index 650e965b2..000000000 --- a/libunwindstack/tests/DwarfMemoryTest.cpp +++ /dev/null @@ -1,545 +0,0 @@ -/* - * Copyright (C) 2017 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 "MemoryFake.h" - -namespace unwindstack { - -class DwarfMemoryTest : public ::testing::Test { - protected: - void SetUp() override { - memory_.Clear(); - dwarf_mem_.reset(new DwarfMemory(&memory_)); - } - - template - void GetEncodedSizeTest(uint8_t value, size_t expected); - template - void ReadEncodedValue_omit(); - template - void ReadEncodedValue_leb128(); - template - void ReadEncodedValue_data1(); - template - void ReadEncodedValue_data2(); - template - void ReadEncodedValue_data4(); - template - void ReadEncodedValue_data8(); - template - void ReadEncodedValue_non_zero_adjust(); - template - void ReadEncodedValue_overflow(); - template - void ReadEncodedValue_high_bit_set(); - template - void ReadEncodedValue_all(); - - MemoryFake memory_; - std::unique_ptr dwarf_mem_; -}; - -TEST_F(DwarfMemoryTest, ReadBytes) { - memory_.SetMemory(0, std::vector{0x10, 0x18, 0xff, 0xfe}); - - uint8_t byte; - ASSERT_TRUE(dwarf_mem_->ReadBytes(&byte, 1)); - ASSERT_EQ(0x10U, byte); - ASSERT_TRUE(dwarf_mem_->ReadBytes(&byte, 1)); - ASSERT_EQ(0x18U, byte); - ASSERT_TRUE(dwarf_mem_->ReadBytes(&byte, 1)); - ASSERT_EQ(0xffU, byte); - ASSERT_TRUE(dwarf_mem_->ReadBytes(&byte, 1)); - ASSERT_EQ(0xfeU, byte); - ASSERT_EQ(4U, dwarf_mem_->cur_offset()); - - dwarf_mem_->set_cur_offset(2); - ASSERT_TRUE(dwarf_mem_->ReadBytes(&byte, 1)); - ASSERT_EQ(0xffU, byte); - ASSERT_EQ(3U, dwarf_mem_->cur_offset()); -} - -TEST_F(DwarfMemoryTest, ReadSigned_check) { - uint64_t value; - - // Signed 8 byte reads. - memory_.SetData8(0, static_cast(-10)); - memory_.SetData8(1, 200); - ASSERT_TRUE(dwarf_mem_->ReadSigned(&value)); - ASSERT_EQ(static_cast(-10), static_cast(value)); - ASSERT_TRUE(dwarf_mem_->ReadSigned(&value)); - ASSERT_EQ(static_cast(200), static_cast(value)); - - // Signed 16 byte reads. - memory_.SetData16(0x10, static_cast(-1000)); - memory_.SetData16(0x12, 50100); - dwarf_mem_->set_cur_offset(0x10); - ASSERT_TRUE(dwarf_mem_->ReadSigned(&value)); - ASSERT_EQ(static_cast(-1000), static_cast(value)); - ASSERT_TRUE(dwarf_mem_->ReadSigned(&value)); - ASSERT_EQ(static_cast(50100), static_cast(value)); - - // Signed 32 byte reads. - memory_.SetData32(0x100, static_cast(-1000000000)); - memory_.SetData32(0x104, 3000000000); - dwarf_mem_->set_cur_offset(0x100); - ASSERT_TRUE(dwarf_mem_->ReadSigned(&value)); - ASSERT_EQ(static_cast(-1000000000), static_cast(value)); - ASSERT_TRUE(dwarf_mem_->ReadSigned(&value)); - ASSERT_EQ(static_cast(3000000000), static_cast(value)); - - // Signed 64 byte reads. - memory_.SetData64(0x200, static_cast(-2000000000000LL)); - memory_.SetData64(0x208, 5000000000000LL); - dwarf_mem_->set_cur_offset(0x200); - ASSERT_TRUE(dwarf_mem_->ReadSigned(&value)); - ASSERT_EQ(static_cast(-2000000000000), static_cast(value)); - ASSERT_TRUE(dwarf_mem_->ReadSigned(&value)); - ASSERT_EQ(static_cast(5000000000000), static_cast(value)); -} - -TEST_F(DwarfMemoryTest, ReadULEB128) { - memory_.SetMemory(0, std::vector{0x01, 0x80, 0x24, 0xff, 0xc3, 0xff, 0x7f}); - - uint64_t value; - ASSERT_TRUE(dwarf_mem_->ReadULEB128(&value)); - ASSERT_EQ(1U, dwarf_mem_->cur_offset()); - ASSERT_EQ(1U, value); - - ASSERT_TRUE(dwarf_mem_->ReadULEB128(&value)); - ASSERT_EQ(3U, dwarf_mem_->cur_offset()); - ASSERT_EQ(0x1200U, value); - - ASSERT_TRUE(dwarf_mem_->ReadULEB128(&value)); - ASSERT_EQ(7U, dwarf_mem_->cur_offset()); - ASSERT_EQ(0xfffe1ffU, value); -} - -TEST_F(DwarfMemoryTest, ReadSLEB128) { - memory_.SetMemory(0, std::vector{0x06, 0x40, 0x82, 0x34, 0x89, 0x64, 0xf9, 0xc3, 0x8f, - 0x2f, 0xbf, 0xc3, 0xf7, 0x5f}); - - int64_t value; - ASSERT_TRUE(dwarf_mem_->ReadSLEB128(&value)); - ASSERT_EQ(1U, dwarf_mem_->cur_offset()); - ASSERT_EQ(6U, value); - - ASSERT_TRUE(dwarf_mem_->ReadSLEB128(&value)); - ASSERT_EQ(2U, dwarf_mem_->cur_offset()); - ASSERT_EQ(0xffffffffffffffc0ULL, static_cast(value)); - - ASSERT_TRUE(dwarf_mem_->ReadSLEB128(&value)); - ASSERT_EQ(4U, dwarf_mem_->cur_offset()); - ASSERT_EQ(0x1a02U, value); - - ASSERT_TRUE(dwarf_mem_->ReadSLEB128(&value)); - ASSERT_EQ(6U, dwarf_mem_->cur_offset()); - ASSERT_EQ(0xfffffffffffff209ULL, static_cast(value)); - - ASSERT_TRUE(dwarf_mem_->ReadSLEB128(&value)); - ASSERT_EQ(10U, dwarf_mem_->cur_offset()); - ASSERT_EQ(0x5e3e1f9U, value); - - ASSERT_TRUE(dwarf_mem_->ReadSLEB128(&value)); - ASSERT_EQ(14U, dwarf_mem_->cur_offset()); - ASSERT_EQ(0xfffffffffbfde1bfULL, static_cast(value)); -} - -template -void DwarfMemoryTest::GetEncodedSizeTest(uint8_t value, size_t expected) { - for (size_t i = 0; i < 16; i++) { - uint8_t encoding = (i << 4) | value; - ASSERT_EQ(expected, dwarf_mem_->GetEncodedSize(encoding)) - << "encoding 0x" << std::hex << static_cast(encoding) << " test value 0x" - << static_cast(value); - } -} - -TEST_F(DwarfMemoryTest, GetEncodedSize_absptr_uint32_t) { - GetEncodedSizeTest(0, sizeof(uint32_t)); -} - -TEST_F(DwarfMemoryTest, GetEncodedSize_absptr_uint64_t) { - GetEncodedSizeTest(0, sizeof(uint64_t)); -} - -TEST_F(DwarfMemoryTest, GetEncodedSize_data1) { - // udata1 - GetEncodedSizeTest(0x0d, 1); - GetEncodedSizeTest(0x0d, 1); - - // sdata1 - GetEncodedSizeTest(0x0e, 1); - GetEncodedSizeTest(0x0e, 1); -} - -TEST_F(DwarfMemoryTest, GetEncodedSize_data2) { - // udata2 - GetEncodedSizeTest(0x02, 2); - GetEncodedSizeTest(0x02, 2); - - // sdata2 - GetEncodedSizeTest(0x0a, 2); - GetEncodedSizeTest(0x0a, 2); -} - -TEST_F(DwarfMemoryTest, GetEncodedSize_data4) { - // udata4 - GetEncodedSizeTest(0x03, 4); - GetEncodedSizeTest(0x03, 4); - - // sdata4 - GetEncodedSizeTest(0x0b, 4); - GetEncodedSizeTest(0x0b, 4); -} - -TEST_F(DwarfMemoryTest, GetEncodedSize_data8) { - // udata8 - GetEncodedSizeTest(0x04, 8); - GetEncodedSizeTest(0x04, 8); - - // sdata8 - GetEncodedSizeTest(0x0c, 8); - GetEncodedSizeTest(0x0c, 8); -} - -TEST_F(DwarfMemoryTest, GetEncodedSize_unknown) { - GetEncodedSizeTest(0x01, 0); - GetEncodedSizeTest(0x01, 0); - - GetEncodedSizeTest(0x09, 0); - GetEncodedSizeTest(0x09, 0); - - GetEncodedSizeTest(0x0f, 0); - GetEncodedSizeTest(0x0f, 0); -} - -template -void DwarfMemoryTest::ReadEncodedValue_omit() { - uint64_t value = 123; - ASSERT_TRUE(dwarf_mem_->ReadEncodedValue(0xff, &value)); - ASSERT_EQ(0U, value); -} - -TEST_F(DwarfMemoryTest, ReadEncodedValue_omit_uint32_t) { - ReadEncodedValue_omit(); -} - -TEST_F(DwarfMemoryTest, ReadEncodedValue_omit_uint64_t) { - ReadEncodedValue_omit(); -} - -TEST_F(DwarfMemoryTest, ReadEncodedValue_absptr_uint32_t) { - uint64_t value = 100; - ASSERT_FALSE(dwarf_mem_->ReadEncodedValue(0x00, &value)); - - memory_.SetData32(0, 0x12345678); - - ASSERT_TRUE(dwarf_mem_->ReadEncodedValue(0x00, &value)); - ASSERT_EQ(4U, dwarf_mem_->cur_offset()); - ASSERT_EQ(0x12345678U, value); -} - -TEST_F(DwarfMemoryTest, ReadEncodedValue_absptr_uint64_t) { - uint64_t value = 100; - ASSERT_FALSE(dwarf_mem_->ReadEncodedValue(0x00, &value)); - - memory_.SetData64(0, 0x12345678f1f2f3f4ULL); - - ASSERT_TRUE(dwarf_mem_->ReadEncodedValue(0x00, &value)); - ASSERT_EQ(8U, dwarf_mem_->cur_offset()); - ASSERT_EQ(0x12345678f1f2f3f4ULL, value); -} - -TEST_F(DwarfMemoryTest, ReadEncodedValue_aligned_uint32_t) { - uint64_t value = 100; - dwarf_mem_->set_cur_offset(1); - ASSERT_FALSE(dwarf_mem_->ReadEncodedValue(0x50, &value)); - - memory_.SetData32(4, 0x12345678); - - ASSERT_TRUE(dwarf_mem_->ReadEncodedValue(0x50, &value)); - ASSERT_EQ(8U, dwarf_mem_->cur_offset()); - ASSERT_EQ(0x12345678U, value); -} - -TEST_F(DwarfMemoryTest, ReadEncodedValue_aligned_uint64_t) { - uint64_t value = 100; - dwarf_mem_->set_cur_offset(1); - ASSERT_FALSE(dwarf_mem_->ReadEncodedValue(0x50, &value)); - - memory_.SetData64(8, 0x12345678f1f2f3f4ULL); - - ASSERT_TRUE(dwarf_mem_->ReadEncodedValue(0x50, &value)); - ASSERT_EQ(16U, dwarf_mem_->cur_offset()); - ASSERT_EQ(0x12345678f1f2f3f4ULL, value); -} - -template -void DwarfMemoryTest::ReadEncodedValue_leb128() { - memory_.SetMemory(0, std::vector{0x80, 0x42}); - - uint64_t value = 100; - // uleb128 - ASSERT_TRUE(dwarf_mem_->ReadEncodedValue(0x01, &value)); - ASSERT_EQ(0x2100U, value); - - dwarf_mem_->set_cur_offset(0); - // sleb128 - ASSERT_TRUE(dwarf_mem_->ReadEncodedValue(0x09, &value)); - ASSERT_EQ(0xffffffffffffe100ULL, value); -} - -TEST_F(DwarfMemoryTest, ReadEncodedValue_leb128_uint32_t) { - ReadEncodedValue_leb128(); -} - -TEST_F(DwarfMemoryTest, ReadEncodedValue_leb128_uint64_t) { - ReadEncodedValue_leb128(); -} - -template -void DwarfMemoryTest::ReadEncodedValue_data1() { - memory_.SetData8(0, 0xe0); - - uint64_t value = 0; - ASSERT_TRUE(dwarf_mem_->ReadEncodedValue(0x0d, &value)); - ASSERT_EQ(0xe0U, value); - - dwarf_mem_->set_cur_offset(0); - ASSERT_TRUE(dwarf_mem_->ReadEncodedValue(0x0e, &value)); - ASSERT_EQ(0xffffffffffffffe0ULL, value); -} - -TEST_F(DwarfMemoryTest, ReadEncodedValue_data1_uint32_t) { - ReadEncodedValue_data1(); -} - -TEST_F(DwarfMemoryTest, ReadEncodedValue_data1_uint64_t) { - ReadEncodedValue_data1(); -} - -template -void DwarfMemoryTest::ReadEncodedValue_data2() { - memory_.SetData16(0, 0xe000); - - uint64_t value = 0; - ASSERT_TRUE(dwarf_mem_->ReadEncodedValue(0x02, &value)); - ASSERT_EQ(0xe000U, value); - - dwarf_mem_->set_cur_offset(0); - ASSERT_TRUE(dwarf_mem_->ReadEncodedValue(0x0a, &value)); - ASSERT_EQ(0xffffffffffffe000ULL, value); -} - -TEST_F(DwarfMemoryTest, ReadEncodedValue_data2_uint32_t) { - ReadEncodedValue_data2(); -} - -TEST_F(DwarfMemoryTest, ReadEncodedValue_data2_uint64_t) { - ReadEncodedValue_data2(); -} - -template -void DwarfMemoryTest::ReadEncodedValue_data4() { - memory_.SetData32(0, 0xe0000000); - - uint64_t value = 0; - ASSERT_TRUE(dwarf_mem_->ReadEncodedValue(0x03, &value)); - ASSERT_EQ(0xe0000000U, value); - - dwarf_mem_->set_cur_offset(0); - ASSERT_TRUE(dwarf_mem_->ReadEncodedValue(0x0b, &value)); - ASSERT_EQ(0xffffffffe0000000ULL, value); -} - -TEST_F(DwarfMemoryTest, ReadEncodedValue_data4_uint32_t) { - ReadEncodedValue_data4(); -} - -TEST_F(DwarfMemoryTest, ReadEncodedValue_data4_uint64_t) { - ReadEncodedValue_data4(); -} - -template -void DwarfMemoryTest::ReadEncodedValue_data8() { - memory_.SetData64(0, 0xe000000000000000ULL); - - uint64_t value = 0; - ASSERT_TRUE(dwarf_mem_->ReadEncodedValue(0x04, &value)); - ASSERT_EQ(0xe000000000000000ULL, value); - - dwarf_mem_->set_cur_offset(0); - ASSERT_TRUE(dwarf_mem_->ReadEncodedValue(0x0c, &value)); - ASSERT_EQ(0xe000000000000000ULL, value); -} - -TEST_F(DwarfMemoryTest, ReadEncodedValue_data8_uint32_t) { - ReadEncodedValue_data8(); -} - -TEST_F(DwarfMemoryTest, ReadEncodedValue_data8_uint64_t) { - ReadEncodedValue_data8(); -} - -template -void DwarfMemoryTest::ReadEncodedValue_non_zero_adjust() { - memory_.SetData64(0, 0xe000000000000000ULL); - - uint64_t value = 0; - dwarf_mem_->set_pc_offset(0x2000); - ASSERT_TRUE(dwarf_mem_->ReadEncodedValue(0x14, &value)); - ASSERT_EQ(0xe000000000002000ULL, value); -} - -TEST_F(DwarfMemoryTest, ReadEncodedValue_non_zero_adjust_uint32_t) { - ReadEncodedValue_non_zero_adjust(); -} - -TEST_F(DwarfMemoryTest, ReadEncodedValue_non_zero_adjust_uint64_t) { - ReadEncodedValue_non_zero_adjust(); -} - -template -void DwarfMemoryTest::ReadEncodedValue_overflow() { - memory_.SetData64(0, 0); - - uint64_t value = 0; - dwarf_mem_->set_cur_offset(UINT64_MAX); - ASSERT_FALSE(dwarf_mem_->ReadEncodedValue(0x50, &value)); -} - -TEST_F(DwarfMemoryTest, ReadEncodedValue_overflow_uint32_t) { - ReadEncodedValue_overflow(); -} - -TEST_F(DwarfMemoryTest, ReadEncodedValue_overflow_uint64_t) { - ReadEncodedValue_overflow(); -} - -template -void DwarfMemoryTest::ReadEncodedValue_high_bit_set() { - uint64_t value; - memory_.SetData32(0, 0x15234); - ASSERT_FALSE(dwarf_mem_->ReadEncodedValue(0xc3, &value)); - - dwarf_mem_->set_func_offset(0x60000); - dwarf_mem_->set_cur_offset(0); - ASSERT_TRUE(dwarf_mem_->ReadEncodedValue(0xc3, &value)); - ASSERT_EQ(0x75234U, value); -} - -TEST_F(DwarfMemoryTest, ReadEncodedValue_high_bit_set_uint32_t) { - ReadEncodedValue_high_bit_set(); -} - -TEST_F(DwarfMemoryTest, ReadEncodedValue_high_bit_set_uint64_t) { - ReadEncodedValue_high_bit_set(); -} - -template -void DwarfMemoryTest::ReadEncodedValue_all() { - MemoryFakeAlwaysReadZero memory; - DwarfMemory dwarf_mem(&memory); - - for (size_t i = 0; i <= 0xff; i++) { - uint64_t value; - if (dwarf_mem.ReadEncodedValue(static_cast(i), &value)) { - ASSERT_EQ(0U, value); - } - } -} - -TEST_F(DwarfMemoryTest, ReadEncodedValue_all_uint32_t) { - ReadEncodedValue_all(); -} - -TEST_F(DwarfMemoryTest, ReadEncodedValue_all_uint64_t) { - ReadEncodedValue_all(); -} - -TEST_F(DwarfMemoryTest, AdjustEncodedValue_absptr) { - uint64_t value = 0x1234; - ASSERT_TRUE(dwarf_mem_->AdjustEncodedValue(0x00, &value)); - ASSERT_EQ(0x1234U, value); -} - -TEST_F(DwarfMemoryTest, AdjustEncodedValue_pcrel) { - uint64_t value = 0x1234; - ASSERT_FALSE(dwarf_mem_->AdjustEncodedValue(0x10, &value)); - - dwarf_mem_->set_pc_offset(0x2000); - ASSERT_TRUE(dwarf_mem_->AdjustEncodedValue(0x10, &value)); - ASSERT_EQ(0x3234U, value); - - dwarf_mem_->set_pc_offset(static_cast(-4)); - value = 0x1234; - ASSERT_TRUE(dwarf_mem_->AdjustEncodedValue(0x10, &value)); - ASSERT_EQ(0x1230U, value); -} - -TEST_F(DwarfMemoryTest, AdjustEncodedValue_textrel) { - uint64_t value = 0x8234; - ASSERT_FALSE(dwarf_mem_->AdjustEncodedValue(0x20, &value)); - - dwarf_mem_->set_text_offset(0x1000); - ASSERT_TRUE(dwarf_mem_->AdjustEncodedValue(0x20, &value)); - ASSERT_EQ(0x9234U, value); - - dwarf_mem_->set_text_offset(static_cast(-16)); - value = 0x8234; - ASSERT_TRUE(dwarf_mem_->AdjustEncodedValue(0x20, &value)); - ASSERT_EQ(0x8224U, value); -} - -TEST_F(DwarfMemoryTest, AdjustEncodedValue_datarel) { - uint64_t value = 0xb234; - ASSERT_FALSE(dwarf_mem_->AdjustEncodedValue(0x30, &value)); - - dwarf_mem_->set_data_offset(0x1200); - ASSERT_TRUE(dwarf_mem_->AdjustEncodedValue(0x30, &value)); - ASSERT_EQ(0xc434U, value); - - dwarf_mem_->set_data_offset(static_cast(-256)); - value = 0xb234; - ASSERT_TRUE(dwarf_mem_->AdjustEncodedValue(0x30, &value)); - ASSERT_EQ(0xb134U, value); -} - -TEST_F(DwarfMemoryTest, AdjustEncodedValue_funcrel) { - uint64_t value = 0x15234; - ASSERT_FALSE(dwarf_mem_->AdjustEncodedValue(0x40, &value)); - - dwarf_mem_->set_func_offset(0x60000); - ASSERT_TRUE(dwarf_mem_->AdjustEncodedValue(0x40, &value)); - ASSERT_EQ(0x75234U, value); - - dwarf_mem_->set_func_offset(static_cast(-4096)); - value = 0x15234; - ASSERT_TRUE(dwarf_mem_->AdjustEncodedValue(0x40, &value)); - ASSERT_EQ(0x14234U, value); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/DwarfOpLogTest.cpp b/libunwindstack/tests/DwarfOpLogTest.cpp deleted file mode 100644 index 8dbf6e815..000000000 --- a/libunwindstack/tests/DwarfOpLogTest.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2016 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 "DwarfOp.h" - -#include "MemoryFake.h" - -namespace unwindstack { - -template -class DwarfOpLogTest : public ::testing::Test { - protected: - void SetUp() override { - op_memory_.Clear(); - regular_memory_.Clear(); - mem_.reset(new DwarfMemory(&op_memory_)); - op_.reset(new DwarfOp(mem_.get(), ®ular_memory_)); - } - - MemoryFake op_memory_; - MemoryFake regular_memory_; - - std::unique_ptr mem_; - std::unique_ptr> op_; -}; -TYPED_TEST_SUITE_P(DwarfOpLogTest); - -TYPED_TEST_P(DwarfOpLogTest, multiple_ops) { - // Multi operation opcodes. - std::vector opcode_buffer = { - 0x0a, 0x20, 0x10, 0x08, 0x03, 0x12, 0x27, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - std::vector lines; - this->op_->GetLogInfo(0, opcode_buffer.size(), &lines); - std::vector expected{ - "DW_OP_const2u 4128", "Raw Data: 0x0a 0x20 0x10", "DW_OP_const1u 3", "Raw Data: 0x08 0x03", - "DW_OP_dup", "Raw Data: 0x12", "DW_OP_xor", "Raw Data: 0x27"}; - ASSERT_EQ(expected, lines); -} - -REGISTER_TYPED_TEST_SUITE_P(DwarfOpLogTest, multiple_ops); - -typedef ::testing::Types DwarfOpLogTestTypes; -INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfOpLogTest, DwarfOpLogTestTypes); - -} // namespace unwindstack diff --git a/libunwindstack/tests/DwarfOpTest.cpp b/libunwindstack/tests/DwarfOpTest.cpp deleted file mode 100644 index 0e2d91a8a..000000000 --- a/libunwindstack/tests/DwarfOpTest.cpp +++ /dev/null @@ -1,1586 +0,0 @@ -/* - * Copyright (C) 2016 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 "DwarfOp.h" - -#include "MemoryFake.h" -#include "RegsFake.h" - -namespace unwindstack { - -template -class DwarfOpTest : public ::testing::Test { - protected: - void SetUp() override { - op_memory_.Clear(); - regular_memory_.Clear(); - mem_.reset(new DwarfMemory(&op_memory_)); - op_.reset(new DwarfOp(mem_.get(), ®ular_memory_)); - } - - MemoryFake op_memory_; - MemoryFake regular_memory_; - - std::unique_ptr mem_; - std::unique_ptr> op_; -}; -TYPED_TEST_SUITE_P(DwarfOpTest); - -TYPED_TEST_P(DwarfOpTest, decode) { - // Memory error. - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->LastErrorCode()); - EXPECT_EQ(0U, this->op_->LastErrorAddress()); - - // No error. - this->op_memory_.SetMemory(0, std::vector{0x96}); - this->mem_->set_cur_offset(0); - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_NONE, this->op_->LastErrorCode()); - ASSERT_EQ(0x96U, this->op_->cur_op()); - ASSERT_EQ(1U, this->mem_->cur_offset()); -} - -TYPED_TEST_P(DwarfOpTest, eval) { - // Memory error. - ASSERT_FALSE(this->op_->Eval(0, 2)); - ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->LastErrorCode()); - EXPECT_EQ(0U, this->op_->LastErrorAddress()); - - // Register set. - // Do this first, to verify that subsequent calls reset the value. - this->op_memory_.SetMemory(0, std::vector{0x50}); - ASSERT_TRUE(this->op_->Eval(0, 1)); - ASSERT_TRUE(this->op_->is_register()); - ASSERT_EQ(1U, this->mem_->cur_offset()); - ASSERT_EQ(1U, this->op_->StackSize()); - - // Multi operation opcodes. - std::vector opcode_buffer = { - 0x08, 0x04, 0x08, 0x03, 0x08, 0x02, 0x08, 0x01, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_TRUE(this->op_->Eval(0, 8)); - ASSERT_EQ(DWARF_ERROR_NONE, this->op_->LastErrorCode()); - ASSERT_FALSE(this->op_->is_register()); - ASSERT_EQ(8U, this->mem_->cur_offset()); - ASSERT_EQ(4U, this->op_->StackSize()); - ASSERT_EQ(1U, this->op_->StackAt(0)); - ASSERT_EQ(2U, this->op_->StackAt(1)); - ASSERT_EQ(3U, this->op_->StackAt(2)); - ASSERT_EQ(4U, this->op_->StackAt(3)); - - // Infinite loop. - this->op_memory_.SetMemory(0, std::vector{0x2f, 0xfd, 0xff}); - ASSERT_FALSE(this->op_->Eval(0, 4)); - ASSERT_EQ(DWARF_ERROR_TOO_MANY_ITERATIONS, this->op_->LastErrorCode()); - ASSERT_FALSE(this->op_->is_register()); - ASSERT_EQ(0U, this->op_->StackSize()); -} - -TYPED_TEST_P(DwarfOpTest, illegal_opcode) { - // Fill the buffer with all of the illegal opcodes. - std::vector opcode_buffer = {0x00, 0x01, 0x02, 0x04, 0x05, 0x07}; - for (size_t opcode = 0xa0; opcode < 256; opcode++) { - opcode_buffer.push_back(opcode); - } - this->op_memory_.SetMemory(0, opcode_buffer); - - for (size_t i = 0; i < opcode_buffer.size(); i++) { - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode()); - ASSERT_EQ(opcode_buffer[i], this->op_->cur_op()); - } -} - -TYPED_TEST_P(DwarfOpTest, not_implemented) { - std::vector opcode_buffer = { - // Push values so that any not implemented ops will return the right error. - 0x08, 0x03, 0x08, 0x02, 0x08, 0x01, - // xderef - 0x18, - // fbreg - 0x91, 0x01, - // piece - 0x93, 0x01, - // xderef_size - 0x95, 0x01, - // push_object_address - 0x97, - // call2 - 0x98, 0x01, 0x02, - // call4 - 0x99, 0x01, 0x02, 0x03, 0x04, - // call_ref - 0x9a, - // form_tls_address - 0x9b, - // call_frame_cfa - 0x9c, - // bit_piece - 0x9d, 0x01, 0x01, - // implicit_value - 0x9e, 0x01, - // stack_value - 0x9f, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - // Push the stack values. - ASSERT_TRUE(this->op_->Decode()); - ASSERT_TRUE(this->op_->Decode()); - ASSERT_TRUE(this->op_->Decode()); - - while (this->mem_->cur_offset() < opcode_buffer.size()) { - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->op_->LastErrorCode()); - } -} - -TYPED_TEST_P(DwarfOpTest, op_addr) { - std::vector opcode_buffer = {0x03, 0x12, 0x23, 0x34, 0x45}; - if (sizeof(TypeParam) == 8) { - opcode_buffer.push_back(0x56); - opcode_buffer.push_back(0x67); - opcode_buffer.push_back(0x78); - opcode_buffer.push_back(0x89); - } - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x03, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - if (sizeof(TypeParam) == 4) { - ASSERT_EQ(0x45342312U, this->op_->StackAt(0)); - } else { - ASSERT_EQ(0x8978675645342312UL, this->op_->StackAt(0)); - } -} - -TYPED_TEST_P(DwarfOpTest, op_deref) { - std::vector opcode_buffer = { - // Try a dereference with nothing on the stack. - 0x06, - // Add an address, then dereference. - 0x0a, 0x10, 0x20, 0x06, - // Now do another dereference that should fail in memory. - 0x06, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - TypeParam value = 0x12345678; - this->regular_memory_.SetMemory(0x2010, &value, sizeof(value)); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x06, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(value, this->op_->StackAt(0)); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->LastErrorCode()); - ASSERT_EQ(0x12345678U, this->op_->LastErrorAddress()); -} - -TYPED_TEST_P(DwarfOpTest, op_deref_size) { - this->op_memory_.SetMemory(0, std::vector{0x94}); - TypeParam value = 0x12345678; - this->regular_memory_.SetMemory(0x2010, &value, sizeof(value)); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - // Read all byte sizes up to the sizeof the type. - for (size_t i = 1; i < sizeof(TypeParam); i++) { - this->op_memory_.SetMemory( - 0, std::vector{0x0a, 0x10, 0x20, 0x94, static_cast(i)}); - ASSERT_TRUE(this->op_->Eval(0, 5)) << "Failed at size " << i; - ASSERT_EQ(1U, this->op_->StackSize()) << "Failed at size " << i; - ASSERT_EQ(0x94, this->op_->cur_op()) << "Failed at size " << i; - TypeParam expected_value = 0; - memcpy(&expected_value, &value, i); - ASSERT_EQ(expected_value, this->op_->StackAt(0)) << "Failed at size " << i; - } - - // Zero byte read. - this->op_memory_.SetMemory(0, std::vector{0x0a, 0x10, 0x20, 0x94, 0x00}); - ASSERT_FALSE(this->op_->Eval(0, 5)); - ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode()); - - // Read too many bytes. - this->op_memory_.SetMemory(0, std::vector{0x0a, 0x10, 0x20, 0x94, sizeof(TypeParam) + 1}); - ASSERT_FALSE(this->op_->Eval(0, 5)); - ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode()); - - // Force bad memory read. - this->op_memory_.SetMemory(0, std::vector{0x0a, 0x10, 0x40, 0x94, 0x01}); - ASSERT_FALSE(this->op_->Eval(0, 5)); - ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->LastErrorCode()); - EXPECT_EQ(0x4010U, this->op_->LastErrorAddress()); -} - -TYPED_TEST_P(DwarfOpTest, const_unsigned) { - std::vector opcode_buffer = { - // const1u - 0x08, 0x12, 0x08, 0xff, - // const2u - 0x0a, 0x45, 0x12, 0x0a, 0x00, 0xff, - // const4u - 0x0c, 0x12, 0x23, 0x34, 0x45, 0x0c, 0x03, 0x02, 0x01, 0xff, - // const8u - 0x0e, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x0e, 0x87, 0x98, 0xa9, 0xba, 0xcb, - 0xdc, 0xed, 0xfe, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - // const1u - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x08, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(0x12U, this->op_->StackAt(0)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x08, this->op_->cur_op()); - ASSERT_EQ(2U, this->op_->StackSize()); - ASSERT_EQ(0xffU, this->op_->StackAt(0)); - - // const2u - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x0a, this->op_->cur_op()); - ASSERT_EQ(3U, this->op_->StackSize()); - ASSERT_EQ(0x1245U, this->op_->StackAt(0)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x0a, this->op_->cur_op()); - ASSERT_EQ(4U, this->op_->StackSize()); - ASSERT_EQ(0xff00U, this->op_->StackAt(0)); - - // const4u - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x0c, this->op_->cur_op()); - ASSERT_EQ(5U, this->op_->StackSize()); - ASSERT_EQ(0x45342312U, this->op_->StackAt(0)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x0c, this->op_->cur_op()); - ASSERT_EQ(6U, this->op_->StackSize()); - ASSERT_EQ(0xff010203U, this->op_->StackAt(0)); - - // const8u - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x0e, this->op_->cur_op()); - ASSERT_EQ(7U, this->op_->StackSize()); - if (sizeof(TypeParam) == 4) { - ASSERT_EQ(0x05060708U, this->op_->StackAt(0)); - } else { - ASSERT_EQ(0x0102030405060708ULL, this->op_->StackAt(0)); - } - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x0e, this->op_->cur_op()); - ASSERT_EQ(8U, this->op_->StackSize()); - if (sizeof(TypeParam) == 4) { - ASSERT_EQ(0xbaa99887UL, this->op_->StackAt(0)); - } else { - ASSERT_EQ(0xfeeddccbbaa99887ULL, this->op_->StackAt(0)); - } -} - -TYPED_TEST_P(DwarfOpTest, const_signed) { - std::vector opcode_buffer = { - // const1s - 0x09, 0x12, 0x09, 0xff, - // const2s - 0x0b, 0x21, 0x32, 0x0b, 0x08, 0xff, - // const4s - 0x0d, 0x45, 0x34, 0x23, 0x12, 0x0d, 0x01, 0x02, 0x03, 0xff, - // const8s - 0x0f, 0x89, 0x78, 0x67, 0x56, 0x45, 0x34, 0x23, 0x12, 0x0f, 0x04, 0x03, 0x02, 0x01, 0xef, - 0xef, 0xef, 0xff, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - // const1s - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x09, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(0x12U, this->op_->StackAt(0)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x09, this->op_->cur_op()); - ASSERT_EQ(2U, this->op_->StackSize()); - ASSERT_EQ(static_cast(-1), this->op_->StackAt(0)); - - // const2s - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x0b, this->op_->cur_op()); - ASSERT_EQ(3U, this->op_->StackSize()); - ASSERT_EQ(0x3221U, this->op_->StackAt(0)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x0b, this->op_->cur_op()); - ASSERT_EQ(4U, this->op_->StackSize()); - ASSERT_EQ(static_cast(-248), this->op_->StackAt(0)); - - // const4s - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x0d, this->op_->cur_op()); - ASSERT_EQ(5U, this->op_->StackSize()); - ASSERT_EQ(0x12233445U, this->op_->StackAt(0)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x0d, this->op_->cur_op()); - ASSERT_EQ(6U, this->op_->StackSize()); - ASSERT_EQ(static_cast(-16580095), this->op_->StackAt(0)); - - // const8s - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x0f, this->op_->cur_op()); - ASSERT_EQ(7U, this->op_->StackSize()); - if (sizeof(TypeParam) == 4) { - ASSERT_EQ(0x56677889ULL, this->op_->StackAt(0)); - } else { - ASSERT_EQ(0x1223344556677889ULL, this->op_->StackAt(0)); - } - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x0f, this->op_->cur_op()); - ASSERT_EQ(8U, this->op_->StackSize()); - if (sizeof(TypeParam) == 4) { - ASSERT_EQ(0x01020304U, this->op_->StackAt(0)); - } else { - ASSERT_EQ(static_cast(-4521264810949884LL), this->op_->StackAt(0)); - } -} - -TYPED_TEST_P(DwarfOpTest, const_uleb) { - std::vector opcode_buffer = { - // Single byte ULEB128 - 0x10, 0x22, 0x10, 0x7f, - // Multi byte ULEB128 - 0x10, 0xa2, 0x22, 0x10, 0xa2, 0x74, 0x10, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, - 0x09, 0x10, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x79, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - // Single byte ULEB128 - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x10, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(0x22U, this->op_->StackAt(0)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x10, this->op_->cur_op()); - ASSERT_EQ(2U, this->op_->StackSize()); - ASSERT_EQ(0x7fU, this->op_->StackAt(0)); - - // Multi byte ULEB128 - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x10, this->op_->cur_op()); - ASSERT_EQ(3U, this->op_->StackSize()); - ASSERT_EQ(0x1122U, this->op_->StackAt(0)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x10, this->op_->cur_op()); - ASSERT_EQ(4U, this->op_->StackSize()); - ASSERT_EQ(0x3a22U, this->op_->StackAt(0)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x10, this->op_->cur_op()); - ASSERT_EQ(5U, this->op_->StackSize()); - if (sizeof(TypeParam) == 4) { - ASSERT_EQ(0x5080c101U, this->op_->StackAt(0)); - } else { - ASSERT_EQ(0x9101c305080c101ULL, this->op_->StackAt(0)); - } - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x10, this->op_->cur_op()); - ASSERT_EQ(6U, this->op_->StackSize()); - if (sizeof(TypeParam) == 4) { - ASSERT_EQ(0x5080c101U, this->op_->StackAt(0)); - } else { - ASSERT_EQ(0x79101c305080c101ULL, this->op_->StackAt(0)); - } -} - -TYPED_TEST_P(DwarfOpTest, const_sleb) { - std::vector opcode_buffer = { - // Single byte SLEB128 - 0x11, 0x22, 0x11, 0x7f, - // Multi byte SLEB128 - 0x11, 0xa2, 0x22, 0x11, 0xa2, 0x74, 0x11, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, - 0x09, 0x11, - }; - if (sizeof(TypeParam) == 4) { - opcode_buffer.push_back(0xb8); - opcode_buffer.push_back(0xd3); - opcode_buffer.push_back(0x63); - } else { - opcode_buffer.push_back(0x81); - opcode_buffer.push_back(0x82); - opcode_buffer.push_back(0x83); - opcode_buffer.push_back(0x84); - opcode_buffer.push_back(0x85); - opcode_buffer.push_back(0x86); - opcode_buffer.push_back(0x87); - opcode_buffer.push_back(0x88); - opcode_buffer.push_back(0x79); - } - this->op_memory_.SetMemory(0, opcode_buffer); - - // Single byte SLEB128 - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x11, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(0x22U, this->op_->StackAt(0)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x11, this->op_->cur_op()); - ASSERT_EQ(2U, this->op_->StackSize()); - ASSERT_EQ(static_cast(-1), this->op_->StackAt(0)); - - // Multi byte SLEB128 - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x11, this->op_->cur_op()); - ASSERT_EQ(3U, this->op_->StackSize()); - ASSERT_EQ(0x1122U, this->op_->StackAt(0)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x11, this->op_->cur_op()); - ASSERT_EQ(4U, this->op_->StackSize()); - ASSERT_EQ(static_cast(-1502), this->op_->StackAt(0)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x11, this->op_->cur_op()); - ASSERT_EQ(5U, this->op_->StackSize()); - if (sizeof(TypeParam) == 4) { - ASSERT_EQ(0x5080c101U, this->op_->StackAt(0)); - } else { - ASSERT_EQ(0x9101c305080c101ULL, this->op_->StackAt(0)); - } - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x11, this->op_->cur_op()); - ASSERT_EQ(6U, this->op_->StackSize()); - if (sizeof(TypeParam) == 4) { - ASSERT_EQ(static_cast(-464456), this->op_->StackAt(0)); - } else { - ASSERT_EQ(static_cast(-499868564803501823LL), this->op_->StackAt(0)); - } -} - -TYPED_TEST_P(DwarfOpTest, op_dup) { - std::vector opcode_buffer = { - // Should fail since nothing is on the stack. - 0x12, - // Push on a value and dup. - 0x08, 0x15, 0x12, - // Do it again. - 0x08, 0x23, 0x12, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(0x12, this->op_->cur_op()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x12, this->op_->cur_op()); - ASSERT_EQ(2U, this->op_->StackSize()); - ASSERT_EQ(0x15U, this->op_->StackAt(0)); - ASSERT_EQ(0x15U, this->op_->StackAt(1)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(3U, this->op_->StackSize()); - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x12, this->op_->cur_op()); - ASSERT_EQ(4U, this->op_->StackSize()); - ASSERT_EQ(0x23U, this->op_->StackAt(0)); - ASSERT_EQ(0x23U, this->op_->StackAt(1)); - ASSERT_EQ(0x15U, this->op_->StackAt(2)); - ASSERT_EQ(0x15U, this->op_->StackAt(3)); -} - -TYPED_TEST_P(DwarfOpTest, op_drop) { - std::vector opcode_buffer = { - // Push a couple of values. - 0x08, 0x10, 0x08, 0x20, - // Drop the values. - 0x13, 0x13, - // Attempt to drop empty stack. - 0x13, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(2U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x13, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(0x10U, this->op_->StackAt(0)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x13, this->op_->cur_op()); - ASSERT_EQ(0U, this->op_->StackSize()); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(0x13, this->op_->cur_op()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); -} - -TYPED_TEST_P(DwarfOpTest, op_over) { - std::vector opcode_buffer = { - // Push a couple of values. - 0x08, 0x1a, 0x08, 0xed, - // Copy a value. - 0x14, - // Remove all but one element. - 0x13, 0x13, - // Provoke a failure with this opcode. - 0x14, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(2U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x14, this->op_->cur_op()); - ASSERT_EQ(3U, this->op_->StackSize()); - ASSERT_EQ(0x1aU, this->op_->StackAt(0)); - ASSERT_EQ(0xedU, this->op_->StackAt(1)); - ASSERT_EQ(0x1aU, this->op_->StackAt(2)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(2U, this->op_->StackSize()); - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(0x14, this->op_->cur_op()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); -} - -TYPED_TEST_P(DwarfOpTest, op_pick) { - std::vector opcode_buffer = { - // Push a few values. - 0x08, 0x1a, 0x08, 0xed, 0x08, 0x34, - // Copy the value at offset 2. - 0x15, 0x01, - // Copy the last value in the stack. - 0x15, 0x03, - // Choose an invalid index. - 0x15, 0x10, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(2U, this->op_->StackSize()); - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(3U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x15, this->op_->cur_op()); - ASSERT_EQ(4U, this->op_->StackSize()); - ASSERT_EQ(0xedU, this->op_->StackAt(0)); - ASSERT_EQ(0x34U, this->op_->StackAt(1)); - ASSERT_EQ(0xedU, this->op_->StackAt(2)); - ASSERT_EQ(0x1aU, this->op_->StackAt(3)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x15, this->op_->cur_op()); - ASSERT_EQ(5U, this->op_->StackSize()); - ASSERT_EQ(0x1aU, this->op_->StackAt(0)); - ASSERT_EQ(0xedU, this->op_->StackAt(1)); - ASSERT_EQ(0x34U, this->op_->StackAt(2)); - ASSERT_EQ(0xedU, this->op_->StackAt(3)); - ASSERT_EQ(0x1aU, this->op_->StackAt(4)); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(0x15, this->op_->cur_op()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); -} - -TYPED_TEST_P(DwarfOpTest, op_swap) { - std::vector opcode_buffer = { - // Push a couple of values. - 0x08, 0x26, 0x08, 0xab, - // Swap values. - 0x16, - // Pop a value to cause a failure. - 0x13, 0x16, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(2U, this->op_->StackSize()); - ASSERT_EQ(0xabU, this->op_->StackAt(0)); - ASSERT_EQ(0x26U, this->op_->StackAt(1)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x16, this->op_->cur_op()); - ASSERT_EQ(2U, this->op_->StackSize()); - ASSERT_EQ(0x26U, this->op_->StackAt(0)); - ASSERT_EQ(0xabU, this->op_->StackAt(1)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(0x16, this->op_->cur_op()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); -} - -TYPED_TEST_P(DwarfOpTest, op_rot) { - std::vector opcode_buffer = { - // Rotate that should cause a failure. - 0x17, 0x08, 0x10, - // Only 1 value on stack, should fail. - 0x17, 0x08, 0x20, - // Only 2 values on stack, should fail. - 0x17, 0x08, 0x30, - // Should rotate properly. - 0x17, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(2U, this->op_->StackSize()); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(3U, this->op_->StackSize()); - ASSERT_EQ(0x30U, this->op_->StackAt(0)); - ASSERT_EQ(0x20U, this->op_->StackAt(1)); - ASSERT_EQ(0x10U, this->op_->StackAt(2)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x17, this->op_->cur_op()); - ASSERT_EQ(3U, this->op_->StackSize()); - ASSERT_EQ(0x20U, this->op_->StackAt(0)); - ASSERT_EQ(0x10U, this->op_->StackAt(1)); - ASSERT_EQ(0x30U, this->op_->StackAt(2)); -} - -TYPED_TEST_P(DwarfOpTest, op_abs) { - std::vector opcode_buffer = { - // Abs that should fail. - 0x19, - // A value that is already positive. - 0x08, 0x10, 0x19, - // A value that is negative. - 0x11, 0x7f, 0x19, - // A value that is large and negative. - 0x11, 0x81, 0x80, 0x80, 0x80, - }; - if (sizeof(TypeParam) == 4) { - opcode_buffer.push_back(0x08); - } else { - opcode_buffer.push_back(0x80); - opcode_buffer.push_back(0x80); - opcode_buffer.push_back(0x01); - } - opcode_buffer.push_back(0x19); - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(0x10U, this->op_->StackAt(0)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x19, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(0x10U, this->op_->StackAt(0)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(2U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x19, this->op_->cur_op()); - ASSERT_EQ(2U, this->op_->StackSize()); - ASSERT_EQ(0x1U, this->op_->StackAt(0)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(3U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x19, this->op_->cur_op()); - ASSERT_EQ(3U, this->op_->StackSize()); - if (sizeof(TypeParam) == 4) { - ASSERT_EQ(2147483647U, this->op_->StackAt(0)); - } else { - ASSERT_EQ(4398046511105UL, this->op_->StackAt(0)); - } -} - -TYPED_TEST_P(DwarfOpTest, op_and) { - std::vector opcode_buffer = { - // No stack, and op will fail. - 0x1b, - // Push a single value. - 0x08, 0x20, - // One element stack, and op will fail. - 0x1b, - // Push another value. - 0x08, 0x02, 0x1b, - // Push on two negative values. - 0x11, 0x7c, 0x11, 0x7f, 0x1b, - // Push one negative, one positive. - 0x11, 0x10, 0x11, 0x7c, 0x1b, - // Divide by zero. - 0x11, 0x10, 0x11, 0x00, 0x1b, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - // Two positive values. - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(2U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x1b, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(0x10U, this->op_->StackAt(0)); - - // Two negative values. - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(2U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(3U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x1b, this->op_->cur_op()); - ASSERT_EQ(2U, this->op_->StackSize()); - ASSERT_EQ(0x04U, this->op_->StackAt(0)); - - // One negative value, one positive value. - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(3U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(4U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x1b, this->op_->cur_op()); - ASSERT_EQ(3U, this->op_->StackSize()); - ASSERT_EQ(static_cast(-4), this->op_->StackAt(0)); - - // Divide by zero. - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(4U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(5U, this->op_->StackSize()); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode()); -} - -TYPED_TEST_P(DwarfOpTest, op_div) { - std::vector opcode_buffer = { - // No stack, and op will fail. - 0x1a, - // Push a single value. - 0x08, 0x48, - // One element stack, and op will fail. - 0x1a, - // Push another value. - 0x08, 0xf0, 0x1a, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(2U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x1a, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(0x40U, this->op_->StackAt(0)); -} - -TYPED_TEST_P(DwarfOpTest, op_minus) { - std::vector opcode_buffer = { - // No stack, and op will fail. - 0x1c, - // Push a single value. - 0x08, 0x48, - // One element stack, and op will fail. - 0x1c, - // Push another value. - 0x08, 0x04, 0x1c, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(2U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x1c, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(0x44U, this->op_->StackAt(0)); -} - -TYPED_TEST_P(DwarfOpTest, op_mod) { - std::vector opcode_buffer = { - // No stack, and op will fail. - 0x1d, - // Push a single value. - 0x08, 0x47, - // One element stack, and op will fail. - 0x1d, - // Push another value. - 0x08, 0x04, 0x1d, - // Try a mod of zero. - 0x08, 0x01, 0x08, 0x00, 0x1d, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(2U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x1d, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(0x03U, this->op_->StackAt(0)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(2U, this->op_->StackSize()); - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(3U, this->op_->StackSize()); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode()); -} - -TYPED_TEST_P(DwarfOpTest, op_mul) { - std::vector opcode_buffer = { - // No stack, and op will fail. - 0x1e, - // Push a single value. - 0x08, 0x48, - // One element stack, and op will fail. - 0x1e, - // Push another value. - 0x08, 0x04, 0x1e, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(2U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x1e, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(0x120U, this->op_->StackAt(0)); -} - -TYPED_TEST_P(DwarfOpTest, op_neg) { - std::vector opcode_buffer = { - // No stack, and op will fail. - 0x1f, - // Push a single value. - 0x08, 0x48, 0x1f, - // Push a negative value. - 0x11, 0x7f, 0x1f, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x1f, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(static_cast(-72), this->op_->StackAt(0)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(2U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x1f, this->op_->cur_op()); - ASSERT_EQ(2U, this->op_->StackSize()); - ASSERT_EQ(0x01U, this->op_->StackAt(0)); -} - -TYPED_TEST_P(DwarfOpTest, op_not) { - std::vector opcode_buffer = { - // No stack, and op will fail. - 0x20, - // Push a single value. - 0x08, 0x4, 0x20, - // Push a negative value. - 0x11, 0x7c, 0x20, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x20, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(static_cast(-5), this->op_->StackAt(0)); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(2U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x20, this->op_->cur_op()); - ASSERT_EQ(2U, this->op_->StackSize()); - ASSERT_EQ(0x03U, this->op_->StackAt(0)); -} - -TYPED_TEST_P(DwarfOpTest, op_or) { - std::vector opcode_buffer = { - // No stack, and op will fail. - 0x21, - // Push a single value. - 0x08, 0x48, - // One element stack, and op will fail. - 0x21, - // Push another value. - 0x08, 0xf4, 0x21, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(2U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x21, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(0xfcU, this->op_->StackAt(0)); -} - -TYPED_TEST_P(DwarfOpTest, op_plus) { - std::vector opcode_buffer = { - // No stack, and op will fail. - 0x22, - // Push a single value. - 0x08, 0xff, - // One element stack, and op will fail. - 0x22, - // Push another value. - 0x08, 0xf2, 0x22, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(2U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x22, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(0x1f1U, this->op_->StackAt(0)); -} - -TYPED_TEST_P(DwarfOpTest, op_plus_uconst) { - std::vector opcode_buffer = { - // No stack, and op will fail. - 0x23, - // Push a single value. - 0x08, 0x50, 0x23, 0x80, 0x51, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x23, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(0x28d0U, this->op_->StackAt(0)); -} - -TYPED_TEST_P(DwarfOpTest, op_shl) { - std::vector opcode_buffer = { - // No stack, and op will fail. - 0x24, - // Push a single value. - 0x08, 0x67, - // One element stack, and op will fail. - 0x24, - // Push another value. - 0x08, 0x03, 0x24, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(2U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x24, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(0x338U, this->op_->StackAt(0)); -} - -TYPED_TEST_P(DwarfOpTest, op_shr) { - std::vector opcode_buffer = { - // No stack, and op will fail. - 0x25, - // Push a single value. - 0x11, 0x70, - // One element stack, and op will fail. - 0x25, - // Push another value. - 0x08, 0x03, 0x25, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(2U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x25, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - if (sizeof(TypeParam) == 4) { - ASSERT_EQ(0x1ffffffeU, this->op_->StackAt(0)); - } else { - ASSERT_EQ(0x1ffffffffffffffeULL, this->op_->StackAt(0)); - } -} - -TYPED_TEST_P(DwarfOpTest, op_shra) { - std::vector opcode_buffer = { - // No stack, and op will fail. - 0x26, - // Push a single value. - 0x11, 0x70, - // One element stack, and op will fail. - 0x26, - // Push another value. - 0x08, 0x03, 0x26, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(2U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x26, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(static_cast(-2), this->op_->StackAt(0)); -} - -TYPED_TEST_P(DwarfOpTest, op_xor) { - std::vector opcode_buffer = { - // No stack, and op will fail. - 0x27, - // Push a single value. - 0x08, 0x11, - // One element stack, and op will fail. - 0x27, - // Push another value. - 0x08, 0x41, 0x27, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(2U, this->op_->StackSize()); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x27, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(0x50U, this->op_->StackAt(0)); -} - -TYPED_TEST_P(DwarfOpTest, op_bra) { - std::vector opcode_buffer = { - // No stack, and op will fail. - 0x28, - // Push on a non-zero value with a positive branch. - 0x08, 0x11, 0x28, 0x02, 0x01, - // Push on a zero value with a positive branch. - 0x08, 0x00, 0x28, 0x05, 0x00, - // Push on a non-zero value with a negative branch. - 0x08, 0x11, 0x28, 0xfc, 0xff, - // Push on a zero value with a negative branch. - 0x08, 0x00, 0x28, 0xf0, 0xff, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_FALSE(this->op_->Decode()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - // Push on a non-zero value with a positive branch. - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - - uint64_t offset = this->mem_->cur_offset() + 3; - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x28, this->op_->cur_op()); - ASSERT_EQ(0U, this->op_->StackSize()); - ASSERT_EQ(offset + 0x102, this->mem_->cur_offset()); - - // Push on a zero value with a positive branch. - this->mem_->set_cur_offset(offset); - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - - offset = this->mem_->cur_offset() + 3; - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x28, this->op_->cur_op()); - ASSERT_EQ(0U, this->op_->StackSize()); - ASSERT_EQ(offset - 5, this->mem_->cur_offset()); - - // Push on a non-zero value with a negative branch. - this->mem_->set_cur_offset(offset); - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - - offset = this->mem_->cur_offset() + 3; - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x28, this->op_->cur_op()); - ASSERT_EQ(0U, this->op_->StackSize()); - ASSERT_EQ(offset - 4, this->mem_->cur_offset()); - - // Push on a zero value with a negative branch. - this->mem_->set_cur_offset(offset); - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(1U, this->op_->StackSize()); - - offset = this->mem_->cur_offset() + 3; - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x28, this->op_->cur_op()); - ASSERT_EQ(0U, this->op_->StackSize()); - ASSERT_EQ(offset + 16, this->mem_->cur_offset()); -} - -TYPED_TEST_P(DwarfOpTest, compare_opcode_stack_error) { - // All of the ops require two stack elements. Loop through all of these - // ops with potential errors. - std::vector opcode_buffer = { - 0xff, // Place holder for compare op. - 0x08, 0x11, - 0xff, // Place holder for compare op. - }; - - for (uint8_t opcode = 0x29; opcode <= 0x2e; opcode++) { - opcode_buffer[0] = opcode; - opcode_buffer[3] = opcode; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_FALSE(this->op_->Eval(0, 1)); - ASSERT_EQ(opcode, this->op_->cur_op()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - - ASSERT_FALSE(this->op_->Eval(1, 4)); - ASSERT_EQ(opcode, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode()); - } -} - -TYPED_TEST_P(DwarfOpTest, compare_opcodes) { - // Have three different checks for each compare op: - // - Both values the same. - // - The first value larger than the second. - // - The second value larger than the first. - std::vector opcode_buffer = { - // Values the same. - 0x08, 0x11, 0x08, 0x11, - 0xff, // Placeholder. - // First value larger. - 0x08, 0x12, 0x08, 0x10, - 0xff, // Placeholder. - // Second value larger. - 0x08, 0x10, 0x08, 0x12, - 0xff, // Placeholder. - }; - - // Opcode followed by the expected values on the stack. - std::vector expected = { - 0x29, 1, 0, 0, // eq - 0x2a, 1, 1, 0, // ge - 0x2b, 0, 1, 0, // gt - 0x2c, 1, 0, 1, // le - 0x2d, 0, 0, 1, // lt - 0x2e, 0, 1, 1, // ne - }; - for (size_t i = 0; i < expected.size(); i += 4) { - opcode_buffer[4] = expected[i]; - opcode_buffer[9] = expected[i]; - opcode_buffer[14] = expected[i]; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_TRUE(this->op_->Eval(0, 15)) - << "Op: 0x" << std::hex << static_cast(expected[i]) << " failed"; - - ASSERT_EQ(3U, this->op_->StackSize()); - ASSERT_EQ(expected[i + 1], this->op_->StackAt(2)); - ASSERT_EQ(expected[i + 2], this->op_->StackAt(1)); - ASSERT_EQ(expected[i + 3], this->op_->StackAt(0)); - } -} - -TYPED_TEST_P(DwarfOpTest, op_skip) { - std::vector opcode_buffer = { - // Positive value. - 0x2f, 0x10, 0x20, - // Negative value. - 0x2f, 0xfd, 0xff, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - uint64_t offset = this->mem_->cur_offset() + 3; - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x2f, this->op_->cur_op()); - ASSERT_EQ(0U, this->op_->StackSize()); - ASSERT_EQ(offset + 0x2010, this->mem_->cur_offset()); - - this->mem_->set_cur_offset(offset); - offset = this->mem_->cur_offset() + 3; - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x2f, this->op_->cur_op()); - ASSERT_EQ(0U, this->op_->StackSize()); - ASSERT_EQ(offset - 3, this->mem_->cur_offset()); -} - -TYPED_TEST_P(DwarfOpTest, op_lit) { - std::vector opcode_buffer; - - // Verify every lit opcode. - for (uint8_t op = 0x30; op <= 0x4f; op++) { - opcode_buffer.push_back(op); - } - this->op_memory_.SetMemory(0, opcode_buffer); - - for (size_t i = 0; i < opcode_buffer.size(); i++) { - uint32_t op = opcode_buffer[i]; - ASSERT_TRUE(this->op_->Eval(i, i + 1)) << "Failed op: 0x" << std::hex << op; - ASSERT_EQ(op, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()) << "Failed op: 0x" << std::hex << op; - ASSERT_EQ(op - 0x30U, this->op_->StackAt(0)) << "Failed op: 0x" << std::hex << op; - } -} - -TYPED_TEST_P(DwarfOpTest, op_reg) { - std::vector opcode_buffer; - - // Verify every reg opcode. - for (uint8_t op = 0x50; op <= 0x6f; op++) { - opcode_buffer.push_back(op); - } - this->op_memory_.SetMemory(0, opcode_buffer); - - for (size_t i = 0; i < opcode_buffer.size(); i++) { - uint32_t op = opcode_buffer[i]; - ASSERT_TRUE(this->op_->Eval(i, i + 1)) << "Failed op: 0x" << std::hex << op; - ASSERT_EQ(op, this->op_->cur_op()); - ASSERT_TRUE(this->op_->is_register()) << "Failed op: 0x" << std::hex << op; - ASSERT_EQ(1U, this->op_->StackSize()) << "Failed op: 0x" << std::hex << op; - ASSERT_EQ(op - 0x50U, this->op_->StackAt(0)) << "Failed op: 0x" << std::hex << op; - } -} - -TYPED_TEST_P(DwarfOpTest, op_regx) { - std::vector opcode_buffer = { - 0x90, 0x02, 0x90, 0x80, 0x15, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - ASSERT_TRUE(this->op_->Eval(0, 2)); - ASSERT_EQ(0x90, this->op_->cur_op()); - ASSERT_TRUE(this->op_->is_register()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(0x02U, this->op_->StackAt(0)); - - ASSERT_TRUE(this->op_->Eval(2, 5)); - ASSERT_EQ(0x90, this->op_->cur_op()); - ASSERT_TRUE(this->op_->is_register()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(0xa80U, this->op_->StackAt(0)); -} - -TYPED_TEST_P(DwarfOpTest, op_breg) { - std::vector opcode_buffer; - - // Verify every reg opcode. - for (uint8_t op = 0x70; op <= 0x8f; op++) { - // Positive value added to register. - opcode_buffer.push_back(op); - opcode_buffer.push_back(0x12); - // Negative value added to register. - opcode_buffer.push_back(op); - opcode_buffer.push_back(0x7e); - } - this->op_memory_.SetMemory(0, opcode_buffer); - - RegsImplFake regs(32); - for (size_t i = 0; i < 32; i++) { - regs[i] = i + 10; - } - RegsInfo regs_info(®s); - this->op_->set_regs_info(®s_info); - - uint64_t offset = 0; - for (uint32_t op = 0x70; op <= 0x8f; op++) { - // Positive value added to register. - ASSERT_TRUE(this->op_->Eval(offset, offset + 2)) << "Failed op: 0x" << std::hex << op; - ASSERT_EQ(op, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()) << "Failed op: 0x" << std::hex << op; - ASSERT_EQ(op - 0x70 + 10 + 0x12, this->op_->StackAt(0)) << "Failed op: 0x" << std::hex << op; - offset += 2; - - // Negative value added to register. - ASSERT_TRUE(this->op_->Eval(offset, offset + 2)) << "Failed op: 0x" << std::hex << op; - ASSERT_EQ(op, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()) << "Failed op: 0x" << std::hex << op; - ASSERT_EQ(op - 0x70 + 10 - 2, this->op_->StackAt(0)) << "Failed op: 0x" << std::hex << op; - offset += 2; - } -} - -TYPED_TEST_P(DwarfOpTest, op_breg_invalid_register) { - std::vector opcode_buffer = { - 0x7f, 0x12, 0x80, 0x12, - }; - this->op_memory_.SetMemory(0, opcode_buffer); - - RegsImplFake regs(16); - for (size_t i = 0; i < 16; i++) { - regs[i] = i + 10; - } - RegsInfo regs_info(®s); - this->op_->set_regs_info(®s_info); - - // Should pass since this references the last regsister. - ASSERT_TRUE(this->op_->Eval(0, 2)); - ASSERT_EQ(0x7fU, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(0x2bU, this->op_->StackAt(0)); - - // Should fail since this references a non-existent register. - ASSERT_FALSE(this->op_->Eval(2, 4)); - ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode()); -} - -TYPED_TEST_P(DwarfOpTest, op_bregx) { - std::vector opcode_buffer = {// Positive value added to register. - 0x92, 0x05, 0x20, - // Negative value added to register. - 0x92, 0x06, 0x80, 0x7e, - // Illegal register. - 0x92, 0x80, 0x15, 0x80, 0x02}; - this->op_memory_.SetMemory(0, opcode_buffer); - - RegsImplFake regs(10); - regs[5] = 0x45; - regs[6] = 0x190; - RegsInfo regs_info(®s); - this->op_->set_regs_info(®s_info); - - ASSERT_TRUE(this->op_->Eval(0, 3)); - ASSERT_EQ(0x92, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(0x65U, this->op_->StackAt(0)); - - ASSERT_TRUE(this->op_->Eval(3, 7)); - ASSERT_EQ(0x92, this->op_->cur_op()); - ASSERT_EQ(1U, this->op_->StackSize()); - ASSERT_EQ(0x90U, this->op_->StackAt(0)); - - ASSERT_FALSE(this->op_->Eval(7, 12)); - ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode()); -} - -TYPED_TEST_P(DwarfOpTest, op_nop) { - this->op_memory_.SetMemory(0, std::vector{0x96}); - - ASSERT_TRUE(this->op_->Decode()); - ASSERT_EQ(0x96, this->op_->cur_op()); - ASSERT_EQ(0U, this->op_->StackSize()); -} - -TYPED_TEST_P(DwarfOpTest, is_dex_pc) { - // Special sequence that indicates this is a dex pc. - this->op_memory_.SetMemory(0, std::vector{0x0c, 'D', 'E', 'X', '1', 0x13}); - - ASSERT_TRUE(this->op_->Eval(0, 6)); - EXPECT_TRUE(this->op_->dex_pc_set()); - - // Try without the last op. - ASSERT_TRUE(this->op_->Eval(0, 5)); - EXPECT_FALSE(this->op_->dex_pc_set()); - - // Change the constant. - this->op_memory_.SetMemory(0, std::vector{0x0c, 'D', 'E', 'X', '2', 0x13}); - ASSERT_TRUE(this->op_->Eval(0, 6)); - EXPECT_FALSE(this->op_->dex_pc_set()); -} - -REGISTER_TYPED_TEST_SUITE_P(DwarfOpTest, decode, eval, illegal_opcode, not_implemented, op_addr, - op_deref, op_deref_size, const_unsigned, const_signed, const_uleb, - const_sleb, op_dup, op_drop, op_over, op_pick, op_swap, op_rot, op_abs, - op_and, op_div, op_minus, op_mod, op_mul, op_neg, op_not, op_or, - op_plus, op_plus_uconst, op_shl, op_shr, op_shra, op_xor, op_bra, - compare_opcode_stack_error, compare_opcodes, op_skip, op_lit, op_reg, - op_regx, op_breg, op_breg_invalid_register, op_bregx, op_nop, - is_dex_pc); - -typedef ::testing::Types DwarfOpTestTypes; -INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfOpTest, DwarfOpTestTypes); - -} // namespace unwindstack diff --git a/libunwindstack/tests/DwarfSectionImplTest.cpp b/libunwindstack/tests/DwarfSectionImplTest.cpp deleted file mode 100644 index a08a8d070..000000000 --- a/libunwindstack/tests/DwarfSectionImplTest.cpp +++ /dev/null @@ -1,624 +0,0 @@ -/* - * Copyright (C) 2016 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 "DwarfEncoding.h" - -#include "LogFake.h" -#include "MemoryFake.h" -#include "RegsFake.h" - -namespace unwindstack { - -template -class TestDwarfSectionImpl : public DwarfSectionImpl { - public: - TestDwarfSectionImpl(Memory* memory) : DwarfSectionImpl(memory) {} - virtual ~TestDwarfSectionImpl() = default; - - bool Init(uint64_t, uint64_t, int64_t) override { return false; } - - void GetFdes(std::vector*) override {} - - const DwarfFde* GetFdeFromPc(uint64_t) override { return nullptr; } - - uint64_t GetCieOffsetFromFde32(uint32_t) { return 0; } - - uint64_t GetCieOffsetFromFde64(uint64_t) { return 0; } - - uint64_t AdjustPcFromFde(uint64_t) override { return 0; } - - void TestSetCachedCieLocRegs(uint64_t offset, const dwarf_loc_regs_t& loc_regs) { - this->cie_loc_regs_[offset] = loc_regs; - } - void TestClearCachedCieLocRegs() { this->cie_loc_regs_.clear(); } - void TestClearError() { this->last_error_.code = DWARF_ERROR_NONE; } -}; - -template -class DwarfSectionImplTest : public ::testing::Test { - protected: - void SetUp() override { - memory_.Clear(); - section_ = new TestDwarfSectionImpl(&memory_); - ResetLogs(); - } - - void TearDown() override { delete section_; } - - MemoryFake memory_; - TestDwarfSectionImpl* section_ = nullptr; -}; -TYPED_TEST_SUITE_P(DwarfSectionImplTest); - -// NOTE: All test class variables need to be referenced as this->. - -TYPED_TEST_P(DwarfSectionImplTest, GetCieFromOffset_fail_should_not_cache) { - ASSERT_TRUE(this->section_->GetCieFromOffset(0x4000) == nullptr); - EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode()); - EXPECT_EQ(0x4000U, this->section_->LastErrorAddress()); - - this->section_->TestClearError(); - ASSERT_TRUE(this->section_->GetCieFromOffset(0x4000) == nullptr); - EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode()); - EXPECT_EQ(0x4000U, this->section_->LastErrorAddress()); -} - -TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_fail_should_not_cache) { - ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr); - EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode()); - EXPECT_EQ(0x4000U, this->section_->LastErrorAddress()); - - this->section_->TestClearError(); - ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr); - EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode()); - EXPECT_EQ(0x4000U, this->section_->LastErrorAddress()); -} - -TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_eval_fail) { - DwarfCie cie{.version = 3, .return_address_register = 5}; - RegsImplFake regs(10); - dwarf_loc_regs_t loc_regs; - - regs.set_pc(0x100); - regs.set_sp(0x2000); - regs[5] = 0x20; - regs[9] = 0x3000; - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x2, 0x5002}}; - bool finished; - ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode()); - EXPECT_EQ(0x5000U, this->section_->LastErrorAddress()); -} - -TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_no_stack) { - DwarfCie cie{.version = 3, .return_address_register = 5}; - RegsImplFake regs(10); - dwarf_loc_regs_t loc_regs; - - regs.set_pc(0x100); - regs.set_sp(0x2000); - regs[5] = 0x20; - regs[9] = 0x3000; - this->memory_.SetMemory(0x5000, std::vector{0x96, 0x96, 0x96}); - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x2, 0x5002}}; - bool finished; - ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->section_->LastErrorCode()); -} - -TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr) { - DwarfCie cie{.version = 3, .return_address_register = 5}; - RegsImplFake regs(10); - dwarf_loc_regs_t loc_regs; - - regs.set_pc(0x100); - regs.set_sp(0x2000); - regs[5] = 0x20; - regs[9] = 0x3000; - this->memory_.SetMemory(0x5000, std::vector{0x0c, 0x00, 0x00, 0x00, 0x80}); - TypeParam cfa_value = 0x12345; - this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value)); - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5004}}; - bool finished; - ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode()); -} - -TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_val_expr) { - DwarfCie cie{.version = 3, .return_address_register = 5}; - RegsImplFake regs(10); - dwarf_loc_regs_t loc_regs; - - regs.set_pc(0x100); - regs.set_sp(0x2000); - regs[5] = 0x20; - regs[9] = 0x3000; - this->memory_.SetMemory(0x5000, std::vector{0x0c, 0x00, 0x00, 0x00, 0x80}); - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5004}}; - bool finished; - ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - ASSERT_FALSE(finished); - EXPECT_EQ(0x80000000U, regs.sp()); - EXPECT_EQ(0x20U, regs.pc()); -} - -TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_is_register) { - DwarfCie cie{.version = 3, .return_address_register = 5}; - RegsImplFake regs(10); - dwarf_loc_regs_t loc_regs; - - regs.set_pc(0x100); - regs.set_sp(0x2000); - regs[5] = 0x20; - regs[9] = 0x3000; - this->memory_.SetMemory(0x5000, std::vector{0x50, 0x96, 0x96}); - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x2, 0x5002}}; - bool finished; - ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->section_->LastErrorCode()); -} - -TYPED_TEST_P(DwarfSectionImplTest, Eval_bad_regs) { - DwarfCie cie{.return_address_register = 60}; - RegsImplFake regs(10); - dwarf_loc_regs_t loc_regs; - - bool finished; - ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode()); -} - -TYPED_TEST_P(DwarfSectionImplTest, Eval_no_cfa) { - DwarfCie cie{.return_address_register = 5}; - RegsImplFake regs(10); - dwarf_loc_regs_t loc_regs; - - bool finished; - ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_EQ(DWARF_ERROR_CFA_NOT_DEFINED, this->section_->LastErrorCode()); -} - -TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_bad) { - DwarfCie cie{.return_address_register = 5}; - RegsImplFake regs(10); - dwarf_loc_regs_t loc_regs; - - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {20, 0}}; - bool finished; - ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode()); - - this->section_->TestClearError(); - loc_regs.erase(CFA_REG); - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_INVALID, {0, 0}}; - ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode()); - - this->section_->TestClearError(); - loc_regs.erase(CFA_REG); - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_OFFSET, {0, 0}}; - ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode()); - - this->section_->TestClearError(); - loc_regs.erase(CFA_REG); - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0, 0}}; - ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode()); -} - -TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_prev) { - DwarfCie cie{.return_address_register = 5}; - RegsImplFake regs(10); - dwarf_loc_regs_t loc_regs; - - regs.set_pc(0x100); - regs.set_sp(0x2000); - regs[5] = 0x20; - regs[9] = 0x3000; - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {9, 0}}; - bool finished; - ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_FALSE(finished); - EXPECT_EQ(0x20U, regs.pc()); - EXPECT_EQ(0x3000U, regs.sp()); -} - -TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_from_value) { - DwarfCie cie{.return_address_register = 5}; - RegsImplFake regs(10); - dwarf_loc_regs_t loc_regs; - - regs.set_pc(0x100); - regs.set_sp(0x2000); - regs[5] = 0x20; - regs[6] = 0x4000; - regs[9] = 0x3000; - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {6, 0}}; - bool finished; - ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_FALSE(finished); - EXPECT_EQ(0x20U, regs.pc()); - EXPECT_EQ(0x4000U, regs.sp()); -} - -TYPED_TEST_P(DwarfSectionImplTest, Eval_double_indirection) { - DwarfCie cie{.return_address_register = 5}; - RegsImplFake regs(10); - dwarf_loc_regs_t loc_regs; - - regs.set_pc(0x100); - regs.set_sp(0x2000); - regs[1] = 0x100; - regs[3] = 0x300; - regs[8] = 0x10; - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; - loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {3, 1}}; - loc_regs[9] = DwarfLocation{DWARF_LOCATION_REGISTER, {1, 2}}; - bool finished; - ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_EQ(0x301U, regs[1]); - EXPECT_EQ(0x300U, regs[3]); - EXPECT_EQ(0x10U, regs[8]); - EXPECT_EQ(0x102U, regs[9]); -} - -TYPED_TEST_P(DwarfSectionImplTest, Eval_register_reference_chain) { - DwarfCie cie{.return_address_register = 5}; - RegsImplFake regs(10); - dwarf_loc_regs_t loc_regs; - - regs.set_pc(0x100); - regs.set_sp(0x2000); - regs[0] = 0x10; - regs[1] = 0x20; - regs[2] = 0x30; - regs[3] = 0x40; - regs[4] = 0x50; - regs[5] = 0x60; - regs[8] = 0x20; - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; - loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {0, 1}}; - loc_regs[2] = DwarfLocation{DWARF_LOCATION_REGISTER, {1, 2}}; - loc_regs[3] = DwarfLocation{DWARF_LOCATION_REGISTER, {2, 3}}; - loc_regs[4] = DwarfLocation{DWARF_LOCATION_REGISTER, {3, 4}}; - loc_regs[5] = DwarfLocation{DWARF_LOCATION_REGISTER, {4, 5}}; - bool finished; - ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_EQ(0x10U, regs[0]); - EXPECT_EQ(0x11U, regs[1]); - EXPECT_EQ(0x22U, regs[2]); - EXPECT_EQ(0x33U, regs[3]); - EXPECT_EQ(0x44U, regs[4]); - EXPECT_EQ(0x55U, regs[5]); - EXPECT_EQ(0x20U, regs[8]); -} - -TYPED_TEST_P(DwarfSectionImplTest, Eval_dex_pc) { - DwarfCie cie{.return_address_register = 5}; - RegsImplFake regs(10); - dwarf_loc_regs_t loc_regs; - - regs.set_pc(0x100); - regs.set_sp(0x2000); - regs[0] = 0x10; - regs[8] = 0x20; - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; - loc_regs[1] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x8, 0x5008}}; - this->memory_.SetMemory(0x5000, std::vector{0x0c, 'D', 'E', 'X', '1', 0x13, 0x08, 0x11}); - bool finished; - ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_EQ(0x10U, regs[0]); - EXPECT_EQ(0x20U, regs[8]); - EXPECT_EQ(0x11U, regs.dex_pc()); -} - -TYPED_TEST_P(DwarfSectionImplTest, Eval_invalid_register) { - DwarfCie cie{.return_address_register = 5}; - RegsImplFake regs(10); - dwarf_loc_regs_t loc_regs; - - regs.set_pc(0x100); - regs.set_sp(0x2000); - regs[8] = 0x10; - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; - loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {10, 0}}; - bool finished; - ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode()); -} - -TYPED_TEST_P(DwarfSectionImplTest, Eval_different_reg_locations) { - DwarfCie cie{.return_address_register = 5}; - RegsImplFake regs(10); - dwarf_loc_regs_t loc_regs; - - if (sizeof(TypeParam) == sizeof(uint64_t)) { - this->memory_.SetData64(0x2150, 0x12345678abcdef00ULL); - } else { - this->memory_.SetData32(0x2150, 0x12345678); - } - - regs.set_pc(0x100); - regs.set_sp(0x2000); - regs[3] = 0x234; - regs[5] = 0x10; - regs[8] = 0x2100; - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; - loc_regs[1] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0x100, 0}}; - loc_regs[2] = DwarfLocation{DWARF_LOCATION_OFFSET, {0x50, 0}}; - loc_regs[3] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}}; - bool finished; - ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_FALSE(finished); - EXPECT_EQ(0x10U, regs.pc()); - EXPECT_EQ(0x2100U, regs.sp()); - EXPECT_EQ(0x2200U, regs[1]); - EXPECT_EQ(0x234U, regs[3]); - if (sizeof(TypeParam) == sizeof(uint64_t)) { - EXPECT_EQ(0x12345678abcdef00ULL, regs[2]); - } else { - EXPECT_EQ(0x12345678U, regs[2]); - } -} - -TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address_undefined) { - DwarfCie cie{.return_address_register = 5}; - RegsImplFake regs(10); - dwarf_loc_regs_t loc_regs; - - regs.set_pc(0x100); - regs.set_sp(0x2000); - regs[5] = 0x20; - regs[8] = 0x10; - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; - loc_regs[5] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}}; - bool finished; - ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_TRUE(finished); - EXPECT_EQ(0U, regs.pc()); - EXPECT_EQ(0x10U, regs.sp()); -} - -TYPED_TEST_P(DwarfSectionImplTest, Eval_pc_zero) { - DwarfCie cie{.return_address_register = 5}; - RegsImplFake regs(10); - dwarf_loc_regs_t loc_regs; - - regs.set_pc(0x100); - regs.set_sp(0x2000); - regs[5] = 0; - regs[8] = 0x10; - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; - bool finished; - ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_TRUE(finished); - EXPECT_EQ(0U, regs.pc()); - EXPECT_EQ(0x10U, regs.sp()); -} - -TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address) { - DwarfCie cie{.return_address_register = 5}; - RegsImplFake regs(10); - dwarf_loc_regs_t loc_regs; - - regs.set_pc(0x100); - regs.set_sp(0x2000); - regs[5] = 0x20; - regs[8] = 0x10; - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; - bool finished; - ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_FALSE(finished); - EXPECT_EQ(0x20U, regs.pc()); - EXPECT_EQ(0x10U, regs.sp()); -} - -TYPED_TEST_P(DwarfSectionImplTest, Eval_ignore_large_reg_loc) { - DwarfCie cie{.return_address_register = 5}; - RegsImplFake regs(10); - dwarf_loc_regs_t loc_regs; - - regs.set_pc(0x100); - regs.set_sp(0x2000); - regs[5] = 0x20; - regs[8] = 0x10; - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; - // This should not result in any errors. - loc_regs[20] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; - bool finished; - ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_FALSE(finished); - EXPECT_EQ(0x20U, regs.pc()); - EXPECT_EQ(0x10U, regs.sp()); -} - -TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_expr) { - DwarfCie cie{.version = 3, .return_address_register = 5}; - RegsImplFake regs(10); - dwarf_loc_regs_t loc_regs; - - regs.set_pc(0x100); - regs.set_sp(0x2000); - regs[8] = 0x3000; - this->memory_.SetMemory(0x5000, std::vector{0x0c, 0x00, 0x00, 0x00, 0x80}); - TypeParam cfa_value = 0x12345; - this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value)); - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; - loc_regs[5] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5004}}; - bool finished; - ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_FALSE(finished); - EXPECT_EQ(0x3000U, regs.sp()); - EXPECT_EQ(0x12345U, regs.pc()); -} - -TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) { - DwarfCie cie{.version = 3, .return_address_register = 5}; - RegsImplFake regs(10); - dwarf_loc_regs_t loc_regs; - - regs.set_pc(0x100); - regs.set_sp(0x2000); - regs[8] = 0x3000; - this->memory_.SetMemory(0x5000, std::vector{0x0c, 0x00, 0x00, 0x00, 0x80}); - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; - loc_regs[5] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5004}}; - bool finished; - ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_FALSE(finished); - EXPECT_EQ(0x3000U, regs.sp()); - EXPECT_EQ(0x80000000U, regs.pc()); -} - -TYPED_TEST_P(DwarfSectionImplTest, Eval_pseudo_register_invalid) { - DwarfCie cie{.return_address_register = 5}; - RegsImplFake regs(10); - regs.set_pseudo_reg(11); - dwarf_loc_regs_t loc_regs; - - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; - loc_regs[1] = DwarfLocation{DWARF_LOCATION_PSEUDO_REGISTER, {20, 0}}; - bool finished; - ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode()); - - loc_regs.clear(); - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; - loc_regs[12] = DwarfLocation{DWARF_LOCATION_PSEUDO_REGISTER, {20, 0}}; - ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode()); -} - -TYPED_TEST_P(DwarfSectionImplTest, Eval_pseudo_register) { - DwarfCie cie{.return_address_register = 5}; - RegsImplFake regs(10); - regs.set_pseudo_reg(11); - dwarf_loc_regs_t loc_regs; - - loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; - loc_regs[11] = DwarfLocation{DWARF_LOCATION_PSEUDO_REGISTER, {20, 0}}; - bool finished; - ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished)); - uint64_t pseudo_value = 0; - ASSERT_TRUE(regs.GetPseudoRegister(11, &pseudo_value)); - EXPECT_EQ(20U, pseudo_value); -} - -TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_not_cached) { - DwarfCie cie{}; - cie.cfa_instructions_offset = 0x3000; - cie.cfa_instructions_end = 0x3002; - DwarfFde fde{}; - fde.cie = &cie; - fde.cie_offset = 0x8000; - fde.cfa_instructions_offset = 0x6000; - fde.cfa_instructions_end = 0x6002; - - this->memory_.SetMemory(0x3000, std::vector{0x09, 0x02, 0x01}); - this->memory_.SetMemory(0x6000, std::vector{0x09, 0x04, 0x03}); - - dwarf_loc_regs_t loc_regs; - ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs, ARCH_UNKNOWN)); - ASSERT_EQ(2U, loc_regs.size()); - - auto entry = loc_regs.find(2); - ASSERT_NE(entry, loc_regs.end()); - ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type); - ASSERT_EQ(1U, entry->second.values[0]); - - entry = loc_regs.find(4); - ASSERT_NE(entry, loc_regs.end()); - ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type); - ASSERT_EQ(3U, entry->second.values[0]); -} - -TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_cached) { - DwarfCie cie{}; - cie.cfa_instructions_offset = 0x3000; - cie.cfa_instructions_end = 0x3002; - DwarfFde fde{}; - fde.cie = &cie; - fde.cie_offset = 0x8000; - fde.cfa_instructions_offset = 0x6000; - fde.cfa_instructions_end = 0x6002; - - dwarf_loc_regs_t cie_loc_regs; - cie_loc_regs[6] = DwarfLocation{DWARF_LOCATION_REGISTER, {4, 0}}; - this->section_->TestSetCachedCieLocRegs(0x8000, cie_loc_regs); - this->memory_.SetMemory(0x6000, std::vector{0x09, 0x04, 0x03}); - - dwarf_loc_regs_t loc_regs; - ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs, ARCH_UNKNOWN)); - ASSERT_EQ(2U, loc_regs.size()); - - auto entry = loc_regs.find(6); - ASSERT_NE(entry, loc_regs.end()); - ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type); - ASSERT_EQ(4U, entry->second.values[0]); - - entry = loc_regs.find(4); - ASSERT_NE(entry, loc_regs.end()); - ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type); - ASSERT_EQ(3U, entry->second.values[0]); -} - -TYPED_TEST_P(DwarfSectionImplTest, Log) { - DwarfCie cie{}; - cie.cfa_instructions_offset = 0x5000; - cie.cfa_instructions_end = 0x5001; - DwarfFde fde{}; - fde.cie = &cie; - fde.cfa_instructions_offset = 0x6000; - fde.cfa_instructions_end = 0x6001; - - this->memory_.SetMemory(0x5000, std::vector{0x00}); - this->memory_.SetMemory(0x6000, std::vector{0xc2}); - ASSERT_TRUE(this->section_->Log(2, 0x1000, &fde, ARCH_UNKNOWN)); - - ASSERT_EQ( - "4 unwind DW_CFA_nop\n" - "4 unwind Raw Data: 0x00\n" - "4 unwind DW_CFA_restore register(2)\n" - "4 unwind Raw Data: 0xc2\n", - GetFakeLogPrint()); - ASSERT_EQ("", GetFakeLogBuf()); -} - -REGISTER_TYPED_TEST_SUITE_P(DwarfSectionImplTest, GetCieFromOffset_fail_should_not_cache, - GetFdeFromOffset_fail_should_not_cache, Eval_cfa_expr_eval_fail, - Eval_cfa_expr_no_stack, Eval_cfa_expr_is_register, Eval_cfa_expr, - Eval_cfa_val_expr, Eval_bad_regs, Eval_no_cfa, Eval_cfa_bad, - Eval_cfa_register_prev, Eval_cfa_register_from_value, - Eval_double_indirection, Eval_register_reference_chain, Eval_dex_pc, - Eval_invalid_register, Eval_different_reg_locations, - Eval_return_address_undefined, Eval_pc_zero, Eval_return_address, - Eval_ignore_large_reg_loc, Eval_reg_expr, Eval_reg_val_expr, - Eval_pseudo_register_invalid, Eval_pseudo_register, - GetCfaLocationInfo_cie_not_cached, GetCfaLocationInfo_cie_cached, Log); - -typedef ::testing::Types DwarfSectionImplTestTypes; -INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfSectionImplTest, DwarfSectionImplTestTypes); - -} // namespace unwindstack diff --git a/libunwindstack/tests/DwarfSectionTest.cpp b/libunwindstack/tests/DwarfSectionTest.cpp deleted file mode 100644 index e5a1aed12..000000000 --- a/libunwindstack/tests/DwarfSectionTest.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2016 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 "MemoryFake.h" -#include "RegsFake.h" - -namespace unwindstack { - -class MockDwarfSection : public DwarfSection { - public: - MockDwarfSection(Memory* memory) : DwarfSection(memory) {} - virtual ~MockDwarfSection() = default; - - MOCK_METHOD(bool, Init, (uint64_t, uint64_t, int64_t), (override)); - - MOCK_METHOD(bool, Eval, (const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*), - (override)); - - MOCK_METHOD(bool, Log, (uint8_t, uint64_t, const DwarfFde*, ArchEnum arch), (override)); - - MOCK_METHOD(void, GetFdes, (std::vector*), (override)); - - MOCK_METHOD(const DwarfFde*, GetFdeFromPc, (uint64_t), (override)); - - MOCK_METHOD(bool, GetCfaLocationInfo, - (uint64_t, const DwarfFde*, dwarf_loc_regs_t*, ArchEnum arch), (override)); - - MOCK_METHOD(uint64_t, GetCieOffsetFromFde32, (uint32_t), (override)); - - MOCK_METHOD(uint64_t, GetCieOffsetFromFde64, (uint64_t), (override)); - - MOCK_METHOD(uint64_t, AdjustPcFromFde, (uint64_t), (override)); -}; - -class DwarfSectionTest : public ::testing::Test { - protected: - void SetUp() override { section_.reset(new MockDwarfSection(&memory_)); } - - MemoryFake memory_; - std::unique_ptr section_; - static RegsFake regs_; -}; - -RegsFake DwarfSectionTest::regs_(10); - -TEST_F(DwarfSectionTest, Step_fail_fde) { - EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(nullptr)); - - bool finished; - bool is_signal_frame; - ASSERT_FALSE(section_->Step(0x1000, nullptr, nullptr, &finished, &is_signal_frame)); -} - -TEST_F(DwarfSectionTest, Step_fail_cie_null) { - DwarfFde fde{}; - fde.pc_end = 0x2000; - fde.cie = nullptr; - - EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde)); - - bool finished; - bool is_signal_frame; - ASSERT_FALSE(section_->Step(0x1000, ®s_, nullptr, &finished, &is_signal_frame)); -} - -TEST_F(DwarfSectionTest, Step_fail_cfa_location) { - DwarfCie cie{}; - DwarfFde fde{}; - fde.pc_end = 0x2000; - fde.cie = &cie; - - EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde)); - EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde, ::testing::_, ::testing::_)) - .WillOnce(::testing::Return(false)); - - bool finished; - bool is_signal_frame; - ASSERT_FALSE(section_->Step(0x1000, ®s_, nullptr, &finished, &is_signal_frame)); -} - -TEST_F(DwarfSectionTest, Step_pass) { - DwarfCie cie{}; - DwarfFde fde{}; - fde.pc_end = 0x2000; - fde.cie = &cie; - - EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde)); - EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde, ::testing::_, ::testing::_)) - .WillOnce(::testing::Return(true)); - - MemoryFake process; - EXPECT_CALL(*section_, Eval(&cie, &process, ::testing::_, ®s_, ::testing::_)) - .WillOnce(::testing::Return(true)); - - bool finished; - bool is_signal_frame; - ASSERT_TRUE(section_->Step(0x1000, ®s_, &process, &finished, &is_signal_frame)); -} - -static bool MockGetCfaLocationInfo(::testing::Unused, const DwarfFde* fde, - dwarf_loc_regs_t* loc_regs, ArchEnum) { - loc_regs->pc_start = fde->pc_start; - loc_regs->pc_end = fde->pc_end; - return true; -} - -TEST_F(DwarfSectionTest, Step_cache) { - DwarfCie cie{}; - DwarfFde fde{}; - fde.pc_start = 0x500; - fde.pc_end = 0x2000; - fde.cie = &cie; - - EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde)); - EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde, ::testing::_, ::testing::_)) - .WillOnce(::testing::Invoke(MockGetCfaLocationInfo)); - - MemoryFake process; - EXPECT_CALL(*section_, Eval(&cie, &process, ::testing::_, ®s_, ::testing::_)) - .WillRepeatedly(::testing::Return(true)); - - bool finished; - bool is_signal_frame; - ASSERT_TRUE(section_->Step(0x1000, ®s_, &process, &finished, &is_signal_frame)); - ASSERT_TRUE(section_->Step(0x1000, ®s_, &process, &finished, &is_signal_frame)); - ASSERT_TRUE(section_->Step(0x1500, ®s_, &process, &finished, &is_signal_frame)); -} - -TEST_F(DwarfSectionTest, Step_cache_not_in_pc) { - DwarfCie cie{}; - DwarfFde fde0{}; - fde0.pc_start = 0x1000; - fde0.pc_end = 0x2000; - fde0.cie = &cie; - EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde0)); - EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde0, ::testing::_, ::testing::_)) - .WillOnce(::testing::Invoke(MockGetCfaLocationInfo)); - - MemoryFake process; - EXPECT_CALL(*section_, Eval(&cie, &process, ::testing::_, ®s_, ::testing::_)) - .WillRepeatedly(::testing::Return(true)); - - bool finished; - bool is_signal_frame; - ASSERT_TRUE(section_->Step(0x1000, ®s_, &process, &finished, &is_signal_frame)); - - DwarfFde fde1{}; - fde1.pc_start = 0x500; - fde1.pc_end = 0x800; - fde1.cie = &cie; - EXPECT_CALL(*section_, GetFdeFromPc(0x600)).WillOnce(::testing::Return(&fde1)); - EXPECT_CALL(*section_, GetCfaLocationInfo(0x600, &fde1, ::testing::_, ::testing::_)) - .WillOnce(::testing::Invoke(MockGetCfaLocationInfo)); - - ASSERT_TRUE(section_->Step(0x600, ®s_, &process, &finished, &is_signal_frame)); - ASSERT_TRUE(section_->Step(0x700, ®s_, &process, &finished, &is_signal_frame)); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/ElfCacheTest.cpp b/libunwindstack/tests/ElfCacheTest.cpp deleted file mode 100644 index 5f135467d..000000000 --- a/libunwindstack/tests/ElfCacheTest.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright (C) 2018 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 "ElfTestUtils.h" -#include "MemoryFake.h" - -namespace unwindstack { - -class ElfCacheTest : public ::testing::Test { - protected: - static void SetUpTestSuite() { memory_.reset(new MemoryFake); } - - void SetUp() override { Elf::SetCachingEnabled(true); } - - void TearDown() override { Elf::SetCachingEnabled(false); } - - void WriteElfFile(uint64_t offset, TemporaryFile* tf, uint32_t type) { - ASSERT_TRUE(type == EM_ARM || type == EM_386 || type == EM_X86_64); - size_t ehdr_size; - Elf32_Ehdr ehdr32; - Elf64_Ehdr ehdr64; - void* ptr; - if (type == EM_ARM || type == EM_386) { - ehdr_size = sizeof(ehdr32); - ptr = &ehdr32; - TestInitEhdr(&ehdr32, ELFCLASS32, type); - } else { - ehdr_size = sizeof(ehdr64); - ptr = &ehdr64; - TestInitEhdr(&ehdr64, ELFCLASS64, type); - } - - ASSERT_EQ(offset, static_cast(lseek(tf->fd, offset, SEEK_SET))); - ASSERT_TRUE(android::base::WriteFully(tf->fd, ptr, ehdr_size)); - } - - void VerifyWithinSameMap(bool cache_enabled); - void VerifySameMap(bool cache_enabled); - void VerifyWithinSameMapNeverReadAtZero(bool cache_enabled); - - static std::shared_ptr memory_; -}; - -std::shared_ptr ElfCacheTest::memory_; - -void ElfCacheTest::VerifySameMap(bool cache_enabled) { - if (!cache_enabled) { - Elf::SetCachingEnabled(false); - } - - TemporaryFile tf; - ASSERT_TRUE(tf.fd != -1); - WriteElfFile(0, &tf, EM_ARM); - close(tf.fd); - - uint64_t start = 0x1000; - uint64_t end = 0x20000; - MapInfo info1(nullptr, nullptr, start, end, 0, 0x5, tf.path); - MapInfo info2(nullptr, nullptr, start, end, 0, 0x5, tf.path); - - Elf* elf1 = info1.GetElf(memory_, ARCH_ARM); - ASSERT_TRUE(elf1->valid()); - Elf* elf2 = info2.GetElf(memory_, ARCH_ARM); - ASSERT_TRUE(elf2->valid()); - - if (cache_enabled) { - EXPECT_EQ(elf1, elf2); - } else { - EXPECT_NE(elf1, elf2); - } -} - -TEST_F(ElfCacheTest, no_caching) { - VerifySameMap(false); -} - -TEST_F(ElfCacheTest, caching_invalid_elf) { - VerifySameMap(true); -} - -void ElfCacheTest::VerifyWithinSameMap(bool cache_enabled) { - if (!cache_enabled) { - Elf::SetCachingEnabled(false); - } - - TemporaryFile tf; - ASSERT_TRUE(tf.fd != -1); - WriteElfFile(0, &tf, EM_ARM); - WriteElfFile(0x100, &tf, EM_386); - WriteElfFile(0x200, &tf, EM_X86_64); - lseek(tf.fd, 0x500, SEEK_SET); - uint8_t value = 0; - write(tf.fd, &value, 1); - close(tf.fd); - - uint64_t start = 0x1000; - uint64_t end = 0x20000; - // Will have an elf at offset 0 in file. - MapInfo info0_1(nullptr, nullptr, start, end, 0, 0x5, tf.path); - MapInfo info0_2(nullptr, nullptr, start, end, 0, 0x5, tf.path); - // Will have an elf at offset 0x100 in file. - MapInfo info100_1(nullptr, nullptr, start, end, 0x100, 0x5, tf.path); - MapInfo info100_2(nullptr, nullptr, start, end, 0x100, 0x5, tf.path); - // Will have an elf at offset 0x200 in file. - MapInfo info200_1(nullptr, nullptr, start, end, 0x200, 0x5, tf.path); - MapInfo info200_2(nullptr, nullptr, start, end, 0x200, 0x5, tf.path); - // Will have an elf at offset 0 in file. - MapInfo info300_1(nullptr, nullptr, start, end, 0x300, 0x5, tf.path); - MapInfo info300_2(nullptr, nullptr, start, end, 0x300, 0x5, tf.path); - - Elf* elf0_1 = info0_1.GetElf(memory_, ARCH_ARM); - ASSERT_TRUE(elf0_1->valid()); - EXPECT_EQ(ARCH_ARM, elf0_1->arch()); - Elf* elf0_2 = info0_2.GetElf(memory_, ARCH_ARM); - ASSERT_TRUE(elf0_2->valid()); - EXPECT_EQ(ARCH_ARM, elf0_2->arch()); - EXPECT_EQ(0U, info0_1.elf_offset); - EXPECT_EQ(0U, info0_2.elf_offset); - if (cache_enabled) { - EXPECT_EQ(elf0_1, elf0_2); - } else { - EXPECT_NE(elf0_1, elf0_2); - } - - Elf* elf100_1 = info100_1.GetElf(memory_, ARCH_X86); - ASSERT_TRUE(elf100_1->valid()); - EXPECT_EQ(ARCH_X86, elf100_1->arch()); - Elf* elf100_2 = info100_2.GetElf(memory_, ARCH_X86); - ASSERT_TRUE(elf100_2->valid()); - EXPECT_EQ(ARCH_X86, elf100_2->arch()); - EXPECT_EQ(0U, info100_1.elf_offset); - EXPECT_EQ(0U, info100_2.elf_offset); - if (cache_enabled) { - EXPECT_EQ(elf100_1, elf100_2); - } else { - EXPECT_NE(elf100_1, elf100_2); - } - - Elf* elf200_1 = info200_1.GetElf(memory_, ARCH_X86_64); - ASSERT_TRUE(elf200_1->valid()); - EXPECT_EQ(ARCH_X86_64, elf200_1->arch()); - Elf* elf200_2 = info200_2.GetElf(memory_, ARCH_X86_64); - ASSERT_TRUE(elf200_2->valid()); - EXPECT_EQ(ARCH_X86_64, elf200_2->arch()); - EXPECT_EQ(0U, info200_1.elf_offset); - EXPECT_EQ(0U, info200_2.elf_offset); - if (cache_enabled) { - EXPECT_EQ(elf200_1, elf200_2); - } else { - EXPECT_NE(elf200_1, elf200_2); - } - - Elf* elf300_1 = info300_1.GetElf(memory_, ARCH_ARM); - ASSERT_TRUE(elf300_1->valid()); - EXPECT_EQ(ARCH_ARM, elf300_1->arch()); - Elf* elf300_2 = info300_2.GetElf(memory_, ARCH_ARM); - ASSERT_TRUE(elf300_2->valid()); - EXPECT_EQ(ARCH_ARM, elf300_2->arch()); - EXPECT_EQ(0x300U, info300_1.elf_offset); - EXPECT_EQ(0x300U, info300_2.elf_offset); - if (cache_enabled) { - EXPECT_EQ(elf300_1, elf300_2); - EXPECT_EQ(elf0_1, elf300_1); - } else { - EXPECT_NE(elf300_1, elf300_2); - EXPECT_NE(elf0_1, elf300_1); - } -} - -TEST_F(ElfCacheTest, no_caching_valid_elf_offset_non_zero) { - VerifyWithinSameMap(false); -} - -TEST_F(ElfCacheTest, caching_valid_elf_offset_non_zero) { - VerifyWithinSameMap(true); -} - -// Verify that when reading from multiple non-zero offsets in the same map -// that when cached, all of the elf objects are the same. -void ElfCacheTest::VerifyWithinSameMapNeverReadAtZero(bool cache_enabled) { - if (!cache_enabled) { - Elf::SetCachingEnabled(false); - } - - TemporaryFile tf; - ASSERT_TRUE(tf.fd != -1); - WriteElfFile(0, &tf, EM_ARM); - lseek(tf.fd, 0x500, SEEK_SET); - uint8_t value = 0; - write(tf.fd, &value, 1); - close(tf.fd); - - uint64_t start = 0x1000; - uint64_t end = 0x20000; - // Multiple info sections at different offsets will have non-zero elf offsets. - MapInfo info300_1(nullptr, nullptr, start, end, 0x300, 0x5, tf.path); - MapInfo info300_2(nullptr, nullptr, start, end, 0x300, 0x5, tf.path); - MapInfo info400_1(nullptr, nullptr, start, end, 0x400, 0x5, tf.path); - MapInfo info400_2(nullptr, nullptr, start, end, 0x400, 0x5, tf.path); - - Elf* elf300_1 = info300_1.GetElf(memory_, ARCH_ARM); - ASSERT_TRUE(elf300_1->valid()); - EXPECT_EQ(ARCH_ARM, elf300_1->arch()); - Elf* elf300_2 = info300_2.GetElf(memory_, ARCH_ARM); - ASSERT_TRUE(elf300_2->valid()); - EXPECT_EQ(ARCH_ARM, elf300_2->arch()); - EXPECT_EQ(0x300U, info300_1.elf_offset); - EXPECT_EQ(0x300U, info300_2.elf_offset); - if (cache_enabled) { - EXPECT_EQ(elf300_1, elf300_2); - } else { - EXPECT_NE(elf300_1, elf300_2); - } - - Elf* elf400_1 = info400_1.GetElf(memory_, ARCH_ARM); - ASSERT_TRUE(elf400_1->valid()); - EXPECT_EQ(ARCH_ARM, elf400_1->arch()); - Elf* elf400_2 = info400_2.GetElf(memory_, ARCH_ARM); - ASSERT_TRUE(elf400_2->valid()); - EXPECT_EQ(ARCH_ARM, elf400_2->arch()); - EXPECT_EQ(0x400U, info400_1.elf_offset); - EXPECT_EQ(0x400U, info400_2.elf_offset); - if (cache_enabled) { - EXPECT_EQ(elf400_1, elf400_2); - EXPECT_EQ(elf300_1, elf400_1); - } else { - EXPECT_NE(elf400_1, elf400_2); - EXPECT_NE(elf300_1, elf400_1); - } -} - -TEST_F(ElfCacheTest, no_caching_valid_elf_offset_non_zero_never_read_at_zero) { - VerifyWithinSameMapNeverReadAtZero(false); -} - -TEST_F(ElfCacheTest, caching_valid_elf_offset_non_zero_never_read_at_zero) { - VerifyWithinSameMapNeverReadAtZero(true); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/ElfFake.cpp b/libunwindstack/tests/ElfFake.cpp deleted file mode 100644 index b16cd53af..000000000 --- a/libunwindstack/tests/ElfFake.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2017 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 "ElfFake.h" -#include "RegsFake.h" - -namespace unwindstack { - -std::deque ElfInterfaceFake::functions_; -std::deque ElfInterfaceFake::steps_; - -bool ElfInterfaceFake::GetFunctionName(uint64_t, std::string* name, uint64_t* offset) { - if (functions_.empty()) { - return false; - } - auto entry = functions_.front(); - functions_.pop_front(); - *name = entry.name; - *offset = entry.offset; - return true; -} - -bool ElfInterfaceFake::GetGlobalVariable(const std::string& global, uint64_t* offset) { - auto entry = globals_.find(global); - if (entry == globals_.end()) { - return false; - } - *offset = entry->second; - return true; -} - -bool ElfInterfaceFake::Step(uint64_t, Regs* regs, Memory*, bool* finished, bool* is_signal_frame) { - if (steps_.empty()) { - return false; - } - auto entry = steps_.front(); - steps_.pop_front(); - - if (entry.pc == 0 && entry.sp == 0 && !entry.finished) { - // Pretend as though there is no frame. - return false; - } - - RegsFake* fake_regs = reinterpret_cast(regs); - fake_regs->set_pc(entry.pc); - fake_regs->set_sp(entry.sp); - *finished = entry.finished; - *is_signal_frame = false; - return true; -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/ElfFake.h b/libunwindstack/tests/ElfFake.h deleted file mode 100644 index abda7b840..000000000 --- a/libunwindstack/tests/ElfFake.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2017 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_TESTS_ELF_FAKE_H -#define _LIBUNWINDSTACK_TESTS_ELF_FAKE_H - -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "ElfInterfaceArm.h" - -namespace unwindstack { - -struct StepData { - StepData(uint64_t pc, uint64_t sp, bool finished) : pc(pc), sp(sp), finished(finished) {} - uint64_t pc; - uint64_t sp; - bool finished; -}; - -struct FunctionData { - FunctionData(std::string name, uint64_t offset) : name(name), offset(offset) {} - - std::string name; - uint64_t offset; -}; - -class ElfFake : public Elf { - public: - ElfFake(Memory* memory) : Elf(memory) { valid_ = true; } - virtual ~ElfFake() = default; - - void FakeSetValid(bool valid) { valid_ = valid; } - - void FakeSetLoadBias(uint64_t load_bias) { load_bias_ = load_bias; } - - void FakeSetArch(ArchEnum arch) { arch_ = arch; } - - void FakeSetInterface(ElfInterface* interface) { interface_.reset(interface); } - void FakeSetGnuDebugdataInterface(ElfInterface* interface) { - gnu_debugdata_interface_.reset(interface); - } -}; - -class ElfInterfaceFake : public ElfInterface { - public: - ElfInterfaceFake(Memory* memory) : ElfInterface(memory) {} - virtual ~ElfInterfaceFake() = default; - - bool Init(int64_t*) override { return false; } - void InitHeaders() override {} - std::string GetSoname() override { return fake_soname_; } - - bool GetFunctionName(uint64_t, std::string*, uint64_t*) override; - bool GetGlobalVariable(const std::string&, uint64_t*) override; - std::string GetBuildID() override { return fake_build_id_; } - - bool Step(uint64_t, Regs*, Memory*, bool*, bool*) override; - - void FakeSetGlobalVariable(const std::string& global, uint64_t offset) { - globals_[global] = offset; - } - - void FakeSetBuildID(std::string& build_id) { fake_build_id_ = build_id; } - void FakeSetBuildID(const char* build_id) { fake_build_id_ = build_id; } - - void FakeSetSoname(const char* soname) { fake_soname_ = soname; } - - static void FakePushFunctionData(const FunctionData data) { functions_.push_back(data); } - static void FakePushStepData(const StepData data) { steps_.push_back(data); } - - static void FakeClear() { - functions_.clear(); - steps_.clear(); - } - - void FakeSetErrorCode(ErrorCode code) { last_error_.code = code; } - - void FakeSetErrorAddress(uint64_t address) { last_error_.address = address; } - - void FakeSetDataOffset(uint64_t offset) { data_offset_ = offset; } - void FakeSetDataVaddrStart(uint64_t vaddr) { data_vaddr_start_ = vaddr; } - void FakeSetDataVaddrEnd(uint64_t vaddr) { data_vaddr_end_ = vaddr; } - - void FakeSetDynamicOffset(uint64_t offset) { dynamic_offset_ = offset; } - void FakeSetDynamicVaddrStart(uint64_t vaddr) { dynamic_vaddr_start_ = vaddr; } - void FakeSetDynamicVaddrEnd(uint64_t vaddr) { dynamic_vaddr_end_ = vaddr; } - - void FakeSetGnuDebugdataOffset(uint64_t offset) { gnu_debugdata_offset_ = offset; } - void FakeSetGnuDebugdataSize(uint64_t size) { gnu_debugdata_size_ = size; } - - private: - std::unordered_map globals_; - std::string fake_build_id_; - std::string fake_soname_; - - static std::deque functions_; - static std::deque steps_; -}; - -class ElfInterface32Fake : public ElfInterface32 { - public: - ElfInterface32Fake(Memory* memory) : ElfInterface32(memory) {} - virtual ~ElfInterface32Fake() = default; - - void FakeSetEhFrameOffset(uint64_t offset) { eh_frame_offset_ = offset; } - void FakeSetEhFrameSize(uint64_t size) { eh_frame_size_ = size; } - void FakeSetDebugFrameOffset(uint64_t offset) { debug_frame_offset_ = offset; } - void FakeSetDebugFrameSize(uint64_t size) { debug_frame_size_ = size; } -}; - -class ElfInterface64Fake : public ElfInterface64 { - public: - ElfInterface64Fake(Memory* memory) : ElfInterface64(memory) {} - virtual ~ElfInterface64Fake() = default; - - void FakeSetEhFrameOffset(uint64_t offset) { eh_frame_offset_ = offset; } - void FakeSetEhFrameSize(uint64_t size) { eh_frame_size_ = size; } - void FakeSetDebugFrameOffset(uint64_t offset) { debug_frame_offset_ = offset; } - void FakeSetDebugFrameSize(uint64_t size) { debug_frame_size_ = size; } -}; - -class ElfInterfaceArmFake : public ElfInterfaceArm { - public: - ElfInterfaceArmFake(Memory* memory) : ElfInterfaceArm(memory) {} - virtual ~ElfInterfaceArmFake() = default; - - void FakeSetStartOffset(uint64_t offset) { start_offset_ = offset; } - void FakeSetTotalEntries(size_t entries) { total_entries_ = entries; } -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_TESTS_ELF_FAKE_H diff --git a/libunwindstack/tests/ElfInterfaceArmTest.cpp b/libunwindstack/tests/ElfInterfaceArmTest.cpp deleted file mode 100644 index 43c6a9734..000000000 --- a/libunwindstack/tests/ElfInterfaceArmTest.cpp +++ /dev/null @@ -1,422 +0,0 @@ -/* - * Copyright (C) 2016 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 "ElfInterfaceArm.h" - -#include "ElfFake.h" -#include "MemoryFake.h" - -namespace unwindstack { - -class ElfInterfaceArmTest : public ::testing::Test { - protected: - void SetUp() override { - memory_.Clear(); - process_memory_.Clear(); - } - - MemoryFake memory_; - MemoryFake process_memory_; -}; - -TEST_F(ElfInterfaceArmTest, GetPrel32Addr) { - ElfInterfaceArmFake interface(&memory_); - memory_.SetData32(0x1000, 0x230000); - - uint32_t value; - ASSERT_TRUE(interface.GetPrel31Addr(0x1000, &value)); - ASSERT_EQ(0x231000U, value); - - memory_.SetData32(0x1000, 0x80001000); - ASSERT_TRUE(interface.GetPrel31Addr(0x1000, &value)); - ASSERT_EQ(0x2000U, value); - - memory_.SetData32(0x1000, 0x70001000); - ASSERT_TRUE(interface.GetPrel31Addr(0x1000, &value)); - ASSERT_EQ(0xf0002000U, value); -} - -TEST_F(ElfInterfaceArmTest, FindEntry_start_zero) { - ElfInterfaceArmFake interface(&memory_); - interface.FakeSetStartOffset(0); - interface.FakeSetTotalEntries(10); - - uint64_t entry_offset; - ASSERT_FALSE(interface.FindEntry(0x1000, &entry_offset)); -} - -TEST_F(ElfInterfaceArmTest, FindEntry_no_entries) { - ElfInterfaceArmFake interface(&memory_); - interface.FakeSetStartOffset(0x100); - interface.FakeSetTotalEntries(0); - - uint64_t entry_offset; - ASSERT_FALSE(interface.FindEntry(0x1000, &entry_offset)); -} - -TEST_F(ElfInterfaceArmTest, FindEntry_no_valid_memory) { - ElfInterfaceArmFake interface(&memory_); - interface.FakeSetStartOffset(0x100); - interface.FakeSetTotalEntries(2); - - uint64_t entry_offset; - ASSERT_FALSE(interface.FindEntry(0x1000, &entry_offset)); -} - -TEST_F(ElfInterfaceArmTest, FindEntry_ip_before_first) { - ElfInterfaceArmFake interface(&memory_); - interface.FakeSetStartOffset(0x1000); - interface.FakeSetTotalEntries(1); - memory_.SetData32(0x1000, 0x6000); - - uint64_t entry_offset; - ASSERT_FALSE(interface.FindEntry(0x1000, &entry_offset)); -} - -TEST_F(ElfInterfaceArmTest, FindEntry_single_entry_negative_value) { - ElfInterfaceArmFake interface(&memory_); - interface.FakeSetStartOffset(0x8000); - interface.FakeSetTotalEntries(1); - memory_.SetData32(0x8000, 0x7fffff00); - - uint64_t entry_offset; - ASSERT_TRUE(interface.FindEntry(0x7ff0, &entry_offset)); - ASSERT_EQ(0x8000U, entry_offset); -} - -TEST_F(ElfInterfaceArmTest, FindEntry_two_entries) { - ElfInterfaceArmFake interface(&memory_); - interface.FakeSetStartOffset(0x1000); - interface.FakeSetTotalEntries(2); - memory_.SetData32(0x1000, 0x6000); - memory_.SetData32(0x1008, 0x7000); - - uint64_t entry_offset; - ASSERT_TRUE(interface.FindEntry(0x7000, &entry_offset)); - ASSERT_EQ(0x1000U, entry_offset); -} - -TEST_F(ElfInterfaceArmTest, FindEntry_last_check_single_entry) { - ElfInterfaceArmFake interface(&memory_); - interface.FakeSetStartOffset(0x1000); - interface.FakeSetTotalEntries(1); - memory_.SetData32(0x1000, 0x6000); - - uint64_t entry_offset; - ASSERT_TRUE(interface.FindEntry(0x7000, &entry_offset)); - ASSERT_EQ(0x1000U, entry_offset); - - // To guarantee that we are using the cache on the second run, - // set the memory to a different value. - memory_.SetData32(0x1000, 0x8000); - ASSERT_TRUE(interface.FindEntry(0x7004, &entry_offset)); - ASSERT_EQ(0x1000U, entry_offset); -} - -TEST_F(ElfInterfaceArmTest, FindEntry_last_check_multiple_entries) { - ElfInterfaceArmFake interface(&memory_); - interface.FakeSetStartOffset(0x1000); - interface.FakeSetTotalEntries(2); - memory_.SetData32(0x1000, 0x6000); - memory_.SetData32(0x1008, 0x8000); - - uint64_t entry_offset; - ASSERT_TRUE(interface.FindEntry(0x9008, &entry_offset)); - ASSERT_EQ(0x1008U, entry_offset); - - // To guarantee that we are using the cache on the second run, - // set the memory to a different value. - memory_.SetData32(0x1000, 0x16000); - memory_.SetData32(0x1008, 0x18000); - ASSERT_TRUE(interface.FindEntry(0x9100, &entry_offset)); - ASSERT_EQ(0x1008U, entry_offset); -} - -TEST_F(ElfInterfaceArmTest, FindEntry_multiple_entries_even) { - ElfInterfaceArmFake interface(&memory_); - interface.FakeSetStartOffset(0x1000); - interface.FakeSetTotalEntries(4); - memory_.SetData32(0x1000, 0x6000); - memory_.SetData32(0x1008, 0x7000); - memory_.SetData32(0x1010, 0x8000); - memory_.SetData32(0x1018, 0x9000); - - uint64_t entry_offset; - ASSERT_TRUE(interface.FindEntry(0x9100, &entry_offset)); - ASSERT_EQ(0x1010U, entry_offset); - - // To guarantee that we are using the cache on the second run, - // set the memory to a different value. - memory_.SetData32(0x1000, 0x16000); - memory_.SetData32(0x1008, 0x17000); - memory_.SetData32(0x1010, 0x18000); - memory_.SetData32(0x1018, 0x19000); - ASSERT_TRUE(interface.FindEntry(0x9100, &entry_offset)); - ASSERT_EQ(0x1010U, entry_offset); -} - -TEST_F(ElfInterfaceArmTest, FindEntry_multiple_entries_odd) { - ElfInterfaceArmFake interface(&memory_); - interface.FakeSetStartOffset(0x1000); - interface.FakeSetTotalEntries(5); - memory_.SetData32(0x1000, 0x5000); - memory_.SetData32(0x1008, 0x6000); - memory_.SetData32(0x1010, 0x7000); - memory_.SetData32(0x1018, 0x8000); - memory_.SetData32(0x1020, 0x9000); - - uint64_t entry_offset; - ASSERT_TRUE(interface.FindEntry(0x8100, &entry_offset)); - ASSERT_EQ(0x1010U, entry_offset); - - // To guarantee that we are using the cache on the second run, - // set the memory to a different value. - memory_.SetData32(0x1000, 0x15000); - memory_.SetData32(0x1008, 0x16000); - memory_.SetData32(0x1010, 0x17000); - memory_.SetData32(0x1018, 0x18000); - memory_.SetData32(0x1020, 0x19000); - ASSERT_TRUE(interface.FindEntry(0x8100, &entry_offset)); - ASSERT_EQ(0x1010U, entry_offset); -} - -TEST_F(ElfInterfaceArmTest, iterate) { - ElfInterfaceArmFake interface(&memory_); - interface.FakeSetStartOffset(0x1000); - interface.FakeSetTotalEntries(5); - memory_.SetData32(0x1000, 0x5000); - memory_.SetData32(0x1008, 0x6000); - memory_.SetData32(0x1010, 0x7000); - memory_.SetData32(0x1018, 0x8000); - memory_.SetData32(0x1020, 0x9000); - - std::vector entries; - for (auto addr : interface) { - entries.push_back(addr); - } - ASSERT_EQ(5U, entries.size()); - ASSERT_EQ(0x6000U, entries[0]); - ASSERT_EQ(0x7008U, entries[1]); - ASSERT_EQ(0x8010U, entries[2]); - ASSERT_EQ(0x9018U, entries[3]); - ASSERT_EQ(0xa020U, entries[4]); - - // Make sure the iterate cached the entries. - memory_.SetData32(0x1000, 0x11000); - memory_.SetData32(0x1008, 0x12000); - memory_.SetData32(0x1010, 0x13000); - memory_.SetData32(0x1018, 0x14000); - memory_.SetData32(0x1020, 0x15000); - - entries.clear(); - for (auto addr : interface) { - entries.push_back(addr); - } - ASSERT_EQ(5U, entries.size()); - ASSERT_EQ(0x6000U, entries[0]); - ASSERT_EQ(0x7008U, entries[1]); - ASSERT_EQ(0x8010U, entries[2]); - ASSERT_EQ(0x9018U, entries[3]); - ASSERT_EQ(0xa020U, entries[4]); -} - -TEST_F(ElfInterfaceArmTest, HandleUnknownType_arm_exidx) { - ElfInterfaceArmFake interface(&memory_); - - interface.FakeSetStartOffset(0x1000); - interface.FakeSetTotalEntries(100); - - // Verify that if the type is not the one we want, we don't set the values. - interface.HandleUnknownType(0x70000000, 0x2000, 320); - ASSERT_EQ(0x1000U, interface.start_offset()); - ASSERT_EQ(100U, interface.total_entries()); - - // Everything is correct and present. - interface.HandleUnknownType(0x70000001, 0x2000, 320); - ASSERT_EQ(0x2000U, interface.start_offset()); - ASSERT_EQ(40U, interface.total_entries()); -} - -TEST_F(ElfInterfaceArmTest, StepExidx) { - ElfInterfaceArmFake interface(&memory_); - - // FindEntry fails. - bool finished; - ASSERT_FALSE(interface.StepExidx(0x7000, nullptr, nullptr, &finished)); - EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode()); - - // ExtractEntry should fail. - interface.FakeSetStartOffset(0x1000); - interface.FakeSetTotalEntries(2); - memory_.SetData32(0x1000, 0x6000); - memory_.SetData32(0x1008, 0x8000); - - RegsArm regs; - regs[ARM_REG_SP] = 0x1000; - regs[ARM_REG_LR] = 0x20000; - regs.set_sp(regs[ARM_REG_SP]); - regs.set_pc(0x1234); - ASSERT_FALSE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished)); - EXPECT_EQ(ERROR_MEMORY_INVALID, interface.LastErrorCode()); - EXPECT_EQ(0x1004U, interface.LastErrorAddress()); - - // Eval should fail. - memory_.SetData32(0x1004, 0x81000000); - ASSERT_FALSE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished)); - EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode()); - - // Everything should pass. - memory_.SetData32(0x1004, 0x80b0b0b0); - ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished)); - EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode()); - ASSERT_FALSE(finished); - ASSERT_EQ(0x1000U, regs.sp()); - ASSERT_EQ(0x1000U, regs[ARM_REG_SP]); - ASSERT_EQ(0x20000U, regs.pc()); - ASSERT_EQ(0x20000U, regs[ARM_REG_PC]); - - // Load bias is non-zero. - interface.set_load_bias(0x1000); - ASSERT_TRUE(interface.StepExidx(0x8000, ®s, &process_memory_, &finished)); - EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode()); - - // Pc too small. - interface.set_load_bias(0x9000); - ASSERT_FALSE(interface.StepExidx(0x8000, ®s, &process_memory_, &finished)); - EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode()); -} - -TEST_F(ElfInterfaceArmTest, StepExidx_pc_set) { - ElfInterfaceArmFake interface(&memory_); - - interface.FakeSetStartOffset(0x1000); - interface.FakeSetTotalEntries(2); - memory_.SetData32(0x1000, 0x6000); - memory_.SetData32(0x1004, 0x808800b0); - memory_.SetData32(0x1008, 0x8000); - process_memory_.SetData32(0x10000, 0x10); - - RegsArm regs; - regs[ARM_REG_SP] = 0x10000; - regs[ARM_REG_LR] = 0x20000; - regs.set_sp(regs[ARM_REG_SP]); - regs.set_pc(0x1234); - - // Everything should pass. - bool finished; - ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished)); - EXPECT_EQ(ERROR_NONE, interface.LastErrorCode()); - ASSERT_FALSE(finished); - ASSERT_EQ(0x10004U, regs.sp()); - ASSERT_EQ(0x10004U, regs[ARM_REG_SP]); - ASSERT_EQ(0x10U, regs.pc()); - ASSERT_EQ(0x10U, regs[ARM_REG_PC]); -} - -TEST_F(ElfInterfaceArmTest, StepExidx_cant_unwind) { - ElfInterfaceArmFake interface(&memory_); - - interface.FakeSetStartOffset(0x1000); - interface.FakeSetTotalEntries(1); - memory_.SetData32(0x1000, 0x6000); - memory_.SetData32(0x1004, 1); - - RegsArm regs; - regs[ARM_REG_SP] = 0x10000; - regs[ARM_REG_LR] = 0x20000; - regs.set_sp(regs[ARM_REG_SP]); - regs.set_pc(0x1234); - - bool finished; - ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished)); - EXPECT_EQ(ERROR_NONE, interface.LastErrorCode()); - ASSERT_TRUE(finished); - ASSERT_EQ(0x10000U, regs.sp()); - ASSERT_EQ(0x10000U, regs[ARM_REG_SP]); - ASSERT_EQ(0x1234U, regs.pc()); -} - -TEST_F(ElfInterfaceArmTest, StepExidx_refuse_unwind) { - ElfInterfaceArmFake interface(&memory_); - - interface.FakeSetStartOffset(0x1000); - interface.FakeSetTotalEntries(1); - memory_.SetData32(0x1000, 0x6000); - memory_.SetData32(0x1004, 0x808000b0); - - RegsArm regs; - regs[ARM_REG_SP] = 0x10000; - regs[ARM_REG_LR] = 0x20000; - regs.set_sp(regs[ARM_REG_SP]); - regs.set_pc(0x1234); - - bool finished; - ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished)); - EXPECT_EQ(ERROR_NONE, interface.LastErrorCode()); - ASSERT_TRUE(finished); - ASSERT_EQ(0x10000U, regs.sp()); - ASSERT_EQ(0x10000U, regs[ARM_REG_SP]); - ASSERT_EQ(0x1234U, regs.pc()); -} - -TEST_F(ElfInterfaceArmTest, StepExidx_pc_zero) { - ElfInterfaceArmFake interface(&memory_); - - interface.FakeSetStartOffset(0x1000); - interface.FakeSetTotalEntries(1); - memory_.SetData32(0x1000, 0x6000); - // Set the pc using a pop r15 command. - memory_.SetData32(0x1004, 0x808800b0); - - // pc value of zero. - process_memory_.SetData32(0x10000, 0); - - RegsArm regs; - regs[ARM_REG_SP] = 0x10000; - regs[ARM_REG_LR] = 0x20000; - regs.set_sp(regs[ARM_REG_SP]); - regs.set_pc(0x1234); - - bool finished; - ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished)); - EXPECT_EQ(ERROR_NONE, interface.LastErrorCode()); - ASSERT_TRUE(finished); - ASSERT_EQ(0U, regs.pc()); - - // Now set the pc from the lr register (pop r14). - memory_.SetData32(0x1004, 0x808400b0); - - regs[ARM_REG_SP] = 0x10000; - regs[ARM_REG_LR] = 0x20000; - regs.set_sp(regs[ARM_REG_SP]); - regs.set_pc(0x1234); - - ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &process_memory_, &finished)); - EXPECT_EQ(ERROR_NONE, interface.LastErrorCode()); - ASSERT_TRUE(finished); - ASSERT_EQ(0U, regs.pc()); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/ElfInterfaceTest.cpp b/libunwindstack/tests/ElfInterfaceTest.cpp deleted file mode 100644 index 3cf90fe4c..000000000 --- a/libunwindstack/tests/ElfInterfaceTest.cpp +++ /dev/null @@ -1,1966 +0,0 @@ -/* - * Copyright (C) 2016 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 "DwarfEncoding.h" -#include "ElfInterfaceArm.h" - -#include "ElfFake.h" -#include "MemoryFake.h" - -#if !defined(PT_ARM_EXIDX) -#define PT_ARM_EXIDX 0x70000001 -#endif - -#if !defined(EM_AARCH64) -#define EM_AARCH64 183 -#endif - -namespace unwindstack { - -class ElfInterfaceTest : public ::testing::Test { - protected: - void SetUp() override { - memory_.Clear(); - } - - void SetStringMemory(uint64_t offset, const char* string) { - memory_.SetMemory(offset, string, strlen(string) + 1); - } - - template - void SinglePtLoad(); - - template - void MultipleExecutablePtLoads(); - - template - void MultipleExecutablePtLoadsIncrementsNotSizeOfPhdr(); - - template - void NonExecutablePtLoads(); - - template - void ManyPhdrs(); - - enum SonameTestEnum : uint8_t { - SONAME_NORMAL, - SONAME_DTNULL_AFTER, - SONAME_DTSIZE_SMALL, - SONAME_MISSING_MAP, - }; - - template - void SonameInit(SonameTestEnum test_type = SONAME_NORMAL); - - template - void Soname(); - - template - void SonameAfterDtNull(); - - template - void SonameSize(); - - template - void SonameMissingMap(); - - template - void InitHeadersEhFrameTest(); - - template - void InitHeadersDebugFrame(); - - template - void InitHeadersEhFrameFail(); - - template - void InitHeadersDebugFrameFail(); - - template - void InitProgramHeadersMalformed(); - - template - void InitSectionHeadersMalformed(); - - template - void InitSectionHeadersMalformedSymData(); - - template - void InitSectionHeaders(uint64_t entry_size); - - template - void InitSectionHeadersOffsets(); - - template - void InitSectionHeadersOffsetsEhFrameSectionBias(uint64_t addr, uint64_t offset, - int64_t expected_bias); - - template - void InitSectionHeadersOffsetsEhFrameHdrSectionBias(uint64_t addr, uint64_t offset, - int64_t expected_bias); - - template - void InitSectionHeadersOffsetsDebugFrameSectionBias(uint64_t addr, uint64_t offset, - int64_t expected_bias); - - template - void CheckGnuEhFrame(uint64_t addr, uint64_t offset, int64_t expected_bias); - - template - void InitSym(uint64_t offset, uint32_t value, uint32_t size, uint32_t name_offset, - uint64_t sym_offset, const char* name); - - template - void BuildID(); - - template - void BuildIDTwoNotes(); - - template - void BuildIDSectionTooSmallForName(); - - template - void BuildIDSectionTooSmallForDesc(); - - template - void BuildIDSectionTooSmallForHeader(); - - template - void CheckLoadBiasInFirstPhdr(int64_t load_bias); - - template - void CheckLoadBiasInFirstExecPhdr(uint64_t offset, uint64_t vaddr, int64_t load_bias); - - MemoryFake memory_; -}; - -template -void ElfInterfaceTest::InitSym(uint64_t offset, uint32_t value, uint32_t size, uint32_t name_offset, - uint64_t sym_offset, const char* name) { - Sym sym = {}; - sym.st_info = STT_FUNC; - sym.st_value = value; - sym.st_size = size; - sym.st_name = name_offset; - sym.st_shndx = SHN_COMMON; - - memory_.SetMemory(offset, &sym, sizeof(sym)); - memory_.SetMemory(sym_offset + name_offset, name, strlen(name) + 1); -} - -template -void ElfInterfaceTest::SinglePtLoad() { - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - - Ehdr ehdr = {}; - ehdr.e_phoff = 0x100; - ehdr.e_phnum = 1; - ehdr.e_phentsize = sizeof(Phdr); - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - Phdr phdr = {}; - phdr.p_type = PT_LOAD; - phdr.p_vaddr = 0x2000; - phdr.p_memsz = 0x10000; - phdr.p_flags = PF_R | PF_X; - phdr.p_align = 0x1000; - memory_.SetMemory(0x100, &phdr, sizeof(phdr)); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0x2000, load_bias); - - const std::unordered_map& pt_loads = elf->pt_loads(); - ASSERT_EQ(1U, pt_loads.size()); - LoadInfo load_data = pt_loads.at(0); - ASSERT_EQ(0U, load_data.offset); - ASSERT_EQ(0x2000U, load_data.table_offset); - ASSERT_EQ(0x10000U, load_data.table_size); -} - -TEST_F(ElfInterfaceTest, single_pt_load_32) { - SinglePtLoad(); -} - -TEST_F(ElfInterfaceTest, single_pt_load_64) { - SinglePtLoad(); -} - -template -void ElfInterfaceTest::MultipleExecutablePtLoads() { - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - - Ehdr ehdr = {}; - ehdr.e_phoff = 0x100; - ehdr.e_phnum = 3; - ehdr.e_phentsize = sizeof(Phdr); - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - Phdr phdr = {}; - phdr.p_type = PT_LOAD; - phdr.p_vaddr = 0x2000; - phdr.p_memsz = 0x10000; - phdr.p_flags = PF_R | PF_X; - phdr.p_align = 0x1000; - memory_.SetMemory(0x100, &phdr, sizeof(phdr)); - - memset(&phdr, 0, sizeof(phdr)); - phdr.p_type = PT_LOAD; - phdr.p_offset = 0x1000; - phdr.p_vaddr = 0x2001; - phdr.p_memsz = 0x10001; - phdr.p_flags = PF_R | PF_X; - phdr.p_align = 0x1001; - memory_.SetMemory(0x100 + sizeof(phdr), &phdr, sizeof(phdr)); - - memset(&phdr, 0, sizeof(phdr)); - phdr.p_type = PT_LOAD; - phdr.p_offset = 0x2000; - phdr.p_vaddr = 0x2002; - phdr.p_memsz = 0x10002; - phdr.p_flags = PF_R | PF_X; - phdr.p_align = 0x1002; - memory_.SetMemory(0x100 + 2 * sizeof(phdr), &phdr, sizeof(phdr)); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0x2000, load_bias); - - const std::unordered_map& pt_loads = elf->pt_loads(); - ASSERT_EQ(3U, pt_loads.size()); - - LoadInfo load_data = pt_loads.at(0); - ASSERT_EQ(0U, load_data.offset); - ASSERT_EQ(0x2000U, load_data.table_offset); - ASSERT_EQ(0x10000U, load_data.table_size); - - load_data = pt_loads.at(0x1000); - ASSERT_EQ(0x1000U, load_data.offset); - ASSERT_EQ(0x2001U, load_data.table_offset); - ASSERT_EQ(0x10001U, load_data.table_size); - - load_data = pt_loads.at(0x2000); - ASSERT_EQ(0x2000U, load_data.offset); - ASSERT_EQ(0x2002U, load_data.table_offset); - ASSERT_EQ(0x10002U, load_data.table_size); -} - -TEST_F(ElfInterfaceTest, multiple_executable_pt_loads_32) { - MultipleExecutablePtLoads(); -} - -TEST_F(ElfInterfaceTest, multiple_executable_pt_loads_64) { - MultipleExecutablePtLoads(); -} - -template -void ElfInterfaceTest::MultipleExecutablePtLoadsIncrementsNotSizeOfPhdr() { - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - - Ehdr ehdr = {}; - ehdr.e_phoff = 0x100; - ehdr.e_phnum = 3; - ehdr.e_phentsize = sizeof(Phdr) + 100; - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - Phdr phdr = {}; - phdr.p_type = PT_LOAD; - phdr.p_vaddr = 0x2000; - phdr.p_memsz = 0x10000; - phdr.p_flags = PF_R | PF_X; - phdr.p_align = 0x1000; - memory_.SetMemory(0x100, &phdr, sizeof(phdr)); - - memset(&phdr, 0, sizeof(phdr)); - phdr.p_type = PT_LOAD; - phdr.p_offset = 0x1000; - phdr.p_vaddr = 0x2001; - phdr.p_memsz = 0x10001; - phdr.p_flags = PF_R | PF_X; - phdr.p_align = 0x1001; - memory_.SetMemory(0x100 + sizeof(phdr) + 100, &phdr, sizeof(phdr)); - - memset(&phdr, 0, sizeof(phdr)); - phdr.p_type = PT_LOAD; - phdr.p_offset = 0x2000; - phdr.p_vaddr = 0x2002; - phdr.p_memsz = 0x10002; - phdr.p_flags = PF_R | PF_X; - phdr.p_align = 0x1002; - memory_.SetMemory(0x100 + 2 * (sizeof(phdr) + 100), &phdr, sizeof(phdr)); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0x2000, load_bias); - - const std::unordered_map& pt_loads = elf->pt_loads(); - ASSERT_EQ(3U, pt_loads.size()); - - LoadInfo load_data = pt_loads.at(0); - ASSERT_EQ(0U, load_data.offset); - ASSERT_EQ(0x2000U, load_data.table_offset); - ASSERT_EQ(0x10000U, load_data.table_size); - - load_data = pt_loads.at(0x1000); - ASSERT_EQ(0x1000U, load_data.offset); - ASSERT_EQ(0x2001U, load_data.table_offset); - ASSERT_EQ(0x10001U, load_data.table_size); - - load_data = pt_loads.at(0x2000); - ASSERT_EQ(0x2000U, load_data.offset); - ASSERT_EQ(0x2002U, load_data.table_offset); - ASSERT_EQ(0x10002U, load_data.table_size); -} - -TEST_F(ElfInterfaceTest, multiple_executable_pt_loads_increments_not_size_of_phdr_32) { - MultipleExecutablePtLoadsIncrementsNotSizeOfPhdr(); -} - -TEST_F(ElfInterfaceTest, multiple_executable_pt_loads_increments_not_size_of_phdr_64) { - MultipleExecutablePtLoadsIncrementsNotSizeOfPhdr(); -} - -template -void ElfInterfaceTest::NonExecutablePtLoads() { - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - - Ehdr ehdr = {}; - ehdr.e_phoff = 0x100; - ehdr.e_phnum = 3; - ehdr.e_phentsize = sizeof(Phdr); - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - Phdr phdr = {}; - phdr.p_type = PT_LOAD; - phdr.p_vaddr = 0x2000; - phdr.p_memsz = 0x10000; - phdr.p_flags = PF_R; - phdr.p_align = 0x1000; - memory_.SetMemory(0x100, &phdr, sizeof(phdr)); - - memset(&phdr, 0, sizeof(phdr)); - phdr.p_type = PT_LOAD; - phdr.p_offset = 0x1000; - phdr.p_vaddr = 0x2001; - phdr.p_memsz = 0x10001; - phdr.p_flags = PF_R | PF_X; - phdr.p_align = 0x1001; - memory_.SetMemory(0x100 + sizeof(phdr), &phdr, sizeof(phdr)); - - memset(&phdr, 0, sizeof(phdr)); - phdr.p_type = PT_LOAD; - phdr.p_offset = 0x2000; - phdr.p_vaddr = 0x2002; - phdr.p_memsz = 0x10002; - phdr.p_flags = PF_R; - phdr.p_align = 0x1002; - memory_.SetMemory(0x100 + 2 * sizeof(phdr), &phdr, sizeof(phdr)); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0x1001, load_bias); - - const std::unordered_map& pt_loads = elf->pt_loads(); - ASSERT_EQ(1U, pt_loads.size()); - - LoadInfo load_data = pt_loads.at(0x1000); - ASSERT_EQ(0x1000U, load_data.offset); - ASSERT_EQ(0x2001U, load_data.table_offset); - ASSERT_EQ(0x10001U, load_data.table_size); -} - -TEST_F(ElfInterfaceTest, non_executable_pt_loads_32) { - NonExecutablePtLoads(); -} - -TEST_F(ElfInterfaceTest, non_executable_pt_loads_64) { - NonExecutablePtLoads(); -} - -template -void ElfInterfaceTest::ManyPhdrs() { - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - - Ehdr ehdr = {}; - ehdr.e_phoff = 0x100; - ehdr.e_phnum = 7; - ehdr.e_phentsize = sizeof(Phdr); - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - uint64_t phdr_offset = 0x100; - - Phdr phdr = {}; - phdr.p_type = PT_LOAD; - phdr.p_vaddr = 0x2000; - phdr.p_memsz = 0x10000; - phdr.p_flags = PF_R | PF_X; - phdr.p_align = 0x1000; - memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr)); - phdr_offset += sizeof(phdr); - - memset(&phdr, 0, sizeof(phdr)); - phdr.p_type = PT_GNU_EH_FRAME; - memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr)); - phdr_offset += sizeof(phdr); - - memset(&phdr, 0, sizeof(phdr)); - phdr.p_type = PT_DYNAMIC; - memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr)); - phdr_offset += sizeof(phdr); - - memset(&phdr, 0, sizeof(phdr)); - phdr.p_type = PT_INTERP; - memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr)); - phdr_offset += sizeof(phdr); - - memset(&phdr, 0, sizeof(phdr)); - phdr.p_type = PT_NOTE; - memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr)); - phdr_offset += sizeof(phdr); - - memset(&phdr, 0, sizeof(phdr)); - phdr.p_type = PT_SHLIB; - memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr)); - phdr_offset += sizeof(phdr); - - memset(&phdr, 0, sizeof(phdr)); - phdr.p_type = PT_GNU_EH_FRAME; - memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr)); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0x2000, load_bias); - - const std::unordered_map& pt_loads = elf->pt_loads(); - ASSERT_EQ(1U, pt_loads.size()); - - LoadInfo load_data = pt_loads.at(0); - ASSERT_EQ(0U, load_data.offset); - ASSERT_EQ(0x2000U, load_data.table_offset); - ASSERT_EQ(0x10000U, load_data.table_size); -} - -TEST_F(ElfInterfaceTest, many_phdrs_32) { - ElfInterfaceTest::ManyPhdrs(); -} - -TEST_F(ElfInterfaceTest, many_phdrs_64) { - ElfInterfaceTest::ManyPhdrs(); -} - -TEST_F(ElfInterfaceTest, arm32) { - ElfInterfaceArm elf_arm(&memory_); - - Elf32_Ehdr ehdr = {}; - ehdr.e_phoff = 0x100; - ehdr.e_phnum = 1; - ehdr.e_phentsize = sizeof(Elf32_Phdr); - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - Elf32_Phdr phdr = {}; - phdr.p_type = PT_ARM_EXIDX; - phdr.p_offset = 0x2000; - phdr.p_filesz = 16; - memory_.SetMemory(0x100, &phdr, sizeof(phdr)); - - // Add arm exidx entries. - memory_.SetData32(0x2000, 0x1000); - memory_.SetData32(0x2008, 0x1000); - - int64_t load_bias = 0; - ASSERT_TRUE(elf_arm.Init(&load_bias)); - EXPECT_EQ(0, load_bias); - - std::vector entries; - for (auto addr : elf_arm) { - entries.push_back(addr); - } - ASSERT_EQ(2U, entries.size()); - ASSERT_EQ(0x3000U, entries[0]); - ASSERT_EQ(0x3008U, entries[1]); - - ASSERT_EQ(0x2000U, elf_arm.start_offset()); - ASSERT_EQ(2U, elf_arm.total_entries()); -} - -template -void ElfInterfaceTest::SonameInit(SonameTestEnum test_type) { - Ehdr ehdr = {}; - ehdr.e_shoff = 0x200; - ehdr.e_shnum = 2; - ehdr.e_shentsize = sizeof(Shdr); - ehdr.e_phoff = 0x100; - ehdr.e_phnum = 1; - ehdr.e_phentsize = sizeof(Phdr); - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - Shdr shdr = {}; - shdr.sh_type = SHT_STRTAB; - if (test_type == SONAME_MISSING_MAP) { - shdr.sh_addr = 0x20100; - } else { - shdr.sh_addr = 0x10100; - } - shdr.sh_offset = 0x10000; - memory_.SetMemory(0x200 + sizeof(shdr), &shdr, sizeof(shdr)); - - Phdr phdr = {}; - phdr.p_type = PT_DYNAMIC; - phdr.p_offset = 0x2000; - phdr.p_memsz = sizeof(Dyn) * 3; - memory_.SetMemory(0x100, &phdr, sizeof(phdr)); - - uint64_t offset = 0x2000; - Dyn dyn; - - dyn.d_tag = DT_STRTAB; - dyn.d_un.d_ptr = 0x10100; - memory_.SetMemory(offset, &dyn, sizeof(dyn)); - offset += sizeof(dyn); - - dyn.d_tag = DT_STRSZ; - if (test_type == SONAME_DTSIZE_SMALL) { - dyn.d_un.d_val = 0x10; - } else { - dyn.d_un.d_val = 0x1000; - } - memory_.SetMemory(offset, &dyn, sizeof(dyn)); - offset += sizeof(dyn); - - if (test_type == SONAME_DTNULL_AFTER) { - dyn.d_tag = DT_NULL; - memory_.SetMemory(offset, &dyn, sizeof(dyn)); - offset += sizeof(dyn); - } - - dyn.d_tag = DT_SONAME; - dyn.d_un.d_val = 0x10; - memory_.SetMemory(offset, &dyn, sizeof(dyn)); - offset += sizeof(dyn); - - dyn.d_tag = DT_NULL; - memory_.SetMemory(offset, &dyn, sizeof(dyn)); - - SetStringMemory(0x10010, "fake_soname.so"); -} - -template -void ElfInterfaceTest::Soname() { - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0, load_bias); - - ASSERT_EQ("fake_soname.so", elf->GetSoname()); -} - -TEST_F(ElfInterfaceTest, soname_32) { - SonameInit(); - Soname(); -} - -TEST_F(ElfInterfaceTest, soname_64) { - SonameInit(); - Soname(); -} - -template -void ElfInterfaceTest::SonameAfterDtNull() { - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0, load_bias); - - ASSERT_EQ("", elf->GetSoname()); -} - -TEST_F(ElfInterfaceTest, soname_after_dt_null_32) { - SonameInit(SONAME_DTNULL_AFTER); - SonameAfterDtNull(); -} - -TEST_F(ElfInterfaceTest, soname_after_dt_null_64) { - SonameInit(SONAME_DTNULL_AFTER); - SonameAfterDtNull(); -} - -template -void ElfInterfaceTest::SonameSize() { - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0, load_bias); - - ASSERT_EQ("", elf->GetSoname()); -} - -TEST_F(ElfInterfaceTest, soname_size_32) { - SonameInit(SONAME_DTSIZE_SMALL); - SonameSize(); -} - -TEST_F(ElfInterfaceTest, soname_size_64) { - SonameInit(SONAME_DTSIZE_SMALL); - SonameSize(); -} - -// Verify that there is no map from STRTAB in the dynamic section to a -// STRTAB entry in the section headers. -template -void ElfInterfaceTest::SonameMissingMap() { - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0, load_bias); - - ASSERT_EQ("", elf->GetSoname()); -} - -TEST_F(ElfInterfaceTest, soname_missing_map_32) { - SonameInit(SONAME_MISSING_MAP); - SonameMissingMap(); -} - -TEST_F(ElfInterfaceTest, soname_missing_map_64) { - SonameInit(SONAME_MISSING_MAP); - SonameMissingMap(); -} - -template -void ElfInterfaceTest::InitHeadersEhFrameTest() { - ElfType elf(&memory_); - - elf.FakeSetEhFrameOffset(0x10000); - elf.FakeSetEhFrameSize(0); - elf.FakeSetDebugFrameOffset(0); - elf.FakeSetDebugFrameSize(0); - - memory_.SetMemory(0x10000, - std::vector{0x1, DW_EH_PE_udata2, DW_EH_PE_udata2, DW_EH_PE_udata2}); - memory_.SetData32(0x10004, 0x500); - memory_.SetData32(0x10008, 250); - - elf.InitHeaders(); - - EXPECT_FALSE(elf.eh_frame() == nullptr); - EXPECT_TRUE(elf.debug_frame() == nullptr); -} - -TEST_F(ElfInterfaceTest, init_headers_eh_frame_32) { - InitHeadersEhFrameTest(); -} - -TEST_F(ElfInterfaceTest, init_headers_eh_frame_64) { - InitHeadersEhFrameTest(); -} - -template -void ElfInterfaceTest::InitHeadersDebugFrame() { - ElfType elf(&memory_); - - elf.FakeSetEhFrameOffset(0); - elf.FakeSetEhFrameSize(0); - elf.FakeSetDebugFrameOffset(0x5000); - elf.FakeSetDebugFrameSize(0x200); - - memory_.SetData32(0x5000, 0xfc); - memory_.SetData32(0x5004, 0xffffffff); - memory_.SetMemory(0x5008, std::vector{1, '\0', 4, 8, 2}); - - memory_.SetData32(0x5100, 0xfc); - memory_.SetData32(0x5104, 0); - memory_.SetData32(0x5108, 0x1500); - memory_.SetData32(0x510c, 0x200); - - elf.InitHeaders(); - - EXPECT_TRUE(elf.eh_frame() == nullptr); - EXPECT_FALSE(elf.debug_frame() == nullptr); -} - -TEST_F(ElfInterfaceTest, init_headers_debug_frame_32) { - InitHeadersDebugFrame(); -} - -TEST_F(ElfInterfaceTest, init_headers_debug_frame_64) { - InitHeadersDebugFrame(); -} - -template -void ElfInterfaceTest::InitProgramHeadersMalformed() { - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - - Ehdr ehdr = {}; - ehdr.e_phoff = 0x100; - ehdr.e_phnum = 3; - ehdr.e_phentsize = sizeof(Phdr); - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0, load_bias); -} - -TEST_F(ElfInterfaceTest, init_program_headers_malformed_32) { - InitProgramHeadersMalformed(); -} - -TEST_F(ElfInterfaceTest, init_program_headers_malformed_64) { - InitProgramHeadersMalformed(); -} - -template -void ElfInterfaceTest::InitSectionHeadersMalformed() { - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - - Ehdr ehdr = {}; - ehdr.e_shoff = 0x1000; - ehdr.e_shnum = 10; - ehdr.e_shentsize = sizeof(Shdr); - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0, load_bias); -} - -TEST_F(ElfInterfaceTest, init_section_headers_malformed_32) { - InitSectionHeadersMalformed(); -} - -TEST_F(ElfInterfaceTest, init_section_headers_malformed_64) { - InitSectionHeadersMalformed(); -} - -template -void ElfInterfaceTest::InitSectionHeadersMalformedSymData() { - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - - uint64_t offset = 0x1000; - - Ehdr ehdr = {}; - ehdr.e_shoff = offset; - ehdr.e_shnum = 5; - ehdr.e_shentsize = sizeof(Shdr); - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - offset += ehdr.e_shentsize; - - Shdr shdr = {}; - shdr.sh_type = SHT_SYMTAB; - shdr.sh_link = 4; - shdr.sh_addr = 0x5000; - shdr.sh_offset = 0x5000; - shdr.sh_entsize = 0x100; - shdr.sh_size = shdr.sh_entsize * 10; - memory_.SetMemory(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; - - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_DYNSYM; - shdr.sh_link = 10; - shdr.sh_addr = 0x6000; - shdr.sh_offset = 0x6000; - shdr.sh_entsize = 0x100; - shdr.sh_size = shdr.sh_entsize * 10; - memory_.SetMemory(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; - - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_DYNSYM; - shdr.sh_link = 2; - shdr.sh_addr = 0x6000; - shdr.sh_offset = 0x6000; - shdr.sh_entsize = 0x100; - shdr.sh_size = shdr.sh_entsize * 10; - memory_.SetMemory(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; - - // The string data for the entries. - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_STRTAB; - shdr.sh_name = 0x20000; - shdr.sh_offset = 0xf000; - shdr.sh_size = 0x1000; - memory_.SetMemory(offset, &shdr, sizeof(shdr)); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0, load_bias); - EXPECT_EQ(0U, elf->debug_frame_offset()); - EXPECT_EQ(0U, elf->debug_frame_size()); - EXPECT_EQ(0U, elf->gnu_debugdata_offset()); - EXPECT_EQ(0U, elf->gnu_debugdata_size()); - - std::string name; - uint64_t name_offset; - ASSERT_FALSE(elf->GetFunctionName(0x90010, &name, &name_offset)); -} - -TEST_F(ElfInterfaceTest, init_section_headers_malformed_symdata_32) { - InitSectionHeadersMalformedSymData(); -} - -TEST_F(ElfInterfaceTest, init_section_headers_malformed_symdata_64) { - InitSectionHeadersMalformedSymData(); -} - -template -void ElfInterfaceTest::InitSectionHeaders(uint64_t entry_size) { - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - - uint64_t offset = 0x1000; - - Ehdr ehdr = {}; - ehdr.e_shoff = offset; - ehdr.e_shnum = 5; - ehdr.e_shentsize = entry_size; - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - offset += ehdr.e_shentsize; - - Shdr shdr = {}; - shdr.sh_type = SHT_SYMTAB; - shdr.sh_link = 4; - shdr.sh_addr = 0x5000; - shdr.sh_offset = 0x5000; - shdr.sh_entsize = sizeof(Sym); - shdr.sh_size = shdr.sh_entsize * 10; - memory_.SetMemory(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; - - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_DYNSYM; - shdr.sh_link = 4; - shdr.sh_addr = 0x6000; - shdr.sh_offset = 0x6000; - shdr.sh_entsize = sizeof(Sym); - shdr.sh_size = shdr.sh_entsize * 10; - memory_.SetMemory(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; - - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_PROGBITS; - shdr.sh_name = 0xa000; - memory_.SetMemory(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; - - // The string data for the entries. - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_STRTAB; - shdr.sh_name = 0x20000; - shdr.sh_offset = 0xf000; - shdr.sh_size = 0x1000; - memory_.SetMemory(offset, &shdr, sizeof(shdr)); - - InitSym(0x5000, 0x90000, 0x1000, 0x100, 0xf000, "function_one"); - InitSym(0x6000, 0xd0000, 0x1000, 0x300, 0xf000, "function_two"); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0, load_bias); - EXPECT_EQ(0U, elf->debug_frame_offset()); - EXPECT_EQ(0U, elf->debug_frame_size()); - EXPECT_EQ(0U, elf->gnu_debugdata_offset()); - EXPECT_EQ(0U, elf->gnu_debugdata_size()); - - // Look in the first symbol table. - std::string name; - uint64_t name_offset; - ASSERT_TRUE(elf->GetFunctionName(0x90010, &name, &name_offset)); - EXPECT_EQ("function_one", name); - EXPECT_EQ(16U, name_offset); - ASSERT_TRUE(elf->GetFunctionName(0xd0020, &name, &name_offset)); - EXPECT_EQ("function_two", name); - EXPECT_EQ(32U, name_offset); -} - -TEST_F(ElfInterfaceTest, init_section_headers_32) { - InitSectionHeaders(sizeof(Elf32_Shdr)); -} - -TEST_F(ElfInterfaceTest, init_section_headers_64) { - InitSectionHeaders(sizeof(Elf64_Shdr)); -} - -TEST_F(ElfInterfaceTest, init_section_headers_non_std_entry_size_32) { - InitSectionHeaders(0x100); -} - -TEST_F(ElfInterfaceTest, init_section_headers_non_std_entry_size_64) { - InitSectionHeaders(0x100); -} - -template -void ElfInterfaceTest::InitSectionHeadersOffsets() { - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - - uint64_t offset = 0x2000; - - Ehdr ehdr = {}; - ehdr.e_shoff = offset; - ehdr.e_shnum = 7; - ehdr.e_shentsize = sizeof(Shdr); - ehdr.e_shstrndx = 2; - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - offset += ehdr.e_shentsize; - - Shdr shdr = {}; - shdr.sh_type = SHT_PROGBITS; - shdr.sh_link = 2; - shdr.sh_name = 0x200; - shdr.sh_addr = 0x5000; - shdr.sh_offset = 0x5000; - shdr.sh_entsize = 0x100; - shdr.sh_size = 0x800; - memory_.SetMemory(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; - - // The string data for section header names. - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_STRTAB; - shdr.sh_name = 0x20000; - shdr.sh_offset = 0xf000; - shdr.sh_size = 0x1000; - memory_.SetMemory(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; - - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_PROGBITS; - shdr.sh_link = 2; - shdr.sh_name = 0x100; - shdr.sh_addr = 0x6000; - shdr.sh_offset = 0x6000; - shdr.sh_entsize = 0x100; - shdr.sh_size = 0x500; - memory_.SetMemory(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; - - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_PROGBITS; - shdr.sh_link = 2; - shdr.sh_name = 0x300; - shdr.sh_addr = 0x7000; - shdr.sh_offset = 0x7000; - shdr.sh_entsize = 0x100; - shdr.sh_size = 0x800; - memory_.SetMemory(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; - - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_PROGBITS; - shdr.sh_link = 2; - shdr.sh_name = 0x400; - shdr.sh_addr = 0xa000; - shdr.sh_offset = 0xa000; - shdr.sh_entsize = 0x100; - shdr.sh_size = 0xf00; - memory_.SetMemory(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; - - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_NOTE; - shdr.sh_name = 0x500; - shdr.sh_addr = 0xb000; - shdr.sh_offset = 0xb000; - shdr.sh_size = 0xf00; - memory_.SetMemory(offset, &shdr, sizeof(shdr)); - - memory_.SetMemory(0xf100, ".debug_frame", sizeof(".debug_frame")); - memory_.SetMemory(0xf200, ".gnu_debugdata", sizeof(".gnu_debugdata")); - memory_.SetMemory(0xf300, ".eh_frame", sizeof(".eh_frame")); - memory_.SetMemory(0xf400, ".eh_frame_hdr", sizeof(".eh_frame_hdr")); - memory_.SetMemory(0xf500, ".note.gnu.build-id", sizeof(".note.gnu.build-id")); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0, load_bias); - EXPECT_EQ(0x6000U, elf->debug_frame_offset()); - EXPECT_EQ(0, elf->debug_frame_section_bias()); - EXPECT_EQ(0x500U, elf->debug_frame_size()); - - EXPECT_EQ(0x5000U, elf->gnu_debugdata_offset()); - EXPECT_EQ(0x800U, elf->gnu_debugdata_size()); - - EXPECT_EQ(0x7000U, elf->eh_frame_offset()); - EXPECT_EQ(0, elf->eh_frame_section_bias()); - EXPECT_EQ(0x800U, elf->eh_frame_size()); - - EXPECT_EQ(0xa000U, elf->eh_frame_hdr_offset()); - EXPECT_EQ(0, elf->eh_frame_hdr_section_bias()); - EXPECT_EQ(0xf00U, elf->eh_frame_hdr_size()); - - EXPECT_EQ(0xb000U, elf->gnu_build_id_offset()); - EXPECT_EQ(0xf00U, elf->gnu_build_id_size()); -} - -TEST_F(ElfInterfaceTest, init_section_headers_offsets_32) { - InitSectionHeadersOffsets(); -} - -TEST_F(ElfInterfaceTest, init_section_headers_offsets_64) { - InitSectionHeadersOffsets(); -} - -template -void ElfInterfaceTest::InitSectionHeadersOffsetsEhFrameSectionBias(uint64_t addr, uint64_t offset, - int64_t expected_bias) { - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - - uint64_t elf_offset = 0x2000; - - Ehdr ehdr = {}; - ehdr.e_shoff = elf_offset; - ehdr.e_shnum = 4; - ehdr.e_shentsize = sizeof(Shdr); - ehdr.e_shstrndx = 2; - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - elf_offset += ehdr.e_shentsize; - - Shdr shdr = {}; - shdr.sh_type = SHT_PROGBITS; - shdr.sh_link = 2; - shdr.sh_name = 0x200; - shdr.sh_addr = 0x8000; - shdr.sh_offset = 0x8000; - shdr.sh_entsize = 0x100; - shdr.sh_size = 0x800; - memory_.SetMemory(elf_offset, &shdr, sizeof(shdr)); - elf_offset += ehdr.e_shentsize; - - // The string data for section header names. - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_STRTAB; - shdr.sh_name = 0x20000; - shdr.sh_offset = 0xf000; - shdr.sh_size = 0x1000; - memory_.SetMemory(elf_offset, &shdr, sizeof(shdr)); - elf_offset += ehdr.e_shentsize; - - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_PROGBITS; - shdr.sh_link = 2; - shdr.sh_name = 0x100; - shdr.sh_addr = addr; - shdr.sh_offset = offset; - shdr.sh_entsize = 0x100; - shdr.sh_size = 0x500; - memory_.SetMemory(elf_offset, &shdr, sizeof(shdr)); - - memory_.SetMemory(0xf100, ".eh_frame", sizeof(".eh_frame")); - memory_.SetMemory(0xf200, ".eh_frame_hdr", sizeof(".eh_frame_hdr")); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0, load_bias); - EXPECT_EQ(offset, elf->eh_frame_offset()); - EXPECT_EQ(expected_bias, elf->eh_frame_section_bias()); - EXPECT_EQ(0x500U, elf->eh_frame_size()); - - EXPECT_EQ(0x8000U, elf->eh_frame_hdr_offset()); - EXPECT_EQ(0, elf->eh_frame_hdr_section_bias()); - EXPECT_EQ(0x800U, elf->eh_frame_hdr_size()); -} - -TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_section_bias_zero_32) { - InitSectionHeadersOffsetsEhFrameSectionBias(0x4000, - 0x4000, 0); -} - -TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_section_bias_zero_64) { - InitSectionHeadersOffsetsEhFrameSectionBias(0x6000, - 0x6000, 0); -} - -TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_section_bias_positive_32) { - InitSectionHeadersOffsetsEhFrameSectionBias( - 0x5000, 0x4000, 0x1000); -} - -TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_section_bias_positive_64) { - InitSectionHeadersOffsetsEhFrameSectionBias( - 0x6000, 0x4000, 0x2000); -} - -TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_section_bias_negative_32) { - InitSectionHeadersOffsetsEhFrameSectionBias( - 0x3000, 0x4000, -0x1000); -} - -TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_section_bias_negative_64) { - InitSectionHeadersOffsetsEhFrameSectionBias( - 0x6000, 0x9000, -0x3000); -} - -template -void ElfInterfaceTest::InitSectionHeadersOffsetsEhFrameHdrSectionBias(uint64_t addr, - uint64_t offset, - int64_t expected_bias) { - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - - uint64_t elf_offset = 0x2000; - - Ehdr ehdr = {}; - ehdr.e_shoff = elf_offset; - ehdr.e_shnum = 4; - ehdr.e_shentsize = sizeof(Shdr); - ehdr.e_shstrndx = 2; - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - elf_offset += ehdr.e_shentsize; - - Shdr shdr = {}; - shdr.sh_type = SHT_PROGBITS; - shdr.sh_link = 2; - shdr.sh_name = 0x200; - shdr.sh_addr = addr; - shdr.sh_offset = offset; - shdr.sh_entsize = 0x100; - shdr.sh_size = 0x800; - memory_.SetMemory(elf_offset, &shdr, sizeof(shdr)); - elf_offset += ehdr.e_shentsize; - - // The string data for section header names. - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_STRTAB; - shdr.sh_name = 0x20000; - shdr.sh_offset = 0xf000; - shdr.sh_size = 0x1000; - memory_.SetMemory(elf_offset, &shdr, sizeof(shdr)); - elf_offset += ehdr.e_shentsize; - - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_PROGBITS; - shdr.sh_link = 2; - shdr.sh_name = 0x100; - shdr.sh_addr = 0x5000; - shdr.sh_offset = 0x5000; - shdr.sh_entsize = 0x100; - shdr.sh_size = 0x500; - memory_.SetMemory(elf_offset, &shdr, sizeof(shdr)); - - memory_.SetMemory(0xf100, ".eh_frame", sizeof(".eh_frame")); - memory_.SetMemory(0xf200, ".eh_frame_hdr", sizeof(".eh_frame_hdr")); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0, load_bias); - EXPECT_EQ(0x5000U, elf->eh_frame_offset()); - EXPECT_EQ(0, elf->eh_frame_section_bias()); - EXPECT_EQ(0x500U, elf->eh_frame_size()); - EXPECT_EQ(offset, elf->eh_frame_hdr_offset()); - EXPECT_EQ(expected_bias, elf->eh_frame_hdr_section_bias()); - EXPECT_EQ(0x800U, elf->eh_frame_hdr_size()); -} - -TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_hdr_section_bias_zero_32) { - InitSectionHeadersOffsetsEhFrameHdrSectionBias(0x9000, - 0x9000, 0); -} - -TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_hdr_section_bias_zero_64) { - InitSectionHeadersOffsetsEhFrameHdrSectionBias(0xa000, - 0xa000, 0); -} - -TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_hdr_section_bias_positive_32) { - InitSectionHeadersOffsetsEhFrameHdrSectionBias( - 0x9000, 0x4000, 0x5000); -} - -TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_hdr_section_bias_positive_64) { - InitSectionHeadersOffsetsEhFrameHdrSectionBias( - 0x6000, 0x1000, 0x5000); -} - -TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_hdr_section_bias_negative_32) { - InitSectionHeadersOffsetsEhFrameHdrSectionBias( - 0x3000, 0x5000, -0x2000); -} - -TEST_F(ElfInterfaceTest, init_section_headers_offsets_eh_frame_hdr_section_bias_negative_64) { - InitSectionHeadersOffsetsEhFrameHdrSectionBias( - 0x5000, 0x9000, -0x4000); -} - -template -void ElfInterfaceTest::InitSectionHeadersOffsetsDebugFrameSectionBias(uint64_t addr, - uint64_t offset, - int64_t expected_bias) { - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - - uint64_t elf_offset = 0x2000; - - Ehdr ehdr = {}; - ehdr.e_shoff = elf_offset; - ehdr.e_shnum = 3; - ehdr.e_shentsize = sizeof(Shdr); - ehdr.e_shstrndx = 2; - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - elf_offset += ehdr.e_shentsize; - - Shdr shdr = {}; - shdr.sh_type = SHT_PROGBITS; - shdr.sh_link = 2; - shdr.sh_name = 0x100; - shdr.sh_addr = addr; - shdr.sh_offset = offset; - shdr.sh_entsize = 0x100; - shdr.sh_size = 0x800; - memory_.SetMemory(elf_offset, &shdr, sizeof(shdr)); - elf_offset += ehdr.e_shentsize; - - // The string data for section header names. - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_STRTAB; - shdr.sh_name = 0x20000; - shdr.sh_offset = 0xf000; - shdr.sh_size = 0x1000; - memory_.SetMemory(elf_offset, &shdr, sizeof(shdr)); - - memory_.SetMemory(0xf100, ".debug_frame", sizeof(".debug_frame")); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0, load_bias); - EXPECT_EQ(offset, elf->debug_frame_offset()); - EXPECT_EQ(expected_bias, elf->debug_frame_section_bias()); - EXPECT_EQ(0x800U, elf->debug_frame_size()); -} - -TEST_F(ElfInterfaceTest, init_section_headers_offsets_debug_frame_section_bias_zero_32) { - InitSectionHeadersOffsetsDebugFrameSectionBias(0x5000, - 0x5000, 0); -} - -TEST_F(ElfInterfaceTest, init_section_headers_offsets_debug_frame_section_bias_zero_64) { - InitSectionHeadersOffsetsDebugFrameSectionBias(0xa000, - 0xa000, 0); -} - -TEST_F(ElfInterfaceTest, init_section_headers_offsets_debug_frame_section_bias_positive_32) { - InitSectionHeadersOffsetsDebugFrameSectionBias( - 0x5000, 0x2000, 0x3000); -} - -TEST_F(ElfInterfaceTest, init_section_headers_offsets_debug_frame_section_bias_positive_64) { - InitSectionHeadersOffsetsDebugFrameSectionBias( - 0x7000, 0x1000, 0x6000); -} - -TEST_F(ElfInterfaceTest, init_section_headers_offsets_debug_frame_section_bias_negative_32) { - InitSectionHeadersOffsetsDebugFrameSectionBias( - 0x6000, 0x7000, -0x1000); -} - -TEST_F(ElfInterfaceTest, init_section_headers_offsets_debug_frame_section_bias_negative_64) { - InitSectionHeadersOffsetsDebugFrameSectionBias( - 0x3000, 0x5000, -0x2000); -} - -template -void ElfInterfaceTest::CheckGnuEhFrame(uint64_t addr, uint64_t offset, int64_t expected_bias) { - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - - Ehdr ehdr = {}; - ehdr.e_phoff = 0x100; - ehdr.e_phnum = 2; - ehdr.e_phentsize = sizeof(Phdr); - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - uint64_t phdr_offset = 0x100; - - Phdr phdr = {}; - phdr.p_type = PT_LOAD; - phdr.p_memsz = 0x10000; - phdr.p_flags = PF_R | PF_X; - phdr.p_align = 0x1000; - memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr)); - phdr_offset += sizeof(phdr); - - memset(&phdr, 0, sizeof(phdr)); - phdr.p_type = PT_GNU_EH_FRAME; - phdr.p_vaddr = addr; - phdr.p_offset = offset; - memory_.SetMemory(phdr_offset, &phdr, sizeof(phdr)); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0, load_bias); - EXPECT_EQ(expected_bias, elf->eh_frame_hdr_section_bias()); -} - -TEST_F(ElfInterfaceTest, eh_frame_zero_section_bias_32) { - ElfInterfaceTest::CheckGnuEhFrame(0x4000, 0x4000, 0); -} - -TEST_F(ElfInterfaceTest, eh_frame_zero_section_bias_64) { - ElfInterfaceTest::CheckGnuEhFrame(0x4000, 0x4000, 0); -} - -TEST_F(ElfInterfaceTest, eh_frame_positive_section_bias_32) { - ElfInterfaceTest::CheckGnuEhFrame(0x4000, 0x1000, 0x3000); -} - -TEST_F(ElfInterfaceTest, eh_frame_positive_section_bias_64) { - ElfInterfaceTest::CheckGnuEhFrame(0x4000, 0x1000, 0x3000); -} - -TEST_F(ElfInterfaceTest, eh_frame_negative_section_bias_32) { - ElfInterfaceTest::CheckGnuEhFrame(0x4000, 0x5000, - -0x1000); -} - -TEST_F(ElfInterfaceTest, eh_frame_negative_section_bias_64) { - ElfInterfaceTest::CheckGnuEhFrame(0x4000, 0x5000, - -0x1000); -} - -TEST_F(ElfInterfaceTest, is_valid_pc_from_pt_load) { - std::unique_ptr elf(new ElfInterface32(&memory_)); - - Elf32_Ehdr ehdr = {}; - ehdr.e_phoff = 0x100; - ehdr.e_phnum = 1; - ehdr.e_phentsize = sizeof(Elf32_Phdr); - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - Elf32_Phdr phdr = {}; - phdr.p_type = PT_LOAD; - phdr.p_vaddr = 0; - phdr.p_memsz = 0x10000; - phdr.p_flags = PF_R | PF_X; - phdr.p_align = 0x1000; - memory_.SetMemory(0x100, &phdr, sizeof(phdr)); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0, load_bias); - EXPECT_TRUE(elf->IsValidPc(0)); - EXPECT_TRUE(elf->IsValidPc(0x5000)); - EXPECT_TRUE(elf->IsValidPc(0xffff)); - EXPECT_FALSE(elf->IsValidPc(0x10000)); -} - -TEST_F(ElfInterfaceTest, is_valid_pc_from_pt_load_non_zero_load_bias) { - std::unique_ptr elf(new ElfInterface32(&memory_)); - - Elf32_Ehdr ehdr = {}; - ehdr.e_phoff = 0x100; - ehdr.e_phnum = 1; - ehdr.e_phentsize = sizeof(Elf32_Phdr); - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - Elf32_Phdr phdr = {}; - phdr.p_type = PT_LOAD; - phdr.p_vaddr = 0x2000; - phdr.p_memsz = 0x10000; - phdr.p_flags = PF_R | PF_X; - phdr.p_align = 0x1000; - memory_.SetMemory(0x100, &phdr, sizeof(phdr)); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - EXPECT_EQ(0x2000, load_bias); - EXPECT_FALSE(elf->IsValidPc(0)); - EXPECT_FALSE(elf->IsValidPc(0x1000)); - EXPECT_FALSE(elf->IsValidPc(0x1fff)); - EXPECT_TRUE(elf->IsValidPc(0x2000)); - EXPECT_TRUE(elf->IsValidPc(0x5000)); - EXPECT_TRUE(elf->IsValidPc(0x11fff)); - EXPECT_FALSE(elf->IsValidPc(0x12000)); -} - -TEST_F(ElfInterfaceTest, is_valid_pc_from_debug_frame) { - std::unique_ptr elf(new ElfInterface32(&memory_)); - - uint64_t sh_offset = 0x100; - - Elf32_Ehdr ehdr = {}; - ehdr.e_shstrndx = 1; - ehdr.e_shoff = sh_offset; - ehdr.e_shentsize = sizeof(Elf32_Shdr); - ehdr.e_shnum = 3; - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - Elf32_Shdr shdr = {}; - shdr.sh_type = SHT_NULL; - memory_.SetMemory(sh_offset, &shdr, sizeof(shdr)); - - sh_offset += sizeof(shdr); - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_STRTAB; - shdr.sh_name = 1; - shdr.sh_offset = 0x500; - shdr.sh_size = 0x100; - memory_.SetMemory(sh_offset, &shdr, sizeof(shdr)); - memory_.SetMemory(0x500, ".debug_frame"); - - sh_offset += sizeof(shdr); - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_PROGBITS; - shdr.sh_name = 0; - shdr.sh_addr = 0x600; - shdr.sh_offset = 0x600; - shdr.sh_size = 0x200; - memory_.SetMemory(sh_offset, &shdr, sizeof(shdr)); - - // CIE 32. - memory_.SetData32(0x600, 0xfc); - memory_.SetData32(0x604, 0xffffffff); - memory_.SetMemory(0x608, std::vector{1, '\0', 4, 4, 1}); - - // FDE 32. - memory_.SetData32(0x700, 0xfc); - memory_.SetData32(0x704, 0); - memory_.SetData32(0x708, 0x2100); - memory_.SetData32(0x70c, 0x200); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - elf->InitHeaders(); - EXPECT_EQ(0, load_bias); - EXPECT_FALSE(elf->IsValidPc(0)); - EXPECT_FALSE(elf->IsValidPc(0x20ff)); - EXPECT_TRUE(elf->IsValidPc(0x2100)); - EXPECT_TRUE(elf->IsValidPc(0x2200)); - EXPECT_TRUE(elf->IsValidPc(0x22ff)); - EXPECT_FALSE(elf->IsValidPc(0x2300)); -} - -TEST_F(ElfInterfaceTest, is_valid_pc_from_eh_frame) { - std::unique_ptr elf(new ElfInterface32(&memory_)); - - uint64_t sh_offset = 0x100; - - Elf32_Ehdr ehdr = {}; - ehdr.e_shstrndx = 1; - ehdr.e_shoff = sh_offset; - ehdr.e_shentsize = sizeof(Elf32_Shdr); - ehdr.e_shnum = 3; - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - Elf32_Shdr shdr = {}; - shdr.sh_type = SHT_NULL; - memory_.SetMemory(sh_offset, &shdr, sizeof(shdr)); - - sh_offset += sizeof(shdr); - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_STRTAB; - shdr.sh_name = 1; - shdr.sh_offset = 0x500; - shdr.sh_size = 0x100; - memory_.SetMemory(sh_offset, &shdr, sizeof(shdr)); - memory_.SetMemory(0x500, ".eh_frame"); - - sh_offset += sizeof(shdr); - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_PROGBITS; - shdr.sh_name = 0; - shdr.sh_addr = 0x600; - shdr.sh_offset = 0x600; - shdr.sh_size = 0x200; - memory_.SetMemory(sh_offset, &shdr, sizeof(shdr)); - - // CIE 32. - memory_.SetData32(0x600, 0xfc); - memory_.SetData32(0x604, 0); - memory_.SetMemory(0x608, std::vector{1, '\0', 4, 4, 1}); - - // FDE 32. - memory_.SetData32(0x700, 0xfc); - memory_.SetData32(0x704, 0x104); - memory_.SetData32(0x708, 0x20f8); - memory_.SetData32(0x70c, 0x200); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - elf->InitHeaders(); - EXPECT_EQ(0, load_bias); - EXPECT_FALSE(elf->IsValidPc(0)); - EXPECT_FALSE(elf->IsValidPc(0x27ff)); - EXPECT_TRUE(elf->IsValidPc(0x2800)); - EXPECT_TRUE(elf->IsValidPc(0x2900)); - EXPECT_TRUE(elf->IsValidPc(0x29ff)); - EXPECT_FALSE(elf->IsValidPc(0x2a00)); -} - -template -void ElfInterfaceTest::BuildID() { - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - - uint64_t offset = 0x2000; - - Ehdr ehdr = {}; - ehdr.e_shoff = offset; - ehdr.e_shnum = 3; - ehdr.e_shentsize = sizeof(Shdr); - ehdr.e_shstrndx = 2; - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - offset += ehdr.e_shentsize; - - char note_section[128]; - Nhdr note_header = {}; - note_header.n_namesz = 4; // "GNU" - note_header.n_descsz = 7; // "BUILDID" - note_header.n_type = NT_GNU_BUILD_ID; - memcpy(¬e_section, ¬e_header, sizeof(note_header)); - size_t note_offset = sizeof(note_header); - // The note information contains the GNU and trailing '\0'. - memcpy(¬e_section[note_offset], "GNU", sizeof("GNU")); - note_offset += sizeof("GNU"); - // This part of the note does not contain any trailing '\0'. - memcpy(¬e_section[note_offset], "BUILDID", 7); - - Shdr shdr = {}; - shdr.sh_type = SHT_NOTE; - shdr.sh_name = 0x500; - shdr.sh_offset = 0xb000; - shdr.sh_size = sizeof(note_section); - memory_.SetMemory(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; - - // The string data for section header names. - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_STRTAB; - shdr.sh_name = 0x20000; - shdr.sh_offset = 0xf000; - shdr.sh_size = 0x1000; - memory_.SetMemory(offset, &shdr, sizeof(shdr)); - - memory_.SetMemory(0xf500, ".note.gnu.build-id", sizeof(".note.gnu.build-id")); - memory_.SetMemory(0xb000, note_section, sizeof(note_section)); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - ASSERT_EQ("BUILDID", elf->GetBuildID()); -} - -TEST_F(ElfInterfaceTest, build_id_32) { - BuildID(); -} - -TEST_F(ElfInterfaceTest, build_id_64) { - BuildID(); -} - -template -void ElfInterfaceTest::BuildIDTwoNotes() { - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - - uint64_t offset = 0x2000; - - Ehdr ehdr = {}; - ehdr.e_shoff = offset; - ehdr.e_shnum = 3; - ehdr.e_shentsize = sizeof(Shdr); - ehdr.e_shstrndx = 2; - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - offset += ehdr.e_shentsize; - - char note_section[128]; - Nhdr note_header = {}; - note_header.n_namesz = 8; // "WRONG" aligned to 4 - note_header.n_descsz = 7; // "BUILDID" - note_header.n_type = NT_GNU_BUILD_ID; - memcpy(¬e_section, ¬e_header, sizeof(note_header)); - size_t note_offset = sizeof(note_header); - memcpy(¬e_section[note_offset], "WRONG", sizeof("WRONG")); - note_offset += 8; - // This part of the note does not contain any trailing '\0'. - memcpy(¬e_section[note_offset], "BUILDID", 7); - note_offset += 8; - - note_header.n_namesz = 4; // "GNU" - note_header.n_descsz = 7; // "BUILDID" - note_header.n_type = NT_GNU_BUILD_ID; - memcpy(¬e_section[note_offset], ¬e_header, sizeof(note_header)); - note_offset += sizeof(note_header); - // The note information contains the GNU and trailing '\0'. - memcpy(¬e_section[note_offset], "GNU", sizeof("GNU")); - note_offset += sizeof("GNU"); - // This part of the note does not contain any trailing '\0'. - memcpy(¬e_section[note_offset], "BUILDID", 7); - - Shdr shdr = {}; - shdr.sh_type = SHT_NOTE; - shdr.sh_name = 0x500; - shdr.sh_offset = 0xb000; - shdr.sh_size = sizeof(note_section); - memory_.SetMemory(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; - - // The string data for section header names. - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_STRTAB; - shdr.sh_name = 0x20000; - shdr.sh_offset = 0xf000; - shdr.sh_size = 0x1000; - memory_.SetMemory(offset, &shdr, sizeof(shdr)); - - memory_.SetMemory(0xf500, ".note.gnu.build-id", sizeof(".note.gnu.build-id")); - memory_.SetMemory(0xb000, note_section, sizeof(note_section)); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - ASSERT_EQ("BUILDID", elf->GetBuildID()); -} - -TEST_F(ElfInterfaceTest, build_id_two_notes_32) { - BuildIDTwoNotes(); -} - -TEST_F(ElfInterfaceTest, build_id_two_notes_64) { - BuildIDTwoNotes(); -} - -template -void ElfInterfaceTest::BuildIDSectionTooSmallForName () { - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - - uint64_t offset = 0x2000; - - Ehdr ehdr = {}; - ehdr.e_shoff = offset; - ehdr.e_shnum = 3; - ehdr.e_shentsize = sizeof(Shdr); - ehdr.e_shstrndx = 2; - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - offset += ehdr.e_shentsize; - - char note_section[128]; - Nhdr note_header = {}; - note_header.n_namesz = 4; // "GNU" - note_header.n_descsz = 7; // "BUILDID" - note_header.n_type = NT_GNU_BUILD_ID; - memcpy(¬e_section, ¬e_header, sizeof(note_header)); - size_t note_offset = sizeof(note_header); - // The note information contains the GNU and trailing '\0'. - memcpy(¬e_section[note_offset], "GNU", sizeof("GNU")); - note_offset += sizeof("GNU"); - // This part of the note does not contain any trailing '\0'. - memcpy(¬e_section[note_offset], "BUILDID", 7); - - Shdr shdr = {}; - shdr.sh_type = SHT_NOTE; - shdr.sh_name = 0x500; - shdr.sh_offset = 0xb000; - shdr.sh_size = sizeof(note_header) + 1; - memory_.SetMemory(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; - - // The string data for section header names. - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_STRTAB; - shdr.sh_name = 0x20000; - shdr.sh_offset = 0xf000; - shdr.sh_size = 0x1000; - memory_.SetMemory(offset, &shdr, sizeof(shdr)); - - memory_.SetMemory(0xf500, ".note.gnu.build-id", sizeof(".note.gnu.build-id")); - memory_.SetMemory(0xb000, note_section, sizeof(note_section)); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - ASSERT_EQ("", elf->GetBuildID()); -} - -TEST_F(ElfInterfaceTest, build_id_section_too_small_for_name_32) { - BuildIDSectionTooSmallForName(); -} - -TEST_F(ElfInterfaceTest, build_id_section_too_small_for_name_64) { - BuildIDSectionTooSmallForName(); -} - -template -void ElfInterfaceTest::BuildIDSectionTooSmallForDesc () { - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - - uint64_t offset = 0x2000; - - Ehdr ehdr = {}; - ehdr.e_shoff = offset; - ehdr.e_shnum = 3; - ehdr.e_shentsize = sizeof(Shdr); - ehdr.e_shstrndx = 2; - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - offset += ehdr.e_shentsize; - - char note_section[128]; - Nhdr note_header = {}; - note_header.n_namesz = 4; // "GNU" - note_header.n_descsz = 7; // "BUILDID" - note_header.n_type = NT_GNU_BUILD_ID; - memcpy(¬e_section, ¬e_header, sizeof(note_header)); - size_t note_offset = sizeof(note_header); - // The note information contains the GNU and trailing '\0'. - memcpy(¬e_section[note_offset], "GNU", sizeof("GNU")); - note_offset += sizeof("GNU"); - // This part of the note does not contain any trailing '\0'. - memcpy(¬e_section[note_offset], "BUILDID", 7); - - Shdr shdr = {}; - shdr.sh_type = SHT_NOTE; - shdr.sh_name = 0x500; - shdr.sh_offset = 0xb000; - shdr.sh_size = sizeof(note_header) + sizeof("GNU") + 1; - memory_.SetMemory(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; - - // The string data for section header names. - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_STRTAB; - shdr.sh_name = 0x20000; - shdr.sh_offset = 0xf000; - shdr.sh_size = 0x1000; - memory_.SetMemory(offset, &shdr, sizeof(shdr)); - - memory_.SetMemory(0xf500, ".note.gnu.build-id", sizeof(".note.gnu.build-id")); - memory_.SetMemory(0xb000, note_section, sizeof(note_section)); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - ASSERT_EQ("", elf->GetBuildID()); -} - -TEST_F(ElfInterfaceTest, build_id_section_too_small_for_desc_32) { - BuildIDSectionTooSmallForDesc(); -} - -TEST_F(ElfInterfaceTest, build_id_section_too_small_for_desc_64) { - BuildIDSectionTooSmallForDesc(); -} - -template -void ElfInterfaceTest::BuildIDSectionTooSmallForHeader () { - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - - uint64_t offset = 0x2000; - - Ehdr ehdr = {}; - ehdr.e_shoff = offset; - ehdr.e_shnum = 3; - ehdr.e_shentsize = sizeof(Shdr); - ehdr.e_shstrndx = 2; - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - offset += ehdr.e_shentsize; - - char note_section[128]; - Nhdr note_header = {}; - note_header.n_namesz = 4; // "GNU" - note_header.n_descsz = 7; // "BUILDID" - note_header.n_type = NT_GNU_BUILD_ID; - memcpy(¬e_section, ¬e_header, sizeof(note_header)); - size_t note_offset = sizeof(note_header); - // The note information contains the GNU and trailing '\0'. - memcpy(¬e_section[note_offset], "GNU", sizeof("GNU")); - note_offset += sizeof("GNU"); - // This part of the note does not contain any trailing '\0'. - memcpy(¬e_section[note_offset], "BUILDID", 7); - - Shdr shdr = {}; - shdr.sh_type = SHT_NOTE; - shdr.sh_name = 0x500; - shdr.sh_offset = 0xb000; - shdr.sh_size = sizeof(note_header) - 1; - memory_.SetMemory(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; - - // The string data for section header names. - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_STRTAB; - shdr.sh_name = 0x20000; - shdr.sh_offset = 0xf000; - shdr.sh_size = 0x1000; - memory_.SetMemory(offset, &shdr, sizeof(shdr)); - - memory_.SetMemory(0xf500, ".note.gnu.build-id", sizeof(".note.gnu.build-id")); - memory_.SetMemory(0xb000, note_section, sizeof(note_section)); - - int64_t load_bias = 0; - ASSERT_TRUE(elf->Init(&load_bias)); - ASSERT_EQ("", elf->GetBuildID()); -} - -TEST_F(ElfInterfaceTest, build_id_section_too_small_for_header_32) { - BuildIDSectionTooSmallForHeader(); -} - -TEST_F(ElfInterfaceTest, build_id_section_too_small_for_header_64) { - BuildIDSectionTooSmallForHeader(); -} - -template -void ElfInterfaceTest::CheckLoadBiasInFirstPhdr(int64_t load_bias) { - Ehdr ehdr = {}; - ehdr.e_phoff = 0x100; - ehdr.e_phnum = 2; - ehdr.e_phentsize = sizeof(Phdr); - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - Phdr phdr = {}; - phdr.p_type = PT_LOAD; - phdr.p_offset = 0; - phdr.p_vaddr = load_bias; - phdr.p_memsz = 0x10000; - phdr.p_flags = PF_R | PF_X; - phdr.p_align = 0x1000; - memory_.SetMemory(0x100, &phdr, sizeof(phdr)); - - memset(&phdr, 0, sizeof(phdr)); - phdr.p_type = PT_LOAD; - phdr.p_offset = 0x1000; - phdr.p_memsz = 0x2000; - phdr.p_flags = PF_R | PF_X; - phdr.p_align = 0x1000; - memory_.SetMemory(0x100 + sizeof(phdr), &phdr, sizeof(phdr)); - - int64_t static_load_bias = ElfInterface::GetLoadBias(&memory_); - ASSERT_EQ(load_bias, static_load_bias); - - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - int64_t init_load_bias = 0; - ASSERT_TRUE(elf->Init(&init_load_bias)); - ASSERT_EQ(init_load_bias, static_load_bias); -} - -TEST_F(ElfInterfaceTest, get_load_bias_zero_32) { - CheckLoadBiasInFirstPhdr(0); -} - -TEST_F(ElfInterfaceTest, get_load_bias_zero_64) { - CheckLoadBiasInFirstPhdr(0); -} - -TEST_F(ElfInterfaceTest, get_load_bias_non_zero_32) { - CheckLoadBiasInFirstPhdr(0x1000); -} - -TEST_F(ElfInterfaceTest, get_load_bias_non_zero_64) { - CheckLoadBiasInFirstPhdr(0x1000); -} - -template -void ElfInterfaceTest::CheckLoadBiasInFirstExecPhdr(uint64_t offset, uint64_t vaddr, - int64_t load_bias) { - Ehdr ehdr = {}; - ehdr.e_phoff = 0x100; - ehdr.e_phnum = 3; - ehdr.e_phentsize = sizeof(Phdr); - memory_.SetMemory(0, &ehdr, sizeof(ehdr)); - - Phdr phdr = {}; - phdr.p_type = PT_LOAD; - phdr.p_memsz = 0x10000; - phdr.p_flags = PF_R; - phdr.p_align = 0x1000; - memory_.SetMemory(0x100, &phdr, sizeof(phdr)); - - memset(&phdr, 0, sizeof(phdr)); - phdr.p_type = PT_LOAD; - phdr.p_offset = offset; - phdr.p_vaddr = vaddr; - phdr.p_memsz = 0x2000; - phdr.p_flags = PF_R | PF_X; - phdr.p_align = 0x1000; - memory_.SetMemory(0x100 + sizeof(phdr), &phdr, sizeof(phdr)); - - // Second executable load should be ignored for load bias computation. - memset(&phdr, 0, sizeof(phdr)); - phdr.p_type = PT_LOAD; - phdr.p_offset = 0x1234; - phdr.p_vaddr = 0x2000; - phdr.p_memsz = 0x2000; - phdr.p_flags = PF_R | PF_X; - phdr.p_align = 0x1000; - memory_.SetMemory(0x200 + sizeof(phdr), &phdr, sizeof(phdr)); - - int64_t static_load_bias = ElfInterface::GetLoadBias(&memory_); - ASSERT_EQ(load_bias, static_load_bias); - - std::unique_ptr elf(new ElfInterfaceType(&memory_)); - int64_t init_load_bias = 0; - ASSERT_TRUE(elf->Init(&init_load_bias)); - ASSERT_EQ(init_load_bias, static_load_bias); -} - -TEST_F(ElfInterfaceTest, get_load_bias_exec_zero_32) { - CheckLoadBiasInFirstExecPhdr(0x1000, 0x1000, 0); -} - -TEST_F(ElfInterfaceTest, get_load_bias_exec_zero_64) { - CheckLoadBiasInFirstExecPhdr(0x1000, 0x1000, 0); -} - -TEST_F(ElfInterfaceTest, get_load_bias_exec_positive_32) { - CheckLoadBiasInFirstExecPhdr(0x1000, 0x4000, 0x3000); -} - -TEST_F(ElfInterfaceTest, get_load_bias_exec_positive_64) { - CheckLoadBiasInFirstExecPhdr(0x1000, 0x4000, 0x3000); -} - -TEST_F(ElfInterfaceTest, get_load_bias_exec_negative_32) { - CheckLoadBiasInFirstExecPhdr(0x5000, 0x1000, -0x4000); -} - -TEST_F(ElfInterfaceTest, get_load_bias_exec_negative_64) { - CheckLoadBiasInFirstExecPhdr(0x5000, 0x1000, -0x4000); -} - -TEST_F(ElfInterfaceTest, huge_gnu_debugdata_size) { - ElfInterfaceFake interface(nullptr); - - interface.FakeSetGnuDebugdataOffset(0x1000); - interface.FakeSetGnuDebugdataSize(0xffffffffffffffffUL); - ASSERT_TRUE(interface.CreateGnuDebugdataMemory() == nullptr); - - interface.FakeSetGnuDebugdataSize(0x4000000000000UL); - ASSERT_TRUE(interface.CreateGnuDebugdataMemory() == nullptr); - - // This should exceed the size_t value of the first allocation. -#if defined(__LP64__) - interface.FakeSetGnuDebugdataSize(0x3333333333333334ULL); -#else - interface.FakeSetGnuDebugdataSize(0x33333334); -#endif - ASSERT_TRUE(interface.CreateGnuDebugdataMemory() == nullptr); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp deleted file mode 100644 index d81edbff7..000000000 --- a/libunwindstack/tests/ElfTest.cpp +++ /dev/null @@ -1,546 +0,0 @@ -/* - * Copyright (C) 2016 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 "ElfFake.h" -#include "ElfTestUtils.h" -#include "LogFake.h" -#include "MemoryFake.h" - -#if !defined(PT_ARM_EXIDX) -#define PT_ARM_EXIDX 0x70000001 -#endif - -namespace unwindstack { - -class ElfTest : public ::testing::Test { - protected: - void SetUp() override { - memory_ = new MemoryFake; - } - - void InitElf32(uint32_t machine_type) { - Elf32_Ehdr ehdr; - TestInitEhdr(&ehdr, ELFCLASS32, machine_type); - - ehdr.e_phoff = 0x100; - ehdr.e_ehsize = sizeof(ehdr); - ehdr.e_phentsize = sizeof(Elf32_Phdr); - ehdr.e_phnum = 1; - ehdr.e_shentsize = sizeof(Elf32_Shdr); - if (machine_type == EM_ARM) { - ehdr.e_flags = 0x5000200; - ehdr.e_phnum = 2; - } - memory_->SetMemory(0, &ehdr, sizeof(ehdr)); - - Elf32_Phdr phdr; - memset(&phdr, 0, sizeof(phdr)); - phdr.p_type = PT_LOAD; - phdr.p_filesz = 0x10000; - phdr.p_memsz = 0x10000; - phdr.p_flags = PF_R | PF_X; - phdr.p_align = 0x1000; - memory_->SetMemory(0x100, &phdr, sizeof(phdr)); - - if (machine_type == EM_ARM) { - memset(&phdr, 0, sizeof(phdr)); - phdr.p_type = PT_ARM_EXIDX; - phdr.p_offset = 0x30000; - phdr.p_vaddr = 0x30000; - phdr.p_paddr = 0x30000; - phdr.p_filesz = 16; - phdr.p_memsz = 16; - phdr.p_flags = PF_R; - phdr.p_align = 0x4; - memory_->SetMemory(0x100 + sizeof(phdr), &phdr, sizeof(phdr)); - } - } - - void InitElf64(uint32_t machine_type) { - Elf64_Ehdr ehdr; - TestInitEhdr(&ehdr, ELFCLASS64, machine_type); - - ehdr.e_phoff = 0x100; - ehdr.e_flags = 0x5000200; - ehdr.e_ehsize = sizeof(ehdr); - ehdr.e_phentsize = sizeof(Elf64_Phdr); - ehdr.e_phnum = 1; - ehdr.e_shentsize = sizeof(Elf64_Shdr); - memory_->SetMemory(0, &ehdr, sizeof(ehdr)); - - Elf64_Phdr phdr; - memset(&phdr, 0, sizeof(phdr)); - phdr.p_type = PT_LOAD; - phdr.p_filesz = 0x10000; - phdr.p_memsz = 0x10000; - phdr.p_flags = PF_R | PF_X; - phdr.p_align = 0x1000; - memory_->SetMemory(0x100, &phdr, sizeof(phdr)); - } - - void VerifyStepIfSignalHandler(uint64_t load_bias); - - MemoryFake* memory_; -}; - -TEST_F(ElfTest, invalid_memory) { - Elf elf(memory_); - - ASSERT_FALSE(elf.Init()); - ASSERT_FALSE(elf.valid()); -} - -TEST_F(ElfTest, elf_invalid) { - Elf elf(memory_); - - InitElf32(EM_386); - - // Corrupt the ELF signature. - memory_->SetData32(0, 0x7f000000); - - ASSERT_FALSE(elf.Init()); - ASSERT_FALSE(elf.valid()); - ASSERT_TRUE(elf.interface() == nullptr); - - ASSERT_EQ("", elf.GetSoname()); - - std::string name; - uint64_t func_offset; - ASSERT_FALSE(elf.GetFunctionName(0, &name, &func_offset)); - - ASSERT_FALSE(elf.StepIfSignalHandler(0, nullptr, nullptr)); - EXPECT_EQ(ERROR_INVALID_ELF, elf.GetLastErrorCode()); - - bool finished; - bool is_signal_frame; - ASSERT_FALSE(elf.Step(0, nullptr, nullptr, &finished, &is_signal_frame)); - EXPECT_EQ(ERROR_INVALID_ELF, elf.GetLastErrorCode()); -} - -TEST_F(ElfTest, elf32_invalid_machine) { - Elf elf(memory_); - - InitElf32(EM_PPC); - - ResetLogs(); - ASSERT_FALSE(elf.Init()); - - ASSERT_EQ("", GetFakeLogBuf()); - ASSERT_EQ("4 unwind 32 bit elf that is neither arm nor x86 nor mips: e_machine = 20\n\n", - GetFakeLogPrint()); -} - -TEST_F(ElfTest, elf64_invalid_machine) { - Elf elf(memory_); - - InitElf64(EM_PPC64); - - ResetLogs(); - ASSERT_FALSE(elf.Init()); - - ASSERT_EQ("", GetFakeLogBuf()); - ASSERT_EQ("4 unwind 64 bit elf that is neither aarch64 nor x86_64 nor mips64: e_machine = 21\n\n", - GetFakeLogPrint()); -} - -TEST_F(ElfTest, elf_arm) { - Elf elf(memory_); - - InitElf32(EM_ARM); - - ASSERT_TRUE(elf.Init()); - ASSERT_TRUE(elf.valid()); - ASSERT_EQ(static_cast(EM_ARM), elf.machine_type()); - ASSERT_EQ(ELFCLASS32, elf.class_type()); - ASSERT_TRUE(elf.interface() != nullptr); -} - -TEST_F(ElfTest, elf_mips) { - Elf elf(memory_); - - InitElf32(EM_MIPS); - - ASSERT_TRUE(elf.Init()); - ASSERT_TRUE(elf.valid()); - ASSERT_EQ(static_cast(EM_MIPS), elf.machine_type()); - ASSERT_EQ(ELFCLASS32, elf.class_type()); - ASSERT_TRUE(elf.interface() != nullptr); -} - -TEST_F(ElfTest, elf_x86) { - Elf elf(memory_); - - InitElf32(EM_386); - - ASSERT_TRUE(elf.Init()); - ASSERT_TRUE(elf.valid()); - ASSERT_EQ(static_cast(EM_386), elf.machine_type()); - ASSERT_EQ(ELFCLASS32, elf.class_type()); - ASSERT_TRUE(elf.interface() != nullptr); -} - -TEST_F(ElfTest, elf_arm64) { - Elf elf(memory_); - - InitElf64(EM_AARCH64); - - ASSERT_TRUE(elf.Init()); - ASSERT_TRUE(elf.valid()); - ASSERT_EQ(static_cast(EM_AARCH64), elf.machine_type()); - ASSERT_EQ(ELFCLASS64, elf.class_type()); - ASSERT_TRUE(elf.interface() != nullptr); -} - -TEST_F(ElfTest, elf_x86_64) { - Elf elf(memory_); - - InitElf64(EM_X86_64); - - ASSERT_TRUE(elf.Init()); - ASSERT_TRUE(elf.valid()); - ASSERT_EQ(static_cast(EM_X86_64), elf.machine_type()); - ASSERT_EQ(ELFCLASS64, elf.class_type()); - ASSERT_TRUE(elf.interface() != nullptr); -} - -TEST_F(ElfTest, elf_mips64) { - Elf elf(memory_); - - InitElf64(EM_MIPS); - - ASSERT_TRUE(elf.Init()); - ASSERT_TRUE(elf.valid()); - ASSERT_EQ(static_cast(EM_MIPS), elf.machine_type()); - ASSERT_EQ(ELFCLASS64, elf.class_type()); - ASSERT_TRUE(elf.interface() != nullptr); -} - -TEST_F(ElfTest, gnu_debugdata_init32) { - TestInitGnuDebugdata(ELFCLASS32, EM_ARM, true, - [&](uint64_t offset, const void* ptr, size_t size) { - memory_->SetMemory(offset, ptr, size); - }); - - Elf elf(memory_); - ASSERT_TRUE(elf.Init()); - ASSERT_TRUE(elf.interface() != nullptr); - ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr); - EXPECT_EQ(0x1acU, elf.interface()->gnu_debugdata_offset()); - EXPECT_EQ(0x8cU, elf.interface()->gnu_debugdata_size()); -} - -TEST_F(ElfTest, gnu_debugdata_init64) { - TestInitGnuDebugdata(ELFCLASS64, EM_AARCH64, true, - [&](uint64_t offset, const void* ptr, size_t size) { - memory_->SetMemory(offset, ptr, size); - }); - - Elf elf(memory_); - ASSERT_TRUE(elf.Init()); - ASSERT_TRUE(elf.interface() != nullptr); - ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr); - EXPECT_EQ(0x200U, elf.interface()->gnu_debugdata_offset()); - EXPECT_EQ(0x90U, elf.interface()->gnu_debugdata_size()); -} - -TEST_F(ElfTest, rel_pc) { - ElfFake elf(memory_); - - ElfInterfaceFake* interface = new ElfInterfaceFake(memory_); - elf.FakeSetInterface(interface); - - elf.FakeSetValid(true); - MapInfo map_info(nullptr, nullptr, 0x1000, 0x2000, 0, 0, ""); - - ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info)); - - elf.FakeSetValid(false); - ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info)); -} - -void ElfTest::VerifyStepIfSignalHandler(uint64_t load_bias) { - ElfFake elf(memory_); - - RegsArm regs; - regs[13] = 0x50000; - regs[15] = 0x8000; - - ElfInterfaceFake* interface = new ElfInterfaceFake(memory_); - elf.FakeSetInterface(interface); - elf.FakeSetLoadBias(load_bias); - - memory_->SetData32(0x3000, 0xdf0027ad); - MemoryFake process_memory; - process_memory.SetData32(0x50000, 0); - for (size_t i = 0; i < 16; i++) { - process_memory.SetData32(0x500a0 + i * sizeof(uint32_t), i); - } - - elf.FakeSetValid(true); - ASSERT_TRUE(elf.StepIfSignalHandler(0x3000 + load_bias, ®s, &process_memory)); - EXPECT_EQ(ERROR_NONE, elf.GetLastErrorCode()); - EXPECT_EQ(15U, regs.pc()); - EXPECT_EQ(13U, regs.sp()); -} - -TEST_F(ElfTest, step_in_signal_map) { - VerifyStepIfSignalHandler(0); -} - -TEST_F(ElfTest, step_in_signal_map_non_zero_load_bias) { - VerifyStepIfSignalHandler(0x1000); -} - -class ElfInterfaceMock : public ElfInterface { - public: - ElfInterfaceMock(Memory* memory) : ElfInterface(memory) {} - virtual ~ElfInterfaceMock() = default; - - bool Init(int64_t*) override { return false; } - void InitHeaders() override {} - std::string GetSoname() override { return ""; } - bool GetFunctionName(uint64_t, std::string*, uint64_t*) override { return false; } - std::string GetBuildID() override { return ""; } - - MOCK_METHOD(bool, Step, (uint64_t, Regs*, Memory*, bool*, bool*), (override)); - MOCK_METHOD(bool, GetGlobalVariable, (const std::string&, uint64_t*), (override)); - MOCK_METHOD(bool, IsValidPc, (uint64_t), (override)); - - void MockSetDataOffset(uint64_t offset) { data_offset_ = offset; } - void MockSetDataVaddrStart(uint64_t vaddr) { data_vaddr_start_ = vaddr; } - void MockSetDataVaddrEnd(uint64_t vaddr) { data_vaddr_end_ = vaddr; } - - void MockSetDynamicOffset(uint64_t offset) { dynamic_offset_ = offset; } - void MockSetDynamicVaddrStart(uint64_t vaddr) { dynamic_vaddr_start_ = vaddr; } - void MockSetDynamicVaddrEnd(uint64_t vaddr) { dynamic_vaddr_end_ = vaddr; } -}; - -TEST_F(ElfTest, step_in_interface) { - ElfFake elf(memory_); - elf.FakeSetValid(true); - - RegsArm regs; - - ElfInterfaceMock* interface = new ElfInterfaceMock(memory_); - elf.FakeSetInterface(interface); - MemoryFake process_memory; - - bool finished; - bool is_signal_frame; - EXPECT_CALL(*interface, Step(0x1000, ®s, &process_memory, &finished, &is_signal_frame)) - .WillOnce(::testing::Return(true)); - - ASSERT_TRUE(elf.Step(0x1000, ®s, &process_memory, &finished, &is_signal_frame)); -} - -TEST_F(ElfTest, get_global_invalid_elf) { - ElfFake elf(memory_); - elf.FakeSetValid(false); - - std::string global("something"); - uint64_t offset; - ASSERT_FALSE(elf.GetGlobalVariableOffset(global, &offset)); -} - -TEST_F(ElfTest, get_global_valid_not_in_interface) { - ElfFake elf(memory_); - elf.FakeSetValid(true); - - ElfInterfaceMock* interface = new ElfInterfaceMock(memory_); - elf.FakeSetInterface(interface); - - std::string global("something"); - EXPECT_CALL(*interface, GetGlobalVariable(global, ::testing::_)) - .WillOnce(::testing::Return(false)); - - uint64_t offset; - ASSERT_FALSE(elf.GetGlobalVariableOffset(global, &offset)); -} - -TEST_F(ElfTest, get_global_vaddr_in_no_sections) { - ElfFake elf(memory_); - elf.FakeSetValid(true); - - ElfInterfaceMock* interface = new ElfInterfaceMock(memory_); - elf.FakeSetInterface(interface); - - std::string global("something"); - EXPECT_CALL(*interface, GetGlobalVariable(global, ::testing::_)) - .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x300), ::testing::Return(true))); - - uint64_t offset; - ASSERT_FALSE(elf.GetGlobalVariableOffset(global, &offset)); -} - -TEST_F(ElfTest, get_global_vaddr_in_data_section) { - ElfFake elf(memory_); - elf.FakeSetValid(true); - - ElfInterfaceMock* interface = new ElfInterfaceMock(memory_); - elf.FakeSetInterface(interface); - interface->MockSetDataVaddrStart(0x500); - interface->MockSetDataVaddrEnd(0x600); - interface->MockSetDataOffset(0xa000); - - std::string global("something"); - EXPECT_CALL(*interface, GetGlobalVariable(global, ::testing::_)) - .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x580), ::testing::Return(true))); - - uint64_t offset; - ASSERT_TRUE(elf.GetGlobalVariableOffset(global, &offset)); - EXPECT_EQ(0xa080U, offset); -} - -TEST_F(ElfTest, get_global_vaddr_in_dynamic_section) { - ElfFake elf(memory_); - elf.FakeSetValid(true); - - ElfInterfaceMock* interface = new ElfInterfaceMock(memory_); - elf.FakeSetInterface(interface); - interface->MockSetDataVaddrStart(0x500); - interface->MockSetDataVaddrEnd(0x600); - interface->MockSetDataOffset(0xa000); - - interface->MockSetDynamicVaddrStart(0x800); - interface->MockSetDynamicVaddrEnd(0x900); - interface->MockSetDynamicOffset(0xc000); - - std::string global("something"); - EXPECT_CALL(*interface, GetGlobalVariable(global, ::testing::_)) - .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x880), ::testing::Return(true))); - - uint64_t offset; - ASSERT_TRUE(elf.GetGlobalVariableOffset(global, &offset)); - EXPECT_EQ(0xc080U, offset); -} - -TEST_F(ElfTest, get_global_vaddr_with_tagged_pointer) { - ElfFake elf(memory_); - elf.FakeSetValid(true); - elf.FakeSetArch(ARCH_ARM64); - - ElfInterfaceMock* interface = new ElfInterfaceMock(memory_); - elf.FakeSetInterface(interface); - interface->MockSetDataVaddrStart(0x500); - interface->MockSetDataVaddrEnd(0x600); - interface->MockSetDataOffset(0xa000); - - std::string global("something"); - EXPECT_CALL(*interface, GetGlobalVariable(global, ::testing::_)) - .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x8800000000000580), - ::testing::Return(true))); - - uint64_t offset; - ASSERT_TRUE(elf.GetGlobalVariableOffset(global, &offset)); - EXPECT_EQ(0xa080U, offset); -} - -TEST_F(ElfTest, get_global_vaddr_without_tagged_pointer) { - ElfFake elf(memory_); - elf.FakeSetValid(true); - elf.FakeSetArch(ARCH_X86_64); - - ElfInterfaceMock* interface = new ElfInterfaceMock(memory_); - elf.FakeSetInterface(interface); - interface->MockSetDataVaddrStart(0x8800000000000500); - interface->MockSetDataVaddrEnd(0x8800000000000600); - interface->MockSetDataOffset(0x880000000000a000); - - std::string global("something"); - EXPECT_CALL(*interface, GetGlobalVariable(global, ::testing::_)) - .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x8800000000000580), - ::testing::Return(true))); - - uint64_t offset; - ASSERT_TRUE(elf.GetGlobalVariableOffset(global, &offset)); - EXPECT_EQ(0x880000000000a080U, offset); -} - -TEST_F(ElfTest, is_valid_pc_elf_invalid) { - ElfFake elf(memory_); - elf.FakeSetValid(false); - - EXPECT_FALSE(elf.IsValidPc(0x100)); - EXPECT_FALSE(elf.IsValidPc(0x200)); -} - -TEST_F(ElfTest, is_valid_pc_interface) { - ElfFake elf(memory_); - elf.FakeSetValid(true); - - ElfInterfaceMock* interface = new ElfInterfaceMock(memory_); - elf.FakeSetInterface(interface); - - EXPECT_CALL(*interface, IsValidPc(0x1500)).WillOnce(::testing::Return(true)); - - EXPECT_TRUE(elf.IsValidPc(0x1500)); -} - -TEST_F(ElfTest, is_valid_pc_from_gnu_debugdata) { - ElfFake elf(memory_); - elf.FakeSetValid(true); - - ElfInterfaceMock* interface = new ElfInterfaceMock(memory_); - elf.FakeSetInterface(interface); - ElfInterfaceMock* gnu_interface = new ElfInterfaceMock(memory_); - elf.FakeSetGnuDebugdataInterface(gnu_interface); - - EXPECT_CALL(*interface, IsValidPc(0x1500)).WillOnce(::testing::Return(false)); - EXPECT_CALL(*gnu_interface, IsValidPc(0x1500)).WillOnce(::testing::Return(true)); - - EXPECT_TRUE(elf.IsValidPc(0x1500)); -} - -TEST_F(ElfTest, error_code_not_valid) { - ElfFake elf(memory_); - elf.FakeSetValid(false); - - ErrorData error{ERROR_MEMORY_INVALID, 0x100}; - elf.GetLastError(&error); - EXPECT_EQ(ERROR_MEMORY_INVALID, error.code); - EXPECT_EQ(0x100U, error.address); -} - -TEST_F(ElfTest, error_code_valid) { - ElfFake elf(memory_); - elf.FakeSetValid(true); - ElfInterfaceFake* interface = new ElfInterfaceFake(memory_); - elf.FakeSetInterface(interface); - interface->FakeSetErrorCode(ERROR_MEMORY_INVALID); - interface->FakeSetErrorAddress(0x1000); - - ErrorData error{ERROR_NONE, 0}; - elf.GetLastError(&error); - EXPECT_EQ(ERROR_MEMORY_INVALID, error.code); - EXPECT_EQ(0x1000U, error.address); - EXPECT_EQ(ERROR_MEMORY_INVALID, elf.GetLastErrorCode()); - EXPECT_EQ(0x1000U, elf.GetLastErrorAddress()); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/ElfTestUtils.cpp b/libunwindstack/tests/ElfTestUtils.cpp deleted file mode 100644 index 69163ac94..000000000 --- a/libunwindstack/tests/ElfTestUtils.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2016 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 "ElfTestUtils.h" - -namespace unwindstack { - -template -void TestInitEhdr(Ehdr* ehdr, uint32_t elf_class, uint32_t machine_type) { - memset(ehdr, 0, sizeof(Ehdr)); - memcpy(&ehdr->e_ident[0], ELFMAG, SELFMAG); - ehdr->e_ident[EI_DATA] = ELFDATA2LSB; - ehdr->e_ident[EI_VERSION] = EV_CURRENT; - ehdr->e_ident[EI_OSABI] = ELFOSABI_SYSV; - ehdr->e_ident[EI_CLASS] = elf_class; - ehdr->e_type = ET_DYN; - ehdr->e_machine = machine_type; - ehdr->e_version = EV_CURRENT; - ehdr->e_ehsize = sizeof(Ehdr); -} - -std::string TestGetFileDirectory() { - std::string exec(testing::internal::GetArgvs()[0]); - auto const value = exec.find_last_of('/'); - if (value == std::string::npos) { - return "tests/files/"; - } - return exec.substr(0, value + 1) + "tests/files/"; -} - -template -void TestInitGnuDebugdata(uint32_t elf_class, uint32_t machine, bool init_gnu_debugdata, - TestCopyFuncType copy_func) { - Ehdr ehdr; - - TestInitEhdr(&ehdr, elf_class, machine); - - uint64_t offset = sizeof(Ehdr); - ehdr.e_shoff = offset; - ehdr.e_shnum = 3; - ehdr.e_shentsize = sizeof(Shdr); - ehdr.e_shstrndx = 2; - copy_func(0, &ehdr, sizeof(ehdr)); - - Shdr shdr; - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_NULL; - copy_func(offset, &shdr, sizeof(shdr)); - offset += ehdr.e_shentsize; - - // Skip this header, it will contain the gnu_debugdata information. - uint64_t gnu_offset = offset; - offset += ehdr.e_shentsize; - - uint64_t symtab_offset = sizeof(ehdr) + ehdr.e_shnum * ehdr.e_shentsize; - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_name = 1; - shdr.sh_type = SHT_STRTAB; - shdr.sh_offset = symtab_offset; - shdr.sh_size = 0x100; - copy_func(offset, &shdr, sizeof(shdr)); - - char value = '\0'; - uint64_t symname_offset = symtab_offset; - copy_func(symname_offset, &value, 1); - symname_offset++; - std::string name(".shstrtab"); - copy_func(symname_offset, name.c_str(), name.size() + 1); - symname_offset += name.size() + 1; - name = ".gnu_debugdata"; - copy_func(symname_offset, name.c_str(), name.size() + 1); - - ssize_t bytes = 0x100; - offset = symtab_offset + 0x100; - if (init_gnu_debugdata) { - // Read in the compressed elf data and copy it in. - name = TestGetFileDirectory(); - if (elf_class == ELFCLASS32) { - name += "elf32.xz"; - } else { - name += "elf64.xz"; - } - int fd = TEMP_FAILURE_RETRY(open(name.c_str(), O_RDONLY)); - ASSERT_NE(-1, fd) << "Cannot open " + name; - // Assumes the file is less than 1024 bytes. - std::vector buf(1024); - bytes = TEMP_FAILURE_RETRY(read(fd, buf.data(), buf.size())); - ASSERT_GT(bytes, 0); - // Make sure the file isn't too big. - ASSERT_NE(static_cast(bytes), buf.size()) - << "File " + name + " is too big, increase buffer size."; - close(fd); - buf.resize(bytes); - copy_func(offset, buf.data(), buf.size()); - } - - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_PROGBITS; - shdr.sh_name = symname_offset - symtab_offset; - shdr.sh_addr = offset; - shdr.sh_offset = offset; - shdr.sh_size = bytes; - copy_func(gnu_offset, &shdr, sizeof(shdr)); -} - -template void TestInitEhdr(Elf32_Ehdr*, uint32_t, uint32_t); -template void TestInitEhdr(Elf64_Ehdr*, uint32_t, uint32_t); - -template void TestInitGnuDebugdata(uint32_t, uint32_t, bool, - TestCopyFuncType); -template void TestInitGnuDebugdata(uint32_t, uint32_t, bool, - TestCopyFuncType); - -} // namespace unwindstack diff --git a/libunwindstack/tests/ElfTestUtils.h b/libunwindstack/tests/ElfTestUtils.h deleted file mode 100644 index 62cd59a29..000000000 --- a/libunwindstack/tests/ElfTestUtils.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2017 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_TESTS_ELF_TEST_UTILS_H -#define _LIBUNWINDSTACK_TESTS_ELF_TEST_UTILS_H - -#include -#include - -namespace unwindstack { - -typedef std::function TestCopyFuncType; - -template -void TestInitEhdr(Ehdr* ehdr, uint32_t elf_class, uint32_t machine_type); - -template -void TestInitGnuDebugdata(uint32_t elf_class, uint32_t machine_type, bool init_gnu_debudata, - TestCopyFuncType copy_func); - -std::string TestGetFileDirectory(); - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_TESTS_ELF_TEST_UTILS_H diff --git a/libunwindstack/tests/GenGnuDebugdata.cpp b/libunwindstack/tests/GenGnuDebugdata.cpp deleted file mode 100644 index 2644582b2..000000000 --- a/libunwindstack/tests/GenGnuDebugdata.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2016 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 - -#if !defined(EM_AARCH64) -#define EM_AARCH64 183 -#endif - -template -void InitEhdr(Ehdr* ehdr, uint32_t elf_class, uint32_t machine) { - memset(ehdr, 0, sizeof(Ehdr)); - memcpy(&ehdr->e_ident[0], ELFMAG, SELFMAG); - ehdr->e_ident[EI_DATA] = ELFDATA2LSB; - ehdr->e_ident[EI_VERSION] = EV_CURRENT; - ehdr->e_ident[EI_OSABI] = ELFOSABI_SYSV; - ehdr->e_ident[EI_CLASS] = elf_class; - ehdr->e_type = ET_DYN; - ehdr->e_machine = machine; - ehdr->e_version = EV_CURRENT; - ehdr->e_ehsize = sizeof(Ehdr); -} - -template -void GenElf(Ehdr* ehdr, int fd) { - uint64_t offset = sizeof(Ehdr); - ehdr->e_shoff = offset; - ehdr->e_shnum = 3; - ehdr->e_shentsize = sizeof(Shdr); - ehdr->e_shstrndx = 2; - TEMP_FAILURE_RETRY(write(fd, ehdr, sizeof(Ehdr))); - - Shdr shdr; - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_name = 0; - shdr.sh_type = SHT_NULL; - TEMP_FAILURE_RETRY(write(fd, &shdr, sizeof(Shdr))); - offset += ehdr->e_shentsize; - - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_PROGBITS; - shdr.sh_name = 11; - shdr.sh_addr = 0x5000; - shdr.sh_offset = 0x5000; - shdr.sh_entsize = 0x100; - shdr.sh_size = 0x800; - TEMP_FAILURE_RETRY(write(fd, &shdr, sizeof(Shdr))); - offset += ehdr->e_shentsize; - - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_STRTAB; - shdr.sh_name = 1; - shdr.sh_offset = 0x200; - shdr.sh_size = 24; - TEMP_FAILURE_RETRY(write(fd, &shdr, sizeof(Shdr))); - - // Write out the name entries information. - lseek(fd, 0x200, SEEK_SET); - std::string name; - TEMP_FAILURE_RETRY(write(fd, name.data(), name.size() + 1)); - name = ".shstrtab"; - TEMP_FAILURE_RETRY(write(fd, name.data(), name.size() + 1)); - name = ".debug_frame"; - TEMP_FAILURE_RETRY(write(fd, name.data(), name.size() + 1)); -} - -int main() { - int elf32_fd = TEMP_FAILURE_RETRY(open("elf32", O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0644)); - if (elf32_fd == -1) { - printf("Failed to create elf32: %s\n", strerror(errno)); - return 1; - } - - int elf64_fd = TEMP_FAILURE_RETRY(open("elf64", O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0644)); - if (elf64_fd == -1) { - printf("Failed to create elf64: %s\n", strerror(errno)); - return 1; - } - - Elf32_Ehdr ehdr32; - InitEhdr(&ehdr32, ELFCLASS32, EM_ARM); - GenElf(&ehdr32, elf32_fd); - close(elf32_fd); - - Elf64_Ehdr ehdr64; - InitEhdr(&ehdr64, ELFCLASS64, EM_AARCH64); - GenElf(&ehdr64, elf64_fd); - close(elf64_fd); -} diff --git a/libunwindstack/tests/IsolatedSettings.cpp b/libunwindstack/tests/IsolatedSettings.cpp deleted file mode 100644 index dbd8bd608..000000000 --- a/libunwindstack/tests/IsolatedSettings.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2016 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 - -extern "C" bool GetInitialArgs(const char*** args, size_t* num_args) { - static const char* initial_args[2] = {"--slow_threshold_ms=90000", - "--deadline_threshold_ms=120000"}; - *args = initial_args; - *num_args = 2; - return true; -} diff --git a/libunwindstack/tests/JitDebugTest.cpp b/libunwindstack/tests/JitDebugTest.cpp deleted file mode 100644 index 9b32a3a43..000000000 --- a/libunwindstack/tests/JitDebugTest.cpp +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Copyright (C) 2018 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 "ElfFake.h" -#include "MemoryFake.h" - -namespace unwindstack { - -class JitDebugTest : public ::testing::Test { - protected: - void CreateFakeElf(MapInfo* map_info, uint64_t global_offset, uint64_t data_offset, - uint64_t data_vaddr, uint64_t data_size) { - MemoryFake* memory = new MemoryFake; - ElfFake* elf = new ElfFake(memory); - elf->FakeSetValid(true); - ElfInterfaceFake* interface = new ElfInterfaceFake(memory); - elf->FakeSetInterface(interface); - interface->FakeSetGlobalVariable("__jit_debug_descriptor", global_offset); - interface->FakeSetDataOffset(data_offset); - interface->FakeSetDataVaddrStart(data_vaddr); - interface->FakeSetDataVaddrEnd(data_vaddr + data_size); - map_info->elf.reset(elf); - } - - void Init(ArchEnum arch) { - jit_debug_.reset(new JitDebug(process_memory_)); - jit_debug_->SetArch(arch); - - maps_.reset( - new BufferMaps("1000-4000 ---s 00000000 00:00 0 /fake/elf1\n" - "4000-6000 r--s 00000000 00:00 0 /fake/elf1\n" - "6000-8000 -wxs 00002000 00:00 0 /fake/elf1\n" - "a000-c000 --xp 00000000 00:00 0 /fake/elf2\n" - "c000-f000 rw-p 00002000 00:00 0 /fake/elf2\n" - "f000-11000 r--p 00000000 00:00 0 /fake/elf3\n" - "11000-12000 rw-p 00002000 00:00 0 /fake/elf3\n" - "12000-14000 r--p 00000000 00:00 0 /fake/elf4\n" - "100000-110000 rw-p 00ee000 00:00 0 /fake/elf4\n" - "200000-210000 rw-p 01ee000 00:00 0 /fake/elf4\n")); - ASSERT_TRUE(maps_->Parse()); - - MapInfo* map_info = maps_->Get(3); - ASSERT_TRUE(map_info != nullptr); - CreateFakeElf(map_info, 0x2800, 0x2000, 0x2000, 0x3000); - - map_info = maps_->Get(5); - ASSERT_TRUE(map_info != nullptr); - CreateFakeElf(map_info, 0x2800, 0x2000, 0x2000, 0x3000); - - map_info = maps_->Get(7); - ASSERT_TRUE(map_info != nullptr); - CreateFakeElf(map_info, 0xee800, 0xee000, 0xee000, 0x10000); - } - - void SetUp() override { - memory_ = new MemoryFake; - process_memory_.reset(memory_); - - Init(ARCH_ARM); - } - - template - void CreateElf(uint64_t offset, uint8_t class_type, uint8_t machine_type, uint32_t pc, - uint32_t size) { - EhdrType ehdr; - memset(&ehdr, 0, sizeof(ehdr)); - uint64_t sh_offset = sizeof(ehdr); - memcpy(ehdr.e_ident, ELFMAG, SELFMAG); - ehdr.e_ident[EI_CLASS] = class_type; - ehdr.e_machine = machine_type; - ehdr.e_shstrndx = 1; - ehdr.e_shoff = sh_offset; - ehdr.e_shentsize = sizeof(ShdrType); - ehdr.e_shnum = 3; - memory_->SetMemory(offset, &ehdr, sizeof(ehdr)); - - ShdrType shdr; - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_NULL; - memory_->SetMemory(offset + sh_offset, &shdr, sizeof(shdr)); - - sh_offset += sizeof(shdr); - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_STRTAB; - shdr.sh_name = 1; - shdr.sh_offset = 0x500; - shdr.sh_size = 0x100; - memory_->SetMemory(offset + sh_offset, &shdr, sizeof(shdr)); - memory_->SetMemory(offset + 0x500, ".debug_frame"); - - sh_offset += sizeof(shdr); - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_PROGBITS; - shdr.sh_name = 0; - shdr.sh_addr = 0x600; - shdr.sh_offset = 0x600; - shdr.sh_size = 0x200; - memory_->SetMemory(offset + sh_offset, &shdr, sizeof(shdr)); - - // Now add a single cie/fde. - uint64_t dwarf_offset = offset + 0x600; - if (class_type == ELFCLASS32) { - // CIE 32 information. - memory_->SetData32(dwarf_offset, 0xfc); - memory_->SetData32(dwarf_offset + 0x4, 0xffffffff); - memory_->SetData8(dwarf_offset + 0x8, 1); - memory_->SetData8(dwarf_offset + 0x9, '\0'); - memory_->SetData8(dwarf_offset + 0xa, 0x4); - memory_->SetData8(dwarf_offset + 0xb, 0x4); - memory_->SetData8(dwarf_offset + 0xc, 0x1); - - // FDE 32 information. - memory_->SetData32(dwarf_offset + 0x100, 0xfc); - memory_->SetData32(dwarf_offset + 0x104, 0); - memory_->SetData32(dwarf_offset + 0x108, pc); - memory_->SetData32(dwarf_offset + 0x10c, size); - } else { - // CIE 64 information. - memory_->SetData32(dwarf_offset, 0xffffffff); - memory_->SetData64(dwarf_offset + 4, 0xf4); - memory_->SetData64(dwarf_offset + 0xc, 0xffffffffffffffffULL); - memory_->SetData8(dwarf_offset + 0x14, 1); - memory_->SetData8(dwarf_offset + 0x15, '\0'); - memory_->SetData8(dwarf_offset + 0x16, 0x4); - memory_->SetData8(dwarf_offset + 0x17, 0x4); - memory_->SetData8(dwarf_offset + 0x18, 0x1); - - // FDE 64 information. - memory_->SetData32(dwarf_offset + 0x100, 0xffffffff); - memory_->SetData64(dwarf_offset + 0x104, 0xf4); - memory_->SetData64(dwarf_offset + 0x10c, 0); - memory_->SetData64(dwarf_offset + 0x114, pc); - memory_->SetData64(dwarf_offset + 0x11c, size); - } - } - - void WriteDescriptor32(uint64_t addr, uint32_t entry); - void WriteDescriptor64(uint64_t addr, uint64_t entry); - void WriteEntry32Pack(uint64_t addr, uint32_t prev, uint32_t next, uint32_t elf_addr, - uint64_t elf_size); - void WriteEntry32Pad(uint64_t addr, uint32_t prev, uint32_t next, uint32_t elf_addr, - uint64_t elf_size); - void WriteEntry64(uint64_t addr, uint64_t prev, uint64_t next, uint64_t elf_addr, - uint64_t elf_size); - - std::shared_ptr process_memory_; - MemoryFake* memory_; - std::unique_ptr jit_debug_; - std::unique_ptr maps_; -}; - -void JitDebugTest::WriteDescriptor32(uint64_t addr, uint32_t entry) { - // Format of the 32 bit JITDescriptor structure: - // uint32_t version - memory_->SetData32(addr, 1); - // uint32_t action_flag - memory_->SetData32(addr + 4, 0); - // uint32_t relevant_entry - memory_->SetData32(addr + 8, 0); - // uint32_t first_entry - memory_->SetData32(addr + 12, entry); -} - -void JitDebugTest::WriteDescriptor64(uint64_t addr, uint64_t entry) { - // Format of the 64 bit JITDescriptor structure: - // uint32_t version - memory_->SetData32(addr, 1); - // uint32_t action_flag - memory_->SetData32(addr + 4, 0); - // uint64_t relevant_entry - memory_->SetData64(addr + 8, 0); - // uint64_t first_entry - memory_->SetData64(addr + 16, entry); -} - -void JitDebugTest::WriteEntry32Pack(uint64_t addr, uint32_t prev, uint32_t next, uint32_t elf_addr, - uint64_t elf_size) { - // Format of the 32 bit JITCodeEntry structure: - // uint32_t next - memory_->SetData32(addr, next); - // uint32_t prev - memory_->SetData32(addr + 4, prev); - // uint32_t symfile_addr - memory_->SetData32(addr + 8, elf_addr); - // uint64_t symfile_size - memory_->SetData64(addr + 12, elf_size); -} - -void JitDebugTest::WriteEntry32Pad(uint64_t addr, uint32_t prev, uint32_t next, uint32_t elf_addr, - uint64_t elf_size) { - // Format of the 32 bit JITCodeEntry structure: - // uint32_t next - memory_->SetData32(addr, next); - // uint32_t prev - memory_->SetData32(addr + 4, prev); - // uint32_t symfile_addr - memory_->SetData32(addr + 8, elf_addr); - // uint32_t pad - memory_->SetData32(addr + 12, 0); - // uint64_t symfile_size - memory_->SetData64(addr + 16, elf_size); -} - -void JitDebugTest::WriteEntry64(uint64_t addr, uint64_t prev, uint64_t next, uint64_t elf_addr, - uint64_t elf_size) { - // Format of the 64 bit JITCodeEntry structure: - // uint64_t next - memory_->SetData64(addr, next); - // uint64_t prev - memory_->SetData64(addr + 8, prev); - // uint64_t symfile_addr - memory_->SetData64(addr + 16, elf_addr); - // uint64_t symfile_size - memory_->SetData64(addr + 24, elf_size); -} - -TEST_F(JitDebugTest, get_elf_invalid) { - Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500); - ASSERT_TRUE(elf == nullptr); -} - -TEST_F(JitDebugTest, get_elf_no_global_variable) { - maps_.reset(new BufferMaps("")); - Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500); - ASSERT_TRUE(elf == nullptr); -} - -TEST_F(JitDebugTest, get_elf_no_valid_descriptor_in_memory) { - CreateElf(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200); - - Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500); - ASSERT_TRUE(elf == nullptr); -} - -TEST_F(JitDebugTest, get_elf_no_valid_code_entry) { - CreateElf(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200); - - WriteDescriptor32(0x11800, 0x200000); - - Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500); - ASSERT_TRUE(elf == nullptr); -} - -TEST_F(JitDebugTest, get_elf_invalid_descriptor_first_entry) { - CreateElf(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200); - - WriteDescriptor32(0x11800, 0); - - Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500); - ASSERT_TRUE(elf == nullptr); -} - -TEST_F(JitDebugTest, get_elf_invalid_descriptor_version) { - CreateElf(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200); - - WriteDescriptor32(0x11800, 0x20000); - // Set the version to an invalid value. - memory_->SetData32(0x11800, 2); - - Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500); - ASSERT_TRUE(elf == nullptr); -} - -TEST_F(JitDebugTest, get_elf_32) { - CreateElf(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200); - - WriteDescriptor32(0x11800, 0x200000); - WriteEntry32Pad(0x200000, 0, 0, 0x4000, 0x1000); - - Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500); - ASSERT_TRUE(elf != nullptr); - - // Clear the memory and verify all of the data is cached. - memory_->Clear(); - Elf* elf2 = jit_debug_->GetElf(maps_.get(), 0x1500); - ASSERT_TRUE(elf2 != nullptr); - EXPECT_EQ(elf, elf2); -} - -TEST_F(JitDebugTest, get_multiple_jit_debug_descriptors_valid) { - CreateElf(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200); - CreateElf(0x5000, ELFCLASS32, EM_ARM, 0x2000, 0x300); - - WriteDescriptor32(0x11800, 0x200000); - WriteEntry32Pad(0x200000, 0, 0, 0x4000, 0x1000); - WriteDescriptor32(0x100800, 0x201000); - WriteEntry32Pad(0x201000, 0, 0, 0x5000, 0x1000); - - ASSERT_TRUE(jit_debug_->GetElf(maps_.get(), 0x1500) != nullptr); - ASSERT_TRUE(jit_debug_->GetElf(maps_.get(), 0x2000) == nullptr); - - // Now clear the descriptor entry for the first one. - WriteDescriptor32(0x11800, 0); - jit_debug_.reset(new JitDebug(process_memory_)); - jit_debug_->SetArch(ARCH_ARM); - - ASSERT_TRUE(jit_debug_->GetElf(maps_.get(), 0x1500) == nullptr); - ASSERT_TRUE(jit_debug_->GetElf(maps_.get(), 0x2000) != nullptr); -} - -TEST_F(JitDebugTest, get_elf_x86) { - Init(ARCH_X86); - - CreateElf(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200); - - WriteDescriptor32(0x11800, 0x200000); - WriteEntry32Pack(0x200000, 0, 0, 0x4000, 0x1000); - - jit_debug_->SetArch(ARCH_X86); - Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500); - ASSERT_TRUE(elf != nullptr); - - // Clear the memory and verify all of the data is cached. - memory_->Clear(); - Elf* elf2 = jit_debug_->GetElf(maps_.get(), 0x1500); - ASSERT_TRUE(elf2 != nullptr); - EXPECT_EQ(elf, elf2); -} - -TEST_F(JitDebugTest, get_elf_64) { - Init(ARCH_ARM64); - - CreateElf(0x4000, ELFCLASS64, EM_AARCH64, 0x1500, 0x200); - - WriteDescriptor64(0x11800, 0x200000); - WriteEntry64(0x200000, 0, 0, 0x4000, 0x1000); - - Elf* elf = jit_debug_->GetElf(maps_.get(), 0x1500); - ASSERT_TRUE(elf != nullptr); - - // Clear the memory and verify all of the data is cached. - memory_->Clear(); - Elf* elf2 = jit_debug_->GetElf(maps_.get(), 0x1500); - ASSERT_TRUE(elf2 != nullptr); - EXPECT_EQ(elf, elf2); -} - -TEST_F(JitDebugTest, get_elf_multiple_entries) { - CreateElf(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200); - CreateElf(0x5000, ELFCLASS32, EM_ARM, 0x2300, 0x400); - - WriteDescriptor32(0x11800, 0x200000); - WriteEntry32Pad(0x200000, 0, 0x200100, 0x4000, 0x1000); - WriteEntry32Pad(0x200100, 0x200100, 0, 0x5000, 0x1000); - - Elf* elf_2 = jit_debug_->GetElf(maps_.get(), 0x2400); - ASSERT_TRUE(elf_2 != nullptr); - - Elf* elf_1 = jit_debug_->GetElf(maps_.get(), 0x1600); - ASSERT_TRUE(elf_1 != nullptr); - - // Clear the memory and verify all of the data is cached. - memory_->Clear(); - EXPECT_EQ(elf_1, jit_debug_->GetElf(maps_.get(), 0x1500)); - EXPECT_EQ(elf_1, jit_debug_->GetElf(maps_.get(), 0x16ff)); - EXPECT_EQ(elf_2, jit_debug_->GetElf(maps_.get(), 0x2300)); - EXPECT_EQ(elf_2, jit_debug_->GetElf(maps_.get(), 0x26ff)); - EXPECT_EQ(nullptr, jit_debug_->GetElf(maps_.get(), 0x1700)); - EXPECT_EQ(nullptr, jit_debug_->GetElf(maps_.get(), 0x2700)); -} - -TEST_F(JitDebugTest, get_elf_search_libs) { - CreateElf(0x4000, ELFCLASS32, EM_ARM, 0x1500, 0x200); - - WriteDescriptor32(0x11800, 0x200000); - WriteEntry32Pad(0x200000, 0, 0, 0x4000, 0x1000); - - // Only search a given named list of libs. - std::vector libs{"libart.so"}; - jit_debug_.reset(new JitDebug(process_memory_, libs)); - jit_debug_->SetArch(ARCH_ARM); - EXPECT_TRUE(jit_debug_->GetElf(maps_.get(), 0x1500) == nullptr); - - // Change the name of the map that includes the value and verify this works. - MapInfo* map_info = maps_->Get(5); - map_info->name = "/system/lib/libart.so"; - map_info = maps_->Get(6); - map_info->name = "/system/lib/libart.so"; - jit_debug_.reset(new JitDebug(process_memory_, libs)); - // Make sure that clearing our copy of the libs doesn't affect the - // JitDebug object. - libs.clear(); - jit_debug_->SetArch(ARCH_ARM); - EXPECT_TRUE(jit_debug_->GetElf(maps_.get(), 0x1500) != nullptr); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/LocalUnwinderTest.cpp b/libunwindstack/tests/LocalUnwinderTest.cpp deleted file mode 100644 index 9936f7afa..000000000 --- a/libunwindstack/tests/LocalUnwinderTest.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (C) 2018 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 - -namespace unwindstack { - -static std::vector* g_frame_info; -static LocalUnwinder* g_unwinder; - -extern "C" void SignalLocalInnerFunction() { - g_unwinder->Unwind(g_frame_info, 256); -} - -extern "C" void SignalLocalMiddleFunction() { - SignalLocalInnerFunction(); -} - -extern "C" void SignalLocalOuterFunction() { - SignalLocalMiddleFunction(); -} - -static void SignalLocalCallerHandler(int, siginfo_t*, void*) { - SignalLocalOuterFunction(); -} - -static std::string ErrorMsg(const std::vector& function_names, - const std::vector& frame_info) { - std::string unwind; - size_t i = 0; - for (const auto& frame : frame_info) { - unwind += android::base::StringPrintf("#%02zu pc 0x%" PRIx64 " rel_pc 0x%" PRIx64, i++, - frame.pc, frame.rel_pc); - if (frame.map_info != nullptr) { - if (!frame.map_info->name.empty()) { - unwind += " " + frame.map_info->name; - } else { - unwind += android::base::StringPrintf(" 0x%" PRIx64 "-0x%" PRIx64, frame.map_info->start, - frame.map_info->end); - } - if (frame.map_info->offset != 0) { - unwind += android::base::StringPrintf(" offset 0x%" PRIx64, frame.map_info->offset); - } - } - if (!frame.function_name.empty()) { - unwind += " " + frame.function_name; - if (frame.function_offset != 0) { - unwind += android::base::StringPrintf("+%" PRId64, frame.function_offset); - } - } - unwind += '\n'; - } - - return std::string( - "Unwind completed without finding all frames\n" - " Looking for function: ") + - function_names.front() + "\n" + "Unwind data:\n" + unwind; -} - -// This test assumes that this code is compiled with optimizations turned -// off. If this doesn't happen, then all of the calls will be optimized -// away. -extern "C" void LocalInnerFunction(LocalUnwinder* unwinder, bool unwind_through_signal) { - std::vector frame_info; - g_frame_info = &frame_info; - g_unwinder = unwinder; - std::vector expected_function_names; - - if (unwind_through_signal) { - struct sigaction act, oldact; - memset(&act, 0, sizeof(act)); - act.sa_sigaction = SignalLocalCallerHandler; - act.sa_flags = SA_RESTART | SA_ONSTACK; - ASSERT_EQ(0, sigaction(SIGUSR1, &act, &oldact)); - - raise(SIGUSR1); - - ASSERT_EQ(0, sigaction(SIGUSR1, &oldact, nullptr)); - - expected_function_names = {"LocalOuterFunction", "LocalMiddleFunction", - "LocalInnerFunction", "SignalLocalOuterFunction", - "SignalLocalMiddleFunction", "SignalLocalInnerFunction"}; - } else { - ASSERT_TRUE(unwinder->Unwind(&frame_info, 256)); - - expected_function_names = {"LocalOuterFunction", "LocalMiddleFunction", "LocalInnerFunction"}; - } - - for (auto& frame : frame_info) { - if (frame.function_name == expected_function_names.back()) { - expected_function_names.pop_back(); - if (expected_function_names.empty()) { - break; - } - } - } - - ASSERT_TRUE(expected_function_names.empty()) << ErrorMsg(expected_function_names, frame_info); -} - -extern "C" void LocalMiddleFunction(LocalUnwinder* unwinder, bool unwind_through_signal) { - LocalInnerFunction(unwinder, unwind_through_signal); -} - -extern "C" void LocalOuterFunction(LocalUnwinder* unwinder, bool unwind_through_signal) { - LocalMiddleFunction(unwinder, unwind_through_signal); -} - -class LocalUnwinderTest : public ::testing::Test { - protected: - void SetUp() override { - unwinder_.reset(new LocalUnwinder); - ASSERT_TRUE(unwinder_->Init()); - } - - std::unique_ptr unwinder_; -}; - -TEST_F(LocalUnwinderTest, local) { - LocalOuterFunction(unwinder_.get(), false); -} - -TEST_F(LocalUnwinderTest, local_signal) { - LocalOuterFunction(unwinder_.get(), true); -} - -TEST_F(LocalUnwinderTest, local_multiple) { - ASSERT_NO_FATAL_FAILURE(LocalOuterFunction(unwinder_.get(), false)); - - ASSERT_NO_FATAL_FAILURE(LocalOuterFunction(unwinder_.get(), true)); - - ASSERT_NO_FATAL_FAILURE(LocalOuterFunction(unwinder_.get(), false)); - - ASSERT_NO_FATAL_FAILURE(LocalOuterFunction(unwinder_.get(), true)); -} - -// This test verifies that doing an unwind before and after a dlopen -// works. It's verifying that the maps read during the first unwind -// do not cause a problem when doing the unwind using the code in -// the dlopen'd code. -TEST_F(LocalUnwinderTest, unwind_after_dlopen) { - // Prime the maps data. - ASSERT_NO_FATAL_FAILURE(LocalOuterFunction(unwinder_.get(), false)); - - std::string testlib(testing::internal::GetArgvs()[0]); - auto const value = testlib.find_last_of('/'); - if (value != std::string::npos) { - testlib = testlib.substr(0, value + 1); - } else { - testlib = ""; - } - testlib += "libunwindstack_local.so"; - - void* handle = dlopen(testlib.c_str(), RTLD_NOW); - ASSERT_TRUE(handle != nullptr); - - void (*unwind_function)(void*, void*) = - reinterpret_cast(dlsym(handle, "TestlibLevel1")); - ASSERT_TRUE(unwind_function != nullptr); - - std::vector frame_info; - unwind_function(unwinder_.get(), &frame_info); - - ASSERT_EQ(0, dlclose(handle)); - - std::vector expected_function_names{"TestlibLevel1", "TestlibLevel2", - "TestlibLevel3", "TestlibLevel4"}; - - for (auto& frame : frame_info) { - if (frame.function_name == expected_function_names.back()) { - expected_function_names.pop_back(); - if (expected_function_names.empty()) { - break; - } - } - } - - ASSERT_TRUE(expected_function_names.empty()) << ErrorMsg(expected_function_names, frame_info); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/LocalUpdatableMapsTest.cpp b/libunwindstack/tests/LocalUpdatableMapsTest.cpp deleted file mode 100644 index 99afb0b23..000000000 --- a/libunwindstack/tests/LocalUpdatableMapsTest.cpp +++ /dev/null @@ -1,373 +0,0 @@ -/* - * 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. - */ - -#include -#include - -#include -#include - -#include - -#include -#include - -namespace unwindstack { - -class TestUpdatableMaps : public LocalUpdatableMaps { - public: - TestUpdatableMaps() : LocalUpdatableMaps() {} - virtual ~TestUpdatableMaps() = default; - - const std::string GetMapsFile() const override { return maps_file_; } - - void TestSetMapsFile(const std::string& maps_file) { maps_file_ = maps_file; } - - const std::vector>& TestGetSavedMaps() { return saved_maps_; } - - private: - std::string maps_file_; -}; - -class LocalUpdatableMapsTest : public ::testing::Test { - protected: - static const std::string GetDefaultMapString() { - return "3000-4000 r-xp 00000 00:00 0\n8000-9000 r-xp 00000 00:00 0\n"; - } - - void SetUp() override { - TemporaryFile tf; - ASSERT_TRUE(android::base::WriteStringToFile(GetDefaultMapString(), tf.path)); - - maps_.TestSetMapsFile(tf.path); - ASSERT_TRUE(maps_.Parse()); - ASSERT_EQ(2U, maps_.Total()); - - MapInfo* map_info = maps_.Get(0); - ASSERT_TRUE(map_info != nullptr); - EXPECT_EQ(0x3000U, map_info->start); - EXPECT_EQ(0x4000U, map_info->end); - EXPECT_EQ(0U, map_info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags); - EXPECT_TRUE(map_info->name.empty()); - - map_info = maps_.Get(1); - ASSERT_TRUE(map_info != nullptr); - EXPECT_EQ(0x8000U, map_info->start); - EXPECT_EQ(0x9000U, map_info->end); - EXPECT_EQ(0U, map_info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags); - EXPECT_TRUE(map_info->name.empty()); - } - - TestUpdatableMaps maps_; -}; - -TEST_F(LocalUpdatableMapsTest, same_map) { - TemporaryFile tf; - ASSERT_TRUE(android::base::WriteStringToFile(GetDefaultMapString(), tf.path)); - - maps_.TestSetMapsFile(tf.path); - ASSERT_TRUE(maps_.Reparse()); - ASSERT_EQ(2U, maps_.Total()); - EXPECT_EQ(0U, maps_.TestGetSavedMaps().size()); - - MapInfo* map_info = maps_.Get(0); - ASSERT_TRUE(map_info != nullptr); - EXPECT_EQ(0x3000U, map_info->start); - EXPECT_EQ(0x4000U, map_info->end); - EXPECT_EQ(0U, map_info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags); - EXPECT_TRUE(map_info->name.empty()); - - map_info = maps_.Get(1); - ASSERT_TRUE(map_info != nullptr); - EXPECT_EQ(0x8000U, map_info->start); - EXPECT_EQ(0x9000U, map_info->end); - EXPECT_EQ(0U, map_info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags); - EXPECT_TRUE(map_info->name.empty()); -} - -TEST_F(LocalUpdatableMapsTest, same_map_new_perms) { - TemporaryFile tf; - ASSERT_TRUE( - android::base::WriteStringToFile("3000-4000 rwxp 00000 00:00 0\n" - "8000-9000 r-xp 00000 00:00 0\n", - tf.path)); - - maps_.TestSetMapsFile(tf.path); - ASSERT_TRUE(maps_.Reparse()); - ASSERT_EQ(2U, maps_.Total()); - - MapInfo* map_info = maps_.Get(0); - ASSERT_TRUE(map_info != nullptr); - EXPECT_EQ(0x3000U, map_info->start); - EXPECT_EQ(0x4000U, map_info->end); - EXPECT_EQ(0U, map_info->offset); - EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, map_info->flags); - EXPECT_TRUE(map_info->name.empty()); - - map_info = maps_.Get(1); - ASSERT_TRUE(map_info != nullptr); - EXPECT_EQ(0x8000U, map_info->start); - EXPECT_EQ(0x9000U, map_info->end); - EXPECT_EQ(0U, map_info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags); - EXPECT_TRUE(map_info->name.empty()); - - auto& saved_maps = maps_.TestGetSavedMaps(); - ASSERT_EQ(1U, saved_maps.size()); - map_info = saved_maps[0].get(); - ASSERT_TRUE(map_info != nullptr); - EXPECT_EQ(0x3000U, map_info->start); - EXPECT_EQ(0x4000U, map_info->end); - EXPECT_EQ(0U, map_info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags); - EXPECT_TRUE(map_info->name.empty()); -} - -TEST_F(LocalUpdatableMapsTest, same_map_new_name) { - TemporaryFile tf; - ASSERT_TRUE( - android::base::WriteStringToFile("3000-4000 r-xp 00000 00:00 0 /fake/lib.so\n" - "8000-9000 r-xp 00000 00:00 0\n", - tf.path)); - - maps_.TestSetMapsFile(tf.path); - ASSERT_TRUE(maps_.Reparse()); - ASSERT_EQ(2U, maps_.Total()); - - MapInfo* map_info = maps_.Get(0); - ASSERT_TRUE(map_info != nullptr); - EXPECT_EQ(0x3000U, map_info->start); - EXPECT_EQ(0x4000U, map_info->end); - EXPECT_EQ(0U, map_info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags); - EXPECT_EQ("/fake/lib.so", map_info->name); - - map_info = maps_.Get(1); - ASSERT_TRUE(map_info != nullptr); - EXPECT_EQ(0x8000U, map_info->start); - EXPECT_EQ(0x9000U, map_info->end); - EXPECT_EQ(0U, map_info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags); - EXPECT_TRUE(map_info->name.empty()); - - auto& saved_maps = maps_.TestGetSavedMaps(); - ASSERT_EQ(1U, saved_maps.size()); - map_info = saved_maps[0].get(); - ASSERT_TRUE(map_info != nullptr); - EXPECT_EQ(0x3000U, map_info->start); - EXPECT_EQ(0x4000U, map_info->end); - EXPECT_EQ(0U, map_info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags); - EXPECT_TRUE(map_info->name.empty()); -} - -TEST_F(LocalUpdatableMapsTest, only_add_maps) { - TemporaryFile tf; - ASSERT_TRUE( - android::base::WriteStringToFile("1000-2000 r-xp 00000 00:00 0\n" - "3000-4000 r-xp 00000 00:00 0\n" - "8000-9000 r-xp 00000 00:00 0\n" - "a000-f000 r-xp 00000 00:00 0\n", - tf.path)); - - maps_.TestSetMapsFile(tf.path); - ASSERT_TRUE(maps_.Reparse()); - ASSERT_EQ(4U, maps_.Total()); - EXPECT_EQ(0U, maps_.TestGetSavedMaps().size()); - - MapInfo* map_info = maps_.Get(0); - ASSERT_TRUE(map_info != nullptr); - EXPECT_EQ(0x1000U, map_info->start); - EXPECT_EQ(0x2000U, map_info->end); - EXPECT_EQ(0U, map_info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags); - EXPECT_TRUE(map_info->name.empty()); - - map_info = maps_.Get(1); - ASSERT_TRUE(map_info != nullptr); - EXPECT_EQ(0x3000U, map_info->start); - EXPECT_EQ(0x4000U, map_info->end); - EXPECT_EQ(0U, map_info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags); - EXPECT_TRUE(map_info->name.empty()); - - map_info = maps_.Get(2); - ASSERT_TRUE(map_info != nullptr); - EXPECT_EQ(0x8000U, map_info->start); - EXPECT_EQ(0x9000U, map_info->end); - EXPECT_EQ(0U, map_info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags); - EXPECT_TRUE(map_info->name.empty()); - - map_info = maps_.Get(3); - ASSERT_TRUE(map_info != nullptr); - EXPECT_EQ(0xa000U, map_info->start); - EXPECT_EQ(0xf000U, map_info->end); - EXPECT_EQ(0U, map_info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags); - EXPECT_TRUE(map_info->name.empty()); -} - -TEST_F(LocalUpdatableMapsTest, all_new_maps) { - TemporaryFile tf; - ASSERT_TRUE( - android::base::WriteStringToFile("1000-2000 r-xp 00000 00:00 0\n" - "a000-f000 r-xp 00000 00:00 0\n", - tf.path)); - - maps_.TestSetMapsFile(tf.path); - ASSERT_TRUE(maps_.Reparse()); - ASSERT_EQ(2U, maps_.Total()); - - MapInfo* map_info = maps_.Get(0); - ASSERT_TRUE(map_info != nullptr); - EXPECT_EQ(0x1000U, map_info->start); - EXPECT_EQ(0x2000U, map_info->end); - EXPECT_EQ(0U, map_info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags); - EXPECT_TRUE(map_info->name.empty()); - - map_info = maps_.Get(1); - ASSERT_TRUE(map_info != nullptr); - EXPECT_EQ(0xa000U, map_info->start); - EXPECT_EQ(0xf000U, map_info->end); - EXPECT_EQ(0U, map_info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags); - EXPECT_TRUE(map_info->name.empty()); - - auto& saved_maps = maps_.TestGetSavedMaps(); - ASSERT_EQ(2U, saved_maps.size()); - map_info = saved_maps[0].get(); - ASSERT_TRUE(map_info != nullptr); - EXPECT_EQ(0x3000U, map_info->start); - EXPECT_EQ(0x4000U, map_info->end); - EXPECT_EQ(0U, map_info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags); - EXPECT_TRUE(map_info->name.empty()); - - map_info = saved_maps[1].get(); - ASSERT_TRUE(map_info != nullptr); - EXPECT_EQ(0x8000U, map_info->start); - EXPECT_EQ(0x9000U, map_info->end); - EXPECT_EQ(0U, map_info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags); - EXPECT_TRUE(map_info->name.empty()); -} - -TEST_F(LocalUpdatableMapsTest, add_map_prev_name_updated) { - TemporaryFile tf; - ASSERT_TRUE( - android::base::WriteStringToFile("3000-4000 rwxp 00000 00:00 0\n" - "8000-9000 r-xp 00000 00:00 0\n" - "9000-a000 r-xp 00000 00:00 0\n", - tf.path)); - - maps_.TestSetMapsFile(tf.path); - ASSERT_TRUE(maps_.Reparse()); - ASSERT_EQ(3U, maps_.Total()); - - MapInfo* map_info = maps_.Get(2); - ASSERT_TRUE(map_info != nullptr); - EXPECT_EQ(0x9000U, map_info->start); - EXPECT_EQ(0xA000U, map_info->end); - EXPECT_EQ(0U, map_info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags); - EXPECT_TRUE(map_info->name.empty()); - EXPECT_EQ(maps_.Get(1), map_info->prev_map); -} - -TEST_F(LocalUpdatableMapsTest, add_map_prev_real_name_updated) { - TemporaryFile tf; - ASSERT_TRUE( - android::base::WriteStringToFile("3000-4000 r-xp 00000 00:00 0 /fake/lib.so\n" - "4000-5000 ---p 00000 00:00 0\n" - "7000-8000 r-xp 00000 00:00 0 /fake/lib1.so\n" - "8000-9000 ---p 00000 00:00 0\n", - tf.path)); - - maps_.TestSetMapsFile(tf.path); - ASSERT_TRUE(maps_.Reparse()); - ASSERT_EQ(4U, maps_.Total()); - - MapInfo* map_info = maps_.Get(2); - ASSERT_TRUE(map_info != nullptr); - EXPECT_EQ(0x7000U, map_info->start); - EXPECT_EQ(0x8000U, map_info->end); - EXPECT_EQ(0U, map_info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags); - EXPECT_EQ(maps_.Get(0), map_info->prev_real_map); - EXPECT_EQ(maps_.Get(1), map_info->prev_map); - EXPECT_EQ("/fake/lib1.so", map_info->name); - - map_info = maps_.Get(3); - ASSERT_TRUE(map_info != nullptr); - EXPECT_EQ(0x8000U, map_info->start); - EXPECT_EQ(0x9000U, map_info->end); - EXPECT_EQ(0U, map_info->offset); - EXPECT_TRUE(map_info->IsBlank()); - EXPECT_EQ(maps_.Get(2), map_info->prev_real_map); - EXPECT_EQ(maps_.Get(2), map_info->prev_map); - EXPECT_TRUE(map_info->name.empty()); - - ASSERT_TRUE( - android::base::WriteStringToFile("3000-4000 r-xp 00000 00:00 0 /fake/lib.so\n" - "4000-5000 ---p 00000 00:00 0\n" - "7000-8000 r-xp 00000 00:00 0 /fake/lib1.so\n" - "8000-9000 ---p 00000 00:00 0\n" - "9000-a000 r-xp 00000 00:00 0 /fake/lib2.so\n" - "a000-b000 r-xp 00000 00:00 0 /fake/lib3.so\n", - tf.path)); - - maps_.TestSetMapsFile(tf.path); - ASSERT_TRUE(maps_.Reparse()); - ASSERT_EQ(6U, maps_.Total()); - - map_info = maps_.Get(2); - ASSERT_TRUE(map_info != nullptr); - EXPECT_EQ(0x7000U, map_info->start); - EXPECT_EQ(0x8000U, map_info->end); - EXPECT_EQ(0U, map_info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags); - EXPECT_EQ("/fake/lib1.so", map_info->name); - EXPECT_EQ(maps_.Get(1), map_info->prev_map); - EXPECT_EQ(maps_.Get(0), map_info->prev_real_map); - - map_info = maps_.Get(4); - ASSERT_TRUE(map_info != nullptr); - EXPECT_EQ(0x9000U, map_info->start); - EXPECT_EQ(0xA000U, map_info->end); - EXPECT_EQ(0U, map_info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags); - EXPECT_EQ("/fake/lib2.so", map_info->name); - EXPECT_EQ(maps_.Get(3), map_info->prev_map); - EXPECT_EQ(maps_.Get(2), map_info->prev_real_map); - - map_info = maps_.Get(5); - ASSERT_TRUE(map_info != nullptr); - EXPECT_EQ(0xA000U, map_info->start); - EXPECT_EQ(0xB000U, map_info->end); - EXPECT_EQ(0U, map_info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags); - EXPECT_EQ("/fake/lib3.so", map_info->name); - EXPECT_EQ(maps_.Get(4), map_info->prev_map); - EXPECT_EQ(maps_.Get(4), map_info->prev_real_map); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/LogFake.cpp b/libunwindstack/tests/LogFake.cpp deleted file mode 100644 index 537ccafb3..000000000 --- a/libunwindstack/tests/LogFake.cpp +++ /dev/null @@ -1,105 +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 "LogFake.h" - -// Forward declarations. -struct EventTagMap; -struct AndroidLogEntry; - -std::string g_fake_log_buf; - -std::string g_fake_log_print; - -namespace unwindstack { - -void ResetLogs() { - g_fake_log_buf = ""; - g_fake_log_print = ""; -} - -std::string GetFakeLogBuf() { - return g_fake_log_buf; -} - -std::string GetFakeLogPrint() { - return g_fake_log_print; -} - -} // namespace unwindstack - -extern "C" int __android_log_buf_write(int bufId, int prio, const char* tag, const char* msg) { - g_fake_log_buf += std::to_string(bufId) + ' ' + std::to_string(prio) + ' '; - g_fake_log_buf += tag; - g_fake_log_buf += ' '; - g_fake_log_buf += msg; - return 1; -} - -extern "C" int __android_log_print(int prio, const char* tag, const char* fmt, ...) { - va_list ap; - va_start(ap, fmt); - int val = __android_log_vprint(prio, tag, fmt, ap); - va_end(ap); - - return val; -} - -extern "C" int __android_log_vprint(int prio, const char* tag, const char* fmt, va_list ap) { - g_fake_log_print += std::to_string(prio) + ' '; - g_fake_log_print += tag; - g_fake_log_print += ' '; - - android::base::StringAppendV(&g_fake_log_print, fmt, ap); - - g_fake_log_print += '\n'; - - return 1; -} - -extern "C" log_id_t android_name_to_log_id(const char*) { - return LOG_ID_SYSTEM; -} - -extern "C" struct logger_list* android_logger_list_open(log_id_t, int, unsigned int, pid_t) { - errno = EACCES; - return nullptr; -} - -extern "C" int android_logger_list_read(struct logger_list*, struct log_msg*) { - return 0; -} - -extern "C" EventTagMap* android_openEventTagMap(const char*) { - return nullptr; -} - -extern "C" int android_log_processBinaryLogBuffer( - struct logger_entry*, - AndroidLogEntry*, const EventTagMap*, char*, int) { - return 0; -} - -extern "C" void android_logger_list_free(struct logger_list*) { -} diff --git a/libunwindstack/tests/LogFake.h b/libunwindstack/tests/LogFake.h deleted file mode 100644 index e1dc50d9c..000000000 --- a/libunwindstack/tests/LogFake.h +++ /dev/null @@ -1,30 +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. - */ - -#ifndef _LIBUNWINDSTACK_TESTS_LOG_FAKE_H -#define _LIBUNWINDSTACK_TESTS_LOG_FAKE_H - -#include - -namespace unwindstack { - -void ResetLogs(); -std::string GetFakeLogBuf(); -std::string GetFakeLogPrint(); - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_TESTS_LOG_FAKE_H diff --git a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp deleted file mode 100644 index 6d8d58e55..000000000 --- a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Copyright (C) 2016 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 "ElfTestUtils.h" -#include "MemoryFake.h" - -namespace unwindstack { - -class MapInfoCreateMemoryTest : public ::testing::Test { - protected: - template - static void InitElf(int fd, uint64_t file_offset, uint64_t sh_offset, uint8_t class_type) { - std::vector buffer(20000); - memset(buffer.data(), 0, buffer.size()); - - Ehdr ehdr; - memset(&ehdr, 0, sizeof(ehdr)); - memcpy(ehdr.e_ident, ELFMAG, SELFMAG); - ehdr.e_ident[EI_CLASS] = class_type; - ehdr.e_shoff = sh_offset; - ehdr.e_shentsize = sizeof(Shdr) + 100; - ehdr.e_shnum = 4; - memcpy(&buffer[file_offset], &ehdr, sizeof(ehdr)); - - ASSERT_TRUE(android::base::WriteFully(fd, buffer.data(), buffer.size())); - } - - void SetUp() override { - std::vector buffer(12288, 0); - memcpy(buffer.data(), ELFMAG, SELFMAG); - buffer[EI_CLASS] = ELFCLASS32; - ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), 1024)); - - memset(buffer.data(), 0, buffer.size()); - memcpy(&buffer[0x1000], ELFMAG, SELFMAG); - buffer[0x1000 + EI_CLASS] = ELFCLASS64; - buffer[0x2000] = 0xff; - ASSERT_TRUE(android::base::WriteFully(elf_at_1000_.fd, buffer.data(), buffer.size())); - - InitElf(elf32_at_map_.fd, 0x1000, 0x2000, ELFCLASS32); - InitElf(elf64_at_map_.fd, 0x2000, 0x3000, ELFCLASS64); - - memory_ = new MemoryFake; - process_memory_.reset(memory_); - } - - MemoryFake* memory_; - std::shared_ptr process_memory_; - - TemporaryFile elf_; - - TemporaryFile elf_at_1000_; - - TemporaryFile elf32_at_map_; - TemporaryFile elf64_at_map_; -}; - -TEST_F(MapInfoCreateMemoryTest, end_le_start) { - MapInfo info(nullptr, nullptr, 0x100, 0x100, 0, 0, elf_.path); - - std::unique_ptr memory(info.CreateMemory(process_memory_)); - ASSERT_TRUE(memory.get() == nullptr); - - info.end = 0xff; - memory.reset(info.CreateMemory(process_memory_)); - ASSERT_TRUE(memory.get() == nullptr); - - // Make sure this test is valid. - info.end = 0x101; - memory.reset(info.CreateMemory(process_memory_)); - ASSERT_TRUE(memory.get() != nullptr); - EXPECT_FALSE(info.memory_backed_elf); -} - -// Verify that if the offset is non-zero but there is no elf at the offset, -// that the full file is used. -TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_full_file) { - MapInfo info(nullptr, nullptr, 0x100, 0x200, 0x100, 0, elf_.path); - - std::unique_ptr memory(info.CreateMemory(process_memory_)); - ASSERT_TRUE(memory.get() != nullptr); - EXPECT_FALSE(info.memory_backed_elf); - ASSERT_EQ(0x100U, info.elf_offset); - EXPECT_EQ(0x100U, info.elf_start_offset); - - // Read the entire file. - std::vector buffer(1024); - ASSERT_TRUE(memory->ReadFully(0, buffer.data(), 1024)); - ASSERT_TRUE(memcmp(buffer.data(), ELFMAG, SELFMAG) == 0); - ASSERT_EQ(ELFCLASS32, buffer[EI_CLASS]); - for (size_t i = EI_CLASS + 1; i < buffer.size(); i++) { - ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i; - } - - ASSERT_FALSE(memory->ReadFully(1024, buffer.data(), 1)); - - // Now verify the elf start offset is set correctly based on the previous - // info. - MapInfo prev_info(nullptr, nullptr, 0, 0x100, 0x10, 0, ""); - info.prev_map = &prev_info; - info.prev_real_map = &prev_info; - - // No preconditions met, change each one until it should set the elf start - // offset to zero. - info.elf_offset = 0; - info.elf_start_offset = 0; - info.memory_backed_elf = false; - memory.reset(info.CreateMemory(process_memory_)); - ASSERT_TRUE(memory.get() != nullptr); - EXPECT_FALSE(info.memory_backed_elf); - ASSERT_EQ(0x100U, info.elf_offset); - EXPECT_EQ(0x100U, info.elf_start_offset); - - prev_info.offset = 0; - info.elf_offset = 0; - info.elf_start_offset = 0; - info.memory_backed_elf = false; - memory.reset(info.CreateMemory(process_memory_)); - ASSERT_TRUE(memory.get() != nullptr); - EXPECT_FALSE(info.memory_backed_elf); - ASSERT_EQ(0x100U, info.elf_offset); - EXPECT_EQ(0x100U, info.elf_start_offset); - - prev_info.flags = PROT_READ; - info.elf_offset = 0; - info.elf_start_offset = 0; - info.memory_backed_elf = false; - memory.reset(info.CreateMemory(process_memory_)); - ASSERT_TRUE(memory.get() != nullptr); - EXPECT_FALSE(info.memory_backed_elf); - ASSERT_EQ(0x100U, info.elf_offset); - EXPECT_EQ(0x100U, info.elf_start_offset); - - prev_info.name = info.name; - info.elf_offset = 0; - info.elf_start_offset = 0; - info.memory_backed_elf = false; - memory.reset(info.CreateMemory(process_memory_)); - ASSERT_TRUE(memory.get() != nullptr); - EXPECT_FALSE(info.memory_backed_elf); - ASSERT_EQ(0x100U, info.elf_offset); - EXPECT_EQ(0U, info.elf_start_offset); -} - -// Verify that if the offset is non-zero and there is an elf at that -// offset, that only part of the file is used. -TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file) { - MapInfo info(nullptr, nullptr, 0x100, 0x200, 0x1000, 0, elf_at_1000_.path); - - std::unique_ptr memory(info.CreateMemory(process_memory_)); - ASSERT_TRUE(memory.get() != nullptr); - EXPECT_FALSE(info.memory_backed_elf); - ASSERT_EQ(0U, info.elf_offset); - EXPECT_EQ(0x1000U, info.elf_start_offset); - - // Read the valid part of the file. - std::vector buffer(0x100); - ASSERT_TRUE(memory->ReadFully(0, buffer.data(), 0x100)); - ASSERT_TRUE(memcmp(buffer.data(), ELFMAG, SELFMAG) == 0); - ASSERT_EQ(ELFCLASS64, buffer[EI_CLASS]); - for (size_t i = EI_CLASS + 1; i < buffer.size(); i++) { - ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i; - } - - ASSERT_FALSE(memory->ReadFully(0x100, buffer.data(), 1)); -} - -// Verify that if the offset is non-zero and there is an elf at that -// offset, that only part of the file is used. Further verify that if the -// embedded elf is bigger than the initial map, the new object is larger -// than the original map size. Do this for a 32 bit elf and a 64 bit elf. -TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf32) { - MapInfo info(nullptr, nullptr, 0x5000, 0x6000, 0x1000, 0, elf32_at_map_.path); - - std::unique_ptr memory(info.CreateMemory(process_memory_)); - ASSERT_TRUE(memory.get() != nullptr); - EXPECT_FALSE(info.memory_backed_elf); - ASSERT_EQ(0U, info.elf_offset); - EXPECT_EQ(0x1000U, info.elf_start_offset); - - // Verify the memory is a valid elf. - uint8_t e_ident[SELFMAG + 1]; - ASSERT_TRUE(memory->ReadFully(0, e_ident, SELFMAG)); - ASSERT_EQ(0, memcmp(e_ident, ELFMAG, SELFMAG)); - - // Read past the end of what would normally be the size of the map. - ASSERT_TRUE(memory->ReadFully(0x1000, e_ident, 1)); -} - -TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf64) { - MapInfo info(nullptr, nullptr, 0x7000, 0x8000, 0x2000, 0, elf64_at_map_.path); - - std::unique_ptr memory(info.CreateMemory(process_memory_)); - ASSERT_TRUE(memory.get() != nullptr); - EXPECT_FALSE(info.memory_backed_elf); - ASSERT_EQ(0U, info.elf_offset); - EXPECT_EQ(0x2000U, info.elf_start_offset); - - // Verify the memory is a valid elf. - uint8_t e_ident[SELFMAG + 1]; - ASSERT_TRUE(memory->ReadFully(0, e_ident, SELFMAG)); - ASSERT_EQ(0, memcmp(e_ident, ELFMAG, SELFMAG)); - - // Read past the end of what would normally be the size of the map. - ASSERT_TRUE(memory->ReadFully(0x1000, e_ident, 1)); -} - -// Verify that device file names will never result in Memory object creation. -TEST_F(MapInfoCreateMemoryTest, check_device_maps) { - // Set up some memory so that a valid local memory object would - // be returned if the file mapping fails, but the device check is incorrect. - std::vector buffer(1024); - uint64_t start = reinterpret_cast(buffer.data()); - MapInfo info(nullptr, nullptr, start, start + buffer.size(), 0, 0x8000, "/dev/something"); - - std::unique_ptr memory(info.CreateMemory(process_memory_)); - ASSERT_TRUE(memory.get() == nullptr); -} - -TEST_F(MapInfoCreateMemoryTest, process_memory) { - MapInfo info(nullptr, nullptr, 0x2000, 0x3000, 0, PROT_READ, ""); - - Elf32_Ehdr ehdr = {}; - TestInitEhdr(&ehdr, ELFCLASS32, EM_ARM); - std::vector buffer(1024); - memcpy(buffer.data(), &ehdr, sizeof(ehdr)); - - // Verify that the the process_memory object is used, so seed it - // with memory. - for (size_t i = sizeof(ehdr); i < buffer.size(); i++) { - buffer[i] = i % 256; - } - memory_->SetMemory(info.start, buffer.data(), buffer.size()); - - std::unique_ptr memory(info.CreateMemory(process_memory_)); - ASSERT_TRUE(memory.get() != nullptr); - EXPECT_TRUE(info.memory_backed_elf); - - memset(buffer.data(), 0, buffer.size()); - ASSERT_TRUE(memory->ReadFully(0, buffer.data(), buffer.size())); - ASSERT_EQ(0, memcmp(&ehdr, buffer.data(), sizeof(ehdr))); - for (size_t i = sizeof(ehdr); i < buffer.size(); i++) { - ASSERT_EQ(i % 256, buffer[i]) << "Failed at byte " << i; - } - - // Try to read outside of the map size. - ASSERT_FALSE(memory->ReadFully(buffer.size(), buffer.data(), 1)); -} - -TEST_F(MapInfoCreateMemoryTest, valid_rosegment_zero_offset) { - Maps maps; - maps.Add(0x500, 0x600, 0, PROT_READ, "something_else", 0); - maps.Add(0x1000, 0x2600, 0, PROT_READ, "/only/in/memory.so", 0); - maps.Add(0x3000, 0x5000, 0x4000, PROT_READ | PROT_EXEC, "/only/in/memory.so", 0); - - Elf32_Ehdr ehdr = {}; - TestInitEhdr(&ehdr, ELFCLASS32, EM_ARM); - memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr)); - memory_->SetMemoryBlock(0x1000 + sizeof(ehdr), 0x1600 - sizeof(ehdr), 0xab); - - // Set the memory in the r-x map. - memory_->SetMemoryBlock(0x3000, 0x2000, 0x5d); - - MapInfo* map_info = maps.Find(0x3000); - ASSERT_TRUE(map_info != nullptr); - - std::unique_ptr mem(map_info->CreateMemory(process_memory_)); - ASSERT_TRUE(mem.get() != nullptr); - EXPECT_TRUE(map_info->memory_backed_elf); - EXPECT_EQ(0x4000UL, map_info->elf_offset); - EXPECT_EQ(0x4000UL, map_info->offset); - EXPECT_EQ(0U, map_info->elf_start_offset); - - // Verify that reading values from this memory works properly. - std::vector buffer(0x4000); - size_t bytes = mem->Read(0, buffer.data(), buffer.size()); - ASSERT_EQ(0x1600UL, bytes); - ASSERT_EQ(0, memcmp(&ehdr, buffer.data(), sizeof(ehdr))); - for (size_t i = sizeof(ehdr); i < bytes; i++) { - ASSERT_EQ(0xab, buffer[i]) << "Failed at byte " << i; - } - - bytes = mem->Read(0x4000, buffer.data(), buffer.size()); - ASSERT_EQ(0x2000UL, bytes); - for (size_t i = 0; i < bytes; i++) { - ASSERT_EQ(0x5d, buffer[i]) << "Failed at byte " << i; - } -} - -TEST_F(MapInfoCreateMemoryTest, valid_rosegment_non_zero_offset) { - Maps maps; - maps.Add(0x500, 0x600, 0, PROT_READ, "something_else", 0); - maps.Add(0x1000, 0x2000, 0, PROT_READ, "/only/in/memory.apk", 0); - maps.Add(0x2000, 0x3000, 0x1000, PROT_READ | PROT_EXEC, "/only/in/memory.apk", 0); - maps.Add(0x3000, 0x4000, 0xa000, PROT_READ, "/only/in/memory.apk", 0); - maps.Add(0x4000, 0x5000, 0xb000, PROT_READ | PROT_EXEC, "/only/in/memory.apk", 0); - - Elf32_Ehdr ehdr = {}; - TestInitEhdr(&ehdr, ELFCLASS32, EM_ARM); - - // Setup an elf at offset 0x1000 in memory. - memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr)); - memory_->SetMemoryBlock(0x1000 + sizeof(ehdr), 0x2000 - sizeof(ehdr), 0x12); - memory_->SetMemoryBlock(0x2000, 0x1000, 0x23); - - // Setup an elf at offset 0x3000 in memory.. - memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr)); - memory_->SetMemoryBlock(0x3000 + sizeof(ehdr), 0x4000 - sizeof(ehdr), 0x34); - memory_->SetMemoryBlock(0x4000, 0x1000, 0x43); - - MapInfo* map_info = maps.Find(0x4000); - ASSERT_TRUE(map_info != nullptr); - - std::unique_ptr mem(map_info->CreateMemory(process_memory_)); - ASSERT_TRUE(mem.get() != nullptr); - EXPECT_TRUE(map_info->memory_backed_elf); - EXPECT_EQ(0x1000UL, map_info->elf_offset); - EXPECT_EQ(0xb000UL, map_info->offset); - EXPECT_EQ(0xa000UL, map_info->elf_start_offset); - - // Verify that reading values from this memory works properly. - std::vector buffer(0x4000); - size_t bytes = mem->Read(0, buffer.data(), buffer.size()); - ASSERT_EQ(0x1000UL, bytes); - ASSERT_EQ(0, memcmp(&ehdr, buffer.data(), sizeof(ehdr))); - for (size_t i = sizeof(ehdr); i < bytes; i++) { - ASSERT_EQ(0x34, buffer[i]) << "Failed at byte " << i; - } - - bytes = mem->Read(0x1000, buffer.data(), buffer.size()); - ASSERT_EQ(0x1000UL, bytes); - for (size_t i = 0; i < bytes; i++) { - ASSERT_EQ(0x43, buffer[i]) << "Failed at byte " << i; - } -} - -TEST_F(MapInfoCreateMemoryTest, rosegment_from_file) { - Maps maps; - maps.Add(0x500, 0x600, 0, PROT_READ, "something_else", 0); - maps.Add(0x1000, 0x2000, 0x1000, PROT_READ, elf_at_1000_.path, 0); - maps.Add(0x2000, 0x3000, 0x2000, PROT_READ | PROT_EXEC, elf_at_1000_.path, 0); - - MapInfo* map_info = maps.Find(0x2000); - ASSERT_TRUE(map_info != nullptr); - - // Set up the size - Elf64_Ehdr ehdr; - ASSERT_EQ(0x1000, lseek(elf_at_1000_.fd, 0x1000, SEEK_SET)); - ASSERT_TRUE(android::base::ReadFully(elf_at_1000_.fd, &ehdr, sizeof(ehdr))); - - // Will not give the elf memory, because the read-only entry does not - // extend over the executable segment. - std::unique_ptr memory(map_info->CreateMemory(process_memory_)); - ASSERT_TRUE(memory.get() != nullptr); - EXPECT_FALSE(map_info->memory_backed_elf); - std::vector buffer(0x100); - EXPECT_EQ(0x2000U, map_info->offset); - EXPECT_EQ(0U, map_info->elf_offset); - EXPECT_EQ(0U, map_info->elf_start_offset); - ASSERT_TRUE(memory->ReadFully(0, buffer.data(), 0x100)); - EXPECT_EQ(0xffU, buffer[0]); - - // Now init the elf data enough so that the file memory object will be used. - ehdr.e_shoff = 0x4000; - ehdr.e_shnum = 1; - ehdr.e_shentsize = 0x100; - ASSERT_EQ(0x1000, lseek(elf_at_1000_.fd, 0x1000, SEEK_SET)); - ASSERT_TRUE(android::base::WriteFully(elf_at_1000_.fd, &ehdr, sizeof(ehdr))); - - map_info->memory_backed_elf = false; - memory.reset(map_info->CreateMemory(process_memory_)); - EXPECT_FALSE(map_info->memory_backed_elf); - EXPECT_EQ(0x2000U, map_info->offset); - EXPECT_EQ(0x1000U, map_info->elf_offset); - EXPECT_EQ(0x1000U, map_info->elf_start_offset); - Elf64_Ehdr ehdr_mem; - ASSERT_TRUE(memory->ReadFully(0, &ehdr_mem, sizeof(ehdr_mem))); - EXPECT_TRUE(memcmp(&ehdr, &ehdr_mem, sizeof(ehdr)) == 0); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/MapInfoGetBuildIDTest.cpp b/libunwindstack/tests/MapInfoGetBuildIDTest.cpp deleted file mode 100644 index 70e136bce..000000000 --- a/libunwindstack/tests/MapInfoGetBuildIDTest.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* - * 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. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include - -#include "ElfFake.h" -#include "ElfTestUtils.h" -#include "MemoryFake.h" - -namespace unwindstack { - -class MapInfoGetBuildIDTest : public ::testing::Test { - protected: - void SetUp() override { - tf_.reset(new TemporaryFile); - - memory_ = new MemoryFake; - elf_ = new ElfFake(new MemoryFake); - elf_interface_ = new ElfInterfaceFake(memory_); - elf_->FakeSetInterface(elf_interface_); - elf_container_.reset(elf_); - map_info_.reset( - new MapInfo(nullptr, nullptr, 0x1000, 0x20000, 0, PROT_READ | PROT_WRITE, tf_->path)); - } - - void MultipleThreadTest(std::string expected_build_id); - - MemoryFake* memory_; - ElfFake* elf_; - ElfInterfaceFake* elf_interface_; - std::unique_ptr elf_container_; - std::unique_ptr map_info_; - std::unique_ptr tf_; -}; - -TEST_F(MapInfoGetBuildIDTest, no_elf_and_no_valid_elf_in_memory) { - MapInfo info(nullptr, nullptr, 0x1000, 0x2000, 0, PROT_READ, ""); - - EXPECT_EQ("", info.GetBuildID()); - EXPECT_EQ("", info.GetPrintableBuildID()); -} - -TEST_F(MapInfoGetBuildIDTest, from_elf) { - map_info_->elf.reset(elf_container_.release()); - elf_interface_->FakeSetBuildID("FAKE_BUILD_ID"); - - EXPECT_EQ("FAKE_BUILD_ID", map_info_->GetBuildID()); - EXPECT_EQ("46414b455f4255494c445f4944", map_info_->GetPrintableBuildID()); -} - -TEST_F(MapInfoGetBuildIDTest, from_elf_no_sign_extension) { - map_info_->elf.reset(elf_container_.release()); - - std::string build_id = {static_cast(0xfa), static_cast(0xab), static_cast(0x12), - static_cast(0x02)}; - elf_interface_->FakeSetBuildID(build_id); - - EXPECT_EQ("\xFA\xAB\x12\x2", map_info_->GetBuildID()); - EXPECT_EQ("faab1202", map_info_->GetPrintableBuildID()); -} - -void MapInfoGetBuildIDTest::MultipleThreadTest(std::string expected_build_id) { - static constexpr size_t kNumConcurrentThreads = 100; - - std::string build_id_values[kNumConcurrentThreads]; - std::vector threads; - - std::atomic_bool wait; - wait = true; - // Create all of the threads and have them do the GetLoadBias at the same time - // to make it likely that a race will occur. - for (size_t i = 0; i < kNumConcurrentThreads; i++) { - std::thread* thread = new std::thread([i, this, &wait, &build_id_values]() { - while (wait) - ; - build_id_values[i] = map_info_->GetBuildID(); - }); - threads.push_back(thread); - } - - // Set them all going and wait for the threads to finish. - wait = false; - for (auto thread : threads) { - thread->join(); - delete thread; - } - - // Now verify that all of the elf files are exactly the same and valid. - for (size_t i = 0; i < kNumConcurrentThreads; i++) { - EXPECT_EQ(expected_build_id, build_id_values[i]) << "Thread " << i << " mismatched."; - } -} - -TEST_F(MapInfoGetBuildIDTest, multiple_thread_elf_exists) { - map_info_->elf.reset(elf_container_.release()); - elf_interface_->FakeSetBuildID("FAKE_BUILD_ID"); - - MultipleThreadTest("FAKE_BUILD_ID"); -} - -static void InitElfData(int fd) { - Elf32_Ehdr ehdr; - TestInitEhdr(&ehdr, ELFCLASS32, EM_ARM); - ehdr.e_shoff = 0x2000; - ehdr.e_shnum = 3; - ehdr.e_shentsize = sizeof(Elf32_Shdr); - ehdr.e_shstrndx = 2; - off_t offset = 0; - ASSERT_EQ(offset, lseek(fd, offset, SEEK_SET)); - ASSERT_EQ(static_cast(sizeof(ehdr)), write(fd, &ehdr, sizeof(ehdr))); - - char note_section[128]; - Elf32_Nhdr note_header = {}; - note_header.n_namesz = sizeof("GNU"); - note_header.n_descsz = sizeof("ELF_BUILDID") - 1; - note_header.n_type = NT_GNU_BUILD_ID; - memcpy(¬e_section, ¬e_header, sizeof(note_header)); - size_t note_offset = sizeof(note_header); - memcpy(¬e_section[note_offset], "GNU", note_header.n_namesz); - note_offset += note_header.n_namesz; - memcpy(¬e_section[note_offset], "ELF_BUILDID", note_header.n_descsz); - - Elf32_Shdr shdr = {}; - shdr.sh_type = SHT_NOTE; - shdr.sh_name = 0x500; - shdr.sh_offset = 0xb000; - shdr.sh_size = sizeof(note_section); - offset += ehdr.e_shoff + sizeof(shdr); - ASSERT_EQ(offset, lseek(fd, offset, SEEK_SET)); - ASSERT_EQ(static_cast(sizeof(shdr)), write(fd, &shdr, sizeof(shdr))); - - // The string data for section header names. - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_STRTAB; - shdr.sh_name = 0x20000; - shdr.sh_offset = 0xf000; - shdr.sh_size = 0x1000; - offset += sizeof(shdr); - ASSERT_EQ(offset, lseek(fd, offset, SEEK_SET)); - ASSERT_EQ(static_cast(sizeof(shdr)), write(fd, &shdr, sizeof(shdr))); - - offset = 0xf500; - ASSERT_EQ(offset, lseek(fd, offset, SEEK_SET)); - ASSERT_EQ(static_cast(sizeof(".note.gnu.build-id")), - write(fd, ".note.gnu.build-id", sizeof(".note.gnu.build-id"))); - - offset = 0xb000; - ASSERT_EQ(offset, lseek(fd, offset, SEEK_SET)); - ASSERT_EQ(static_cast(sizeof(note_section)), - write(fd, note_section, sizeof(note_section))); -} - -TEST_F(MapInfoGetBuildIDTest, from_memory) { - InitElfData(tf_->fd); - - EXPECT_EQ("ELF_BUILDID", map_info_->GetBuildID()); - EXPECT_EQ("454c465f4255494c444944", map_info_->GetPrintableBuildID()); -} - -TEST_F(MapInfoGetBuildIDTest, multiple_thread_elf_exists_in_memory) { - InitElfData(tf_->fd); - - MultipleThreadTest("ELF_BUILDID"); -} - -TEST_F(MapInfoGetBuildIDTest, real_elf) { - MapInfo map_info(nullptr, nullptr, 0x1000, 0x20000, 0, PROT_READ | PROT_WRITE, - TestGetFileDirectory() + "offline/empty_arm64/libc.so"); - EXPECT_EQ("6df0590c4920f4c7b9f34fe833f37d54", map_info.GetPrintableBuildID()); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/MapInfoGetElfTest.cpp b/libunwindstack/tests/MapInfoGetElfTest.cpp deleted file mode 100644 index 7f9781491..000000000 --- a/libunwindstack/tests/MapInfoGetElfTest.cpp +++ /dev/null @@ -1,422 +0,0 @@ -/* - * Copyright (C) 2016 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 "ElfTestUtils.h" -#include "MemoryFake.h" - -namespace unwindstack { - -class MapInfoGetElfTest : public ::testing::Test { - protected: - void SetUp() override { - memory_ = new MemoryFake; - process_memory_.reset(memory_); - } - - template - static void InitElf(uint64_t sh_offset, Ehdr* ehdr, uint8_t class_type, uint8_t machine_type) { - memset(ehdr, 0, sizeof(*ehdr)); - memcpy(ehdr->e_ident, ELFMAG, SELFMAG); - ehdr->e_ident[EI_CLASS] = class_type; - ehdr->e_machine = machine_type; - ehdr->e_shoff = sh_offset; - ehdr->e_shentsize = sizeof(Shdr) + 100; - ehdr->e_shnum = 4; - } - - const size_t kMapSize = 4096; - - std::shared_ptr process_memory_; - MemoryFake* memory_; - - TemporaryFile elf_; -}; - -TEST_F(MapInfoGetElfTest, invalid) { - MapInfo info(nullptr, nullptr, 0x1000, 0x2000, 0, PROT_READ, ""); - - // The map is empty, but this should still create an invalid elf object. - Elf* elf = info.GetElf(process_memory_, ARCH_ARM); - ASSERT_TRUE(elf != nullptr); - ASSERT_FALSE(elf->valid()); -} - -TEST_F(MapInfoGetElfTest, valid32) { - MapInfo info(nullptr, nullptr, 0x3000, 0x4000, 0, PROT_READ, ""); - - Elf32_Ehdr ehdr; - TestInitEhdr(&ehdr, ELFCLASS32, EM_ARM); - memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr)); - - Elf* elf = info.GetElf(process_memory_, ARCH_ARM); - ASSERT_TRUE(elf != nullptr); - ASSERT_TRUE(elf->valid()); - EXPECT_EQ(static_cast(EM_ARM), elf->machine_type()); - EXPECT_EQ(ELFCLASS32, elf->class_type()); - - // Now verify that an empty process memory returns an invalid elf object. - info.elf.reset(); - elf = info.GetElf(std::shared_ptr(), ARCH_ARM); - ASSERT_TRUE(elf != nullptr); - ASSERT_FALSE(elf->valid()); -} - -TEST_F(MapInfoGetElfTest, valid64) { - MapInfo info(nullptr, nullptr, 0x8000, 0x9000, 0, PROT_READ, ""); - - Elf64_Ehdr ehdr; - TestInitEhdr(&ehdr, ELFCLASS64, EM_AARCH64); - memory_->SetMemory(0x8000, &ehdr, sizeof(ehdr)); - - Elf* elf = info.GetElf(process_memory_, ARCH_ARM64); - ASSERT_TRUE(elf != nullptr); - ASSERT_TRUE(elf->valid()); - EXPECT_EQ(static_cast(EM_AARCH64), elf->machine_type()); - EXPECT_EQ(ELFCLASS64, elf->class_type()); -} - -TEST_F(MapInfoGetElfTest, invalid_arch_mismatch) { - MapInfo info(nullptr, nullptr, 0x3000, 0x4000, 0, PROT_READ, ""); - - Elf32_Ehdr ehdr; - TestInitEhdr(&ehdr, ELFCLASS32, EM_ARM); - memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr)); - - Elf* elf = info.GetElf(process_memory_, ARCH_X86); - ASSERT_TRUE(elf != nullptr); - ASSERT_FALSE(elf->valid()); -} - -TEST_F(MapInfoGetElfTest, gnu_debugdata_init32) { - MapInfo info(nullptr, nullptr, 0x2000, 0x3000, 0, PROT_READ, ""); - - TestInitGnuDebugdata(ELFCLASS32, EM_ARM, true, - [&](uint64_t offset, const void* ptr, size_t size) { - memory_->SetMemory(0x2000 + offset, ptr, size); - }); - - Elf* elf = info.GetElf(process_memory_, ARCH_ARM); - ASSERT_TRUE(elf != nullptr); - ASSERT_TRUE(elf->valid()); - EXPECT_EQ(static_cast(EM_ARM), elf->machine_type()); - EXPECT_EQ(ELFCLASS32, elf->class_type()); - EXPECT_TRUE(elf->gnu_debugdata_interface() != nullptr); -} - -TEST_F(MapInfoGetElfTest, gnu_debugdata_init64) { - MapInfo info(nullptr, nullptr, 0x5000, 0x8000, 0, PROT_READ, ""); - - TestInitGnuDebugdata(ELFCLASS64, EM_AARCH64, true, - [&](uint64_t offset, const void* ptr, size_t size) { - memory_->SetMemory(0x5000 + offset, ptr, size); - }); - - Elf* elf = info.GetElf(process_memory_, ARCH_ARM64); - ASSERT_TRUE(elf != nullptr); - ASSERT_TRUE(elf->valid()); - EXPECT_EQ(static_cast(EM_AARCH64), elf->machine_type()); - EXPECT_EQ(ELFCLASS64, elf->class_type()); - EXPECT_TRUE(elf->gnu_debugdata_interface() != nullptr); -} - -TEST_F(MapInfoGetElfTest, end_le_start) { - MapInfo info(nullptr, nullptr, 0x1000, 0x1000, 0, PROT_READ, elf_.path); - - Elf32_Ehdr ehdr; - TestInitEhdr(&ehdr, ELFCLASS32, EM_ARM); - ASSERT_TRUE(android::base::WriteFully(elf_.fd, &ehdr, sizeof(ehdr))); - - Elf* elf = info.GetElf(process_memory_, ARCH_ARM); - ASSERT_TRUE(elf != nullptr); - ASSERT_FALSE(elf->valid()); - - info.elf.reset(); - info.end = 0xfff; - elf = info.GetElf(process_memory_, ARCH_ARM); - ASSERT_TRUE(elf != nullptr); - ASSERT_FALSE(elf->valid()); - - // Make sure this test is valid. - info.elf.reset(); - info.end = 0x2000; - elf = info.GetElf(process_memory_, ARCH_ARM); - ASSERT_TRUE(elf != nullptr); - ASSERT_TRUE(elf->valid()); -} - -// Verify that if the offset is non-zero but there is no elf at the offset, -// that the full file is used. -TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_full_file) { - MapInfo info(nullptr, nullptr, 0x1000, 0x2000, 0x100, PROT_READ, elf_.path); - - std::vector buffer(0x1000); - memset(buffer.data(), 0, buffer.size()); - Elf32_Ehdr ehdr; - TestInitEhdr(&ehdr, ELFCLASS32, EM_ARM); - memcpy(buffer.data(), &ehdr, sizeof(ehdr)); - ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size())); - - Elf* elf = info.GetElf(process_memory_, ARCH_ARM); - ASSERT_TRUE(elf != nullptr); - ASSERT_TRUE(elf->valid()); - ASSERT_TRUE(elf->memory() != nullptr); - ASSERT_EQ(0x100U, info.elf_offset); - - // Read the entire file. - memset(buffer.data(), 0, buffer.size()); - ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), buffer.size())); - ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr))); - for (size_t i = sizeof(ehdr); i < buffer.size(); i++) { - ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i; - } - - ASSERT_FALSE(elf->memory()->ReadFully(buffer.size(), buffer.data(), 1)); -} - -// Verify that if the offset is non-zero and there is an elf at that -// offset, that only part of the file is used. -TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file) { - MapInfo info(nullptr, nullptr, 0x1000, 0x2000, 0x2000, PROT_READ, elf_.path); - - std::vector buffer(0x4000); - memset(buffer.data(), 0, buffer.size()); - Elf32_Ehdr ehdr; - TestInitEhdr(&ehdr, ELFCLASS32, EM_ARM); - memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr)); - ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size())); - - Elf* elf = info.GetElf(process_memory_, ARCH_ARM); - ASSERT_TRUE(elf != nullptr); - ASSERT_TRUE(elf->valid()); - ASSERT_TRUE(elf->memory() != nullptr); - ASSERT_EQ(0U, info.elf_offset); - - // Read the valid part of the file. - ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000)); - ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr))); - for (size_t i = sizeof(ehdr); i < 0x1000; i++) { - ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i; - } - - ASSERT_FALSE(elf->memory()->ReadFully(0x1000, buffer.data(), 1)); -} - -// Verify that if the offset is non-zero and there is an elf at that -// offset, that only part of the file is used. Further verify that if the -// embedded elf is bigger than the initial map, the new object is larger -// than the original map size. Do this for a 32 bit elf and a 64 bit elf. -TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf32) { - MapInfo info(nullptr, nullptr, 0x5000, 0x6000, 0x1000, PROT_READ, elf_.path); - - std::vector buffer(0x4000); - memset(buffer.data(), 0, buffer.size()); - Elf32_Ehdr ehdr; - TestInitEhdr(&ehdr, ELFCLASS32, EM_ARM); - ehdr.e_shoff = 0x2000; - ehdr.e_shentsize = sizeof(Elf32_Shdr) + 100; - ehdr.e_shnum = 4; - memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr)); - ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size())); - - Elf* elf = info.GetElf(process_memory_, ARCH_ARM); - ASSERT_TRUE(elf != nullptr); - ASSERT_TRUE(elf->valid()); - ASSERT_TRUE(elf->memory() != nullptr); - ASSERT_EQ(0U, info.elf_offset); - - // Verify the memory is a valid elf. - memset(buffer.data(), 0, buffer.size()); - ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000)); - ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr))); - - // Read past the end of what would normally be the size of the map. - ASSERT_TRUE(elf->memory()->ReadFully(0x1000, buffer.data(), 1)); -} - -TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf64) { - MapInfo info(nullptr, nullptr, 0x7000, 0x8000, 0x1000, PROT_READ, elf_.path); - - std::vector buffer(0x4000); - memset(buffer.data(), 0, buffer.size()); - Elf64_Ehdr ehdr; - TestInitEhdr(&ehdr, ELFCLASS64, EM_AARCH64); - ehdr.e_shoff = 0x2000; - ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100; - ehdr.e_shnum = 4; - memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr)); - ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size())); - - Elf* elf = info.GetElf(process_memory_, ARCH_ARM64); - ASSERT_TRUE(elf != nullptr); - ASSERT_TRUE(elf->valid()); - ASSERT_TRUE(elf->memory() != nullptr); - ASSERT_EQ(0U, info.elf_offset); - - // Verify the memory is a valid elf. - memset(buffer.data(), 0, buffer.size()); - ASSERT_TRUE(elf->memory()->ReadFully(0, buffer.data(), 0x1000)); - ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr))); - - // Read past the end of what would normally be the size of the map. - ASSERT_TRUE(elf->memory()->ReadFully(0x1000, buffer.data(), 1)); -} - -TEST_F(MapInfoGetElfTest, check_device_maps) { - MapInfo info(nullptr, nullptr, 0x7000, 0x8000, 0x1000, PROT_READ | MAPS_FLAGS_DEVICE_MAP, - "/dev/something"); - - // Create valid elf data in process memory for this to verify that only - // the name is causing invalid elf data. - Elf64_Ehdr ehdr; - TestInitEhdr(&ehdr, ELFCLASS64, EM_X86_64); - ehdr.e_shoff = 0x2000; - ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100; - ehdr.e_shnum = 0; - memory_->SetMemory(0x7000, &ehdr, sizeof(ehdr)); - - Elf* elf = info.GetElf(process_memory_, ARCH_X86_64); - ASSERT_TRUE(elf != nullptr); - ASSERT_FALSE(elf->valid()); - - // Set the name to nothing to verify that it still fails. - info.elf.reset(); - info.name = ""; - elf = info.GetElf(process_memory_, ARCH_X86_64); - ASSERT_FALSE(elf->valid()); - - // Change the flags and verify the elf is valid now. - info.elf.reset(); - info.flags = PROT_READ; - elf = info.GetElf(process_memory_, ARCH_X86_64); - ASSERT_TRUE(elf->valid()); -} - -TEST_F(MapInfoGetElfTest, multiple_thread_get_elf) { - static constexpr size_t kNumConcurrentThreads = 100; - - Elf64_Ehdr ehdr; - TestInitEhdr(&ehdr, ELFCLASS64, EM_X86_64); - ehdr.e_shoff = 0x2000; - ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100; - ehdr.e_shnum = 0; - memory_->SetMemory(0x7000, &ehdr, sizeof(ehdr)); - - Elf* elf_in_threads[kNumConcurrentThreads]; - std::vector threads; - - std::atomic_bool wait; - wait = true; - // Create all of the threads and have them do the GetElf at the same time - // to make it likely that a race will occur. - MapInfo info(nullptr, nullptr, 0x7000, 0x8000, 0x1000, PROT_READ, ""); - for (size_t i = 0; i < kNumConcurrentThreads; i++) { - std::thread* thread = new std::thread([i, this, &wait, &info, &elf_in_threads]() { - while (wait) - ; - Elf* elf = info.GetElf(process_memory_, ARCH_X86_64); - elf_in_threads[i] = elf; - }); - threads.push_back(thread); - } - ASSERT_TRUE(info.elf == nullptr); - - // Set them all going and wait for the threads to finish. - wait = false; - for (auto thread : threads) { - thread->join(); - delete thread; - } - - // Now verify that all of the elf files are exactly the same and valid. - Elf* elf = info.elf.get(); - ASSERT_TRUE(elf != nullptr); - EXPECT_TRUE(elf->valid()); - for (size_t i = 0; i < kNumConcurrentThreads; i++) { - EXPECT_EQ(elf, elf_in_threads[i]) << "Thread " << i << " mismatched."; - } -} - -// Verify that previous maps don't automatically get the same elf object. -TEST_F(MapInfoGetElfTest, prev_map_elf_not_set) { - MapInfo info1(nullptr, nullptr, 0x1000, 0x2000, 0, PROT_READ, "/not/present"); - MapInfo info2(&info1, &info1, 0x2000, 0x3000, 0, PROT_READ, elf_.path); - - Elf32_Ehdr ehdr; - TestInitEhdr(&ehdr, ELFCLASS32, EM_ARM); - memory_->SetMemory(0x2000, &ehdr, sizeof(ehdr)); - Elf* elf = info2.GetElf(process_memory_, ARCH_ARM); - ASSERT_TRUE(elf != nullptr); - ASSERT_TRUE(elf->valid()); - - ASSERT_NE(elf, info1.GetElf(process_memory_, ARCH_ARM)); -} - -// Verify that a read-only map followed by a read-execute map will result -// in the same elf object in both maps. -TEST_F(MapInfoGetElfTest, read_only_followed_by_read_exec_share_elf) { - MapInfo r_info(nullptr, nullptr, 0x1000, 0x2000, 0, PROT_READ, elf_.path); - MapInfo rw_info(&r_info, &r_info, 0x2000, 0x3000, 0x1000, PROT_READ | PROT_EXEC, elf_.path); - - Elf32_Ehdr ehdr; - TestInitEhdr(&ehdr, ELFCLASS32, EM_ARM); - memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr)); - Elf* elf = rw_info.GetElf(process_memory_, ARCH_ARM); - ASSERT_TRUE(elf != nullptr); - ASSERT_TRUE(elf->valid()); - - ASSERT_EQ(elf, r_info.GetElf(process_memory_, ARCH_ARM)); -} - -// Verify that a read-only map followed by an empty map, then followed by -// a read-execute map will result in the same elf object in both maps. -TEST_F(MapInfoGetElfTest, read_only_followed_by_empty_then_read_exec_share_elf) { - MapInfo r_info(nullptr, nullptr, 0x1000, 0x2000, 0, PROT_READ, elf_.path); - MapInfo empty(&r_info, &r_info, 0x2000, 0x3000, 0, 0, ""); - MapInfo rw_info(&empty, &r_info, 0x3000, 0x4000, 0x2000, PROT_READ | PROT_EXEC, elf_.path); - - Elf32_Ehdr ehdr; - TestInitEhdr(&ehdr, ELFCLASS32, EM_ARM); - memory_->SetMemory(0x1000, &ehdr, sizeof(ehdr)); - Elf* elf = rw_info.GetElf(process_memory_, ARCH_ARM); - ASSERT_TRUE(elf != nullptr); - ASSERT_TRUE(elf->valid()); - - ASSERT_EQ(elf, r_info.GetElf(process_memory_, ARCH_ARM)); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp b/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp deleted file mode 100644 index 971d4520e..000000000 --- a/libunwindstack/tests/MapInfoGetLoadBiasTest.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2016 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 "ElfFake.h" -#include "ElfTestUtils.h" -#include "MemoryFake.h" - -namespace unwindstack { - -class MapInfoGetLoadBiasTest : public ::testing::Test { - protected: - void SetUp() override { - memory_ = new MemoryFake; - process_memory_.reset(memory_); - elf_ = new ElfFake(new MemoryFake); - elf_container_.reset(elf_); - map_info_.reset(new MapInfo(nullptr, nullptr, 0x1000, 0x20000, 0, PROT_READ | PROT_WRITE, "")); - } - - void MultipleThreadTest(uint64_t expected_load_bias); - - std::shared_ptr process_memory_; - MemoryFake* memory_; - ElfFake* elf_; - std::unique_ptr elf_container_; - std::unique_ptr map_info_; -}; - -TEST_F(MapInfoGetLoadBiasTest, no_elf_and_no_valid_elf_in_memory) { - MapInfo info(nullptr, nullptr, 0x1000, 0x2000, 0, PROT_READ, ""); - - EXPECT_EQ(0U, info.GetLoadBias(process_memory_)); -} - -TEST_F(MapInfoGetLoadBiasTest, load_bias_cached_from_elf) { - map_info_->elf.reset(elf_container_.release()); - - elf_->FakeSetLoadBias(0); - EXPECT_EQ(0U, map_info_->GetLoadBias(process_memory_)); - - elf_->FakeSetLoadBias(0x1000); - EXPECT_EQ(0U, map_info_->GetLoadBias(process_memory_)); -} - -TEST_F(MapInfoGetLoadBiasTest, elf_exists) { - map_info_->elf.reset(elf_container_.release()); - - elf_->FakeSetLoadBias(0); - EXPECT_EQ(0U, map_info_->GetLoadBias(process_memory_)); - - map_info_->load_bias = INT64_MAX; - elf_->FakeSetLoadBias(0x1000); - EXPECT_EQ(0x1000U, map_info_->GetLoadBias(process_memory_)); -} - -void MapInfoGetLoadBiasTest::MultipleThreadTest(uint64_t expected_load_bias) { - static constexpr size_t kNumConcurrentThreads = 100; - - uint64_t load_bias_values[kNumConcurrentThreads]; - std::vector threads; - - std::atomic_bool wait; - wait = true; - // Create all of the threads and have them do the GetLoadBias at the same time - // to make it likely that a race will occur. - for (size_t i = 0; i < kNumConcurrentThreads; i++) { - std::thread* thread = new std::thread([i, this, &wait, &load_bias_values]() { - while (wait) - ; - load_bias_values[i] = map_info_->GetLoadBias(process_memory_); - }); - threads.push_back(thread); - } - - // Set them all going and wait for the threads to finish. - wait = false; - for (auto thread : threads) { - thread->join(); - delete thread; - } - - // Now verify that all of the elf files are exactly the same and valid. - for (size_t i = 0; i < kNumConcurrentThreads; i++) { - EXPECT_EQ(expected_load_bias, load_bias_values[i]) << "Thread " << i << " mismatched."; - } -} - -TEST_F(MapInfoGetLoadBiasTest, multiple_thread_elf_exists) { - map_info_->elf.reset(elf_container_.release()); - elf_->FakeSetLoadBias(0x1000); - - MultipleThreadTest(0x1000); -} - -static void InitElfData(MemoryFake* memory, uint64_t offset) { - Elf32_Ehdr ehdr; - TestInitEhdr(&ehdr, ELFCLASS32, EM_ARM); - ehdr.e_phoff = 0x5000; - ehdr.e_phnum = 2; - ehdr.e_phentsize = sizeof(Elf32_Phdr); - memory->SetMemory(offset, &ehdr, sizeof(ehdr)); - - Elf32_Phdr phdr; - memset(&phdr, 0, sizeof(phdr)); - phdr.p_type = PT_NULL; - memory->SetMemory(offset + 0x5000, &phdr, sizeof(phdr)); - phdr.p_type = PT_LOAD; - phdr.p_flags = PF_X; - phdr.p_offset = 0; - phdr.p_vaddr = 0xe000; - memory->SetMemory(offset + 0x5000 + sizeof(phdr), &phdr, sizeof(phdr)); -} - -TEST_F(MapInfoGetLoadBiasTest, elf_exists_in_memory) { - InitElfData(memory_, map_info_->start); - - EXPECT_EQ(0xe000U, map_info_->GetLoadBias(process_memory_)); -} - -TEST_F(MapInfoGetLoadBiasTest, elf_exists_in_memory_cached) { - InitElfData(memory_, map_info_->start); - - EXPECT_EQ(0xe000U, map_info_->GetLoadBias(process_memory_)); - - memory_->Clear(); - EXPECT_EQ(0xe000U, map_info_->GetLoadBias(process_memory_)); -} - -TEST_F(MapInfoGetLoadBiasTest, multiple_thread_elf_exists_in_memory) { - InitElfData(memory_, map_info_->start); - - MultipleThreadTest(0xe000); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/MapInfoTest.cpp b/libunwindstack/tests/MapInfoTest.cpp deleted file mode 100644 index 98edc0e7c..000000000 --- a/libunwindstack/tests/MapInfoTest.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2018 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 "ElfFake.h" - -namespace unwindstack { - -TEST(MapInfoTest, maps_constructor_const_char) { - MapInfo prev_map(nullptr, nullptr, 0, 0, 0, 0, ""); - MapInfo map_info(&prev_map, &prev_map, 1, 2, 3, 4, "map"); - - EXPECT_EQ(&prev_map, map_info.prev_map); - EXPECT_EQ(1UL, map_info.start); - EXPECT_EQ(2UL, map_info.end); - EXPECT_EQ(3UL, map_info.offset); - EXPECT_EQ(4UL, map_info.flags); - EXPECT_EQ("map", map_info.name); - EXPECT_EQ(INT64_MAX, map_info.load_bias); - EXPECT_EQ(0UL, map_info.elf_offset); - EXPECT_TRUE(map_info.elf.get() == nullptr); -} - -TEST(MapInfoTest, maps_constructor_string) { - std::string name("string_map"); - MapInfo prev_map(nullptr, nullptr, 0, 0, 0, 0, ""); - MapInfo map_info(&prev_map, &prev_map, 1, 2, 3, 4, name); - - EXPECT_EQ(&prev_map, map_info.prev_map); - EXPECT_EQ(1UL, map_info.start); - EXPECT_EQ(2UL, map_info.end); - EXPECT_EQ(3UL, map_info.offset); - EXPECT_EQ(4UL, map_info.flags); - EXPECT_EQ("string_map", map_info.name); - EXPECT_EQ(INT64_MAX, map_info.load_bias); - EXPECT_EQ(0UL, map_info.elf_offset); - EXPECT_TRUE(map_info.elf.get() == nullptr); -} - -TEST(MapInfoTest, get_function_name) { - ElfFake* elf = new ElfFake(nullptr); - ElfInterfaceFake* interface = new ElfInterfaceFake(nullptr); - elf->FakeSetInterface(interface); - interface->FakePushFunctionData(FunctionData("function", 1000)); - - MapInfo map_info(nullptr, nullptr, 1, 2, 3, 4, ""); - map_info.elf.reset(elf); - - std::string name; - uint64_t offset; - ASSERT_TRUE(map_info.GetFunctionName(1000, &name, &offset)); - EXPECT_EQ("function", name); - EXPECT_EQ(1000UL, offset); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/MapsTest.cpp b/libunwindstack/tests/MapsTest.cpp deleted file mode 100644 index 724eeb513..000000000 --- a/libunwindstack/tests/MapsTest.cpp +++ /dev/null @@ -1,618 +0,0 @@ -/* - * Copyright (C) 2016 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 - -namespace unwindstack { - -static void VerifyLine(std::string line, MapInfo* info) { - BufferMaps maps(line.c_str()); - - if (info == nullptr) { - ASSERT_FALSE(maps.Parse()) << "Failed on: " + line; - } else { - ASSERT_TRUE(maps.Parse()) << "Failed on: " + line; - MapInfo* element = maps.Get(0); - ASSERT_TRUE(element != nullptr) << "Failed on: " + line; - info->start = element->start; - info->end = element->end; - info->offset = element->offset; - info->flags = element->flags; - info->name = element->name; - info->elf_offset = element->elf_offset; - } -} - -TEST(MapsTest, map_add) { - Maps maps; - - maps.Add(0x1000, 0x2000, 0, PROT_READ, "fake_map", 0); - maps.Add(0x3000, 0x4000, 0x10, 0, "", 0x1234); - maps.Add(0x5000, 0x6000, 1, 2, "fake_map2", static_cast(-1)); - - ASSERT_EQ(3U, maps.Total()); - MapInfo* info = maps.Get(0); - ASSERT_EQ(0x1000U, info->start); - ASSERT_EQ(0x2000U, info->end); - ASSERT_EQ(0U, info->offset); - ASSERT_EQ(PROT_READ, info->flags); - ASSERT_EQ("fake_map", info->name); - ASSERT_EQ(0U, info->elf_offset); - ASSERT_EQ(0U, info->load_bias.load()); -} - -TEST(MapsTest, map_move) { - Maps maps; - - maps.Add(0x1000, 0x2000, 0, PROT_READ, "fake_map", 0); - maps.Add(0x3000, 0x4000, 0x10, 0, "", 0x1234); - maps.Add(0x5000, 0x6000, 1, 2, "fake_map2", static_cast(-1)); - - Maps maps2 = std::move(maps); - - ASSERT_EQ(3U, maps2.Total()); - MapInfo* info = maps2.Get(0); - ASSERT_EQ(0x1000U, info->start); - ASSERT_EQ(0x2000U, info->end); - ASSERT_EQ(0U, info->offset); - ASSERT_EQ(PROT_READ, info->flags); - ASSERT_EQ("fake_map", info->name); - ASSERT_EQ(0U, info->elf_offset); - ASSERT_EQ(0U, info->load_bias.load()); -} - -TEST(MapsTest, verify_parse_line) { - MapInfo info(nullptr, nullptr, 0, 0, 0, 0, ""); - - VerifyLine("01-02 rwxp 03 04:05 06\n", &info); - EXPECT_EQ(1U, info.start); - EXPECT_EQ(2U, info.end); - EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info.flags); - EXPECT_EQ(3U, info.offset); - EXPECT_EQ("", info.name); - - VerifyLine("0a-0b ---s 0c 0d:0e 06 /fake/name\n", &info); - EXPECT_EQ(0xaU, info.start); - EXPECT_EQ(0xbU, info.end); - EXPECT_EQ(0U, info.flags); - EXPECT_EQ(0xcU, info.offset); - EXPECT_EQ("/fake/name", info.name); - - VerifyLine("01-02 rwxp 03 04:05 06 /fake/name/again\n", &info); - EXPECT_EQ(1U, info.start); - EXPECT_EQ(2U, info.end); - EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info.flags); - EXPECT_EQ(3U, info.offset); - EXPECT_EQ("/fake/name/again", info.name); - - VerifyLine("-00 rwxp 00 00:00 0\n", nullptr); - VerifyLine("00- rwxp 00 00:00 0\n", nullptr); - VerifyLine("00-00 rwxp 00 :00 0\n", nullptr); - VerifyLine("00-00 rwxp 00 00:00 \n", nullptr); - VerifyLine("x-00 rwxp 00 00:00 0\n", nullptr); - VerifyLine("00 -00 rwxp 00 00:00 0\n", nullptr); - VerifyLine("00-x rwxp 00 00:00 0\n", nullptr); - VerifyLine("00-x rwxp 00 00:00 0\n", nullptr); - VerifyLine("00-00x rwxp 00 00:00 0\n", nullptr); - VerifyLine("00-00 rwxp0 00 00:00 0\n", nullptr); - VerifyLine("00-00 rwxp0 00 00:00 0\n", nullptr); - VerifyLine("00-00 rwp 00 00:00 0\n", nullptr); - VerifyLine("00-00 rwxp 0000:00 0\n", nullptr); - VerifyLine("00-00 rwxp 00 00 :00 0\n", nullptr); - VerifyLine("00-00 rwxp 00 00: 00 0\n", nullptr); - VerifyLine("00-00 rwxp 00 00:000\n", nullptr); - VerifyLine("00-00 rwxp 00 00:00 0/fake\n", nullptr); - VerifyLine("00-00 xxxx 00 00:00 0 /fake\n", nullptr); - VerifyLine("00-00 ywxp 00 00:00 0 /fake\n", nullptr); - VerifyLine("00-00 ryxp 00 00:00 0 /fake\n", nullptr); - VerifyLine("00-00 rwyp 00 00:00 0 /fake\n", nullptr); - VerifyLine("00-00 rwx- 00 00:00 0 /fake\n", nullptr); - VerifyLine("0\n", nullptr); - VerifyLine("00\n", nullptr); - VerifyLine("00-\n", nullptr); - VerifyLine("00-0\n", nullptr); - VerifyLine("00-00\n", nullptr); - VerifyLine("00-00 \n", nullptr); - VerifyLine("00-00 -\n", nullptr); - VerifyLine("00-00 r\n", nullptr); - VerifyLine("00-00 --\n", nullptr); - VerifyLine("00-00 rw\n", nullptr); - VerifyLine("00-00 ---\n", nullptr); - VerifyLine("00-00 rwx\n", nullptr); - VerifyLine("00-00 ---s\n", nullptr); - VerifyLine("00-00 ---p\n", nullptr); - VerifyLine("00-00 ---s 0\n", nullptr); - VerifyLine("00-00 ---p 0 \n", nullptr); - VerifyLine("00-00 ---p 0 0\n", nullptr); - VerifyLine("00-00 ---p 0 0:\n", nullptr); - VerifyLine("00-00 ---p 0 0:0\n", nullptr); - VerifyLine("00-00 ---p 0 0:0 \n", nullptr); - - // Line to verify that the parser will detect a completely malformed line - // properly. - VerifyLine("7ffff7dda000-7ffff7dfd7ffff7ff3000-7ffff7ff4000 ---p 0000f000 fc:02 44171565\n", - nullptr); -} - -TEST(MapsTest, verify_large_values) { - MapInfo info(nullptr, nullptr, 0, 0, 0, 0, ""); -#if defined(__LP64__) - VerifyLine("fabcdef012345678-f12345678abcdef8 rwxp f0b0d0f010305070 00:00 0\n", &info); - EXPECT_EQ(0xfabcdef012345678UL, info.start); - EXPECT_EQ(0xf12345678abcdef8UL, info.end); - EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info.flags); - EXPECT_EQ(0xf0b0d0f010305070UL, info.offset); -#else - VerifyLine("f2345678-fabcdef8 rwxp f0305070 00:00 0\n", &info); - EXPECT_EQ(0xf2345678UL, info.start); - EXPECT_EQ(0xfabcdef8UL, info.end); - EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info.flags); - EXPECT_EQ(0xf0305070UL, info.offset); -#endif -} - -TEST(MapsTest, parse_permissions) { - BufferMaps maps( - "1000-2000 ---s 00000000 00:00 0\n" - "2000-3000 r--s 00000000 00:00 0\n" - "3000-4000 -w-s 00000000 00:00 0\n" - "4000-5000 --xp 00000000 00:00 0\n" - "5000-6000 rwxp 00000000 00:00 0\n"); - - ASSERT_TRUE(maps.Parse()); - ASSERT_EQ(5U, maps.Total()); - - MapInfo* info = maps.Get(0); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(PROT_NONE, info->flags); - EXPECT_EQ(0x1000U, info->start); - EXPECT_EQ(0x2000U, info->end); - EXPECT_EQ(0U, info->offset); - EXPECT_EQ("", info->name); - - info = maps.Get(1); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(PROT_READ, info->flags); - EXPECT_EQ(0x2000U, info->start); - EXPECT_EQ(0x3000U, info->end); - EXPECT_EQ(0U, info->offset); - EXPECT_EQ("", info->name); - - info = maps.Get(2); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(PROT_WRITE, info->flags); - EXPECT_EQ(0x3000U, info->start); - EXPECT_EQ(0x4000U, info->end); - EXPECT_EQ(0U, info->offset); - EXPECT_EQ("", info->name); - - info = maps.Get(3); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(PROT_EXEC, info->flags); - EXPECT_EQ(0x4000U, info->start); - EXPECT_EQ(0x5000U, info->end); - EXPECT_EQ(0U, info->offset); - EXPECT_EQ("", info->name); - - info = maps.Get(4); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info->flags); - EXPECT_EQ(0x5000U, info->start); - EXPECT_EQ(0x6000U, info->end); - EXPECT_EQ(0U, info->offset); - EXPECT_EQ("", info->name); - - ASSERT_TRUE(maps.Get(5) == nullptr); -} - -TEST(MapsTest, parse_name) { - BufferMaps maps( - "7b29b000-7b29e000 rw-p 00000000 00:00 0\n" - "7b29e000-7b29f000 rw-p 00000000 00:00 0 /system/lib/fake.so\n" - "7b29f000-7b2a0000 rw-p 00000000 00:00 0"); - - ASSERT_TRUE(maps.Parse()); - ASSERT_EQ(3U, maps.Total()); - - MapInfo* info = maps.Get(0); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ("", info->name); - EXPECT_EQ(0x7b29b000U, info->start); - EXPECT_EQ(0x7b29e000U, info->end); - EXPECT_EQ(0U, info->offset); - EXPECT_EQ(PROT_READ | PROT_WRITE, info->flags); - - info = maps.Get(1); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ("/system/lib/fake.so", info->name); - EXPECT_EQ(0x7b29e000U, info->start); - EXPECT_EQ(0x7b29f000U, info->end); - EXPECT_EQ(0U, info->offset); - EXPECT_EQ(PROT_READ | PROT_WRITE, info->flags); - - info = maps.Get(2); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ("", info->name); - EXPECT_EQ(0x7b29f000U, info->start); - EXPECT_EQ(0x7b2a0000U, info->end); - EXPECT_EQ(0U, info->offset); - EXPECT_EQ(PROT_READ | PROT_WRITE, info->flags); - - ASSERT_TRUE(maps.Get(3) == nullptr); -} - -TEST(MapsTest, parse_offset) { - BufferMaps maps( - "a000-e000 rw-p 00000000 00:00 0 /system/lib/fake.so\n" - "e000-f000 rw-p 00a12345 00:00 0 /system/lib/fake.so\n"); - - ASSERT_TRUE(maps.Parse()); - ASSERT_EQ(2U, maps.Total()); - - MapInfo* info = maps.Get(0); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(0U, info->offset); - EXPECT_EQ(0xa000U, info->start); - EXPECT_EQ(0xe000U, info->end); - EXPECT_EQ(PROT_READ | PROT_WRITE, info->flags); - EXPECT_EQ("/system/lib/fake.so", info->name); - - info = maps.Get(1); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(0xa12345U, info->offset); - EXPECT_EQ(0xe000U, info->start); - EXPECT_EQ(0xf000U, info->end); - EXPECT_EQ(PROT_READ | PROT_WRITE, info->flags); - EXPECT_EQ("/system/lib/fake.so", info->name); - - ASSERT_TRUE(maps.Get(2) == nullptr); -} - -TEST(MapsTest, iterate) { - BufferMaps maps( - "a000-e000 rw-p 00000000 00:00 0 /system/lib/fake.so\n" - "e000-f000 rw-p 00a12345 00:00 0 /system/lib/fake.so\n"); - - ASSERT_TRUE(maps.Parse()); - ASSERT_EQ(2U, maps.Total()); - - Maps::iterator it = maps.begin(); - EXPECT_EQ(0xa000U, (*it)->start); - EXPECT_EQ(0xe000U, (*it)->end); - ++it; - EXPECT_EQ(0xe000U, (*it)->start); - EXPECT_EQ(0xf000U, (*it)->end); - ++it; - EXPECT_EQ(maps.end(), it); -} - -TEST(MapsTest, const_iterate) { - BufferMaps maps( - "a000-e000 rw-p 00000000 00:00 0 /system/lib/fake.so\n" - "e000-f000 rw-p 00a12345 00:00 0 /system/lib/fake.so\n"); - - ASSERT_TRUE(maps.Parse()); - ASSERT_EQ(2U, maps.Total()); - - Maps::const_iterator it = maps.begin(); - EXPECT_EQ(0xa000U, (*it)->start); - EXPECT_EQ(0xe000U, (*it)->end); - ++it; - EXPECT_EQ(0xe000U, (*it)->start); - EXPECT_EQ(0xf000U, (*it)->end); - ++it; - EXPECT_EQ(maps.end(), it); -} - -TEST(MapsTest, device) { - BufferMaps maps( - "a000-e000 rw-p 00000000 00:00 0 /dev/\n" - "f000-f100 rw-p 00000000 00:00 0 /dev/does_not_exist\n" - "f100-f200 rw-p 00000000 00:00 0 /dev/ashmem/does_not_exist\n" - "f200-f300 rw-p 00000000 00:00 0 /devsomething/does_not_exist\n"); - - ASSERT_TRUE(maps.Parse()); - ASSERT_EQ(4U, maps.Total()); - - MapInfo* info = maps.Get(0); - ASSERT_TRUE(info != nullptr); - EXPECT_TRUE(info->flags & 0x8000); - EXPECT_EQ("/dev/", info->name); - - info = maps.Get(1); - EXPECT_TRUE(info->flags & 0x8000); - EXPECT_EQ("/dev/does_not_exist", info->name); - - info = maps.Get(2); - EXPECT_FALSE(info->flags & 0x8000); - EXPECT_EQ("/dev/ashmem/does_not_exist", info->name); - - info = maps.Get(3); - EXPECT_FALSE(info->flags & 0x8000); - EXPECT_EQ("/devsomething/does_not_exist", info->name); -} - -TEST(MapsTest, file_smoke) { - TemporaryFile tf; - ASSERT_TRUE(tf.fd != -1); - - ASSERT_TRUE( - android::base::WriteStringToFile("7b29b000-7b29e000 r-xp a0000000 00:00 0 /fake.so\n" - "7b2b0000-7b2e0000 r-xp b0000000 00:00 0 /fake2.so\n" - "7b2e0000-7b2f0000 r-xp c0000000 00:00 0 /fake3.so\n", - tf.path, 0660, getuid(), getgid())); - - FileMaps maps(tf.path); - - ASSERT_TRUE(maps.Parse()); - ASSERT_EQ(3U, maps.Total()); - - MapInfo* info = maps.Get(0); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(0x7b29b000U, info->start); - EXPECT_EQ(0x7b29e000U, info->end); - EXPECT_EQ(0xa0000000U, info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, info->flags); - EXPECT_EQ("/fake.so", info->name); - - info = maps.Get(1); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(0x7b2b0000U, info->start); - EXPECT_EQ(0x7b2e0000U, info->end); - EXPECT_EQ(0xb0000000U, info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, info->flags); - EXPECT_EQ("/fake2.so", info->name); - - info = maps.Get(2); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(0x7b2e0000U, info->start); - EXPECT_EQ(0x7b2f0000U, info->end); - EXPECT_EQ(0xc0000000U, info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, info->flags); - EXPECT_EQ("/fake3.so", info->name); - - ASSERT_TRUE(maps.Get(3) == nullptr); -} - -TEST(MapsTest, file_no_map_name) { - TemporaryFile tf; - ASSERT_TRUE(tf.fd != -1); - - ASSERT_TRUE( - android::base::WriteStringToFile("7b29b000-7b29e000 r-xp a0000000 00:00 0\n" - "7b2b0000-7b2e0000 r-xp b0000000 00:00 0 /fake2.so\n" - "7b2e0000-7b2f0000 r-xp c0000000 00:00 0 \n", - tf.path, 0660, getuid(), getgid())); - - FileMaps maps(tf.path); - - ASSERT_TRUE(maps.Parse()); - ASSERT_EQ(3U, maps.Total()); - - MapInfo* info = maps.Get(0); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(0x7b29b000U, info->start); - EXPECT_EQ(0x7b29e000U, info->end); - EXPECT_EQ(0xa0000000U, info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, info->flags); - EXPECT_EQ("", info->name); - - info = maps.Get(1); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(0x7b2b0000U, info->start); - EXPECT_EQ(0x7b2e0000U, info->end); - EXPECT_EQ(0xb0000000U, info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, info->flags); - EXPECT_EQ("/fake2.so", info->name); - - info = maps.Get(2); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(0x7b2e0000U, info->start); - EXPECT_EQ(0x7b2f0000U, info->end); - EXPECT_EQ(0xc0000000U, info->offset); - EXPECT_EQ(PROT_READ | PROT_EXEC, info->flags); - EXPECT_EQ("", info->name); - - ASSERT_TRUE(maps.Get(3) == nullptr); -} - -// Verify that a file that crosses a buffer is parsed correctly. -static std::string CreateEntry(size_t index) { - return android::base::StringPrintf("%08zx-%08zx rwxp 0000 00:00 0\n", index * 4096, - (index + 1) * 4096); -} - -TEST(MapsTest, file_buffer_cross) { - constexpr size_t kBufferSize = 2048; - TemporaryFile tf; - ASSERT_TRUE(tf.fd != -1); - - // Compute how many to add in the first buffer. - size_t entry_len = CreateEntry(0).size(); - size_t index; - std::string file_data; - for (index = 0; index < kBufferSize / entry_len; index++) { - file_data += CreateEntry(index); - } - // Add a long name to make sure that the first buffer does not contain a - // complete line. - // Remove the last newline. - size_t extra = 0; - size_t leftover = kBufferSize % entry_len; - size_t overlap1_index = 0; - std::string overlap1_name; - if (leftover == 0) { - // Exact match, add a long name to cross over the value. - overlap1_name = "/fake/name/is/long/on/purpose"; - file_data.erase(file_data.size() - 1); - file_data += ' ' + overlap1_name + '\n'; - extra = entry_len + overlap1_name.size() + 1; - overlap1_index = index; - } - - // Compute how many need to go in to hit the buffer boundary exactly. - size_t bytes_left_in_buffer = kBufferSize - extra; - size_t entries_to_add = bytes_left_in_buffer / entry_len + index; - for (; index < entries_to_add; index++) { - file_data += CreateEntry(index); - } - - // Now figure out how many bytes to add to get exactly to the buffer boundary. - leftover = bytes_left_in_buffer % entry_len; - std::string overlap2_name; - size_t overlap2_index = 0; - if (leftover != 0) { - file_data.erase(file_data.size() - 1); - file_data += ' '; - overlap2_name = std::string(leftover - 1, 'x'); - file_data += overlap2_name + '\n'; - overlap2_index = index - 1; - } - - // Now add a few entries on the next page. - for (size_t start = index; index < start + 10; index++) { - file_data += CreateEntry(index); - } - - ASSERT_TRUE(android::base::WriteStringToFile(file_data, tf.path, 0660, getuid(), getgid())); - - FileMaps maps(tf.path); - ASSERT_TRUE(maps.Parse()); - EXPECT_EQ(index, maps.Total()); - // Verify all of the maps. - for (size_t i = 0; i < index; i++) { - MapInfo* info = maps.Get(i); - ASSERT_TRUE(info != nullptr) << "Failed verifying index " + std::to_string(i); - EXPECT_EQ(i * 4096, info->start) << "Failed verifying index " + std::to_string(i); - EXPECT_EQ((i + 1) * 4096, info->end) << "Failed verifying index " + std::to_string(i); - EXPECT_EQ(0U, info->offset) << "Failed verifying index " + std::to_string(i); - if (overlap1_index != 0 && i == overlap1_index) { - EXPECT_EQ(overlap1_name, info->name) << "Failed verifying overlap1 name " + std::to_string(i); - } else if (overlap2_index != 0 && i == overlap2_index) { - EXPECT_EQ(overlap2_name, info->name) << "Failed verifying overlap2 name " + std::to_string(i); - } else { - EXPECT_EQ("", info->name) << "Failed verifying index " + std::to_string(i); - } - } -} - -TEST(MapsTest, file_should_fail) { - TemporaryFile tf; - ASSERT_TRUE(tf.fd != -1); - - ASSERT_TRUE(android::base::WriteStringToFile( - "7ffff7dda000-7ffff7dfd7ffff7ff3000-7ffff7ff4000 ---p 0000f000 fc:02 44171565\n", tf.path, - 0660, getuid(), getgid())); - - FileMaps maps(tf.path); - - ASSERT_FALSE(maps.Parse()); -} - -// Create a maps file that is extremely large. -TEST(MapsTest, large_file) { - TemporaryFile tf; - ASSERT_TRUE(tf.fd != -1); - - std::string file_data; - uint64_t start = 0x700000; - for (size_t i = 0; i < 5000; i++) { - file_data += - android::base::StringPrintf("%" PRIx64 "-%" PRIx64 " r-xp 1000 00:0 0 /fake%zu.so\n", - start + i * 4096, start + (i + 1) * 4096, i); - } - - ASSERT_TRUE(android::base::WriteStringToFile(file_data, tf.path, 0660, getuid(), getgid())); - - FileMaps maps(tf.path); - - ASSERT_TRUE(maps.Parse()); - ASSERT_EQ(5000U, maps.Total()); - for (size_t i = 0; i < 5000; i++) { - MapInfo* info = maps.Get(i); - EXPECT_EQ(start + i * 4096, info->start) << "Failed at map " + std::to_string(i); - EXPECT_EQ(start + (i + 1) * 4096, info->end) << "Failed at map " + std::to_string(i); - std::string name = "/fake" + std::to_string(i) + ".so"; - EXPECT_EQ(name, info->name) << "Failed at map " + std::to_string(i); - } -} - -TEST(MapsTest, find) { - BufferMaps maps( - "1000-2000 r--p 00000010 00:00 0 /system/lib/fake1.so\n" - "3000-4000 -w-p 00000020 00:00 0 /system/lib/fake2.so\n" - "6000-8000 --xp 00000030 00:00 0 /system/lib/fake3.so\n" - "a000-b000 rw-p 00000040 00:00 0 /system/lib/fake4.so\n" - "e000-f000 rwxp 00000050 00:00 0 /system/lib/fake5.so\n"); - ASSERT_TRUE(maps.Parse()); - ASSERT_EQ(5U, maps.Total()); - - EXPECT_TRUE(maps.Find(0x500) == nullptr); - EXPECT_TRUE(maps.Find(0x2000) == nullptr); - EXPECT_TRUE(maps.Find(0x5010) == nullptr); - EXPECT_TRUE(maps.Find(0x9a00) == nullptr); - EXPECT_TRUE(maps.Find(0xf000) == nullptr); - EXPECT_TRUE(maps.Find(0xf010) == nullptr); - - MapInfo* info = maps.Find(0x1000); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(0x1000U, info->start); - EXPECT_EQ(0x2000U, info->end); - EXPECT_EQ(0x10U, info->offset); - EXPECT_EQ(PROT_READ, info->flags); - EXPECT_EQ("/system/lib/fake1.so", info->name); - - info = maps.Find(0x3020); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(0x3000U, info->start); - EXPECT_EQ(0x4000U, info->end); - EXPECT_EQ(0x20U, info->offset); - EXPECT_EQ(PROT_WRITE, info->flags); - EXPECT_EQ("/system/lib/fake2.so", info->name); - - info = maps.Find(0x6020); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(0x6000U, info->start); - EXPECT_EQ(0x8000U, info->end); - EXPECT_EQ(0x30U, info->offset); - EXPECT_EQ(PROT_EXEC, info->flags); - EXPECT_EQ("/system/lib/fake3.so", info->name); - - info = maps.Find(0xafff); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(0xa000U, info->start); - EXPECT_EQ(0xb000U, info->end); - EXPECT_EQ(0x40U, info->offset); - EXPECT_EQ(PROT_READ | PROT_WRITE, info->flags); - EXPECT_EQ("/system/lib/fake4.so", info->name); - - info = maps.Find(0xe500); - ASSERT_TRUE(info != nullptr); - EXPECT_EQ(0xe000U, info->start); - EXPECT_EQ(0xf000U, info->end); - EXPECT_EQ(0x50U, info->offset); - EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info->flags); - EXPECT_EQ("/system/lib/fake5.so", info->name); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/MemoryBufferTest.cpp b/libunwindstack/tests/MemoryBufferTest.cpp deleted file mode 100644 index a6c12aab0..000000000 --- a/libunwindstack/tests/MemoryBufferTest.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2016 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 "LogFake.h" -#include "MemoryBuffer.h" - -namespace unwindstack { - -class MemoryBufferTest : public ::testing::Test { - protected: - void SetUp() override { - ResetLogs(); - memory_.reset(new MemoryBuffer); - } - std::unique_ptr memory_; -}; - -TEST_F(MemoryBufferTest, empty) { - ASSERT_EQ(0U, memory_->Size()); - std::vector buffer(1024); - ASSERT_FALSE(memory_->ReadFully(0, buffer.data(), 1)); - ASSERT_EQ(nullptr, memory_->GetPtr(0)); - ASSERT_EQ(nullptr, memory_->GetPtr(1)); -} - -TEST_F(MemoryBufferTest, write_read) { - memory_->Resize(256); - ASSERT_EQ(256U, memory_->Size()); - ASSERT_TRUE(memory_->GetPtr(0) != nullptr); - ASSERT_TRUE(memory_->GetPtr(1) != nullptr); - ASSERT_TRUE(memory_->GetPtr(255) != nullptr); - ASSERT_TRUE(memory_->GetPtr(256) == nullptr); - - uint8_t* data = memory_->GetPtr(0); - for (size_t i = 0; i < memory_->Size(); i++) { - data[i] = i; - } - - std::vector buffer(memory_->Size()); - ASSERT_TRUE(memory_->ReadFully(0, buffer.data(), buffer.size())); - for (size_t i = 0; i < buffer.size(); i++) { - ASSERT_EQ(i, buffer[i]) << "Failed at byte " << i; - } -} - -TEST_F(MemoryBufferTest, read_failures) { - memory_->Resize(100); - std::vector buffer(200); - ASSERT_FALSE(memory_->ReadFully(0, buffer.data(), 101)); - ASSERT_FALSE(memory_->ReadFully(100, buffer.data(), 1)); - ASSERT_FALSE(memory_->ReadFully(101, buffer.data(), 2)); - ASSERT_FALSE(memory_->ReadFully(99, buffer.data(), 2)); - ASSERT_TRUE(memory_->ReadFully(99, buffer.data(), 1)); -} - -TEST_F(MemoryBufferTest, read_failure_overflow) { - memory_->Resize(100); - std::vector buffer(200); - - ASSERT_FALSE(memory_->ReadFully(UINT64_MAX - 100, buffer.data(), 200)); -} - -TEST_F(MemoryBufferTest, Read) { - memory_->Resize(256); - ASSERT_EQ(256U, memory_->Size()); - ASSERT_TRUE(memory_->GetPtr(0) != nullptr); - ASSERT_TRUE(memory_->GetPtr(1) != nullptr); - ASSERT_TRUE(memory_->GetPtr(255) != nullptr); - ASSERT_TRUE(memory_->GetPtr(256) == nullptr); - - uint8_t* data = memory_->GetPtr(0); - for (size_t i = 0; i < memory_->Size(); i++) { - data[i] = i; - } - - std::vector buffer(memory_->Size()); - ASSERT_EQ(128U, memory_->Read(128, buffer.data(), buffer.size())); - for (size_t i = 0; i < 128; i++) { - ASSERT_EQ(128 + i, buffer[i]) << "Failed at byte " << i; - } -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/MemoryCacheTest.cpp b/libunwindstack/tests/MemoryCacheTest.cpp deleted file mode 100644 index 3bd3e4dbe..000000000 --- a/libunwindstack/tests/MemoryCacheTest.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2018 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 "MemoryCache.h" -#include "MemoryFake.h" - -namespace unwindstack { - -class MemoryCacheTest : public ::testing::Test { - protected: - void SetUp() override { - memory_ = new MemoryFake; - memory_cache_.reset(new MemoryCache(memory_)); - - memory_->SetMemoryBlock(0x8000, 4096, 0xab); - memory_->SetMemoryBlock(0x9000, 4096, 0xde); - memory_->SetMemoryBlock(0xa000, 3000, 0x50); - } - - MemoryFake* memory_; - std::unique_ptr memory_cache_; - - constexpr static size_t kMaxCachedSize = 64; -}; - -TEST_F(MemoryCacheTest, cached_read) { - for (size_t i = 1; i <= kMaxCachedSize; i++) { - std::vector buffer(i); - ASSERT_TRUE(memory_cache_->ReadFully(0x8000 + i, buffer.data(), i)) - << "Read failed at size " << i; - ASSERT_EQ(std::vector(i, 0xab), buffer) << "Failed at size " << i; - } - - // Verify the cached data is used. - memory_->SetMemoryBlock(0x8000, 4096, 0xff); - for (size_t i = 1; i <= kMaxCachedSize; i++) { - std::vector buffer(i); - ASSERT_TRUE(memory_cache_->ReadFully(0x8000 + i, buffer.data(), i)) - << "Read failed at size " << i; - ASSERT_EQ(std::vector(i, 0xab), buffer) << "Failed at size " << i; - } -} - -TEST_F(MemoryCacheTest, no_cached_read_after_clear) { - for (size_t i = 1; i <= kMaxCachedSize; i++) { - std::vector buffer(i); - ASSERT_TRUE(memory_cache_->ReadFully(0x8000 + i, buffer.data(), i)) - << "Read failed at size " << i; - ASSERT_EQ(std::vector(i, 0xab), buffer) << "Failed at size " << i; - } - - // Verify the cached data is not used after a reset. - memory_cache_->Clear(); - memory_->SetMemoryBlock(0x8000, 4096, 0xff); - for (size_t i = 1; i <= kMaxCachedSize; i++) { - std::vector buffer(i); - ASSERT_TRUE(memory_cache_->ReadFully(0x8000 + i, buffer.data(), i)) - << "Read failed at size " << i; - ASSERT_EQ(std::vector(i, 0xff), buffer) << "Failed at size " << i; - } -} - -TEST_F(MemoryCacheTest, cached_read_across_caches) { - std::vector expect(16, 0xab); - expect.resize(32, 0xde); - - std::vector buffer(32); - ASSERT_TRUE(memory_cache_->ReadFully(0x8ff0, buffer.data(), 32)); - ASSERT_EQ(expect, buffer); - - // Verify the cached data is used. - memory_->SetMemoryBlock(0x8000, 4096, 0xff); - memory_->SetMemoryBlock(0x9000, 4096, 0xff); - ASSERT_TRUE(memory_cache_->ReadFully(0x8ff0, buffer.data(), 32)); - ASSERT_EQ(expect, buffer); -} - -TEST_F(MemoryCacheTest, no_cache_read) { - for (size_t i = kMaxCachedSize + 1; i < 2 * kMaxCachedSize; i++) { - std::vector buffer(i); - ASSERT_TRUE(memory_cache_->ReadFully(0x8000 + i, buffer.data(), i)) - << "Read failed at size " << i; - ASSERT_EQ(std::vector(i, 0xab), buffer) << "Failed at size " << i; - } - - // Verify the cached data is not used. - memory_->SetMemoryBlock(0x8000, 4096, 0xff); - for (size_t i = kMaxCachedSize + 1; i < 2 * kMaxCachedSize; i++) { - std::vector buffer(i); - ASSERT_TRUE(memory_cache_->ReadFully(0x8000 + i, buffer.data(), i)) - << "Read failed at size " << i; - ASSERT_EQ(std::vector(i, 0xff), buffer) << "Failed at size " << i; - } -} - -TEST_F(MemoryCacheTest, read_for_cache_fail) { - std::vector buffer(kMaxCachedSize); - ASSERT_TRUE(memory_cache_->ReadFully(0xa010, buffer.data(), kMaxCachedSize)); - ASSERT_EQ(std::vector(kMaxCachedSize, 0x50), buffer); - - // Verify the cached data is not used. - memory_->SetMemoryBlock(0xa000, 3000, 0xff); - ASSERT_TRUE(memory_cache_->ReadFully(0xa010, buffer.data(), kMaxCachedSize)); - ASSERT_EQ(std::vector(kMaxCachedSize, 0xff), buffer); -} - -TEST_F(MemoryCacheTest, read_for_cache_fail_cross) { - std::vector expect(16, 0xde); - expect.resize(32, 0x50); - - std::vector buffer(32); - ASSERT_TRUE(memory_cache_->ReadFully(0x9ff0, buffer.data(), 32)); - ASSERT_EQ(expect, buffer); - - // Verify the cached data is not used for the second half but for the first. - memory_->SetMemoryBlock(0xa000, 3000, 0xff); - ASSERT_TRUE(memory_cache_->ReadFully(0x9ff0, buffer.data(), 32)); - expect.resize(16); - expect.resize(32, 0xff); - ASSERT_EQ(expect, buffer); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/MemoryFake.cpp b/libunwindstack/tests/MemoryFake.cpp deleted file mode 100644 index 5695dfcba..000000000 --- a/libunwindstack/tests/MemoryFake.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2016 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 "MemoryFake.h" - -namespace unwindstack { - -void MemoryFake::SetMemoryBlock(uint64_t addr, size_t length, uint8_t value) { - for (size_t i = 0; i < length; i++, addr++) { - auto entry = data_.find(addr); - if (entry != data_.end()) { - entry->second = value; - } else { - data_.insert({addr, value}); - } - } -} - -void MemoryFake::SetMemory(uint64_t addr, const void* memory, size_t length) { - const uint8_t* src = reinterpret_cast(memory); - for (size_t i = 0; i < length; i++, addr++) { - auto value = data_.find(addr); - if (value != data_.end()) { - value->second = src[i]; - } else { - data_.insert({ addr, src[i] }); - } - } -} - -size_t MemoryFake::Read(uint64_t addr, void* memory, size_t size) { - uint8_t* dst = reinterpret_cast(memory); - for (size_t i = 0; i < size; i++, addr++) { - auto value = data_.find(addr); - if (value == data_.end()) { - return i; - } - dst[i] = value->second; - } - return size; -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/MemoryFake.h b/libunwindstack/tests/MemoryFake.h deleted file mode 100644 index 20610a5e9..000000000 --- a/libunwindstack/tests/MemoryFake.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2016 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_TESTS_MEMORY_FAKE_H -#define _LIBUNWINDSTACK_TESTS_MEMORY_FAKE_H - -#include - -#include -#include -#include - -#include - -namespace unwindstack { - -class MemoryFake : public Memory { - public: - MemoryFake() = default; - virtual ~MemoryFake() = default; - - size_t Read(uint64_t addr, void* buffer, size_t size) override; - - void SetMemory(uint64_t addr, const void* memory, size_t length); - - void SetMemoryBlock(uint64_t addr, size_t length, uint8_t value); - - void SetData8(uint64_t addr, uint8_t value) { - SetMemory(addr, &value, sizeof(value)); - } - - void SetData16(uint64_t addr, uint16_t value) { - SetMemory(addr, &value, sizeof(value)); - } - - void SetData32(uint64_t addr, uint32_t value) { - SetMemory(addr, &value, sizeof(value)); - } - - void SetData64(uint64_t addr, uint64_t value) { - SetMemory(addr, &value, sizeof(value)); - } - - void SetMemory(uint64_t addr, std::vector values) { - SetMemory(addr, values.data(), values.size()); - } - - void SetMemory(uint64_t addr, std::string string) { - SetMemory(addr, string.c_str(), string.size() + 1); - } - - void Clear() { data_.clear(); } - - private: - std::unordered_map data_; -}; - -class MemoryFakeAlwaysReadZero : public Memory { - public: - MemoryFakeAlwaysReadZero() = default; - virtual ~MemoryFakeAlwaysReadZero() = default; - - size_t Read(uint64_t, void* buffer, size_t size) override { - memset(buffer, 0, size); - return size; - } -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_TESTS_MEMORY_FAKE_H diff --git a/libunwindstack/tests/MemoryFileTest.cpp b/libunwindstack/tests/MemoryFileTest.cpp deleted file mode 100644 index 4124a491c..000000000 --- a/libunwindstack/tests/MemoryFileTest.cpp +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright (C) 2016 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 "MemoryFileAtOffset.h" - -namespace unwindstack { - -class MemoryFileTest : public ::testing::Test { - protected: - void SetUp() override { - tf_ = new TemporaryFile; - } - - void TearDown() override { - delete tf_; - } - - void WriteTestData() { - ASSERT_TRUE(android::base::WriteStringToFd("0123456789abcdefghijklmnopqrstuvxyz", tf_->fd)); - } - - MemoryFileAtOffset memory_; - - TemporaryFile* tf_ = nullptr; -}; - -TEST_F(MemoryFileTest, init_offset_0) { - WriteTestData(); - - ASSERT_TRUE(memory_.Init(tf_->path, 0)); - std::vector buffer(11); - ASSERT_TRUE(memory_.ReadFully(0, buffer.data(), 10)); - buffer[10] = '\0'; - ASSERT_STREQ("0123456789", buffer.data()); -} - -TEST_F(MemoryFileTest, init_offset_non_zero) { - WriteTestData(); - - ASSERT_TRUE(memory_.Init(tf_->path, 10)); - std::vector buffer(11); - ASSERT_TRUE(memory_.ReadFully(0, buffer.data(), 10)); - buffer[10] = '\0'; - ASSERT_STREQ("abcdefghij", buffer.data()); -} - -TEST_F(MemoryFileTest, init_offset_non_zero_larger_than_pagesize) { - size_t pagesize = getpagesize(); - std::string large_string; - for (size_t i = 0; i < pagesize; i++) { - large_string += '1'; - } - large_string += "012345678901234abcdefgh"; - ASSERT_TRUE(android::base::WriteStringToFd(large_string, tf_->fd)); - - ASSERT_TRUE(memory_.Init(tf_->path, pagesize + 15)); - std::vector buffer(9); - ASSERT_TRUE(memory_.ReadFully(0, buffer.data(), 8)); - buffer[8] = '\0'; - ASSERT_STREQ("abcdefgh", buffer.data()); -} - -TEST_F(MemoryFileTest, init_offset_pagesize_aligned) { - size_t pagesize = getpagesize(); - std::string data; - for (size_t i = 0; i < 2 * pagesize; i++) { - data += static_cast((i / pagesize) + '0'); - data += static_cast((i % 10) + '0'); - } - ASSERT_TRUE(android::base::WriteStringToFd(data, tf_->fd)); - - ASSERT_TRUE(memory_.Init(tf_->path, 2 * pagesize)); - std::vector buffer(11); - ASSERT_TRUE(memory_.ReadFully(0, buffer.data(), 10)); - buffer[10] = '\0'; - std::string expected_str; - for (size_t i = 0; i < 5; i++) { - expected_str += '1'; - expected_str += static_cast(((i + pagesize) % 10) + '0'); - } - ASSERT_STREQ(expected_str.c_str(), buffer.data()); -} - -TEST_F(MemoryFileTest, init_offset_pagesize_aligned_plus_extra) { - size_t pagesize = getpagesize(); - std::string data; - for (size_t i = 0; i < 2 * pagesize; i++) { - data += static_cast((i / pagesize) + '0'); - data += static_cast((i % 10) + '0'); - } - ASSERT_TRUE(android::base::WriteStringToFd(data, tf_->fd)); - - ASSERT_TRUE(memory_.Init(tf_->path, 2 * pagesize + 10)); - std::vector buffer(11); - ASSERT_TRUE(memory_.ReadFully(0, buffer.data(), 10)); - buffer[10] = '\0'; - std::string expected_str; - for (size_t i = 0; i < 5; i++) { - expected_str += '1'; - expected_str += static_cast(((i + pagesize + 5) % 10) + '0'); - } - ASSERT_STREQ(expected_str.c_str(), buffer.data()); -} - -TEST_F(MemoryFileTest, init_offset_greater_than_filesize) { - size_t pagesize = getpagesize(); - std::string data; - uint64_t file_size = 2 * pagesize + pagesize / 2; - for (size_t i = 0; i < file_size; i++) { - data += static_cast((i / pagesize) + '0'); - } - ASSERT_TRUE(android::base::WriteStringToFd(data, tf_->fd)); - - // Check offset > file size fails and aligned_offset > file size. - ASSERT_FALSE(memory_.Init(tf_->path, file_size + 2 * pagesize)); - // Check offset == filesize fails. - ASSERT_FALSE(memory_.Init(tf_->path, file_size)); - // Check aligned_offset < filesize, but offset > filesize fails. - ASSERT_FALSE(memory_.Init(tf_->path, 2 * pagesize + pagesize / 2 + pagesize / 4)); -} - -TEST_F(MemoryFileTest, read_error) { - std::string data; - for (size_t i = 0; i < 5000; i++) { - data += static_cast((i % 10) + '0'); - } - ASSERT_TRUE(android::base::WriteStringToFd(data, tf_->fd)); - - std::vector buffer(100); - - // Read before init. - ASSERT_FALSE(memory_.ReadFully(0, buffer.data(), 10)); - - ASSERT_TRUE(memory_.Init(tf_->path, 0)); - - ASSERT_FALSE(memory_.ReadFully(10000, buffer.data(), 10)); - ASSERT_FALSE(memory_.ReadFully(5000, buffer.data(), 10)); - ASSERT_FALSE(memory_.ReadFully(4990, buffer.data(), 11)); - ASSERT_TRUE(memory_.ReadFully(4990, buffer.data(), 10)); - ASSERT_FALSE(memory_.ReadFully(4999, buffer.data(), 2)); - ASSERT_TRUE(memory_.ReadFully(4999, buffer.data(), 1)); - - // Check that overflow fails properly. - ASSERT_FALSE(memory_.ReadFully(UINT64_MAX - 100, buffer.data(), 200)); -} - -TEST_F(MemoryFileTest, read_past_file_within_mapping) { - size_t pagesize = getpagesize(); - - ASSERT_TRUE(pagesize > 100); - std::vector buffer(pagesize - 100); - for (size_t i = 0; i < pagesize - 100; i++) { - buffer[i] = static_cast((i % 0x5e) + 0x20); - } - ASSERT_TRUE(android::base::WriteFully(tf_->fd, buffer.data(), buffer.size())); - - ASSERT_TRUE(memory_.Init(tf_->path, 0)); - - for (size_t i = 0; i < 100; i++) { - uint8_t value; - ASSERT_FALSE(memory_.ReadFully(buffer.size() + i, &value, 1)) - << "Should have failed at value " << i; - } -} - -TEST_F(MemoryFileTest, map_partial_offset_aligned) { - size_t pagesize = getpagesize(); - std::vector buffer(pagesize * 10); - for (size_t i = 0; i < pagesize * 10; i++) { - buffer[i] = i / pagesize + 1; - } - ASSERT_TRUE(android::base::WriteFully(tf_->fd, buffer.data(), buffer.size())); - - // Map in only two pages of the data, and after the first page. - ASSERT_TRUE(memory_.Init(tf_->path, pagesize, pagesize * 2)); - - std::vector read_buffer(pagesize * 2); - // Make sure that reading after mapped data is a failure. - ASSERT_FALSE(memory_.ReadFully(pagesize * 2, read_buffer.data(), 1)); - ASSERT_TRUE(memory_.ReadFully(0, read_buffer.data(), pagesize * 2)); - for (size_t i = 0; i < pagesize; i++) { - ASSERT_EQ(2, read_buffer[i]) << "Failed at byte " << i; - } - for (size_t i = pagesize; i < pagesize * 2; i++) { - ASSERT_EQ(3, read_buffer[i]) << "Failed at byte " << i; - } -} - -TEST_F(MemoryFileTest, map_partial_offset_unaligned) { - size_t pagesize = getpagesize(); - ASSERT_TRUE(pagesize > 0x100); - std::vector buffer(pagesize * 10); - for (size_t i = 0; i < buffer.size(); i++) { - buffer[i] = i / pagesize + 1; - } - ASSERT_TRUE(android::base::WriteFully(tf_->fd, buffer.data(), buffer.size())); - - // Map in only two pages of the data, and after the first page. - ASSERT_TRUE(memory_.Init(tf_->path, pagesize + 0x100, pagesize * 2)); - - std::vector read_buffer(pagesize * 2); - // Make sure that reading after mapped data is a failure. - ASSERT_FALSE(memory_.ReadFully(pagesize * 2, read_buffer.data(), 1)); - ASSERT_TRUE(memory_.ReadFully(0, read_buffer.data(), pagesize * 2)); - for (size_t i = 0; i < pagesize - 0x100; i++) { - ASSERT_EQ(2, read_buffer[i]) << "Failed at byte " << i; - } - for (size_t i = pagesize - 0x100; i < 2 * pagesize - 0x100; i++) { - ASSERT_EQ(3, read_buffer[i]) << "Failed at byte " << i; - } - for (size_t i = 2 * pagesize - 0x100; i < pagesize * 2; i++) { - ASSERT_EQ(4, read_buffer[i]) << "Failed at byte " << i; - } -} - -TEST_F(MemoryFileTest, map_overflow) { - size_t pagesize = getpagesize(); - ASSERT_TRUE(pagesize > 0x100); - std::vector buffer(pagesize * 10); - for (size_t i = 0; i < buffer.size(); i++) { - buffer[i] = i / pagesize + 1; - } - ASSERT_TRUE(android::base::WriteFully(tf_->fd, buffer.data(), buffer.size())); - - // Map in only two pages of the data, and after the first page. - ASSERT_TRUE(memory_.Init(tf_->path, pagesize + 0x100, UINT64_MAX)); - - std::vector read_buffer(pagesize * 10); - ASSERT_FALSE(memory_.ReadFully(pagesize * 9 - 0x100 + 1, read_buffer.data(), 1)); - ASSERT_TRUE(memory_.ReadFully(0, read_buffer.data(), pagesize * 9 - 0x100)); -} - -TEST_F(MemoryFileTest, init_reinit) { - size_t pagesize = getpagesize(); - std::vector buffer(pagesize * 2); - for (size_t i = 0; i < buffer.size(); i++) { - buffer[i] = i / pagesize + 1; - } - ASSERT_TRUE(android::base::WriteFully(tf_->fd, buffer.data(), buffer.size())); - - ASSERT_TRUE(memory_.Init(tf_->path, 0)); - std::vector read_buffer(buffer.size()); - ASSERT_TRUE(memory_.ReadFully(0, read_buffer.data(), pagesize)); - for (size_t i = 0; i < pagesize; i++) { - ASSERT_EQ(1, read_buffer[i]) << "Failed at byte " << i; - } - - // Now reinit. - ASSERT_TRUE(memory_.Init(tf_->path, pagesize)); - ASSERT_TRUE(memory_.ReadFully(0, read_buffer.data(), pagesize)); - for (size_t i = 0; i < pagesize; i++) { - ASSERT_EQ(2, read_buffer[i]) << "Failed at byte " << i; - } -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/MemoryLocalTest.cpp b/libunwindstack/tests/MemoryLocalTest.cpp deleted file mode 100644 index c9e5dc0fd..000000000 --- a/libunwindstack/tests/MemoryLocalTest.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2017 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 "MemoryLocal.h" - -namespace unwindstack { - -TEST(MemoryLocalTest, read) { - std::vector src(1024); - memset(src.data(), 0x4c, 1024); - - MemoryLocal local; - - std::vector dst(1024); - ASSERT_TRUE(local.ReadFully(reinterpret_cast(src.data()), dst.data(), 1024)); - ASSERT_EQ(0, memcmp(src.data(), dst.data(), 1024)); - for (size_t i = 0; i < 1024; i++) { - ASSERT_EQ(0x4cU, dst[i]); - } - - memset(src.data(), 0x23, 512); - ASSERT_TRUE(local.ReadFully(reinterpret_cast(src.data()), dst.data(), 1024)); - ASSERT_EQ(0, memcmp(src.data(), dst.data(), 1024)); - for (size_t i = 0; i < 512; i++) { - ASSERT_EQ(0x23U, dst[i]); - } - for (size_t i = 512; i < 1024; i++) { - ASSERT_EQ(0x4cU, dst[i]); - } -} - -TEST(MemoryLocalTest, read_illegal) { - MemoryLocal local; - - std::vector dst(100); - ASSERT_FALSE(local.ReadFully(0, dst.data(), 1)); - ASSERT_FALSE(local.ReadFully(0, dst.data(), 100)); -} - -TEST(MemoryLocalTest, read_overflow) { - MemoryLocal local; - - // On 32 bit this test doesn't necessarily cause an overflow. The 64 bit - // version will always go through the overflow check. - std::vector dst(100); - uint64_t value; - ASSERT_FALSE(local.ReadFully(reinterpret_cast(&value), dst.data(), SIZE_MAX)); -} - -TEST(MemoryLocalTest, Read) { - char* mapping = static_cast( - mmap(nullptr, 2 * getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); - - ASSERT_NE(MAP_FAILED, mapping); - - mprotect(mapping + getpagesize(), getpagesize(), PROT_NONE); - memset(mapping + getpagesize() - 1024, 0x4c, 1024); - - MemoryLocal local; - - std::vector dst(4096); - ASSERT_EQ(1024U, local.Read(reinterpret_cast(mapping + getpagesize() - 1024), - dst.data(), 4096)); - for (size_t i = 0; i < 1024; i++) { - ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i; - } - - ASSERT_EQ(0, munmap(mapping, 2 * getpagesize())); -} - -TEST(MemoryLocalTest, read_hole) { - void* mapping = - mmap(nullptr, 3 * 4096, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - ASSERT_NE(MAP_FAILED, mapping); - memset(mapping, 0xFF, 3 * 4096); - mprotect(static_cast(mapping) + 4096, 4096, PROT_NONE); - - MemoryLocal local; - std::vector dst(4096 * 3, 0xCC); - ASSERT_EQ(4096U, local.Read(reinterpret_cast(mapping), dst.data(), 4096 * 3)); - for (size_t i = 0; i < 4096; ++i) { - ASSERT_EQ(0xFF, dst[i]); - } - for (size_t i = 4096; i < 4096 * 3; ++i) { - ASSERT_EQ(0xCC, dst[i]); - } - ASSERT_EQ(0, munmap(mapping, 3 * 4096)); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/MemoryMteTest.cpp b/libunwindstack/tests/MemoryMteTest.cpp deleted file mode 100644 index 3ae322e35..000000000 --- a/libunwindstack/tests/MemoryMteTest.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2020 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. - */ - -#if defined(ANDROID_EXPERIMENTAL_MTE) - -#include -#include - -#include - -#include - -#include "MemoryLocal.h" -#include "MemoryRemote.h" -#include "TestUtils.h" - -namespace unwindstack { - -static uintptr_t CreateTagMapping() { - uintptr_t mapping = - reinterpret_cast(mmap(nullptr, getpagesize(), PROT_READ | PROT_WRITE | PROT_MTE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); - if (reinterpret_cast(mapping) == MAP_FAILED) { - return 0; - } -#if defined(__aarch64__) - __asm__ __volatile__(".arch_extension mte; stg %0, [%0]" - : - : "r"(mapping + (1ULL << 56)) - : "memory"); -#endif - return mapping; -} - -TEST(MemoryMteTest, remote_read_tag) { -#if !defined(__aarch64__) - GTEST_SKIP() << "Requires aarch64"; -#else - if (!mte_supported()) { - GTEST_SKIP() << "Requires MTE"; - } -#endif - - uintptr_t mapping = CreateTagMapping(); - ASSERT_NE(0U, mapping); - - pid_t pid; - if ((pid = fork()) == 0) { - while (true) - ; - exit(1); - } - ASSERT_LT(0, pid); - TestScopedPidReaper reap(pid); - - ASSERT_TRUE(TestAttach(pid)); - - MemoryRemote remote(pid); - - EXPECT_EQ(1, remote.ReadTag(mapping)); - EXPECT_EQ(0, remote.ReadTag(mapping + 16)); - - ASSERT_TRUE(TestDetach(pid)); -} - -TEST(MemoryMteTest, local_read_tag) { -#if !defined(__aarch64__) - GTEST_SKIP() << "Requires aarch64"; -#else - if (!mte_supported()) { - GTEST_SKIP() << "Requires MTE"; - } -#endif - - uintptr_t mapping = CreateTagMapping(); - ASSERT_NE(0U, mapping); - - MemoryLocal local; - - EXPECT_EQ(1, local.ReadTag(mapping)); - EXPECT_EQ(0, local.ReadTag(mapping + 16)); -} - -} // namespace unwindstack - -#endif diff --git a/libunwindstack/tests/MemoryOfflineBufferTest.cpp b/libunwindstack/tests/MemoryOfflineBufferTest.cpp deleted file mode 100644 index 953170848..000000000 --- a/libunwindstack/tests/MemoryOfflineBufferTest.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2018 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 "LogFake.h" -#include "MemoryOfflineBuffer.h" - -namespace unwindstack { - -class MemoryOfflineBufferTest : public ::testing::Test { - protected: - void SetUp() override { - ResetLogs(); - memory_.reset(new MemoryOfflineBuffer(buffer_.data(), kStart, kEnd)); - } - - static void SetUpTestSuite() { - buffer_.resize(kLength); - for (size_t i = 0; i < kLength; i++) { - buffer_[i] = i % 189; - } - } - - std::unique_ptr memory_; - - static constexpr size_t kLength = 0x2000; - static constexpr uint64_t kStart = 0x1000; - static constexpr uint64_t kEnd = kStart + kLength; - static std::vector buffer_; -}; - -std::vector MemoryOfflineBufferTest::buffer_; - -static void VerifyBuffer(uint8_t* buffer, size_t start_value, size_t length) { - for (size_t i = 0; i < length; i++) { - ASSERT_EQ((start_value + i) % 189, buffer[i]) << "Failed at byte " << i; - } -} - -TEST_F(MemoryOfflineBufferTest, read_out_of_bounds) { - std::vector buffer(1024); - ASSERT_FALSE(memory_->ReadFully(0, buffer.data(), 1)); - ASSERT_FALSE(memory_->ReadFully(0xfff, buffer.data(), 1)); - ASSERT_FALSE(memory_->ReadFully(0xfff, buffer.data(), 2)); - ASSERT_FALSE(memory_->ReadFully(0x3000, buffer.data(), 1)); - ASSERT_FALSE(memory_->ReadFully(0x3001, buffer.data(), 1)); -} - -TEST_F(MemoryOfflineBufferTest, read) { - std::vector buffer(1024); - ASSERT_TRUE(memory_->ReadFully(kStart, buffer.data(), 10)); - ASSERT_NO_FATAL_FAILURE(VerifyBuffer(buffer.data(), 0, 10)); - - ASSERT_TRUE(memory_->ReadFully(kStart + 555, buffer.data(), 40)); - ASSERT_NO_FATAL_FAILURE(VerifyBuffer(buffer.data(), 555, 40)); - - ASSERT_TRUE(memory_->ReadFully(kStart + kLength - 105, buffer.data(), 105)); - ASSERT_NO_FATAL_FAILURE(VerifyBuffer(buffer.data(), kLength - 105, 105)); -} - -TEST_F(MemoryOfflineBufferTest, read_past_end) { - std::vector buffer(1024); - ASSERT_EQ(100U, memory_->Read(kStart + kLength - 100, buffer.data(), buffer.size())); - VerifyBuffer(buffer.data(), kLength - 100, 100); -} - -TEST_F(MemoryOfflineBufferTest, read_after_reset) { - std::vector buffer(1024); - ASSERT_TRUE(memory_->ReadFully(kStart, buffer.data(), 100)); - ASSERT_NO_FATAL_FAILURE(VerifyBuffer(buffer.data(), 0, 100)); - - memory_->Reset(&buffer_[10], 0x12000, 0x13000); - ASSERT_TRUE(memory_->ReadFully(0x12000, buffer.data(), 100)); - ASSERT_NO_FATAL_FAILURE(VerifyBuffer(buffer.data(), 10, 100)); - - ASSERT_EQ(50U, memory_->Read(0x13000 - 50, buffer.data(), buffer.size())); - ASSERT_NO_FATAL_FAILURE(VerifyBuffer(buffer.data(), 0x1000 - 50 + 10, 50)); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/MemoryOfflineTest.cpp b/libunwindstack/tests/MemoryOfflineTest.cpp deleted file mode 100644 index d0c441ba5..000000000 --- a/libunwindstack/tests/MemoryOfflineTest.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2017 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 "MemoryOffline.h" - -namespace unwindstack { - -class MemoryOfflineTest : public ::testing::Test { - protected: - void SetUp() override { - for (size_t i = 0; i < 1024; ++i) { - data.push_back(i & 0xff); - } - - ASSERT_TRUE(android::base::WriteFully(temp_file.fd, &offset, sizeof(offset))); - ASSERT_TRUE(android::base::WriteFully(temp_file.fd, data.data(), data.size())); - - memory = std::make_unique(); - ASSERT_TRUE(memory != nullptr); - - ASSERT_TRUE(memory->Init(temp_file.path, 0)); - } - - TemporaryFile temp_file; - uint64_t offset = 4096; - std::vector data; - std::unique_ptr memory; -}; - -TEST_F(MemoryOfflineTest, read_boundaries) { - char buf = '\0'; - ASSERT_EQ(0U, memory->Read(offset - 1, &buf, 1)); - ASSERT_EQ(0U, memory->Read(offset + data.size(), &buf, 1)); - ASSERT_EQ(1U, memory->Read(offset, &buf, 1)); - ASSERT_EQ(buf, data.front()); - ASSERT_EQ(1U, memory->Read(offset + data.size() - 1, &buf, 1)); - ASSERT_EQ(buf, data.back()); -} - -TEST_F(MemoryOfflineTest, read_values) { - std::vector buf; - buf.resize(2 * data.size()); - ASSERT_EQ(data.size(), memory->Read(offset, buf.data(), buf.size())); - buf.resize(data.size()); - ASSERT_EQ(buf, data); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/MemoryRangeTest.cpp b/libunwindstack/tests/MemoryRangeTest.cpp deleted file mode 100644 index 2d4f141ab..000000000 --- a/libunwindstack/tests/MemoryRangeTest.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2017 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 "MemoryFake.h" -#include "MemoryRange.h" - -namespace unwindstack { - -class MemoryRangeTest : public ::testing::Test { - protected: - void SetUp() override { - process_memory_.reset(); - memory_fake_ = new MemoryFake; - process_memory_.reset(memory_fake_); - } - - std::shared_ptr process_memory_; - MemoryFake* memory_fake_ = nullptr; -}; - -TEST_F(MemoryRangeTest, read_fully) { - memory_fake_->SetMemoryBlock(9000, 2048, 0x4c); - - MemoryRange range(process_memory_, 9001, 1024, 0); - - std::vector dst(1024); - ASSERT_TRUE(range.ReadFully(0, dst.data(), dst.size())); - for (size_t i = 0; i < dst.size(); i++) { - ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i; - } -} - -TEST_F(MemoryRangeTest, read_fully_near_limit) { - memory_fake_->SetMemoryBlock(0, 8192, 0x4c); - - MemoryRange range(process_memory_, 1000, 1024, 0); - - std::vector dst(1024); - ASSERT_TRUE(range.ReadFully(1020, dst.data(), 4)); - for (size_t i = 0; i < 4; i++) { - ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i; - } - - // Verify that reads outside of the range will fail. - ASSERT_FALSE(range.ReadFully(1020, dst.data(), 5)); - ASSERT_FALSE(range.ReadFully(1024, dst.data(), 1)); - ASSERT_FALSE(range.ReadFully(1024, dst.data(), 1024)); - - // Verify that reading up to the end works. - ASSERT_TRUE(range.ReadFully(1020, dst.data(), 4)); -} - -TEST_F(MemoryRangeTest, read_fully_overflow) { - std::vector buffer(100); - - std::shared_ptr process_memory(new MemoryFakeAlwaysReadZero); - std::unique_ptr overflow(new MemoryRange(process_memory, 100, 200, 0)); - ASSERT_FALSE(overflow->ReadFully(UINT64_MAX - 10, buffer.data(), 100)); -} - -TEST_F(MemoryRangeTest, read) { - memory_fake_->SetMemoryBlock(0, 4096, 0x4c); - - MemoryRange range(process_memory_, 1000, 1024, 0); - - std::vector dst(1024); - ASSERT_EQ(4U, range.Read(1020, dst.data(), dst.size())); - for (size_t i = 0; i < 4; i++) { - ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i; - } -} - -TEST_F(MemoryRangeTest, read_non_zero_offset) { - memory_fake_->SetMemoryBlock(1000, 1024, 0x12); - - MemoryRange range(process_memory_, 1000, 1024, 400); - - std::vector dst(1024); - ASSERT_EQ(1024U, range.Read(400, dst.data(), dst.size())); - for (size_t i = 0; i < dst.size(); i++) { - ASSERT_EQ(0x12U, dst[i]) << "Failed at byte " << i; - } -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/MemoryRangesTest.cpp b/libunwindstack/tests/MemoryRangesTest.cpp deleted file mode 100644 index e4e9fc4e9..000000000 --- a/libunwindstack/tests/MemoryRangesTest.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2018 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 "MemoryFake.h" -#include "MemoryRange.h" - -namespace unwindstack { - -class MemoryRangesTest : public ::testing::Test { - protected: - void SetUp() override { - MemoryFake* memory = new MemoryFake; - process_memory_.reset(memory); - memory->SetMemoryBlock(1000, 5000, 0x15); - memory->SetMemoryBlock(6000, 12000, 0x26); - memory->SetMemoryBlock(14000, 20000, 0x37); - memory->SetMemoryBlock(20000, 22000, 0x48); - - ranges_.reset(new MemoryRanges); - ranges_->Insert(new MemoryRange(process_memory_, 15000, 100, 4000)); - ranges_->Insert(new MemoryRange(process_memory_, 10000, 2000, 2000)); - ranges_->Insert(new MemoryRange(process_memory_, 3000, 1000, 0)); - ranges_->Insert(new MemoryRange(process_memory_, 19000, 1000, 6000)); - ranges_->Insert(new MemoryRange(process_memory_, 20000, 1000, 7000)); - } - - std::shared_ptr process_memory_; - std::unique_ptr ranges_; -}; - -TEST_F(MemoryRangesTest, read) { - std::vector dst(2000); - size_t bytes = ranges_->Read(0, dst.data(), dst.size()); - ASSERT_EQ(1000UL, bytes); - for (size_t i = 0; i < bytes; i++) { - ASSERT_EQ(0x15U, dst[i]) << "Failed at byte " << i; - } - - bytes = ranges_->Read(2000, dst.data(), dst.size()); - ASSERT_EQ(2000UL, bytes); - for (size_t i = 0; i < bytes; i++) { - ASSERT_EQ(0x26U, dst[i]) << "Failed at byte " << i; - } - - bytes = ranges_->Read(4000, dst.data(), dst.size()); - ASSERT_EQ(100UL, bytes); - for (size_t i = 0; i < bytes; i++) { - ASSERT_EQ(0x37U, dst[i]) << "Failed at byte " << i; - } -} - -TEST_F(MemoryRangesTest, read_fail) { - std::vector dst(4096); - ASSERT_EQ(0UL, ranges_->Read(1000, dst.data(), dst.size())); - ASSERT_EQ(0UL, ranges_->Read(5000, dst.data(), dst.size())); - ASSERT_EQ(0UL, ranges_->Read(8000, dst.data(), dst.size())); -} - -TEST_F(MemoryRangesTest, read_across_ranges) { - // The MemoryRanges object does not support reading across a range, - // so this will only read in the first range. - std::vector dst(4096); - size_t bytes = ranges_->Read(6000, dst.data(), dst.size()); - ASSERT_EQ(1000UL, bytes); - for (size_t i = 0; i < bytes; i++) { - ASSERT_EQ(0x37U, dst[i]) << "Failed at byte " << i; - } -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/MemoryRemoteTest.cpp b/libunwindstack/tests/MemoryRemoteTest.cpp deleted file mode 100644 index 621893b1f..000000000 --- a/libunwindstack/tests/MemoryRemoteTest.cpp +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright (C) 2016 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 "MemoryRemote.h" - -#include "MemoryFake.h" -#include "TestUtils.h" - -namespace unwindstack { - -TEST(MemoryRemoteTest, read) { - std::vector src(1024); - memset(src.data(), 0x4c, 1024); - - pid_t pid; - if ((pid = fork()) == 0) { - while (true); - exit(1); - } - ASSERT_LT(0, pid); - TestScopedPidReaper reap(pid); - - ASSERT_TRUE(TestAttach(pid)); - - MemoryRemote remote(pid); - - std::vector dst(1024); - ASSERT_TRUE(remote.ReadFully(reinterpret_cast(src.data()), dst.data(), 1024)); - for (size_t i = 0; i < 1024; i++) { - ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i; - } - - ASSERT_TRUE(TestDetach(pid)); -} - -TEST(MemoryRemoteTest, read_large) { - static constexpr size_t kTotalPages = 245; - std::vector src(kTotalPages * getpagesize()); - for (size_t i = 0; i < kTotalPages; i++) { - memset(&src[i * getpagesize()], i, getpagesize()); - } - - pid_t pid; - if ((pid = fork()) == 0) { - while (true) - ; - exit(1); - } - ASSERT_LT(0, pid); - TestScopedPidReaper reap(pid); - - ASSERT_TRUE(TestAttach(pid)); - - MemoryRemote remote(pid); - - std::vector dst(kTotalPages * getpagesize()); - ASSERT_TRUE(remote.ReadFully(reinterpret_cast(src.data()), dst.data(), src.size())); - for (size_t i = 0; i < kTotalPages * getpagesize(); i++) { - ASSERT_EQ(i / getpagesize(), dst[i]) << "Failed at byte " << i; - } - - ASSERT_TRUE(TestDetach(pid)); -} - -TEST(MemoryRemoteTest, read_partial) { - char* mapping = static_cast( - mmap(nullptr, 4 * getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); - ASSERT_NE(MAP_FAILED, mapping); - memset(mapping, 0x4c, 4 * getpagesize()); - ASSERT_EQ(0, mprotect(mapping + getpagesize(), getpagesize(), PROT_NONE)); - ASSERT_EQ(0, munmap(mapping + 3 * getpagesize(), getpagesize())); - - pid_t pid; - if ((pid = fork()) == 0) { - while (true) - ; - exit(1); - } - ASSERT_LT(0, pid); - TestScopedPidReaper reap(pid); - - // Unmap from our process. - ASSERT_EQ(0, munmap(mapping, 3 * getpagesize())); - - ASSERT_TRUE(TestAttach(pid)); - - MemoryRemote remote(pid); - - std::vector dst(4096); - size_t bytes = - remote.Read(reinterpret_cast(mapping + getpagesize() - 1024), dst.data(), 4096); - // Some read methods can read PROT_NONE maps, allow that. - ASSERT_LE(1024U, bytes); - for (size_t i = 0; i < bytes; i++) { - ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i; - } - - // Now verify that reading stops at the end of a map. - bytes = - remote.Read(reinterpret_cast(mapping + 3 * getpagesize() - 1024), dst.data(), 4096); - ASSERT_EQ(1024U, bytes); - for (size_t i = 0; i < bytes; i++) { - ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i; - } - - ASSERT_TRUE(TestDetach(pid)); -} - -TEST(MemoryRemoteTest, read_fail) { - int pagesize = getpagesize(); - void* src = mmap(nullptr, pagesize * 2, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,-1, 0); - memset(src, 0x4c, pagesize * 2); - ASSERT_NE(MAP_FAILED, src); - // Put a hole right after the first page. - ASSERT_EQ(0, munmap(reinterpret_cast(reinterpret_cast(src) + pagesize), - pagesize)); - - pid_t pid; - if ((pid = fork()) == 0) { - while (true); - exit(1); - } - ASSERT_LT(0, pid); - TestScopedPidReaper reap(pid); - - ASSERT_TRUE(TestAttach(pid)); - - MemoryRemote remote(pid); - - std::vector dst(pagesize); - ASSERT_TRUE(remote.ReadFully(reinterpret_cast(src), dst.data(), pagesize)); - for (size_t i = 0; i < 1024; i++) { - ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i; - } - - ASSERT_FALSE(remote.ReadFully(reinterpret_cast(src) + pagesize, dst.data(), 1)); - ASSERT_TRUE(remote.ReadFully(reinterpret_cast(src) + pagesize - 1, dst.data(), 1)); - ASSERT_FALSE(remote.ReadFully(reinterpret_cast(src) + pagesize - 4, dst.data(), 8)); - - // Check overflow condition is caught properly. - ASSERT_FALSE(remote.ReadFully(UINT64_MAX - 100, dst.data(), 200)); - - ASSERT_EQ(0, munmap(src, pagesize)); - - ASSERT_TRUE(TestDetach(pid)); -} - -TEST(MemoryRemoteTest, read_overflow) { - pid_t pid; - if ((pid = fork()) == 0) { - while (true) - ; - exit(1); - } - ASSERT_LT(0, pid); - TestScopedPidReaper reap(pid); - - ASSERT_TRUE(TestAttach(pid)); - - MemoryRemote remote(pid); - - // Check overflow condition is caught properly. - std::vector dst(200); - ASSERT_FALSE(remote.ReadFully(UINT64_MAX - 100, dst.data(), 200)); - - ASSERT_TRUE(TestDetach(pid)); -} - -TEST(MemoryRemoteTest, read_illegal) { - pid_t pid; - if ((pid = fork()) == 0) { - while (true); - exit(1); - } - ASSERT_LT(0, pid); - TestScopedPidReaper reap(pid); - - ASSERT_TRUE(TestAttach(pid)); - - MemoryRemote remote(pid); - - std::vector dst(100); - ASSERT_FALSE(remote.ReadFully(0, dst.data(), 1)); - ASSERT_FALSE(remote.ReadFully(0, dst.data(), 100)); - - ASSERT_TRUE(TestDetach(pid)); -} - -TEST(MemoryRemoteTest, read_mprotect_hole) { - size_t page_size = getpagesize(); - void* mapping = - mmap(nullptr, 3 * getpagesize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - ASSERT_NE(MAP_FAILED, mapping); - memset(mapping, 0xFF, 3 * page_size); - ASSERT_EQ(0, mprotect(static_cast(mapping) + page_size, page_size, PROT_NONE)); - - pid_t pid; - if ((pid = fork()) == 0) { - while (true); - exit(1); - } - ASSERT_LT(0, pid); - TestScopedPidReaper reap(pid); - - ASSERT_EQ(0, munmap(mapping, 3 * page_size)); - - ASSERT_TRUE(TestAttach(pid)); - - MemoryRemote remote(pid); - std::vector dst(getpagesize() * 4, 0xCC); - size_t read_size = remote.Read(reinterpret_cast(mapping), dst.data(), page_size * 3); - // Some read methods can read PROT_NONE maps, allow that. - ASSERT_LE(page_size, read_size); - for (size_t i = 0; i < read_size; ++i) { - ASSERT_EQ(0xFF, dst[i]); - } - for (size_t i = read_size; i < dst.size(); ++i) { - ASSERT_EQ(0xCC, dst[i]); - } - - ASSERT_TRUE(TestDetach(pid)); -} - -TEST(MemoryRemoteTest, read_munmap_hole) { - size_t page_size = getpagesize(); - void* mapping = - mmap(nullptr, 3 * getpagesize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - ASSERT_NE(MAP_FAILED, mapping); - memset(mapping, 0xFF, 3 * page_size); - ASSERT_EQ(0, munmap(static_cast(mapping) + page_size, page_size)); - - pid_t pid; - if ((pid = fork()) == 0) { - while (true) - ; - exit(1); - } - ASSERT_LT(0, pid); - TestScopedPidReaper reap(pid); - - ASSERT_EQ(0, munmap(mapping, page_size)); - ASSERT_EQ(0, munmap(static_cast(mapping) + 2 * page_size, page_size)); - - ASSERT_TRUE(TestAttach(pid)); - - MemoryRemote remote(pid); - std::vector dst(getpagesize() * 4, 0xCC); - size_t read_size = remote.Read(reinterpret_cast(mapping), dst.data(), page_size * 3); - ASSERT_EQ(page_size, read_size); - for (size_t i = 0; i < read_size; ++i) { - ASSERT_EQ(0xFF, dst[i]); - } - for (size_t i = read_size; i < dst.size(); ++i) { - ASSERT_EQ(0xCC, dst[i]); - } - - ASSERT_TRUE(TestDetach(pid)); -} - -// Verify that the memory remote object chooses a memory read function -// properly. Either process_vm_readv or ptrace. -TEST(MemoryRemoteTest, read_choose_correctly) { - size_t page_size = getpagesize(); - void* mapping = - mmap(nullptr, 2 * getpagesize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - ASSERT_NE(MAP_FAILED, mapping); - memset(mapping, 0xFC, 2 * page_size); - ASSERT_EQ(0, mprotect(static_cast(mapping), page_size, PROT_NONE)); - - pid_t pid; - if ((pid = fork()) == 0) { - while (true) - ; - exit(1); - } - ASSERT_LT(0, pid); - TestScopedPidReaper reap(pid); - - ASSERT_EQ(0, munmap(mapping, 2 * page_size)); - - ASSERT_TRUE(TestAttach(pid)); - - // We know that process_vm_readv of a mprotect'd PROT_NONE region will fail. - // Read from the PROT_NONE area first to force the choice of ptrace. - MemoryRemote remote_ptrace(pid); - uint32_t value; - size_t bytes = remote_ptrace.Read(reinterpret_cast(mapping), &value, sizeof(value)); - ASSERT_EQ(sizeof(value), bytes); - ASSERT_EQ(0xfcfcfcfcU, value); - bytes = remote_ptrace.Read(reinterpret_cast(mapping) + page_size, &value, sizeof(value)); - ASSERT_EQ(sizeof(value), bytes); - ASSERT_EQ(0xfcfcfcfcU, value); - bytes = remote_ptrace.Read(reinterpret_cast(mapping), &value, sizeof(value)); - ASSERT_EQ(sizeof(value), bytes); - ASSERT_EQ(0xfcfcfcfcU, value); - - // Now verify that choosing process_vm_readv results in failing reads of - // the PROT_NONE part of the map. Read from a valid map first which - // should prefer process_vm_readv, and keep that as the read function. - MemoryRemote remote_readv(pid); - bytes = remote_readv.Read(reinterpret_cast(mapping) + page_size, &value, sizeof(value)); - ASSERT_EQ(sizeof(value), bytes); - ASSERT_EQ(0xfcfcfcfcU, value); - bytes = remote_readv.Read(reinterpret_cast(mapping), &value, sizeof(value)); - ASSERT_EQ(0U, bytes); - bytes = remote_readv.Read(reinterpret_cast(mapping) + page_size, &value, sizeof(value)); - ASSERT_EQ(sizeof(value), bytes); - ASSERT_EQ(0xfcfcfcfcU, value); - - ASSERT_TRUE(TestDetach(pid)); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/MemoryTest.cpp b/libunwindstack/tests/MemoryTest.cpp deleted file mode 100644 index 8a8eb24f5..000000000 --- a/libunwindstack/tests/MemoryTest.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2017 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 "MemoryFake.h" - -namespace unwindstack { - -TEST(MemoryTest, read32) { - MemoryFakeAlwaysReadZero memory; - - uint32_t data = 0xffffffff; - ASSERT_TRUE(memory.Read32(0, &data)); - ASSERT_EQ(0U, data); -} - -TEST(MemoryTest, read64) { - MemoryFakeAlwaysReadZero memory; - - uint64_t data = 0xffffffffffffffffULL; - ASSERT_TRUE(memory.Read64(0, &data)); - ASSERT_EQ(0U, data); -} - -struct FakeStruct { - int one; - bool two; - uint32_t three; - uint64_t four; -}; - -TEST(MemoryTest, read_string) { - std::string name("string_in_memory"); - - MemoryFake memory; - - memory.SetMemory(100, name.c_str(), name.size() + 1); - - std::string dst_name; - ASSERT_TRUE(memory.ReadString(100, &dst_name, 100)); - ASSERT_EQ("string_in_memory", dst_name); - - ASSERT_TRUE(memory.ReadString(107, &dst_name, 100)); - ASSERT_EQ("in_memory", dst_name); - - // Set size greater than string. - ASSERT_TRUE(memory.ReadString(107, &dst_name, 10)); - ASSERT_EQ("in_memory", dst_name); - - ASSERT_FALSE(memory.ReadString(107, &dst_name, 9)); -} - -TEST(MemoryTest, read_string_error) { - std::string name("short"); - - MemoryFake memory; - - // Save everything except the terminating '\0'. - memory.SetMemory(0, name.c_str(), name.size()); - - std::string dst_name; - // Read from a non-existant address. - ASSERT_FALSE(memory.ReadString(100, &dst_name, 100)); - - // This should fail because there is no terminating '\0'. - ASSERT_FALSE(memory.ReadString(0, &dst_name, 100)); - - // This should pass because there is a terminating '\0'. - memory.SetData8(name.size(), '\0'); - ASSERT_TRUE(memory.ReadString(0, &dst_name, 100)); - ASSERT_EQ("short", dst_name); -} - -TEST(MemoryTest, read_string_long) { - // This string should be greater than 768 characters long (greater than 3 times - // the buffer in the ReadString function) to read multiple blocks. - static constexpr char kLongString[] = - "one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen " - "sixteen seventeen eightteen nineteen twenty twenty-one twenty-two twenty-three twenty-four " - "twenty-five twenty-six twenty-seven twenty-eight twenty-nine thirty thirty-one thirty-two " - "thirty-three thirty-four thirty-five thirty-six thirty-seven thirty-eight thirty-nine forty " - "forty-one forty-two forty-three forty-four forty-five forty-size forty-seven forty-eight " - "forty-nine fifty fifty-one fifty-two fifty-three fifty-four fifty-five fifty-six " - "fifty-seven fifty-eight fifty-nine sixty sixty-one sixty-two sixty-three sixty-four " - "sixty-five sixty-six sixty-seven sixty-eight sixty-nine seventy seventy-one seventy-two " - "seventy-three seventy-four seventy-five seventy-six seventy-seven seventy-eight " - "seventy-nine eighty"; - - MemoryFake memory; - - memory.SetMemory(100, kLongString, sizeof(kLongString)); - - std::string dst_name; - ASSERT_TRUE(memory.ReadString(100, &dst_name, sizeof(kLongString))); - ASSERT_EQ(kLongString, dst_name); - - std::string expected_str(kLongString, 255); - memory.SetMemory(100, expected_str.data(), expected_str.length() + 1); - ASSERT_TRUE(memory.ReadString(100, &dst_name, 256)); - ASSERT_EQ(expected_str, dst_name); - ASSERT_FALSE(memory.ReadString(100, &dst_name, 255)); - - expected_str = std::string(kLongString, 256); - memory.SetMemory(100, expected_str.data(), expected_str.length() + 1); - ASSERT_TRUE(memory.ReadString(100, &dst_name, 257)); - ASSERT_EQ(expected_str, dst_name); - ASSERT_FALSE(memory.ReadString(100, &dst_name, 256)); - - expected_str = std::string(kLongString, 299); - memory.SetMemory(100, expected_str.data(), expected_str.length() + 1); - ASSERT_TRUE(memory.ReadString(100, &dst_name, 300)); - ASSERT_EQ(expected_str, dst_name); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/RegsFake.h b/libunwindstack/tests/RegsFake.h deleted file mode 100644 index f67d7dc61..000000000 --- a/libunwindstack/tests/RegsFake.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2016 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_TESTS_REGS_FAKE_H -#define _LIBUNWINDSTACK_TESTS_REGS_FAKE_H - -#include - -#include -#include -#include - -#include "Check.h" - -namespace unwindstack { - -class RegsFake : public Regs { - public: - RegsFake(uint16_t total_regs) : Regs(total_regs, Regs::Location(Regs::LOCATION_UNKNOWN, 0)) {} - virtual ~RegsFake() = default; - - ArchEnum Arch() override { return fake_arch_; } - void* RawData() override { return nullptr; } - uint64_t pc() override { return fake_pc_; } - uint64_t sp() override { return fake_sp_; } - void set_pc(uint64_t pc) override { fake_pc_ = pc; } - void set_sp(uint64_t sp) override { fake_sp_ = sp; } - - bool SetPcFromReturnAddress(Memory*) override { - if (!fake_return_address_valid_) { - return false; - } - fake_pc_ = fake_return_address_; - return true; - } - - void IterateRegisters(std::function) override {} - - bool Is32Bit() { - CHECK(fake_arch_ != ARCH_UNKNOWN); - return fake_arch_ == ARCH_ARM || fake_arch_ == ARCH_X86 || fake_arch_ == ARCH_MIPS; - } - - bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; } - - void FakeSetArch(ArchEnum arch) { fake_arch_ = arch; } - void FakeSetDexPc(uint64_t dex_pc) { dex_pc_ = dex_pc; } - void FakeSetReturnAddress(uint64_t return_address) { fake_return_address_ = return_address; } - void FakeSetReturnAddressValid(bool valid) { fake_return_address_valid_ = valid; } - - Regs* Clone() override { return nullptr; } - - private: - ArchEnum fake_arch_ = ARCH_UNKNOWN; - uint64_t fake_pc_ = 0; - uint64_t fake_sp_ = 0; - bool fake_return_address_valid_ = false; - uint64_t fake_return_address_ = 0; -}; - -template -class RegsImplFake : public RegsImpl { - public: - RegsImplFake(uint16_t total_regs) - : RegsImpl(total_regs, Regs::Location(Regs::LOCATION_UNKNOWN, 0)) {} - virtual ~RegsImplFake() = default; - - ArchEnum Arch() override { return ARCH_UNKNOWN; } - uint64_t pc() override { return fake_pc_; } - uint64_t sp() override { return fake_sp_; } - void set_pc(uint64_t pc) override { fake_pc_ = pc; } - void set_sp(uint64_t sp) override { fake_sp_ = sp; } - void set_pseudo_reg(uint64_t reg) { fake_pseudo_reg_ = reg; } - - bool SetPcFromReturnAddress(Memory*) override { return false; } - bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; } - - bool SetPseudoRegister(uint16_t reg, uint64_t value) override { - if (fake_pseudo_reg_ != reg) { - return false; - } - fake_pseudo_reg_value_ = value; - return true; - } - bool GetPseudoRegister(uint16_t reg, uint64_t* value) override { - if (fake_pseudo_reg_ != reg) { - return false; - } - *value = fake_pseudo_reg_value_; - return true; - } - - Regs* Clone() override { return nullptr; } - - private: - uint64_t fake_pc_ = 0; - uint64_t fake_sp_ = 0; - uint16_t fake_pseudo_reg_ = 0; - uint64_t fake_pseudo_reg_value_ = 0; -}; - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_TESTS_REGS_FAKE_H diff --git a/libunwindstack/tests/RegsInfoTest.cpp b/libunwindstack/tests/RegsInfoTest.cpp deleted file mode 100644 index a6bc2c5ae..000000000 --- a/libunwindstack/tests/RegsInfoTest.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2018 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 "RegsFake.h" -#include "RegsInfo.h" - -namespace unwindstack { - -TEST(RegsInfoTest, single_uint32_t) { - RegsImplFake regs(10); - RegsInfo info(®s); - - regs[1] = 0x100; - ASSERT_FALSE(info.IsSaved(1)); - ASSERT_EQ(0x100U, info.Get(1)); - ASSERT_EQ(10, info.Total()); - - uint32_t* value = info.Save(1); - ASSERT_EQ(value, ®s[1]); - regs[1] = 0x200; - ASSERT_TRUE(info.IsSaved(1)); - ASSERT_EQ(0x100U, info.Get(1)); - ASSERT_EQ(0x200U, regs[1]); -} - -TEST(RegsInfoTest, single_uint64_t) { - RegsImplFake regs(20); - RegsInfo info(®s); - - regs[3] = 0x300; - ASSERT_FALSE(info.IsSaved(3)); - ASSERT_EQ(0x300U, info.Get(3)); - ASSERT_EQ(20, info.Total()); - - uint64_t* value = info.Save(3); - ASSERT_EQ(value, ®s[3]); - regs[3] = 0x400; - ASSERT_TRUE(info.IsSaved(3)); - ASSERT_EQ(0x300U, info.Get(3)); - ASSERT_EQ(0x400U, regs[3]); -} - -TEST(RegsInfoTest, all) { - RegsImplFake regs(64); - RegsInfo info(®s); - - for (uint32_t i = 0; i < 64; i++) { - regs[i] = i * 0x100; - ASSERT_EQ(i * 0x100, info.Get(i)) << "Reg " + std::to_string(i) + " failed."; - } - - for (uint32_t i = 0; i < 64; i++) { - ASSERT_FALSE(info.IsSaved(i)) << "Reg " + std::to_string(i) + " failed."; - uint64_t* reg = info.Save(i); - ASSERT_EQ(reg, ®s[i]) << "Reg " + std::to_string(i) + " failed."; - *reg = i * 0x1000 + 0x100; - ASSERT_EQ(i * 0x1000 + 0x100, regs[i]) << "Reg " + std::to_string(i) + " failed."; - } - - for (uint32_t i = 0; i < 64; i++) { - ASSERT_TRUE(info.IsSaved(i)) << "Reg " + std::to_string(i) + " failed."; - ASSERT_EQ(i * 0x100, info.Get(i)) << "Reg " + std::to_string(i) + " failed."; - } -} - -TEST(RegsInfoTest, invalid_register) { - RegsImplFake regs(64); - RegsInfo info(®s); - - EXPECT_DEATH(info.Save(RegsInfo::MAX_REGISTERS), ""); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/RegsIterateTest.cpp b/libunwindstack/tests/RegsIterateTest.cpp deleted file mode 100644 index 47e605a82..000000000 --- a/libunwindstack/tests/RegsIterateTest.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (C) 2017 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 - -namespace unwindstack { - -struct Register { - std::string expected_name; - uint64_t offset; - - bool operator==(const Register& rhs) const { - return std::tie(expected_name, offset) == std::tie(rhs.expected_name, rhs.offset); - } -}; - -template -class RegsIterateTest : public ::testing::Test { -}; - -template -std::vector ExpectedRegisters(); - -template<> -std::vector ExpectedRegisters() { - std::vector result; - result.push_back({"r0", ARM_REG_R0}); - result.push_back({"r1", ARM_REG_R1}); - result.push_back({"r2", ARM_REG_R2}); - result.push_back({"r3", ARM_REG_R3}); - result.push_back({"r4", ARM_REG_R4}); - result.push_back({"r5", ARM_REG_R5}); - result.push_back({"r6", ARM_REG_R6}); - result.push_back({"r7", ARM_REG_R7}); - result.push_back({"r8", ARM_REG_R8}); - result.push_back({"r9", ARM_REG_R9}); - result.push_back({"r10", ARM_REG_R10}); - result.push_back({"r11", ARM_REG_R11}); - result.push_back({"ip", ARM_REG_R12}); - result.push_back({"sp", ARM_REG_SP}); - result.push_back({"lr", ARM_REG_LR}); - result.push_back({"pc", ARM_REG_PC}); - return result; -} - -template<> -std::vector ExpectedRegisters() { - std::vector result; - result.push_back({"x0", ARM64_REG_R0}); - result.push_back({"x1", ARM64_REG_R1}); - result.push_back({"x2", ARM64_REG_R2}); - result.push_back({"x3", ARM64_REG_R3}); - result.push_back({"x4", ARM64_REG_R4}); - result.push_back({"x5", ARM64_REG_R5}); - result.push_back({"x6", ARM64_REG_R6}); - result.push_back({"x7", ARM64_REG_R7}); - result.push_back({"x8", ARM64_REG_R8}); - result.push_back({"x9", ARM64_REG_R9}); - result.push_back({"x10", ARM64_REG_R10}); - result.push_back({"x11", ARM64_REG_R11}); - result.push_back({"x12", ARM64_REG_R12}); - result.push_back({"x13", ARM64_REG_R13}); - result.push_back({"x14", ARM64_REG_R14}); - result.push_back({"x15", ARM64_REG_R15}); - result.push_back({"x16", ARM64_REG_R16}); - result.push_back({"x17", ARM64_REG_R17}); - result.push_back({"x18", ARM64_REG_R18}); - result.push_back({"x19", ARM64_REG_R19}); - result.push_back({"x20", ARM64_REG_R20}); - result.push_back({"x21", ARM64_REG_R21}); - result.push_back({"x22", ARM64_REG_R22}); - result.push_back({"x23", ARM64_REG_R23}); - result.push_back({"x24", ARM64_REG_R24}); - result.push_back({"x25", ARM64_REG_R25}); - result.push_back({"x26", ARM64_REG_R26}); - result.push_back({"x27", ARM64_REG_R27}); - result.push_back({"x28", ARM64_REG_R28}); - result.push_back({"x29", ARM64_REG_R29}); - result.push_back({"lr", ARM64_REG_LR}); - result.push_back({"sp", ARM64_REG_SP}); - result.push_back({"pc", ARM64_REG_PC}); - result.push_back({"pst", ARM64_REG_PSTATE}); - return result; -} - -template<> -std::vector ExpectedRegisters() { - std::vector result; - result.push_back({"eax", X86_REG_EAX}); - result.push_back({"ebx", X86_REG_EBX}); - result.push_back({"ecx", X86_REG_ECX}); - result.push_back({"edx", X86_REG_EDX}); - result.push_back({"ebp", X86_REG_EBP}); - result.push_back({"edi", X86_REG_EDI}); - result.push_back({"esi", X86_REG_ESI}); - result.push_back({"esp", X86_REG_ESP}); - result.push_back({"eip", X86_REG_EIP}); - return result; -} - -template<> -std::vector ExpectedRegisters() { - std::vector result; - result.push_back({"rax", X86_64_REG_RAX}); - result.push_back({"rbx", X86_64_REG_RBX}); - result.push_back({"rcx", X86_64_REG_RCX}); - result.push_back({"rdx", X86_64_REG_RDX}); - result.push_back({"r8", X86_64_REG_R8}); - result.push_back({"r9", X86_64_REG_R9}); - result.push_back({"r10", X86_64_REG_R10}); - result.push_back({"r11", X86_64_REG_R11}); - result.push_back({"r12", X86_64_REG_R12}); - result.push_back({"r13", X86_64_REG_R13}); - result.push_back({"r14", X86_64_REG_R14}); - result.push_back({"r15", X86_64_REG_R15}); - result.push_back({"rdi", X86_64_REG_RDI}); - result.push_back({"rsi", X86_64_REG_RSI}); - result.push_back({"rbp", X86_64_REG_RBP}); - result.push_back({"rsp", X86_64_REG_RSP}); - result.push_back({"rip", X86_64_REG_RIP}); - return result; -} - -template<> -std::vector ExpectedRegisters() { - std::vector result; - result.push_back({"r0", MIPS_REG_R0}); - result.push_back({"r1", MIPS_REG_R1}); - result.push_back({"r2", MIPS_REG_R2}); - result.push_back({"r3", MIPS_REG_R3}); - result.push_back({"r4", MIPS_REG_R4}); - result.push_back({"r5", MIPS_REG_R5}); - result.push_back({"r6", MIPS_REG_R6}); - result.push_back({"r7", MIPS_REG_R7}); - result.push_back({"r8", MIPS_REG_R8}); - result.push_back({"r9", MIPS_REG_R9}); - result.push_back({"r10", MIPS_REG_R10}); - result.push_back({"r11", MIPS_REG_R11}); - result.push_back({"r12", MIPS_REG_R12}); - result.push_back({"r13", MIPS_REG_R13}); - result.push_back({"r14", MIPS_REG_R14}); - result.push_back({"r15", MIPS_REG_R15}); - result.push_back({"r16", MIPS_REG_R16}); - result.push_back({"r17", MIPS_REG_R17}); - result.push_back({"r18", MIPS_REG_R18}); - result.push_back({"r19", MIPS_REG_R19}); - result.push_back({"r20", MIPS_REG_R20}); - result.push_back({"r21", MIPS_REG_R21}); - result.push_back({"r22", MIPS_REG_R22}); - result.push_back({"r23", MIPS_REG_R23}); - result.push_back({"r24", MIPS_REG_R24}); - result.push_back({"r25", MIPS_REG_R25}); - result.push_back({"r26", MIPS_REG_R26}); - result.push_back({"r27", MIPS_REG_R27}); - result.push_back({"r28", MIPS_REG_R28}); - result.push_back({"sp", MIPS_REG_SP}); - result.push_back({"r30", MIPS_REG_R30}); - result.push_back({"ra", MIPS_REG_RA}); - result.push_back({"pc", MIPS_REG_PC}); - - return result; -} - -template<> -std::vector ExpectedRegisters() { - std::vector result; - result.push_back({"r0", MIPS64_REG_R0}); - result.push_back({"r1", MIPS64_REG_R1}); - result.push_back({"r2", MIPS64_REG_R2}); - result.push_back({"r3", MIPS64_REG_R3}); - result.push_back({"r4", MIPS64_REG_R4}); - result.push_back({"r5", MIPS64_REG_R5}); - result.push_back({"r6", MIPS64_REG_R6}); - result.push_back({"r7", MIPS64_REG_R7}); - result.push_back({"r8", MIPS64_REG_R8}); - result.push_back({"r9", MIPS64_REG_R9}); - result.push_back({"r10", MIPS64_REG_R10}); - result.push_back({"r11", MIPS64_REG_R11}); - result.push_back({"r12", MIPS64_REG_R12}); - result.push_back({"r13", MIPS64_REG_R13}); - result.push_back({"r14", MIPS64_REG_R14}); - result.push_back({"r15", MIPS64_REG_R15}); - result.push_back({"r16", MIPS64_REG_R16}); - result.push_back({"r17", MIPS64_REG_R17}); - result.push_back({"r18", MIPS64_REG_R18}); - result.push_back({"r19", MIPS64_REG_R19}); - result.push_back({"r20", MIPS64_REG_R20}); - result.push_back({"r21", MIPS64_REG_R21}); - result.push_back({"r22", MIPS64_REG_R22}); - result.push_back({"r23", MIPS64_REG_R23}); - result.push_back({"r24", MIPS64_REG_R24}); - result.push_back({"r25", MIPS64_REG_R25}); - result.push_back({"r26", MIPS64_REG_R26}); - result.push_back({"r27", MIPS64_REG_R27}); - result.push_back({"r28", MIPS64_REG_R28}); - result.push_back({"sp", MIPS64_REG_SP}); - result.push_back({"r30", MIPS64_REG_R30}); - result.push_back({"ra", MIPS64_REG_RA}); - result.push_back({"pc", MIPS64_REG_PC}); - - return result; -} - -using RegTypes = ::testing::Types; -TYPED_TEST_SUITE(RegsIterateTest, RegTypes); - -TYPED_TEST(RegsIterateTest, iterate) { - std::vector expected = ExpectedRegisters(); - TypeParam regs; - for (const auto& reg : expected) { - regs[reg.offset] = reg.offset; - } - - std::vector actual; - regs.IterateRegisters([&actual](const char* name, uint64_t value) { - actual.push_back({name, value}); - }); - - ASSERT_EQ(expected, actual); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp b/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp deleted file mode 100644 index eac12ca64..000000000 --- a/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (C) 2017 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 "MemoryFake.h" - -namespace unwindstack { - -class RegsStepIfSignalHandlerTest : public ::testing::Test { - protected: - void SetUp() override { - elf_memory_ = new MemoryFake; - elf_.reset(new Elf(elf_memory_)); - } - - void ArmStepIfSignalHandlerNonRt(uint32_t pc_data); - void ArmStepIfSignalHandlerRt(uint32_t pc_data); - - MemoryFake* elf_memory_; - MemoryFake process_memory_; - std::unique_ptr elf_; -}; - -void RegsStepIfSignalHandlerTest::ArmStepIfSignalHandlerNonRt(uint32_t pc_data) { - uint64_t addr = 0x1000; - RegsArm regs; - regs[ARM_REG_PC] = 0x5000; - regs[ARM_REG_SP] = addr; - - elf_memory_->SetData32(0x5000, pc_data); - - for (uint64_t index = 0; index <= 30; index++) { - process_memory_.SetData32(addr + index * 4, index * 0x10); - } - - ASSERT_TRUE(regs.StepIfSignalHandler(0x5000, elf_.get(), &process_memory_)); - EXPECT_EQ(0x100U, regs[ARM_REG_SP]); - EXPECT_EQ(0x120U, regs[ARM_REG_PC]); - EXPECT_EQ(0x100U, regs.sp()); - EXPECT_EQ(0x120U, regs.pc()); -} - -TEST_F(RegsStepIfSignalHandlerTest, arm_step_if_signal_handler_non_rt) { - // Form 1 - ArmStepIfSignalHandlerNonRt(0xe3a07077); - - // Form 2 - ArmStepIfSignalHandlerNonRt(0xef900077); - - // Form 3 - ArmStepIfSignalHandlerNonRt(0xdf002777); -} - -void RegsStepIfSignalHandlerTest::ArmStepIfSignalHandlerRt(uint32_t pc_data) { - uint64_t addr = 0x1000; - RegsArm regs; - regs[ARM_REG_PC] = 0x5000; - regs[ARM_REG_SP] = addr; - - elf_memory_->SetData32(0x5000, pc_data); - - for (uint64_t index = 0; index <= 100; index++) { - process_memory_.SetData32(addr + index * 4, index * 0x10); - } - - ASSERT_TRUE(regs.StepIfSignalHandler(0x5000, elf_.get(), &process_memory_)); - EXPECT_EQ(0x350U, regs[ARM_REG_SP]); - EXPECT_EQ(0x370U, regs[ARM_REG_PC]); - EXPECT_EQ(0x350U, regs.sp()); - EXPECT_EQ(0x370U, regs.pc()); -} - -TEST_F(RegsStepIfSignalHandlerTest, arm_step_if_signal_handler_rt) { - // Form 1 - ArmStepIfSignalHandlerRt(0xe3a070ad); - - // Form 2 - ArmStepIfSignalHandlerRt(0xef9000ad); - - // Form 3 - ArmStepIfSignalHandlerRt(0xdf0027ad); -} - -TEST_F(RegsStepIfSignalHandlerTest, arm64_step_if_signal_handler) { - uint64_t addr = 0x1000; - RegsArm64 regs; - regs[ARM64_REG_PC] = 0x8000; - regs[ARM64_REG_SP] = addr; - - elf_memory_->SetData64(0x8000, 0xd4000001d2801168ULL); - - for (uint64_t index = 0; index <= 100; index++) { - process_memory_.SetData64(addr + index * 8, index * 0x10); - } - - ASSERT_TRUE(regs.StepIfSignalHandler(0x8000, elf_.get(), &process_memory_)); - EXPECT_EQ(0x460U, regs[ARM64_REG_SP]); - EXPECT_EQ(0x470U, regs[ARM64_REG_PC]); - EXPECT_EQ(0x460U, regs.sp()); - EXPECT_EQ(0x470U, regs.pc()); -} - -TEST_F(RegsStepIfSignalHandlerTest, x86_step_if_signal_handler_no_siginfo) { - uint64_t addr = 0xa00; - RegsX86 regs; - regs[X86_REG_EIP] = 0x4100; - regs[X86_REG_ESP] = addr; - - elf_memory_->SetData64(0x4100, 0x80cd00000077b858ULL); - for (uint64_t index = 0; index <= 25; index++) { - process_memory_.SetData32(addr + index * 4, index * 0x10); - } - - ASSERT_TRUE(regs.StepIfSignalHandler(0x4100, elf_.get(), &process_memory_)); - EXPECT_EQ(0x70U, regs[X86_REG_EBP]); - EXPECT_EQ(0x80U, regs[X86_REG_ESP]); - EXPECT_EQ(0x90U, regs[X86_REG_EBX]); - EXPECT_EQ(0xa0U, regs[X86_REG_EDX]); - EXPECT_EQ(0xb0U, regs[X86_REG_ECX]); - EXPECT_EQ(0xc0U, regs[X86_REG_EAX]); - EXPECT_EQ(0xf0U, regs[X86_REG_EIP]); - EXPECT_EQ(0x80U, regs.sp()); - EXPECT_EQ(0xf0U, regs.pc()); -} - -TEST_F(RegsStepIfSignalHandlerTest, x86_step_if_signal_handler_siginfo) { - uint64_t addr = 0xa00; - RegsX86 regs; - regs[X86_REG_EIP] = 0x4100; - regs[X86_REG_ESP] = addr; - - elf_memory_->SetData64(0x4100, 0x0080cd000000adb8ULL); - addr += 8; - // Pointer to ucontext data. - process_memory_.SetData32(addr, 0x8100); - - addr = 0x8100; - for (uint64_t index = 0; index <= 30; index++) { - process_memory_.SetData32(addr + index * 4, index * 0x10); - } - - ASSERT_TRUE(regs.StepIfSignalHandler(0x4100, elf_.get(), &process_memory_)); - EXPECT_EQ(0xb0U, regs[X86_REG_EBP]); - EXPECT_EQ(0xc0U, regs[X86_REG_ESP]); - EXPECT_EQ(0xd0U, regs[X86_REG_EBX]); - EXPECT_EQ(0xe0U, regs[X86_REG_EDX]); - EXPECT_EQ(0xf0U, regs[X86_REG_ECX]); - EXPECT_EQ(0x100U, regs[X86_REG_EAX]); - EXPECT_EQ(0x130U, regs[X86_REG_EIP]); - EXPECT_EQ(0xc0U, regs.sp()); - EXPECT_EQ(0x130U, regs.pc()); -} - -TEST_F(RegsStepIfSignalHandlerTest, x86_64_step_if_signal_handler) { - uint64_t addr = 0x500; - RegsX86_64 regs; - regs[X86_64_REG_RIP] = 0x7000; - regs[X86_64_REG_RSP] = addr; - - elf_memory_->SetData64(0x7000, 0x0f0000000fc0c748); - elf_memory_->SetData16(0x7008, 0x0f05); - - for (uint64_t index = 0; index <= 30; index++) { - process_memory_.SetData64(addr + index * 8, index * 0x10); - } - - ASSERT_TRUE(regs.StepIfSignalHandler(0x7000, elf_.get(), &process_memory_)); - EXPECT_EQ(0x140U, regs[X86_64_REG_RSP]); - EXPECT_EQ(0x150U, regs[X86_64_REG_RIP]); - EXPECT_EQ(0x140U, regs.sp()); - EXPECT_EQ(0x150U, regs.pc()); -} - -TEST_F(RegsStepIfSignalHandlerTest, mips_step_if_signal_handler_non_rt) { - uint64_t addr = 0x1000; - RegsMips regs; - regs[MIPS_REG_PC] = 0x8000; - regs[MIPS_REG_SP] = addr; - - elf_memory_->SetData64(0x8000, 0x0000000c24021017ULL); - - for (uint64_t index = 0; index <= 50; index++) { - process_memory_.SetData64(addr + index * 8, index * 0x10); - } - - ASSERT_TRUE(regs.StepIfSignalHandler(0x8000, elf_.get(), &process_memory_)); - EXPECT_EQ(0x220U, regs[MIPS_REG_SP]); - EXPECT_EQ(0x040U, regs[MIPS_REG_PC]); - EXPECT_EQ(0x220U, regs.sp()); - EXPECT_EQ(0x040U, regs.pc()); -} - -TEST_F(RegsStepIfSignalHandlerTest, mips_step_if_signal_handler_rt) { - uint64_t addr = 0x1000; - RegsMips regs; - regs[MIPS_REG_PC] = 0x8000; - regs[MIPS_REG_SP] = addr; - - elf_memory_->SetData64(0x8000, 0x0000000c24021061ULL); - - for (uint64_t index = 0; index <= 100; index++) { - process_memory_.SetData64(addr + index * 8, index * 0x10); - } - - ASSERT_TRUE(regs.StepIfSignalHandler(0x8000, elf_.get(), &process_memory_)); - EXPECT_EQ(0x350U, regs[MIPS_REG_SP]); - EXPECT_EQ(0x170U, regs[MIPS_REG_PC]); - EXPECT_EQ(0x350U, regs.sp()); - EXPECT_EQ(0x170U, regs.pc()); -} - -TEST_F(RegsStepIfSignalHandlerTest, mips64_step_if_signal_handler) { - uint64_t addr = 0x1000; - RegsMips64 regs; - regs[MIPS64_REG_PC] = 0x8000; - regs[MIPS64_REG_SP] = addr; - - elf_memory_->SetData64(0x8000, 0x0000000c2402145bULL); - - for (uint64_t index = 0; index <= 100; index++) { - process_memory_.SetData64(addr + index * 8, index * 0x10); - } - - ASSERT_TRUE(regs.StepIfSignalHandler(0x8000, elf_.get(), &process_memory_)); - EXPECT_EQ(0x350U, regs[MIPS64_REG_SP]); - EXPECT_EQ(0x600U, regs[MIPS64_REG_PC]); - EXPECT_EQ(0x350U, regs.sp()); - EXPECT_EQ(0x600U, regs.pc()); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/RegsTest.cpp b/libunwindstack/tests/RegsTest.cpp deleted file mode 100644 index acf72de2c..000000000 --- a/libunwindstack/tests/RegsTest.cpp +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Copyright (C) 2017 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 "ElfFake.h" -#include "MemoryFake.h" -#include "RegsFake.h" - -namespace unwindstack { - -class RegsTest : public ::testing::Test { - protected: - void SetUp() override { - memory_ = new MemoryFake; - elf_.reset(new ElfFake(memory_)); - elf_interface_ = new ElfInterfaceFake(elf_->memory()); - elf_->FakeSetInterface(elf_interface_); - } - - ElfInterfaceFake* elf_interface_; - MemoryFake* memory_; - std::unique_ptr elf_; -}; - -TEST_F(RegsTest, regs32) { - RegsImplFake regs32(50); - ASSERT_EQ(50U, regs32.total_regs()); - - uint32_t* raw = reinterpret_cast(regs32.RawData()); - for (size_t i = 0; i < 50; i++) { - raw[i] = 0xf0000000 + i; - } - regs32.set_pc(0xf0120340); - regs32.set_sp(0xa0ab0cd0); - - for (size_t i = 0; i < 50; i++) { - ASSERT_EQ(0xf0000000U + i, regs32[i]) << "Failed comparing register " << i; - } - - ASSERT_EQ(0xf0120340U, regs32.pc()); - ASSERT_EQ(0xa0ab0cd0U, regs32.sp()); - - regs32[32] = 10; - ASSERT_EQ(10U, regs32[32]); -} - -TEST_F(RegsTest, regs64) { - RegsImplFake regs64(30); - ASSERT_EQ(30U, regs64.total_regs()); - - uint64_t* raw = reinterpret_cast(regs64.RawData()); - for (size_t i = 0; i < 30; i++) { - raw[i] = 0xf123456780000000UL + i; - } - regs64.set_pc(0xf123456780102030UL); - regs64.set_sp(0xa123456780a0b0c0UL); - - for (size_t i = 0; i < 30; i++) { - ASSERT_EQ(0xf123456780000000U + i, regs64[i]) << "Failed reading register " << i; - } - - ASSERT_EQ(0xf123456780102030UL, regs64.pc()); - ASSERT_EQ(0xa123456780a0b0c0UL, regs64.sp()); - - regs64[8] = 10; - ASSERT_EQ(10U, regs64[8]); -} - -TEST_F(RegsTest, rel_pc) { - EXPECT_EQ(4U, GetPcAdjustment(0x10, elf_.get(), ARCH_ARM64)); - EXPECT_EQ(4U, GetPcAdjustment(0x4, elf_.get(), ARCH_ARM64)); - EXPECT_EQ(0U, GetPcAdjustment(0x3, elf_.get(), ARCH_ARM64)); - EXPECT_EQ(0U, GetPcAdjustment(0x2, elf_.get(), ARCH_ARM64)); - EXPECT_EQ(0U, GetPcAdjustment(0x1, elf_.get(), ARCH_ARM64)); - EXPECT_EQ(0U, GetPcAdjustment(0x0, elf_.get(), ARCH_ARM64)); - - EXPECT_EQ(1U, GetPcAdjustment(0x100, elf_.get(), ARCH_X86)); - EXPECT_EQ(1U, GetPcAdjustment(0x2, elf_.get(), ARCH_X86)); - EXPECT_EQ(1U, GetPcAdjustment(0x1, elf_.get(), ARCH_X86)); - EXPECT_EQ(0U, GetPcAdjustment(0x0, elf_.get(), ARCH_X86)); - - EXPECT_EQ(1U, GetPcAdjustment(0x100, elf_.get(), ARCH_X86_64)); - EXPECT_EQ(1U, GetPcAdjustment(0x2, elf_.get(), ARCH_X86_64)); - EXPECT_EQ(1U, GetPcAdjustment(0x1, elf_.get(), ARCH_X86_64)); - EXPECT_EQ(0U, GetPcAdjustment(0x0, elf_.get(), ARCH_X86_64)); - - EXPECT_EQ(8U, GetPcAdjustment(0x10, elf_.get(), ARCH_MIPS)); - EXPECT_EQ(8U, GetPcAdjustment(0x8, elf_.get(), ARCH_MIPS)); - EXPECT_EQ(0U, GetPcAdjustment(0x7, elf_.get(), ARCH_MIPS)); - EXPECT_EQ(0U, GetPcAdjustment(0x6, elf_.get(), ARCH_MIPS)); - EXPECT_EQ(0U, GetPcAdjustment(0x5, elf_.get(), ARCH_MIPS)); - EXPECT_EQ(0U, GetPcAdjustment(0x4, elf_.get(), ARCH_MIPS)); - EXPECT_EQ(0U, GetPcAdjustment(0x3, elf_.get(), ARCH_MIPS)); - EXPECT_EQ(0U, GetPcAdjustment(0x2, elf_.get(), ARCH_MIPS)); - EXPECT_EQ(0U, GetPcAdjustment(0x1, elf_.get(), ARCH_MIPS)); - EXPECT_EQ(0U, GetPcAdjustment(0x0, elf_.get(), ARCH_MIPS)); - - EXPECT_EQ(8U, GetPcAdjustment(0x10, elf_.get(), ARCH_MIPS64)); - EXPECT_EQ(8U, GetPcAdjustment(0x8, elf_.get(), ARCH_MIPS64)); - EXPECT_EQ(0U, GetPcAdjustment(0x7, elf_.get(), ARCH_MIPS64)); - EXPECT_EQ(0U, GetPcAdjustment(0x6, elf_.get(), ARCH_MIPS64)); - EXPECT_EQ(0U, GetPcAdjustment(0x5, elf_.get(), ARCH_MIPS64)); - EXPECT_EQ(0U, GetPcAdjustment(0x4, elf_.get(), ARCH_MIPS64)); - EXPECT_EQ(0U, GetPcAdjustment(0x3, elf_.get(), ARCH_MIPS64)); - EXPECT_EQ(0U, GetPcAdjustment(0x2, elf_.get(), ARCH_MIPS64)); - EXPECT_EQ(0U, GetPcAdjustment(0x1, elf_.get(), ARCH_MIPS64)); - EXPECT_EQ(0U, GetPcAdjustment(0x0, elf_.get(), ARCH_MIPS64)); -} - -TEST_F(RegsTest, rel_pc_arm) { - // Check fence posts. - elf_->FakeSetLoadBias(0); - EXPECT_EQ(2U, GetPcAdjustment(0x5, elf_.get(), ARCH_ARM)); - EXPECT_EQ(2U, GetPcAdjustment(0x4, elf_.get(), ARCH_ARM)); - EXPECT_EQ(2U, GetPcAdjustment(0x3, elf_.get(), ARCH_ARM)); - EXPECT_EQ(2U, GetPcAdjustment(0x2, elf_.get(), ARCH_ARM)); - EXPECT_EQ(0U, GetPcAdjustment(0x1, elf_.get(), ARCH_ARM)); - EXPECT_EQ(0U, GetPcAdjustment(0x0, elf_.get(), ARCH_ARM)); - - elf_->FakeSetLoadBias(0x100); - EXPECT_EQ(0U, GetPcAdjustment(0x1, elf_.get(), ARCH_ARM)); - EXPECT_EQ(2U, GetPcAdjustment(0x2, elf_.get(), ARCH_ARM)); - EXPECT_EQ(2U, GetPcAdjustment(0xff, elf_.get(), ARCH_ARM)); - EXPECT_EQ(2U, GetPcAdjustment(0x105, elf_.get(), ARCH_ARM)); - EXPECT_EQ(2U, GetPcAdjustment(0x104, elf_.get(), ARCH_ARM)); - EXPECT_EQ(2U, GetPcAdjustment(0x103, elf_.get(), ARCH_ARM)); - EXPECT_EQ(2U, GetPcAdjustment(0x102, elf_.get(), ARCH_ARM)); - EXPECT_EQ(0U, GetPcAdjustment(0x101, elf_.get(), ARCH_ARM)); - EXPECT_EQ(0U, GetPcAdjustment(0x100, elf_.get(), ARCH_ARM)); - - // Check thumb instructions handling. - elf_->FakeSetLoadBias(0); - memory_->SetData32(0x2000, 0); - EXPECT_EQ(2U, GetPcAdjustment(0x2005, elf_.get(), ARCH_ARM)); - memory_->SetData32(0x2000, 0xe000f000); - EXPECT_EQ(4U, GetPcAdjustment(0x2005, elf_.get(), ARCH_ARM)); - - elf_->FakeSetLoadBias(0x400); - memory_->SetData32(0x2100, 0); - EXPECT_EQ(2U, GetPcAdjustment(0x2505, elf_.get(), ARCH_ARM)); - memory_->SetData32(0x2100, 0xf111f111); - EXPECT_EQ(4U, GetPcAdjustment(0x2505, elf_.get(), ARCH_ARM)); -} - -TEST_F(RegsTest, elf_invalid) { - MapInfo map_info(nullptr, nullptr, 0x1000, 0x2000, 0, 0, ""); - Elf* invalid_elf = new Elf(nullptr); - map_info.elf.reset(invalid_elf); - - EXPECT_EQ(0x500U, invalid_elf->GetRelPc(0x1500, &map_info)); - EXPECT_EQ(2U, GetPcAdjustment(0x500U, invalid_elf, ARCH_ARM)); - EXPECT_EQ(2U, GetPcAdjustment(0x511U, invalid_elf, ARCH_ARM)); - - EXPECT_EQ(0x600U, invalid_elf->GetRelPc(0x1600, &map_info)); - EXPECT_EQ(4U, GetPcAdjustment(0x600U, invalid_elf, ARCH_ARM64)); - - EXPECT_EQ(0x700U, invalid_elf->GetRelPc(0x1700, &map_info)); - EXPECT_EQ(1U, GetPcAdjustment(0x700U, invalid_elf, ARCH_X86)); - - EXPECT_EQ(0x800U, invalid_elf->GetRelPc(0x1800, &map_info)); - EXPECT_EQ(1U, GetPcAdjustment(0x800U, invalid_elf, ARCH_X86_64)); - - EXPECT_EQ(0x900U, invalid_elf->GetRelPc(0x1900, &map_info)); - EXPECT_EQ(8U, GetPcAdjustment(0x900U, invalid_elf, ARCH_MIPS)); - - EXPECT_EQ(0xa00U, invalid_elf->GetRelPc(0x1a00, &map_info)); - EXPECT_EQ(8U, GetPcAdjustment(0xa00U, invalid_elf, ARCH_MIPS64)); -} - -TEST_F(RegsTest, arm_verify_sp_pc) { - RegsArm arm; - uint32_t* regs = reinterpret_cast(arm.RawData()); - regs[13] = 0x100; - regs[15] = 0x200; - EXPECT_EQ(0x100U, arm.sp()); - EXPECT_EQ(0x200U, arm.pc()); -} - -TEST_F(RegsTest, arm64_verify_sp_pc) { - RegsArm64 arm64; - uint64_t* regs = reinterpret_cast(arm64.RawData()); - regs[31] = 0xb100000000ULL; - regs[32] = 0xc200000000ULL; - EXPECT_EQ(0xb100000000U, arm64.sp()); - EXPECT_EQ(0xc200000000U, arm64.pc()); -} - -TEST_F(RegsTest, x86_verify_sp_pc) { - RegsX86 x86; - uint32_t* regs = reinterpret_cast(x86.RawData()); - regs[4] = 0x23450000; - regs[8] = 0xabcd0000; - EXPECT_EQ(0x23450000U, x86.sp()); - EXPECT_EQ(0xabcd0000U, x86.pc()); -} - -TEST_F(RegsTest, x86_64_verify_sp_pc) { - RegsX86_64 x86_64; - uint64_t* regs = reinterpret_cast(x86_64.RawData()); - regs[7] = 0x1200000000ULL; - regs[16] = 0x4900000000ULL; - EXPECT_EQ(0x1200000000U, x86_64.sp()); - EXPECT_EQ(0x4900000000U, x86_64.pc()); -} - -TEST_F(RegsTest, mips_verify_sp_pc) { - RegsMips mips; - uint32_t* regs = reinterpret_cast(mips.RawData()); - regs[29] = 0x100; - regs[32] = 0x200; - EXPECT_EQ(0x100U, mips.sp()); - EXPECT_EQ(0x200U, mips.pc()); -} - -TEST_F(RegsTest, mips64_verify_sp_pc) { - RegsMips64 mips64; - uint64_t* regs = reinterpret_cast(mips64.RawData()); - regs[29] = 0xb100000000ULL; - regs[32] = 0xc200000000ULL; - EXPECT_EQ(0xb100000000U, mips64.sp()); - EXPECT_EQ(0xc200000000U, mips64.pc()); -} - -TEST_F(RegsTest, arm64_strip_pac_mask) { - RegsArm64 arm64; - arm64.SetPseudoRegister(Arm64Reg::ARM64_PREG_RA_SIGN_STATE, 1); - arm64.SetPACMask(0x007fff8000000000ULL); - arm64.set_pc(0x0020007214bb3a04ULL); - EXPECT_EQ(0x0000007214bb3a04ULL, arm64.pc()); -} - -TEST_F(RegsTest, machine_type) { - RegsArm arm_regs; - EXPECT_EQ(ARCH_ARM, arm_regs.Arch()); - - RegsArm64 arm64_regs; - EXPECT_EQ(ARCH_ARM64, arm64_regs.Arch()); - - RegsX86 x86_regs; - EXPECT_EQ(ARCH_X86, x86_regs.Arch()); - - RegsX86_64 x86_64_regs; - EXPECT_EQ(ARCH_X86_64, x86_64_regs.Arch()); - - RegsMips mips_regs; - EXPECT_EQ(ARCH_MIPS, mips_regs.Arch()); - - RegsMips64 mips64_regs; - EXPECT_EQ(ARCH_MIPS64, mips64_regs.Arch()); -} - -template -void clone_test(Regs* regs) { - RegisterType* register_values = reinterpret_cast(regs->RawData()); - int num_regs = regs->total_regs(); - for (int i = 0; i < num_regs; ++i) { - register_values[i] = i; - } - - std::unique_ptr clone(regs->Clone()); - ASSERT_EQ(regs->total_regs(), clone->total_regs()); - RegisterType* clone_values = reinterpret_cast(clone->RawData()); - for (int i = 0; i < num_regs; ++i) { - EXPECT_EQ(register_values[i], clone_values[i]); - EXPECT_NE(®ister_values[i], &clone_values[i]); - } -} - -TEST_F(RegsTest, clone) { - std::vector> regs; - regs.emplace_back(new RegsArm()); - regs.emplace_back(new RegsArm64()); - regs.emplace_back(new RegsX86()); - regs.emplace_back(new RegsX86_64()); - regs.emplace_back(new RegsMips()); - regs.emplace_back(new RegsMips64()); - - for (auto& r : regs) { - if (r->Is32Bit()) { - clone_test(r.get()); - } else { - clone_test(r.get()); - } - } -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/SymbolsTest.cpp b/libunwindstack/tests/SymbolsTest.cpp deleted file mode 100644 index 9afbeec55..000000000 --- a/libunwindstack/tests/SymbolsTest.cpp +++ /dev/null @@ -1,377 +0,0 @@ -/* - * Copyright (C) 2016 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 "MemoryFake.h" -#include "Symbols.h" - -namespace unwindstack { - -template -class SymbolsTest : public ::testing::Test { - protected: - void SetUp() override { memory_.Clear(); } - - void InitSym(TypeParam* sym, uint32_t st_value, uint32_t st_size, uint32_t st_name) { - memset(sym, 0, sizeof(*sym)); - sym->st_info = STT_FUNC; - sym->st_value = st_value; - sym->st_size = st_size; - sym->st_name = st_name; - sym->st_shndx = SHN_COMMON; - } - - MemoryFake memory_; -}; -TYPED_TEST_SUITE_P(SymbolsTest); - -TYPED_TEST_P(SymbolsTest, function_bounds_check) { - Symbols symbols(0x1000, sizeof(TypeParam), sizeof(TypeParam), 0x2000, 0x100); - - TypeParam sym; - this->InitSym(&sym, 0x5000, 0x10, 0x40); - uint64_t offset = 0x1000; - this->memory_.SetMemory(offset, &sym, sizeof(sym)); - - std::string fake_name("fake_function"); - this->memory_.SetMemory(0x2040, fake_name.c_str(), fake_name.size() + 1); - - std::string name; - uint64_t func_offset; - ASSERT_TRUE(symbols.GetName(0x5000, &this->memory_, &name, &func_offset)); - ASSERT_EQ("fake_function", name); - ASSERT_EQ(0U, func_offset); - - name.clear(); - ASSERT_TRUE(symbols.GetName(0x500f, &this->memory_, &name, &func_offset)); - ASSERT_EQ("fake_function", name); - ASSERT_EQ(0xfU, func_offset); - - // Check one before and one after the function. - ASSERT_FALSE(symbols.GetName(0x4fff, &this->memory_, &name, &func_offset)); - ASSERT_FALSE(symbols.GetName(0x5010, &this->memory_, &name, &func_offset)); -} - -TYPED_TEST_P(SymbolsTest, no_symbol) { - Symbols symbols(0x1000, sizeof(TypeParam), sizeof(TypeParam), 0x2000, 0x100); - - TypeParam sym; - this->InitSym(&sym, 0x5000, 0x10, 0x40); - uint64_t offset = 0x1000; - this->memory_.SetMemory(offset, &sym, sizeof(sym)); - - std::string fake_name("fake_function"); - this->memory_.SetMemory(0x2040, fake_name.c_str(), fake_name.size() + 1); - - // First verify that we can get the name. - std::string name; - uint64_t func_offset; - ASSERT_TRUE(symbols.GetName(0x5000, &this->memory_, &name, &func_offset)); - ASSERT_EQ("fake_function", name); - ASSERT_EQ(0U, func_offset); - - // Now modify the info field so it's no longer a function. - sym.st_info = 0; - this->memory_.SetMemory(offset, &sym, sizeof(sym)); - // Clear the cache to force the symbol data to be re-read. - symbols.ClearCache(); - ASSERT_FALSE(symbols.GetName(0x5000, &this->memory_, &name, &func_offset)); - - // Set the function back, and set the shndx to UNDEF. - sym.st_info = STT_FUNC; - sym.st_shndx = SHN_UNDEF; - this->memory_.SetMemory(offset, &sym, sizeof(sym)); - // Clear the cache to force the symbol data to be re-read. - symbols.ClearCache(); - ASSERT_FALSE(symbols.GetName(0x5000, &this->memory_, &name, &func_offset)); -} - -TYPED_TEST_P(SymbolsTest, multiple_entries) { - Symbols symbols(0x1000, sizeof(TypeParam) * 3, sizeof(TypeParam), 0x2000, 0x500); - - TypeParam sym; - uint64_t offset = 0x1000; - std::string fake_name; - - this->InitSym(&sym, 0x5000, 0x10, 0x40); - this->memory_.SetMemory(offset, &sym, sizeof(sym)); - fake_name = "function_one"; - this->memory_.SetMemory(0x2040, fake_name.c_str(), fake_name.size() + 1); - offset += sizeof(sym); - - this->InitSym(&sym, 0x3004, 0x200, 0x100); - this->memory_.SetMemory(offset, &sym, sizeof(sym)); - fake_name = "function_two"; - this->memory_.SetMemory(0x2100, fake_name.c_str(), fake_name.size() + 1); - offset += sizeof(sym); - - this->InitSym(&sym, 0xa010, 0x20, 0x230); - this->memory_.SetMemory(offset, &sym, sizeof(sym)); - fake_name = "function_three"; - this->memory_.SetMemory(0x2230, fake_name.c_str(), fake_name.size() + 1); - - std::string name; - uint64_t func_offset; - ASSERT_TRUE(symbols.GetName(0x3005, &this->memory_, &name, &func_offset)); - ASSERT_EQ("function_two", name); - ASSERT_EQ(1U, func_offset); - - name.clear(); - ASSERT_TRUE(symbols.GetName(0x5004, &this->memory_, &name, &func_offset)); - ASSERT_EQ("function_one", name); - ASSERT_EQ(4U, func_offset); - - name.clear(); - ASSERT_TRUE(symbols.GetName(0xa011, &this->memory_, &name, &func_offset)); - ASSERT_EQ("function_three", name); - ASSERT_EQ(1U, func_offset); - - // Reget some of the others to verify getting one function name doesn't - // affect any of the next calls. - name.clear(); - ASSERT_TRUE(symbols.GetName(0x5008, &this->memory_, &name, &func_offset)); - ASSERT_EQ("function_one", name); - ASSERT_EQ(8U, func_offset); - - name.clear(); - ASSERT_TRUE(symbols.GetName(0x3008, &this->memory_, &name, &func_offset)); - ASSERT_EQ("function_two", name); - ASSERT_EQ(4U, func_offset); - - name.clear(); - ASSERT_TRUE(symbols.GetName(0xa01a, &this->memory_, &name, &func_offset)); - ASSERT_EQ("function_three", name); - ASSERT_EQ(0xaU, func_offset); -} - -TYPED_TEST_P(SymbolsTest, multiple_entries_nonstandard_size) { - uint64_t entry_size = sizeof(TypeParam) + 5; - Symbols symbols(0x1000, entry_size * 3, entry_size, 0x2000, 0x500); - - TypeParam sym; - uint64_t offset = 0x1000; - std::string fake_name; - - this->InitSym(&sym, 0x5000, 0x10, 0x40); - this->memory_.SetMemoryBlock(offset, entry_size, 0); - this->memory_.SetMemory(offset, &sym, sizeof(sym)); - fake_name = "function_one"; - this->memory_.SetMemory(0x2040, fake_name.c_str(), fake_name.size() + 1); - offset += entry_size; - - this->InitSym(&sym, 0x3004, 0x200, 0x100); - this->memory_.SetMemoryBlock(offset, entry_size, 0); - this->memory_.SetMemory(offset, &sym, sizeof(sym)); - fake_name = "function_two"; - this->memory_.SetMemory(0x2100, fake_name.c_str(), fake_name.size() + 1); - offset += entry_size; - - this->InitSym(&sym, 0xa010, 0x20, 0x230); - this->memory_.SetMemoryBlock(offset, entry_size, 0); - this->memory_.SetMemory(offset, &sym, sizeof(sym)); - fake_name = "function_three"; - this->memory_.SetMemory(0x2230, fake_name.c_str(), fake_name.size() + 1); - - std::string name; - uint64_t func_offset; - ASSERT_TRUE(symbols.GetName(0x3005, &this->memory_, &name, &func_offset)); - ASSERT_EQ("function_two", name); - ASSERT_EQ(1U, func_offset); - - name.clear(); - ASSERT_TRUE(symbols.GetName(0x5004, &this->memory_, &name, &func_offset)); - ASSERT_EQ("function_one", name); - ASSERT_EQ(4U, func_offset); - - name.clear(); - ASSERT_TRUE(symbols.GetName(0xa011, &this->memory_, &name, &func_offset)); - ASSERT_EQ("function_three", name); - ASSERT_EQ(1U, func_offset); -} - -TYPED_TEST_P(SymbolsTest, symtab_value_out_of_bounds) { - Symbols symbols_end_at_100(0x1000, sizeof(TypeParam) * 2, sizeof(TypeParam), 0x2000, 0x100); - Symbols symbols_end_at_200(0x1000, sizeof(TypeParam) * 2, sizeof(TypeParam), 0x2000, 0x200); - - TypeParam sym; - uint64_t offset = 0x1000; - - this->InitSym(&sym, 0x5000, 0x10, 0xfb); - this->memory_.SetMemory(offset, &sym, sizeof(sym)); - offset += sizeof(sym); - - this->InitSym(&sym, 0x3000, 0x10, 0x100); - this->memory_.SetMemory(offset, &sym, sizeof(sym)); - - // Put the name across the end of the tab. - std::string fake_name("fake_function"); - this->memory_.SetMemory(0x20fb, fake_name.c_str(), fake_name.size() + 1); - - std::string name; - uint64_t func_offset; - // Verify that we can get the function name properly for both entries. - ASSERT_TRUE(symbols_end_at_200.GetName(0x5000, &this->memory_, &name, &func_offset)); - ASSERT_EQ("fake_function", name); - ASSERT_EQ(0U, func_offset); - ASSERT_TRUE(symbols_end_at_200.GetName(0x3000, &this->memory_, &name, &func_offset)); - ASSERT_EQ("function", name); - ASSERT_EQ(0U, func_offset); - - // Now use the symbol table that ends at 0x100. - ASSERT_FALSE(symbols_end_at_100.GetName(0x5000, &this->memory_, &name, &func_offset)); - ASSERT_FALSE(symbols_end_at_100.GetName(0x3000, &this->memory_, &name, &func_offset)); -} - -// Verify the entire func table is cached. -TYPED_TEST_P(SymbolsTest, symtab_read_cached) { - Symbols symbols(0x1000, 3 * sizeof(TypeParam), sizeof(TypeParam), 0xa000, 0x1000); - - TypeParam sym; - uint64_t offset = 0x1000; - - // Make sure that these entries are not in ascending order. - this->InitSym(&sym, 0x5000, 0x10, 0x100); - this->memory_.SetMemory(offset, &sym, sizeof(sym)); - offset += sizeof(sym); - - this->InitSym(&sym, 0x2000, 0x300, 0x200); - this->memory_.SetMemory(offset, &sym, sizeof(sym)); - offset += sizeof(sym); - - this->InitSym(&sym, 0x1000, 0x100, 0x300); - this->memory_.SetMemory(offset, &sym, sizeof(sym)); - offset += sizeof(sym); - - // Do call that should cache all of the entries (except the string data). - std::string name; - uint64_t func_offset; - ASSERT_FALSE(symbols.GetName(0x5000, &this->memory_, &name, &func_offset)); - ASSERT_FALSE(symbols.GetName(0x2000, &this->memory_, &name, &func_offset)); - ASSERT_FALSE(symbols.GetName(0x1000, &this->memory_, &name, &func_offset)); - this->memory_.Clear(); - ASSERT_FALSE(symbols.GetName(0x6000, &this->memory_, &name, &func_offset)); - - // Clear the memory and only put the symbol data string data in memory. - this->memory_.Clear(); - - std::string fake_name; - fake_name = "first_entry"; - this->memory_.SetMemory(0xa100, fake_name.c_str(), fake_name.size() + 1); - fake_name = "second_entry"; - this->memory_.SetMemory(0xa200, fake_name.c_str(), fake_name.size() + 1); - fake_name = "third_entry"; - this->memory_.SetMemory(0xa300, fake_name.c_str(), fake_name.size() + 1); - - ASSERT_TRUE(symbols.GetName(0x5001, &this->memory_, &name, &func_offset)); - ASSERT_EQ("first_entry", name); - ASSERT_EQ(1U, func_offset); - - ASSERT_TRUE(symbols.GetName(0x2002, &this->memory_, &name, &func_offset)); - ASSERT_EQ("second_entry", name); - ASSERT_EQ(2U, func_offset); - - ASSERT_TRUE(symbols.GetName(0x1003, &this->memory_, &name, &func_offset)); - ASSERT_EQ("third_entry", name); - ASSERT_EQ(3U, func_offset); -} - -TYPED_TEST_P(SymbolsTest, get_global) { - uint64_t start_offset = 0x1000; - uint64_t str_offset = 0xa000; - Symbols symbols(start_offset, 4 * sizeof(TypeParam), sizeof(TypeParam), str_offset, 0x1000); - - TypeParam sym; - memset(&sym, 0, sizeof(sym)); - sym.st_shndx = SHN_COMMON; - sym.st_info = STT_OBJECT | (STB_GLOBAL << 4); - sym.st_name = 0x100; - this->memory_.SetMemory(start_offset, &sym, sizeof(sym)); - this->memory_.SetMemory(str_offset + 0x100, "global_0"); - - start_offset += sizeof(sym); - memset(&sym, 0, sizeof(sym)); - sym.st_shndx = SHN_COMMON; - sym.st_info = STT_FUNC; - sym.st_name = 0x200; - sym.st_value = 0x10000; - sym.st_size = 0x100; - this->memory_.SetMemory(start_offset, &sym, sizeof(sym)); - this->memory_.SetMemory(str_offset + 0x200, "function_0"); - - start_offset += sizeof(sym); - memset(&sym, 0, sizeof(sym)); - sym.st_shndx = SHN_COMMON; - sym.st_info = STT_OBJECT | (STB_GLOBAL << 4); - sym.st_name = 0x300; - this->memory_.SetMemory(start_offset, &sym, sizeof(sym)); - this->memory_.SetMemory(str_offset + 0x300, "global_1"); - - start_offset += sizeof(sym); - memset(&sym, 0, sizeof(sym)); - sym.st_shndx = SHN_COMMON; - sym.st_info = STT_FUNC; - sym.st_name = 0x400; - sym.st_value = 0x12000; - sym.st_size = 0x100; - this->memory_.SetMemory(start_offset, &sym, sizeof(sym)); - this->memory_.SetMemory(str_offset + 0x400, "function_1"); - - uint64_t offset; - EXPECT_TRUE(symbols.GetGlobal(&this->memory_, "global_0", &offset)); - EXPECT_TRUE(symbols.GetGlobal(&this->memory_, "global_1", &offset)); - EXPECT_TRUE(symbols.GetGlobal(&this->memory_, "global_0", &offset)); - EXPECT_TRUE(symbols.GetGlobal(&this->memory_, "global_1", &offset)); - - EXPECT_FALSE(symbols.GetGlobal(&this->memory_, "function_0", &offset)); - EXPECT_FALSE(symbols.GetGlobal(&this->memory_, "function_1", &offset)); - - std::string name; - EXPECT_TRUE(symbols.GetName(0x10002, &this->memory_, &name, &offset)); - EXPECT_EQ("function_0", name); - EXPECT_EQ(2U, offset); - - EXPECT_TRUE(symbols.GetName(0x12004, &this->memory_, &name, &offset)); - EXPECT_EQ("function_1", name); - EXPECT_EQ(4U, offset); -} - -REGISTER_TYPED_TEST_SUITE_P(SymbolsTest, function_bounds_check, no_symbol, multiple_entries, - multiple_entries_nonstandard_size, symtab_value_out_of_bounds, - symtab_read_cached, get_global); - -typedef ::testing::Types SymbolsTestTypes; -INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, SymbolsTest, SymbolsTestTypes); - -} // namespace unwindstack diff --git a/libunwindstack/tests/TestLocal.cpp b/libunwindstack/tests/TestLocal.cpp deleted file mode 100644 index fa0baff36..000000000 --- a/libunwindstack/tests/TestLocal.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2018 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 - -extern "C" void TestlibLevel4(void* unwinder_data, void* frame_data) { - unwindstack::LocalUnwinder* unwinder = - reinterpret_cast(unwinder_data); - std::vector* frame_info = - reinterpret_cast*>(frame_data); - unwinder->Unwind(frame_info, 256); -} - -extern "C" void TestlibLevel3(void* unwinder_data, void* frame_data) { - TestlibLevel4(unwinder_data, frame_data); -} - -extern "C" void TestlibLevel2(void* unwinder_data, void* frame_data) { - TestlibLevel3(unwinder_data, frame_data); -} - -extern "C" void TestlibLevel1(void* unwinder_data, void* frame_data) { - TestlibLevel2(unwinder_data, frame_data); -} diff --git a/libunwindstack/tests/TestUtils.cpp b/libunwindstack/tests/TestUtils.cpp deleted file mode 100644 index e76f5f8de..000000000 --- a/libunwindstack/tests/TestUtils.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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. - */ - -#include -#include - -#include - -namespace unwindstack { - -void TestCheckForLeaks(void (*unwind_func)(void*), void* data) { - static constexpr size_t kNumLeakLoops = 200; - static constexpr size_t kMaxAllowedLeakBytes = 32 * 1024; - - size_t first_allocated_bytes = 0; - size_t last_allocated_bytes = 0; - for (size_t i = 0; i < kNumLeakLoops; i++) { - unwind_func(data); - - size_t allocated_bytes = mallinfo().uordblks; - if (first_allocated_bytes == 0) { - first_allocated_bytes = allocated_bytes; - } else if (last_allocated_bytes > first_allocated_bytes) { - // Check that the memory did not increase too much over the first loop. - ASSERT_LE(last_allocated_bytes - first_allocated_bytes, kMaxAllowedLeakBytes); - } - last_allocated_bytes = allocated_bytes; - } -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/TestUtils.h b/libunwindstack/tests/TestUtils.h deleted file mode 100644 index 0685006bf..000000000 --- a/libunwindstack/tests/TestUtils.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2017 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_TESTS_TEST_UTILS_H -#define _LIBUNWINDSTACK_TESTS_TEST_UTILS_H - -#include -#include -#include -#include -#include - -namespace unwindstack { - -class TestScopedPidReaper { - public: - TestScopedPidReaper(pid_t pid) : pid_(pid) {} - ~TestScopedPidReaper() { - kill(pid_, SIGKILL); - waitpid(pid_, nullptr, 0); - } - - private: - pid_t pid_; -}; - -inline bool TestQuiescePid(pid_t pid) { - siginfo_t si; - bool ready = false; - // Wait for up to 5 seconds. - for (size_t i = 0; i < 5000; i++) { - if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) { - ready = true; - break; - } - usleep(1000); - } - return ready; -} - -inline bool TestAttach(pid_t pid) { - if (ptrace(PTRACE_ATTACH, pid, 0, 0) == -1) { - return false; - } - - return TestQuiescePid(pid); -} - -inline bool TestDetach(pid_t pid) { - return ptrace(PTRACE_DETACH, pid, 0, 0) == 0; -} - -void TestCheckForLeaks(void (*unwind_func)(void*), void* data); - -} // namespace unwindstack - -#endif // _LIBUNWINDSTACK_TESTS_TEST_UTILS_H diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp deleted file mode 100644 index ab427b545..000000000 --- a/libunwindstack/tests/UnwindOfflineTest.cpp +++ /dev/null @@ -1,1893 +0,0 @@ -/* - * Copyright (C) 2017 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 -#include -#include - -#include "ElfTestUtils.h" -#include "MemoryOffline.h" -#include "TestUtils.h" - -namespace unwindstack { - -static void AddMemory(std::string file_name, MemoryOfflineParts* parts) { - MemoryOffline* memory = new MemoryOffline; - ASSERT_TRUE(memory->Init(file_name.c_str(), 0)); - parts->Add(memory); -} - -class UnwindOfflineTest : public ::testing::Test { - protected: - void TearDown() override { - if (cwd_ != nullptr) { - ASSERT_EQ(0, chdir(cwd_)); - } - free(cwd_); - } - - void Init(const char* file_dir, ArchEnum arch, bool add_stack = true) { - dir_ = TestGetFileDirectory() + "offline/" + file_dir; - - std::string data; - ASSERT_TRUE(android::base::ReadFileToString((dir_ + "maps.txt"), &data)); - - maps_.reset(new BufferMaps(data.c_str())); - ASSERT_TRUE(maps_->Parse()); - - if (add_stack) { - std::string stack_name(dir_ + "stack.data"); - struct stat st; - if (stat(stack_name.c_str(), &st) == 0 && S_ISREG(st.st_mode)) { - std::unique_ptr stack_memory(new MemoryOffline); - ASSERT_TRUE(stack_memory->Init((dir_ + "stack.data").c_str(), 0)); - process_memory_.reset(stack_memory.release()); - } else { - std::unique_ptr stack_memory(new MemoryOfflineParts); - for (size_t i = 0;; i++) { - stack_name = dir_ + "stack" + std::to_string(i) + ".data"; - if (stat(stack_name.c_str(), &st) == -1 || !S_ISREG(st.st_mode)) { - ASSERT_TRUE(i != 0) << "No stack data files found."; - break; - } - AddMemory(stack_name, stack_memory.get()); - } - process_memory_.reset(stack_memory.release()); - } - } - - switch (arch) { - case ARCH_ARM: { - RegsArm* regs = new RegsArm; - regs_.reset(regs); - ReadRegs(regs, arm_regs_); - break; - } - case ARCH_ARM64: { - RegsArm64* regs = new RegsArm64; - regs_.reset(regs); - ReadRegs(regs, arm64_regs_); - break; - } - case ARCH_X86: { - RegsX86* regs = new RegsX86; - regs_.reset(regs); - ReadRegs(regs, x86_regs_); - break; - } - case ARCH_X86_64: { - RegsX86_64* regs = new RegsX86_64; - regs_.reset(regs); - ReadRegs(regs, x86_64_regs_); - break; - } - default: - ASSERT_TRUE(false) << "Unknown arch " << std::to_string(arch); - } - cwd_ = getcwd(nullptr, 0); - // Make dir_ an absolute directory. - if (dir_.empty() || dir_[0] != '/') { - dir_ = std::string(cwd_) + '/' + dir_; - } - ASSERT_EQ(0, chdir(dir_.c_str())); - } - - template - void ReadRegs(RegsImpl* regs, - const std::unordered_map& name_to_reg) { - FILE* fp = fopen((dir_ + "regs.txt").c_str(), "r"); - ASSERT_TRUE(fp != nullptr); - while (!feof(fp)) { - uint64_t value; - char reg_name[100]; - ASSERT_EQ(2, fscanf(fp, "%s %" SCNx64 "\n", reg_name, &value)); - std::string name(reg_name); - if (!name.empty()) { - // Remove the : from the end. - name.resize(name.size() - 1); - } - auto entry = name_to_reg.find(name); - ASSERT_TRUE(entry != name_to_reg.end()) << "Unknown register named " << name; - (*regs)[entry->second] = value; - } - fclose(fp); - } - - static std::unordered_map arm_regs_; - static std::unordered_map arm64_regs_; - static std::unordered_map x86_regs_; - static std::unordered_map x86_64_regs_; - - char* cwd_ = nullptr; - std::string dir_; - std::unique_ptr regs_; - std::unique_ptr maps_; - std::shared_ptr process_memory_; -}; - -std::unordered_map UnwindOfflineTest::arm_regs_ = { - {"r0", ARM_REG_R0}, {"r1", ARM_REG_R1}, {"r2", ARM_REG_R2}, {"r3", ARM_REG_R3}, - {"r4", ARM_REG_R4}, {"r5", ARM_REG_R5}, {"r6", ARM_REG_R6}, {"r7", ARM_REG_R7}, - {"r8", ARM_REG_R8}, {"r9", ARM_REG_R9}, {"r10", ARM_REG_R10}, {"r11", ARM_REG_R11}, - {"ip", ARM_REG_R12}, {"sp", ARM_REG_SP}, {"lr", ARM_REG_LR}, {"pc", ARM_REG_PC}, -}; - -std::unordered_map UnwindOfflineTest::arm64_regs_ = { - {"x0", ARM64_REG_R0}, {"x1", ARM64_REG_R1}, {"x2", ARM64_REG_R2}, - {"x3", ARM64_REG_R3}, {"x4", ARM64_REG_R4}, {"x5", ARM64_REG_R5}, - {"x6", ARM64_REG_R6}, {"x7", ARM64_REG_R7}, {"x8", ARM64_REG_R8}, - {"x9", ARM64_REG_R9}, {"x10", ARM64_REG_R10}, {"x11", ARM64_REG_R11}, - {"x12", ARM64_REG_R12}, {"x13", ARM64_REG_R13}, {"x14", ARM64_REG_R14}, - {"x15", ARM64_REG_R15}, {"x16", ARM64_REG_R16}, {"x17", ARM64_REG_R17}, - {"x18", ARM64_REG_R18}, {"x19", ARM64_REG_R19}, {"x20", ARM64_REG_R20}, - {"x21", ARM64_REG_R21}, {"x22", ARM64_REG_R22}, {"x23", ARM64_REG_R23}, - {"x24", ARM64_REG_R24}, {"x25", ARM64_REG_R25}, {"x26", ARM64_REG_R26}, - {"x27", ARM64_REG_R27}, {"x28", ARM64_REG_R28}, {"x29", ARM64_REG_R29}, - {"sp", ARM64_REG_SP}, {"lr", ARM64_REG_LR}, {"pc", ARM64_REG_PC}, - {"pst", ARM64_REG_PSTATE}, -}; - -std::unordered_map UnwindOfflineTest::x86_regs_ = { - {"eax", X86_REG_EAX}, {"ebx", X86_REG_EBX}, {"ecx", X86_REG_ECX}, - {"edx", X86_REG_EDX}, {"ebp", X86_REG_EBP}, {"edi", X86_REG_EDI}, - {"esi", X86_REG_ESI}, {"esp", X86_REG_ESP}, {"eip", X86_REG_EIP}, -}; - -std::unordered_map UnwindOfflineTest::x86_64_regs_ = { - {"rax", X86_64_REG_RAX}, {"rbx", X86_64_REG_RBX}, {"rcx", X86_64_REG_RCX}, - {"rdx", X86_64_REG_RDX}, {"r8", X86_64_REG_R8}, {"r9", X86_64_REG_R9}, - {"r10", X86_64_REG_R10}, {"r11", X86_64_REG_R11}, {"r12", X86_64_REG_R12}, - {"r13", X86_64_REG_R13}, {"r14", X86_64_REG_R14}, {"r15", X86_64_REG_R15}, - {"rdi", X86_64_REG_RDI}, {"rsi", X86_64_REG_RSI}, {"rbp", X86_64_REG_RBP}, - {"rsp", X86_64_REG_RSP}, {"rip", X86_64_REG_RIP}, -}; - -static std::string DumpFrames(Unwinder& unwinder) { - std::string str; - for (size_t i = 0; i < unwinder.NumFrames(); i++) { - str += unwinder.FormatFrame(i) + "\n"; - } - return str; -} - -TEST_F(UnwindOfflineTest, pc_straddle_arm) { - ASSERT_NO_FATAL_FAILURE(Init("straddle_arm/", ARCH_ARM)); - - std::unique_ptr regs_copy(regs_->Clone()); - Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.Unwind(); - - std::string frame_info(DumpFrames(unwinder)); - ASSERT_EQ(4U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; - EXPECT_EQ( - " #00 pc 0001a9f8 libc.so (abort+64)\n" - " #01 pc 00006a1b libbase.so (android::base::DefaultAborter(char const*)+6)\n" - " #02 pc 00007441 libbase.so (android::base::LogMessage::~LogMessage()+748)\n" - " #03 pc 00015147 /does/not/exist/libhidlbase.so\n", - frame_info); - EXPECT_EQ(0xf31ea9f8U, unwinder.frames()[0].pc); - EXPECT_EQ(0xe9c866f8U, unwinder.frames()[0].sp); - EXPECT_EQ(0xf2da0a1bU, unwinder.frames()[1].pc); - EXPECT_EQ(0xe9c86728U, unwinder.frames()[1].sp); - EXPECT_EQ(0xf2da1441U, unwinder.frames()[2].pc); - EXPECT_EQ(0xe9c86730U, unwinder.frames()[2].sp); - EXPECT_EQ(0xf3367147U, unwinder.frames()[3].pc); - EXPECT_EQ(0xe9c86778U, unwinder.frames()[3].sp); - - // Display build ids now. - unwinder.SetRegs(regs_copy.get()); - unwinder.SetDisplayBuildID(true); - unwinder.Unwind(); - - frame_info = DumpFrames(unwinder); - ASSERT_EQ(4U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; - EXPECT_EQ( - " #00 pc 0001a9f8 libc.so (abort+64) (BuildId: 2dd0d4ba881322a0edabeed94808048c)\n" - " #01 pc 00006a1b libbase.so (android::base::DefaultAborter(char const*)+6) (BuildId: " - "ed43842c239cac1a618e600ea91c4cbd)\n" - " #02 pc 00007441 libbase.so (android::base::LogMessage::~LogMessage()+748) (BuildId: " - "ed43842c239cac1a618e600ea91c4cbd)\n" - " #03 pc 00015147 /does/not/exist/libhidlbase.so\n", - frame_info); -} - -TEST_F(UnwindOfflineTest, pc_in_gnu_debugdata_arm) { - ASSERT_NO_FATAL_FAILURE(Init("gnu_debugdata_arm/", ARCH_ARM)); - - Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.Unwind(); - - std::string frame_info(DumpFrames(unwinder)); - ASSERT_EQ(2U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; - EXPECT_EQ( - " #00 pc 0006dc49 libandroid_runtime.so " - "(android::AndroidRuntime::javaThreadShell(void*)+80)\n" - " #01 pc 0006dce5 libandroid_runtime.so " - "(android::AndroidRuntime::javaCreateThreadEtc(int (*)(void*), void*, char const*, int, " - "unsigned int, void**))\n", - frame_info); - EXPECT_EQ(0xf1f6dc49U, unwinder.frames()[0].pc); - EXPECT_EQ(0xd8fe6930U, unwinder.frames()[0].sp); - EXPECT_EQ(0xf1f6dce5U, unwinder.frames()[1].pc); - EXPECT_EQ(0xd8fe6958U, unwinder.frames()[1].sp); -} - -TEST_F(UnwindOfflineTest, pc_straddle_arm64) { - ASSERT_NO_FATAL_FAILURE(Init("straddle_arm64/", ARCH_ARM64)); - - Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.Unwind(); - - std::string frame_info(DumpFrames(unwinder)); - ASSERT_EQ(6U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; - EXPECT_EQ( - " #00 pc 0000000000429fd8 libunwindstack_test (SignalInnerFunction+24)\n" - " #01 pc 000000000042a078 libunwindstack_test (SignalMiddleFunction+8)\n" - " #02 pc 000000000042a08c libunwindstack_test (SignalOuterFunction+8)\n" - " #03 pc 000000000042d8fc libunwindstack_test " - "(unwindstack::RemoteThroughSignal(int, unsigned int)+20)\n" - " #04 pc 000000000042d8d8 libunwindstack_test " - "(unwindstack::UnwindTest_remote_through_signal_Test::TestBody()+32)\n" - " #05 pc 0000000000455d70 libunwindstack_test (testing::Test::Run()+392)\n", - frame_info); - EXPECT_EQ(0x64d09d4fd8U, unwinder.frames()[0].pc); - EXPECT_EQ(0x7fe0d84040U, unwinder.frames()[0].sp); - EXPECT_EQ(0x64d09d5078U, unwinder.frames()[1].pc); - EXPECT_EQ(0x7fe0d84070U, unwinder.frames()[1].sp); - EXPECT_EQ(0x64d09d508cU, unwinder.frames()[2].pc); - EXPECT_EQ(0x7fe0d84080U, unwinder.frames()[2].sp); - EXPECT_EQ(0x64d09d88fcU, unwinder.frames()[3].pc); - EXPECT_EQ(0x7fe0d84090U, unwinder.frames()[3].sp); - EXPECT_EQ(0x64d09d88d8U, unwinder.frames()[4].pc); - EXPECT_EQ(0x7fe0d840f0U, unwinder.frames()[4].sp); - EXPECT_EQ(0x64d0a00d70U, unwinder.frames()[5].pc); - EXPECT_EQ(0x7fe0d84110U, unwinder.frames()[5].sp); -} - -TEST_F(UnwindOfflineTest, jit_debug_x86) { - ASSERT_NO_FATAL_FAILURE(Init("jit_debug_x86/", ARCH_X86)); - - MemoryOfflineParts* memory = new MemoryOfflineParts; - AddMemory(dir_ + "descriptor.data", memory); - AddMemory(dir_ + "stack.data", memory); - for (size_t i = 0; i < 7; i++) { - AddMemory(dir_ + "entry" + std::to_string(i) + ".data", memory); - AddMemory(dir_ + "jit" + std::to_string(i) + ".data", memory); - } - process_memory_.reset(memory); - - JitDebug jit_debug(process_memory_); - Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.SetJitDebug(&jit_debug); - unwinder.Unwind(); - - std::string frame_info(DumpFrames(unwinder)); - ASSERT_EQ(69U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; - EXPECT_EQ( - " #00 pc 00068fb8 libarttestd.so (art::CauseSegfault()+72)\n" - " #01 pc 00067f00 libarttestd.so (Java_Main_unwindInProcess+10032)\n" - " #02 pc 000021a8 137-cfi.odex (boolean Main.unwindInProcess(boolean, int, " - "boolean)+136)\n" - " #03 pc 0000fe80 anonymous:ee74c000 (boolean Main.bar(boolean)+64)\n" - " #04 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n" - " #05 pc 00146ab5 libartd.so " - "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " - "const*)+885)\n" - " #06 pc 0039cf0d libartd.so " - "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " - "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n" - " #07 pc 00392552 libartd.so " - "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " - "art::ShadowFrame&, art::JValue, bool)+354)\n" - " #08 pc 0039399a libartd.so " - "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " - "const&, art::ShadowFrame*)+234)\n" - " #09 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n" - " #10 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n" - " #11 pc 0000fe03 anonymous:ee74c000 (int Main.compare(Main, Main)+51)\n" - " #12 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n" - " #13 pc 00146ab5 libartd.so " - "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " - "const*)+885)\n" - " #14 pc 0039cf0d libartd.so " - "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " - "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n" - " #15 pc 00392552 libartd.so " - "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " - "art::ShadowFrame&, art::JValue, bool)+354)\n" - " #16 pc 0039399a libartd.so " - "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " - "const&, art::ShadowFrame*)+234)\n" - " #17 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n" - " #18 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n" - " #19 pc 0000fd3b anonymous:ee74c000 (int Main.compare(java.lang.Object, " - "java.lang.Object)+107)\n" - " #20 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n" - " #21 pc 00146ab5 libartd.so " - "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " - "const*)+885)\n" - " #22 pc 0039cf0d libartd.so " - "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " - "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n" - " #23 pc 00392552 libartd.so " - "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " - "art::ShadowFrame&, art::JValue, bool)+354)\n" - " #24 pc 0039399a libartd.so " - "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " - "const&, art::ShadowFrame*)+234)\n" - " #25 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n" - " #26 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n" - " #27 pc 0000fbdb anonymous:ee74c000 (int " - "java.util.Arrays.binarySearch0(java.lang.Object[], int, int, java.lang.Object, " - "java.util.Comparator)+331)\n" - " #28 pc 006ad6a2 libartd.so (art_quick_invoke_static_stub+418)\n" - " #29 pc 00146acb libartd.so " - "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " - "const*)+907)\n" - " #30 pc 0039cf0d libartd.so " - "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " - "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n" - " #31 pc 00392552 libartd.so " - "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " - "art::ShadowFrame&, art::JValue, bool)+354)\n" - " #32 pc 0039399a libartd.so " - "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " - "const&, art::ShadowFrame*)+234)\n" - " #33 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n" - " #34 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n" - " #35 pc 0000f624 anonymous:ee74c000 (boolean Main.foo()+164)\n" - " #36 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n" - " #37 pc 00146ab5 libartd.so " - "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " - "const*)+885)\n" - " #38 pc 0039cf0d libartd.so " - "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " - "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n" - " #39 pc 00392552 libartd.so " - "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " - "art::ShadowFrame&, art::JValue, bool)+354)\n" - " #40 pc 0039399a libartd.so " - "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " - "const&, art::ShadowFrame*)+234)\n" - " #41 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n" - " #42 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n" - " #43 pc 0000eedb anonymous:ee74c000 (void Main.runPrimary()+59)\n" - " #44 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n" - " #45 pc 00146ab5 libartd.so " - "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " - "const*)+885)\n" - " #46 pc 0039cf0d libartd.so " - "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " - "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n" - " #47 pc 00392552 libartd.so " - "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " - "art::ShadowFrame&, art::JValue, bool)+354)\n" - " #48 pc 0039399a libartd.so " - "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " - "const&, art::ShadowFrame*)+234)\n" - " #49 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n" - " #50 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n" - " #51 pc 0000ac21 anonymous:ee74c000 (void Main.main(java.lang.String[])+97)\n" - " #52 pc 006ad6a2 libartd.so (art_quick_invoke_static_stub+418)\n" - " #53 pc 00146acb libartd.so " - "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " - "const*)+907)\n" - " #54 pc 0039cf0d libartd.so " - "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " - "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n" - " #55 pc 00392552 libartd.so " - "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " - "art::ShadowFrame&, art::JValue, bool)+354)\n" - " #56 pc 0039399a libartd.so " - "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " - "const&, art::ShadowFrame*)+234)\n" - " #57 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n" - " #58 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n" - " #59 pc 006ad6a2 libartd.so (art_quick_invoke_static_stub+418)\n" - " #60 pc 00146acb libartd.so " - "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " - "const*)+907)\n" - " #61 pc 005aac95 libartd.so " - "(art::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, " - "art::ArgArray*, art::JValue*, char const*)+85)\n" - " #62 pc 005aab5a libartd.so " - "(art::InvokeWithVarArgs(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, " - "_jmethodID*, char*)+362)\n" - " #63 pc 0048a3dd libartd.so " - "(art::JNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, char*)+125)\n" - " #64 pc 0018448c libartd.so " - "(art::CheckJNI::CallMethodV(char const*, _JNIEnv*, _jobject*, _jclass*, _jmethodID*, char*, " - "art::Primitive::Type, art::InvokeType)+1964)\n" - " #65 pc 0017cf06 libartd.so " - "(art::CheckJNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, char*)+70)\n" - " #66 pc 00001d8c dalvikvm32 " - "(_JNIEnv::CallStaticVoidMethod(_jclass*, _jmethodID*, ...)+60)\n" - " #67 pc 00001a80 dalvikvm32 (main+1312)\n" - " #68 pc 00018275 libc.so\n", - frame_info); - EXPECT_EQ(0xeb89bfb8U, unwinder.frames()[0].pc); - EXPECT_EQ(0xffeb5280U, unwinder.frames()[0].sp); - EXPECT_EQ(0xeb89af00U, unwinder.frames()[1].pc); - EXPECT_EQ(0xffeb52a0U, unwinder.frames()[1].sp); - EXPECT_EQ(0xec6061a8U, unwinder.frames()[2].pc); - EXPECT_EQ(0xffeb5ce0U, unwinder.frames()[2].sp); - EXPECT_EQ(0xee75be80U, unwinder.frames()[3].pc); - EXPECT_EQ(0xffeb5d30U, unwinder.frames()[3].sp); - EXPECT_EQ(0xf728e4d2U, unwinder.frames()[4].pc); - EXPECT_EQ(0xffeb5d60U, unwinder.frames()[4].sp); - EXPECT_EQ(0xf6d27ab5U, unwinder.frames()[5].pc); - EXPECT_EQ(0xffeb5d80U, unwinder.frames()[5].sp); - EXPECT_EQ(0xf6f7df0dU, unwinder.frames()[6].pc); - EXPECT_EQ(0xffeb5e20U, unwinder.frames()[6].sp); - EXPECT_EQ(0xf6f73552U, unwinder.frames()[7].pc); - EXPECT_EQ(0xffeb5ec0U, unwinder.frames()[7].sp); - EXPECT_EQ(0xf6f7499aU, unwinder.frames()[8].pc); - EXPECT_EQ(0xffeb5f40U, unwinder.frames()[8].sp); - EXPECT_EQ(0xf7265362U, unwinder.frames()[9].pc); - EXPECT_EQ(0xffeb5fb0U, unwinder.frames()[9].sp); - EXPECT_EQ(0xf72945bdU, unwinder.frames()[10].pc); - EXPECT_EQ(0xffeb6110U, unwinder.frames()[10].sp); - EXPECT_EQ(0xee75be03U, unwinder.frames()[11].pc); - EXPECT_EQ(0xffeb6160U, unwinder.frames()[11].sp); - EXPECT_EQ(0xf728e4d2U, unwinder.frames()[12].pc); - EXPECT_EQ(0xffeb6180U, unwinder.frames()[12].sp); - EXPECT_EQ(0xf6d27ab5U, unwinder.frames()[13].pc); - EXPECT_EQ(0xffeb61b0U, unwinder.frames()[13].sp); - EXPECT_EQ(0xf6f7df0dU, unwinder.frames()[14].pc); - EXPECT_EQ(0xffeb6250U, unwinder.frames()[14].sp); - EXPECT_EQ(0xf6f73552U, unwinder.frames()[15].pc); - EXPECT_EQ(0xffeb62f0U, unwinder.frames()[15].sp); - EXPECT_EQ(0xf6f7499aU, unwinder.frames()[16].pc); - EXPECT_EQ(0xffeb6370U, unwinder.frames()[16].sp); - EXPECT_EQ(0xf7265362U, unwinder.frames()[17].pc); - EXPECT_EQ(0xffeb63e0U, unwinder.frames()[17].sp); - EXPECT_EQ(0xf72945bdU, unwinder.frames()[18].pc); - EXPECT_EQ(0xffeb6530U, unwinder.frames()[18].sp); - EXPECT_EQ(0xee75bd3bU, unwinder.frames()[19].pc); - EXPECT_EQ(0xffeb6580U, unwinder.frames()[19].sp); - EXPECT_EQ(0xf728e4d2U, unwinder.frames()[20].pc); - EXPECT_EQ(0xffeb65b0U, unwinder.frames()[20].sp); - EXPECT_EQ(0xf6d27ab5U, unwinder.frames()[21].pc); - EXPECT_EQ(0xffeb65e0U, unwinder.frames()[21].sp); - EXPECT_EQ(0xf6f7df0dU, unwinder.frames()[22].pc); - EXPECT_EQ(0xffeb6680U, unwinder.frames()[22].sp); - EXPECT_EQ(0xf6f73552U, unwinder.frames()[23].pc); - EXPECT_EQ(0xffeb6720U, unwinder.frames()[23].sp); - EXPECT_EQ(0xf6f7499aU, unwinder.frames()[24].pc); - EXPECT_EQ(0xffeb67a0U, unwinder.frames()[24].sp); - EXPECT_EQ(0xf7265362U, unwinder.frames()[25].pc); - EXPECT_EQ(0xffeb6810U, unwinder.frames()[25].sp); - EXPECT_EQ(0xf72945bdU, unwinder.frames()[26].pc); - EXPECT_EQ(0xffeb6960U, unwinder.frames()[26].sp); - EXPECT_EQ(0xee75bbdbU, unwinder.frames()[27].pc); - EXPECT_EQ(0xffeb69b0U, unwinder.frames()[27].sp); - EXPECT_EQ(0xf728e6a2U, unwinder.frames()[28].pc); - EXPECT_EQ(0xffeb69f0U, unwinder.frames()[28].sp); - EXPECT_EQ(0xf6d27acbU, unwinder.frames()[29].pc); - EXPECT_EQ(0xffeb6a20U, unwinder.frames()[29].sp); - EXPECT_EQ(0xf6f7df0dU, unwinder.frames()[30].pc); - EXPECT_EQ(0xffeb6ac0U, unwinder.frames()[30].sp); - EXPECT_EQ(0xf6f73552U, unwinder.frames()[31].pc); - EXPECT_EQ(0xffeb6b60U, unwinder.frames()[31].sp); - EXPECT_EQ(0xf6f7499aU, unwinder.frames()[32].pc); - EXPECT_EQ(0xffeb6be0U, unwinder.frames()[32].sp); - EXPECT_EQ(0xf7265362U, unwinder.frames()[33].pc); - EXPECT_EQ(0xffeb6c50U, unwinder.frames()[33].sp); - EXPECT_EQ(0xf72945bdU, unwinder.frames()[34].pc); - EXPECT_EQ(0xffeb6dd0U, unwinder.frames()[34].sp); - EXPECT_EQ(0xee75b624U, unwinder.frames()[35].pc); - EXPECT_EQ(0xffeb6e20U, unwinder.frames()[35].sp); - EXPECT_EQ(0xf728e4d2U, unwinder.frames()[36].pc); - EXPECT_EQ(0xffeb6e50U, unwinder.frames()[36].sp); - EXPECT_EQ(0xf6d27ab5U, unwinder.frames()[37].pc); - EXPECT_EQ(0xffeb6e70U, unwinder.frames()[37].sp); - EXPECT_EQ(0xf6f7df0dU, unwinder.frames()[38].pc); - EXPECT_EQ(0xffeb6f10U, unwinder.frames()[38].sp); - EXPECT_EQ(0xf6f73552U, unwinder.frames()[39].pc); - EXPECT_EQ(0xffeb6fb0U, unwinder.frames()[39].sp); - EXPECT_EQ(0xf6f7499aU, unwinder.frames()[40].pc); - EXPECT_EQ(0xffeb7030U, unwinder.frames()[40].sp); - EXPECT_EQ(0xf7265362U, unwinder.frames()[41].pc); - EXPECT_EQ(0xffeb70a0U, unwinder.frames()[41].sp); - EXPECT_EQ(0xf72945bdU, unwinder.frames()[42].pc); - EXPECT_EQ(0xffeb71f0U, unwinder.frames()[42].sp); - EXPECT_EQ(0xee75aedbU, unwinder.frames()[43].pc); - EXPECT_EQ(0xffeb7240U, unwinder.frames()[43].sp); - EXPECT_EQ(0xf728e4d2U, unwinder.frames()[44].pc); - EXPECT_EQ(0xffeb72a0U, unwinder.frames()[44].sp); - EXPECT_EQ(0xf6d27ab5U, unwinder.frames()[45].pc); - EXPECT_EQ(0xffeb72c0U, unwinder.frames()[45].sp); - EXPECT_EQ(0xf6f7df0dU, unwinder.frames()[46].pc); - EXPECT_EQ(0xffeb7360U, unwinder.frames()[46].sp); - EXPECT_EQ(0xf6f73552U, unwinder.frames()[47].pc); - EXPECT_EQ(0xffeb7400U, unwinder.frames()[47].sp); - EXPECT_EQ(0xf6f7499aU, unwinder.frames()[48].pc); - EXPECT_EQ(0xffeb7480U, unwinder.frames()[48].sp); - EXPECT_EQ(0xf7265362U, unwinder.frames()[49].pc); - EXPECT_EQ(0xffeb74f0U, unwinder.frames()[49].sp); - EXPECT_EQ(0xf72945bdU, unwinder.frames()[50].pc); - EXPECT_EQ(0xffeb7680U, unwinder.frames()[50].sp); - EXPECT_EQ(0xee756c21U, unwinder.frames()[51].pc); - EXPECT_EQ(0xffeb76d0U, unwinder.frames()[51].sp); - EXPECT_EQ(0xf728e6a2U, unwinder.frames()[52].pc); - EXPECT_EQ(0xffeb76f0U, unwinder.frames()[52].sp); - EXPECT_EQ(0xf6d27acbU, unwinder.frames()[53].pc); - EXPECT_EQ(0xffeb7710U, unwinder.frames()[53].sp); - EXPECT_EQ(0xf6f7df0dU, unwinder.frames()[54].pc); - EXPECT_EQ(0xffeb77b0U, unwinder.frames()[54].sp); - EXPECT_EQ(0xf6f73552U, unwinder.frames()[55].pc); - EXPECT_EQ(0xffeb7850U, unwinder.frames()[55].sp); - EXPECT_EQ(0xf6f7499aU, unwinder.frames()[56].pc); - EXPECT_EQ(0xffeb78d0U, unwinder.frames()[56].sp); - EXPECT_EQ(0xf7265362U, unwinder.frames()[57].pc); - EXPECT_EQ(0xffeb7940U, unwinder.frames()[57].sp); - EXPECT_EQ(0xf72945bdU, unwinder.frames()[58].pc); - EXPECT_EQ(0xffeb7a80U, unwinder.frames()[58].sp); - EXPECT_EQ(0xf728e6a2U, unwinder.frames()[59].pc); - EXPECT_EQ(0xffeb7ad0U, unwinder.frames()[59].sp); - EXPECT_EQ(0xf6d27acbU, unwinder.frames()[60].pc); - EXPECT_EQ(0xffeb7af0U, unwinder.frames()[60].sp); - EXPECT_EQ(0xf718bc95U, unwinder.frames()[61].pc); - EXPECT_EQ(0xffeb7b90U, unwinder.frames()[61].sp); - EXPECT_EQ(0xf718bb5aU, unwinder.frames()[62].pc); - EXPECT_EQ(0xffeb7c50U, unwinder.frames()[62].sp); - EXPECT_EQ(0xf706b3ddU, unwinder.frames()[63].pc); - EXPECT_EQ(0xffeb7d10U, unwinder.frames()[63].sp); - EXPECT_EQ(0xf6d6548cU, unwinder.frames()[64].pc); - EXPECT_EQ(0xffeb7d70U, unwinder.frames()[64].sp); - EXPECT_EQ(0xf6d5df06U, unwinder.frames()[65].pc); - EXPECT_EQ(0xffeb7df0U, unwinder.frames()[65].sp); - EXPECT_EQ(0x56574d8cU, unwinder.frames()[66].pc); - EXPECT_EQ(0xffeb7e40U, unwinder.frames()[66].sp); - EXPECT_EQ(0x56574a80U, unwinder.frames()[67].pc); - EXPECT_EQ(0xffeb7e70U, unwinder.frames()[67].sp); - EXPECT_EQ(0xf7363275U, unwinder.frames()[68].pc); - EXPECT_EQ(0xffeb7ef0U, unwinder.frames()[68].sp); -} - -TEST_F(UnwindOfflineTest, jit_debug_arm) { - ASSERT_NO_FATAL_FAILURE(Init("jit_debug_arm/", ARCH_ARM)); - - MemoryOfflineParts* memory = new MemoryOfflineParts; - AddMemory(dir_ + "descriptor.data", memory); - AddMemory(dir_ + "descriptor1.data", memory); - AddMemory(dir_ + "stack.data", memory); - for (size_t i = 0; i < 7; i++) { - AddMemory(dir_ + "entry" + std::to_string(i) + ".data", memory); - AddMemory(dir_ + "jit" + std::to_string(i) + ".data", memory); - } - process_memory_.reset(memory); - - JitDebug jit_debug(process_memory_); - Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.SetJitDebug(&jit_debug); - unwinder.Unwind(); - - std::string frame_info(DumpFrames(unwinder)); - ASSERT_EQ(76U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; - EXPECT_EQ( - " #00 pc 00018a5e libarttestd.so (Java_Main_unwindInProcess+866)\n" - " #01 pc 0000212d 137-cfi.odex (boolean Main.unwindInProcess(boolean, int, " - "boolean)+92)\n" - " #02 pc 00011cb1 anonymous:e2796000 (boolean Main.bar(boolean)+72)\n" - " #03 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n" - " #04 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n" - " #05 pc 000bf7a9 libartd.so " - "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " - "const*)+864)\n" - " #06 pc 00247833 libartd.so " - "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " - "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n" - " #07 pc 0022e935 libartd.so " - "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " - "art::ShadowFrame&, art::JValue, bool)+244)\n" - " #08 pc 0022f71d libartd.so " - "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " - "const&, art::ShadowFrame*)+128)\n" - " #09 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n" - " #10 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n" - " #11 pc 00011c31 anonymous:e2796000 (int Main.compare(Main, Main)+64)\n" - " #12 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n" - " #13 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n" - " #14 pc 000bf7a9 libartd.so " - "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " - "const*)+864)\n" - " #15 pc 00247833 libartd.so " - "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " - "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n" - " #16 pc 0022e935 libartd.so " - "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " - "art::ShadowFrame&, art::JValue, bool)+244)\n" - " #17 pc 0022f71d libartd.so " - "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " - "const&, art::ShadowFrame*)+128)\n" - " #18 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n" - " #19 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n" - " #20 pc 00011b77 anonymous:e2796000 (int Main.compare(java.lang.Object, " - "java.lang.Object)+118)\n" - " #21 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n" - " #22 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n" - " #23 pc 000bf7a9 libartd.so " - "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " - "const*)+864)\n" - " #24 pc 00247833 libartd.so " - "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " - "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n" - " #25 pc 0022e935 libartd.so " - "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " - "art::ShadowFrame&, art::JValue, bool)+244)\n" - " #26 pc 0022f71d libartd.so " - "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " - "const&, art::ShadowFrame*)+128)\n" - " #27 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n" - " #28 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n" - " #29 pc 00011a29 anonymous:e2796000 (int " - "java.util.Arrays.binarySearch0(java.lang.Object[], int, int, java.lang.Object, " - "java.util.Comparator)+304)\n" - " #30 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n" - " #31 pc 0046722f libartd.so (art_quick_invoke_static_stub+226)\n" - " #32 pc 000bf7bb libartd.so " - "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " - "const*)+882)\n" - " #33 pc 00247833 libartd.so " - "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " - "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n" - " #34 pc 0022e935 libartd.so " - "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " - "art::ShadowFrame&, art::JValue, bool)+244)\n" - " #35 pc 0022f71d libartd.so " - "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " - "const&, art::ShadowFrame*)+128)\n" - " #36 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n" - " #37 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n" - " #38 pc 0001139b anonymous:e2796000 (boolean Main.foo()+178)\n" - " #39 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n" - " #40 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n" - " #41 pc 000bf7a9 libartd.so " - "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " - "const*)+864)\n" - " #42 pc 00247833 libartd.so " - "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " - "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n" - " #43 pc 0022e935 libartd.so " - "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " - "art::ShadowFrame&, art::JValue, bool)+244)\n" - " #44 pc 0022f71d libartd.so " - "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " - "const&, art::ShadowFrame*)+128)\n" - " #45 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n" - " #46 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n" - " #47 pc 00010aa7 anonymous:e2796000 (void Main.runPrimary()+70)\n" - " #48 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n" - " #49 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n" - " #50 pc 000bf7a9 libartd.so " - "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " - "const*)+864)\n" - " #51 pc 00247833 libartd.so " - "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " - "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n" - " #52 pc 0022e935 libartd.so " - "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " - "art::ShadowFrame&, art::JValue, bool)+244)\n" - " #53 pc 0022f71d libartd.so " - "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " - "const&, art::ShadowFrame*)+128)\n" - " #54 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n" - " #55 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n" - " #56 pc 0000ba99 anonymous:e2796000 (void Main.main(java.lang.String[])+144)\n" - " #57 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n" - " #58 pc 0046722f libartd.so (art_quick_invoke_static_stub+226)\n" - " #59 pc 000bf7bb libartd.so " - "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " - "const*)+882)\n" - " #60 pc 00247833 libartd.so " - "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, " - "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n" - " #61 pc 0022e935 libartd.so " - "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " - "art::ShadowFrame&, art::JValue, bool)+244)\n" - " #62 pc 0022f71d libartd.so " - "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " - "const&, art::ShadowFrame*)+128)\n" - " #63 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n" - " #64 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n" - " #65 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n" - " #66 pc 0046722f libartd.so (art_quick_invoke_static_stub+226)\n" - " #67 pc 000bf7bb libartd.so " - "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char " - "const*)+882)\n" - " #68 pc 003b292d libartd.so " - "(art::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, " - "art::ArgArray*, art::JValue*, char const*)+52)\n" - " #69 pc 003b26c3 libartd.so " - "(art::InvokeWithVarArgs(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, " - "_jmethodID*, std::__va_list)+210)\n" - " #70 pc 00308411 libartd.so " - "(art::JNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, std::__va_list)+76)\n" - " #71 pc 000e6a9f libartd.so " - "(art::CheckJNI::CallMethodV(char const*, _JNIEnv*, _jobject*, _jclass*, _jmethodID*, " - "std::__va_list, art::Primitive::Type, art::InvokeType)+1486)\n" - " #72 pc 000e19b9 libartd.so " - "(art::CheckJNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, std::__va_list)+40)\n" - " #73 pc 0000159f dalvikvm32 " - "(_JNIEnv::CallStaticVoidMethod(_jclass*, _jmethodID*, ...)+30)\n" - " #74 pc 00001349 dalvikvm32 (main+896)\n" - " #75 pc 000850c9 libc.so\n", - frame_info); - EXPECT_EQ(0xdfe66a5eU, unwinder.frames()[0].pc); - EXPECT_EQ(0xff85d180U, unwinder.frames()[0].sp); - EXPECT_EQ(0xe044712dU, unwinder.frames()[1].pc); - EXPECT_EQ(0xff85d200U, unwinder.frames()[1].sp); - EXPECT_EQ(0xe27a7cb1U, unwinder.frames()[2].pc); - EXPECT_EQ(0xff85d290U, unwinder.frames()[2].sp); - EXPECT_EQ(0xed75c175U, unwinder.frames()[3].pc); - EXPECT_EQ(0xff85d2b0U, unwinder.frames()[3].sp); - EXPECT_EQ(0xed761129U, unwinder.frames()[4].pc); - EXPECT_EQ(0xff85d2e8U, unwinder.frames()[4].sp); - EXPECT_EQ(0xed3b97a9U, unwinder.frames()[5].pc); - EXPECT_EQ(0xff85d370U, unwinder.frames()[5].sp); - EXPECT_EQ(0xed541833U, unwinder.frames()[6].pc); - EXPECT_EQ(0xff85d3d8U, unwinder.frames()[6].sp); - EXPECT_EQ(0xed528935U, unwinder.frames()[7].pc); - EXPECT_EQ(0xff85d428U, unwinder.frames()[7].sp); - EXPECT_EQ(0xed52971dU, unwinder.frames()[8].pc); - EXPECT_EQ(0xff85d470U, unwinder.frames()[8].sp); - EXPECT_EQ(0xed73c865U, unwinder.frames()[9].pc); - EXPECT_EQ(0xff85d4b0U, unwinder.frames()[9].sp); - EXPECT_EQ(0xed7606ffU, unwinder.frames()[10].pc); - EXPECT_EQ(0xff85d5d0U, unwinder.frames()[10].sp); - EXPECT_EQ(0xe27a7c31U, unwinder.frames()[11].pc); - EXPECT_EQ(0xff85d640U, unwinder.frames()[11].sp); - EXPECT_EQ(0xed75c175U, unwinder.frames()[12].pc); - EXPECT_EQ(0xff85d660U, unwinder.frames()[12].sp); - EXPECT_EQ(0xed761129U, unwinder.frames()[13].pc); - EXPECT_EQ(0xff85d698U, unwinder.frames()[13].sp); - EXPECT_EQ(0xed3b97a9U, unwinder.frames()[14].pc); - EXPECT_EQ(0xff85d720U, unwinder.frames()[14].sp); - EXPECT_EQ(0xed541833U, unwinder.frames()[15].pc); - EXPECT_EQ(0xff85d788U, unwinder.frames()[15].sp); - EXPECT_EQ(0xed528935U, unwinder.frames()[16].pc); - EXPECT_EQ(0xff85d7d8U, unwinder.frames()[16].sp); - EXPECT_EQ(0xed52971dU, unwinder.frames()[17].pc); - EXPECT_EQ(0xff85d820U, unwinder.frames()[17].sp); - EXPECT_EQ(0xed73c865U, unwinder.frames()[18].pc); - EXPECT_EQ(0xff85d860U, unwinder.frames()[18].sp); - EXPECT_EQ(0xed7606ffU, unwinder.frames()[19].pc); - EXPECT_EQ(0xff85d970U, unwinder.frames()[19].sp); - EXPECT_EQ(0xe27a7b77U, unwinder.frames()[20].pc); - EXPECT_EQ(0xff85d9e0U, unwinder.frames()[20].sp); - EXPECT_EQ(0xed75c175U, unwinder.frames()[21].pc); - EXPECT_EQ(0xff85da10U, unwinder.frames()[21].sp); - EXPECT_EQ(0xed761129U, unwinder.frames()[22].pc); - EXPECT_EQ(0xff85da48U, unwinder.frames()[22].sp); - EXPECT_EQ(0xed3b97a9U, unwinder.frames()[23].pc); - EXPECT_EQ(0xff85dad0U, unwinder.frames()[23].sp); - EXPECT_EQ(0xed541833U, unwinder.frames()[24].pc); - EXPECT_EQ(0xff85db38U, unwinder.frames()[24].sp); - EXPECT_EQ(0xed528935U, unwinder.frames()[25].pc); - EXPECT_EQ(0xff85db88U, unwinder.frames()[25].sp); - EXPECT_EQ(0xed52971dU, unwinder.frames()[26].pc); - EXPECT_EQ(0xff85dbd0U, unwinder.frames()[26].sp); - EXPECT_EQ(0xed73c865U, unwinder.frames()[27].pc); - EXPECT_EQ(0xff85dc10U, unwinder.frames()[27].sp); - EXPECT_EQ(0xed7606ffU, unwinder.frames()[28].pc); - EXPECT_EQ(0xff85dd20U, unwinder.frames()[28].sp); - EXPECT_EQ(0xe27a7a29U, unwinder.frames()[29].pc); - EXPECT_EQ(0xff85dd90U, unwinder.frames()[29].sp); - EXPECT_EQ(0xed75c175U, unwinder.frames()[30].pc); - EXPECT_EQ(0xff85ddc0U, unwinder.frames()[30].sp); - EXPECT_EQ(0xed76122fU, unwinder.frames()[31].pc); - EXPECT_EQ(0xff85de08U, unwinder.frames()[31].sp); - EXPECT_EQ(0xed3b97bbU, unwinder.frames()[32].pc); - EXPECT_EQ(0xff85de90U, unwinder.frames()[32].sp); - EXPECT_EQ(0xed541833U, unwinder.frames()[33].pc); - EXPECT_EQ(0xff85def8U, unwinder.frames()[33].sp); - EXPECT_EQ(0xed528935U, unwinder.frames()[34].pc); - EXPECT_EQ(0xff85df48U, unwinder.frames()[34].sp); - EXPECT_EQ(0xed52971dU, unwinder.frames()[35].pc); - EXPECT_EQ(0xff85df90U, unwinder.frames()[35].sp); - EXPECT_EQ(0xed73c865U, unwinder.frames()[36].pc); - EXPECT_EQ(0xff85dfd0U, unwinder.frames()[36].sp); - EXPECT_EQ(0xed7606ffU, unwinder.frames()[37].pc); - EXPECT_EQ(0xff85e110U, unwinder.frames()[37].sp); - EXPECT_EQ(0xe27a739bU, unwinder.frames()[38].pc); - EXPECT_EQ(0xff85e180U, unwinder.frames()[38].sp); - EXPECT_EQ(0xed75c175U, unwinder.frames()[39].pc); - EXPECT_EQ(0xff85e1b0U, unwinder.frames()[39].sp); - EXPECT_EQ(0xed761129U, unwinder.frames()[40].pc); - EXPECT_EQ(0xff85e1e0U, unwinder.frames()[40].sp); - EXPECT_EQ(0xed3b97a9U, unwinder.frames()[41].pc); - EXPECT_EQ(0xff85e268U, unwinder.frames()[41].sp); - EXPECT_EQ(0xed541833U, unwinder.frames()[42].pc); - EXPECT_EQ(0xff85e2d0U, unwinder.frames()[42].sp); - EXPECT_EQ(0xed528935U, unwinder.frames()[43].pc); - EXPECT_EQ(0xff85e320U, unwinder.frames()[43].sp); - EXPECT_EQ(0xed52971dU, unwinder.frames()[44].pc); - EXPECT_EQ(0xff85e368U, unwinder.frames()[44].sp); - EXPECT_EQ(0xed73c865U, unwinder.frames()[45].pc); - EXPECT_EQ(0xff85e3a8U, unwinder.frames()[45].sp); - EXPECT_EQ(0xed7606ffU, unwinder.frames()[46].pc); - EXPECT_EQ(0xff85e4c0U, unwinder.frames()[46].sp); - EXPECT_EQ(0xe27a6aa7U, unwinder.frames()[47].pc); - EXPECT_EQ(0xff85e530U, unwinder.frames()[47].sp); - EXPECT_EQ(0xed75c175U, unwinder.frames()[48].pc); - EXPECT_EQ(0xff85e5a0U, unwinder.frames()[48].sp); - EXPECT_EQ(0xed761129U, unwinder.frames()[49].pc); - EXPECT_EQ(0xff85e5d8U, unwinder.frames()[49].sp); - EXPECT_EQ(0xed3b97a9U, unwinder.frames()[50].pc); - EXPECT_EQ(0xff85e660U, unwinder.frames()[50].sp); - EXPECT_EQ(0xed541833U, unwinder.frames()[51].pc); - EXPECT_EQ(0xff85e6c8U, unwinder.frames()[51].sp); - EXPECT_EQ(0xed528935U, unwinder.frames()[52].pc); - EXPECT_EQ(0xff85e718U, unwinder.frames()[52].sp); - EXPECT_EQ(0xed52971dU, unwinder.frames()[53].pc); - EXPECT_EQ(0xff85e760U, unwinder.frames()[53].sp); - EXPECT_EQ(0xed73c865U, unwinder.frames()[54].pc); - EXPECT_EQ(0xff85e7a0U, unwinder.frames()[54].sp); - EXPECT_EQ(0xed7606ffU, unwinder.frames()[55].pc); - EXPECT_EQ(0xff85e8f0U, unwinder.frames()[55].sp); - EXPECT_EQ(0xe27a1a99U, unwinder.frames()[56].pc); - EXPECT_EQ(0xff85e960U, unwinder.frames()[56].sp); - EXPECT_EQ(0xed75c175U, unwinder.frames()[57].pc); - EXPECT_EQ(0xff85e990U, unwinder.frames()[57].sp); - EXPECT_EQ(0xed76122fU, unwinder.frames()[58].pc); - EXPECT_EQ(0xff85e9c8U, unwinder.frames()[58].sp); - EXPECT_EQ(0xed3b97bbU, unwinder.frames()[59].pc); - EXPECT_EQ(0xff85ea50U, unwinder.frames()[59].sp); - EXPECT_EQ(0xed541833U, unwinder.frames()[60].pc); - EXPECT_EQ(0xff85eab8U, unwinder.frames()[60].sp); - EXPECT_EQ(0xed528935U, unwinder.frames()[61].pc); - EXPECT_EQ(0xff85eb08U, unwinder.frames()[61].sp); - EXPECT_EQ(0xed52971dU, unwinder.frames()[62].pc); - EXPECT_EQ(0xff85eb50U, unwinder.frames()[62].sp); - EXPECT_EQ(0xed73c865U, unwinder.frames()[63].pc); - EXPECT_EQ(0xff85eb90U, unwinder.frames()[63].sp); - EXPECT_EQ(0xed7606ffU, unwinder.frames()[64].pc); - EXPECT_EQ(0xff85ec90U, unwinder.frames()[64].sp); - EXPECT_EQ(0xed75c175U, unwinder.frames()[65].pc); - EXPECT_EQ(0xff85ed00U, unwinder.frames()[65].sp); - EXPECT_EQ(0xed76122fU, unwinder.frames()[66].pc); - EXPECT_EQ(0xff85ed38U, unwinder.frames()[66].sp); - EXPECT_EQ(0xed3b97bbU, unwinder.frames()[67].pc); - EXPECT_EQ(0xff85edc0U, unwinder.frames()[67].sp); - EXPECT_EQ(0xed6ac92dU, unwinder.frames()[68].pc); - EXPECT_EQ(0xff85ee28U, unwinder.frames()[68].sp); - EXPECT_EQ(0xed6ac6c3U, unwinder.frames()[69].pc); - EXPECT_EQ(0xff85eeb8U, unwinder.frames()[69].sp); - EXPECT_EQ(0xed602411U, unwinder.frames()[70].pc); - EXPECT_EQ(0xff85ef48U, unwinder.frames()[70].sp); - EXPECT_EQ(0xed3e0a9fU, unwinder.frames()[71].pc); - EXPECT_EQ(0xff85ef90U, unwinder.frames()[71].sp); - EXPECT_EQ(0xed3db9b9U, unwinder.frames()[72].pc); - EXPECT_EQ(0xff85f008U, unwinder.frames()[72].sp); - EXPECT_EQ(0xab0d459fU, unwinder.frames()[73].pc); - EXPECT_EQ(0xff85f038U, unwinder.frames()[73].sp); - EXPECT_EQ(0xab0d4349U, unwinder.frames()[74].pc); - EXPECT_EQ(0xff85f050U, unwinder.frames()[74].sp); - EXPECT_EQ(0xedb0d0c9U, unwinder.frames()[75].pc); - EXPECT_EQ(0xff85f0c0U, unwinder.frames()[75].sp); -} - -struct LeakType { - LeakType(Maps* maps, Regs* regs, std::shared_ptr& process_memory) - : maps(maps), regs(regs), process_memory(process_memory) {} - - Maps* maps; - Regs* regs; - std::shared_ptr& process_memory; -}; - -static void OfflineUnwind(void* data) { - LeakType* leak_data = reinterpret_cast(data); - - std::unique_ptr regs_copy(leak_data->regs->Clone()); - JitDebug jit_debug(leak_data->process_memory); - Unwinder unwinder(128, leak_data->maps, regs_copy.get(), leak_data->process_memory); - unwinder.SetJitDebug(&jit_debug); - unwinder.Unwind(); - ASSERT_EQ(76U, unwinder.NumFrames()); -} - -TEST_F(UnwindOfflineTest, unwind_offline_check_for_leaks) { - ASSERT_NO_FATAL_FAILURE(Init("jit_debug_arm/", ARCH_ARM)); - - MemoryOfflineParts* memory = new MemoryOfflineParts; - AddMemory(dir_ + "descriptor.data", memory); - AddMemory(dir_ + "descriptor1.data", memory); - AddMemory(dir_ + "stack.data", memory); - for (size_t i = 0; i < 7; i++) { - AddMemory(dir_ + "entry" + std::to_string(i) + ".data", memory); - AddMemory(dir_ + "jit" + std::to_string(i) + ".data", memory); - } - process_memory_.reset(memory); - - LeakType data(maps_.get(), regs_.get(), process_memory_); - TestCheckForLeaks(OfflineUnwind, &data); -} - -// The eh_frame_hdr data is present but set to zero fdes. This should -// fallback to iterating over the cies/fdes and ignore the eh_frame_hdr. -// No .gnu_debugdata section in the elf file, so no symbols. -TEST_F(UnwindOfflineTest, bad_eh_frame_hdr_arm64) { - ASSERT_NO_FATAL_FAILURE(Init("bad_eh_frame_hdr_arm64/", ARCH_ARM64)); - - Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.Unwind(); - - std::string frame_info(DumpFrames(unwinder)); - ASSERT_EQ(5U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; - EXPECT_EQ( - " #00 pc 0000000000000550 waiter64\n" - " #01 pc 0000000000000568 waiter64\n" - " #02 pc 000000000000057c waiter64\n" - " #03 pc 0000000000000590 waiter64\n" - " #04 pc 00000000000a8e98 libc.so (__libc_init+88)\n", - frame_info); - EXPECT_EQ(0x60a9fdf550U, unwinder.frames()[0].pc); - EXPECT_EQ(0x7fdd141990U, unwinder.frames()[0].sp); - EXPECT_EQ(0x60a9fdf568U, unwinder.frames()[1].pc); - EXPECT_EQ(0x7fdd1419a0U, unwinder.frames()[1].sp); - EXPECT_EQ(0x60a9fdf57cU, unwinder.frames()[2].pc); - EXPECT_EQ(0x7fdd1419b0U, unwinder.frames()[2].sp); - EXPECT_EQ(0x60a9fdf590U, unwinder.frames()[3].pc); - EXPECT_EQ(0x7fdd1419c0U, unwinder.frames()[3].sp); - EXPECT_EQ(0x7542d68e98U, unwinder.frames()[4].pc); - EXPECT_EQ(0x7fdd1419d0U, unwinder.frames()[4].sp); -} - -// The elf has bad eh_frame unwind information for the pcs. If eh_frame -// is used first, the unwind will not match the expected output. -TEST_F(UnwindOfflineTest, debug_frame_first_x86) { - ASSERT_NO_FATAL_FAILURE(Init("debug_frame_first_x86/", ARCH_X86)); - - Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.Unwind(); - - std::string frame_info(DumpFrames(unwinder)); - ASSERT_EQ(5U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; - EXPECT_EQ( - " #00 pc 00000685 waiter (call_level3+53)\n" - " #01 pc 000006b7 waiter (call_level2+23)\n" - " #02 pc 000006d7 waiter (call_level1+23)\n" - " #03 pc 000006f7 waiter (main+23)\n" - " #04 pc 00018275 libc.so\n", - frame_info); - EXPECT_EQ(0x56598685U, unwinder.frames()[0].pc); - EXPECT_EQ(0xffcf9e38U, unwinder.frames()[0].sp); - EXPECT_EQ(0x565986b7U, unwinder.frames()[1].pc); - EXPECT_EQ(0xffcf9e50U, unwinder.frames()[1].sp); - EXPECT_EQ(0x565986d7U, unwinder.frames()[2].pc); - EXPECT_EQ(0xffcf9e60U, unwinder.frames()[2].sp); - EXPECT_EQ(0x565986f7U, unwinder.frames()[3].pc); - EXPECT_EQ(0xffcf9e70U, unwinder.frames()[3].sp); - EXPECT_EQ(0xf744a275U, unwinder.frames()[4].pc); - EXPECT_EQ(0xffcf9e80U, unwinder.frames()[4].sp); -} - -// Make sure that a pc that is at the beginning of an fde unwinds correctly. -TEST_F(UnwindOfflineTest, eh_frame_hdr_begin_x86_64) { - ASSERT_NO_FATAL_FAILURE(Init("eh_frame_hdr_begin_x86_64/", ARCH_X86_64)); - - Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.Unwind(); - - std::string frame_info(DumpFrames(unwinder)); - ASSERT_EQ(5U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; - EXPECT_EQ( - " #00 pc 0000000000000a80 unwind_test64 (calling3)\n" - " #01 pc 0000000000000dd9 unwind_test64 (calling2+633)\n" - " #02 pc 000000000000121e unwind_test64 (calling1+638)\n" - " #03 pc 00000000000013ed unwind_test64 (main+13)\n" - " #04 pc 00000000000202b0 libc.so\n", - frame_info); - EXPECT_EQ(0x561550b17a80U, unwinder.frames()[0].pc); - EXPECT_EQ(0x7ffcc8596ce8U, unwinder.frames()[0].sp); - EXPECT_EQ(0x561550b17dd9U, unwinder.frames()[1].pc); - EXPECT_EQ(0x7ffcc8596cf0U, unwinder.frames()[1].sp); - EXPECT_EQ(0x561550b1821eU, unwinder.frames()[2].pc); - EXPECT_EQ(0x7ffcc8596f40U, unwinder.frames()[2].sp); - EXPECT_EQ(0x561550b183edU, unwinder.frames()[3].pc); - EXPECT_EQ(0x7ffcc8597190U, unwinder.frames()[3].sp); - EXPECT_EQ(0x7f4de62162b0U, unwinder.frames()[4].pc); - EXPECT_EQ(0x7ffcc85971a0U, unwinder.frames()[4].sp); -} - -TEST_F(UnwindOfflineTest, art_quick_osr_stub_arm) { - ASSERT_NO_FATAL_FAILURE(Init("art_quick_osr_stub_arm/", ARCH_ARM)); - - MemoryOfflineParts* memory = new MemoryOfflineParts; - AddMemory(dir_ + "descriptor.data", memory); - AddMemory(dir_ + "stack.data", memory); - for (size_t i = 0; i < 2; i++) { - AddMemory(dir_ + "entry" + std::to_string(i) + ".data", memory); - AddMemory(dir_ + "jit" + std::to_string(i) + ".data", memory); - } - process_memory_.reset(memory); - - JitDebug jit_debug(process_memory_); - Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.SetJitDebug(&jit_debug); - unwinder.Unwind(); - - std::string frame_info(DumpFrames(unwinder)); - ASSERT_EQ(25U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; - EXPECT_EQ( - " #00 pc 0000c788 " - "(com.example.simpleperf.simpleperfexamplewithnative.MixActivity.access$000)\n" - " #01 pc 0000cdd5 " - "(com.example.simpleperf.simpleperfexamplewithnative.MixActivity$1.run+60)\n" - " #02 pc 004135bb libart.so (art_quick_osr_stub+42)\n" - " #03 pc 002657a5 libart.so " - "(art::jit::Jit::MaybeDoOnStackReplacement(art::Thread*, art::ArtMethod*, unsigned int, int, " - "art::JValue*)+876)\n" - " #04 pc 004021a7 libart.so (MterpMaybeDoOnStackReplacement+86)\n" - " #05 pc 00412474 libart.so (ExecuteMterpImpl+66164)\n" - " #06 pc cd8365b0 \n" // symbol in dex file - " #07 pc 001d7f1b libart.so " - "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " - "art::ShadowFrame&, art::JValue, bool)+374)\n" - " #08 pc 001dc593 libart.so " - "(art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, " - "art::CodeItemDataAccessor const&, art::ShadowFrame*, art::JValue*)+154)\n" - " #09 pc 001f4d01 libart.so " - "(bool art::interpreter::DoCall(art::ArtMethod*, art::Thread*, " - "art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+732)\n" - " #10 pc 003fe427 libart.so (MterpInvokeInterface+1354)\n" - " #11 pc 00405b94 libart.so (ExecuteMterpImpl+14740)\n" - " #12 pc 7004873e \n" // symbol in dex file - " #13 pc 001d7f1b libart.so " - "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, " - "art::ShadowFrame&, art::JValue, bool)+374)\n" - " #14 pc 001dc4d5 libart.so " - "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor " - "const&, art::ShadowFrame*)+92)\n" - " #15 pc 003f25ab libart.so (artQuickToInterpreterBridge+970)\n" - " #16 pc 00417aff libart.so (art_quick_to_interpreter_bridge+30)\n" - " #17 pc 00413575 libart.so (art_quick_invoke_stub_internal+68)\n" - " #18 pc 00418531 libart.so (art_quick_invoke_stub+236)\n" - " #19 pc 000b468d libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned " - "int, art::JValue*, char const*)+136)\n" - " #20 pc 00362f49 libart.so " - "(art::(anonymous namespace)::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable " - "const&, art::ArtMethod*, art::(anonymous namespace)::ArgArray*, art::JValue*, char " - "const*)+52)\n" - " #21 pc 00363cd9 libart.so " - "(art::InvokeVirtualOrInterfaceWithJValues(art::ScopedObjectAccessAlreadyRunnable const&, " - "_jobject*, _jmethodID*, jvalue*)+332)\n" - " #22 pc 003851dd libart.so (art::Thread::CreateCallback(void*)+868)\n" - " #23 pc 00062925 libc.so (__pthread_start(void*)+22)\n" - " #24 pc 0001de39 libc.so (__start_thread+24)\n", - frame_info); - EXPECT_EQ(0xd025c788U, unwinder.frames()[0].pc); - EXPECT_EQ(0xcd4ff140U, unwinder.frames()[0].sp); - EXPECT_EQ(0xd025cdd5U, unwinder.frames()[1].pc); - EXPECT_EQ(0xcd4ff140U, unwinder.frames()[1].sp); - EXPECT_EQ(0xe4a755bbU, unwinder.frames()[2].pc); - EXPECT_EQ(0xcd4ff160U, unwinder.frames()[2].sp); - EXPECT_EQ(0xe48c77a5U, unwinder.frames()[3].pc); - EXPECT_EQ(0xcd4ff190U, unwinder.frames()[3].sp); - EXPECT_EQ(0xe4a641a7U, unwinder.frames()[4].pc); - EXPECT_EQ(0xcd4ff298U, unwinder.frames()[4].sp); - EXPECT_EQ(0xe4a74474U, unwinder.frames()[5].pc); - EXPECT_EQ(0xcd4ff2b8U, unwinder.frames()[5].sp); - EXPECT_EQ(0xcd8365b0U, unwinder.frames()[6].pc); - EXPECT_EQ(0xcd4ff2e0U, unwinder.frames()[6].sp); - EXPECT_EQ(0xe4839f1bU, unwinder.frames()[7].pc); - EXPECT_EQ(0xcd4ff2e0U, unwinder.frames()[7].sp); - EXPECT_EQ(0xe483e593U, unwinder.frames()[8].pc); - EXPECT_EQ(0xcd4ff330U, unwinder.frames()[8].sp); - EXPECT_EQ(0xe4856d01U, unwinder.frames()[9].pc); - EXPECT_EQ(0xcd4ff380U, unwinder.frames()[9].sp); - EXPECT_EQ(0xe4a60427U, unwinder.frames()[10].pc); - EXPECT_EQ(0xcd4ff430U, unwinder.frames()[10].sp); - EXPECT_EQ(0xe4a67b94U, unwinder.frames()[11].pc); - EXPECT_EQ(0xcd4ff498U, unwinder.frames()[11].sp); - EXPECT_EQ(0x7004873eU, unwinder.frames()[12].pc); - EXPECT_EQ(0xcd4ff4c0U, unwinder.frames()[12].sp); - EXPECT_EQ(0xe4839f1bU, unwinder.frames()[13].pc); - EXPECT_EQ(0xcd4ff4c0U, unwinder.frames()[13].sp); - EXPECT_EQ(0xe483e4d5U, unwinder.frames()[14].pc); - EXPECT_EQ(0xcd4ff510U, unwinder.frames()[14].sp); - EXPECT_EQ(0xe4a545abU, unwinder.frames()[15].pc); - EXPECT_EQ(0xcd4ff538U, unwinder.frames()[15].sp); - EXPECT_EQ(0xe4a79affU, unwinder.frames()[16].pc); - EXPECT_EQ(0xcd4ff640U, unwinder.frames()[16].sp); - EXPECT_EQ(0xe4a75575U, unwinder.frames()[17].pc); - EXPECT_EQ(0xcd4ff6b0U, unwinder.frames()[17].sp); - EXPECT_EQ(0xe4a7a531U, unwinder.frames()[18].pc); - EXPECT_EQ(0xcd4ff6e8U, unwinder.frames()[18].sp); - EXPECT_EQ(0xe471668dU, unwinder.frames()[19].pc); - EXPECT_EQ(0xcd4ff770U, unwinder.frames()[19].sp); - EXPECT_EQ(0xe49c4f49U, unwinder.frames()[20].pc); - EXPECT_EQ(0xcd4ff7c8U, unwinder.frames()[20].sp); - EXPECT_EQ(0xe49c5cd9U, unwinder.frames()[21].pc); - EXPECT_EQ(0xcd4ff850U, unwinder.frames()[21].sp); - EXPECT_EQ(0xe49e71ddU, unwinder.frames()[22].pc); - EXPECT_EQ(0xcd4ff8e8U, unwinder.frames()[22].sp); - EXPECT_EQ(0xe7df3925U, unwinder.frames()[23].pc); - EXPECT_EQ(0xcd4ff958U, unwinder.frames()[23].sp); - EXPECT_EQ(0xe7daee39U, unwinder.frames()[24].pc); - EXPECT_EQ(0xcd4ff960U, unwinder.frames()[24].sp); -} - -TEST_F(UnwindOfflineTest, jit_map_arm) { - ASSERT_NO_FATAL_FAILURE(Init("jit_map_arm/", ARCH_ARM)); - - maps_->Add(0xd025c788, 0xd025c9f0, 0, PROT_READ | PROT_EXEC | MAPS_FLAGS_JIT_SYMFILE_MAP, - "jit_map0.so", 0); - maps_->Add(0xd025cd98, 0xd025cff4, 0, PROT_READ | PROT_EXEC | MAPS_FLAGS_JIT_SYMFILE_MAP, - "jit_map1.so", 0); - maps_->Sort(); - - Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.Unwind(); - - std::string frame_info(DumpFrames(unwinder)); - ASSERT_EQ(6U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; - EXPECT_EQ( - " #00 pc 00000000 jit_map0.so " - "(com.example.simpleperf.simpleperfexamplewithnative.MixActivity.access$000)\n" - " #01 pc 0000003d jit_map1.so " - "(com.example.simpleperf.simpleperfexamplewithnative.MixActivity$1.run+60)\n" - " #02 pc 004135bb libart.so (art_quick_osr_stub+42)\n" - - " #03 pc 003851dd libart.so (art::Thread::CreateCallback(void*)+868)\n" - " #04 pc 00062925 libc.so (__pthread_start(void*)+22)\n" - " #05 pc 0001de39 libc.so (__start_thread+24)\n", - frame_info); - - EXPECT_EQ(0xd025c788U, unwinder.frames()[0].pc); - EXPECT_EQ(0xcd4ff140U, unwinder.frames()[0].sp); - EXPECT_EQ(0xd025cdd5U, unwinder.frames()[1].pc); - EXPECT_EQ(0xcd4ff140U, unwinder.frames()[1].sp); - EXPECT_EQ(0xe4a755bbU, unwinder.frames()[2].pc); - EXPECT_EQ(0xcd4ff160U, unwinder.frames()[2].sp); - EXPECT_EQ(0xe49e71ddU, unwinder.frames()[3].pc); - EXPECT_EQ(0xcd4ff8e8U, unwinder.frames()[3].sp); - EXPECT_EQ(0xe7df3925U, unwinder.frames()[4].pc); - EXPECT_EQ(0xcd4ff958U, unwinder.frames()[4].sp); - EXPECT_EQ(0xe7daee39U, unwinder.frames()[5].pc); - EXPECT_EQ(0xcd4ff960U, unwinder.frames()[5].sp); -} - -TEST_F(UnwindOfflineTest, offset_arm) { - ASSERT_NO_FATAL_FAILURE(Init("offset_arm/", ARCH_ARM)); - - Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.Unwind(); - - std::string frame_info(DumpFrames(unwinder)); - ASSERT_EQ(19U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; - EXPECT_EQ( - " #00 pc 0032bfa0 libunwindstack_test (SignalInnerFunction+40)\n" - " #01 pc 0032bfeb libunwindstack_test (SignalMiddleFunction+2)\n" - " #02 pc 0032bff3 libunwindstack_test (SignalOuterFunction+2)\n" - " #03 pc 0032fed3 libunwindstack_test " - "(unwindstack::SignalCallerHandler(int, siginfo*, void*)+26)\n" - " #04 pc 0002652c libc.so (__restore)\n" - " #05 pc 00000000 \n" - " #06 pc 0032c2d9 libunwindstack_test (InnerFunction+736)\n" - " #07 pc 0032cc4f libunwindstack_test (MiddleFunction+42)\n" - " #08 pc 0032cc81 libunwindstack_test (OuterFunction+42)\n" - " #09 pc 0032e547 libunwindstack_test " - "(unwindstack::RemoteThroughSignal(int, unsigned int)+270)\n" - " #10 pc 0032ed99 libunwindstack_test " - "(unwindstack::UnwindTest_remote_through_signal_with_invalid_func_Test::TestBody()+16)\n" - " #11 pc 00354453 libunwindstack_test (testing::Test::Run()+154)\n" - " #12 pc 00354de7 libunwindstack_test (testing::TestInfo::Run()+194)\n" - " #13 pc 00355105 libunwindstack_test (testing::TestCase::Run()+180)\n" - " #14 pc 0035a215 libunwindstack_test " - "(testing::internal::UnitTestImpl::RunAllTests()+664)\n" - " #15 pc 00359f4f libunwindstack_test (testing::UnitTest::Run()+110)\n" - " #16 pc 0034d3db libunwindstack_test (main+38)\n" - " #17 pc 00092c0d libc.so (__libc_init+48)\n" - " #18 pc 0004202f libunwindstack_test (_start_main+38)\n", - frame_info); - - EXPECT_EQ(0x2e55fa0U, unwinder.frames()[0].pc); - EXPECT_EQ(0xf43d2cccU, unwinder.frames()[0].sp); - EXPECT_EQ(0x2e55febU, unwinder.frames()[1].pc); - EXPECT_EQ(0xf43d2ce0U, unwinder.frames()[1].sp); - EXPECT_EQ(0x2e55ff3U, unwinder.frames()[2].pc); - EXPECT_EQ(0xf43d2ce8U, unwinder.frames()[2].sp); - EXPECT_EQ(0x2e59ed3U, unwinder.frames()[3].pc); - EXPECT_EQ(0xf43d2cf0U, unwinder.frames()[3].sp); - EXPECT_EQ(0xf413652cU, unwinder.frames()[4].pc); - EXPECT_EQ(0xf43d2d10U, unwinder.frames()[4].sp); - EXPECT_EQ(0U, unwinder.frames()[5].pc); - EXPECT_EQ(0xffcc0ee0U, unwinder.frames()[5].sp); - EXPECT_EQ(0x2e562d9U, unwinder.frames()[6].pc); - EXPECT_EQ(0xffcc0ee0U, unwinder.frames()[6].sp); - EXPECT_EQ(0x2e56c4fU, unwinder.frames()[7].pc); - EXPECT_EQ(0xffcc1060U, unwinder.frames()[7].sp); - EXPECT_EQ(0x2e56c81U, unwinder.frames()[8].pc); - EXPECT_EQ(0xffcc1078U, unwinder.frames()[8].sp); - EXPECT_EQ(0x2e58547U, unwinder.frames()[9].pc); - EXPECT_EQ(0xffcc1090U, unwinder.frames()[9].sp); - EXPECT_EQ(0x2e58d99U, unwinder.frames()[10].pc); - EXPECT_EQ(0xffcc1438U, unwinder.frames()[10].sp); - EXPECT_EQ(0x2e7e453U, unwinder.frames()[11].pc); - EXPECT_EQ(0xffcc1448U, unwinder.frames()[11].sp); - EXPECT_EQ(0x2e7ede7U, unwinder.frames()[12].pc); - EXPECT_EQ(0xffcc1458U, unwinder.frames()[12].sp); - EXPECT_EQ(0x2e7f105U, unwinder.frames()[13].pc); - EXPECT_EQ(0xffcc1490U, unwinder.frames()[13].sp); - EXPECT_EQ(0x2e84215U, unwinder.frames()[14].pc); - EXPECT_EQ(0xffcc14c0U, unwinder.frames()[14].sp); - EXPECT_EQ(0x2e83f4fU, unwinder.frames()[15].pc); - EXPECT_EQ(0xffcc1510U, unwinder.frames()[15].sp); - EXPECT_EQ(0x2e773dbU, unwinder.frames()[16].pc); - EXPECT_EQ(0xffcc1528U, unwinder.frames()[16].sp); - EXPECT_EQ(0xf41a2c0dU, unwinder.frames()[17].pc); - EXPECT_EQ(0xffcc1540U, unwinder.frames()[17].sp); - EXPECT_EQ(0x2b6c02fU, unwinder.frames()[18].pc); - EXPECT_EQ(0xffcc1558U, unwinder.frames()[18].sp); -} - -// Test using a non-zero load bias library that has the fde entries -// encoded as 0xb, which is not set as pc relative. -TEST_F(UnwindOfflineTest, debug_frame_load_bias_arm) { - ASSERT_NO_FATAL_FAILURE(Init("debug_frame_load_bias_arm/", ARCH_ARM)); - - Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.Unwind(); - - std::string frame_info(DumpFrames(unwinder)); - ASSERT_EQ(8U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; - EXPECT_EQ( - " #00 pc 0005138c libc.so (__ioctl+8)\n" - " #01 pc 0002140f libc.so (ioctl+30)\n" - " #02 pc 00039535 libbinder.so (android::IPCThreadState::talkWithDriver(bool)+204)\n" - " #03 pc 00039633 libbinder.so (android::IPCThreadState::getAndExecuteCommand()+10)\n" - " #04 pc 00039b57 libbinder.so (android::IPCThreadState::joinThreadPool(bool)+38)\n" - " #05 pc 00000c21 mediaserver (main+104)\n" - " #06 pc 00084b89 libc.so (__libc_init+48)\n" - " #07 pc 00000b77 mediaserver (_start_main+38)\n", - frame_info); - - EXPECT_EQ(0xf0be238cU, unwinder.frames()[0].pc); - EXPECT_EQ(0xffd4a638U, unwinder.frames()[0].sp); - EXPECT_EQ(0xf0bb240fU, unwinder.frames()[1].pc); - EXPECT_EQ(0xffd4a638U, unwinder.frames()[1].sp); - EXPECT_EQ(0xf1a75535U, unwinder.frames()[2].pc); - EXPECT_EQ(0xffd4a650U, unwinder.frames()[2].sp); - EXPECT_EQ(0xf1a75633U, unwinder.frames()[3].pc); - EXPECT_EQ(0xffd4a6b0U, unwinder.frames()[3].sp); - EXPECT_EQ(0xf1a75b57U, unwinder.frames()[4].pc); - EXPECT_EQ(0xffd4a6d0U, unwinder.frames()[4].sp); - EXPECT_EQ(0x8d1cc21U, unwinder.frames()[5].pc); - EXPECT_EQ(0xffd4a6e8U, unwinder.frames()[5].sp); - EXPECT_EQ(0xf0c15b89U, unwinder.frames()[6].pc); - EXPECT_EQ(0xffd4a700U, unwinder.frames()[6].sp); - EXPECT_EQ(0x8d1cb77U, unwinder.frames()[7].pc); - EXPECT_EQ(0xffd4a718U, unwinder.frames()[7].sp); -} - -TEST_F(UnwindOfflineTest, shared_lib_in_apk_arm64) { - ASSERT_NO_FATAL_FAILURE(Init("shared_lib_in_apk_arm64/", ARCH_ARM64)); - - Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.Unwind(); - - std::string frame_info(DumpFrames(unwinder)); - ASSERT_EQ(7U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; - EXPECT_EQ( - " #00 pc 000000000014ccbc linker64 (__dl_syscall+28)\n" - " #01 pc 000000000005426c linker64 " - "(__dl__ZL24debuggerd_signal_handleriP7siginfoPv+1128)\n" - " #02 pc 00000000000008c0 vdso.so (__kernel_rt_sigreturn)\n" - " #03 pc 00000000000846f4 libc.so (abort+172)\n" - " #04 pc 0000000000084ad4 libc.so (__assert2+36)\n" - " #05 pc 000000000003d5b4 ANGLEPrebuilt.apk!libfeature_support_angle.so (offset 0x4000) " - "(ANGLEGetUtilityAPI+56)\n" - " #06 pc 000000000007fe68 libc.so (__libc_init)\n", - frame_info); - - EXPECT_EQ(0x7e82c4fcbcULL, unwinder.frames()[0].pc); - EXPECT_EQ(0x7df8ca3bf0ULL, unwinder.frames()[0].sp); - EXPECT_EQ(0x7e82b5726cULL, unwinder.frames()[1].pc); - EXPECT_EQ(0x7df8ca3bf0ULL, unwinder.frames()[1].sp); - EXPECT_EQ(0x7e82b018c0ULL, unwinder.frames()[2].pc); - EXPECT_EQ(0x7df8ca3da0ULL, unwinder.frames()[2].sp); - EXPECT_EQ(0x7e7eecc6f4ULL, unwinder.frames()[3].pc); - EXPECT_EQ(0x7dabf3db60ULL, unwinder.frames()[3].sp); - EXPECT_EQ(0x7e7eeccad4ULL, unwinder.frames()[4].pc); - EXPECT_EQ(0x7dabf3dc40ULL, unwinder.frames()[4].sp); - EXPECT_EQ(0x7dabc405b4ULL, unwinder.frames()[5].pc); - EXPECT_EQ(0x7dabf3dc50ULL, unwinder.frames()[5].sp); - EXPECT_EQ(0x7e7eec7e68ULL, unwinder.frames()[6].pc); - EXPECT_EQ(0x7dabf3dc70ULL, unwinder.frames()[6].sp); - // Ignore top frame since the test code was modified to end in __libc_init. -} - -TEST_F(UnwindOfflineTest, shared_lib_in_apk_memory_only_arm64) { - ASSERT_NO_FATAL_FAILURE(Init("shared_lib_in_apk_memory_only_arm64/", ARCH_ARM64)); - // Add the memory that represents the shared library. - MemoryOfflineParts* memory = reinterpret_cast(process_memory_.get()); - AddMemory(dir_ + "lib_mem.data", memory); - - Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.Unwind(); - - std::string frame_info(DumpFrames(unwinder)); - ASSERT_EQ(7U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; - EXPECT_EQ( - " #00 pc 000000000014ccbc linker64 (__dl_syscall+28)\n" - " #01 pc 000000000005426c linker64 " - "(__dl__ZL24debuggerd_signal_handleriP7siginfoPv+1128)\n" - " #02 pc 00000000000008c0 vdso.so (__kernel_rt_sigreturn)\n" - " #03 pc 00000000000846f4 libc.so (abort+172)\n" - " #04 pc 0000000000084ad4 libc.so (__assert2+36)\n" - " #05 pc 000000000003d5b4 ANGLEPrebuilt.apk (offset 0x21d5000)\n" - " #06 pc 000000000007fe68 libc.so (__libc_init)\n", - frame_info); - - EXPECT_EQ(0x7e82c4fcbcULL, unwinder.frames()[0].pc); - EXPECT_EQ(0x7df8ca3bf0ULL, unwinder.frames()[0].sp); - EXPECT_EQ(0x7e82b5726cULL, unwinder.frames()[1].pc); - EXPECT_EQ(0x7df8ca3bf0ULL, unwinder.frames()[1].sp); - EXPECT_EQ(0x7e82b018c0ULL, unwinder.frames()[2].pc); - EXPECT_EQ(0x7df8ca3da0ULL, unwinder.frames()[2].sp); - EXPECT_EQ(0x7e7eecc6f4ULL, unwinder.frames()[3].pc); - EXPECT_EQ(0x7dabf3db60ULL, unwinder.frames()[3].sp); - EXPECT_EQ(0x7e7eeccad4ULL, unwinder.frames()[4].pc); - EXPECT_EQ(0x7dabf3dc40ULL, unwinder.frames()[4].sp); - EXPECT_EQ(0x7dabc405b4ULL, unwinder.frames()[5].pc); - EXPECT_EQ(0x7dabf3dc50ULL, unwinder.frames()[5].sp); - EXPECT_EQ(0x7e7eec7e68ULL, unwinder.frames()[6].pc); - EXPECT_EQ(0x7dabf3dc70ULL, unwinder.frames()[6].sp); - // Ignore top frame since the test code was modified to end in __libc_init. -} - -TEST_F(UnwindOfflineTest, shared_lib_in_apk_single_map_arm64) { - ASSERT_NO_FATAL_FAILURE(Init("shared_lib_in_apk_single_map_arm64/", ARCH_ARM64)); - - Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.Unwind(); - - std::string frame_info(DumpFrames(unwinder)); - ASSERT_EQ(13U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; - EXPECT_EQ( - " #00 pc 00000000000814bc libc.so (syscall+28)\n" - " #01 pc 00000000008cdf5c test.apk (offset 0x5000)\n" - " #02 pc 00000000008cde9c test.apk (offset 0x5000)\n" - " #03 pc 00000000008cdd70 test.apk (offset 0x5000)\n" - " #04 pc 00000000008ce408 test.apk (offset 0x5000)\n" - " #05 pc 00000000008ce8d8 test.apk (offset 0x5000)\n" - " #06 pc 00000000008ce814 test.apk (offset 0x5000)\n" - " #07 pc 00000000008bcf60 test.apk (offset 0x5000)\n" - " #08 pc 0000000000133024 test.apk (offset 0x5000)\n" - " #09 pc 0000000000134ad0 test.apk (offset 0x5000)\n" - " #10 pc 0000000000134b64 test.apk (offset 0x5000)\n" - " #11 pc 00000000000e406c libc.so (__pthread_start(void*)+36)\n" - " #12 pc 0000000000085e18 libc.so (__start_thread+64)\n", - frame_info); - - EXPECT_EQ(0x7cbe0b14bcULL, unwinder.frames()[0].pc); - EXPECT_EQ(0x7be4f077d0ULL, unwinder.frames()[0].sp); - EXPECT_EQ(0x7be6715f5cULL, unwinder.frames()[1].pc); - EXPECT_EQ(0x7be4f077d0ULL, unwinder.frames()[1].sp); - EXPECT_EQ(0x7be6715e9cULL, unwinder.frames()[2].pc); - EXPECT_EQ(0x7be4f07800ULL, unwinder.frames()[2].sp); - EXPECT_EQ(0x7be6715d70ULL, unwinder.frames()[3].pc); - EXPECT_EQ(0x7be4f07840ULL, unwinder.frames()[3].sp); - EXPECT_EQ(0x7be6716408ULL, unwinder.frames()[4].pc); - EXPECT_EQ(0x7be4f07860ULL, unwinder.frames()[4].sp); - EXPECT_EQ(0x7be67168d8ULL, unwinder.frames()[5].pc); - EXPECT_EQ(0x7be4f07880ULL, unwinder.frames()[5].sp); - EXPECT_EQ(0x7be6716814ULL, unwinder.frames()[6].pc); - EXPECT_EQ(0x7be4f078f0ULL, unwinder.frames()[6].sp); - EXPECT_EQ(0x7be6704f60ULL, unwinder.frames()[7].pc); - EXPECT_EQ(0x7be4f07910ULL, unwinder.frames()[7].sp); - EXPECT_EQ(0x7be5f7b024ULL, unwinder.frames()[8].pc); - EXPECT_EQ(0x7be4f07950ULL, unwinder.frames()[8].sp); - EXPECT_EQ(0x7be5f7cad0ULL, unwinder.frames()[9].pc); - EXPECT_EQ(0x7be4f07aa0ULL, unwinder.frames()[9].sp); - EXPECT_EQ(0x7be5f7cb64ULL, unwinder.frames()[10].pc); - EXPECT_EQ(0x7be4f07ce0ULL, unwinder.frames()[10].sp); - EXPECT_EQ(0x7cbe11406cULL, unwinder.frames()[11].pc); - EXPECT_EQ(0x7be4f07d00ULL, unwinder.frames()[11].sp); - EXPECT_EQ(0x7cbe0b5e18ULL, unwinder.frames()[12].pc); - EXPECT_EQ(0x7be4f07d20ULL, unwinder.frames()[12].sp); -} - -TEST_F(UnwindOfflineTest, invalid_elf_offset_arm) { - ASSERT_NO_FATAL_FAILURE(Init("invalid_elf_offset_arm/", ARCH_ARM, false)); - - Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.Unwind(); - - std::string frame_info(DumpFrames(unwinder)); - ASSERT_EQ(1U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; - EXPECT_EQ(" #00 pc 00aa7508 invalid.apk (offset 0x12e4000)\n", frame_info); - EXPECT_EQ(0xc898f508, unwinder.frames()[0].pc); - EXPECT_EQ(0xc2044218, unwinder.frames()[0].sp); -} - -TEST_F(UnwindOfflineTest, load_bias_ro_rx_x86_64) { - ASSERT_NO_FATAL_FAILURE(Init("load_bias_ro_rx_x86_64/", ARCH_X86_64)); - - Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.Unwind(); - - std::string frame_info(DumpFrames(unwinder)); - ASSERT_EQ(17U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; - EXPECT_EQ( - " #00 pc 00000000000e9dd4 libc.so (__write+20)\n" - " #01 pc 000000000007ab9c libc.so (_IO_file_write+44)\n" - " #02 pc 0000000000079f3e libc.so\n" - " #03 pc 000000000007bce8 libc.so (_IO_do_write+24)\n" - " #04 pc 000000000007b26e libc.so (_IO_file_xsputn+270)\n" - " #05 pc 000000000004f7f9 libc.so (_IO_vfprintf+1945)\n" - " #06 pc 0000000000057cb5 libc.so (_IO_printf+165)\n" - " #07 pc 0000000000ed1796 perfetto_unittests " - "(testing::internal::PrettyUnitTestResultPrinter::OnTestIterationStart(testing::UnitTest " - "const&, int)+374)\n" - " #08 pc 0000000000ed30fd perfetto_unittests " - "(testing::internal::TestEventRepeater::OnTestIterationStart(testing::UnitTest const&, " - "int)+125)\n" - " #09 pc 0000000000ed5e25 perfetto_unittests " - "(testing::internal::UnitTestImpl::RunAllTests()+581)\n" - " #10 pc 0000000000ef63f3 perfetto_unittests " - "(bool " - "testing::internal::HandleSehExceptionsInMethodIfSupported(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char " - "const*)+131)\n" - " #11 pc 0000000000ee2a21 perfetto_unittests " - "(bool " - "testing::internal::HandleExceptionsInMethodIfSupported(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char " - "const*)+113)\n" - " #12 pc 0000000000ed5bb9 perfetto_unittests (testing::UnitTest::Run()+185)\n" - " #13 pc 0000000000e900f0 perfetto_unittests (RUN_ALL_TESTS()+16)\n" - " #14 pc 0000000000e900d8 perfetto_unittests (main+56)\n" - " #15 pc 000000000002352a libc.so (__libc_start_main+234)\n" - " #16 pc 0000000000919029 perfetto_unittests (_start+41)\n", - frame_info); - - EXPECT_EQ(0x7f9326a57dd4ULL, unwinder.frames()[0].pc); - EXPECT_EQ(0x7ffd224153c8ULL, unwinder.frames()[0].sp); - EXPECT_EQ(0x7f93269e8b9cULL, unwinder.frames()[1].pc); - EXPECT_EQ(0x7ffd224153d0ULL, unwinder.frames()[1].sp); - EXPECT_EQ(0x7f93269e7f3eULL, unwinder.frames()[2].pc); - EXPECT_EQ(0x7ffd22415400ULL, unwinder.frames()[2].sp); - EXPECT_EQ(0x7f93269e9ce8ULL, unwinder.frames()[3].pc); - EXPECT_EQ(0x7ffd22415440ULL, unwinder.frames()[3].sp); - EXPECT_EQ(0x7f93269e926eULL, unwinder.frames()[4].pc); - EXPECT_EQ(0x7ffd22415450ULL, unwinder.frames()[4].sp); - EXPECT_EQ(0x7f93269bd7f9ULL, unwinder.frames()[5].pc); - EXPECT_EQ(0x7ffd22415490ULL, unwinder.frames()[5].sp); - EXPECT_EQ(0x7f93269c5cb5ULL, unwinder.frames()[6].pc); - EXPECT_EQ(0x7ffd22415a10ULL, unwinder.frames()[6].sp); - EXPECT_EQ(0xed1796ULL, unwinder.frames()[7].pc); - EXPECT_EQ(0x7ffd22415af0ULL, unwinder.frames()[7].sp); - EXPECT_EQ(0xed30fdULL, unwinder.frames()[8].pc); - EXPECT_EQ(0x7ffd22415b70ULL, unwinder.frames()[8].sp); - EXPECT_EQ(0xed5e25ULL, unwinder.frames()[9].pc); - EXPECT_EQ(0x7ffd22415bb0ULL, unwinder.frames()[9].sp); - EXPECT_EQ(0xef63f3ULL, unwinder.frames()[10].pc); - EXPECT_EQ(0x7ffd22415c60ULL, unwinder.frames()[10].sp); - EXPECT_EQ(0xee2a21ULL, unwinder.frames()[11].pc); - EXPECT_EQ(0x7ffd22415cc0ULL, unwinder.frames()[11].sp); - EXPECT_EQ(0xed5bb9ULL, unwinder.frames()[12].pc); - EXPECT_EQ(0x7ffd22415d40ULL, unwinder.frames()[12].sp); - EXPECT_EQ(0xe900f0ULL, unwinder.frames()[13].pc); - EXPECT_EQ(0x7ffd22415d90ULL, unwinder.frames()[13].sp); - EXPECT_EQ(0xe900d8ULL, unwinder.frames()[14].pc); - EXPECT_EQ(0x7ffd22415da0ULL, unwinder.frames()[14].sp); - EXPECT_EQ(0x7f932699152aULL, unwinder.frames()[15].pc); - EXPECT_EQ(0x7ffd22415dd0ULL, unwinder.frames()[15].sp); - EXPECT_EQ(0x919029ULL, unwinder.frames()[16].pc); - EXPECT_EQ(0x7ffd22415e90ULL, unwinder.frames()[16].sp); -} - -TEST_F(UnwindOfflineTest, load_bias_different_section_bias_arm64) { - ASSERT_NO_FATAL_FAILURE(Init("load_bias_different_section_bias_arm64/", ARCH_ARM64)); - - Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.Unwind(); - - std::string frame_info(DumpFrames(unwinder)); - ASSERT_EQ(12U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; - EXPECT_EQ( - " #00 pc 00000000000d59bc linker64 (__dl_syscall+28)\n" - " #01 pc 00000000000554e8 linker64 (__dl__ZL24debuggerd_signal_handleriP7siginfoPv+1148)\n" - " #02 pc 00000000000008c0 vdso (__kernel_rt_sigreturn)\n" - " #03 pc 000000000007f3e8 libc.so (abort+168)\n" - " #04 pc 00000000000459fc test (std::__ndk1::__throw_bad_cast()+4)\n" - " #05 pc 0000000000056d80 test (testing::Test::Run()+88)\n" - " #06 pc 000000000005724c test (testing::TestInfo::Run()+112)\n" - " #07 pc 0000000000057558 test (testing::TestSuite::Run()+116)\n" - " #08 pc 000000000005bffc test (testing::internal::UnitTestImpl::RunAllTests()+464)\n" - " #09 pc 000000000005bd9c test (testing::UnitTest::Run()+116)\n" - " #10 pc 00000000000464e4 test (main+144)\n" - " #11 pc 000000000007aa34 libc.so (__libc_init+108)\n", - frame_info); - - EXPECT_EQ(0x7112cb99bcULL, unwinder.frames()[0].pc); - EXPECT_EQ(0x7112bdbbf0ULL, unwinder.frames()[0].sp); - EXPECT_EQ(0x7112c394e8ULL, unwinder.frames()[1].pc); - EXPECT_EQ(0x7112bdbbf0ULL, unwinder.frames()[1].sp); - EXPECT_EQ(0x7112be28c0ULL, unwinder.frames()[2].pc); - EXPECT_EQ(0x7112bdbda0ULL, unwinder.frames()[2].sp); - EXPECT_EQ(0x71115ab3e8ULL, unwinder.frames()[3].pc); - EXPECT_EQ(0x7fdd4a3f00ULL, unwinder.frames()[3].sp); - EXPECT_EQ(0x5f739dc9fcULL, unwinder.frames()[4].pc); - EXPECT_EQ(0x7fdd4a3fe0ULL, unwinder.frames()[4].sp); - EXPECT_EQ(0x5f739edd80ULL, unwinder.frames()[5].pc); - EXPECT_EQ(0x7fdd4a3ff0ULL, unwinder.frames()[5].sp); - EXPECT_EQ(0x5f739ee24cULL, unwinder.frames()[6].pc); - EXPECT_EQ(0x7fdd4a4010ULL, unwinder.frames()[6].sp); - EXPECT_EQ(0x5f739ee558ULL, unwinder.frames()[7].pc); - EXPECT_EQ(0x7fdd4a4040ULL, unwinder.frames()[7].sp); - EXPECT_EQ(0x5f739f2ffcULL, unwinder.frames()[8].pc); - EXPECT_EQ(0x7fdd4a4070ULL, unwinder.frames()[8].sp); - EXPECT_EQ(0x5f739f2d9cULL, unwinder.frames()[9].pc); - EXPECT_EQ(0x7fdd4a4100ULL, unwinder.frames()[9].sp); - EXPECT_EQ(0x5f739dd4e4ULL, unwinder.frames()[10].pc); - EXPECT_EQ(0x7fdd4a4130ULL, unwinder.frames()[10].sp); - EXPECT_EQ(0x71115a6a34ULL, unwinder.frames()[11].pc); - EXPECT_EQ(0x7fdd4a4170ULL, unwinder.frames()[11].sp); -} - -TEST_F(UnwindOfflineTest, eh_frame_bias_x86) { - ASSERT_NO_FATAL_FAILURE(Init("eh_frame_bias_x86/", ARCH_X86)); - - Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.Unwind(); - - std::string frame_info(DumpFrames(unwinder)); - ASSERT_EQ(11U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; - EXPECT_EQ( - " #00 pc ffffe430 vdso.so (__kernel_vsyscall+16)\n" - " #01 pc 00082a4b libc.so (__epoll_pwait+43)\n" - " #02 pc 000303a3 libc.so (epoll_pwait+115)\n" - " #03 pc 000303ed libc.so (epoll_wait+45)\n" - " #04 pc 00010ea2 tombstoned (epoll_dispatch+226)\n" - " #05 pc 0000c5e7 tombstoned (event_base_loop+1095)\n" - " #06 pc 0000c193 tombstoned (event_base_dispatch+35)\n" - " #07 pc 00005c77 tombstoned (main+884)\n" - " #08 pc 00015f66 libc.so (__libc_init+102)\n" - " #09 pc 0000360e tombstoned (_start+98)\n" - " #10 pc 00000001 \n", - frame_info); - - EXPECT_EQ(0xffffe430ULL, unwinder.frames()[0].pc); - EXPECT_EQ(0xfffe1a30ULL, unwinder.frames()[0].sp); - EXPECT_EQ(0xeb585a4bULL, unwinder.frames()[1].pc); - EXPECT_EQ(0xfffe1a40ULL, unwinder.frames()[1].sp); - EXPECT_EQ(0xeb5333a3ULL, unwinder.frames()[2].pc); - EXPECT_EQ(0xfffe1a60ULL, unwinder.frames()[2].sp); - EXPECT_EQ(0xeb5333edULL, unwinder.frames()[3].pc); - EXPECT_EQ(0xfffe1ab0ULL, unwinder.frames()[3].sp); - EXPECT_EQ(0xeb841ea2ULL, unwinder.frames()[4].pc); - EXPECT_EQ(0xfffe1ae0ULL, unwinder.frames()[4].sp); - EXPECT_EQ(0xeb83d5e7ULL, unwinder.frames()[5].pc); - EXPECT_EQ(0xfffe1b30ULL, unwinder.frames()[5].sp); - EXPECT_EQ(0xeb83d193ULL, unwinder.frames()[6].pc); - EXPECT_EQ(0xfffe1bd0ULL, unwinder.frames()[6].sp); - EXPECT_EQ(0xeb836c77ULL, unwinder.frames()[7].pc); - EXPECT_EQ(0xfffe1c00ULL, unwinder.frames()[7].sp); - EXPECT_EQ(0xeb518f66ULL, unwinder.frames()[8].pc); - EXPECT_EQ(0xfffe1d00ULL, unwinder.frames()[8].sp); - EXPECT_EQ(0xeb83460eULL, unwinder.frames()[9].pc); - EXPECT_EQ(0xfffe1d40ULL, unwinder.frames()[9].sp); - EXPECT_EQ(0x00000001ULL, unwinder.frames()[10].pc); - EXPECT_EQ(0xfffe1d74ULL, unwinder.frames()[10].sp); -} - -TEST_F(UnwindOfflineTest, signal_load_bias_arm) { - ASSERT_NO_FATAL_FAILURE(Init("signal_load_bias_arm/", ARCH_ARM)); - - Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.Unwind(); - - std::string frame_info(DumpFrames(unwinder)); - ASSERT_EQ(17U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; - EXPECT_EQ( - " #00 pc 0029ef9e libunwindstack_unit_test (SignalInnerFunction+10)\n" - " #01 pc 0029efa7 libunwindstack_unit_test (SignalMiddleFunction+2)\n" - " #02 pc 0029efaf libunwindstack_unit_test (SignalOuterFunction+2)\n" - " #03 pc 002a280b libunwindstack_unit_test (unwindstack::SignalCallerHandler(int, " - "siginfo*, void*)+10)\n" - " #04 pc 00058bd4 libc.so (__restore)\n" - " #05 pc 0029f01e libunwindstack_unit_test (InnerFunction+106)\n" - " #06 pc 0029f633 libunwindstack_unit_test (MiddleFunction+16)\n" - " #07 pc 0029f64b libunwindstack_unit_test (OuterFunction+16)\n" - " #08 pc 002a1711 libunwindstack_unit_test (unwindstack::RemoteThroughSignal(int, unsigned " - "int)+260)\n" - " #09 pc 002a1603 libunwindstack_unit_test " - "(unwindstack::UnwindTest_remote_through_signal_Test::TestBody()+10)\n" - " #10 pc 002c8fe3 libunwindstack_unit_test (testing::Test::Run()+130)\n" - " #11 pc 002c9b25 libunwindstack_unit_test (testing::TestInfo::Run()+184)\n" - " #12 pc 002c9e27 libunwindstack_unit_test (testing::TestSuite::Run()+202)\n" - " #13 pc 002d193d libunwindstack_unit_test " - "(testing::internal::UnitTestImpl::RunAllTests()+660)\n" - " #14 pc 002d160b libunwindstack_unit_test (testing::UnitTest::Run()+134)\n" - " #15 pc 002de035 libunwindstack_unit_test (IsolateMain+680)\n" - " #16 pc 00058155 libc.so (__libc_init+68)\n", - frame_info); - - EXPECT_EQ(0xb6955f9eULL, unwinder.frames()[0].pc); - EXPECT_EQ(0xf2790ce8ULL, unwinder.frames()[0].sp); - EXPECT_EQ(0xb6955fa7ULL, unwinder.frames()[1].pc); - EXPECT_EQ(0xf2790ce8ULL, unwinder.frames()[1].sp); - EXPECT_EQ(0xb6955fafULL, unwinder.frames()[2].pc); - EXPECT_EQ(0xf2790cf0ULL, unwinder.frames()[2].sp); - EXPECT_EQ(0xb695980bULL, unwinder.frames()[3].pc); - EXPECT_EQ(0xf2790cf8ULL, unwinder.frames()[3].sp); - EXPECT_EQ(0xf23febd4ULL, unwinder.frames()[4].pc); - EXPECT_EQ(0xf2790d10ULL, unwinder.frames()[4].sp); - EXPECT_EQ(0xb695601eULL, unwinder.frames()[5].pc); - EXPECT_EQ(0xffe67798ULL, unwinder.frames()[5].sp); - EXPECT_EQ(0xb6956633ULL, unwinder.frames()[6].pc); - EXPECT_EQ(0xffe67890ULL, unwinder.frames()[6].sp); - EXPECT_EQ(0xb695664bULL, unwinder.frames()[7].pc); - EXPECT_EQ(0xffe678a0ULL, unwinder.frames()[7].sp); - EXPECT_EQ(0xb6958711ULL, unwinder.frames()[8].pc); - EXPECT_EQ(0xffe678b0ULL, unwinder.frames()[8].sp); - EXPECT_EQ(0xb6958603ULL, unwinder.frames()[9].pc); - EXPECT_EQ(0xffe67ac8ULL, unwinder.frames()[9].sp); - EXPECT_EQ(0xb697ffe3ULL, unwinder.frames()[10].pc); - EXPECT_EQ(0xffe67ad8ULL, unwinder.frames()[10].sp); - EXPECT_EQ(0xb6980b25ULL, unwinder.frames()[11].pc); - EXPECT_EQ(0xffe67ae8ULL, unwinder.frames()[11].sp); - EXPECT_EQ(0xb6980e27ULL, unwinder.frames()[12].pc); - EXPECT_EQ(0xffe67b18ULL, unwinder.frames()[12].sp); - EXPECT_EQ(0xb698893dULL, unwinder.frames()[13].pc); - EXPECT_EQ(0xffe67b48ULL, unwinder.frames()[13].sp); - EXPECT_EQ(0xb698860bULL, unwinder.frames()[14].pc); - EXPECT_EQ(0xffe67bb0ULL, unwinder.frames()[14].sp); - EXPECT_EQ(0xb6995035ULL, unwinder.frames()[15].pc); - EXPECT_EQ(0xffe67bd0ULL, unwinder.frames()[15].sp); - EXPECT_EQ(0xf23fe155ULL, unwinder.frames()[16].pc); - EXPECT_EQ(0xffe67d10ULL, unwinder.frames()[16].sp); -} - -TEST_F(UnwindOfflineTest, empty_arm64) { - ASSERT_NO_FATAL_FAILURE(Init("empty_arm64/", ARCH_ARM64)); - - Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.Unwind(); - - std::string frame_info(DumpFrames(unwinder)); - ASSERT_EQ(7U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; - EXPECT_EQ( - " #00 pc 00000000000963a4 libc.so (__ioctl+4)\n" - " #01 pc 000000000005344c libc.so (ioctl+140)\n" - " #02 pc 0000000000050ce4 libbinder.so " - "(android::IPCThreadState::talkWithDriver(bool)+308)\n" - " #03 pc 0000000000050e98 libbinder.so " - "(android::IPCThreadState::getAndExecuteCommand()+24)\n" - " #04 pc 00000000000516ac libbinder.so (android::IPCThreadState::joinThreadPool(bool)+60)\n" - " #05 pc 00000000000443b0 netd (main+1056)\n" - " #06 pc 0000000000045594 libc.so (__libc_init+108)\n", - frame_info); - - EXPECT_EQ(0x72a02203a4U, unwinder.frames()[0].pc); - EXPECT_EQ(0x7ffb6c0b50U, unwinder.frames()[0].sp); - EXPECT_EQ(0x72a01dd44cU, unwinder.frames()[1].pc); - EXPECT_EQ(0x7ffb6c0b50U, unwinder.frames()[1].sp); - EXPECT_EQ(0x729f759ce4U, unwinder.frames()[2].pc); - EXPECT_EQ(0x7ffb6c0c50U, unwinder.frames()[2].sp); - EXPECT_EQ(0x729f759e98U, unwinder.frames()[3].pc); - EXPECT_EQ(0x7ffb6c0ce0U, unwinder.frames()[3].sp); - EXPECT_EQ(0x729f75a6acU, unwinder.frames()[4].pc); - EXPECT_EQ(0x7ffb6c0d10U, unwinder.frames()[4].sp); - EXPECT_EQ(0x5d478af3b0U, unwinder.frames()[5].pc); - EXPECT_EQ(0x7ffb6c0d40U, unwinder.frames()[5].sp); - EXPECT_EQ(0x72a01cf594U, unwinder.frames()[6].pc); - EXPECT_EQ(0x7ffb6c0f30U, unwinder.frames()[6].sp); -} - -// This test has a libc.so where the __restore has been changed so -// that the signal handler match does not occur and it uses the -// fde to do the unwind. -TEST_F(UnwindOfflineTest, signal_fde_x86) { - ASSERT_NO_FATAL_FAILURE(Init("signal_fde_x86/", ARCH_X86)); - - Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.Unwind(); - - std::string frame_info(DumpFrames(unwinder)); - ASSERT_EQ(20U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; - EXPECT_EQ( - " #00 pc 007914d9 libunwindstack_test (SignalInnerFunction+25)\n" - " #01 pc 007914fc libunwindstack_test (SignalMiddleFunction+28)\n" - " #02 pc 0079152c libunwindstack_test (SignalOuterFunction+28)\n" - " #03 pc 0079af62 libunwindstack_test (unwindstack::SignalCallerHandler(int, siginfo*, " - "void*)+50)\n" - " #04 pc 00058fb0 libc.so (__restore)\n" - " #05 pc 00000000 \n" - " #06 pc 0079161a libunwindstack_test (InnerFunction+218)\n" - " #07 pc 007923aa libunwindstack_test (MiddleFunction+42)\n" - " #08 pc 007923ea libunwindstack_test (OuterFunction+42)\n" - " #09 pc 00797444 libunwindstack_test (unwindstack::RemoteThroughSignal(int, unsigned " - "int)+868)\n" - " #10 pc 007985b8 libunwindstack_test " - "(unwindstack::UnwindTest_remote_through_signal_with_invalid_func_Test::TestBody()+56)\n" - " #11 pc 00817a19 libunwindstack_test\n" - " #12 pc 008178c5 libunwindstack_test (testing::Test::Run()+277)\n" - " #13 pc 00818d3e libunwindstack_test (testing::TestInfo::Run()+318)\n" - " #14 pc 008198b4 libunwindstack_test (testing::TestSuite::Run()+436)\n" - " #15 pc 00828cb0 libunwindstack_test " - "(testing::internal::UnitTestImpl::RunAllTests()+1216)\n" - " #16 pc 0082870f libunwindstack_test (testing::UnitTest::Run()+367)\n" - " #17 pc 0084031e libunwindstack_test (IsolateMain+2334)\n" - " #18 pc 0083f9e9 libunwindstack_test (main+41)\n" - " #19 pc 00050646 libc.so (__libc_init+118)\n", - frame_info); - - EXPECT_EQ(0x5ae0d4d9U, unwinder.frames()[0].pc); - EXPECT_EQ(0xecb37188U, unwinder.frames()[0].sp); - EXPECT_EQ(0x5ae0d4fcU, unwinder.frames()[1].pc); - EXPECT_EQ(0xecb37190U, unwinder.frames()[1].sp); - EXPECT_EQ(0x5ae0d52cU, unwinder.frames()[2].pc); - EXPECT_EQ(0xecb371b0U, unwinder.frames()[2].sp); - EXPECT_EQ(0x5ae16f62U, unwinder.frames()[3].pc); - EXPECT_EQ(0xecb371d0U, unwinder.frames()[3].sp); - EXPECT_EQ(0xec169fb0U, unwinder.frames()[4].pc); - EXPECT_EQ(0xecb371f0U, unwinder.frames()[4].sp); - EXPECT_EQ(0x0U, unwinder.frames()[5].pc); - EXPECT_EQ(0xffcfac6cU, unwinder.frames()[5].sp); - EXPECT_EQ(0x5ae0d61aU, unwinder.frames()[6].pc); - EXPECT_EQ(0xffcfac6cU, unwinder.frames()[6].sp); - EXPECT_EQ(0x5ae0e3aaU, unwinder.frames()[7].pc); - EXPECT_EQ(0xffcfad60U, unwinder.frames()[7].sp); - EXPECT_EQ(0x5ae0e3eaU, unwinder.frames()[8].pc); - EXPECT_EQ(0xffcfad90U, unwinder.frames()[8].sp); - EXPECT_EQ(0x5ae13444U, unwinder.frames()[9].pc); - EXPECT_EQ(0xffcfadc0U, unwinder.frames()[9].sp); - EXPECT_EQ(0x5ae145b8U, unwinder.frames()[10].pc); - EXPECT_EQ(0xffcfb020U, unwinder.frames()[10].sp); - EXPECT_EQ(0x5ae93a19U, unwinder.frames()[11].pc); - EXPECT_EQ(0xffcfb050U, unwinder.frames()[11].sp); - EXPECT_EQ(0x5ae938c5U, unwinder.frames()[12].pc); - EXPECT_EQ(0xffcfb090U, unwinder.frames()[12].sp); - EXPECT_EQ(0x5ae94d3eU, unwinder.frames()[13].pc); - EXPECT_EQ(0xffcfb0f0U, unwinder.frames()[13].sp); - EXPECT_EQ(0x5ae958b4U, unwinder.frames()[14].pc); - EXPECT_EQ(0xffcfb160U, unwinder.frames()[14].sp); - EXPECT_EQ(0x5aea4cb0U, unwinder.frames()[15].pc); - EXPECT_EQ(0xffcfb1d0U, unwinder.frames()[15].sp); - EXPECT_EQ(0x5aea470fU, unwinder.frames()[16].pc); - EXPECT_EQ(0xffcfb270U, unwinder.frames()[16].sp); - EXPECT_EQ(0x5aebc31eU, unwinder.frames()[17].pc); - EXPECT_EQ(0xffcfb2c0U, unwinder.frames()[17].sp); - EXPECT_EQ(0x5aebb9e9U, unwinder.frames()[18].pc); - EXPECT_EQ(0xffcfc3c0U, unwinder.frames()[18].sp); - EXPECT_EQ(0xec161646U, unwinder.frames()[19].pc); - EXPECT_EQ(0xffcfc3f0U, unwinder.frames()[19].sp); -} - -// This test has a libc.so where the __restore_rt has been changed so -// that the signal handler match does not occur and it uses the -// fde to do the unwind. -TEST_F(UnwindOfflineTest, signal_fde_x86_64) { - ASSERT_NO_FATAL_FAILURE(Init("signal_fde_x86_64/", ARCH_X86_64)); - - Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_); - unwinder.Unwind(); - - std::string frame_info(DumpFrames(unwinder)); - ASSERT_EQ(18U, unwinder.NumFrames()) << "Unwind:\n" << frame_info; - EXPECT_EQ( - " #00 pc 000000000058415b libunwindstack_test (SignalInnerFunction+11)\n" - " #01 pc 0000000000584168 libunwindstack_test (SignalMiddleFunction+8)\n" - " #02 pc 0000000000584178 libunwindstack_test (SignalOuterFunction+8)\n" - " #03 pc 000000000058ac77 libunwindstack_test (unwindstack::SignalCallerHandler(int, " - "siginfo*, void*)+23)\n" - " #04 pc 0000000000057d10 libc.so (__restore_rt)\n" - " #05 pc 0000000000000000 \n" - " #06 pc 0000000000584244 libunwindstack_test (InnerFunction+196)\n" - " #07 pc 0000000000584b44 libunwindstack_test (MiddleFunction+20)\n" - " #08 pc 0000000000584b64 libunwindstack_test (OuterFunction+20)\n" - " #09 pc 0000000000588457 libunwindstack_test (unwindstack::RemoteThroughSignal(int, " - "unsigned int)+583)\n" - " #10 pc 0000000000588f67 libunwindstack_test " - "(unwindstack::UnwindTest_remote_through_signal_with_invalid_func_Test::TestBody()+23)\n" - " #11 pc 00000000005d9c38 libunwindstack_test (testing::Test::Run()+216)\n" - " #12 pc 00000000005daf9a libunwindstack_test (testing::TestInfo::Run()+266)\n" - " #13 pc 00000000005dba46 libunwindstack_test (testing::TestSuite::Run()+390)\n" - " #14 pc 00000000005ea4c6 libunwindstack_test " - "(testing::internal::UnitTestImpl::RunAllTests()+1190)\n" - " #15 pc 00000000005e9f61 libunwindstack_test (testing::UnitTest::Run()+337)\n" - " #16 pc 0000000000600155 libunwindstack_test (IsolateMain+2037)\n" - " #17 pc 000000000004e405 libc.so (__libc_init+101)\n", - frame_info); - - EXPECT_EQ(0x5bb41271e15bU, unwinder.frames()[0].pc); - EXPECT_EQ(0x707eb5aa8320U, unwinder.frames()[0].sp); - EXPECT_EQ(0x5bb41271e168U, unwinder.frames()[1].pc); - EXPECT_EQ(0x707eb5aa8330U, unwinder.frames()[1].sp); - EXPECT_EQ(0x5bb41271e178U, unwinder.frames()[2].pc); - EXPECT_EQ(0x707eb5aa8340U, unwinder.frames()[2].sp); - EXPECT_EQ(0x5bb412724c77U, unwinder.frames()[3].pc); - EXPECT_EQ(0x707eb5aa8350U, unwinder.frames()[3].sp); - EXPECT_EQ(0x707eb2ca5d10U, unwinder.frames()[4].pc); - EXPECT_EQ(0x707eb5aa8380U, unwinder.frames()[4].sp); - EXPECT_EQ(0x0U, unwinder.frames()[5].pc); - EXPECT_EQ(0x7ffcaadde078U, unwinder.frames()[5].sp); - EXPECT_EQ(0x5bb41271e244U, unwinder.frames()[6].pc); - EXPECT_EQ(0x7ffcaadde078U, unwinder.frames()[6].sp); - EXPECT_EQ(0x5bb41271eb44U, unwinder.frames()[7].pc); - EXPECT_EQ(0x7ffcaadde1a0U, unwinder.frames()[7].sp); - EXPECT_EQ(0x5bb41271eb64U, unwinder.frames()[8].pc); - EXPECT_EQ(0x7ffcaadde1c0U, unwinder.frames()[8].sp); - EXPECT_EQ(0x5bb412722457U, unwinder.frames()[9].pc); - EXPECT_EQ(0x7ffcaadde1e0U, unwinder.frames()[9].sp); - EXPECT_EQ(0x5bb412722f67U, unwinder.frames()[10].pc); - EXPECT_EQ(0x7ffcaadde510U, unwinder.frames()[10].sp); - EXPECT_EQ(0x5bb412773c38U, unwinder.frames()[11].pc); - EXPECT_EQ(0x7ffcaadde530U, unwinder.frames()[11].sp); - EXPECT_EQ(0x5bb412774f9aU, unwinder.frames()[12].pc); - EXPECT_EQ(0x7ffcaadde560U, unwinder.frames()[12].sp); - EXPECT_EQ(0x5bb412775a46U, unwinder.frames()[13].pc); - EXPECT_EQ(0x7ffcaadde5b0U, unwinder.frames()[13].sp); - EXPECT_EQ(0x5bb4127844c6U, unwinder.frames()[14].pc); - EXPECT_EQ(0x7ffcaadde5f0U, unwinder.frames()[14].sp); - EXPECT_EQ(0x5bb412783f61U, unwinder.frames()[15].pc); - EXPECT_EQ(0x7ffcaadde6c0U, unwinder.frames()[15].sp); - EXPECT_EQ(0x5bb41279a155U, unwinder.frames()[16].pc); - EXPECT_EQ(0x7ffcaadde720U, unwinder.frames()[16].sp); - EXPECT_EQ(0x707eb2c9c405U, unwinder.frames()[17].pc); - EXPECT_EQ(0x7ffcaaddf870U, unwinder.frames()[17].sp); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/UnwindTest.cpp b/libunwindstack/tests/UnwindTest.cpp deleted file mode 100644 index b11d213f6..000000000 --- a/libunwindstack/tests/UnwindTest.cpp +++ /dev/null @@ -1,476 +0,0 @@ -/* - * Copyright (C) 2017 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 - -#include "MemoryRemote.h" -#include "TestUtils.h" - -namespace unwindstack { - -enum TestTypeEnum : uint8_t { - TEST_TYPE_LOCAL_UNWINDER = 0, - TEST_TYPE_LOCAL_UNWINDER_FROM_PID, - TEST_TYPE_LOCAL_WAIT_FOR_FINISH, - TEST_TYPE_REMOTE, - TEST_TYPE_REMOTE_WITH_INVALID_CALL, -}; - -static std::atomic_bool g_ready; -static volatile bool g_ready_for_remote; -static volatile bool g_signal_ready_for_remote; -static std::atomic_bool g_finish; -static std::atomic_uintptr_t g_ucontext; - -static void ResetGlobals() { - g_ready = false; - g_ready_for_remote = false; - g_signal_ready_for_remote = false; - g_finish = false; - g_ucontext = 0; -} - -static std::vector kFunctionOrder{"OuterFunction", "MiddleFunction", "InnerFunction"}; - -static std::vector kFunctionSignalOrder{"OuterFunction", "MiddleFunction", - "InnerFunction", "SignalOuterFunction", - "SignalMiddleFunction", "SignalInnerFunction"}; - -static void SignalHandler(int, siginfo_t*, void* sigcontext) { - g_ucontext = reinterpret_cast(sigcontext); - while (!g_finish.load()) { - } -} - -extern "C" void SignalInnerFunction() { - g_signal_ready_for_remote = true; - // Avoid any function calls because not every instruction will be - // unwindable. - // This method of looping is only used when testing a remote unwind. - while (true) { - } -} - -extern "C" void SignalMiddleFunction() { - SignalInnerFunction(); -} - -extern "C" void SignalOuterFunction() { - SignalMiddleFunction(); -} - -static void SignalCallerHandler(int, siginfo_t*, void*) { - SignalOuterFunction(); -} - -static std::string ErrorMsg(const std::vector& function_names, Unwinder* unwinder) { - std::string unwind; - for (size_t i = 0; i < unwinder->NumFrames(); i++) { - unwind += unwinder->FormatFrame(i) + '\n'; - } - - return std::string( - "Unwind completed without finding all frames\n" - " Looking for function: ") + - function_names.front() + "\n" + "Unwind data:\n" + unwind; -} - -static void VerifyUnwind(Unwinder* unwinder, std::vector expected_function_names) { - unwinder->Unwind(); - - for (auto& frame : unwinder->frames()) { - if (frame.function_name == expected_function_names.back()) { - expected_function_names.pop_back(); - if (expected_function_names.empty()) { - break; - } - } - } - - ASSERT_TRUE(expected_function_names.empty()) << ErrorMsg(expected_function_names, unwinder); -} - -static void VerifyUnwind(pid_t pid, Maps* maps, Regs* regs, - std::vector expected_function_names) { - auto process_memory(Memory::CreateProcessMemory(pid)); - - Unwinder unwinder(512, maps, regs, process_memory); - VerifyUnwind(&unwinder, expected_function_names); -} - -// This test assumes that this code is compiled with optimizations turned -// off. If this doesn't happen, then all of the calls will be optimized -// away. -extern "C" void InnerFunction(TestTypeEnum test_type) { - if (test_type == TEST_TYPE_LOCAL_WAIT_FOR_FINISH) { - while (!g_finish.load()) { - } - return; - } - if (test_type == TEST_TYPE_REMOTE || test_type == TEST_TYPE_REMOTE_WITH_INVALID_CALL) { - g_ready_for_remote = true; - g_ready = true; - if (test_type == TEST_TYPE_REMOTE_WITH_INVALID_CALL) { - void (*crash_func)() = nullptr; - crash_func(); - } - // Avoid any function calls because not every instruction will be - // unwindable. - // This method of looping is only used when testing a remote unwind. - while (true) { - } - return; - } - - std::unique_ptr unwinder; - std::unique_ptr regs(Regs::CreateFromLocal()); - RegsGetLocal(regs.get()); - std::unique_ptr maps; - - if (test_type == TEST_TYPE_LOCAL_UNWINDER) { - maps.reset(new LocalMaps()); - ASSERT_TRUE(maps->Parse()); - auto process_memory(Memory::CreateProcessMemory(getpid())); - unwinder.reset(new Unwinder(512, maps.get(), regs.get(), process_memory)); - } else { - UnwinderFromPid* unwinder_from_pid = new UnwinderFromPid(512, getpid()); - unwinder_from_pid->SetRegs(regs.get()); - unwinder.reset(unwinder_from_pid); - } - VerifyUnwind(unwinder.get(), kFunctionOrder); -} - -extern "C" void MiddleFunction(TestTypeEnum test_type) { - InnerFunction(test_type); -} - -extern "C" void OuterFunction(TestTypeEnum test_type) { - MiddleFunction(test_type); -} - -class UnwindTest : public ::testing::Test { - public: - void SetUp() override { ResetGlobals(); } -}; - -TEST_F(UnwindTest, local) { - OuterFunction(TEST_TYPE_LOCAL_UNWINDER); -} - -TEST_F(UnwindTest, local_use_from_pid) { - OuterFunction(TEST_TYPE_LOCAL_UNWINDER_FROM_PID); -} - -static void LocalUnwind(void* data) { - TestTypeEnum* test_type = reinterpret_cast(data); - OuterFunction(*test_type); -} - -TEST_F(UnwindTest, local_check_for_leak) { - TestTypeEnum test_type = TEST_TYPE_LOCAL_UNWINDER; - TestCheckForLeaks(LocalUnwind, &test_type); -} - -TEST_F(UnwindTest, local_use_from_pid_check_for_leak) { - TestTypeEnum test_type = TEST_TYPE_LOCAL_UNWINDER_FROM_PID; - TestCheckForLeaks(LocalUnwind, &test_type); -} - -void WaitForRemote(pid_t pid, uint64_t addr, bool leave_attached, bool* completed) { - *completed = false; - // Need to sleep before attempting first ptrace. Without this, on the - // host it becomes impossible to attach and ptrace sets errno to EPERM. - usleep(1000); - for (size_t i = 0; i < 1000; i++) { - if (ptrace(PTRACE_ATTACH, pid, 0, 0) == 0) { - ASSERT_TRUE(TestQuiescePid(pid)) - << "Waiting for process to quiesce failed: " << strerror(errno); - - MemoryRemote memory(pid); - // Read the remote value to see if we are ready. - bool value; - if (memory.ReadFully(addr, &value, sizeof(value)) && value) { - *completed = true; - } - if (!*completed || !leave_attached) { - ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0)); - } - if (*completed) { - break; - } - } else { - ASSERT_EQ(ESRCH, errno) << "ptrace attach failed with unexpected error: " << strerror(errno); - } - usleep(5000); - } -} - -TEST_F(UnwindTest, remote) { - pid_t pid; - if ((pid = fork()) == 0) { - OuterFunction(TEST_TYPE_REMOTE); - exit(0); - } - ASSERT_NE(-1, pid); - TestScopedPidReaper reap(pid); - - bool completed; - WaitForRemote(pid, reinterpret_cast(&g_ready_for_remote), true, &completed); - ASSERT_TRUE(completed) << "Timed out waiting for remote process to be ready."; - - RemoteMaps maps(pid); - ASSERT_TRUE(maps.Parse()); - std::unique_ptr regs(Regs::RemoteGet(pid)); - ASSERT_TRUE(regs.get() != nullptr); - - VerifyUnwind(pid, &maps, regs.get(), kFunctionOrder); - - ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0)) - << "ptrace detach failed with unexpected error: " << strerror(errno); -} - -TEST_F(UnwindTest, unwind_from_pid_remote) { - pid_t pid; - if ((pid = fork()) == 0) { - OuterFunction(TEST_TYPE_REMOTE); - exit(0); - } - ASSERT_NE(-1, pid); - TestScopedPidReaper reap(pid); - - bool completed; - WaitForRemote(pid, reinterpret_cast(&g_ready_for_remote), true, &completed); - ASSERT_TRUE(completed) << "Timed out waiting for remote process to be ready."; - - std::unique_ptr regs(Regs::RemoteGet(pid)); - ASSERT_TRUE(regs.get() != nullptr); - - UnwinderFromPid unwinder(512, pid); - unwinder.SetRegs(regs.get()); - - VerifyUnwind(&unwinder, kFunctionOrder); - - // Verify that calling the same object works again. - - ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0)) - << "ptrace detach failed with unexpected error: " << strerror(errno); -} - -static void RemoteCheckForLeaks(void (*unwind_func)(void*)) { - pid_t pid; - if ((pid = fork()) == 0) { - OuterFunction(TEST_TYPE_REMOTE); - exit(0); - } - ASSERT_NE(-1, pid); - TestScopedPidReaper reap(pid); - - bool completed; - WaitForRemote(pid, reinterpret_cast(&g_ready_for_remote), true, &completed); - ASSERT_TRUE(completed) << "Timed out waiting for remote process to be ready."; - - TestCheckForLeaks(unwind_func, &pid); - - ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0)) - << "ptrace detach failed with unexpected error: " << strerror(errno); -} - -static void RemoteUnwind(void* data) { - pid_t* pid = reinterpret_cast(data); - - RemoteMaps maps(*pid); - ASSERT_TRUE(maps.Parse()); - std::unique_ptr regs(Regs::RemoteGet(*pid)); - ASSERT_TRUE(regs.get() != nullptr); - - VerifyUnwind(*pid, &maps, regs.get(), kFunctionOrder); -} - -TEST_F(UnwindTest, remote_check_for_leaks) { - RemoteCheckForLeaks(RemoteUnwind); -} - -static void RemoteUnwindFromPid(void* data) { - pid_t* pid = reinterpret_cast(data); - - std::unique_ptr regs(Regs::RemoteGet(*pid)); - ASSERT_TRUE(regs.get() != nullptr); - - UnwinderFromPid unwinder(512, *pid); - unwinder.SetRegs(regs.get()); - - VerifyUnwind(&unwinder, kFunctionOrder); -} - -TEST_F(UnwindTest, remote_unwind_for_pid_check_for_leaks) { - RemoteCheckForLeaks(RemoteUnwindFromPid); -} - -TEST_F(UnwindTest, from_context) { - std::atomic_int tid(0); - std::thread thread([&]() { - tid = syscall(__NR_gettid); - OuterFunction(TEST_TYPE_LOCAL_WAIT_FOR_FINISH); - }); - - struct sigaction act, oldact; - memset(&act, 0, sizeof(act)); - act.sa_sigaction = SignalHandler; - act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; - ASSERT_EQ(0, sigaction(SIGUSR1, &act, &oldact)); - // Wait for the tid to get set. - for (size_t i = 0; i < 100; i++) { - if (tid.load() != 0) { - break; - } - usleep(1000); - } - ASSERT_NE(0, tid.load()); - ASSERT_EQ(0, tgkill(getpid(), tid.load(), SIGUSR1)) << "Error: " << strerror(errno); - - // Wait for context data. - void* ucontext; - for (size_t i = 0; i < 2000; i++) { - ucontext = reinterpret_cast(g_ucontext.load()); - if (ucontext != nullptr) { - break; - } - usleep(1000); - } - ASSERT_TRUE(ucontext != nullptr) << "Timed out waiting for thread to respond to signal."; - - LocalMaps maps; - ASSERT_TRUE(maps.Parse()); - std::unique_ptr regs(Regs::CreateFromUcontext(Regs::CurrentArch(), ucontext)); - - VerifyUnwind(getpid(), &maps, regs.get(), kFunctionOrder); - - ASSERT_EQ(0, sigaction(SIGUSR1, &oldact, nullptr)); - - g_finish = true; - thread.join(); -} - -static void RemoteThroughSignal(int signal, unsigned int sa_flags) { - pid_t pid; - if ((pid = fork()) == 0) { - struct sigaction act, oldact; - memset(&act, 0, sizeof(act)); - act.sa_sigaction = SignalCallerHandler; - act.sa_flags = SA_RESTART | SA_ONSTACK | sa_flags; - ASSERT_EQ(0, sigaction(signal, &act, &oldact)); - - OuterFunction(signal != SIGSEGV ? TEST_TYPE_REMOTE : TEST_TYPE_REMOTE_WITH_INVALID_CALL); - exit(0); - } - ASSERT_NE(-1, pid); - TestScopedPidReaper reap(pid); - - bool completed; - if (signal != SIGSEGV) { - WaitForRemote(pid, reinterpret_cast(&g_ready_for_remote), false, &completed); - ASSERT_TRUE(completed) << "Timed out waiting for remote process to be ready."; - ASSERT_EQ(0, kill(pid, SIGUSR1)); - } - WaitForRemote(pid, reinterpret_cast(&g_signal_ready_for_remote), true, &completed); - ASSERT_TRUE(completed) << "Timed out waiting for remote process to be in signal handler."; - - RemoteMaps maps(pid); - ASSERT_TRUE(maps.Parse()); - std::unique_ptr regs(Regs::RemoteGet(pid)); - ASSERT_TRUE(regs.get() != nullptr); - - VerifyUnwind(pid, &maps, regs.get(), kFunctionSignalOrder); - - ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0)) - << "ptrace detach failed with unexpected error: " << strerror(errno); -} - -TEST_F(UnwindTest, remote_through_signal) { - RemoteThroughSignal(SIGUSR1, 0); -} - -TEST_F(UnwindTest, remote_through_signal_sa_siginfo) { - RemoteThroughSignal(SIGUSR1, SA_SIGINFO); -} - -TEST_F(UnwindTest, remote_through_signal_with_invalid_func) { - RemoteThroughSignal(SIGSEGV, 0); -} - -TEST_F(UnwindTest, remote_through_signal_sa_siginfo_with_invalid_func) { - RemoteThroughSignal(SIGSEGV, SA_SIGINFO); -} - -// Verify that using the same map while unwinding multiple threads at the -// same time doesn't cause problems. -TEST_F(UnwindTest, multiple_threads_unwind_same_map) { - static constexpr size_t kNumConcurrentThreads = 100; - - LocalMaps maps; - ASSERT_TRUE(maps.Parse()); - auto process_memory(Memory::CreateProcessMemory(getpid())); - - std::vector threads; - - std::atomic_bool wait; - wait = true; - size_t frames[kNumConcurrentThreads]; - for (size_t i = 0; i < kNumConcurrentThreads; i++) { - std::thread* thread = new std::thread([i, &frames, &maps, &process_memory, &wait]() { - while (wait) - ; - std::unique_ptr regs(Regs::CreateFromLocal()); - RegsGetLocal(regs.get()); - - Unwinder unwinder(512, &maps, regs.get(), process_memory); - unwinder.Unwind(); - frames[i] = unwinder.NumFrames(); - ASSERT_LE(3U, frames[i]) << "Failed for thread " << i; - }); - threads.push_back(thread); - } - wait = false; - for (auto thread : threads) { - thread->join(); - delete thread; - } -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp deleted file mode 100644 index 8bae242d7..000000000 --- a/libunwindstack/tests/UnwinderTest.cpp +++ /dev/null @@ -1,1771 +0,0 @@ -/* - * Copyright (C) 2017 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 "ElfFake.h" -#include "ElfTestUtils.h" -#include "MemoryFake.h" -#include "RegsFake.h" - -namespace unwindstack { - -class UnwinderTest : public ::testing::Test { - protected: - static MapInfo* AddMapInfo(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags, - const char* name, Elf* elf = nullptr) { - std::string str_name(name); - maps_->Add(start, end, offset, flags, name, static_cast(-1)); - MapInfo* map_info = maps_->Find(start); - if (elf != nullptr) { - map_info->elf.reset(elf); - } - return map_info; - } - - static void SetUpTestSuite() { - maps_.reset(new Maps); - - memory_ = new MemoryFake; - process_memory_.reset(memory_); - - ElfFake* elf; - ElfInterfaceFake* interface; - MapInfo* map_info; - - elf = new ElfFake(new MemoryFake); - interface = new ElfInterfaceFake(nullptr); - interface->FakeSetBuildID("FAKE"); - elf->FakeSetInterface(interface); - AddMapInfo(0x1000, 0x8000, 0, PROT_READ | PROT_WRITE, "/system/fake/libc.so", elf); - - AddMapInfo(0x10000, 0x12000, 0, PROT_READ | PROT_WRITE, "[stack]"); - - AddMapInfo(0x13000, 0x15000, 0, PROT_READ | PROT_WRITE | MAPS_FLAGS_DEVICE_MAP, - "/dev/fake_device"); - - elf = new ElfFake(new MemoryFake); - elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); - AddMapInfo(0x20000, 0x22000, 0, PROT_READ | PROT_WRITE, "/system/fake/libunwind.so", elf); - - elf = new ElfFake(new MemoryFake); - elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); - AddMapInfo(0x23000, 0x24000, 0, PROT_READ | PROT_WRITE, "/fake/libanother.so", elf); - - elf = new ElfFake(new MemoryFake); - elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); - AddMapInfo(0x33000, 0x34000, 0, PROT_READ | PROT_WRITE, "/fake/compressed.so", elf); - - elf = new ElfFake(new MemoryFake); - interface = new ElfInterfaceFake(nullptr); - interface->FakeSetSoname("lib_fake.so"); - elf->FakeSetInterface(interface); - map_info = AddMapInfo(0x43000, 0x44000, 0x1d000, PROT_READ | PROT_WRITE, "/fake/fake.apk", elf); - map_info->elf_start_offset = 0x1d000; - - AddMapInfo(0x53000, 0x54000, 0, PROT_READ | PROT_WRITE, "/fake/fake.oat"); - - map_info = - AddMapInfo(0xa3000, 0xa4000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/fake.vdex"); - map_info->load_bias = 0; - - elf = new ElfFake(new MemoryFake); - elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); - elf->FakeSetLoadBias(0x5000); - AddMapInfo(0xa5000, 0xa6000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/fake_load_bias.so", - elf); - - elf = new ElfFake(new MemoryFake); - elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); - map_info = AddMapInfo(0xa7000, 0xa8000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, - "/fake/fake_offset.oat", elf); - map_info->elf_offset = 0x8000; - - elf = new ElfFake(new MemoryFake); - elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); - map_info = AddMapInfo(0xc0000, 0xc1000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, - "/fake/unreadable.so", elf); - map_info->memory_backed_elf = true; - - elf = new ElfFake(new MemoryFake); - elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); - map_info = AddMapInfo(0xc1000, 0xc2000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "[vdso]", elf); - map_info->memory_backed_elf = true; - - elf = new ElfFake(new MemoryFake); - elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); - map_info = AddMapInfo(0xc2000, 0xc3000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "", elf); - map_info->memory_backed_elf = true; - - elf = new ElfFake(new MemoryFake); - elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); - map_info = AddMapInfo(0xc3000, 0xc4000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, - "/memfd:/jit-cache", elf); - map_info->memory_backed_elf = true; - - map_info = - AddMapInfo(0xd0000, 0xd1000, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/fake.apk"); - map_info->load_bias = 0; - - elf = new ElfFake(new MemoryFake); - interface = new ElfInterfaceFake(nullptr); - elf->FakeSetInterface(interface); - interface->FakeSetGlobalVariable("__dex_debug_descriptor", 0x1800); - interface->FakeSetGlobalVariable("__jit_debug_descriptor", 0x1900); - interface->FakeSetDataOffset(0x1000); - interface->FakeSetDataVaddrStart(0x1000); - interface->FakeSetDataVaddrEnd(0x8000); - AddMapInfo(0xf0000, 0xf1000, 0, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/global.so", elf); - AddMapInfo(0xf1000, 0xf9000, 0x1000, PROT_READ | PROT_WRITE, "/fake/global.so"); - // dex debug data - memory_->SetData32(0xf180c, 0xf3000); - memory_->SetData32(0xf3000, 0xf4000); - memory_->SetData32(0xf3004, 0xf4000); - memory_->SetData32(0xf3008, 0xf5000); - // jit debug data - memory_->SetData32(0xf1900, 1); - memory_->SetData32(0xf1904, 0); - memory_->SetData32(0xf1908, 0xf6000); - memory_->SetData32(0xf190c, 0xf6000); - memory_->SetData32(0xf6000, 0); - memory_->SetData32(0xf6004, 0); - memory_->SetData32(0xf6008, 0xf7000); - memory_->SetData32(0xf600c, 0); - memory_->SetData64(0xf6010, 0x1000); - - elf = new ElfFake(new MemoryFake); - elf->FakeSetValid(false); - elf->FakeSetLoadBias(0x300); - map_info = AddMapInfo(0x100000, 0x101000, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, - "/fake/jit.so", elf); - map_info->elf_start_offset = 0x100; - map_info->offset = 0x200; - -#if 0 - elf = new ElfFake(new MemoryFake); - interface = new ElfInterfaceFake(nullptr); - interface->FakePushFunctionData(FunctionData("Fake0", 10)); - AddMapInfo(0x110000, 0x111000, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, "/fake/elf.so", elf); -#endif - } - - void SetUp() override { - ElfInterfaceFake::FakeClear(); - regs_.FakeSetArch(ARCH_ARM); - regs_.FakeSetReturnAddressValid(false); - } - - static std::unique_ptr maps_; - static RegsFake regs_; - static MemoryFake* memory_; - static std::shared_ptr process_memory_; -}; - -std::unique_ptr UnwinderTest::maps_; -RegsFake UnwinderTest::regs_(5); -MemoryFake* UnwinderTest::memory_; -std::shared_ptr UnwinderTest::process_memory_(nullptr); - -TEST_F(UnwinderTest, multiple_frames) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2)); - - regs_.set_pc(0x1000); - regs_.set_sp(0x10000); - ElfInterfaceFake::FakePushStepData(StepData(0x1104, 0x10010, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x1204, 0x10020, false)); - ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.Unwind(); - EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(3U, unwinder.NumFrames()); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0U, frame->rel_pc); - EXPECT_EQ(0x1000U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("Frame0", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("/system/fake/libc.so", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x1000U, frame->map_start); - EXPECT_EQ(0x8000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); - - frame = &unwinder.frames()[1]; - EXPECT_EQ(1U, frame->num); - EXPECT_EQ(0x100U, frame->rel_pc); - EXPECT_EQ(0x1100U, frame->pc); - EXPECT_EQ(0x10010U, frame->sp); - EXPECT_EQ("Frame1", frame->function_name); - EXPECT_EQ(1U, frame->function_offset); - EXPECT_EQ("/system/fake/libc.so", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x1000U, frame->map_start); - EXPECT_EQ(0x8000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); - - frame = &unwinder.frames()[2]; - EXPECT_EQ(2U, frame->num); - EXPECT_EQ(0x200U, frame->rel_pc); - EXPECT_EQ(0x1200U, frame->pc); - EXPECT_EQ(0x10020U, frame->sp); - EXPECT_EQ("Frame2", frame->function_name); - EXPECT_EQ(2U, frame->function_offset); - EXPECT_EQ("/system/fake/libc.so", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x1000U, frame->map_start); - EXPECT_EQ(0x8000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); -} - -TEST_F(UnwinderTest, multiple_frames_dont_resolve_names) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2)); - - regs_.set_pc(0x1000); - regs_.set_sp(0x10000); - ElfInterfaceFake::FakePushStepData(StepData(0x1104, 0x10010, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x1204, 0x10020, false)); - ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.SetResolveNames(false); - unwinder.Unwind(); - EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(3U, unwinder.NumFrames()); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0U, frame->rel_pc); - EXPECT_EQ(0x1000U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x1000U, frame->map_start); - EXPECT_EQ(0x8000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); - - frame = &unwinder.frames()[1]; - EXPECT_EQ(1U, frame->num); - EXPECT_EQ(0x100U, frame->rel_pc); - EXPECT_EQ(0x1100U, frame->pc); - EXPECT_EQ(0x10010U, frame->sp); - EXPECT_EQ("", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x1000U, frame->map_start); - EXPECT_EQ(0x8000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); - - frame = &unwinder.frames()[2]; - EXPECT_EQ(2U, frame->num); - EXPECT_EQ(0x200U, frame->rel_pc); - EXPECT_EQ(0x1200U, frame->pc); - EXPECT_EQ(0x10020U, frame->sp); - EXPECT_EQ("", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x1000U, frame->map_start); - EXPECT_EQ(0x8000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); -} - -TEST_F(UnwinderTest, non_zero_load_bias) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - - regs_.set_pc(0xa5500); - regs_.set_sp(0x10000); - ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.Unwind(); - EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(1U, unwinder.NumFrames()); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0x5500U, frame->rel_pc); - EXPECT_EQ(0xa5500U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("Frame0", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("/fake/fake_load_bias.so", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0xa5000U, frame->map_start); - EXPECT_EQ(0xa6000U, frame->map_end); - EXPECT_EQ(0x5000U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags); -} - -TEST_F(UnwinderTest, non_zero_elf_offset) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - - regs_.set_pc(0xa7500); - regs_.set_sp(0x10000); - ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.Unwind(); - EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(1U, unwinder.NumFrames()); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0x8500U, frame->rel_pc); - EXPECT_EQ(0xa7500U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("Frame0", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("/fake/fake_offset.oat", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0xa7000U, frame->map_start); - EXPECT_EQ(0xa8000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags); -} - -TEST_F(UnwinderTest, non_zero_map_offset) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - - regs_.set_pc(0x43000); - regs_.set_sp(0x10000); - ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.Unwind(); - EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(1U, unwinder.NumFrames()); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0U, frame->rel_pc); - EXPECT_EQ(0x43000U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("Frame0", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("/fake/fake.apk!lib_fake.so", frame->map_name); - EXPECT_EQ(0x1d000U, frame->map_elf_start_offset); - EXPECT_EQ(0x1d000U, frame->map_exact_offset); - EXPECT_EQ(0x43000U, frame->map_start); - EXPECT_EQ(0x44000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); -} - -TEST_F(UnwinderTest, disable_embedded_soname) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - - regs_.set_pc(0x43000); - regs_.set_sp(0x10000); - ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.SetEmbeddedSoname(false); - unwinder.Unwind(); - EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(1U, unwinder.NumFrames()); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0U, frame->rel_pc); - EXPECT_EQ(0x43000U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("Frame0", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("/fake/fake.apk", frame->map_name); - EXPECT_EQ(0x1d000U, frame->map_elf_start_offset); - EXPECT_EQ(0x1d000U, frame->map_exact_offset); - EXPECT_EQ(0x43000U, frame->map_start); - EXPECT_EQ(0x44000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); -} - -// Verify that no attempt to continue after the step indicates it is done. -TEST_F(UnwinderTest, no_frames_after_finished) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame3", 3)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame4", 4)); - - regs_.set_pc(0x1000); - regs_.set_sp(0x10000); - ElfInterfaceFake::FakePushStepData(StepData(0x1000, 0x10000, true)); - ElfInterfaceFake::FakePushStepData(StepData(0x1102, 0x10010, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x1202, 0x10020, false)); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.Unwind(); - EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(1U, unwinder.NumFrames()); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0U, frame->rel_pc); - EXPECT_EQ(0x1000U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("Frame0", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("/system/fake/libc.so", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x1000U, frame->map_start); - EXPECT_EQ(0x8000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); -} - -// Verify the maximum frames to save. -TEST_F(UnwinderTest, max_frames) { - for (size_t i = 0; i < 30; i++) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame" + std::to_string(i), i)); - ElfInterfaceFake::FakePushStepData(StepData(0x1104 + i * 0x100, 0x10010 + i * 0x10, false)); - } - - regs_.set_pc(0x1000); - regs_.set_sp(0x10000); - - Unwinder unwinder(20, maps_.get(), ®s_, process_memory_); - unwinder.Unwind(); - EXPECT_EQ(ERROR_MAX_FRAMES_EXCEEDED, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(20U, unwinder.NumFrames()); - - for (size_t i = 0; i < 20; i++) { - auto* frame = &unwinder.frames()[i]; - EXPECT_EQ(i, frame->num); - EXPECT_EQ(i * 0x100, frame->rel_pc) << "Failed at frame " << i; - EXPECT_EQ(0x1000 + i * 0x100, frame->pc) << "Failed at frame " << i; - EXPECT_EQ(0x10000 + 0x10 * i, frame->sp) << "Failed at frame " << i; - EXPECT_EQ("Frame" + std::to_string(i), frame->function_name) << "Failed at frame " << i; - EXPECT_EQ(i, frame->function_offset) << "Failed at frame " << i; - EXPECT_EQ("/system/fake/libc.so", frame->map_name) << "Failed at frame " << i; - EXPECT_EQ(0U, frame->map_elf_start_offset) << "Failed at frame " << i; - EXPECT_EQ(0U, frame->map_exact_offset) << "Failed at frame " << i; - EXPECT_EQ(0x1000U, frame->map_start) << "Failed at frame " << i; - EXPECT_EQ(0x8000U, frame->map_end) << "Failed at frame " << i; - EXPECT_EQ(0U, frame->map_load_bias) << "Failed at frame " << i; - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags) << "Failed at frame " << i; - } -} - -// Verify that initial map names frames are removed. -TEST_F(UnwinderTest, verify_frames_skipped) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2)); - - regs_.set_pc(0x20000); - regs_.set_sp(0x10000); - ElfInterfaceFake::FakePushStepData(StepData(0x23004, 0x10010, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x23104, 0x10020, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x20004, 0x10030, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x21004, 0x10040, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x1002, 0x10050, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x21004, 0x10060, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x23002, 0x10070, false)); - ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - std::vector skip_libs{"libunwind.so", "libanother.so"}; - unwinder.Unwind(&skip_libs); - EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(3U, unwinder.NumFrames()); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0U, frame->rel_pc); - EXPECT_EQ(0x1000U, frame->pc); - EXPECT_EQ(0x10050U, frame->sp); - EXPECT_EQ("Frame0", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("/system/fake/libc.so", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x1000U, frame->map_start); - EXPECT_EQ(0x8000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); - - frame = &unwinder.frames()[1]; - EXPECT_EQ(1U, frame->num); - EXPECT_EQ(0x1000U, frame->rel_pc); - EXPECT_EQ(0x21000U, frame->pc); - EXPECT_EQ(0x10060U, frame->sp); - EXPECT_EQ("Frame1", frame->function_name); - EXPECT_EQ(1U, frame->function_offset); - EXPECT_EQ("/system/fake/libunwind.so", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x20000U, frame->map_start); - EXPECT_EQ(0x22000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); - - frame = &unwinder.frames()[2]; - EXPECT_EQ(2U, frame->num); - EXPECT_EQ(0U, frame->rel_pc); - EXPECT_EQ(0x23000U, frame->pc); - EXPECT_EQ(0x10070U, frame->sp); - EXPECT_EQ("Frame2", frame->function_name); - EXPECT_EQ(2U, frame->function_offset); - EXPECT_EQ("/fake/libanother.so", frame->map_name); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x23000U, frame->map_start); - EXPECT_EQ(0x24000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); -} - -// Verify SP in a non-existant map is okay. -TEST_F(UnwinderTest, sp_not_in_map) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1)); - - regs_.set_pc(0x1000); - regs_.set_sp(0x63000); - ElfInterfaceFake::FakePushStepData(StepData(0x21004, 0x50020, false)); - ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.Unwind(); - EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(2U, unwinder.NumFrames()); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0U, frame->rel_pc); - EXPECT_EQ(0x1000U, frame->pc); - EXPECT_EQ(0x63000U, frame->sp); - EXPECT_EQ("Frame0", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("/system/fake/libc.so", frame->map_name); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x1000U, frame->map_start); - EXPECT_EQ(0x8000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); - - frame = &unwinder.frames()[1]; - EXPECT_EQ(1U, frame->num); - EXPECT_EQ(0x1000U, frame->rel_pc); - EXPECT_EQ(0x21000U, frame->pc); - EXPECT_EQ(0x50020U, frame->sp); - EXPECT_EQ("Frame1", frame->function_name); - EXPECT_EQ(1U, frame->function_offset); - EXPECT_EQ("/system/fake/libunwind.so", frame->map_name); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x20000U, frame->map_start); - EXPECT_EQ(0x22000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); -} - -// Verify PC in a device stops the unwind. -TEST_F(UnwinderTest, pc_in_device_stops_unwind) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2)); - - regs_.set_pc(0x13000); - regs_.set_sp(0x10000); - ElfInterfaceFake::FakePushStepData(StepData(0x23002, 0x10010, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x23102, 0x10020, false)); - ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.Unwind(); - EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(1U, unwinder.NumFrames()); -} - -// Verify SP in a device stops the unwind. -TEST_F(UnwinderTest, sp_in_device_stops_unwind) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2)); - - regs_.set_pc(0x1000); - regs_.set_sp(0x13000); - ElfInterfaceFake::FakePushStepData(StepData(0x23002, 0x10010, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x23102, 0x10020, false)); - ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.Unwind(); - EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(1U, unwinder.NumFrames()); -} - -// Verify a no map info frame gets a frame. -TEST_F(UnwinderTest, pc_without_map) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - - regs_.set_pc(0x41000); - regs_.set_sp(0x13000); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.Unwind(); - EXPECT_EQ(ERROR_INVALID_MAP, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(1U, unwinder.NumFrames()); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0x41000U, frame->rel_pc); - EXPECT_EQ(0x41000U, frame->pc); - EXPECT_EQ(0x13000U, frame->sp); - EXPECT_EQ("", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0U, frame->map_start); - EXPECT_EQ(0U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(0, frame->map_flags); -} - -// Verify that a speculative frame is added. -TEST_F(UnwinderTest, speculative_frame) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1)); - - // Fake as if code called a nullptr function. - regs_.set_pc(0); - regs_.set_sp(0x10000); - regs_.FakeSetReturnAddress(0x1204); - regs_.FakeSetReturnAddressValid(true); - - ElfInterfaceFake::FakePushStepData(StepData(0x23104, 0x10020, false)); - ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.Unwind(); - EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(3U, unwinder.NumFrames()); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0U, frame->rel_pc); - EXPECT_EQ(0U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0U, frame->map_start); - EXPECT_EQ(0U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(0, frame->map_flags); - - frame = &unwinder.frames()[1]; - EXPECT_EQ(1U, frame->num); - EXPECT_EQ(0x200U, frame->rel_pc); - EXPECT_EQ(0x1200U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("Frame0", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("/system/fake/libc.so", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x1000U, frame->map_start); - EXPECT_EQ(0x8000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); - - frame = &unwinder.frames()[2]; - EXPECT_EQ(2U, frame->num); - EXPECT_EQ(0x100U, frame->rel_pc); - EXPECT_EQ(0x23100U, frame->pc); - EXPECT_EQ(0x10020U, frame->sp); - EXPECT_EQ("Frame1", frame->function_name); - EXPECT_EQ(1U, frame->function_offset); - EXPECT_EQ("/fake/libanother.so", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x23000U, frame->map_start); - EXPECT_EQ(0x24000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); -} - -// Verify that a speculative frame is added then removed because no other -// frames are added. -TEST_F(UnwinderTest, speculative_frame_removed) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1)); - - // Fake as if code called a nullptr function. - regs_.set_pc(0x20000); - regs_.set_sp(0x10000); - ElfInterfaceFake::FakePushStepData(StepData(0, 0x10010, false)); - regs_.FakeSetReturnAddress(0x12); - regs_.FakeSetReturnAddressValid(true); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.Unwind(); - EXPECT_EQ(ERROR_INVALID_MAP, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(2U, unwinder.NumFrames()); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0U, frame->rel_pc); - EXPECT_EQ(0x20000U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("Frame0", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("/system/fake/libunwind.so", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x20000U, frame->map_start); - EXPECT_EQ(0x22000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); - - frame = &unwinder.frames()[1]; - EXPECT_EQ(1U, frame->num); - EXPECT_EQ(0U, frame->rel_pc); - EXPECT_EQ(0U, frame->pc); - EXPECT_EQ(0x10010U, frame->sp); - EXPECT_EQ("", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0U, frame->map_start); - EXPECT_EQ(0U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(0, frame->map_flags); -} - -// Verify that a speculative frame is added and left if there are only -// two frames and the pc is in the middle nowhere. -TEST_F(UnwinderTest, speculative_frame_not_removed_pc_bad) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1)); - - // Fake as if code called a nullptr function. - regs_.set_pc(0); - regs_.set_sp(0x10000); - regs_.FakeSetReturnAddress(0x1204); - regs_.FakeSetReturnAddressValid(true); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.Unwind(); - EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(2U, unwinder.NumFrames()); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0U, frame->rel_pc); - EXPECT_EQ(0U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0U, frame->map_start); - EXPECT_EQ(0U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(0, frame->map_flags); - - frame = &unwinder.frames()[1]; - EXPECT_EQ(1U, frame->num); - EXPECT_EQ(0x200U, frame->rel_pc); - EXPECT_EQ(0x1200U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("Frame0", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("/system/fake/libc.so", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x1000U, frame->map_start); - EXPECT_EQ(0x8000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); -} - -// Verify that a speculative frame does not cause a crash when it wasn't -// really added due to a filter. -TEST_F(UnwinderTest, speculative_frame_check_with_no_frames) { - regs_.set_pc(0x23000); - regs_.set_sp(0x10000); - regs_.FakeSetReturnAddress(0x23100); - regs_.FakeSetReturnAddressValid(true); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - - std::vector skip_names{"libanother.so"}; - unwinder.Unwind(&skip_names); - EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(0U, unwinder.NumFrames()); -} - -// Verify that an unwind stops when a frame is in given suffix. -TEST_F(UnwinderTest, map_ignore_suffixes) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame3", 3)); - - // Fake as if code called a nullptr function. - regs_.set_pc(0x1000); - regs_.set_sp(0x10000); - ElfInterfaceFake::FakePushStepData(StepData(0x43404, 0x10010, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x53504, 0x10020, false)); - ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - std::vector suffixes{"oat"}; - unwinder.Unwind(nullptr, &suffixes); - EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(2U, unwinder.NumFrames()); - // Make sure the elf was not initialized. - MapInfo* map_info = maps_->Find(0x53000); - ASSERT_TRUE(map_info != nullptr); - EXPECT_TRUE(map_info->elf == nullptr); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0U, frame->rel_pc); - EXPECT_EQ(0x1000U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("Frame0", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("/system/fake/libc.so", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x1000U, frame->map_start); - EXPECT_EQ(0x8000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); - - frame = &unwinder.frames()[1]; - EXPECT_EQ(1U, frame->num); - EXPECT_EQ(0x400U, frame->rel_pc); - EXPECT_EQ(0x43400U, frame->pc); - EXPECT_EQ(0x10010U, frame->sp); - EXPECT_EQ("Frame1", frame->function_name); - EXPECT_EQ(1U, frame->function_offset); - EXPECT_EQ("/fake/fake.apk!lib_fake.so", frame->map_name); - EXPECT_EQ(0x1d000U, frame->map_elf_start_offset); - EXPECT_EQ(0x1d000U, frame->map_exact_offset); - EXPECT_EQ(0x43000U, frame->map_start); - EXPECT_EQ(0x44000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); -} - -// Verify that an unwind stops when the sp and pc don't change. -TEST_F(UnwinderTest, sp_pc_do_not_change) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame3", 3)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame4", 4)); - - regs_.set_pc(0x1000); - regs_.set_sp(0x10000); - ElfInterfaceFake::FakePushStepData(StepData(0x33404, 0x10010, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x33504, 0x10020, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x33504, 0x10020, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x33504, 0x10020, false)); - ElfInterfaceFake::FakePushStepData(StepData(0x33504, 0x10020, false)); - ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.Unwind(); - EXPECT_EQ(ERROR_REPEATED_FRAME, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(3U, unwinder.NumFrames()); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0U, frame->rel_pc); - EXPECT_EQ(0x1000U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("Frame0", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("/system/fake/libc.so", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x1000U, frame->map_start); - EXPECT_EQ(0x8000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); - - frame = &unwinder.frames()[1]; - EXPECT_EQ(1U, frame->num); - EXPECT_EQ(0x400U, frame->rel_pc); - EXPECT_EQ(0x33400U, frame->pc); - EXPECT_EQ(0x10010U, frame->sp); - EXPECT_EQ("Frame1", frame->function_name); - EXPECT_EQ(1U, frame->function_offset); - EXPECT_EQ("/fake/compressed.so", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x33000U, frame->map_start); - EXPECT_EQ(0x34000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); - - frame = &unwinder.frames()[2]; - EXPECT_EQ(2U, frame->num); - EXPECT_EQ(0x500U, frame->rel_pc); - EXPECT_EQ(0x33500U, frame->pc); - EXPECT_EQ(0x10020U, frame->sp); - EXPECT_EQ("Frame2", frame->function_name); - EXPECT_EQ(2U, frame->function_offset); - EXPECT_EQ("/fake/compressed.so", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x33000U, frame->map_start); - EXPECT_EQ(0x34000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); -} - -TEST_F(UnwinderTest, dex_pc_in_map) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - regs_.set_pc(0x1000); - regs_.set_sp(0x10000); - regs_.FakeSetDexPc(0xa3400); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.Unwind(); - EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(2U, unwinder.NumFrames()); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0x400U, frame->rel_pc); - EXPECT_EQ(0xa3400U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("/fake/fake.vdex", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0xa3000U, frame->map_start); - EXPECT_EQ(0xa4000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags); - - frame = &unwinder.frames()[1]; - EXPECT_EQ(1U, frame->num); - EXPECT_EQ(0U, frame->rel_pc); - EXPECT_EQ(0x1000U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("Frame0", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("/system/fake/libc.so", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x1000U, frame->map_start); - EXPECT_EQ(0x8000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); -} - -TEST_F(UnwinderTest, dex_pc_in_map_non_zero_offset) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - regs_.set_pc(0x1000); - regs_.set_sp(0x10000); - regs_.FakeSetDexPc(0xd0400); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.Unwind(); - EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(2U, unwinder.NumFrames()); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0x400U, frame->rel_pc); - EXPECT_EQ(0xd0400U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("/fake/fake.apk", frame->map_name); - EXPECT_EQ(0x1000U, frame->map_elf_start_offset); - EXPECT_EQ(0x1000U, frame->map_exact_offset); - EXPECT_EQ(0xd0000U, frame->map_start); - EXPECT_EQ(0xd1000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags); - - frame = &unwinder.frames()[1]; - EXPECT_EQ(1U, frame->num); - EXPECT_EQ(0U, frame->rel_pc); - EXPECT_EQ(0x1000U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("Frame0", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("/system/fake/libc.so", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x1000U, frame->map_start); - EXPECT_EQ(0x8000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); -} - -TEST_F(UnwinderTest, dex_pc_not_in_map) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - regs_.set_pc(0x1000); - regs_.set_sp(0x10000); - regs_.FakeSetDexPc(0x50000); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.Unwind(); - EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_DEX_PC_NOT_IN_MAP, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(2U, unwinder.NumFrames()); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0x50000U, frame->rel_pc); - EXPECT_EQ(0x50000U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0U, frame->map_start); - EXPECT_EQ(0U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(0, frame->map_flags); - - frame = &unwinder.frames()[1]; - EXPECT_EQ(1U, frame->num); - EXPECT_EQ(0U, frame->rel_pc); - EXPECT_EQ(0x1000U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("Frame0", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("/system/fake/libc.so", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x1000U, frame->map_start); - EXPECT_EQ(0x8000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); -} - -TEST_F(UnwinderTest, dex_pc_not_in_map_valid_dex_files) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - regs_.set_pc(0x1000); - regs_.set_sp(0x10000); - regs_.FakeSetDexPc(0x50000); - - DexFiles dex_files(process_memory_); - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.SetDexFiles(&dex_files); - unwinder.Unwind(); - EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_DEX_PC_NOT_IN_MAP, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(2U, unwinder.NumFrames()); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0x50000U, frame->rel_pc); - EXPECT_EQ(0x50000U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0U, frame->map_start); - EXPECT_EQ(0U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(0, frame->map_flags); - - frame = &unwinder.frames()[1]; - EXPECT_EQ(1U, frame->num); - EXPECT_EQ(0U, frame->rel_pc); - EXPECT_EQ(0x1000U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("Frame0", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("/system/fake/libc.so", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x1000U, frame->map_start); - EXPECT_EQ(0x8000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); -} - -TEST_F(UnwinderTest, dex_pc_multiple_frames) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1)); - regs_.set_pc(0x1000); - regs_.set_sp(0x10000); - regs_.FakeSetDexPc(0xa3400); - ElfInterfaceFake::FakePushStepData(StepData(0x33404, 0x10010, false)); - ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.Unwind(); - EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(3U, unwinder.NumFrames()); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0x400U, frame->rel_pc); - EXPECT_EQ(0xa3400U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("/fake/fake.vdex", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0xa3000U, frame->map_start); - EXPECT_EQ(0xa4000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags); - - frame = &unwinder.frames()[1]; - EXPECT_EQ(1U, frame->num); - EXPECT_EQ(0U, frame->rel_pc); - EXPECT_EQ(0x1000U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("Frame0", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("/system/fake/libc.so", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x1000U, frame->map_start); - EXPECT_EQ(0x8000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); - - frame = &unwinder.frames()[2]; - EXPECT_EQ(2U, frame->num); - EXPECT_EQ(0x400U, frame->rel_pc); - EXPECT_EQ(0x33400U, frame->pc); - EXPECT_EQ(0x10010U, frame->sp); - EXPECT_EQ("Frame1", frame->function_name); - EXPECT_EQ(1U, frame->function_offset); - EXPECT_EQ("/fake/compressed.so", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0x33000U, frame->map_start); - EXPECT_EQ(0x34000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags); -} - -TEST_F(UnwinderTest, dex_pc_max_frames) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - regs_.set_pc(0x1000); - regs_.set_sp(0x10000); - regs_.FakeSetDexPc(0xa3400); - - Unwinder unwinder(1, maps_.get(), ®s_, process_memory_); - unwinder.Unwind(); - EXPECT_EQ(ERROR_MAX_FRAMES_EXCEEDED, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(1U, unwinder.NumFrames()); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0x400U, frame->rel_pc); - EXPECT_EQ(0xa3400U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("/fake/fake.vdex", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0xa3000U, frame->map_start); - EXPECT_EQ(0xa4000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags); -} - -TEST_F(UnwinderTest, elf_from_memory_not_file) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - - regs_.set_pc(0xc0050); - regs_.set_sp(0x10000); - ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.Unwind(); - EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_TRUE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(1U, unwinder.NumFrames()); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0x50U, frame->rel_pc); - EXPECT_EQ(0xc0050U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("Frame0", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("/fake/unreadable.so", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0xc0000U, frame->map_start); - EXPECT_EQ(0xc1000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags); -} - -TEST_F(UnwinderTest, elf_from_memory_but_no_valid_file_with_bracket) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - - regs_.set_pc(0xc1050); - regs_.set_sp(0x10000); - ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.Unwind(); - EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(1U, unwinder.NumFrames()); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0x50U, frame->rel_pc); - EXPECT_EQ(0xc1050U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("Frame0", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("[vdso]", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0xc1000U, frame->map_start); - EXPECT_EQ(0xc2000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags); -} - -TEST_F(UnwinderTest, elf_from_memory_but_empty_filename) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - - regs_.set_pc(0xc2050); - regs_.set_sp(0x10000); - ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.Unwind(); - EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(1U, unwinder.NumFrames()); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0x50U, frame->rel_pc); - EXPECT_EQ(0xc2050U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("Frame0", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0xc2000U, frame->map_start); - EXPECT_EQ(0xc3000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags); -} - -TEST_F(UnwinderTest, elf_from_memory_but_from_memfd) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0)); - - regs_.set_pc(0xc3050); - regs_.set_sp(0x10000); - ElfInterfaceFake::FakePushStepData(StepData(0, 0, true)); - - Unwinder unwinder(64, maps_.get(), ®s_, process_memory_); - unwinder.Unwind(); - EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode()); - EXPECT_EQ(WARNING_NONE, unwinder.warnings()); - EXPECT_FALSE(unwinder.elf_from_memory_not_file()); - - ASSERT_EQ(1U, unwinder.NumFrames()); - - auto* frame = &unwinder.frames()[0]; - EXPECT_EQ(0U, frame->num); - EXPECT_EQ(0x50U, frame->rel_pc); - EXPECT_EQ(0xc3050U, frame->pc); - EXPECT_EQ(0x10000U, frame->sp); - EXPECT_EQ("Frame0", frame->function_name); - EXPECT_EQ(0U, frame->function_offset); - EXPECT_EQ("/memfd:/jit-cache", frame->map_name); - EXPECT_EQ(0U, frame->map_elf_start_offset); - EXPECT_EQ(0U, frame->map_exact_offset); - EXPECT_EQ(0xc3000U, frame->map_start); - EXPECT_EQ(0xc4000U, frame->map_end); - EXPECT_EQ(0U, frame->map_load_bias); - EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags); -} - -// Verify format frame code. -TEST_F(UnwinderTest, format_frame) { - RegsFake regs_arm(10); - regs_arm.FakeSetArch(ARCH_ARM); - Unwinder unwinder32(10, maps_.get(), ®s_arm, process_memory_); - - RegsFake regs_arm64(10); - regs_arm64.FakeSetArch(ARCH_ARM64); - Unwinder unwinder64(10, maps_.get(), ®s_arm64, process_memory_); - - FrameData frame; - frame.num = 1; - frame.rel_pc = 0x1000; - frame.pc = 0x4000; - frame.sp = 0x1000; - frame.function_name = "function"; - frame.function_offset = 100; - frame.map_name = "/fake/libfake.so"; - frame.map_elf_start_offset = 0x2000; - frame.map_start = 0x3000; - frame.map_end = 0x6000; - frame.map_flags = PROT_READ; - - EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so (offset 0x2000) (function+100)", - unwinder64.FormatFrame(frame)); - EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (offset 0x2000) (function+100)", - unwinder32.FormatFrame(frame)); - - frame.map_elf_start_offset = 0; - EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so (function+100)", - unwinder64.FormatFrame(frame)); - EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (function+100)", unwinder32.FormatFrame(frame)); - - frame.function_offset = 0; - EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so (function)", - unwinder64.FormatFrame(frame)); - EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (function)", unwinder32.FormatFrame(frame)); - - // Verify the function name is demangled. - frame.function_name = "_ZN4funcEv"; - EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so (func())", unwinder64.FormatFrame(frame)); - EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (func())", unwinder32.FormatFrame(frame)); - - frame.function_name = ""; - EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so", unwinder64.FormatFrame(frame)); - EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so", unwinder32.FormatFrame(frame)); - - frame.map_name = ""; - EXPECT_EQ(" #01 pc 0000000000001000 ", unwinder64.FormatFrame(frame)); - EXPECT_EQ(" #01 pc 00001000 ", unwinder32.FormatFrame(frame)); - - frame.map_start = 0; - frame.map_end = 0; - EXPECT_EQ(" #01 pc 0000000000001000 ", unwinder64.FormatFrame(frame)); - EXPECT_EQ(" #01 pc 00001000 ", unwinder32.FormatFrame(frame)); -} - -TEST_F(UnwinderTest, format_frame_build_id) { - RegsFake regs(10); - regs.FakeSetArch(ARCH_ARM); - Unwinder unwinder(10, maps_.get(), ®s, process_memory_); - - FrameData frame; - frame.num = 1; - frame.rel_pc = 0x1000; - frame.pc = 0x4000; - frame.sp = 0x1000; - frame.function_name = "function"; - frame.function_offset = 100; - frame.map_name = "/fake/libfake.so"; - frame.map_elf_start_offset = 0; - frame.map_start = 0x3000; - frame.map_end = 0x6000; - frame.map_flags = PROT_READ; - - EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (function+100)", unwinder.FormatFrame(frame)); - unwinder.SetDisplayBuildID(true); - EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (function+100) (BuildId: 46414b45)", - unwinder.FormatFrame(frame)); -} - -static std::string ArchToString(ArchEnum arch) { - if (arch == ARCH_ARM) { - return "Arm"; - } else if (arch == ARCH_ARM64) { - return "Arm64"; - } else if (arch == ARCH_X86) { - return "X86"; - } else if (arch == ARCH_X86_64) { - return "X86_64"; - } else { - return "Unknown"; - } -} - -// Verify format frame code. -TEST_F(UnwinderTest, format_frame_by_arch) { - std::vector reg_list; - RegsArm* arm = new RegsArm; - arm->set_pc(0x2300); - arm->set_sp(0x10000); - reg_list.push_back(arm); - - RegsArm64* arm64 = new RegsArm64; - arm64->set_pc(0x2300); - arm64->set_sp(0x10000); - reg_list.push_back(arm64); - - RegsX86* x86 = new RegsX86; - x86->set_pc(0x2300); - x86->set_sp(0x10000); - reg_list.push_back(x86); - - RegsX86_64* x86_64 = new RegsX86_64; - x86_64->set_pc(0x2300); - x86_64->set_sp(0x10000); - reg_list.push_back(x86_64); - - RegsMips* mips = new RegsMips; - mips->set_pc(0x2300); - mips->set_sp(0x10000); - reg_list.push_back(mips); - - RegsMips64* mips64 = new RegsMips64; - mips64->set_pc(0x2300); - mips64->set_sp(0x10000); - reg_list.push_back(mips64); - - for (auto regs : reg_list) { - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 10)); - - Unwinder unwinder(64, maps_.get(), regs, process_memory_); - unwinder.Unwind(); - - ASSERT_EQ(1U, unwinder.NumFrames()); - std::string expected; - switch (regs->Arch()) { - case ARCH_ARM: - case ARCH_X86: - case ARCH_MIPS: - expected = " #00 pc 00001300 /system/fake/libc.so (Frame0+10)"; - break; - case ARCH_ARM64: - case ARCH_X86_64: - case ARCH_MIPS64: - expected = " #00 pc 0000000000001300 /system/fake/libc.so (Frame0+10)"; - break; - default: - expected = ""; - } - EXPECT_EQ(expected, unwinder.FormatFrame(0)) - << "Mismatch of frame format for regs arch " << ArchToString(regs->Arch()); - delete regs; - } -} - -TEST_F(UnwinderTest, build_frame_pc_only_errors) { - RegsFake regs(10); - regs.FakeSetArch(ARCH_ARM); - Unwinder unwinder(10, maps_.get(), ®s, process_memory_); - - FrameData frame; - - // Pc not in map - frame = unwinder.BuildFrameFromPcOnly(0x10); - EXPECT_EQ(0x10U, frame.pc); - EXPECT_EQ(0x10U, frame.rel_pc); - - // No regs set - unwinder.SetRegs(nullptr); - frame = unwinder.BuildFrameFromPcOnly(0x100310); - EXPECT_EQ(0x100310U, frame.pc); - EXPECT_EQ(0x100310U, frame.rel_pc); - unwinder.SetRegs(®s); - - // Invalid elf - frame = unwinder.BuildFrameFromPcOnly(0x100310); - EXPECT_EQ(0x10030eU, frame.pc); - EXPECT_EQ(0x60eU, frame.rel_pc); - EXPECT_EQ("/fake/jit.so", frame.map_name); - EXPECT_EQ(0x100U, frame.map_elf_start_offset); - EXPECT_EQ(0x200U, frame.map_exact_offset); - EXPECT_EQ(0x100000U, frame.map_start); - EXPECT_EQ(0x101000U, frame.map_end); - EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame.map_flags); - EXPECT_EQ(0x300U, frame.map_load_bias); - EXPECT_EQ("", frame.function_name); - EXPECT_EQ(0U, frame.function_offset); -} - -TEST_F(UnwinderTest, build_frame_pc_valid_elf) { - RegsFake regs(10); - regs.FakeSetArch(ARCH_ARM); - Unwinder unwinder(10, maps_.get(), ®s, process_memory_); - - FrameData frame; - - // Valid elf, no function data. - frame = unwinder.BuildFrameFromPcOnly(0x1010); - EXPECT_EQ(0x100cU, frame.pc); - EXPECT_EQ(0xcU, frame.rel_pc); - EXPECT_EQ("/system/fake/libc.so", frame.map_name); - EXPECT_EQ(0U, frame.map_elf_start_offset); - EXPECT_EQ(0U, frame.map_exact_offset); - EXPECT_EQ(0x1000U, frame.map_start); - EXPECT_EQ(0x8000U, frame.map_end); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame.map_flags); - EXPECT_EQ(0U, frame.map_load_bias); - EXPECT_EQ("", frame.function_name); - EXPECT_EQ(0U, frame.function_offset); - - // Valid elf, function data present, but do not resolve. - ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 10)); - unwinder.SetResolveNames(false); - - frame = unwinder.BuildFrameFromPcOnly(0x1010); - EXPECT_EQ(0x100cU, frame.pc); - EXPECT_EQ(0xcU, frame.rel_pc); - EXPECT_EQ("/system/fake/libc.so", frame.map_name); - EXPECT_EQ(0U, frame.map_elf_start_offset); - EXPECT_EQ(0U, frame.map_exact_offset); - EXPECT_EQ(0x1000U, frame.map_start); - EXPECT_EQ(0x8000U, frame.map_end); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame.map_flags); - EXPECT_EQ(0U, frame.map_load_bias); - EXPECT_EQ("", frame.function_name); - EXPECT_EQ(0U, frame.function_offset); - - // Valid elf, function data present. - unwinder.SetResolveNames(true); - - frame = unwinder.BuildFrameFromPcOnly(0x1010); - EXPECT_EQ(0x100cU, frame.pc); - EXPECT_EQ(0xcU, frame.rel_pc); - EXPECT_EQ("/system/fake/libc.so", frame.map_name); - EXPECT_EQ(0U, frame.map_elf_start_offset); - EXPECT_EQ(0U, frame.map_exact_offset); - EXPECT_EQ(0x1000U, frame.map_start); - EXPECT_EQ(0x8000U, frame.map_end); - EXPECT_EQ(PROT_READ | PROT_WRITE, frame.map_flags); - EXPECT_EQ(0U, frame.map_load_bias); - EXPECT_EQ("Frame0", frame.function_name); - EXPECT_EQ(10U, frame.function_offset); -} - -TEST_F(UnwinderTest, build_frame_pc_in_jit) { - // Create the elf data for the jit debug information. - Elf32_Ehdr ehdr = {}; - TestInitEhdr(&ehdr, ELFCLASS32, EM_ARM); - ehdr.e_phoff = 0x50; - ehdr.e_phnum = 1; - ehdr.e_phentsize = sizeof(Elf32_Phdr); - ehdr.e_shoff = 0x100; - ehdr.e_shstrndx = 1; - ehdr.e_shentsize = sizeof(Elf32_Shdr); - ehdr.e_shnum = 3; - memory_->SetMemory(0xf7000, &ehdr, sizeof(ehdr)); - - Elf32_Phdr phdr = {}; - phdr.p_flags = PF_X; - phdr.p_type = PT_LOAD; - phdr.p_offset = 0x100000; - phdr.p_vaddr = 0x100000; - phdr.p_memsz = 0x1000; - memory_->SetMemory(0xf7050, &phdr, sizeof(phdr)); - - Elf32_Shdr shdr = {}; - shdr.sh_type = SHT_NULL; - memory_->SetMemory(0xf7100, &shdr, sizeof(shdr)); - - shdr.sh_type = SHT_SYMTAB; - shdr.sh_link = 2; - shdr.sh_addr = 0x300; - shdr.sh_offset = 0x300; - shdr.sh_entsize = sizeof(Elf32_Sym); - shdr.sh_size = shdr.sh_entsize; - memory_->SetMemory(0xf7100 + sizeof(shdr), &shdr, sizeof(shdr)); - - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_STRTAB; - shdr.sh_name = 0x500; - shdr.sh_offset = 0x400; - shdr.sh_size = 0x100; - memory_->SetMemory(0xf7100 + 2 * sizeof(shdr), &shdr, sizeof(shdr)); - - Elf32_Sym sym = {}; - sym.st_shndx = 2; - sym.st_info = STT_FUNC; - sym.st_value = 0x100300; - sym.st_size = 0x100; - memory_->SetMemory(0xf7300, &sym, sizeof(sym)); - memory_->SetMemory(0xf7400, "FakeJitFunction"); - - RegsFake regs(10); - regs.FakeSetArch(ARCH_ARM); - JitDebug jit_debug(process_memory_); - Unwinder unwinder(10, maps_.get(), ®s, process_memory_); - unwinder.SetJitDebug(&jit_debug); - - FrameData frame = unwinder.BuildFrameFromPcOnly(0x100310); - EXPECT_EQ(0x10030eU, frame.pc); - EXPECT_EQ(0x60eU, frame.rel_pc); - EXPECT_EQ("/fake/jit.so", frame.map_name); - EXPECT_EQ(0x100U, frame.map_elf_start_offset); - EXPECT_EQ(0x200U, frame.map_exact_offset); - EXPECT_EQ(0x100000U, frame.map_start); - EXPECT_EQ(0x101000U, frame.map_end); - EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame.map_flags); - EXPECT_EQ(0U, frame.map_load_bias); - EXPECT_EQ("FakeJitFunction", frame.function_name); - EXPECT_EQ(0xeU, frame.function_offset); -} - -TEST_F(UnwinderTest, unwinder_from_pid_init_error) { - UnwinderFromPid unwinder(10, getpid()); - ASSERT_DEATH(unwinder.Init(), ""); -} - -TEST_F(UnwinderTest, set_jit_debug_error) { - Unwinder unwinder(10, maps_.get(), process_memory_); - JitDebug jit_debug(process_memory_); - ASSERT_DEATH(unwinder.SetJitDebug(&jit_debug), ""); -} - -TEST_F(UnwinderTest, set_dex_files_error) { - Unwinder unwinder(10, maps_.get(), process_memory_); - DexFiles dex_files(process_memory_); - ASSERT_DEATH(unwinder.SetDexFiles(&dex_files), ""); -} - -} // namespace unwindstack diff --git a/libunwindstack/tests/VerifyBionicTerminationTest.cpp b/libunwindstack/tests/VerifyBionicTerminationTest.cpp deleted file mode 100644 index 3e67dc940..000000000 --- a/libunwindstack/tests/VerifyBionicTerminationTest.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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. - */ - -#define _GNU_SOURCE 1 -#include -#include - -#include - -#if defined(__BIONIC__) - -#include - -#include -#include -#include -#include -#include -#include - -// This test is specific to bionic to verify that __libc_init is -// properly setting the return address to undefined so that the -// unwind properly terminates. - -namespace unwindstack { - -static std::string DumpFrames(const UnwinderFromPid& unwinder) { - std::string unwind; - for (size_t i = 0; i < unwinder.NumFrames(); i++) { - unwind += unwinder.FormatFrame(i) + '\n'; - } - return unwind; -} - -static DwarfLocationEnum GetReturnAddressLocation(uint64_t rel_pc, DwarfSection* section) { - if (section == nullptr) { - return DWARF_LOCATION_INVALID; - } - - const DwarfFde* fde = section->GetFdeFromPc(rel_pc); - if (fde == nullptr || fde->cie == nullptr) { - return DWARF_LOCATION_INVALID; - } - dwarf_loc_regs_t regs; - if (!section->GetCfaLocationInfo(rel_pc, fde, ®s, ARCH_UNKNOWN)) { - return DWARF_LOCATION_INVALID; - } - - auto reg_entry = regs.find(fde->cie->return_address_register); - if (reg_entry == regs.end()) { - return DWARF_LOCATION_INVALID; - } - return reg_entry->second.type; -} - -static void VerifyReturnAddress(const FrameData& frame) { - // Now go and find information about the register data and verify that the relative pc results in - // an undefined register. - Elf elf(Memory::CreateFileMemory(frame.map_name, 0).release()); - ASSERT_TRUE(elf.Init()) << "Failed to init elf object from " << frame.map_name; - ASSERT_TRUE(elf.valid()) << "Elf " << frame.map_name << " is not valid."; - ElfInterface* interface = elf.interface(); - - // Only check the eh_frame and the debug_frame since the undefined register - // is set using a cfi directive. - // Check debug_frame first, then eh_frame since debug_frame always - // contains the most specific data. - DwarfLocationEnum location = GetReturnAddressLocation(frame.rel_pc, interface->debug_frame()); - if (location == DWARF_LOCATION_UNDEFINED) { - return; - } - - location = GetReturnAddressLocation(frame.rel_pc, interface->eh_frame()); - ASSERT_EQ(DWARF_LOCATION_UNDEFINED, location); -} - -// This test assumes that it starts from the main thread, and that the -// libc.so on device will include symbols so that function names can -// be resolved. -TEST(VerifyBionicTermination, local_terminate) { - std::unique_ptr regs(Regs::CreateFromLocal()); - - UnwinderFromPid unwinder(512, getpid()); - unwinder.SetRegs(regs.get()); - - RegsGetLocal(regs.get()); - unwinder.Unwind(); - ASSERT_LT(0U, unwinder.NumFrames()); - - SCOPED_TRACE(DumpFrames(unwinder)); - - // Look for the frame that includes __libc_init, there should only - // be one and it should be the last. - bool found = false; - const std::vector& frames = unwinder.frames(); - for (size_t i = 0; i < unwinder.NumFrames(); i++) { - const FrameData& frame = frames[i]; - if (frame.function_name == "__libc_init" && !frame.map_name.empty() && - std::string("libc.so") == basename(frame.map_name.c_str())) { - ASSERT_EQ(unwinder.NumFrames(), i + 1) << "__libc_init is not last frame."; - ASSERT_NO_FATAL_FAILURE(VerifyReturnAddress(frame)); - found = true; - } - } - ASSERT_TRUE(found) << "Unable to find libc.so:__libc_init frame\n"; -} - -} // namespace unwindstack - -#endif diff --git a/libunwindstack/tests/files/elf32.xz b/libunwindstack/tests/files/elf32.xz deleted file mode 100644 index f25d43349..000000000 Binary files a/libunwindstack/tests/files/elf32.xz and /dev/null differ diff --git a/libunwindstack/tests/files/elf64.xz b/libunwindstack/tests/files/elf64.xz deleted file mode 100644 index eb1618e7e..000000000 Binary files a/libunwindstack/tests/files/elf64.xz and /dev/null differ diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/descriptor.data b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/descriptor.data deleted file mode 100644 index 300646b7b..000000000 Binary files a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/descriptor.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry0.data b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry0.data deleted file mode 100644 index 999cb790a..000000000 Binary files a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry0.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry1.data b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry1.data deleted file mode 100644 index 6aa1c824f..000000000 Binary files a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry1.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit0.data b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit0.data deleted file mode 100644 index 19d7b65cf..000000000 Binary files a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit0.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit1.data b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit1.data deleted file mode 100644 index edcd3e169..000000000 Binary files a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit1.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libart.so b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libart.so deleted file mode 100644 index 09ba49532..000000000 Binary files a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libart.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libc.so b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libc.so deleted file mode 100644 index 39c9025db..000000000 Binary files a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libc.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/maps.txt b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/maps.txt deleted file mode 100644 index 1ff12db1e..000000000 --- a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/maps.txt +++ /dev/null @@ -1,4 +0,0 @@ -d0250000-d2600000 r-xp 0 00:00 0 -e466e000-e4ae8000 r-xp 0 00:00 0 libart.so -e4af1000-e4af2000 rw-p 482000 00:00 0 libart.so -e7d91000-e7e31000 r-xp 0 00:00 0 libc.so diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/regs.txt b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/regs.txt deleted file mode 100644 index 0b518143a..000000000 --- a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/regs.txt +++ /dev/null @@ -1,16 +0,0 @@ -r0: e814103c -r1: 12dcf218 -r2: 1a90df75 -r3: ffffffbf -r4: 0 -r5: 12dc0800 -r6: 12dcf218 -r7: 1a90df75 -r8: 0 -r9: dd23cc00 -r10: 1c -r11: cd4ff16c -ip: 0 -sp: cd4ff140 -lr: d025cdd7 -pc: d025c788 diff --git a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/stack.data b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/stack.data deleted file mode 100644 index f00917b77..000000000 Binary files a/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/stack.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/libc.so b/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/libc.so deleted file mode 100644 index 78449bf8e..000000000 Binary files a/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/libc.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/maps.txt b/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/maps.txt deleted file mode 100644 index 7cada1505..000000000 --- a/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/maps.txt +++ /dev/null @@ -1,2 +0,0 @@ -60a9fdf000-60a9fe0000 r-xp 0 00:00 0 waiter64 -7542cc0000-7542d8e000 r-xp 0 00:00 0 libc.so diff --git a/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/regs.txt b/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/regs.txt deleted file mode 100644 index c24adbe64..000000000 --- a/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/regs.txt +++ /dev/null @@ -1,4 +0,0 @@ -pc: 60a9fdf550 -sp: 7fdd141990 -lr: 60a9fdf56c -x29: 7fdd1419a0 diff --git a/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/stack.data b/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/stack.data deleted file mode 100644 index b56d42008..000000000 Binary files a/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/stack.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/waiter64 b/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/waiter64 deleted file mode 100644 index 81bda1d2e..000000000 Binary files a/libunwindstack/tests/files/offline/bad_eh_frame_hdr_arm64/waiter64 and /dev/null differ diff --git a/libunwindstack/tests/files/offline/debug_frame_first_x86/libc.so b/libunwindstack/tests/files/offline/debug_frame_first_x86/libc.so deleted file mode 100644 index 9c787902b..000000000 Binary files a/libunwindstack/tests/files/offline/debug_frame_first_x86/libc.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/debug_frame_first_x86/maps.txt b/libunwindstack/tests/files/offline/debug_frame_first_x86/maps.txt deleted file mode 100644 index 74fc89f6d..000000000 --- a/libunwindstack/tests/files/offline/debug_frame_first_x86/maps.txt +++ /dev/null @@ -1,2 +0,0 @@ -56598000-56599000 r-xp 0 00:00 0 waiter -f7432000-f75e3000 r-xp 0 00:00 0 libc.so diff --git a/libunwindstack/tests/files/offline/debug_frame_first_x86/regs.txt b/libunwindstack/tests/files/offline/debug_frame_first_x86/regs.txt deleted file mode 100644 index 48f44401c..000000000 --- a/libunwindstack/tests/files/offline/debug_frame_first_x86/regs.txt +++ /dev/null @@ -1,9 +0,0 @@ -eax: 1d88ef8c -ebx: 56599fe8 -ecx: 3 -edx: ffcf9ea4 -ebp: ffcf9e48 -edi: f75e5000 -esi: 1 -esp: ffcf9e38 -eip: 56598685 diff --git a/libunwindstack/tests/files/offline/debug_frame_first_x86/stack.data b/libunwindstack/tests/files/offline/debug_frame_first_x86/stack.data deleted file mode 100644 index 0cf7d55a8..000000000 Binary files a/libunwindstack/tests/files/offline/debug_frame_first_x86/stack.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/debug_frame_first_x86/waiter b/libunwindstack/tests/files/offline/debug_frame_first_x86/waiter deleted file mode 100644 index b1fc0241b..000000000 Binary files a/libunwindstack/tests/files/offline/debug_frame_first_x86/waiter and /dev/null differ diff --git a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libbinder.so b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libbinder.so deleted file mode 100644 index 4b7bf44c4..000000000 Binary files a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libbinder.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libc.so b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libc.so deleted file mode 100644 index 013858ef5..000000000 Binary files a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libc.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/maps.txt b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/maps.txt deleted file mode 100644 index 10f13254b..000000000 --- a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/maps.txt +++ /dev/null @@ -1,3 +0,0 @@ -8d1c000-8d1f000 r-xp 0 00:00 0 mediaserver -f0b91000-f0c2c000 r-xp 0 00:00 0 libc.so -f1a41000-f1a97000 r-xp 0 00:00 0 libbinder.so diff --git a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/mediaserver b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/mediaserver deleted file mode 100644 index 9e4a83f01..000000000 Binary files a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/mediaserver and /dev/null differ diff --git a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/regs.txt b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/regs.txt deleted file mode 100644 index f147247e5..000000000 --- a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/regs.txt +++ /dev/null @@ -1,16 +0,0 @@ -r0: 3 -r1: c0306201 -r2: ffd4a658 -r3: 0 -r4: f0c36d8c -r5: ffd4a658 -r6: f0168000 -r7: 36 -r8: ffd4a678 -r9: f016802c -r10: ffd4a660 -r11: 0 -ip: 0 -sp: ffd4a638 -lr: f0bb2413 -pc: f0be238c diff --git a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/stack.data b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/stack.data deleted file mode 100644 index 847c8192a..000000000 Binary files a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/stack.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/libc.so b/libunwindstack/tests/files/offline/eh_frame_bias_x86/libc.so deleted file mode 100644 index f3eb6153d..000000000 Binary files a/libunwindstack/tests/files/offline/eh_frame_bias_x86/libc.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/maps.txt b/libunwindstack/tests/files/offline/eh_frame_bias_x86/maps.txt deleted file mode 100644 index 7d5248393..000000000 --- a/libunwindstack/tests/files/offline/eh_frame_bias_x86/maps.txt +++ /dev/null @@ -1,3 +0,0 @@ -eb503000-eb5e8000 r-xp 0 00:00 0 libc.so -eb831000-eb852000 r-xp 0 00:00 0 tombstoned -ffffe000-fffff000 r-xp 0 00:00 0 vdso.so diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/regs.txt b/libunwindstack/tests/files/offline/eh_frame_bias_x86/regs.txt deleted file mode 100644 index 821928e79..000000000 --- a/libunwindstack/tests/files/offline/eh_frame_bias_x86/regs.txt +++ /dev/null @@ -1,9 +0,0 @@ -eax: fffffffc -ebx: 4 -ecx: eb290180 -edx: 20 -ebp: 8 -edi: 0 -esi: ffffffff -esp: fffe1a30 -eip: ffffe430 diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/stack.data b/libunwindstack/tests/files/offline/eh_frame_bias_x86/stack.data deleted file mode 100644 index b95bfac9e..000000000 Binary files a/libunwindstack/tests/files/offline/eh_frame_bias_x86/stack.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/tombstoned b/libunwindstack/tests/files/offline/eh_frame_bias_x86/tombstoned deleted file mode 100644 index aefdb6b4c..000000000 Binary files a/libunwindstack/tests/files/offline/eh_frame_bias_x86/tombstoned and /dev/null differ diff --git a/libunwindstack/tests/files/offline/eh_frame_bias_x86/vdso.so b/libunwindstack/tests/files/offline/eh_frame_bias_x86/vdso.so deleted file mode 100644 index c71dcfbe5..000000000 Binary files a/libunwindstack/tests/files/offline/eh_frame_bias_x86/vdso.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/libc.so b/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/libc.so deleted file mode 100644 index 46b6f4560..000000000 Binary files a/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/libc.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/maps.txt b/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/maps.txt deleted file mode 100644 index ac2e56432..000000000 --- a/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/maps.txt +++ /dev/null @@ -1,2 +0,0 @@ -561550b17000-561550b1a000 r-xp 0 00:00 0 unwind_test64 -7f4de61f6000-7f4de638b000 r-xp 0 00:00 0 libc.so diff --git a/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/regs.txt b/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/regs.txt deleted file mode 100644 index 38af274bb..000000000 --- a/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/regs.txt +++ /dev/null @@ -1,11 +0,0 @@ -rax: 92134c6fbbdc12ff -rbx: 0 -rcx: 92134c6fbbdc1200 -rdx: 92134c6fbbdc1200 -r8: 561552153034 -r12: 561550b17930 -r13: 7ffcc8597270 -rsi: 561552153034 -rbp: 7ffcc8596f30 -rsp: 7ffcc8596ce8 -rip: 561550b17a80 diff --git a/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/stack.data b/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/stack.data deleted file mode 100644 index cc7882b83..000000000 Binary files a/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/stack.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/unwind_test64 b/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/unwind_test64 deleted file mode 100644 index ab0ef8f70..000000000 Binary files a/libunwindstack/tests/files/offline/eh_frame_hdr_begin_x86_64/unwind_test64 and /dev/null differ diff --git a/libunwindstack/tests/files/offline/empty_arm64/libbinder.so b/libunwindstack/tests/files/offline/empty_arm64/libbinder.so deleted file mode 100644 index f30384cd0..000000000 Binary files a/libunwindstack/tests/files/offline/empty_arm64/libbinder.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/empty_arm64/libc.so b/libunwindstack/tests/files/offline/empty_arm64/libc.so deleted file mode 100644 index b05dcafde..000000000 Binary files a/libunwindstack/tests/files/offline/empty_arm64/libc.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/empty_arm64/maps.txt b/libunwindstack/tests/files/offline/empty_arm64/maps.txt deleted file mode 100644 index edb83c6d1..000000000 --- a/libunwindstack/tests/files/offline/empty_arm64/maps.txt +++ /dev/null @@ -1,9 +0,0 @@ -5d4786b000-5d47893000 r--p 0 00:00 0 netd -5d47893000-5d47894000 ---p 0 00:00 0 -5d47894000-5d47901000 --xp 29000 00:00 0 netd -729f709000-729f750000 r--p 0 00:00 0 libbinder.so -729f750000-729f751000 ---p 0 00:00 0 -729f751000-729f794000 --xp 48000 00:00 0 libbinder.so -72a018a000-72a01c2000 r--p 0 00:00 0 libc.so -72a01c2000-72a01c3000 ---p 0 00:00 0 -72a01c3000-72a023b000 --xp 39000 00:00 0 libc.so diff --git a/libunwindstack/tests/files/offline/empty_arm64/netd b/libunwindstack/tests/files/offline/empty_arm64/netd deleted file mode 100644 index 8a72e9491..000000000 Binary files a/libunwindstack/tests/files/offline/empty_arm64/netd and /dev/null differ diff --git a/libunwindstack/tests/files/offline/empty_arm64/regs.txt b/libunwindstack/tests/files/offline/empty_arm64/regs.txt deleted file mode 100644 index 3d4279f7a..000000000 --- a/libunwindstack/tests/files/offline/empty_arm64/regs.txt +++ /dev/null @@ -1,34 +0,0 @@ -x0: 1d -x1: c0306201 -x2: 7ffb6c0c50 -x3: 0 -x4: 0 -x5: 0 -x6: 0 -x7: 0 -x8: 1d -x9: 7ffb6c0c00 -x10: 7ffb6c0c50 -x11: 7ffb6c0bd0 -x12: ffffff80ffffffd0 -x13: 0 -x14: 72a0240ce2 -x15: 20 -x16: 729f7a54e8 -x17: 72a01dd3c0 -x18: 72a0ac2000 -x19: 72a0666000 -x20: 719769b610 -x21: 719769b730 -x22: c0306201 -x23: fffffff7 -x24: 72a0666000 -x25: 0 -x26: 0 -x27: 0 -x28: 0 -x29: 7ffb6c0c30 -sp: 7ffb6c0b50 -lr: 72a01dd450 -pc: 72a02203a4 -pst: a0000000 diff --git a/libunwindstack/tests/files/offline/empty_arm64/stack.data b/libunwindstack/tests/files/offline/empty_arm64/stack.data deleted file mode 100644 index 6d6108c60..000000000 Binary files a/libunwindstack/tests/files/offline/empty_arm64/stack.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/gnu_debugdata_arm/libandroid_runtime.so b/libunwindstack/tests/files/offline/gnu_debugdata_arm/libandroid_runtime.so deleted file mode 100644 index e4283e63b..000000000 Binary files a/libunwindstack/tests/files/offline/gnu_debugdata_arm/libandroid_runtime.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/gnu_debugdata_arm/maps.txt b/libunwindstack/tests/files/offline/gnu_debugdata_arm/maps.txt deleted file mode 100644 index 1bcddb6b8..000000000 --- a/libunwindstack/tests/files/offline/gnu_debugdata_arm/maps.txt +++ /dev/null @@ -1 +0,0 @@ -f1f10000-f2049000 r-xp 00000000 00:00 0 libandroid_runtime.so diff --git a/libunwindstack/tests/files/offline/gnu_debugdata_arm/regs.txt b/libunwindstack/tests/files/offline/gnu_debugdata_arm/regs.txt deleted file mode 100644 index c6a93dce5..000000000 --- a/libunwindstack/tests/files/offline/gnu_debugdata_arm/regs.txt +++ /dev/null @@ -1,2 +0,0 @@ -pc: f1f6dc49 -sp: d8fe6930 diff --git a/libunwindstack/tests/files/offline/gnu_debugdata_arm/stack.data b/libunwindstack/tests/files/offline/gnu_debugdata_arm/stack.data deleted file mode 100644 index 19cdf2ddf..000000000 Binary files a/libunwindstack/tests/files/offline/gnu_debugdata_arm/stack.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/invalid_elf_offset_arm/maps.txt b/libunwindstack/tests/files/offline/invalid_elf_offset_arm/maps.txt deleted file mode 100644 index 022404c77..000000000 --- a/libunwindstack/tests/files/offline/invalid_elf_offset_arm/maps.txt +++ /dev/null @@ -1 +0,0 @@ -c7ee8000-c8c52fff r-xp 12e4000 00:00 0 invalid.apk diff --git a/libunwindstack/tests/files/offline/invalid_elf_offset_arm/regs.txt b/libunwindstack/tests/files/offline/invalid_elf_offset_arm/regs.txt deleted file mode 100644 index b7f10efc1..000000000 --- a/libunwindstack/tests/files/offline/invalid_elf_offset_arm/regs.txt +++ /dev/null @@ -1,16 +0,0 @@ -r0: c0434c00 -r1: 2a4c9fbc -r2: 00000000 -r3: c83ef1f9 -r4: 00000004 -r5: c2044904 -r6: 00000000 -r7: c20443b8 -r8: 000b33ff -r9: c20444b0 -r10: cac90740 -r11: 00000000 -ip: ed891ca4 -sp: c2044218 -lr: ed807265 -pc: c898f508 diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/137-cfi.odex b/libunwindstack/tests/files/offline/jit_debug_arm/137-cfi.odex deleted file mode 100644 index 35a6bc5ab..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_arm/137-cfi.odex and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/dalvikvm32 b/libunwindstack/tests/files/offline/jit_debug_arm/dalvikvm32 deleted file mode 100644 index def299e01..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_arm/dalvikvm32 and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/descriptor.data b/libunwindstack/tests/files/offline/jit_debug_arm/descriptor.data deleted file mode 100644 index 7b876b5fc..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_arm/descriptor.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/descriptor1.data b/libunwindstack/tests/files/offline/jit_debug_arm/descriptor1.data deleted file mode 100644 index 3c468d641..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_arm/descriptor1.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/entry0.data b/libunwindstack/tests/files/offline/jit_debug_arm/entry0.data deleted file mode 100644 index 2c7689b3c..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_arm/entry0.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/entry1.data b/libunwindstack/tests/files/offline/jit_debug_arm/entry1.data deleted file mode 100644 index 22a35b82b..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_arm/entry1.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/entry2.data b/libunwindstack/tests/files/offline/jit_debug_arm/entry2.data deleted file mode 100644 index 61f39275e..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_arm/entry2.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/entry3.data b/libunwindstack/tests/files/offline/jit_debug_arm/entry3.data deleted file mode 100644 index 1a37628e4..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_arm/entry3.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/entry4.data b/libunwindstack/tests/files/offline/jit_debug_arm/entry4.data deleted file mode 100644 index 7ef62caef..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_arm/entry4.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/entry5.data b/libunwindstack/tests/files/offline/jit_debug_arm/entry5.data deleted file mode 100644 index 6d27c890b..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_arm/entry5.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/entry6.data b/libunwindstack/tests/files/offline/jit_debug_arm/entry6.data deleted file mode 100644 index bfbceeabd..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_arm/entry6.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/jit0.data b/libunwindstack/tests/files/offline/jit_debug_arm/jit0.data deleted file mode 100644 index b78848e9a..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_arm/jit0.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/jit1.data b/libunwindstack/tests/files/offline/jit_debug_arm/jit1.data deleted file mode 100644 index 8f927ac79..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_arm/jit1.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/jit2.data b/libunwindstack/tests/files/offline/jit_debug_arm/jit2.data deleted file mode 100644 index 1d1dfca8c..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_arm/jit2.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/jit3.data b/libunwindstack/tests/files/offline/jit_debug_arm/jit3.data deleted file mode 100644 index 89aeb43c1..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_arm/jit3.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/jit4.data b/libunwindstack/tests/files/offline/jit_debug_arm/jit4.data deleted file mode 100644 index e076934c5..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_arm/jit4.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/jit5.data b/libunwindstack/tests/files/offline/jit_debug_arm/jit5.data deleted file mode 100644 index 17d604157..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_arm/jit5.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/jit6.data b/libunwindstack/tests/files/offline/jit_debug_arm/jit6.data deleted file mode 100644 index aaff0378c..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_arm/jit6.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/libart.so b/libunwindstack/tests/files/offline/jit_debug_arm/libart.so deleted file mode 100644 index 05278936b..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_arm/libart.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/libartd.so b/libunwindstack/tests/files/offline/jit_debug_arm/libartd.so deleted file mode 100644 index 855905655..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_arm/libartd.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/libarttestd.so b/libunwindstack/tests/files/offline/jit_debug_arm/libarttestd.so deleted file mode 100644 index 06dbf10c7..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_arm/libarttestd.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/libc.so b/libunwindstack/tests/files/offline/jit_debug_arm/libc.so deleted file mode 100644 index 9894e6627..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_arm/libc.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt b/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt deleted file mode 100644 index 3b87f2f62..000000000 --- a/libunwindstack/tests/files/offline/jit_debug_arm/maps.txt +++ /dev/null @@ -1,11 +0,0 @@ -ab0d3000-ab0d8000 r-xp 0 00:00 0 dalvikvm32 -dfe4e000-dfe7b000 r-xp 0 00:00 0 libarttestd.so -e0445000-e0447000 r--p 0 00:00 0 137-cfi.odex -e0447000-e0448000 r-xp 2000 00:00 0 137-cfi.odex -e2796000-e4796000 r-xp 0 00:00 0 anonymous:e2796000 -e648e000-e690f000 r-xp 0 00:00 0 libart.so -e6918000-e6919000 rw-p 489000 00:00 0 libart.so -ed306000-ed801000 r-xp 0 00:00 0 libartd.so -ed80a000-ed80b000 rw-p 503000 00:00 0 libartd.so -eda88000-edb23000 r-xp 0 00:00 0 libc.so -ede4e000-ede50000 r-xp 0 00:00 0 anonymous:ede4e000 diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/regs.txt b/libunwindstack/tests/files/offline/jit_debug_arm/regs.txt deleted file mode 100644 index 0e20066ed..000000000 --- a/libunwindstack/tests/files/offline/jit_debug_arm/regs.txt +++ /dev/null @@ -1,16 +0,0 @@ -r0: dfe7c0f8 -r1: 0 -r2: 0 -r3: 40000000 -r4: e051ffb4 -r5: 0 -r6: e051ffc0 -r7: ede514e8 -r8: ff85d1a8 -r9: ed9210c0 -r10: 58 -r11: 0 -ip: edb26d04 -sp: ff85d180 -lr: edaff5af -pc: dfe66a5e diff --git a/libunwindstack/tests/files/offline/jit_debug_arm/stack.data b/libunwindstack/tests/files/offline/jit_debug_arm/stack.data deleted file mode 100644 index b2ff14eb9..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_arm/stack.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/137-cfi.odex b/libunwindstack/tests/files/offline/jit_debug_x86/137-cfi.odex deleted file mode 100644 index 870ac0a74..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_x86/137-cfi.odex and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/dalvikvm32 b/libunwindstack/tests/files/offline/jit_debug_x86/dalvikvm32 deleted file mode 100644 index 76ffad93e..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_x86/dalvikvm32 and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/descriptor.data b/libunwindstack/tests/files/offline/jit_debug_x86/descriptor.data deleted file mode 100644 index 466dae28b..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_x86/descriptor.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/entry0.data b/libunwindstack/tests/files/offline/jit_debug_x86/entry0.data deleted file mode 100644 index 3a725e800..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_x86/entry0.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/entry1.data b/libunwindstack/tests/files/offline/jit_debug_x86/entry1.data deleted file mode 100644 index 767550f00..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_x86/entry1.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/entry2.data b/libunwindstack/tests/files/offline/jit_debug_x86/entry2.data deleted file mode 100644 index e7e492e79..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_x86/entry2.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/entry3.data b/libunwindstack/tests/files/offline/jit_debug_x86/entry3.data deleted file mode 100644 index 65f9cd432..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_x86/entry3.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/entry4.data b/libunwindstack/tests/files/offline/jit_debug_x86/entry4.data deleted file mode 100644 index 30aa28cfb..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_x86/entry4.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/entry5.data b/libunwindstack/tests/files/offline/jit_debug_x86/entry5.data deleted file mode 100644 index 3c89673f2..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_x86/entry5.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/entry6.data b/libunwindstack/tests/files/offline/jit_debug_x86/entry6.data deleted file mode 100644 index 9c9b83c3c..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_x86/entry6.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/jit0.data b/libunwindstack/tests/files/offline/jit_debug_x86/jit0.data deleted file mode 100644 index eaad1420a..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_x86/jit0.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/jit1.data b/libunwindstack/tests/files/offline/jit_debug_x86/jit1.data deleted file mode 100644 index d53481644..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_x86/jit1.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/jit2.data b/libunwindstack/tests/files/offline/jit_debug_x86/jit2.data deleted file mode 100644 index dbeb886cc..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_x86/jit2.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/jit3.data b/libunwindstack/tests/files/offline/jit_debug_x86/jit3.data deleted file mode 100644 index bf2142d82..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_x86/jit3.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/jit4.data b/libunwindstack/tests/files/offline/jit_debug_x86/jit4.data deleted file mode 100644 index e2ba1b0f2..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_x86/jit4.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/jit5.data b/libunwindstack/tests/files/offline/jit_debug_x86/jit5.data deleted file mode 100644 index c27ba541c..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_x86/jit5.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/jit6.data b/libunwindstack/tests/files/offline/jit_debug_x86/jit6.data deleted file mode 100644 index 5fc8fae46..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_x86/jit6.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/libartd.so b/libunwindstack/tests/files/offline/jit_debug_x86/libartd.so deleted file mode 100644 index 92ed9915d..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_x86/libartd.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/libarttestd.so b/libunwindstack/tests/files/offline/jit_debug_x86/libarttestd.so deleted file mode 100644 index 5efae0273..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_x86/libarttestd.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/libc.so b/libunwindstack/tests/files/offline/jit_debug_x86/libc.so deleted file mode 100644 index 9c787902b..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_x86/libc.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/maps.txt b/libunwindstack/tests/files/offline/jit_debug_x86/maps.txt deleted file mode 100644 index c22b5deaf..000000000 --- a/libunwindstack/tests/files/offline/jit_debug_x86/maps.txt +++ /dev/null @@ -1,8 +0,0 @@ -56573000-56577000 r-xp 0 00:00 0 dalvikvm32 -eb833000-eb8cc000 r-xp 0 00:00 0 libarttestd.so -ec604000-ec606000 r--p 0 00:00 0 137-cfi.odex -ec606000-ec607000 r-xp 2000 00:00 0 137-cfi.odex -ee74c000-f074c000 r-xp 0 00:00 0 anonymous:ee74c000 -f6be1000-f732b000 r-xp 0 00:00 0 libartd.so -f7334000-f7335000 rw-p 752000 00:00 0 libartd.so -f734b000-f74fc000 r-xp 0 00:00 0 libc.so diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/regs.txt b/libunwindstack/tests/files/offline/jit_debug_x86/regs.txt deleted file mode 100644 index f68305b81..000000000 --- a/libunwindstack/tests/files/offline/jit_debug_x86/regs.txt +++ /dev/null @@ -1,9 +0,0 @@ -eax: eb8cccd0 -ebx: eb8cccd0 -ecx: ff -edx: ffeb2ca8 -ebp: ffeb5298 -edi: ffeb5c08 -esi: ffeb5c00 -esp: ffeb5280 -eip: eb89bfb8 diff --git a/libunwindstack/tests/files/offline/jit_debug_x86/stack.data b/libunwindstack/tests/files/offline/jit_debug_x86/stack.data deleted file mode 100644 index c3457624e..000000000 Binary files a/libunwindstack/tests/files/offline/jit_debug_x86/stack.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_map_arm/jit_map0.so b/libunwindstack/tests/files/offline/jit_map_arm/jit_map0.so deleted file mode 100644 index e66788377..000000000 Binary files a/libunwindstack/tests/files/offline/jit_map_arm/jit_map0.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_map_arm/jit_map1.so b/libunwindstack/tests/files/offline/jit_map_arm/jit_map1.so deleted file mode 100644 index 9a1d71483..000000000 Binary files a/libunwindstack/tests/files/offline/jit_map_arm/jit_map1.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_map_arm/libart.so b/libunwindstack/tests/files/offline/jit_map_arm/libart.so deleted file mode 100644 index 09ba49532..000000000 Binary files a/libunwindstack/tests/files/offline/jit_map_arm/libart.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_map_arm/libc.so b/libunwindstack/tests/files/offline/jit_map_arm/libc.so deleted file mode 100644 index 39c9025db..000000000 Binary files a/libunwindstack/tests/files/offline/jit_map_arm/libc.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/jit_map_arm/maps.txt b/libunwindstack/tests/files/offline/jit_map_arm/maps.txt deleted file mode 100644 index 5aaec5420..000000000 --- a/libunwindstack/tests/files/offline/jit_map_arm/maps.txt +++ /dev/null @@ -1,2 +0,0 @@ -e466e000-e4ae8000 r-xp 0 00:00 0 libart.so -e7d91000-e7e31000 r-xp 0 00:00 0 libc.so diff --git a/libunwindstack/tests/files/offline/jit_map_arm/regs.txt b/libunwindstack/tests/files/offline/jit_map_arm/regs.txt deleted file mode 100644 index 0b518143a..000000000 --- a/libunwindstack/tests/files/offline/jit_map_arm/regs.txt +++ /dev/null @@ -1,16 +0,0 @@ -r0: e814103c -r1: 12dcf218 -r2: 1a90df75 -r3: ffffffbf -r4: 0 -r5: 12dc0800 -r6: 12dcf218 -r7: 1a90df75 -r8: 0 -r9: dd23cc00 -r10: 1c -r11: cd4ff16c -ip: 0 -sp: cd4ff140 -lr: d025cdd7 -pc: d025c788 diff --git a/libunwindstack/tests/files/offline/jit_map_arm/stack.data b/libunwindstack/tests/files/offline/jit_map_arm/stack.data deleted file mode 100644 index fb8feebf1..000000000 Binary files a/libunwindstack/tests/files/offline/jit_map_arm/stack.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/libc.so b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/libc.so deleted file mode 100644 index 7bb7156bb..000000000 Binary files a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/libc.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/linker64 b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/linker64 deleted file mode 100644 index 00a3896d6..000000000 Binary files a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/linker64 and /dev/null differ diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/maps.txt b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/maps.txt deleted file mode 100644 index a2babee1c..000000000 --- a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/maps.txt +++ /dev/null @@ -1,7 +0,0 @@ -5f73997000-5f739dc000 r--p 0 00:00 0 test -5f739dc000-5f73a43000 r-xp 44000 00:00 0 test -711152c000-711156e000 r--p 0 00:00 0 libc.so -711156e000-7111611000 --xp 42000 00:00 0 libc.so -7112be2000-7112be4000 r-xp 0 00:00 0 vdso -7112be4000-7112c1c000 r--p 0 00:00 0 linker64 -7112c1c000-7112ce1000 r-xp 38000 00:00 0 linker64 diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/regs.txt b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/regs.txt deleted file mode 100644 index 3c601e15e..000000000 --- a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/regs.txt +++ /dev/null @@ -1,33 +0,0 @@ -x0: 7112bdbc24 -x1: 0 -x2: ffffffff -x3: 0 -x4: 0 -x5: 0 -x6: 0 -x7: 7f7f7f7f7f7f7f7f -x8: 62 -x9: a78826643b37f4a1 -x10: 7112bdbc20 -x11: 4100 -x12: 7112bdbb70 -x13: 18 -x14: 1d6518077 -x15: 2a43148faf732a -x16: 16fc0 -x17: 71115f61a0 -x18: 7111d6a000 -x19: 7112cef1b0 -x20: 7112bdbda0 -x21: 59616d61 -x22: 1 -x23: 7112bdbc24 -x24: 4b0e -x25: 62 -x26: 2 -x27: 0 -x28: 7111934020 -x29: 7112bdbd90 -sp: 7112bdbbf0 -lr: 7112c394ec -pc: 7112cb99bc diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack0.data b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack0.data deleted file mode 100644 index 167473373..000000000 Binary files a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack0.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack1.data b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack1.data deleted file mode 100644 index 6d7b48ab1..000000000 Binary files a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/stack1.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/test b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/test deleted file mode 100644 index 3a75b8fbe..000000000 Binary files a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/test and /dev/null differ diff --git a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/vdso b/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/vdso deleted file mode 100644 index 49409167f..000000000 Binary files a/libunwindstack/tests/files/offline/load_bias_different_section_bias_arm64/vdso and /dev/null differ diff --git a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/libc.so b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/libc.so deleted file mode 100644 index 63383d043..000000000 Binary files a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/libc.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/maps.txt b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/maps.txt deleted file mode 100644 index ba5a31bac..000000000 --- a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/maps.txt +++ /dev/null @@ -1,3 +0,0 @@ -200000-919000 r--p 0 00:00 0 perfetto_unittests -919000-1a0c000 r-xp 719000 00:00 0 perfetto_unittests -7f932696e000-7f9326b23000 r-xp 0 00:00 0 libc.so diff --git a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/perfetto_unittests b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/perfetto_unittests deleted file mode 100644 index a30e5999f..000000000 Binary files a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/perfetto_unittests and /dev/null differ diff --git a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/regs.txt b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/regs.txt deleted file mode 100644 index 6cb405516..000000000 --- a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/regs.txt +++ /dev/null @@ -1,17 +0,0 @@ -rax: 3b -rbx: 3b -rcx: 7f9326a57dd4 -rdx: 3b -r8: 7ffd22415b09 -r9: 7ffd224155e0 -r10: 0 -r11: 246 -r12: 7f9326d28760 -r13: 3b -r14: 7f9326d23760 -r15: 3b -rdi: 1 -rsi: 2678850 -rbp: 2678850 -rsp: 7ffd224153c8 -rip: 7f9326a57dd4 diff --git a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/stack.data b/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/stack.data deleted file mode 100644 index 4edfe0751..000000000 Binary files a/libunwindstack/tests/files/offline/load_bias_ro_rx_x86_64/stack.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/offset_arm/libc.so b/libunwindstack/tests/files/offline/offset_arm/libc.so deleted file mode 100644 index 9f5c8ca44..000000000 Binary files a/libunwindstack/tests/files/offline/offset_arm/libc.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/offset_arm/libunwindstack_test b/libunwindstack/tests/files/offline/offset_arm/libunwindstack_test deleted file mode 100644 index 7a30bfa44..000000000 Binary files a/libunwindstack/tests/files/offline/offset_arm/libunwindstack_test and /dev/null differ diff --git a/libunwindstack/tests/files/offline/offset_arm/maps.txt b/libunwindstack/tests/files/offline/offset_arm/maps.txt deleted file mode 100644 index 768dd9f8d..000000000 --- a/libunwindstack/tests/files/offline/offset_arm/maps.txt +++ /dev/null @@ -1,4 +0,0 @@ -2b2a000-2b6c000 r--p 0 00:00 0 libunwindstack_test -2b6c000-2e92000 r-xp 42000 00:00 0 libunwindstack_test -f4110000-f4135000 r--p 0 00:00 0 libc.so -f4135000-f41a9000 r-xp 25000 00:00 0 libc.so diff --git a/libunwindstack/tests/files/offline/offset_arm/regs.txt b/libunwindstack/tests/files/offline/offset_arm/regs.txt deleted file mode 100644 index 1f4ac8f7b..000000000 --- a/libunwindstack/tests/files/offline/offset_arm/regs.txt +++ /dev/null @@ -1,16 +0,0 @@ -r0: 5 -r1: 5 -r2: 4 -r3: 1 -r4: 73804b6b -r5: f3c9c000 -r6: 2ea09ac -r7: 10624dd3 -r8: f41b5d8c -r9: f3c9c000 -r10: 6f17 -r11: f3c94048 -ip: 2ea0807 -sp: f43d2ccc -lr: 2e55fef -pc: 2e55fa0 diff --git a/libunwindstack/tests/files/offline/offset_arm/stack0.data b/libunwindstack/tests/files/offline/offset_arm/stack0.data deleted file mode 100644 index 23a987415..000000000 Binary files a/libunwindstack/tests/files/offline/offset_arm/stack0.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/offset_arm/stack1.data b/libunwindstack/tests/files/offline/offset_arm/stack1.data deleted file mode 100644 index 49bdd1e26..000000000 Binary files a/libunwindstack/tests/files/offline/offset_arm/stack1.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/ANGLEPrebuilt.apk b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/ANGLEPrebuilt.apk deleted file mode 100644 index 02773599b..000000000 Binary files a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/ANGLEPrebuilt.apk and /dev/null differ diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/libc.so b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/libc.so deleted file mode 100644 index 20008fd15..000000000 Binary files a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/libc.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/linker64 b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/linker64 deleted file mode 100644 index b90933ba6..000000000 Binary files a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/linker64 and /dev/null differ diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/maps.txt b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/maps.txt deleted file mode 100644 index c4fc06764..000000000 --- a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/maps.txt +++ /dev/null @@ -1,7 +0,0 @@ -7dabc03000-7dabc3f000 r--p 4000 00:00 0 ANGLEPrebuilt.apk -7dabc3f000-7dabcf0000 r-xp 40000 00:00 0 ANGLEPrebuilt.apk -7e7ee48000-7e7ee88000 r--p 0 00:00 0 libc.so -7e7ee88000-7e7ef32000 r-xp 40000 00:00 0 libc.so -7e82b01000-7e82b03000 r-xp 0 00:00 0 vdso.so -7e82b03000-7e82b3c000 r--p 0 00:00 0 linker64 -7e82b3c000-7e82c77000 r-xp 39000 00:00 0 linker64 diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/regs.txt b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/regs.txt deleted file mode 100644 index 1e2ea3206..000000000 --- a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/regs.txt +++ /dev/null @@ -1,33 +0,0 @@ -x0: 7df8ca3c24 -x1: 0 -x2: ffffffff -x3: 0 -x4: 0 -x5: 0 -x6: 0 -x7: 7f7f7f7f7f7f7f7f -x8: 62 -x9: 20dd5829922a93ac -x10: 7e82b57420 -x11: 4100 -x12: 7df8ca3b70 -x13: 7df8ca3b98 -x14: 73d015e5 -x15: 39a36122467299 -x16: 76ac -x17: 0 -x18: 7df8cfc000 -x19: 7dabf3e7a0 -x20: 7df8ca3da0 -x21: 59616d61 -x22: 1 -x23: 7df8ca3c24 -x24: 1894 -x25: 62 -x26: 2 -x27: 0 -x28: 7dabf3e790 -x29: 7df8ca3d90 -sp: 7df8ca3bf0 -lr: 7e82b57270 -pc: 7e82c4fcbc diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/stack0.data b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/stack0.data deleted file mode 100644 index ec07e15c5..000000000 Binary files a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/stack0.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/stack1.data b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/stack1.data deleted file mode 100644 index 825bb1aa5..000000000 Binary files a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/stack1.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/vdso.so b/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/vdso.so deleted file mode 100644 index 205ebd43a..000000000 Binary files a/libunwindstack/tests/files/offline/shared_lib_in_apk_arm64/vdso.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/lib_mem.data b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/lib_mem.data deleted file mode 100644 index f39d127e0..000000000 Binary files a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/lib_mem.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/libc.so b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/libc.so deleted file mode 100644 index 20008fd15..000000000 Binary files a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/libc.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/linker64 b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/linker64 deleted file mode 100644 index b90933ba6..000000000 Binary files a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/linker64 and /dev/null differ diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/maps.txt b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/maps.txt deleted file mode 100644 index 386d57a24..000000000 --- a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/maps.txt +++ /dev/null @@ -1,7 +0,0 @@ -7dabc03000-7dabc3f000 r--p 21d5000 00:00 0 ANGLEPrebuilt.apk -7dabc3f000-7dabcf0000 r-xp 2211000 00:00 0 ANGLEPrebuilt.apk -7e7ee48000-7e7ee88000 r--p 0 00:00 0 libc.so -7e7ee88000-7e7ef32000 r-xp 40000 00:00 0 libc.so -7e82b01000-7e82b03000 r-xp 0 00:00 0 vdso.so -7e82b03000-7e82b3c000 r--p 0 00:00 0 linker64 -7e82b3c000-7e82c77000 r-xp 39000 00:00 0 linker64 diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/regs.txt b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/regs.txt deleted file mode 100644 index 1e2ea3206..000000000 --- a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/regs.txt +++ /dev/null @@ -1,33 +0,0 @@ -x0: 7df8ca3c24 -x1: 0 -x2: ffffffff -x3: 0 -x4: 0 -x5: 0 -x6: 0 -x7: 7f7f7f7f7f7f7f7f -x8: 62 -x9: 20dd5829922a93ac -x10: 7e82b57420 -x11: 4100 -x12: 7df8ca3b70 -x13: 7df8ca3b98 -x14: 73d015e5 -x15: 39a36122467299 -x16: 76ac -x17: 0 -x18: 7df8cfc000 -x19: 7dabf3e7a0 -x20: 7df8ca3da0 -x21: 59616d61 -x22: 1 -x23: 7df8ca3c24 -x24: 1894 -x25: 62 -x26: 2 -x27: 0 -x28: 7dabf3e790 -x29: 7df8ca3d90 -sp: 7df8ca3bf0 -lr: 7e82b57270 -pc: 7e82c4fcbc diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/stack0.data b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/stack0.data deleted file mode 100644 index ec07e15c5..000000000 Binary files a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/stack0.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/stack1.data b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/stack1.data deleted file mode 100644 index 825bb1aa5..000000000 Binary files a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/stack1.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/vdso.so b/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/vdso.so deleted file mode 100644 index 205ebd43a..000000000 Binary files a/libunwindstack/tests/files/offline/shared_lib_in_apk_memory_only_arm64/vdso.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/libc.so b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/libc.so deleted file mode 100644 index cac1dd9b8..000000000 Binary files a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/libc.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/maps.txt b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/maps.txt deleted file mode 100644 index 2c5ca62e1..000000000 --- a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/maps.txt +++ /dev/null @@ -1,3 +0,0 @@ -7be5e48000-7be6b2b000 r-xp 5000 00:00 0 test.apk -7cbe030000-7cbe070000 r--p 0 00:00 0 libc.so -7cbe070000-7cbe11a000 r-xp 40000 00:00 0 libc.so diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/regs.txt b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/regs.txt deleted file mode 100644 index 090aedae6..000000000 --- a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/regs.txt +++ /dev/null @@ -1,33 +0,0 @@ -x0: 7c326f6568 -x1: 80 -x2: 0 -x3: 0 -x4: 0 -x5: 0 -x6: 0 -x7: 7f7f7f7f7f7f7f7f -x8: 62 -x9: 1 -x10: 1 -x11: 0 -x12: ffffffffc4653600 -x13: 17645696f -x14: 2742ed97ca77a3 -x15: 3ab49084 -x16: 7be6b6bdb8 -x17: 7cbe0b14a0 -x18: 7c2b02a000 -x19: 0 -x20: 7c326f6568 -x21: 7be69c827c -x22: 7be69c8272 -x23: 1 -x24: 7be74f7100 -x25: 881 -x26: 7be4f07a00 -x27: c479c000 -x28: 7be4f07998 -x29: 7be4f079b4 -sp: 7be4f077d0 -lr: 7be6715f60 -pc: 7cbe0b14bc diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/stack.data b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/stack.data deleted file mode 100644 index 27d5bf34b..000000000 Binary files a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/stack.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/test.apk b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/test.apk deleted file mode 100644 index 70a9c71ea..000000000 Binary files a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/test.apk and /dev/null differ diff --git a/libunwindstack/tests/files/offline/signal_fde_x86/libc.so b/libunwindstack/tests/files/offline/signal_fde_x86/libc.so deleted file mode 100644 index 5c882e44d..000000000 Binary files a/libunwindstack/tests/files/offline/signal_fde_x86/libc.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/signal_fde_x86/libunwindstack_test b/libunwindstack/tests/files/offline/signal_fde_x86/libunwindstack_test deleted file mode 100644 index 8dcff6787..000000000 Binary files a/libunwindstack/tests/files/offline/signal_fde_x86/libunwindstack_test and /dev/null differ diff --git a/libunwindstack/tests/files/offline/signal_fde_x86/maps.txt b/libunwindstack/tests/files/offline/signal_fde_x86/maps.txt deleted file mode 100644 index 6166a9d5d..000000000 --- a/libunwindstack/tests/files/offline/signal_fde_x86/maps.txt +++ /dev/null @@ -1,4 +0,0 @@ -5a67c000-5a7ba000 r--p 0 00:00 0 libunwindstack_test -5a7ba000-5aedd000 r-xp 13d000 00:00 0 libunwindstack_test -ec111000-ec153000 r--p 0 00:00 0 libc.so -ec153000-ec200000 r-xp 41000 00:00 0 libc.so diff --git a/libunwindstack/tests/files/offline/signal_fde_x86/regs.txt b/libunwindstack/tests/files/offline/signal_fde_x86/regs.txt deleted file mode 100644 index 456b212b5..000000000 --- a/libunwindstack/tests/files/offline/signal_fde_x86/regs.txt +++ /dev/null @@ -1,9 +0,0 @@ -eax: 5aeec4ac -ebx: 5aeec4ac -ecx: 0 -edx: 6b -ebp: ecb37188 -edi: ebecda30 -esi: b -esp: ecb37188 -eip: 5ae0d4d9 diff --git a/libunwindstack/tests/files/offline/signal_fde_x86/stack0.data b/libunwindstack/tests/files/offline/signal_fde_x86/stack0.data deleted file mode 100644 index 0bbbe2260..000000000 Binary files a/libunwindstack/tests/files/offline/signal_fde_x86/stack0.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/signal_fde_x86/stack1.data b/libunwindstack/tests/files/offline/signal_fde_x86/stack1.data deleted file mode 100644 index 0873046f3..000000000 Binary files a/libunwindstack/tests/files/offline/signal_fde_x86/stack1.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/signal_fde_x86_64/libc.so b/libunwindstack/tests/files/offline/signal_fde_x86_64/libc.so deleted file mode 100644 index cea7336c7..000000000 Binary files a/libunwindstack/tests/files/offline/signal_fde_x86_64/libc.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/signal_fde_x86_64/libunwindstack_test b/libunwindstack/tests/files/offline/signal_fde_x86_64/libunwindstack_test deleted file mode 100644 index c48e84eaa..000000000 Binary files a/libunwindstack/tests/files/offline/signal_fde_x86_64/libunwindstack_test and /dev/null differ diff --git a/libunwindstack/tests/files/offline/signal_fde_x86_64/maps.txt b/libunwindstack/tests/files/offline/signal_fde_x86_64/maps.txt deleted file mode 100644 index 514aa71db..000000000 --- a/libunwindstack/tests/files/offline/signal_fde_x86_64/maps.txt +++ /dev/null @@ -1,4 +0,0 @@ -5bb41219a000-5bb4122cd000 r--p 0 00:00 0 libunwindstack_test -5bb4122cd000-5bb4127b9000 r-xp 132000 00:00 0 libunwindstack_test -707eb2c4e000-707eb2c91000 r--p 0 00:00 0 libc.so -707eb2c91000-707eb2d1b000 r-xp 42000 00:00 0 libc.so diff --git a/libunwindstack/tests/files/offline/signal_fde_x86_64/regs.txt b/libunwindstack/tests/files/offline/signal_fde_x86_64/regs.txt deleted file mode 100644 index 8da7b4ef0..000000000 --- a/libunwindstack/tests/files/offline/signal_fde_x86_64/regs.txt +++ /dev/null @@ -1,17 +0,0 @@ -rax: 0 -rbx: 707d82c59c60 -rcx: 4 -rdx: 707eb5aa8380 -r8: 7ffcaadde470 -r9: 7ffcaadde478 -r10: 8 -r11: 206 -r12: 707cb2c64330 -r13: 0 -r14: 174e9096a8f -r15: 707d52c96cb0 -rdi: b -rsi: 707eb5aa84b0 -rbp: 707eb5aa8320 -rsp: 707eb5aa8320 -rip: 5bb41271e15b diff --git a/libunwindstack/tests/files/offline/signal_fde_x86_64/stack0.data b/libunwindstack/tests/files/offline/signal_fde_x86_64/stack0.data deleted file mode 100644 index e19a01629..000000000 Binary files a/libunwindstack/tests/files/offline/signal_fde_x86_64/stack0.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/signal_fde_x86_64/stack1.data b/libunwindstack/tests/files/offline/signal_fde_x86_64/stack1.data deleted file mode 100644 index 3435f7cb2..000000000 Binary files a/libunwindstack/tests/files/offline/signal_fde_x86_64/stack1.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/signal_load_bias_arm/libc.so b/libunwindstack/tests/files/offline/signal_load_bias_arm/libc.so deleted file mode 100644 index f046624f6..000000000 Binary files a/libunwindstack/tests/files/offline/signal_load_bias_arm/libc.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/signal_load_bias_arm/libunwindstack_unit_test b/libunwindstack/tests/files/offline/signal_load_bias_arm/libunwindstack_unit_test deleted file mode 100644 index f460dd673..000000000 Binary files a/libunwindstack/tests/files/offline/signal_load_bias_arm/libunwindstack_unit_test and /dev/null differ diff --git a/libunwindstack/tests/files/offline/signal_load_bias_arm/maps.txt b/libunwindstack/tests/files/offline/signal_load_bias_arm/maps.txt deleted file mode 100644 index 165ae4964..000000000 --- a/libunwindstack/tests/files/offline/signal_load_bias_arm/maps.txt +++ /dev/null @@ -1,4 +0,0 @@ -b66b7000-b670c000 r--p 0 00:00 0 libunwindstack_unit_test -b670c000-b69a8000 r-xp 54000 00:00 0 libunwindstack_unit_test -f23a6000-f23d0000 r--p 0 00:00 0 libc.so -f23d0000-f2451000 r-xp 29000 00:00 0 libc.so diff --git a/libunwindstack/tests/files/offline/signal_load_bias_arm/regs.txt b/libunwindstack/tests/files/offline/signal_load_bias_arm/regs.txt deleted file mode 100644 index e03f8fd81..000000000 --- a/libunwindstack/tests/files/offline/signal_load_bias_arm/regs.txt +++ /dev/null @@ -1,16 +0,0 @@ -r0: b69b7c84 -r1: 1 -r2: 1 -r3: 1 -r4: f1e52bd0 -r5: f1e11000 -r6: f1e52bd0 -r7: f1e52a38 -r8: f1e11000 -r9: 5de82a8f -r10: f1e06030 -r11: f1e6d080 -ip: ffe67a88 -sp: f2790ce8 -lr: b6955fab -pc: b6955f9e diff --git a/libunwindstack/tests/files/offline/signal_load_bias_arm/stack0.data b/libunwindstack/tests/files/offline/signal_load_bias_arm/stack0.data deleted file mode 100644 index d9f23f8e9..000000000 Binary files a/libunwindstack/tests/files/offline/signal_load_bias_arm/stack0.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/signal_load_bias_arm/stack1.data b/libunwindstack/tests/files/offline/signal_load_bias_arm/stack1.data deleted file mode 100644 index 6011883e3..000000000 Binary files a/libunwindstack/tests/files/offline/signal_load_bias_arm/stack1.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/straddle_arm/libbase.so b/libunwindstack/tests/files/offline/straddle_arm/libbase.so deleted file mode 100644 index d1f16ee8a..000000000 Binary files a/libunwindstack/tests/files/offline/straddle_arm/libbase.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/straddle_arm/libc.so b/libunwindstack/tests/files/offline/straddle_arm/libc.so deleted file mode 100644 index 4dc19ca6c..000000000 Binary files a/libunwindstack/tests/files/offline/straddle_arm/libc.so and /dev/null differ diff --git a/libunwindstack/tests/files/offline/straddle_arm/maps.txt b/libunwindstack/tests/files/offline/straddle_arm/maps.txt deleted file mode 100644 index 8c26479fa..000000000 --- a/libunwindstack/tests/files/offline/straddle_arm/maps.txt +++ /dev/null @@ -1,4 +0,0 @@ -f2d9a000-f2da7fff r-xp 00000000 00:00 0 libbase.so -f3002000-f3005fff rw-p 00000000 00:00 0 [stack:25941] -f31d0000-f326bfff r-xp 00000000 00:00 0 libc.so -f3352000-f336bfff r-xp 00000000 00:00 0 /does/not/exist/libhidlbase.so diff --git a/libunwindstack/tests/files/offline/straddle_arm/regs.txt b/libunwindstack/tests/files/offline/straddle_arm/regs.txt deleted file mode 100644 index 3baedf365..000000000 --- a/libunwindstack/tests/files/offline/straddle_arm/regs.txt +++ /dev/null @@ -1,3 +0,0 @@ -pc: f31ea9f8 -sp: e9c866f8 -lr: f31f179f diff --git a/libunwindstack/tests/files/offline/straddle_arm/stack.data b/libunwindstack/tests/files/offline/straddle_arm/stack.data deleted file mode 100644 index 83aeb4aaa..000000000 Binary files a/libunwindstack/tests/files/offline/straddle_arm/stack.data and /dev/null differ diff --git a/libunwindstack/tests/files/offline/straddle_arm64/libunwindstack_test b/libunwindstack/tests/files/offline/straddle_arm64/libunwindstack_test deleted file mode 100644 index 092fc3aec..000000000 Binary files a/libunwindstack/tests/files/offline/straddle_arm64/libunwindstack_test and /dev/null differ diff --git a/libunwindstack/tests/files/offline/straddle_arm64/maps.txt b/libunwindstack/tests/files/offline/straddle_arm64/maps.txt deleted file mode 100644 index bdf29b5fe..000000000 --- a/libunwindstack/tests/files/offline/straddle_arm64/maps.txt +++ /dev/null @@ -1,2 +0,0 @@ -00000064d05ab000-00000064d0a6cfff r-xp 00000000 00:00 0 libunwindstack_test -0000007fe0d64000-0000007fe0d84fff rw-p 00000000 00:00 0 [stack] diff --git a/libunwindstack/tests/files/offline/straddle_arm64/regs.txt b/libunwindstack/tests/files/offline/straddle_arm64/regs.txt deleted file mode 100644 index ff8a936d2..000000000 --- a/libunwindstack/tests/files/offline/straddle_arm64/regs.txt +++ /dev/null @@ -1,4 +0,0 @@ -pc: 00000064d09d4fd8 -sp: 0000007fe0d84040 -lr: 00000064d09d507c -x29: 0000007fe0d84070 diff --git a/libunwindstack/tests/files/offline/straddle_arm64/stack.data b/libunwindstack/tests/files/offline/straddle_arm64/stack.data deleted file mode 100644 index 824d0e2c3..000000000 Binary files a/libunwindstack/tests/files/offline/straddle_arm64/stack.data and /dev/null differ diff --git a/libunwindstack/tests/fuzz/UnwinderComponentCreator.cpp b/libunwindstack/tests/fuzz/UnwinderComponentCreator.cpp deleted file mode 100644 index 65052b6c1..000000000 --- a/libunwindstack/tests/fuzz/UnwinderComponentCreator.cpp +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Copyright 2020 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 "UnwinderComponentCreator.h" - -#include -#include -#include -#include - -std::unique_ptr GetRegisters(ArchEnum arch) { - switch (arch) { - case unwindstack::ARCH_ARM: { - std::unique_ptr regs = std::make_unique(); - return regs; - } - case unwindstack::ARCH_ARM64: { - std::unique_ptr regs = std::make_unique(); - return regs; - } - case unwindstack::ARCH_X86: { - std::unique_ptr regs = std::make_unique(); - return regs; - } - case unwindstack::ARCH_X86_64: { - std::unique_ptr regs = std::make_unique(); - return regs; - } - case unwindstack::ARCH_MIPS: { - std::unique_ptr regs = std::make_unique(); - return regs; - } - case unwindstack::ARCH_MIPS64: { - std::unique_ptr regs = std::make_unique(); - return regs; - } - case unwindstack::ARCH_UNKNOWN: - default: { - std::unique_ptr regs = std::make_unique(); - return regs; - } - } -} - -ArchEnum GetArch(FuzzedDataProvider* data_provider) { - uint8_t arch = data_provider->ConsumeIntegralInRange(1, kArchCount); - return static_cast(arch); -} - -void ElfAddMapInfo(Maps* maps, uint64_t start, uint64_t end, uint64_t offset, uint64_t flags, - const char* name, Elf* elf = nullptr) { - std::string str_name(name); - maps->Add(start, end, offset, flags, name, static_cast(-1)); - if (elf != nullptr) { - const auto& map_info = *--maps->end(); - map_info->elf.reset(elf); - } -} - -void ElfPushFakeFunctionData(FuzzedDataProvider* data_provider, ElfInterfaceFake* elf) { - uint8_t func_count = data_provider->ConsumeIntegralInRange(0, kMaxFuncCount); - for (uint8_t i = 0; i < func_count; i++) { - std::string func_name = data_provider->ConsumeRandomLengthString(kMaxFuncNameLen); - bool global = data_provider->ConsumeBool(); - if (global) { - elf->FakeSetGlobalVariable(func_name, data_provider->ConsumeIntegral()); - } else { - ElfInterfaceFake::FakePushFunctionData(FunctionData(func_name, i)); - } - } -} -void ElfPushFakeStepData(FuzzedDataProvider* data_provider) { - uint8_t step_count = data_provider->ConsumeIntegralInRange(0, kMaxStepCount); - for (uint8_t i = 0; i < step_count; i++) { - uint64_t pc = data_provider->ConsumeIntegral(); - uint64_t sp = data_provider->ConsumeIntegral(); - bool finished = i + 1 == step_count; - ElfInterfaceFake::FakePushStepData(StepData(pc, sp, finished)); - } -} - -ElfFake* PopulateElfFake(FuzzedDataProvider* data_provider) { - // This will be passed to a smart pointer in ElfAddMapInfo. - ElfFake* elf = new ElfFake(new MemoryFake); - - // This will be handled by a smart pointer within Elf. - ElfInterfaceFake* interface_fake = new ElfInterfaceFake(nullptr); - std::string build_id = data_provider->ConsumeRandomLengthString(kMaxBuildIdLen); - interface_fake->FakeSetBuildID(build_id); - std::string so_name = data_provider->ConsumeRandomLengthString(kMaxSoNameLen); - interface_fake->FakeSetSoname(so_name.c_str()); - - elf->FakeSetArch(GetArch(data_provider)); - elf->FakeSetLoadBias(data_provider->ConsumeIntegral()); - - ElfPushFakeFunctionData(data_provider, interface_fake); - ElfPushFakeStepData(data_provider); - - elf->FakeSetInterface(interface_fake); - ElfInterfaceFake::FakeClear(); - return elf; -} - -static constexpr size_t kPageSize = 4096; - -static inline bool AlignToPage(uint64_t address, uint64_t* aligned_address) { - if (__builtin_add_overflow(address, kPageSize - 1, aligned_address)) { - return false; - } - *aligned_address &= ~(kPageSize - 1); - return true; -} - -std::unique_ptr GetMaps(FuzzedDataProvider* data_provider) { - std::unique_ptr maps = std::make_unique(); - std::map map_ends; - uint8_t entry_count = data_provider->ConsumeIntegralInRange(0, kMaxMapEntryCount); - for (uint8_t i = 0; i < entry_count; i++) { - uint64_t start; - if (!AlignToPage(data_provider->ConsumeIntegral(), &start)) { - // Overflowed. - continue; - } - uint64_t end; - if (!AlignToPage(data_provider->ConsumeIntegralInRange(start, UINT64_MAX), &end)) { - // Overflowed. - continue; - } - if (start == end) { - // It's impossible to see start == end in the real world, so - // make sure the map contains at least one page of data. - if (__builtin_add_overflow(end, 0x1000, &end)) { - continue; - } - } - // Make sure not to add overlapping maps, that is not something that can - // happen in the real world. - auto entry = map_ends.upper_bound(start); - if (entry != map_ends.end() && end > entry->second) { - continue; - } - map_ends[end] = start; - - uint64_t offset; - if (!AlignToPage(data_provider->ConsumeIntegral(), &offset)) { - // Overflowed. - continue; - } - std::string map_info_name = data_provider->ConsumeRandomLengthString(kMaxMapInfoNameLen); - uint8_t flags = PROT_READ | PROT_WRITE; - - bool exec = data_provider->ConsumeBool(); - if (exec) { - flags |= PROT_EXEC; - } - - bool shouldAddElf = data_provider->ConsumeBool(); - if (shouldAddElf) { - ElfAddMapInfo(maps.get(), start, end, offset, flags, map_info_name.c_str(), - PopulateElfFake(data_provider)); - } else { - ElfAddMapInfo(maps.get(), start, end, offset, flags, map_info_name.c_str()); - } - } - maps->Sort(); - return maps; -} - -// This code (until PutElfFilesInMemory) is pretty much directly copied from JitDebugTest.cpp -// There's a few minor modifications, most notably, all methods accept a MemoryFake pointer, and -// PutElfInMemory inserts JIT data when called. -void WriteDescriptor32(MemoryFake* memory, uint64_t addr, uint32_t entry) { - // Format of the 32 bit JITDescriptor structure: - // uint32_t version - memory->SetData32(addr, 1); - // uint32_t action_flag - memory->SetData32(addr + 4, 0); - // uint32_t relevant_entry - memory->SetData32(addr + 8, 0); - // uint32_t first_entry - memory->SetData32(addr + 12, entry); -} - -void WriteDescriptor64(MemoryFake* memory, uint64_t addr, uint64_t entry) { - // Format of the 64 bit JITDescriptor structure: - // uint32_t version - memory->SetData32(addr, 1); - // uint32_t action_flag - memory->SetData32(addr + 4, 0); - // uint64_t relevant_entry - memory->SetData64(addr + 8, 0); - // uint64_t first_entry - memory->SetData64(addr + 16, entry); -} - -void WriteEntry32Pack(MemoryFake* memory, uint64_t addr, uint32_t prev, uint32_t next, - uint32_t elf_addr, uint64_t elf_size) { - // Format of the 32 bit JITCodeEntry structure: - // uint32_t next - memory->SetData32(addr, next); - // uint32_t prev - memory->SetData32(addr + 4, prev); - // uint32_t symfile_addr - memory->SetData32(addr + 8, elf_addr); - // uint64_t symfile_size - memory->SetData64(addr + 12, elf_size); -} - -void WriteEntry32Pad(MemoryFake* memory, uint64_t addr, uint32_t prev, uint32_t next, - uint32_t elf_addr, uint64_t elf_size) { - // Format of the 32 bit JITCodeEntry structure: - // uint32_t next - memory->SetData32(addr, next); - // uint32_t prev - memory->SetData32(addr + 4, prev); - // uint32_t symfile_addr - memory->SetData32(addr + 8, elf_addr); - // uint32_t pad - memory->SetData32(addr + 12, 0); - // uint64_t symfile_size - memory->SetData64(addr + 16, elf_size); -} - -void WriteEntry64(MemoryFake* memory, uint64_t addr, uint64_t prev, uint64_t next, - uint64_t elf_addr, uint64_t elf_size) { - // Format of the 64 bit JITCodeEntry structure: - // uint64_t next - memory->SetData64(addr, next); - // uint64_t prev - memory->SetData64(addr + 8, prev); - // uint64_t symfile_addr - memory->SetData64(addr + 16, elf_addr); - // uint64_t symfile_size - memory->SetData64(addr + 24, elf_size); -} - -template -void PutElfInMemory(MemoryFake* memory, uint64_t offset, uint8_t class_type, uint8_t machine_type, - uint32_t pc, uint32_t size) { - EhdrType ehdr; - memset(&ehdr, 0, sizeof(ehdr)); - uint64_t sh_offset = sizeof(ehdr); - memcpy(ehdr.e_ident, ELFMAG, SELFMAG); - ehdr.e_ident[EI_CLASS] = class_type; - ehdr.e_machine = machine_type; - ehdr.e_shstrndx = 1; - ehdr.e_shoff = sh_offset; - ehdr.e_shentsize = sizeof(ShdrType); - ehdr.e_shnum = 3; - memory->SetMemory(offset, &ehdr, sizeof(ehdr)); - - ShdrType shdr; - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_NULL; - memory->SetMemory(offset + sh_offset, &shdr, sizeof(shdr)); - - sh_offset += sizeof(shdr); - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_STRTAB; - shdr.sh_name = 1; - shdr.sh_offset = 0x500; - shdr.sh_size = 0x100; - memory->SetMemory(offset + sh_offset, &shdr, sizeof(shdr)); - memory->SetMemory(offset + 0x500, ".debug_frame"); - - sh_offset += sizeof(shdr); - memset(&shdr, 0, sizeof(shdr)); - shdr.sh_type = SHT_PROGBITS; - shdr.sh_name = 0; - shdr.sh_addr = 0x600; - shdr.sh_offset = 0x600; - shdr.sh_size = 0x200; - memory->SetMemory(offset + sh_offset, &shdr, sizeof(shdr)); - - // Now add a single cie/fde. - uint64_t dwarf_offset = offset + 0x600; - if (class_type == ELFCLASS32) { - // CIE 32 information. - memory->SetData32(dwarf_offset, 0xfc); - memory->SetData32(dwarf_offset + 0x4, 0xffffffff); - memory->SetData8(dwarf_offset + 0x8, 1); - memory->SetData8(dwarf_offset + 0x9, '\0'); - memory->SetData8(dwarf_offset + 0xa, 0x4); - memory->SetData8(dwarf_offset + 0xb, 0x4); - memory->SetData8(dwarf_offset + 0xc, 0x1); - - // FDE 32 information. - memory->SetData32(dwarf_offset + 0x100, 0xfc); - memory->SetData32(dwarf_offset + 0x104, 0); - memory->SetData32(dwarf_offset + 0x108, pc); - memory->SetData32(dwarf_offset + 0x10c, size); - } else { - // CIE 64 information. - memory->SetData32(dwarf_offset, 0xffffffff); - memory->SetData64(dwarf_offset + 4, 0xf4); - memory->SetData64(dwarf_offset + 0xc, 0xffffffffffffffffULL); - memory->SetData8(dwarf_offset + 0x14, 1); - memory->SetData8(dwarf_offset + 0x15, '\0'); - memory->SetData8(dwarf_offset + 0x16, 0x4); - memory->SetData8(dwarf_offset + 0x17, 0x4); - memory->SetData8(dwarf_offset + 0x18, 0x1); - - // FDE 64 information. - memory->SetData32(dwarf_offset + 0x100, 0xffffffff); - memory->SetData64(dwarf_offset + 0x104, 0xf4); - memory->SetData64(dwarf_offset + 0x10c, 0); - memory->SetData64(dwarf_offset + 0x114, pc); - memory->SetData64(dwarf_offset + 0x11c, size); - } -} - -void PutElfFilesInMemory(MemoryFake* memory, FuzzedDataProvider* data_provider) { - uint8_t elf_file_count = data_provider->ConsumeIntegralInRange(0, kMaxJitElfFiles); - int entry_offset = 0; - int prev_jit_addr = 0; - for (uint8_t i = 0; i < elf_file_count; i++) { - uint64_t offset = data_provider->ConsumeIntegral(); - // Technically the max valid value is ELFCLASSNUM - 1 (2), but - // we want to test values outside of that range. - uint8_t class_type = data_provider->ConsumeIntegral(); - // Same here, EM_NUM is 253, max valid machine type is 252 - uint8_t machine_type = data_provider->ConsumeIntegral(); - uint32_t pc = data_provider->ConsumeIntegral(); - uint32_t size = data_provider->ConsumeIntegral(); - bool sixty_four_bit = data_provider->ConsumeBool(); - bool write_jit = data_provider->ConsumeBool(); - if (sixty_four_bit) { - PutElfInMemory(memory, offset, class_type, machine_type, pc, size); - } else { - PutElfInMemory(memory, offset, class_type, machine_type, pc, size); - } - if (write_jit) { - bool use_pad = data_provider->ConsumeBool(); - // It is possible this will overwrite part of the ELF. - // This provides an interesting test of how malformed ELF - // data is handled. - uint64_t cur_descriptor_addr = 0x11800 + entry_offset; - uint64_t cur_jit_addr = 0x200000 + entry_offset; - uint64_t next_jit_addr = cur_jit_addr + size; - if (sixty_four_bit) { - WriteDescriptor64(memory, 0x11800, cur_jit_addr); - WriteEntry64(memory, cur_jit_addr, prev_jit_addr, next_jit_addr, pc, size); - } else { - // Loop back. Again, this may corrupt data, - // but that will allow for testing edge cases with - // malformed JIT data. - if (cur_jit_addr > UINT32_MAX) { - entry_offset = 0; - cur_jit_addr = 0x200000; - cur_descriptor_addr = 0x11800; - next_jit_addr = cur_jit_addr + size; - } - WriteDescriptor32(memory, cur_descriptor_addr, cur_jit_addr); - if (use_pad) { - WriteEntry32Pad(memory, cur_jit_addr, prev_jit_addr, next_jit_addr, pc, size); - } else { - WriteEntry32Pack(memory, cur_jit_addr, prev_jit_addr, next_jit_addr, pc, size); - } - } - entry_offset += size; - prev_jit_addr = cur_jit_addr; - } - } -} - -std::vector GetStringList(FuzzedDataProvider* data_provider, uint max_str_len, - uint max_strings) { - uint str_count = data_provider->ConsumeIntegralInRange(0, max_strings); - std::vector strings; - for (uint i = 0; i < str_count; i++) { - strings.push_back(data_provider->ConsumeRandomLengthString(max_str_len)); - } - return strings; -} - -std::unique_ptr GetDexFiles(FuzzedDataProvider* data_provider, - std::shared_ptr memory, uint max_library_length, - uint max_libraries) { - std::vector search_libs = - GetStringList(data_provider, max_library_length, max_libraries); - if (search_libs.size() <= 0) { - return std::make_unique(memory); - } - - return std::make_unique(memory, search_libs); -} diff --git a/libunwindstack/tests/fuzz/UnwinderComponentCreator.h b/libunwindstack/tests/fuzz/UnwinderComponentCreator.h deleted file mode 100644 index 09b3379a2..000000000 --- a/libunwindstack/tests/fuzz/UnwinderComponentCreator.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2020 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_UNWINDERCOMPONENTCREATOR_H -#define _LIBUNWINDSTACK_UNWINDERCOMPONENTCREATOR_H - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../ElfFake.h" -#include "../MemoryFake.h" - -#include "fuzzer/FuzzedDataProvider.h" - -using unwindstack::ArchEnum; -using unwindstack::DexFiles; -using unwindstack::Elf; -using unwindstack::ElfFake; -using unwindstack::ElfInterfaceFake; -using unwindstack::FunctionData; -using unwindstack::Maps; -using unwindstack::Memory; -using unwindstack::MemoryFake; -using unwindstack::Regs; -using unwindstack::StepData; - -static constexpr uint8_t kArchCount = 6; - -static constexpr uint8_t kMaxSoNameLen = 150; - -static constexpr uint8_t kMaxFuncNameLen = 50; -static constexpr uint8_t kMaxFuncCount = 100; - -static constexpr uint8_t kMaxJitElfFiles = 20; -static constexpr uint8_t kJitElfPadding = 32; - -static constexpr uint8_t kMaxStepCount = 100; -static constexpr uint8_t kMaxMapEntryCount = 50; -static constexpr uint8_t kMaxBuildIdLen = 100; -static constexpr uint8_t kMaxMapInfoNameLen = 150; - -std::unique_ptr GetRegisters(unwindstack::ArchEnum arch); -std::unique_ptr GetMaps(FuzzedDataProvider* data_provider); -std::vector GetStringList(FuzzedDataProvider* data_provider, uint max_str_len, - uint max_strings); -unwindstack::ArchEnum GetArch(FuzzedDataProvider* data_provider); - -void AddMapInfo(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags, const char* name, - Elf* elf = nullptr); -void PutElfFilesInMemory(MemoryFake* memory, FuzzedDataProvider* data_provider); - -std::unique_ptr GetDexFiles(FuzzedDataProvider* data_provider, - std::shared_ptr memory, - uint max_libraries, uint max_library_length); -#endif // _LIBUNWINDSTACK_UNWINDERCOMPONENTCREATOR_H diff --git a/libunwindstack/tests/fuzz/UnwinderFuzz.cpp b/libunwindstack/tests/fuzz/UnwinderFuzz.cpp deleted file mode 100644 index 160054791..000000000 --- a/libunwindstack/tests/fuzz/UnwinderFuzz.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2020 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 "../MemoryFake.h" -#include "UnwinderComponentCreator.h" -#include "fuzzer/FuzzedDataProvider.h" - -namespace unwindstack { - -static constexpr int kMaxUnwindStringLen = 50; -static constexpr int kMaxUnwindStrings = 50; - -void PerformUnwind(FuzzedDataProvider* data_provider, Unwinder* unwinder) { - // 0 = don't set any values - // 1 = set initial_map_names_to_skip - // 2 = set map_suffixes_to_ignore - // 3 = set both - uint8_t set_values = data_provider->ConsumeIntegral() % 4; - if (set_values == 0) { - unwinder->Unwind(); - } else if (set_values == 1) { - // Only setting initial_map_names_to_skip - std::vector skip_names = - GetStringList(data_provider, kMaxUnwindStringLen, kMaxUnwindStrings); - - unwinder->Unwind(&skip_names, nullptr); - } else if (set_values == 2) { - // Only setting map_suffixes_to_ignore - std::vector ignore_suffixes = - GetStringList(data_provider, kMaxUnwindStringLen, kMaxUnwindStrings); - - unwinder->Unwind(nullptr, &ignore_suffixes); - } else if (set_values == 3) { - // Setting both values - std::vector skip_names = - GetStringList(data_provider, kMaxUnwindStringLen, kMaxUnwindStrings); - std::vector ignore_suffixes = - GetStringList(data_provider, kMaxUnwindStringLen, kMaxUnwindStrings); - - unwinder->Unwind(&skip_names, &ignore_suffixes); - } -} - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - FuzzedDataProvider data_provider(data, size); - - // We need to construct an unwinder. - // Generate the Maps: - std::unique_ptr maps = GetMaps(&data_provider); - - // Generate the Regs: - uint8_t arch_val = data_provider.ConsumeIntegralInRange(1, kArchCount); - ArchEnum arch = static_cast(arch_val); - std::unique_ptr regs = GetRegisters(arch); - - // Generate memory: - std::shared_ptr memory = std::make_shared(); - PutElfFilesInMemory(reinterpret_cast(memory.get()), &data_provider); - - size_t max_frames = data_provider.ConsumeIntegralInRange(0, 5000); - - std::unique_ptr jit_debug_ptr = std::make_unique(memory); - - // Create instance - Unwinder unwinder(max_frames, maps.get(), regs.get(), memory); - unwinder.SetJitDebug(jit_debug_ptr.get()); - unwinder.SetResolveNames(data_provider.ConsumeBool()); - // Call unwind - PerformUnwind(&data_provider, &unwinder); - - // Run some additional logic that changes after unwind - uint64_t pc = data_provider.ConsumeIntegral(); - unwinder.BuildFrameFromPcOnly(pc); - unwinder.ConsumeFrames(); - return 0; -} -} // namespace unwindstack diff --git a/libunwindstack/tools/unwind.cpp b/libunwindstack/tools/unwind.cpp deleted file mode 100644 index ae45f06bc..000000000 --- a/libunwindstack/tools/unwind.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2016 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 - -static bool Attach(pid_t pid) { - if (ptrace(PTRACE_SEIZE, pid, 0, 0) == -1) { - return false; - } - - if (ptrace(PTRACE_INTERRUPT, pid, 0, 0) == -1) { - ptrace(PTRACE_DETACH, pid, 0, 0); - return false; - } - - // Allow at least 1 second to attach properly. - for (size_t i = 0; i < 1000; i++) { - siginfo_t si; - if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) { - return true; - } - usleep(1000); - } - printf("%d: Failed to stop.\n", pid); - return false; -} - -void DoUnwind(pid_t pid) { - unwindstack::Regs* regs = unwindstack::Regs::RemoteGet(pid); - if (regs == nullptr) { - printf("Unable to get remote reg data\n"); - return; - } - - printf("ABI: "); - switch (regs->Arch()) { - case unwindstack::ARCH_ARM: - printf("arm"); - break; - case unwindstack::ARCH_X86: - printf("x86"); - break; - case unwindstack::ARCH_ARM64: - printf("arm64"); - break; - case unwindstack::ARCH_X86_64: - printf("x86_64"); - break; - case unwindstack::ARCH_MIPS: - printf("mips"); - break; - case unwindstack::ARCH_MIPS64: - printf("mips64"); - break; - default: - printf("unknown\n"); - return; - } - printf("\n"); - - unwindstack::UnwinderFromPid unwinder(1024, pid); - unwinder.SetRegs(regs); - unwinder.Unwind(); - - // Print the frames. - for (size_t i = 0; i < unwinder.NumFrames(); i++) { - printf("%s\n", unwinder.FormatFrame(i).c_str()); - } -} - -int main(int argc, char** argv) { - if (argc != 2) { - printf("Usage: unwind \n"); - return 1; - } - - pid_t pid = atoi(argv[1]); - if (!Attach(pid)) { - printf("Failed to attach to pid %d: %s\n", pid, strerror(errno)); - return 1; - } - - DoUnwind(pid); - - ptrace(PTRACE_DETACH, pid, 0, 0); - - return 0; -} diff --git a/libunwindstack/tools/unwind_for_offline.cpp b/libunwindstack/tools/unwind_for_offline.cpp deleted file mode 100644 index c44a121ba..000000000 --- a/libunwindstack/tools/unwind_for_offline.cpp +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright (C) 2017 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. - */ - -#define _GNU_SOURCE 1 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -struct map_info_t { - uint64_t start; - uint64_t end; - uint64_t offset; - uint64_t flags; - std::string name; -}; - -static bool Attach(pid_t pid) { - if (ptrace(PTRACE_SEIZE, pid, 0, 0) == -1) { - return false; - } - - if (ptrace(PTRACE_INTERRUPT, pid, 0, 0) == -1) { - ptrace(PTRACE_DETACH, pid, 0, 0); - return false; - } - - // Allow at least 1 second to attach properly. - for (size_t i = 0; i < 1000; i++) { - siginfo_t si; - if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) { - return true; - } - usleep(1000); - } - printf("%d: Failed to stop.\n", pid); - return false; -} - -bool SaveRegs(unwindstack::Regs* regs) { - std::unique_ptr fp(fopen("regs.txt", "w+"), &fclose); - if (fp == nullptr) { - perror("Failed to create file regs.txt"); - return false; - } - regs->IterateRegisters([&fp](const char* name, uint64_t value) { - fprintf(fp.get(), "%s: %" PRIx64 "\n", name, value); - }); - - return true; -} - -bool SaveStack(pid_t pid, const std::vector>& stacks) { - for (size_t i = 0; i < stacks.size(); i++) { - std::string file_name; - if (stacks.size() != 1) { - file_name = "stack" + std::to_string(i) + ".data"; - } else { - file_name = "stack.data"; - } - - // Do this first, so if it fails, we don't create the file. - uint64_t sp_start = stacks[i].first; - uint64_t sp_end = stacks[i].second; - std::vector buffer(sp_end - sp_start); - auto process_memory = unwindstack::Memory::CreateProcessMemory(pid); - if (!process_memory->Read(sp_start, buffer.data(), buffer.size())) { - printf("Unable to read stack data.\n"); - return false; - } - - printf("Saving the stack 0x%" PRIx64 "-0x%" PRIx64 "\n", sp_start, sp_end); - - std::unique_ptr fp(fopen(file_name.c_str(), "w+"), &fclose); - if (fp == nullptr) { - perror("Failed to create stack.data"); - return false; - } - - size_t bytes = fwrite(&sp_start, 1, sizeof(sp_start), fp.get()); - if (bytes != sizeof(sp_start)) { - printf("Failed to write sp_start data: sizeof(sp_start) %zu, written %zu\n", sizeof(sp_start), - bytes); - return false; - } - - bytes = fwrite(buffer.data(), 1, buffer.size(), fp.get()); - if (bytes != buffer.size()) { - printf("Failed to write all stack data: stack size %zu, written %zu\n", buffer.size(), bytes); - return false; - } - } - - return true; -} - -bool CreateElfFromMemory(std::shared_ptr& memory, map_info_t* info) { - std::string cur_name; - if (info->name.empty()) { - cur_name = android::base::StringPrintf("anonymous_%" PRIx64, info->start); - } else { - cur_name = android::base::StringPrintf("%s_%" PRIx64, basename(info->name.c_str()), info->start); - } - - std::vector buffer(info->end - info->start); - // If this is a mapped in file, it might not be possible to read the entire - // map, so read all that is readable. - size_t bytes = memory->Read(info->start, buffer.data(), buffer.size()); - if (bytes == 0) { - printf("Cannot read data from address %" PRIx64 " length %zu\n", info->start, buffer.size()); - return false; - } - - std::unique_ptr output(fopen(cur_name.c_str(), "w+"), &fclose); - if (output == nullptr) { - perror((std::string("Cannot create ") + cur_name).c_str()); - return false; - } - - size_t bytes_written = fwrite(buffer.data(), 1, bytes, output.get()); - if (bytes_written != bytes) { - printf("Failed to write all data to file: bytes read %zu, written %zu\n", bytes, bytes_written); - return false; - } - - // Replace the name with the new name. - info->name = cur_name; - - return true; -} - -bool CopyElfFromFile(map_info_t* info, bool* file_copied) { - std::string cur_name = basename(info->name.c_str()); - if (*file_copied) { - info->name = cur_name; - return true; - } - - std::unique_ptr fp(fopen(info->name.c_str(), "r"), &fclose); - if (fp == nullptr) { - perror((std::string("Cannot open ") + info->name).c_str()); - return false; - } - - std::unique_ptr output(fopen(cur_name.c_str(), "w+"), &fclose); - if (output == nullptr) { - perror((std::string("Cannot create file " + cur_name)).c_str()); - return false; - } - std::vector buffer(10000); - size_t bytes; - while ((bytes = fread(buffer.data(), 1, buffer.size(), fp.get())) > 0) { - size_t bytes_written = fwrite(buffer.data(), 1, bytes, output.get()); - if (bytes_written != bytes) { - printf("Bytes written doesn't match bytes read: read %zu, written %zu\n", bytes, - bytes_written); - return false; - } - } - - // Replace the name with the new name. - info->name = cur_name; - - return true; -} - -map_info_t* FillInAndGetMapInfo(std::unordered_map& maps_by_start, - unwindstack::MapInfo* map_info) { - auto info = &maps_by_start[map_info->start]; - info->start = map_info->start; - info->end = map_info->end; - info->offset = map_info->offset; - info->name = map_info->name; - info->flags = map_info->flags; - - return info; -} - -void SaveMapInformation(std::shared_ptr& process_memory, map_info_t* info, - bool* file_copied) { - if (CopyElfFromFile(info, file_copied)) { - return; - } - *file_copied = false; - - // Try to create the elf from memory, this will handle cases where - // the data only exists in memory such as vdso data on x86. - if (CreateElfFromMemory(process_memory, info)) { - return; - } - - printf("Cannot save memory or file for map "); - if (!info->name.empty()) { - printf("%s\n", info->name.c_str()); - } else { - printf("anonymous:%" PRIx64 "\n", info->start); - } -} - -int SaveData(pid_t pid) { - unwindstack::Regs* regs = unwindstack::Regs::RemoteGet(pid); - if (regs == nullptr) { - printf("Unable to get remote reg data.\n"); - return 1; - } - - // Save the current state of the registers. - if (!SaveRegs(regs)) { - return 1; - } - - // Do an unwind so we know how much of the stack to save, and what - // elf files are involved. - unwindstack::UnwinderFromPid unwinder(1024, pid); - unwinder.SetRegs(regs); - uint64_t sp = regs->sp(); - unwinder.Unwind(); - - std::unordered_map maps_by_start; - std::vector> stacks; - unwindstack::Maps* maps = unwinder.GetMaps(); - uint64_t sp_map_start = 0; - unwindstack::MapInfo* map_info = maps->Find(sp); - if (map_info != nullptr) { - stacks.emplace_back(std::make_pair(sp, map_info->end)); - sp_map_start = map_info->start; - } - - for (const auto& frame : unwinder.frames()) { - map_info = maps->Find(frame.sp); - if (map_info != nullptr && sp_map_start != map_info->start) { - stacks.emplace_back(std::make_pair(frame.sp, map_info->end)); - sp_map_start = map_info->start; - } - - if (maps_by_start.count(frame.map_start) == 0) { - map_info = maps->Find(frame.map_start); - if (map_info == nullptr) { - continue; - } - - auto info = FillInAndGetMapInfo(maps_by_start, map_info); - bool file_copied = false; - SaveMapInformation(unwinder.GetProcessMemory(), info, &file_copied); - - // If you are using a a linker that creates two maps (one read-only, one - // read-executable), it's necessary to capture the previous map - // information if needed. - unwindstack::MapInfo* prev_map = map_info->prev_map; - if (prev_map != nullptr && map_info->offset != 0 && prev_map->offset == 0 && - prev_map->flags == PROT_READ && map_info->name == prev_map->name && - maps_by_start.count(prev_map->start) == 0) { - info = FillInAndGetMapInfo(maps_by_start, prev_map); - SaveMapInformation(unwinder.GetProcessMemory(), info, &file_copied); - } - } - } - - for (size_t i = 0; i < unwinder.NumFrames(); i++) { - printf("%s\n", unwinder.FormatFrame(i).c_str()); - } - - if (!SaveStack(pid, stacks)) { - return 1; - } - - std::vector> sorted_maps(maps_by_start.begin(), - maps_by_start.end()); - std::sort(sorted_maps.begin(), sorted_maps.end(), - [](auto& a, auto& b) { return a.first < b.first; }); - - std::unique_ptr fp(fopen("maps.txt", "w+"), &fclose); - if (fp == nullptr) { - perror("Failed to create maps.txt"); - return false; - } - - for (auto& element : sorted_maps) { - char perms[5] = {"---p"}; - map_info_t& map = element.second; - if (map.flags & PROT_READ) { - perms[0] = 'r'; - } - if (map.flags & PROT_WRITE) { - perms[1] = 'w'; - } - if (map.flags & PROT_EXEC) { - perms[2] = 'x'; - } - fprintf(fp.get(), "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " 00:00 0", map.start, map.end, perms, - map.offset); - if (!map.name.empty()) { - fprintf(fp.get(), " %s", map.name.c_str()); - } - fprintf(fp.get(), "\n"); - } - - return 0; -} - -int main(int argc, char** argv) { - if (argc != 2) { - printf("Usage: unwind_for_offline \n"); - return 1; - } - - pid_t pid = atoi(argv[1]); - if (!Attach(pid)) { - printf("Failed to attach to pid %d: %s\n", pid, strerror(errno)); - return 1; - } - - int return_code = SaveData(pid); - - ptrace(PTRACE_DETACH, pid, 0, 0); - - return return_code; -} diff --git a/libunwindstack/tools/unwind_info.cpp b/libunwindstack/tools/unwind_info.cpp deleted file mode 100644 index a5002f226..000000000 --- a/libunwindstack/tools/unwind_info.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2016 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 "ArmExidx.h" -#include "ElfInterfaceArm.h" - -namespace unwindstack { - -void DumpArm(Elf* elf, ElfInterfaceArm* interface) { - if (interface == nullptr) { - printf("No ARM Unwind Information.\n\n"); - return; - } - - printf("ARM Unwind Information:\n"); - uint64_t load_bias = elf->GetLoadBias(); - for (const auto& entry : interface->pt_loads()) { - printf(" PC Range 0x%" PRIx64 " - 0x%" PRIx64 "\n", entry.second.offset + load_bias, - entry.second.offset + entry.second.table_size + load_bias); - for (auto pc : *interface) { - std::string name; - printf(" PC 0x%" PRIx64, pc + load_bias); - uint64_t func_offset; - if (elf->GetFunctionName(pc + load_bias, &name, &func_offset) && !name.empty()) { - printf(" <%s>", name.c_str()); - } - printf("\n"); - uint64_t entry; - if (!interface->FindEntry(pc, &entry)) { - printf(" Cannot find entry for address.\n"); - continue; - } - ArmExidx arm(nullptr, interface->memory(), nullptr); - arm.set_log(ARM_LOG_FULL); - arm.set_log_skip_execution(true); - arm.set_log_indent(2); - if (!arm.ExtractEntryData(entry)) { - if (arm.status() != ARM_STATUS_NO_UNWIND) { - printf(" Error trying to extract data.\n"); - } - continue; - } - if (arm.data()->size() > 0) { - if (!arm.Eval() && arm.status() != ARM_STATUS_NO_UNWIND) { - printf(" Error trying to evaluate dwarf data.\n"); - } - } - } - } - printf("\n"); -} - -void DumpDwarfSection(Elf* elf, DwarfSection* section, uint64_t) { - for (const DwarfFde* fde : *section) { - // Sometimes there are entries that have empty length, skip those since - // they don't contain any interesting information. - if (fde == nullptr || fde->pc_start == fde->pc_end) { - continue; - } - printf("\n PC 0x%" PRIx64 "-0x%" PRIx64, fde->pc_start, fde->pc_end); - std::string name; - uint64_t func_offset; - if (elf->GetFunctionName(fde->pc_start, &name, &func_offset) && !name.empty()) { - printf(" <%s>", name.c_str()); - } - printf("\n"); - if (!section->Log(2, UINT64_MAX, fde, elf->arch())) { - printf("Failed to process cfa information for entry at 0x%" PRIx64 "\n", fde->pc_start); - } - } -} - -int GetElfInfo(const char* file, uint64_t offset) { - // Send all log messages to stdout. - log_to_stdout(true); - - Elf elf(Memory::CreateFileMemory(file, offset).release()); - if (!elf.Init() || !elf.valid()) { - printf("%s is not a valid elf file.\n", file); - return 1; - } - - std::string soname(elf.GetSoname()); - if (!soname.empty()) { - printf("Soname: %s\n", soname.c_str()); - } - - std::string build_id = elf.GetBuildID(); - if (!build_id.empty()) { - printf("Build ID: "); - for (size_t i = 0; i < build_id.size(); ++i) { - printf("%02hhx", build_id[i]); - } - printf("\n"); - } - - ElfInterface* interface = elf.interface(); - if (elf.machine_type() == EM_ARM) { - DumpArm(&elf, reinterpret_cast(interface)); - printf("\n"); - } - - if (interface->eh_frame() != nullptr) { - printf("eh_frame information:\n"); - DumpDwarfSection(&elf, interface->eh_frame(), elf.GetLoadBias()); - printf("\n"); - } else { - printf("\nno eh_frame information\n"); - } - - if (interface->debug_frame() != nullptr) { - printf("\ndebug_frame information:\n"); - DumpDwarfSection(&elf, interface->debug_frame(), elf.GetLoadBias()); - printf("\n"); - } else { - printf("\nno debug_frame information\n"); - } - - // If there is a gnu_debugdata interface, dump the information for that. - ElfInterface* gnu_debugdata_interface = elf.gnu_debugdata_interface(); - if (gnu_debugdata_interface != nullptr) { - if (gnu_debugdata_interface->eh_frame() != nullptr) { - printf("\ngnu_debugdata (eh_frame):\n"); - DumpDwarfSection(&elf, gnu_debugdata_interface->eh_frame(), 0); - printf("\n"); - } - if (gnu_debugdata_interface->debug_frame() != nullptr) { - printf("\ngnu_debugdata (debug_frame):\n"); - DumpDwarfSection(&elf, gnu_debugdata_interface->debug_frame(), 0); - printf("\n"); - } - } else { - printf("\nno valid gnu_debugdata information\n"); - } - - return 0; -} - -} // namespace unwindstack - -int main(int argc, char** argv) { - if (argc != 2 && argc != 3) { - printf("Usage: unwind_info ELF_FILE [OFFSET]\n"); - printf(" ELF_FILE\n"); - printf(" The path to an elf file.\n"); - printf(" OFFSET\n"); - printf(" Use the offset into the ELF file as the beginning of the elf.\n"); - return 1; - } - - struct stat st; - if (stat(argv[1], &st) == -1) { - printf("Cannot stat %s: %s\n", argv[1], strerror(errno)); - return 1; - } - if (!S_ISREG(st.st_mode)) { - printf("%s is not a regular file.\n", argv[1]); - return 1; - } - - uint64_t offset = 0; - if (argc == 3) { - char* end; - offset = strtoull(argv[2], &end, 16); - if (*end != '\0') { - printf("Malformed OFFSET value: %s\n", argv[2]); - return 1; - } - } - - return unwindstack::GetElfInfo(argv[1], offset); -} diff --git a/libunwindstack/tools/unwind_reg_info.cpp b/libunwindstack/tools/unwind_reg_info.cpp deleted file mode 100644 index 68e02735d..000000000 --- a/libunwindstack/tools/unwind_reg_info.cpp +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright (C) 2018 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 "ArmExidx.h" -#include "DwarfOp.h" -#include "ElfInterfaceArm.h" - -namespace unwindstack { - -void PrintSignedValue(int64_t value) { - if (value < 0) { - printf("- %" PRId64, -value); - } else if (value > 0) { - printf("+ %" PRId64, value); - } -} - -void PrintExpression(Memory* memory, uint8_t class_type, uint64_t end, uint64_t length) { - std::vector lines; - DwarfMemory dwarf_memory(memory); - if (class_type == ELFCLASS32) { - DwarfOp op(&dwarf_memory, nullptr); - op.GetLogInfo(end - length, end, &lines); - } else { - DwarfOp op(&dwarf_memory, nullptr); - op.GetLogInfo(end - length, end, &lines); - } - for (auto& line : lines) { - printf(" %s\n", line.c_str()); - } -} - -void PrintRegInformation(DwarfSection* section, Memory* memory, uint64_t pc, uint8_t class_type, - ArchEnum arch) { - const DwarfFde* fde = section->GetFdeFromPc(pc); - if (fde == nullptr) { - printf(" No fde found.\n"); - return; - } - - dwarf_loc_regs_t regs; - if (!section->GetCfaLocationInfo(pc, fde, ®s, arch)) { - printf(" Cannot get location information.\n"); - return; - } - - std::vector> loc_regs; - for (auto& loc : regs) { - loc_regs.push_back(loc); - } - std::sort(loc_regs.begin(), loc_regs.end(), [](auto a, auto b) { - if (a.first == CFA_REG) { - return true; - } else if (b.first == CFA_REG) { - return false; - } - return a.first < b.first; - }); - - for (auto& entry : loc_regs) { - const DwarfLocation* loc = &entry.second; - if (entry.first == CFA_REG) { - printf(" cfa = "); - } else { - printf(" r%d = ", entry.first); - } - switch (loc->type) { - case DWARF_LOCATION_OFFSET: - printf("[cfa "); - PrintSignedValue(loc->values[0]); - printf("]\n"); - break; - - case DWARF_LOCATION_VAL_OFFSET: - printf("cfa "); - PrintSignedValue(loc->values[0]); - printf("\n"); - break; - - case DWARF_LOCATION_REGISTER: - printf("r%" PRId64 " ", loc->values[0]); - PrintSignedValue(loc->values[1]); - printf("\n"); - break; - - case DWARF_LOCATION_EXPRESSION: { - printf("EXPRESSION\n"); - PrintExpression(memory, class_type, loc->values[1], loc->values[0]); - break; - } - - case DWARF_LOCATION_VAL_EXPRESSION: { - printf("VAL EXPRESSION\n"); - PrintExpression(memory, class_type, loc->values[1], loc->values[0]); - break; - } - - case DWARF_LOCATION_PSEUDO_REGISTER: { - printf("%" PRId64 " (pseudo)\n", loc->values[0]); - break; - } - - case DWARF_LOCATION_UNDEFINED: - printf("undefine\n"); - break; - - case DWARF_LOCATION_INVALID: - printf("INVALID\n"); - break; - } - } -} - -void PrintArmRegInformation(ElfInterfaceArm* interface, uint64_t pc) { - printf("\nArm exidx:\n"); - uint64_t entry_offset; - if (!interface->FindEntry(pc, &entry_offset)) { - return; - } - - ArmExidx arm(nullptr, interface->memory(), nullptr); - - log_to_stdout(true); - arm.set_log(ARM_LOG_BY_REG); - arm.set_log_skip_execution(true); - arm.set_log_indent(1); - if (!arm.ExtractEntryData(entry_offset)) { - if (arm.status() != ARM_STATUS_NO_UNWIND) { - printf(" Error trying to extract data.\n"); - } - return; - } - if (arm.data()->size() != 0 && arm.Eval()) { - arm.LogByReg(); - } else { - printf(" Error tring to evaluate exidx data.\n"); - } -} - -int GetInfo(const char* file, uint64_t offset, uint64_t pc) { - Elf elf(Memory::CreateFileMemory(file, offset).release()); - if (!elf.Init() || !elf.valid()) { - printf("%s is not a valid elf file.\n", file); - return 1; - } - - ElfInterface* interface = elf.interface(); - uint64_t load_bias = elf.GetLoadBias(); - if (pc < load_bias) { - printf("PC is less than load bias.\n"); - return 1; - } - - std::string soname(elf.GetSoname()); - if (!soname.empty()) { - printf("Soname: %s\n\n", soname.c_str()); - } - - printf("PC 0x%" PRIx64, pc); - std::string function_name; - uint64_t function_offset; - if (elf.GetFunctionName(pc, &function_name, &function_offset)) { - printf(" (%s)", function_name.c_str()); - } - printf(":\n"); - - if (elf.machine_type() == EM_ARM) { - PrintArmRegInformation(reinterpret_cast(interface), pc - load_bias); - } - - DwarfSection* section = interface->eh_frame(); - if (section != nullptr) { - printf("\neh_frame:\n"); - PrintRegInformation(section, elf.memory(), pc, elf.class_type(), elf.arch()); - } else { - printf("\nno eh_frame information\n"); - } - - section = interface->debug_frame(); - if (section != nullptr) { - printf("\ndebug_frame:\n"); - PrintRegInformation(section, elf.memory(), pc, elf.class_type(), elf.arch()); - printf("\n"); - } else { - printf("\nno debug_frame information\n"); - } - - // If there is a gnu_debugdata interface, dump the information for that. - ElfInterface* gnu_debugdata_interface = elf.gnu_debugdata_interface(); - if (gnu_debugdata_interface != nullptr) { - section = gnu_debugdata_interface->eh_frame(); - if (section != nullptr) { - printf("\ngnu_debugdata (eh_frame):\n"); - PrintRegInformation(section, gnu_debugdata_interface->memory(), pc, elf.class_type(), - elf.arch()); - printf("\n"); - } else { - printf("\nno gnu_debugdata (eh_frame)\n"); - } - - section = gnu_debugdata_interface->debug_frame(); - if (section != nullptr) { - printf("\ngnu_debugdata (debug_frame):\n"); - PrintRegInformation(section, gnu_debugdata_interface->memory(), pc, elf.class_type(), - elf.arch()); - printf("\n"); - } else { - printf("\nno gnu_debugdata (debug_frame)\n"); - } - } else { - printf("\nno valid gnu_debugdata information\n"); - } - - return 0; -} - -} // namespace unwindstack - -int main(int argc, char** argv) { - if (argc != 3 && argc != 4) { - printf("Usage: unwind_reg_info ELF_FILE PC [OFFSET]\n"); - printf(" ELF_FILE\n"); - printf(" The path to an elf file.\n"); - printf(" PC\n"); - printf(" The pc for which the register information should be obtained.\n"); - printf(" OFFSET\n"); - printf(" Use the offset into the ELF file as the beginning of the elf.\n"); - return 1; - } - - struct stat st; - if (stat(argv[1], &st) == -1) { - printf("Cannot stat %s: %s\n", argv[1], strerror(errno)); - return 1; - } - if (!S_ISREG(st.st_mode)) { - printf("%s is not a regular file.\n", argv[1]); - return 1; - } - - uint64_t pc = 0; - char* end; - pc = strtoull(argv[2], &end, 16); - if (*end != '\0') { - printf("Malformed OFFSET value: %s\n", argv[2]); - return 1; - } - - uint64_t offset = 0; - if (argc == 4) { - char* end; - offset = strtoull(argv[3], &end, 16); - if (*end != '\0') { - printf("Malformed OFFSET value: %s\n", argv[3]); - return 1; - } - } - - return unwindstack::GetInfo(argv[1], offset, pc); -} diff --git a/libunwindstack/tools/unwind_symbols.cpp b/libunwindstack/tools/unwind_symbols.cpp deleted file mode 100644 index 8df228412..000000000 --- a/libunwindstack/tools/unwind_symbols.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2016 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 - -int main(int argc, char** argv) { - if (argc != 2 && argc != 3) { - printf("Usage: unwind_symbols []\n"); - printf(" Dump all function symbols in ELF_FILE. If FUNC_ADDRESS is\n"); - printf(" specified, then get the function at that address.\n"); - printf(" FUNC_ADDRESS must be a hex number.\n"); - return 1; - } - - struct stat st; - if (stat(argv[1], &st) == -1) { - printf("Cannot stat %s: %s\n", argv[1], strerror(errno)); - return 1; - } - if (!S_ISREG(st.st_mode)) { - printf("%s is not a regular file.\n", argv[1]); - return 1; - } - - uint64_t func_addr; - if (argc == 3) { - char* name; - func_addr = strtoull(argv[2], &name, 16); - if (*name != '\0') { - printf("%s is not a hex number.\n", argv[2]); - return 1; - } - } - - // Send all log messages to stdout. - unwindstack::log_to_stdout(true); - - 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; - } - - std::string soname(elf.GetSoname()); - if (!soname.empty()) { - printf("Soname: %s\n\n", soname.c_str()); - } - - switch (elf.machine_type()) { - case EM_ARM: - printf("ABI: arm\n"); - break; - case EM_AARCH64: - printf("ABI: arm64\n"); - break; - case EM_386: - printf("ABI: x86\n"); - break; - case EM_X86_64: - printf("ABI: x86_64\n"); - break; - default: - printf("ABI: unknown\n"); - return 1; - } - - std::string name; - if (argc == 3) { - std::string cur_name; - uint64_t func_offset; - if (!elf.GetFunctionName(func_addr, &cur_name, &func_offset)) { - printf("No known function at 0x%" PRIx64 "\n", func_addr); - return 1; - } - printf("<0x%" PRIx64 ">", func_addr - func_offset); - if (func_offset != 0) { - printf("+%" PRId64, func_offset); - } - printf(": %s\n", cur_name.c_str()); - return 0; - } - - // This is a crude way to get the symbols in order. - for (const auto& entry : elf.interface()->pt_loads()) { - uint64_t start = entry.second.offset; - uint64_t end = entry.second.table_size; - for (uint64_t addr = start; addr < end; addr += 4) { - std::string cur_name; - uint64_t func_offset; - if (elf.GetFunctionName(addr, &cur_name, &func_offset)) { - if (cur_name != name) { - printf("<0x%" PRIx64 "> Function: %s\n", addr - func_offset, cur_name.c_str()); - } - name = cur_name; - } - } - } - - return 0; -}