Merge "Document property expansion."
diff --git a/base/Android.bp b/base/Android.bp
index acbc6b7..5d70d47 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -15,7 +15,7 @@
//
cc_defaults {
- name: "libbase_defaults",
+ name: "libbase_cflags_defaults",
cflags: [
"-Wall",
"-Werror",
@@ -39,15 +39,9 @@
},
}
-cc_library {
- name: "libbase",
- defaults: ["libbase_defaults"],
- vendor_available: true,
- host_supported: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
+cc_defaults {
+ name: "libbase_defaults",
+ defaults: ["libbase_cflags_defaults"],
srcs: [
"chrono_utils.cpp",
"file.cpp",
@@ -59,11 +53,6 @@
"test_utils.cpp",
],
- header_libs: [
- "libbase_headers",
- ],
- export_header_lib_headers: ["libbase_headers"],
-
shared_libs: ["liblog"],
target: {
android: {
@@ -100,11 +89,34 @@
},
}
+cc_library {
+ name: "libbase",
+ defaults: ["libbase_defaults"],
+ vendor_available: true,
+ host_supported: true,
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ },
+ header_libs: [
+ "libbase_headers",
+ ],
+ export_header_lib_headers: ["libbase_headers"],
+}
+
+cc_library_static {
+ name: "libbase_ndk",
+ defaults: ["libbase_defaults"],
+ sdk_version: "current",
+ stl: "c++_static",
+ export_include_dirs: ["include"],
+}
+
// Tests
// ------------------------------------------------------------------------------
cc_test {
name: "libbase_test",
- defaults: ["libbase_defaults"],
+ defaults: ["libbase_cflags_defaults"],
host_supported: true,
srcs: [
"endian_test.cpp",
diff --git a/base/logging.cpp b/base/logging.cpp
index 0f2012a..1f7bc2a 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -45,7 +45,7 @@
// Headers for LogMessage::LogLine.
#ifdef __ANDROID__
-#include <log/log.h>
+#include <android/log.h>
#include <android/set_abort_message.h>
#else
#include <sys/types.h>
diff --git a/base/properties.cpp b/base/properties.cpp
index ca8e96f..6cf43f9 100644
--- a/base/properties.cpp
+++ b/base/properties.cpp
@@ -28,8 +28,6 @@
#include <android-base/parseint.h>
-using namespace std::chrono_literals;
-
namespace android {
namespace base {
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index f8b4bad..397ff2f 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -20,6 +20,7 @@
#include <sys/capability.h>
#include <sys/prctl.h>
#include <sys/ptrace.h>
+#include <sys/resource.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
@@ -570,7 +571,7 @@
static const char* const kDebuggerdSeccompPolicy =
"/system/etc/seccomp_policy/crash_dump." ABI_STRING ".policy";
-pid_t seccomp_fork() {
+static pid_t seccomp_fork_impl(void (*prejail)()) {
unique_fd policy_fd(open(kDebuggerdSeccompPolicy, O_RDONLY | O_CLOEXEC));
if (policy_fd == -1) {
LOG(FATAL) << "failed to open policy " << kDebuggerdSeccompPolicy;
@@ -607,10 +608,18 @@
continue;
}
+ if (prejail) {
+ prejail();
+ }
+
minijail_enter(jail.get());
return result;
}
+static pid_t seccomp_fork() {
+ return seccomp_fork_impl(nullptr);
+}
+
TEST_F(CrasherTest, seccomp_crash) {
int intercept_result;
unique_fd output_fd;
@@ -628,6 +637,46 @@
ASSERT_BACKTRACE_FRAME(result, "abort");
}
+static pid_t seccomp_fork_rlimit() {
+ return seccomp_fork_impl([]() {
+ struct rlimit rlim = {
+ .rlim_cur = 512 * 1024 * 1024,
+ .rlim_max = 512 * 1024 * 1024,
+ };
+
+ if (setrlimit(RLIMIT_AS, &rlim) != 0) {
+ raise(SIGINT);
+ }
+ });
+}
+
+TEST_F(CrasherTest, seccomp_crash_oom) {
+ int intercept_result;
+ unique_fd output_fd;
+
+ StartProcess(
+ []() {
+ std::vector<void*> vec;
+ for (int i = 0; i < 512; ++i) {
+ char* buf = static_cast<char*>(malloc(1024 * 1024));
+ if (!buf) {
+ abort();
+ }
+ memset(buf, 0xff, 1024 * 1024);
+ vec.push_back(buf);
+ }
+ },
+ &seccomp_fork_rlimit);
+
+ StartIntercept(&output_fd);
+ FinishCrasher();
+ AssertDeath(SIGABRT);
+ FinishIntercept(&intercept_result);
+ ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+ // We can't actually generate a backtrace, just make sure that the process terminates.
+}
+
__attribute__((noinline)) extern "C" bool raise_debugger_signal(DebuggerdDumpType dump_type) {
siginfo_t siginfo;
siginfo.si_code = SI_QUEUE;
diff --git a/debuggerd/handler/debuggerd_fallback.cpp b/debuggerd/handler/debuggerd_fallback.cpp
index 364fca5..dea2e17 100644
--- a/debuggerd/handler/debuggerd_fallback.cpp
+++ b/debuggerd/handler/debuggerd_fallback.cpp
@@ -37,6 +37,7 @@
#include <atomic>
#include <memory>
+#include <mutex>
#include <android-base/file.h>
#include <android-base/unique_fd.h>
@@ -298,11 +299,13 @@
static void crash_handler(siginfo_t* info, ucontext_t* ucontext, void* abort_message) {
// Only allow one thread to handle a crash at a time (this can happen multiple times without
// exit, since tombstones can be requested without a real crash happening.)
- static pthread_mutex_t crash_mutex = PTHREAD_MUTEX_INITIALIZER;
- int ret = pthread_mutex_lock(&crash_mutex);
- if (ret != 0) {
- async_safe_format_log(ANDROID_LOG_INFO, "libc", "pthread_mutex_lock failed: %s", strerror(ret));
- return;
+ static std::recursive_mutex crash_mutex;
+ static int lock_count;
+
+ crash_mutex.lock();
+ if (lock_count++ > 0) {
+ async_safe_format_log(ANDROID_LOG_ERROR, "libc", "recursed signal handler call, exiting");
+ _exit(1);
}
unique_fd tombstone_socket, output_fd;
@@ -313,7 +316,8 @@
tombstoned_notify_completion(tombstone_socket.get());
}
- pthread_mutex_unlock(&crash_mutex);
+ --lock_count;
+ crash_mutex.unlock();
}
extern "C" void debuggerd_fallback_handler(siginfo_t* info, ucontext_t* ucontext,
diff --git a/init/init.cpp b/init/init.cpp
index 7e4eaa8..efb9c1d 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -35,6 +35,7 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <cutils/android_reboot.h>
#include <keyutils.h>
@@ -63,7 +64,10 @@
using android::base::boot_clock;
using android::base::GetProperty;
+using android::base::ReadFileToString;
+using android::base::StringPrintf;
using android::base::Timer;
+using android::base::Trim;
namespace android {
namespace init {
@@ -246,7 +250,7 @@
return control_message_functions;
}
-void handle_control_message(const std::string& msg, const std::string& name) {
+void HandleControlMessage(const std::string& msg, const std::string& name, pid_t pid) {
const auto& map = get_control_message_map();
const auto it = map.find(msg);
@@ -255,6 +259,18 @@
return;
}
+ std::string cmdline_path = StringPrintf("proc/%d/cmdline", pid);
+ std::string process_cmdline;
+ if (ReadFileToString(cmdline_path, &process_cmdline)) {
+ std::replace(process_cmdline.begin(), process_cmdline.end(), '\0', ' ');
+ process_cmdline = Trim(process_cmdline);
+ } else {
+ process_cmdline = "unknown process";
+ }
+
+ LOG(INFO) << "Received control message '" << msg << "' for '" << name << "' from pid: " << pid
+ << " (" << process_cmdline << ")";
+
const ControlMessageFunction& function = it->second;
if (function.target == ControlTarget::SERVICE) {
diff --git a/init/init.h b/init/init.h
index ecce5d7..d4a0e96 100644
--- a/init/init.h
+++ b/init/init.h
@@ -17,6 +17,8 @@
#ifndef _INIT_INIT_H
#define _INIT_INIT_H
+#include <sys/types.h>
+
#include <string>
#include <vector>
@@ -36,7 +38,7 @@
Parser CreateParser(ActionManager& action_manager, ServiceList& service_list);
-void handle_control_message(const std::string& msg, const std::string& arg);
+void HandleControlMessage(const std::string& msg, const std::string& arg, pid_t pid);
void property_changed(const std::string& name, const std::string& value);
diff --git a/init/property_service.cpp b/init/property_service.cpp
index ecd5baa..0cf6184 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -436,7 +436,7 @@
return PROP_ERROR_HANDLE_CONTROL_MESSAGE;
}
- handle_control_message(name.c_str() + 4, value.c_str());
+ HandleControlMessage(name.c_str() + 4, value, cr.pid);
return PROP_SUCCESS;
}
diff --git a/init/property_service_test.cpp b/init/property_service_test.cpp
index 95dd340..c038aff 100644
--- a/init/property_service_test.cpp
+++ b/init/property_service_test.cpp
@@ -45,11 +45,13 @@
// ...so we can send it a malformed request.
uint32_t msg = PROP_MSG_SETPROP2;
uint32_t size = 0xffffffff;
- uint32_t data = 0xdeadbeef;
ASSERT_EQ(static_cast<ssize_t>(sizeof(msg)), send(fd, &msg, sizeof(msg), 0));
ASSERT_EQ(static_cast<ssize_t>(sizeof(size)), send(fd, &size, sizeof(size), 0));
- ASSERT_EQ(static_cast<ssize_t>(sizeof(data)), send(fd, &data, sizeof(data), 0));
+ uint32_t result = 0;
+ ASSERT_EQ(static_cast<ssize_t>(sizeof(result)),
+ TEMP_FAILURE_RETRY(recv(fd, &result, sizeof(result), MSG_WAITALL)));
+ EXPECT_EQ(static_cast<uint32_t>(PROP_ERROR_READ_DATA), result);
ASSERT_EQ(0, close(fd));
}
diff --git a/libbacktrace/UnwindStack.cpp b/libbacktrace/UnwindStack.cpp
index 7e2e6d0..711a12a 100644
--- a/libbacktrace/UnwindStack.cpp
+++ b/libbacktrace/UnwindStack.cpp
@@ -52,6 +52,7 @@
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());
if (stack_map->GetJitDebug() != nullptr) {
unwinder.SetJitDebug(stack_map->GetJitDebug(), regs->Arch());
}
@@ -127,6 +128,22 @@
return true;
}
+bool Backtrace::UnwindOffline(unwindstack::Regs* regs, BacktraceMap* back_map,
+ const backtrace_stackinfo_t& stack,
+ std::vector<backtrace_frame_data_t>* frames,
+ BacktraceUnwindError* error) {
+ UnwindStackOfflineMap* offline_map = reinterpret_cast<UnwindStackOfflineMap*>(back_map);
+ // Create the process memory from the stack data since this will almost
+ // always be different each unwind.
+ if (!offline_map->CreateProcessMemory(stack)) {
+ if (error != nullptr) {
+ error->error_code = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
+ }
+ return false;
+ }
+ return Backtrace::Unwind(regs, back_map, frames, 0U, nullptr, error);
+}
+
UnwindStackCurrent::UnwindStackCurrent(pid_t pid, pid_t tid, BacktraceMap* map)
: BacktraceCurrent(pid, tid, map) {}
@@ -220,12 +237,12 @@
Backtrace* Backtrace::CreateOffline(ArchEnum arch, pid_t pid, pid_t tid,
const std::vector<backtrace_map_t>& maps,
const backtrace_stackinfo_t& stack) {
- BacktraceMap* map = BacktraceMap::CreateOffline(pid, maps, stack);
- if (map == nullptr) {
+ std::unique_ptr<UnwindStackOfflineMap> map(
+ reinterpret_cast<UnwindStackOfflineMap*>(BacktraceMap::CreateOffline(pid, maps)));
+ if (map.get() == nullptr || !map->CreateProcessMemory(stack)) {
return nullptr;
}
-
- return new UnwindStackOffline(arch, pid, tid, map, false);
+ return new UnwindStackOffline(arch, pid, tid, map.release(), false);
}
Backtrace* Backtrace::CreateOffline(ArchEnum arch, pid_t pid, pid_t tid, BacktraceMap* map) {
diff --git a/libbacktrace/UnwindStackMap.cpp b/libbacktrace/UnwindStackMap.cpp
index 6dcc621..9c6fed4 100644
--- a/libbacktrace/UnwindStackMap.cpp
+++ b/libbacktrace/UnwindStackMap.cpp
@@ -127,12 +127,7 @@
return false;
}
-bool UnwindStackOfflineMap::Build(const std::vector<backtrace_map_t>& backtrace_maps,
- const backtrace_stackinfo_t& stack) {
- if (stack.start >= stack.end) {
- return false;
- }
-
+bool UnwindStackOfflineMap::Build(const std::vector<backtrace_map_t>& backtrace_maps) {
for (const backtrace_map_t& map : backtrace_maps) {
maps_.push_back(map);
}
@@ -145,6 +140,13 @@
for (const backtrace_map_t& map : maps_) {
maps->Add(map.start, map.end, map.offset, map.flags, map.name, map.load_bias);
}
+ return true;
+}
+
+bool UnwindStackOfflineMap::CreateProcessMemory(const backtrace_stackinfo_t& stack) {
+ if (stack.start >= stack.end) {
+ return false;
+ }
// Create the process memory from the stack data.
uint64_t size = stack.end - stack.start;
@@ -154,7 +156,6 @@
std::shared_ptr<unwindstack::Memory> shared_memory(memory);
process_memory_.reset(new unwindstack::MemoryRange(shared_memory, 0, size, stack.start));
-
return true;
}
@@ -182,10 +183,9 @@
//-------------------------------------------------------------------------
// BacktraceMap create offline function.
//-------------------------------------------------------------------------
-BacktraceMap* BacktraceMap::CreateOffline(pid_t pid, const std::vector<backtrace_map_t>& maps,
- const backtrace_stackinfo_t& stack) {
+BacktraceMap* BacktraceMap::CreateOffline(pid_t pid, const std::vector<backtrace_map_t>& maps) {
UnwindStackOfflineMap* map = new UnwindStackOfflineMap(pid);
- if (!map->Build(maps, stack)) {
+ if (!map->Build(maps)) {
delete map;
return nullptr;
}
diff --git a/libbacktrace/UnwindStackMap.h b/libbacktrace/UnwindStackMap.h
index 94cbfb2..ec0d9c1 100644
--- a/libbacktrace/UnwindStackMap.h
+++ b/libbacktrace/UnwindStackMap.h
@@ -76,7 +76,9 @@
bool Build() override;
- bool Build(const std::vector<backtrace_map_t>& maps, const backtrace_stackinfo_t& stack);
+ bool Build(const std::vector<backtrace_map_t>& maps);
+
+ bool CreateProcessMemory(const backtrace_stackinfo_t& stack);
};
#endif // _LIBBACKTRACE_UNWINDSTACK_MAP_H
diff --git a/libbacktrace/include/backtrace/Backtrace.h b/libbacktrace/include/backtrace/Backtrace.h
index 7a37015..a088207 100644
--- a/libbacktrace/include/backtrace/Backtrace.h
+++ b/libbacktrace/include/backtrace/Backtrace.h
@@ -151,6 +151,11 @@
std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames,
std::vector<std::string>* skip_names, BacktraceUnwindError* error = nullptr);
+ static bool UnwindOffline(unwindstack::Regs* regs, BacktraceMap* back_map,
+ const backtrace_stackinfo_t& stack_info,
+ std::vector<backtrace_frame_data_t>* frames,
+ BacktraceUnwindError* error = nullptr);
+
// Get the function name and offset into the function given the pc.
// If the string is empty, then no valid function name was found,
// or the pc is not in any valid map.
diff --git a/libbacktrace/include/backtrace/BacktraceMap.h b/libbacktrace/include/backtrace/BacktraceMap.h
index 7b26079..473d195 100644
--- a/libbacktrace/include/backtrace/BacktraceMap.h
+++ b/libbacktrace/include/backtrace/BacktraceMap.h
@@ -64,8 +64,7 @@
// is unsupported.
static BacktraceMap* Create(pid_t pid, bool uncached = false);
- static BacktraceMap* CreateOffline(pid_t pid, const std::vector<backtrace_map_t>& maps,
- const backtrace_stackinfo_t& stack);
+ static BacktraceMap* CreateOffline(pid_t pid, const std::vector<backtrace_map_t>& maps);
virtual ~BacktraceMap();
@@ -154,6 +153,13 @@
const std::vector<std::string>& 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);
@@ -164,6 +170,7 @@
pid_t pid_;
std::deque<backtrace_map_t> maps_;
std::vector<std::string> suffixes_to_ignore_;
+ bool resolve_names_ = true;
};
class ScopedBacktraceMapIteratorLock {
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index a993d41..5ea981f 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -202,16 +202,6 @@
CAP_MASK_LONG(CAP_NET_RAW),
"vendor/bin/hw/android.hardware.wifi@1.0-service" },
- // A non-privileged zygote that spawns isolated processes for web rendering.
- { 0750, AID_ROOT, AID_ROOT, CAP_MASK_LONG(CAP_SETUID) |
- CAP_MASK_LONG(CAP_SETGID) |
- CAP_MASK_LONG(CAP_SETPCAP),
- "system/bin/webview_zygote32" },
- { 0750, AID_ROOT, AID_ROOT, CAP_MASK_LONG(CAP_SETUID) |
- CAP_MASK_LONG(CAP_SETGID) |
- CAP_MASK_LONG(CAP_SETPCAP),
- "system/bin/webview_zygote64" },
-
// generic defaults
{ 00755, AID_ROOT, AID_ROOT, 0, "bin/*" },
{ 00640, AID_ROOT, AID_SHELL, 0, "fstab.*" },
diff --git a/liblog/include/android/log.h b/liblog/include/android/log.h
index ade2821..28c87e4 100644
--- a/liblog/include/android/log.h
+++ b/liblog/include/android/log.h
@@ -171,6 +171,36 @@
#endif
;
+#ifndef log_id_t_defined
+#define log_id_t_defined
+typedef enum log_id {
+ LOG_ID_MIN = 0,
+
+ LOG_ID_MAIN = 0,
+ LOG_ID_RADIO = 1,
+ LOG_ID_EVENTS = 2,
+ LOG_ID_SYSTEM = 3,
+ LOG_ID_CRASH = 4,
+ LOG_ID_STATS = 5,
+ LOG_ID_SECURITY = 6,
+ LOG_ID_KERNEL = 7, /* place last, third-parties can not use it */
+
+ LOG_ID_MAX
+} log_id_t;
+#endif
+
+/*
+ * Send a simple string to the log.
+ */
+int __android_log_buf_write(int bufID, int prio, const char* tag,
+ const char* text);
+int __android_log_buf_print(int bufID, int prio, const char* tag,
+ const char* fmt, ...)
+#if defined(__GNUC__)
+ __attribute__((__format__(printf, 4, 5)))
+#endif
+ ;
+
#ifdef __cplusplus
}
#endif
diff --git a/liblog/liblog.map.txt b/liblog/liblog.map.txt
index 9d21e56..66670fe 100644
--- a/liblog/liblog.map.txt
+++ b/liblog/liblog.map.txt
@@ -3,8 +3,8 @@
android_name_to_log_id; # vndk
android_log_id_to_name; # vndk
__android_log_assert;
- __android_log_buf_print; # vndk
- __android_log_buf_write; # vndk
+ __android_log_buf_print;
+ __android_log_buf_write;
__android_log_print;
__android_log_vprint;
__android_log_write;
diff --git a/libunwindstack/DexFiles.cpp b/libunwindstack/DexFiles.cpp
index c5f8138..430f6c5 100644
--- a/libunwindstack/DexFiles.cpp
+++ b/libunwindstack/DexFiles.cpp
@@ -77,7 +77,8 @@
uint64_t DexFiles::ReadEntryPtr32(uint64_t addr) {
uint32_t entry;
- if (!memory_->ReadFully(addr, &entry, sizeof(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;
@@ -85,7 +86,8 @@
uint64_t DexFiles::ReadEntryPtr64(uint64_t addr) {
uint64_t entry;
- if (!memory_->ReadFully(addr, &entry, sizeof(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;
@@ -122,7 +124,7 @@
initialized_ = true;
entry_addr_ = 0;
- const std::string dex_debug_name("__art_debug_dexfiles");
+ const std::string dex_debug_name("__dex_debug_descriptor");
for (MapInfo* info : *maps) {
if (!(info->flags & PROT_EXEC) || !(info->flags & PROT_READ) || info->offset != 0) {
continue;
diff --git a/libunwindstack/RegsArm.cpp b/libunwindstack/RegsArm.cpp
index 7f16146..5502ce1 100644
--- a/libunwindstack/RegsArm.cpp
+++ b/libunwindstack/RegsArm.cpp
@@ -35,26 +35,25 @@
return ARCH_ARM;
}
-uint64_t RegsArm::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
+uint64_t RegsArm::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
uint64_t load_bias = elf->GetLoadBias();
if (rel_pc < load_bias) {
- return rel_pc;
+ return 0;
}
uint64_t adjusted_rel_pc = rel_pc - load_bias;
-
if (adjusted_rel_pc < 5) {
- return rel_pc;
+ return 0;
}
if (adjusted_rel_pc & 1) {
// This is a thumb instruction, it could be 2 or 4 bytes.
uint32_t value;
- if (rel_pc < 5 || !elf->memory()->ReadFully(adjusted_rel_pc - 5, &value, sizeof(value)) ||
+ if (!elf->memory()->ReadFully(adjusted_rel_pc - 5, &value, sizeof(value)) ||
(value & 0xe000f000) != 0xe000f000) {
- return rel_pc - 2;
+ return 2;
}
}
- return rel_pc - 4;
+ return 4;
}
void RegsArm::SetFromRaw() {
diff --git a/libunwindstack/RegsArm64.cpp b/libunwindstack/RegsArm64.cpp
index d6b467a..cc6f5ce 100644
--- a/libunwindstack/RegsArm64.cpp
+++ b/libunwindstack/RegsArm64.cpp
@@ -35,15 +35,11 @@
return ARCH_ARM64;
}
-uint64_t RegsArm64::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
- if (!elf->valid()) {
- return rel_pc;
+uint64_t RegsArm64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
+ if (!elf->valid() || rel_pc < 4) {
+ return 0;
}
-
- if (rel_pc < 4) {
- return rel_pc;
- }
- return rel_pc - 4;
+ return 4;
}
void RegsArm64::SetFromRaw() {
diff --git a/libunwindstack/RegsMips.cpp b/libunwindstack/RegsMips.cpp
index 6751f52..5d20bef 100644
--- a/libunwindstack/RegsMips.cpp
+++ b/libunwindstack/RegsMips.cpp
@@ -35,16 +35,12 @@
return ARCH_MIPS;
}
-uint64_t RegsMips::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
- if (!elf->valid()) {
- return rel_pc;
+uint64_t RegsMips::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
+ if (!elf->valid() || rel_pc < 8) {
+ return 0;
}
-
- // For now, just assuming no compact branches
- if (rel_pc < 8) {
- return rel_pc;
- }
- return rel_pc - 8;
+ // For now, just assume no compact branches
+ return 8;
}
void RegsMips::SetFromRaw() {
diff --git a/libunwindstack/RegsMips64.cpp b/libunwindstack/RegsMips64.cpp
index 97082bd..4a03538 100644
--- a/libunwindstack/RegsMips64.cpp
+++ b/libunwindstack/RegsMips64.cpp
@@ -36,16 +36,12 @@
return ARCH_MIPS64;
}
-uint64_t RegsMips64::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
- if (!elf->valid()) {
- return rel_pc;
+uint64_t RegsMips64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
+ if (!elf->valid() || rel_pc < 8) {
+ return 0;
}
-
- // For now, just assuming no compact branches
- if (rel_pc < 8) {
- return rel_pc;
- }
- return rel_pc - 8;
+ // For now, just assume no compact branches
+ return 8;
}
void RegsMips64::SetFromRaw() {
diff --git a/libunwindstack/RegsX86.cpp b/libunwindstack/RegsX86.cpp
index 27476b7..573cb23 100644
--- a/libunwindstack/RegsX86.cpp
+++ b/libunwindstack/RegsX86.cpp
@@ -35,15 +35,11 @@
return ARCH_X86;
}
-uint64_t RegsX86::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
- if (!elf->valid()) {
- return rel_pc;
- }
-
- if (rel_pc == 0) {
+uint64_t RegsX86::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
+ if (!elf->valid() || rel_pc == 0) {
return 0;
}
- return rel_pc - 1;
+ return 1;
}
void RegsX86::SetFromRaw() {
diff --git a/libunwindstack/RegsX86_64.cpp b/libunwindstack/RegsX86_64.cpp
index 0f66943..3175a90 100644
--- a/libunwindstack/RegsX86_64.cpp
+++ b/libunwindstack/RegsX86_64.cpp
@@ -35,16 +35,11 @@
return ARCH_X86_64;
}
-uint64_t RegsX86_64::GetAdjustedPc(uint64_t rel_pc, Elf* elf) {
- if (!elf->valid()) {
- return rel_pc;
- }
-
- if (rel_pc == 0) {
+uint64_t RegsX86_64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
+ if (!elf->valid() || rel_pc == 0) {
return 0;
}
-
- return rel_pc - 1;
+ return 1;
}
void RegsX86_64::SetFromRaw() {
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp
index d52a0bf..7da6994 100644
--- a/libunwindstack/Unwinder.cpp
+++ b/libunwindstack/Unwinder.cpp
@@ -68,6 +68,10 @@
return;
}
+ if (!resolve_names_) {
+ return;
+ }
+
#if !defined(NO_LIBDEXFILE_SUPPORT)
if (dex_files_ == nullptr) {
return;
@@ -79,20 +83,20 @@
#endif
}
-void Unwinder::FillInFrame(MapInfo* map_info, Elf* elf, uint64_t adjusted_rel_pc, uint64_t func_pc) {
+void Unwinder::FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, uint64_t func_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 = adjusted_rel_pc;
+ frame->rel_pc = rel_pc - pc_adjustment;
+ frame->pc = regs_->pc() - pc_adjustment;
if (map_info == nullptr) {
- frame->pc = regs_->pc();
return;
}
- frame->pc = map_info->start + adjusted_rel_pc - elf->GetLoadBias() - map_info->elf_offset;
frame->map_name = map_info->name;
frame->map_offset = map_info->offset;
frame->map_start = map_info->start;
@@ -100,7 +104,8 @@
frame->map_flags = map_info->flags;
frame->map_load_bias = elf->GetLoadBias();
- if (!elf->GetFunctionName(func_pc, &frame->function_name, &frame->function_offset)) {
+ if (!resolve_names_ ||
+ !elf->GetFunctionName(func_pc, &frame->function_name, &frame->function_offset)) {
frame->function_name = "";
frame->function_offset = 0;
}
@@ -135,13 +140,12 @@
MapInfo* map_info = maps_->Find(regs_->pc());
uint64_t rel_pc;
- uint64_t adjusted_pc;
- uint64_t adjusted_rel_pc;
+ uint64_t pc_adjustment = 0;
+ uint64_t step_pc;
Elf* elf;
if (map_info == nullptr) {
rel_pc = regs_->pc();
- adjusted_rel_pc = rel_pc;
- adjusted_pc = rel_pc;
+ step_pc = rel_pc;
last_error_.code = ERROR_INVALID_MAP;
} else {
if (ShouldStop(map_suffixes_to_ignore, map_info->name)) {
@@ -150,21 +154,20 @@
elf = map_info->GetElf(process_memory_, true);
rel_pc = elf->GetRelPc(regs_->pc(), map_info);
if (adjust_pc) {
- adjusted_pc = regs_->GetAdjustedPc(rel_pc, elf);
+ pc_adjustment = regs_->GetPcAdjustment(rel_pc, elf);
} else {
- adjusted_pc = rel_pc;
+ pc_adjustment = 0;
}
- adjusted_rel_pc = adjusted_pc;
+ step_pc = rel_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() - (rel_pc - adjusted_pc);
+ 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.
- adjusted_pc = adjusted_jit_pc;
- adjusted_rel_pc = adjusted_pc - map_info->start;
+ step_pc = adjusted_jit_pc;
elf = jit_elf;
}
}
@@ -180,7 +183,7 @@
regs_->set_dex_pc(0);
}
- FillInFrame(map_info, elf, adjusted_rel_pc, adjusted_pc);
+ FillInFrame(map_info, elf, rel_pc, step_pc, pc_adjustment);
// Once a frame is added, stop skipping frames.
initial_map_names_to_skip = nullptr;
@@ -208,8 +211,8 @@
in_device_map = true;
} else {
bool finished;
- stepped = elf->Step(rel_pc, adjusted_pc, map_info->elf_offset, regs_,
- process_memory_.get(), &finished);
+ stepped = elf->Step(rel_pc, step_pc, map_info->elf_offset, regs_, process_memory_.get(),
+ &finished);
elf->GetLastError(&last_error_);
if (stepped && finished) {
break;
diff --git a/libunwindstack/include/unwindstack/Regs.h b/libunwindstack/include/unwindstack/Regs.h
index a5ba7a0..b0e7ea1 100644
--- a/libunwindstack/include/unwindstack/Regs.h
+++ b/libunwindstack/include/unwindstack/Regs.h
@@ -60,7 +60,7 @@
uint64_t dex_pc() { return dex_pc_; }
void set_dex_pc(uint64_t dex_pc) { dex_pc_ = dex_pc; }
- virtual uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) = 0;
+ virtual uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) = 0;
virtual bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) = 0;
diff --git a/libunwindstack/include/unwindstack/RegsArm.h b/libunwindstack/include/unwindstack/RegsArm.h
index b5d344b..5af90d3 100644
--- a/libunwindstack/include/unwindstack/RegsArm.h
+++ b/libunwindstack/include/unwindstack/RegsArm.h
@@ -36,7 +36,7 @@
virtual ArchEnum Arch() override final;
- uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) override;
+ uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
void SetFromRaw() override;
diff --git a/libunwindstack/include/unwindstack/RegsArm64.h b/libunwindstack/include/unwindstack/RegsArm64.h
index 30e626c..cb05732 100644
--- a/libunwindstack/include/unwindstack/RegsArm64.h
+++ b/libunwindstack/include/unwindstack/RegsArm64.h
@@ -36,7 +36,7 @@
virtual ArchEnum Arch() override final;
- uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) override;
+ uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
void SetFromRaw() override;
diff --git a/libunwindstack/include/unwindstack/RegsMips.h b/libunwindstack/include/unwindstack/RegsMips.h
index 3fe6a9f..8e3c01f 100644
--- a/libunwindstack/include/unwindstack/RegsMips.h
+++ b/libunwindstack/include/unwindstack/RegsMips.h
@@ -36,7 +36,7 @@
virtual ArchEnum Arch() override final;
- uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) override;
+ uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
void SetFromRaw() override;
diff --git a/libunwindstack/include/unwindstack/RegsMips64.h b/libunwindstack/include/unwindstack/RegsMips64.h
index 6b4bcdf..8c2d443 100644
--- a/libunwindstack/include/unwindstack/RegsMips64.h
+++ b/libunwindstack/include/unwindstack/RegsMips64.h
@@ -36,7 +36,7 @@
virtual ArchEnum Arch() override final;
- uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) override;
+ uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
void SetFromRaw() override;
diff --git a/libunwindstack/include/unwindstack/RegsX86.h b/libunwindstack/include/unwindstack/RegsX86.h
index a695bbf..1bc145d 100644
--- a/libunwindstack/include/unwindstack/RegsX86.h
+++ b/libunwindstack/include/unwindstack/RegsX86.h
@@ -37,7 +37,7 @@
virtual ArchEnum Arch() override final;
- uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) override;
+ uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
void SetFromRaw() override;
diff --git a/libunwindstack/include/unwindstack/RegsX86_64.h b/libunwindstack/include/unwindstack/RegsX86_64.h
index 23a3f20..4cd45d4 100644
--- a/libunwindstack/include/unwindstack/RegsX86_64.h
+++ b/libunwindstack/include/unwindstack/RegsX86_64.h
@@ -37,7 +37,7 @@
virtual ArchEnum Arch() override final;
- uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) override;
+ uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
void SetFromRaw() override;
diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h
index ebe7b0a..56b0581 100644
--- a/libunwindstack/include/unwindstack/Unwinder.h
+++ b/libunwindstack/include/unwindstack/Unwinder.h
@@ -75,6 +75,10 @@
void SetJitDebug(JitDebug* jit_debug, ArchEnum arch);
+ // 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; }
+
#if !defined(NO_LIBDEXFILE_SUPPORT)
void SetDexFiles(DexFiles* dex_files, ArchEnum arch);
#endif
@@ -84,7 +88,8 @@
private:
void FillInDexFrame();
- void FillInFrame(MapInfo* map_info, Elf* elf, uint64_t adjusted_rel_pc, uint64_t adjusted_pc);
+ void FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, uint64_t func_pc,
+ uint64_t pc_adjustment);
size_t max_frames_;
Maps* maps_;
@@ -95,6 +100,7 @@
#if !defined(NO_LIBDEXFILE_SUPPORT)
DexFiles* dex_files_ = nullptr;
#endif
+ bool resolve_names_ = true;
ErrorData last_error_;
};
diff --git a/libunwindstack/tests/DexFilesTest.cpp b/libunwindstack/tests/DexFilesTest.cpp
index dca5605..d029bb0 100644
--- a/libunwindstack/tests/DexFilesTest.cpp
+++ b/libunwindstack/tests/DexFilesTest.cpp
@@ -63,7 +63,7 @@
elf->FakeSetValid(true);
ElfInterfaceFake* interface = new ElfInterfaceFake(memory);
elf->FakeSetInterface(interface);
- interface->FakeSetGlobalVariable("__art_debug_dexfiles", 0x800);
+ interface->FakeSetGlobalVariable("__dex_debug_descriptor", 0x800);
map_info->elf.reset(elf);
// Global variable not set by default.
@@ -74,7 +74,7 @@
elf->FakeSetValid(true);
interface = new ElfInterfaceFake(memory);
elf->FakeSetInterface(interface);
- interface->FakeSetGlobalVariable("__art_debug_dexfiles", 0x800);
+ interface->FakeSetGlobalVariable("__dex_debug_descriptor", 0x800);
map_info->elf.reset(elf);
// Global variable set in this map.
@@ -85,10 +85,12 @@
elf->FakeSetValid(true);
interface = new ElfInterfaceFake(memory);
elf->FakeSetInterface(interface);
- interface->FakeSetGlobalVariable("__art_debug_dexfiles", 0x800);
+ interface->FakeSetGlobalVariable("__dex_debug_descriptor", 0x800);
map_info->elf.reset(elf);
}
+ 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);
@@ -105,6 +107,16 @@
std::unique_ptr<BufferMaps> 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:
@@ -146,7 +158,7 @@
uint64_t method_offset = 0x124;
MapInfo* info = maps_->Get(kMapDexFiles);
- memory_->SetData32(0xf800, 0x200000);
+ WriteDescriptor32(0xf800, 0x200000);
WriteEntry32(0x200000, 0, 0, 0x300000);
WriteDex(0x300000);
@@ -161,7 +173,7 @@
MapInfo* info = maps_->Get(kMapDexFiles);
dex_files_->SetArch(ARCH_ARM64);
- memory_->SetData64(0xf800, 0x200000);
+ WriteDescriptor64(0xf800, 0x200000);
WriteEntry64(0x200000, 0, 0, 0x301000);
WriteDex(0x301000);
@@ -175,7 +187,7 @@
uint64_t method_offset = 0x124;
MapInfo* info = maps_->Get(kMapDexFiles);
- memory_->SetData32(0xf800, 0x200000);
+ WriteDescriptor32(0xf800, 0x200000);
WriteEntry32(0x200000, 0x200100, 0, 0x100000);
WriteEntry32(0x200100, 0, 0x200000, 0x300000);
WriteDex(0x300000);
@@ -191,7 +203,7 @@
MapInfo* info = maps_->Get(kMapDexFiles);
dex_files_->SetArch(ARCH_ARM64);
- memory_->SetData64(0xf800, 0x200000);
+ WriteDescriptor64(0xf800, 0x200000);
WriteEntry64(0x200000, 0x200100, 0, 0x100000);
WriteEntry64(0x200100, 0, 0x200000, 0x300000);
WriteDex(0x300000);
@@ -206,7 +218,7 @@
uint64_t method_offset = 0x124;
MapInfo* info = maps_->Get(kMapDexFiles);
- memory_->SetData32(0xf800, 0x200000);
+ WriteDescriptor32(0xf800, 0x200000);
WriteEntry32(0x200000, 0, 0, 0x300000);
WriteDex(0x300000);
@@ -226,7 +238,7 @@
uint64_t method_offset = 0x124;
MapInfo* info = maps_->Get(kMapDexFiles);
- memory_->SetData32(0xf800, 0x200000);
+ WriteDescriptor32(0xf800, 0x200000);
WriteEntry32(0x200000, 0x200100, 0, 0x100000);
WriteEntry32(0x200100, 0, 0x200000, 0x300000);
WriteDex(0x300000);
@@ -259,9 +271,9 @@
MapInfo* info = maps_->Get(kMapDexFiles);
// First global variable found, but value is zero.
- memory_->SetData32(0xc800, 0);
+ WriteDescriptor32(0xc800, 0);
- memory_->SetData32(0xf800, 0x200000);
+ WriteDescriptor32(0xf800, 0x200000);
WriteEntry32(0x200000, 0, 0, 0x300000);
WriteDex(0x300000);
@@ -274,7 +286,7 @@
dex_files_->SetArch(ARCH_ARM);
method_name = "fail";
method_offset = 0x123;
- memory_->SetData32(0xc800, 0x100000);
+ WriteDescriptor32(0xc800, 0x100000);
dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
EXPECT_EQ("fail", method_name);
EXPECT_EQ(0x123U, method_offset);
@@ -286,9 +298,9 @@
MapInfo* info = maps_->Get(kMapDexFiles);
// First global variable found, but value is zero.
- memory_->SetData64(0xc800, 0);
+ WriteDescriptor64(0xc800, 0);
- memory_->SetData64(0xf800, 0x200000);
+ WriteDescriptor64(0xf800, 0x200000);
WriteEntry64(0x200000, 0, 0, 0x300000);
WriteDex(0x300000);
@@ -302,7 +314,7 @@
dex_files_->SetArch(ARCH_ARM64);
method_name = "fail";
method_offset = 0x123;
- memory_->SetData32(0xc800, 0x100000);
+ WriteDescriptor64(0xc800, 0x100000);
dex_files_->GetMethodInformation(maps_.get(), info, 0x300100, &method_name, &method_offset);
EXPECT_EQ("fail", method_name);
EXPECT_EQ(0x123U, method_offset);
diff --git a/libunwindstack/tests/RegsFake.h b/libunwindstack/tests/RegsFake.h
index cd7f2ff..ab23194 100644
--- a/libunwindstack/tests/RegsFake.h
+++ b/libunwindstack/tests/RegsFake.h
@@ -47,7 +47,7 @@
bool Is32Bit() { return false; }
- uint64_t GetAdjustedPc(uint64_t rel_pc, Elf*) override { return rel_pc - 2; }
+ uint64_t GetPcAdjustment(uint64_t, Elf*) override { return 2; }
bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; }
@@ -77,7 +77,7 @@
ArchEnum Arch() override { return ARCH_UNKNOWN; }
- uint64_t GetAdjustedPc(uint64_t, Elf*) override { return 0; }
+ uint64_t GetPcAdjustment(uint64_t, Elf*) override { return 0; }
void SetFromRaw() override {}
bool SetPcFromReturnAddress(Memory*) override { return false; }
bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; }
diff --git a/libunwindstack/tests/RegsTest.cpp b/libunwindstack/tests/RegsTest.cpp
index 7c06373..8b2f6c8 100644
--- a/libunwindstack/tests/RegsTest.cpp
+++ b/libunwindstack/tests/RegsTest.cpp
@@ -96,48 +96,48 @@
TEST_F(RegsTest, rel_pc) {
RegsArm64 arm64;
- ASSERT_EQ(0xcU, arm64.GetAdjustedPc(0x10, elf_.get()));
- ASSERT_EQ(0x0U, arm64.GetAdjustedPc(0x4, elf_.get()));
- ASSERT_EQ(0x3U, arm64.GetAdjustedPc(0x3, elf_.get()));
- ASSERT_EQ(0x2U, arm64.GetAdjustedPc(0x2, elf_.get()));
- ASSERT_EQ(0x1U, arm64.GetAdjustedPc(0x1, elf_.get()));
- ASSERT_EQ(0x0U, arm64.GetAdjustedPc(0x0, elf_.get()));
+ ASSERT_EQ(4U, arm64.GetPcAdjustment(0x10, elf_.get()));
+ ASSERT_EQ(4U, arm64.GetPcAdjustment(0x4, elf_.get()));
+ ASSERT_EQ(0U, arm64.GetPcAdjustment(0x3, elf_.get()));
+ ASSERT_EQ(0U, arm64.GetPcAdjustment(0x2, elf_.get()));
+ ASSERT_EQ(0U, arm64.GetPcAdjustment(0x1, elf_.get()));
+ ASSERT_EQ(0U, arm64.GetPcAdjustment(0x0, elf_.get()));
RegsX86 x86;
- ASSERT_EQ(0xffU, x86.GetAdjustedPc(0x100, elf_.get()));
- ASSERT_EQ(0x1U, x86.GetAdjustedPc(0x2, elf_.get()));
- ASSERT_EQ(0x0U, x86.GetAdjustedPc(0x1, elf_.get()));
- ASSERT_EQ(0x0U, x86.GetAdjustedPc(0x0, elf_.get()));
+ ASSERT_EQ(1U, x86.GetPcAdjustment(0x100, elf_.get()));
+ ASSERT_EQ(1U, x86.GetPcAdjustment(0x2, elf_.get()));
+ ASSERT_EQ(1U, x86.GetPcAdjustment(0x1, elf_.get()));
+ ASSERT_EQ(0U, x86.GetPcAdjustment(0x0, elf_.get()));
RegsX86_64 x86_64;
- ASSERT_EQ(0xffU, x86_64.GetAdjustedPc(0x100, elf_.get()));
- ASSERT_EQ(0x1U, x86_64.GetAdjustedPc(0x2, elf_.get()));
- ASSERT_EQ(0x0U, x86_64.GetAdjustedPc(0x1, elf_.get()));
- ASSERT_EQ(0x0U, x86_64.GetAdjustedPc(0x0, elf_.get()));
+ ASSERT_EQ(1U, x86_64.GetPcAdjustment(0x100, elf_.get()));
+ ASSERT_EQ(1U, x86_64.GetPcAdjustment(0x2, elf_.get()));
+ ASSERT_EQ(1U, x86_64.GetPcAdjustment(0x1, elf_.get()));
+ ASSERT_EQ(0U, x86_64.GetPcAdjustment(0x0, elf_.get()));
RegsMips mips;
- ASSERT_EQ(0x8U, mips.GetAdjustedPc(0x10, elf_.get()));
- ASSERT_EQ(0x0U, mips.GetAdjustedPc(0x8, elf_.get()));
- ASSERT_EQ(0x7U, mips.GetAdjustedPc(0x7, elf_.get()));
- ASSERT_EQ(0x6U, mips.GetAdjustedPc(0x6, elf_.get()));
- ASSERT_EQ(0x5U, mips.GetAdjustedPc(0x5, elf_.get()));
- ASSERT_EQ(0x4U, mips.GetAdjustedPc(0x4, elf_.get()));
- ASSERT_EQ(0x3U, mips.GetAdjustedPc(0x3, elf_.get()));
- ASSERT_EQ(0x2U, mips.GetAdjustedPc(0x2, elf_.get()));
- ASSERT_EQ(0x1U, mips.GetAdjustedPc(0x1, elf_.get()));
- ASSERT_EQ(0x0U, mips.GetAdjustedPc(0x0, elf_.get()));
+ ASSERT_EQ(8U, mips.GetPcAdjustment(0x10, elf_.get()));
+ ASSERT_EQ(8U, mips.GetPcAdjustment(0x8, elf_.get()));
+ ASSERT_EQ(0U, mips.GetPcAdjustment(0x7, elf_.get()));
+ ASSERT_EQ(0U, mips.GetPcAdjustment(0x6, elf_.get()));
+ ASSERT_EQ(0U, mips.GetPcAdjustment(0x5, elf_.get()));
+ ASSERT_EQ(0U, mips.GetPcAdjustment(0x4, elf_.get()));
+ ASSERT_EQ(0U, mips.GetPcAdjustment(0x3, elf_.get()));
+ ASSERT_EQ(0U, mips.GetPcAdjustment(0x2, elf_.get()));
+ ASSERT_EQ(0U, mips.GetPcAdjustment(0x1, elf_.get()));
+ ASSERT_EQ(0U, mips.GetPcAdjustment(0x0, elf_.get()));
RegsMips64 mips64;
- ASSERT_EQ(0x8U, mips64.GetAdjustedPc(0x10, elf_.get()));
- ASSERT_EQ(0x0U, mips64.GetAdjustedPc(0x8, elf_.get()));
- ASSERT_EQ(0x7U, mips64.GetAdjustedPc(0x7, elf_.get()));
- ASSERT_EQ(0x6U, mips64.GetAdjustedPc(0x6, elf_.get()));
- ASSERT_EQ(0x5U, mips64.GetAdjustedPc(0x5, elf_.get()));
- ASSERT_EQ(0x4U, mips64.GetAdjustedPc(0x4, elf_.get()));
- ASSERT_EQ(0x3U, mips64.GetAdjustedPc(0x3, elf_.get()));
- ASSERT_EQ(0x2U, mips64.GetAdjustedPc(0x2, elf_.get()));
- ASSERT_EQ(0x1U, mips64.GetAdjustedPc(0x1, elf_.get()));
- ASSERT_EQ(0x0U, mips64.GetAdjustedPc(0x0, elf_.get()));
+ ASSERT_EQ(8U, mips64.GetPcAdjustment(0x10, elf_.get()));
+ ASSERT_EQ(8U, mips64.GetPcAdjustment(0x8, elf_.get()));
+ ASSERT_EQ(0U, mips64.GetPcAdjustment(0x7, elf_.get()));
+ ASSERT_EQ(0U, mips64.GetPcAdjustment(0x6, elf_.get()));
+ ASSERT_EQ(0U, mips64.GetPcAdjustment(0x5, elf_.get()));
+ ASSERT_EQ(0U, mips64.GetPcAdjustment(0x4, elf_.get()));
+ ASSERT_EQ(0U, mips64.GetPcAdjustment(0x3, elf_.get()));
+ ASSERT_EQ(0U, mips64.GetPcAdjustment(0x2, elf_.get()));
+ ASSERT_EQ(0U, mips64.GetPcAdjustment(0x1, elf_.get()));
+ ASSERT_EQ(0U, mips64.GetPcAdjustment(0x0, elf_.get()));
}
TEST_F(RegsTest, rel_pc_arm) {
@@ -145,34 +145,34 @@
// Check fence posts.
elf_->FakeSetLoadBias(0);
- ASSERT_EQ(3U, arm.GetAdjustedPc(0x5, elf_.get()));
- ASSERT_EQ(4U, arm.GetAdjustedPc(0x4, elf_.get()));
- ASSERT_EQ(3U, arm.GetAdjustedPc(0x3, elf_.get()));
- ASSERT_EQ(2U, arm.GetAdjustedPc(0x2, elf_.get()));
- ASSERT_EQ(1U, arm.GetAdjustedPc(0x1, elf_.get()));
- ASSERT_EQ(0U, arm.GetAdjustedPc(0x0, elf_.get()));
+ ASSERT_EQ(2U, arm.GetPcAdjustment(0x5, elf_.get()));
+ ASSERT_EQ(0U, arm.GetPcAdjustment(0x4, elf_.get()));
+ ASSERT_EQ(0U, arm.GetPcAdjustment(0x3, elf_.get()));
+ ASSERT_EQ(0U, arm.GetPcAdjustment(0x2, elf_.get()));
+ ASSERT_EQ(0U, arm.GetPcAdjustment(0x1, elf_.get()));
+ ASSERT_EQ(0U, arm.GetPcAdjustment(0x0, elf_.get()));
elf_->FakeSetLoadBias(0x100);
- ASSERT_EQ(0xffU, arm.GetAdjustedPc(0xff, elf_.get()));
- ASSERT_EQ(0x103U, arm.GetAdjustedPc(0x105, elf_.get()));
- ASSERT_EQ(0x104U, arm.GetAdjustedPc(0x104, elf_.get()));
- ASSERT_EQ(0x103U, arm.GetAdjustedPc(0x103, elf_.get()));
- ASSERT_EQ(0x102U, arm.GetAdjustedPc(0x102, elf_.get()));
- ASSERT_EQ(0x101U, arm.GetAdjustedPc(0x101, elf_.get()));
- ASSERT_EQ(0x100U, arm.GetAdjustedPc(0x100, elf_.get()));
+ ASSERT_EQ(0U, arm.GetPcAdjustment(0xff, elf_.get()));
+ ASSERT_EQ(2U, arm.GetPcAdjustment(0x105, elf_.get()));
+ ASSERT_EQ(0U, arm.GetPcAdjustment(0x104, elf_.get()));
+ ASSERT_EQ(0U, arm.GetPcAdjustment(0x103, elf_.get()));
+ ASSERT_EQ(0U, arm.GetPcAdjustment(0x102, elf_.get()));
+ ASSERT_EQ(0U, arm.GetPcAdjustment(0x101, elf_.get()));
+ ASSERT_EQ(0U, arm.GetPcAdjustment(0x100, elf_.get()));
// Check thumb instructions handling.
elf_->FakeSetLoadBias(0);
memory_->SetData32(0x2000, 0);
- ASSERT_EQ(0x2003U, arm.GetAdjustedPc(0x2005, elf_.get()));
+ ASSERT_EQ(2U, arm.GetPcAdjustment(0x2005, elf_.get()));
memory_->SetData32(0x2000, 0xe000f000);
- ASSERT_EQ(0x2001U, arm.GetAdjustedPc(0x2005, elf_.get()));
+ ASSERT_EQ(4U, arm.GetPcAdjustment(0x2005, elf_.get()));
elf_->FakeSetLoadBias(0x400);
memory_->SetData32(0x2100, 0);
- ASSERT_EQ(0x2503U, arm.GetAdjustedPc(0x2505, elf_.get()));
+ ASSERT_EQ(2U, arm.GetPcAdjustment(0x2505, elf_.get()));
memory_->SetData32(0x2100, 0xf111f111);
- ASSERT_EQ(0x2501U, arm.GetAdjustedPc(0x2505, elf_.get()));
+ ASSERT_EQ(4U, arm.GetPcAdjustment(0x2505, elf_.get()));
}
TEST_F(RegsTest, elf_invalid) {
@@ -188,27 +188,27 @@
regs_arm.set_pc(0x1500);
EXPECT_EQ(0x500U, invalid_elf->GetRelPc(regs_arm.pc(), &map_info));
- EXPECT_EQ(0x4fcU, regs_arm.GetAdjustedPc(0x500U, invalid_elf));
+ EXPECT_EQ(4U, regs_arm.GetPcAdjustment(0x500U, invalid_elf));
regs_arm64.set_pc(0x1600);
EXPECT_EQ(0x600U, invalid_elf->GetRelPc(regs_arm64.pc(), &map_info));
- EXPECT_EQ(0x600U, regs_arm64.GetAdjustedPc(0x600U, invalid_elf));
+ EXPECT_EQ(0U, regs_arm64.GetPcAdjustment(0x600U, invalid_elf));
regs_x86.set_pc(0x1700);
EXPECT_EQ(0x700U, invalid_elf->GetRelPc(regs_x86.pc(), &map_info));
- EXPECT_EQ(0x700U, regs_x86.GetAdjustedPc(0x700U, invalid_elf));
+ EXPECT_EQ(0U, regs_x86.GetPcAdjustment(0x700U, invalid_elf));
regs_x86_64.set_pc(0x1800);
EXPECT_EQ(0x800U, invalid_elf->GetRelPc(regs_x86_64.pc(), &map_info));
- EXPECT_EQ(0x800U, regs_x86_64.GetAdjustedPc(0x800U, invalid_elf));
+ EXPECT_EQ(0U, regs_x86_64.GetPcAdjustment(0x800U, invalid_elf));
regs_mips.set_pc(0x1900);
EXPECT_EQ(0x900U, invalid_elf->GetRelPc(regs_mips.pc(), &map_info));
- EXPECT_EQ(0x900U, regs_mips.GetAdjustedPc(0x900U, invalid_elf));
+ EXPECT_EQ(0U, regs_mips.GetPcAdjustment(0x900U, invalid_elf));
regs_mips64.set_pc(0x1a00);
EXPECT_EQ(0xa00U, invalid_elf->GetRelPc(regs_mips64.pc(), &map_info));
- EXPECT_EQ(0xa00U, regs_mips64.GetAdjustedPc(0xa00U, invalid_elf));
+ EXPECT_EQ(0U, regs_mips64.GetPcAdjustment(0xa00U, invalid_elf));
}
TEST_F(RegsTest, arm_set_from_raw) {
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
index df262f5..af4a5b5 100644
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -193,6 +193,14 @@
" #02 pc 00007441 libbase.so (_ZN7android4base10LogMessageD2Ev+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);
}
TEST_F(UnwindOfflineTest, pc_in_gnu_debugdata_arm) {
@@ -209,6 +217,10 @@
" #01 pc 0006dce5 libandroid_runtime.so "
"(_ZN7android14AndroidRuntime19javaCreateThreadEtcEPFiPvES1_PKcijPS1_)\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) {
@@ -229,6 +241,18 @@
"(_ZN11unwindstack37UnwindTest_remote_through_signal_Test8TestBodyEv+32)\n"
" #05 pc 0000000000455d70 libunwindstack_test (_ZN7testing4Test3RunEv+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);
}
static void AddMemory(std::string file_name, MemoryOfflineParts* parts) {
@@ -390,6 +414,144 @@
" #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(0xee75be81U, 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(0xee75be04U, 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(0xee75bd3cU, 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(0xee75bbdcU, 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(0xee75b625U, 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(0xee75aedcU, 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(0xee756c22U, 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) {
@@ -553,6 +715,158 @@
" #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);
}
// The eh_frame_hdr data is present but set to zero fdes. This should
@@ -573,6 +887,16 @@
" #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
@@ -592,6 +916,16 @@
" #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.
@@ -610,6 +944,16 @@
" #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);
}
} // namespace unwindstack
diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp
index 7fbae4c..e44b225 100644
--- a/libunwindstack/tests/UnwinderTest.cpp
+++ b/libunwindstack/tests/UnwinderTest.cpp
@@ -196,6 +196,67 @@
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_.FakeSetPc(0x1000);
+ regs_.FakeSetSp(0x10000);
+ ElfInterfaceFake::FakePushStepData(StepData(0x1102, 0x10010, false));
+ ElfInterfaceFake::FakePushStepData(StepData(0x1202, 0x10020, false));
+ ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
+
+ Unwinder unwinder(64, &maps_, ®s_, process_memory_);
+ unwinder.SetResolveNames(false);
+ unwinder.Unwind();
+ EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+
+ 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("/system/fake/libc.so", frame->map_name);
+ EXPECT_EQ(0U, frame->map_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("/system/fake/libc.so", frame->map_name);
+ EXPECT_EQ(0U, frame->map_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("/system/fake/libc.so", frame->map_name);
+ EXPECT_EQ(0U, frame->map_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));