Merge "fastboot: only require Linux modules on Linux"
diff --git a/adb/Android.bp b/adb/Android.bp
index 41f7b89..0858a6c 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -13,39 +13,39 @@
// limitations under the License.
python_binary_host {
- name: "adb_integration_test_adb",
- main: "test_adb.py",
- srcs: [
- "test_adb.py",
- ],
- libs: [
- "adb_py",
- ],
- version: {
- py2: {
- enabled: true,
+ name: "adb_integration_test_adb",
+ main: "test_adb.py",
+ srcs: [
+ "test_adb.py",
+ ],
+ libs: [
+ "adb_py",
+ ],
+ version: {
+ py2: {
+ enabled: true,
+ },
+ py3: {
+ enabled: false,
+ },
},
- py3: {
- enabled: false,
- },
- },
}
python_binary_host {
- name: "adb_integration_test_device",
- main: "test_device.py",
- srcs: [
- "test_device.py",
- ],
- libs: [
- "adb_py",
- ],
- version: {
- py2: {
- enabled: true,
+ name: "adb_integration_test_device",
+ main: "test_device.py",
+ srcs: [
+ "test_device.py",
+ ],
+ libs: [
+ "adb_py",
+ ],
+ version: {
+ py2: {
+ enabled: true,
+ },
+ py3: {
+ enabled: false,
+ },
},
- py3: {
- enabled: false,
- },
- },
}
diff --git a/adb/adb.cpp b/adb/adb.cpp
index ee3503b..c4df5c4 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -42,7 +42,6 @@
#include <android-base/logging.h>
#include <android-base/macros.h>
#include <android-base/parsenetaddress.h>
-#include <android-base/quick_exit.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
@@ -105,31 +104,27 @@
}
uint32_t calculate_apacket_checksum(const apacket* p) {
- const unsigned char* x = reinterpret_cast<const unsigned char*>(p->data);
uint32_t sum = 0;
- size_t count = p->msg.data_length;
-
- while (count-- > 0) {
- sum += *x++;
+ for (size_t i = 0; i < p->msg.data_length; ++i) {
+ sum += static_cast<uint8_t>(p->payload[i]);
}
-
return sum;
}
apacket* get_apacket(void)
{
- apacket* p = reinterpret_cast<apacket*>(malloc(sizeof(apacket)));
+ apacket* p = new apacket();
if (p == nullptr) {
fatal("failed to allocate an apacket");
}
- memset(p, 0, sizeof(apacket) - MAX_PAYLOAD);
+ memset(&p->msg, 0, sizeof(p->msg));
return p;
}
void put_apacket(apacket *p)
{
- free(p);
+ delete p;
}
void handle_online(atransport *t)
@@ -155,8 +150,7 @@
#define DUMPMAX 32
void print_packet(const char *label, apacket *p)
{
- char *tag;
- char *x;
+ const char* tag;
unsigned count;
switch(p->msg.command){
@@ -173,15 +167,15 @@
fprintf(stderr, "%s: %s %08x %08x %04x \"",
label, tag, p->msg.arg0, p->msg.arg1, p->msg.data_length);
count = p->msg.data_length;
- x = (char*) p->data;
- if(count > DUMPMAX) {
+ const char* x = p->payload.data();
+ if (count > DUMPMAX) {
count = DUMPMAX;
tag = "\n";
} else {
tag = "\"\n";
}
- while(count-- > 0){
- if((*x >= ' ') && (*x < 127)) {
+ while (count-- > 0) {
+ if ((*x >= ' ') && (*x < 127)) {
fputc(*x, stderr);
} else {
fputc('.', stderr);
@@ -254,8 +248,8 @@
<< connection_str.length() << ")";
}
- memcpy(cp->data, connection_str.c_str(), connection_str.length());
- cp->msg.data_length = connection_str.length();
+ cp->payload = std::move(connection_str);
+ cp->msg.data_length = cp->payload.size();
send_packet(cp, t);
}
@@ -329,9 +323,7 @@
}
t->update_version(p->msg.arg0, p->msg.arg1);
- std::string banner(reinterpret_cast<const char*>(p->data),
- p->msg.data_length);
- parse_banner(banner, t);
+ parse_banner(p->payload, t);
#if ADB_HOST
handle_online(t);
@@ -354,6 +346,7 @@
((char*) (&(p->msg.command)))[2],
((char*) (&(p->msg.command)))[3]);
print_packet("recv", p);
+ CHECK_EQ(p->payload.size(), p->msg.data_length);
switch(p->msg.command){
case A_SYNC:
@@ -380,11 +373,11 @@
if (t->GetConnectionState() == kCsOffline) {
t->SetConnectionState(kCsUnauthorized);
}
- send_auth_response(p->data, p->msg.data_length, t);
+ send_auth_response(p->payload.data(), p->msg.data_length, t);
break;
#else
case ADB_AUTH_SIGNATURE:
- if (adbd_auth_verify(t->token, sizeof(t->token), p->data, p->msg.data_length)) {
+ if (adbd_auth_verify(t->token, sizeof(t->token), p->payload)) {
adbd_auth_verified(t);
t->failed_auth_attempts = 0;
} else {
@@ -394,7 +387,7 @@
break;
case ADB_AUTH_RSAPUBLICKEY:
- adbd_auth_confirm_key(p->data, p->msg.data_length, t);
+ adbd_auth_confirm_key(p->payload.data(), p->msg.data_length, t);
break;
#endif
default:
@@ -406,9 +399,7 @@
case A_OPEN: /* OPEN(local-id, 0, "destination") */
if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) {
- char *name = (char*) p->data;
- name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
- asocket* s = create_local_service_socket(name, t);
+ asocket* s = create_local_service_socket(p->payload.c_str(), t);
if (s == nullptr) {
send_close(0, p->msg.arg0, t);
} else {
@@ -474,11 +465,7 @@
asocket* s = find_local_socket(p->msg.arg1, p->msg.arg0);
if (s) {
unsigned rid = p->msg.arg0;
-
- // TODO: Convert apacket::data to a type that we can move out of.
- std::string copy(p->data, p->data + p->msg.data_length);
-
- if (s->enqueue(s, std::move(copy)) == 0) {
+ if (s->enqueue(s, std::move(p->payload)) == 0) {
D("Enqueue the socket");
send_ready(s->id, rid, t);
}
@@ -1071,7 +1058,7 @@
SendOkay(reply_fd);
// Rely on process exit to close the socket for us.
- android::base::quick_exit(0);
+ exit(0);
}
// "transport:" is used for switching transport with a specified serial number
diff --git a/adb/adb.h b/adb/adb.h
index c9c635a..a6d0463 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -74,7 +74,7 @@
struct apacket {
amessage msg;
- char data[MAX_PAYLOAD];
+ std::string payload;
};
uint32_t calculate_apacket_checksum(const apacket* packet);
diff --git a/adb/adb_auth.h b/adb/adb_auth.h
index a6f224f..715e04f 100644
--- a/adb/adb_auth.h
+++ b/adb/adb_auth.h
@@ -49,7 +49,7 @@
void adbd_auth_verified(atransport *t);
void adbd_cloexec_auth_socket();
-bool adbd_auth_verify(const char* token, size_t token_size, const char* sig, int sig_len);
+bool adbd_auth_verify(const char* token, size_t token_size, const std::string& sig);
void adbd_auth_confirm_key(const char* data, size_t len, atransport* t);
void send_auth_request(atransport *t);
diff --git a/adb/adb_auth_host.cpp b/adb/adb_auth_host.cpp
index 365bf77..c3aef16 100644
--- a/adb/adb_auth_host.cpp
+++ b/adb/adb_auth_host.cpp
@@ -299,20 +299,25 @@
return result;
}
-static int adb_auth_sign(RSA* key, const char* token, size_t token_size, char* sig) {
+static std::string adb_auth_sign(RSA* key, const char* token, size_t token_size) {
if (token_size != TOKEN_SIZE) {
D("Unexpected token size %zd", token_size);
return 0;
}
+ std::string result;
+ result.resize(MAX_PAYLOAD);
+
unsigned int len;
if (!RSA_sign(NID_sha1, reinterpret_cast<const uint8_t*>(token), token_size,
- reinterpret_cast<uint8_t*>(sig), &len, key)) {
- return 0;
+ reinterpret_cast<uint8_t*>(&result[0]), &len, key)) {
+ return std::string();
}
+ result.resize(len);
+
D("adb_auth_sign len=%d", len);
- return (int)len;
+ return result;
}
std::string adb_auth_get_userkey() {
@@ -446,13 +451,14 @@
}
apacket* p = get_apacket();
- memcpy(p->data, key.c_str(), key.size() + 1);
-
p->msg.command = A_AUTH;
p->msg.arg0 = ADB_AUTH_RSAPUBLICKEY;
+ p->payload = std::move(key);
+
// adbd expects a null-terminated string.
- p->msg.data_length = key.size() + 1;
+ p->payload.push_back('\0');
+ p->msg.data_length = p->payload.size();
send_packet(p, t);
}
@@ -467,8 +473,8 @@
LOG(INFO) << "Calling send_auth_response";
apacket* p = get_apacket();
- int ret = adb_auth_sign(key.get(), token, token_size, p->data);
- if (!ret) {
+ std::string result = adb_auth_sign(key.get(), token, token_size);
+ if (result.empty()) {
D("Error signing the token");
put_apacket(p);
return;
@@ -476,6 +482,7 @@
p->msg.command = A_AUTH;
p->msg.arg0 = ADB_AUTH_SIGNATURE;
- p->msg.data_length = ret;
+ p->payload = std::move(result);
+ p->msg.data_length = p->payload.size();
send_packet(p, t);
}
diff --git a/adb/adbd_auth.cpp b/adb/adbd_auth.cpp
index 3488ad1..3fd2b31 100644
--- a/adb/adbd_auth.cpp
+++ b/adb/adbd_auth.cpp
@@ -46,7 +46,7 @@
bool auth_required = true;
-bool adbd_auth_verify(const char* token, size_t token_size, const char* sig, int sig_len) {
+bool adbd_auth_verify(const char* token, size_t token_size, const std::string& sig) {
static constexpr const char* key_paths[] = { "/adb_keys", "/data/misc/adb/adb_keys", nullptr };
for (const auto& path : key_paths) {
@@ -80,7 +80,8 @@
bool verified =
(RSA_verify(NID_sha1, reinterpret_cast<const uint8_t*>(token), token_size,
- reinterpret_cast<const uint8_t*>(sig), sig_len, key) == 1);
+ reinterpret_cast<const uint8_t*>(sig.c_str()), sig.size(),
+ key) == 1);
RSA_free(key);
if (verified) return true;
}
@@ -210,10 +211,10 @@
}
apacket* p = get_apacket();
- memcpy(p->data, t->token, sizeof(t->token));
p->msg.command = A_AUTH;
p->msg.arg0 = ADB_AUTH_TOKEN;
p->msg.data_length = sizeof(t->token);
+ p->payload.assign(t->token, t->token + sizeof(t->token));
send_packet(p, t);
}
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index f0d0ce7..31cb853 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -28,7 +28,6 @@
#include <android-base/errors.h>
#include <android-base/file.h>
#include <android-base/logging.h>
-#include <android-base/quick_exit.h>
#include <android-base/stringprintf.h>
#include "adb.h"
@@ -61,7 +60,7 @@
static BOOL WINAPI ctrlc_handler(DWORD type) {
// TODO: Consider trying to kill a starting up adb server (if we're in
// launch_server) by calling GenerateConsoleCtrlEvent().
- android::base::quick_exit(STATUS_CONTROL_C_EXIT);
+ exit(STATUS_CONTROL_C_EXIT);
return TRUE;
}
#endif
@@ -76,6 +75,12 @@
usb_cleanup();
}
+static void intentionally_leak() {
+ void* p = ::operator new(1);
+ // The analyzer is upset about this leaking. NOLINTNEXTLINE
+ LOG(INFO) << "leaking pointer " << p;
+}
+
int adb_server_main(int is_daemon, const std::string& socket_spec, int ack_reply_fd) {
#if defined(_WIN32)
// adb start-server starts us up with stdout and stderr hooked up to
@@ -95,16 +100,21 @@
SetConsoleCtrlHandler(ctrlc_handler, TRUE);
#else
signal(SIGINT, [](int) {
- fdevent_run_on_main_thread([]() { android::base::quick_exit(0); });
+ fdevent_run_on_main_thread([]() { exit(0); });
});
#endif
+ char* leak = getenv("ADB_LEAK");
+ if (leak && strcmp(leak, "1") == 0) {
+ intentionally_leak();
+ }
+
if (is_daemon) {
close_stdin();
setup_daemon_logging();
}
- android::base::at_quick_exit(adb_server_cleanup);
+ atexit(adb_server_cleanup);
init_transport_registration();
init_mdns_transport_discovery();
diff --git a/adb/client/usb_libusb.cpp b/adb/client/usb_libusb.cpp
index 18f585d..46c3f58 100644
--- a/adb/client/usb_libusb.cpp
+++ b/adb/client/usb_libusb.cpp
@@ -19,6 +19,7 @@
#include "sysdeps.h"
#include <stdint.h>
+#include <stdlib.h>
#include <atomic>
#include <chrono>
@@ -33,7 +34,6 @@
#include <android-base/file.h>
#include <android-base/logging.h>
-#include <android-base/quick_exit.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp
index b28de4b..d285561 100644
--- a/adb/fdevent.cpp
+++ b/adb/fdevent.cpp
@@ -26,6 +26,7 @@
#include <unistd.h>
#include <atomic>
+#include <deque>
#include <functional>
#include <list>
#include <mutex>
@@ -81,7 +82,7 @@
static auto& run_queue_notify_fd = *new unique_fd();
static auto& run_queue_mutex = *new std::mutex();
-static auto& run_queue GUARDED_BY(run_queue_mutex) = *new std::vector<std::function<void()>>();
+static auto& run_queue GUARDED_BY(run_queue_mutex) = *new std::deque<std::function<void()>>();
void check_main_thread() {
if (main_thread_valid) {
@@ -359,11 +360,21 @@
}
#endif // !ADB_HOST
-static void fdevent_run_flush() REQUIRES(run_queue_mutex) {
- for (auto& f : run_queue) {
- f();
+static void fdevent_run_flush() EXCLUDES(run_queue_mutex) {
+ // We need to be careful around reentrancy here, since a function we call can queue up another
+ // function.
+ while (true) {
+ std::function<void()> fn;
+ {
+ std::lock_guard<std::mutex> lock(run_queue_mutex);
+ if (run_queue.empty()) {
+ break;
+ }
+ fn = run_queue.front();
+ run_queue.pop_front();
+ }
+ fn();
}
- run_queue.clear();
}
static void fdevent_run_func(int fd, unsigned ev, void* /* userdata */) {
@@ -377,22 +388,23 @@
PLOG(FATAL) << "failed to empty run queue notify fd";
}
- std::lock_guard<std::mutex> lock(run_queue_mutex);
fdevent_run_flush();
}
static void fdevent_run_setup() {
- std::lock_guard<std::mutex> lock(run_queue_mutex);
- CHECK(run_queue_notify_fd.get() == -1);
- int s[2];
- if (adb_socketpair(s) != 0) {
- PLOG(FATAL) << "failed to create run queue notify socketpair";
- }
+ {
+ std::lock_guard<std::mutex> lock(run_queue_mutex);
+ CHECK(run_queue_notify_fd.get() == -1);
+ int s[2];
+ if (adb_socketpair(s) != 0) {
+ PLOG(FATAL) << "failed to create run queue notify socketpair";
+ }
- run_queue_notify_fd.reset(s[0]);
- fdevent* fde = fdevent_create(s[1], fdevent_run_func, nullptr);
- CHECK(fde != nullptr);
- fdevent_add(fde, FDE_READ);
+ run_queue_notify_fd.reset(s[0]);
+ fdevent* fde = fdevent_create(s[1], fdevent_run_func, nullptr);
+ CHECK(fde != nullptr);
+ fdevent_add(fde, FDE_READ);
+ }
fdevent_run_flush();
}
diff --git a/adb/fdevent_test.cpp b/adb/fdevent_test.cpp
index 86e0209..63cc4d1 100644
--- a/adb/fdevent_test.cpp
+++ b/adb/fdevent_test.cpp
@@ -194,3 +194,31 @@
ASSERT_EQ(i, vec[i]);
}
}
+
+static std::function<void()> make_appender(std::vector<int>* vec, int value) {
+ return [vec, value]() {
+ check_main_thread();
+ if (value == 100) {
+ return;
+ }
+
+ vec->push_back(value);
+ fdevent_run_on_main_thread(make_appender(vec, value + 1));
+ };
+}
+
+TEST_F(FdeventTest, run_on_main_thread_reentrant) {
+ std::vector<int> vec;
+
+ PrepareThread();
+ std::thread thread(fdevent_loop);
+
+ fdevent_run_on_main_thread(make_appender(&vec, 0));
+
+ TerminateThread(thread);
+
+ ASSERT_EQ(100u, vec.size());
+ for (int i = 0; i < 100; ++i) {
+ ASSERT_EQ(i, vec[i]);
+ }
+}
diff --git a/adb/jdwp_service.cpp b/adb/jdwp_service.cpp
index 7adbf2d..6f5396a 100644
--- a/adb/jdwp_service.cpp
+++ b/adb/jdwp_service.cpp
@@ -124,9 +124,6 @@
** for each JDWP process, we record its pid and its connected socket
**/
-// PIDs are transmitted as 4 hex digits in ascii.
-static constexpr size_t PID_LEN = 4;
-
static void jdwp_process_event(int socket, unsigned events, void* _proc);
static void jdwp_process_list_updated(void);
@@ -174,7 +171,7 @@
_jdwp_list.remove_if(pred);
}
- int pid = -1;
+ int32_t pid = -1;
int socket = -1;
fdevent* fde = nullptr;
@@ -221,17 +218,9 @@
if (events & FDE_READ) {
if (proc->pid < 0) {
- /* read the PID as a 4-hexchar string */
- char buf[PID_LEN + 1];
- ssize_t rc = TEMP_FAILURE_RETRY(recv(socket, buf, PID_LEN, 0));
- if (rc != PID_LEN) {
- D("failed to read jdwp pid: %s", strerror(errno));
- goto CloseProcess;
- }
- buf[PID_LEN] = '\0';
-
- if (sscanf(buf, "%04x", &proc->pid) != 1) {
- D("could not decode JDWP %p PID number: '%s'", proc, buf);
+ ssize_t rc = TEMP_FAILURE_RETRY(recv(socket, &proc->pid, sizeof(proc->pid), 0));
+ if (rc != sizeof(proc->pid)) {
+ D("failed to read jdwp pid: rc = %zd, errno = %s", rc, strerror(errno));
goto CloseProcess;
}
diff --git a/adb/remount_service.cpp b/adb/remount_service.cpp
index 32ed28f..a4c7a5a 100644
--- a/adb/remount_service.cpp
+++ b/adb/remount_service.cpp
@@ -62,9 +62,9 @@
// The proc entry for / is full of lies, so check fstab instead.
// /proc/mounts lists rootfs and /dev/root, neither of which is what we want.
-static std::string find_mount(const char* dir) {
- if (strcmp(dir, "/") == 0) {
- return find_fstab_mount(dir);
+static std::string find_mount(const char* dir, bool is_root) {
+ if (is_root) {
+ return find_fstab_mount(dir);
} else {
return find_proc_mount(dir);
}
@@ -86,17 +86,29 @@
if (!directory_exists(dir)) {
return true;
}
- std::string dev = find_mount(dir);
- if (dev.empty()) {
+ bool is_root = strcmp(dir, "/") == 0;
+ std::string dev = find_mount(dir, is_root);
+ // Even if the device for the root is not found, we still try to remount it
+ // as rw. This typically only happens when running Android in a container:
+ // the root will almost always be in a loop device, which is dynamic, so
+ // it's not convenient to put in the fstab.
+ if (dev.empty() && !is_root) {
return true;
}
- if (!make_block_device_writable(dev)) {
+ if (!dev.empty() && !make_block_device_writable(dev)) {
WriteFdFmt(fd, "remount of %s failed; couldn't make block device %s writable: %s\n",
dir, dev.c_str(), strerror(errno));
return false;
}
+ if (mount(dev.c_str(), dir, "none", MS_REMOUNT | MS_BIND, nullptr) == -1) {
+ // This is useful for cases where the superblock is already marked as
+ // read-write, but the mount itself is read-only, such as containers
+ // where the remount with just MS_REMOUNT is forbidden by the kernel.
+ WriteFdFmt(fd, "remount of the %s mount failed: %s.\n", dir, strerror(errno));
+ return false;
+ }
if (mount(dev.c_str(), dir, "none", MS_REMOUNT, nullptr) == -1) {
- WriteFdFmt(fd, "remount of %s failed: %s\n", dir, strerror(errno));
+ WriteFdFmt(fd, "remount of the %s superblock failed: %s\n", dir, strerror(errno));
return false;
}
return true;
diff --git a/adb/services.cpp b/adb/services.cpp
index 6dc71cf..fe74eb6 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -296,6 +296,7 @@
void* arg = strdup(name + 7);
if (arg == NULL) return -1;
ret = create_service_thread("reboot", reboot_service, arg);
+ if (ret < 0) free(arg);
} else if(!strncmp(name, "root:", 5)) {
ret = create_service_thread("root", restart_root_service, nullptr);
} else if(!strncmp(name, "unroot:", 7)) {
diff --git a/adb/socket.h b/adb/socket.h
index 34915b6..2f09080 100644
--- a/adb/socket.h
+++ b/adb/socket.h
@@ -59,7 +59,7 @@
* us to our fd event system. For remote asockets
* these fields are not used.
*/
- fdevent fde = {0};
+ fdevent fde = {};
int fd = 0;
// queue of data waiting to be written
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index 307cbfe..0007fed 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -413,15 +413,15 @@
p->msg.command = A_WRTE;
p->msg.arg0 = s->peer->id;
p->msg.arg1 = s->id;
- p->msg.data_length = data.size();
- if (data.size() > sizeof(p->data)) {
+ if (data.size() > MAX_PAYLOAD) {
put_apacket(p);
return -1;
}
- // TODO: Convert apacket::data to a type that we can move into.
- memcpy(p->data, data.data(), data.size());
+ p->payload = std::move(data);
+ p->msg.data_length = p->payload.size();
+
send_packet(p, s->transport);
return 1;
}
@@ -482,17 +482,20 @@
void connect_to_remote(asocket* s, const char* destination) {
D("Connect_to_remote call RS(%d) fd=%d", s->id, s->fd);
apacket* p = get_apacket();
- size_t len = strlen(destination) + 1;
-
- if (len > (s->get_max_payload() - 1)) {
- fatal("destination oversized");
- }
D("LS(%d): connect('%s')", s->id, destination);
p->msg.command = A_OPEN;
p->msg.arg0 = s->id;
- p->msg.data_length = len;
- strcpy((char*)p->data, destination);
+
+ // adbd expects a null-terminated string.
+ p->payload = destination;
+ p->payload.push_back('\0');
+ p->msg.data_length = p->payload.size();
+
+ if (p->msg.data_length > s->get_max_payload()) {
+ fatal("destination oversized");
+ }
+
send_packet(p, s->transport);
}
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 9ae1297..6b1a00b 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -34,7 +34,6 @@
#include <android-base/logging.h>
#include <android-base/parsenetaddress.h>
-#include <android-base/quick_exit.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/thread_annotations.h>
@@ -72,12 +71,14 @@
return false;
}
- if (packet->msg.data_length > sizeof(packet->data)) {
+ if (packet->msg.data_length > MAX_PAYLOAD) {
D("remote local: read overflow (data length = %" PRIu32 ")", packet->msg.data_length);
return false;
}
- if (!ReadFdExactly(fd_.get(), &packet->data, packet->msg.data_length)) {
+ packet->payload.resize(packet->msg.data_length);
+
+ if (!ReadFdExactly(fd_.get(), &packet->payload[0], packet->payload.size())) {
D("remote local: terminated (data)");
return false;
}
@@ -86,13 +87,18 @@
}
bool FdConnection::Write(apacket* packet) {
- uint32_t length = packet->msg.data_length;
-
- if (!WriteFdExactly(fd_.get(), &packet->msg, sizeof(amessage) + length)) {
+ if (!WriteFdExactly(fd_.get(), &packet->msg, sizeof(packet->msg))) {
D("remote local: write terminated");
return false;
}
+ if (packet->msg.data_length) {
+ if (!WriteFdExactly(fd_.get(), &packet->payload[0], packet->msg.data_length)) {
+ D("remote local: write terminated");
+ return false;
+ }
+ }
+
return true;
}
@@ -133,7 +139,7 @@
std::string result = android::base::StringPrintf("%s: %s: [%s] arg0=%s arg1=%s (len=%d) ", name,
func, cmd, arg0, arg1, len);
- result += dump_hex(p->data, len);
+ result += dump_hex(p->payload.data(), p->payload.size());
return result;
}
@@ -191,9 +197,10 @@
apacket* p = 0;
if (read_packet(fd, t->serial, &p)) {
D("%s: failed to read packet from transport socket on fd %d", t->serial, fd);
- } else {
- handle_packet(p, (atransport*)_t);
+ return;
}
+
+ handle_packet(p, (atransport*)_t);
}
}
@@ -243,6 +250,7 @@
p->msg.arg0 = 1;
p->msg.arg1 = ++(t->sync_token);
p->msg.magic = A_SYNC ^ 0xffffffff;
+ D("sending SYNC packet (len = %u, payload.size() = %zu)", p->msg.data_length, p->payload.size());
if (write_packet(t->fd, t->serial, &p)) {
put_apacket(p);
D("%s: failed to write SYNC packet", t->serial);
@@ -336,6 +344,13 @@
if (active) {
D("%s: transport got packet, sending to remote", t->serial);
ATRACE_NAME("write_transport write_remote");
+
+ // Allow sending the payload's implicit null terminator.
+ if (p->msg.data_length != p->payload.size()) {
+ LOG(FATAL) << "packet data length doesn't match payload: msg.data_length = "
+ << p->msg.data_length << ", payload.size() = " << p->payload.size();
+ }
+
if (t->Write(p) != 0) {
D("%s: remote write failed for transport", t->serial);
put_apacket(p);
diff --git a/adb/transport_usb.cpp b/adb/transport_usb.cpp
index a108699..d7565f6 100644
--- a/adb/transport_usb.cpp
+++ b/adb/transport_usb.cpp
@@ -61,13 +61,12 @@
static int UsbReadPayload(usb_handle* h, apacket* p) {
D("UsbReadPayload(%d)", p->msg.data_length);
- if (p->msg.data_length > sizeof(p->data)) {
+ if (p->msg.data_length > MAX_PAYLOAD) {
return -1;
}
#if CHECK_PACKET_OVERFLOW
size_t usb_packet_size = usb_get_max_packet_size(h);
- CHECK_EQ(0ULL, sizeof(p->data) % usb_packet_size);
// Round the data length up to the nearest packet size boundary.
// The device won't send a zero packet for packet size aligned payloads,
@@ -77,10 +76,18 @@
if (rem_size) {
len += usb_packet_size - rem_size;
}
- CHECK_LE(len, sizeof(p->data));
- return usb_read(h, &p->data, len);
+
+ p->payload.resize(len);
+ int rc = usb_read(h, &p->payload[0], p->payload.size());
+ if (rc != static_cast<int>(p->msg.data_length)) {
+ return -1;
+ }
+
+ p->payload.resize(rc);
+ return rc;
#else
- return usb_read(h, &p->data, p->msg.data_length);
+ p->payload.resize(p->msg.data_length);
+ return usb_read(h, &p->payload[0], p->payload.size());
#endif
}
@@ -120,12 +127,13 @@
}
if (p->msg.data_length) {
- if (p->msg.data_length > sizeof(p->data)) {
+ if (p->msg.data_length > MAX_PAYLOAD) {
PLOG(ERROR) << "remote usb: read overflow (data length = " << p->msg.data_length << ")";
return -1;
}
- if (usb_read(usb, p->data, p->msg.data_length)) {
+ p->payload.resize(p->msg.data_length);
+ if (usb_read(usb, &p->payload[0], p->payload.size())) {
PLOG(ERROR) << "remote usb: terminated (data)";
return -1;
}
@@ -152,7 +160,7 @@
return false;
}
- if (packet->msg.data_length != 0 && usb_write(handle_, &packet->data, size) != 0) {
+ if (packet->msg.data_length != 0 && usb_write(handle_, packet->payload.data(), size) != 0) {
PLOG(ERROR) << "remote usb: 2 - write terminated";
return false;
}
diff --git a/base/Android.bp b/base/Android.bp
index 6cadcfc..5d70d47 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -15,8 +15,12 @@
//
cc_defaults {
- name: "libbase_defaults",
- cflags: ["-Wall", "-Werror", "-Wextra"],
+ name: "libbase_cflags_defaults",
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
}
cc_library_headers {
@@ -35,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",
@@ -55,11 +53,6 @@
"test_utils.cpp",
],
- header_libs: [
- "libbase_headers",
- ],
- export_header_lib_headers: ["libbase_headers"],
-
shared_libs: ["liblog"],
target: {
android: {
@@ -96,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/include/android-base/strings.h b/base/include/android-base/strings.h
index c11acb1..4d9fa34 100644
--- a/base/include/android-base/strings.h
+++ b/base/include/android-base/strings.h
@@ -67,8 +67,8 @@
// TODO: string_view
bool EndsWith(const std::string& s, const char* suffix);
bool EndsWithIgnoreCase(const std::string& s, const char* suffix);
-bool EndsWith(const std::string& s, const std::string& prefix);
-bool EndsWithIgnoreCase(const std::string& s, const std::string& prefix);
+bool EndsWith(const std::string& s, const std::string& suffix);
+bool EndsWithIgnoreCase(const std::string& s, const std::string& suffix);
// Tests whether 'lhs' equals 'rhs', ignoring case.
bool EqualsIgnoreCase(const std::string& lhs, const std::string& rhs);
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 cde4d69..6cf43f9 100644
--- a/base/properties.cpp
+++ b/base/properties.cpp
@@ -23,12 +23,11 @@
#include <algorithm>
#include <chrono>
+#include <limits>
#include <string>
#include <android-base/parseint.h>
-using namespace std::chrono_literals;
-
namespace android {
namespace base {
@@ -109,7 +108,7 @@
static void DurationToTimeSpec(timespec& ts, const std::chrono::milliseconds d) {
auto s = std::chrono::duration_cast<std::chrono::seconds>(d);
auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(d - s);
- ts.tv_sec = s.count();
+ ts.tv_sec = std::min<std::chrono::seconds::rep>(s.count(), std::numeric_limits<time_t>::max());
ts.tv_nsec = ns.count();
}
diff --git a/bootstat/Android.bp b/bootstat/Android.bp
index 2c87018..dd9ba88 100644
--- a/bootstat/Android.bp
+++ b/bootstat/Android.bp
@@ -66,6 +66,9 @@
shared_libs: ["liblogcat"],
init_rc: ["bootstat.rc"],
product_variables: {
+ pdk: {
+ enabled: false,
+ },
debuggable: {
init_rc: ["bootstat-debug.rc"],
},
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 5323524..7e6f24d 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -16,7 +16,7 @@
cc_library_headers {
name: "libdebuggerd_common_headers",
- export_include_dirs: ["common/include"]
+ export_include_dirs: ["common/include"],
}
cc_library_shared {
@@ -39,7 +39,7 @@
],
export_header_lib_headers: ["libdebuggerd_common_headers"],
- export_include_dirs: ["tombstoned/include"]
+ export_include_dirs: ["tombstoned/include"],
}
// Utility library to tombstoned and get an output fd.
@@ -60,7 +60,7 @@
],
export_header_lib_headers: ["libdebuggerd_common_headers"],
- export_include_dirs: ["tombstoned/include"]
+ export_include_dirs: ["tombstoned/include"],
}
// Core implementation, linked into libdebuggerd_handler and the dynamic linker.
@@ -186,7 +186,10 @@
"client/debuggerd_client_test.cpp",
"debuggerd_test.cpp",
],
- static_libs: ["libasync_safe", "libtombstoned_client_static"],
+ static_libs: [
+ "libasync_safe",
+ "libtombstoned_client_static",
+ ],
},
},
@@ -197,7 +200,7 @@
"libdebuggerd_client",
"liblog",
"libminijail",
- "libnativehelper"
+ "libnativehelper",
],
static_libs: [
@@ -298,7 +301,7 @@
"liblog",
],
- init_rc: ["tombstoned/tombstoned.rc"]
+ init_rc: ["tombstoned/tombstoned.rc"],
}
subdirs = [
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index 3bc1742..c03b41d 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -20,4 +20,5 @@
LOCAL_SRC_FILES_arm64 := seccomp_policy/crash_dump.arm64.policy
LOCAL_SRC_FILES_x86 := seccomp_policy/crash_dump.x86.policy
LOCAL_SRC_FILES_x86_64 := seccomp_policy/crash_dump.x86_64.policy
+LOCAL_MODULE_TARGET_ARCH := arm arm64 x86 x86_64
include $(BUILD_PREBUILT)
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/debuggerd/libdebuggerd/include/libdebuggerd/utility.h b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
index 0f049fd..7b04e71 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
@@ -68,7 +68,7 @@
class Memory;
}
-void dump_memory(log_t* log, unwindstack::Memory* backtrace, uint64_t addr, const char* fmt, ...);
+void dump_memory(log_t* log, unwindstack::Memory* backtrace, uint64_t addr, const std::string&);
void read_with_default(const char* path, char* buf, size_t len, const char* default_value);
diff --git a/debuggerd/libdebuggerd/test/dump_memory_test.cpp b/debuggerd/libdebuggerd/test/dump_memory_test.cpp
index 7c8a0ea..be39582 100644
--- a/debuggerd/libdebuggerd/test/dump_memory_test.cpp
+++ b/debuggerd/libdebuggerd/test/dump_memory_test.cpp
@@ -201,7 +201,7 @@
}
memory_mock_->SetReadData(buffer, sizeof(buffer));
- dump_memory(&log_, memory_mock_.get(), 0x12345678, "memory near %.2s:", "r1");
+ dump_memory(&log_, memory_mock_.get(), 0x12345678, "memory near r1");
std::string tombstone_contents;
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
@@ -221,7 +221,7 @@
memory_mock_->SetReadData(buffer, sizeof(buffer));
memory_mock_->SetPartialReadAmount(96);
- dump_memory(&log_, memory_mock_.get(), 0x12345679, "memory near %.2s:", "r1");
+ dump_memory(&log_, memory_mock_.get(), 0x12345679, "memory near r1");
std::string tombstone_contents;
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
@@ -240,7 +240,7 @@
}
memory_mock_->SetReadData(buffer, sizeof(buffer));
- dump_memory(&log_, memory_mock_.get(), 0x12345679, "memory near %.2s:", "r1");
+ dump_memory(&log_, memory_mock_.get(), 0x12345679, "memory near r1");
std::string tombstone_contents;
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
@@ -253,7 +253,7 @@
}
TEST_F(DumpMemoryTest, memory_unreadable) {
- dump_memory(&log_, memory_mock_.get(), 0xa2345678, "memory near pc:");
+ dump_memory(&log_, memory_mock_.get(), 0xa2345678, "memory near pc");
std::string tombstone_contents;
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
@@ -309,7 +309,7 @@
}
memory_mock_->SetReadData(buffer, sizeof(buffer));
- dump_memory(&log_, memory_mock_.get(), 0x12345600, "memory near pc:");
+ dump_memory(&log_, memory_mock_.get(), 0x12345600, "memory near pc");
std::string tombstone_contents;
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
@@ -329,7 +329,7 @@
memory_mock_->SetReadData(buffer, sizeof(buffer));
memory_mock_->SetPartialReadAmount(102);
- dump_memory(&log_, memory_mock_.get(), 0x12345600, "memory near pc:");
+ dump_memory(&log_, memory_mock_.get(), 0x12345600, "memory near pc");
std::string tombstone_contents;
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
@@ -354,7 +354,7 @@
memory_mock_->SetReadData(buffer, sizeof(buffer));
memory_mock_->SetPartialReadAmount(45);
- dump_memory(&log_, memory_mock_.get(), 0x12345600, "memory near pc:");
+ dump_memory(&log_, memory_mock_.get(), 0x12345600, "memory near pc");
std::string tombstone_contents;
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
@@ -380,7 +380,7 @@
memset(buffer, 0, sizeof(buffer));
memory_mock_->SetReadData(buffer, sizeof(buffer));
- dump_memory(&log_, memory_mock_.get(), 0x1000, "memory near %.2s:", "r1");
+ dump_memory(&log_, memory_mock_.get(), 0x1000, "memory near r1");
std::string tombstone_contents;
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
@@ -434,7 +434,7 @@
memset(buffer, 0, sizeof(buffer));
memory_mock_->SetReadData(buffer, sizeof(buffer));
- dump_memory(&log_, memory_mock_.get(), 0, "memory near %.2s:", "r1");
+ dump_memory(&log_, memory_mock_.get(), 0, "memory near r1");
std::string tombstone_contents;
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
@@ -452,13 +452,13 @@
memory_mock_->SetReadData(buffer, sizeof(buffer));
#if defined(__LP64__)
- dump_memory(&log_, memory_mock_.get(), 0x4000000000000000UL, "memory near %.2s:", "r1");
- dump_memory(&log_, memory_mock_.get(), 0x4000000000000000UL - 32, "memory near %.2s:", "r1");
- dump_memory(&log_, memory_mock_.get(), 0x4000000000000000UL - 216, "memory near %.2s:", "r1");
+ dump_memory(&log_, memory_mock_.get(), 0x4000000000000000UL, "memory near r1");
+ dump_memory(&log_, memory_mock_.get(), 0x4000000000000000UL - 32, "memory near r1");
+ dump_memory(&log_, memory_mock_.get(), 0x4000000000000000UL - 216, "memory near r1");
#else
- dump_memory(&log_, memory_mock_.get(), 0xffff0000, "memory near %.2s:", "r1");
- dump_memory(&log_, memory_mock_.get(), 0xffff0000 - 32, "memory near %.2s:", "r1");
- dump_memory(&log_, memory_mock_.get(), 0xffff0000 - 220, "memory near %.2s:", "r1");
+ dump_memory(&log_, memory_mock_.get(), 0xffff0000, "memory near r1");
+ dump_memory(&log_, memory_mock_.get(), 0xffff0000 - 32, "memory near r1");
+ dump_memory(&log_, memory_mock_.get(), 0xffff0000 - 220, "memory near r1");
#endif
std::string tombstone_contents;
@@ -477,9 +477,9 @@
memory_mock_->SetReadData(buffer, sizeof(buffer));
#if defined(__LP64__)
- dump_memory(&log_, memory_mock_.get(), 0xfffffffffffffff0, "memory near %.2s:", "r1");
+ dump_memory(&log_, memory_mock_.get(), 0xfffffffffffffff0, "memory near r1");
#else
- dump_memory(&log_, memory_mock_.get(), 0xfffffff0, "memory near %.2s:", "r1");
+ dump_memory(&log_, memory_mock_.get(), 0xfffffff0, "memory near r1");
#endif
std::string tombstone_contents;
@@ -500,9 +500,9 @@
memory_mock_->SetReadData(buffer, sizeof(buffer));
#if defined(__LP64__)
- dump_memory(&log_, memory_mock_.get(), 0x4000000000000000UL - 224, "memory near %.2s:", "r4");
+ dump_memory(&log_, memory_mock_.get(), 0x4000000000000000UL - 224, "memory near r4");
#else
- dump_memory(&log_, memory_mock_.get(), 0xffff0000 - 224, "memory near %.2s:", "r4");
+ dump_memory(&log_, memory_mock_.get(), 0xffff0000 - 224, "memory near r4");
#endif
std::string tombstone_contents;
@@ -562,7 +562,7 @@
size_t page_size = sysconf(_SC_PAGE_SIZE);
uintptr_t addr = 0x10000020 + page_size - 120;
- dump_memory(&log_, memory_mock_.get(), addr, "memory near %.2s:", "r4");
+ dump_memory(&log_, memory_mock_.get(), addr, "memory near r4");
std::string tombstone_contents;
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
@@ -621,7 +621,7 @@
size_t page_size = sysconf(_SC_PAGE_SIZE);
uintptr_t addr = 0x10000020 + page_size - 192;
- dump_memory(&log_, memory_mock_.get(), addr, "memory near %.2s:", "r4");
+ dump_memory(&log_, memory_mock_.get(), addr, "memory near r4");
std::string tombstone_contents;
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
@@ -679,7 +679,7 @@
memory_mock_->SetPartialReadAmount(0);
uintptr_t addr = 0x10000020;
- dump_memory(&log_, memory_mock_.get(), addr, "memory near %.2s:", "r4");
+ dump_memory(&log_, memory_mock_.get(), addr, "memory near r4");
std::string tombstone_contents;
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
@@ -739,7 +739,7 @@
size_t page_size = sysconf(_SC_PAGE_SIZE);
uintptr_t addr = 0x10000020 + page_size - 256;
- dump_memory(&log_, memory_mock_.get(), addr, "memory near %.2s:", "r4");
+ dump_memory(&log_, memory_mock_.get(), addr, "memory near r4");
std::string tombstone_contents;
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index 7d85602..140ef6d 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -65,6 +65,8 @@
using unwindstack::Memory;
using unwindstack::Regs;
+using namespace std::literals::string_literals;
+
#define STACK_WORDS 16
static void dump_header_info(log_t* log) {
@@ -148,8 +150,9 @@
backtrace_map_t map;
backtrace_map->FillIn(stack_data[i], &map);
- if (BacktraceMap::IsValid(map) && !map.name.empty()) {
- line += " " + map.name;
+ std::string map_name{map.Name()};
+ if (BacktraceMap::IsValid(map) && !map_name.empty()) {
+ line += " " + map_name;
uint64_t offset = 0;
std::string func_name = backtrace_map->GetFunctionName(stack_data[i], &offset);
if (!func_name.empty()) {
@@ -382,9 +385,16 @@
print_register_row(log, special_row);
}
-void dump_memory_and_code(log_t* log, Memory* memory, Regs* regs) {
- regs->IterateRegisters([log, memory](const char* name, uint64_t value) {
- dump_memory(log, memory, value, "memory near %s:", name);
+void dump_memory_and_code(log_t* log, BacktraceMap* map, Memory* memory, Regs* regs) {
+ regs->IterateRegisters([log, map, memory](const char* reg_name, uint64_t reg_value) {
+ std::string label{"memory near "s + reg_name};
+ if (map) {
+ backtrace_map_t map_info;
+ map->FillIn(reg_value, &map_info);
+ std::string map_name{map_info.Name()};
+ if (!map_name.empty()) label += " (" + map_info.Name() + ")";
+ }
+ dump_memory(log, memory, reg_value, label);
});
}
@@ -423,7 +433,7 @@
}
if (primary_thread) {
- dump_memory_and_code(log, process_memory, thread_info.registers.get());
+ dump_memory_and_code(log, map, process_memory, thread_info.registers.get());
if (map) {
uint64_t addr = 0;
siginfo_t* si = thread_info.siginfo;
diff --git a/debuggerd/libdebuggerd/utility.cpp b/debuggerd/libdebuggerd/utility.cpp
index 3ac98f5..d153865 100644
--- a/debuggerd/libdebuggerd/utility.cpp
+++ b/debuggerd/libdebuggerd/utility.cpp
@@ -124,13 +124,7 @@
#define MEMORY_BYTES_TO_DUMP 256
#define MEMORY_BYTES_PER_LINE 16
-void dump_memory(log_t* log, unwindstack::Memory* memory, uint64_t addr, const char* fmt, ...) {
- std::string log_msg;
- va_list ap;
- va_start(ap, fmt);
- android::base::StringAppendV(&log_msg, fmt, ap);
- va_end(ap);
-
+void dump_memory(log_t* log, unwindstack::Memory* memory, uint64_t addr, const std::string& label) {
// Align the address to sizeof(long) and start 32 bytes before the address.
addr &= ~(sizeof(long) - 1);
if (addr >= 4128) {
@@ -147,7 +141,7 @@
return;
}
- _LOG(log, logtype::MEMORY, "\n%s\n", log_msg.c_str());
+ _LOG(log, logtype::MEMORY, "\n%s:\n", label.c_str());
// Dump 256 bytes
uintptr_t data[MEMORY_BYTES_TO_DUMP/sizeof(uintptr_t)];
diff --git a/debuggerd/seccomp_policy/crash_dump.arm.policy b/debuggerd/seccomp_policy/crash_dump.arm.policy
index b1f459d..254330d 100644
--- a/debuggerd/seccomp_policy/crash_dump.arm.policy
+++ b/debuggerd/seccomp_policy/crash_dump.arm.policy
@@ -26,11 +26,11 @@
rt_tgsigqueueinfo: 1
prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41
madvise: 1
-mprotect: arg2 in PROT_READ|PROT_WRITE
+mprotect: arg2 in 0x1|0x2
munmap: 1
getuid32: 1
fstat64: 1
-mmap2: arg2 in PROT_READ|PROT_WRITE
+mmap2: arg2 in 0x1|0x2
geteuid32: 1
getgid32: 1
getegid32: 1
diff --git a/debuggerd/seccomp_policy/crash_dump.arm64.policy b/debuggerd/seccomp_policy/crash_dump.arm64.policy
index e5e7afb..9b3ef09 100644
--- a/debuggerd/seccomp_policy/crash_dump.arm64.policy
+++ b/debuggerd/seccomp_policy/crash_dump.arm64.policy
@@ -25,11 +25,11 @@
rt_tgsigqueueinfo: 1
prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41
madvise: 1
-mprotect: arg2 in PROT_READ|PROT_WRITE
+mprotect: arg2 in 0x1|0x2
munmap: 1
getuid: 1
fstat: 1
-mmap: arg2 in PROT_READ|PROT_WRITE
+mmap: arg2 in 0x1|0x2
geteuid: 1
getgid: 1
getegid: 1
diff --git a/debuggerd/seccomp_policy/crash_dump.policy.def b/debuggerd/seccomp_policy/crash_dump.policy.def
index b78c94a..2ef31b0 100644
--- a/debuggerd/seccomp_policy/crash_dump.policy.def
+++ b/debuggerd/seccomp_policy/crash_dump.policy.def
@@ -35,6 +35,14 @@
#define PR_SET_VMA 0x53564d41
prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == PR_SET_VMA
+#if 0
+libminijail on vendor partitions older than P does not have constants from <sys/mman.h>.
+Define the values of PROT_READ and PROT_WRITE ourselves to maintain backwards compatibility.
+#else
+#define PROT_READ 0x1
+#define PROT_WRITE 0x2
+#endif
+
madvise: 1
mprotect: arg2 in PROT_READ|PROT_WRITE
munmap: 1
diff --git a/debuggerd/seccomp_policy/crash_dump.x86.policy b/debuggerd/seccomp_policy/crash_dump.x86.policy
index b1f459d..254330d 100644
--- a/debuggerd/seccomp_policy/crash_dump.x86.policy
+++ b/debuggerd/seccomp_policy/crash_dump.x86.policy
@@ -26,11 +26,11 @@
rt_tgsigqueueinfo: 1
prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41
madvise: 1
-mprotect: arg2 in PROT_READ|PROT_WRITE
+mprotect: arg2 in 0x1|0x2
munmap: 1
getuid32: 1
fstat64: 1
-mmap2: arg2 in PROT_READ|PROT_WRITE
+mmap2: arg2 in 0x1|0x2
geteuid32: 1
getgid32: 1
getegid32: 1
diff --git a/debuggerd/seccomp_policy/crash_dump.x86_64.policy b/debuggerd/seccomp_policy/crash_dump.x86_64.policy
index e5e7afb..9b3ef09 100644
--- a/debuggerd/seccomp_policy/crash_dump.x86_64.policy
+++ b/debuggerd/seccomp_policy/crash_dump.x86_64.policy
@@ -25,11 +25,11 @@
rt_tgsigqueueinfo: 1
prctl: arg0 == PR_GET_NO_NEW_PRIVS || arg0 == 0x53564d41
madvise: 1
-mprotect: arg2 in PROT_READ|PROT_WRITE
+mprotect: arg2 in 0x1|0x2
munmap: 1
getuid: 1
fstat: 1
-mmap: arg2 in PROT_READ|PROT_WRITE
+mmap: arg2 in 0x1|0x2
geteuid: 1
getgid: 1
getegid: 1
diff --git a/demangle/Android.bp b/demangle/Android.bp
index 89b8772..8d5b135 100644
--- a/demangle/Android.bp
+++ b/demangle/Android.bp
@@ -42,11 +42,11 @@
],
local_include_dirs: [
- "include",
+ "include",
],
export_include_dirs: [
- "include",
+ "include",
],
}
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 1c01d8c..9b7405a 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -39,6 +39,7 @@
char *key_loc;
char* key_dir;
char *verity_loc;
+ char *sysfs_path;
long long part_length;
char *label;
int partnum;
@@ -104,6 +105,7 @@
{"quota", MF_QUOTA},
{"eraseblk=", MF_ERASEBLKSIZE},
{"logicalblk=", MF_LOGICALBLKSIZE},
+ {"sysfs_path=", MF_SYSFS},
{"defaults", 0},
{0, 0},
};
@@ -341,6 +343,9 @@
unsigned int val = strtoul(strchr(p, '=') + 1, NULL, 0);
if (val >= 4096 && (val & (val - 1)) == 0)
flag_vals->logical_blk_size = val;
+ } else if ((fl[i].flag == MF_SYSFS) && flag_vals) {
+ /* The path to trigger device gc by idle-maint of vold. */
+ flag_vals->sysfs_path = strdup(strchr(p, '=') + 1);
}
break;
}
@@ -615,6 +620,7 @@
fstab->recs[cnt].file_names_mode = flag_vals.file_names_mode;
fstab->recs[cnt].erase_blk_size = flag_vals.erase_blk_size;
fstab->recs[cnt].logical_blk_size = flag_vals.logical_blk_size;
+ fstab->recs[cnt].sysfs_path = flag_vals.sysfs_path;
cnt++;
}
/* If an A/B partition, modify block device to be the real block device */
@@ -787,6 +793,7 @@
free(fstab->recs[i].key_loc);
free(fstab->recs[i].key_dir);
free(fstab->recs[i].label);
+ free(fstab->recs[i].sysfs_path);
}
/* Free the fstab_recs array created by calloc(3) */
@@ -922,3 +929,8 @@
int fs_mgr_is_quota(const struct fstab_rec* fstab) {
return fstab->fs_mgr_flags & MF_QUOTA;
}
+
+int fs_mgr_has_sysfs_path(const struct fstab_rec *fstab)
+{
+ return fstab->fs_mgr_flags & MF_SYSFS;
+}
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 724156d..ade0cc4 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -109,7 +109,8 @@
#define MF_ERASEBLKSIZE 0x800000
#define MF_LOGICALBLKSIZE 0X1000000
#define MF_AVB 0X2000000
-#define MF_KEYDIRECTORY 0X4000000
+#define MF_KEYDIRECTORY 0X4000000
+#define MF_SYSFS 0X8000000
#define DM_BUF_SIZE 4096
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index 94aacfd..8c585dd 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -56,6 +56,7 @@
unsigned int file_names_mode;
unsigned int erase_blk_size;
unsigned int logical_blk_size;
+ char* sysfs_path;
};
struct fstab* fs_mgr_read_fstab_default();
@@ -83,6 +84,7 @@
int fs_mgr_is_nofail(const struct fstab_rec* fstab);
int fs_mgr_is_latemount(const struct fstab_rec* fstab);
int fs_mgr_is_quota(const struct fstab_rec* fstab);
+int fs_mgr_has_sysfs_path(const struct fstab_rec* fstab);
std::string fs_mgr_get_slot_suffix();
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index 08b8b26..fa79d0b 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -143,7 +143,7 @@
BatteryMonitor::PowerSupplyType BatteryMonitor::readPowerSupplyType(const String8& path) {
std::string buf;
- BatteryMonitor::PowerSupplyType ret;
+ int ret;
struct sysfsStringEnumMap supplyTypeMap[] = {
{ "Unknown", ANDROID_POWER_SUPPLY_TYPE_UNKNOWN },
{ "Battery", ANDROID_POWER_SUPPLY_TYPE_BATTERY },
@@ -164,13 +164,13 @@
if (readFromFile(path, &buf) <= 0)
return ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
- ret = (BatteryMonitor::PowerSupplyType)mapSysfsString(buf.c_str(), supplyTypeMap);
+ ret = mapSysfsString(buf.c_str(), supplyTypeMap);
if (ret < 0) {
KLOG_WARNING(LOG_TAG, "Unknown power supply type '%s'\n", buf.c_str());
ret = ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
}
- return ret;
+ return static_cast<BatteryMonitor::PowerSupplyType>(ret);
}
bool BatteryMonitor::getBooleanField(const String8& path) {
diff --git a/init/Android.bp b/init/Android.bp
index 6c80ee6..31c8efb 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -56,7 +56,7 @@
},
uml: {
cppflags: ["-DUSER_MODE_LINUX"],
- }
+ },
},
static_libs: [
"libbootloader_message",
@@ -93,6 +93,8 @@
defaults: ["init_defaults"],
srcs: [
"action.cpp",
+ "action_manager.cpp",
+ "action_parser.cpp",
"bootchart.cpp",
"builtins.cpp",
"capabilities.cpp",
@@ -192,4 +194,67 @@
static_libs: ["libinit"],
}
+// Host Verifier
+// ------------------------------------------------------------------------------
+
+genrule {
+ name: "generated_stub_builtin_function_map",
+ out: ["generated_stub_builtin_function_map.h"],
+ srcs: ["builtins.cpp"],
+ cmd: "sed -n '/Builtin-function-map start/{:a;n;/Builtin-function-map end/q;p;ba}' $(in) | sed -e 's/do_[^}]*/do_stub/g' > $(out)",
+}
+
+cc_binary {
+ name: "host_init_verifier",
+ host_supported: true,
+ cpp_std: "experimental",
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Wno-unused-parameter",
+ "-Werror",
+ ],
+ static_libs: [
+ "libbase",
+ "libselinux",
+ ],
+ whole_static_libs: ["libcap"],
+ shared_libs: [
+ "libprotobuf-cpp-lite",
+ "libhidl-gen-utils",
+ "libprocessgroup",
+ "liblog",
+ "libcutils",
+ ],
+ srcs: [
+ "action.cpp",
+ "action_manager.cpp",
+ "action_parser.cpp",
+ "capabilities.cpp",
+ "descriptors.cpp",
+ "import_parser.cpp",
+ "host_init_parser.cpp",
+ "host_init_stubs.cpp",
+ "parser.cpp",
+ "rlimit_parser.cpp",
+ "tokenizer.cpp",
+ "service.cpp",
+ "subcontext.cpp",
+ "subcontext.proto",
+ "util.cpp",
+ ],
+ proto: {
+ type: "lite",
+ },
+ generated_headers: ["generated_stub_builtin_function_map"],
+ target: {
+ android: {
+ enabled: false,
+ },
+ darwin: {
+ enabled: false,
+ },
+ },
+}
+
subdirs = ["*"]
diff --git a/init/README.md b/init/README.md
index d7edf21..5c2352b 100644
--- a/init/README.md
+++ b/init/README.md
@@ -10,7 +10,11 @@
whitespace from breaking text into multiple tokens. The backslash,
when it is the last character on a line, may be used for line-folding.
-Lines which start with a # (leading whitespace allowed) are comments.
+Lines which start with a `#` (leading whitespace allowed) are comments.
+
+System properties can be expanded using the syntax
+`${property.name}`. This also works in contexts where concatenation is
+required, such as `import /init.recovery.${ro.hardware}.rc`.
Actions and Services implicitly declare a new section. All commands
or options belong to the section most recently declared. Commands
diff --git a/init/action.cpp b/init/action.cpp
index ba03e66..f782b51 100644
--- a/init/action.cpp
+++ b/init/action.cpp
@@ -18,14 +18,17 @@
#include <android-base/chrono_utils.h>
#include <android-base/logging.h>
-#include <android-base/properties.h>
#include <android-base/strings.h>
-#include "stable_properties.h"
#include "util.h"
+#if defined(__ANDROID__)
+#include <android-base/properties.h>
+#else
+#include "host_init_stubs.h"
+#endif
+
using android::base::Join;
-using android::base::StartsWith;
namespace android {
namespace init {
@@ -70,8 +73,15 @@
return Join(args_, ' ');
}
-Action::Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line)
- : oneshot_(oneshot), subcontext_(subcontext), filename_(filename), line_(line) {}
+Action::Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line,
+ const std::string& event_trigger,
+ const std::map<std::string, std::string>& property_triggers)
+ : property_triggers_(property_triggers),
+ event_trigger_(event_trigger),
+ oneshot_(oneshot),
+ subcontext_(subcontext),
+ filename_(filename),
+ line_(line) {}
const KeywordFunctionMap* Action::function_map_ = nullptr;
@@ -135,85 +145,6 @@
}
}
-static bool IsActionableProperty(Subcontext* subcontext, const std::string& prop_name) {
- static bool enabled =
- android::base::GetBoolProperty("ro.actionable_compatible_property.enabled", false);
-
- if (subcontext == nullptr || !enabled) {
- return true;
- }
-
- if (kExportedActionableProperties.count(prop_name) == 1) {
- return true;
- }
- for (const auto& prefix : kPartnerPrefixes) {
- if (android::base::StartsWith(prop_name, prefix)) {
- return true;
- }
- }
- return false;
-}
-
-Result<Success> Action::ParsePropertyTrigger(const std::string& trigger) {
- const static std::string prop_str("property:");
- std::string prop_name(trigger.substr(prop_str.length()));
- size_t equal_pos = prop_name.find('=');
- if (equal_pos == std::string::npos) {
- return Error() << "property trigger found without matching '='";
- }
-
- std::string prop_value(prop_name.substr(equal_pos + 1));
- prop_name.erase(equal_pos);
-
- if (!IsActionableProperty(subcontext_, prop_name)) {
- return Error() << "unexported property tigger found: " << prop_name;
- }
-
- if (auto [it, inserted] = property_triggers_.emplace(prop_name, prop_value); !inserted) {
- return Error() << "multiple property triggers found for same property";
- }
- return Success();
-}
-
-Result<Success> Action::InitTriggers(const std::vector<std::string>& args) {
- const static std::string prop_str("property:");
- for (std::size_t i = 0; i < args.size(); ++i) {
- if (args[i].empty()) {
- return Error() << "empty trigger is not valid";
- }
-
- if (i % 2) {
- if (args[i] != "&&") {
- return Error() << "&& is the only symbol allowed to concatenate actions";
- } else {
- continue;
- }
- }
-
- if (!args[i].compare(0, prop_str.length(), prop_str)) {
- if (auto result = ParsePropertyTrigger(args[i]); !result) {
- return result;
- }
- } else {
- if (!event_trigger_.empty()) {
- return Error() << "multiple event triggers are not allowed";
- }
-
- event_trigger_ = args[i];
- }
- }
-
- return Success();
-}
-
-Result<Success> Action::InitSingleTrigger(const std::string& trigger) {
- std::vector<std::string> name_vector{trigger};
- if (auto result = InitTriggers(name_vector); !result) {
- return Error() << "InitTriggers() failed: " << result.error();
- }
- return Success();
-}
-
// This function checks that all property triggers are satisfied, that is
// for each (name, value) in property_triggers_, check that the current
// value of the property 'name' == value.
@@ -281,142 +212,5 @@
}
}
-ActionManager::ActionManager() : current_command_(0) {
-}
-
-ActionManager& ActionManager::GetInstance() {
- static ActionManager instance;
- return instance;
-}
-
-void ActionManager::AddAction(std::unique_ptr<Action> action) {
- actions_.emplace_back(std::move(action));
-}
-
-void ActionManager::QueueEventTrigger(const std::string& trigger) {
- event_queue_.emplace(trigger);
-}
-
-void ActionManager::QueuePropertyChange(const std::string& name, const std::string& value) {
- event_queue_.emplace(std::make_pair(name, value));
-}
-
-void ActionManager::QueueAllPropertyActions() {
- QueuePropertyChange("", "");
-}
-
-void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) {
- auto action = std::make_unique<Action>(true, nullptr, "<Builtin Action>", 0);
- std::vector<std::string> name_vector{name};
-
- if (auto result = action->InitSingleTrigger(name); !result) {
- LOG(ERROR) << "Cannot queue BuiltinAction for " << name << ": " << result.error();
- return;
- }
-
- action->AddCommand(func, name_vector, 0);
-
- event_queue_.emplace(action.get());
- actions_.emplace_back(std::move(action));
-}
-
-void ActionManager::ExecuteOneCommand() {
- // Loop through the event queue until we have an action to execute
- while (current_executing_actions_.empty() && !event_queue_.empty()) {
- for (const auto& action : actions_) {
- if (std::visit([&action](const auto& event) { return action->CheckEvent(event); },
- event_queue_.front())) {
- current_executing_actions_.emplace(action.get());
- }
- }
- event_queue_.pop();
- }
-
- if (current_executing_actions_.empty()) {
- return;
- }
-
- auto action = current_executing_actions_.front();
-
- if (current_command_ == 0) {
- std::string trigger_name = action->BuildTriggersString();
- LOG(INFO) << "processing action (" << trigger_name << ") from (" << action->filename()
- << ":" << action->line() << ")";
- }
-
- action->ExecuteOneCommand(current_command_);
-
- // If this was the last command in the current action, then remove
- // the action from the executing list.
- // If this action was oneshot, then also remove it from actions_.
- ++current_command_;
- if (current_command_ == action->NumCommands()) {
- current_executing_actions_.pop();
- current_command_ = 0;
- if (action->oneshot()) {
- auto eraser = [&action] (std::unique_ptr<Action>& a) {
- return a.get() == action;
- };
- actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser));
- }
- }
-}
-
-bool ActionManager::HasMoreCommands() const {
- return !current_executing_actions_.empty() || !event_queue_.empty();
-}
-
-void ActionManager::DumpState() const {
- for (const auto& a : actions_) {
- a->DumpState();
- }
-}
-
-void ActionManager::ClearQueue() {
- // We are shutting down so don't claim the oneshot builtin actions back
- current_executing_actions_ = {};
- event_queue_ = {};
- current_command_ = 0;
-}
-
-Result<Success> ActionParser::ParseSection(std::vector<std::string>&& args,
- const std::string& filename, int line) {
- std::vector<std::string> triggers(args.begin() + 1, args.end());
- if (triggers.size() < 1) {
- return Error() << "Actions must have a trigger";
- }
-
- Subcontext* action_subcontext = nullptr;
- if (subcontexts_) {
- for (auto& subcontext : *subcontexts_) {
- if (StartsWith(filename, subcontext.path_prefix())) {
- action_subcontext = &subcontext;
- break;
- }
- }
- }
-
- auto action = std::make_unique<Action>(false, action_subcontext, filename, line);
-
- if (auto result = action->InitTriggers(triggers); !result) {
- return Error() << "InitTriggers() failed: " << result.error();
- }
-
- action_ = std::move(action);
- return Success();
-}
-
-Result<Success> ActionParser::ParseLineSection(std::vector<std::string>&& args, int line) {
- return action_ ? action_->AddCommand(std::move(args), line) : Success();
-}
-
-Result<Success> ActionParser::EndSection() {
- if (action_ && action_->NumCommands() > 0) {
- action_manager_->AddAction(std::move(action_));
- }
-
- return Success();
-}
-
} // namespace init
} // namespace android
diff --git a/init/action.h b/init/action.h
index 1bfc6c7..4f063cc 100644
--- a/init/action.h
+++ b/init/action.h
@@ -25,7 +25,6 @@
#include "builtins.h"
#include "keyword_map.h"
-#include "parser.h"
#include "result.h"
#include "subcontext.h"
@@ -58,12 +57,12 @@
class Action {
public:
- Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line);
+ Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line,
+ const std::string& event_trigger,
+ const std::map<std::string, std::string>& property_triggers);
Result<Success> AddCommand(const std::vector<std::string>& args, int line);
void AddCommand(BuiltinFunction f, const std::vector<std::string>& args, int line);
- Result<Success> InitTriggers(const std::vector<std::string>& args);
- Result<Success> InitSingleTrigger(const std::string& trigger);
std::size_t NumCommands() const;
void ExecuteOneCommand(std::size_t command) const;
void ExecuteAllCommands() const;
@@ -84,7 +83,6 @@
void ExecuteCommand(const Command& command) const;
bool CheckPropertyTriggers(const std::string& name = "",
const std::string& value = "") const;
- Result<Success> ParsePropertyTrigger(const std::string& trigger);
std::map<std::string, std::string> property_triggers_;
std::string event_trigger_;
@@ -96,48 +94,6 @@
static const KeywordFunctionMap* function_map_;
};
-class ActionManager {
- public:
- static ActionManager& GetInstance();
-
- // Exposed for testing
- ActionManager();
-
- void AddAction(std::unique_ptr<Action> action);
- void QueueEventTrigger(const std::string& trigger);
- void QueuePropertyChange(const std::string& name, const std::string& value);
- void QueueAllPropertyActions();
- void QueueBuiltinAction(BuiltinFunction func, const std::string& name);
- void ExecuteOneCommand();
- bool HasMoreCommands() const;
- void DumpState() const;
- void ClearQueue();
-
- private:
- ActionManager(ActionManager const&) = delete;
- void operator=(ActionManager const&) = delete;
-
- std::vector<std::unique_ptr<Action>> actions_;
- std::queue<std::variant<EventTrigger, PropertyChange, BuiltinAction>> event_queue_;
- std::queue<const Action*> current_executing_actions_;
- std::size_t current_command_;
-};
-
-class ActionParser : public SectionParser {
- public:
- ActionParser(ActionManager* action_manager, std::vector<Subcontext>* subcontexts)
- : action_manager_(action_manager), subcontexts_(subcontexts), action_(nullptr) {}
- Result<Success> ParseSection(std::vector<std::string>&& args, const std::string& filename,
- int line) override;
- Result<Success> ParseLineSection(std::vector<std::string>&& args, int line) override;
- Result<Success> EndSection() override;
-
- private:
- ActionManager* action_manager_;
- std::vector<Subcontext>* subcontexts_;
- std::unique_ptr<Action> action_;
-};
-
} // namespace init
} // namespace android
diff --git a/init/action_manager.cpp b/init/action_manager.cpp
new file mode 100644
index 0000000..22977bb
--- /dev/null
+++ b/init/action_manager.cpp
@@ -0,0 +1,116 @@
+/*
+ * 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 "action_manager.h"
+
+#include <android-base/logging.h>
+
+namespace android {
+namespace init {
+
+ActionManager::ActionManager() : current_command_(0) {}
+
+ActionManager& ActionManager::GetInstance() {
+ static ActionManager instance;
+ return instance;
+}
+
+void ActionManager::AddAction(std::unique_ptr<Action> action) {
+ actions_.emplace_back(std::move(action));
+}
+
+void ActionManager::QueueEventTrigger(const std::string& trigger) {
+ event_queue_.emplace(trigger);
+}
+
+void ActionManager::QueuePropertyChange(const std::string& name, const std::string& value) {
+ event_queue_.emplace(std::make_pair(name, value));
+}
+
+void ActionManager::QueueAllPropertyActions() {
+ QueuePropertyChange("", "");
+}
+
+void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) {
+ auto action = std::make_unique<Action>(true, nullptr, "<Builtin Action>", 0, name,
+ std::map<std::string, std::string>{});
+ std::vector<std::string> name_vector{name};
+
+ action->AddCommand(func, name_vector, 0);
+
+ event_queue_.emplace(action.get());
+ actions_.emplace_back(std::move(action));
+}
+
+void ActionManager::ExecuteOneCommand() {
+ // Loop through the event queue until we have an action to execute
+ while (current_executing_actions_.empty() && !event_queue_.empty()) {
+ for (const auto& action : actions_) {
+ if (std::visit([&action](const auto& event) { return action->CheckEvent(event); },
+ event_queue_.front())) {
+ current_executing_actions_.emplace(action.get());
+ }
+ }
+ event_queue_.pop();
+ }
+
+ if (current_executing_actions_.empty()) {
+ return;
+ }
+
+ auto action = current_executing_actions_.front();
+
+ if (current_command_ == 0) {
+ std::string trigger_name = action->BuildTriggersString();
+ LOG(INFO) << "processing action (" << trigger_name << ") from (" << action->filename()
+ << ":" << action->line() << ")";
+ }
+
+ action->ExecuteOneCommand(current_command_);
+
+ // If this was the last command in the current action, then remove
+ // the action from the executing list.
+ // If this action was oneshot, then also remove it from actions_.
+ ++current_command_;
+ if (current_command_ == action->NumCommands()) {
+ current_executing_actions_.pop();
+ current_command_ = 0;
+ if (action->oneshot()) {
+ auto eraser = [&action](std::unique_ptr<Action>& a) { return a.get() == action; };
+ actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser));
+ }
+ }
+}
+
+bool ActionManager::HasMoreCommands() const {
+ return !current_executing_actions_.empty() || !event_queue_.empty();
+}
+
+void ActionManager::DumpState() const {
+ for (const auto& a : actions_) {
+ a->DumpState();
+ }
+}
+
+void ActionManager::ClearQueue() {
+ // We are shutting down so don't claim the oneshot builtin actions back
+ current_executing_actions_ = {};
+ event_queue_ = {};
+ current_command_ = 0;
+}
+
+} // namespace init
+} // namespace android
diff --git a/init/action_manager.h b/init/action_manager.h
new file mode 100644
index 0000000..5f47a6d
--- /dev/null
+++ b/init/action_manager.h
@@ -0,0 +1,59 @@
+/*
+ * 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 _INIT_ACTION_MANAGER_H
+#define _INIT_ACTION_MANAGER_H
+
+#include <string>
+#include <vector>
+
+#include "action.h"
+#include "builtins.h"
+
+namespace android {
+namespace init {
+
+class ActionManager {
+ public:
+ static ActionManager& GetInstance();
+
+ // Exposed for testing
+ ActionManager();
+
+ void AddAction(std::unique_ptr<Action> action);
+ void QueueEventTrigger(const std::string& trigger);
+ void QueuePropertyChange(const std::string& name, const std::string& value);
+ void QueueAllPropertyActions();
+ void QueueBuiltinAction(BuiltinFunction func, const std::string& name);
+ void ExecuteOneCommand();
+ bool HasMoreCommands() const;
+ void DumpState() const;
+ void ClearQueue();
+
+ private:
+ ActionManager(ActionManager const&) = delete;
+ void operator=(ActionManager const&) = delete;
+
+ std::vector<std::unique_ptr<Action>> actions_;
+ std::queue<std::variant<EventTrigger, PropertyChange, BuiltinAction>> event_queue_;
+ std::queue<const Action*> current_executing_actions_;
+ std::size_t current_command_;
+};
+
+} // namespace init
+} // namespace android
+
+#endif
diff --git a/init/action_parser.cpp b/init/action_parser.cpp
new file mode 100644
index 0000000..a2c9671
--- /dev/null
+++ b/init/action_parser.cpp
@@ -0,0 +1,158 @@
+/*
+ * 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 "action_parser.h"
+
+#include <android-base/strings.h>
+
+#include "stable_properties.h"
+
+#if defined(__ANDROID__)
+#include <android-base/properties.h>
+#else
+#include "host_init_stubs.h"
+#endif
+
+using android::base::GetBoolProperty;
+using android::base::StartsWith;
+
+namespace android {
+namespace init {
+
+namespace {
+
+bool IsActionableProperty(Subcontext* subcontext, const std::string& prop_name) {
+ static bool enabled = GetBoolProperty("ro.actionable_compatible_property.enabled", false);
+
+ if (subcontext == nullptr || !enabled) {
+ return true;
+ }
+
+ if (kExportedActionableProperties.count(prop_name) == 1) {
+ return true;
+ }
+ for (const auto& prefix : kPartnerPrefixes) {
+ if (android::base::StartsWith(prop_name, prefix)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+Result<Success> ParsePropertyTrigger(const std::string& trigger, Subcontext* subcontext,
+ std::map<std::string, std::string>* property_triggers) {
+ const static std::string prop_str("property:");
+ std::string prop_name(trigger.substr(prop_str.length()));
+ size_t equal_pos = prop_name.find('=');
+ if (equal_pos == std::string::npos) {
+ return Error() << "property trigger found without matching '='";
+ }
+
+ std::string prop_value(prop_name.substr(equal_pos + 1));
+ prop_name.erase(equal_pos);
+
+ if (!IsActionableProperty(subcontext, prop_name)) {
+ return Error() << "unexported property tigger found: " << prop_name;
+ }
+
+ if (auto [it, inserted] = property_triggers->emplace(prop_name, prop_value); !inserted) {
+ return Error() << "multiple property triggers found for same property";
+ }
+ return Success();
+}
+
+Result<Success> ParseTriggers(const std::vector<std::string>& args, Subcontext* subcontext,
+ std::string* event_trigger,
+ std::map<std::string, std::string>* property_triggers) {
+ const static std::string prop_str("property:");
+ for (std::size_t i = 0; i < args.size(); ++i) {
+ if (args[i].empty()) {
+ return Error() << "empty trigger is not valid";
+ }
+
+ if (i % 2) {
+ if (args[i] != "&&") {
+ return Error() << "&& is the only symbol allowed to concatenate actions";
+ } else {
+ continue;
+ }
+ }
+
+ if (!args[i].compare(0, prop_str.length(), prop_str)) {
+ if (auto result = ParsePropertyTrigger(args[i], subcontext, property_triggers);
+ !result) {
+ return result;
+ }
+ } else {
+ if (!event_trigger->empty()) {
+ return Error() << "multiple event triggers are not allowed";
+ }
+
+ *event_trigger = args[i];
+ }
+ }
+
+ return Success();
+}
+
+} // namespace
+
+Result<Success> ActionParser::ParseSection(std::vector<std::string>&& args,
+ const std::string& filename, int line) {
+ std::vector<std::string> triggers(args.begin() + 1, args.end());
+ if (triggers.size() < 1) {
+ return Error() << "Actions must have a trigger";
+ }
+
+ Subcontext* action_subcontext = nullptr;
+ if (subcontexts_) {
+ for (auto& subcontext : *subcontexts_) {
+ if (StartsWith(filename, subcontext.path_prefix())) {
+ action_subcontext = &subcontext;
+ break;
+ }
+ }
+ }
+
+ std::string event_trigger;
+ std::map<std::string, std::string> property_triggers;
+
+ if (auto result = ParseTriggers(triggers, action_subcontext, &event_trigger, &property_triggers);
+ !result) {
+ return Error() << "ParseTriggers() failed: " << result.error();
+ }
+
+ auto action = std::make_unique<Action>(false, action_subcontext, filename, line, event_trigger,
+ property_triggers);
+
+ action_ = std::move(action);
+ return Success();
+}
+
+Result<Success> ActionParser::ParseLineSection(std::vector<std::string>&& args, int line) {
+ return action_ ? action_->AddCommand(std::move(args), line) : Success();
+}
+
+Result<Success> ActionParser::EndSection() {
+ if (action_ && action_->NumCommands() > 0) {
+ action_manager_->AddAction(std::move(action_));
+ }
+
+ return Success();
+}
+
+} // namespace init
+} // namespace android
diff --git a/init/action_parser.h b/init/action_parser.h
new file mode 100644
index 0000000..b7f7074
--- /dev/null
+++ b/init/action_parser.h
@@ -0,0 +1,49 @@
+/*
+ * 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 _INIT_ACTION_PARSER_H
+#define _INIT_ACTION_PARSER_H
+
+#include <string>
+#include <vector>
+
+#include "action.h"
+#include "action_manager.h"
+#include "parser.h"
+#include "subcontext.h"
+
+namespace android {
+namespace init {
+
+class ActionParser : public SectionParser {
+ public:
+ ActionParser(ActionManager* action_manager, std::vector<Subcontext>* subcontexts)
+ : action_manager_(action_manager), subcontexts_(subcontexts), action_(nullptr) {}
+ Result<Success> ParseSection(std::vector<std::string>&& args, const std::string& filename,
+ int line) override;
+ Result<Success> ParseLineSection(std::vector<std::string>&& args, int line) override;
+ Result<Success> EndSection() override;
+
+ private:
+ ActionManager* action_manager_;
+ std::vector<Subcontext>* subcontexts_;
+ std::unique_ptr<Action> action_;
+};
+
+} // namespace init
+} // namespace android
+
+#endif
diff --git a/init/builtins.cpp b/init/builtins.cpp
index be259c2..fc74dda 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -58,7 +58,7 @@
#include <selinux/selinux.h>
#include <system/thread_defs.h>
-#include "action.h"
+#include "action_manager.h"
#include "bootchart.h"
#include "init.h"
#include "parser.h"
@@ -971,8 +971,8 @@
const char* value = args[2].c_str();
size_t value_len = strlen(value);
- if (!is_legal_property_name(name)) {
- return Error() << "is_legal_property_name(" << name << ") failed";
+ if (!IsLegalPropertyName(name)) {
+ return Error() << "IsLegalPropertyName(" << name << ") failed";
}
if (value_len >= PROP_VALUE_MAX) {
return Error() << "value too long";
@@ -1005,6 +1005,7 @@
return do_exec({std::move(exec_args), args.context});
}
+// Builtin-function-map start
const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
// clang-format off
@@ -1062,6 +1063,7 @@
// clang-format on
return builtin_functions;
}
+// Builtin-function-map end
} // namespace init
} // namespace android
diff --git a/init/capabilities.cpp b/init/capabilities.cpp
index 50987db..a91cd1d 100644
--- a/init/capabilities.cpp
+++ b/init/capabilities.cpp
@@ -14,7 +14,6 @@
#include "capabilities.h"
-#include <sys/capability.h>
#include <sys/prctl.h>
#include <map>
@@ -72,10 +71,15 @@
static_assert(CAP_LAST_CAP == CAP_AUDIT_READ, "CAP_LAST_CAP is not CAP_AUDIT_READ");
static bool ComputeCapAmbientSupported() {
+#if defined(__ANDROID__)
return prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) >= 0;
+#else
+ return true;
+#endif
}
static unsigned int ComputeLastValidCap() {
+#if defined(__ANDROID__)
// Android does not support kernels < 3.8. 'CAP_WAKE_ALARM' has been present since 3.0, see
// http://lxr.free-electrons.com/source/include/linux/capability.h?v=3.0#L360.
unsigned int last_valid_cap = CAP_WAKE_ALARM;
@@ -83,6 +87,9 @@
// |last_valid_cap| will be the first failing value.
return last_valid_cap - 1;
+#else
+ return CAP_LAST_CAP;
+#endif
}
static bool DropBoundingSet(const CapSet& to_keep) {
@@ -139,6 +146,7 @@
}
static bool SetAmbientCaps(const CapSet& to_raise) {
+#if defined(__ANDROID__)
for (size_t cap = 0; cap < to_raise.size(); ++cap) {
if (to_raise.test(cap)) {
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap, 0, 0) != 0) {
@@ -147,6 +155,7 @@
}
}
}
+#endif
return true;
}
diff --git a/init/capabilities.h b/init/capabilities.h
index fc80c98..891e0ac 100644
--- a/init/capabilities.h
+++ b/init/capabilities.h
@@ -21,6 +21,17 @@
#include <string>
#include <type_traits>
+#if !defined(__ANDROID__)
+#ifndef CAP_BLOCK_SUSPEND
+#define CAP_BLOCK_SUSPEND 36
+#endif
+#ifndef CAP_AUDIT_READ
+#define CAP_AUDIT_READ 37
+#endif
+#undef CAP_LAST_CAP
+#define CAP_LAST_CAP CAP_AUDIT_READ
+#endif
+
namespace android {
namespace init {
diff --git a/init/host_init_parser.cpp b/init/host_init_parser.cpp
new file mode 100644
index 0000000..5232b7e
--- /dev/null
+++ b/init/host_init_parser.cpp
@@ -0,0 +1,82 @@
+//
+// 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 <pwd.h>
+
+#include <android-base/logging.h>
+
+#include "action.h"
+#include "action_manager.h"
+#include "action_parser.h"
+#include "parser.h"
+#include "result.h"
+#include "service.h"
+
+// The host passwd file won't have the Android entries, so we fake success here.
+passwd* getpwnam(const char* login) { // NOLINT: implementing bad function.
+ char dummy_buf[] = "dummy";
+ static passwd dummy_passwd = {
+ .pw_name = dummy_buf,
+ .pw_dir = dummy_buf,
+ .pw_shell = dummy_buf,
+ .pw_uid = 123,
+ .pw_gid = 123,
+ };
+ return &dummy_passwd;
+}
+
+namespace android {
+namespace init {
+
+static Result<Success> do_stub(const BuiltinArguments& args) {
+ return Success();
+}
+
+#include "generated_stub_builtin_function_map.h"
+
+int main(int argc, char** argv) {
+ android::base::InitLogging(argv, &android::base::StderrLogger);
+ if (argc != 2) {
+ LOG(ERROR) << "Usage: " << argv[0] << " <init file to parse>";
+ return -1;
+ }
+ const BuiltinFunctionMap function_map;
+ Action::set_function_map(&function_map);
+ ActionManager& am = ActionManager::GetInstance();
+ ServiceList& sl = ServiceList::GetInstance();
+ Parser parser;
+ parser.AddSectionParser("service", std::make_unique<ServiceParser>(&sl, nullptr));
+ parser.AddSectionParser("on", std::make_unique<ActionParser>(&am, nullptr));
+
+ size_t num_errors = 0;
+ if (!parser.ParseConfig(argv[1], &num_errors)) {
+ LOG(ERROR) << "Failed to find script";
+ return -1;
+ }
+ if (num_errors > 0) {
+ LOG(ERROR) << "Parse failed with " << num_errors << " errors";
+ return -1;
+ }
+ LOG(INFO) << "Parse success!";
+ return 0;
+}
+
+} // namespace init
+} // namespace android
+
+int main(int argc, char** argv) {
+ android::init::main(argc, argv);
+}
diff --git a/init/host_init_stubs.cpp b/init/host_init_stubs.cpp
new file mode 100644
index 0000000..e6cc08a
--- /dev/null
+++ b/init/host_init_stubs.cpp
@@ -0,0 +1,59 @@
+/*
+ * 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 "host_init_stubs.h"
+
+// unistd.h
+int setgroups(size_t __size, const gid_t* __list) {
+ return 0;
+}
+
+namespace android {
+namespace base {
+
+std::string GetProperty(const std::string&, const std::string& default_value) {
+ return default_value;
+}
+
+bool GetBoolProperty(const std::string&, bool default_value) {
+ return default_value;
+}
+
+} // namespace base
+} // namespace android
+
+namespace android {
+namespace init {
+
+// init.h
+std::string default_console = "/dev/console";
+
+// property_service.h
+uint32_t (*property_set)(const std::string& name, const std::string& value) = nullptr;
+uint32_t HandlePropertySet(const std::string&, const std::string&, const std::string&, const ucred&,
+ std::string*) {
+ return 0;
+}
+
+// selinux.h
+void SelabelInitialize() {}
+
+bool SelabelLookupFileContext(const std::string& key, int type, std::string* result) {
+ return false;
+}
+
+} // namespace init
+} // namespace android
diff --git a/init/host_init_stubs.h b/init/host_init_stubs.h
new file mode 100644
index 0000000..f31ece6
--- /dev/null
+++ b/init/host_init_stubs.h
@@ -0,0 +1,60 @@
+/*
+ * 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 _INIT_HOST_INIT_STUBS_H
+#define _INIT_HOST_INIT_STUBS_H
+
+#include <stddef.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include <string>
+
+// sys/system_properties.h
+#define PROP_VALUE_MAX 92
+
+// unistd.h
+int setgroups(size_t __size, const gid_t* __list);
+
+// android-base/properties.h
+namespace android {
+namespace base {
+
+std::string GetProperty(const std::string& key, const std::string& default_value);
+bool GetBoolProperty(const std::string& key, bool default_value);
+
+} // namespace base
+} // namespace android
+
+namespace android {
+namespace init {
+
+// init.h
+extern std::string default_console;
+
+// property_service.h
+extern uint32_t (*property_set)(const std::string& name, const std::string& value);
+uint32_t HandlePropertySet(const std::string& name, const std::string& value,
+ const std::string& source_context, const ucred& cr, std::string* error);
+
+// selinux.h
+void SelabelInitialize();
+bool SelabelLookupFileContext(const std::string& key, int type, std::string* result);
+
+} // namespace init
+} // namespace android
+
+#endif
diff --git a/init/init.cpp b/init/init.cpp
index bd09e4b..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>
@@ -45,6 +46,7 @@
#include <memory>
#include <optional>
+#include "action_parser.h"
#include "import_parser.h"
#include "init_first_stage.h"
#include "keychords.h"
@@ -62,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 {
@@ -245,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);
@@ -254,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 ff7bdeb..d4a0e96 100644
--- a/init/init.h
+++ b/init/init.h
@@ -17,10 +17,13 @@
#ifndef _INIT_INIT_H
#define _INIT_INIT_H
+#include <sys/types.h>
+
#include <string>
#include <vector>
#include "action.h"
+#include "action_manager.h"
#include "parser.h"
#include "service.h"
@@ -35,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/init_test.cpp b/init/init_test.cpp
index 268873c..0f9635f 100644
--- a/init/init_test.cpp
+++ b/init/init_test.cpp
@@ -21,6 +21,8 @@
#include <gtest/gtest.h>
#include "action.h"
+#include "action_manager.h"
+#include "action_parser.h"
#include "builtins.h"
#include "import_parser.h"
#include "keyword_map.h"
diff --git a/init/parser.cpp b/init/parser.cpp
index 4c69bac..4453aaa 100644
--- a/init/parser.cpp
+++ b/init/parser.cpp
@@ -39,7 +39,7 @@
line_callbacks_.emplace_back(prefix, callback);
}
-void Parser::ParseData(const std::string& filename, const std::string& data) {
+void Parser::ParseData(const std::string& filename, const std::string& data, size_t* parse_errors) {
// TODO: Use a parser with const input and remove this copy
std::vector<char> data_copy(data.begin(), data.end());
data_copy.push_back('\0');
@@ -57,6 +57,7 @@
if (section_parser == nullptr) return;
if (auto result = section_parser->EndSection(); !result) {
+ (*parse_errors)++;
LOG(ERROR) << filename << ": " << section_start_line << ": " << result.error();
}
@@ -80,6 +81,7 @@
end_section();
if (auto result = callback(std::move(args)); !result) {
+ (*parse_errors)++;
LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
}
break;
@@ -92,12 +94,14 @@
if (auto result =
section_parser->ParseSection(std::move(args), filename, state.line);
!result) {
+ (*parse_errors)++;
LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
section_parser = nullptr;
}
} else if (section_parser) {
if (auto result = section_parser->ParseLineSection(std::move(args), state.line);
!result) {
+ (*parse_errors)++;
LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
}
}
@@ -110,7 +114,7 @@
}
}
-bool Parser::ParseConfigFile(const std::string& path) {
+bool Parser::ParseConfigFile(const std::string& path, size_t* parse_errors) {
LOG(INFO) << "Parsing file " << path << "...";
android::base::Timer t;
auto config_contents = ReadFile(path);
@@ -120,7 +124,7 @@
}
config_contents->push_back('\n'); // TODO: fix parse_config.
- ParseData(path, *config_contents);
+ ParseData(path, *config_contents, parse_errors);
for (const auto& [section_name, section_parser] : section_parsers_) {
section_parser->EndFile();
}
@@ -129,7 +133,7 @@
return true;
}
-bool Parser::ParseConfigDir(const std::string& path) {
+bool Parser::ParseConfigDir(const std::string& path, size_t* parse_errors) {
LOG(INFO) << "Parsing directory " << path << "...";
std::unique_ptr<DIR, decltype(&closedir)> config_dir(opendir(path.c_str()), closedir);
if (!config_dir) {
@@ -149,7 +153,7 @@
// Sort first so we load files in a consistent order (bug 31996208)
std::sort(files.begin(), files.end());
for (const auto& file : files) {
- if (!ParseConfigFile(file)) {
+ if (!ParseConfigFile(file, parse_errors)) {
LOG(ERROR) << "could not import file '" << file << "'";
}
}
@@ -157,10 +161,16 @@
}
bool Parser::ParseConfig(const std::string& path) {
+ size_t parse_errors;
+ return ParseConfig(path, &parse_errors);
+}
+
+bool Parser::ParseConfig(const std::string& path, size_t* parse_errors) {
+ *parse_errors = 0;
if (is_dir(path.c_str())) {
- return ParseConfigDir(path);
+ return ParseConfigDir(path, parse_errors);
}
- return ParseConfigFile(path);
+ return ParseConfigFile(path, parse_errors);
}
} // namespace init
diff --git a/init/parser.h b/init/parser.h
index 110a468..f6e237f 100644
--- a/init/parser.h
+++ b/init/parser.h
@@ -72,13 +72,14 @@
Parser();
bool ParseConfig(const std::string& path);
+ bool ParseConfig(const std::string& path, size_t* parse_errors);
void AddSectionParser(const std::string& name, std::unique_ptr<SectionParser> parser);
void AddSingleLineParser(const std::string& prefix, LineCallback callback);
private:
- void ParseData(const std::string& filename, const std::string& data);
- bool ParseConfigFile(const std::string& path);
- bool ParseConfigDir(const std::string& path);
+ void ParseData(const std::string& filename, const std::string& data, size_t* parse_errors);
+ bool ParseConfigFile(const std::string& path, size_t* parse_errors);
+ bool ParseConfigDir(const std::string& path, size_t* parse_errors);
std::map<std::string, std::unique_ptr<SectionParser>> section_parsers_;
std::vector<std::pair<std::string, LineCallback>> line_callbacks_;
diff --git a/init/property_service.cpp b/init/property_service.cpp
index ecd5baa..95ef35c 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -59,8 +59,11 @@
#include "init.h"
#include "persistent_properties.h"
#include "property_type.h"
+#include "subcontext.h"
#include "util.h"
+using namespace std::literals;
+
using android::base::ReadFileToString;
using android::base::Split;
using android::base::StartsWith;
@@ -117,48 +120,21 @@
return has_access;
}
-bool is_legal_property_name(const std::string& name) {
- size_t namelen = name.size();
-
- if (namelen < 1) return false;
- if (name[0] == '.') return false;
- if (name[namelen - 1] == '.') return false;
-
- /* Only allow alphanumeric, plus '.', '-', '@', ':', or '_' */
- /* Don't allow ".." to appear in a property name */
- for (size_t i = 0; i < namelen; i++) {
- if (name[i] == '.') {
- // i=0 is guaranteed to never have a dot. See above.
- if (name[i-1] == '.') return false;
- continue;
- }
- if (name[i] == '_' || name[i] == '-' || name[i] == '@' || name[i] == ':') continue;
- if (name[i] >= 'a' && name[i] <= 'z') continue;
- if (name[i] >= 'A' && name[i] <= 'Z') continue;
- if (name[i] >= '0' && name[i] <= '9') continue;
- return false;
- }
-
- return true;
-}
-
-static uint32_t PropertySetImpl(const std::string& name, const std::string& value) {
+static uint32_t PropertySet(const std::string& name, const std::string& value, std::string* error) {
size_t valuelen = value.size();
- if (!is_legal_property_name(name)) {
- LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: bad name";
+ if (!IsLegalPropertyName(name)) {
+ *error = "Illegal property name";
return PROP_ERROR_INVALID_NAME;
}
if (valuelen >= PROP_VALUE_MAX && !StartsWith(name, "ro.")) {
- LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: "
- << "value too long";
+ *error = "Property value too long";
return PROP_ERROR_INVALID_VALUE;
}
if (mbstowcs(nullptr, value.data(), 0) == static_cast<std::size_t>(-1)) {
- LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: "
- << "value not a UTF8 encoded string";
+ *error = "Value is not a UTF8 encoded string";
return PROP_ERROR_INVALID_VALUE;
}
@@ -166,8 +142,7 @@
if (pi != nullptr) {
// ro.* properties are actually "write-once".
if (StartsWith(name, "ro.")) {
- LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: "
- << "property already set";
+ *error = "Read-only property was already set";
return PROP_ERROR_READ_ONLY_PROPERTY;
}
@@ -175,8 +150,7 @@
} else {
int rc = __system_property_add(name.c_str(), name.size(), value.c_str(), valuelen);
if (rc < 0) {
- LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: "
- << "__system_property_add failed";
+ *error = "__system_property_add failed";
return PROP_ERROR_SET_FAILED;
}
}
@@ -230,8 +204,10 @@
if (info.pid != pid) {
return false;
}
- if (PropertySetImpl(info.name, info.value) != PROP_SUCCESS) {
- LOG(ERROR) << "Failed to set async property " << info.name;
+ std::string error;
+ if (PropertySet(info.name, info.value, &error) != PROP_SUCCESS) {
+ LOG(ERROR) << "Failed to set async property " << info.name << " to " << info.value << ": "
+ << error;
}
property_children.pop();
if (!property_children.empty()) {
@@ -241,9 +217,9 @@
}
static uint32_t PropertySetAsync(const std::string& name, const std::string& value,
- PropertyAsyncFunc func) {
+ PropertyAsyncFunc func, std::string* error) {
if (value.empty()) {
- return PropertySetImpl(name, value);
+ return PropertySet(name, value, error);
}
PropertyChildInfo info;
@@ -261,30 +237,27 @@
return selinux_android_restorecon(value.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE);
}
-uint32_t PropertySet(const std::string& name, const std::string& value) {
- if (name == "selinux.restorecon_recursive") {
- return PropertySetAsync(name, value, RestoreconRecursiveAsync);
- }
-
- return PropertySetImpl(name, value);
-}
-
uint32_t InitPropertySet(const std::string& name, const std::string& value) {
if (StartsWith(name, "ctl.")) {
- LOG(ERROR) << "Do not set ctl. properties from init; call the Service functions directly";
+ LOG(ERROR) << "InitPropertySet: Do not set ctl. properties from init; call the Service "
+ "functions directly";
+ return PROP_ERROR_INVALID_NAME;
+ }
+ if (name == "selinux.restorecon_recursive") {
+ LOG(ERROR) << "InitPropertySet: Do not set selinux.restorecon_recursive from init; use the "
+ "restorecon builtin directly";
return PROP_ERROR_INVALID_NAME;
}
- const char* type = nullptr;
- property_info_area->GetPropertyInfo(name.c_str(), nullptr, &type);
-
- if (type == nullptr || !CheckType(type, value)) {
- LOG(ERROR) << "property_set: name: '" << name << "' type check failed, type: '"
- << (type ?: "(null)") << "' value: '" << value << "'";
- return PROP_ERROR_INVALID_VALUE;
+ uint32_t result = 0;
+ ucred cr = {.pid = 1, .uid = 0, .gid = 0};
+ std::string error;
+ result = HandlePropertySet(name, value, kInitContext.c_str(), cr, &error);
+ if (result != PROP_SUCCESS) {
+ LOG(ERROR) << "Init cannot set '" << name << "' to '" << value << "': " << error;
}
- return PropertySet(name, value);
+ return result;
}
class SocketConnection {
@@ -415,9 +388,9 @@
// This returns one of the enum of PROP_SUCCESS or PROP_ERROR*.
uint32_t HandlePropertySet(const std::string& name, const std::string& value,
- const std::string& source_context, const ucred& cr) {
- if (!is_legal_property_name(name)) {
- LOG(ERROR) << "PropertySet: illegal property name \"" << name << "\"";
+ const std::string& source_context, const ucred& cr, std::string* error) {
+ if (!IsLegalPropertyName(name)) {
+ *error = "Illegal property name";
return PROP_ERROR_INVALID_NAME;
}
@@ -430,13 +403,11 @@
const char* type = nullptr;
property_info_area->GetPropertyInfo(control_string.c_str(), &target_context, &type);
if (!CheckMacPerms(control_string, target_context, source_context.c_str(), cr)) {
- LOG(ERROR) << "PropertySet: Unable to " << (name.c_str() + 4) << " service ctl ["
- << value << "]"
- << " uid:" << cr.uid << " gid:" << cr.gid << " pid:" << cr.pid;
+ *error = StringPrintf("Unable to '%s' service %s", name.c_str() + 4, value.c_str());
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;
}
@@ -445,13 +416,13 @@
property_info_area->GetPropertyInfo(name.c_str(), &target_context, &type);
if (!CheckMacPerms(name, target_context, source_context.c_str(), cr)) {
- LOG(ERROR) << "PropertySet: permission denied uid:" << cr.uid << " name:" << name;
+ *error = "SELinux permission check failed";
return PROP_ERROR_PERMISSION_DENIED;
}
if (type == nullptr || !CheckType(type, value)) {
- LOG(ERROR) << "PropertySet: name: '" << name << "' type check failed, type: '"
- << (type ?: "(null)") << "' value: '" << value << "'";
+ *error = StringPrintf("Property type check failed, value doesn't match expected type '%s'",
+ (type ?: "(null)"));
return PROP_ERROR_INVALID_VALUE;
}
@@ -470,7 +441,11 @@
<< process_log_string;
}
- return PropertySet(name, value);
+ if (name == "selinux.restorecon_recursive") {
+ return PropertySetAsync(name, value, RestoreconRecursiveAsync, error);
+ }
+
+ return PropertySet(name, value, error);
}
static void handle_property_set_fd() {
@@ -513,7 +488,16 @@
prop_name[PROP_NAME_MAX-1] = 0;
prop_value[PROP_VALUE_MAX-1] = 0;
- HandlePropertySet(prop_value, prop_value, socket.source_context(), socket.cred());
+ const auto& cr = socket.cred();
+ std::string error;
+ uint32_t result =
+ HandlePropertySet(prop_name, prop_value, socket.source_context(), cr, &error);
+ if (result != PROP_SUCCESS) {
+ LOG(ERROR) << "Unable to set property '" << prop_name << "' to '" << prop_value
+ << "' from uid:" << cr.uid << " gid:" << cr.gid << " pid:" << cr.pid << ": "
+ << error;
+ }
+
break;
}
@@ -527,7 +511,14 @@
return;
}
- auto result = HandlePropertySet(name, value, socket.source_context(), socket.cred());
+ const auto& cr = socket.cred();
+ std::string error;
+ uint32_t result = HandlePropertySet(name, value, socket.source_context(), cr, &error);
+ if (result != PROP_SUCCESS) {
+ LOG(ERROR) << "Unable to set property '" << name << "' to '" << value
+ << "' from uid:" << cr.uid << " gid:" << cr.gid << " pid:" << cr.pid << ": "
+ << error;
+ }
socket.SendUint32(result);
break;
}
@@ -545,11 +536,17 @@
* Filter is used to decide which properties to load: NULL loads all keys,
* "ro.foo.*" is a prefix match, and "ro.foo.bar" is an exact match.
*/
-static void load_properties(char *data, const char *filter)
-{
+static void LoadProperties(char* data, const char* filter, const char* filename) {
char *key, *value, *eol, *sol, *tmp, *fn;
size_t flen = 0;
+ const char* context = kInitContext.c_str();
+ for (const auto& [path_prefix, secontext] : paths_and_secontexts) {
+ if (StartsWith(filename, path_prefix)) {
+ context = secontext;
+ }
+ }
+
if (filter) {
flen = strlen(filter);
}
@@ -596,7 +593,21 @@
}
}
- property_set(key, value);
+ if (StartsWith(key, "ctl.") || key == "sys.powerctl"s ||
+ key == "selinux.restorecon_recursive"s) {
+ LOG(ERROR) << "Ignoring disallowed property '" << key
+ << "' with special meaning in prop file '" << filename << "'";
+ continue;
+ }
+
+ uint32_t result = 0;
+ ucred cr = {.pid = 1, .uid = 0, .gid = 0};
+ std::string error;
+ result = HandlePropertySet(key, value, context, cr, &error);
+ if (result != PROP_SUCCESS) {
+ LOG(ERROR) << "Unable to set property '" << key << "' to '" << value
+ << "' in property file '" << filename << "': " << error;
+ }
}
}
}
@@ -612,7 +623,8 @@
return false;
}
file_contents->push_back('\n');
- load_properties(file_contents->data(), filter);
+
+ LoadProperties(file_contents->data(), filter, filename);
LOG(VERBOSE) << "(Loading properties from " << filename << " took " << t << ".)";
return true;
}
diff --git a/init/property_service.h b/init/property_service.h
index 8161b40..29eaaa9 100644
--- a/init/property_service.h
+++ b/init/property_service.h
@@ -32,7 +32,7 @@
extern uint32_t (*property_set)(const std::string& name, const std::string& value);
uint32_t HandlePropertySet(const std::string& name, const std::string& value,
- const std::string& source_context, const ucred& cr);
+ const std::string& source_context, const ucred& cr, std::string* error);
extern bool PropertyChildReap(pid_t pid);
@@ -41,7 +41,6 @@
void load_persist_props(void);
void load_system_props(void);
void start_property_service(void);
-bool is_legal_property_name(const std::string& name);
} // namespace init
} // namespace android
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/init/reboot.cpp b/init/reboot.cpp
index a88a42d..03ed55a 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -20,6 +20,7 @@
#include <fcntl.h>
#include <linux/fs.h>
#include <mntent.h>
+#include <semaphore.h>
#include <sys/capability.h>
#include <sys/cdefs.h>
#include <sys/ioctl.h>
@@ -50,6 +51,7 @@
#include <private/android_filesystem_config.h>
#include <selinux/selinux.h>
+#include "action_manager.h"
#include "capabilities.h"
#include "init.h"
#include "property_service.h"
@@ -88,12 +90,13 @@
mnt_opts_(entry.mnt_opts) {}
bool Umount(bool force) {
+ LOG(INFO) << "Unmounting " << mnt_fsname_ << ":" << mnt_dir_ << " opts " << mnt_opts_;
int r = umount2(mnt_dir_.c_str(), force ? MNT_FORCE : 0);
if (r == 0) {
- LOG(INFO) << "umounted " << mnt_fsname_ << ":" << mnt_dir_ << " opts " << mnt_opts_;
+ LOG(INFO) << "Umounted " << mnt_fsname_ << ":" << mnt_dir_ << " opts " << mnt_opts_;
return true;
} else {
- PLOG(WARNING) << "cannot umount " << mnt_fsname_ << ":" << mnt_dir_ << " opts "
+ PLOG(WARNING) << "Cannot umount " << mnt_fsname_ << ":" << mnt_dir_ << " opts "
<< mnt_opts_;
return false;
}
@@ -327,39 +330,9 @@
return stat;
}
-void DoReboot(unsigned int cmd, const std::string& reason, const std::string& rebootTarget,
- bool runFsck) {
+void RebootThread(unsigned int cmd, std::chrono::milliseconds shutdown_timeout, bool runFsck,
+ sem_t* reboot_semaphore) {
Timer t;
- LOG(INFO) << "Reboot start, reason: " << reason << ", rebootTarget: " << rebootTarget;
-
- // Ensure last reboot reason is reduced to canonical
- // alias reported in bootloader or system boot reason.
- size_t skip = 0;
- std::vector<std::string> reasons = Split(reason, ",");
- if (reasons.size() >= 2 && reasons[0] == "reboot" &&
- (reasons[1] == "recovery" || reasons[1] == "bootloader" || reasons[1] == "cold" ||
- reasons[1] == "hard" || reasons[1] == "warm")) {
- skip = strlen("reboot,");
- }
- property_set(LAST_REBOOT_REASON_PROPERTY, reason.c_str() + skip);
- sync();
-
- bool is_thermal_shutdown = cmd == ANDROID_RB_THERMOFF;
-
- auto shutdown_timeout = 0ms;
- if (!SHUTDOWN_ZERO_TIMEOUT) {
- if (is_thermal_shutdown) {
- constexpr unsigned int thermal_shutdown_timeout = 1;
- shutdown_timeout = std::chrono::seconds(thermal_shutdown_timeout);
- } else {
- constexpr unsigned int shutdown_timeout_default = 6;
- auto shutdown_timeout_property = android::base::GetUintProperty(
- "ro.build.shutdown_timeout", shutdown_timeout_default);
- shutdown_timeout = std::chrono::seconds(shutdown_timeout_property);
- }
- }
- LOG(INFO) << "Shutdown timeout: " << shutdown_timeout.count() << " ms";
-
// keep debugging tools until non critical ones are all gone.
const std::set<std::string> kill_after_apps{"tombstoned", "logd", "adbd"};
// watchdogd is a vendor specific component but should be alive to complete shutdown safely.
@@ -383,7 +356,7 @@
}
// remaining operations (specifically fsck) may take a substantial duration
- if (cmd == ANDROID_RB_POWEROFF || is_thermal_shutdown) {
+ if (cmd == ANDROID_RB_POWEROFF || cmd == ANDROID_RB_THERMOFF) {
TurnOffBacklight();
}
@@ -460,8 +433,77 @@
UmountStat stat = TryUmountAndFsck(runFsck, shutdown_timeout - t.duration());
// Follow what linux shutdown is doing: one more sync with little bit delay
sync();
- if (!is_thermal_shutdown) std::this_thread::sleep_for(100ms);
+ if (cmd != ANDROID_RB_THERMOFF) std::this_thread::sleep_for(100ms);
LogShutdownTime(stat, &t);
+
+ if (reboot_semaphore != nullptr) {
+ sem_post(reboot_semaphore);
+ }
+}
+
+void RunRebootThread(unsigned int cmd, std::chrono::milliseconds shutdown_timeout) {
+ sem_t reboot_semaphore;
+ timespec shutdown_timeout_timespec;
+
+ if (sem_init(&reboot_semaphore, false, 0) == -1 ||
+ clock_gettime(CLOCK_REALTIME, &shutdown_timeout_timespec) == -1) {
+ // These should never fail, but if they do, skip the graceful reboot and reboot immediately.
+ return;
+ }
+
+ std::thread reboot_thread(&RebootThread, cmd, shutdown_timeout, false, &reboot_semaphore);
+ reboot_thread.detach();
+
+ // One extra second than the timeout passed to the thread as there is a final Umount pass
+ // after the timeout is reached.
+ shutdown_timeout_timespec.tv_sec += 1 + shutdown_timeout.count() / 1000;
+
+ int sem_return = 0;
+ while ((sem_return = sem_timedwait(&reboot_semaphore, &shutdown_timeout_timespec)) == -1 &&
+ errno == EINTR) {
+ }
+
+ if (sem_return == -1) {
+ LOG(ERROR) << "Reboot thread timed out";
+ }
+}
+
+void DoReboot(unsigned int cmd, const std::string& reason, const std::string& rebootTarget,
+ bool runFsck) {
+ LOG(INFO) << "Reboot start, reason: " << reason << ", rebootTarget: " << rebootTarget;
+
+ // Ensure last reboot reason is reduced to canonical
+ // alias reported in bootloader or system boot reason.
+ size_t skip = 0;
+ std::vector<std::string> reasons = Split(reason, ",");
+ if (reasons.size() >= 2 && reasons[0] == "reboot" &&
+ (reasons[1] == "recovery" || reasons[1] == "bootloader" || reasons[1] == "cold" ||
+ reasons[1] == "hard" || reasons[1] == "warm")) {
+ skip = strlen("reboot,");
+ }
+ property_set(LAST_REBOOT_REASON_PROPERTY, reason.c_str() + skip);
+ sync();
+
+ auto shutdown_timeout = 0ms;
+ if (!SHUTDOWN_ZERO_TIMEOUT) {
+ if (cmd == ANDROID_RB_THERMOFF) {
+ constexpr auto kThermalShutdownTimeout = 1s;
+ shutdown_timeout = kThermalShutdownTimeout;
+ } else {
+ constexpr unsigned int kShutdownTimeoutDefault = 6;
+ auto shutdown_timeout_property = android::base::GetUintProperty(
+ "ro.build.shutdown_timeout", kShutdownTimeoutDefault);
+ shutdown_timeout = std::chrono::seconds(shutdown_timeout_property);
+ }
+ }
+ LOG(INFO) << "Shutdown timeout: " << shutdown_timeout.count() << " ms";
+
+ if (runFsck) {
+ RebootThread(cmd, shutdown_timeout, true, nullptr);
+ } else {
+ RunRebootThread(cmd, shutdown_timeout);
+ }
+
// Reboot regardless of umount status. If umount fails, fsck after reboot will fix it.
RebootSystem(cmd, rebootTarget);
abort();
diff --git a/init/service.cpp b/init/service.cpp
index a4e33f7..8130e73 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -24,7 +24,6 @@
#include <sys/prctl.h>
#include <sys/resource.h>
#include <sys/stat.h>
-#include <sys/system_properties.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <termios.h>
@@ -33,8 +32,6 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/parseint.h>
-#include <android-base/properties.h>
-#include <android-base/scopeguard.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <hidl-util/FQName.h>
@@ -42,15 +39,23 @@
#include <selinux/selinux.h>
#include <system/thread_defs.h>
-#include "init.h"
-#include "property_service.h"
#include "rlimit_parser.h"
#include "util.h"
+#if defined(__ANDROID__)
+#include <sys/system_properties.h>
+
+#include <android-base/properties.h>
+
+#include "init.h"
+#include "property_service.h"
+#else
+#include "host_init_stubs.h"
+#endif
+
using android::base::boot_clock;
using android::base::GetProperty;
using android::base::Join;
-using android::base::make_scope_guard;
using android::base::ParseInt;
using android::base::StartsWith;
using android::base::StringPrintf;
@@ -189,7 +194,8 @@
capabilities_(capabilities),
namespace_flags_(namespace_flags),
seclabel_(seclabel),
- onrestart_(false, subcontext_for_restart_commands, "<Service '" + name + "' onrestart>", 0),
+ onrestart_(false, subcontext_for_restart_commands, "<Service '" + name + "' onrestart>", 0,
+ "onrestart", {}),
keychord_id_(0),
ioprio_class_(IoSchedClass_NONE),
ioprio_pri_(0),
@@ -199,9 +205,7 @@
soft_limit_in_bytes_(-1),
limit_in_bytes_(-1),
start_order_(0),
- args_(args) {
- onrestart_.InitSingleTrigger("onrestart");
-}
+ args_(args) {}
void Service::NotifyStateChange(const std::string& new_state) const {
if ((flags_ & SVC_TEMPORARY) != 0) {
@@ -1165,7 +1169,7 @@
// Property values can contain any characters, but may only be a certain length.
// (The latter restriction is needed because `start` and `stop` work by writing
// the service name to the "ctl.start" and "ctl.stop" properties.)
- return is_legal_property_name("init.svc." + name) && name.size() <= PROP_VALUE_MAX;
+ return IsLegalPropertyName("init.svc." + name) && name.size() <= PROP_VALUE_MAX;
}
} // namespace init
diff --git a/init/subcontext.cpp b/init/subcontext.cpp
index f3b643a..c1846f7 100644
--- a/init/subcontext.cpp
+++ b/init/subcontext.cpp
@@ -27,12 +27,14 @@
#include <selinux/android.h>
#include "action.h"
-#include "property_service.h"
-#include "selinux.h"
#include "util.h"
-#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
-#include <sys/_system_properties.h>
+#if defined(__ANDROID__)
+#include "property_service.h"
+#include "selinux.h"
+#else
+#include "host_init_stubs.h"
+#endif
using android::base::GetExecutablePath;
using android::base::Join;
@@ -47,6 +49,11 @@
const std::string kInitContext = "u:r:init:s0";
const std::string kVendorContext = "u:r:vendor_init:s0";
+const char* const paths_and_secontexts[2][2] = {
+ {"/vendor", kVendorContext.c_str()},
+ {"/odm", kVendorContext.c_str()},
+};
+
namespace {
constexpr size_t kBufferSize = 4096;
@@ -83,7 +90,7 @@
uint32_t SubcontextPropertySet(const std::string& name, const std::string& value) {
properties_to_set.emplace_back(name, value);
- return PROP_SUCCESS;
+ return 0;
}
class SubcontextProcess {
@@ -295,7 +302,11 @@
for (const auto& property : subcontext_reply->properties_to_set()) {
ucred cr = {.pid = pid_, .uid = 0, .gid = 0};
- HandlePropertySet(property.name(), property.value(), context_, cr);
+ std::string error;
+ if (HandlePropertySet(property.name(), property.value(), context_, cr, &error) != 0) {
+ LOG(ERROR) << "Subcontext init could not set '" << property.name() << "' to '"
+ << property.value() << "': " << error;
+ }
}
if (subcontext_reply->reply_case() == SubcontextReply::kFailure) {
@@ -343,9 +354,6 @@
static std::vector<Subcontext> subcontexts;
std::vector<Subcontext>* InitializeSubcontexts() {
- static const char* const paths_and_secontexts[][2] = {
- {"/vendor", kVendorContext.c_str()},
- };
for (const auto& [path_prefix, secontext] : paths_and_secontexts) {
subcontexts.emplace_back(path_prefix, secontext);
}
diff --git a/init/subcontext.h b/init/subcontext.h
index 5601b80..22d7d43 100644
--- a/init/subcontext.h
+++ b/init/subcontext.h
@@ -33,6 +33,7 @@
extern const std::string kInitContext;
extern const std::string kVendorContext;
+extern const char* const paths_and_secontexts[2][2];
class Subcontext {
public:
diff --git a/init/test_service/Android.bp b/init/test_service/Android.bp
index 6399699..8bd16a7 100644
--- a/init/test_service/Android.bp
+++ b/init/test_service/Android.bp
@@ -17,7 +17,10 @@
cc_binary {
name: "test_service",
srcs: ["test_service.cpp"],
- cflags: ["-Wall", "-Werror"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
shared_libs: ["libbase"],
init_rc: ["test_service.rc"],
}
diff --git a/init/util.cpp b/init/util.cpp
index d80cb1e..4455b2e 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -33,7 +33,6 @@
#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 <android-base/unique_fd.h>
@@ -42,7 +41,14 @@
#include <selinux/android.h>
#include "reboot.h"
+
+#if defined(__ANDROID__)
+#include <android-base/properties.h>
+
#include "selinux.h"
+#else
+#include "host_init_stubs.h"
+#endif
#ifdef _INIT_INIT_H
#error "Do not include init.h in files used by ueventd or watchdogd; it will expose init's globals"
@@ -409,5 +415,30 @@
return false;
}
+bool IsLegalPropertyName(const std::string& name) {
+ size_t namelen = name.size();
+
+ if (namelen < 1) return false;
+ if (name[0] == '.') return false;
+ if (name[namelen - 1] == '.') return false;
+
+ /* Only allow alphanumeric, plus '.', '-', '@', ':', or '_' */
+ /* Don't allow ".." to appear in a property name */
+ for (size_t i = 0; i < namelen; i++) {
+ if (name[i] == '.') {
+ // i=0 is guaranteed to never have a dot. See above.
+ if (name[i - 1] == '.') return false;
+ continue;
+ }
+ if (name[i] == '_' || name[i] == '-' || name[i] == '@' || name[i] == ':') continue;
+ if (name[i] >= 'a' && name[i] <= 'z') continue;
+ if (name[i] >= 'A' && name[i] <= 'Z') continue;
+ if (name[i] >= '0' && name[i] <= '9') continue;
+ return false;
+ }
+
+ return true;
+}
+
} // namespace init
} // namespace android
diff --git a/init/util.h b/init/util.h
index 2cfcf6c..07e4864 100644
--- a/init/util.h
+++ b/init/util.h
@@ -62,6 +62,8 @@
bool read_android_dt_file(const std::string& sub_path, std::string* dt_content);
bool is_android_dt_value_expected(const std::string& sub_path, const std::string& expected_content);
+bool IsLegalPropertyName(const std::string& name);
+
} // namespace init
} // namespace android
diff --git a/libappfuse/Android.bp b/libappfuse/Android.bp
index 29ffe32..ae1481f 100644
--- a/libappfuse/Android.bp
+++ b/libappfuse/Android.bp
@@ -19,7 +19,7 @@
"FuseBuffer.cc",
"FuseBridgeLoop.cc",
"EpollController.cc",
- ]
+ ],
}
cc_test {
@@ -31,5 +31,5 @@
"tests/FuseAppLoopTest.cc",
"tests/FuseBridgeLoopTest.cc",
"tests/FuseBufferTest.cc",
- ]
+ ],
}
diff --git a/libasyncio/Android.bp b/libasyncio/Android.bp
index 9a12f0d..8a2afea 100644
--- a/libasyncio/Android.bp
+++ b/libasyncio/Android.bp
@@ -16,7 +16,11 @@
cc_defaults {
name: "libasyncio_defaults",
- cflags: ["-Wall", "-Werror", "-Wextra"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
}
cc_library {
diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp
index 10a4e46..4bd01d2 100644
--- a/libbacktrace/Android.bp
+++ b/libbacktrace/Android.bp
@@ -27,7 +27,6 @@
include_dirs: ["external/libunwind/include/tdep"],
-
target: {
darwin: {
enabled: false,
@@ -41,7 +40,7 @@
lib64: {
suffix: "64",
},
- }
+ },
}
libbacktrace_sources = [
@@ -83,6 +82,9 @@
target: {
darwin: {
enabled: true,
+ shared_libs: [
+ "libbase",
+ ],
},
linux: {
srcs: libbacktrace_sources,
@@ -103,7 +105,7 @@
"art/runtime",
],
- header_libs: [ "jni_headers", ],
+ header_libs: ["jni_headers"],
},
android: {
static_libs: ["libasync_safe"],
@@ -111,7 +113,7 @@
vendor: {
cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
exclude_shared_libs: ["libdexfile"],
- }
+ },
},
whole_static_libs: ["libdemangle"],
}
@@ -127,7 +129,7 @@
srcs: ["backtrace_testlib.cpp"],
shared_libs: [
- "libunwindstack",
+ "libunwindstack",
],
}
diff --git a/libbacktrace/Backtrace.cpp b/libbacktrace/Backtrace.cpp
index dec241c..6445a7c 100644
--- a/libbacktrace/Backtrace.cpp
+++ b/libbacktrace/Backtrace.cpp
@@ -85,14 +85,12 @@
std::string Backtrace::FormatFrameData(const backtrace_frame_data_t* frame) {
std::string map_name;
if (BacktraceMap::IsValid(frame->map)) {
+ map_name = frame->map.Name();
if (!frame->map.name.empty()) {
- map_name = frame->map.name.c_str();
if (map_name[0] == '[' && map_name[map_name.size() - 1] == ']') {
map_name.resize(map_name.size() - 1);
map_name += StringPrintf(":%" PRIPTR "]", frame->map.start);
}
- } else {
- map_name = StringPrintf("<anonymous:%" PRIPTR ">", frame->map.start);
}
} else {
map_name = "<unknown>";
diff --git a/libbacktrace/BacktraceMap.cpp b/libbacktrace/BacktraceMap.cpp
index c8a500c..bdae140 100644
--- a/libbacktrace/BacktraceMap.cpp
+++ b/libbacktrace/BacktraceMap.cpp
@@ -24,11 +24,21 @@
#include <log/log.h>
-#include <backtrace/backtrace_constants.h>
+#include <android-base/stringprintf.h>
+#include <backtrace/Backtrace.h>
#include <backtrace/BacktraceMap.h>
+#include <backtrace/backtrace_constants.h>
#include "thread_utils.h"
+using android::base::StringPrintf;
+
+std::string backtrace_map_t::Name() const {
+ if (!name.empty()) return name;
+ if (start == 0 && end == 0) return "";
+ return StringPrintf("<anonymous:%" PRIPTR ">", start);
+}
+
BacktraceMap::BacktraceMap(pid_t pid) : pid_(pid) {
if (pid_ < 0) {
pid_ = getpid();
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 e19c413..473d195 100644
--- a/libbacktrace/include/backtrace/BacktraceMap.h
+++ b/libbacktrace/include/backtrace/BacktraceMap.h
@@ -48,6 +48,9 @@
uint64_t load_bias = 0;
int flags = 0;
std::string name;
+
+ // Returns `name` if non-empty, or `<anonymous:0x...>` otherwise.
+ std::string Name() const;
};
namespace unwindstack {
@@ -61,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();
@@ -151,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);
@@ -161,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/libcutils/include/cutils/trace.h b/libcutils/include/cutils/trace.h
index fcbdc9b..b2779b2 100644
--- a/libcutils/include/cutils/trace.h
+++ b/libcutils/include/cutils/trace.h
@@ -72,7 +72,8 @@
#define ATRACE_TAG_DATABASE (1<<20)
#define ATRACE_TAG_NETWORK (1<<21)
#define ATRACE_TAG_ADB (1<<22)
-#define ATRACE_TAG_LAST ATRACE_TAG_ADB
+#define ATRACE_TAG_VIBRATOR (1<<23)
+#define ATRACE_TAG_LAST ATRACE_TAG_VIBRATOR
// Reserved for initialization.
#define ATRACE_TAG_NOT_READY (1ULL<<63)
diff --git a/libion/Android.bp b/libion/Android.bp
index 6d9fae0..2f73d92 100644
--- a/libion/Android.bp
+++ b/libion/Android.bp
@@ -1,4 +1,3 @@
-
cc_library {
name: "libion",
vendor_available: true,
diff --git a/libion/ion_test.c b/libion/ion_test.c
index b7d5583..f3874ae 100644
--- a/libion/ion_test.c
+++ b/libion/ion_test.c
@@ -250,7 +250,7 @@
case 'p':
prot = 0;
prot |= strstr(optarg, "MAP_PRIVATE") ? MAP_PRIVATE : 0;
- prot |= strstr(optarg, "MAP_SHARED") ? MAP_PRIVATE : 0;
+ prot |= strstr(optarg, "MAP_SHARED") ? MAP_SHARED : 0;
break;
case 'f':
alloc_flags = atol(optarg);
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/include_vndk/log/log_event_list.h b/liblog/include_vndk/log/log_event_list.h
new file mode 100644
index 0000000..cbd3091
--- /dev/null
+++ b/liblog/include_vndk/log/log_event_list.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2005-2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Special log_event_list.h file for VNDK linking modules */
+
+#ifndef _LIBS_LOG_EVENT_LIST_H
+#define _LIBS_LOG_EVENT_LIST_H
+
+#include <stdint.h>
+
+#include <log/log_id.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __ANDROID_USE_LIBLOG_EVENT_INTERFACE 1
+
+/*
+ * The opaque context used to manipulate lists of events.
+ */
+#ifndef __android_log_context_defined
+#define __android_log_context_defined
+typedef struct android_log_context_internal* android_log_context;
+#endif
+
+/*
+ * Creates a context associated with an event tag to write elements to
+ * the list of events.
+ */
+android_log_context create_android_logger(uint32_t tag);
+
+/* All lists must be braced by a begin and end call */
+/*
+ * NB: If the first level braces are missing when specifying multiple
+ * elements, we will manufacturer a list to embrace it for your API
+ * convenience. For a single element, it will remain solitary.
+ */
+int android_log_write_list_begin(android_log_context ctx);
+int android_log_write_list_end(android_log_context ctx);
+
+int android_log_write_int32(android_log_context ctx, int32_t value);
+int android_log_write_int64(android_log_context ctx, int64_t value);
+int android_log_write_string8(android_log_context ctx, const char* value);
+int android_log_write_string8_len(android_log_context ctx, const char* value,
+ size_t maxlen);
+int android_log_write_float32(android_log_context ctx, float value);
+
+/* Submit the composed list context to the specified logger id */
+/* NB: LOG_ID_EVENTS and LOG_ID_SECURITY only valid binary buffers */
+int android_log_write_list(android_log_context ctx, log_id_t id);
+
+/* Finished with reader or writer context */
+int android_log_destroy(android_log_context* ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _LIBS_LOG_EVENT_LIST_H */
diff --git a/liblog/liblog.map.txt b/liblog/liblog.map.txt
index 3c4c1f1..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;
@@ -35,6 +35,17 @@
android_logger_get_statistics; # vndk
__android_log_error_write; # vndk
__android_log_is_loggable;
+ create_android_logger; #vndk
+ android_log_destroy; #vndk
+ android_log_write_list_begin; #vndk
+ android_log_write_list_end; #vndk
+ android_log_write_int32; #vndk
+ android_log_write_int64; #vndk
+ android_log_write_string8; #vndk
+ android_log_write_string8_len; #vndk
+ android_log_write_float32; #vndk
+ android_log_write_list; #vndk
+
};
LIBLOG_O {
diff --git a/libmemunreachable/Android.bp b/libmemunreachable/Android.bp
index 8b76a65..caca377 100644
--- a/libmemunreachable/Android.bp
+++ b/libmemunreachable/Android.bp
@@ -16,11 +16,11 @@
},
host: {
shared_libs: ["liblog"],
- }
+ },
},
}
-cc_library_shared {
+cc_library {
name: "libmemunreachable",
defaults: ["libmemunreachable_defaults"],
srcs: [
@@ -88,14 +88,14 @@
cc_test {
name: "memunreachable_binder_test",
defaults: ["libmemunreachable_defaults"],
+ test_suites: ["vts"],
srcs: [
"tests/Binder_test.cpp",
- "tests/MemUnreachable_test.cpp",
],
+ static_libs: ["libmemunreachable"],
shared_libs: [
"libbinder",
"libhwbinder",
- "libmemunreachable",
"libutils",
],
}
diff --git a/libmemunreachable/tests/Binder_test.cpp b/libmemunreachable/tests/Binder_test.cpp
index 6e85d5a..eaf7652 100644
--- a/libmemunreachable/tests/Binder_test.cpp
+++ b/libmemunreachable/tests/Binder_test.cpp
@@ -33,6 +33,9 @@
static const String16 service_name("test.libmemunreachable_binder");
+// Provides a service that will hold a strong reference to any remote binder
+// object, so that the test can verify that a remote strong reference is
+// visible to libmemunreachable.
class BinderService : public BBinder {
public:
BinderService() = default;
@@ -55,6 +58,8 @@
~BinderObject() = default;
};
+// Forks a subprocess that registers a BinderService with the global binder
+// servicemanager. Requires root permissions.
class ServiceProcess {
public:
ServiceProcess() : child_(0) {}
@@ -97,6 +102,7 @@
fprintf(stderr, "Failed to get service manager\n");
return 1;
}
+ // This step requires root permissions
if (sm->addService(service_name, new BinderService()) != OK) {
fprintf(stderr, "Failed to add test service\n");
return 1;
@@ -110,12 +116,18 @@
pid_t child_;
};
-class BinderTest : public ::testing::Test {
+class MemunreachableBinderTest : public ::testing::Test {
protected:
ServiceProcess service_process_;
};
-TEST_F(BinderTest, binder) {
+// Tests that a local binder object with a remote strong reference is visible
+// through the libmemunreachable BinderReferences interface, which uses the
+// getBinderKernelReferences method in libbinder. Starts a BinderService
+// through ServiceProcess as a remote service to hold the strong reference.
+TEST_F(MemunreachableBinderTest, binder) {
+ ASSERT_EQ(static_cast<uid_t>(0), getuid()) << "This test must be run as root.";
+
ServiceProcess service_process;
ASSERT_TRUE(service_process.Run());
diff --git a/libnativebridge/Android.bp b/libnativebridge/Android.bp
index 089f3b8..6e63b74 100644
--- a/libnativebridge/Android.bp
+++ b/libnativebridge/Android.bp
@@ -1,9 +1,8 @@
-
cc_library_headers {
name: "libnativebridge-dummy-headers",
host_supported: true,
- export_include_dirs=["include"],
+ export_include_dirs: ["include"],
}
cc_library {
@@ -11,9 +10,12 @@
host_supported: true,
srcs: ["native_bridge.cc"],
- shared_libs: ["liblog", "libbase"],
+ shared_libs: [
+ "liblog",
+ "libbase",
+ ],
- export_include_dirs=["include"],
+ export_include_dirs: ["include"],
cflags: [
"-Werror",
diff --git a/libnativeloader/test/Android.bp b/libnativeloader/test/Android.bp
index 2d33704..5cf88b0 100644
--- a/libnativeloader/test/Android.bp
+++ b/libnativeloader/test/Android.bp
@@ -17,31 +17,34 @@
cc_library {
name: "libfoo.oem1",
srcs: ["test.cpp"],
- cflags : ["-DLIBNAME=\"libfoo.oem1.so\""],
+ cflags: ["-DLIBNAME=\"libfoo.oem1.so\""],
shared_libs: [
"libbase",
],
}
+
cc_library {
name: "libbar.oem1",
srcs: ["test.cpp"],
- cflags : ["-DLIBNAME=\"libbar.oem1.so\""],
+ cflags: ["-DLIBNAME=\"libbar.oem1.so\""],
shared_libs: [
"libbase",
],
}
+
cc_library {
name: "libfoo.oem2",
srcs: ["test.cpp"],
- cflags : ["-DLIBNAME=\"libfoo.oem2.so\""],
+ cflags: ["-DLIBNAME=\"libfoo.oem2.so\""],
shared_libs: [
"libbase",
],
}
+
cc_library {
name: "libbar.oem2",
srcs: ["test.cpp"],
- cflags : ["-DLIBNAME=\"libbar.oem2.so\""],
+ cflags: ["-DLIBNAME=\"libbar.oem2.so\""],
shared_libs: [
"libbase",
],
diff --git a/libpackagelistparser/Android.bp b/libpackagelistparser/Android.bp
index 3d202fc..27693b3 100644
--- a/libpackagelistparser/Android.bp
+++ b/libpackagelistparser/Android.bp
@@ -2,7 +2,10 @@
name: "libpackagelistparser",
srcs: ["packagelistparser.c"],
- cflags: ["-Wall", "-Werror"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
shared_libs: ["liblog"],
local_include_dirs: ["include"],
export_include_dirs: ["include"],
diff --git a/libprocessgroup/Android.bp b/libprocessgroup/Android.bp
index 1974f2c..b0bc497 100644
--- a/libprocessgroup/Android.bp
+++ b/libprocessgroup/Android.bp
@@ -1,7 +1,7 @@
cc_library {
srcs: ["processgroup.cpp"],
name: "libprocessgroup",
- defaults: ["linux_bionic_supported"],
+ host_supported: true,
shared_libs: ["libbase"],
export_include_dirs: ["include"],
cflags: [
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 8526b3a..6dfa697 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -22,6 +22,7 @@
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -33,15 +34,19 @@
#include <memory>
#include <mutex>
#include <set>
+#include <string>
#include <thread>
#include <android-base/file.h>
#include <android-base/logging.h>
-#include <android-base/unique_fd.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include <private/android_filesystem_config.h>
#include <processgroup/processgroup.h>
+using android::base::StartsWith;
+using android::base::StringPrintf;
using android::base::WriteStringToFile;
using namespace std::chrono_literals;
@@ -50,171 +55,58 @@
#define MEM_CGROUP_TASKS "/dev/memcg/apps/tasks"
#define ACCT_CGROUP_PATH "/acct"
-#define PROCESSGROUP_UID_PREFIX "uid_"
-#define PROCESSGROUP_PID_PREFIX "pid_"
#define PROCESSGROUP_CGROUP_PROCS_FILE "/cgroup.procs"
-#define PROCESSGROUP_MAX_UID_LEN 11
-#define PROCESSGROUP_MAX_PID_LEN 11
-#define PROCESSGROUP_MAX_PATH_LEN \
- ((sizeof(MEM_CGROUP_PATH) > sizeof(ACCT_CGROUP_PATH) ? \
- sizeof(MEM_CGROUP_PATH) : sizeof(ACCT_CGROUP_PATH)) + \
- sizeof(PROCESSGROUP_UID_PREFIX) + 1 + \
- PROCESSGROUP_MAX_UID_LEN + \
- sizeof(PROCESSGROUP_PID_PREFIX) + 1 + \
- PROCESSGROUP_MAX_PID_LEN + \
- sizeof(PROCESSGROUP_CGROUP_PROCS_FILE) + \
- 1)
std::once_flag init_path_flag;
-class ProcessGroup {
- public:
- ProcessGroup() : buf_ptr_(buf_), buf_len_(0) {}
-
- bool Open(uid_t uid, int pid);
-
- // Return positive number and sets *pid = next pid in process cgroup on success
- // Returns 0 if there are no pids left in the process cgroup
- // Returns -errno if an error was encountered
- int GetOneAppProcess(pid_t* pid);
-
- private:
- // Returns positive number of bytes filled on success
- // Returns 0 if there was nothing to read
- // Returns -errno if an error was encountered
- int RefillBuffer();
-
- android::base::unique_fd fd_;
- char buf_[128];
- char* buf_ptr_;
- size_t buf_len_;
-};
-
-static const char* getCgroupRootPath() {
- static const char* cgroup_root_path = NULL;
+static const std::string& GetCgroupRootPath() {
+ static std::string cgroup_root_path;
std::call_once(init_path_flag, [&]() {
// Check if mem cgroup is mounted, only then check for write-access to avoid
// SELinux denials
- cgroup_root_path = access(MEM_CGROUP_TASKS, F_OK) || access(MEM_CGROUP_PATH, W_OK) ?
- ACCT_CGROUP_PATH : MEM_CGROUP_PATH;
+ cgroup_root_path =
+ (access(MEM_CGROUP_TASKS, F_OK) || access(MEM_CGROUP_PATH, W_OK) ? ACCT_CGROUP_PATH
+ : MEM_CGROUP_PATH);
});
return cgroup_root_path;
}
-static int convertUidToPath(char *path, size_t size, uid_t uid)
-{
- return snprintf(path, size, "%s/%s%d",
- getCgroupRootPath(),
- PROCESSGROUP_UID_PREFIX,
- uid);
+static std::string ConvertUidToPath(uid_t uid) {
+ return StringPrintf("%s/uid_%d", GetCgroupRootPath().c_str(), uid);
}
-static int convertUidPidToPath(char *path, size_t size, uid_t uid, int pid)
-{
- return snprintf(path, size, "%s/%s%d/%s%d",
- getCgroupRootPath(),
- PROCESSGROUP_UID_PREFIX,
- uid,
- PROCESSGROUP_PID_PREFIX,
- pid);
+static std::string ConvertUidPidToPath(uid_t uid, int pid) {
+ return StringPrintf("%s/uid_%d/pid_%d", GetCgroupRootPath().c_str(), uid, pid);
}
-bool ProcessGroup::Open(uid_t uid, int pid) {
- char path[PROCESSGROUP_MAX_PATH_LEN] = {0};
- convertUidPidToPath(path, sizeof(path), uid, pid);
- strlcat(path, PROCESSGROUP_CGROUP_PROCS_FILE, sizeof(path));
-
- int fd = open(path, O_RDONLY);
- if (fd < 0) return false;
-
- fd_.reset(fd);
-
- LOG(VERBOSE) << "Initialized context for " << path;
-
- return true;
-}
-
-int ProcessGroup::RefillBuffer() {
- memmove(buf_, buf_ptr_, buf_len_);
- buf_ptr_ = buf_;
-
- ssize_t ret = read(fd_, buf_ptr_ + buf_len_, sizeof(buf_) - buf_len_ - 1);
- if (ret < 0) {
- return -errno;
- } else if (ret == 0) {
- return 0;
- }
-
- buf_len_ += ret;
- buf_[buf_len_] = 0;
- LOG(VERBOSE) << "Read " << ret << " to buffer: " << buf_;
-
- assert(buf_len_ <= sizeof(buf_));
-
- return ret;
-}
-
-int ProcessGroup::GetOneAppProcess(pid_t* out_pid) {
- *out_pid = 0;
-
- char* eptr;
- while ((eptr = static_cast<char*>(memchr(buf_ptr_, '\n', buf_len_))) == nullptr) {
- int ret = RefillBuffer();
- if (ret <= 0) return ret;
- }
-
- *eptr = '\0';
- char* pid_eptr = nullptr;
- errno = 0;
- long pid = strtol(buf_ptr_, &pid_eptr, 10);
- if (errno != 0) {
- return -errno;
- }
- if (pid_eptr != eptr) {
- errno = EINVAL;
- return -errno;
- }
-
- buf_len_ -= (eptr - buf_ptr_) + 1;
- buf_ptr_ = eptr + 1;
-
- *out_pid = static_cast<pid_t>(pid);
- return 1;
-}
-
-static int removeProcessGroup(uid_t uid, int pid)
-{
+static int RemoveProcessGroup(uid_t uid, int pid) {
int ret;
- char path[PROCESSGROUP_MAX_PATH_LEN] = {0};
- convertUidPidToPath(path, sizeof(path), uid, pid);
- ret = rmdir(path);
+ auto uid_pid_path = ConvertUidPidToPath(uid, pid);
+ ret = rmdir(uid_pid_path.c_str());
- convertUidToPath(path, sizeof(path), uid);
- rmdir(path);
+ auto uid_path = ConvertUidToPath(uid);
+ rmdir(uid_path.c_str());
return ret;
}
-static void removeUidProcessGroups(const char *uid_path)
-{
- std::unique_ptr<DIR, decltype(&closedir)> uid(opendir(uid_path), closedir);
+static void RemoveUidProcessGroups(const std::string& uid_path) {
+ std::unique_ptr<DIR, decltype(&closedir)> uid(opendir(uid_path.c_str()), closedir);
if (uid != NULL) {
dirent* dir;
while ((dir = readdir(uid.get())) != nullptr) {
- char path[PROCESSGROUP_MAX_PATH_LEN];
-
if (dir->d_type != DT_DIR) {
continue;
}
- if (strncmp(dir->d_name, PROCESSGROUP_PID_PREFIX, strlen(PROCESSGROUP_PID_PREFIX))) {
+ if (!StartsWith(dir->d_name, "pid_")) {
continue;
}
- snprintf(path, sizeof(path), "%s/%s", uid_path, dir->d_name);
+ auto path = StringPrintf("%s/%s", uid_path.c_str(), dir->d_name);
LOG(VERBOSE) << "Removing " << path;
- if (rmdir(path) == -1) PLOG(WARNING) << "Failed to remove " << path;
+ if (rmdir(path.c_str()) == -1) PLOG(WARNING) << "Failed to remove " << path;
}
}
}
@@ -222,38 +114,38 @@
void removeAllProcessGroups()
{
LOG(VERBOSE) << "removeAllProcessGroups()";
- const char* cgroup_root_path = getCgroupRootPath();
- std::unique_ptr<DIR, decltype(&closedir)> root(opendir(cgroup_root_path), closedir);
+ const auto& cgroup_root_path = GetCgroupRootPath();
+ std::unique_ptr<DIR, decltype(&closedir)> root(opendir(cgroup_root_path.c_str()), closedir);
if (root == NULL) {
PLOG(ERROR) << "Failed to open " << cgroup_root_path;
} else {
dirent* dir;
while ((dir = readdir(root.get())) != nullptr) {
- char path[PROCESSGROUP_MAX_PATH_LEN];
-
if (dir->d_type != DT_DIR) {
continue;
}
- if (strncmp(dir->d_name, PROCESSGROUP_UID_PREFIX, strlen(PROCESSGROUP_UID_PREFIX))) {
+
+ if (!StartsWith(dir->d_name, "uid_")) {
continue;
}
- snprintf(path, sizeof(path), "%s/%s", cgroup_root_path, dir->d_name);
- removeUidProcessGroups(path);
+ auto path = StringPrintf("%s/%s", cgroup_root_path.c_str(), dir->d_name);
+ RemoveUidProcessGroups(path);
LOG(VERBOSE) << "Removing " << path;
- if (rmdir(path) == -1) PLOG(WARNING) << "Failed to remove " << path;
+ if (rmdir(path.c_str()) == -1) PLOG(WARNING) << "Failed to remove " << path;
}
}
}
// Returns number of processes killed on success
// Returns 0 if there are no processes in the process cgroup left to kill
-// Returns -errno on error
-static int doKillProcessGroupOnce(uid_t uid, int initialPid, int signal) {
- ProcessGroup process_group;
- if (!process_group.Open(uid, initialPid)) {
+// Returns -1 on error
+static int DoKillProcessGroupOnce(uid_t uid, int initialPid, int signal) {
+ auto path = ConvertUidPidToPath(uid, initialPid) + PROCESSGROUP_CGROUP_PROCS_FILE;
+ std::unique_ptr<FILE, decltype(&fclose)> fd(fopen(path.c_str(), "re"), fclose);
+ if (!fd) {
PLOG(WARNING) << "Failed to open process cgroup uid " << uid << " pid " << initialPid;
- return -errno;
+ return -1;
}
// We separate all of the pids in the cgroup into those pids that are also the leaders of
@@ -262,10 +154,9 @@
pgids.emplace(initialPid);
std::set<pid_t> pids;
- int ret;
pid_t pid;
int processes = 0;
- while ((ret = process_group.GetOneAppProcess(&pid)) > 0 && pid >= 0) {
+ while (fscanf(fd.get(), "%d\n", &pid) == 1 && pid >= 0) {
processes++;
if (pid == 0) {
// Should never happen... but if it does, trying to kill this
@@ -312,15 +203,15 @@
}
}
- return ret >= 0 ? processes : ret;
+ return feof(fd.get()) ? processes : -1;
}
-static int killProcessGroup(uid_t uid, int initialPid, int signal, int retries) {
+static int KillProcessGroup(uid_t uid, int initialPid, int signal, int retries) {
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
int retry = retries;
int processes;
- while ((processes = doKillProcessGroupOnce(uid, initialPid, signal)) > 0) {
+ while ((processes = DoKillProcessGroupOnce(uid, initialPid, signal)) > 0) {
LOG(VERBOSE) << "Killed " << processes << " processes for processgroup " << initialPid;
if (retry > 0) {
std::this_thread::sleep_for(5ms);
@@ -350,7 +241,7 @@
LOG(INFO) << "Successfully killed process cgroup uid " << uid << " pid " << initialPid
<< " in " << static_cast<int>(ms) << "ms";
}
- return removeProcessGroup(uid, initialPid);
+ return RemoveProcessGroup(uid, initialPid);
} else {
if (retries > 0) {
LOG(ERROR) << "Failed to kill process cgroup uid " << uid << " pid " << initialPid
@@ -362,22 +253,21 @@
}
int killProcessGroup(uid_t uid, int initialPid, int signal) {
- return killProcessGroup(uid, initialPid, signal, 40 /*retries*/);
+ return KillProcessGroup(uid, initialPid, signal, 40 /*retries*/);
}
int killProcessGroupOnce(uid_t uid, int initialPid, int signal) {
- return killProcessGroup(uid, initialPid, signal, 0 /*retries*/);
+ return KillProcessGroup(uid, initialPid, signal, 0 /*retries*/);
}
-static bool mkdirAndChown(const char *path, mode_t mode, uid_t uid, gid_t gid)
-{
- if (mkdir(path, mode) == -1 && errno != EEXIST) {
+static bool MkdirAndChown(const std::string& path, mode_t mode, uid_t uid, gid_t gid) {
+ if (mkdir(path.c_str(), mode) == -1 && errno != EEXIST) {
return false;
}
- if (chown(path, uid, gid) == -1) {
+ if (chown(path.c_str(), uid, gid) == -1) {
int saved_errno = errno;
- rmdir(path);
+ rmdir(path.c_str());
errno = saved_errno;
return false;
}
@@ -387,42 +277,38 @@
int createProcessGroup(uid_t uid, int initialPid)
{
- char path[PROCESSGROUP_MAX_PATH_LEN] = {0};
+ auto uid_path = ConvertUidToPath(uid);
- convertUidToPath(path, sizeof(path), uid);
-
- if (!mkdirAndChown(path, 0750, AID_SYSTEM, AID_SYSTEM)) {
- PLOG(ERROR) << "Failed to make and chown " << path;
+ if (!MkdirAndChown(uid_path, 0750, AID_SYSTEM, AID_SYSTEM)) {
+ PLOG(ERROR) << "Failed to make and chown " << uid_path;
return -errno;
}
- convertUidPidToPath(path, sizeof(path), uid, initialPid);
+ auto uid_pid_path = ConvertUidPidToPath(uid, initialPid);
- if (!mkdirAndChown(path, 0750, AID_SYSTEM, AID_SYSTEM)) {
- PLOG(ERROR) << "Failed to make and chown " << path;
+ if (!MkdirAndChown(uid_pid_path, 0750, AID_SYSTEM, AID_SYSTEM)) {
+ PLOG(ERROR) << "Failed to make and chown " << uid_pid_path;
return -errno;
}
- strlcat(path, PROCESSGROUP_CGROUP_PROCS_FILE, sizeof(path));
+ auto uid_pid_procs_file = uid_pid_path + PROCESSGROUP_CGROUP_PROCS_FILE;
int ret = 0;
- if (!WriteStringToFile(std::to_string(initialPid), path)) {
+ if (!WriteStringToFile(std::to_string(initialPid), uid_pid_procs_file)) {
ret = -errno;
- PLOG(ERROR) << "Failed to write '" << initialPid << "' to " << path;
+ PLOG(ERROR) << "Failed to write '" << initialPid << "' to " << uid_pid_procs_file;
}
return ret;
}
-static bool setProcessGroupValue(uid_t uid, int pid, const char* fileName, int64_t value) {
- char path[PROCESSGROUP_MAX_PATH_LEN] = {0};
- if (strcmp(getCgroupRootPath(), MEM_CGROUP_PATH)) {
- PLOG(ERROR) << "Memcg is not mounted." << path;
+static bool SetProcessGroupValue(uid_t uid, int pid, const std::string& file_name, int64_t value) {
+ if (GetCgroupRootPath() != MEM_CGROUP_PATH) {
+ PLOG(ERROR) << "Memcg is not mounted.";
return false;
}
- convertUidPidToPath(path, sizeof(path), uid, pid);
- strlcat(path, fileName, sizeof(path));
+ auto path = ConvertUidPidToPath(uid, pid) + file_name;
if (!WriteStringToFile(std::to_string(value), path)) {
PLOG(ERROR) << "Failed to write '" << value << "' to " << path;
@@ -432,13 +318,13 @@
}
bool setProcessGroupSwappiness(uid_t uid, int pid, int swappiness) {
- return setProcessGroupValue(uid, pid, "/memory.swappiness", swappiness);
+ return SetProcessGroupValue(uid, pid, "/memory.swappiness", swappiness);
}
bool setProcessGroupSoftLimit(uid_t uid, int pid, int64_t soft_limit_in_bytes) {
- return setProcessGroupValue(uid, pid, "/memory.soft_limit_in_bytes", soft_limit_in_bytes);
+ return SetProcessGroupValue(uid, pid, "/memory.soft_limit_in_bytes", soft_limit_in_bytes);
}
bool setProcessGroupLimit(uid_t uid, int pid, int64_t limit_in_bytes) {
- return setProcessGroupValue(uid, pid, "/memory.limit_in_bytes", limit_in_bytes);
+ return SetProcessGroupValue(uid, pid, "/memory.limit_in_bytes", limit_in_bytes);
}
diff --git a/libprocinfo/Android.bp b/libprocinfo/Android.bp
index 1cfabd5..83b0a7f 100644
--- a/libprocinfo/Android.bp
+++ b/libprocinfo/Android.bp
@@ -16,7 +16,11 @@
cc_defaults {
name: "libprocinfo_defaults",
- cflags: ["-Wall", "-Werror", "-Wextra"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
}
cc_library {
@@ -65,7 +69,10 @@
},
},
- shared_libs: ["libbase", "libprocinfo"],
+ shared_libs: [
+ "libbase",
+ "libprocinfo",
+ ],
compile_multilib: "both",
multilib: {
diff --git a/libsystem/Android.bp b/libsystem/Android.bp
index 846a585..82bf1bc 100644
--- a/libsystem/Android.bp
+++ b/libsystem/Android.bp
@@ -11,5 +11,5 @@
windows: {
enabled: true,
},
- }
+ },
}
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index 34bfcef..124c70e 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -78,7 +78,10 @@
target: {
// Always disable optimizations for host to make it easier to debug.
host: {
- cflags: ["-O0", "-g"],
+ cflags: [
+ "-O0",
+ "-g",
+ ],
},
vendor: {
cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
@@ -131,7 +134,10 @@
target: {
// Always disable optimizations for host to make it easier to debug.
host: {
- cflags: ["-O0", "-g"],
+ cflags: [
+ "-O0",
+ "-g",
+ ],
},
},
@@ -171,6 +177,7 @@
shared_libs: [
"libbase",
"libunwindstack",
+ "libdexfile",
],
// libdexfile will eventually properly export headers, for now include
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/DwarfOp.cpp b/libunwindstack/DwarfOp.cpp
index dcf04e6..5bc60b9 100644
--- a/libunwindstack/DwarfOp.cpp
+++ b/libunwindstack/DwarfOp.cpp
@@ -36,13 +36,45 @@
constexpr typename DwarfOp<AddressType>::OpCallback DwarfOp<AddressType>::kCallbackTable[256];
template <typename AddressType>
-bool DwarfOp<AddressType>::Eval(uint64_t start, uint64_t end, uint8_t dwarf_version) {
- uint32_t iterations = 0;
+bool DwarfOp<AddressType>::Eval(uint64_t start, uint64_t end) {
is_register_ = false;
stack_.clear();
memory_->set_cur_offset(start);
+ dex_pc_set_ = false;
+
+ // Unroll the first Decode calls to be able to check for a special
+ // sequence of ops and values that indicate this is the dex pc.
+ // The pattern is:
+ // OP_const4u (0x0c) 'D' 'E' 'X' '1'
+ // OP_drop (0x13)
+ if (memory_->cur_offset() < end) {
+ if (!Decode()) {
+ return false;
+ }
+ } else {
+ return true;
+ }
+ bool check_for_drop;
+ if (cur_op_ == 0x0c && operands_.back() == 0x31584544) {
+ check_for_drop = true;
+ } else {
+ check_for_drop = false;
+ }
+ if (memory_->cur_offset() < end) {
+ if (!Decode()) {
+ return false;
+ }
+ } else {
+ return true;
+ }
+
+ if (check_for_drop && cur_op_ == 0x13) {
+ dex_pc_set_ = true;
+ }
+
+ uint32_t iterations = 2;
while (memory_->cur_offset() < end) {
- if (!Decode(dwarf_version)) {
+ if (!Decode()) {
return false;
}
// To protect against a branch that creates an infinite loop,
@@ -56,7 +88,7 @@
}
template <typename AddressType>
-bool DwarfOp<AddressType>::Decode(uint8_t dwarf_version) {
+bool DwarfOp<AddressType>::Decode() {
last_error_.code = DWARF_ERROR_NONE;
if (!memory_->ReadBytes(&cur_op_, 1)) {
last_error_.code = DWARF_ERROR_MEMORY_INVALID;
@@ -71,12 +103,6 @@
return false;
}
- // Check for an unsupported opcode.
- if (dwarf_version < op->supported_version) {
- last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
- return false;
- }
-
// Make sure that the required number of stack elements is available.
if (stack_.size() < op->num_required_stack_values) {
last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID;
@@ -434,22 +460,22 @@
template <typename AddressType>
bool DwarfOp<AddressType>::op_breg() {
uint16_t reg = cur_op() - 0x70;
- if (reg >= regs_->total_regs()) {
+ if (reg >= regs_info_->Total()) {
last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
return false;
}
- stack_.push_front((*regs_)[reg] + OperandAt(0));
+ stack_.push_front(regs_info_->Get(reg) + OperandAt(0));
return true;
}
template <typename AddressType>
bool DwarfOp<AddressType>::op_bregx() {
AddressType reg = OperandAt(0);
- if (reg >= regs_->total_regs()) {
+ if (reg >= regs_info_->Total()) {
last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
return false;
}
- stack_.push_front((*regs_)[reg] + OperandAt(1));
+ stack_.push_front(regs_info_->Get(reg) + OperandAt(1));
return true;
}
diff --git a/libunwindstack/DwarfOp.h b/libunwindstack/DwarfOp.h
index 40b7b23..4c69b3d 100644
--- a/libunwindstack/DwarfOp.h
+++ b/libunwindstack/DwarfOp.h
@@ -27,16 +27,10 @@
#include <unwindstack/DwarfError.h>
#include "DwarfEncoding.h"
+#include "RegsInfo.h"
namespace unwindstack {
-enum DwarfVersion : uint8_t {
- DWARF_VERSION_2 = 2,
- DWARF_VERSION_3 = 3,
- DWARF_VERSION_4 = 4,
- DWARF_VERSION_MAX = DWARF_VERSION_4,
-};
-
// Forward declarations.
class DwarfMemory;
class Memory;
@@ -51,7 +45,6 @@
struct OpCallback {
const char* name;
bool (DwarfOp::*handle_func)();
- uint8_t supported_version;
uint8_t num_required_stack_values;
uint8_t num_operands;
uint8_t operands[2];
@@ -62,21 +55,23 @@
: memory_(memory), regular_memory_(regular_memory) {}
virtual ~DwarfOp() = default;
- bool Decode(uint8_t dwarf_version);
+ bool Decode();
- bool Eval(uint64_t start, uint64_t end, uint8_t dwarf_version);
+ bool Eval(uint64_t start, uint64_t end);
void GetLogInfo(uint64_t start, uint64_t end, std::vector<std::string>* lines);
AddressType StackAt(size_t index) { return stack_[index]; }
size_t StackSize() { return stack_.size(); }
- void set_regs(RegsImpl<AddressType>* regs) { regs_ = regs; }
+ void set_regs_info(RegsInfo<AddressType>* regs_info) { regs_info_ = regs_info; }
const DwarfErrorData& last_error() { return last_error_; }
DwarfErrorCode LastErrorCode() { return last_error_.code; }
uint64_t LastErrorAddress() { return last_error_.address; }
+ bool dex_pc_set() { return dex_pc_set_; }
+
bool is_register() { return is_register_; }
uint8_t cur_op() { return cur_op_; }
@@ -97,7 +92,8 @@
DwarfMemory* memory_;
Memory* regular_memory_;
- RegsImpl<AddressType>* regs_;
+ RegsInfo<AddressType>* regs_info_;
+ bool dex_pc_set_ = false;
bool is_register_ = false;
DwarfErrorData last_error_{DWARF_ERROR_NONE, 0};
uint8_t cur_op_;
@@ -148,35 +144,32 @@
bool op_not_implemented();
constexpr static OpCallback kCallbackTable[256] = {
- {nullptr, nullptr, 0, 0, 0, {}}, // 0x00 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0x01 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0x02 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0x00 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0x01 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0x02 illegal op
{
// 0x03 DW_OP_addr
"DW_OP_addr",
&DwarfOp::op_push,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_absptr},
},
- {nullptr, nullptr, 0, 0, 0, {}}, // 0x04 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0x05 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0x04 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0x05 illegal op
{
// 0x06 DW_OP_deref
"DW_OP_deref",
&DwarfOp::op_deref,
- DWARF_VERSION_2,
1,
0,
{},
},
- {nullptr, nullptr, 0, 0, 0, {}}, // 0x07 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0x07 illegal op
{
// 0x08 DW_OP_const1u
"DW_OP_const1u",
&DwarfOp::op_push,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_udata1},
@@ -185,7 +178,6 @@
// 0x09 DW_OP_const1s
"DW_OP_const1s",
&DwarfOp::op_push,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sdata1},
@@ -194,7 +186,6 @@
// 0x0a DW_OP_const2u
"DW_OP_const2u",
&DwarfOp::op_push,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_udata2},
@@ -203,7 +194,6 @@
// 0x0b DW_OP_const2s
"DW_OP_const2s",
&DwarfOp::op_push,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sdata2},
@@ -212,7 +202,6 @@
// 0x0c DW_OP_const4u
"DW_OP_const4u",
&DwarfOp::op_push,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_udata4},
@@ -221,7 +210,6 @@
// 0x0d DW_OP_const4s
"DW_OP_const4s",
&DwarfOp::op_push,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sdata4},
@@ -230,7 +218,6 @@
// 0x0e DW_OP_const8u
"DW_OP_const8u",
&DwarfOp::op_push,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_udata8},
@@ -239,7 +226,6 @@
// 0x0f DW_OP_const8s
"DW_OP_const8s",
&DwarfOp::op_push,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sdata8},
@@ -248,7 +234,6 @@
// 0x10 DW_OP_constu
"DW_OP_constu",
&DwarfOp::op_push,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_uleb128},
@@ -257,7 +242,6 @@
// 0x11 DW_OP_consts
"DW_OP_consts",
&DwarfOp::op_push,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -266,7 +250,6 @@
// 0x12 DW_OP_dup
"DW_OP_dup",
&DwarfOp::op_dup,
- DWARF_VERSION_2,
1,
0,
{},
@@ -275,7 +258,6 @@
// 0x13 DW_OP_drop
"DW_OP_drop",
&DwarfOp::op_drop,
- DWARF_VERSION_2,
1,
0,
{},
@@ -284,7 +266,6 @@
// 0x14 DW_OP_over
"DW_OP_over",
&DwarfOp::op_over,
- DWARF_VERSION_2,
2,
0,
{},
@@ -293,7 +274,6 @@
// 0x15 DW_OP_pick
"DW_OP_pick",
&DwarfOp::op_pick,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_udata1},
@@ -302,7 +282,6 @@
// 0x16 DW_OP_swap
"DW_OP_swap",
&DwarfOp::op_swap,
- DWARF_VERSION_2,
2,
0,
{},
@@ -311,7 +290,6 @@
// 0x17 DW_OP_rot
"DW_OP_rot",
&DwarfOp::op_rot,
- DWARF_VERSION_2,
3,
0,
{},
@@ -320,7 +298,6 @@
// 0x18 DW_OP_xderef
"DW_OP_xderef",
&DwarfOp::op_not_implemented,
- DWARF_VERSION_2,
2,
0,
{},
@@ -329,7 +306,6 @@
// 0x19 DW_OP_abs
"DW_OP_abs",
&DwarfOp::op_abs,
- DWARF_VERSION_2,
1,
0,
{},
@@ -338,7 +314,6 @@
// 0x1a DW_OP_and
"DW_OP_and",
&DwarfOp::op_and,
- DWARF_VERSION_2,
2,
0,
{},
@@ -347,7 +322,6 @@
// 0x1b DW_OP_div
"DW_OP_div",
&DwarfOp::op_div,
- DWARF_VERSION_2,
2,
0,
{},
@@ -356,7 +330,6 @@
// 0x1c DW_OP_minus
"DW_OP_minus",
&DwarfOp::op_minus,
- DWARF_VERSION_2,
2,
0,
{},
@@ -365,7 +338,6 @@
// 0x1d DW_OP_mod
"DW_OP_mod",
&DwarfOp::op_mod,
- DWARF_VERSION_2,
2,
0,
{},
@@ -374,7 +346,6 @@
// 0x1e DW_OP_mul
"DW_OP_mul",
&DwarfOp::op_mul,
- DWARF_VERSION_2,
2,
0,
{},
@@ -383,7 +354,6 @@
// 0x1f DW_OP_neg
"DW_OP_neg",
&DwarfOp::op_neg,
- DWARF_VERSION_2,
1,
0,
{},
@@ -392,7 +362,6 @@
// 0x20 DW_OP_not
"DW_OP_not",
&DwarfOp::op_not,
- DWARF_VERSION_2,
1,
0,
{},
@@ -401,7 +370,6 @@
// 0x21 DW_OP_or
"DW_OP_or",
&DwarfOp::op_or,
- DWARF_VERSION_2,
2,
0,
{},
@@ -410,7 +378,6 @@
// 0x22 DW_OP_plus
"DW_OP_plus",
&DwarfOp::op_plus,
- DWARF_VERSION_2,
2,
0,
{},
@@ -419,7 +386,6 @@
// 0x23 DW_OP_plus_uconst
"DW_OP_plus_uconst",
&DwarfOp::op_plus_uconst,
- DWARF_VERSION_2,
1,
1,
{DW_EH_PE_uleb128},
@@ -428,7 +394,6 @@
// 0x24 DW_OP_shl
"DW_OP_shl",
&DwarfOp::op_shl,
- DWARF_VERSION_2,
2,
0,
{},
@@ -437,7 +402,6 @@
// 0x25 DW_OP_shr
"DW_OP_shr",
&DwarfOp::op_shr,
- DWARF_VERSION_2,
2,
0,
{},
@@ -446,7 +410,6 @@
// 0x26 DW_OP_shra
"DW_OP_shra",
&DwarfOp::op_shra,
- DWARF_VERSION_2,
2,
0,
{},
@@ -455,7 +418,6 @@
// 0x27 DW_OP_xor
"DW_OP_xor",
&DwarfOp::op_xor,
- DWARF_VERSION_2,
2,
0,
{},
@@ -464,7 +426,6 @@
// 0x28 DW_OP_bra
"DW_OP_bra",
&DwarfOp::op_bra,
- DWARF_VERSION_2,
1,
1,
{DW_EH_PE_sdata2},
@@ -473,7 +434,6 @@
// 0x29 DW_OP_eq
"DW_OP_eq",
&DwarfOp::op_eq,
- DWARF_VERSION_2,
2,
0,
{},
@@ -482,7 +442,6 @@
// 0x2a DW_OP_ge
"DW_OP_ge",
&DwarfOp::op_ge,
- DWARF_VERSION_2,
2,
0,
{},
@@ -491,7 +450,6 @@
// 0x2b DW_OP_gt
"DW_OP_gt",
&DwarfOp::op_gt,
- DWARF_VERSION_2,
2,
0,
{},
@@ -500,7 +458,6 @@
// 0x2c DW_OP_le
"DW_OP_le",
&DwarfOp::op_le,
- DWARF_VERSION_2,
2,
0,
{},
@@ -509,7 +466,6 @@
// 0x2d DW_OP_lt
"DW_OP_lt",
&DwarfOp::op_lt,
- DWARF_VERSION_2,
2,
0,
{},
@@ -518,7 +474,6 @@
// 0x2e DW_OP_ne
"DW_OP_ne",
&DwarfOp::op_ne,
- DWARF_VERSION_2,
2,
0,
{},
@@ -527,7 +482,6 @@
// 0x2f DW_OP_skip
"DW_OP_skip",
&DwarfOp::op_skip,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sdata2},
@@ -536,7 +490,6 @@
// 0x30 DW_OP_lit0
"DW_OP_lit0",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -545,7 +498,6 @@
// 0x31 DW_OP_lit1
"DW_OP_lit1",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -554,7 +506,6 @@
// 0x32 DW_OP_lit2
"DW_OP_lit2",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -563,7 +514,6 @@
// 0x33 DW_OP_lit3
"DW_OP_lit3",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -572,7 +522,6 @@
// 0x34 DW_OP_lit4
"DW_OP_lit4",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -581,7 +530,6 @@
// 0x35 DW_OP_lit5
"DW_OP_lit5",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -590,7 +538,6 @@
// 0x36 DW_OP_lit6
"DW_OP_lit6",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -599,7 +546,6 @@
// 0x37 DW_OP_lit7
"DW_OP_lit7",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -608,7 +554,6 @@
// 0x38 DW_OP_lit8
"DW_OP_lit8",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -617,7 +562,6 @@
// 0x39 DW_OP_lit9
"DW_OP_lit9",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -626,7 +570,6 @@
// 0x3a DW_OP_lit10
"DW_OP_lit10",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -635,7 +578,6 @@
// 0x3b DW_OP_lit11
"DW_OP_lit11",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -644,7 +586,6 @@
// 0x3c DW_OP_lit12
"DW_OP_lit12",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -653,7 +594,6 @@
// 0x3d DW_OP_lit13
"DW_OP_lit13",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -662,7 +602,6 @@
// 0x3e DW_OP_lit14
"DW_OP_lit14",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -671,7 +610,6 @@
// 0x3f DW_OP_lit15
"DW_OP_lit15",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -680,7 +618,6 @@
// 0x40 DW_OP_lit16
"DW_OP_lit16",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -689,7 +626,6 @@
// 0x41 DW_OP_lit17
"DW_OP_lit17",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -698,7 +634,6 @@
// 0x42 DW_OP_lit18
"DW_OP_lit18",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -707,7 +642,6 @@
// 0x43 DW_OP_lit19
"DW_OP_lit19",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -716,7 +650,6 @@
// 0x44 DW_OP_lit20
"DW_OP_lit20",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -725,7 +658,6 @@
// 0x45 DW_OP_lit21
"DW_OP_lit21",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -734,7 +666,6 @@
// 0x46 DW_OP_lit22
"DW_OP_lit22",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -743,7 +674,6 @@
// 0x47 DW_OP_lit23
"DW_OP_lit23",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -752,7 +682,6 @@
// 0x48 DW_OP_lit24
"DW_OP_lit24",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -761,7 +690,6 @@
// 0x49 DW_OP_lit25
"DW_OP_lit25",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -770,7 +698,6 @@
// 0x4a DW_OP_lit26
"DW_OP_lit26",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -779,7 +706,6 @@
// 0x4b DW_OP_lit27
"DW_OP_lit27",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -788,7 +714,6 @@
// 0x4c DW_OP_lit28
"DW_OP_lit28",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -797,7 +722,6 @@
// 0x4d DW_OP_lit29
"DW_OP_lit29",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -806,7 +730,6 @@
// 0x4e DW_OP_lit30
"DW_OP_lit30",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -815,7 +738,6 @@
// 0x4f DW_OP_lit31
"DW_OP_lit31",
&DwarfOp::op_lit,
- DWARF_VERSION_2,
0,
0,
{},
@@ -824,7 +746,6 @@
// 0x50 DW_OP_reg0
"DW_OP_reg0",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -833,7 +754,6 @@
// 0x51 DW_OP_reg1
"DW_OP_reg1",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -842,7 +762,6 @@
// 0x52 DW_OP_reg2
"DW_OP_reg2",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -851,7 +770,6 @@
// 0x53 DW_OP_reg3
"DW_OP_reg3",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -860,7 +778,6 @@
// 0x54 DW_OP_reg4
"DW_OP_reg4",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -869,7 +786,6 @@
// 0x55 DW_OP_reg5
"DW_OP_reg5",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -878,7 +794,6 @@
// 0x56 DW_OP_reg6
"DW_OP_reg6",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -887,7 +802,6 @@
// 0x57 DW_OP_reg7
"DW_OP_reg7",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -896,7 +810,6 @@
// 0x58 DW_OP_reg8
"DW_OP_reg8",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -905,7 +818,6 @@
// 0x59 DW_OP_reg9
"DW_OP_reg9",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -914,7 +826,6 @@
// 0x5a DW_OP_reg10
"DW_OP_reg10",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -923,7 +834,6 @@
// 0x5b DW_OP_reg11
"DW_OP_reg11",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -932,7 +842,6 @@
// 0x5c DW_OP_reg12
"DW_OP_reg12",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -941,7 +850,6 @@
// 0x5d DW_OP_reg13
"DW_OP_reg13",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -950,7 +858,6 @@
// 0x5e DW_OP_reg14
"DW_OP_reg14",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -959,7 +866,6 @@
// 0x5f DW_OP_reg15
"DW_OP_reg15",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -968,7 +874,6 @@
// 0x60 DW_OP_reg16
"DW_OP_reg16",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -977,7 +882,6 @@
// 0x61 DW_OP_reg17
"DW_OP_reg17",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -986,7 +890,6 @@
// 0x62 DW_OP_reg18
"DW_OP_reg18",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -995,7 +898,6 @@
// 0x63 DW_OP_reg19
"DW_OP_reg19",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -1004,7 +906,6 @@
// 0x64 DW_OP_reg20
"DW_OP_reg20",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -1013,7 +914,6 @@
// 0x65 DW_OP_reg21
"DW_OP_reg21",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -1022,7 +922,6 @@
// 0x66 DW_OP_reg22
"DW_OP_reg22",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -1031,7 +930,6 @@
// 0x67 DW_OP_reg23
"DW_OP_reg23",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -1040,7 +938,6 @@
// 0x68 DW_OP_reg24
"DW_OP_reg24",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -1049,7 +946,6 @@
// 0x69 DW_OP_reg25
"DW_OP_reg25",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -1058,7 +954,6 @@
// 0x6a DW_OP_reg26
"DW_OP_reg26",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -1067,7 +962,6 @@
// 0x6b DW_OP_reg27
"DW_OP_reg27",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -1076,7 +970,6 @@
// 0x6c DW_OP_reg28
"DW_OP_reg28",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -1085,7 +978,6 @@
// 0x6d DW_OP_reg29
"DW_OP_reg29",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -1094,7 +986,6 @@
// 0x6e DW_OP_reg30
"DW_OP_reg30",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -1103,7 +994,6 @@
// 0x6f DW_OP_reg31
"DW_OP_reg31",
&DwarfOp::op_reg,
- DWARF_VERSION_2,
0,
0,
{},
@@ -1112,7 +1002,6 @@
// 0x70 DW_OP_breg0
"DW_OP_breg0",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1121,7 +1010,6 @@
// 0x71 DW_OP_breg1
"DW_OP_breg1",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1130,7 +1018,6 @@
// 0x72 DW_OP_breg2
"DW_OP_breg2",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1139,7 +1026,6 @@
// 0x73 DW_OP_breg3
"DW_OP_breg3",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1148,7 +1034,6 @@
// 0x74 DW_OP_breg4
"DW_OP_breg4",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1157,7 +1042,6 @@
// 0x75 DW_OP_breg5
"DW_OP_breg5",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1166,7 +1050,6 @@
// 0x76 DW_OP_breg6
"DW_OP_breg6",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1175,7 +1058,6 @@
// 0x77 DW_OP_breg7
"DW_OP_breg7",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1184,7 +1066,6 @@
// 0x78 DW_OP_breg8
"DW_OP_breg8",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1193,7 +1074,6 @@
// 0x79 DW_OP_breg9
"DW_OP_breg9",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1202,7 +1082,6 @@
// 0x7a DW_OP_breg10
"DW_OP_breg10",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1211,7 +1090,6 @@
// 0x7b DW_OP_breg11
"DW_OP_breg11",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1220,7 +1098,6 @@
// 0x7c DW_OP_breg12
"DW_OP_breg12",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1229,7 +1106,6 @@
// 0x7d DW_OP_breg13
"DW_OP_breg13",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1238,7 +1114,6 @@
// 0x7e DW_OP_breg14
"DW_OP_breg14",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1247,7 +1122,6 @@
// 0x7f DW_OP_breg15
"DW_OP_breg15",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1256,7 +1130,6 @@
// 0x80 DW_OP_breg16
"DW_OP_breg16",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1265,7 +1138,6 @@
// 0x81 DW_OP_breg17
"DW_OP_breg17",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1274,7 +1146,6 @@
// 0x82 DW_OP_breg18
"DW_OP_breg18",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1283,7 +1154,6 @@
// 0x83 DW_OP_breg19
"DW_OP_breg19",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1292,7 +1162,6 @@
// 0x84 DW_OP_breg20
"DW_OP_breg20",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1301,7 +1170,6 @@
// 0x85 DW_OP_breg21
"DW_OP_breg21",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1310,7 +1178,6 @@
// 0x86 DW_OP_breg22
"DW_OP_breg22",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1319,7 +1186,6 @@
// 0x87 DW_OP_breg23
"DW_OP_breg23",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1328,7 +1194,6 @@
// 0x88 DW_OP_breg24
"DW_OP_breg24",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1337,7 +1202,6 @@
// 0x89 DW_OP_breg25
"DW_OP_breg25",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1346,7 +1210,6 @@
// 0x8a DW_OP_breg26
"DW_OP_breg26",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1355,7 +1218,6 @@
// 0x8b DW_OP_breg27
"DW_OP_breg27",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1364,7 +1226,6 @@
// 0x8c DW_OP_breg28
"DW_OP_breg28",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1373,7 +1234,6 @@
// 0x8d DW_OP_breg29
"DW_OP_breg29",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1382,7 +1242,6 @@
// 0x8e DW_OP_breg30
"DW_OP_breg30",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1391,7 +1250,6 @@
// 0x8f DW_OP_breg31
"DW_OP_breg31",
&DwarfOp::op_breg,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1400,7 +1258,6 @@
// 0x90 DW_OP_regx
"DW_OP_regx",
&DwarfOp::op_regx,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_uleb128},
@@ -1409,7 +1266,6 @@
// 0x91 DW_OP_fbreg
"DW_OP_fbreg",
&DwarfOp::op_not_implemented,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_sleb128},
@@ -1418,7 +1274,6 @@
// 0x92 DW_OP_bregx
"DW_OP_bregx",
&DwarfOp::op_bregx,
- DWARF_VERSION_2,
0,
2,
{DW_EH_PE_uleb128, DW_EH_PE_sleb128},
@@ -1427,7 +1282,6 @@
// 0x93 DW_OP_piece
"DW_OP_piece",
&DwarfOp::op_not_implemented,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_uleb128},
@@ -1436,7 +1290,6 @@
// 0x94 DW_OP_deref_size
"DW_OP_deref_size",
&DwarfOp::op_deref_size,
- DWARF_VERSION_2,
1,
1,
{DW_EH_PE_udata1},
@@ -1445,7 +1298,6 @@
// 0x95 DW_OP_xderef_size
"DW_OP_xderef_size",
&DwarfOp::op_not_implemented,
- DWARF_VERSION_2,
0,
1,
{DW_EH_PE_udata1},
@@ -1454,7 +1306,6 @@
// 0x96 DW_OP_nop
"DW_OP_nop",
&DwarfOp::op_nop,
- DWARF_VERSION_2,
0,
0,
{},
@@ -1463,7 +1314,6 @@
// 0x97 DW_OP_push_object_address
"DW_OP_push_object_address",
&DwarfOp::op_not_implemented,
- DWARF_VERSION_3,
0,
0,
{},
@@ -1472,7 +1322,6 @@
// 0x98 DW_OP_call2
"DW_OP_call2",
&DwarfOp::op_not_implemented,
- DWARF_VERSION_3,
0,
1,
{DW_EH_PE_udata2},
@@ -1481,7 +1330,6 @@
// 0x99 DW_OP_call4
"DW_OP_call4",
&DwarfOp::op_not_implemented,
- DWARF_VERSION_3,
0,
1,
{DW_EH_PE_udata4},
@@ -1490,7 +1338,6 @@
// 0x9a DW_OP_call_ref
"DW_OP_call_ref",
&DwarfOp::op_not_implemented,
- DWARF_VERSION_3,
0,
0, // Has a different sized operand (4 bytes or 8 bytes).
{},
@@ -1499,7 +1346,6 @@
// 0x9b DW_OP_form_tls_address
"DW_OP_form_tls_address",
&DwarfOp::op_not_implemented,
- DWARF_VERSION_3,
0,
0,
{},
@@ -1508,7 +1354,6 @@
// 0x9c DW_OP_call_frame_cfa
"DW_OP_call_frame_cfa",
&DwarfOp::op_not_implemented,
- DWARF_VERSION_3,
0,
0,
{},
@@ -1517,7 +1362,6 @@
// 0x9d DW_OP_bit_piece
"DW_OP_bit_piece",
&DwarfOp::op_not_implemented,
- DWARF_VERSION_3,
0,
2,
{DW_EH_PE_uleb128, DW_EH_PE_uleb128},
@@ -1526,7 +1370,6 @@
// 0x9e DW_OP_implicit_value
"DW_OP_implicit_value",
&DwarfOp::op_not_implemented,
- DWARF_VERSION_4,
0,
1,
{DW_EH_PE_uleb128},
@@ -1535,107 +1378,106 @@
// 0x9f DW_OP_stack_value
"DW_OP_stack_value",
&DwarfOp::op_not_implemented,
- DWARF_VERSION_4,
1,
0,
{},
},
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xa0 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xa1 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xa2 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xa3 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xa4 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xa5 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xa6 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xa7 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xa8 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xa9 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xaa illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xab illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xac illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xad illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xae illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xaf illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xb0 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xb1 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xb2 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xb3 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xb4 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xb5 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xb6 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xb7 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xb8 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xb9 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xba illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xbb illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xbc illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xbd illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xbe illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xbf illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xc0 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xc1 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xc2 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xc3 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xc4 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xc5 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xc6 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xc7 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xc8 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xc9 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xca illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xcb illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xcc illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xcd illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xce illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xcf illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xd0 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xd1 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xd2 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xd3 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xd4 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xd5 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xd6 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xd7 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xd8 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xd9 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xda illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xdb illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xdc illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xdd illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xde illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xdf illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xe0 DW_OP_lo_user
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xe1 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xe2 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xe3 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xe4 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xe5 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xe6 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xe7 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xe8 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xe9 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xea illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xeb illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xec illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xed illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xee illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xef illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xf0 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xf1 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xf2 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xf3 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xf4 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xf5 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xf6 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xf7 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xf8 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xf9 illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xfa illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xfb illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xfc illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xfd illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xfe illegal op
- {nullptr, nullptr, 0, 0, 0, {}}, // 0xff DW_OP_hi_user
+ {nullptr, nullptr, 0, 0, {}}, // 0xa0 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xa1 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xa2 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xa3 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xa4 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xa5 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xa6 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xa7 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xa8 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xa9 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xaa illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xab illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xac illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xad illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xae illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xaf illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xb0 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xb1 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xb2 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xb3 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xb4 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xb5 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xb6 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xb7 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xb8 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xb9 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xba illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xbb illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xbc illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xbd illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xbe illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xbf illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xc0 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xc1 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xc2 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xc3 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xc4 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xc5 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xc6 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xc7 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xc8 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xc9 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xca illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xcb illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xcc illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xcd illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xce illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xcf illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xd0 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xd1 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xd2 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xd3 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xd4 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xd5 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xd6 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xd7 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xd8 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xd9 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xda illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xdb illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xdc illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xdd illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xde illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xdf illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xe0 DW_OP_lo_user
+ {nullptr, nullptr, 0, 0, {}}, // 0xe1 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xe2 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xe3 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xe4 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xe5 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xe6 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xe7 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xe8 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xe9 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xea illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xeb illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xec illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xed illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xee illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xef illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xf0 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xf1 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xf2 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xf3 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xf4 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xf5 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xf6 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xf7 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xf8 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xf9 illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xfa illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xfb illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xfc illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xfd illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xfe illegal op
+ {nullptr, nullptr, 0, 0, {}}, // 0xff DW_OP_hi_user
};
};
diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp
index 4e94f88..7649798 100644
--- a/libunwindstack/DwarfSection.cpp
+++ b/libunwindstack/DwarfSection.cpp
@@ -26,16 +26,14 @@
#include <unwindstack/Regs.h>
#include "DwarfCfa.h"
-#include "DwarfEncoding.h"
-#include "DwarfOp.h"
-
#include "DwarfDebugFrame.h"
#include "DwarfEhFrame.h"
+#include "DwarfEncoding.h"
+#include "DwarfOp.h"
+#include "RegsInfo.h"
namespace unwindstack {
-constexpr uint64_t DEX_PC_REG = 0x20444558;
-
DwarfSection::DwarfSection(Memory* memory) : memory_(memory) {}
const DwarfFde* DwarfSection::GetFdeFromPc(uint64_t pc) {
@@ -75,14 +73,17 @@
}
template <typename AddressType>
-bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, uint8_t version,
- Memory* regular_memory, AddressType* value) {
+bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, Memory* regular_memory,
+ AddressType* value,
+ RegsInfo<AddressType>* regs_info,
+ bool* is_dex_pc) {
DwarfOp<AddressType> op(&memory_, regular_memory);
+ op.set_regs_info(regs_info);
// Need to evaluate the op data.
- uint64_t start = loc.values[1];
- uint64_t end = start + loc.values[0];
- if (!op.Eval(start, end, version)) {
+ uint64_t end = loc.values[1];
+ uint64_t start = end - loc.values[0];
+ if (!op.Eval(start, end)) {
last_error_ = op.last_error();
return false;
}
@@ -96,6 +97,9 @@
return false;
}
*value = op.StackAt(0);
+ if (is_dex_pc != nullptr && op.dex_pc_set()) {
+ *is_dex_pc = true;
+ }
return true;
}
@@ -103,12 +107,10 @@
struct EvalInfo {
const dwarf_loc_regs_t* loc_regs;
const DwarfCie* cie;
- RegsImpl<AddressType>* cur_regs;
Memory* regular_memory;
AddressType cfa;
bool return_address_undefined = false;
- uint64_t reg_map = 0;
- AddressType reg_values[64];
+ RegsInfo<AddressType> regs_info;
};
template <typename AddressType>
@@ -129,32 +131,18 @@
break;
case DWARF_LOCATION_REGISTER: {
uint32_t cur_reg = loc->values[0];
- if (cur_reg >= eval_info->cur_regs->total_regs()) {
+ if (cur_reg >= eval_info->regs_info.Total()) {
last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
return false;
}
- AddressType* cur_reg_ptr = &(*eval_info->cur_regs)[cur_reg];
- const auto& entry = eval_info->loc_regs->find(cur_reg);
- if (entry != eval_info->loc_regs->end()) {
- if (!(eval_info->reg_map & (1 << cur_reg))) {
- eval_info->reg_map |= 1 << cur_reg;
- eval_info->reg_values[cur_reg] = *cur_reg_ptr;
- if (!EvalRegister(&entry->second, cur_reg, cur_reg_ptr, eval_info)) {
- return false;
- }
- }
-
- // Use the register value from before any evaluations.
- *reg_ptr = eval_info->reg_values[cur_reg] + loc->values[1];
- } else {
- *reg_ptr = *cur_reg_ptr + loc->values[1];
- }
+ *reg_ptr = eval_info->regs_info.Get(cur_reg) + loc->values[1];
break;
}
case DWARF_LOCATION_EXPRESSION:
case DWARF_LOCATION_VAL_EXPRESSION: {
AddressType value;
- if (!EvalExpression(*loc, eval_info->cie->version, regular_memory, &value)) {
+ bool is_dex_pc = false;
+ if (!EvalExpression(*loc, regular_memory, &value, &eval_info->regs_info, &is_dex_pc)) {
return false;
}
if (loc->type == DWARF_LOCATION_EXPRESSION) {
@@ -165,6 +153,9 @@
}
} else {
*reg_ptr = value;
+ if (is_dex_pc) {
+ eval_info->regs_info.regs->set_dex_pc(value);
+ }
}
break;
}
@@ -201,8 +192,10 @@
AddressType prev_cfa = regs->sp();
- EvalInfo<AddressType> eval_info{
- .loc_regs = &loc_regs, .cie = cie, .regular_memory = regular_memory, .cur_regs = cur_regs};
+ EvalInfo<AddressType> eval_info{.loc_regs = &loc_regs,
+ .cie = cie,
+ .regular_memory = regular_memory,
+ .regs_info = RegsInfo<AddressType>(cur_regs)};
const DwarfLocation* loc = &cfa_entry->second;
// Only a few location types are valid for the cfa.
switch (loc->type) {
@@ -224,7 +217,7 @@
case DWARF_LOCATION_EXPRESSION:
case DWARF_LOCATION_VAL_EXPRESSION: {
AddressType value;
- if (!EvalExpression(*loc, cie->version, regular_memory, &value)) {
+ if (!EvalExpression(*loc, regular_memory, &value, &eval_info.regs_info, nullptr)) {
return false;
}
if (loc->type == DWARF_LOCATION_EXPRESSION) {
@@ -249,28 +242,15 @@
if (reg == CFA_REG) continue;
AddressType* reg_ptr;
- AddressType dex_pc = 0;
- if (reg == DEX_PC_REG) {
- // Special register that indicates this is a dex pc.
- dex_pc = 0;
- reg_ptr = &dex_pc;
- } else if (reg >= cur_regs->total_regs() || eval_info.reg_map & (1 << reg)) {
- // Skip this unknown register, or a register that has already been
- // processed.
+ if (reg >= cur_regs->total_regs()) {
+ // Skip this unknown register.
continue;
- } else {
- reg_ptr = &(*cur_regs)[reg];
- eval_info.reg_map |= 1 << reg;
- eval_info.reg_values[reg] = *reg_ptr;
}
+ reg_ptr = eval_info.regs_info.Save(reg);
if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) {
return false;
}
-
- if (reg == DEX_PC_REG) {
- cur_regs->set_dex_pc(dex_pc);
- }
}
// Find the return address location.
diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp
index dbf772e..02f8a9a 100644
--- a/libunwindstack/Elf.cpp
+++ b/libunwindstack/Elf.cpp
@@ -20,6 +20,7 @@
#include <memory>
#include <mutex>
#include <string>
+#include <utility>
#define LOG_TAG "unwind"
#include <log/log.h>
@@ -36,7 +37,7 @@
namespace unwindstack {
bool Elf::cache_enabled_;
-std::unordered_map<std::string, std::shared_ptr<Elf>>* Elf::cache_;
+std::unordered_map<std::string, std::pair<std::shared_ptr<Elf>, bool>>* Elf::cache_;
std::mutex* Elf::cache_lock_;
bool Elf::Init(bool init_gnu_debugdata) {
@@ -308,7 +309,7 @@
void Elf::SetCachingEnabled(bool enable) {
if (!cache_enabled_ && enable) {
cache_enabled_ = true;
- cache_ = new std::unordered_map<std::string, std::shared_ptr<Elf>>;
+ cache_ = new std::unordered_map<std::string, std::pair<std::shared_ptr<Elf>, bool>>;
cache_lock_ = new std::mutex;
} else if (cache_enabled_ && !enable) {
cache_enabled_ = false;
@@ -326,18 +327,54 @@
}
void Elf::CacheAdd(MapInfo* info) {
- if (info->offset == 0) {
- (*cache_)[info->name] = info->elf;
- } else {
- std::string name(info->name + ':' + std::to_string(info->offset));
- (*cache_)[name] = info->elf;
+ // If elf_offset != 0, then cache both name:offset and name.
+ // The cached name is used to do lookups if multiple maps for the same
+ // named elf file exist.
+ // For example, if there are two maps boot.odex:1000 and boot.odex:2000
+ // where each reference the entire boot.odex, the cache will properly
+ // use the same cached elf object.
+
+ if (info->offset == 0 || info->elf_offset != 0) {
+ (*cache_)[info->name] = std::make_pair(info->elf, true);
+ }
+
+ if (info->offset != 0) {
+ // The second element in the pair indicates whether elf_offset should
+ // be set to offset when getting out of the cache.
+ (*cache_)[info->name + ':' + std::to_string(info->offset)] =
+ std::make_pair(info->elf, info->elf_offset != 0);
}
}
-bool Elf::CacheGet(const std::string& name, std::shared_ptr<Elf>* elf) {
+bool Elf::CacheAfterCreateMemory(MapInfo* info) {
+ if (info->name.empty() || info->offset == 0 || info->elf_offset == 0) {
+ return false;
+ }
+
+ auto entry = cache_->find(info->name);
+ if (entry == cache_->end()) {
+ return false;
+ }
+
+ // In this case, the whole file is the elf, and the name has already
+ // been cached. Add an entry at name:offset to get this directly out
+ // of the cache next time.
+ info->elf = entry->second.first;
+ (*cache_)[info->name + ':' + std::to_string(info->offset)] = std::make_pair(info->elf, true);
+ return true;
+}
+
+bool Elf::CacheGet(MapInfo* info) {
+ std::string name(info->name);
+ if (info->offset != 0) {
+ name += ':' + std::to_string(info->offset);
+ }
auto entry = cache_->find(name);
if (entry != cache_->end()) {
- *elf = entry->second;
+ info->elf = entry->second.first;
+ if (entry->second.second) {
+ info->elf_offset = info->offset;
+ }
return true;
}
return false;
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index e413081..10afe33 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -19,6 +19,7 @@
#include <memory>
#include <string>
+#include <utility>
#include <7zCrc.h>
#include <Xz.h>
@@ -322,19 +323,13 @@
// Skip the first header, it's always going to be NULL.
offset += ehdr.e_shentsize;
for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) {
- if (!memory_->ReadField(offset, &shdr, &shdr.sh_type, sizeof(shdr.sh_type))) {
+ if (!memory_->Read(offset, &shdr, sizeof(shdr))) {
last_error_.code = ERROR_MEMORY_INVALID;
- last_error_.address =
- offset + reinterpret_cast<uintptr_t>(&shdr.sh_type) - reinterpret_cast<uintptr_t>(&shdr);
+ last_error_.address = offset;
return false;
}
if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
- if (!memory_->ReadFully(offset, &shdr, sizeof(shdr))) {
- last_error_.code = ERROR_MEMORY_INVALID;
- last_error_.address = offset;
- return false;
- }
// Need to go get the information about the section that contains
// the string terminated names.
ShdrType str_shdr;
@@ -343,39 +338,19 @@
return false;
}
uint64_t str_offset = ehdr.e_shoff + shdr.sh_link * ehdr.e_shentsize;
- if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_type, sizeof(str_shdr.sh_type))) {
+ if (!memory_->Read(str_offset, &str_shdr, sizeof(str_shdr))) {
last_error_.code = ERROR_MEMORY_INVALID;
- last_error_.address = str_offset + reinterpret_cast<uintptr_t>(&str_shdr.sh_type) -
- reinterpret_cast<uintptr_t>(&str_shdr);
+ last_error_.address = str_offset;
return false;
}
if (str_shdr.sh_type != SHT_STRTAB) {
last_error_.code = ERROR_UNWIND_INFO;
return false;
}
- if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_offset,
- sizeof(str_shdr.sh_offset))) {
- last_error_.code = ERROR_MEMORY_INVALID;
- last_error_.address = str_offset + reinterpret_cast<uintptr_t>(&str_shdr.sh_offset) -
- reinterpret_cast<uintptr_t>(&str_shdr);
- return false;
- }
- if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_size, sizeof(str_shdr.sh_size))) {
- last_error_.code = ERROR_MEMORY_INVALID;
- last_error_.address = str_offset + reinterpret_cast<uintptr_t>(&str_shdr.sh_size) -
- reinterpret_cast<uintptr_t>(&str_shdr);
- return false;
- }
symbols_.push_back(new Symbols(shdr.sh_offset, shdr.sh_size, shdr.sh_entsize,
str_shdr.sh_offset, str_shdr.sh_size));
} else if (shdr.sh_type == SHT_PROGBITS && sec_size != 0) {
// Look for the .debug_frame and .gnu_debugdata.
- if (!memory_->ReadField(offset, &shdr, &shdr.sh_name, sizeof(shdr.sh_name))) {
- last_error_.code = ERROR_MEMORY_INVALID;
- last_error_.address = offset + reinterpret_cast<uintptr_t>(&shdr.sh_name) -
- reinterpret_cast<uintptr_t>(&shdr);
- return false;
- }
if (shdr.sh_name < sec_size) {
std::string name;
if (memory_->ReadString(sec_offset + shdr.sh_name, &name)) {
@@ -394,14 +369,16 @@
offset_ptr = &eh_frame_hdr_offset_;
size_ptr = &eh_frame_hdr_size_;
}
- if (offset_ptr != nullptr &&
- memory_->ReadField(offset, &shdr, &shdr.sh_offset, sizeof(shdr.sh_offset)) &&
- memory_->ReadField(offset, &shdr, &shdr.sh_size, sizeof(shdr.sh_size))) {
+ if (offset_ptr != nullptr) {
*offset_ptr = shdr.sh_offset;
*size_ptr = shdr.sh_size;
}
}
}
+ } else if (shdr.sh_type == SHT_STRTAB) {
+ // In order to read soname, keep track of address to offset mapping.
+ strtabs_.push_back(std::make_pair<uint64_t, uint64_t>(static_cast<uint64_t>(shdr.sh_addr),
+ static_cast<uint64_t>(shdr.sh_offset)));
}
}
return true;
@@ -420,7 +397,7 @@
soname_type_ = SONAME_INVALID;
uint64_t soname_offset = 0;
- uint64_t strtab_offset = 0;
+ uint64_t strtab_addr = 0;
uint64_t strtab_size = 0;
// Find the soname location from the dynamic headers section.
@@ -435,7 +412,7 @@
}
if (dyn.d_tag == DT_STRTAB) {
- strtab_offset = dyn.d_un.d_ptr;
+ strtab_addr = dyn.d_un.d_ptr;
} else if (dyn.d_tag == DT_STRSZ) {
strtab_size = dyn.d_un.d_val;
} else if (dyn.d_tag == DT_SONAME) {
@@ -445,16 +422,22 @@
}
}
- soname_offset += strtab_offset;
- if (soname_offset >= strtab_offset + strtab_size) {
- return false;
+ // Need to map the strtab address to the real offset.
+ for (const auto& entry : strtabs_) {
+ if (entry.first == strtab_addr) {
+ soname_offset = entry.second + soname_offset;
+ if (soname_offset >= entry.second + strtab_size) {
+ return false;
+ }
+ if (!memory_->ReadString(soname_offset, &soname_)) {
+ return false;
+ }
+ soname_type_ = SONAME_VALID;
+ *soname = soname_;
+ return true;
+ }
}
- if (!memory_->ReadString(soname_offset, &soname_)) {
- return false;
- }
- soname_type_ = SONAME_VALID;
- *soname = soname_;
- return true;
+ return false;
}
template <typename SymType>
diff --git a/libunwindstack/MapInfo.cpp b/libunwindstack/MapInfo.cpp
index 0c15335..39378a3 100644
--- a/libunwindstack/MapInfo.cpp
+++ b/libunwindstack/MapInfo.cpp
@@ -117,23 +117,15 @@
if (Elf::CachingEnabled() && !name.empty()) {
Elf::CacheLock();
locked = true;
- if (offset != 0) {
- std::string hash(name + ':' + std::to_string(offset));
- if (Elf::CacheGet(hash, &elf)) {
- Elf::CacheUnlock();
- return elf.get();
- }
- } else if (Elf::CacheGet(name, &elf)) {
+ if (Elf::CacheGet(this)) {
Elf::CacheUnlock();
return elf.get();
}
}
Memory* memory = CreateMemory(process_memory);
- if (locked && offset != 0 && elf_offset != 0) {
- // In this case, the whole file is the elf, need to see if the elf
- // data was cached.
- if (Elf::CacheGet(name, &elf)) {
+ if (locked) {
+ if (Elf::CacheAfterCreateMemory(this)) {
delete memory;
Elf::CacheUnlock();
return elf.get();
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/RegsInfo.h b/libunwindstack/RegsInfo.h
new file mode 100644
index 0000000..47825f5
--- /dev/null
+++ b/libunwindstack/RegsInfo.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBUNWINDSTACK_REGS_INFO_H
+#define _LIBUNWINDSTACK_REGS_INFO_H
+
+#include <stdint.h>
+
+#include <unwindstack/Regs.h>
+
+namespace unwindstack {
+
+template <typename AddressType>
+struct RegsInfo {
+ RegsInfo(RegsImpl<AddressType>* regs) : regs(regs) {}
+
+ RegsImpl<AddressType>* regs = nullptr;
+ uint64_t saved_reg_map = 0;
+ AddressType saved_regs[64];
+
+ inline AddressType Get(uint32_t reg) {
+ if (IsSaved(reg)) {
+ return saved_regs[reg];
+ }
+ return (*regs)[reg];
+ }
+
+ inline AddressType* Save(uint32_t reg) {
+ if (reg > sizeof(saved_regs) / sizeof(AddressType)) {
+ // This should never happen as since all currently supported
+ // architectures have the total number of registers < 64.
+ abort();
+ }
+ saved_reg_map |= 1 << reg;
+ saved_regs[reg] = (*regs)[reg];
+ return &(*regs)[reg];
+ }
+
+ inline bool IsSaved(uint32_t reg) {
+ if (reg > sizeof(saved_regs) / sizeof(AddressType)) {
+ // This should never happen as since all currently supported
+ // architectures have the total number of registers < 64.
+ abort();
+ }
+ return saved_reg_map & (1 << reg);
+ }
+
+ inline uint16_t Total() { return regs->total_regs(); }
+};
+
+} // namespace unwindstack
+
+#endif // _LIBUNWINDSTACK_REGS_INFO_H
diff --git a/libunwindstack/RegsMips.cpp b/libunwindstack/RegsMips.cpp
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 dfd7b18..7da6994 100644
--- a/libunwindstack/Unwinder.cpp
+++ b/libunwindstack/Unwinder.cpp
@@ -48,6 +48,7 @@
size_t frame_num = frames_.size();
frames_.resize(frame_num + 1);
FrameData* frame = &frames_.at(frame_num);
+ frame->num = frame_num;
uint64_t dex_pc = regs_->dex_pc();
frame->pc = dex_pc;
@@ -67,6 +68,10 @@
return;
}
+ if (!resolve_names_) {
+ return;
+ }
+
#if !defined(NO_LIBDEXFILE_SUPPORT)
if (dex_files_ == nullptr) {
return;
@@ -78,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;
frame->map_name = map_info->name;
frame->map_offset = map_info->offset;
frame->map_start = map_info->start;
@@ -99,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;
}
@@ -134,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)) {
@@ -149,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;
}
}
@@ -179,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;
@@ -207,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/DwarfSection.h b/libunwindstack/include/unwindstack/DwarfSection.h
index 03f40d6..da91fd0 100644
--- a/libunwindstack/include/unwindstack/DwarfSection.h
+++ b/libunwindstack/include/unwindstack/DwarfSection.h
@@ -32,6 +32,8 @@
// Forward declarations.
class Memory;
class Regs;
+template <typename AddressType>
+struct RegsInfo;
class DwarfSection {
public:
@@ -149,8 +151,8 @@
bool Log(uint8_t indent, uint64_t pc, uint64_t load_bias, const DwarfFde* fde) override;
protected:
- bool EvalExpression(const DwarfLocation& loc, uint8_t version, Memory* regular_memory,
- AddressType* value);
+ bool EvalExpression(const DwarfLocation& loc, Memory* regular_memory, AddressType* value,
+ RegsInfo<AddressType>* regs_info, bool* is_dex_pc);
bool GetCieInfo(uint8_t* segment_size, uint8_t* encoding);
diff --git a/libunwindstack/include/unwindstack/Elf.h b/libunwindstack/include/unwindstack/Elf.h
index a874709..385973e 100644
--- a/libunwindstack/include/unwindstack/Elf.h
+++ b/libunwindstack/include/unwindstack/Elf.h
@@ -23,6 +23,7 @@
#include <mutex>
#include <string>
#include <unordered_map>
+#include <utility>
#include <unwindstack/ElfInterface.h>
#include <unwindstack/Memory.h>
@@ -103,7 +104,8 @@
static void CacheLock();
static void CacheUnlock();
static void CacheAdd(MapInfo* info);
- static bool CacheGet(const std::string& name, std::shared_ptr<Elf>* elf);
+ static bool CacheGet(MapInfo* info);
+ static bool CacheAfterCreateMemory(MapInfo* info);
protected:
bool valid_ = false;
@@ -120,7 +122,7 @@
std::unique_ptr<ElfInterface> gnu_debugdata_interface_;
static bool cache_enabled_;
- static std::unordered_map<std::string, std::shared_ptr<Elf>>* cache_;
+ static std::unordered_map<std::string, std::pair<std::shared_ptr<Elf>, bool>>* cache_;
static std::mutex* cache_lock_;
};
diff --git a/libunwindstack/include/unwindstack/ElfInterface.h b/libunwindstack/include/unwindstack/ElfInterface.h
index ea9ec9d..3a221bc 100644
--- a/libunwindstack/include/unwindstack/ElfInterface.h
+++ b/libunwindstack/include/unwindstack/ElfInterface.h
@@ -157,6 +157,7 @@
ElfInterface* gnu_debugdata_interface_ = nullptr;
std::vector<Symbols*> symbols_;
+ std::vector<std::pair<uint64_t, uint64_t>> strtabs_;
};
class ElfInterface32 : public ElfInterface {
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/DwarfOpTest.cpp b/libunwindstack/tests/DwarfOpTest.cpp
index 036226d..6e15227 100644
--- a/libunwindstack/tests/DwarfOpTest.cpp
+++ b/libunwindstack/tests/DwarfOpTest.cpp
@@ -52,14 +52,14 @@
TYPED_TEST_P(DwarfOpTest, decode) {
// Memory error.
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->LastErrorCode());
EXPECT_EQ(0U, this->op_->LastErrorAddress());
// No error.
this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x96});
this->mem_->set_cur_offset(0);
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_NONE, this->op_->LastErrorCode());
ASSERT_EQ(0x96U, this->op_->cur_op());
ASSERT_EQ(1U, this->mem_->cur_offset());
@@ -67,14 +67,14 @@
TYPED_TEST_P(DwarfOpTest, eval) {
// Memory error.
- ASSERT_FALSE(this->op_->Eval(0, 2, DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Eval(0, 2));
ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->LastErrorCode());
EXPECT_EQ(0U, this->op_->LastErrorAddress());
// Register set.
// Do this first, to verify that subsequent calls reset the value.
this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x50});
- ASSERT_TRUE(this->op_->Eval(0, 1, DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Eval(0, 1));
ASSERT_TRUE(this->op_->is_register());
ASSERT_EQ(1U, this->mem_->cur_offset());
ASSERT_EQ(1U, this->op_->StackSize());
@@ -85,7 +85,7 @@
};
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_TRUE(this->op_->Eval(0, 8, DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Eval(0, 8));
ASSERT_EQ(DWARF_ERROR_NONE, this->op_->LastErrorCode());
ASSERT_FALSE(this->op_->is_register());
ASSERT_EQ(8U, this->mem_->cur_offset());
@@ -97,7 +97,7 @@
// Infinite loop.
this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x2f, 0xfd, 0xff});
- ASSERT_FALSE(this->op_->Eval(0, 4, DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Eval(0, 4));
ASSERT_EQ(DWARF_ERROR_TOO_MANY_ITERATIONS, this->op_->LastErrorCode());
ASSERT_FALSE(this->op_->is_register());
ASSERT_EQ(0U, this->op_->StackSize());
@@ -112,29 +112,7 @@
this->op_memory_.SetMemory(0, opcode_buffer);
for (size_t i = 0; i < opcode_buffer.size(); i++) {
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
- ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
- ASSERT_EQ(opcode_buffer[i], this->op_->cur_op());
- }
-}
-
-TYPED_TEST_P(DwarfOpTest, illegal_in_version3) {
- std::vector<uint8_t> opcode_buffer = {0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d};
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- for (size_t i = 0; i < opcode_buffer.size(); i++) {
- ASSERT_FALSE(this->op_->Decode(2));
- ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
- ASSERT_EQ(opcode_buffer[i], this->op_->cur_op());
- }
-}
-
-TYPED_TEST_P(DwarfOpTest, illegal_in_version4) {
- std::vector<uint8_t> opcode_buffer = {0x9e, 0x9f};
- this->op_memory_.SetMemory(0, opcode_buffer);
-
- for (size_t i = 0; i < opcode_buffer.size(); i++) {
- ASSERT_FALSE(this->op_->Decode(3));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
ASSERT_EQ(opcode_buffer[i], this->op_->cur_op());
}
@@ -174,12 +152,12 @@
this->op_memory_.SetMemory(0, opcode_buffer);
// Push the stack values.
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
+ ASSERT_TRUE(this->op_->Decode());
+ ASSERT_TRUE(this->op_->Decode());
while (this->mem_->cur_offset() < opcode_buffer.size()) {
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->op_->LastErrorCode());
}
}
@@ -194,7 +172,7 @@
}
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x03, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
if (sizeof(TypeParam) == 4) {
@@ -217,17 +195,17 @@
TypeParam value = 0x12345678;
this->regular_memory_.SetMemory(0x2010, &value, sizeof(value));
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x06, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(value, this->op_->StackAt(0));
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->LastErrorCode());
ASSERT_EQ(0x12345678U, this->op_->LastErrorAddress());
}
@@ -237,14 +215,14 @@
TypeParam value = 0x12345678;
this->regular_memory_.SetMemory(0x2010, &value, sizeof(value));
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
// Read all byte sizes up to the sizeof the type.
for (size_t i = 1; i < sizeof(TypeParam); i++) {
this->op_memory_.SetMemory(
0, std::vector<uint8_t>{0x0a, 0x10, 0x20, 0x94, static_cast<uint8_t>(i)});
- ASSERT_TRUE(this->op_->Eval(0, 5, DWARF_VERSION_MAX)) << "Failed at size " << i;
+ ASSERT_TRUE(this->op_->Eval(0, 5)) << "Failed at size " << i;
ASSERT_EQ(1U, this->op_->StackSize()) << "Failed at size " << i;
ASSERT_EQ(0x94, this->op_->cur_op()) << "Failed at size " << i;
TypeParam expected_value = 0;
@@ -254,17 +232,17 @@
// Zero byte read.
this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x0a, 0x10, 0x20, 0x94, 0x00});
- ASSERT_FALSE(this->op_->Eval(0, 5, DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Eval(0, 5));
ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
// Read too many bytes.
this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x0a, 0x10, 0x20, 0x94, sizeof(TypeParam) + 1});
- ASSERT_FALSE(this->op_->Eval(0, 5, DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Eval(0, 5));
ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
// Force bad memory read.
this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x0a, 0x10, 0x40, 0x94, 0x01});
- ASSERT_FALSE(this->op_->Eval(0, 5, DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Eval(0, 5));
ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->LastErrorCode());
EXPECT_EQ(0x4010U, this->op_->LastErrorAddress());
}
@@ -284,40 +262,40 @@
this->op_memory_.SetMemory(0, opcode_buffer);
// const1u
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x08, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(0x12U, this->op_->StackAt(0));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x08, this->op_->cur_op());
ASSERT_EQ(2U, this->op_->StackSize());
ASSERT_EQ(0xffU, this->op_->StackAt(0));
// const2u
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x0a, this->op_->cur_op());
ASSERT_EQ(3U, this->op_->StackSize());
ASSERT_EQ(0x1245U, this->op_->StackAt(0));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x0a, this->op_->cur_op());
ASSERT_EQ(4U, this->op_->StackSize());
ASSERT_EQ(0xff00U, this->op_->StackAt(0));
// const4u
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x0c, this->op_->cur_op());
ASSERT_EQ(5U, this->op_->StackSize());
ASSERT_EQ(0x45342312U, this->op_->StackAt(0));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x0c, this->op_->cur_op());
ASSERT_EQ(6U, this->op_->StackSize());
ASSERT_EQ(0xff010203U, this->op_->StackAt(0));
// const8u
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x0e, this->op_->cur_op());
ASSERT_EQ(7U, this->op_->StackSize());
if (sizeof(TypeParam) == 4) {
@@ -326,7 +304,7 @@
ASSERT_EQ(0x0102030405060708ULL, this->op_->StackAt(0));
}
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x0e, this->op_->cur_op());
ASSERT_EQ(8U, this->op_->StackSize());
if (sizeof(TypeParam) == 4) {
@@ -351,40 +329,40 @@
this->op_memory_.SetMemory(0, opcode_buffer);
// const1s
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x09, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(0x12U, this->op_->StackAt(0));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x09, this->op_->cur_op());
ASSERT_EQ(2U, this->op_->StackSize());
ASSERT_EQ(static_cast<TypeParam>(-1), this->op_->StackAt(0));
// const2s
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x0b, this->op_->cur_op());
ASSERT_EQ(3U, this->op_->StackSize());
ASSERT_EQ(0x3221U, this->op_->StackAt(0));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x0b, this->op_->cur_op());
ASSERT_EQ(4U, this->op_->StackSize());
ASSERT_EQ(static_cast<TypeParam>(-248), this->op_->StackAt(0));
// const4s
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x0d, this->op_->cur_op());
ASSERT_EQ(5U, this->op_->StackSize());
ASSERT_EQ(0x12233445U, this->op_->StackAt(0));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x0d, this->op_->cur_op());
ASSERT_EQ(6U, this->op_->StackSize());
ASSERT_EQ(static_cast<TypeParam>(-16580095), this->op_->StackAt(0));
// const8s
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x0f, this->op_->cur_op());
ASSERT_EQ(7U, this->op_->StackSize());
if (sizeof(TypeParam) == 4) {
@@ -393,7 +371,7 @@
ASSERT_EQ(0x1223344556677889ULL, this->op_->StackAt(0));
}
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x0f, this->op_->cur_op());
ASSERT_EQ(8U, this->op_->StackSize());
if (sizeof(TypeParam) == 4) {
@@ -414,28 +392,28 @@
this->op_memory_.SetMemory(0, opcode_buffer);
// Single byte ULEB128
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x10, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(0x22U, this->op_->StackAt(0));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x10, this->op_->cur_op());
ASSERT_EQ(2U, this->op_->StackSize());
ASSERT_EQ(0x7fU, this->op_->StackAt(0));
// Multi byte ULEB128
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x10, this->op_->cur_op());
ASSERT_EQ(3U, this->op_->StackSize());
ASSERT_EQ(0x1122U, this->op_->StackAt(0));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x10, this->op_->cur_op());
ASSERT_EQ(4U, this->op_->StackSize());
ASSERT_EQ(0x3a22U, this->op_->StackAt(0));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x10, this->op_->cur_op());
ASSERT_EQ(5U, this->op_->StackSize());
if (sizeof(TypeParam) == 4) {
@@ -444,7 +422,7 @@
ASSERT_EQ(0x9101c305080c101ULL, this->op_->StackAt(0));
}
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x10, this->op_->cur_op());
ASSERT_EQ(6U, this->op_->StackSize());
if (sizeof(TypeParam) == 4) {
@@ -480,28 +458,28 @@
this->op_memory_.SetMemory(0, opcode_buffer);
// Single byte SLEB128
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x11, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(0x22U, this->op_->StackAt(0));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x11, this->op_->cur_op());
ASSERT_EQ(2U, this->op_->StackSize());
ASSERT_EQ(static_cast<TypeParam>(-1), this->op_->StackAt(0));
// Multi byte SLEB128
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x11, this->op_->cur_op());
ASSERT_EQ(3U, this->op_->StackSize());
ASSERT_EQ(0x1122U, this->op_->StackAt(0));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x11, this->op_->cur_op());
ASSERT_EQ(4U, this->op_->StackSize());
ASSERT_EQ(static_cast<TypeParam>(-1502), this->op_->StackAt(0));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x11, this->op_->cur_op());
ASSERT_EQ(5U, this->op_->StackSize());
if (sizeof(TypeParam) == 4) {
@@ -510,7 +488,7 @@
ASSERT_EQ(0x9101c305080c101ULL, this->op_->StackAt(0));
}
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x11, this->op_->cur_op());
ASSERT_EQ(6U, this->op_->StackSize());
if (sizeof(TypeParam) == 4) {
@@ -531,21 +509,21 @@
};
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(0x12, this->op_->cur_op());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x12, this->op_->cur_op());
ASSERT_EQ(2U, this->op_->StackSize());
ASSERT_EQ(0x15U, this->op_->StackAt(0));
ASSERT_EQ(0x15U, this->op_->StackAt(1));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(3U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x12, this->op_->cur_op());
ASSERT_EQ(4U, this->op_->StackSize());
ASSERT_EQ(0x23U, this->op_->StackAt(0));
@@ -565,21 +543,21 @@
};
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x13, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(0x10U, this->op_->StackAt(0));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x13, this->op_->cur_op());
ASSERT_EQ(0U, this->op_->StackSize());
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(0x13, this->op_->cur_op());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
}
@@ -597,24 +575,24 @@
};
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x14, this->op_->cur_op());
ASSERT_EQ(3U, this->op_->StackSize());
ASSERT_EQ(0x1aU, this->op_->StackAt(0));
ASSERT_EQ(0xedU, this->op_->StackAt(1));
ASSERT_EQ(0x1aU, this->op_->StackAt(2));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(0x14, this->op_->cur_op());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
}
@@ -632,14 +610,14 @@
};
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(3U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x15, this->op_->cur_op());
ASSERT_EQ(4U, this->op_->StackSize());
ASSERT_EQ(0xedU, this->op_->StackAt(0));
@@ -647,7 +625,7 @@
ASSERT_EQ(0xedU, this->op_->StackAt(2));
ASSERT_EQ(0x1aU, this->op_->StackAt(3));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x15, this->op_->cur_op());
ASSERT_EQ(5U, this->op_->StackSize());
ASSERT_EQ(0x1aU, this->op_->StackAt(0));
@@ -656,7 +634,7 @@
ASSERT_EQ(0xedU, this->op_->StackAt(3));
ASSERT_EQ(0x1aU, this->op_->StackAt(4));
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(0x15, this->op_->cur_op());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
}
@@ -672,23 +650,23 @@
};
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(2U, this->op_->StackSize());
ASSERT_EQ(0xabU, this->op_->StackAt(0));
ASSERT_EQ(0x26U, this->op_->StackAt(1));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x16, this->op_->cur_op());
ASSERT_EQ(2U, this->op_->StackSize());
ASSERT_EQ(0x26U, this->op_->StackAt(0));
ASSERT_EQ(0xabU, this->op_->StackAt(1));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(0x16, this->op_->cur_op());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
}
@@ -706,28 +684,28 @@
};
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(3U, this->op_->StackSize());
ASSERT_EQ(0x30U, this->op_->StackAt(0));
ASSERT_EQ(0x20U, this->op_->StackAt(1));
ASSERT_EQ(0x10U, this->op_->StackAt(2));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x17, this->op_->cur_op());
ASSERT_EQ(3U, this->op_->StackSize());
ASSERT_EQ(0x20U, this->op_->StackAt(0));
@@ -756,30 +734,30 @@
opcode_buffer.push_back(0x19);
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(0x10U, this->op_->StackAt(0));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x19, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(0x10U, this->op_->StackAt(0));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x19, this->op_->cur_op());
ASSERT_EQ(2U, this->op_->StackSize());
ASSERT_EQ(0x1U, this->op_->StackAt(0));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(3U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x19, this->op_->cur_op());
ASSERT_EQ(3U, this->op_->StackSize());
if (sizeof(TypeParam) == 4) {
@@ -808,56 +786,56 @@
};
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
// Two positive values.
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x1b, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(0x10U, this->op_->StackAt(0));
// Two negative values.
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(3U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x1b, this->op_->cur_op());
ASSERT_EQ(2U, this->op_->StackSize());
ASSERT_EQ(0x04U, this->op_->StackAt(0));
// One negative value, one positive value.
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(3U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(4U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x1b, this->op_->cur_op());
ASSERT_EQ(3U, this->op_->StackSize());
ASSERT_EQ(static_cast<TypeParam>(-4), this->op_->StackAt(0));
// Divide by zero.
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(4U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(5U, this->op_->StackSize());
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
}
@@ -874,19 +852,19 @@
};
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x1a, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(0x40U, this->op_->StackAt(0));
@@ -905,19 +883,19 @@
};
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x1c, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(0x44U, this->op_->StackAt(0));
@@ -938,29 +916,29 @@
};
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x1d, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(0x03U, this->op_->StackAt(0));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(3U, this->op_->StackSize());
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
}
@@ -977,19 +955,19 @@
};
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x1e, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(0x120U, this->op_->StackAt(0));
@@ -1006,21 +984,21 @@
};
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x1f, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(static_cast<TypeParam>(-72), this->op_->StackAt(0));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x1f, this->op_->cur_op());
ASSERT_EQ(2U, this->op_->StackSize());
ASSERT_EQ(0x01U, this->op_->StackAt(0));
@@ -1037,21 +1015,21 @@
};
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x20, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(static_cast<TypeParam>(-5), this->op_->StackAt(0));
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x20, this->op_->cur_op());
ASSERT_EQ(2U, this->op_->StackSize());
ASSERT_EQ(0x03U, this->op_->StackAt(0));
@@ -1070,19 +1048,19 @@
};
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x21, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(0xfcU, this->op_->StackAt(0));
@@ -1101,19 +1079,19 @@
};
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x22, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(0x1f1U, this->op_->StackAt(0));
@@ -1128,13 +1106,13 @@
};
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x23, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(0x28d0U, this->op_->StackAt(0));
@@ -1153,19 +1131,19 @@
};
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x24, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(0x338U, this->op_->StackAt(0));
@@ -1184,19 +1162,19 @@
};
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x25, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
if (sizeof(TypeParam) == 4) {
@@ -1219,19 +1197,19 @@
};
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x26, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(static_cast<TypeParam>(-2), this->op_->StackAt(0));
@@ -1250,19 +1228,19 @@
};
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(2U, this->op_->StackSize());
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x27, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(0x50U, this->op_->StackAt(0));
@@ -1283,48 +1261,48 @@
};
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Decode());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
// Push on a non-zero value with a positive branch.
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
uint64_t offset = this->mem_->cur_offset() + 3;
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x28, this->op_->cur_op());
ASSERT_EQ(0U, this->op_->StackSize());
ASSERT_EQ(offset + 0x102, this->mem_->cur_offset());
// Push on a zero value with a positive branch.
this->mem_->set_cur_offset(offset);
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
offset = this->mem_->cur_offset() + 3;
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x28, this->op_->cur_op());
ASSERT_EQ(0U, this->op_->StackSize());
ASSERT_EQ(offset - 5, this->mem_->cur_offset());
// Push on a non-zero value with a negative branch.
this->mem_->set_cur_offset(offset);
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
offset = this->mem_->cur_offset() + 3;
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x28, this->op_->cur_op());
ASSERT_EQ(0U, this->op_->StackSize());
ASSERT_EQ(offset - 4, this->mem_->cur_offset());
// Push on a zero value with a negative branch.
this->mem_->set_cur_offset(offset);
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(1U, this->op_->StackSize());
offset = this->mem_->cur_offset() + 3;
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x28, this->op_->cur_op());
ASSERT_EQ(0U, this->op_->StackSize());
ASSERT_EQ(offset + 16, this->mem_->cur_offset());
@@ -1344,11 +1322,11 @@
opcode_buffer[3] = opcode;
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_FALSE(this->op_->Eval(0, 1, DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Eval(0, 1));
ASSERT_EQ(opcode, this->op_->cur_op());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
- ASSERT_FALSE(this->op_->Eval(1, 4, DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Eval(1, 4));
ASSERT_EQ(opcode, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
@@ -1387,7 +1365,7 @@
opcode_buffer[14] = expected[i];
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_TRUE(this->op_->Eval(0, 15, DWARF_VERSION_MAX))
+ ASSERT_TRUE(this->op_->Eval(0, 15))
<< "Op: 0x" << std::hex << static_cast<uint32_t>(expected[i]) << " failed";
ASSERT_EQ(3U, this->op_->StackSize());
@@ -1407,14 +1385,14 @@
this->op_memory_.SetMemory(0, opcode_buffer);
uint64_t offset = this->mem_->cur_offset() + 3;
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x2f, this->op_->cur_op());
ASSERT_EQ(0U, this->op_->StackSize());
ASSERT_EQ(offset + 0x2010, this->mem_->cur_offset());
this->mem_->set_cur_offset(offset);
offset = this->mem_->cur_offset() + 3;
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x2f, this->op_->cur_op());
ASSERT_EQ(0U, this->op_->StackSize());
ASSERT_EQ(offset - 3, this->mem_->cur_offset());
@@ -1431,7 +1409,7 @@
for (size_t i = 0; i < opcode_buffer.size(); i++) {
uint32_t op = opcode_buffer[i];
- ASSERT_TRUE(this->op_->Eval(i, i + 1, DWARF_VERSION_MAX)) << "Failed op: 0x" << std::hex << op;
+ ASSERT_TRUE(this->op_->Eval(i, i + 1)) << "Failed op: 0x" << std::hex << op;
ASSERT_EQ(op, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize()) << "Failed op: 0x" << std::hex << op;
ASSERT_EQ(op - 0x30U, this->op_->StackAt(0)) << "Failed op: 0x" << std::hex << op;
@@ -1449,7 +1427,7 @@
for (size_t i = 0; i < opcode_buffer.size(); i++) {
uint32_t op = opcode_buffer[i];
- ASSERT_TRUE(this->op_->Eval(i, i + 1, DWARF_VERSION_MAX)) << "Failed op: 0x" << std::hex << op;
+ ASSERT_TRUE(this->op_->Eval(i, i + 1)) << "Failed op: 0x" << std::hex << op;
ASSERT_EQ(op, this->op_->cur_op());
ASSERT_TRUE(this->op_->is_register()) << "Failed op: 0x" << std::hex << op;
ASSERT_EQ(1U, this->op_->StackSize()) << "Failed op: 0x" << std::hex << op;
@@ -1463,13 +1441,13 @@
};
this->op_memory_.SetMemory(0, opcode_buffer);
- ASSERT_TRUE(this->op_->Eval(0, 2, DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Eval(0, 2));
ASSERT_EQ(0x90, this->op_->cur_op());
ASSERT_TRUE(this->op_->is_register());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(0x02U, this->op_->StackAt(0));
- ASSERT_TRUE(this->op_->Eval(2, 5, DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Eval(2, 5));
ASSERT_EQ(0x90, this->op_->cur_op());
ASSERT_TRUE(this->op_->is_register());
ASSERT_EQ(1U, this->op_->StackSize());
@@ -1494,21 +1472,20 @@
for (size_t i = 0; i < 32; i++) {
regs[i] = i + 10;
}
- this->op_->set_regs(®s);
+ RegsInfo<TypeParam> regs_info(®s);
+ this->op_->set_regs_info(®s_info);
uint64_t offset = 0;
for (uint32_t op = 0x70; op <= 0x8f; op++) {
// Positive value added to register.
- ASSERT_TRUE(this->op_->Eval(offset, offset + 2, DWARF_VERSION_MAX)) << "Failed op: 0x"
- << std::hex << op;
+ ASSERT_TRUE(this->op_->Eval(offset, offset + 2)) << "Failed op: 0x" << std::hex << op;
ASSERT_EQ(op, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize()) << "Failed op: 0x" << std::hex << op;
ASSERT_EQ(op - 0x70 + 10 + 0x12, this->op_->StackAt(0)) << "Failed op: 0x" << std::hex << op;
offset += 2;
// Negative value added to register.
- ASSERT_TRUE(this->op_->Eval(offset, offset + 2, DWARF_VERSION_MAX)) << "Failed op: 0x"
- << std::hex << op;
+ ASSERT_TRUE(this->op_->Eval(offset, offset + 2)) << "Failed op: 0x" << std::hex << op;
ASSERT_EQ(op, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize()) << "Failed op: 0x" << std::hex << op;
ASSERT_EQ(op - 0x70 + 10 - 2, this->op_->StackAt(0)) << "Failed op: 0x" << std::hex << op;
@@ -1526,16 +1503,17 @@
for (size_t i = 0; i < 16; i++) {
regs[i] = i + 10;
}
- this->op_->set_regs(®s);
+ RegsInfo<TypeParam> regs_info(®s);
+ this->op_->set_regs_info(®s_info);
// Should pass since this references the last regsister.
- ASSERT_TRUE(this->op_->Eval(0, 2, DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Eval(0, 2));
ASSERT_EQ(0x7fU, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(0x2bU, this->op_->StackAt(0));
// Should fail since this references a non-existent register.
- ASSERT_FALSE(this->op_->Eval(2, 4, DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Eval(2, 4));
ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
}
@@ -1551,38 +1529,55 @@
RegsImplFake<TypeParam> regs(10, 10);
regs[5] = 0x45;
regs[6] = 0x190;
- this->op_->set_regs(®s);
+ RegsInfo<TypeParam> regs_info(®s);
+ this->op_->set_regs_info(®s_info);
- ASSERT_TRUE(this->op_->Eval(0, 3, DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Eval(0, 3));
ASSERT_EQ(0x92, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(0x65U, this->op_->StackAt(0));
- ASSERT_TRUE(this->op_->Eval(3, 7, DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Eval(3, 7));
ASSERT_EQ(0x92, this->op_->cur_op());
ASSERT_EQ(1U, this->op_->StackSize());
ASSERT_EQ(0x90U, this->op_->StackAt(0));
- ASSERT_FALSE(this->op_->Eval(7, 12, DWARF_VERSION_MAX));
+ ASSERT_FALSE(this->op_->Eval(7, 12));
ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
}
TYPED_TEST_P(DwarfOpTest, op_nop) {
this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x96});
- ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
+ ASSERT_TRUE(this->op_->Decode());
ASSERT_EQ(0x96, this->op_->cur_op());
ASSERT_EQ(0U, this->op_->StackSize());
}
-REGISTER_TYPED_TEST_CASE_P(DwarfOpTest, decode, eval, illegal_opcode, illegal_in_version3,
- illegal_in_version4, not_implemented, op_addr, op_deref, op_deref_size,
- const_unsigned, const_signed, const_uleb, const_sleb, op_dup, op_drop,
- op_over, op_pick, op_swap, op_rot, op_abs, op_and, op_div, op_minus,
- op_mod, op_mul, op_neg, op_not, op_or, op_plus, op_plus_uconst, op_shl,
- op_shr, op_shra, op_xor, op_bra, compare_opcode_stack_error,
- compare_opcodes, op_skip, op_lit, op_reg, op_regx, op_breg,
- op_breg_invalid_register, op_bregx, op_nop);
+TYPED_TEST_P(DwarfOpTest, is_dex_pc) {
+ // Special sequence that indicates this is a dex pc.
+ this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x0c, 'D', 'E', 'X', '1', 0x13});
+
+ ASSERT_TRUE(this->op_->Eval(0, 6));
+ EXPECT_TRUE(this->op_->dex_pc_set());
+
+ // Try without the last op.
+ ASSERT_TRUE(this->op_->Eval(0, 5));
+ EXPECT_FALSE(this->op_->dex_pc_set());
+
+ // Change the constant.
+ this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x0c, 'D', 'E', 'X', '2', 0x13});
+ ASSERT_TRUE(this->op_->Eval(0, 6));
+ EXPECT_FALSE(this->op_->dex_pc_set());
+}
+
+REGISTER_TYPED_TEST_CASE_P(DwarfOpTest, decode, eval, illegal_opcode, not_implemented, op_addr,
+ op_deref, op_deref_size, const_unsigned, const_signed, const_uleb,
+ const_sleb, op_dup, op_drop, op_over, op_pick, op_swap, op_rot, op_abs,
+ op_and, op_div, op_minus, op_mod, op_mul, op_neg, op_not, op_or, op_plus,
+ op_plus_uconst, op_shl, op_shr, op_shra, op_xor, op_bra,
+ compare_opcode_stack_error, compare_opcodes, op_skip, op_lit, op_reg,
+ op_regx, op_breg, op_breg_invalid_register, op_bregx, op_nop, is_dex_pc);
typedef ::testing::Types<uint32_t, uint64_t> DwarfOpTestTypes;
INSTANTIATE_TYPED_TEST_CASE_P(, DwarfOpTest, DwarfOpTestTypes);
diff --git a/libunwindstack/tests/DwarfSectionImplTest.cpp b/libunwindstack/tests/DwarfSectionImplTest.cpp
index 7e10935..37305b2 100644
--- a/libunwindstack/tests/DwarfSectionImplTest.cpp
+++ b/libunwindstack/tests/DwarfSectionImplTest.cpp
@@ -99,7 +99,7 @@
regs.set_sp(0x2000);
regs[5] = 0x20;
regs[9] = 0x3000;
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}};
+ loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5002}};
bool finished;
ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
@@ -116,7 +116,7 @@
regs[5] = 0x20;
regs[9] = 0x3000;
this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x96, 0x96, 0x96});
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}};
+ loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5002}};
bool finished;
ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
EXPECT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->section_->LastErrorCode());
@@ -134,7 +134,7 @@
this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
TypeParam cfa_value = 0x12345;
this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value));
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5000}};
+ loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5004}};
bool finished;
ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
EXPECT_FALSE(finished);
@@ -152,7 +152,7 @@
regs[5] = 0x20;
regs[9] = 0x3000;
this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5000}};
+ loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5004}};
bool finished;
ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
ASSERT_FALSE(finished);
@@ -170,7 +170,7 @@
regs[5] = 0x20;
regs[9] = 0x3000;
this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x50, 0x96, 0x96});
- loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}};
+ loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5002}};
bool finished;
ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
EXPECT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->section_->LastErrorCode());
@@ -322,7 +322,8 @@
regs[0] = 0x10;
regs[8] = 0x20;
loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
- loc_regs[0x20444558] = DwarfLocation{DWARF_LOCATION_REGISTER, {0, 1}};
+ loc_regs[1] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x8, 0x5008}};
+ this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 'D', 'E', 'X', '1', 0x13, 0x08, 0x11});
bool finished;
ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
EXPECT_EQ(0x10U, regs[0]);
@@ -462,7 +463,7 @@
TypeParam cfa_value = 0x12345;
this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value));
loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
- loc_regs[5] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5000}};
+ loc_regs[5] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5004}};
bool finished;
ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
EXPECT_FALSE(finished);
@@ -480,7 +481,7 @@
regs[8] = 0x3000;
this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
- loc_regs[5] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5000}};
+ loc_regs[5] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5004}};
bool finished;
ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
EXPECT_FALSE(finished);
diff --git a/libunwindstack/tests/ElfCacheTest.cpp b/libunwindstack/tests/ElfCacheTest.cpp
index 0086c9e..89331ea 100644
--- a/libunwindstack/tests/ElfCacheTest.cpp
+++ b/libunwindstack/tests/ElfCacheTest.cpp
@@ -60,6 +60,7 @@
void VerifyWithinSameMap(bool cache_enabled);
void VerifySameMap(bool cache_enabled);
+ void VerifyWithinSameMapNeverReadAtZero(bool cache_enabled);
static std::shared_ptr<Memory> memory_;
};
@@ -198,4 +199,66 @@
VerifyWithinSameMap(true);
}
+// Verify that when reading from multiple non-zero offsets in the same map
+// that when cached, all of the elf objects are the same.
+void ElfCacheTest::VerifyWithinSameMapNeverReadAtZero(bool cache_enabled) {
+ if (!cache_enabled) {
+ Elf::SetCachingEnabled(false);
+ }
+
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ WriteElfFile(0, &tf, EM_ARM);
+ lseek(tf.fd, 0x500, SEEK_SET);
+ uint8_t value = 0;
+ write(tf.fd, &value, 1);
+ close(tf.fd);
+
+ uint64_t start = 0x1000;
+ uint64_t end = 0x20000;
+ // Multiple info sections at different offsets will have non-zero elf offsets.
+ MapInfo info300_1(start, end, 0x300, 0x5, tf.path);
+ MapInfo info300_2(start, end, 0x300, 0x5, tf.path);
+ MapInfo info400_1(start, end, 0x400, 0x5, tf.path);
+ MapInfo info400_2(start, end, 0x400, 0x5, tf.path);
+
+ Elf* elf300_1 = info300_1.GetElf(memory_, true);
+ ASSERT_TRUE(elf300_1->valid());
+ EXPECT_EQ(ARCH_ARM, elf300_1->arch());
+ Elf* elf300_2 = info300_2.GetElf(memory_, true);
+ ASSERT_TRUE(elf300_2->valid());
+ EXPECT_EQ(ARCH_ARM, elf300_2->arch());
+ EXPECT_EQ(0x300U, info300_1.elf_offset);
+ EXPECT_EQ(0x300U, info300_2.elf_offset);
+ if (cache_enabled) {
+ EXPECT_EQ(elf300_1, elf300_2);
+ } else {
+ EXPECT_NE(elf300_1, elf300_2);
+ }
+
+ Elf* elf400_1 = info400_1.GetElf(memory_, true);
+ ASSERT_TRUE(elf400_1->valid());
+ EXPECT_EQ(ARCH_ARM, elf400_1->arch());
+ Elf* elf400_2 = info400_2.GetElf(memory_, true);
+ ASSERT_TRUE(elf400_2->valid());
+ EXPECT_EQ(ARCH_ARM, elf400_2->arch());
+ EXPECT_EQ(0x400U, info400_1.elf_offset);
+ EXPECT_EQ(0x400U, info400_2.elf_offset);
+ if (cache_enabled) {
+ EXPECT_EQ(elf400_1, elf400_2);
+ EXPECT_EQ(elf300_1, elf400_1);
+ } else {
+ EXPECT_NE(elf400_1, elf400_2);
+ EXPECT_NE(elf300_1, elf400_1);
+ }
+}
+
+TEST_F(ElfCacheTest, no_caching_valid_elf_offset_non_zero_never_read_at_zero) {
+ VerifyWithinSameMapNeverReadAtZero(false);
+}
+
+TEST_F(ElfCacheTest, caching_valid_elf_offset_non_zero_never_read_at_zero) {
+ VerifyWithinSameMapNeverReadAtZero(true);
+}
+
} // namespace unwindstack
diff --git a/libunwindstack/tests/ElfInterfaceTest.cpp b/libunwindstack/tests/ElfInterfaceTest.cpp
index 042c5fb..bf97e30 100644
--- a/libunwindstack/tests/ElfInterfaceTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceTest.cpp
@@ -63,15 +63,28 @@
template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
void ManyPhdrs();
- template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
+ enum SonameTestEnum : uint8_t {
+ SONAME_NORMAL,
+ SONAME_DTNULL_AFTER,
+ SONAME_DTSIZE_SMALL,
+ SONAME_MISSING_MAP,
+ };
+
+ template <typename Ehdr, typename Phdr, typename Shdr, typename Dyn>
+ void SonameInit(SonameTestEnum test_type = SONAME_NORMAL);
+
+ template <typename ElfInterfaceType>
void Soname();
- template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
+ template <typename ElfInterfaceType>
void SonameAfterDtNull();
- template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
+ template <typename ElfInterfaceType>
void SonameSize();
+ template <typename ElfInterfaceType>
+ void SonameMissingMap();
+
template <typename ElfType>
void InitHeadersEhFrameTest();
@@ -465,17 +478,29 @@
ASSERT_EQ(2U, elf_arm.total_entries());
}
-template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
-void ElfInterfaceTest::Soname() {
- std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
-
+template <typename Ehdr, typename Phdr, typename Shdr, typename Dyn>
+void ElfInterfaceTest::SonameInit(SonameTestEnum test_type) {
Ehdr ehdr;
memset(&ehdr, 0, sizeof(ehdr));
+ ehdr.e_shoff = 0x200;
+ ehdr.e_shnum = 2;
+ ehdr.e_shentsize = sizeof(Shdr);
ehdr.e_phoff = 0x100;
ehdr.e_phnum = 1;
ehdr.e_phentsize = sizeof(Phdr);
memory_.SetMemory(0, &ehdr, sizeof(ehdr));
+ Shdr shdr;
+ memset(&shdr, 0, sizeof(shdr));
+ shdr.sh_type = SHT_STRTAB;
+ if (test_type == SONAME_MISSING_MAP) {
+ shdr.sh_addr = 0x20100;
+ } else {
+ shdr.sh_addr = 0x10100;
+ }
+ shdr.sh_offset = 0x10000;
+ memory_.SetMemory(0x200 + sizeof(shdr), &shdr, sizeof(shdr));
+
Phdr phdr;
memset(&phdr, 0, sizeof(phdr));
phdr.p_type = PT_DYNAMIC;
@@ -487,15 +512,25 @@
Dyn dyn;
dyn.d_tag = DT_STRTAB;
- dyn.d_un.d_ptr = 0x10000;
+ dyn.d_un.d_ptr = 0x10100;
memory_.SetMemory(offset, &dyn, sizeof(dyn));
offset += sizeof(dyn);
dyn.d_tag = DT_STRSZ;
- dyn.d_un.d_val = 0x1000;
+ if (test_type == SONAME_DTSIZE_SMALL) {
+ dyn.d_un.d_val = 0x10;
+ } else {
+ dyn.d_un.d_val = 0x1000;
+ }
memory_.SetMemory(offset, &dyn, sizeof(dyn));
offset += sizeof(dyn);
+ if (test_type == SONAME_DTNULL_AFTER) {
+ dyn.d_tag = DT_NULL;
+ memory_.SetMemory(offset, &dyn, sizeof(dyn));
+ offset += sizeof(dyn);
+ }
+
dyn.d_tag = DT_SONAME;
dyn.d_un.d_val = 0x10;
memory_.SetMemory(offset, &dyn, sizeof(dyn));
@@ -505,6 +540,11 @@
memory_.SetMemory(offset, &dyn, sizeof(dyn));
SetStringMemory(0x10010, "fake_soname.so");
+}
+
+template <typename ElfInterfaceType>
+void ElfInterfaceTest::Soname() {
+ std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
uint64_t load_bias = 0;
ASSERT_TRUE(elf->Init(&load_bias));
@@ -516,55 +556,19 @@
}
TEST_F(ElfInterfaceTest, elf32_soname) {
- Soname<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn, ElfInterface32>();
+ SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>();
+ Soname<ElfInterface32>();
}
TEST_F(ElfInterfaceTest, elf64_soname) {
- Soname<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>();
+ SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>();
+ Soname<ElfInterface64>();
}
-template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
+template <typename ElfInterfaceType>
void ElfInterfaceTest::SonameAfterDtNull() {
std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
- Ehdr ehdr;
- memset(&ehdr, 0, sizeof(ehdr));
- ehdr.e_phoff = 0x100;
- ehdr.e_phnum = 1;
- ehdr.e_phentsize = sizeof(Phdr);
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- Phdr phdr;
- memset(&phdr, 0, sizeof(phdr));
- phdr.p_type = PT_DYNAMIC;
- phdr.p_offset = 0x2000;
- phdr.p_memsz = sizeof(Dyn) * 3;
- memory_.SetMemory(0x100, &phdr, sizeof(phdr));
-
- Dyn dyn;
- uint64_t offset = 0x2000;
-
- dyn.d_tag = DT_STRTAB;
- dyn.d_un.d_ptr = 0x10000;
- memory_.SetMemory(offset, &dyn, sizeof(dyn));
- offset += sizeof(dyn);
-
- dyn.d_tag = DT_STRSZ;
- dyn.d_un.d_val = 0x1000;
- memory_.SetMemory(offset, &dyn, sizeof(dyn));
- offset += sizeof(dyn);
-
- dyn.d_tag = DT_NULL;
- memory_.SetMemory(offset, &dyn, sizeof(dyn));
- offset += sizeof(dyn);
-
- dyn.d_tag = DT_SONAME;
- dyn.d_un.d_val = 0x10;
- memory_.SetMemory(offset, &dyn, sizeof(dyn));
- offset += sizeof(dyn);
-
- SetStringMemory(0x10010, "fake_soname.so");
-
uint64_t load_bias = 0;
ASSERT_TRUE(elf->Init(&load_bias));
EXPECT_EQ(0U, load_bias);
@@ -574,54 +578,19 @@
}
TEST_F(ElfInterfaceTest, elf32_soname_after_dt_null) {
- SonameAfterDtNull<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn, ElfInterface32>();
+ SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>(SONAME_DTNULL_AFTER);
+ SonameAfterDtNull<ElfInterface32>();
}
TEST_F(ElfInterfaceTest, elf64_soname_after_dt_null) {
- SonameAfterDtNull<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>();
+ SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(SONAME_DTNULL_AFTER);
+ SonameAfterDtNull<ElfInterface64>();
}
-template <typename Ehdr, typename Phdr, typename Dyn, typename ElfInterfaceType>
+template <typename ElfInterfaceType>
void ElfInterfaceTest::SonameSize() {
std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
- Ehdr ehdr;
- memset(&ehdr, 0, sizeof(ehdr));
- ehdr.e_phoff = 0x100;
- ehdr.e_phnum = 1;
- ehdr.e_phentsize = sizeof(Phdr);
- memory_.SetMemory(0, &ehdr, sizeof(ehdr));
-
- Phdr phdr;
- memset(&phdr, 0, sizeof(phdr));
- phdr.p_type = PT_DYNAMIC;
- phdr.p_offset = 0x2000;
- phdr.p_memsz = sizeof(Dyn);
- memory_.SetMemory(0x100, &phdr, sizeof(phdr));
-
- Dyn dyn;
- uint64_t offset = 0x2000;
-
- dyn.d_tag = DT_STRTAB;
- dyn.d_un.d_ptr = 0x10000;
- memory_.SetMemory(offset, &dyn, sizeof(dyn));
- offset += sizeof(dyn);
-
- dyn.d_tag = DT_STRSZ;
- dyn.d_un.d_val = 0x10;
- memory_.SetMemory(offset, &dyn, sizeof(dyn));
- offset += sizeof(dyn);
-
- dyn.d_tag = DT_SONAME;
- dyn.d_un.d_val = 0x10;
- memory_.SetMemory(offset, &dyn, sizeof(dyn));
- offset += sizeof(dyn);
-
- dyn.d_tag = DT_NULL;
- memory_.SetMemory(offset, &dyn, sizeof(dyn));
-
- SetStringMemory(0x10010, "fake_soname.so");
-
uint64_t load_bias = 0;
ASSERT_TRUE(elf->Init(&load_bias));
EXPECT_EQ(0U, load_bias);
@@ -631,11 +600,37 @@
}
TEST_F(ElfInterfaceTest, elf32_soname_size) {
- SonameSize<Elf32_Ehdr, Elf32_Phdr, Elf32_Dyn, ElfInterface32>();
+ SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>(SONAME_DTSIZE_SMALL);
+ SonameSize<ElfInterface32>();
}
TEST_F(ElfInterfaceTest, elf64_soname_size) {
- SonameSize<Elf64_Ehdr, Elf64_Phdr, Elf64_Dyn, ElfInterface64>();
+ SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(SONAME_DTSIZE_SMALL);
+ SonameSize<ElfInterface64>();
+}
+
+// Verify that there is no map from STRTAB in the dynamic section to a
+// STRTAB entry in the section headers.
+template <typename ElfInterfaceType>
+void ElfInterfaceTest::SonameMissingMap() {
+ std::unique_ptr<ElfInterface> elf(new ElfInterfaceType(&memory_));
+
+ uint64_t load_bias = 0;
+ ASSERT_TRUE(elf->Init(&load_bias));
+ EXPECT_EQ(0U, load_bias);
+
+ std::string name;
+ ASSERT_FALSE(elf->GetSoname(&name));
+}
+
+TEST_F(ElfInterfaceTest, elf32_soname_missing_map) {
+ SonameInit<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Dyn>(SONAME_MISSING_MAP);
+ SonameMissingMap<ElfInterface32>();
+}
+
+TEST_F(ElfInterfaceTest, elf64_soname_missing_map) {
+ SonameInit<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Dyn>(SONAME_MISSING_MAP);
+ SonameMissingMap<ElfInterface64>();
}
template <typename ElfType>
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 7358ae6..e44b225 100644
--- a/libunwindstack/tests/UnwinderTest.cpp
+++ b/libunwindstack/tests/UnwinderTest.cpp
@@ -102,6 +102,22 @@
info->load_bias = 0;
maps_.FakeAddMapInfo(info);
+ info = new MapInfo(0xa5000, 0xa6000, 0, PROT_READ | PROT_WRITE | PROT_EXEC,
+ "/fake/fake_load_bias.so");
+ elf = new ElfFake(new MemoryFake);
+ info->elf.reset(elf);
+ elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
+ elf->FakeSetLoadBias(0x5000);
+ maps_.FakeAddMapInfo(info);
+
+ info = new MapInfo(0xa7000, 0xa8000, 0, PROT_READ | PROT_WRITE | PROT_EXEC,
+ "/fake/fake_offset.oat");
+ elf = new ElfFake(new MemoryFake);
+ info->elf.reset(elf);
+ elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
+ info->elf_offset = 0x8000;
+ maps_.FakeAddMapInfo(info);
+
process_memory_.reset(new MemoryFake);
}
@@ -180,6 +196,123 @@
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));
+
+ regs_.FakeSetPc(0xa5500);
+ regs_.FakeSetSp(0x10000);
+ ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
+
+ Unwinder unwinder(64, &maps_, ®s_, process_memory_);
+ unwinder.Unwind();
+ EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+
+ ASSERT_EQ(1U, unwinder.NumFrames());
+
+ auto* frame = &unwinder.frames()[0];
+ EXPECT_EQ(0U, frame->num);
+ EXPECT_EQ(0x5500U, frame->rel_pc);
+ EXPECT_EQ(0xa5500U, frame->pc);
+ EXPECT_EQ(0x10000U, frame->sp);
+ EXPECT_EQ("Frame0", frame->function_name);
+ EXPECT_EQ(0U, frame->function_offset);
+ EXPECT_EQ("/fake/fake_load_bias.so", frame->map_name);
+ EXPECT_EQ(0U, frame->map_offset);
+ EXPECT_EQ(0xa5000U, frame->map_start);
+ EXPECT_EQ(0xa6000U, frame->map_end);
+ EXPECT_EQ(0x5000U, frame->map_load_bias);
+ EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
+}
+
+TEST_F(UnwinderTest, non_zero_elf_offset) {
+ ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
+
+ regs_.FakeSetPc(0xa7500);
+ regs_.FakeSetSp(0x10000);
+ ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
+
+ Unwinder unwinder(64, &maps_, ®s_, process_memory_);
+ unwinder.Unwind();
+ EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+
+ ASSERT_EQ(1U, unwinder.NumFrames());
+
+ auto* frame = &unwinder.frames()[0];
+ EXPECT_EQ(0U, frame->num);
+ EXPECT_EQ(0x8500U, frame->rel_pc);
+ EXPECT_EQ(0xa7500U, frame->pc);
+ EXPECT_EQ(0x10000U, frame->sp);
+ EXPECT_EQ("Frame0", frame->function_name);
+ EXPECT_EQ(0U, frame->function_offset);
+ EXPECT_EQ("/fake/fake_offset.oat", frame->map_name);
+ EXPECT_EQ(0U, frame->map_offset);
+ EXPECT_EQ(0xa7000U, frame->map_start);
+ EXPECT_EQ(0xa8000U, frame->map_end);
+ EXPECT_EQ(0U, frame->map_load_bias);
+ EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, frame->map_flags);
+}
+
TEST_F(UnwinderTest, non_zero_map_offset) {
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
diff --git a/libunwindstack/tools/unwind_info.cpp b/libunwindstack/tools/unwind_info.cpp
index 7f2d11d..a0abcca 100644
--- a/libunwindstack/tools/unwind_info.cpp
+++ b/libunwindstack/tools/unwind_info.cpp
@@ -120,6 +120,11 @@
return 1;
}
+ std::string soname;
+ if (elf.GetSoname(&soname)) {
+ printf("Soname: %s\n", soname.c_str());
+ }
+
ElfInterface* interface = elf.interface();
if (elf.machine_type() == EM_ARM) {
DumpArm(reinterpret_cast<ElfInterfaceArm*>(interface));
diff --git a/libunwindstack/tools/unwind_reg_info.cpp b/libunwindstack/tools/unwind_reg_info.cpp
index 4d89087..47a4f91 100644
--- a/libunwindstack/tools/unwind_reg_info.cpp
+++ b/libunwindstack/tools/unwind_reg_info.cpp
@@ -157,6 +157,11 @@
return 1;
}
+ std::string soname;
+ if (elf.GetSoname(&soname)) {
+ printf("Soname: %s\n\n", soname.c_str());
+ }
+
printf("PC 0x%" PRIx64 ":\n", pc);
DwarfSection* section = interface->eh_frame();
diff --git a/libunwindstack/tools/unwind_symbols.cpp b/libunwindstack/tools/unwind_symbols.cpp
index 697e4cd..086dffe 100644
--- a/libunwindstack/tools/unwind_symbols.cpp
+++ b/libunwindstack/tools/unwind_symbols.cpp
@@ -71,6 +71,11 @@
return 1;
}
+ std::string soname;
+ if (elf.GetSoname(&soname)) {
+ printf("Soname: %s\n\n", soname.c_str());
+ }
+
switch (elf.machine_type()) {
case EM_ARM:
printf("ABI: arm\n");
diff --git a/libusbhost/usbhost.c b/libusbhost/usbhost.c
index fa0191b..cb8d430 100644
--- a/libusbhost/usbhost.c
+++ b/libusbhost/usbhost.c
@@ -64,10 +64,6 @@
// Some devices fail to send string descriptors if we attempt reading > 255 bytes
#define MAX_STRING_DESCRIPTOR_LENGTH 255
-// From drivers/usb/core/devio.c
-// I don't know why this isn't in a kernel header
-#define MAX_USBFS_BUFFER_SIZE 16384
-
#define MAX_USBFS_WD_COUNT 10
struct usb_host_context {
@@ -664,10 +660,6 @@
{
struct usbdevfs_bulktransfer ctrl;
- // need to limit request size to avoid EINVAL
- if (length > MAX_USBFS_BUFFER_SIZE)
- length = MAX_USBFS_BUFFER_SIZE;
-
memset(&ctrl, 0, sizeof(ctrl));
ctrl.ep = endpoint;
ctrl.len = length;
@@ -727,11 +719,7 @@
urb->status = -1;
urb->buffer = req->buffer;
- // need to limit request size to avoid EINVAL
- if (req->buffer_length > MAX_USBFS_BUFFER_SIZE)
- urb->buffer_length = MAX_USBFS_BUFFER_SIZE;
- else
- urb->buffer_length = req->buffer_length;
+ urb->buffer_length = req->buffer_length;
do {
res = ioctl(req->dev->fd, USBDEVFS_SUBMITURB, urb);
diff --git a/libutils/Android.bp b/libutils/Android.bp
index 2be5d98..80dcdcb 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -20,12 +20,12 @@
header_libs: [
"liblog_headers",
"libsystem_headers",
- "libcutils_headers"
+ "libcutils_headers",
],
export_header_lib_headers: [
"liblog_headers",
"libsystem_headers",
- "libcutils_headers"
+ "libcutils_headers",
],
export_include_dirs: ["include"],
@@ -52,7 +52,10 @@
},
host_supported: true,
- cflags: ["-Wall", "-Werror"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
include_dirs: ["external/safe-iop/include"],
header_libs: [
"libutils_headers",
@@ -193,7 +196,8 @@
static_libs: ["libutils"],
shared_libs: ["liblog"],
srcs: ["SharedBufferTest.cpp"],
- cflags: ["-Wall", "-Werror"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
}
-
-subdirs = ["tests"]
diff --git a/libutils/tests/Android.bp b/libutils/tests/Android.bp
index a3e7ffe..1390552 100644
--- a/libutils/tests/Android.bp
+++ b/libutils/tests/Android.bp
@@ -77,7 +77,10 @@
host_supported: true,
relative_install_path: "libutils_tests",
srcs: ["Singleton_test1.cpp"],
- cflags: ["-Wall", "-Werror"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
}
cc_test_library {
@@ -85,6 +88,9 @@
host_supported: true,
relative_install_path: "libutils_tests",
srcs: ["Singleton_test2.cpp"],
- cflags: ["-Wall", "-Werror"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
shared_libs: ["libutils_tests_singleton1"],
}
diff --git a/libvndksupport/Android.bp b/libvndksupport/Android.bp
index fec79b7..e73b366 100644
--- a/libvndksupport/Android.bp
+++ b/libvndksupport/Android.bp
@@ -3,7 +3,10 @@
cc_library {
name: "libvndksupport",
srcs: ["linker.c"],
- cflags: ["-Wall", "-Werror"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
local_include_dirs: ["include/vndksupport"],
export_include_dirs: ["include"],
shared_libs: ["liblog"],
diff --git a/libvndksupport/tests/Android.bp b/libvndksupport/tests/Android.bp
index 5b467f8..2570cce 100644
--- a/libvndksupport/tests/Android.bp
+++ b/libvndksupport/tests/Android.bp
@@ -17,11 +17,14 @@
srcs: [
"linker_test.cpp",
],
- cflags: ["-Wall", "-Werror"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
host_supported: false,
shared_libs: [
"libvndksupport",
"libbase",
- ]
+ ],
}
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index f9f8c73..5e5e7af 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -224,7 +224,9 @@
return kInvalidOffset;
}
if (eocd->num_records == 0) {
+#if defined(__ANDROID__)
ALOGW("Zip: empty archive?");
+#endif
return kEmptyArchive;
}
diff --git a/logcat/Android.bp b/logcat/Android.bp
index afc7a01..01beb53 100644
--- a/logcat/Android.bp
+++ b/logcat/Android.bp
@@ -68,8 +68,11 @@
srcs: ["logpersist"],
init_rc: ["logcatd.rc"],
required: ["logcatd"],
- symlinks: ["logpersist.stop", "logpersist.cat"],
+ symlinks: [
+ "logpersist.stop",
+ "logpersist.cat",
+ ],
strip: {
none: true,
- }
+ },
}
diff --git a/logd/Android.bp b/logd/Android.bp
index 68b79d3..5c79976 100644
--- a/logd/Android.bp
+++ b/logd/Android.bp
@@ -25,7 +25,7 @@
"-DAUDITD_LOG_TAG=1003",
"-DCHATTY_LOG_TAG=1004",
"-DTAG_DEF_LOG_TAG=1005",
- "-DLIBLOG_LOG_TAG=1006"
+ "-DLIBLOG_LOG_TAG=1006",
]
cc_library_static {
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 560f490..b8af2f0 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -198,7 +198,7 @@
int LogBuffer::log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
pid_t tid, const char* msg, unsigned short len) {
- if ((log_id >= LOG_ID_MAX) || (log_id < 0)) {
+ if (log_id >= LOG_ID_MAX) {
return -EINVAL;
}
diff --git a/logwrapper/Android.bp b/logwrapper/Android.bp
index ccb1aa6..f163f57 100644
--- a/logwrapper/Android.bp
+++ b/logwrapper/Android.bp
@@ -49,5 +49,5 @@
],
cflags: [
"-Werror",
- ]
+ ],
}
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index f4509a4..feb100e 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -145,13 +145,21 @@
# $(1): Input source file (ld.config.txt)
# $(2): Output built module
# $(3): VNDK version suffix
+# $(4): true if libz must be included in llndk not in vndk-sp
define update_and_install_ld_config
+# If $(4) is true, move libz to llndk from vndk-sp.
+$(if $(filter true,$(4)),\
+ $(eval llndk_libraries_list := $(LLNDK_LIBRARIES) libz) \
+ $(eval vndksp_libraries_list := $(filter-out libz,$(VNDK_SAMEPROCESS_LIBRARIES))),\
+ $(eval llndk_libraries_list := $(LLNDK_LIBRARIES)) \
+ $(eval vndksp_libraries_list := $(VNDK_SAMEPROCESS_LIBRARIES)))
+
llndk_libraries := $(call normalize-path-list,$(addsuffix .so,\
- $(filter-out $(VNDK_PRIVATE_LIBRARIES),$(LLNDK_LIBRARIES))))
+ $(filter-out $(VNDK_PRIVATE_LIBRARIES),$(llndk_libraries_list))))
private_llndk_libraries := $(call normalize-path-list,$(addsuffix .so,\
- $(filter $(VNDK_PRIVATE_LIBRARIES),$(LLNDK_LIBRARIES))))
+ $(filter $(VNDK_PRIVATE_LIBRARIES),$(llndk_libraries_list))))
vndk_sameprocess_libraries := $(call normalize-path-list,$(addsuffix .so,\
- $(filter-out $(VNDK_PRIVATE_LIBRARIES),$(VNDK_SAMEPROCESS_LIBRARIES))))
+ $(filter-out $(VNDK_PRIVATE_LIBRARIES),$(vndksp_libraries_list))))
vndk_core_libraries := $(call normalize-path-list,$(addsuffix .so,\
$(filter-out $(VNDK_PRIVATE_LIBRARIES),$(VNDK_CORE_LIBRARIES))))
sanitizer_runtime_libraries := $(call normalize-path-list,$(addsuffix .so,\
@@ -180,6 +188,8 @@
$$(hide) sed -i -e 's?%SANITIZER_RUNTIME_LIBRARIES%?$$(PRIVATE_SANITIZER_RUNTIME_LIBRARIES)?g' $$@
$$(hide) sed -i -e 's?%VNDK_VER%?$$(PRIVATE_VNDK_VERSION)?g' $$@
+llndk_libraries_list :=
+vndksp_libraries_list :=
llndk_libraries :=
private_llndk_libraries :=
vndk_sameprocess_libraries :=
@@ -228,7 +238,8 @@
$(eval $(call update_and_install_ld_config,\
$(LOCAL_PATH)/etc/ld.config.vndk_lite.txt,\
$(LOCAL_BUILT_MODULE),\
- $(if $(BOARD_VNDK_VERSION),$(PLATFORM_VNDK_VERSION))))
+ $(if $(BOARD_VNDK_VERSION),$(PLATFORM_VNDK_VERSION)),\
+ true))
else
# for legacy non-treblized devices
@@ -258,7 +269,8 @@
$(eval $(call update_and_install_ld_config,\
$(LOCAL_PATH)/etc/ld.config.vndk_lite.txt,\
$(LOCAL_BUILT_MODULE),\
- $(PLATFORM_VNDK_VERSION)))
+ $(PLATFORM_VNDK_VERSION),\
+ true))
#######################################
# llndk.libraries.txt
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 6a1872f..a213ffb 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -28,12 +28,12 @@
restorecon /postinstall
# Mount cgroup mount point for cpu accounting
- mount cgroup none /acct cpuacct
+ mount cgroup none /acct nodev noexec nosuid cpuacct
mkdir /acct/uid
# root memory control cgroup, used by lmkd
mkdir /dev/memcg 0700 root system
- mount cgroup none /dev/memcg memory
+ mount cgroup none /dev/memcg nodev noexec nosuid memory
# app mem cgroups, used by activity manager, lmkd and zygote
mkdir /dev/memcg/apps/ 0755 system system
# cgroup for system_server and surfaceflinger
@@ -59,7 +59,7 @@
# Create energy-aware scheduler tuning nodes
mkdir /dev/stune
- mount cgroup none /dev/stune schedtune
+ mount cgroup none /dev/stune nodev noexec nosuid schedtune
mkdir /dev/stune/foreground
mkdir /dev/stune/background
mkdir /dev/stune/top-app
@@ -82,10 +82,10 @@
# Mount staging areas for devices managed by vold
# See storage config details at http://source.android.com/tech/storage/
- mount tmpfs tmpfs /mnt mode=0755,uid=0,gid=1000
+ mount tmpfs tmpfs /mnt nodev noexec nosuid mode=0755,uid=0,gid=1000
restorecon_recursive /mnt
- mount configfs none /config
+ mount configfs none /config nodev noexec nosuid
chmod 0775 /config/sdcardfs
chown system package_info /config/sdcardfs
@@ -155,7 +155,7 @@
# Create cgroup mount points for process groups
mkdir /dev/cpuctl
- mount cgroup none /dev/cpuctl cpu
+ mount cgroup none /dev/cpuctl nodev noexec nosuid cpu
chown system system /dev/cpuctl
chown system system /dev/cpuctl/tasks
chmod 0666 /dev/cpuctl/tasks
@@ -164,7 +164,7 @@
# sets up initial cpusets for ActivityManager
mkdir /dev/cpuset
- mount cpuset none /dev/cpuset
+ mount cpuset none /dev/cpuset nodev noexec nosuid
# this ensures that the cpusets are present and usable, but the device's
# init.rc must actually set the correct cpus
@@ -219,17 +219,17 @@
chmod 0644 /dev/xt_qtaguid
mkdir /dev/cg2_bpf
- mount cgroup2 cg2_bpf /dev/cg2_bpf
+ mount cgroup2 cg2_bpf /dev/cg2_bpf nodev noexec nosuid
chown root root /dev/cg2_bpf
chmod 0600 /dev/cg2_bpf
- mount bpf bpf /sys/fs/bpf
+ mount bpf bpf /sys/fs/bpf nodev noexec nosuid
# Create location for fs_mgr to store abbreviated output from filesystem
# checker programs.
mkdir /dev/fscklogs 0770 root system
# pstore/ramoops previous console log
- mount pstore pstore /sys/fs/pstore
+ mount pstore pstore /sys/fs/pstore nodev noexec nosuid
chown system log /sys/fs/pstore/console-ramoops
chmod 0440 /sys/fs/pstore/console-ramoops
chown system log /sys/fs/pstore/console-ramoops-0
@@ -318,8 +318,9 @@
start hwservicemanager
start vndservicemanager
- # once everything is setup, no need to modify /
- mount rootfs rootfs / ro remount
+ # Once everything is setup, no need to modify /.
+ # The bind+ro combination avoids modifying any other mount flags.
+ mount rootfs rootfs / remount bind ro
# Mount shared so changes propagate into child namespaces
mount rootfs rootfs / shared rec
# Mount default storage into root namespace
diff --git a/trusty/keymaster/Android.bp b/trusty/keymaster/Android.bp
index 322a63d..5428e73 100644
--- a/trusty/keymaster/Android.bp
+++ b/trusty/keymaster/Android.bp
@@ -31,7 +31,10 @@
"trusty_keymaster_ipc.cpp",
"trusty_keymaster_main.cpp",
],
- cflags: ["-Wall", "-Werror"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
shared_libs: [
"libcrypto",
"libcutils",
diff --git a/trusty/libtrusty/Android.bp b/trusty/libtrusty/Android.bp
index c48deed..f6e9bee 100644
--- a/trusty/libtrusty/Android.bp
+++ b/trusty/libtrusty/Android.bp
@@ -22,7 +22,10 @@
srcs: ["trusty.c"],
export_include_dirs: ["include"],
- cflags: ["-Wall", "-Werror"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
shared_libs: ["liblog"],
}
diff --git a/trusty/libtrusty/tipc-test/Android.bp b/trusty/libtrusty/tipc-test/Android.bp
index 1e8467f..32499e3 100644
--- a/trusty/libtrusty/tipc-test/Android.bp
+++ b/trusty/libtrusty/tipc-test/Android.bp
@@ -25,5 +25,8 @@
"liblog",
],
gtest: false,
- cflags: ["-Wall", "-Werror"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
}
diff --git a/trusty/storage/lib/Android.bp b/trusty/storage/lib/Android.bp
index 4e41674..2fba17e 100644
--- a/trusty/storage/lib/Android.bp
+++ b/trusty/storage/lib/Android.bp
@@ -34,5 +34,5 @@
"-fvisibility=hidden",
"-Wall",
"-Werror",
- ]
+ ],
}
diff --git a/trusty/storage/proxy/Android.bp b/trusty/storage/proxy/Android.bp
index da8542d..b93facb 100644
--- a/trusty/storage/proxy/Android.bp
+++ b/trusty/storage/proxy/Android.bp
@@ -36,5 +36,5 @@
cflags: [
"-Wall",
"-Werror",
- ]
+ ],
}
diff --git a/usbd/Android.bp b/usbd/Android.bp
index 4f9338f..3afa7a9 100644
--- a/usbd/Android.bp
+++ b/usbd/Android.bp
@@ -13,4 +13,3 @@
"libcutils",
],
}
-