Merge "Revert "init: Reboot after timeout passes during reboot""
diff --git a/adb/adb_listeners.cpp b/adb/adb_listeners.cpp
index a142384..fecf452 100644
--- a/adb/adb_listeners.cpp
+++ b/adb/adb_listeners.cpp
@@ -29,6 +29,7 @@
#include "socket_spec.h"
#include "sysdeps.h"
+#include "sysdeps/memory.h"
#include "transport.h"
// A listener is an entity which binds to a local port and, upon receiving a connection on that
@@ -203,7 +204,7 @@
}
}
- std::unique_ptr<alistener> listener(new alistener(local_name, connect_to));
+ auto listener = std::make_unique<alistener>(local_name, connect_to);
int resolved = 0;
listener->fd = socket_spec_listen(listener->local_name, error, &resolved);
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index d126f52..34930c6 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -61,6 +61,7 @@
#include "services.h"
#include "shell_service.h"
#include "sysdeps/chrono.h"
+#include "sysdeps/memory.h"
static int install_app(int argc, const char** argv);
static int install_multiple_app(int argc, const char** argv);
@@ -263,7 +264,7 @@
char raw_buffer[BUFSIZ];
char* buffer_ptr = raw_buffer;
if (use_shell_protocol) {
- protocol.reset(new ShellProtocol(fd));
+ protocol = std::make_unique<ShellProtocol>(fd);
if (!protocol) {
LOG(ERROR) << "failed to allocate memory for ShellProtocol object";
return 1;
@@ -630,7 +631,7 @@
args->raw_stdin = raw_stdin;
args->escape_char = escape_char;
if (use_shell_protocol) {
- args->protocol.reset(new ShellProtocol(args->write_fd));
+ args->protocol = std::make_unique<ShellProtocol>(args->write_fd);
}
if (raw_stdin) stdin_raw_init();
diff --git a/adb/daemon/shell_service.cpp b/adb/daemon/shell_service.cpp
index f9f80c0..c04ceaf 100644
--- a/adb/daemon/shell_service.cpp
+++ b/adb/daemon/shell_service.cpp
@@ -372,8 +372,8 @@
}
D("protocol FD = %d", protocol_sfd_.get());
- input_.reset(new ShellProtocol(protocol_sfd_));
- output_.reset(new ShellProtocol(protocol_sfd_));
+ input_ = std::make_unique<ShellProtocol>(protocol_sfd_);
+ output_ = std::make_unique<ShellProtocol>(protocol_sfd_);
if (!input_ || !output_) {
*error = "failed to allocate shell protocol objects";
kill(pid_, SIGKILL);
diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp
index d285561..ba82e7c 100644
--- a/adb/fdevent.cpp
+++ b/adb/fdevent.cpp
@@ -21,6 +21,7 @@
#include "fdevent.h"
#include <fcntl.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -36,6 +37,7 @@
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android-base/thread_annotations.h>
+#include <android-base/threads.h>
#include "adb_io.h"
#include "adb_trace.h"
@@ -78,7 +80,7 @@
static auto& g_pending_list = *new std::list<fdevent*>();
static std::atomic<bool> terminate_loop(false);
static bool main_thread_valid;
-static unsigned long main_thread_id;
+static uint64_t main_thread_id;
static auto& run_queue_notify_fd = *new unique_fd();
static auto& run_queue_mutex = *new std::mutex();
@@ -86,13 +88,13 @@
void check_main_thread() {
if (main_thread_valid) {
- CHECK_EQ(main_thread_id, adb_thread_id());
+ CHECK_EQ(main_thread_id, android::base::GetThreadId());
}
}
void set_main_thread() {
main_thread_valid = true;
- main_thread_id = adb_thread_id();
+ main_thread_id = android::base::GetThreadId();
}
static std::string dump_fde(const fdevent* fde) {
diff --git a/adb/fdevent_test.cpp b/adb/fdevent_test.cpp
index 63cc4d1..dadae5a 100644
--- a/adb/fdevent_test.cpp
+++ b/adb/fdevent_test.cpp
@@ -99,7 +99,7 @@
std::vector<std::unique_ptr<FdHandler>> fd_handlers;
for (size_t i = 0; i < read_fds.size(); ++i) {
- fd_handlers.push_back(std::unique_ptr<FdHandler>(new FdHandler(read_fds[i], write_fds[i])));
+ fd_handlers.push_back(std::make_unique<FdHandler>(read_fds[i], write_fds[i]));
}
fdevent_loop();
diff --git a/adb/socket_test.cpp b/adb/socket_test.cpp
index c818fca..44d3276 100644
--- a/adb/socket_test.cpp
+++ b/adb/socket_test.cpp
@@ -113,16 +113,12 @@
asocket* s = create_local_socket(arg->socket_fd);
ASSERT_TRUE(s != nullptr);
arg->bytes_written = 0;
- while (true) {
- std::string data;
- data.resize(MAX_PAYLOAD);
- arg->bytes_written += data.size();
- int ret = s->enqueue(s, std::move(data));
- if (ret == 1) {
- // The writer has one packet waiting to send.
- break;
- }
- }
+
+ std::string data;
+ data.resize(MAX_PAYLOAD);
+ arg->bytes_written += data.size();
+ int ret = s->enqueue(s, std::move(data));
+ ASSERT_EQ(1, ret);
asocket* cause_close_s = create_local_socket(arg->cause_close_fd);
ASSERT_TRUE(cause_close_s != nullptr);
@@ -233,15 +229,16 @@
PrepareThread();
std::thread thread(fdevent_loop);
- ASSERT_TRUE(WriteFdExactly(head_fd[0], "foo", 3));
- ASSERT_EQ(0, adb_shutdown(head_fd[0], SHUT_RD));
- const char* str = "write succeeds, but local_socket will fail to write";
- ASSERT_TRUE(WriteFdExactly(tail_fd[0], str, strlen(str)));
- ASSERT_TRUE(WriteFdExactly(head_fd[0], "bar", 3));
- char buf[6];
- ASSERT_TRUE(ReadFdExactly(tail_fd[0], buf, 6));
+ EXPECT_TRUE(WriteFdExactly(head_fd[0], "foo", 3));
- ASSERT_EQ(0, memcmp(buf, "foobar", 6));
+ EXPECT_EQ(0, adb_shutdown(head_fd[0], SHUT_RD));
+ const char* str = "write succeeds, but local_socket will fail to write";
+ EXPECT_TRUE(WriteFdExactly(tail_fd[0], str, strlen(str)));
+ EXPECT_TRUE(WriteFdExactly(head_fd[0], "bar", 3));
+
+ char buf[6];
+ EXPECT_TRUE(ReadFdExactly(tail_fd[0], buf, 6));
+ EXPECT_EQ(0, memcmp(buf, "foobar", 6));
adb_close(head_fd[0]);
adb_close(tail_fd[0]);
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 307be6d..fd08ad8 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -92,11 +92,6 @@
return 0;
}
-static __inline__ unsigned long adb_thread_id()
-{
- return GetCurrentThreadId();
-}
-
static __inline__ void close_on_exec(int fd)
{
/* nothing really */
@@ -625,11 +620,6 @@
return path[0] == '/';
}
-static __inline__ unsigned long adb_thread_id()
-{
- return (unsigned long)gettid();
-}
-
#endif /* !_WIN32 */
static inline void disable_tcp_nagle(int fd) {
diff --git a/adb/sysdeps/memory.h b/adb/sysdeps/memory.h
new file mode 100644
index 0000000..0e4c509
--- /dev/null
+++ b/adb/sysdeps/memory.h
@@ -0,0 +1,36 @@
+#pragma once
+
+/*
+ * 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 <memory>
+#include <type_traits>
+
+#if defined(_WIN32)
+// We don't have C++14 on Windows yet.
+// Reimplement std::make_unique ourselves until we do.
+
+namespace std {
+
+template <typename T, typename... Args>
+typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type make_unique(
+ Args&&... args) {
+ return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+}
+
+} // namespace std
+
+#endif
diff --git a/adb/test_adb.py b/adb/test_adb.py
index 98c8a59..e771106 100644
--- a/adb/test_adb.py
+++ b/adb/test_adb.py
@@ -217,8 +217,12 @@
ipv4.listen(1)
ipv6 = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
- ipv6.bind(('::1', ipv4.getsockname()[1] + 1))
- ipv6.listen(1)
+ try:
+ ipv6.bind(('::1', ipv4.getsockname()[1] + 1))
+ ipv6.listen(1)
+ except socket.error:
+ print("IPv6 not available, skipping")
+ return
for s in (ipv4, ipv6):
port = s.getsockname()[1]
diff --git a/adb/test_device.py b/adb/test_device.py
index 4cf2206..d422df2 100644
--- a/adb/test_device.py
+++ b/adb/test_device.py
@@ -31,6 +31,7 @@
import subprocess
import sys
import tempfile
+import threading
import time
import unittest
@@ -493,6 +494,29 @@
stdout, _ = self.device.shell(["cat", log_path])
self.assertEqual(stdout.strip(), "SIGHUP")
+ def test_exit_stress(self):
+ """Hammer `adb shell exit 42` with multiple threads."""
+ thread_count = 48
+ result = dict()
+ def hammer(thread_idx, thread_count, result):
+ success = True
+ for i in range(thread_idx, 240, thread_count):
+ ret = subprocess.call(['adb', 'shell', 'exit {}'.format(i)])
+ if ret != i % 256:
+ success = False
+ break
+ result[thread_idx] = success
+
+ threads = []
+ for i in range(thread_count):
+ thread = threading.Thread(target=hammer, args=(i, thread_count, result))
+ thread.start()
+ threads.append(thread)
+ for thread in threads:
+ thread.join()
+ for i, success in result.iteritems():
+ self.assertTrue(success)
+
class ArgumentEscapingTest(DeviceTest):
def test_shell_escaping(self):
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 3329f0f..37b56e2 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -17,6 +17,8 @@
#define TRACE_TAG TRANSPORT
#include "sysdeps.h"
+#include "sysdeps/memory.h"
+
#include "transport.h"
#include <ctype.h>
@@ -79,7 +81,7 @@
read_thread_ = std::thread([this]() {
LOG(INFO) << this->transport_name_ << ": read thread spawning";
while (true) {
- std::unique_ptr<apacket> packet(new apacket());
+ auto packet = std::make_unique<apacket>();
if (!underlying_->Read(packet.get())) {
PLOG(INFO) << this->transport_name_ << ": read failed";
break;
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index ff395dc..c09fcb7 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -45,6 +45,7 @@
#include "adb_unique_fd.h"
#include "adb_utils.h"
#include "sysdeps/chrono.h"
+#include "sysdeps/memory.h"
#if ADB_HOST
@@ -450,9 +451,8 @@
#if ADB_HOST
// Emulator connection.
if (local) {
- std::unique_ptr<BlockingConnection> emulator_connection(
- new EmulatorConnection(std::move(fd), adb_port));
- t->connection.reset(new BlockingConnectionAdapter(std::move(emulator_connection)));
+ auto emulator_connection = std::make_unique<EmulatorConnection>(std::move(fd), adb_port);
+ t->connection = std::make_unique<BlockingConnectionAdapter>(std::move(emulator_connection));
std::lock_guard<std::mutex> lock(local_transports_lock);
atransport* existing_transport = find_emulator_transport_by_adb_port_locked(adb_port);
if (existing_transport != NULL) {
@@ -471,7 +471,7 @@
#endif
// Regular tcp connection.
- std::unique_ptr<BlockingConnection> fd_connection(new FdConnection(std::move(fd)));
- t->connection.reset(new BlockingConnectionAdapter(std::move(fd_connection)));
+ auto fd_connection = std::make_unique<FdConnection>(std::move(fd));
+ t->connection = std::make_unique<BlockingConnectionAdapter>(std::move(fd_connection));
return fail;
}
diff --git a/adb/transport_usb.cpp b/adb/transport_usb.cpp
index 33e00a1..e9a75cd 100644
--- a/adb/transport_usb.cpp
+++ b/adb/transport_usb.cpp
@@ -17,6 +17,7 @@
#define TRACE_TAG TRANSPORT
#include "sysdeps.h"
+#include "sysdeps/memory.h"
#include "transport.h"
#include <stdio.h>
@@ -174,8 +175,8 @@
void init_usb_transport(atransport* t, usb_handle* h) {
D("transport: usb");
- std::unique_ptr<BlockingConnection> connection(new UsbConnection(h));
- t->connection.reset(new BlockingConnectionAdapter(std::move(connection)));
+ auto connection = std::make_unique<UsbConnection>(h);
+ t->connection = std::make_unique<BlockingConnectionAdapter>(std::move(connection));
t->type = kTransportUsb;
}
diff --git a/base/Android.bp b/base/Android.bp
index 5d70d47..7b0ba11 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -50,6 +50,7 @@
"quick_exit.cpp",
"stringprintf.cpp",
"strings.cpp",
+ "threads.cpp",
"test_utils.cpp",
],
diff --git a/base/include/android-base/threads.h b/base/include/android-base/threads.h
new file mode 100644
index 0000000..85e65ba
--- /dev/null
+++ b/base/include/android-base/threads.h
@@ -0,0 +1,28 @@
+/*
+ * 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 ANDROID_BASE_THREADS_H
+#define ANDROID_BASE_THREADS_H
+
+#include <stdint.h>
+
+namespace android {
+namespace base {
+uint64_t GetThreadId();
+}
+} // namespace android
+
+#endif
diff --git a/base/logging.cpp b/base/logging.cpp
index a31feef..30d7f8d 100644
--- a/base/logging.cpp
+++ b/base/logging.cpp
@@ -21,6 +21,7 @@
#include "android-base/logging.h"
#include <fcntl.h>
+#include <inttypes.h>
#include <libgen.h>
#include <time.h>
@@ -54,41 +55,7 @@
#include <android-base/macros.h>
#include <android-base/strings.h>
-
-// For gettid.
-#if defined(__APPLE__)
-#include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED
-#include <stdint.h>
-#include <stdlib.h>
-#include <sys/syscall.h>
-#include <sys/time.h>
-#include <unistd.h>
-#elif defined(__linux__) && !defined(__ANDROID__)
-#include <syscall.h>
-#include <unistd.h>
-#elif defined(_WIN32)
-#include <windows.h>
-#endif
-
-#if defined(_WIN32)
-typedef uint32_t thread_id;
-#else
-typedef pid_t thread_id;
-#endif
-
-static thread_id GetThreadId() {
-#if defined(__BIONIC__)
- return gettid();
-#elif defined(__APPLE__)
- uint64_t tid;
- pthread_threadid_np(NULL, &tid);
- return tid;
-#elif defined(__linux__)
- return syscall(__NR_gettid);
-#elif defined(_WIN32)
- return GetCurrentThreadId();
-#endif
-}
+#include <android-base/threads.h>
namespace {
#if defined(__GLIBC__)
@@ -223,8 +190,8 @@
static_assert(arraysize(log_characters) - 1 == FATAL + 1,
"Mismatch in size of log_characters and values in LogSeverity");
char severity_char = log_characters[severity];
- fprintf(stderr, "%s %c %s %5d %5d %s:%u] %s\n", tag ? tag : "nullptr", severity_char, timestamp,
- getpid(), GetThreadId(), file, line, message);
+ fprintf(stderr, "%s %c %s %5d %5" PRIu64 " %s:%u] %s\n", tag ? tag : "nullptr", severity_char,
+ timestamp, getpid(), GetThreadId(), file, line, message);
}
void DefaultAborter(const char* abort_message) {
diff --git a/base/threads.cpp b/base/threads.cpp
new file mode 100644
index 0000000..a71382b
--- /dev/null
+++ b/base/threads.cpp
@@ -0,0 +1,48 @@
+/*
+ * 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 <android-base/threads.h>
+
+#include <stdint.h>
+#include <unistd.h>
+
+#if defined(__APPLE__)
+#include <pthread.h>
+#elif defined(__linux__) && !defined(__ANDROID__)
+#include <syscall.h>
+#elif defined(_WIN32)
+#include <windows.h>
+#endif
+
+namespace android {
+namespace base {
+
+uint64_t GetThreadId() {
+#if defined(__BIONIC__)
+ return gettid();
+#elif defined(__APPLE__)
+ uint64_t tid;
+ pthread_threadid_np(NULL, &tid);
+ return tid;
+#elif defined(__linux__)
+ return syscall(__NR_gettid);
+#elif defined(_WIN32)
+ return GetCurrentThreadId();
+#endif
+}
+
+} // namespace base
+} // namespace android
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index 8717283..08dcf77 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -188,6 +188,7 @@
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/eh_frame_hdr_begin_x86_64/*",
diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp
index ddbc12e..5586e72 100644
--- a/libunwindstack/DwarfSection.cpp
+++ b/libunwindstack/DwarfSection.cpp
@@ -190,8 +190,6 @@
// Always set the dex pc to zero when evaluating.
cur_regs->set_dex_pc(0);
- AddressType prev_cfa = regs->sp();
-
EvalInfo<AddressType> eval_info{.loc_regs = &loc_regs,
.cie = cie,
.regular_memory = regular_memory,
@@ -204,14 +202,7 @@
last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
return false;
}
- // If the stack pointer register is the CFA, and the stack
- // pointer register does not have any associated location
- // information, use the current cfa value.
- if (regs->sp_reg() == loc->values[0] && loc_regs.count(regs->sp_reg()) == 0) {
- eval_info.cfa = prev_cfa;
- } else {
- eval_info.cfa = (*cur_regs)[loc->values[0]];
- }
+ eval_info.cfa = (*cur_regs)[loc->values[0]];
eval_info.cfa += loc->values[1];
break;
case DWARF_LOCATION_VAL_EXPRESSION: {
diff --git a/libunwindstack/ElfInterfaceArm.cpp b/libunwindstack/ElfInterfaceArm.cpp
index a5afc7e..f93baeb 100644
--- a/libunwindstack/ElfInterfaceArm.cpp
+++ b/libunwindstack/ElfInterfaceArm.cpp
@@ -127,13 +127,9 @@
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->set_pc((*regs_arm)[ARM_REG_LR]);
- (*regs_arm)[ARM_REG_PC] = regs_arm->pc();
- } else {
- regs_arm->set_pc((*regs_arm)[ARM_REG_PC]);
+ (*regs_arm)[ARM_REG_PC] = (*regs_arm)[ARM_REG_LR];
}
- regs_arm->set_sp(arm.cfa());
- (*regs_arm)[ARM_REG_SP] = regs_arm->sp();
+ (*regs_arm)[ARM_REG_SP] = arm.cfa();
return_value = true;
// If the pc was set to zero, consider this the final frame.
diff --git a/libunwindstack/RegsArm.cpp b/libunwindstack/RegsArm.cpp
index 5502ce1..e2a9cb0 100644
--- a/libunwindstack/RegsArm.cpp
+++ b/libunwindstack/RegsArm.cpp
@@ -28,13 +28,28 @@
namespace unwindstack {
-RegsArm::RegsArm()
- : RegsImpl<uint32_t>(ARM_REG_LAST, ARM_REG_SP, Location(LOCATION_REGISTER, ARM_REG_LR)) {}
+RegsArm::RegsArm() : RegsImpl<uint32_t>(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;
+}
+
uint64_t RegsArm::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
uint64_t load_bias = elf->GetLoadBias();
if (rel_pc < load_bias) {
@@ -56,17 +71,13 @@
return 4;
}
-void RegsArm::SetFromRaw() {
- set_pc(regs_[ARM_REG_PC]);
- set_sp(regs_[ARM_REG_SP]);
-}
-
bool RegsArm::SetPcFromReturnAddress(Memory*) {
- if (pc() == regs_[ARM_REG_LR]) {
+ uint32_t lr = regs_[ARM_REG_LR];
+ if (regs_[ARM_REG_PC] == lr) {
return false;
}
- set_pc(regs_[ARM_REG_LR]);
+ regs_[ARM_REG_PC] = lr;
return true;
}
@@ -94,7 +105,6 @@
RegsArm* regs = new RegsArm();
memcpy(regs->RawData(), &user->regs[0], ARM_REG_LAST * sizeof(uint32_t));
- regs->SetFromRaw();
return regs;
}
@@ -103,7 +113,6 @@
RegsArm* regs = new RegsArm();
memcpy(regs->RawData(), &arm_ucontext->uc_mcontext.regs[0], ARM_REG_LAST * sizeof(uint32_t));
- regs->SetFromRaw();
return regs;
}
@@ -118,6 +127,7 @@
uint64_t offset = 0;
if (data == 0xe3a07077 || data == 0xef900077 || data == 0xdf002777) {
+ uint64_t sp = regs_[ARM_REG_SP];
// non-RT sigreturn call.
// __restore:
//
@@ -131,17 +141,18 @@
// Form 3 (thumb):
// 0x77 0x27 movs r7, #77
// 0x00 0xdf svc 0
- if (!process_memory->ReadFully(sp(), &data, sizeof(data))) {
+ if (!process_memory->ReadFully(sp, &data, sizeof(data))) {
return false;
}
if (data == 0x5ac3c35a) {
// SP + uc_mcontext offset + r0 offset.
- offset = sp() + 0x14 + 0xc;
+ offset = sp + 0x14 + 0xc;
} else {
// SP + r0 offset
- offset = sp() + 0xc;
+ offset = sp + 0xc;
}
} else if (data == 0xe3a070ad || data == 0xef9000ad || data == 0xdf0027ad) {
+ uint64_t sp = regs_[ARM_REG_SP];
// RT sigreturn call.
// __restore_rt:
//
@@ -155,15 +166,15 @@
// Form 3 (thumb):
// 0xad 0x27 movs r7, #ad
// 0x00 0xdf svc 0
- if (!process_memory->ReadFully(sp(), &data, sizeof(data))) {
+ if (!process_memory->ReadFully(sp, &data, sizeof(data))) {
return false;
}
- if (data == sp() + 8) {
+ if (data == sp + 8) {
// SP + 8 + sizeof(siginfo_t) + uc_mcontext_offset + r0 offset
- offset = sp() + 8 + 0x80 + 0x14 + 0xc;
+ offset = sp + 8 + 0x80 + 0x14 + 0xc;
} else {
// SP + sizeof(siginfo_t) + uc_mcontext_offset + r0 offset
- offset = sp() + 0x80 + 0x14 + 0xc;
+ offset = sp + 0x80 + 0x14 + 0xc;
}
}
if (offset == 0) {
@@ -173,7 +184,6 @@
if (!process_memory->ReadFully(offset, regs_.data(), sizeof(uint32_t) * ARM_REG_LAST)) {
return false;
}
- SetFromRaw();
return true;
}
diff --git a/libunwindstack/RegsArm64.cpp b/libunwindstack/RegsArm64.cpp
index cc6f5ce..fe24c80 100644
--- a/libunwindstack/RegsArm64.cpp
+++ b/libunwindstack/RegsArm64.cpp
@@ -29,12 +29,28 @@
namespace unwindstack {
RegsArm64::RegsArm64()
- : RegsImpl<uint64_t>(ARM64_REG_LAST, ARM64_REG_SP, Location(LOCATION_REGISTER, ARM64_REG_LR)) {}
+ : RegsImpl<uint64_t>(ARM64_REG_LAST, Location(LOCATION_REGISTER, ARM64_REG_LR)) {}
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) {
+ regs_[ARM64_REG_PC] = pc;
+}
+
+void RegsArm64::set_sp(uint64_t sp) {
+ regs_[ARM64_REG_SP] = sp;
+}
+
uint64_t RegsArm64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
if (!elf->valid() || rel_pc < 4) {
return 0;
@@ -42,17 +58,13 @@
return 4;
}
-void RegsArm64::SetFromRaw() {
- set_pc(regs_[ARM64_REG_PC]);
- set_sp(regs_[ARM64_REG_SP]);
-}
-
bool RegsArm64::SetPcFromReturnAddress(Memory*) {
- if (pc() == regs_[ARM64_REG_LR]) {
+ uint64_t lr = regs_[ARM64_REG_LR];
+ if (regs_[ARM64_REG_PC] == lr) {
return false;
}
- set_pc(regs_[ARM64_REG_LR]);
+ regs_[ARM64_REG_PC] = lr;
return true;
}
@@ -100,7 +112,6 @@
uint64_t* reg_data = reinterpret_cast<uint64_t*>(regs->RawData());
reg_data[ARM64_REG_PC] = user->pc;
reg_data[ARM64_REG_SP] = user->sp;
- regs->SetFromRaw();
return regs;
}
@@ -109,7 +120,6 @@
RegsArm64* regs = new RegsArm64();
memcpy(regs->RawData(), &arm64_ucontext->uc_mcontext.regs[0], ARM64_REG_LAST * sizeof(uint64_t));
- regs->SetFromRaw();
return regs;
}
@@ -131,12 +141,10 @@
}
// SP + sizeof(siginfo_t) + uc_mcontext offset + X0 offset.
- if (!process_memory->ReadFully(sp() + 0x80 + 0xb0 + 0x08, regs_.data(),
+ if (!process_memory->ReadFully(regs_[ARM64_REG_SP] + 0x80 + 0xb0 + 0x08, regs_.data(),
sizeof(uint64_t) * ARM64_REG_LAST)) {
return false;
}
-
- SetFromRaw();
return true;
}
diff --git a/libunwindstack/RegsMips.cpp b/libunwindstack/RegsMips.cpp
index 5d20bef..0b10e21 100644
--- a/libunwindstack/RegsMips.cpp
+++ b/libunwindstack/RegsMips.cpp
@@ -29,12 +29,28 @@
namespace unwindstack {
RegsMips::RegsMips()
- : RegsImpl<uint32_t>(MIPS_REG_LAST, MIPS_REG_SP, Location(LOCATION_REGISTER, MIPS_REG_RA)) {}
+ : RegsImpl<uint32_t>(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<uint32_t>(pc);
+}
+
+void RegsMips::set_sp(uint64_t sp) {
+ regs_[MIPS_REG_SP] = static_cast<uint32_t>(sp);
+}
+
uint64_t RegsMips::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
if (!elf->valid() || rel_pc < 8) {
return 0;
@@ -43,17 +59,13 @@
return 8;
}
-void RegsMips::SetFromRaw() {
- set_pc(regs_[MIPS_REG_PC]);
- set_sp(regs_[MIPS_REG_SP]);
-}
-
bool RegsMips::SetPcFromReturnAddress(Memory*) {
- if (pc() == regs_[MIPS_REG_RA]) {
+ uint32_t ra = regs_[MIPS_REG_RA];
+ if (regs_[MIPS_REG_PC] == ra) {
return false;
}
- set_pc(regs_[MIPS_REG_RA]);
+ regs_[MIPS_REG_PC] = ra;
return true;
}
@@ -101,7 +113,6 @@
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];
- regs->SetFromRaw();
return regs;
}
@@ -114,7 +125,6 @@
(*regs)[MIPS_REG_R0 + i] = mips_ucontext->uc_mcontext.sc_regs[i];
}
(*regs)[MIPS_REG_PC] = mips_ucontext->uc_mcontext.sc_pc;
- regs->SetFromRaw();
return regs;
}
@@ -149,7 +159,7 @@
// read sc_pc and sc_regs[32] from stack
uint64_t values[MIPS_REG_LAST];
- if (!process_memory->Read(sp() + offset, values, sizeof(values))) {
+ if (!process_memory->Read(regs_[MIPS_REG_SP] + offset, values, sizeof(values))) {
return false;
}
@@ -160,8 +170,6 @@
for (int i = 0; i < 32; i++) {
regs_[MIPS_REG_R0 + i] = values[1 + i];
}
-
- SetFromRaw();
return true;
}
diff --git a/libunwindstack/RegsMips64.cpp b/libunwindstack/RegsMips64.cpp
index 4a03538..8848e3b 100644
--- a/libunwindstack/RegsMips64.cpp
+++ b/libunwindstack/RegsMips64.cpp
@@ -29,13 +29,28 @@
namespace unwindstack {
RegsMips64::RegsMips64()
- : RegsImpl<uint64_t>(MIPS64_REG_LAST, MIPS64_REG_SP,
- Location(LOCATION_REGISTER, MIPS64_REG_RA)) {}
+ : RegsImpl<uint64_t>(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;
+}
+
uint64_t RegsMips64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
if (!elf->valid() || rel_pc < 8) {
return 0;
@@ -44,17 +59,13 @@
return 8;
}
-void RegsMips64::SetFromRaw() {
- set_pc(regs_[MIPS64_REG_PC]);
- set_sp(regs_[MIPS64_REG_SP]);
-}
-
bool RegsMips64::SetPcFromReturnAddress(Memory*) {
- if (pc() == regs_[MIPS64_REG_RA]) {
+ uint64_t ra = regs_[MIPS64_REG_RA];
+ if (regs_[MIPS64_REG_PC] == ra) {
return false;
}
- set_pc(regs_[MIPS64_REG_RA]);
+ regs_[MIPS64_REG_PC] = ra;
return true;
}
@@ -102,7 +113,6 @@
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];
- regs->SetFromRaw();
return regs;
}
@@ -113,7 +123,6 @@
// 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;
- regs->SetFromRaw();
return regs;
}
@@ -137,19 +146,17 @@
// 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_
- if (!process_memory->Read(sp() + 24 + 128 + 40, regs_.data(),
+ 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))) {
+ if (!process_memory->Read(sp + 24 + 128 + 40 + 576, ®s_[MIPS64_REG_PC], sizeof(uint64_t))) {
return false;
}
-
- SetFromRaw();
return true;
}
diff --git a/libunwindstack/RegsX86.cpp b/libunwindstack/RegsX86.cpp
index 573cb23..bb95a13 100644
--- a/libunwindstack/RegsX86.cpp
+++ b/libunwindstack/RegsX86.cpp
@@ -28,13 +28,28 @@
namespace unwindstack {
-RegsX86::RegsX86()
- : RegsImpl<uint32_t>(X86_REG_LAST, X86_REG_SP, Location(LOCATION_SP_OFFSET, -4)) {}
+RegsX86::RegsX86() : RegsImpl<uint32_t>(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<uint32_t>(pc);
+}
+
+void RegsX86::set_sp(uint64_t sp) {
+ regs_[X86_REG_SP] = static_cast<uint32_t>(sp);
+}
+
uint64_t RegsX86::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
if (!elf->valid() || rel_pc == 0) {
return 0;
@@ -42,19 +57,15 @@
return 1;
}
-void RegsX86::SetFromRaw() {
- set_pc(regs_[X86_REG_PC]);
- set_sp(regs_[X86_REG_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(sp_, &new_pc, sizeof(new_pc)) || new_pc == pc()) {
+ if (!process_memory->ReadFully(regs_[X86_REG_SP], &new_pc, sizeof(new_pc)) ||
+ new_pc == regs_[X86_REG_PC]) {
return false;
}
- set_pc(new_pc);
+ regs_[X86_REG_PC] = new_pc;
return true;
}
@@ -84,7 +95,6 @@
(*regs)[X86_REG_ESP] = user->esp;
(*regs)[X86_REG_EIP] = user->eip;
- regs->SetFromRaw();
return regs;
}
@@ -99,7 +109,6 @@
regs_[X86_REG_ECX] = ucontext->uc_mcontext.ecx;
regs_[X86_REG_EAX] = ucontext->uc_mcontext.eax;
regs_[X86_REG_EIP] = ucontext->uc_mcontext.eip;
- SetFromRaw();
}
Regs* RegsX86::CreateFromUcontext(void* ucontext) {
@@ -131,7 +140,7 @@
// int signum
// struct sigcontext (same format as mcontext)
struct x86_mcontext_t context;
- if (!process_memory->ReadFully(sp() + 4, &context, sizeof(context))) {
+ if (!process_memory->ReadFully(regs_[X86_REG_SP] + 4, &context, sizeof(context))) {
return false;
}
regs_[X86_REG_EBP] = context.ebp;
@@ -141,7 +150,6 @@
regs_[X86_REG_ECX] = context.ecx;
regs_[X86_REG_EAX] = context.eax;
regs_[X86_REG_EIP] = context.eip;
- SetFromRaw();
return true;
} else if ((data & 0x00ffffffffffffffULL) == 0x0080cd000000adb8ULL) {
// With SA_SIGINFO set, the return sequence is:
@@ -157,7 +165,7 @@
// Get the location of the sigcontext data.
uint32_t ptr;
- if (!process_memory->ReadFully(sp() + 8, &ptr, sizeof(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.
diff --git a/libunwindstack/RegsX86_64.cpp b/libunwindstack/RegsX86_64.cpp
index 3175a90..e57e2bc 100644
--- a/libunwindstack/RegsX86_64.cpp
+++ b/libunwindstack/RegsX86_64.cpp
@@ -28,13 +28,28 @@
namespace unwindstack {
-RegsX86_64::RegsX86_64()
- : RegsImpl<uint64_t>(X86_64_REG_LAST, X86_64_REG_SP, Location(LOCATION_SP_OFFSET, -8)) {}
+RegsX86_64::RegsX86_64() : RegsImpl<uint64_t>(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;
+}
+
uint64_t RegsX86_64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
if (!elf->valid() || rel_pc == 0) {
return 0;
@@ -42,19 +57,15 @@
return 1;
}
-void RegsX86_64::SetFromRaw() {
- set_pc(regs_[X86_64_REG_PC]);
- set_sp(regs_[X86_64_REG_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(sp_, &new_pc, sizeof(new_pc)) || new_pc == pc()) {
+ if (!process_memory->ReadFully(regs_[X86_64_REG_SP], &new_pc, sizeof(new_pc)) ||
+ new_pc == regs_[X86_64_REG_PC]) {
return false;
}
- set_pc(new_pc);
+ regs_[X86_64_REG_PC] = new_pc;
return true;
}
@@ -100,7 +111,6 @@
(*regs)[X86_64_REG_RSP] = user->rsp;
(*regs)[X86_64_REG_RIP] = user->rip;
- regs->SetFromRaw();
return regs;
}
@@ -118,8 +128,6 @@
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;
-
- SetFromRaw();
}
Regs* RegsX86_64::CreateFromUcontext(void* ucontext) {
@@ -152,7 +160,7 @@
// 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(sp() + 0x28, &x86_64_ucontext.uc_mcontext,
+ if (!process_memory->ReadFully(regs_[X86_64_REG_SP] + 0x28, &x86_64_ucontext.uc_mcontext,
sizeof(x86_64_mcontext_t))) {
return false;
}
diff --git a/libunwindstack/include/unwindstack/Regs.h b/libunwindstack/include/unwindstack/Regs.h
index b0e7ea1..4bac473 100644
--- a/libunwindstack/include/unwindstack/Regs.h
+++ b/libunwindstack/include/unwindstack/Regs.h
@@ -45,8 +45,8 @@
int16_t value;
};
- Regs(uint16_t total_regs, uint16_t sp_reg, const Location& return_loc)
- : total_regs_(total_regs), sp_reg_(sp_reg), return_loc_(return_loc) {}
+ Regs(uint16_t total_regs, const Location& return_loc)
+ : total_regs_(total_regs), return_loc_(return_loc) {}
virtual ~Regs() = default;
virtual ArchEnum Arch() = 0;
@@ -57,6 +57,9 @@
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; }
@@ -64,13 +67,10 @@
virtual bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) = 0;
- virtual void SetFromRaw() = 0;
-
virtual bool SetPcFromReturnAddress(Memory* process_memory) = 0;
virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) = 0;
- uint16_t sp_reg() { return sp_reg_; }
uint16_t total_regs() { return total_regs_; }
static ArchEnum CurrentArch();
@@ -80,7 +80,6 @@
protected:
uint16_t total_regs_;
- uint16_t sp_reg_;
Location return_loc_;
uint64_t dex_pc_ = 0;
};
@@ -88,16 +87,10 @@
template <typename AddressType>
class RegsImpl : public Regs {
public:
- RegsImpl(uint16_t total_regs, uint16_t sp_reg, Location return_loc)
- : Regs(total_regs, sp_reg, return_loc), regs_(total_regs) {}
+ RegsImpl(uint16_t total_regs, Location return_loc)
+ : Regs(total_regs, return_loc), regs_(total_regs) {}
virtual ~RegsImpl() = default;
- uint64_t pc() override { return pc_; }
- uint64_t sp() override { return sp_; }
-
- void set_pc(AddressType pc) { pc_ = pc; }
- void set_sp(AddressType sp) { sp_ = sp; }
-
bool Is32Bit() override { return sizeof(AddressType) == sizeof(uint32_t); }
inline AddressType& operator[](size_t reg) { return regs_[reg]; }
@@ -111,8 +104,6 @@
}
protected:
- AddressType pc_;
- AddressType sp_;
std::vector<AddressType> regs_;
};
diff --git a/libunwindstack/include/unwindstack/RegsArm.h b/libunwindstack/include/unwindstack/RegsArm.h
index 5af90d3..31e6797 100644
--- a/libunwindstack/include/unwindstack/RegsArm.h
+++ b/libunwindstack/include/unwindstack/RegsArm.h
@@ -34,17 +34,21 @@
RegsArm();
virtual ~RegsArm() = default;
- virtual ArchEnum Arch() override final;
+ ArchEnum Arch() override final;
uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
- void SetFromRaw() override;
-
bool SetPcFromReturnAddress(Memory* process_memory) override;
bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
- virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
+ void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
+
+ uint64_t pc() override;
+ uint64_t sp() override;
+
+ void set_pc(uint64_t pc) override;
+ void set_sp(uint64_t sp) override;
static Regs* Read(void* data);
diff --git a/libunwindstack/include/unwindstack/RegsArm64.h b/libunwindstack/include/unwindstack/RegsArm64.h
index cb05732..0c45eba 100644
--- a/libunwindstack/include/unwindstack/RegsArm64.h
+++ b/libunwindstack/include/unwindstack/RegsArm64.h
@@ -34,17 +34,21 @@
RegsArm64();
virtual ~RegsArm64() = default;
- virtual ArchEnum Arch() override final;
+ ArchEnum Arch() override final;
uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
- void SetFromRaw() override;
-
bool SetPcFromReturnAddress(Memory* process_memory) override;
bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
- virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
+ void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
+
+ uint64_t pc() override;
+ uint64_t sp() override;
+
+ void set_pc(uint64_t pc) override;
+ void set_sp(uint64_t sp) override;
static Regs* Read(void* data);
diff --git a/libunwindstack/include/unwindstack/RegsGetLocal.h b/libunwindstack/include/unwindstack/RegsGetLocal.h
index 557eace..81c0af3 100644
--- a/libunwindstack/include/unwindstack/RegsGetLocal.h
+++ b/libunwindstack/include/unwindstack/RegsGetLocal.h
@@ -51,8 +51,6 @@
: [base] "+r"(reg_data)
:
: "memory");
-
- regs->SetFromRaw();
}
#elif defined(__aarch64__)
@@ -83,8 +81,6 @@
: [base] "+r"(reg_data)
:
: "x12", "x13", "memory");
-
- regs->SetFromRaw();
}
#elif defined(__i386__) || defined(__x86_64__) || defined(__mips__)
@@ -93,8 +89,6 @@
inline void RegsGetLocal(Regs* regs) {
AsmGetRegs(regs->RawData());
-
- regs->SetFromRaw();
}
#endif
diff --git a/libunwindstack/include/unwindstack/RegsMips.h b/libunwindstack/include/unwindstack/RegsMips.h
index 8e3c01f..709f9e2 100644
--- a/libunwindstack/include/unwindstack/RegsMips.h
+++ b/libunwindstack/include/unwindstack/RegsMips.h
@@ -34,17 +34,21 @@
RegsMips();
virtual ~RegsMips() = default;
- virtual ArchEnum Arch() override final;
+ ArchEnum Arch() override final;
uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
- void SetFromRaw() override;
-
bool SetPcFromReturnAddress(Memory* process_memory) override;
bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
- virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
+ void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
+
+ uint64_t pc() override;
+ uint64_t sp() override;
+
+ void set_pc(uint64_t pc) override;
+ void set_sp(uint64_t sp) override;
static Regs* Read(void* data);
diff --git a/libunwindstack/include/unwindstack/RegsMips64.h b/libunwindstack/include/unwindstack/RegsMips64.h
index 8c2d443..1de83ea 100644
--- a/libunwindstack/include/unwindstack/RegsMips64.h
+++ b/libunwindstack/include/unwindstack/RegsMips64.h
@@ -34,17 +34,21 @@
RegsMips64();
virtual ~RegsMips64() = default;
- virtual ArchEnum Arch() override final;
+ ArchEnum Arch() override final;
uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
- void SetFromRaw() override;
-
bool SetPcFromReturnAddress(Memory* process_memory) override;
bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
- virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
+ void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
+
+ uint64_t pc() override;
+ uint64_t sp() override;
+
+ void set_pc(uint64_t pc) override;
+ void set_sp(uint64_t sp) override;
static Regs* Read(void* data);
diff --git a/libunwindstack/include/unwindstack/RegsX86.h b/libunwindstack/include/unwindstack/RegsX86.h
index 1bc145d..586c9d8 100644
--- a/libunwindstack/include/unwindstack/RegsX86.h
+++ b/libunwindstack/include/unwindstack/RegsX86.h
@@ -35,19 +35,23 @@
RegsX86();
virtual ~RegsX86() = default;
- virtual ArchEnum Arch() override final;
+ ArchEnum Arch() override final;
uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
- void SetFromRaw() override;
-
bool SetPcFromReturnAddress(Memory* process_memory) override;
bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
void SetFromUcontext(x86_ucontext_t* ucontext);
- virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
+ void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
+
+ uint64_t pc() override;
+ uint64_t sp() override;
+
+ void set_pc(uint64_t pc) override;
+ void set_sp(uint64_t sp) override;
static Regs* Read(void* data);
diff --git a/libunwindstack/include/unwindstack/RegsX86_64.h b/libunwindstack/include/unwindstack/RegsX86_64.h
index 4cd45d4..061f479 100644
--- a/libunwindstack/include/unwindstack/RegsX86_64.h
+++ b/libunwindstack/include/unwindstack/RegsX86_64.h
@@ -35,19 +35,23 @@
RegsX86_64();
virtual ~RegsX86_64() = default;
- virtual ArchEnum Arch() override final;
+ ArchEnum Arch() override final;
uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
- void SetFromRaw() override;
-
bool SetPcFromReturnAddress(Memory* process_memory) override;
bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
void SetFromUcontext(x86_64_ucontext_t* ucontext);
- virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
+ void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
+
+ uint64_t pc() override;
+ uint64_t sp() override;
+
+ void set_pc(uint64_t pc) override;
+ void set_sp(uint64_t sp) override;
static Regs* Read(void* data);
diff --git a/libunwindstack/tests/DwarfOpTest.cpp b/libunwindstack/tests/DwarfOpTest.cpp
index 6e15227..d424d5f 100644
--- a/libunwindstack/tests/DwarfOpTest.cpp
+++ b/libunwindstack/tests/DwarfOpTest.cpp
@@ -1468,7 +1468,7 @@
}
this->op_memory_.SetMemory(0, opcode_buffer);
- RegsImplFake<TypeParam> regs(32, 10);
+ RegsImplFake<TypeParam> regs(32);
for (size_t i = 0; i < 32; i++) {
regs[i] = i + 10;
}
@@ -1499,7 +1499,7 @@
};
this->op_memory_.SetMemory(0, opcode_buffer);
- RegsImplFake<TypeParam> regs(16, 10);
+ RegsImplFake<TypeParam> regs(16);
for (size_t i = 0; i < 16; i++) {
regs[i] = i + 10;
}
@@ -1526,7 +1526,7 @@
0x92, 0x80, 0x15, 0x80, 0x02};
this->op_memory_.SetMemory(0, opcode_buffer);
- RegsImplFake<TypeParam> regs(10, 10);
+ RegsImplFake<TypeParam> regs(10);
regs[5] = 0x45;
regs[6] = 0x190;
RegsInfo<TypeParam> regs_info(®s);
diff --git a/libunwindstack/tests/DwarfSectionImplTest.cpp b/libunwindstack/tests/DwarfSectionImplTest.cpp
index 99f4d87..c85764c 100644
--- a/libunwindstack/tests/DwarfSectionImplTest.cpp
+++ b/libunwindstack/tests/DwarfSectionImplTest.cpp
@@ -92,7 +92,7 @@
TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_eval_fail) {
DwarfCie cie{.version = 3, .return_address_register = 5};
- RegsImplFake<TypeParam> regs(10, 9);
+ RegsImplFake<TypeParam> regs(10);
dwarf_loc_regs_t loc_regs;
regs.set_pc(0x100);
@@ -108,7 +108,7 @@
TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_no_stack) {
DwarfCie cie{.version = 3, .return_address_register = 5};
- RegsImplFake<TypeParam> regs(10, 9);
+ RegsImplFake<TypeParam> regs(10);
dwarf_loc_regs_t loc_regs;
regs.set_pc(0x100);
@@ -124,7 +124,7 @@
TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr) {
DwarfCie cie{.version = 3, .return_address_register = 5};
- RegsImplFake<TypeParam> regs(10, 9);
+ RegsImplFake<TypeParam> regs(10);
dwarf_loc_regs_t loc_regs;
regs.set_pc(0x100);
@@ -142,7 +142,7 @@
TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_val_expr) {
DwarfCie cie{.version = 3, .return_address_register = 5};
- RegsImplFake<TypeParam> regs(10, 9);
+ RegsImplFake<TypeParam> regs(10);
dwarf_loc_regs_t loc_regs;
regs.set_pc(0x100);
@@ -160,7 +160,7 @@
TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_is_register) {
DwarfCie cie{.version = 3, .return_address_register = 5};
- RegsImplFake<TypeParam> regs(10, 9);
+ RegsImplFake<TypeParam> regs(10);
dwarf_loc_regs_t loc_regs;
regs.set_pc(0x100);
@@ -176,7 +176,7 @@
TYPED_TEST_P(DwarfSectionImplTest, Eval_bad_regs) {
DwarfCie cie{.return_address_register = 60};
- RegsImplFake<TypeParam> regs(10, 9);
+ RegsImplFake<TypeParam> regs(10);
dwarf_loc_regs_t loc_regs;
bool finished;
@@ -186,7 +186,7 @@
TYPED_TEST_P(DwarfSectionImplTest, Eval_no_cfa) {
DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10, 9);
+ RegsImplFake<TypeParam> regs(10);
dwarf_loc_regs_t loc_regs;
bool finished;
@@ -196,7 +196,7 @@
TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_bad) {
DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10, 9);
+ RegsImplFake<TypeParam> regs(10);
dwarf_loc_regs_t loc_regs;
loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {20, 0}};
@@ -225,7 +225,7 @@
TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_prev) {
DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10, 9);
+ RegsImplFake<TypeParam> regs(10);
dwarf_loc_regs_t loc_regs;
regs.set_pc(0x100);
@@ -237,12 +237,12 @@
ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
EXPECT_FALSE(finished);
EXPECT_EQ(0x20U, regs.pc());
- EXPECT_EQ(0x2000U, regs.sp());
+ EXPECT_EQ(0x3000U, regs.sp());
}
TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_from_value) {
DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10, 9);
+ RegsImplFake<TypeParam> regs(10);
dwarf_loc_regs_t loc_regs;
regs.set_pc(0x100);
@@ -260,7 +260,7 @@
TYPED_TEST_P(DwarfSectionImplTest, Eval_double_indirection) {
DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10, 9);
+ RegsImplFake<TypeParam> regs(10);
dwarf_loc_regs_t loc_regs;
regs.set_pc(0x100);
@@ -281,7 +281,7 @@
TYPED_TEST_P(DwarfSectionImplTest, Eval_register_reference_chain) {
DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10, 9);
+ RegsImplFake<TypeParam> regs(10);
dwarf_loc_regs_t loc_regs;
regs.set_pc(0x100);
@@ -312,7 +312,7 @@
TYPED_TEST_P(DwarfSectionImplTest, Eval_dex_pc) {
DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10, 9);
+ RegsImplFake<TypeParam> regs(10);
dwarf_loc_regs_t loc_regs;
regs.set_pc(0x100);
@@ -331,7 +331,7 @@
TYPED_TEST_P(DwarfSectionImplTest, Eval_invalid_register) {
DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10, 9);
+ RegsImplFake<TypeParam> regs(10);
dwarf_loc_regs_t loc_regs;
regs.set_pc(0x100);
@@ -346,7 +346,7 @@
TYPED_TEST_P(DwarfSectionImplTest, Eval_different_reg_locations) {
DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10, 9);
+ RegsImplFake<TypeParam> regs(10);
dwarf_loc_regs_t loc_regs;
if (sizeof(TypeParam) == sizeof(uint64_t)) {
@@ -380,7 +380,7 @@
TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address_undefined) {
DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10, 9);
+ RegsImplFake<TypeParam> regs(10);
dwarf_loc_regs_t loc_regs;
regs.set_pc(0x100);
@@ -398,7 +398,7 @@
TYPED_TEST_P(DwarfSectionImplTest, Eval_pc_zero) {
DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10, 9);
+ RegsImplFake<TypeParam> regs(10);
dwarf_loc_regs_t loc_regs;
regs.set_pc(0x100);
@@ -415,7 +415,7 @@
TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address) {
DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10, 9);
+ RegsImplFake<TypeParam> regs(10);
dwarf_loc_regs_t loc_regs;
regs.set_pc(0x100);
@@ -432,7 +432,7 @@
TYPED_TEST_P(DwarfSectionImplTest, Eval_ignore_large_reg_loc) {
DwarfCie cie{.return_address_register = 5};
- RegsImplFake<TypeParam> regs(10, 9);
+ RegsImplFake<TypeParam> regs(10);
dwarf_loc_regs_t loc_regs;
regs.set_pc(0x100);
@@ -451,7 +451,7 @@
TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_expr) {
DwarfCie cie{.version = 3, .return_address_register = 5};
- RegsImplFake<TypeParam> regs(10, 9);
+ RegsImplFake<TypeParam> regs(10);
dwarf_loc_regs_t loc_regs;
regs.set_pc(0x100);
@@ -471,7 +471,7 @@
TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) {
DwarfCie cie{.version = 3, .return_address_register = 5};
- RegsImplFake<TypeParam> regs(10, 9);
+ RegsImplFake<TypeParam> regs(10);
dwarf_loc_regs_t loc_regs;
regs.set_pc(0x100);
diff --git a/libunwindstack/tests/ElfFake.cpp b/libunwindstack/tests/ElfFake.cpp
index ae9da5e..66207db 100644
--- a/libunwindstack/tests/ElfFake.cpp
+++ b/libunwindstack/tests/ElfFake.cpp
@@ -65,8 +65,8 @@
}
RegsFake* fake_regs = reinterpret_cast<RegsFake*>(regs);
- fake_regs->FakeSetPc(entry.pc);
- fake_regs->FakeSetSp(entry.sp);
+ fake_regs->set_pc(entry.pc);
+ fake_regs->set_sp(entry.sp);
*finished = entry.finished;
return true;
}
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp
index eb85033..f9028c4 100644
--- a/libunwindstack/tests/ElfTest.cpp
+++ b/libunwindstack/tests/ElfTest.cpp
@@ -316,7 +316,6 @@
RegsArm regs;
regs[13] = 0x50000;
regs[15] = 0x8000;
- regs.SetFromRaw();
ElfInterfaceFake* interface = new ElfInterfaceFake(memory_);
elf.FakeSetInterface(interface);
diff --git a/libunwindstack/tests/RegsFake.h b/libunwindstack/tests/RegsFake.h
index ab23194..ede16b3 100644
--- a/libunwindstack/tests/RegsFake.h
+++ b/libunwindstack/tests/RegsFake.h
@@ -27,14 +27,16 @@
class RegsFake : public Regs {
public:
- RegsFake(uint16_t total_regs, uint16_t sp_reg)
- : Regs(total_regs, sp_reg, Regs::Location(Regs::LOCATION_UNKNOWN, 0)) {}
+ 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;
@@ -51,11 +53,7 @@
bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; }
- void SetFromRaw() override {}
-
void FakeSetArch(ArchEnum arch) { fake_arch_ = arch; }
- void FakeSetPc(uint64_t pc) { fake_pc_ = pc; }
- void FakeSetSp(uint64_t sp) { fake_sp_ = sp; }
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; }
@@ -71,19 +69,23 @@
template <typename TypeParam>
class RegsImplFake : public RegsImpl<TypeParam> {
public:
- RegsImplFake(uint16_t total_regs, uint16_t sp_reg)
- : RegsImpl<TypeParam>(total_regs, sp_reg, Regs::Location(Regs::LOCATION_UNKNOWN, 0)) {}
+ RegsImplFake(uint16_t total_regs)
+ : RegsImpl<TypeParam>(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; }
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; }
- void FakeSetPc(uint64_t pc) { this->pc_ = pc; }
- void FakeSetSp(uint64_t sp) { this->sp_ = sp; }
+ private:
+ uint64_t fake_pc_ = 0;
+ uint64_t fake_sp_ = 0;
};
} // namespace unwindstack
diff --git a/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp b/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp
index ecd4051..eac12ca 100644
--- a/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp
+++ b/libunwindstack/tests/RegsStepIfSignalHandlerTest.cpp
@@ -56,7 +56,6 @@
RegsArm regs;
regs[ARM_REG_PC] = 0x5000;
regs[ARM_REG_SP] = addr;
- regs.SetFromRaw();
elf_memory_->SetData32(0x5000, pc_data);
@@ -87,7 +86,6 @@
RegsArm regs;
regs[ARM_REG_PC] = 0x5000;
regs[ARM_REG_SP] = addr;
- regs.SetFromRaw();
elf_memory_->SetData32(0x5000, pc_data);
@@ -118,7 +116,6 @@
RegsArm64 regs;
regs[ARM64_REG_PC] = 0x8000;
regs[ARM64_REG_SP] = addr;
- regs.SetFromRaw();
elf_memory_->SetData64(0x8000, 0xd4000001d2801168ULL);
@@ -138,7 +135,6 @@
RegsX86 regs;
regs[X86_REG_EIP] = 0x4100;
regs[X86_REG_ESP] = addr;
- regs.SetFromRaw();
elf_memory_->SetData64(0x4100, 0x80cd00000077b858ULL);
for (uint64_t index = 0; index <= 25; index++) {
@@ -162,7 +158,6 @@
RegsX86 regs;
regs[X86_REG_EIP] = 0x4100;
regs[X86_REG_ESP] = addr;
- regs.SetFromRaw();
elf_memory_->SetData64(0x4100, 0x0080cd000000adb8ULL);
addr += 8;
@@ -191,7 +186,6 @@
RegsX86_64 regs;
regs[X86_64_REG_RIP] = 0x7000;
regs[X86_64_REG_RSP] = addr;
- regs.SetFromRaw();
elf_memory_->SetData64(0x7000, 0x0f0000000fc0c748);
elf_memory_->SetData16(0x7008, 0x0f05);
@@ -212,7 +206,6 @@
RegsMips regs;
regs[MIPS_REG_PC] = 0x8000;
regs[MIPS_REG_SP] = addr;
- regs.SetFromRaw();
elf_memory_->SetData64(0x8000, 0x0000000c24021017ULL);
@@ -232,7 +225,6 @@
RegsMips regs;
regs[MIPS_REG_PC] = 0x8000;
regs[MIPS_REG_SP] = addr;
- regs.SetFromRaw();
elf_memory_->SetData64(0x8000, 0x0000000c24021061ULL);
@@ -252,7 +244,6 @@
RegsMips64 regs;
regs[MIPS64_REG_PC] = 0x8000;
regs[MIPS64_REG_SP] = addr;
- regs.SetFromRaw();
elf_memory_->SetData64(0x8000, 0x0000000c2402145bULL);
diff --git a/libunwindstack/tests/RegsTest.cpp b/libunwindstack/tests/RegsTest.cpp
index 8b2f6c8..3e80733 100644
--- a/libunwindstack/tests/RegsTest.cpp
+++ b/libunwindstack/tests/RegsTest.cpp
@@ -49,9 +49,8 @@
};
TEST_F(RegsTest, regs32) {
- RegsImplFake<uint32_t> regs32(50, 10);
+ RegsImplFake<uint32_t> regs32(50);
ASSERT_EQ(50U, regs32.total_regs());
- ASSERT_EQ(10U, regs32.sp_reg());
uint32_t* raw = reinterpret_cast<uint32_t*>(regs32.RawData());
for (size_t i = 0; i < 50; i++) {
@@ -72,9 +71,8 @@
}
TEST_F(RegsTest, regs64) {
- RegsImplFake<uint64_t> regs64(30, 12);
+ RegsImplFake<uint64_t> regs64(30);
ASSERT_EQ(30U, regs64.total_regs());
- ASSERT_EQ(12U, regs64.sp_reg());
uint64_t* raw = reinterpret_cast<uint64_t*>(regs64.RawData());
for (size_t i = 0; i < 30; i++) {
@@ -211,62 +209,56 @@
EXPECT_EQ(0U, regs_mips64.GetPcAdjustment(0xa00U, invalid_elf));
}
-TEST_F(RegsTest, arm_set_from_raw) {
+TEST_F(RegsTest, arm_verify_sp_pc) {
RegsArm arm;
uint32_t* regs = reinterpret_cast<uint32_t*>(arm.RawData());
regs[13] = 0x100;
regs[15] = 0x200;
- arm.SetFromRaw();
EXPECT_EQ(0x100U, arm.sp());
EXPECT_EQ(0x200U, arm.pc());
}
-TEST_F(RegsTest, arm64_set_from_raw) {
+TEST_F(RegsTest, arm64_verify_sp_pc) {
RegsArm64 arm64;
uint64_t* regs = reinterpret_cast<uint64_t*>(arm64.RawData());
regs[31] = 0xb100000000ULL;
regs[32] = 0xc200000000ULL;
- arm64.SetFromRaw();
EXPECT_EQ(0xb100000000U, arm64.sp());
EXPECT_EQ(0xc200000000U, arm64.pc());
}
-TEST_F(RegsTest, x86_set_from_raw) {
+TEST_F(RegsTest, x86_verify_sp_pc) {
RegsX86 x86;
uint32_t* regs = reinterpret_cast<uint32_t*>(x86.RawData());
regs[4] = 0x23450000;
regs[8] = 0xabcd0000;
- x86.SetFromRaw();
EXPECT_EQ(0x23450000U, x86.sp());
EXPECT_EQ(0xabcd0000U, x86.pc());
}
-TEST_F(RegsTest, x86_64_set_from_raw) {
+TEST_F(RegsTest, x86_64_verify_sp_pc) {
RegsX86_64 x86_64;
uint64_t* regs = reinterpret_cast<uint64_t*>(x86_64.RawData());
regs[7] = 0x1200000000ULL;
regs[16] = 0x4900000000ULL;
- x86_64.SetFromRaw();
EXPECT_EQ(0x1200000000U, x86_64.sp());
EXPECT_EQ(0x4900000000U, x86_64.pc());
}
-TEST_F(RegsTest, mips_set_from_raw) {
+TEST_F(RegsTest, mips_verify_sp_pc) {
RegsMips mips;
uint32_t* regs = reinterpret_cast<uint32_t*>(mips.RawData());
regs[29] = 0x100;
regs[32] = 0x200;
- mips.SetFromRaw();
EXPECT_EQ(0x100U, mips.sp());
EXPECT_EQ(0x200U, mips.pc());
}
-TEST_F(RegsTest, mips64_set_from_raw) {
+TEST_F(RegsTest, mips64_verify_sp_pc) {
RegsMips64 mips64;
uint64_t* regs = reinterpret_cast<uint64_t*>(mips64.RawData());
regs[29] = 0xb100000000ULL;
regs[32] = 0xc200000000ULL;
- mips64.SetFromRaw();
EXPECT_EQ(0xb100000000U, mips64.sp());
EXPECT_EQ(0xc200000000U, mips64.pc());
}
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
index 515bc8c..532640f 100644
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -122,7 +122,6 @@
(*regs)[entry->second] = value;
}
fclose(fp);
- regs->SetFromRaw();
}
static std::unordered_map<std::string, uint32_t> arm_regs_;
@@ -956,4 +955,119 @@
EXPECT_EQ(0x7ffcc85971a0U, unwinder.frames()[4].sp);
}
+TEST_F(UnwindOfflineTest, art_quick_osr_stub_arm) {
+ 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, regs_->Arch());
+ unwinder.Unwind();
+
+ std::string frame_info(DumpFrames(unwinder));
+ ASSERT_EQ(25U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+ EXPECT_EQ(
+ " #00 pc 0000c788 <anonymous:d0250000> "
+ "(com.example.simpleperf.simpleperfexamplewithnative.MixActivity.access$000)\n"
+ " #01 pc 0000cdd5 <anonymous:d0250000> "
+ "(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 "
+ "(_ZN3art3jit3Jit25MaybeDoOnStackReplacementEPNS_6ThreadEPNS_9ArtMethodEjiPNS_6JValueE+876)\n"
+ " #04 pc 004021a7 libart.so (MterpMaybeDoOnStackReplacement+86)\n"
+ " #05 pc 00412474 libart.so (ExecuteMterpImpl+66164)\n"
+ " #06 pc cd8365b0 <unknown>\n" // symbol in dex file
+ " #07 pc 001d7f1b libart.so "
+ "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
+ "6JValueEb+374)\n"
+ " #08 pc 001dc593 libart.so "
+ "(_ZN3art11interpreter33ArtInterpreterToInterpreterBridgeEPNS_6ThreadERKNS_"
+ "20CodeItemDataAccessorEPNS_11ShadowFrameEPNS_6JValueE+154)\n"
+ " #09 pc 001f4d01 libart.so "
+ "(_ZN3art11interpreter6DoCallILb0ELb0EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_"
+ "11InstructionEtPNS_6JValueE+732)\n"
+ " #10 pc 003fe427 libart.so (MterpInvokeInterface+1354)\n"
+ " #11 pc 00405b94 libart.so (ExecuteMterpImpl+14740)\n"
+ " #12 pc 7004873e <unknown>\n" // symbol in dex file
+ " #13 pc 001d7f1b libart.so "
+ "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
+ "6JValueEb+374)\n"
+ " #14 pc 001dc4d5 libart.so "
+ "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
+ "20CodeItemDataAccessorEPNS_11ShadowFrameE+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 (_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+136)\n"
+ " #20 pc 00362f49 libart.so "
+ "(_ZN3art12_GLOBAL__N_118InvokeWithArgArrayERKNS_33ScopedObjectAccessAlreadyRunnableEPNS_"
+ "9ArtMethodEPNS0_8ArgArrayEPNS_6JValueEPKc+52)\n"
+ " #21 pc 00363cd9 libart.so "
+ "(_ZN3art35InvokeVirtualOrInterfaceWithJValuesERKNS_33ScopedObjectAccessAlreadyRunnableEP8_"
+ "jobjectP10_jmethodIDP6jvalue+332)\n"
+ " #22 pc 003851dd libart.so (_ZN3art6Thread14CreateCallbackEPv+868)\n"
+ " #23 pc 00062925 libc.so (_ZL15__pthread_startPv+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);
+}
+
} // namespace unwindstack
diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp
index 551f46c..2428f68 100644
--- a/libunwindstack/tests/UnwinderTest.cpp
+++ b/libunwindstack/tests/UnwinderTest.cpp
@@ -133,7 +133,7 @@
};
MapsFake UnwinderTest::maps_;
-RegsFake UnwinderTest::regs_(5, 0);
+RegsFake UnwinderTest::regs_(5);
std::shared_ptr<Memory> UnwinderTest::process_memory_(nullptr);
TEST_F(UnwinderTest, multiple_frames) {
@@ -141,8 +141,8 @@
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
- regs_.FakeSetPc(0x1000);
- regs_.FakeSetSp(0x10000);
+ regs_.set_pc(0x1000);
+ regs_.set_sp(0x10000);
ElfInterfaceFake::FakePushStepData(StepData(0x1102, 0x10010, false));
ElfInterfaceFake::FakePushStepData(StepData(0x1202, 0x10020, false));
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
@@ -201,8 +201,8 @@
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
- regs_.FakeSetPc(0x1000);
- regs_.FakeSetSp(0x10000);
+ regs_.set_pc(0x1000);
+ regs_.set_sp(0x10000);
ElfInterfaceFake::FakePushStepData(StepData(0x1102, 0x10010, false));
ElfInterfaceFake::FakePushStepData(StepData(0x1202, 0x10020, false));
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
@@ -260,8 +260,8 @@
TEST_F(UnwinderTest, non_zero_load_bias) {
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
- regs_.FakeSetPc(0xa5500);
- regs_.FakeSetSp(0x10000);
+ regs_.set_pc(0xa5500);
+ regs_.set_sp(0x10000);
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
Unwinder unwinder(64, &maps_, ®s_, process_memory_);
@@ -288,8 +288,8 @@
TEST_F(UnwinderTest, non_zero_elf_offset) {
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
- regs_.FakeSetPc(0xa7500);
- regs_.FakeSetSp(0x10000);
+ regs_.set_pc(0xa7500);
+ regs_.set_sp(0x10000);
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
Unwinder unwinder(64, &maps_, ®s_, process_memory_);
@@ -316,8 +316,8 @@
TEST_F(UnwinderTest, non_zero_map_offset) {
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
- regs_.FakeSetPc(0x43000);
- regs_.FakeSetSp(0x10000);
+ regs_.set_pc(0x43000);
+ regs_.set_sp(0x10000);
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
Unwinder unwinder(64, &maps_, ®s_, process_memory_);
@@ -349,8 +349,8 @@
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame3", 3));
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame4", 4));
- regs_.FakeSetPc(0x1000);
- regs_.FakeSetSp(0x10000);
+ 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));
@@ -383,8 +383,8 @@
ElfInterfaceFake::FakePushStepData(StepData(0x1102 + i * 0x100, 0x10010 + i * 0x10, false));
}
- regs_.FakeSetPc(0x1000);
- regs_.FakeSetSp(0x10000);
+ regs_.set_pc(0x1000);
+ regs_.set_sp(0x10000);
Unwinder unwinder(20, &maps_, ®s_, process_memory_);
unwinder.Unwind();
@@ -415,8 +415,8 @@
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
- regs_.FakeSetPc(0x20000);
- regs_.FakeSetSp(0x10000);
+ regs_.set_pc(0x20000);
+ regs_.set_sp(0x10000);
ElfInterfaceFake::FakePushStepData(StepData(0x23002, 0x10010, false));
ElfInterfaceFake::FakePushStepData(StepData(0x23102, 0x10020, false));
ElfInterfaceFake::FakePushStepData(StepData(0x20002, 0x10030, false));
@@ -481,8 +481,8 @@
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
- regs_.FakeSetPc(0x1000);
- regs_.FakeSetSp(0x63000);
+ regs_.set_pc(0x1000);
+ regs_.set_sp(0x63000);
ElfInterfaceFake::FakePushStepData(StepData(0x21002, 0x50020, false));
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
@@ -527,8 +527,8 @@
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
- regs_.FakeSetPc(0x13000);
- regs_.FakeSetSp(0x10000);
+ 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));
@@ -546,8 +546,8 @@
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
- regs_.FakeSetPc(0x1000);
- regs_.FakeSetSp(0x13000);
+ 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));
@@ -563,8 +563,8 @@
TEST_F(UnwinderTest, pc_without_map) {
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
- regs_.FakeSetPc(0x41000);
- regs_.FakeSetSp(0x13000);
+ regs_.set_pc(0x41000);
+ regs_.set_sp(0x13000);
Unwinder unwinder(64, &maps_, ®s_, process_memory_);
unwinder.Unwind();
@@ -593,8 +593,8 @@
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
// Fake as if code called a nullptr function.
- regs_.FakeSetPc(0);
- regs_.FakeSetSp(0x10000);
+ regs_.set_pc(0);
+ regs_.set_sp(0x10000);
regs_.FakeSetReturnAddress(0x1202);
regs_.FakeSetReturnAddressValid(true);
@@ -657,8 +657,8 @@
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
// Fake as if code called a nullptr function.
- regs_.FakeSetPc(0);
- regs_.FakeSetSp(0x10000);
+ regs_.set_pc(0);
+ regs_.set_sp(0x10000);
regs_.FakeSetReturnAddress(0x1202);
regs_.FakeSetReturnAddressValid(true);
@@ -691,8 +691,8 @@
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame3", 3));
// Fake as if code called a nullptr function.
- regs_.FakeSetPc(0x1000);
- regs_.FakeSetSp(0x10000);
+ regs_.set_pc(0x1000);
+ regs_.set_sp(0x10000);
ElfInterfaceFake::FakePushStepData(StepData(0x43402, 0x10010, false));
ElfInterfaceFake::FakePushStepData(StepData(0x53502, 0x10020, false));
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
@@ -745,8 +745,8 @@
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame3", 3));
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame4", 4));
- regs_.FakeSetPc(0x1000);
- regs_.FakeSetSp(0x10000);
+ regs_.set_pc(0x1000);
+ regs_.set_sp(0x10000);
ElfInterfaceFake::FakePushStepData(StepData(0x33402, 0x10010, false));
ElfInterfaceFake::FakePushStepData(StepData(0x33502, 0x10020, false));
ElfInterfaceFake::FakePushStepData(StepData(0x33502, 0x10020, false));
@@ -805,8 +805,8 @@
TEST_F(UnwinderTest, dex_pc_in_map) {
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
- regs_.FakeSetPc(0x1000);
- regs_.FakeSetSp(0x10000);
+ regs_.set_pc(0x1000);
+ regs_.set_sp(0x10000);
regs_.FakeSetDexPc(0xa3400);
Unwinder unwinder(64, &maps_, ®s_, process_memory_);
@@ -846,8 +846,8 @@
TEST_F(UnwinderTest, dex_pc_not_in_map) {
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
- regs_.FakeSetPc(0x1000);
- regs_.FakeSetSp(0x10000);
+ regs_.set_pc(0x1000);
+ regs_.set_sp(0x10000);
regs_.FakeSetDexPc(0x50000);
Unwinder unwinder(64, &maps_, ®s_, process_memory_);
@@ -888,8 +888,8 @@
TEST_F(UnwinderTest, dex_pc_multiple_frames) {
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
- regs_.FakeSetPc(0x1000);
- regs_.FakeSetSp(0x10000);
+ regs_.set_pc(0x1000);
+ regs_.set_sp(0x10000);
regs_.FakeSetDexPc(0xa3400);
ElfInterfaceFake::FakePushStepData(StepData(0x33402, 0x10010, false));
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
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
new file mode 100644
index 0000000..300646b
--- /dev/null
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/descriptor.data
Binary files 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
new file mode 100644
index 0000000..999cb79
--- /dev/null
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry0.data
Binary files 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
new file mode 100644
index 0000000..6aa1c82
--- /dev/null
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/entry1.data
Binary files 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
new file mode 100644
index 0000000..19d7b65
--- /dev/null
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit0.data
Binary files 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
new file mode 100644
index 0000000..edcd3e1
--- /dev/null
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/jit1.data
Binary files 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
new file mode 100644
index 0000000..09ba495
--- /dev/null
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libart.so
Binary files 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
new file mode 100644
index 0000000..39c9025
--- /dev/null
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/libc.so
Binary files 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
new file mode 100644
index 0000000..55aaaf6
--- /dev/null
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/maps.txt
@@ -0,0 +1,3 @@
+d0250000-d2600000 r-xp 0 00:00 0 <anonymous:d0250000>
+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/art_quick_osr_stub_arm/regs.txt b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/regs.txt
new file mode 100644
index 0000000..0b51814
--- /dev/null
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/regs.txt
@@ -0,0 +1,16 @@
+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
new file mode 100644
index 0000000..f00917b
--- /dev/null
+++ b/libunwindstack/tests/files/offline/art_quick_osr_stub_arm/stack.data
Binary files differ