Merge "Add APEX namespaces in ld.config.legacy.txt."
diff --git a/adb/Android.bp b/adb/Android.bp
index 36bfad4..8199fff 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -22,35 +22,16 @@
"-Wexit-time-destructors",
"-Wno-unused-parameter",
"-Wno-missing-field-initializers",
+ "-Wthread-safety",
"-Wvla",
+ "-DADB_HOST=1", // overridden by adbd_defaults
],
cpp_std: "experimental",
use_version_lib: true,
-
compile_multilib: "first",
- product_variables: {
- debuggable: {
- cflags: [
- "-DALLOW_ADBD_ROOT",
- "-DALLOW_ADBD_DISABLE_VERITY",
- "-DALLOW_ADBD_NO_AUTH",
- ],
- },
- },
target: {
- android: {
- cflags: [
- "-DADB_HOST=0",
- "-Wthread-safety",
- ],
- },
-
- host: {
- cflags: ["-DADB_HOST=1"],
- },
-
darwin: {
host_ldlibs: [
"-lpthread",
@@ -76,6 +57,9 @@
// MinGW hides some things behind _POSIX_SOURCE.
"-D_POSIX_SOURCE",
+
+ // Not supported yet.
+ "-Wno-thread-safety",
],
host_ldlibs: [
@@ -84,15 +68,46 @@
"-luserenv",
],
},
+ },
+}
- not_windows: {
+cc_defaults {
+ name: "adbd_defaults",
+ defaults: ["adb_defaults"],
+
+ cflags: ["-UADB_HOST", "-DADB_HOST=0"],
+ product_variables: {
+ debuggable: {
cflags: [
- "-Wthread-safety",
+ "-DALLOW_ADBD_ROOT",
+ "-DALLOW_ADBD_DISABLE_VERITY",
+ "-DALLOW_ADBD_NO_AUTH",
],
},
},
}
+cc_defaults {
+ name: "host_adbd_supported",
+
+ host_supported: true,
+ target: {
+ linux: {
+ enabled: true,
+ host_ldlibs: [
+ "-lresolv", // b64_pton
+ "-lutil", // forkpty
+ ],
+ },
+ darwin: {
+ enabled: false,
+ },
+ windows: {
+ enabled: false,
+ },
+ },
+}
+
// libadb
// =========================================================
// These files are compiled for both the host and the device.
@@ -313,7 +328,7 @@
// libadbd_core contains the common sources to build libadbd and libadbd_services.
cc_library_static {
name: "libadbd_core",
- defaults: ["adb_defaults"],
+ defaults: ["adbd_defaults", "host_adbd_supported"],
recovery_available: true,
// libminadbd wants both, as it's used to build native tests.
@@ -322,9 +337,6 @@
srcs: libadb_srcs + libadb_posix_srcs + [
"daemon/auth.cpp",
"daemon/jdwp_service.cpp",
- "daemon/usb.cpp",
- "daemon/usb_ffs.cpp",
- "daemon/usb_legacy.cpp",
],
local_include_dirs: [
@@ -335,7 +347,6 @@
static_libs: [
"libdiagnose_usb",
- "libqemu_pipe",
],
shared_libs: [
@@ -346,22 +357,36 @@
"libcutils",
"liblog",
],
+
+ target: {
+ android: {
+ whole_static_libs: [
+ "libqemu_pipe",
+ ],
+ srcs: [
+ "daemon/transport_qemu.cpp",
+ "daemon/usb.cpp",
+ "daemon/usb_ffs.cpp",
+ "daemon/usb_legacy.cpp",
+ ]
+ },
+ linux_glibc: {
+ srcs: [
+ "daemon/usb_dummy.cpp",
+ ]
+ }
+ },
}
cc_library {
name: "libadbd_services",
- defaults: ["adb_defaults"],
+ defaults: ["adbd_defaults", "host_adbd_supported"],
recovery_available: true,
compile_multilib: "both",
srcs: [
- "daemon/abb_service.cpp",
"daemon/file_sync_service.cpp",
- "daemon/framebuffer_service.cpp",
- "daemon/mdns.cpp",
- "daemon/remount_service.cpp",
"daemon/services.cpp",
- "daemon/set_verity_enable_state_service.cpp",
"daemon/shell_service.cpp",
"shell_service_protocol.cpp",
],
@@ -373,27 +398,41 @@
static_libs: [
"libadbd_core",
- "libavb_user",
"libdiagnose_usb",
- "libqemu_pipe",
],
shared_libs: [
"libasyncio",
"libbase",
- "libbootloader_message",
"libcrypto",
"libcrypto_utils",
"libcutils",
- "libext4_utils",
- "libfec",
- "libfs_mgr",
"liblog",
- "libmdnssd",
- "libselinux",
],
target: {
+ android: {
+ srcs: [
+ "daemon/abb_service.cpp",
+ "daemon/framebuffer_service.cpp",
+ "daemon/mdns.cpp",
+ "daemon/reboot_service.cpp",
+ "daemon/remount_service.cpp",
+ "daemon/restart_service.cpp",
+ "daemon/set_verity_enable_state_service.cpp",
+ ],
+ static_libs: [
+ "libavb_user",
+ ],
+ shared_libs: [
+ "libbootloader_message",
+ "libmdnssd",
+ "libext4_utils",
+ "libfec",
+ "libfs_mgr",
+ "libselinux",
+ ],
+ },
recovery: {
exclude_srcs: [
"daemon/abb_service.cpp",
@@ -404,7 +443,7 @@
cc_library {
name: "libadbd",
- defaults: ["adb_defaults"],
+ defaults: ["adbd_defaults", "host_adbd_supported"],
recovery_available: true,
// Avoid getting duplicate symbol of android::build::GetBuildNumber().
@@ -435,7 +474,7 @@
cc_binary {
name: "adbd",
- defaults: ["adb_defaults"],
+ defaults: ["adbd_defaults", "host_adbd_supported"],
recovery_available: true,
srcs: [
@@ -467,7 +506,7 @@
cc_binary {
name: "abb",
- defaults: ["adb_defaults"],
+ defaults: ["adbd_defaults"],
recovery_available: false,
srcs: [
@@ -500,7 +539,7 @@
cc_test {
name: "adbd_test",
- defaults: ["adb_defaults"],
+ defaults: ["adbd_defaults"],
srcs: libadb_test_srcs + [
"daemon/services.cpp",
"daemon/shell_service.cpp",
diff --git a/adb/adb_trace.cpp b/adb/adb_trace.cpp
index 2bd6a3e..80f146c 100644
--- a/adb/adb_trace.cpp
+++ b/adb/adb_trace.cpp
@@ -32,7 +32,9 @@
#if !ADB_HOST
const char* adb_device_banner = "device";
+#if defined(__ANDROID__)
static android::base::LogdLogger gLogdLogger;
+#endif
#else
const char* adb_device_banner = "host";
#endif
@@ -46,7 +48,7 @@
fflush(stderr);
#endif
-#if !ADB_HOST
+#if !ADB_HOST && defined(__ANDROID__)
// Only print logs of INFO or higher to logcat, so that `adb logcat` with adbd tracing on
// doesn't result in exponential logging.
if (severity >= android::base::INFO) {
diff --git a/adb/daemon/auth.cpp b/adb/daemon/auth.cpp
index 180df8f..1800f84 100644
--- a/adb/daemon/auth.cpp
+++ b/adb/daemon/auth.cpp
@@ -67,7 +67,7 @@
// b64_pton requires one additional byte in the target buffer for
// decoding to succeed. See http://b/28035006 for details.
uint8_t keybuf[ANDROID_PUBKEY_ENCODED_SIZE + 1];
- if (__b64_pton(line.c_str(), keybuf, sizeof(keybuf)) != ANDROID_PUBKEY_ENCODED_SIZE) {
+ if (b64_pton(line.c_str(), keybuf, sizeof(keybuf)) != ANDROID_PUBKEY_ENCODED_SIZE) {
LOG(ERROR) << "Invalid base64 key " << line.c_str() << " in " << path;
continue;
}
diff --git a/adb/daemon/file_sync_service.cpp b/adb/daemon/file_sync_service.cpp
index d55096a..62c18c5 100644
--- a/adb/daemon/file_sync_service.cpp
+++ b/adb/daemon/file_sync_service.cpp
@@ -22,13 +22,11 @@
#include <dirent.h>
#include <errno.h>
-#include <linux/xattr.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <sys/xattr.h>
#include <unistd.h>
#include <utime.h>
@@ -37,11 +35,17 @@
#include <vector>
#include <android-base/file.h>
+#include <android-base/macros.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
+
#include <private/android_filesystem_config.h>
#include <private/android_logger.h>
+
+#if defined(__ANDROID__)
#include <selinux/android.h>
+#include <sys/xattr.h>
+#endif
#include "adb.h"
#include "adb_io.h"
@@ -55,11 +59,17 @@
using android::base::StringPrintf;
static bool should_use_fs_config(const std::string& path) {
+#if defined(__ANDROID__)
// TODO: use fs_config to configure permissions on /data too.
return !android::base::StartsWith(path, "/data/");
+#else
+ UNUSED(path);
+ return false;
+#endif
}
static bool update_capabilities(const char* path, uint64_t capabilities) {
+#if defined(__ANDROID__)
if (capabilities == 0) {
// Ensure we clean up in case the capabilities weren't 0 in the past.
removexattr(path, XATTR_NAME_CAPS);
@@ -73,6 +83,10 @@
cap_data.data[1].permitted = (capabilities >> 32);
cap_data.data[1].inheritable = 0;
return setxattr(path, XATTR_NAME_CAPS, &cap_data, sizeof(cap_data), 0) != -1;
+#else
+ UNUSED(path, capabilities);
+ return true;
+#endif
}
static bool secure_mkdirs(const std::string& path) {
@@ -105,8 +119,10 @@
} else {
if (chown(partial_path.c_str(), uid, gid) == -1) return false;
+#if defined(__ANDROID__)
// Not all filesystems support setting SELinux labels. http://b/23530370.
selinux_android_restorecon(partial_path.c_str(), 0);
+#endif
if (!update_capabilities(partial_path.c_str(), capabilities)) return false;
}
@@ -242,8 +258,10 @@
goto fail;
}
+#if defined(__ANDROID__)
// Not all filesystems support setting SELinux labels. http://b/23530370.
selinux_android_restorecon(path, 0);
+#endif
// fchown clears the setuid bit - restore it if present.
// Ignore the result of calling fchmod. It's not supported
diff --git a/adb/daemon/framebuffer_service.h b/adb/daemon/framebuffer_service.h
index 264da59..bab44be 100644
--- a/adb/daemon/framebuffer_service.h
+++ b/adb/daemon/framebuffer_service.h
@@ -18,4 +18,6 @@
#include "adb_unique_fd.h"
+#if defined(__ANDROID__)
void framebuffer_service(unique_fd fd);
+#endif
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index f6f1acc..fce3a4f 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -18,7 +18,10 @@
#include "sysdeps.h"
+#if defined(__BIONIC__)
#include <android/fdsan.h>
+#endif
+
#include <errno.h>
#include <getopt.h>
#include <malloc.h>
@@ -34,12 +37,15 @@
#include <android-base/macros.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
+
+#if defined(__ANDROID__)
#include <libminijail.h>
#include <log/log_properties.h>
#include <scoped_minijail.h>
#include <private/android_filesystem_config.h>
#include "selinux/android.h"
+#endif
#include "adb.h"
#include "adb_auth.h"
@@ -49,6 +55,7 @@
#include "mdns.h"
+#if defined(__ANDROID__)
static const char* root_seclabel = nullptr;
static bool should_drop_capabilities_bounding_set() {
@@ -167,10 +174,14 @@
}
}
}
+#endif
static void setup_port(int port) {
+ LOG(INFO) << "adbd listening on port " << port;
local_init(port);
+#if defined(__ANDROID__)
setup_mdns(port);
+#endif
}
int adbd_main(int server_port) {
@@ -178,10 +189,12 @@
signal(SIGPIPE, SIG_IGN);
+#if defined(__BIONIC__)
auto fdsan_level = android_fdsan_get_error_level();
if (fdsan_level == ANDROID_FDSAN_ERROR_LEVEL_DISABLED) {
android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE);
}
+#endif
init_transport_registration();
@@ -206,14 +219,19 @@
" unchanged.\n");
}
+#if defined(__ANDROID__)
drop_privileges(server_port);
+#endif
bool is_usb = false;
+
+#if defined(__ANDROID__)
if (access(USB_FFS_ADB_EP0, F_OK) == 0) {
// Listen on USB.
usb_init();
is_usb = true;
}
+#endif
// If one of these properties is set, also listen on that port.
// If one of the properties isn't set and we couldn't listen on usb, listen
@@ -244,8 +262,10 @@
}
int main(int argc, char** argv) {
+#if defined(__BIONIC__)
// Set M_DECAY_TIME so that our allocations aren't immediately purged on free.
mallopt(M_DECAY_TIME, 1);
+#endif
while (true) {
static struct option opts[] = {
@@ -261,19 +281,21 @@
}
switch (c) {
- case 's':
- root_seclabel = optarg;
- break;
- case 'b':
- adb_device_banner = optarg;
- break;
- case 'v':
- printf("Android Debug Bridge Daemon version %d.%d.%d\n", ADB_VERSION_MAJOR,
- ADB_VERSION_MINOR, ADB_SERVER_VERSION);
- return 0;
- default:
- // getopt already prints "adbd: invalid option -- %c" for us.
- return 1;
+#if defined(__ANDROID__)
+ case 's':
+ root_seclabel = optarg;
+ break;
+#endif
+ case 'b':
+ adb_device_banner = optarg;
+ break;
+ case 'v':
+ printf("Android Debug Bridge Daemon version %d.%d.%d\n", ADB_VERSION_MAJOR,
+ ADB_VERSION_MINOR, ADB_SERVER_VERSION);
+ return 0;
+ default:
+ // getopt already prints "adbd: invalid option -- %c" for us.
+ return 1;
}
}
diff --git a/adb/daemon/reboot_service.cpp b/adb/daemon/reboot_service.cpp
new file mode 100644
index 0000000..a5a11b8
--- /dev/null
+++ b/adb/daemon/reboot_service.cpp
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+#define TRACE_TAG SERVICES
+
+#include "sysdeps.h"
+
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <string>
+
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
+#include <bootloader_message/bootloader_message.h>
+#include <cutils/android_reboot.h>
+
+#include "adb_io.h"
+#include "adb_unique_fd.h"
+
+void reboot_service(unique_fd fd, const std::string& arg) {
+ std::string reboot_arg = arg;
+ sync();
+
+ if (reboot_arg.empty()) reboot_arg = "adb";
+ std::string reboot_string = android::base::StringPrintf("reboot,%s", reboot_arg.c_str());
+
+ if (reboot_arg == "fastboot" &&
+ android::base::GetBoolProperty("ro.boot.dynamic_partitions", false) &&
+ access("/dev/socket/recovery", F_OK) == 0) {
+ LOG(INFO) << "Recovery specific reboot fastboot";
+ /*
+ * The socket is created to allow switching between recovery and
+ * fastboot.
+ */
+ android::base::unique_fd sock(socket(AF_UNIX, SOCK_STREAM, 0));
+ if (sock < 0) {
+ WriteFdFmt(fd, "reboot (%s) create\n", strerror(errno));
+ PLOG(ERROR) << "Creating recovery socket failed";
+ return;
+ }
+
+ sockaddr_un addr = {.sun_family = AF_UNIX};
+ strncpy(addr.sun_path, "/dev/socket/recovery", sizeof(addr.sun_path) - 1);
+ if (connect(sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == -1) {
+ WriteFdFmt(fd, "reboot (%s) connect\n", strerror(errno));
+ PLOG(ERROR) << "Couldn't connect to recovery socket";
+ return;
+ }
+ const char msg_switch_to_fastboot = 'f';
+ auto ret = adb_write(sock, &msg_switch_to_fastboot, sizeof(msg_switch_to_fastboot));
+ if (ret != sizeof(msg_switch_to_fastboot)) {
+ WriteFdFmt(fd, "reboot (%s) write\n", strerror(errno));
+ PLOG(ERROR) << "Couldn't write message to recovery socket to switch to fastboot";
+ return;
+ }
+ } else {
+ if (!android::base::SetProperty(ANDROID_RB_PROPERTY, reboot_string)) {
+ WriteFdFmt(fd.get(), "reboot (%s) failed\n", reboot_string.c_str());
+ return;
+ }
+ }
+ // Don't return early. Give the reboot command time to take effect
+ // to avoid messing up scripts which do "adb reboot && adb wait-for-device"
+ while (true) {
+ pause();
+ }
+}
diff --git a/adb/daemon/reboot_service.h b/adb/daemon/reboot_service.h
new file mode 100644
index 0000000..f68913e
--- /dev/null
+++ b/adb/daemon/reboot_service.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+
+#include "adb_unique_fd.h"
+
+#if defined(__ANDROID__)
+void reboot_service(unique_fd fd, const std::string& arg);
+#endif
diff --git a/adb/daemon/remount_service.h b/adb/daemon/remount_service.h
index e4e2550..c847403 100644
--- a/adb/daemon/remount_service.h
+++ b/adb/daemon/remount_service.h
@@ -20,5 +20,7 @@
#include "adb_unique_fd.h"
+#if defined(__ANDROID__)
bool make_block_device_writable(const std::string&);
void remount_service(unique_fd, const std::string&);
+#endif
diff --git a/adb/daemon/restart_service.cpp b/adb/daemon/restart_service.cpp
new file mode 100644
index 0000000..6803d93
--- /dev/null
+++ b/adb/daemon/restart_service.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define TRACE_TAG SERVICES
+
+#include "sysdeps.h"
+
+#include <unistd.h>
+
+#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
+#include <log/log_properties.h>
+
+#include "adb_io.h"
+#include "adb_unique_fd.h"
+
+void restart_root_service(unique_fd fd) {
+ if (getuid() == 0) {
+ WriteFdExactly(fd.get(), "adbd is already running as root\n");
+ return;
+ }
+ if (!__android_log_is_debuggable()) {
+ WriteFdExactly(fd.get(), "adbd cannot run as root in production builds\n");
+ return;
+ }
+
+ android::base::SetProperty("service.adb.root", "1");
+ WriteFdExactly(fd.get(), "restarting adbd as root\n");
+}
+
+void restart_unroot_service(unique_fd fd) {
+ if (getuid() != 0) {
+ WriteFdExactly(fd.get(), "adbd not running as root\n");
+ return;
+ }
+ android::base::SetProperty("service.adb.root", "0");
+ WriteFdExactly(fd.get(), "restarting adbd as non root\n");
+}
+
+void restart_tcp_service(unique_fd fd, int port) {
+ if (port <= 0) {
+ WriteFdFmt(fd.get(), "invalid port %d\n", port);
+ return;
+ }
+
+ android::base::SetProperty("service.adb.tcp.port", android::base::StringPrintf("%d", port));
+ WriteFdFmt(fd.get(), "restarting in TCP mode port: %d\n", port);
+}
+
+void restart_usb_service(unique_fd fd) {
+ android::base::SetProperty("service.adb.tcp.port", "0");
+ WriteFdExactly(fd.get(), "restarting in USB mode\n");
+}
diff --git a/adb/daemon/restart_service.h b/adb/daemon/restart_service.h
new file mode 100644
index 0000000..19840bd
--- /dev/null
+++ b/adb/daemon/restart_service.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "adb_unique_fd.h"
+
+#if defined(__ANDROID__)
+void restart_root_service(unique_fd fd);
+void restart_unroot_service(unique_fd fd);
+void restart_tcp_service(unique_fd fd, int port);
+void restart_usb_service(unique_fd fd);
+#endif
diff --git a/adb/daemon/services.cpp b/adb/daemon/services.cpp
index 5ae210f..d1f0345 100644
--- a/adb/daemon/services.cpp
+++ b/adb/daemon/services.cpp
@@ -39,8 +39,6 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
-#include <bootloader_message/bootloader_message.h>
-#include <cutils/android_reboot.h>
#include <cutils/sockets.h>
#include <log/log_properties.h>
@@ -55,96 +53,12 @@
#include "daemon/file_sync_service.h"
#include "daemon/framebuffer_service.h"
+#include "daemon/reboot_service.h"
#include "daemon/remount_service.h"
+#include "daemon/restart_service.h"
#include "daemon/set_verity_enable_state_service.h"
#include "daemon/shell_service.h"
-void restart_root_service(unique_fd fd) {
- if (getuid() == 0) {
- WriteFdExactly(fd.get(), "adbd is already running as root\n");
- return;
- }
- if (!__android_log_is_debuggable()) {
- WriteFdExactly(fd.get(), "adbd cannot run as root in production builds\n");
- return;
- }
-
- android::base::SetProperty("service.adb.root", "1");
- WriteFdExactly(fd.get(), "restarting adbd as root\n");
-}
-
-void restart_unroot_service(unique_fd fd) {
- if (getuid() != 0) {
- WriteFdExactly(fd.get(), "adbd not running as root\n");
- return;
- }
- android::base::SetProperty("service.adb.root", "0");
- WriteFdExactly(fd.get(), "restarting adbd as non root\n");
-}
-
-void restart_tcp_service(unique_fd fd, int port) {
- if (port <= 0) {
- WriteFdFmt(fd.get(), "invalid port %d\n", port);
- return;
- }
-
- android::base::SetProperty("service.adb.tcp.port", android::base::StringPrintf("%d", port));
- WriteFdFmt(fd.get(), "restarting in TCP mode port: %d\n", port);
-}
-
-void restart_usb_service(unique_fd fd) {
- android::base::SetProperty("service.adb.tcp.port", "0");
- WriteFdExactly(fd.get(), "restarting in USB mode\n");
-}
-
-void reboot_service(unique_fd fd, const std::string& arg) {
- std::string reboot_arg = arg;
- sync();
-
- if (reboot_arg.empty()) reboot_arg = "adb";
- std::string reboot_string = android::base::StringPrintf("reboot,%s", reboot_arg.c_str());
-
- if (reboot_arg == "fastboot" &&
- android::base::GetBoolProperty("ro.boot.dynamic_partitions", false) &&
- access("/dev/socket/recovery", F_OK) == 0) {
- LOG(INFO) << "Recovery specific reboot fastboot";
- /*
- * The socket is created to allow switching between recovery and
- * fastboot.
- */
- android::base::unique_fd sock(socket(AF_UNIX, SOCK_STREAM, 0));
- if (sock < 0) {
- WriteFdFmt(fd, "reboot (%s) create\n", strerror(errno));
- PLOG(ERROR) << "Creating recovery socket failed";
- return;
- }
-
- sockaddr_un addr = {.sun_family = AF_UNIX};
- strncpy(addr.sun_path, "/dev/socket/recovery", sizeof(addr.sun_path) - 1);
- if (connect(sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) == -1) {
- WriteFdFmt(fd, "reboot (%s) connect\n", strerror(errno));
- PLOG(ERROR) << "Couldn't connect to recovery socket";
- return;
- }
- const char msg_switch_to_fastboot = 'f';
- auto ret = adb_write(sock, &msg_switch_to_fastboot, sizeof(msg_switch_to_fastboot));
- if (ret != sizeof(msg_switch_to_fastboot)) {
- WriteFdFmt(fd, "reboot (%s) write\n", strerror(errno));
- PLOG(ERROR) << "Couldn't write message to recovery socket to switch to fastboot";
- return;
- }
- } else {
- if (!android::base::SetProperty(ANDROID_RB_PROPERTY, reboot_string)) {
- WriteFdFmt(fd.get(), "reboot (%s) failed\n", reboot_string.c_str());
- return;
- }
- }
- // Don't return early. Give the reboot command time to take effect
- // to avoid messing up scripts which do "adb reboot && adb wait-for-device"
- while (true) {
- pause();
- }
-}
void reconnect_service(unique_fd fd, atransport* t) {
WriteFdExactly(fd.get(), "done");
@@ -221,7 +135,8 @@
}
fdevent_run_on_main_thread([fd = pipe_read.release()]() {
- fdevent* fde = fdevent_create(fd, [](int, unsigned, void*) {}, nullptr);
+ fdevent* fde = fdevent_create(
+ fd, [](int, unsigned, void*) {}, nullptr);
fdevent_add(fde, FDE_READ);
});
@@ -328,31 +243,16 @@
}
unique_fd daemon_service_to_fd(std::string_view name, atransport* transport) {
-#ifndef __ANDROID_RECOVERY__
+#if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__)
if (name.starts_with("abb:")) {
name.remove_prefix(strlen("abb:"));
return execute_binder_command(name);
}
#endif
- if (name.starts_with("dev:")) {
- name.remove_prefix(strlen("dev:"));
- return unique_fd{unix_open(name, O_RDWR | O_CLOEXEC)};
- } else if (name.starts_with("framebuffer:")) {
+#if defined(__ANDROID__)
+ if (name.starts_with("framebuffer:")) {
return create_service_thread("fb", framebuffer_service);
- } else if (name.starts_with("jdwp:")) {
- name.remove_prefix(strlen("jdwp:"));
- std::string str(name);
- return create_jdwp_connection_fd(atoi(str.c_str()));
- } else if (name.starts_with("shell")) {
- name.remove_prefix(strlen("shell"));
- return ShellService(name, transport);
- } else if (name.starts_with("exec:")) {
- name.remove_prefix(strlen("exec:"));
- return StartSubprocess(std::string(name), nullptr, SubprocessType::kRaw,
- SubprocessProtocol::kNone);
- } else if (name.starts_with("sync:")) {
- return create_service_thread("sync", file_sync_service);
} else if (name.starts_with("remount:")) {
std::string arg(name.begin() + strlen("remount:"), name.end());
return create_service_thread("remount",
@@ -373,6 +273,12 @@
} else if (name.starts_with("restore:")) {
return StartSubprocess("/system/bin/bu restore", nullptr, SubprocessType::kRaw,
SubprocessProtocol::kNone);
+ } else if (name.starts_with("disable-verity:")) {
+ return create_service_thread("verity-on", std::bind(set_verity_enabled_state_service,
+ std::placeholders::_1, false));
+ } else if (name.starts_with("enable-verity:")) {
+ return create_service_thread("verity-off", std::bind(set_verity_enabled_state_service,
+ std::placeholders::_1, true));
} else if (name.starts_with("tcpip:")) {
name.remove_prefix(strlen("tcpip:"));
std::string str(name);
@@ -385,15 +291,28 @@
std::bind(restart_tcp_service, std::placeholders::_1, port));
} else if (name.starts_with("usb:")) {
return create_service_thread("usb", restart_usb_service);
+ }
+#endif
+
+ if (name.starts_with("dev:")) {
+ name.remove_prefix(strlen("dev:"));
+ return unique_fd{unix_open(name, O_RDWR | O_CLOEXEC)};
+ } else if (name.starts_with("jdwp:")) {
+ name.remove_prefix(strlen("jdwp:"));
+ std::string str(name);
+ return create_jdwp_connection_fd(atoi(str.c_str()));
+ } else if (name.starts_with("shell")) {
+ name.remove_prefix(strlen("shell"));
+ return ShellService(name, transport);
+ } else if (name.starts_with("exec:")) {
+ name.remove_prefix(strlen("exec:"));
+ return StartSubprocess(std::string(name), nullptr, SubprocessType::kRaw,
+ SubprocessProtocol::kNone);
+ } else if (name.starts_with("sync:")) {
+ return create_service_thread("sync", file_sync_service);
} else if (name.starts_with("reverse:")) {
name.remove_prefix(strlen("reverse:"));
return reverse_service(name, transport);
- } else if (name.starts_with("disable-verity:")) {
- return create_service_thread("verity-on", std::bind(set_verity_enabled_state_service,
- std::placeholders::_1, false));
- } else if (name.starts_with("enable-verity:")) {
- return create_service_thread("verity-off", std::bind(set_verity_enabled_state_service,
- std::placeholders::_1, true));
} else if (name == "reconnect") {
return create_service_thread(
"reconnect", std::bind(reconnect_service, std::placeholders::_1, transport));
diff --git a/adb/daemon/set_verity_enable_state_service.h b/adb/daemon/set_verity_enable_state_service.h
index c1413c8..c0ed98e 100644
--- a/adb/daemon/set_verity_enable_state_service.h
+++ b/adb/daemon/set_verity_enable_state_service.h
@@ -18,4 +18,6 @@
#include "adb_unique_fd.h"
+#if defined(__ANDROID__)
void set_verity_enabled_state_service(unique_fd fd, bool enable);
+#endif
diff --git a/adb/daemon/shell_service.cpp b/adb/daemon/shell_service.cpp
index 455595f..0794bcd 100644
--- a/adb/daemon/shell_service.cpp
+++ b/adb/daemon/shell_service.cpp
@@ -98,7 +98,10 @@
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <private/android_logger.h>
+
+#if defined(__ANDROID__)
#include <selinux/android.h>
+#endif
#include "adb.h"
#include "adb_io.h"
diff --git a/adb/daemon/transport_qemu.cpp b/adb/daemon/transport_qemu.cpp
new file mode 100644
index 0000000..8ad2572
--- /dev/null
+++ b/adb/daemon/transport_qemu.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Include qemu_pipe.h before sysdeps, since it has inlined references to open, read, write.
+#include <qemu_pipe.h>
+
+#define TRACE_TAG TRANSPORT
+#include "sysdeps.h"
+#include "transport.h"
+
+#include <android-base/properties.h>
+
+#include "adb_io.h"
+#include "adb_trace.h"
+#include "adb_unique_fd.h"
+
+/* A worker thread that monitors host connections, and registers a transport for
+ * every new host connection. This thread replaces server_socket_thread on
+ * condition that adbd daemon runs inside the emulator, and emulator uses QEMUD
+ * pipe to communicate with adbd daemon inside the guest. This is done in order
+ * to provide more robust communication channel between ADB host and guest. The
+ * main issue with server_socket_thread approach is that it runs on top of TCP,
+ * and thus is sensitive to network disruptions. For instance, the
+ * ConnectionManager may decide to reset all network connections, in which case
+ * the connection between ADB host and guest will be lost. To make ADB traffic
+ * independent from the network, we use here 'adb' QEMUD service to transfer data
+ * between the host, and the guest. See external/qemu/android/adb-*.* that
+ * implements the emulator's side of the protocol. Another advantage of using
+ * QEMUD approach is that ADB will be up much sooner, since it doesn't depend
+ * anymore on network being set up.
+ * The guest side of the protocol contains the following phases:
+ * - Connect with adb QEMUD service. In this phase a handle to 'adb' QEMUD service
+ * is opened, and it becomes clear whether or not emulator supports that
+ * protocol.
+ * - Wait for the ADB host to create connection with the guest. This is done by
+ * sending an 'accept' request to the adb QEMUD service, and waiting on
+ * response.
+ * - When new ADB host connection is accepted, the connection with adb QEMUD
+ * service is registered as the transport, and a 'start' request is sent to the
+ * adb QEMUD service, indicating that the guest is ready to receive messages.
+ * Note that the guest will ignore messages sent down from the emulator before
+ * the transport registration is completed. That's why we need to send the
+ * 'start' request after the transport is registered.
+ */
+void qemu_socket_thread(int port) {
+ /* 'accept' request to the adb QEMUD service. */
+ static const char _accept_req[] = "accept";
+ /* 'start' request to the adb QEMUD service. */
+ static const char _start_req[] = "start";
+ /* 'ok' reply from the adb QEMUD service. */
+ static const char _ok_resp[] = "ok";
+
+ char tmp[256];
+ char con_name[32];
+
+ adb_thread_setname("qemu socket");
+ D("transport: qemu_socket_thread() starting");
+
+ /* adb QEMUD service connection request. */
+ snprintf(con_name, sizeof(con_name), "pipe:qemud:adb:%d", port);
+
+ /* Connect to the adb QEMUD service. */
+ unique_fd fd(qemu_pipe_open(con_name));
+ if (fd < 0) {
+ /* This could be an older version of the emulator, that doesn't
+ * implement adb QEMUD service. Fall back to the old TCP way. */
+ D("adb service is not available. Falling back to TCP socket.");
+ std::thread(server_socket_thread, port).detach();
+ return;
+ }
+
+ while (true) {
+ /*
+ * Wait till the host creates a new connection.
+ */
+
+ /* Send the 'accept' request. */
+ if (WriteFdExactly(fd.get(), _accept_req, strlen(_accept_req))) {
+ /* Wait for the response. In the response we expect 'ok' on success,
+ * or 'ko' on failure. */
+ if (!ReadFdExactly(fd.get(), tmp, 2) || memcmp(tmp, _ok_resp, 2)) {
+ D("Accepting ADB host connection has failed.");
+ } else {
+ /* Host is connected. Register the transport, and start the
+ * exchange. */
+ std::string serial = android::base::StringPrintf("host-%d", fd.get());
+ WriteFdExactly(fd.get(), _start_req, strlen(_start_req));
+ register_socket_transport(std::move(fd), std::move(serial), port, 1,
+ [](atransport*) { return ReconnectResult::Abort; });
+ }
+
+ /* Prepare for accepting of the next ADB host connection. */
+ fd.reset(qemu_pipe_open(con_name));
+ if (fd < 0) {
+ D("adb service become unavailable.");
+ return;
+ }
+ } else {
+ D("Unable to send the '%s' request to ADB service.", _accept_req);
+ return;
+ }
+ }
+ D("transport: qemu_socket_thread() exiting");
+ return;
+}
+
+// If adbd is running inside the emulator, it will normally use QEMUD pipe (aka
+// goldfish) as the transport. This can either be explicitly set by the
+// service.adb.transport property, or be inferred from ro.kernel.qemu that is
+// set to "1" for ranchu/goldfish.
+bool use_qemu_goldfish() {
+ // Legacy way to detect if adbd should use the goldfish pipe is to check for
+ // ro.kernel.qemu, keep that behaviour for backward compatibility.
+ if (android::base::GetBoolProperty("ro.kernel.qemu", false)) {
+ return true;
+ }
+ // If service.adb.transport is present and is set to "goldfish", use the
+ // QEMUD pipe.
+ if (android::base::GetProperty("service.adb.transport", "") == "goldfish") {
+ return true;
+ }
+ return false;
+}
diff --git a/adb/daemon/usb_dummy.cpp b/adb/daemon/usb_dummy.cpp
new file mode 100644
index 0000000..984bc25
--- /dev/null
+++ b/adb/daemon/usb_dummy.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <adbd/usb.h>
+
+#include <android-base/logging.h>
+
+int usb_write(usb_handle*, const void*, int) {
+ LOG(FATAL) << "unimplemented";
+ return -1;
+}
+
+int usb_read(usb_handle*, void*, int) {
+ LOG(FATAL) << "unimplemented";
+ return -1;
+}
+
+int usb_close(usb_handle*) {
+ LOG(FATAL) << "unimplemented";
+ return -1;
+}
+
+void usb_kick(usb_handle*) {
+ LOG(FATAL) << "unimplemented";
+}
diff --git a/adb/transport.h b/adb/transport.h
index 6f53e6ec..3baeb1c 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -399,4 +399,14 @@
asocket* create_device_tracker(bool long_output);
+#if !ADB_HOST
+void server_socket_thread(int port);
+
+#if defined(__ANDROID__)
+void qemu_socket_thread(int port);
+bool use_qemu_goldfish();
+#endif
+
+#endif
+
#endif /* __TRANSPORT_H */
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index b384085..8885db4 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -229,9 +229,9 @@
}
}
-#else // ADB_HOST
+#else // !ADB_HOST
-static void server_socket_thread(int port) {
+void server_socket_thread(int port) {
unique_fd serverfd;
adb_thread_setname("server socket");
@@ -263,143 +263,19 @@
D("transport: server_socket_thread() exiting");
}
-/* This is relevant only for ADB daemon running inside the emulator. */
-/*
- * Redefine open and write for qemu_pipe.h that contains inlined references
- * to those routines. We will redefine them back after qemu_pipe.h inclusion.
- */
-#undef open
-#undef read
-#undef write
-#define open adb_open
-#define read adb_read
-#define write adb_write
-#include <qemu_pipe.h>
-#undef open
-#undef read
-#undef write
-#define open ___xxx_open
-#define read ___xxx_read
-#define write ___xxx_write
+#endif
-/* A worker thread that monitors host connections, and registers a transport for
- * every new host connection. This thread replaces server_socket_thread on
- * condition that adbd daemon runs inside the emulator, and emulator uses QEMUD
- * pipe to communicate with adbd daemon inside the guest. This is done in order
- * to provide more robust communication channel between ADB host and guest. The
- * main issue with server_socket_thread approach is that it runs on top of TCP,
- * and thus is sensitive to network disruptions. For instance, the
- * ConnectionManager may decide to reset all network connections, in which case
- * the connection between ADB host and guest will be lost. To make ADB traffic
- * independent from the network, we use here 'adb' QEMUD service to transfer data
- * between the host, and the guest. See external/qemu/android/adb-*.* that
- * implements the emulator's side of the protocol. Another advantage of using
- * QEMUD approach is that ADB will be up much sooner, since it doesn't depend
- * anymore on network being set up.
- * The guest side of the protocol contains the following phases:
- * - Connect with adb QEMUD service. In this phase a handle to 'adb' QEMUD service
- * is opened, and it becomes clear whether or not emulator supports that
- * protocol.
- * - Wait for the ADB host to create connection with the guest. This is done by
- * sending an 'accept' request to the adb QEMUD service, and waiting on
- * response.
- * - When new ADB host connection is accepted, the connection with adb QEMUD
- * service is registered as the transport, and a 'start' request is sent to the
- * adb QEMUD service, indicating that the guest is ready to receive messages.
- * Note that the guest will ignore messages sent down from the emulator before
- * the transport registration is completed. That's why we need to send the
- * 'start' request after the transport is registered.
- */
-static void qemu_socket_thread(int port) {
- /* 'accept' request to the adb QEMUD service. */
- static const char _accept_req[] = "accept";
- /* 'start' request to the adb QEMUD service. */
- static const char _start_req[] = "start";
- /* 'ok' reply from the adb QEMUD service. */
- static const char _ok_resp[] = "ok";
-
- char tmp[256];
- char con_name[32];
-
- adb_thread_setname("qemu socket");
- D("transport: qemu_socket_thread() starting");
-
- /* adb QEMUD service connection request. */
- snprintf(con_name, sizeof(con_name), "pipe:qemud:adb:%d", port);
-
- /* Connect to the adb QEMUD service. */
- unique_fd fd(qemu_pipe_open(con_name));
- if (fd < 0) {
- /* This could be an older version of the emulator, that doesn't
- * implement adb QEMUD service. Fall back to the old TCP way. */
- D("adb service is not available. Falling back to TCP socket.");
- std::thread(server_socket_thread, port).detach();
- return;
- }
-
- while (true) {
- /*
- * Wait till the host creates a new connection.
- */
-
- /* Send the 'accept' request. */
- if (WriteFdExactly(fd.get(), _accept_req, strlen(_accept_req))) {
- /* Wait for the response. In the response we expect 'ok' on success,
- * or 'ko' on failure. */
- if (!ReadFdExactly(fd.get(), tmp, 2) || memcmp(tmp, _ok_resp, 2)) {
- D("Accepting ADB host connection has failed.");
- } else {
- /* Host is connected. Register the transport, and start the
- * exchange. */
- std::string serial = android::base::StringPrintf("host-%d", fd.get());
- WriteFdExactly(fd.get(), _start_req, strlen(_start_req));
- register_socket_transport(std::move(fd), std::move(serial), port, 1,
- [](atransport*) { return ReconnectResult::Abort; });
- }
-
- /* Prepare for accepting of the next ADB host connection. */
- fd.reset(qemu_pipe_open(con_name));
- if (fd < 0) {
- D("adb service become unavailable.");
- return;
- }
- } else {
- D("Unable to send the '%s' request to ADB service.", _accept_req);
- return;
- }
- }
- D("transport: qemu_socket_thread() exiting");
- return;
-}
-
-// If adbd is running inside the emulator, it will normally use QEMUD pipe (aka
-// goldfish) as the transport. This can either be explicitly set by the
-// service.adb.transport property, or be inferred from ro.kernel.qemu that is
-// set to "1" for ranchu/goldfish.
-static bool use_qemu_goldfish() {
- // Legacy way to detect if adbd should use the goldfish pipe is to check for
- // ro.kernel.qemu, keep that behaviour for backward compatibility.
- if (android::base::GetBoolProperty("ro.kernel.qemu", false)) {
- return true;
- }
- // If service.adb.transport is present and is set to "goldfish", use the
- // QEMUD pipe.
- if (android::base::GetProperty("service.adb.transport", "") == "goldfish") {
- return true;
- }
- return false;
-}
-
-#endif // !ADB_HOST
-
-void local_init(int port)
-{
+void local_init(int port) {
void (*func)(int);
const char* debug_name = "";
#if ADB_HOST
func = client_socket_thread;
debug_name = "client";
+#elif !defined(__ANDROID__)
+ // Host adbd.
+ func = server_socket_thread;
+ debug_name = "server";
#else
// For the adbd daemon in the system image we need to distinguish
// between the device, and the emulator.
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index 110d56e..c39fbe7 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -838,9 +838,10 @@
<< block_device.size << ")";
return false;
}
- if (device_info.logical_block_size != geometry_.logical_block_size) {
- LERROR << "Device logical block size does not match (got " << device_info.logical_block_size
- << ", expected " << geometry_.logical_block_size << ")";
+ if (geometry_.logical_block_size % device_info.logical_block_size) {
+ LERROR << "Device logical block size is misaligned (block size="
+ << device_info.logical_block_size << ", alignment=" << geometry_.logical_block_size
+ << ")";
return false;
}
diff --git a/fs_mgr/liblp/builder_test.cpp b/fs_mgr/liblp/builder_test.cpp
index 7d615a3..8f08169 100644
--- a/fs_mgr/liblp/builder_test.cpp
+++ b/fs_mgr/liblp/builder_test.cpp
@@ -495,6 +495,11 @@
EXPECT_EQ(new_info.size, 1024 * 1024);
new_info.logical_block_size = 512;
+ ASSERT_TRUE(builder->UpdateBlockDeviceInfo("super", new_info));
+ ASSERT_TRUE(builder->GetBlockDeviceInfo("super", &new_info));
+ EXPECT_EQ(new_info.logical_block_size, 4096);
+
+ new_info.logical_block_size = 7;
ASSERT_FALSE(builder->UpdateBlockDeviceInfo("super", new_info));
ASSERT_TRUE(builder->GetBlockDeviceInfo("super", &new_info));
EXPECT_EQ(new_info.logical_block_size, 4096);
diff --git a/init/selinux.cpp b/init/selinux.cpp
index d93e9ec..ee302c1 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -34,16 +34,18 @@
// identical to the system image shipped on a vendor's device.
// The split SEPolicy is loaded as described below:
-// 1) There is a precompiled SEPolicy located at /vendor/etc/selinux/precompiled_sepolicy.
-// Stored along with this file is the sha256 hash of the parts of the SEPolicy on /system that
-// were used to compile this precompiled policy. The system partition contains a similar sha256
-// of the parts of the SEPolicy that it currently contains. If these two hashes match, then the
-// system loads this precompiled_sepolicy directly.
-// 2) If these hashes do not match, then /system has been updated out of sync with /vendor and the
-// init needs to compile the SEPolicy. /system contains the SEPolicy compiler, secilc, and it
-// is used by the LoadSplitPolicy() function below to compile the SEPolicy to a temp directory
-// and load it. That function contains even more documentation with the specific implementation
-// details of how the SEPolicy is compiled if needed.
+// 1) There is a precompiled SEPolicy located at either /vendor/etc/selinux/precompiled_sepolicy or
+// /odm/etc/selinux/precompiled_sepolicy if odm parition is present. Stored along with this file
+// are the sha256 hashes of the parts of the SEPolicy on /system and /product that were used to
+// compile this precompiled policy. The system partition contains a similar sha256 of the parts
+// of the SEPolicy that it currently contains. Symmetrically, product paritition contains a
+// sha256 of its SEPolicy. System loads this precompiled_sepolicy directly if and only if hashes
+// for system policy match and hashes for product policy match.
+// 2) If these hashes do not match, then either /system or /product (or both) have been updated out
+// of sync with /vendor and the init needs to compile the SEPolicy. /system contains the
+// SEPolicy compiler, secilc, and it is used by the LoadSplitPolicy() function below to compile
+// the SEPolicy to a temp directory and load it. That function contains even more documentation
+// with the specific implementation details of how the SEPolicy is compiled if needed.
#include "selinux.h"
@@ -217,20 +219,35 @@
return false;
}
std::string actual_plat_id;
- if (!ReadFirstLine("/system/etc/selinux/plat_and_mapping_sepolicy.cil.sha256", &actual_plat_id)) {
+ if (!ReadFirstLine("/system/etc/selinux/plat_sepolicy_and_mapping.sha256", &actual_plat_id)) {
PLOG(INFO) << "Failed to read "
- "/system/etc/selinux/plat_and_mapping_sepolicy.cil.sha256";
+ "/system/etc/selinux/plat_sepolicy_and_mapping.sha256";
+ return false;
+ }
+ std::string actual_product_id;
+ if (!ReadFirstLine("/product/etc/selinux/product_sepolicy_and_mapping.sha256",
+ &actual_product_id)) {
+ PLOG(INFO) << "Failed to read "
+ "/product/etc/selinux/product_sepolicy_and_mapping.sha256";
return false;
}
std::string precompiled_plat_id;
- std::string precompiled_sha256 = *file + ".plat_and_mapping.sha256";
- if (!ReadFirstLine(precompiled_sha256.c_str(), &precompiled_plat_id)) {
- PLOG(INFO) << "Failed to read " << precompiled_sha256;
+ std::string precompiled_plat_sha256 = *file + ".plat_sepolicy_and_mapping.sha256";
+ if (!ReadFirstLine(precompiled_plat_sha256.c_str(), &precompiled_plat_id)) {
+ PLOG(INFO) << "Failed to read " << precompiled_plat_sha256;
file->clear();
return false;
}
- if ((actual_plat_id.empty()) || (actual_plat_id != precompiled_plat_id)) {
+ std::string precompiled_product_id;
+ std::string precompiled_product_sha256 = *file + ".product_sepolicy_and_mapping.sha256";
+ if (!ReadFirstLine(precompiled_product_sha256.c_str(), &precompiled_product_id)) {
+ PLOG(INFO) << "Failed to read " << precompiled_product_sha256;
+ file->clear();
+ return false;
+ }
+ if (actual_plat_id.empty() || actual_plat_id != precompiled_plat_id ||
+ actual_product_id.empty() || actual_product_id != precompiled_product_id) {
file->clear();
return false;
}
diff --git a/libunwindstack/DwarfOp.cpp b/libunwindstack/DwarfOp.cpp
index 5bc60b9..393eb3e 100644
--- a/libunwindstack/DwarfOp.cpp
+++ b/libunwindstack/DwarfOp.cpp
@@ -32,8 +32,1451 @@
namespace unwindstack {
+enum DwarfOpHandleFunc : uint8_t {
+ OP_ILLEGAL = 0,
+ OP_DEREF,
+ OP_DEREF_SIZE,
+ OP_PUSH,
+ OP_DUP,
+ OP_DROP,
+ OP_OVER,
+ OP_PICK,
+ OP_SWAP,
+ OP_ROT,
+ OP_ABS,
+ OP_AND,
+ OP_DIV,
+ OP_MINUS,
+ OP_MOD,
+ OP_MUL,
+ OP_NEG,
+ OP_NOT,
+ OP_OR,
+ OP_PLUS,
+ OP_PLUS_UCONST,
+ OP_SHL,
+ OP_SHR,
+ OP_SHRA,
+ OP_XOR,
+ OP_BRA,
+ OP_EQ,
+ OP_GE,
+ OP_GT,
+ OP_LE,
+ OP_LT,
+ OP_NE,
+ OP_SKIP,
+ OP_LIT,
+ OP_REG,
+ OP_REGX,
+ OP_BREG,
+ OP_BREGX,
+ OP_NOP,
+ OP_NOT_IMPLEMENTED,
+};
+
+struct OpCallback {
+ // It may seem tempting to "clean this up" by replacing "const char[26]" with
+ // "const char*", but doing so would place the entire callback table in
+ // .data.rel.ro section, instead of .rodata section, and thus increase
+ // dirty memory usage. Libunwindstack is used by the linker and therefore
+ // loaded for every running process, so every bit of memory counts.
+ // Unlike C standard, C++ standard guarantees this array is big enough to
+ // store the names, or else we would get a compilation error.
+ const char name[26];
+
+ // Similarily for this field, we do NOT want to directly store function
+ // pointers here. Not only would that cause the callback table to be placed
+ // in .data.rel.ro section, but it would be duplicated for each AddressType.
+ // Instead, we use DwarfOpHandleFunc enum to decouple the callback table from
+ // the function pointers.
+ DwarfOpHandleFunc handle_func;
+
+ uint8_t num_required_stack_values;
+ uint8_t num_operands;
+ uint8_t operands[2];
+};
+
+constexpr static OpCallback kCallbackTable[256] = {
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0x00 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0x01 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0x02 illegal op
+ {
+ // 0x03 DW_OP_addr
+ "DW_OP_addr",
+ OP_PUSH,
+ 0,
+ 1,
+ {DW_EH_PE_absptr},
+ },
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0x04 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0x05 illegal op
+ {
+ // 0x06 DW_OP_deref
+ "DW_OP_deref",
+ OP_DEREF,
+ 1,
+ 0,
+ {},
+ },
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0x07 illegal op
+ {
+ // 0x08 DW_OP_const1u
+ "DW_OP_const1u",
+ OP_PUSH,
+ 0,
+ 1,
+ {DW_EH_PE_udata1},
+ },
+ {
+ // 0x09 DW_OP_const1s
+ "DW_OP_const1s",
+ OP_PUSH,
+ 0,
+ 1,
+ {DW_EH_PE_sdata1},
+ },
+ {
+ // 0x0a DW_OP_const2u
+ "DW_OP_const2u",
+ OP_PUSH,
+ 0,
+ 1,
+ {DW_EH_PE_udata2},
+ },
+ {
+ // 0x0b DW_OP_const2s
+ "DW_OP_const2s",
+ OP_PUSH,
+ 0,
+ 1,
+ {DW_EH_PE_sdata2},
+ },
+ {
+ // 0x0c DW_OP_const4u
+ "DW_OP_const4u",
+ OP_PUSH,
+ 0,
+ 1,
+ {DW_EH_PE_udata4},
+ },
+ {
+ // 0x0d DW_OP_const4s
+ "DW_OP_const4s",
+ OP_PUSH,
+ 0,
+ 1,
+ {DW_EH_PE_sdata4},
+ },
+ {
+ // 0x0e DW_OP_const8u
+ "DW_OP_const8u",
+ OP_PUSH,
+ 0,
+ 1,
+ {DW_EH_PE_udata8},
+ },
+ {
+ // 0x0f DW_OP_const8s
+ "DW_OP_const8s",
+ OP_PUSH,
+ 0,
+ 1,
+ {DW_EH_PE_sdata8},
+ },
+ {
+ // 0x10 DW_OP_constu
+ "DW_OP_constu",
+ OP_PUSH,
+ 0,
+ 1,
+ {DW_EH_PE_uleb128},
+ },
+ {
+ // 0x11 DW_OP_consts
+ "DW_OP_consts",
+ OP_PUSH,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x12 DW_OP_dup
+ "DW_OP_dup",
+ OP_DUP,
+ 1,
+ 0,
+ {},
+ },
+ {
+ // 0x13 DW_OP_drop
+ "DW_OP_drop",
+ OP_DROP,
+ 1,
+ 0,
+ {},
+ },
+ {
+ // 0x14 DW_OP_over
+ "DW_OP_over",
+ OP_OVER,
+ 2,
+ 0,
+ {},
+ },
+ {
+ // 0x15 DW_OP_pick
+ "DW_OP_pick",
+ OP_PICK,
+ 0,
+ 1,
+ {DW_EH_PE_udata1},
+ },
+ {
+ // 0x16 DW_OP_swap
+ "DW_OP_swap",
+ OP_SWAP,
+ 2,
+ 0,
+ {},
+ },
+ {
+ // 0x17 DW_OP_rot
+ "DW_OP_rot",
+ OP_ROT,
+ 3,
+ 0,
+ {},
+ },
+ {
+ // 0x18 DW_OP_xderef
+ "DW_OP_xderef",
+ OP_NOT_IMPLEMENTED,
+ 2,
+ 0,
+ {},
+ },
+ {
+ // 0x19 DW_OP_abs
+ "DW_OP_abs",
+ OP_ABS,
+ 1,
+ 0,
+ {},
+ },
+ {
+ // 0x1a DW_OP_and
+ "DW_OP_and",
+ OP_AND,
+ 2,
+ 0,
+ {},
+ },
+ {
+ // 0x1b DW_OP_div
+ "DW_OP_div",
+ OP_DIV,
+ 2,
+ 0,
+ {},
+ },
+ {
+ // 0x1c DW_OP_minus
+ "DW_OP_minus",
+ OP_MINUS,
+ 2,
+ 0,
+ {},
+ },
+ {
+ // 0x1d DW_OP_mod
+ "DW_OP_mod",
+ OP_MOD,
+ 2,
+ 0,
+ {},
+ },
+ {
+ // 0x1e DW_OP_mul
+ "DW_OP_mul",
+ OP_MUL,
+ 2,
+ 0,
+ {},
+ },
+ {
+ // 0x1f DW_OP_neg
+ "DW_OP_neg",
+ OP_NEG,
+ 1,
+ 0,
+ {},
+ },
+ {
+ // 0x20 DW_OP_not
+ "DW_OP_not",
+ OP_NOT,
+ 1,
+ 0,
+ {},
+ },
+ {
+ // 0x21 DW_OP_or
+ "DW_OP_or",
+ OP_OR,
+ 2,
+ 0,
+ {},
+ },
+ {
+ // 0x22 DW_OP_plus
+ "DW_OP_plus",
+ OP_PLUS,
+ 2,
+ 0,
+ {},
+ },
+ {
+ // 0x23 DW_OP_plus_uconst
+ "DW_OP_plus_uconst",
+ OP_PLUS_UCONST,
+ 1,
+ 1,
+ {DW_EH_PE_uleb128},
+ },
+ {
+ // 0x24 DW_OP_shl
+ "DW_OP_shl",
+ OP_SHL,
+ 2,
+ 0,
+ {},
+ },
+ {
+ // 0x25 DW_OP_shr
+ "DW_OP_shr",
+ OP_SHR,
+ 2,
+ 0,
+ {},
+ },
+ {
+ // 0x26 DW_OP_shra
+ "DW_OP_shra",
+ OP_SHRA,
+ 2,
+ 0,
+ {},
+ },
+ {
+ // 0x27 DW_OP_xor
+ "DW_OP_xor",
+ OP_XOR,
+ 2,
+ 0,
+ {},
+ },
+ {
+ // 0x28 DW_OP_bra
+ "DW_OP_bra",
+ OP_BRA,
+ 1,
+ 1,
+ {DW_EH_PE_sdata2},
+ },
+ {
+ // 0x29 DW_OP_eq
+ "DW_OP_eq",
+ OP_EQ,
+ 2,
+ 0,
+ {},
+ },
+ {
+ // 0x2a DW_OP_ge
+ "DW_OP_ge",
+ OP_GE,
+ 2,
+ 0,
+ {},
+ },
+ {
+ // 0x2b DW_OP_gt
+ "DW_OP_gt",
+ OP_GT,
+ 2,
+ 0,
+ {},
+ },
+ {
+ // 0x2c DW_OP_le
+ "DW_OP_le",
+ OP_LE,
+ 2,
+ 0,
+ {},
+ },
+ {
+ // 0x2d DW_OP_lt
+ "DW_OP_lt",
+ OP_LT,
+ 2,
+ 0,
+ {},
+ },
+ {
+ // 0x2e DW_OP_ne
+ "DW_OP_ne",
+ OP_NE,
+ 2,
+ 0,
+ {},
+ },
+ {
+ // 0x2f DW_OP_skip
+ "DW_OP_skip",
+ OP_SKIP,
+ 0,
+ 1,
+ {DW_EH_PE_sdata2},
+ },
+ {
+ // 0x30 DW_OP_lit0
+ "DW_OP_lit0",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x31 DW_OP_lit1
+ "DW_OP_lit1",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x32 DW_OP_lit2
+ "DW_OP_lit2",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x33 DW_OP_lit3
+ "DW_OP_lit3",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x34 DW_OP_lit4
+ "DW_OP_lit4",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x35 DW_OP_lit5
+ "DW_OP_lit5",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x36 DW_OP_lit6
+ "DW_OP_lit6",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x37 DW_OP_lit7
+ "DW_OP_lit7",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x38 DW_OP_lit8
+ "DW_OP_lit8",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x39 DW_OP_lit9
+ "DW_OP_lit9",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x3a DW_OP_lit10
+ "DW_OP_lit10",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x3b DW_OP_lit11
+ "DW_OP_lit11",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x3c DW_OP_lit12
+ "DW_OP_lit12",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x3d DW_OP_lit13
+ "DW_OP_lit13",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x3e DW_OP_lit14
+ "DW_OP_lit14",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x3f DW_OP_lit15
+ "DW_OP_lit15",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x40 DW_OP_lit16
+ "DW_OP_lit16",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x41 DW_OP_lit17
+ "DW_OP_lit17",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x42 DW_OP_lit18
+ "DW_OP_lit18",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x43 DW_OP_lit19
+ "DW_OP_lit19",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x44 DW_OP_lit20
+ "DW_OP_lit20",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x45 DW_OP_lit21
+ "DW_OP_lit21",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x46 DW_OP_lit22
+ "DW_OP_lit22",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x47 DW_OP_lit23
+ "DW_OP_lit23",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x48 DW_OP_lit24
+ "DW_OP_lit24",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x49 DW_OP_lit25
+ "DW_OP_lit25",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x4a DW_OP_lit26
+ "DW_OP_lit26",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x4b DW_OP_lit27
+ "DW_OP_lit27",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x4c DW_OP_lit28
+ "DW_OP_lit28",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x4d DW_OP_lit29
+ "DW_OP_lit29",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x4e DW_OP_lit30
+ "DW_OP_lit30",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x4f DW_OP_lit31
+ "DW_OP_lit31",
+ OP_LIT,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x50 DW_OP_reg0
+ "DW_OP_reg0",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x51 DW_OP_reg1
+ "DW_OP_reg1",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x52 DW_OP_reg2
+ "DW_OP_reg2",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x53 DW_OP_reg3
+ "DW_OP_reg3",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x54 DW_OP_reg4
+ "DW_OP_reg4",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x55 DW_OP_reg5
+ "DW_OP_reg5",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x56 DW_OP_reg6
+ "DW_OP_reg6",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x57 DW_OP_reg7
+ "DW_OP_reg7",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x58 DW_OP_reg8
+ "DW_OP_reg8",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x59 DW_OP_reg9
+ "DW_OP_reg9",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x5a DW_OP_reg10
+ "DW_OP_reg10",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x5b DW_OP_reg11
+ "DW_OP_reg11",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x5c DW_OP_reg12
+ "DW_OP_reg12",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x5d DW_OP_reg13
+ "DW_OP_reg13",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x5e DW_OP_reg14
+ "DW_OP_reg14",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x5f DW_OP_reg15
+ "DW_OP_reg15",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x60 DW_OP_reg16
+ "DW_OP_reg16",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x61 DW_OP_reg17
+ "DW_OP_reg17",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x62 DW_OP_reg18
+ "DW_OP_reg18",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x63 DW_OP_reg19
+ "DW_OP_reg19",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x64 DW_OP_reg20
+ "DW_OP_reg20",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x65 DW_OP_reg21
+ "DW_OP_reg21",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x66 DW_OP_reg22
+ "DW_OP_reg22",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x67 DW_OP_reg23
+ "DW_OP_reg23",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x68 DW_OP_reg24
+ "DW_OP_reg24",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x69 DW_OP_reg25
+ "DW_OP_reg25",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x6a DW_OP_reg26
+ "DW_OP_reg26",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x6b DW_OP_reg27
+ "DW_OP_reg27",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x6c DW_OP_reg28
+ "DW_OP_reg28",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x6d DW_OP_reg29
+ "DW_OP_reg29",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x6e DW_OP_reg30
+ "DW_OP_reg30",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x6f DW_OP_reg31
+ "DW_OP_reg31",
+ OP_REG,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x70 DW_OP_breg0
+ "DW_OP_breg0",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x71 DW_OP_breg1
+ "DW_OP_breg1",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x72 DW_OP_breg2
+ "DW_OP_breg2",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x73 DW_OP_breg3
+ "DW_OP_breg3",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x74 DW_OP_breg4
+ "DW_OP_breg4",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x75 DW_OP_breg5
+ "DW_OP_breg5",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x76 DW_OP_breg6
+ "DW_OP_breg6",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x77 DW_OP_breg7
+ "DW_OP_breg7",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x78 DW_OP_breg8
+ "DW_OP_breg8",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x79 DW_OP_breg9
+ "DW_OP_breg9",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x7a DW_OP_breg10
+ "DW_OP_breg10",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x7b DW_OP_breg11
+ "DW_OP_breg11",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x7c DW_OP_breg12
+ "DW_OP_breg12",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x7d DW_OP_breg13
+ "DW_OP_breg13",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x7e DW_OP_breg14
+ "DW_OP_breg14",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x7f DW_OP_breg15
+ "DW_OP_breg15",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x80 DW_OP_breg16
+ "DW_OP_breg16",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x81 DW_OP_breg17
+ "DW_OP_breg17",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x82 DW_OP_breg18
+ "DW_OP_breg18",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x83 DW_OP_breg19
+ "DW_OP_breg19",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x84 DW_OP_breg20
+ "DW_OP_breg20",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x85 DW_OP_breg21
+ "DW_OP_breg21",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x86 DW_OP_breg22
+ "DW_OP_breg22",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x87 DW_OP_breg23
+ "DW_OP_breg23",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x88 DW_OP_breg24
+ "DW_OP_breg24",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x89 DW_OP_breg25
+ "DW_OP_breg25",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x8a DW_OP_breg26
+ "DW_OP_breg26",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x8b DW_OP_breg27
+ "DW_OP_breg27",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x8c DW_OP_breg28
+ "DW_OP_breg28",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x8d DW_OP_breg29
+ "DW_OP_breg29",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x8e DW_OP_breg30
+ "DW_OP_breg30",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x8f DW_OP_breg31
+ "DW_OP_breg31",
+ OP_BREG,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x90 DW_OP_regx
+ "DW_OP_regx",
+ OP_REGX,
+ 0,
+ 1,
+ {DW_EH_PE_uleb128},
+ },
+ {
+ // 0x91 DW_OP_fbreg
+ "DW_OP_fbreg",
+ OP_NOT_IMPLEMENTED,
+ 0,
+ 1,
+ {DW_EH_PE_sleb128},
+ },
+ {
+ // 0x92 DW_OP_bregx
+ "DW_OP_bregx",
+ OP_BREGX,
+ 0,
+ 2,
+ {DW_EH_PE_uleb128, DW_EH_PE_sleb128},
+ },
+ {
+ // 0x93 DW_OP_piece
+ "DW_OP_piece",
+ OP_NOT_IMPLEMENTED,
+ 0,
+ 1,
+ {DW_EH_PE_uleb128},
+ },
+ {
+ // 0x94 DW_OP_deref_size
+ "DW_OP_deref_size",
+ OP_DEREF_SIZE,
+ 1,
+ 1,
+ {DW_EH_PE_udata1},
+ },
+ {
+ // 0x95 DW_OP_xderef_size
+ "DW_OP_xderef_size",
+ OP_NOT_IMPLEMENTED,
+ 0,
+ 1,
+ {DW_EH_PE_udata1},
+ },
+ {
+ // 0x96 DW_OP_nop
+ "DW_OP_nop",
+ OP_NOP,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x97 DW_OP_push_object_address
+ "DW_OP_push_object_address",
+ OP_NOT_IMPLEMENTED,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x98 DW_OP_call2
+ "DW_OP_call2",
+ OP_NOT_IMPLEMENTED,
+ 0,
+ 1,
+ {DW_EH_PE_udata2},
+ },
+ {
+ // 0x99 DW_OP_call4
+ "DW_OP_call4",
+ OP_NOT_IMPLEMENTED,
+ 0,
+ 1,
+ {DW_EH_PE_udata4},
+ },
+ {
+ // 0x9a DW_OP_call_ref
+ "DW_OP_call_ref",
+ OP_NOT_IMPLEMENTED,
+ 0,
+ 0, // Has a different sized operand (4 bytes or 8 bytes).
+ {},
+ },
+ {
+ // 0x9b DW_OP_form_tls_address
+ "DW_OP_form_tls_address",
+ OP_NOT_IMPLEMENTED,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x9c DW_OP_call_frame_cfa
+ "DW_OP_call_frame_cfa",
+ OP_NOT_IMPLEMENTED,
+ 0,
+ 0,
+ {},
+ },
+ {
+ // 0x9d DW_OP_bit_piece
+ "DW_OP_bit_piece",
+ OP_NOT_IMPLEMENTED,
+ 0,
+ 2,
+ {DW_EH_PE_uleb128, DW_EH_PE_uleb128},
+ },
+ {
+ // 0x9e DW_OP_implicit_value
+ "DW_OP_implicit_value",
+ OP_NOT_IMPLEMENTED,
+ 0,
+ 1,
+ {DW_EH_PE_uleb128},
+ },
+ {
+ // 0x9f DW_OP_stack_value
+ "DW_OP_stack_value",
+ OP_NOT_IMPLEMENTED,
+ 1,
+ 0,
+ {},
+ },
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xa0 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xa1 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xa2 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xa3 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xa4 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xa5 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xa6 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xa7 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xa8 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xa9 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xaa illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xab illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xac illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xad illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xae illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xaf illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xb0 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xb1 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xb2 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xb3 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xb4 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xb5 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xb6 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xb7 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xb8 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xb9 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xba illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xbb illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xbc illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xbd illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xbe illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xbf illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xc0 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xc1 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xc2 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xc3 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xc4 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xc5 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xc6 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xc7 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xc8 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xc9 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xca illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xcb illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xcc illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xcd illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xce illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xcf illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xd0 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xd1 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xd2 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xd3 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xd4 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xd5 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xd6 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xd7 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xd8 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xd9 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xda illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xdb illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xdc illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xdd illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xde illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xdf illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xe0 DW_OP_lo_user
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xe1 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xe2 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xe3 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xe4 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xe5 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xe6 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xe7 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xe8 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xe9 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xea illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xeb illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xec illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xed illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xee illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xef illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xf0 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xf1 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xf2 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xf3 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xf4 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xf5 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xf6 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xf7 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xf8 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xf9 illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xfa illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xfb illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xfc illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xfd illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xfe illegal op
+ {"", OP_ILLEGAL, 0, 0, {}}, // 0xff DW_OP_hi_user
+};
+
template <typename AddressType>
-constexpr typename DwarfOp<AddressType>::OpCallback DwarfOp<AddressType>::kCallbackTable[256];
+const typename DwarfOp<AddressType>::OpHandleFuncPtr DwarfOp<AddressType>::kOpHandleFuncList[] = {
+ [OP_ILLEGAL] = nullptr,
+ [OP_DEREF] = &DwarfOp<AddressType>::op_deref,
+ [OP_DEREF_SIZE] = &DwarfOp<AddressType>::op_deref_size,
+ [OP_PUSH] = &DwarfOp<AddressType>::op_push,
+ [OP_DUP] = &DwarfOp<AddressType>::op_dup,
+ [OP_DROP] = &DwarfOp<AddressType>::op_drop,
+ [OP_OVER] = &DwarfOp<AddressType>::op_over,
+ [OP_PICK] = &DwarfOp<AddressType>::op_pick,
+ [OP_SWAP] = &DwarfOp<AddressType>::op_swap,
+ [OP_ROT] = &DwarfOp<AddressType>::op_rot,
+ [OP_ABS] = &DwarfOp<AddressType>::op_abs,
+ [OP_AND] = &DwarfOp<AddressType>::op_and,
+ [OP_DIV] = &DwarfOp<AddressType>::op_div,
+ [OP_MINUS] = &DwarfOp<AddressType>::op_minus,
+ [OP_MOD] = &DwarfOp<AddressType>::op_mod,
+ [OP_MUL] = &DwarfOp<AddressType>::op_mul,
+ [OP_NEG] = &DwarfOp<AddressType>::op_neg,
+ [OP_NOT] = &DwarfOp<AddressType>::op_not,
+ [OP_OR] = &DwarfOp<AddressType>::op_or,
+ [OP_PLUS] = &DwarfOp<AddressType>::op_plus,
+ [OP_PLUS_UCONST] = &DwarfOp<AddressType>::op_plus_uconst,
+ [OP_SHL] = &DwarfOp<AddressType>::op_shl,
+ [OP_SHR] = &DwarfOp<AddressType>::op_shr,
+ [OP_SHRA] = &DwarfOp<AddressType>::op_shra,
+ [OP_XOR] = &DwarfOp<AddressType>::op_xor,
+ [OP_BRA] = &DwarfOp<AddressType>::op_bra,
+ [OP_EQ] = &DwarfOp<AddressType>::op_eq,
+ [OP_GE] = &DwarfOp<AddressType>::op_ge,
+ [OP_GT] = &DwarfOp<AddressType>::op_gt,
+ [OP_LE] = &DwarfOp<AddressType>::op_le,
+ [OP_LT] = &DwarfOp<AddressType>::op_lt,
+ [OP_NE] = &DwarfOp<AddressType>::op_ne,
+ [OP_SKIP] = &DwarfOp<AddressType>::op_skip,
+ [OP_LIT] = &DwarfOp<AddressType>::op_lit,
+ [OP_REG] = &DwarfOp<AddressType>::op_reg,
+ [OP_REGX] = &DwarfOp<AddressType>::op_regx,
+ [OP_BREG] = &DwarfOp<AddressType>::op_breg,
+ [OP_BREGX] = &DwarfOp<AddressType>::op_bregx,
+ [OP_NOP] = &DwarfOp<AddressType>::op_nop,
+ [OP_NOT_IMPLEMENTED] = &DwarfOp<AddressType>::op_not_implemented,
+};
template <typename AddressType>
bool DwarfOp<AddressType>::Eval(uint64_t start, uint64_t end) {
@@ -97,12 +1540,13 @@
}
const auto* op = &kCallbackTable[cur_op_];
- const auto handle_func = op->handle_func;
- if (handle_func == nullptr) {
+ if (op->handle_func == OP_ILLEGAL) {
last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
return false;
}
+ const auto handle_func = kOpHandleFuncList[op->handle_func];
+
// Make sure that the required number of stack elements is available.
if (stack_.size() < op->num_required_stack_values) {
last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID;
@@ -135,7 +1579,7 @@
std::string raw_string(android::base::StringPrintf("Raw Data: 0x%02x", cur_op));
std::string log_string;
const auto* op = &kCallbackTable[cur_op];
- if (op->handle_func == nullptr) {
+ if (op->handle_func == OP_ILLEGAL) {
log_string = "Illegal";
} else {
log_string = op->name;
diff --git a/libunwindstack/DwarfOp.h b/libunwindstack/DwarfOp.h
index 4c69b3d..ac9fd2d 100644
--- a/libunwindstack/DwarfOp.h
+++ b/libunwindstack/DwarfOp.h
@@ -42,14 +42,6 @@
// Signed version of AddressType
typedef typename std::make_signed<AddressType>::type SignedType;
- struct OpCallback {
- const char* name;
- bool (DwarfOp::*handle_func)();
- uint8_t num_required_stack_values;
- uint8_t num_operands;
- uint8_t operands[2];
- };
-
public:
DwarfOp(DwarfMemory* memory, Memory* regular_memory)
: memory_(memory), regular_memory_(regular_memory) {}
@@ -143,1342 +135,8 @@
bool op_nop();
bool op_not_implemented();
- constexpr static OpCallback kCallbackTable[256] = {
- {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,
- 0,
- 1,
- {DW_EH_PE_absptr},
- },
- {nullptr, nullptr, 0, 0, {}}, // 0x04 illegal op
- {nullptr, nullptr, 0, 0, {}}, // 0x05 illegal op
- {
- // 0x06 DW_OP_deref
- "DW_OP_deref",
- &DwarfOp::op_deref,
- 1,
- 0,
- {},
- },
- {nullptr, nullptr, 0, 0, {}}, // 0x07 illegal op
- {
- // 0x08 DW_OP_const1u
- "DW_OP_const1u",
- &DwarfOp::op_push,
- 0,
- 1,
- {DW_EH_PE_udata1},
- },
- {
- // 0x09 DW_OP_const1s
- "DW_OP_const1s",
- &DwarfOp::op_push,
- 0,
- 1,
- {DW_EH_PE_sdata1},
- },
- {
- // 0x0a DW_OP_const2u
- "DW_OP_const2u",
- &DwarfOp::op_push,
- 0,
- 1,
- {DW_EH_PE_udata2},
- },
- {
- // 0x0b DW_OP_const2s
- "DW_OP_const2s",
- &DwarfOp::op_push,
- 0,
- 1,
- {DW_EH_PE_sdata2},
- },
- {
- // 0x0c DW_OP_const4u
- "DW_OP_const4u",
- &DwarfOp::op_push,
- 0,
- 1,
- {DW_EH_PE_udata4},
- },
- {
- // 0x0d DW_OP_const4s
- "DW_OP_const4s",
- &DwarfOp::op_push,
- 0,
- 1,
- {DW_EH_PE_sdata4},
- },
- {
- // 0x0e DW_OP_const8u
- "DW_OP_const8u",
- &DwarfOp::op_push,
- 0,
- 1,
- {DW_EH_PE_udata8},
- },
- {
- // 0x0f DW_OP_const8s
- "DW_OP_const8s",
- &DwarfOp::op_push,
- 0,
- 1,
- {DW_EH_PE_sdata8},
- },
- {
- // 0x10 DW_OP_constu
- "DW_OP_constu",
- &DwarfOp::op_push,
- 0,
- 1,
- {DW_EH_PE_uleb128},
- },
- {
- // 0x11 DW_OP_consts
- "DW_OP_consts",
- &DwarfOp::op_push,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x12 DW_OP_dup
- "DW_OP_dup",
- &DwarfOp::op_dup,
- 1,
- 0,
- {},
- },
- {
- // 0x13 DW_OP_drop
- "DW_OP_drop",
- &DwarfOp::op_drop,
- 1,
- 0,
- {},
- },
- {
- // 0x14 DW_OP_over
- "DW_OP_over",
- &DwarfOp::op_over,
- 2,
- 0,
- {},
- },
- {
- // 0x15 DW_OP_pick
- "DW_OP_pick",
- &DwarfOp::op_pick,
- 0,
- 1,
- {DW_EH_PE_udata1},
- },
- {
- // 0x16 DW_OP_swap
- "DW_OP_swap",
- &DwarfOp::op_swap,
- 2,
- 0,
- {},
- },
- {
- // 0x17 DW_OP_rot
- "DW_OP_rot",
- &DwarfOp::op_rot,
- 3,
- 0,
- {},
- },
- {
- // 0x18 DW_OP_xderef
- "DW_OP_xderef",
- &DwarfOp::op_not_implemented,
- 2,
- 0,
- {},
- },
- {
- // 0x19 DW_OP_abs
- "DW_OP_abs",
- &DwarfOp::op_abs,
- 1,
- 0,
- {},
- },
- {
- // 0x1a DW_OP_and
- "DW_OP_and",
- &DwarfOp::op_and,
- 2,
- 0,
- {},
- },
- {
- // 0x1b DW_OP_div
- "DW_OP_div",
- &DwarfOp::op_div,
- 2,
- 0,
- {},
- },
- {
- // 0x1c DW_OP_minus
- "DW_OP_minus",
- &DwarfOp::op_minus,
- 2,
- 0,
- {},
- },
- {
- // 0x1d DW_OP_mod
- "DW_OP_mod",
- &DwarfOp::op_mod,
- 2,
- 0,
- {},
- },
- {
- // 0x1e DW_OP_mul
- "DW_OP_mul",
- &DwarfOp::op_mul,
- 2,
- 0,
- {},
- },
- {
- // 0x1f DW_OP_neg
- "DW_OP_neg",
- &DwarfOp::op_neg,
- 1,
- 0,
- {},
- },
- {
- // 0x20 DW_OP_not
- "DW_OP_not",
- &DwarfOp::op_not,
- 1,
- 0,
- {},
- },
- {
- // 0x21 DW_OP_or
- "DW_OP_or",
- &DwarfOp::op_or,
- 2,
- 0,
- {},
- },
- {
- // 0x22 DW_OP_plus
- "DW_OP_plus",
- &DwarfOp::op_plus,
- 2,
- 0,
- {},
- },
- {
- // 0x23 DW_OP_plus_uconst
- "DW_OP_plus_uconst",
- &DwarfOp::op_plus_uconst,
- 1,
- 1,
- {DW_EH_PE_uleb128},
- },
- {
- // 0x24 DW_OP_shl
- "DW_OP_shl",
- &DwarfOp::op_shl,
- 2,
- 0,
- {},
- },
- {
- // 0x25 DW_OP_shr
- "DW_OP_shr",
- &DwarfOp::op_shr,
- 2,
- 0,
- {},
- },
- {
- // 0x26 DW_OP_shra
- "DW_OP_shra",
- &DwarfOp::op_shra,
- 2,
- 0,
- {},
- },
- {
- // 0x27 DW_OP_xor
- "DW_OP_xor",
- &DwarfOp::op_xor,
- 2,
- 0,
- {},
- },
- {
- // 0x28 DW_OP_bra
- "DW_OP_bra",
- &DwarfOp::op_bra,
- 1,
- 1,
- {DW_EH_PE_sdata2},
- },
- {
- // 0x29 DW_OP_eq
- "DW_OP_eq",
- &DwarfOp::op_eq,
- 2,
- 0,
- {},
- },
- {
- // 0x2a DW_OP_ge
- "DW_OP_ge",
- &DwarfOp::op_ge,
- 2,
- 0,
- {},
- },
- {
- // 0x2b DW_OP_gt
- "DW_OP_gt",
- &DwarfOp::op_gt,
- 2,
- 0,
- {},
- },
- {
- // 0x2c DW_OP_le
- "DW_OP_le",
- &DwarfOp::op_le,
- 2,
- 0,
- {},
- },
- {
- // 0x2d DW_OP_lt
- "DW_OP_lt",
- &DwarfOp::op_lt,
- 2,
- 0,
- {},
- },
- {
- // 0x2e DW_OP_ne
- "DW_OP_ne",
- &DwarfOp::op_ne,
- 2,
- 0,
- {},
- },
- {
- // 0x2f DW_OP_skip
- "DW_OP_skip",
- &DwarfOp::op_skip,
- 0,
- 1,
- {DW_EH_PE_sdata2},
- },
- {
- // 0x30 DW_OP_lit0
- "DW_OP_lit0",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x31 DW_OP_lit1
- "DW_OP_lit1",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x32 DW_OP_lit2
- "DW_OP_lit2",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x33 DW_OP_lit3
- "DW_OP_lit3",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x34 DW_OP_lit4
- "DW_OP_lit4",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x35 DW_OP_lit5
- "DW_OP_lit5",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x36 DW_OP_lit6
- "DW_OP_lit6",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x37 DW_OP_lit7
- "DW_OP_lit7",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x38 DW_OP_lit8
- "DW_OP_lit8",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x39 DW_OP_lit9
- "DW_OP_lit9",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x3a DW_OP_lit10
- "DW_OP_lit10",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x3b DW_OP_lit11
- "DW_OP_lit11",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x3c DW_OP_lit12
- "DW_OP_lit12",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x3d DW_OP_lit13
- "DW_OP_lit13",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x3e DW_OP_lit14
- "DW_OP_lit14",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x3f DW_OP_lit15
- "DW_OP_lit15",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x40 DW_OP_lit16
- "DW_OP_lit16",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x41 DW_OP_lit17
- "DW_OP_lit17",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x42 DW_OP_lit18
- "DW_OP_lit18",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x43 DW_OP_lit19
- "DW_OP_lit19",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x44 DW_OP_lit20
- "DW_OP_lit20",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x45 DW_OP_lit21
- "DW_OP_lit21",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x46 DW_OP_lit22
- "DW_OP_lit22",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x47 DW_OP_lit23
- "DW_OP_lit23",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x48 DW_OP_lit24
- "DW_OP_lit24",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x49 DW_OP_lit25
- "DW_OP_lit25",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x4a DW_OP_lit26
- "DW_OP_lit26",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x4b DW_OP_lit27
- "DW_OP_lit27",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x4c DW_OP_lit28
- "DW_OP_lit28",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x4d DW_OP_lit29
- "DW_OP_lit29",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x4e DW_OP_lit30
- "DW_OP_lit30",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x4f DW_OP_lit31
- "DW_OP_lit31",
- &DwarfOp::op_lit,
- 0,
- 0,
- {},
- },
- {
- // 0x50 DW_OP_reg0
- "DW_OP_reg0",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x51 DW_OP_reg1
- "DW_OP_reg1",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x52 DW_OP_reg2
- "DW_OP_reg2",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x53 DW_OP_reg3
- "DW_OP_reg3",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x54 DW_OP_reg4
- "DW_OP_reg4",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x55 DW_OP_reg5
- "DW_OP_reg5",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x56 DW_OP_reg6
- "DW_OP_reg6",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x57 DW_OP_reg7
- "DW_OP_reg7",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x58 DW_OP_reg8
- "DW_OP_reg8",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x59 DW_OP_reg9
- "DW_OP_reg9",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x5a DW_OP_reg10
- "DW_OP_reg10",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x5b DW_OP_reg11
- "DW_OP_reg11",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x5c DW_OP_reg12
- "DW_OP_reg12",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x5d DW_OP_reg13
- "DW_OP_reg13",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x5e DW_OP_reg14
- "DW_OP_reg14",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x5f DW_OP_reg15
- "DW_OP_reg15",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x60 DW_OP_reg16
- "DW_OP_reg16",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x61 DW_OP_reg17
- "DW_OP_reg17",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x62 DW_OP_reg18
- "DW_OP_reg18",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x63 DW_OP_reg19
- "DW_OP_reg19",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x64 DW_OP_reg20
- "DW_OP_reg20",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x65 DW_OP_reg21
- "DW_OP_reg21",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x66 DW_OP_reg22
- "DW_OP_reg22",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x67 DW_OP_reg23
- "DW_OP_reg23",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x68 DW_OP_reg24
- "DW_OP_reg24",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x69 DW_OP_reg25
- "DW_OP_reg25",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x6a DW_OP_reg26
- "DW_OP_reg26",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x6b DW_OP_reg27
- "DW_OP_reg27",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x6c DW_OP_reg28
- "DW_OP_reg28",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x6d DW_OP_reg29
- "DW_OP_reg29",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x6e DW_OP_reg30
- "DW_OP_reg30",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x6f DW_OP_reg31
- "DW_OP_reg31",
- &DwarfOp::op_reg,
- 0,
- 0,
- {},
- },
- {
- // 0x70 DW_OP_breg0
- "DW_OP_breg0",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x71 DW_OP_breg1
- "DW_OP_breg1",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x72 DW_OP_breg2
- "DW_OP_breg2",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x73 DW_OP_breg3
- "DW_OP_breg3",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x74 DW_OP_breg4
- "DW_OP_breg4",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x75 DW_OP_breg5
- "DW_OP_breg5",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x76 DW_OP_breg6
- "DW_OP_breg6",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x77 DW_OP_breg7
- "DW_OP_breg7",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x78 DW_OP_breg8
- "DW_OP_breg8",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x79 DW_OP_breg9
- "DW_OP_breg9",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x7a DW_OP_breg10
- "DW_OP_breg10",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x7b DW_OP_breg11
- "DW_OP_breg11",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x7c DW_OP_breg12
- "DW_OP_breg12",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x7d DW_OP_breg13
- "DW_OP_breg13",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x7e DW_OP_breg14
- "DW_OP_breg14",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x7f DW_OP_breg15
- "DW_OP_breg15",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x80 DW_OP_breg16
- "DW_OP_breg16",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x81 DW_OP_breg17
- "DW_OP_breg17",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x82 DW_OP_breg18
- "DW_OP_breg18",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x83 DW_OP_breg19
- "DW_OP_breg19",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x84 DW_OP_breg20
- "DW_OP_breg20",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x85 DW_OP_breg21
- "DW_OP_breg21",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x86 DW_OP_breg22
- "DW_OP_breg22",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x87 DW_OP_breg23
- "DW_OP_breg23",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x88 DW_OP_breg24
- "DW_OP_breg24",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x89 DW_OP_breg25
- "DW_OP_breg25",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x8a DW_OP_breg26
- "DW_OP_breg26",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x8b DW_OP_breg27
- "DW_OP_breg27",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x8c DW_OP_breg28
- "DW_OP_breg28",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x8d DW_OP_breg29
- "DW_OP_breg29",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x8e DW_OP_breg30
- "DW_OP_breg30",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x8f DW_OP_breg31
- "DW_OP_breg31",
- &DwarfOp::op_breg,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x90 DW_OP_regx
- "DW_OP_regx",
- &DwarfOp::op_regx,
- 0,
- 1,
- {DW_EH_PE_uleb128},
- },
- {
- // 0x91 DW_OP_fbreg
- "DW_OP_fbreg",
- &DwarfOp::op_not_implemented,
- 0,
- 1,
- {DW_EH_PE_sleb128},
- },
- {
- // 0x92 DW_OP_bregx
- "DW_OP_bregx",
- &DwarfOp::op_bregx,
- 0,
- 2,
- {DW_EH_PE_uleb128, DW_EH_PE_sleb128},
- },
- {
- // 0x93 DW_OP_piece
- "DW_OP_piece",
- &DwarfOp::op_not_implemented,
- 0,
- 1,
- {DW_EH_PE_uleb128},
- },
- {
- // 0x94 DW_OP_deref_size
- "DW_OP_deref_size",
- &DwarfOp::op_deref_size,
- 1,
- 1,
- {DW_EH_PE_udata1},
- },
- {
- // 0x95 DW_OP_xderef_size
- "DW_OP_xderef_size",
- &DwarfOp::op_not_implemented,
- 0,
- 1,
- {DW_EH_PE_udata1},
- },
- {
- // 0x96 DW_OP_nop
- "DW_OP_nop",
- &DwarfOp::op_nop,
- 0,
- 0,
- {},
- },
- {
- // 0x97 DW_OP_push_object_address
- "DW_OP_push_object_address",
- &DwarfOp::op_not_implemented,
- 0,
- 0,
- {},
- },
- {
- // 0x98 DW_OP_call2
- "DW_OP_call2",
- &DwarfOp::op_not_implemented,
- 0,
- 1,
- {DW_EH_PE_udata2},
- },
- {
- // 0x99 DW_OP_call4
- "DW_OP_call4",
- &DwarfOp::op_not_implemented,
- 0,
- 1,
- {DW_EH_PE_udata4},
- },
- {
- // 0x9a DW_OP_call_ref
- "DW_OP_call_ref",
- &DwarfOp::op_not_implemented,
- 0,
- 0, // Has a different sized operand (4 bytes or 8 bytes).
- {},
- },
- {
- // 0x9b DW_OP_form_tls_address
- "DW_OP_form_tls_address",
- &DwarfOp::op_not_implemented,
- 0,
- 0,
- {},
- },
- {
- // 0x9c DW_OP_call_frame_cfa
- "DW_OP_call_frame_cfa",
- &DwarfOp::op_not_implemented,
- 0,
- 0,
- {},
- },
- {
- // 0x9d DW_OP_bit_piece
- "DW_OP_bit_piece",
- &DwarfOp::op_not_implemented,
- 0,
- 2,
- {DW_EH_PE_uleb128, DW_EH_PE_uleb128},
- },
- {
- // 0x9e DW_OP_implicit_value
- "DW_OP_implicit_value",
- &DwarfOp::op_not_implemented,
- 0,
- 1,
- {DW_EH_PE_uleb128},
- },
- {
- // 0x9f DW_OP_stack_value
- "DW_OP_stack_value",
- &DwarfOp::op_not_implemented,
- 1,
- 0,
- {},
- },
- {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
- };
+ using OpHandleFuncPtr = bool (DwarfOp::*)();
+ static const OpHandleFuncPtr kOpHandleFuncList[];
};
} // namespace unwindstack
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp
index 0dd95cf..2734cf8 100644
--- a/libunwindstack/Unwinder.cpp
+++ b/libunwindstack/Unwinder.cpp
@@ -247,7 +247,7 @@
// or the pc in the first frame is in a valid map.
// This allows for a case where the code jumps into the middle of
// nowhere, but there is no other unwind information after that.
- if (frames_.size() != 2 || maps_->Find(frames_[0].pc) != nullptr) {
+ if (frames_.size() > 2 || (frames_.size() > 0 && maps_->Find(frames_[0].pc) != nullptr)) {
// Remove the speculative frame.
frames_.pop_back();
}
diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp
index 49aeeb3..d88531f 100644
--- a/libunwindstack/tests/UnwinderTest.cpp
+++ b/libunwindstack/tests/UnwinderTest.cpp
@@ -749,6 +749,23 @@
EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
}
+// Verify that a speculative frame does not cause a crash when it wasn't
+// really added due to a filter.
+TEST_F(UnwinderTest, speculative_frame_check_with_no_frames) {
+ regs_.set_pc(0x23000);
+ regs_.set_sp(0x10000);
+ regs_.FakeSetReturnAddress(0x23100);
+ regs_.FakeSetReturnAddressValid(true);
+
+ Unwinder unwinder(64, maps_.get(), ®s_, process_memory_);
+
+ std::vector<std::string> skip_names{"libanother.so"};
+ unwinder.Unwind(&skip_names);
+ EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
+
+ ASSERT_EQ(0U, unwinder.NumFrames());
+}
+
// Verify that an unwind stops when a frame is in given suffix.
TEST_F(UnwinderTest, map_ignore_suffixes) {
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 54e7c7e..4e2af86 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -148,6 +148,7 @@
namespace.media.link.default.shared_libs = %LLNDK_LIBRARIES%
namespace.media.link.default.shared_libs += libandroid.so
namespace.media.link.default.shared_libs += libbinder_ndk.so
+namespace.media.link.default.shared_libs += libmediametrics.so
namespace.media.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
###############################################################################
diff --git a/rootdir/etc/ld.config.vndk_lite.txt b/rootdir/etc/ld.config.vndk_lite.txt
index 39f69ca..335369e 100644
--- a/rootdir/etc/ld.config.vndk_lite.txt
+++ b/rootdir/etc/ld.config.vndk_lite.txt
@@ -97,6 +97,7 @@
namespace.media.link.default.shared_libs = %LLNDK_LIBRARIES%
namespace.media.link.default.shared_libs += libandroid.so
namespace.media.link.default.shared_libs += libbinder_ndk.so
+namespace.media.link.default.shared_libs += libmediametrics.so
namespace.media.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
###############################################################################