summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CleanSpec.mk1
-rw-r--r--adb/Android.mk4
-rw-r--r--adb/adb.cpp15
-rw-r--r--adb/adb.h3
-rw-r--r--adb/client/usb_libusb.cpp14
-rw-r--r--adb/daemon/main.cpp24
-rw-r--r--adb/services.cpp40
-rw-r--r--adb/set_verity_enable_state_service.cpp14
-rw-r--r--adb/shell_service.cpp15
-rw-r--r--adb/socket.h117
-rw-r--r--adb/sockets.cpp2
-rw-r--r--adb/test_device.py4
-rw-r--r--adb/transport.cpp25
-rw-r--r--adb/transport.h7
-rw-r--r--adb/transport_usb.cpp10
-rw-r--r--base/Android.bp6
-rw-r--r--base/chrono_utils.cpp4
-rw-r--r--base/include/android-base/logging.h32
-rw-r--r--base/include/android-base/test_utils.h4
-rw-r--r--base/properties.cpp11
-rw-r--r--base/test_utils.cpp10
-rw-r--r--bootstat/Android.bp6
-rw-r--r--bootstat/boot_event_record_store.cpp18
-rw-r--r--bootstat/boot_event_record_store.h4
-rw-r--r--bootstat/boot_event_record_store_test.cpp18
-rwxr-xr-xbootstat/boot_reason_test.sh1069
-rw-r--r--bootstat/bootstat-debug.rc7
-rw-r--r--bootstat/bootstat.cpp593
-rw-r--r--bootstat/bootstat.rc34
-rw-r--r--debuggerd/crash_dump.cpp25
-rw-r--r--debuggerd/crasher/Android.bp2
-rw-r--r--debuggerd/crasher/crasher.cpp8
-rw-r--r--debuggerd/debuggerd_test.cpp1
-rw-r--r--debuggerd/handler/debuggerd_fallback.cpp4
-rw-r--r--debuggerd/libdebuggerd/arm/machine.cpp5
-rw-r--r--debuggerd/libdebuggerd/arm64/machine.cpp5
-rw-r--r--debuggerd/libdebuggerd/backtrace.cpp6
-rw-r--r--debuggerd/libdebuggerd/elf_utils.cpp4
-rw-r--r--debuggerd/libdebuggerd/include/libdebuggerd/backtrace.h (renamed from debuggerd/libdebuggerd/include/backtrace.h)0
-rw-r--r--debuggerd/libdebuggerd/include/libdebuggerd/elf_utils.h (renamed from debuggerd/libdebuggerd/include/elf_utils.h)0
-rw-r--r--debuggerd/libdebuggerd/include/libdebuggerd/machine.h (renamed from debuggerd/libdebuggerd/include/machine.h)0
-rw-r--r--debuggerd/libdebuggerd/include/libdebuggerd/open_files_list.h (renamed from debuggerd/libdebuggerd/include/open_files_list.h)0
-rw-r--r--debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h (renamed from debuggerd/libdebuggerd/include/tombstone.h)0
-rw-r--r--debuggerd/libdebuggerd/include/libdebuggerd/utility.h (renamed from debuggerd/libdebuggerd/include/utility.h)0
-rw-r--r--debuggerd/libdebuggerd/mips/machine.cpp5
-rw-r--r--debuggerd/libdebuggerd/mips64/machine.cpp5
-rw-r--r--debuggerd/libdebuggerd/open_files_list.cpp6
-rw-r--r--debuggerd/libdebuggerd/test/dump_memory_test.cpp3
-rw-r--r--debuggerd/libdebuggerd/test/elf_fake.cpp2
-rw-r--r--debuggerd/libdebuggerd/test/log_fake.cpp2
-rw-r--r--debuggerd/libdebuggerd/test/open_files_list_test.cpp2
-rw-r--r--debuggerd/libdebuggerd/test/ptrace_fake.cpp4
-rw-r--r--debuggerd/libdebuggerd/test/tombstone_test.cpp24
-rw-r--r--debuggerd/libdebuggerd/tombstone.cpp118
-rw-r--r--debuggerd/libdebuggerd/utility.cpp2
-rw-r--r--debuggerd/libdebuggerd/x86/machine.cpp5
-rw-r--r--debuggerd/libdebuggerd/x86_64/machine.cpp5
-rw-r--r--debuggerd/tombstoned/intercept_manager.cpp4
-rw-r--r--debuggerd/tombstoned/tombstoned.cpp10
-rw-r--r--demangle/Android.bp6
-rw-r--r--demangle/DemangleTest.cpp8
-rw-r--r--demangle/Demangler.cpp28
-rw-r--r--demangle/Demangler.h1
-rw-r--r--fs_mgr/Android.bp13
-rw-r--r--fs_mgr/Android.mk1
-rw-r--r--fs_mgr/fs_mgr.cpp34
-rw-r--r--fs_mgr/fs_mgr_format.cpp93
-rw-r--r--fs_mgr/fs_mgr_fstab.cpp39
-rw-r--r--fs_mgr/fs_mgr_priv.h1
-rw-r--r--fs_mgr/fs_mgr_slotselect.cpp13
-rw-r--r--fs_mgr/fs_mgr_verity.cpp9
-rw-r--r--fs_mgr/include/fs_mgr.h4
-rw-r--r--fs_mgr/include_fstab/fstab/fstab.h14
-rw-r--r--gatekeeperd/SoftGateKeeper.h4
-rw-r--r--gatekeeperd/SoftGateKeeperDevice.h4
-rw-r--r--gatekeeperd/gatekeeperd.cpp3
-rw-r--r--gatekeeperd/tests/gatekeeper_test.cpp1
-rw-r--r--init/Android.bp33
-rw-r--r--init/Android.mk3
-rw-r--r--init/README.md8
-rw-r--r--init/action.cpp60
-rw-r--r--init/action.h25
-rw-r--r--init/bootchart.cpp2
-rw-r--r--init/bootchart.h3
-rw-r--r--init/builtin_arguments.h43
-rw-r--r--init/builtins.cpp276
-rw-r--r--init/builtins.h7
-rw-r--r--init/init.cpp95
-rw-r--r--init/init_test.cpp29
-rw-r--r--init/persistent_properties.cpp246
-rw-r--r--init/persistent_properties.h39
-rw-r--r--init/persistent_properties.proto27
-rw-r--r--init/persistent_properties_test.cpp156
-rw-r--r--init/property_service.cpp131
-rw-r--r--init/property_service_test.cpp17
-rw-r--r--init/reboot.cpp38
-rw-r--r--init/reboot.h4
-rw-r--r--init/result.h10
-rw-r--r--init/result_test.cpp43
-rw-r--r--init/security.cpp6
-rw-r--r--init/security.h7
-rw-r--r--init/selinux.cpp69
-rw-r--r--init/service.cpp41
-rw-r--r--init/service.h10
-rw-r--r--init/service_test.cpp7
-rw-r--r--init/sigchld_handler.cpp (renamed from init/signal_handler.cpp)39
-rw-r--r--init/sigchld_handler.h (renamed from init/signal_handler.h)6
-rw-r--r--init/subcontext.cpp285
-rw-r--r--init/subcontext.h80
-rw-r--r--init/subcontext.proto33
-rw-r--r--init/subcontext_benchmark.cpp57
-rw-r--r--init/subcontext_test.cpp179
-rw-r--r--init/test_function_map.h55
-rw-r--r--libbacktrace/Android.bp11
-rw-r--r--libbacktrace/UnwindStack.cpp126
-rw-r--r--libbacktrace/UnwindStack.h6
-rw-r--r--libbacktrace/UnwindStackMap.cpp5
-rw-r--r--libbacktrace/UnwindStackMap.h5
-rw-r--r--libbacktrace/backtrace_test.cpp56
-rw-r--r--libbacktrace/include/backtrace/Backtrace.h2
-rw-r--r--libbacktrace/include/backtrace/BacktraceMap.h2
-rw-r--r--libcrypto_utils/Android.bp3
-rw-r--r--libcutils/ashmem-dev.c2
-rw-r--r--libcutils/fs_config.cpp3
-rw-r--r--libdiskconfig/Android.bp5
-rw-r--r--libgrallocusage/Android.bp2
-rw-r--r--libion/include/ion/ion.h9
-rw-r--r--libion/ion.c158
-rw-r--r--libion/ion_4.12.h125
-rw-r--r--liblog/Android.bp26
-rw-r--r--liblog/include/log/log_main.h9
-rw-r--r--liblog/include/log/log_safetynet.h2
-rw-r--r--liblog/include/log/log_time.h10
-rw-r--r--[l---------]liblog/include_vndk/log/log_time.h48
-rw-r--r--liblog/local_logger.c1
-rw-r--r--liblog/logprint.c1
-rw-r--r--libmemtrack/Android.bp4
-rw-r--r--libmemunreachable/tests/DisableMalloc_test.cpp17
-rw-r--r--libmemunreachable/tests/MemUnreachable_test.cpp3
-rw-r--r--libmetricslogger/Android.bp5
-rw-r--r--libmetricslogger/include/metricslogger/metrics_logger.h12
-rw-r--r--libmetricslogger/metrics_logger.cpp20
-rw-r--r--libnativebridge/Android.bp7
-rw-r--r--libnativebridge/tests/Android.bp8
-rw-r--r--libnativeloader/Android.bp9
-rw-r--r--libnetutils/Android.bp3
-rw-r--r--libprocinfo/Android.bp3
-rw-r--r--libsparse/Android.bp16
-rw-r--r--libsparse/sparse_read.cpp1
-rw-r--r--libsuspend/Android.bp3
-rw-r--r--libsync/Android.bp7
-rw-r--r--libsync/libsync.map.txt16
-rw-r--r--libsync/sync.c3
-rw-r--r--libsync/tests/sync_test.cpp35
-rw-r--r--libsysutils/Android.bp4
-rw-r--r--libsysutils/include/sysutils/NetlinkEvent.h1
-rw-r--r--libsysutils/src/NetlinkEvent.cpp53
-rw-r--r--libunwindstack/Android.bp34
-rw-r--r--libunwindstack/DwarfSection.cpp13
-rw-r--r--libunwindstack/Elf.cpp38
-rw-r--r--libunwindstack/ElfInterface.cpp26
-rw-r--r--libunwindstack/ElfInterfaceArm.cpp17
-rw-r--r--libunwindstack/ElfInterfaceArm.h4
-rw-r--r--libunwindstack/MapInfo.cpp101
-rw-r--r--libunwindstack/Memory.cpp9
-rw-r--r--libunwindstack/Regs.cpp60
-rw-r--r--libunwindstack/Unwinder.cpp183
-rw-r--r--libunwindstack/include/unwindstack/DwarfSection.h6
-rw-r--r--libunwindstack/include/unwindstack/Elf.h4
-rw-r--r--libunwindstack/include/unwindstack/ElfInterface.h13
-rw-r--r--libunwindstack/include/unwindstack/MapInfo.h8
-rw-r--r--libunwindstack/include/unwindstack/Memory.h9
-rw-r--r--libunwindstack/include/unwindstack/Regs.h14
-rw-r--r--libunwindstack/include/unwindstack/Unwinder.h84
-rw-r--r--libunwindstack/tests/DwarfDebugFrameTest.cpp1
-rw-r--r--libunwindstack/tests/DwarfEhFrameTest.cpp1
-rw-r--r--libunwindstack/tests/DwarfOpTest.cpp6
-rw-r--r--libunwindstack/tests/DwarfSectionImplTest.cpp111
-rw-r--r--libunwindstack/tests/DwarfSectionTest.cpp16
-rw-r--r--libunwindstack/tests/ElfFake.cpp65
-rw-r--r--libunwindstack/tests/ElfFake.h84
-rw-r--r--libunwindstack/tests/ElfInterfaceArmTest.cpp58
-rw-r--r--libunwindstack/tests/ElfTest.cpp3
-rw-r--r--libunwindstack/tests/MapInfoCreateMemoryTest.cpp182
-rw-r--r--libunwindstack/tests/MapInfoGetElfTest.cpp281
-rw-r--r--libunwindstack/tests/MemoryRangeTest.cpp17
-rw-r--r--libunwindstack/tests/MemoryRemoteTest.cpp31
-rw-r--r--libunwindstack/tests/RegsFake.h49
-rw-r--r--libunwindstack/tests/RegsTest.cpp95
-rw-r--r--libunwindstack/tests/TestUtils.h55
-rw-r--r--libunwindstack/tests/UnwindTest.cpp230
-rw-r--r--libunwindstack/tests/UnwinderTest.cpp576
-rw-r--r--libunwindstack/tools/unwind.cpp65
-rw-r--r--libunwindstack/tools/unwind_symbols.cpp34
-rw-r--r--libusbhost/Android.bp4
-rw-r--r--libutils/Android.bp4
-rw-r--r--libutils/RefBase.cpp5
-rw-r--r--libutils/SystemClock.cpp2
-rw-r--r--libutils/include/utils/StrongPointer.h7
-rw-r--r--libutils/tests/Android.bp4
-rw-r--r--libziparchive/Android.bp17
-rw-r--r--logd/tests/logd_test.cpp2
-rw-r--r--reboot/reboot.c21
-rw-r--r--rootdir/Android.mk2
-rw-r--r--rootdir/init.rc1
-rw-r--r--rootdir/init.usb.rc2
-rw-r--r--run-as/run-as.cpp1
-rw-r--r--shell_and_utilities/README.md45
-rw-r--r--trusty/keymaster/Android.bp3
-rw-r--r--trusty/keymaster/trusty_keymaster_device_test.cpp30
-rw-r--r--trusty/nvram/trusty_nvram_device.cpp2
211 files changed, 6513 insertions, 1882 deletions
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 5b5eff406..304ce4ec0 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -60,3 +60,4 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/hw/gatekeeper.$(TARGET_D
60$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib64/hw/gatekeeper.$(TARGET_DEVICE).so) 60$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib64/hw/gatekeeper.$(TARGET_DEVICE).so)
61$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/vendor) 61$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/vendor)
62$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/init.rc) 62$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/init.rc)
63$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/root)
diff --git a/adb/Android.mk b/adb/Android.mk
index d033d5a3f..05b0284a1 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -345,18 +345,16 @@ LOCAL_CFLAGS := \
345 -D_GNU_SOURCE \ 345 -D_GNU_SOURCE \
346 -Wno-deprecated-declarations \ 346 -Wno-deprecated-declarations \
347 347
348LOCAL_CFLAGS += -DALLOW_ADBD_ROOT=$(if $(filter userdebug eng,$(TARGET_BUILD_VARIANT)),1,0)
349LOCAL_CFLAGS += -DALLOW_ADBD_NO_AUTH=$(if $(filter userdebug eng,$(TARGET_BUILD_VARIANT)),1,0) 348LOCAL_CFLAGS += -DALLOW_ADBD_NO_AUTH=$(if $(filter userdebug eng,$(TARGET_BUILD_VARIANT)),1,0)
350 349
351ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT))) 350ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
352LOCAL_CFLAGS += -DALLOW_ADBD_DISABLE_VERITY=1 351LOCAL_CFLAGS += -DALLOW_ADBD_DISABLE_VERITY=1
352LOCAL_CFLAGS += -DALLOW_ADBD_ROOT=1
353endif 353endif
354 354
355LOCAL_MODULE := adbd 355LOCAL_MODULE := adbd
356 356
357LOCAL_FORCE_STATIC_EXECUTABLE := true 357LOCAL_FORCE_STATIC_EXECUTABLE := true
358LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN)
359LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)
360 358
361LOCAL_SANITIZE := $(adb_target_sanitize) 359LOCAL_SANITIZE := $(adb_target_sanitize)
362LOCAL_STRIP_MODULE := keep_symbols 360LOCAL_STRIP_MODULE := keep_symbols
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 8c24bbba3..6b30be884 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -257,19 +257,6 @@ void send_connect(atransport* t) {
257 send_packet(cp, t); 257 send_packet(cp, t);
258} 258}
259 259
260#if ADB_HOST
261
262void SendConnectOnHost(atransport* t) {
263 // Send an empty message before A_CNXN message. This is because the data toggle of the ep_out on
264 // host and ep_in on device may not be the same.
265 apacket* p = get_apacket();
266 CHECK(p);
267 send_packet(p, t);
268 send_connect(t);
269}
270
271#endif
272
273// qual_overwrite is used to overwrite a qualifier string. dst is a 260// qual_overwrite is used to overwrite a qualifier string. dst is a
274// pointer to a char pointer. It is assumed that if *dst is non-NULL, it 261// pointer to a char pointer. It is assumed that if *dst is non-NULL, it
275// was malloc'ed and needs to freed. *dst will be set to a dup of src. 262// was malloc'ed and needs to freed. *dst will be set to a dup of src.
@@ -370,7 +357,7 @@ void handle_packet(apacket *p, atransport *t)
370 if (p->msg.arg0){ 357 if (p->msg.arg0){
371 send_packet(p, t); 358 send_packet(p, t);
372#if ADB_HOST 359#if ADB_HOST
373 SendConnectOnHost(t); 360 send_connect(t);
374#endif 361#endif
375 } else { 362 } else {
376 t->SetConnectionState(kCsOffline); 363 t->SetConnectionState(kCsOffline);
diff --git a/adb/adb.h b/adb/adb.h
index 6a9897f63..a4d233ead 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -224,9 +224,6 @@ void handle_online(atransport *t);
224void handle_offline(atransport *t); 224void handle_offline(atransport *t);
225 225
226void send_connect(atransport *t); 226void send_connect(atransport *t);
227#if ADB_HOST
228void SendConnectOnHost(atransport* t);
229#endif
230 227
231void parse_banner(const std::string&, atransport* t); 228void parse_banner(const std::string&, atransport* t);
232 229
diff --git a/adb/client/usb_libusb.cpp b/adb/client/usb_libusb.cpp
index e7f44c685..81201995a 100644
--- a/adb/client/usb_libusb.cpp
+++ b/adb/client/usb_libusb.cpp
@@ -333,6 +333,13 @@ static void process_device(libusb_device* device) {
333 return; 333 return;
334 } 334 }
335 335
336 rc = libusb_set_interface_alt_setting(handle.get(), interface_num, 0);
337 if (rc != 0) {
338 LOG(WARNING) << "failed to set interface alt setting for device '" << device_serial
339 << "'" << libusb_error_name(rc);
340 return;
341 }
342
336 for (uint8_t endpoint : {bulk_in, bulk_out}) { 343 for (uint8_t endpoint : {bulk_in, bulk_out}) {
337 rc = libusb_clear_halt(handle.get(), endpoint); 344 rc = libusb_clear_halt(handle.get(), endpoint);
338 if (rc != 0) { 345 if (rc != 0) {
@@ -412,8 +419,13 @@ static void device_disconnected(libusb_device* device) {
412 if (it != usb_handles.end()) { 419 if (it != usb_handles.end()) {
413 if (!it->second->device_handle) { 420 if (!it->second->device_handle) {
414 // If the handle is null, we were never able to open the device. 421 // If the handle is null, we were never able to open the device.
415 unregister_usb_transport(it->second.get()); 422
423 // Temporarily release the usb handles mutex to avoid deadlock.
424 std::unique_ptr<usb_handle> handle = std::move(it->second);
416 usb_handles.erase(it); 425 usb_handles.erase(it);
426 lock.unlock();
427 unregister_usb_transport(handle.get());
428 lock.lock();
417 } else { 429 } else {
418 // Closure of the transport will erase the usb_handle. 430 // Closure of the transport will erase the usb_handle.
419 } 431 }
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index e0629abdd..1c94298da 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -49,23 +49,17 @@
49 49
50static const char* root_seclabel = nullptr; 50static const char* root_seclabel = nullptr;
51 51
52static inline bool is_device_unlocked() {
53 return "orange" == android::base::GetProperty("ro.boot.verifiedbootstate", "");
54}
55
56static void drop_capabilities_bounding_set_if_needed(struct minijail *j) { 52static void drop_capabilities_bounding_set_if_needed(struct minijail *j) {
57 if (ALLOW_ADBD_ROOT || is_device_unlocked()) { 53#if defined(ALLOW_ADBD_ROOT)
58 if (__android_log_is_debuggable()) { 54 if (__android_log_is_debuggable()) {
59 return; 55 return;
60 }
61 } 56 }
57#endif
62 minijail_capbset_drop(j, CAP_TO_MASK(CAP_SETUID) | CAP_TO_MASK(CAP_SETGID)); 58 minijail_capbset_drop(j, CAP_TO_MASK(CAP_SETUID) | CAP_TO_MASK(CAP_SETGID));
63} 59}
64 60
65static bool should_drop_privileges() { 61static bool should_drop_privileges() {
66 // "adb root" not allowed, always drop privileges. 62#if defined(ALLOW_ADBD_ROOT)
67 if (!ALLOW_ADBD_ROOT && !is_device_unlocked()) return true;
68
69 // The properties that affect `adb root` and `adb unroot` are ro.secure and 63 // The properties that affect `adb root` and `adb unroot` are ro.secure and
70 // ro.debuggable. In this context the names don't make the expected behavior 64 // ro.debuggable. In this context the names don't make the expected behavior
71 // particularly obvious. 65 // particularly obvious.
@@ -95,6 +89,9 @@ static bool should_drop_privileges() {
95 } 89 }
96 90
97 return drop; 91 return drop;
92#else
93 return true; // "adb root" not allowed, always drop privileges.
94#endif // ALLOW_ADBD_ROOT
98} 95}
99 96
100static void drop_privileges(int server_port) { 97static void drop_privileges(int server_port) {
@@ -161,10 +158,7 @@ int adbd_main(int server_port) {
161 // descriptor will always be open. 158 // descriptor will always be open.
162 adbd_cloexec_auth_socket(); 159 adbd_cloexec_auth_socket();
163 160
164 // Respect ro.adb.secure in userdebug/eng builds (ALLOW_ADBD_NO_AUTH), or when the 161 if (ALLOW_ADBD_NO_AUTH && !android::base::GetBoolProperty("ro.adb.secure", false)) {
165 // device is unlocked.
166 if ((ALLOW_ADBD_NO_AUTH || is_device_unlocked()) &&
167 !android::base::GetBoolProperty("ro.adb.secure", false)) {
168 auth_required = false; 162 auth_required = false;
169 } 163 }
170 164
diff --git a/adb/services.cpp b/adb/services.cpp
index dbf71d36d..aff7012ee 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -58,6 +58,7 @@
58#include "transport.h" 58#include "transport.h"
59 59
60struct stinfo { 60struct stinfo {
61 const char* service_name;
61 void (*func)(int fd, void *cookie); 62 void (*func)(int fd, void *cookie);
62 int fd; 63 int fd;
63 void *cookie; 64 void *cookie;
@@ -65,7 +66,7 @@ struct stinfo {
65 66
66static void service_bootstrap_func(void* x) { 67static void service_bootstrap_func(void* x) {
67 stinfo* sti = reinterpret_cast<stinfo*>(x); 68 stinfo* sti = reinterpret_cast<stinfo*>(x);
68 adb_thread_setname(android::base::StringPrintf("service %d", sti->fd)); 69 adb_thread_setname(android::base::StringPrintf("%s svc %d", sti->service_name, sti->fd));
69 sti->func(sti->fd, sti->cookie); 70 sti->func(sti->fd, sti->cookie);
70 free(sti); 71 free(sti);
71} 72}
@@ -150,6 +151,7 @@ static bool reboot_service_impl(int fd, const char* arg) {
150 151
151 sync(); 152 sync();
152 153
154 if (!reboot_arg || !reboot_arg[0]) reboot_arg = "adb";
153 std::string reboot_string = android::base::StringPrintf("reboot,%s", reboot_arg); 155 std::string reboot_string = android::base::StringPrintf("reboot,%s", reboot_arg);
154 if (!android::base::SetProperty(ANDROID_RB_PROPERTY, reboot_string)) { 156 if (!android::base::SetProperty(ANDROID_RB_PROPERTY, reboot_string)) {
155 WriteFdFmt(fd, "reboot (%s) failed\n", reboot_string.c_str()); 157 WriteFdFmt(fd, "reboot (%s) failed\n", reboot_string.c_str());
@@ -159,8 +161,7 @@ static bool reboot_service_impl(int fd, const char* arg) {
159 return true; 161 return true;
160} 162}
161 163
162void reboot_service(int fd, void* arg) 164void reboot_service(int fd, void* arg) {
163{
164 if (reboot_service_impl(fd, static_cast<const char*>(arg))) { 165 if (reboot_service_impl(fd, static_cast<const char*>(arg))) {
165 // Don't return early. Give the reboot command time to take effect 166 // Don't return early. Give the reboot command time to take effect
166 // to avoid messing up scripts which do "adb reboot && adb wait-for-device" 167 // to avoid messing up scripts which do "adb reboot && adb wait-for-device"
@@ -235,8 +236,7 @@ static int ShellService(const std::string& args, const atransport* transport) {
235 236
236#endif // !ADB_HOST 237#endif // !ADB_HOST
237 238
238static int create_service_thread(void (*func)(int, void *), void *cookie) 239static int create_service_thread(const char* service_name, void (*func)(int, void*), void* cookie) {
239{
240 int s[2]; 240 int s[2];
241 if (adb_socketpair(s)) { 241 if (adb_socketpair(s)) {
242 printf("cannot create service socket pair\n"); 242 printf("cannot create service socket pair\n");
@@ -257,6 +257,7 @@ static int create_service_thread(void (*func)(int, void *), void *cookie)
257 if (sti == nullptr) { 257 if (sti == nullptr) {
258 fatal("cannot allocate stinfo"); 258 fatal("cannot allocate stinfo");
259 } 259 }
260 sti->service_name = service_name;
260 sti->func = func; 261 sti->func = func;
261 sti->cookie = cookie; 262 sti->cookie = cookie;
262 sti->fd = s[1]; 263 sti->fd = s[1];
@@ -280,7 +281,7 @@ int service_to_fd(const char* name, const atransport* transport) {
280 } else if(!strncmp("dev:", name, 4)) { 281 } else if(!strncmp("dev:", name, 4)) {
281 ret = unix_open(name + 4, O_RDWR | O_CLOEXEC); 282 ret = unix_open(name + 4, O_RDWR | O_CLOEXEC);
282 } else if(!strncmp(name, "framebuffer:", 12)) { 283 } else if(!strncmp(name, "framebuffer:", 12)) {
283 ret = create_service_thread(framebuffer_service, 0); 284 ret = create_service_thread("fb", framebuffer_service, nullptr);
284 } else if (!strncmp(name, "jdwp:", 5)) { 285 } else if (!strncmp(name, "jdwp:", 5)) {
285 ret = create_jdwp_connection_fd(atoi(name+5)); 286 ret = create_jdwp_connection_fd(atoi(name+5));
286 } else if(!strncmp(name, "shell", 5)) { 287 } else if(!strncmp(name, "shell", 5)) {
@@ -288,17 +289,17 @@ int service_to_fd(const char* name, const atransport* transport) {
288 } else if(!strncmp(name, "exec:", 5)) { 289 } else if(!strncmp(name, "exec:", 5)) {
289 ret = StartSubprocess(name + 5, nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone); 290 ret = StartSubprocess(name + 5, nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
290 } else if(!strncmp(name, "sync:", 5)) { 291 } else if(!strncmp(name, "sync:", 5)) {
291 ret = create_service_thread(file_sync_service, NULL); 292 ret = create_service_thread("sync", file_sync_service, nullptr);
292 } else if(!strncmp(name, "remount:", 8)) { 293 } else if(!strncmp(name, "remount:", 8)) {
293 ret = create_service_thread(remount_service, NULL); 294 ret = create_service_thread("remount", remount_service, nullptr);
294 } else if(!strncmp(name, "reboot:", 7)) { 295 } else if(!strncmp(name, "reboot:", 7)) {
295 void* arg = strdup(name + 7); 296 void* arg = strdup(name + 7);
296 if (arg == NULL) return -1; 297 if (arg == NULL) return -1;
297 ret = create_service_thread(reboot_service, arg); 298 ret = create_service_thread("reboot", reboot_service, arg);
298 } else if(!strncmp(name, "root:", 5)) { 299 } else if(!strncmp(name, "root:", 5)) {
299 ret = create_service_thread(restart_root_service, NULL); 300 ret = create_service_thread("root", restart_root_service, nullptr);
300 } else if(!strncmp(name, "unroot:", 7)) { 301 } else if(!strncmp(name, "unroot:", 7)) {
301 ret = create_service_thread(restart_unroot_service, NULL); 302 ret = create_service_thread("unroot", restart_unroot_service, nullptr);
302 } else if(!strncmp(name, "backup:", 7)) { 303 } else if(!strncmp(name, "backup:", 7)) {
303 ret = StartSubprocess(android::base::StringPrintf("/system/bin/bu backup %s", 304 ret = StartSubprocess(android::base::StringPrintf("/system/bin/bu backup %s",
304 (name + 7)).c_str(), 305 (name + 7)).c_str(),
@@ -311,17 +312,20 @@ int service_to_fd(const char* name, const atransport* transport) {
311 if (sscanf(name + 6, "%d", &port) != 1) { 312 if (sscanf(name + 6, "%d", &port) != 1) {
312 return -1; 313 return -1;
313 } 314 }
314 ret = create_service_thread(restart_tcp_service, (void *) (uintptr_t) port); 315 ret = create_service_thread("tcp", restart_tcp_service, reinterpret_cast<void*>(port));
315 } else if(!strncmp(name, "usb:", 4)) { 316 } else if(!strncmp(name, "usb:", 4)) {
316 ret = create_service_thread(restart_usb_service, NULL); 317 ret = create_service_thread("usb", restart_usb_service, nullptr);
317 } else if (!strncmp(name, "reverse:", 8)) { 318 } else if (!strncmp(name, "reverse:", 8)) {
318 ret = reverse_service(name + 8); 319 ret = reverse_service(name + 8);
319 } else if(!strncmp(name, "disable-verity:", 15)) { 320 } else if(!strncmp(name, "disable-verity:", 15)) {
320 ret = create_service_thread(set_verity_enabled_state_service, (void*)0); 321 ret = create_service_thread("verity-on", set_verity_enabled_state_service,
322 reinterpret_cast<void*>(0));
321 } else if(!strncmp(name, "enable-verity:", 15)) { 323 } else if(!strncmp(name, "enable-verity:", 15)) {
322 ret = create_service_thread(set_verity_enabled_state_service, (void*)1); 324 ret = create_service_thread("verity-off", set_verity_enabled_state_service,
325 reinterpret_cast<void*>(1));
323 } else if (!strcmp(name, "reconnect")) { 326 } else if (!strcmp(name, "reconnect")) {
324 ret = create_service_thread(reconnect_service, const_cast<atransport*>(transport)); 327 ret = create_service_thread("reconnect", reconnect_service,
328 const_cast<atransport*>(transport));
325#endif 329#endif
326 } 330 }
327 if (ret >= 0) { 331 if (ret >= 0) {
@@ -483,14 +487,14 @@ asocket* host_service_to_socket(const char* name, const char* serial, TransportI
483 return nullptr; 487 return nullptr;
484 } 488 }
485 489
486 int fd = create_service_thread(wait_for_state, sinfo.get()); 490 int fd = create_service_thread("wait", wait_for_state, sinfo.get());
487 if (fd != -1) { 491 if (fd != -1) {
488 sinfo.release(); 492 sinfo.release();
489 } 493 }
490 return create_local_socket(fd); 494 return create_local_socket(fd);
491 } else if (!strncmp(name, "connect:", 8)) { 495 } else if (!strncmp(name, "connect:", 8)) {
492 char* host = strdup(name + 8); 496 char* host = strdup(name + 8);
493 int fd = create_service_thread(connect_service, host); 497 int fd = create_service_thread("connect", connect_service, host);
494 if (fd == -1) { 498 if (fd == -1) {
495 free(host); 499 free(host);
496 } 500 }
diff --git a/adb/set_verity_enable_state_service.cpp b/adb/set_verity_enable_state_service.cpp
index 253d14a0e..49e0363a1 100644
--- a/adb/set_verity_enable_state_service.cpp
+++ b/adb/set_verity_enable_state_service.cpp
@@ -93,21 +93,9 @@ static bool set_verity_enabled_state(int fd, const char* block_device, const cha
93/* Helper function to get A/B suffix, if any. If the device isn't 93/* Helper function to get A/B suffix, if any. If the device isn't
94 * using A/B the empty string is returned. Otherwise either "_a", 94 * using A/B the empty string is returned. Otherwise either "_a",
95 * "_b", ... is returned. 95 * "_b", ... is returned.
96 *
97 * Note that since sometime in O androidboot.slot_suffix is deprecated
98 * and androidboot.slot should be used instead. Since bootloaders may
99 * be out of sync with the OS, we check both and for extra safety
100 * prepend a leading underscore if there isn't one already.
101 */ 96 */
102static std::string get_ab_suffix() { 97static std::string get_ab_suffix() {
103 std::string ab_suffix = android::base::GetProperty("ro.boot.slot_suffix", ""); 98 return android::base::GetProperty("ro.boot.slot_suffix", "");
104 if (ab_suffix == "") {
105 ab_suffix = android::base::GetProperty("ro.boot.slot", "");
106 }
107 if (ab_suffix.size() > 0 && ab_suffix[0] != '_') {
108 ab_suffix = std::string("_") + ab_suffix;
109 }
110 return ab_suffix;
111} 99}
112 100
113/* Use AVB to turn verity on/off */ 101/* Use AVB to turn verity on/off */
diff --git a/adb/shell_service.cpp b/adb/shell_service.cpp
index ee821f834..0c7e1f99b 100644
--- a/adb/shell_service.cpp
+++ b/adb/shell_service.cpp
@@ -95,6 +95,7 @@
95#include <vector> 95#include <vector>
96 96
97#include <android-base/logging.h> 97#include <android-base/logging.h>
98#include <android-base/properties.h>
98#include <android-base/stringprintf.h> 99#include <android-base/stringprintf.h>
99#include <private/android_logger.h> 100#include <private/android_logger.h>
100 101
@@ -212,6 +213,13 @@ Subprocess::~Subprocess() {
212 WaitForExit(); 213 WaitForExit();
213} 214}
214 215
216static std::string GetHostName() {
217 char buf[HOST_NAME_MAX];
218 if (gethostname(buf, sizeof(buf)) != -1 && strcmp(buf, "localhost") != 0) return buf;
219
220 return android::base::GetProperty("ro.product.device", "android");
221}
222
215bool Subprocess::ForkAndExec(std::string* error) { 223bool Subprocess::ForkAndExec(std::string* error) {
216 unique_fd child_stdinout_sfd, child_stderr_sfd; 224 unique_fd child_stdinout_sfd, child_stderr_sfd;
217 unique_fd parent_error_sfd, child_error_sfd; 225 unique_fd parent_error_sfd, child_error_sfd;
@@ -250,11 +258,11 @@ bool Subprocess::ForkAndExec(std::string* error) {
250 } 258 }
251 259
252 if (pw != nullptr) { 260 if (pw != nullptr) {
253 // TODO: $HOSTNAME? Normally bash automatically sets that, but mksh doesn't.
254 env["HOME"] = pw->pw_dir; 261 env["HOME"] = pw->pw_dir;
262 env["HOSTNAME"] = GetHostName();
255 env["LOGNAME"] = pw->pw_name; 263 env["LOGNAME"] = pw->pw_name;
256 env["USER"] = pw->pw_name;
257 env["SHELL"] = pw->pw_shell; 264 env["SHELL"] = pw->pw_shell;
265 env["USER"] = pw->pw_name;
258 } 266 }
259 267
260 if (!terminal_type_.empty()) { 268 if (!terminal_type_.empty()) {
@@ -435,8 +443,7 @@ int Subprocess::OpenPtyChildFd(const char* pts_name, unique_fd* error_sfd) {
435void Subprocess::ThreadHandler(void* userdata) { 443void Subprocess::ThreadHandler(void* userdata) {
436 Subprocess* subprocess = reinterpret_cast<Subprocess*>(userdata); 444 Subprocess* subprocess = reinterpret_cast<Subprocess*>(userdata);
437 445
438 adb_thread_setname(android::base::StringPrintf( 446 adb_thread_setname(android::base::StringPrintf("shell svc %d", subprocess->pid()));
439 "shell srvc %d", subprocess->pid()));
440 447
441 D("passing data streams for PID %d", subprocess->pid()); 448 D("passing data streams for PID %d", subprocess->pid());
442 subprocess->PassDataStreams(); 449 subprocess->PassDataStreams();
diff --git a/adb/socket.h b/adb/socket.h
index 4acdf4a6d..64d05a92a 100644
--- a/adb/socket.h
+++ b/adb/socket.h
@@ -19,84 +19,83 @@
19 19
20#include <stddef.h> 20#include <stddef.h>
21 21
22#include <memory>
23
22#include "fdevent.h" 24#include "fdevent.h"
23 25
24struct apacket; 26struct apacket;
25class atransport; 27class atransport;
26 28
27/* An asocket represents one half of a connection between a local and 29/* An asocket represents one half of a connection between a local and
28** remote entity. A local asocket is bound to a file descriptor. A 30 * remote entity. A local asocket is bound to a file descriptor. A
29** remote asocket is bound to the protocol engine. 31 * remote asocket is bound to the protocol engine.
30*/ 32 */
31struct asocket { 33struct asocket {
32 /* chain pointers for the local/remote list of 34 /* chain pointers for the local/remote list of
33 ** asockets that this asocket lives in 35 * asockets that this asocket lives in
34 */ 36 */
35 asocket *next; 37 asocket* next;
36 asocket *prev; 38 asocket* prev;
37 39
38 /* the unique identifier for this asocket 40 /* the unique identifier for this asocket
39 */ 41 */
40 unsigned id; 42 unsigned id;
41 43
42 /* flag: set when the socket's peer has closed 44 /* flag: set when the socket's peer has closed
43 ** but packets are still queued for delivery 45 * but packets are still queued for delivery
44 */ 46 */
45 int closing; 47 int closing;
46 48
47 // flag: set when the socket failed to write, so the socket will not wait to 49 // flag: set when the socket failed to write, so the socket will not wait to
48 // write packets and close directly. 50 // write packets and close directly.
49 bool has_write_error; 51 bool has_write_error;
50 52
51 /* flag: quit adbd when both ends close the 53 /* flag: quit adbd when both ends close the
52 ** local service socket 54 * local service socket
53 */ 55 */
54 int exit_on_close; 56 int exit_on_close;
55
56 /* the asocket we are connected to
57 */
58 57
59 asocket *peer; 58 // the asocket we are connected to
59 asocket* peer;
60 60
61 /* For local asockets, the fde is used to bind 61 /* For local asockets, the fde is used to bind
62 ** us to our fd event system. For remote asockets 62 * us to our fd event system. For remote asockets
63 ** these fields are not used. 63 * these fields are not used.
64 */ 64 */
65 fdevent fde; 65 fdevent fde;
66 int fd; 66 int fd;
67 67
68 /* queue of apackets waiting to be written 68 // queue of apackets waiting to be written
69 */ 69 apacket* pkt_first;
70 apacket *pkt_first; 70 apacket* pkt_last;
71 apacket *pkt_last; 71
72 72 /* enqueue is called by our peer when it has data
73 /* enqueue is called by our peer when it has data 73 * for us. It should return 0 if we can accept more
74 ** for us. It should return 0 if we can accept more 74 * data or 1 if not. If we return 1, we must call
75 ** data or 1 if not. If we return 1, we must call 75 * peer->ready() when we once again are ready to
76 ** peer->ready() when we once again are ready to 76 * receive data.
77 ** receive data. 77 */
78 */ 78 int (*enqueue)(asocket* s, apacket* pkt);
79 int (*enqueue)(asocket *s, apacket *pkt); 79
80 80 /* ready is called by the peer when it is ready for
81 /* ready is called by the peer when it is ready for 81 * us to send data via enqueue again
82 ** us to send data via enqueue again 82 */
83 */ 83 void (*ready)(asocket* s);
84 void (*ready)(asocket *s); 84
85 85 /* shutdown is called by the peer before it goes away.
86 /* shutdown is called by the peer before it goes away. 86 * the socket should not do any further calls on its peer.
87 ** the socket should not do any further calls on its peer. 87 * Always followed by a call to close. Optional, i.e. can be NULL.
88 ** Always followed by a call to close. Optional, i.e. can be NULL. 88 */
89 */ 89 void (*shutdown)(asocket* s);
90 void (*shutdown)(asocket *s); 90
91 91 /* close is called by the peer when it has gone away.
92 /* close is called by the peer when it has gone away. 92 * we are not allowed to make any further calls on the
93 ** we are not allowed to make any further calls on the 93 * peer once our close method is called.
94 ** peer once our close method is called. 94 */
95 */ 95 void (*close)(asocket* s);
96 void (*close)(asocket *s); 96
97 97 /* A socket is bound to atransport */
98 /* A socket is bound to atransport */ 98 atransport* transport;
99 atransport *transport;
100 99
101 size_t get_max_payload() const; 100 size_t get_max_payload() const;
102}; 101};
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index f28a3df50..c53fbb4ff 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -96,7 +96,7 @@ void install_local_socket(asocket* s) {
96} 96}
97 97
98void remove_socket(asocket* s) { 98void remove_socket(asocket* s) {
99 // socket_list_lock should already be held 99 std::lock_guard<std::recursive_mutex> lock(local_socket_list_lock);
100 if (s->prev && s->next) { 100 if (s->prev && s->next) {
101 s->prev->next = s->next; 101 s->prev->next = s->next;
102 s->next->prev = s->prev; 102 s->next->prev = s->prev;
diff --git a/adb/test_device.py b/adb/test_device.py
index 9e1a2ec2d..ddceda9d9 100644
--- a/adb/test_device.py
+++ b/adb/test_device.py
@@ -1237,7 +1237,7 @@ class DeviceOfflineTest(DeviceTest):
1237 return m.group(2) 1237 return m.group(2)
1238 return None 1238 return None
1239 1239
1240 def test_killed_when_pushing_a_large_file(self): 1240 def disabled_test_killed_when_pushing_a_large_file(self):
1241 """ 1241 """
1242 While running adb push with a large file, kill adb server. 1242 While running adb push with a large file, kill adb server.
1243 Occasionally the device becomes offline. Because the device is still 1243 Occasionally the device becomes offline. Because the device is still
@@ -1268,7 +1268,7 @@ class DeviceOfflineTest(DeviceTest):
1268 # 4. The device should be online 1268 # 4. The device should be online
1269 self.assertEqual(self._get_device_state(serialno), 'device') 1269 self.assertEqual(self._get_device_state(serialno), 'device')
1270 1270
1271 def test_killed_when_pulling_a_large_file(self): 1271 def disabled_test_killed_when_pulling_a_large_file(self):
1272 """ 1272 """
1273 While running adb pull with a large file, kill adb server. 1273 While running adb pull with a large file, kill adb server.
1274 Occasionally the device can't be connected. Because the device is trying to 1274 Occasionally the device can't be connected. Because the device is trying to
diff --git a/adb/transport.cpp b/adb/transport.cpp
index b2e03a057..089a1ecf4 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -615,15 +615,15 @@ static void remove_transport(atransport* transport) {
615static void transport_unref(atransport* t) { 615static void transport_unref(atransport* t) {
616 CHECK(t != nullptr); 616 CHECK(t != nullptr);
617 617
618 size_t old_refcount = t->ref_count--; 618 std::lock_guard<std::recursive_mutex> lock(transport_lock);
619 CHECK_GT(old_refcount, 0u); 619 CHECK_GT(t->ref_count, 0u);
620 620 t->ref_count--;
621 if (old_refcount == 1u) { 621 if (t->ref_count == 0) {
622 D("transport: %s unref (kicking and closing)", t->serial); 622 D("transport: %s unref (kicking and closing)", t->serial);
623 t->close(t); 623 t->close(t);
624 remove_transport(t); 624 remove_transport(t);
625 } else { 625 } else {
626 D("transport: %s unref (count=%zu)", t->serial, old_refcount - 1); 626 D("transport: %s unref (count=%zu)", t->serial, t->ref_count);
627 } 627 }
628} 628}
629 629
@@ -748,9 +748,6 @@ atransport* acquire_one_transport(TransportType type, const char* serial, Transp
748} 748}
749 749
750int atransport::Write(apacket* p) { 750int atransport::Write(apacket* p) {
751#if ADB_HOST
752 std::lock_guard<std::mutex> lock(write_msg_lock_);
753#endif
754 return write_func_(p, this); 751 return write_func_(p, this);
755} 752}
756 753
@@ -758,11 +755,6 @@ void atransport::Kick() {
758 if (!kicked_) { 755 if (!kicked_) {
759 kicked_ = true; 756 kicked_ = true;
760 CHECK(kick_func_ != nullptr); 757 CHECK(kick_func_ != nullptr);
761#if ADB_HOST
762 // On host, adb server should avoid writing part of a packet, so don't
763 // kick a transport whiling writing a packet.
764 std::lock_guard<std::mutex> lock(write_msg_lock_);
765#endif
766 kick_func_(this); 758 kick_func_(this);
767 } 759 }
768} 760}
@@ -1109,11 +1101,4 @@ std::shared_ptr<RSA> atransport::NextKey() {
1109 keys_.pop_front(); 1101 keys_.pop_front();
1110 return result; 1102 return result;
1111} 1103}
1112bool atransport::SetSendConnectOnError() {
1113 if (has_send_connect_on_error_) {
1114 return false;
1115 }
1116 has_send_connect_on_error_ = true;
1117 return true;
1118}
1119#endif 1104#endif
diff --git a/adb/transport.h b/adb/transport.h
index 00fad5646..8c101fdc5 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -64,7 +64,7 @@ class atransport {
64 // it's better to do this piece by piece. 64 // it's better to do this piece by piece.
65 65
66 atransport(ConnectionState state = kCsOffline) 66 atransport(ConnectionState state = kCsOffline)
67 : id(NextTransportId()), ref_count(0), connection_state_(state) { 67 : id(NextTransportId()), connection_state_(state) {
68 transport_fde = {}; 68 transport_fde = {};
69 protocol_version = A_VERSION; 69 protocol_version = A_VERSION;
70 max_payload = MAX_PAYLOAD; 70 max_payload = MAX_PAYLOAD;
@@ -88,7 +88,7 @@ class atransport {
88 int fd = -1; 88 int fd = -1;
89 int transport_socket = -1; 89 int transport_socket = -1;
90 fdevent transport_fde; 90 fdevent transport_fde;
91 std::atomic<size_t> ref_count; 91 size_t ref_count = 0;
92 uint32_t sync_token = 0; 92 uint32_t sync_token = 0;
93 bool online = false; 93 bool online = false;
94 TransportType type = kTransportAny; 94 TransportType type = kTransportAny;
@@ -122,7 +122,6 @@ class atransport {
122 122
123#if ADB_HOST 123#if ADB_HOST
124 std::shared_ptr<RSA> NextKey(); 124 std::shared_ptr<RSA> NextKey();
125 bool SetSendConnectOnError();
126#endif 125#endif
127 126
128 char token[TOKEN_SIZE] = {}; 127 char token[TOKEN_SIZE] = {};
@@ -181,8 +180,6 @@ private:
181 std::atomic<ConnectionState> connection_state_; 180 std::atomic<ConnectionState> connection_state_;
182#if ADB_HOST 181#if ADB_HOST
183 std::deque<std::shared_ptr<RSA>> keys_; 182 std::deque<std::shared_ptr<RSA>> keys_;
184 std::mutex write_msg_lock_;
185 bool has_send_connect_on_error_ = false;
186#endif 183#endif
187 184
188 DISALLOW_COPY_AND_ASSIGN(atransport); 185 DISALLOW_COPY_AND_ASSIGN(atransport);
diff --git a/adb/transport_usb.cpp b/adb/transport_usb.cpp
index 6768d31a1..fdecccfc3 100644
--- a/adb/transport_usb.cpp
+++ b/adb/transport_usb.cpp
@@ -103,13 +103,6 @@ static int remote_read(apacket* p, atransport* t) {
103 103
104err_msg: 104err_msg:
105 p->msg.command = 0; 105 p->msg.command = 0;
106 if (t->GetConnectionState() == kCsOffline) {
107 // If the data toggle of ep_out on device and ep_in on host are not the same, we may receive
108 // an error message. In this case, resend one A_CNXN message to connect the device.
109 if (t->SetSendConnectOnError()) {
110 SendConnectOnHost(t);
111 }
112 }
113 return 0; 106 return 0;
114} 107}
115 108
@@ -162,8 +155,7 @@ static int remote_write(apacket *p, atransport *t)
162 return 0; 155 return 0;
163} 156}
164 157
165static void remote_close(atransport *t) 158static void remote_close(atransport* t) {
166{
167 usb_close(t->usb); 159 usb_close(t->usb);
168 t->usb = 0; 160 t->usb = 0;
169} 161}
diff --git a/base/Android.bp b/base/Android.bp
index 82aee2a38..0fd00ea5d 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -89,13 +89,12 @@ cc_library {
89 cppflags: ["-Wexit-time-destructors"], 89 cppflags: ["-Wexit-time-destructors"],
90 enabled: true, 90 enabled: true,
91 }, 91 },
92 linux: { 92 linux_glibc: {
93 srcs: [ 93 srcs: [
94 "chrono_utils.cpp", 94 "chrono_utils.cpp",
95 "errors_unix.cpp", 95 "errors_unix.cpp",
96 ], 96 ],
97 cppflags: ["-Wexit-time-destructors"], 97 cppflags: ["-Wexit-time-destructors"],
98 host_ldlibs: ["-lrt"],
99 }, 98 },
100 windows: { 99 windows: {
101 srcs: [ 100 srcs: [
@@ -136,9 +135,8 @@ cc_test {
136 misc_undefined: ["integer"], 135 misc_undefined: ["integer"],
137 }, 136 },
138 }, 137 },
139 linux: { 138 linux_glibc: {
140 srcs: ["chrono_utils_test.cpp"], 139 srcs: ["chrono_utils_test.cpp"],
141 host_ldlibs: ["-lrt"],
142 }, 140 },
143 windows: { 141 windows: {
144 srcs: ["utf8_test.cpp"], 142 srcs: ["utf8_test.cpp"],
diff --git a/base/chrono_utils.cpp b/base/chrono_utils.cpp
index b6bf701ea..dbe54830f 100644
--- a/base/chrono_utils.cpp
+++ b/base/chrono_utils.cpp
@@ -22,7 +22,7 @@ namespace android {
22namespace base { 22namespace base {
23 23
24boot_clock::time_point boot_clock::now() { 24boot_clock::time_point boot_clock::now() {
25#ifdef __ANDROID__ 25#ifdef __linux__
26 timespec ts; 26 timespec ts;
27 clock_gettime(CLOCK_BOOTTIME, &ts); 27 clock_gettime(CLOCK_BOOTTIME, &ts);
28 return boot_clock::time_point(std::chrono::seconds(ts.tv_sec) + 28 return boot_clock::time_point(std::chrono::seconds(ts.tv_sec) +
@@ -30,7 +30,7 @@ boot_clock::time_point boot_clock::now() {
30#else 30#else
31 // Darwin does not support clock_gettime. 31 // Darwin does not support clock_gettime.
32 return boot_clock::time_point(); 32 return boot_clock::time_point();
33#endif // __ANDROID__ 33#endif // __linux__
34} 34}
35 35
36std::ostream& operator<<(std::ostream& os, const Timer& t) { 36std::ostream& operator<<(std::ostream& os, const Timer& t) {
diff --git a/base/include/android-base/logging.h b/base/include/android-base/logging.h
index 548b286c4..f93c69615 100644
--- a/base/include/android-base/logging.h
+++ b/base/include/android-base/logging.h
@@ -438,4 +438,36 @@ class ScopedLogSeverity {
438} // namespace base 438} // namespace base
439} // namespace android 439} // namespace android
440 440
441namespace std {
442
443// Emit a warning of ostream<< with std::string*. The intention was most likely to print *string.
444//
445// Note: for this to work, we need to have this in a namespace.
446// Note: lots of ifdef magic to make this work with Clang (platform) vs GCC (windows tools)
447// Note: using diagnose_if(true) under Clang and nothing under GCC/mingw as there is no common
448// attribute support.
449// Note: using a pragma because "-Wgcc-compat" (included in "-Weverything") complains about
450// diagnose_if.
451// Note: to print the pointer, use "<< static_cast<const void*>(string_pointer)" instead.
452// Note: a not-recommended alternative is to let Clang ignore the warning by adding
453// -Wno-user-defined-warnings to CPPFLAGS.
454#ifdef __clang__
455#pragma clang diagnostic push
456#pragma clang diagnostic ignored "-Wgcc-compat"
457#define OSTREAM_STRING_POINTER_USAGE_WARNING \
458 __attribute__((diagnose_if(true, "Unexpected logging of string pointer", "warning")))
459#else
460#define OSTREAM_STRING_POINTER_USAGE_WARNING /* empty */
461#endif
462inline std::ostream& operator<<(std::ostream& stream, const std::string* string_pointer)
463 OSTREAM_STRING_POINTER_USAGE_WARNING {
464 return stream << static_cast<const void*>(string_pointer);
465}
466#ifdef __clang__
467#pragma clang diagnostic pop
468#endif
469#undef OSTREAM_STRING_POINTER_USAGE_WARNING
470
471} // namespace std
472
441#endif // ANDROID_BASE_LOGGING_H 473#endif // ANDROID_BASE_LOGGING_H
diff --git a/base/include/android-base/test_utils.h b/base/include/android-base/test_utils.h
index c0bf0c1e1..07a5edda0 100644
--- a/base/include/android-base/test_utils.h
+++ b/base/include/android-base/test_utils.h
@@ -26,6 +26,10 @@ class TemporaryFile {
26 TemporaryFile(); 26 TemporaryFile();
27 ~TemporaryFile(); 27 ~TemporaryFile();
28 28
29 // Release the ownership of fd, caller is reponsible for closing the
30 // fd or stream properly.
31 int release();
32
29 int fd; 33 int fd;
30 char path[1024]; 34 char path[1024];
31 35
diff --git a/base/properties.cpp b/base/properties.cpp
index 816bca0eb..cde4d69e3 100644
--- a/base/properties.cpp
+++ b/base/properties.cpp
@@ -36,13 +36,18 @@ std::string GetProperty(const std::string& key, const std::string& default_value
36 const prop_info* pi = __system_property_find(key.c_str()); 36 const prop_info* pi = __system_property_find(key.c_str());
37 if (pi == nullptr) return default_value; 37 if (pi == nullptr) return default_value;
38 38
39 char buf[PROP_VALUE_MAX]; 39 std::string property_value;
40 if (__system_property_read(pi, nullptr, buf) > 0) return buf; 40 __system_property_read_callback(pi,
41 [](void* cookie, const char*, const char* value, unsigned) {
42 auto property_value = reinterpret_cast<std::string*>(cookie);
43 *property_value = value;
44 },
45 &property_value);
41 46
42 // If the property exists but is empty, also return the default value. 47 // If the property exists but is empty, also return the default value.
43 // Since we can't remove system properties, "empty" is traditionally 48 // Since we can't remove system properties, "empty" is traditionally
44 // the same as "missing" (this was true for cutils' property_get). 49 // the same as "missing" (this was true for cutils' property_get).
45 return default_value; 50 return property_value.empty() ? default_value : property_value;
46} 51}
47 52
48bool GetBoolProperty(const std::string& key, bool default_value) { 53bool GetBoolProperty(const std::string& key, bool default_value) {
diff --git a/base/test_utils.cpp b/base/test_utils.cpp
index 636477d36..1cfa9e66f 100644
--- a/base/test_utils.cpp
+++ b/base/test_utils.cpp
@@ -85,10 +85,18 @@ TemporaryFile::TemporaryFile() {
85} 85}
86 86
87TemporaryFile::~TemporaryFile() { 87TemporaryFile::~TemporaryFile() {
88 close(fd); 88 if (fd != -1) {
89 close(fd);
90 }
89 unlink(path); 91 unlink(path);
90} 92}
91 93
94int TemporaryFile::release() {
95 int result = fd;
96 fd = -1;
97 return result;
98}
99
92void TemporaryFile::init(const std::string& tmp_dir) { 100void TemporaryFile::init(const std::string& tmp_dir) {
93 snprintf(path, sizeof(path), "%s%cTemporaryFile-XXXXXX", tmp_dir.c_str(), 101 snprintf(path, sizeof(path), "%s%cTemporaryFile-XXXXXX", tmp_dir.c_str(),
94 OS_PATH_SEPARATOR); 102 OS_PATH_SEPARATOR);
diff --git a/bootstat/Android.bp b/bootstat/Android.bp
index dd357edd7..2c870182c 100644
--- a/bootstat/Android.bp
+++ b/bootstat/Android.bp
@@ -63,7 +63,13 @@ cc_binary {
63 name: "bootstat", 63 name: "bootstat",
64 defaults: ["bootstat_defaults"], 64 defaults: ["bootstat_defaults"],
65 static_libs: ["libbootstat"], 65 static_libs: ["libbootstat"],
66 shared_libs: ["liblogcat"],
66 init_rc: ["bootstat.rc"], 67 init_rc: ["bootstat.rc"],
68 product_variables: {
69 debuggable: {
70 init_rc: ["bootstat-debug.rc"],
71 },
72 },
67 srcs: ["bootstat.cpp"], 73 srcs: ["bootstat.cpp"],
68} 74}
69 75
diff --git a/bootstat/boot_event_record_store.cpp b/bootstat/boot_event_record_store.cpp
index 99d94057c..e2a4b0403 100644
--- a/bootstat/boot_event_record_store.cpp
+++ b/bootstat/boot_event_record_store.cpp
@@ -58,16 +58,15 @@ BootEventRecordStore::BootEventRecordStore() {
58} 58}
59 59
60void BootEventRecordStore::AddBootEvent(const std::string& event) { 60void BootEventRecordStore::AddBootEvent(const std::string& event) {
61 auto uptime = std::chrono::duration_cast<std::chrono::seconds>( 61 auto uptime = std::chrono::duration_cast<std::chrono::seconds>(
62 android::base::boot_clock::now().time_since_epoch()); 62 android::base::boot_clock::now().time_since_epoch());
63 AddBootEventWithValue(event, uptime.count()); 63 AddBootEventWithValue(event, uptime.count());
64} 64}
65 65
66// The implementation of AddBootEventValue makes use of the mtime file 66// The implementation of AddBootEventValue makes use of the mtime file
67// attribute to store the value associated with a boot event in order to 67// attribute to store the value associated with a boot event in order to
68// optimize on-disk size requirements and small-file thrashing. 68// optimize on-disk size requirements and small-file thrashing.
69void BootEventRecordStore::AddBootEventWithValue( 69void BootEventRecordStore::AddBootEventWithValue(const std::string& event, int32_t value) {
70 const std::string& event, int32_t value) {
71 std::string record_path = GetBootEventPath(event); 70 std::string record_path = GetBootEventPath(event);
72 int record_fd = creat(record_path.c_str(), S_IRUSR | S_IWUSR); 71 int record_fd = creat(record_path.c_str(), S_IRUSR | S_IWUSR);
73 if (record_fd == -1) { 72 if (record_fd == -1) {
@@ -96,8 +95,7 @@ void BootEventRecordStore::AddBootEventWithValue(
96 close(record_fd); 95 close(record_fd);
97} 96}
98 97
99bool BootEventRecordStore::GetBootEvent( 98bool BootEventRecordStore::GetBootEvent(const std::string& event, BootEventRecord* record) const {
100 const std::string& event, BootEventRecord* record) const {
101 CHECK_NE(static_cast<BootEventRecord*>(nullptr), record); 99 CHECK_NE(static_cast<BootEventRecord*>(nullptr), record);
102 CHECK(!event.empty()); 100 CHECK(!event.empty());
103 101
@@ -112,8 +110,7 @@ bool BootEventRecordStore::GetBootEvent(
112 return true; 110 return true;
113} 111}
114 112
115std::vector<BootEventRecordStore::BootEventRecord> BootEventRecordStore:: 113std::vector<BootEventRecordStore::BootEventRecord> BootEventRecordStore::GetAllBootEvents() const {
116 GetAllBootEvents() const {
117 std::vector<BootEventRecord> events; 114 std::vector<BootEventRecord> events;
118 115
119 std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(store_path_.c_str()), closedir); 116 std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(store_path_.c_str()), closedir);
@@ -147,8 +144,7 @@ void BootEventRecordStore::SetStorePath(const std::string& path) {
147 store_path_ = path; 144 store_path_ = path;
148} 145}
149 146
150std::string BootEventRecordStore::GetBootEventPath( 147std::string BootEventRecordStore::GetBootEventPath(const std::string& event) const {
151 const std::string& event) const {
152 DCHECK_EQ('/', store_path_.back()); 148 DCHECK_EQ('/', store_path_.back());
153 return store_path_ + event; 149 return store_path_ + event;
154} 150}
diff --git a/bootstat/boot_event_record_store.h b/bootstat/boot_event_record_store.h
index a2b83184e..f872c85c8 100644
--- a/bootstat/boot_event_record_store.h
+++ b/bootstat/boot_event_record_store.h
@@ -17,12 +17,12 @@
17#ifndef BOOT_EVENT_RECORD_STORE_H_ 17#ifndef BOOT_EVENT_RECORD_STORE_H_
18#define BOOT_EVENT_RECORD_STORE_H_ 18#define BOOT_EVENT_RECORD_STORE_H_
19 19
20#include <android-base/macros.h>
21#include <gtest/gtest_prod.h>
20#include <cstdint> 22#include <cstdint>
21#include <string> 23#include <string>
22#include <utility> 24#include <utility>
23#include <vector> 25#include <vector>
24#include <android-base/macros.h>
25#include <gtest/gtest_prod.h>
26 26
27// BootEventRecordStore manages the persistence of boot events to the record 27// BootEventRecordStore manages the persistence of boot events to the record
28// store and the retrieval of all boot event records from the store. 28// store and the retrieval of all boot event records from the store.
diff --git a/bootstat/boot_event_record_store_test.cpp b/bootstat/boot_event_record_store_test.cpp
index d98169b87..4b7ab36ee 100644
--- a/bootstat/boot_event_record_store_test.cpp
+++ b/bootstat/boot_event_record_store_test.cpp
@@ -94,20 +94,16 @@ void DeleteDirectory(const std::string& path) {
94 94
95// Returns the time in seconds since boot. 95// Returns the time in seconds since boot.
96time_t GetUptimeSeconds() { 96time_t GetUptimeSeconds() {
97 return std::chrono::duration_cast<std::chrono::seconds>( 97 return std::chrono::duration_cast<std::chrono::seconds>(
98 android::base::boot_clock::now().time_since_epoch()) 98 android::base::boot_clock::now().time_since_epoch())
99 .count(); 99 .count();
100} 100}
101 101
102class BootEventRecordStoreTest : public ::testing::Test { 102class BootEventRecordStoreTest : public ::testing::Test {
103 public: 103 public:
104 BootEventRecordStoreTest() { 104 BootEventRecordStoreTest() { store_path_ = std::string(store_dir_.path) + "/"; }
105 store_path_ = std::string(store_dir_.path) + "/";
106 }
107 105
108 const std::string& GetStorePathForTesting() const { 106 const std::string& GetStorePathForTesting() const { return store_path_; }
109 return store_path_;
110 }
111 107
112 private: 108 private:
113 void TearDown() { 109 void TearDown() {
@@ -159,9 +155,7 @@ TEST_F(BootEventRecordStoreTest, AddMultipleBootEvents) {
159 store.AddBootEvent("triassic"); 155 store.AddBootEvent("triassic");
160 156
161 const std::string EXPECTED_NAMES[] = { 157 const std::string EXPECTED_NAMES[] = {
162 "cretaceous", 158 "cretaceous", "jurassic", "triassic",
163 "jurassic",
164 "triassic",
165 }; 159 };
166 160
167 auto events = store.GetAllBootEvents(); 161 auto events = store.GetAllBootEvents();
diff --git a/bootstat/boot_reason_test.sh b/bootstat/boot_reason_test.sh
new file mode 100755
index 000000000..209e81b4c
--- /dev/null
+++ b/bootstat/boot_reason_test.sh
@@ -0,0 +1,1069 @@
1#! /bin/bash
2#
3# Bootstat boot reason tests
4#
5# throughout testing:
6# - manual tests can only run on eng/userdebug builds
7# - watch adb logcat -b all -d -s bootstat
8# - watch adb logcat -b all -d | audit2allow
9# - wait until screen is up, boot has completed, can mean wait for
10# sys.boot_completed=1 and sys.logbootcomplete=1 to be true
11#
12# All test frames, and nothing else, must be function names prefixed and
13# specifiged with the pattern 'test_<test>() {' as this is also how the
14# script discovers the full list of tests by inspecting its own code.
15#
16
17# Helper variables
18
19SPACE=" "
20ESCAPE=""
21TAB=" "
22GREEN="${ESCAPE}[38;5;40m"
23RED="${ESCAPE}[38;5;196m"
24NORMAL="${ESCAPE}[0m"
25# Best guess to an average device's reboot time, refined as tests return
26DURATION_DEFAULT=45
27
28# Helper functions
29
30[ "USAGE: inFastboot
31
32Returns: true if device is in fastboot mode" ]
33inFastboot() {
34 fastboot devices | grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null
35}
36
37[ "USAGE: inAdb
38
39Returns: true if device is in adb mode" ]
40inAdb() {
41 adb devices | grep -v 'List of devices attached' | grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null
42}
43
44[ "USAGE: hasPstore
45
46Returns: true if device (likely) has pstore data" ]
47hasPstore() {
48 if inAdb && [ 0 -eq `adb shell su root ls /sys/fs/pstore | wc -l` ]; then
49 false
50 fi
51}
52
53[ "USAGE: isDebuggable
54
55Returns: true if device is (likely) a debug build" ]
56isDebuggable() {
57 if inAdb && [ 1 -ne `adb shell getprop ro.debuggable` ]; then
58 false
59 fi
60}
61
62[ "USAGE: checkDebugBuild [--noerror]
63
64Returns: true if device is a userdebug or eng release" ]
65checkDebugBuild() {
66 if isDebuggable; then
67 echo "INFO: '${TEST}' test requires userdebug build"
68 elif [ -n "${1}" ]; then
69 echo "WARNING: '${TEST}' test requires userdebug build"
70 false
71 else
72 echo "ERROR: '${TEST}' test requires userdebug build, skipping FAILURE"
73 duration_prefix="~"
74 duration_estimate=1
75 false
76 fi >&2
77}
78
79[ "USAGE: setBootloaderBootReason [value]
80
81Returns: true if device supports and set boot reason injection" ]
82setBootloaderBootReason() {
83 inAdb || ( echo "ERROR: device not in adb mode." >&2 ; false ) || return 1
84 if [ -z "`adb shell ls /etc/init/bootstat-debug.rc 2>/dev/null`" ]; then
85 echo "ERROR: '${TEST}' test requires /etc/init/bootstat-debug.rc" >&2
86 return 1
87 fi
88 checkDebugBuild || return 1
89 if adb shell su root "cat /proc/cmdline | tr '\\0 ' '\\n\\n'" |
90 grep '^androidboot[.]bootreason=[^ ]' >/dev/null; then
91 echo "ERROR: '${TEST}' test requires a device with a bootloader that" >&2
92 echo " does not set androidboot.bootreason kernel parameter." >&2
93 return 1
94 fi
95 adb shell su root setprop persist.test.boot.reason "'${1}'" 2>/dev/null
96 test_reason="`adb shell getprop persist.test.boot.reason 2>/dev/null`"
97 if [ X"${test_reason}" != X"${1}" ]; then
98 echo "ERROR: can not set persist.test.boot.reason to '${1}'." >&2
99 return 1
100 fi
101}
102
103[ "USAGE: enterPstore
104
105Prints a warning string requiring functional pstore
106
107Returns: pstore_ok variable set to true or false" ]
108enterPstore() {
109 if hasPstore; then
110 echo "INFO: '${TEST}' test requires functional and reliable pstore"
111 pstore_ok=true
112 else
113 echo "WARNING: '${TEST}' test requires functional pstore"
114 pstore_ok=false
115 fi >&2
116 ${pstore_ok}
117}
118
119[ "USAGE: exitPstore
120
121Prints an error string requiring functional pstore
122
123Returns: clears error if pstore dysfunctional" ]
124exitPstore() {
125 save_ret=${?}
126 if [ ${save_ret} != 0 ]; then
127 if hasPstore; then
128 return ${save_ret}
129 fi
130 if [ true = ${pstore_ok} ]; then
131 echo "WARNING: '${TEST}' test requires functional pstore"
132 return ${save_ret}
133 fi
134 echo "ERROR: '${TEST}' test requires functional pstore, skipping FAILURE"
135 duration_prefix="~"
136 duration_estimate=1
137 fi >&2
138}
139
140[ "USAGE: format_duration <seconds>
141
142human readable output whole seconds, whole minutes or mm:ss" ]
143format_duration() {
144 if [ -z "${1}" ]; then
145 echo unknown
146 return
147 fi
148 seconds=`expr ${1} % 60`
149 minutes=`expr ${1} / 60`
150 if [ 0 -eq ${minutes} ]; then
151 if [ 1 -eq ${1} ]; then
152 echo 1 second
153 return
154 fi
155 echo ${1} seconds
156 return
157 elif [ 60 -eq ${1} ]; then
158 echo 1 minute
159 return
160 elif [ 0 -eq ${seconds} ]; then
161 echo ${minutes} minutes
162 return
163 fi
164 echo ${minutes}:`expr ${seconds} / 10``expr ${seconds} % 10`
165}
166
167wait_for_screen_timeout=900
168[ "USAGE: wait_for_screen [-n] [TIMEOUT]
169
170-n - echo newline at exit
171TIMEOUT - default `format_duration ${wait_for_screen_timeout}`" ]
172wait_for_screen() {
173 exit_function=true
174 if [ X"-n" = X"${1}" ]; then
175 exit_function=echo
176 shift
177 fi
178 timeout=${wait_for_screen_timeout}
179 if [ ${#} -gt 0 ]; then
180 timeout=${1}
181 shift
182 fi
183 counter=0
184 while true; do
185 if inFastboot; then
186 fastboot reboot
187 elif inAdb; then
188 if [ 0 != ${counter} ]; then
189 adb wait-for-device </dev/null >/dev/null 2>/dev/null
190 fi
191 if [ -n "`adb shell getprop sys.boot.reason </dev/null 2>/dev/null`" ]
192 then
193 vals=`adb shell getprop </dev/null 2>/dev/null |
194 sed -n 's/[[]sys[.]\(boot_completed\|logbootcomplete\)[]]: [[]\([01]\)[]]$/\1=\2/p'`
195 if [ "${vals}" = "`echo boot_completed=1 ; echo logbootcomplete=1`" ]
196 then
197 break
198 fi
199 if [ "${vals}" = "`echo logbootcomplete=1 ; echo boot_completed=1`" ]
200 then
201 break
202 fi
203 fi
204 fi
205 counter=`expr ${counter} + 1`
206 if [ ${counter} -gt ${timeout} ]; then
207 ${exit_function}
208 echo "ERROR: wait_for_screen() timed out (`format_duration ${timeout}`)" >&2
209 return 1
210 fi
211 sleep 1
212 done
213 ${exit_function}
214}
215
216[ "USAGE: EXPECT_EQ <lval> <rval> [message]
217
218Returns true if (regex) lval matches rval" ]
219EXPECT_EQ() {
220 lval="${1}"
221 rval="${2}"
222 shift 2
223 if ! ( echo X"${rval}" | grep '^X'"${lval}"'$' >/dev/null 2>/dev/null ); then
224 echo "ERROR: expected \"${lval}\" got \"${rval}\"" >&2
225 if [ -n "${*}" ] ; then
226 echo " ${*}" >&2
227 fi
228 return 1
229 fi
230 if [ -n "${*}" ] ; then
231 if [ X"${lval}" != X"${rval}" ]; then
232 echo "INFO: ok \"${lval}\"(=\"${rval}\") ${*}" >&2
233 else
234 echo "INFO: ok \"${lval}\" ${*}" >&2
235 fi
236 fi
237 return 0
238}
239
240[ "USAGE: EXPECT_PROPERTY <prop> <value> [--allow_failure]
241
242Returns true if current return (regex) value is true and the result matches" ]
243EXPECT_PROPERTY() {
244 save_ret=${?}
245 property="${1}"
246 value="${2}"
247 shift 2
248 val=`adb shell getprop ${property} 2>&1`
249 EXPECT_EQ "${value}" "${val}" for Android property ${property} ||
250 [ -n "${1}" ] ||
251 save_ret=${?}
252 return ${save_ret}
253}
254
255[ "USAGE: report_bootstat_logs <expected> ...
256
257if not prefixed with a minus (-), <expected> will become a series of expected
258matches:
259
260 bootstat: Canonical boot reason: <expected_property_value>
261
262If prefixed with a minus, <expected> will look for an exact match after
263removing the minux prefix. All expected content is _dropped_ from the output
264and in essence forms a known blacklist, unexpected content will show.
265
266Report any logs, minus a known blacklist, preserve the current exit status" ]
267report_bootstat_logs() {
268 save_ret=${?}
269 match=
270 for i in "${@}"; do
271 if [ X"${i}" != X"${i#-}" ] ; then
272 match="${match}
273${i#-}"
274 else
275 match="${match}
276bootstat: Canonical boot reason: ${i}"
277 fi
278 done
279 adb logcat -b all -d |
280 grep bootstat[^e] |
281 grep -v -F "bootstat: Service started: /system/bin/bootstat --record_boot_complete${match}
282bootstat: Failed to read /data/misc/bootstat/post_decrypt_time_elapsed: No such file or directory
283bootstat: Failed to parse boot time record: /data/misc/bootstat/post_decrypt_time_elapsed
284bootstat: Service started: /system/bin/bootstat --record_boot_reason
285bootstat: Service started: /system/bin/bootstat --record_time_since_factory_reset
286bootstat: Service started: /system/bin/bootstat -l
287bootstat: Battery level at shutdown 100%
288bootstat: Battery level at startup 100%
289init : Parsing file /system/etc/init/bootstat.rc...
290init : processing action (persist.test.boot.reason=*) from (/system/etc/init/bootstat-debug.rc:
291init : Command 'setprop ro.boot.bootreason \${persist.test.boot.reason}' action=persist.test.boot.reason=* (/system/etc/init/bootstat-debug.rc:
292init : processing action (post-fs-data) from (/system/etc/init/bootstat.rc
293init : processing action (boot) from (/system/etc/init/bootstat.rc
294init : processing action (ro.boot.bootreason=*) from (/system/etc/init/bootstat.rc
295init : processing action (sys.boot_completed=1 && sys.logbootcomplete=1) from (/system/etc/init/bootstat.rc
296 (/system/bin/bootstat --record_boot_complete --record_boot_reason --record_time_since_factory_reset -l)'
297 (/system/bin/bootstat -r post_decrypt_time_elapsed)'
298init : Command 'exec - system log -- /system/bin/bootstat --record_boot_complete' action=sys.boot_completed=1 && sys.logbootcomplete=1 (/system/etc/init/bootstat.rc:
299init : Command 'exec - system log -- /system/bin/bootstat --record_boot_reason' action=sys.boot_completed=1 && sys.logbootcomplete=1 (/system/etc/init/bootstat.rc:
300init : Command 'exec - system log -- /system/bin/bootstat --record_time_since_factory_reset' action=sys.boot_completed=1 && sys.logbootcomplete=1 (/system/etc/init/bootstat.rc:
301 (/system/bin/bootstat --record_boot_complete)'...
302 (/system/bin/bootstat --record_boot_complete)' (pid${SPACE}
303 (/system/bin/bootstat --record_boot_reason)'...
304 (/system/bin/bootstat --record_boot_reason)' (pid${SPACE}
305 (/system/bin/bootstat --record_time_since_factory_reset)'...
306 (/system/bin/bootstat --record_time_since_factory_reset)' (pid${SPACE}
307 (/system/bin/bootstat -l)'...
308 (/system/bin/bootstat -l)' (pid " |
309 grep -v 'bootstat: Unknown boot reason: $' # Hikey Special
310 return ${save_ret}
311}
312
313[ "USAGE: start_test [message]
314
315Record start of test, preserve exit status" ]
316start_test() {
317 save_ret=${?}
318 duration_prefix="~"
319 duration_estimate=1
320 START=`date +%s`
321 echo "${GREEN}[ RUN ]${NORMAL} ${TEST} ${*}"
322 return ${save_ret}
323}
324
325duration_sum_diff=0
326duration_num=0
327[ "USAGE: duration_test [[prefix]seconds]
328
329Report the adjusted and expected test duration" ]
330duration_test() {
331 duration_prefix=${1%%[0123456789]*}
332 if [ -z "${duration_prefix}" ]; then
333 duration_prefix="~"
334 fi
335 duration_estimate="${1#${duration_prefix}}"
336 if [ -z "${duration_estimate}" ]; then
337 duration_estimate="${DURATION_DEFAULT}"
338 fi
339 duration_new_estimate="${duration_estimate}"
340 if [ 0 -ne ${duration_num} ]; then
341 duration_new_estimate=`expr ${duration_new_estimate} + \
342 \( ${duration_num} / 2 + ${duration_sum_diff} \) / ${duration_num}`
343 # guard against catastrophe
344 if [ -z "${duration_new_estimate}" ]; then
345 duration_new_estimate=${duration_estimate}
346 fi
347 fi
348 # negative values are so undignified
349 if [ 0 -ge ${duration_new_estimate} ]; then
350 duration_new_estimate=1
351 fi
352 echo "INFO: expected duration of '${TEST}' test" \
353 "${duration_prefix}`format_duration ${duration_new_estimate}`" >&2
354}
355
356[ "USAGE: end_test [message]
357
358Document duration and success of test, preserve exit status" ]
359end_test() {
360 save_ret=${?}
361 END=`date +%s`
362 duration=`expr ${END} - ${START} 2>/dev/null`
363 [ 0 -ge ${duration} ] ||
364 echo "INFO: '${TEST}' test duration `format_duration ${duration}`" >&2
365 if [ ${save_ret} = 0 ]; then
366 if [ 0 -lt ${duration} -a 0 -lt ${duration_estimate} -a \( \
367 X"~" = X"${duration_prefix}" -o \
368 ${duration_estimate} -gt ${duration} \) ]; then
369 duration_sum_diff=`expr ${duration_sum_diff} + \
370 ${duration} - ${duration_estimate}`
371 duration_num=`expr ${duration_num} + 1`
372 fi
373 echo "${GREEN}[ OK ]${NORMAL} ${TEST} ${*}"
374 else
375 echo "${RED}[ FAILED ]${NORMAL} ${TEST} ${*}"
376 fi
377 return ${save_ret}
378}
379
380[ "USAGE: wrap_test <test> [message]
381
382All tests below are wrapped with this helper" ]
383wrap_test() {
384 if [ -z "${1}" -o X"nothing" = X"${1}" ]; then
385 return
386 fi
387 TEST=${1}
388 shift
389 start_test ${1}
390 eval test_${TEST}
391 end_test ${2}
392}
393
394[ "USAGE: validate_reason <value>
395
396Check property for CTS compliance with our expectations. Return a cleansed
397string representing what is acceptable.
398
399NB: must also roughly match heuristics in system/core/bootstat/bootstat.cpp" ]
400validate_reason() {
401 var=`echo -n ${*} |
402 tr '[A-Z]' '[a-z]' |
403 tr ' \f\t\r\n' '_____'`
404 case ${var} in
405 watchdog | watchdog,?* ) ;;
406 kernel_panic | kernel_panic,?*) ;;
407 recovery | recovery,?*) ;;
408 bootloader | bootloader,?*) ;;
409 cold | cold,?*) ;;
410 hard | hard,?*) ;;
411 warm | warm,?*) ;;
412 shutdown | shutdown,?*) ;;
413 reboot,reboot | reboot,reboot,* ) var=${var#reboot,} ; var=${var%,} ;;
414 reboot,cold | reboot,cold,* ) var=${var#reboot,} ; var=${var%,} ;;
415 reboot,hard | reboot,hard,* ) var=${var#reboot,} ; var=${var%,} ;;
416 reboot,warm | reboot,warm,* ) var=${var#reboot,} ; var=${var%,} ;;
417 reboot,recovery | reboot,recovery,* ) var=${var#reboot,} ; var=${var%,} ;;
418 reboot,bootloader | reboot,bootloader,* ) var=${var#reboot,} ; var=${var%,} ;;
419 reboot | reboot,?*) ;;
420 # Aliases and Heuristics
421 *wdog* | *watchdog* ) var="watchdog" ;;
422 *powerkey* ) var="cold,powerkey" ;;
423 *panic* | *kernel_panic*) var="kernel_panic" ;;
424 *thermal*) var="shutdown,thermal" ;;
425 *s3_wakeup*) var="warm,s3_wakeup" ;;
426 *hw_reset*) var="hard,hw_reset" ;;
427 *bootloader*) var="bootloader" ;;
428 *) var="reboot" ;;
429 esac
430 echo ${var}
431}
432
433[ "USAGE: validate_property <property>
434
435Check property for CTS compliance with our expectations. Return a cleansed
436string representing what is acceptable.
437
438NB: must also roughly match heuristics in system/core/bootstat/bootstat.cpp" ]
439validate_property() {
440 val="`adb shell getprop ${1} 2>&1`"
441 ret=`validate_reason "${val}"`
442 if [ "reboot" = "${ret}" ]; then
443 ret=`validate_reason "reboot,${val}"`
444 fi
445 echo ${ret}
446}
447
448#
449# Actual test frames
450#
451
452[ "USAGE: test_properties
453
454properties test
455- (wait until screen is up, boot has completed)
456- adb shell getprop ro.boot.bootreason (bootloader reason)
457- adb shell getprop persist.sys.boot.reason (last reason)
458- adb shell getprop sys.boot.reason (system reason)
459- NB: all should have a value that is compliant with our known set." ]
460test_properties() {
461 duration_test 1
462 wait_for_screen
463 retval=0
464 check_set="ro.boot.bootreason persist.sys.boot.reason sys.boot.reason"
465 bootloader=""
466 # NB: this test could fail if performed _after_ optional_factory_reset test
467 # and will report
468 # ERROR: expected "reboot" got ""
469 # for Android property persist.sys.boot.reason
470 # following is mitigation for the persist.sys.boot.reason, skip it
471 if [ "reboot,factory_reset" = "`validate_property ro.boot_bootreason`" ]; then
472 check_set="ro.boot.bootreason sys.boot.reason"
473 bootloader="bootloader"
474 fi
475 for prop in ${check_set}; do
476 reason=`validate_property ${prop}`
477 EXPECT_PROPERTY ${prop} ${reason} || retval=${?}
478 done
479 # sys.boot.reason is last for a reason
480 report_bootstat_logs ${reason} ${bootloader}
481 return ${retval}
482}
483
484[ "USAGE: test_ota
485
486ota test
487- rm out/.kati_stamp-* out/build_date.txt out/build_number.txt
488- rm out/target/product/*/*/*.prop
489- rm -r out/target/product/*/obj/ETC/system_build_prop_intermediates
490- m
491- NB: ro.build.date.utc should update
492- fastboot flashall
493- (wait until screen is up, boot has completed)
494- adb shell getprop sys.boot.reason
495- NB: should report ota
496
497Decision to change the build itself rather than trick bootstat by
498rummaging through its data files was made." ]
499test_ota() {
500 duration_test ">300"
501 echo " extended by build and flashing times" >&2
502 if [ -z "${TARGET_PRODUCT}" -o \
503 -z "${ANDROID_PRODUCT_OUT}" -o \
504 -z "${ANDROID_BUILD_TOP}" -o \
505 -z "${TARGET_BUILD_VARIANT}" ]; then
506 echo "ERROR: Missing envsetup.sh and lunch" >&2
507 return 1
508 fi
509 rm ${ANDROID_PRODUCT_OUT%/out/*}/out/.kati_stamp-* ||
510 true
511 rm ${ANDROID_PRODUCT_OUT%/out/*}/out/build_date.txt ||
512 true
513 rm ${ANDROID_PRODUCT_OUT%/out/*}/out/build_number.txt ||
514 true
515 rm ${ANDROID_PRODUCT_OUT}/*/*.prop ||
516 true
517 rm -r ${ANDROID_PRODUCT_OUT}/obj/ETC/system_build_prop_intermediates ||
518 true
519 pushd ${ANDROID_BUILD_TOP} >&2
520 make -j50 >&2
521 if [ ${?} != 0 ]; then
522 popd >&2
523 return 1
524 fi
525 if ! inFastboot; then
526 adb reboot-bootloader >&2
527 fi
528 fastboot flashall >&2
529 popd >&2
530 wait_for_screen
531 EXPECT_PROPERTY sys.boot.reason "\(reboot,ota\|bootloader\)"
532 EXPECT_PROPERTY persist.sys.boot.reason bootloader
533 report_bootstat_logs reboot,ota bootloader
534}
535
536[ "USAGE: test_optional_ota
537
538fast and fake (touch build_date on device to make it different)" ]
539test_optional_ota() {
540 checkDebugBuild || return
541 duration_test
542 adb shell su root touch /data/misc/bootstat/build_date >&2
543 adb reboot ota
544 wait_for_screen
545 EXPECT_PROPERTY sys.boot.reason reboot,ota
546 EXPECT_PROPERTY persist.sys.boot.reason reboot,ota
547 report_bootstat_logs reboot,ota
548}
549
550[ "USAGE: [TEST=<test>] blind_reboot_test
551
552Simple tests helper
553- adb reboot <test>
554- (wait until screen is up, boot has completed)
555- adb shell getprop sys.boot.reason
556- NB: should report <test>, or reboot,<test> depending on canonical rules
557
558We interleave the simple reboot tests between the hard/complex ones
559as a means of checking sanity and any persistent side effect of the
560other tests." ]
561blind_reboot_test() {
562 duration_test
563 case ${TEST} in
564 bootloader | recovery | cold | hard | warm ) reason=${TEST} ;;
565 *) reason=reboot,${TEST} ;;
566 esac
567 adb reboot ${TEST}
568 wait_for_screen
569 EXPECT_PROPERTY sys.boot.reason ${reason}
570 EXPECT_PROPERTY persist.sys.boot.reason ${reason}
571 report_bootstat_logs ${reason}
572}
573
574[ "USAGE: test_cold
575
576cold test
577- adb reboot cold
578- (wait until screen is up, boot has completed)
579- adb shell getprop sys.boot.reason
580- NB: should report cold" ]
581test_cold() {
582 blind_reboot_test
583}
584
585[ "USAGE: test_factory_reset
586
587factory_reset test
588- adb shell su root rm /data/misc/bootstat/build_date
589- adb reboot
590- (wait until screen is up, boot has completed)
591- adb shell getprop sys.boot.reason
592- NB: should report factory_reset
593
594Decision to rummage through bootstat data files was made as
595a _real_ factory_reset is too destructive to the device." ]
596test_factory_reset() {
597 checkDebugBuild || return
598 duration_test
599 adb shell su root rm /data/misc/bootstat/build_date >&2
600 adb reboot >&2
601 wait_for_screen
602 EXPECT_PROPERTY sys.boot.reason reboot,factory_reset
603 EXPECT_PROPERTY persist.sys.boot.reason "reboot,.*"
604 report_bootstat_logs reboot,factory_reset reboot, reboot,adb \
605 "-bootstat: Failed to read /data/misc/bootstat/build_date: No such file or directory" \
606 "-bootstat: Failed to parse boot time record: /data/misc/bootstat/build_date"
607}
608
609[ "USAGE: test_optional_factory_reset
610
611factory_reset test
612- adb reboot-bootloader
613- fastboot format userdata
614- fastboot reboot
615- (wait until screen is up, boot has completed)
616- adb shell getprop sys.boot.reason
617- NB: should report factory_reset
618
619For realz, and disruptive" ]
620test_optional_factory_reset() {
621 duration_test 60
622 if ! inFastboot; then
623 adb reboot-bootloader
624 fi
625 fastboot format userdata >&2
626 fastboot reboot >&2
627 wait_for_screen
628 EXPECT_PROPERTY sys.boot.reason reboot,factory_reset
629 EXPECT_PROPERTY persist.sys.boot.reason ""
630 report_bootstat_logs reboot,factory_reset bootloader \
631 "-bootstat: Failed to read /data/misc/bootstat/last_boot_time_utc: No such file or directory" \
632 "-bootstat: Failed to parse boot time record: /data/misc/bootstat/last_boot_time_utc" \
633 "-bootstat: Failed to read /data/misc/bootstat/build_date: No such file or directory" \
634 "-bootstat: Failed to parse boot time record: /data/misc/bootstat/build_date" \
635 "-bootstat: Failed to read /data/misc/bootstat/factory_reset: No such file or directory" \
636 "-bootstat: Failed to parse boot time record: /data/misc/bootstat/factory_reset"
637}
638
639[ "USAGE: test_hard
640
641hard test:
642- adb reboot hard
643- (wait until screen is up, boot has completed)
644- adb shell getprop sys.boot.reason
645- NB: should report hard" ]
646test_hard() {
647 blind_reboot_test
648}
649
650[ "USAGE: test_battery
651
652battery test (trick):
653- echo healthd: battery l=2<space> | adb shell su root tee /dev/kmsg
654- adb reboot cold
655- (wait until screen is up, boot has completed)
656- adb shell getprop sys.boot.reason
657- NB: should report reboot,battery, unless healthd managed to log
658 before reboot in above trick.
659
660- Bonus points (manual extras)
661- Make sure the following is added to the /init.rc file in post-fs
662 section before logd is started:
663 + setprop logd.kernel false
664 + rm /sys/fs/pstore/console-ramoops
665 + rm /sys/fs/pstore/console-ramoops-0
666 + write /dev/kmsg \"healthd: battery l=2${SPACE}
667 +\"
668- adb reboot fs
669- (wait until screen is up, boot has completed)
670- adb shell getprop sys.boot.reason
671- NB: should report reboot,battery
672- (replace set logd.kernel true to the above, and retry test)" ]
673test_battery() {
674 checkDebugBuild || return
675 duration_test 120
676 enterPstore
677 # Send it _many_ times to combat devices with flakey pstore
678 for i in a b c d e f g h i j k l m n o p q r s t u v w x y z; do
679 echo 'healthd: battery l=2 ' | adb shell su root tee /dev/kmsg >/dev/null
680 done
681 adb reboot cold >&2
682 adb wait-for-device
683 wait_for_screen
684 adb shell su root \
685 cat /proc/fs/pstore/console-ramoops \
686 /proc/fs/pstore/console-ramoops-0 2>/dev/null |
687 grep 'healthd: battery l=' |
688 tail -1 |
689 grep 'healthd: battery l=2 ' >/dev/null || (
690 if ! EXPECT_PROPERTY sys.boot.reason reboot,battery >/dev/null 2>/dev/null; then
691 # retry
692 for i in a b c d e f g h i j k l m n o p q r s t u v w x y z; do
693 echo 'healthd: battery l=2 ' | adb shell su root tee /dev/kmsg >/dev/null
694 done
695 adb reboot cold >&2
696 adb wait-for-device
697 wait_for_screen
698 fi
699 )
700
701 EXPECT_PROPERTY sys.boot.reason shutdown,battery
702 EXPECT_PROPERTY persist.sys.boot.reason cold
703 report_bootstat_logs shutdown,battery "-bootstat: Battery level at shutdown 2%"
704 exitPstore
705}
706
707[ "USAGE: test_optional_battery
708
709battery shutdown test:
710- adb shell setprop sys.powerctl shutdown,battery
711- (power up the device)
712- (wait until screen is up, boot has completed)
713- adb shell getprop sys.boot.reason
714- NB: should report shutdown,battery" ]
715test_optional_battery() {
716 duration_test ">60"
717 echo " power on request" >&2
718 adb shell setprop sys.powerctl shutdown,battery
719 sleep 5
720 echo -n "WARNING: Please power device back up, waiting ... " >&2
721 wait_for_screen -n >&2
722 EXPECT_PROPERTY sys.boot.reason shutdown,battery
723 EXPECT_PROPERTY persist.sys.boot.reason shutdown,battery
724 report_bootstat_logs shutdown,battery
725}
726
727[ "USAGE: test_optional_battery_thermal
728
729battery thermal shutdown test:
730- adb shell setprop sys.powerctl shutdown,thermal,battery
731- (power up the device)
732- (wait until screen is up, boot has completed)
733- adb shell getprop sys.boot.reason
734- NB: should report shutdown,thermal,battery" ]
735test_optional_battery_thermal() {
736 duration_test ">60"
737 echo " power on request" >&2
738 adb shell setprop sys.powerctl shutdown,thermal,battery
739 sleep 5
740 echo -n "WARNING: Please power device back up, waiting ... " >&2
741 wait_for_screen -n >&2
742 EXPECT_PROPERTY sys.boot.reason shutdown,thermal,battery
743 EXPECT_PROPERTY persist.sys.boot.reason shutdown,thermal,battery
744 report_bootstat_logs shutdown,thermal,battery
745}
746
747[ "USAGE: test_unknown
748
749unknown test
750- adb reboot unknown
751- (wait until screen is up, boot has completed)
752- adb shell getprop sys.boot.reason
753- NB: should report reboot,unknown
754- NB: expect log \"... I bootstat: Unknown boot reason: reboot,unknown\"" ]
755test_unknown() {
756 blind_reboot_test
757}
758
759[ "USAGE: test_kernel_panic
760
761kernel_panic test:
762- echo c | adb shell su root tee /proc/sysrq-trigger
763- (wait until screen is up, boot has completed)
764- adb shell getprop sys.boot.reason
765- NB: should report kernel_panic,sysrq" ]
766test_kernel_panic() {
767 checkDebugBuild || return
768 duration_test ">90"
769 panic_msg="kernel_panic,sysrq"
770 enterPstore || panic_msg="\(kernel_panic,sysrq\|kernel_panic\)"
771 echo c | adb shell su root tee /proc/sysrq-trigger >/dev/null
772 wait_for_screen
773 EXPECT_PROPERTY sys.boot.reason ${panic_msg}
774 EXPECT_PROPERTY persist.sys.boot.reason ${panic_msg}
775 report_bootstat_logs kernel_panic,sysrq
776 exitPstore
777}
778
779[ "USAGE: test_warm
780
781warm test
782- adb reboot warm
783- (wait until screen is up, boot has completed)
784- adb shell getprop sys.boot.reason
785- NB: should report warm" ]
786test_warm() {
787 blind_reboot_test
788}
789
790[ "USAGE: test_thermal_shutdown
791
792thermal shutdown test:
793- adb shell setprop sys.powerctl shutdown,thermal
794- (power up the device)
795- (wait until screen is up, boot has completed)
796- adb shell getprop sys.boot.reason
797- NB: should report shutdown,thermal" ]
798test_thermal_shutdown() {
799 duration_test ">60"
800 echo " power on request" >&2
801 adb shell setprop sys.powerctl shutdown,thermal
802 sleep 5
803 echo -n "WARNING: Please power device back up, waiting ... " >&2
804 wait_for_screen -n >&2
805 EXPECT_PROPERTY sys.boot.reason shutdown,thermal
806 EXPECT_PROPERTY persist.sys.boot.reason shutdown,thermal
807 report_bootstat_logs shutdown,thermal
808}
809
810[ "USAGE: test_userrequested_shutdown
811
812userrequested shutdown test:
813- adb shell setprop sys.powerctl shutdown,userrequested
814- (power up the device)
815- (wait until screen is up, boot has completed)
816- adb shell getprop sys.boot.reason
817- NB: should report shutdown,userrequested" ]
818test_userrequested_shutdown() {
819 duration_test ">60"
820 echo " power on request" >&2
821 adb shell setprop sys.powerctl shutdown,userrequested
822 sleep 5
823 echo -n "WARNING: Please power device back up, waiting ... " >&2
824 wait_for_screen -n >&2
825 EXPECT_PROPERTY sys.boot.reason shutdown,userrequested
826 EXPECT_PROPERTY persist.sys.boot.reason shutdown,userrequested
827 report_bootstat_logs shutdown,userrequested
828}
829
830[ "USAGE: test_shell_reboot
831
832shell reboot test:
833- adb shell reboot
834- (wait until screen is up, boot has completed)
835- adb shell getprop sys.boot.reason
836- NB: should report reboot,shell" ]
837test_shell_reboot() {
838 duration_test
839 adb shell reboot
840 wait_for_screen
841 EXPECT_PROPERTY sys.boot.reason reboot,shell
842 EXPECT_PROPERTY persist.sys.boot.reason reboot,shell
843 report_bootstat_logs reboot,shell
844}
845
846[ "USAGE: test_adb_reboot
847
848adb reboot test:
849- adb reboot
850- (wait until screen is up, boot has completed)
851- adb shell getprop sys.boot.reason
852- NB: should report reboot,adb" ]
853test_adb_reboot() {
854 duration_test
855 adb reboot
856 wait_for_screen
857 EXPECT_PROPERTY sys.boot.reason reboot,adb
858 EXPECT_PROPERTY persist.sys.boot.reason reboot,adb
859 report_bootstat_logs reboot,adb
860}
861
862[ "USAGE: test_Its_Just_So_Hard_reboot
863
864Its Just So Hard reboot test:
865- adb shell reboot 'Its Just So Hard'
866- (wait until screen is up, boot has completed)
867- adb shell getprop sys.boot.reason
868- NB: should report reboot,its_just_so_hard
869- NB: expect log \"... I bootstat: Unknown boot reason: reboot,its_just_so_hard\"" ]
870test_Its_Just_So_Hard_reboot() {
871 duration_test
872 adb shell 'reboot "Its Just So Hard"'
873 wait_for_screen
874 EXPECT_PROPERTY sys.boot.reason reboot,its_just_so_hard
875 EXPECT_PROPERTY persist.sys.boot.reason "reboot,Its Just So Hard"
876 adb shell su root setprop persist.sys.boot.reason reboot,its_just_so_hard
877 if checkDebugBuild; then
878 flag=""
879 else
880 flag="--allow_failure"
881 fi
882 EXPECT_PROPERTY persist.sys.boot.reason reboot,its_just_so_hard ${flag}
883 report_bootstat_logs reboot,its_just_so_hard
884}
885
886[ "USAGE: run_bootloader [value [expected]]
887
888bootloader boot reason injection tests:
889- setBootloaderBootReason value
890- adb shell reboot
891- (wait until screen is up, boot has completed)
892- adb shell getprop sys.boot.reason
893- NB: should report reboot,value" ]
894run_bootloader() {
895 bootloader_expected="${1}"
896 if [ -z "${bootloader_expected}" ]; then
897 bootloader_expected="${TEST#bootloader_}"
898 fi
899 if ! setBootloaderBootReason ${bootloader_expected}; then
900 echo " Skipping FAILURE." 2>&1
901 return
902 fi
903 duration_test
904 if [ X"warm" = X"${bootloader_expected}" ]; then
905 last_expected=cold
906 else
907 last_expected=warm
908 fi
909 adb reboot ${last_expected}
910 wait_for_screen
911 # Reset so that other tests do not get unexpected injection
912 setBootloaderBootReason
913 # Determine the expected values
914 sys_expected="${2}"
915 if [ -z "${sys_expected}" ]; then
916 sys_expected="`validate_reason ${bootloader_expected}`"
917 if [ "reboot" = "${sys_expected}" ]; then
918 sys_expected="${last_expected}"
919 fi
920 else
921 sys_expected=`validate_reason ${sys_expected}`
922 fi
923 case ${sys_expected} in
924 kernel_panic | kernel_panic,* | watchdog | watchdog,* )
925 last_expected=${sys_expected}
926 ;;
927 esac
928 # Check values
929 EXPECT_PROPERTY ro.boot.bootreason "${bootloader_expected}"
930 EXPECT_PROPERTY sys.boot.reason "${sys_expected}"
931 EXPECT_PROPERTY persist.sys.boot.reason "${last_expected}"
932 report_bootstat_logs "${sys_expected}"
933}
934
935[ "USAGE: test_bootloader_<type>
936
937bootloader boot reasons test injection" ]
938test_bootloader_normal() {
939 run_bootloader
940}
941
942test_bootloader_watchdog() {
943 run_bootloader
944}
945
946test_bootloader_kernel_panic() {
947 run_bootloader
948}
949
950test_bootloader_oem_powerkey() {
951 run_bootloader
952}
953
954test_bootloader_wdog_reset() {
955 run_bootloader
956}
957
958test_bootloader_cold() {
959 run_bootloader
960}
961
962test_bootloader_warm() {
963 run_bootloader
964}
965
966test_bootloader_hard() {
967 run_bootloader
968}
969
970test_bootloader_recovery() {
971 run_bootloader
972}
973
974[ "USAGE: ${0##*/} [-s SERIAL] [tests]
975
976Mainline executive to run the above tests" ]
977
978# Rudimentary argument parsing
979
980if [ ${#} -ge 2 -a X"-s" = X"${1}" ]; then
981 export ANDROID_SERIAL="${2}"
982 shift 2
983fi
984
985if [ X"--help" = X"${1}" -o X"-h" = X"${1}" -o X"-?" = X"${1}" ]; then
986 echo "USAGE: ${0##*/} [-s SERIAL] [tests]"
987 echo tests - `sed -n 's/^test_\([^ ()]*\)() {/\1/p' $0 </dev/null`
988 exit 0
989fi
990
991# Check if all conditions for the script are sane
992
993if [ -z "${ANDROID_SERIAL}" ]; then
994 ndev=`(
995 adb devices | grep -v 'List of devices attached'
996 fastboot devices
997 ) |
998 grep -v "^[${SPACE}${TAB}]*\$" |
999 wc -l`
1000 if [ ${ndev} -gt 1 ]; then
1001 echo "ERROR: no target device specified, ${ndev} connected" >&2
1002 echo "${RED}[ FAILED ]${NORMAL}"
1003 exit 1
1004 fi
1005 echo "WARNING: no target device specified" >&2
1006fi
1007
1008ret=0
1009
1010# Test Series
1011if [ X"all" = X"${*}" ]; then
1012 # automagically pick up all test_<function>s.
1013 eval set nothing `sed -n 's/^test_\([^ ()]*\)() {/\1/p' $0 </dev/null`
1014 if [ X"nothing" = X"${1}" ]; then
1015 shift 1
1016 fi
1017fi
1018if [ -z "$*" ]; then
1019 # automagically pick up all test_<function>, except test_optional_<function>.
1020 eval set nothing `sed -n 's/^test_\([^ ()]*\)() {/\1/p' $0 </dev/null |
1021 grep -v '^optional_'`
1022 if [ -z "${2}" ]; then
1023 # Hard coded should shell fail to find them above (search/permission issues)
1024 eval set properties ota cold factory_reset hard battery unknown \
1025 kernel_panic warm thermal_shutdown userrequested_shutdown \
1026 shell_reboot adb_reboot Its_Just_So_Hard_reboot \
1027 bootloader_normal bootloader_watchdog bootloader_kernel_panic \
1028 bootloader_oem_powerkey bootloader_wdog_reset \
1029 bootloader_wdog_reset bootloader_wdog_reset bootloader_hard \
1030 bootloader_recovery
1031 fi
1032 if [ X"nothing" = X"${1}" ]; then
1033 shift 1
1034 fi
1035fi
1036echo "INFO: selected test(s): ${@}" >&2
1037echo
1038# Prepare device
1039setBootloaderBootReason 2>/dev/null
1040# Start pouring through the tests.
1041failures=
1042successes=
1043for t in "${@}"; do
1044 wrap_test ${t}
1045 retval=${?}
1046 if [ 0 = ${retval} ]; then
1047 if [ -z "${successes}" ]; then
1048 successes=${t}
1049 else
1050 successes="${successes} ${t}"
1051 fi
1052 else
1053 ret=${retval}
1054 if [ -z "${failures}" ]; then
1055 failures=${t}
1056 else
1057 failures="${failures} ${t}"
1058 fi
1059 fi
1060 echo
1061done
1062
1063if [ -n "${successes}" ]; then
1064 echo "${GREEN}[ PASSED ]${NORMAL} ${successes}"
1065fi
1066if [ -n "${failures}" ]; then
1067 echo "${RED}[ FAILED ]${NORMAL} ${failures}"
1068fi
1069exit ${ret}
diff --git a/bootstat/bootstat-debug.rc b/bootstat/bootstat-debug.rc
new file mode 100644
index 000000000..6a0044067
--- /dev/null
+++ b/bootstat/bootstat-debug.rc
@@ -0,0 +1,7 @@
1# This file is the userdebug LOCAL_INIT_RC file for the bootstat command.
2
3# FOR TESTING
4# For devices w/o bootloader boot reason reported, mirror test boot reason
5# to bootloader boot reason to allow test to inject reasons
6on property:persist.test.boot.reason=*
7 setprop ro.boot.bootreason ${persist.test.boot.reason}
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index bd611f0b9..f8eaa1cd3 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -19,6 +19,7 @@
19// uploaded to Android log storage via Tron. 19// uploaded to Android log storage via Tron.
20 20
21#include <getopt.h> 21#include <getopt.h>
22#include <sys/klog.h>
22#include <unistd.h> 23#include <unistd.h>
23 24
24#include <chrono> 25#include <chrono>
@@ -32,11 +33,14 @@
32#include <vector> 33#include <vector>
33 34
34#include <android-base/chrono_utils.h> 35#include <android-base/chrono_utils.h>
36#include <android-base/file.h>
35#include <android-base/logging.h> 37#include <android-base/logging.h>
36#include <android-base/parseint.h> 38#include <android-base/parseint.h>
37#include <android-base/strings.h> 39#include <android-base/strings.h>
38#include <android/log.h> 40#include <android/log.h>
41#include <cutils/android_reboot.h>
39#include <cutils/properties.h> 42#include <cutils/properties.h>
43#include <log/logcat.h>
40#include <metricslogger/metrics_logger.h> 44#include <metricslogger/metrics_logger.h>
41 45
42#include "boot_event_record_store.h" 46#include "boot_event_record_store.h"
@@ -57,8 +61,7 @@ void LogBootEvents() {
57// Records the named boot |event| to the record store. If |value| is non-empty 61// Records the named boot |event| to the record store. If |value| is non-empty
58// and is a proper string representation of an integer value, the converted 62// and is a proper string representation of an integer value, the converted
59// integer value is associated with the boot event. 63// integer value is associated with the boot event.
60void RecordBootEventFromCommandLine( 64void RecordBootEventFromCommandLine(const std::string& event, const std::string& value_str) {
61 const std::string& event, const std::string& value_str) {
62 BootEventRecordStore boot_event_store; 65 BootEventRecordStore boot_event_store;
63 if (!value_str.empty()) { 66 if (!value_str.empty()) {
64 int32_t value = 0; 67 int32_t value = 0;
@@ -81,7 +84,7 @@ void PrintBootEvents() {
81 } 84 }
82} 85}
83 86
84void ShowHelp(const char *cmd) { 87void ShowHelp(const char* cmd) {
85 fprintf(stderr, "Usage: %s [options]\n", cmd); 88 fprintf(stderr, "Usage: %s [options]\n", cmd);
86 fprintf(stderr, 89 fprintf(stderr,
87 "options include:\n" 90 "options include:\n"
@@ -97,7 +100,7 @@ void ShowHelp(const char *cmd) {
97 100
98// Constructs a readable, printable string from the givencommand line 101// Constructs a readable, printable string from the givencommand line
99// arguments. 102// arguments.
100std::string GetCommandLine(int argc, char **argv) { 103std::string GetCommandLine(int argc, char** argv) {
101 std::string cmd; 104 std::string cmd;
102 for (int i = 0; i < argc; ++i) { 105 for (int i = 0; i < argc; ++i) {
103 cmd += argv[i]; 106 cmd += argv[i];
@@ -118,6 +121,15 @@ std::string GetProperty(const char* key) {
118 return std::string(&temp[0], len); 121 return std::string(&temp[0], len);
119} 122}
120 123
124void SetProperty(const char* key, const std::string& val) {
125 property_set(key, val.c_str());
126}
127
128void SetProperty(const char* key, const char* val) {
129 property_set(key, val);
130}
131
132constexpr int32_t kEmptyBootReason = 0;
121constexpr int32_t kUnknownBootReason = 1; 133constexpr int32_t kUnknownBootReason = 1;
122 134
123// A mapping from boot reason string, as read from the ro.boot.bootreason 135// A mapping from boot reason string, as read from the ro.boot.bootreason
@@ -125,57 +137,81 @@ constexpr int32_t kUnknownBootReason = 1;
125// the boot_reason metric may refer to this mapping to discern the histogram 137// the boot_reason metric may refer to this mapping to discern the histogram
126// values. 138// values.
127const std::map<std::string, int32_t> kBootReasonMap = { 139const std::map<std::string, int32_t> kBootReasonMap = {
128 {"unknown", kUnknownBootReason}, 140 {"empty", kEmptyBootReason},
129 {"normal", 2}, 141 {"unknown", kUnknownBootReason},
130 {"recovery", 3}, 142 {"normal", 2},
131 {"reboot", 4}, 143 {"recovery", 3},
132 {"PowerKey", 5}, 144 {"reboot", 4},
133 {"hard_reset", 6}, 145 {"PowerKey", 5},
134 {"kernel_panic", 7}, 146 {"hard_reset", 6},
135 {"rpm_err", 8}, 147 {"kernel_panic", 7},
136 {"hw_reset", 9}, 148 {"rpm_err", 8},
137 {"tz_err", 10}, 149 {"hw_reset", 9},
138 {"adsp_err", 11}, 150 {"tz_err", 10},
139 {"modem_err", 12}, 151 {"adsp_err", 11},
140 {"mba_err", 13}, 152 {"modem_err", 12},
141 {"Watchdog", 14}, 153 {"mba_err", 13},
142 {"Panic", 15}, 154 {"Watchdog", 14},
143 {"power_key", 16}, 155 {"Panic", 15},
144 {"power_on", 17}, 156 {"power_key", 16},
145 {"Reboot", 18}, 157 {"power_on", 17},
146 {"rtc", 19}, 158 {"Reboot", 18},
147 {"edl", 20}, 159 {"rtc", 19},
148 {"oem_pon1", 21}, 160 {"edl", 20},
149 {"oem_powerkey", 22}, 161 {"oem_pon1", 21},
150 {"oem_unknown_reset", 23}, 162 {"oem_powerkey", 22},
151 {"srto: HWWDT reset SC", 24}, 163 {"oem_unknown_reset", 23},
152 {"srto: HWWDT reset platform", 25}, 164 {"srto: HWWDT reset SC", 24},
153 {"srto: bootloader", 26}, 165 {"srto: HWWDT reset platform", 25},
154 {"srto: kernel panic", 27}, 166 {"srto: bootloader", 26},
155 {"srto: kernel watchdog reset", 28}, 167 {"srto: kernel panic", 27},
156 {"srto: normal", 29}, 168 {"srto: kernel watchdog reset", 28},
157 {"srto: reboot", 30}, 169 {"srto: normal", 29},
158 {"srto: reboot-bootloader", 31}, 170 {"srto: reboot", 30},
159 {"srto: security watchdog reset", 32}, 171 {"srto: reboot-bootloader", 31},
160 {"srto: wakesrc", 33}, 172 {"srto: security watchdog reset", 32},
161 {"srto: watchdog", 34}, 173 {"srto: wakesrc", 33},
162 {"srto:1-1", 35}, 174 {"srto: watchdog", 34},
163 {"srto:omap_hsmm", 36}, 175 {"srto:1-1", 35},
164 {"srto:phy0", 37}, 176 {"srto:omap_hsmm", 36},
165 {"srto:rtc0", 38}, 177 {"srto:phy0", 37},
166 {"srto:touchpad", 39}, 178 {"srto:rtc0", 38},
167 {"watchdog", 40}, 179 {"srto:touchpad", 39},
168 {"watchdogr", 41}, 180 {"watchdog", 40},
169 {"wdog_bark", 42}, 181 {"watchdogr", 41},
170 {"wdog_bite", 43}, 182 {"wdog_bark", 42},
171 {"wdog_reset", 44}, 183 {"wdog_bite", 43},
172 {"shutdown,", 45}, // Trailing comma is intentional. 184 {"wdog_reset", 44},
173 {"shutdown,userrequested", 46}, 185 {"shutdown,", 45}, // Trailing comma is intentional.
174 {"reboot,bootloader", 47}, 186 {"shutdown,userrequested", 46},
175 {"reboot,cold", 48}, 187 {"reboot,bootloader", 47},
176 {"reboot,recovery", 49}, 188 {"reboot,cold", 48},
177 {"thermal_shutdown", 50}, 189 {"reboot,recovery", 49},
178 {"s3_wakeup", 51} 190 {"thermal_shutdown", 50},
191 {"s3_wakeup", 51},
192 {"kernel_panic,sysrq", 52},
193 {"kernel_panic,NULL", 53},
194 {"kernel_panic,BUG", 54},
195 {"bootloader", 55},
196 {"cold", 56},
197 {"hard", 57},
198 {"warm", 58},
199 {"recovery", 59},
200 {"thermal-shutdown", 60},
201 {"shutdown,thermal", 61},
202 {"shutdown,battery", 62},
203 {"reboot,ota", 63},
204 {"reboot,factory_reset", 64},
205 {"reboot,", 65},
206 {"reboot,shell", 66},
207 {"reboot,adb", 67},
208 {"reboot,userrequested", 68},
209 {"shutdown,container", 69}, // Host OS asking Android Container to shutdown
210 {"cold,powerkey", 70},
211 {"warm,s3_wakeup", 71},
212 {"hard,hw_reset", 72},
213 {"shutdown,suspend", 73}, // Suspend to RAM
214 {"shutdown,hibernate", 74}, // Suspend to DISK
179}; 215};
180 216
181// Converts a string value representing the reason the system booted to an 217// Converts a string value representing the reason the system booted to an
@@ -187,10 +223,373 @@ int32_t BootReasonStrToEnum(const std::string& boot_reason) {
187 return mapping->second; 223 return mapping->second;
188 } 224 }
189 225
226 if (boot_reason.empty()) {
227 return kEmptyBootReason;
228 }
229
190 LOG(INFO) << "Unknown boot reason: " << boot_reason; 230 LOG(INFO) << "Unknown boot reason: " << boot_reason;
191 return kUnknownBootReason; 231 return kUnknownBootReason;
192} 232}
193 233
234// Canonical list of supported primary reboot reasons.
235const std::vector<const std::string> knownReasons = {
236 // clang-format off
237 // kernel
238 "watchdog",
239 "kernel_panic",
240 // strong
241 "recovery", // Should not happen from ro.boot.bootreason
242 "bootloader", // Should not happen from ro.boot.bootreason
243 // blunt
244 "cold",
245 "hard",
246 "warm",
247 // super blunt
248 "shutdown", // Can not happen from ro.boot.bootreason
249 "reboot", // Default catch-all for anything unknown
250 // clang-format on
251};
252
253// Returns true if the supplied reason prefix is considered detailed enough.
254bool isStrongRebootReason(const std::string& r) {
255 for (auto& s : knownReasons) {
256 if (s == "cold") break;
257 // Prefix defined as terminated by a nul or comma (,).
258 if (android::base::StartsWith(r, s.c_str()) &&
259 ((r.length() == s.length()) || (r[s.length()] == ','))) {
260 return true;
261 }
262 }
263 return false;
264}
265
266// Returns true if the supplied reason prefix is associated with the kernel.
267bool isKernelRebootReason(const std::string& r) {
268 for (auto& s : knownReasons) {
269 if (s == "recovery") break;
270 // Prefix defined as terminated by a nul or comma (,).
271 if (android::base::StartsWith(r, s.c_str()) &&
272 ((r.length() == s.length()) || (r[s.length()] == ','))) {
273 return true;
274 }
275 }
276 return false;
277}
278
279// Returns true if the supplied reason prefix is considered known.
280bool isKnownRebootReason(const std::string& r) {
281 for (auto& s : knownReasons) {
282 // Prefix defined as terminated by a nul or comma (,).
283 if (android::base::StartsWith(r, s.c_str()) &&
284 ((r.length() == s.length()) || (r[s.length()] == ','))) {
285 return true;
286 }
287 }
288 return false;
289}
290
291// If the reboot reason should be improved, report true if is too blunt.
292bool isBluntRebootReason(const std::string& r) {
293 if (isStrongRebootReason(r)) return false;
294
295 if (!isKnownRebootReason(r)) return true; // Can not support unknown as detail
296
297 size_t pos = 0;
298 while ((pos = r.find(',', pos)) != std::string::npos) {
299 ++pos;
300 std::string next(r.substr(pos));
301 if (next.length() == 0) break;
302 if (next[0] == ',') continue;
303 if (!isKnownRebootReason(next)) return false; // Unknown subreason is good.
304 if (isStrongRebootReason(next)) return false; // eg: reboot,reboot
305 }
306 return true;
307}
308
309bool readPstoreConsole(std::string& console) {
310 if (android::base::ReadFileToString("/sys/fs/pstore/console-ramoops-0", &console)) {
311 return true;
312 }
313 return android::base::ReadFileToString("/sys/fs/pstore/console-ramoops", &console);
314}
315
316bool addKernelPanicSubReason(const std::string& console, std::string& ret) {
317 // Check for kernel panic types to refine information
318 if (console.rfind("SysRq : Trigger a crash") != std::string::npos) {
319 // Can not happen, except on userdebug, during testing/debugging.
320 ret = "kernel_panic,sysrq";
321 return true;
322 }
323 if (console.rfind("Unable to handle kernel NULL pointer dereference at virtual address") !=
324 std::string::npos) {
325 ret = "kernel_panic,NULL";
326 return true;
327 }
328 if (console.rfind("Kernel BUG at ") != std::string::npos) {
329 ret = "kernel_panic,BUG";
330 return true;
331 }
332 return false;
333}
334
335// std::transform Helper callback functions:
336// Converts a string value representing the reason the system booted to a
337// string complying with Android system standard reason.
338char tounderline(char c) {
339 return ::isblank(c) ? '_' : c;
340}
341char toprintable(char c) {
342 return ::isprint(c) ? c : '?';
343}
344
345const char system_reboot_reason_property[] = "sys.boot.reason";
346const char last_reboot_reason_property[] = LAST_REBOOT_REASON_PROPERTY;
347const char bootloader_reboot_reason_property[] = "ro.boot.bootreason";
348
349// Scrub, Sanitize, Standardize and Enhance the boot reason string supplied.
350std::string BootReasonStrToReason(const std::string& boot_reason) {
351 static const size_t max_reason_length = 256;
352
353 std::string ret(GetProperty(system_reboot_reason_property));
354 std::string reason(boot_reason);
355 // If sys.boot.reason == ro.boot.bootreason, let's re-evaluate
356 if (reason == ret) ret = "";
357
358 // Cleanup boot_reason regarding acceptable character set
359 std::transform(reason.begin(), reason.end(), reason.begin(), ::tolower);
360 std::transform(reason.begin(), reason.end(), reason.begin(), tounderline);
361 std::transform(reason.begin(), reason.end(), reason.begin(), toprintable);
362
363 // Is the current system boot reason sys.boot.reason valid?
364 if (!isKnownRebootReason(ret)) ret = "";
365
366 if (ret == "") {
367 // Is the bootloader boot reason ro.boot.bootreason known?
368 std::vector<std::string> words(android::base::Split(reason, ",_-"));
369 for (auto& s : knownReasons) {
370 std::string blunt;
371 for (auto& r : words) {
372 if (r == s) {
373 if (isBluntRebootReason(s)) {
374 blunt = s;
375 } else {
376 ret = s;
377 break;
378 }
379 }
380 }
381 if (ret == "") ret = blunt;
382 if (ret != "") break;
383 }
384 }
385
386 if (ret == "") {
387 // A series of checks to take some officially unsupported reasons
388 // reported by the bootloader and find some logical and canonical
389 // sense. In an ideal world, we would require those bootloaders
390 // to behave and follow our standards.
391 static const std::vector<std::pair<const std::string, const std::string>> aliasReasons = {
392 {"watchdog", "wdog"},
393 {"cold,powerkey", "powerkey"},
394 {"kernel_panic", "panic"},
395 {"shutdown,thermal", "thermal"},
396 {"warm,s3_wakeup", "s3_wakeup"},
397 {"hard,hw_reset", "hw_reset"},
398 {"bootloader", ""},
399 };
400
401 // Either the primary or alias is found _somewhere_ in the reason string.
402 for (auto& s : aliasReasons) {
403 if (reason.find(s.first) != std::string::npos) {
404 ret = s.first;
405 break;
406 }
407 if (s.second.size() && (reason.find(s.second) != std::string::npos)) {
408 ret = s.first;
409 break;
410 }
411 }
412 }
413
414 // If watchdog is the reason, see if there is a security angle?
415 if (ret == "watchdog") {
416 if (reason.find("sec") != std::string::npos) {
417 ret += ",security";
418 }
419 }
420
421 if (ret == "kernel_panic") {
422 // Check to see if last klog has some refinement hints.
423 std::string content;
424 if (readPstoreConsole(content)) {
425 addKernelPanicSubReason(content, ret);
426 }
427 } else if (isBluntRebootReason(ret)) {
428 // Check the other available reason resources if the reason is still blunt.
429
430 // Check to see if last klog has some refinement hints.
431 std::string content;
432 if (readPstoreConsole(content)) {
433 // The toybox reboot command used directly (unlikely)? But also
434 // catches init's response to Android's more controlled reboot command.
435 if (content.rfind("reboot: Power down") != std::string::npos) {
436 ret = "shutdown"; // Still too blunt, but more accurate.
437 // ToDo: init should record the shutdown reason to kernel messages ala:
438 // init: shutdown system with command 'last_reboot_reason'
439 // so that if pstore has persistence we can get some details
440 // that could be missing in last_reboot_reason_property.
441 }
442
443 static const char cmd[] = "reboot: Restarting system with command '";
444 size_t pos = content.rfind(cmd);
445 if (pos != std::string::npos) {
446 pos += strlen(cmd);
447 std::string subReason(content.substr(pos, max_reason_length));
448 for (pos = 0; pos < subReason.length(); ++pos) {
449 char c = tounderline(subReason[pos]);
450 if (!::isprint(c) || (c == '\'')) {
451 subReason.erase(pos);
452 break;
453 }
454 subReason[pos] = ::tolower(c);
455 }
456 if (subReason != "") { // Will not land "reboot" as that is too blunt.
457 if (isKernelRebootReason(subReason)) {
458 ret = "reboot," + subReason; // User space can't talk kernel reasons.
459 } else {
460 ret = subReason;
461 }
462 }
463 }
464
465 // Check for kernel panics, allowed to override reboot command.
466 if (!addKernelPanicSubReason(content, ret) &&
467 // check for long-press power down
468 ((content.rfind("Power held for ") != std::string::npos) ||
469 (content.rfind("charger: [") != std::string::npos))) {
470 ret = "cold";
471 }
472 }
473
474 // The following battery test should migrate to a default system health HAL
475
476 // Let us not worry if the reboot command was issued, for the cases of
477 // reboot -p, reboot <no reason>, reboot cold, reboot warm and reboot hard.
478 // Same for bootloader and ro.boot.bootreasons of this set, but a dead
479 // battery could conceivably lead to these, so worthy of override.
480 if (isBluntRebootReason(ret)) {
481 // Heuristic to determine if shutdown possibly because of a dead battery?
482 // Really a hail-mary pass to find it in last klog content ...
483 static const int battery_dead_threshold = 2; // percent
484 static const char battery[] = "healthd: battery l=";
485 size_t pos = content.rfind(battery); // last one
486 std::string digits;
487 if (pos != std::string::npos) {
488 digits = content.substr(pos + strlen(battery));
489 }
490 char* endptr = NULL;
491 unsigned long long level = strtoull(digits.c_str(), &endptr, 10);
492 if ((level <= 100) && (endptr != digits.c_str()) && (*endptr == ' ')) {
493 LOG(INFO) << "Battery level at shutdown " << level << "%";
494 if (level <= battery_dead_threshold) {
495 ret = "shutdown,battery";
496 }
497 } else { // Most likely
498 digits = ""; // reset digits
499
500 // Content buffer no longer will have console data. Beware if more
501 // checks added below, that depend on parsing console content.
502 content = "";
503
504 LOG(DEBUG) << "Can not find last low battery in last console messages";
505 android_logcat_context ctx = create_android_logcat();
506 FILE* fp = android_logcat_popen(&ctx, "logcat -b kernel -v brief -d");
507 if (fp != nullptr) {
508 android::base::ReadFdToString(fileno(fp), &content);
509 }
510 android_logcat_pclose(&ctx, fp);
511 android_logcat_destroy(&ctx);
512 static const char logcat_battery[] = "W/healthd ( 0): battery l=";
513 const char* match = logcat_battery;
514
515 if (content == "") {
516 // Service logd.klog not running, go to smaller buffer in the kernel.
517 int rc = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
518 if (rc > 0) {
519 ssize_t len = rc + 1024; // 1K Margin should it grow between calls.
520 std::unique_ptr<char[]> buf(new char[len]);
521 rc = klogctl(KLOG_READ_ALL, buf.get(), len);
522 if (rc < len) {
523 len = rc + 1;
524 }
525 buf[--len] = '\0';
526 content = buf.get();
527 }
528 match = battery;
529 }
530
531 pos = content.find(match); // The first one it finds.
532 if (pos != std::string::npos) {
533 digits = content.substr(pos + strlen(match));
534 }
535 endptr = NULL;
536 level = strtoull(digits.c_str(), &endptr, 10);
537 if ((level <= 100) && (endptr != digits.c_str()) && (*endptr == ' ')) {
538 LOG(INFO) << "Battery level at startup " << level << "%";
539 if (level <= battery_dead_threshold) {
540 ret = "shutdown,battery";
541 }
542 } else {
543 LOG(DEBUG) << "Can not find first battery level in dmesg or logcat";
544 }
545 }
546 }
547
548 // Is there a controlled shutdown hint in last_reboot_reason_property?
549 if (isBluntRebootReason(ret)) {
550 // Content buffer no longer will have console data. Beware if more
551 // checks added below, that depend on parsing console content.
552 content = GetProperty(last_reboot_reason_property);
553 // Cleanup last_boot_reason regarding acceptable character set
554 std::transform(content.begin(), content.end(), content.begin(), ::tolower);
555 std::transform(content.begin(), content.end(), content.begin(), tounderline);
556 std::transform(content.begin(), content.end(), content.begin(), toprintable);
557
558 // Anything in last is better than 'super-blunt' reboot or shutdown.
559 if ((ret == "") || (ret == "reboot") || (ret == "shutdown") || !isBluntRebootReason(content)) {
560 ret = content;
561 }
562 }
563
564 // Other System Health HAL reasons?
565
566 // ToDo: /proc/sys/kernel/boot_reason needs a HAL interface to
567 // possibly offer hardware-specific clues from the PMIC.
568 }
569
570 // If unknown left over from above, make it "reboot,<boot_reason>"
571 if (ret == "") {
572 ret = "reboot";
573 if (android::base::StartsWith(reason, "reboot")) {
574 reason = reason.substr(strlen("reboot"));
575 while ((reason[0] == ',') || (reason[0] == '_')) {
576 reason = reason.substr(1);
577 }
578 }
579 if (reason != "") {
580 ret += ",";
581 ret += reason;
582 }
583 }
584
585 LOG(INFO) << "Canonical boot reason: " << ret;
586 if (isKernelRebootReason(ret) && (GetProperty(last_reboot_reason_property) != "")) {
587 // Rewrite as it must be old news, kernel reasons trump user space.
588 SetProperty(last_reboot_reason_property, ret);
589 }
590 return ret;
591}
592
194// Returns the appropriate metric key prefix for the boot_complete metric such 593// Returns the appropriate metric key prefix for the boot_complete metric such
195// that boot metrics after a system update are labeled as ota_boot_complete; 594// that boot metrics after a system update are labeled as ota_boot_complete;
196// otherwise, they are labeled as boot_complete. This method encapsulates the 595// otherwise, they are labeled as boot_complete. This method encapsulates the
@@ -212,17 +611,20 @@ std::string CalculateBootCompletePrefix() {
212 if (!boot_event_store.GetBootEvent(kBuildDateKey, &record)) { 611 if (!boot_event_store.GetBootEvent(kBuildDateKey, &record)) {
213 boot_complete_prefix = "factory_reset_" + boot_complete_prefix; 612 boot_complete_prefix = "factory_reset_" + boot_complete_prefix;
214 boot_event_store.AddBootEventWithValue(kBuildDateKey, build_date); 613 boot_event_store.AddBootEventWithValue(kBuildDateKey, build_date);
614 LOG(INFO) << "Canonical boot reason: reboot,factory_reset";
615 SetProperty(system_reboot_reason_property, "reboot,factory_reset");
215 } else if (build_date != record.second) { 616 } else if (build_date != record.second) {
216 boot_complete_prefix = "ota_" + boot_complete_prefix; 617 boot_complete_prefix = "ota_" + boot_complete_prefix;
217 boot_event_store.AddBootEventWithValue(kBuildDateKey, build_date); 618 boot_event_store.AddBootEventWithValue(kBuildDateKey, build_date);
619 LOG(INFO) << "Canonical boot reason: reboot,ota";
620 SetProperty(system_reboot_reason_property, "reboot,ota");
218 } 621 }
219 622
220 return boot_complete_prefix; 623 return boot_complete_prefix;
221} 624}
222 625
223// Records the value of a given ro.boottime.init property in milliseconds. 626// Records the value of a given ro.boottime.init property in milliseconds.
224void RecordInitBootTimeProp( 627void RecordInitBootTimeProp(BootEventRecordStore* boot_event_store, const char* property) {
225 BootEventRecordStore* boot_event_store, const char* property) {
226 std::string value = GetProperty(property); 628 std::string value = GetProperty(property);
227 629
228 int32_t time_in_ms; 630 int32_t time_in_ms;
@@ -307,10 +709,8 @@ void RecordBootComplete() {
307 709
308 if (boot_event_store.GetBootEvent("last_boot_time_utc", &record)) { 710 if (boot_event_store.GetBootEvent("last_boot_time_utc", &record)) {
309 time_t last_boot_time_utc = record.second; 711 time_t last_boot_time_utc = record.second;
310 time_t time_since_last_boot = difftime(current_time_utc, 712 time_t time_since_last_boot = difftime(current_time_utc, last_boot_time_utc);
311 last_boot_time_utc); 713 boot_event_store.AddBootEventWithValue("time_since_last_boot", time_since_last_boot);
312 boot_event_store.AddBootEventWithValue("time_since_last_boot",
313 time_since_last_boot);
314 } 714 }
315 715
316 boot_event_store.AddBootEventWithValue("last_boot_time_utc", current_time_utc); 716 boot_event_store.AddBootEventWithValue("last_boot_time_utc", current_time_utc);
@@ -336,8 +736,7 @@ void RecordBootComplete() {
336 boot_event_store.AddBootEventWithValue(boot_complete_prefix + "_post_decrypt", 736 boot_event_store.AddBootEventWithValue(boot_complete_prefix + "_post_decrypt",
337 boot_complete.count()); 737 boot_complete.count());
338 } else { 738 } else {
339 boot_event_store.AddBootEventWithValue(boot_complete_prefix + "_no_encryption", 739 boot_event_store.AddBootEventWithValue(boot_complete_prefix + "_no_encryption", uptime.count());
340 uptime.count());
341 } 740 }
342 741
343 // Record the total time from device startup to boot complete, regardless of 742 // Record the total time from device startup to boot complete, regardless of
@@ -358,9 +757,33 @@ void RecordBootComplete() {
358// Records the boot_reason metric by querying the ro.boot.bootreason system 757// Records the boot_reason metric by querying the ro.boot.bootreason system
359// property. 758// property.
360void RecordBootReason() { 759void RecordBootReason() {
361 int32_t boot_reason = BootReasonStrToEnum(GetProperty("ro.boot.bootreason")); 760 const std::string reason(GetProperty(bootloader_reboot_reason_property));
761
762 if (reason.empty()) {
763 // Log an empty boot reason value as '<EMPTY>' to ensure the value is intentional
764 // (and not corruption anywhere else in the reporting pipeline).
765 android::metricslogger::LogMultiAction(android::metricslogger::ACTION_BOOT,
766 android::metricslogger::FIELD_PLATFORM_REASON, "<EMPTY>");
767 } else {
768 android::metricslogger::LogMultiAction(android::metricslogger::ACTION_BOOT,
769 android::metricslogger::FIELD_PLATFORM_REASON, reason);
770 }
771
772 // Log the raw bootloader_boot_reason property value.
773 int32_t boot_reason = BootReasonStrToEnum(reason);
362 BootEventRecordStore boot_event_store; 774 BootEventRecordStore boot_event_store;
363 boot_event_store.AddBootEventWithValue("boot_reason", boot_reason); 775 boot_event_store.AddBootEventWithValue("boot_reason", boot_reason);
776
777 // Log the scrubbed system_boot_reason.
778 const std::string system_reason(BootReasonStrToReason(reason));
779 int32_t system_boot_reason = BootReasonStrToEnum(system_reason);
780 boot_event_store.AddBootEventWithValue("system_boot_reason", system_boot_reason);
781
782 // Record the scrubbed system_boot_reason to the property
783 SetProperty(system_reboot_reason_property, system_reason);
784 if (reason == "") {
785 SetProperty(bootloader_reboot_reason_property, system_reason);
786 }
364} 787}
365 788
366// Records two metrics related to the user resetting a device: the time at 789// Records two metrics related to the user resetting a device: the time at
@@ -374,21 +797,20 @@ void RecordFactoryReset() {
374 797
375 if (current_time_utc < 0) { 798 if (current_time_utc < 0) {
376 // UMA does not display negative values in buckets, so convert to positive. 799 // UMA does not display negative values in buckets, so convert to positive.
377 android::metricslogger::LogHistogram( 800 android::metricslogger::LogHistogram("factory_reset_current_time_failure",
378 "factory_reset_current_time_failure", std::abs(current_time_utc)); 801 std::abs(current_time_utc));
379 802
380 // Logging via BootEventRecordStore to see if using android::metricslogger::LogHistogram 803 // Logging via BootEventRecordStore to see if using android::metricslogger::LogHistogram
381 // is losing records somehow. 804 // is losing records somehow.
382 boot_event_store.AddBootEventWithValue( 805 boot_event_store.AddBootEventWithValue("factory_reset_current_time_failure",
383 "factory_reset_current_time_failure", std::abs(current_time_utc)); 806 std::abs(current_time_utc));
384 return; 807 return;
385 } else { 808 } else {
386 android::metricslogger::LogHistogram("factory_reset_current_time", current_time_utc); 809 android::metricslogger::LogHistogram("factory_reset_current_time", current_time_utc);
387 810
388 // Logging via BootEventRecordStore to see if using android::metricslogger::LogHistogram 811 // Logging via BootEventRecordStore to see if using android::metricslogger::LogHistogram
389 // is losing records somehow. 812 // is losing records somehow.
390 boot_event_store.AddBootEventWithValue( 813 boot_event_store.AddBootEventWithValue("factory_reset_current_time", current_time_utc);
391 "factory_reset_current_time", current_time_utc);
392 } 814 }
393 815
394 // The factory_reset boot event does not exist after the device is reset, so 816 // The factory_reset boot event does not exist after the device is reset, so
@@ -408,18 +830,15 @@ void RecordFactoryReset() {
408 830
409 // Logging via BootEventRecordStore to see if using android::metricslogger::LogHistogram 831 // Logging via BootEventRecordStore to see if using android::metricslogger::LogHistogram
410 // is losing records somehow. 832 // is losing records somehow.
411 boot_event_store.AddBootEventWithValue( 833 boot_event_store.AddBootEventWithValue("factory_reset_record_value", factory_reset_utc);
412 "factory_reset_record_value", factory_reset_utc);
413 834
414 time_t time_since_factory_reset = difftime(current_time_utc, 835 time_t time_since_factory_reset = difftime(current_time_utc, factory_reset_utc);
415 factory_reset_utc); 836 boot_event_store.AddBootEventWithValue("time_since_factory_reset", time_since_factory_reset);
416 boot_event_store.AddBootEventWithValue("time_since_factory_reset",
417 time_since_factory_reset);
418} 837}
419 838
420} // namespace 839} // namespace
421 840
422int main(int argc, char **argv) { 841int main(int argc, char** argv) {
423 android::base::InitLogging(argv); 842 android::base::InitLogging(argv);
424 843
425 const std::string cmd_line = GetCommandLine(argc, argv); 844 const std::string cmd_line = GetCommandLine(argc, argv);
@@ -431,15 +850,17 @@ int main(int argc, char **argv) {
431 static const char boot_reason_str[] = "record_boot_reason"; 850 static const char boot_reason_str[] = "record_boot_reason";
432 static const char factory_reset_str[] = "record_time_since_factory_reset"; 851 static const char factory_reset_str[] = "record_time_since_factory_reset";
433 static const struct option long_options[] = { 852 static const struct option long_options[] = {
434 { "help", no_argument, NULL, 'h' }, 853 // clang-format off
435 { "log", no_argument, NULL, 'l' }, 854 { "help", no_argument, NULL, 'h' },
436 { "print", no_argument, NULL, 'p' }, 855 { "log", no_argument, NULL, 'l' },
437 { "record", required_argument, NULL, 'r' }, 856 { "print", no_argument, NULL, 'p' },
438 { value_str, required_argument, NULL, 0 }, 857 { "record", required_argument, NULL, 'r' },
439 { boot_complete_str, no_argument, NULL, 0 }, 858 { value_str, required_argument, NULL, 0 },
440 { boot_reason_str, no_argument, NULL, 0 }, 859 { boot_complete_str, no_argument, NULL, 0 },
441 { factory_reset_str, no_argument, NULL, 0 }, 860 { boot_reason_str, no_argument, NULL, 0 },
442 { NULL, 0, NULL, 0 } 861 { factory_reset_str, no_argument, NULL, 0 },
862 { NULL, 0, NULL, 0 }
863 // clang-format on
443 }; 864 };
444 865
445 std::string boot_event; 866 std::string boot_event;
diff --git a/bootstat/bootstat.rc b/bootstat/bootstat.rc
index d697efba0..f06a38ff1 100644
--- a/bootstat/bootstat.rc
+++ b/bootstat/bootstat.rc
@@ -1,5 +1,9 @@
1# This file is the LOCAL_INIT_RC file for the bootstat command. 1# This file is the LOCAL_INIT_RC file for the bootstat command.
2 2
3# mirror bootloader boot reason to system boot reason
4on property:ro.boot.bootreason=*
5 setprop sys.boot.reason ${ro.boot.bootreason}
6
3on post-fs-data 7on post-fs-data
4 mkdir /data/misc/bootstat 0700 system log 8 mkdir /data/misc/bootstat 0700 system log
5 # To deal with ota transition resulting from a change in DAC from 9 # To deal with ota transition resulting from a change in DAC from
@@ -8,16 +12,16 @@ on post-fs-data
8 chown system log /data/misc/bootstat/boot_complete 12 chown system log /data/misc/bootstat/boot_complete
9 chown system log /data/misc/bootstat/boot_complete_no_encryption 13 chown system log /data/misc/bootstat/boot_complete_no_encryption
10 chown system log /data/misc/bootstat/boot_reason 14 chown system log /data/misc/bootstat/boot_reason
11 chown system log /data/misc/bootstat/bootime.bootloader.1BLE 15 chown system log /data/misc/bootstat/boottime.bootloader.1BLE
12 chown system log /data/misc/bootstat/bootime.bootloader.1BLL 16 chown system log /data/misc/bootstat/boottime.bootloader.1BLL
13 chown system log /data/misc/bootstat/bootime.bootloader.2BLE 17 chown system log /data/misc/bootstat/boottime.bootloader.2BLE
14 chown system log /data/misc/bootstat/bootime.bootloader.2BLL 18 chown system log /data/misc/bootstat/boottime.bootloader.2BLL
15 chown system log /data/misc/bootstat/bootime.bootloader.AVB 19 chown system log /data/misc/bootstat/boottime.bootloader.AVB
16 chown system log /data/misc/bootstat/bootime.bootloader.KD 20 chown system log /data/misc/bootstat/boottime.bootloader.KD
17 chown system log /data/misc/bootstat/bootime.bootloader.KL 21 chown system log /data/misc/bootstat/boottime.bootloader.KL
18 chown system log /data/misc/bootstat/bootime.bootloader.ODT 22 chown system log /data/misc/bootstat/boottime.bootloader.ODT
19 chown system log /data/misc/bootstat/bootime.bootloader.SW 23 chown system log /data/misc/bootstat/boottime.bootloader.SW
20 chown system log /data/misc/bootstat/bootime.bootloader.total 24 chown system log /data/misc/bootstat/boottime.bootloader.total
21 chown system log /data/misc/bootstat/build_date 25 chown system log /data/misc/bootstat/build_date
22 chown system log /data/misc/bootstat/factory_reset 26 chown system log /data/misc/bootstat/factory_reset
23 chown system log /data/misc/bootstat/factory_reset_boot_complete 27 chown system log /data/misc/bootstat/factory_reset_boot_complete
@@ -42,7 +46,7 @@ on post-fs-data
42# property:init.svc.bootanim=running: The boot animation is running 46# property:init.svc.bootanim=running: The boot animation is running
43# property:ro.crypto.type=block: FDE device 47# property:ro.crypto.type=block: FDE device
44on post-fs-data && property:init.svc.bootanim=running && property:ro.crypto.type=block 48on post-fs-data && property:init.svc.bootanim=running && property:ro.crypto.type=block
45 exec - system log -- /system/bin/bootstat -r post_decrypt_time_elapsed 49 exec_background - system log -- /system/bin/bootstat -r post_decrypt_time_elapsed
46 50
47# sys.logbootcomplete is a signal to enable the bootstat logging mechanism. 51# sys.logbootcomplete is a signal to enable the bootstat logging mechanism.
48# This signaling is necessary to prevent logging boot metrics after a runtime 52# This signaling is necessary to prevent logging boot metrics after a runtime
@@ -65,13 +69,7 @@ on property:init.svc.zygote=stopping
65# Record boot complete metrics. 69# Record boot complete metrics.
66on property:sys.boot_completed=1 && property:sys.logbootcomplete=1 70on property:sys.boot_completed=1 && property:sys.logbootcomplete=1
67 # Record boot_complete and related stats (decryption, etc). 71 # Record boot_complete and related stats (decryption, etc).
68 exec - system log -- /system/bin/bootstat --record_boot_complete
69
70 # Record the boot reason. 72 # Record the boot reason.
71 exec - system log -- /system/bin/bootstat --record_boot_reason
72
73 # Record time since factory reset. 73 # Record time since factory reset.
74 exec - system log -- /system/bin/bootstat --record_time_since_factory_reset
75
76 # Log all boot events. 74 # Log all boot events.
77 exec - system log -- /system/bin/bootstat -l 75 exec_background - system log -- /system/bin/bootstat --record_boot_complete --record_boot_reason --record_time_since_factory_reset -l
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 35139801f..6ef3ed650 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -47,13 +47,14 @@
47#define ATRACE_TAG ATRACE_TAG_BIONIC 47#define ATRACE_TAG ATRACE_TAG_BIONIC
48#include <utils/Trace.h> 48#include <utils/Trace.h>
49 49
50#include "backtrace.h" 50#include "libdebuggerd/backtrace.h"
51#include "tombstone.h" 51#include "libdebuggerd/tombstone.h"
52#include "utility.h" 52#include "libdebuggerd/utility.h"
53 53
54#include "debuggerd/handler.h" 54#include "debuggerd/handler.h"
55#include "protocol.h"
56#include "tombstoned/tombstoned.h" 55#include "tombstoned/tombstoned.h"
56
57#include "protocol.h"
57#include "util.h" 58#include "util.h"
58 59
59using android::base::unique_fd; 60using android::base::unique_fd;
@@ -461,14 +462,14 @@ int main(int argc, char** argv) {
461 if (wait_for_gdb) { 462 if (wait_for_gdb) {
462 // Use ALOGI to line up with output from engrave_tombstone. 463 // Use ALOGI to line up with output from engrave_tombstone.
463 ALOGI( 464 ALOGI(
464 "***********************************************************\n" 465 "***********************************************************\n"
465 "* Process %d has been suspended while crashing.\n" 466 "* Process %d has been suspended while crashing.\n"
466 "* To attach gdbserver and start gdb, run this on the host:\n" 467 "* To attach gdbserver and start gdb, run this on the host:\n"
467 "*\n" 468 "*\n"
468 "* gdbclient.py -p %d\n" 469 "* gdbclient.py -p %d\n"
469 "*\n" 470 "*\n"
470 "***********************************************************", 471 "***********************************************************",
471 target, main_tid); 472 target, target);
472 } 473 }
473 474
474 if (fatal_signal) { 475 if (fatal_signal) {
diff --git a/debuggerd/crasher/Android.bp b/debuggerd/crasher/Android.bp
index b7b19384b..67b4ab7b5 100644
--- a/debuggerd/crasher/Android.bp
+++ b/debuggerd/crasher/Android.bp
@@ -17,7 +17,7 @@ cc_defaults {
17 arm: { 17 arm: {
18 srcs: ["arm/crashglue.S"], 18 srcs: ["arm/crashglue.S"],
19 19
20 armv7_a_neon: { 20 neon: {
21 asflags: ["-DHAS_VFP_D32"], 21 asflags: ["-DHAS_VFP_D32"],
22 }, 22 },
23 }, 23 },
diff --git a/debuggerd/crasher/crasher.cpp b/debuggerd/crasher/crasher.cpp
index f57349b16..e9a3ebd5b 100644
--- a/debuggerd/crasher/crasher.cpp
+++ b/debuggerd/crasher/crasher.cpp
@@ -114,6 +114,11 @@ noinline int do_action_on_thread(const char* arg) {
114 return reinterpret_cast<uintptr_t>(result); 114 return reinterpret_cast<uintptr_t>(result);
115} 115}
116 116
117noinline int crash_null() {
118 int (*null_func)() = nullptr;
119 return null_func();
120}
121
117noinline int crash3(int a) { 122noinline int crash3(int a) {
118 *reinterpret_cast<int*>(0xdead) = a; 123 *reinterpret_cast<int*>(0xdead) = a;
119 return a*4; 124 return a*4;
@@ -169,6 +174,7 @@ static int usage() {
169 fprintf(stderr, " nostack crash with a NULL stack pointer\n"); 174 fprintf(stderr, " nostack crash with a NULL stack pointer\n");
170 fprintf(stderr, "\n"); 175 fprintf(stderr, "\n");
171 fprintf(stderr, " heap-usage cause a libc abort by abusing a heap function\n"); 176 fprintf(stderr, " heap-usage cause a libc abort by abusing a heap function\n");
177 fprintf(stderr, " call-null cause a crash by calling through a nullptr\n");
172 fprintf(stderr, " leak leak memory until we get OOM-killed\n"); 178 fprintf(stderr, " leak leak memory until we get OOM-killed\n");
173 fprintf(stderr, "\n"); 179 fprintf(stderr, "\n");
174 fprintf(stderr, " abort call abort()\n"); 180 fprintf(stderr, " abort call abort()\n");
@@ -239,6 +245,8 @@ noinline int do_action(const char* arg) {
239 crashnostack(); 245 crashnostack();
240 } else if (!strcasecmp(arg, "exit")) { 246 } else if (!strcasecmp(arg, "exit")) {
241 exit(1); 247 exit(1);
248 } else if (!strcasecmp(arg, "call-null")) {
249 return crash_null();
242 } else if (!strcasecmp(arg, "crash") || !strcmp(arg, "SIGSEGV")) { 250 } else if (!strcasecmp(arg, "crash") || !strcmp(arg, "SIGSEGV")) {
243 return crash(42); 251 return crash(42);
244 } else if (!strcasecmp(arg, "abort")) { 252 } else if (!strcasecmp(arg, "abort")) {
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index dbf81a4ee..45e768dbc 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -19,6 +19,7 @@
19#include <sys/capability.h> 19#include <sys/capability.h>
20#include <sys/prctl.h> 20#include <sys/prctl.h>
21#include <sys/ptrace.h> 21#include <sys/ptrace.h>
22#include <sys/syscall.h>
22#include <sys/types.h> 23#include <sys/types.h>
23#include <unistd.h> 24#include <unistd.h>
24 25
diff --git a/debuggerd/handler/debuggerd_fallback.cpp b/debuggerd/handler/debuggerd_fallback.cpp
index 43104ecbd..06d4a9b72 100644
--- a/debuggerd/handler/debuggerd_fallback.cpp
+++ b/debuggerd/handler/debuggerd_fallback.cpp
@@ -45,8 +45,8 @@
45#include "tombstoned/tombstoned.h" 45#include "tombstoned/tombstoned.h"
46#include "util.h" 46#include "util.h"
47 47
48#include "backtrace.h" 48#include "libdebuggerd/backtrace.h"
49#include "tombstone.h" 49#include "libdebuggerd/tombstone.h"
50 50
51using android::base::unique_fd; 51using android::base::unique_fd;
52 52
diff --git a/debuggerd/libdebuggerd/arm/machine.cpp b/debuggerd/libdebuggerd/arm/machine.cpp
index ac833aef2..bfb5ea4e9 100644
--- a/debuggerd/libdebuggerd/arm/machine.cpp
+++ b/debuggerd/libdebuggerd/arm/machine.cpp
@@ -17,6 +17,8 @@
17 17
18#define LOG_TAG "DEBUG" 18#define LOG_TAG "DEBUG"
19 19
20#include "libdebuggerd/machine.h"
21
20#include <errno.h> 22#include <errno.h>
21#include <stdint.h> 23#include <stdint.h>
22#include <string.h> 24#include <string.h>
@@ -25,8 +27,7 @@
25#include <backtrace/Backtrace.h> 27#include <backtrace/Backtrace.h>
26#include <log/log.h> 28#include <log/log.h>
27 29
28#include "machine.h" 30#include "libdebuggerd/utility.h"
29#include "utility.h"
30 31
31void dump_memory_and_code(log_t* log, Backtrace* backtrace) { 32void dump_memory_and_code(log_t* log, Backtrace* backtrace) {
32 pt_regs regs; 33 pt_regs regs;
diff --git a/debuggerd/libdebuggerd/arm64/machine.cpp b/debuggerd/libdebuggerd/arm64/machine.cpp
index fa73c99ac..ad1c95110 100644
--- a/debuggerd/libdebuggerd/arm64/machine.cpp
+++ b/debuggerd/libdebuggerd/arm64/machine.cpp
@@ -17,6 +17,8 @@
17 17
18#define LOG_TAG "DEBUG" 18#define LOG_TAG "DEBUG"
19 19
20#include "libdebuggerd/machine.h"
21
20#include <elf.h> 22#include <elf.h>
21#include <errno.h> 23#include <errno.h>
22#include <stdint.h> 24#include <stdint.h>
@@ -27,8 +29,7 @@
27#include <backtrace/Backtrace.h> 29#include <backtrace/Backtrace.h>
28#include <log/log.h> 30#include <log/log.h>
29 31
30#include "machine.h" 32#include "libdebuggerd/utility.h"
31#include "utility.h"
32 33
33void dump_memory_and_code(log_t* log, Backtrace* backtrace) { 34void dump_memory_and_code(log_t* log, Backtrace* backtrace) {
34 struct user_pt_regs regs; 35 struct user_pt_regs regs;
diff --git a/debuggerd/libdebuggerd/backtrace.cpp b/debuggerd/libdebuggerd/backtrace.cpp
index 334d97f33..f616e1ba0 100644
--- a/debuggerd/libdebuggerd/backtrace.cpp
+++ b/debuggerd/libdebuggerd/backtrace.cpp
@@ -16,6 +16,8 @@
16 16
17#define LOG_TAG "DEBUG" 17#define LOG_TAG "DEBUG"
18 18
19#include "libdebuggerd/backtrace.h"
20
19#include <errno.h> 21#include <errno.h>
20#include <dirent.h> 22#include <dirent.h>
21#include <limits.h> 23#include <limits.h>
@@ -34,9 +36,7 @@
34#include <backtrace/Backtrace.h> 36#include <backtrace/Backtrace.h>
35#include <log/log.h> 37#include <log/log.h>
36 38
37#include "backtrace.h" 39#include "libdebuggerd/utility.h"
38
39#include "utility.h"
40 40
41static void dump_process_header(log_t* log, pid_t pid, const char* process_name) { 41static void dump_process_header(log_t* log, pid_t pid, const char* process_name) {
42 time_t t = time(NULL); 42 time_t t = time(NULL);
diff --git a/debuggerd/libdebuggerd/elf_utils.cpp b/debuggerd/libdebuggerd/elf_utils.cpp
index 4e798e243..a35102f63 100644
--- a/debuggerd/libdebuggerd/elf_utils.cpp
+++ b/debuggerd/libdebuggerd/elf_utils.cpp
@@ -16,6 +16,8 @@
16 16
17#define LOG_TAG "DEBUG" 17#define LOG_TAG "DEBUG"
18 18
19#include "libdebuggerd/elf_utils.h"
20
19#include <elf.h> 21#include <elf.h>
20#include <stdint.h> 22#include <stdint.h>
21#include <stdlib.h> 23#include <stdlib.h>
@@ -27,8 +29,6 @@
27#include <backtrace/Backtrace.h> 29#include <backtrace/Backtrace.h>
28#include <log/log.h> 30#include <log/log.h>
29 31
30#include "elf_utils.h"
31
32#define NOTE_ALIGN(size) (((size) + 3) & ~3) 32#define NOTE_ALIGN(size) (((size) + 3) & ~3)
33 33
34template <typename HdrType, typename PhdrType, typename NhdrType> 34template <typename HdrType, typename PhdrType, typename NhdrType>
diff --git a/debuggerd/libdebuggerd/include/backtrace.h b/debuggerd/libdebuggerd/include/libdebuggerd/backtrace.h
index fe738f1c7..fe738f1c7 100644
--- a/debuggerd/libdebuggerd/include/backtrace.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/backtrace.h
diff --git a/debuggerd/libdebuggerd/include/elf_utils.h b/debuggerd/libdebuggerd/include/libdebuggerd/elf_utils.h
index 11d0a4348..11d0a4348 100644
--- a/debuggerd/libdebuggerd/include/elf_utils.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/elf_utils.h
diff --git a/debuggerd/libdebuggerd/include/machine.h b/debuggerd/libdebuggerd/include/libdebuggerd/machine.h
index 5e5668253..5e5668253 100644
--- a/debuggerd/libdebuggerd/include/machine.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/machine.h
diff --git a/debuggerd/libdebuggerd/include/open_files_list.h b/debuggerd/libdebuggerd/include/libdebuggerd/open_files_list.h
index b37228d03..b37228d03 100644
--- a/debuggerd/libdebuggerd/include/open_files_list.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/open_files_list.h
diff --git a/debuggerd/libdebuggerd/include/tombstone.h b/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h
index 45740df7d..45740df7d 100644
--- a/debuggerd/libdebuggerd/include/tombstone.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h
diff --git a/debuggerd/libdebuggerd/include/utility.h b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
index f481b78b8..f481b78b8 100644
--- a/debuggerd/libdebuggerd/include/utility.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
diff --git a/debuggerd/libdebuggerd/mips/machine.cpp b/debuggerd/libdebuggerd/mips/machine.cpp
index cbf272a36..1fc690b4a 100644
--- a/debuggerd/libdebuggerd/mips/machine.cpp
+++ b/debuggerd/libdebuggerd/mips/machine.cpp
@@ -16,6 +16,8 @@
16 16
17#define LOG_TAG "DEBUG" 17#define LOG_TAG "DEBUG"
18 18
19#include "libdebuggerd/machine.h"
20
19#include <errno.h> 21#include <errno.h>
20#include <inttypes.h> 22#include <inttypes.h>
21#include <stdint.h> 23#include <stdint.h>
@@ -25,8 +27,7 @@
25#include <backtrace/Backtrace.h> 27#include <backtrace/Backtrace.h>
26#include <log/log.h> 28#include <log/log.h>
27 29
28#include "machine.h" 30#include "libdebuggerd/utility.h"
29#include "utility.h"
30 31
31#define R(x) (static_cast<uintptr_t>(x)) 32#define R(x) (static_cast<uintptr_t>(x))
32 33
diff --git a/debuggerd/libdebuggerd/mips64/machine.cpp b/debuggerd/libdebuggerd/mips64/machine.cpp
index 0a8d53257..955e50728 100644
--- a/debuggerd/libdebuggerd/mips64/machine.cpp
+++ b/debuggerd/libdebuggerd/mips64/machine.cpp
@@ -16,6 +16,8 @@
16 16
17#define LOG_TAG "DEBUG" 17#define LOG_TAG "DEBUG"
18 18
19#include "libdebuggerd/machine.h"
20
19#include <errno.h> 21#include <errno.h>
20#include <inttypes.h> 22#include <inttypes.h>
21#include <stdint.h> 23#include <stdint.h>
@@ -25,8 +27,7 @@
25#include <backtrace/Backtrace.h> 27#include <backtrace/Backtrace.h>
26#include <log/log.h> 28#include <log/log.h>
27 29
28#include "machine.h" 30#include "libdebuggerd/utility.h"
29#include "utility.h"
30 31
31#define R(x) (static_cast<uintptr_t>(x)) 32#define R(x) (static_cast<uintptr_t>(x))
32 33
diff --git a/debuggerd/libdebuggerd/open_files_list.cpp b/debuggerd/libdebuggerd/open_files_list.cpp
index 5c7ea7083..e199db8b4 100644
--- a/debuggerd/libdebuggerd/open_files_list.cpp
+++ b/debuggerd/libdebuggerd/open_files_list.cpp
@@ -16,6 +16,8 @@
16 16
17#define LOG_TAG "DEBUG" 17#define LOG_TAG "DEBUG"
18 18
19#include "libdebuggerd/open_files_list.h"
20
19#include <dirent.h> 21#include <dirent.h>
20#include <errno.h> 22#include <errno.h>
21#include <stdio.h> 23#include <stdio.h>
@@ -31,9 +33,7 @@
31#include <android-base/file.h> 33#include <android-base/file.h>
32#include <log/log.h> 34#include <log/log.h>
33 35
34#include "open_files_list.h" 36#include "libdebuggerd/utility.h"
35
36#include "utility.h"
37 37
38void populate_open_files_list(pid_t pid, OpenFilesList* list) { 38void populate_open_files_list(pid_t pid, OpenFilesList* list) {
39 std::string fd_dir_name = "/proc/" + std::to_string(pid) + "/fd"; 39 std::string fd_dir_name = "/proc/" + std::to_string(pid) + "/fd";
diff --git a/debuggerd/libdebuggerd/test/dump_memory_test.cpp b/debuggerd/libdebuggerd/test/dump_memory_test.cpp
index 49f369018..0fad2cf7c 100644
--- a/debuggerd/libdebuggerd/test/dump_memory_test.cpp
+++ b/debuggerd/libdebuggerd/test/dump_memory_test.cpp
@@ -22,9 +22,10 @@
22#include <gtest/gtest.h> 22#include <gtest/gtest.h>
23#include <android-base/file.h> 23#include <android-base/file.h>
24 24
25#include "libdebuggerd/utility.h"
26
25#include "BacktraceMock.h" 27#include "BacktraceMock.h"
26#include "log_fake.h" 28#include "log_fake.h"
27#include "utility.h"
28 29
29const char g_expected_full_dump[] = 30const char g_expected_full_dump[] =
30"\nmemory near r1:\n" 31"\nmemory near r1:\n"
diff --git a/debuggerd/libdebuggerd/test/elf_fake.cpp b/debuggerd/libdebuggerd/test/elf_fake.cpp
index bb52b59c9..f8cbca771 100644
--- a/debuggerd/libdebuggerd/test/elf_fake.cpp
+++ b/debuggerd/libdebuggerd/test/elf_fake.cpp
@@ -14,6 +14,8 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17#include "elf_fake.h"
18
17#include <stdint.h> 19#include <stdint.h>
18 20
19#include <string> 21#include <string>
diff --git a/debuggerd/libdebuggerd/test/log_fake.cpp b/debuggerd/libdebuggerd/test/log_fake.cpp
index 3336bcb50..68f401302 100644
--- a/debuggerd/libdebuggerd/test/log_fake.cpp
+++ b/debuggerd/libdebuggerd/test/log_fake.cpp
@@ -14,6 +14,8 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17#include "log_fake.h"
18
17#include <errno.h> 19#include <errno.h>
18#include <stdarg.h> 20#include <stdarg.h>
19 21
diff --git a/debuggerd/libdebuggerd/test/open_files_list_test.cpp b/debuggerd/libdebuggerd/test/open_files_list_test.cpp
index 85e069510..acac72c22 100644
--- a/debuggerd/libdebuggerd/test/open_files_list_test.cpp
+++ b/debuggerd/libdebuggerd/test/open_files_list_test.cpp
@@ -24,7 +24,7 @@
24 24
25#include "android-base/test_utils.h" 25#include "android-base/test_utils.h"
26 26
27#include "open_files_list.h" 27#include "libdebuggerd/open_files_list.h"
28 28
29// Check that we can produce a list of open files for the current process, and 29// Check that we can produce a list of open files for the current process, and
30// that it includes a known open file. 30// that it includes a known open file.
diff --git a/debuggerd/libdebuggerd/test/ptrace_fake.cpp b/debuggerd/libdebuggerd/test/ptrace_fake.cpp
index f40cbd429..0d4080ebf 100644
--- a/debuggerd/libdebuggerd/test/ptrace_fake.cpp
+++ b/debuggerd/libdebuggerd/test/ptrace_fake.cpp
@@ -14,6 +14,8 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17#include "ptrace_fake.h"
18
17#include <errno.h> 19#include <errno.h>
18#include <signal.h> 20#include <signal.h>
19#include <stdarg.h> 21#include <stdarg.h>
@@ -21,8 +23,6 @@
21 23
22#include <string> 24#include <string>
23 25
24#include "ptrace_fake.h"
25
26siginfo_t g_fake_si = {.si_signo = 0}; 26siginfo_t g_fake_si = {.si_signo = 0};
27 27
28void ptrace_set_fake_getsiginfo(const siginfo_t& si) { 28void ptrace_set_fake_getsiginfo(const siginfo_t& si) {
diff --git a/debuggerd/libdebuggerd/test/tombstone_test.cpp b/debuggerd/libdebuggerd/test/tombstone_test.cpp
index 6be59e7ac..934ceba49 100644
--- a/debuggerd/libdebuggerd/test/tombstone_test.cpp
+++ b/debuggerd/libdebuggerd/test/tombstone_test.cpp
@@ -22,7 +22,7 @@
22#include <gtest/gtest.h> 22#include <gtest/gtest.h>
23#include <android-base/file.h> 23#include <android-base/file.h>
24 24
25#include "utility.h" 25#include "libdebuggerd/utility.h"
26 26
27#include "BacktraceMock.h" 27#include "BacktraceMock.h"
28#include "elf_fake.h" 28#include "elf_fake.h"
@@ -113,7 +113,7 @@ TEST_F(TombstoneTest, single_map) {
113 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); 113 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
114 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents)); 114 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
115 const char* expected_dump = \ 115 const char* expected_dump = \
116"\nmemory map:\n" 116"\nmemory map (1 entry):\n"
117#if defined(__LP64__) 117#if defined(__LP64__)
118" 12345678'9abcd000-12345678'9abdefff --- 0 12000\n"; 118" 12345678'9abcd000-12345678'9abdefff --- 0 12000\n";
119#else 119#else
@@ -148,7 +148,7 @@ TEST_F(TombstoneTest, single_map_elf_build_id) {
148 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); 148 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
149 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents)); 149 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
150 const char* expected_dump = \ 150 const char* expected_dump = \
151"\nmemory map:\n" 151"\nmemory map (1 entry):\n"
152#if defined(__LP64__) 152#if defined(__LP64__)
153" 12345678'9abcd000-12345678'9abdefff r-- 0 12000 /system/lib/libfake.so (BuildId: abcdef1234567890abcdef1234567890)\n"; 153" 12345678'9abcd000-12345678'9abdefff r-- 0 12000 /system/lib/libfake.so (BuildId: abcdef1234567890abcdef1234567890)\n";
154#else 154#else
@@ -187,7 +187,7 @@ TEST_F(TombstoneTest, single_map_no_build_id) {
187 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); 187 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
188 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents)); 188 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
189 const char* expected_dump = \ 189 const char* expected_dump = \
190"\nmemory map:\n" 190"\nmemory map (2 entries):\n"
191#if defined(__LP64__) 191#if defined(__LP64__)
192" 12345678'9abcd000-12345678'9abdefff -w- 0 12000\n" 192" 12345678'9abcd000-12345678'9abdefff -w- 0 12000\n"
193" 12345678'9abcd000-12345678'9abdefff -w- 0 12000 /system/lib/libfake.so\n"; 193" 12345678'9abcd000-12345678'9abdefff -w- 0 12000 /system/lib/libfake.so\n";
@@ -245,7 +245,7 @@ TEST_F(TombstoneTest, multiple_maps) {
245 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); 245 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
246 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents)); 246 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
247 const char* expected_dump = 247 const char* expected_dump =
248 "\nmemory map:\n" 248 "\nmemory map (5 entries):\n"
249#if defined(__LP64__) 249#if defined(__LP64__)
250 " 00000000'0a234000-00000000'0a234fff --- 0 1000\n" 250 " 00000000'0a234000-00000000'0a234fff --- 0 1000\n"
251 " 00000000'0a334000-00000000'0a334fff r-- f000 1000\n" 251 " 00000000'0a334000-00000000'0a334fff r-- f000 1000\n"
@@ -305,7 +305,7 @@ TEST_F(TombstoneTest, multiple_maps_fault_address_before) {
305 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); 305 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
306 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents)); 306 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
307 const char* expected_dump = 307 const char* expected_dump =
308 "\nmemory map: (fault address prefixed with --->)\n" 308 "\nmemory map (3 entries):\n"
309#if defined(__LP64__) 309#if defined(__LP64__)
310 "--->Fault address falls at 00000000'00001000 before any mapped regions\n" 310 "--->Fault address falls at 00000000'00001000 before any mapped regions\n"
311 " 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load bias 0xd000)\n" 311 " 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load bias 0xd000)\n"
@@ -363,7 +363,7 @@ TEST_F(TombstoneTest, multiple_maps_fault_address_between) {
363 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); 363 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
364 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents)); 364 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
365 const char* expected_dump = 365 const char* expected_dump =
366 "\nmemory map: (fault address prefixed with --->)\n" 366 "\nmemory map (3 entries): (fault address prefixed with --->)\n"
367#if defined(__LP64__) 367#if defined(__LP64__)
368 " 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load bias 0xd000)\n" 368 " 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load bias 0xd000)\n"
369 "--->Fault address falls at 00000000'0a533000 between mapped regions\n" 369 "--->Fault address falls at 00000000'0a533000 between mapped regions\n"
@@ -421,7 +421,7 @@ TEST_F(TombstoneTest, multiple_maps_fault_address_in_map) {
421 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); 421 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
422 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents)); 422 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
423 const char* expected_dump = 423 const char* expected_dump =
424 "\nmemory map: (fault address prefixed with --->)\n" 424 "\nmemory map (3 entries): (fault address prefixed with --->)\n"
425#if defined(__LP64__) 425#if defined(__LP64__)
426 " 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load bias 0xd000)\n" 426 " 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load bias 0xd000)\n"
427 "--->00000000'0a534000-00000000'0a534fff --x 3000 1000 (load bias 0x2000)\n" 427 "--->00000000'0a534000-00000000'0a534fff --x 3000 1000 (load bias 0x2000)\n"
@@ -481,7 +481,7 @@ TEST_F(TombstoneTest, multiple_maps_fault_address_after) {
481 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); 481 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
482 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents)); 482 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
483 const char* expected_dump = 483 const char* expected_dump =
484 "\nmemory map: (fault address prefixed with --->)\n" 484 "\nmemory map (3 entries): (fault address prefixed with --->)\n"
485#if defined(__LP64__) 485#if defined(__LP64__)
486 " 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load bias 0xd000)\n" 486 " 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load bias 0xd000)\n"
487 " 00000000'0a534000-00000000'0a534fff --x 3000 1000 (load bias 0x2000)\n" 487 " 00000000'0a534000-00000000'0a534fff --x 3000 1000 (load bias 0x2000)\n"
@@ -521,7 +521,7 @@ TEST_F(TombstoneTest, multiple_maps_getsiginfo_fail) {
521 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0); 521 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
522 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents)); 522 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
523 const char* expected_dump = 523 const char* expected_dump =
524 "\nmemory map:\n" 524 "\nmemory map (1 entry):\n"
525#if defined(__LP64__) 525#if defined(__LP64__)
526 " 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load bias 0xd000)\n"; 526 " 00000000'0a434000-00000000'0a434fff -w- 1000 1000 (load bias 0xd000)\n";
527#else 527#else
@@ -571,7 +571,7 @@ TEST_F(TombstoneTest, multiple_maps_check_signal_has_si_addr) {
571 } 571 }
572 572
573 const char* expected_addr_dump = \ 573 const char* expected_addr_dump = \
574"\nmemory map: (fault address prefixed with --->)\n" 574"\nmemory map (1 entry):\n"
575#if defined(__LP64__) 575#if defined(__LP64__)
576"--->Fault address falls at 00000000'00001000 before any mapped regions\n" 576"--->Fault address falls at 00000000'00001000 before any mapped regions\n"
577" 00000000'0a434000-00000000'0a434fff -w- 0 1000\n"; 577" 00000000'0a434000-00000000'0a434fff -w- 0 1000\n";
@@ -580,7 +580,7 @@ TEST_F(TombstoneTest, multiple_maps_check_signal_has_si_addr) {
580" 0a434000-0a434fff -w- 0 1000\n"; 580" 0a434000-0a434fff -w- 0 1000\n";
581#endif 581#endif
582 const char* expected_dump = \ 582 const char* expected_dump = \
583"\nmemory map:\n" 583"\nmemory map (1 entry):\n"
584#if defined(__LP64__) 584#if defined(__LP64__)
585" 00000000'0a434000-00000000'0a434fff -w- 0 1000\n"; 585" 00000000'0a434000-00000000'0a434fff -w- 0 1000\n";
586#else 586#else
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index b809ed4bc..6fb29a938 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -16,6 +16,8 @@
16 16
17#define LOG_TAG "DEBUG" 17#define LOG_TAG "DEBUG"
18 18
19#include "libdebuggerd/tombstone.h"
20
19#include <dirent.h> 21#include <dirent.h>
20#include <errno.h> 22#include <errno.h>
21#include <fcntl.h> 23#include <fcntl.h>
@@ -33,32 +35,30 @@
33#include <string> 35#include <string>
34 36
35#include <android-base/file.h> 37#include <android-base/file.h>
38#include <android-base/properties.h>
36#include <android-base/stringprintf.h> 39#include <android-base/stringprintf.h>
37#include <android-base/unique_fd.h> 40#include <android-base/unique_fd.h>
38#include <android/log.h> 41#include <android/log.h>
39#include <backtrace/Backtrace.h> 42#include <backtrace/Backtrace.h>
40#include <backtrace/BacktraceMap.h> 43#include <backtrace/BacktraceMap.h>
41#include <cutils/properties.h>
42#include <log/log.h> 44#include <log/log.h>
43#include <log/logprint.h> 45#include <log/logprint.h>
44#include <private/android_filesystem_config.h> 46#include <private/android_filesystem_config.h>
45 47
48// Needed to get DEBUGGER_SIGNAL.
46#include "debuggerd/handler.h" 49#include "debuggerd/handler.h"
47 50
48#include "backtrace.h" 51#include "libdebuggerd/backtrace.h"
49#include "elf_utils.h" 52#include "libdebuggerd/elf_utils.h"
50#include "machine.h" 53#include "libdebuggerd/machine.h"
51#include "open_files_list.h" 54#include "libdebuggerd/open_files_list.h"
52#include "tombstone.h"
53 55
56using android::base::GetBoolProperty;
57using android::base::GetProperty;
54using android::base::StringPrintf; 58using android::base::StringPrintf;
55 59
56#define STACK_WORDS 16 60#define STACK_WORDS 16
57 61
58#define MAX_TOMBSTONES 10
59#define TOMBSTONE_DIR "/data/tombstones"
60#define TOMBSTONE_TEMPLATE (TOMBSTONE_DIR"/tombstone_%02d")
61
62static bool signal_has_si_addr(int si_signo, int si_code) { 62static bool signal_has_si_addr(int si_signo, int si_code) {
63 // Manually sent signals won't have si_addr. 63 // Manually sent signals won't have si_addr.
64 if (si_code == SI_USER || si_code == SI_QUEUE || si_code == SI_TKILL) { 64 if (si_code == SI_USER || si_code == SI_QUEUE || si_code == SI_TKILL) {
@@ -208,14 +208,11 @@ static const char* get_sigcode(int signo, int code) {
208} 208}
209 209
210static void dump_header_info(log_t* log) { 210static void dump_header_info(log_t* log) {
211 char fingerprint[PROPERTY_VALUE_MAX]; 211 auto fingerprint = GetProperty("ro.build.fingerprint", "unknown");
212 char revision[PROPERTY_VALUE_MAX]; 212 auto revision = GetProperty("ro.revision", "unknown");
213 213
214 property_get("ro.build.fingerprint", fingerprint, "unknown"); 214 _LOG(log, logtype::HEADER, "Build fingerprint: '%s'\n", fingerprint.c_str());
215 property_get("ro.revision", revision, "unknown"); 215 _LOG(log, logtype::HEADER, "Revision: '%s'\n", revision.c_str());
216
217 _LOG(log, logtype::HEADER, "Build fingerprint: '%s'\n", fingerprint);
218 _LOG(log, logtype::HEADER, "Revision: '%s'\n", revision);
219 _LOG(log, logtype::HEADER, "ABI: '%s'\n", ABI_STRING); 216 _LOG(log, logtype::HEADER, "ABI: '%s'\n", ABI_STRING);
220} 217}
221 218
@@ -415,16 +412,20 @@ static void dump_all_maps(Backtrace* backtrace, BacktraceMap* map, log_t* log, p
415 } 412 }
416 413
417 ScopedBacktraceMapIteratorLock lock(map); 414 ScopedBacktraceMapIteratorLock lock(map);
418 _LOG(log, logtype::MAPS, "\n"); 415 _LOG(log, logtype::MAPS,
419 if (!print_fault_address_marker) { 416 "\n"
420 _LOG(log, logtype::MAPS, "memory map:\n"); 417 "memory map (%zu entr%s):",
421 } else { 418 map->size(), map->size() == 1 ? "y" : "ies");
422 _LOG(log, logtype::MAPS, "memory map: (fault address prefixed with --->)\n"); 419 if (print_fault_address_marker) {
423 if (map->begin() != map->end() && addr < map->begin()->start) { 420 if (map->begin() != map->end() && addr < map->begin()->start) {
424 _LOG(log, logtype::MAPS, "--->Fault address falls at %s before any mapped regions\n", 421 _LOG(log, logtype::MAPS, "\n--->Fault address falls at %s before any mapped regions\n",
425 get_addr_string(addr).c_str()); 422 get_addr_string(addr).c_str());
426 print_fault_address_marker = false; 423 print_fault_address_marker = false;
424 } else {
425 _LOG(log, logtype::MAPS, " (fault address prefixed with --->)\n");
427 } 426 }
427 } else {
428 _LOG(log, logtype::MAPS, "\n");
428 } 429 }
429 430
430 std::string line; 431 std::string line;
@@ -722,9 +723,7 @@ static void dump_crash(log_t* log, BacktraceMap* map, BacktraceMap* map_new,
722 const std::string& process_name, const std::map<pid_t, std::string>& threads, 723 const std::string& process_name, const std::map<pid_t, std::string>& threads,
723 uintptr_t abort_msg_address) { 724 uintptr_t abort_msg_address) {
724 // don't copy log messages to tombstone unless this is a dev device 725 // don't copy log messages to tombstone unless this is a dev device
725 char value[PROPERTY_VALUE_MAX]; 726 bool want_logs = GetBoolProperty("ro.debuggable", false);
726 property_get("ro.debuggable", value, "0");
727 bool want_logs = (value[0] == '1');
728 727
729 _LOG(log, logtype::HEADER, 728 _LOG(log, logtype::HEADER,
730 "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"); 729 "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");
@@ -764,59 +763,6 @@ static void dump_crash(log_t* log, BacktraceMap* map, BacktraceMap* map_new,
764 } 763 }
765} 764}
766 765
767// open_tombstone - find an available tombstone slot, if any, of the
768// form tombstone_XX where XX is 00 to MAX_TOMBSTONES-1, inclusive. If no
769// file is available, we reuse the least-recently-modified file.
770int open_tombstone(std::string* out_path) {
771 // In a single pass, find an available slot and, in case none
772 // exist, find and record the least-recently-modified file.
773 char path[128];
774 int fd = -1;
775 int oldest = -1;
776 struct stat oldest_sb;
777 for (int i = 0; i < MAX_TOMBSTONES; i++) {
778 snprintf(path, sizeof(path), TOMBSTONE_TEMPLATE, i);
779
780 struct stat sb;
781 if (stat(path, &sb) == 0) {
782 if (oldest < 0 || sb.st_mtime < oldest_sb.st_mtime) {
783 oldest = i;
784 oldest_sb.st_mtime = sb.st_mtime;
785 }
786 continue;
787 }
788 if (errno != ENOENT) continue;
789
790 fd = open(path, O_CREAT | O_EXCL | O_WRONLY | O_NOFOLLOW | O_CLOEXEC, 0600);
791 if (fd < 0) continue; // raced ?
792
793 if (out_path) {
794 *out_path = path;
795 }
796 fchown(fd, AID_SYSTEM, AID_SYSTEM);
797 return fd;
798 }
799
800 if (oldest < 0) {
801 ALOGE("debuggerd: failed to find a valid tombstone, default to using tombstone 0.\n");
802 oldest = 0;
803 }
804
805 // we didn't find an available file, so we clobber the oldest one
806 snprintf(path, sizeof(path), TOMBSTONE_TEMPLATE, oldest);
807 fd = open(path, O_CREAT | O_TRUNC | O_WRONLY | O_NOFOLLOW | O_CLOEXEC, 0600);
808 if (fd < 0) {
809 ALOGE("debuggerd: failed to open tombstone file '%s': %s\n", path, strerror(errno));
810 return -1;
811 }
812
813 if (out_path) {
814 *out_path = path;
815 }
816 fchown(fd, AID_SYSTEM, AID_SYSTEM);
817 return fd;
818}
819
820void engrave_tombstone(int tombstone_fd, BacktraceMap* map, BacktraceMap* map_new, 766void engrave_tombstone(int tombstone_fd, BacktraceMap* map, BacktraceMap* map_new,
821 const OpenFilesList* open_files, pid_t pid, pid_t tid, 767 const OpenFilesList* open_files, pid_t pid, pid_t tid,
822 const std::string& process_name, const std::map<pid_t, std::string>& threads, 768 const std::string& process_name, const std::map<pid_t, std::string>& threads,
@@ -855,10 +801,22 @@ void engrave_tombstone_ucontext(int tombstone_fd, uintptr_t abort_msg_address, s
855 dump_abort_message(backtrace.get(), &log, abort_msg_address); 801 dump_abort_message(backtrace.get(), &log, abort_msg_address);
856 dump_registers(&log, ucontext); 802 dump_registers(&log, ucontext);
857 803
858 // TODO: Dump registers from the ucontext.
859 if (backtrace->Unwind(0, ucontext)) { 804 if (backtrace->Unwind(0, ucontext)) {
860 dump_backtrace_and_stack(backtrace.get(), &log); 805 dump_backtrace_and_stack(backtrace.get(), &log);
861 } else { 806 } else {
862 ALOGE("Unwind failed: pid = %d, tid = %d", pid, tid); 807 ALOGE("Unwind failed: pid = %d, tid = %d", pid, tid);
863 } 808 }
809
810 // TODO: Make this match the format of dump_all_maps above.
811 _LOG(&log, logtype::MAPS, "memory map:\n");
812 android::base::unique_fd maps_fd(open("/proc/self/maps", O_RDONLY | O_CLOEXEC));
813 if (maps_fd == -1) {
814 _LOG(&log, logtype::MAPS, " failed to open /proc/self/maps: %s", strerror(errno));
815 } else {
816 char buf[256];
817 ssize_t rc;
818 while ((rc = TEMP_FAILURE_RETRY(read(maps_fd.get(), buf, sizeof(buf)))) > 0) {
819 android::base::WriteFully(tombstone_fd, buf, rc);
820 }
821 }
864} 822}
diff --git a/debuggerd/libdebuggerd/utility.cpp b/debuggerd/libdebuggerd/utility.cpp
index 7f450e6bc..1b746527e 100644
--- a/debuggerd/libdebuggerd/utility.cpp
+++ b/debuggerd/libdebuggerd/utility.cpp
@@ -16,7 +16,7 @@
16 16
17#define LOG_TAG "DEBUG" 17#define LOG_TAG "DEBUG"
18 18
19#include "utility.h" 19#include "libdebuggerd/utility.h"
20 20
21#include <errno.h> 21#include <errno.h>
22#include <signal.h> 22#include <signal.h>
diff --git a/debuggerd/libdebuggerd/x86/machine.cpp b/debuggerd/libdebuggerd/x86/machine.cpp
index af10817a4..09a64cdb6 100644
--- a/debuggerd/libdebuggerd/x86/machine.cpp
+++ b/debuggerd/libdebuggerd/x86/machine.cpp
@@ -16,6 +16,8 @@
16 16
17#define LOG_TAG "DEBUG" 17#define LOG_TAG "DEBUG"
18 18
19#include "libdebuggerd/machine.h"
20
19#include <errno.h> 21#include <errno.h>
20#include <stdint.h> 22#include <stdint.h>
21#include <string.h> 23#include <string.h>
@@ -24,8 +26,7 @@
24#include <backtrace/Backtrace.h> 26#include <backtrace/Backtrace.h>
25#include <log/log.h> 27#include <log/log.h>
26 28
27#include "machine.h" 29#include "libdebuggerd/utility.h"
28#include "utility.h"
29 30
30void dump_memory_and_code(log_t* log, Backtrace* backtrace) { 31void dump_memory_and_code(log_t* log, Backtrace* backtrace) {
31 struct pt_regs r; 32 struct pt_regs r;
diff --git a/debuggerd/libdebuggerd/x86_64/machine.cpp b/debuggerd/libdebuggerd/x86_64/machine.cpp
index bf2c2b4e0..de1c26836 100644
--- a/debuggerd/libdebuggerd/x86_64/machine.cpp
+++ b/debuggerd/libdebuggerd/x86_64/machine.cpp
@@ -16,6 +16,8 @@
16 16
17#define LOG_TAG "DEBUG" 17#define LOG_TAG "DEBUG"
18 18
19#include "libdebuggerd/machine.h"
20
19#include <errno.h> 21#include <errno.h>
20#include <stdint.h> 22#include <stdint.h>
21#include <string.h> 23#include <string.h>
@@ -25,8 +27,7 @@
25#include <backtrace/Backtrace.h> 27#include <backtrace/Backtrace.h>
26#include <log/log.h> 28#include <log/log.h>
27 29
28#include "machine.h" 30#include "libdebuggerd/utility.h"
29#include "utility.h"
30 31
31void dump_memory_and_code(log_t* log, Backtrace* backtrace) { 32void dump_memory_and_code(log_t* log, Backtrace* backtrace) {
32 struct user_regs_struct r; 33 struct user_regs_struct r;
diff --git a/debuggerd/tombstoned/intercept_manager.cpp b/debuggerd/tombstoned/intercept_manager.cpp
index 24960bc98..c446dbba8 100644
--- a/debuggerd/tombstoned/intercept_manager.cpp
+++ b/debuggerd/tombstoned/intercept_manager.cpp
@@ -185,8 +185,8 @@ static void intercept_accept_cb(evconnlistener* listener, evutil_socket_t sockfd
185} 185}
186 186
187InterceptManager::InterceptManager(event_base* base, int intercept_socket) : base(base) { 187InterceptManager::InterceptManager(event_base* base, int intercept_socket) : base(base) {
188 this->listener = evconnlistener_new(base, intercept_accept_cb, this, -1, LEV_OPT_CLOSE_ON_FREE, 188 this->listener = evconnlistener_new(base, intercept_accept_cb, this, LEV_OPT_CLOSE_ON_FREE,
189 intercept_socket); 189 /* backlog */ -1, intercept_socket);
190} 190}
191 191
192bool InterceptManager::GetIntercept(pid_t pid, DebuggerdDumpType dump_type, 192bool InterceptManager::GetIntercept(pid_t pid, DebuggerdDumpType dump_type,
diff --git a/debuggerd/tombstoned/tombstoned.cpp b/debuggerd/tombstoned/tombstoned.cpp
index 93c7fb5b8..1bf8f14d0 100644
--- a/debuggerd/tombstoned/tombstoned.cpp
+++ b/debuggerd/tombstoned/tombstoned.cpp
@@ -389,8 +389,9 @@ int main(int, char* []) {
389 389
390 intercept_manager = new InterceptManager(base, intercept_socket); 390 intercept_manager = new InterceptManager(base, intercept_socket);
391 391
392 evconnlistener* tombstone_listener = evconnlistener_new( 392 evconnlistener* tombstone_listener =
393 base, crash_accept_cb, CrashQueue::for_tombstones(), -1, LEV_OPT_CLOSE_ON_FREE, crash_socket); 393 evconnlistener_new(base, crash_accept_cb, CrashQueue::for_tombstones(), LEV_OPT_CLOSE_ON_FREE,
394 -1 /* backlog */, crash_socket);
394 if (!tombstone_listener) { 395 if (!tombstone_listener) {
395 LOG(FATAL) << "failed to create evconnlistener for tombstones."; 396 LOG(FATAL) << "failed to create evconnlistener for tombstones.";
396 } 397 }
@@ -402,8 +403,9 @@ int main(int, char* []) {
402 } 403 }
403 404
404 evutil_make_socket_nonblocking(java_trace_socket); 405 evutil_make_socket_nonblocking(java_trace_socket);
405 evconnlistener* java_trace_listener = evconnlistener_new( 406 evconnlistener* java_trace_listener =
406 base, crash_accept_cb, CrashQueue::for_anrs(), -1, LEV_OPT_CLOSE_ON_FREE, java_trace_socket); 407 evconnlistener_new(base, crash_accept_cb, CrashQueue::for_anrs(), LEV_OPT_CLOSE_ON_FREE,
408 -1 /* backlog */, java_trace_socket);
407 if (!java_trace_listener) { 409 if (!java_trace_listener) {
408 LOG(FATAL) << "failed to create evconnlistener for java traces."; 410 LOG(FATAL) << "failed to create evconnlistener for java traces.";
409 } 411 }
diff --git a/demangle/Android.bp b/demangle/Android.bp
index e55c8869f..89b87725f 100644
--- a/demangle/Android.bp
+++ b/demangle/Android.bp
@@ -24,6 +24,12 @@ cc_defaults {
24 "-Werror", 24 "-Werror",
25 "-Wextra", 25 "-Wextra",
26 ], 26 ],
27
28 target: {
29 linux_bionic: {
30 enabled: true,
31 },
32 },
27} 33}
28 34
29cc_library { 35cc_library {
diff --git a/demangle/DemangleTest.cpp b/demangle/DemangleTest.cpp
index f56a9be3c..c93e2ab93 100644
--- a/demangle/DemangleTest.cpp
+++ b/demangle/DemangleTest.cpp
@@ -428,6 +428,14 @@ TEST(DemangleTest, StringTooLong) {
428 ASSERT_EQ("_ZN3one3twoEDa", demangler.Parse("_ZN3one3twoEDa", 12)); 428 ASSERT_EQ("_ZN3one3twoEDa", demangler.Parse("_ZN3one3twoEDa", 12));
429} 429}
430 430
431TEST(DemangleTest, BooleanLiterals) {
432 Demangler demangler;
433
434 ASSERT_EQ("one<true>", demangler.Parse("_ZN3oneILb1EEE"));
435 ASSERT_EQ("one<false>", demangler.Parse("_ZN3oneILb0EEE"));
436 ASSERT_EQ("one<false, true>", demangler.Parse("_ZN3oneILb0ELb1EEE"));
437}
438
431TEST(DemangleTest, demangle) { 439TEST(DemangleTest, demangle) {
432 std::string str; 440 std::string str;
433 441
diff --git a/demangle/Demangler.cpp b/demangle/Demangler.cpp
index c0a96aae5..f148b21a5 100644
--- a/demangle/Demangler.cpp
+++ b/demangle/Demangler.cpp
@@ -660,6 +660,29 @@ const char* Demangler::ParseArguments(const char* name) {
660 return nullptr; 660 return nullptr;
661} 661}
662 662
663const char* Demangler::ParseTemplateLiteral(const char* name) {
664 if (*name == 'E') {
665 parse_func_ = parse_funcs_.back();
666 parse_funcs_.pop_back();
667 return name + 1;
668 }
669 // Only understand boolean values with 0 or 1.
670 if (*name == 'b') {
671 name++;
672 if (*name == '0') {
673 AppendArgument("false");
674 cur_state_.str.clear();
675 } else if (*name == '1') {
676 AppendArgument("true");
677 cur_state_.str.clear();
678 } else {
679 return nullptr;
680 }
681 return name + 1;
682 }
683 return nullptr;
684}
685
663const char* Demangler::ParseTemplateArgumentsComplex(const char* name) { 686const char* Demangler::ParseTemplateArgumentsComplex(const char* name) {
664 if (*name == 'E') { 687 if (*name == 'E') {
665 if (parse_funcs_.empty()) { 688 if (parse_funcs_.empty()) {
@@ -670,6 +693,11 @@ const char* Demangler::ParseTemplateArgumentsComplex(const char* name) {
670 FinalizeTemplate(); 693 FinalizeTemplate();
671 Save(cur_state_.str, false); 694 Save(cur_state_.str, false);
672 return name + 1; 695 return name + 1;
696 } else if (*name == 'L') {
697 // Literal value for a template.
698 parse_funcs_.push_back(parse_func_);
699 parse_func_ = &Demangler::ParseTemplateLiteral;
700 return name + 1;
673 } 701 }
674 return ParseArguments(name); 702 return ParseArguments(name);
675} 703}
diff --git a/demangle/Demangler.h b/demangle/Demangler.h
index 3bd4f3c00..f76def64a 100644
--- a/demangle/Demangler.h
+++ b/demangle/Demangler.h
@@ -92,6 +92,7 @@ class Demangler {
92 const char* ParseArguments(const char* name); 92 const char* ParseArguments(const char* name);
93 const char* ParseTemplateArguments(const char* name); 93 const char* ParseTemplateArguments(const char* name);
94 const char* ParseTemplateArgumentsComplex(const char* name); 94 const char* ParseTemplateArgumentsComplex(const char* name);
95 const char* ParseTemplateLiteral(const char* name);
95 const char* ParseFunctionArgument(const char* name); 96 const char* ParseFunctionArgument(const char* name);
96 const char* ParseFunctionName(const char* name); 97 const char* ParseFunctionName(const char* name);
97 const char* FindFunctionName(const char* name); 98 const char* FindFunctionName(const char* name);
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index 608917ab9..5a6298e9b 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -37,7 +37,6 @@ cc_library_static {
37 "fs_mgr_avb_ops.cpp", 37 "fs_mgr_avb_ops.cpp",
38 ], 38 ],
39 static_libs: [ 39 static_libs: [
40 "liblogwrap",
41 "libfec", 40 "libfec",
42 "libfec_rs", 41 "libfec_rs",
43 "libbase", 42 "libbase",
@@ -53,14 +52,18 @@ cc_library_static {
53 "libfstab", 52 "libfstab",
54 ], 53 ],
55 whole_static_libs: [ 54 whole_static_libs: [
55 "liblogwrap",
56 "libfstab", 56 "libfstab",
57 ], 57 ],
58 cppflags: [
59 "-DALLOW_ADBD_DISABLE_VERITY=0",
60 ],
58 product_variables: { 61 product_variables: {
59 debuggable: { 62 debuggable: {
60 cppflags: ["-DALLOW_ADBD_DISABLE_VERITY=1"], 63 cppflags: [
61 }, 64 "-UALLOW_ADBD_DISABLE_VERITY",
62 eng: { 65 "-DALLOW_ADBD_DISABLE_VERITY=1",
63 cppflags: ["-DALLOW_SKIP_SECURE_CHECK=1"], 66 ],
64 }, 67 },
65 }, 68 },
66} 69}
diff --git a/fs_mgr/Android.mk b/fs_mgr/Android.mk
index 18ccc436c..007189db1 100644
--- a/fs_mgr/Android.mk
+++ b/fs_mgr/Android.mk
@@ -20,6 +20,7 @@ LOCAL_SRC_FILES:= fs_mgr_main.cpp
20LOCAL_C_INCLUDES := $(LOCAL_PATH)/include 20LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
21LOCAL_MODULE:= fs_mgr 21LOCAL_MODULE:= fs_mgr
22LOCAL_MODULE_TAGS := optional 22LOCAL_MODULE_TAGS := optional
23LOCAL_REQUIRED_MODULES := mke2fs mke2fs.conf e2fsdroid
23LOCAL_FORCE_STATIC_EXECUTABLE := true 24LOCAL_FORCE_STATIC_EXECUTABLE := true
24LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)/sbin 25LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)/sbin
25LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED) 26LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 874189a80..074f83840 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -543,15 +543,6 @@ static int fs_match(const char *in1, const char *in2)
543 return ret; 543 return ret;
544} 544}
545 545
546static int device_is_force_encrypted() {
547 int ret = -1;
548 char value[PROP_VALUE_MAX];
549 ret = __system_property_get("ro.vold.forceencryption", value);
550 if (ret < 0)
551 return 0;
552 return strcmp(value, "1") ? 0 : 1;
553}
554
555/* 546/*
556 * Tries to mount any of the consecutive fstab entries that match 547 * Tries to mount any of the consecutive fstab entries that match
557 * the mountpoint of the one given by fstab->recs[start_idx]. 548 * the mountpoint of the one given by fstab->recs[start_idx].
@@ -726,7 +717,9 @@ out:
726 717
727static bool needs_block_encryption(const struct fstab_rec* rec) 718static bool needs_block_encryption(const struct fstab_rec* rec)
728{ 719{
729 if (device_is_force_encrypted() && fs_mgr_is_encryptable(rec)) return true; 720 if (android::base::GetBoolProperty("ro.vold.forceencryption", false) &&
721 fs_mgr_is_encryptable(rec))
722 return true;
730 if (rec->fs_mgr_flags & MF_FORCECRYPT) return true; 723 if (rec->fs_mgr_flags & MF_FORCECRYPT) return true;
731 if (rec->fs_mgr_flags & MF_CRYPT) { 724 if (rec->fs_mgr_flags & MF_CRYPT) {
732 /* Check for existence of convert_fde breadcrumb file */ 725 /* Check for existence of convert_fde breadcrumb file */
@@ -768,23 +761,6 @@ static int handle_encryptable(const struct fstab_rec* rec)
768 } 761 }
769} 762}
770 763
771bool is_device_secure() {
772 int ret = -1;
773 char value[PROP_VALUE_MAX];
774 ret = __system_property_get("ro.secure", value);
775 if (ret == 0) {
776#ifdef ALLOW_SKIP_SECURE_CHECK
777 // Allow eng builds to skip this check if the property
778 // is not readable (happens during early mount)
779 return false;
780#else
781 // If error and not an 'eng' build, we want to fail secure.
782 return true;
783#endif
784 }
785 return strcmp(value, "0") ? true : false;
786}
787
788/* When multiple fstab records share the same mount_point, it will 764/* When multiple fstab records share the same mount_point, it will
789 * try to mount each one in turn, and ignore any duplicates after a 765 * try to mount each one in turn, and ignore any duplicates after a
790 * first successful mount. 766 * first successful mount.
@@ -857,7 +833,7 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode)
857 /* Skips mounting the device. */ 833 /* Skips mounting the device. */
858 continue; 834 continue;
859 } 835 }
860 } else if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && is_device_secure()) { 836 } else if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY)) {
861 int rc = fs_mgr_setup_verity(&fstab->recs[i], true); 837 int rc = fs_mgr_setup_verity(&fstab->recs[i], true);
862 if (__android_log_is_debuggable() && 838 if (__android_log_is_debuggable() &&
863 (rc == FS_MGR_SETUP_VERITY_DISABLED || 839 (rc == FS_MGR_SETUP_VERITY_DISABLED ||
@@ -1064,7 +1040,7 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device,
1064 /* Skips mounting the device. */ 1040 /* Skips mounting the device. */
1065 continue; 1041 continue;
1066 } 1042 }
1067 } else if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && is_device_secure()) { 1043 } else if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY)) {
1068 int rc = fs_mgr_setup_verity(&fstab->recs[i], true); 1044 int rc = fs_mgr_setup_verity(&fstab->recs[i], true);
1069 if (__android_log_is_debuggable() && 1045 if (__android_log_is_debuggable() &&
1070 (rc == FS_MGR_SETUP_VERITY_DISABLED || 1046 (rc == FS_MGR_SETUP_VERITY_DISABLED ||
diff --git a/fs_mgr/fs_mgr_format.cpp b/fs_mgr/fs_mgr_format.cpp
index a03d92c6b..75feee798 100644
--- a/fs_mgr/fs_mgr_format.cpp
+++ b/fs_mgr/fs_mgr_format.cpp
@@ -24,25 +24,21 @@
24#include <cutils/partition_utils.h> 24#include <cutils/partition_utils.h>
25#include <sys/mount.h> 25#include <sys/mount.h>
26 26
27#include <ext4_utils/ext4_utils.h>
28#include <ext4_utils/ext4.h> 27#include <ext4_utils/ext4.h>
29#include <ext4_utils/make_ext4fs.h> 28#include <ext4_utils/ext4_utils.h>
30#include <selinux/selinux.h> 29#include <logwrap/logwrap.h>
31#include <selinux/label.h>
32#include <selinux/android.h> 30#include <selinux/android.h>
31#include <selinux/label.h>
32#include <selinux/selinux.h>
33 33
34#include "fs_mgr_priv.h" 34#include "fs_mgr_priv.h"
35#include "cryptfs.h" 35#include "cryptfs.h"
36 36
37extern "C" {
38extern struct fs_info info; /* magic global from ext4_utils */
39extern void reset_ext4fs_info();
40}
41
42static int format_ext4(char *fs_blkdev, char *fs_mnt_point, bool crypt_footer) 37static int format_ext4(char *fs_blkdev, char *fs_mnt_point, bool crypt_footer)
43{ 38{
44 uint64_t dev_sz; 39 uint64_t dev_sz;
45 int fd, rc = 0; 40 int fd, rc = 0;
41 int status;
46 42
47 if ((fd = open(fs_blkdev, O_WRONLY)) < 0) { 43 if ((fd = open(fs_blkdev, O_WRONLY)) < 0) {
48 PERROR << "Cannot open block device"; 44 PERROR << "Cannot open block device";
@@ -55,30 +51,36 @@ static int format_ext4(char *fs_blkdev, char *fs_mnt_point, bool crypt_footer)
55 return -1; 51 return -1;
56 } 52 }
57 53
58 struct selabel_handle *sehandle = selinux_android_file_context_handle(); 54 close(fd);
59 if (!sehandle) {
60 /* libselinux logs specific error */
61 LERROR << "Cannot initialize android file_contexts";
62 close(fd);
63 return -1;
64 }
65 55
66 /* Format the partition using the calculated length */ 56 /* Format the partition using the calculated length */
67 reset_ext4fs_info();
68 info.len = (off64_t)dev_sz;
69 if (crypt_footer) { 57 if (crypt_footer) {
70 info.len -= CRYPT_FOOTER_OFFSET; 58 dev_sz -= CRYPT_FOOTER_OFFSET;
71 } 59 }
72 60
73 /* Use make_ext4fs_internal to avoid wiping an already-wiped partition. */ 61 std::string size_str = std::to_string(dev_sz / 4096);
74 rc = make_ext4fs_internal(fd, NULL, NULL, fs_mnt_point, 0, 0, 0, 0, 0, 0, sehandle, 0, 0, NULL, NULL, NULL); 62 const char* const mke2fs_args[] = {
63 "/system/bin/mke2fs", "-t", "ext4", "-b", "4096", fs_blkdev, size_str.c_str(), nullptr};
64
65 rc = android_fork_execvp_ext(arraysize(mke2fs_args), const_cast<char**>(mke2fs_args), &status,
66 true, LOG_KLOG, true, nullptr, nullptr, 0);
75 if (rc) { 67 if (rc) {
76 LERROR << "make_ext4fs returned " << rc; 68 LERROR << "mke2fs returned " << rc;
69 return rc;
77 } 70 }
78 close(fd);
79 71
80 if (sehandle) { 72 const char* const e2fsdroid_args[] = {
81 selabel_close(sehandle); 73 "/system/bin/e2fsdroid",
74 "-e",
75 "-a",
76 fs_mnt_point,
77 fs_blkdev,
78 nullptr};
79
80 rc = android_fork_execvp_ext(arraysize(e2fsdroid_args), const_cast<char**>(e2fsdroid_args),
81 &status, true, LOG_KLOG, true, nullptr, nullptr, 0);
82 if (rc) {
83 LERROR << "e2fsdroid returned " << rc;
82 } 84 }
83 85
84 return rc; 86 return rc;
@@ -86,44 +88,11 @@ static int format_ext4(char *fs_blkdev, char *fs_mnt_point, bool crypt_footer)
86 88
87static int format_f2fs(char *fs_blkdev) 89static int format_f2fs(char *fs_blkdev)
88{ 90{
89 char * args[5]; 91 int status;
90 int pid; 92 const char* const args[] = {"/system/bin/make_f2fs", "-f", "-O encrypt", fs_blkdev, nullptr};
91 int rc = 0;
92
93 args[0] = (char *)"/system/bin/make_f2fs";
94 args[1] = (char *)"-f";
95 args[2] = (char *)"-O encrypt";
96 args[3] = fs_blkdev;
97 args[4] = (char *)0;
98
99 pid = fork();
100 if (pid < 0) {
101 return pid;
102 }
103 if (!pid) {
104 /* This doesn't return */
105 execv(args[0], args);
106 exit(1);
107 }
108 for(;;) {
109 pid_t p = waitpid(pid, &rc, 0);
110 if (p != pid) {
111 LERROR << "Error waiting for child process - " << p;
112 rc = -1;
113 break;
114 }
115 if (WIFEXITED(rc)) {
116 rc = WEXITSTATUS(rc);
117 LINFO << args[0] << " done, status " << rc;
118 if (rc) {
119 rc = -1;
120 }
121 break;
122 }
123 LERROR << "Still waiting for " << args[0] << "...";
124 }
125 93
126 return rc; 94 return android_fork_execvp_ext(arraysize(args), const_cast<char**>(args), &status, true,
95 LOG_KLOG, true, nullptr, nullptr, 0);
127} 96}
128 97
129int fs_mgr_do_format(struct fstab_rec *fstab, bool crypt_footer) 98int fs_mgr_do_format(struct fstab_rec *fstab, bool crypt_footer)
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 41a58683e..bce245ce3 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -779,44 +779,19 @@ int fs_mgr_add_entry(struct fstab *fstab,
779} 779}
780 780
781/* 781/*
782 * Returns the 1st matching fstab_rec that follows the start_rec. 782 * Returns the fstab_rec* whose mount_point is path.
783 * start_rec is the result of a previous search or NULL. 783 * Returns nullptr if not found.
784 */ 784 */
785struct fstab_rec *fs_mgr_get_entry_for_mount_point_after(struct fstab_rec *start_rec, struct fstab *fstab, const char *path) 785struct fstab_rec* fs_mgr_get_entry_for_mount_point(struct fstab* fstab, const std::string& path) {
786{
787 int i;
788 if (!fstab) { 786 if (!fstab) {
789 return NULL; 787 return nullptr;
790 }
791
792 if (start_rec) {
793 for (i = 0; i < fstab->num_entries; i++) {
794 if (&fstab->recs[i] == start_rec) {
795 i++;
796 break;
797 }
798 }
799 } else {
800 i = 0;
801 } 788 }
802 for (; i < fstab->num_entries; i++) { 789 for (int i = 0; i < fstab->num_entries; i++) {
803 int len = strlen(fstab->recs[i].mount_point); 790 if (fstab->recs[i].mount_point && path == fstab->recs[i].mount_point) {
804 if (strncmp(path, fstab->recs[i].mount_point, len) == 0 &&
805 (path[len] == '\0' || path[len] == '/')) {
806 return &fstab->recs[i]; 791 return &fstab->recs[i];
807 } 792 }
808 } 793 }
809 return NULL; 794 return nullptr;
810}
811
812/*
813 * Returns the 1st matching mount point.
814 * There might be more. To look for others, use fs_mgr_get_entry_for_mount_point_after()
815 * and give the fstab_rec from the previous search.
816 */
817struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path)
818{
819 return fs_mgr_get_entry_for_mount_point_after(NULL, fstab, path);
820} 795}
821 796
822int fs_mgr_is_voldmanaged(const struct fstab_rec *fstab) 797int fs_mgr_is_voldmanaged(const struct fstab_rec *fstab)
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 7423c1f8a..c3c87fa81 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -121,7 +121,6 @@ bool fs_mgr_update_for_slotselect(struct fstab *fstab);
121bool fs_mgr_is_device_unlocked(); 121bool fs_mgr_is_device_unlocked();
122const std::string& get_android_dt_dir(); 122const std::string& get_android_dt_dir();
123bool is_dt_compatible(); 123bool is_dt_compatible();
124bool is_device_secure();
125int load_verity_state(struct fstab_rec* fstab, int* mode); 124int load_verity_state(struct fstab_rec* fstab, int* mode);
126 125
127#endif /* __CORE_FS_MGR_PRIV_H */ 126#endif /* __CORE_FS_MGR_PRIV_H */
diff --git a/fs_mgr/fs_mgr_slotselect.cpp b/fs_mgr/fs_mgr_slotselect.cpp
index 9ca15e237..33fd56240 100644
--- a/fs_mgr/fs_mgr_slotselect.cpp
+++ b/fs_mgr/fs_mgr_slotselect.cpp
@@ -21,19 +21,12 @@
21#include "fs_mgr.h" 21#include "fs_mgr.h"
22#include "fs_mgr_priv.h" 22#include "fs_mgr_priv.h"
23 23
24// Returns "_a" or "_b" based on two possible values in kernel cmdline: 24// Returns "_a" or "_b" based on androidboot.slot_suffix in kernel cmdline, or an empty string
25// - androidboot.slot = a or b OR 25// if that parameter does not exist.
26// - androidboot.slot_suffix = _a or _b
27// TODO: remove slot_suffix once it's deprecated.
28std::string fs_mgr_get_slot_suffix() { 26std::string fs_mgr_get_slot_suffix() {
29 std::string slot;
30 std::string ab_suffix; 27 std::string ab_suffix;
31 28
32 if (fs_mgr_get_boot_config("slot", &slot)) { 29 fs_mgr_get_boot_config("slot_suffix", &ab_suffix);
33 ab_suffix = "_" + slot;
34 } else if (!fs_mgr_get_boot_config("slot_suffix", &ab_suffix)) {
35 ab_suffix = "";
36 }
37 return ab_suffix; 30 return ab_suffix;
38} 31}
39 32
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index 7f8e1e213..896b60313 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -765,13 +765,6 @@ int fs_mgr_setup_verity(struct fstab_rec *fstab, bool wait_for_verity_dev)
765 const std::string mount_point(basename(fstab->mount_point)); 765 const std::string mount_point(basename(fstab->mount_point));
766 bool verified_at_boot = false; 766 bool verified_at_boot = false;
767 767
768 // This is a public API and so deserves its own check to see if verity
769 // setup is needed at all.
770 if (!is_device_secure()) {
771 LINFO << "Verity setup skipped for " << mount_point;
772 return FS_MGR_SETUP_VERITY_SKIPPED;
773 }
774
775 if (fec_open(&f, fstab->blk_device, O_RDONLY, FEC_VERITY_DISABLE, 768 if (fec_open(&f, fstab->blk_device, O_RDONLY, FEC_VERITY_DISABLE,
776 FEC_DEFAULT_ROOTS) < 0) { 769 FEC_DEFAULT_ROOTS) < 0) {
777 PERROR << "Failed to open '" << fstab->blk_device << "'"; 770 PERROR << "Failed to open '" << fstab->blk_device << "'";
@@ -792,7 +785,7 @@ int fs_mgr_setup_verity(struct fstab_rec *fstab, bool wait_for_verity_dev)
792#ifdef ALLOW_ADBD_DISABLE_VERITY 785#ifdef ALLOW_ADBD_DISABLE_VERITY
793 if (verity.disabled) { 786 if (verity.disabled) {
794 retval = FS_MGR_SETUP_VERITY_DISABLED; 787 retval = FS_MGR_SETUP_VERITY_DISABLED;
795 LINFO << "Attempt to cleanly disable verity - only works in USERDEBUG"; 788 LINFO << "Attempt to cleanly disable verity - only works in USERDEBUG/ENG";
796 goto out; 789 goto out;
797 } 790 }
798#endif 791#endif
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 3d3faf325..5c26c2ebe 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -31,8 +31,6 @@
31// turn verity off in userdebug builds. 31// turn verity off in userdebug builds.
32#define VERITY_METADATA_MAGIC_DISABLE 0x46464f56 // "VOFF" 32#define VERITY_METADATA_MAGIC_DISABLE 0x46464f56 // "VOFF"
33 33
34__BEGIN_DECLS
35
36// Verity modes 34// Verity modes
37enum verity_mode { 35enum verity_mode {
38 VERITY_MODE_EIO = 0, 36 VERITY_MODE_EIO = 0,
@@ -85,6 +83,4 @@ int fs_mgr_do_format(struct fstab_rec *fstab, bool reserve_footer);
85#define FS_MGR_SETUP_VERITY_SUCCESS 0 83#define FS_MGR_SETUP_VERITY_SUCCESS 0
86int fs_mgr_setup_verity(struct fstab_rec *fstab, bool wait_for_verity_dev); 84int fs_mgr_setup_verity(struct fstab_rec *fstab, bool wait_for_verity_dev);
87 85
88__END_DECLS
89
90#endif /* __CORE_FS_MGR_H */ 86#endif /* __CORE_FS_MGR_H */
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index 8a18ec030..bc2942d0c 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -22,13 +22,7 @@
22#include <stdint.h> 22#include <stdint.h>
23#include <stdio.h> 23#include <stdio.h>
24 24
25// C++ only headers
26// TODO: move this into separate header files under include/fs_mgr/*.h
27#ifdef __cplusplus
28#include <string> 25#include <string>
29#endif
30
31__BEGIN_DECLS
32 26
33/* 27/*
34 * The entries must be kept in the same order as they were seen in the fstab. 28 * The entries must be kept in the same order as they were seen in the fstab.
@@ -70,7 +64,7 @@ void fs_mgr_free_fstab(struct fstab* fstab);
70 64
71int fs_mgr_add_entry(struct fstab* fstab, const char* mount_point, const char* fs_type, 65int fs_mgr_add_entry(struct fstab* fstab, const char* mount_point, const char* fs_type,
72 const char* blk_device); 66 const char* blk_device);
73struct fstab_rec* fs_mgr_get_entry_for_mount_point(struct fstab* fstab, const char* path); 67struct fstab_rec* fs_mgr_get_entry_for_mount_point(struct fstab* fstab, const std::string& path);
74int fs_mgr_is_voldmanaged(const struct fstab_rec* fstab); 68int fs_mgr_is_voldmanaged(const struct fstab_rec* fstab);
75int fs_mgr_is_nonremovable(const struct fstab_rec* fstab); 69int fs_mgr_is_nonremovable(const struct fstab_rec* fstab);
76int fs_mgr_is_verified(const struct fstab_rec* fstab); 70int fs_mgr_is_verified(const struct fstab_rec* fstab);
@@ -89,12 +83,6 @@ int fs_mgr_is_nofail(const struct fstab_rec* fstab);
89int fs_mgr_is_latemount(const struct fstab_rec* fstab); 83int fs_mgr_is_latemount(const struct fstab_rec* fstab);
90int fs_mgr_is_quota(const struct fstab_rec* fstab); 84int fs_mgr_is_quota(const struct fstab_rec* fstab);
91 85
92__END_DECLS
93
94// C++ only functions
95// TODO: move this into separate header files under include/fs_mgr/*.h
96#ifdef __cplusplus
97std::string fs_mgr_get_slot_suffix(); 86std::string fs_mgr_get_slot_suffix();
98#endif
99 87
100#endif /* __CORE_FS_TAB_H */ 88#endif /* __CORE_FS_TAB_H */
diff --git a/gatekeeperd/SoftGateKeeper.h b/gatekeeperd/SoftGateKeeper.h
index 92d175290..2f4f4d7e6 100644
--- a/gatekeeperd/SoftGateKeeper.h
+++ b/gatekeeperd/SoftGateKeeper.h
@@ -27,10 +27,10 @@ extern "C" {
27 27
28#include <android-base/memory.h> 28#include <android-base/memory.h>
29#include <gatekeeper/gatekeeper.h> 29#include <gatekeeper/gatekeeper.h>
30#include <nativehelper/UniquePtr.h>
31 30
32#include <iostream> 31#include <iostream>
33#include <unordered_map> 32#include <unordered_map>
33#include <memory>
34 34
35namespace gatekeeper { 35namespace gatekeeper {
36 36
@@ -173,7 +173,7 @@ private:
173 typedef std::unordered_map<uint32_t, failure_record_t> FailureRecordMap; 173 typedef std::unordered_map<uint32_t, failure_record_t> FailureRecordMap;
174 typedef std::unordered_map<uint64_t, fast_hash_t> FastHashMap; 174 typedef std::unordered_map<uint64_t, fast_hash_t> FastHashMap;
175 175
176 UniquePtr<uint8_t[]> key_; 176 std::unique_ptr<uint8_t[]> key_;
177 FailureRecordMap failure_map_; 177 FailureRecordMap failure_map_;
178 FastHashMap fast_hash_map_; 178 FastHashMap fast_hash_map_;
179}; 179};
diff --git a/gatekeeperd/SoftGateKeeperDevice.h b/gatekeeperd/SoftGateKeeperDevice.h
index 229f9a9e6..e3dc068fb 100644
--- a/gatekeeperd/SoftGateKeeperDevice.h
+++ b/gatekeeperd/SoftGateKeeperDevice.h
@@ -19,7 +19,7 @@
19 19
20#include "SoftGateKeeper.h" 20#include "SoftGateKeeper.h"
21 21
22#include <nativehelper/UniquePtr.h> 22#include <memory>
23 23
24using namespace gatekeeper; 24using namespace gatekeeper;
25 25
@@ -68,7 +68,7 @@ public:
68 const uint8_t *provided_password, uint32_t provided_password_length, 68 const uint8_t *provided_password, uint32_t provided_password_length,
69 uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll); 69 uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll);
70private: 70private:
71 UniquePtr<SoftGateKeeper> impl_; 71 std::unique_ptr<SoftGateKeeper> impl_;
72}; 72};
73 73
74} // namespace gatekeeper 74} // namespace gatekeeper
diff --git a/gatekeeperd/gatekeeperd.cpp b/gatekeeperd/gatekeeperd.cpp
index e6eb3bc25..73dab9b9e 100644
--- a/gatekeeperd/gatekeeperd.cpp
+++ b/gatekeeperd/gatekeeperd.cpp
@@ -23,6 +23,7 @@
23#include <inttypes.h> 23#include <inttypes.h>
24#include <stdint.h> 24#include <stdint.h>
25#include <unistd.h> 25#include <unistd.h>
26#include <memory>
26 27
27#include <binder/IPCThreadState.h> 28#include <binder/IPCThreadState.h>
28#include <binder/IServiceManager.h> 29#include <binder/IServiceManager.h>
@@ -375,7 +376,7 @@ public:
375 376
376private: 377private:
377 sp<IGatekeeper> hw_device; 378 sp<IGatekeeper> hw_device;
378 UniquePtr<SoftGateKeeperDevice> soft_device; 379 std::unique_ptr<SoftGateKeeperDevice> soft_device;
379}; 380};
380}// namespace android 381}// namespace android
381 382
diff --git a/gatekeeperd/tests/gatekeeper_test.cpp b/gatekeeperd/tests/gatekeeper_test.cpp
index b3aea7b5d..100375fb8 100644
--- a/gatekeeperd/tests/gatekeeper_test.cpp
+++ b/gatekeeperd/tests/gatekeeper_test.cpp
@@ -19,7 +19,6 @@
19 19
20#include <gtest/gtest.h> 20#include <gtest/gtest.h>
21#include <hardware/hw_auth_token.h> 21#include <hardware/hw_auth_token.h>
22#include <nativehelper/UniquePtr.h>
23 22
24#include "../SoftGateKeeper.h" 23#include "../SoftGateKeeper.h"
25 24
diff --git a/init/Android.bp b/init/Android.bp
index 33dfe566c..e906771da 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -72,10 +72,14 @@ cc_library_static {
72 "import_parser.cpp", 72 "import_parser.cpp",
73 "log.cpp", 73 "log.cpp",
74 "parser.cpp", 74 "parser.cpp",
75 "persistent_properties.cpp",
76 "persistent_properties.proto",
75 "property_service.cpp", 77 "property_service.cpp",
76 "security.cpp", 78 "security.cpp",
77 "selinux.cpp", 79 "selinux.cpp",
78 "service.cpp", 80 "service.cpp",
81 "subcontext.cpp",
82 "subcontext.proto",
79 "rlimit_parser.cpp", 83 "rlimit_parser.cpp",
80 "tokenizer.cpp", 84 "tokenizer.cpp",
81 "uevent_listener.cpp", 85 "uevent_listener.cpp",
@@ -89,11 +93,15 @@ cc_library_static {
89 "liblog", 93 "liblog",
90 "libprocessgroup", 94 "libprocessgroup",
91 "libfs_mgr", 95 "libfs_mgr",
96 "libprotobuf-cpp-lite",
92 ], 97 ],
93 include_dirs: [ 98 include_dirs: [
94 "system/core/mkbootimg", 99 "system/core/mkbootimg",
95 ], 100 ],
96 101 proto: {
102 type: "lite",
103 export_proto_headers: true,
104 },
97} 105}
98 106
99/* 107/*
@@ -118,7 +126,7 @@ cc_binary {
118 "init_first_stage.cpp", 126 "init_first_stage.cpp",
119 "keychords.cpp", 127 "keychords.cpp",
120 "reboot.cpp", 128 "reboot.cpp",
121 "signal_handler.cpp", 129 "sigchld_handler.cpp",
122 "ueventd.cpp", 130 "ueventd.cpp",
123 "watchdogd.cpp", 131 "watchdogd.cpp",
124 ], 132 ],
@@ -162,10 +170,12 @@ cc_test {
162 srcs: [ 170 srcs: [
163 "devices_test.cpp", 171 "devices_test.cpp",
164 "init_test.cpp", 172 "init_test.cpp",
173 "persistent_properties_test.cpp",
165 "property_service_test.cpp", 174 "property_service_test.cpp",
166 "result_test.cpp", 175 "result_test.cpp",
167 "rlimit_parser_test.cpp", 176 "rlimit_parser_test.cpp",
168 "service_test.cpp", 177 "service_test.cpp",
178 "subcontext_test.cpp",
169 "ueventd_test.cpp", 179 "ueventd_test.cpp",
170 "util_test.cpp", 180 "util_test.cpp",
171 ], 181 ],
@@ -177,6 +187,25 @@ cc_test {
177 "libinit", 187 "libinit",
178 "libselinux", 188 "libselinux",
179 "libcrypto", 189 "libcrypto",
190 "libprotobuf-cpp-lite",
191 ],
192}
193
194cc_benchmark {
195 name: "init_benchmarks",
196 defaults: ["init_defaults"],
197 srcs: [
198 "subcontext_benchmark.cpp",
199 ],
200 shared_libs: [
201 "libbase",
202 "libcutils",
203 ],
204 static_libs: [
205 "libinit",
206 "libselinux",
207 "libcrypto",
208 "libprotobuf-cpp-lite",
180 ], 209 ],
181} 210}
182 211
diff --git a/init/Android.mk b/init/Android.mk
index 23ada73a5..dd0f1bfd7 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -48,7 +48,7 @@ LOCAL_SRC_FILES:= \
48 init_first_stage.cpp \ 48 init_first_stage.cpp \
49 keychords.cpp \ 49 keychords.cpp \
50 reboot.cpp \ 50 reboot.cpp \
51 signal_handler.cpp \ 51 sigchld_handler.cpp \
52 ueventd.cpp \ 52 ueventd.cpp \
53 watchdogd.cpp \ 53 watchdogd.cpp \
54 54
@@ -82,6 +82,7 @@ LOCAL_STATIC_LIBRARIES := \
82 libprocessgroup \ 82 libprocessgroup \
83 libavb \ 83 libavb \
84 libkeyutils \ 84 libkeyutils \
85 libprotobuf-cpp-lite \
85 86
86LOCAL_REQUIRED_MODULES := \ 87LOCAL_REQUIRED_MODULES := \
87 e2fsdroid \ 88 e2fsdroid \
diff --git a/init/README.md b/init/README.md
index b681f2115..d7edf21ac 100644
--- a/init/README.md
+++ b/init/README.md
@@ -381,6 +381,11 @@ Commands
381 within _argument_. 381 within _argument_.
382 Init halts executing commands until the forked process exits. 382 Init halts executing commands until the forked process exits.
383 383
384`exec_background [ <seclabel> [ <user> [ <group>\* ] ] ] -- <command> [ <argument>\* ]`
385> Fork and execute command with the given arguments. This is handled similarly
386 to the `exec` command. The difference is that init does not halt executing
387 commands until the process exits for `exec_background`.
388
384`exec_start <service>` 389`exec_start <service>`
385> Start a given service and halt the processing of additional init commands 390> Start a given service and halt the processing of additional init commands
386 until it returns. The command functions similarly to the `exec` command, 391 until it returns. The command functions similarly to the `exec` command,
@@ -453,8 +458,9 @@ Commands
453`rmdir <path>` 458`rmdir <path>`
454> Calls rmdir(2) on the given path. 459> Calls rmdir(2) on the given path.
455 460
456`readahead <file|dir>` 461`readahead <file|dir> [--fully]`
457> Calls readahead(2) on the file or files within given directory. 462> Calls readahead(2) on the file or files within given directory.
463 Use option --fully to read the full file content.
458 464
459`setprop <name> <value>` 465`setprop <name> <value>`
460> Set system property _name_ to _value_. Properties are expanded 466> Set system property _name_ to _value_. Properties are expanded
diff --git a/init/action.cpp b/init/action.cpp
index 60204a8d8..2617d009f 100644
--- a/init/action.cpp
+++ b/init/action.cpp
@@ -24,34 +24,48 @@
24#include "util.h" 24#include "util.h"
25 25
26using android::base::Join; 26using android::base::Join;
27using android::base::StartsWith;
27 28
28namespace android { 29namespace android {
29namespace init { 30namespace init {
30 31
31Command::Command(BuiltinFunction f, const std::vector<std::string>& args, int line) 32Result<Success> RunBuiltinFunction(const BuiltinFunction& function,
32 : func_(f), args_(args), line_(line) {} 33 const std::vector<std::string>& args,
34 const std::string& context) {
35 auto builtin_arguments = BuiltinArguments(context);
33 36
34Result<Success> Command::InvokeFunc() const { 37 builtin_arguments.args.resize(args.size());
35 std::vector<std::string> expanded_args; 38 builtin_arguments.args[0] = args[0];
36 expanded_args.resize(args_.size()); 39 for (std::size_t i = 1; i < args.size(); ++i) {
37 expanded_args[0] = args_[0]; 40 if (!expand_props(args[i], &builtin_arguments.args[i])) {
38 for (std::size_t i = 1; i < args_.size(); ++i) { 41 return Error() << "cannot expand '" << args[i] << "'";
39 if (!expand_props(args_[i], &expanded_args[i])) {
40 return Error() << "cannot expand '" << args_[i] << "'";
41 } 42 }
42 } 43 }
43 44
44 return func_(expanded_args); 45 return function(builtin_arguments);
46}
47
48Command::Command(BuiltinFunction f, bool execute_in_subcontext,
49 const std::vector<std::string>& args, int line)
50 : func_(std::move(f)), execute_in_subcontext_(execute_in_subcontext), args_(args), line_(line) {}
51
52Result<Success> Command::InvokeFunc(Subcontext* subcontext) const {
53 if (execute_in_subcontext_ && subcontext) {
54 return subcontext->Execute(args_);
55 } else {
56 const std::string& context = subcontext ? subcontext->context() : kInitContext;
57 return RunBuiltinFunction(func_, args_, context);
58 }
45} 59}
46 60
47std::string Command::BuildCommandString() const { 61std::string Command::BuildCommandString() const {
48 return Join(args_, ' '); 62 return Join(args_, ' ');
49} 63}
50 64
51Action::Action(bool oneshot, const std::string& filename, int line) 65Action::Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line)
52 : oneshot_(oneshot), filename_(filename), line_(line) {} 66 : oneshot_(oneshot), subcontext_(subcontext), filename_(filename), line_(line) {}
53 67
54const KeywordMap<BuiltinFunction>* Action::function_map_ = nullptr; 68const KeywordFunctionMap* Action::function_map_ = nullptr;
55 69
56Result<Success> Action::AddCommand(const std::vector<std::string>& args, int line) { 70Result<Success> Action::AddCommand(const std::vector<std::string>& args, int line) {
57 if (!function_map_) { 71 if (!function_map_) {
@@ -61,12 +75,12 @@ Result<Success> Action::AddCommand(const std::vector<std::string>& args, int lin
61 auto function = function_map_->FindFunction(args); 75 auto function = function_map_->FindFunction(args);
62 if (!function) return Error() << function.error(); 76 if (!function) return Error() << function.error();
63 77
64 AddCommand(*function, args, line); 78 commands_.emplace_back(function->second, function->first, args, line);
65 return Success(); 79 return Success();
66} 80}
67 81
68void Action::AddCommand(BuiltinFunction f, const std::vector<std::string>& args, int line) { 82void Action::AddCommand(BuiltinFunction f, const std::vector<std::string>& args, int line) {
69 commands_.emplace_back(f, args, line); 83 commands_.emplace_back(f, false, args, line);
70} 84}
71 85
72std::size_t Action::NumCommands() const { 86std::size_t Action::NumCommands() const {
@@ -88,7 +102,7 @@ void Action::ExecuteAllCommands() const {
88 102
89void Action::ExecuteCommand(const Command& command) const { 103void Action::ExecuteCommand(const Command& command) const {
90 android::base::Timer t; 104 android::base::Timer t;
91 auto result = command.InvokeFunc(); 105 auto result = command.InvokeFunc(subcontext_);
92 auto duration = t.duration(); 106 auto duration = t.duration();
93 107
94 // There are many legacy paths in rootdir/init.rc that will virtually never exist on a new 108 // There are many legacy paths in rootdir/init.rc that will virtually never exist on a new
@@ -261,7 +275,7 @@ void ActionManager::QueueAllPropertyActions() {
261} 275}
262 276
263void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) { 277void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) {
264 auto action = std::make_unique<Action>(true, "<Builtin Action>", 0); 278 auto action = std::make_unique<Action>(true, nullptr, "<Builtin Action>", 0);
265 std::vector<std::string> name_vector{name}; 279 std::vector<std::string> name_vector{name};
266 280
267 if (auto result = action->InitSingleTrigger(name); !result) { 281 if (auto result = action->InitSingleTrigger(name); !result) {
@@ -341,7 +355,17 @@ Result<Success> ActionParser::ParseSection(std::vector<std::string>&& args,
341 return Error() << "Actions must have a trigger"; 355 return Error() << "Actions must have a trigger";
342 } 356 }
343 357
344 auto action = std::make_unique<Action>(false, filename, line); 358 Subcontext* action_subcontext = nullptr;
359 if (subcontexts_) {
360 for (auto& subcontext : *subcontexts_) {
361 if (StartsWith(filename, subcontext.path_prefix().c_str())) {
362 action_subcontext = &subcontext;
363 break;
364 }
365 }
366 }
367
368 auto action = std::make_unique<Action>(false, action_subcontext, filename, line);
345 369
346 if (auto result = action->InitTriggers(triggers); !result) { 370 if (auto result = action->InitTriggers(triggers); !result) {
347 return Error() << "InitTriggers() failed: " << result.error(); 371 return Error() << "InitTriggers() failed: " << result.error();
diff --git a/init/action.h b/init/action.h
index d977f827a..cdfc6a053 100644
--- a/init/action.h
+++ b/init/action.h
@@ -27,21 +27,27 @@
27#include "keyword_map.h" 27#include "keyword_map.h"
28#include "parser.h" 28#include "parser.h"
29#include "result.h" 29#include "result.h"
30#include "subcontext.h"
30 31
31namespace android { 32namespace android {
32namespace init { 33namespace init {
33 34
35Result<Success> RunBuiltinFunction(const BuiltinFunction& function,
36 const std::vector<std::string>& args, const std::string& context);
37
34class Command { 38class Command {
35 public: 39 public:
36 Command(BuiltinFunction f, const std::vector<std::string>& args, int line); 40 Command(BuiltinFunction f, bool execute_in_subcontext, const std::vector<std::string>& args,
41 int line);
37 42
38 Result<Success> InvokeFunc() const; 43 Result<Success> InvokeFunc(Subcontext* subcontext) const;
39 std::string BuildCommandString() const; 44 std::string BuildCommandString() const;
40 45
41 int line() const { return line_; } 46 int line() const { return line_; }
42 47
43 private: 48 private:
44 BuiltinFunction func_; 49 BuiltinFunction func_;
50 bool execute_in_subcontext_;
45 std::vector<std::string> args_; 51 std::vector<std::string> args_;
46 int line_; 52 int line_;
47}; 53};
@@ -52,7 +58,7 @@ using BuiltinAction = class Action*;
52 58
53class Action { 59class Action {
54 public: 60 public:
55 explicit Action(bool oneshot, const std::string& filename, int line); 61 Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line);
56 62
57 Result<Success> AddCommand(const std::vector<std::string>& args, int line); 63 Result<Success> AddCommand(const std::vector<std::string>& args, int line);
58 void AddCommand(BuiltinFunction f, const std::vector<std::string>& args, int line); 64 void AddCommand(BuiltinFunction f, const std::vector<std::string>& args, int line);
@@ -70,12 +76,11 @@ class Action {
70 bool oneshot() const { return oneshot_; } 76 bool oneshot() const { return oneshot_; }
71 const std::string& filename() const { return filename_; } 77 const std::string& filename() const { return filename_; }
72 int line() const { return line_; } 78 int line() const { return line_; }
73 static void set_function_map(const KeywordMap<BuiltinFunction>* function_map) { 79 static void set_function_map(const KeywordFunctionMap* function_map) {
74 function_map_ = function_map; 80 function_map_ = function_map;
75 } 81 }
76 82
77 83 private:
78private:
79 void ExecuteCommand(const Command& command) const; 84 void ExecuteCommand(const Command& command) const;
80 bool CheckPropertyTriggers(const std::string& name = "", 85 bool CheckPropertyTriggers(const std::string& name = "",
81 const std::string& value = "") const; 86 const std::string& value = "") const;
@@ -85,9 +90,10 @@ private:
85 std::string event_trigger_; 90 std::string event_trigger_;
86 std::vector<Command> commands_; 91 std::vector<Command> commands_;
87 bool oneshot_; 92 bool oneshot_;
93 Subcontext* subcontext_;
88 std::string filename_; 94 std::string filename_;
89 int line_; 95 int line_;
90 static const KeywordMap<BuiltinFunction>* function_map_; 96 static const KeywordFunctionMap* function_map_;
91}; 97};
92 98
93class ActionManager { 99class ActionManager {
@@ -119,8 +125,8 @@ class ActionManager {
119 125
120class ActionParser : public SectionParser { 126class ActionParser : public SectionParser {
121 public: 127 public:
122 ActionParser(ActionManager* action_manager) 128 ActionParser(ActionManager* action_manager, std::vector<Subcontext>* subcontexts)
123 : action_manager_(action_manager), action_(nullptr) {} 129 : action_manager_(action_manager), subcontexts_(subcontexts), action_(nullptr) {}
124 Result<Success> ParseSection(std::vector<std::string>&& args, const std::string& filename, 130 Result<Success> ParseSection(std::vector<std::string>&& args, const std::string& filename,
125 int line) override; 131 int line) override;
126 Result<Success> ParseLineSection(std::vector<std::string>&& args, int line) override; 132 Result<Success> ParseLineSection(std::vector<std::string>&& args, int line) override;
@@ -128,6 +134,7 @@ class ActionParser : public SectionParser {
128 134
129 private: 135 private:
130 ActionManager* action_manager_; 136 ActionManager* action_manager_;
137 std::vector<Subcontext>* subcontexts_;
131 std::unique_ptr<Action> action_; 138 std::unique_ptr<Action> action_;
132}; 139};
133 140
diff --git a/init/bootchart.cpp b/init/bootchart.cpp
index ec84317c3..379b4fa84 100644
--- a/init/bootchart.cpp
+++ b/init/bootchart.cpp
@@ -191,7 +191,7 @@ static Result<Success> do_bootchart_stop() {
191 return Success(); 191 return Success();
192} 192}
193 193
194Result<Success> do_bootchart(const std::vector<std::string>& args) { 194Result<Success> do_bootchart(const BuiltinArguments& args) {
195 if (args[1] == "start") return do_bootchart_start(); 195 if (args[1] == "start") return do_bootchart_start();
196 return do_bootchart_stop(); 196 return do_bootchart_stop();
197} 197}
diff --git a/init/bootchart.h b/init/bootchart.h
index f614f712f..05474ca09 100644
--- a/init/bootchart.h
+++ b/init/bootchart.h
@@ -20,12 +20,13 @@
20#include <string> 20#include <string>
21#include <vector> 21#include <vector>
22 22
23#include "builtin_arguments.h"
23#include "result.h" 24#include "result.h"
24 25
25namespace android { 26namespace android {
26namespace init { 27namespace init {
27 28
28Result<Success> do_bootchart(const std::vector<std::string>& args); 29Result<Success> do_bootchart(const BuiltinArguments& args);
29 30
30} // namespace init 31} // namespace init
31} // namespace android 32} // namespace android
diff --git a/init/builtin_arguments.h b/init/builtin_arguments.h
new file mode 100644
index 000000000..1742b78a6
--- /dev/null
+++ b/init/builtin_arguments.h
@@ -0,0 +1,43 @@
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _INIT_BUILTIN_ARGUMENTS_H
18#define _INIT_BUILTIN_ARGUMENTS_H
19
20#include <string>
21#include <vector>
22
23namespace android {
24namespace init {
25
26struct BuiltinArguments {
27 BuiltinArguments(const std::string& context) : context(context) {}
28 BuiltinArguments(std::vector<std::string> args, const std::string& context)
29 : args(std::move(args)), context(context) {}
30
31 const std::string& operator[](std::size_t i) const { return args[i]; }
32 auto begin() const { return args.begin(); }
33 auto end() const { return args.end(); }
34 auto size() const { return args.size(); }
35
36 std::vector<std::string> args;
37 const std::string& context;
38};
39
40} // namespace init
41} // namespace android
42
43#endif
diff --git a/init/builtins.cpp b/init/builtins.cpp
index e2e3d933b..027b392fd 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -56,6 +56,7 @@
56#include <selinux/android.h> 56#include <selinux/android.h>
57#include <selinux/label.h> 57#include <selinux/label.h>
58#include <selinux/selinux.h> 58#include <selinux/selinux.h>
59#include <system/thread_defs.h>
59 60
60#include "action.h" 61#include "action.h"
61#include "bootchart.h" 62#include "bootchart.h"
@@ -65,7 +66,7 @@
65#include "reboot.h" 66#include "reboot.h"
66#include "rlimit_parser.h" 67#include "rlimit_parser.h"
67#include "service.h" 68#include "service.h"
68#include "signal_handler.h" 69#include "subcontext.h"
69#include "util.h" 70#include "util.h"
70 71
71using namespace std::literals::string_literals; 72using namespace std::literals::string_literals;
@@ -95,36 +96,43 @@ static void ForEachServiceInClass(const std::string& classname, F function) {
95 } 96 }
96} 97}
97 98
98static Result<Success> do_class_start(const std::vector<std::string>& args) { 99static Result<Success> do_class_start(const BuiltinArguments& args) {
99 // Starting a class does not start services which are explicitly disabled. 100 // Starting a class does not start services which are explicitly disabled.
100 // They must be started individually. 101 // They must be started individually.
101 ForEachServiceInClass(args[1], &Service::StartIfNotDisabled); 102 for (const auto& service : ServiceList::GetInstance()) {
103 if (service->classnames().count(args[1])) {
104 if (auto result = service->StartIfNotDisabled(); !result) {
105 LOG(ERROR) << "Could not start service '" << service->name()
106 << "' as part of class '" << args[1] << "': " << result.error();
107 }
108 }
109 }
102 return Success(); 110 return Success();
103} 111}
104 112
105static Result<Success> do_class_stop(const std::vector<std::string>& args) { 113static Result<Success> do_class_stop(const BuiltinArguments& args) {
106 ForEachServiceInClass(args[1], &Service::Stop); 114 ForEachServiceInClass(args[1], &Service::Stop);
107 return Success(); 115 return Success();
108} 116}
109 117
110static Result<Success> do_class_reset(const std::vector<std::string>& args) { 118static Result<Success> do_class_reset(const BuiltinArguments& args) {
111 ForEachServiceInClass(args[1], &Service::Reset); 119 ForEachServiceInClass(args[1], &Service::Reset);
112 return Success(); 120 return Success();
113} 121}
114 122
115static Result<Success> do_class_restart(const std::vector<std::string>& args) { 123static Result<Success> do_class_restart(const BuiltinArguments& args) {
116 ForEachServiceInClass(args[1], &Service::Restart); 124 ForEachServiceInClass(args[1], &Service::Restart);
117 return Success(); 125 return Success();
118} 126}
119 127
120static Result<Success> do_domainname(const std::vector<std::string>& args) { 128static Result<Success> do_domainname(const BuiltinArguments& args) {
121 if (auto result = WriteFile("/proc/sys/kernel/domainname", args[1]); !result) { 129 if (auto result = WriteFile("/proc/sys/kernel/domainname", args[1]); !result) {
122 return Error() << "Unable to write to /proc/sys/kernel/domainname: " << result.error(); 130 return Error() << "Unable to write to /proc/sys/kernel/domainname: " << result.error();
123 } 131 }
124 return Success(); 132 return Success();
125} 133}
126 134
127static Result<Success> do_enable(const std::vector<std::string>& args) { 135static Result<Success> do_enable(const BuiltinArguments& args) {
128 Service* svc = ServiceList::GetInstance().FindService(args[1]); 136 Service* svc = ServiceList::GetInstance().FindService(args[1]);
129 if (!svc) return Error() << "Could not find service"; 137 if (!svc) return Error() << "Could not find service";
130 138
@@ -135,8 +143,8 @@ static Result<Success> do_enable(const std::vector<std::string>& args) {
135 return Success(); 143 return Success();
136} 144}
137 145
138static Result<Success> do_exec(const std::vector<std::string>& args) { 146static Result<Success> do_exec(const BuiltinArguments& args) {
139 auto service = Service::MakeTemporaryOneshotService(args); 147 auto service = Service::MakeTemporaryOneshotService(args.args);
140 if (!service) { 148 if (!service) {
141 return Error() << "Could not create exec service"; 149 return Error() << "Could not create exec service";
142 } 150 }
@@ -148,7 +156,20 @@ static Result<Success> do_exec(const std::vector<std::string>& args) {
148 return Success(); 156 return Success();
149} 157}
150 158
151static Result<Success> do_exec_start(const std::vector<std::string>& args) { 159static Result<Success> do_exec_background(const BuiltinArguments& args) {
160 auto service = Service::MakeTemporaryOneshotService(args.args);
161 if (!service) {
162 return Error() << "Could not create exec background service";
163 }
164 if (auto result = service->Start(); !result) {
165 return Error() << "Could not start exec background service: " << result.error();
166 }
167
168 ServiceList::GetInstance().AddService(std::move(service));
169 return Success();
170}
171
172static Result<Success> do_exec_start(const BuiltinArguments& args) {
152 Service* service = ServiceList::GetInstance().FindService(args[1]); 173 Service* service = ServiceList::GetInstance().FindService(args[1]);
153 if (!service) { 174 if (!service) {
154 return Error() << "Service not found"; 175 return Error() << "Service not found";
@@ -161,21 +182,21 @@ static Result<Success> do_exec_start(const std::vector<std::string>& args) {
161 return Success(); 182 return Success();
162} 183}
163 184
164static Result<Success> do_export(const std::vector<std::string>& args) { 185static Result<Success> do_export(const BuiltinArguments& args) {
165 if (setenv(args[1].c_str(), args[2].c_str(), 1) == -1) { 186 if (setenv(args[1].c_str(), args[2].c_str(), 1) == -1) {
166 return ErrnoError() << "setenv() failed"; 187 return ErrnoError() << "setenv() failed";
167 } 188 }
168 return Success(); 189 return Success();
169} 190}
170 191
171static Result<Success> do_hostname(const std::vector<std::string>& args) { 192static Result<Success> do_hostname(const BuiltinArguments& args) {
172 if (auto result = WriteFile("/proc/sys/kernel/hostname", args[1]); !result) { 193 if (auto result = WriteFile("/proc/sys/kernel/hostname", args[1]); !result) {
173 return Error() << "Unable to write to /proc/sys/kernel/hostname: " << result.error(); 194 return Error() << "Unable to write to /proc/sys/kernel/hostname: " << result.error();
174 } 195 }
175 return Success(); 196 return Success();
176} 197}
177 198
178static Result<Success> do_ifup(const std::vector<std::string>& args) { 199static Result<Success> do_ifup(const BuiltinArguments& args) {
179 struct ifreq ifr; 200 struct ifreq ifr;
180 201
181 strlcpy(ifr.ifr_name, args[1].c_str(), IFNAMSIZ); 202 strlcpy(ifr.ifr_name, args[1].c_str(), IFNAMSIZ);
@@ -196,7 +217,7 @@ static Result<Success> do_ifup(const std::vector<std::string>& args) {
196 return Success(); 217 return Success();
197} 218}
198 219
199static Result<Success> do_insmod(const std::vector<std::string>& args) { 220static Result<Success> do_insmod(const BuiltinArguments& args) {
200 int flags = 0; 221 int flags = 0;
201 auto it = args.begin() + 1; 222 auto it = args.begin() + 1;
202 223
@@ -218,7 +239,7 @@ static Result<Success> do_insmod(const std::vector<std::string>& args) {
218} 239}
219 240
220// mkdir <path> [mode] [owner] [group] 241// mkdir <path> [mode] [owner] [group]
221static Result<Success> do_mkdir(const std::vector<std::string>& args) { 242static Result<Success> do_mkdir(const BuiltinArguments& args) {
222 mode_t mode = 0755; 243 mode_t mode = 0755;
223 if (args.size() >= 3) { 244 if (args.size() >= 3) {
224 mode = std::strtoul(args[2].c_str(), 0, 8); 245 mode = std::strtoul(args[2].c_str(), 0, 8);
@@ -267,14 +288,14 @@ static Result<Success> do_mkdir(const std::vector<std::string>& args) {
267 "--prompt_and_wipe_data", 288 "--prompt_and_wipe_data",
268 "--reason=set_policy_failed:"s + args[1]}; 289 "--reason=set_policy_failed:"s + args[1]};
269 reboot_into_recovery(options); 290 reboot_into_recovery(options);
270 return Error() << "reboot into recovery failed"; 291 return Success();
271 } 292 }
272 } 293 }
273 return Success(); 294 return Success();
274} 295}
275 296
276/* umount <path> */ 297/* umount <path> */
277static Result<Success> do_umount(const std::vector<std::string>& args) { 298static Result<Success> do_umount(const BuiltinArguments& args) {
278 if (umount(args[1].c_str()) < 0) { 299 if (umount(args[1].c_str()) < 0) {
279 return ErrnoError() << "umount() failed"; 300 return ErrnoError() << "umount() failed";
280 } 301 }
@@ -306,7 +327,7 @@ static struct {
306#define DATA_MNT_POINT "/data" 327#define DATA_MNT_POINT "/data"
307 328
308/* mount <type> <device> <path> <flags ...> <options> */ 329/* mount <type> <device> <path> <flags ...> <options> */
309static Result<Success> do_mount(const std::vector<std::string>& args) { 330static Result<Success> do_mount(const BuiltinArguments& args) {
310 const char* options = nullptr; 331 const char* options = nullptr;
311 unsigned flags = 0; 332 unsigned flags = 0;
312 bool wait = false; 333 bool wait = false;
@@ -472,7 +493,7 @@ static Result<Success> queue_fs_event(int code) {
472 PLOG(ERROR) << "fs_mgr_mount_all suggested recovery, so wiping data via recovery."; 493 PLOG(ERROR) << "fs_mgr_mount_all suggested recovery, so wiping data via recovery.";
473 const std::vector<std::string> options = {"--wipe_data", "--reason=fs_mgr_mount_all" }; 494 const std::vector<std::string> options = {"--wipe_data", "--reason=fs_mgr_mount_all" };
474 reboot_into_recovery(options); 495 reboot_into_recovery(options);
475 return Error() << "reboot_into_recovery() failed"; 496 return Success();
476 /* If reboot worked, there is no return. */ 497 /* If reboot worked, there is no return. */
477 } else if (code == FS_MGR_MNTALL_DEV_FILE_ENCRYPTED) { 498 } else if (code == FS_MGR_MNTALL_DEV_FILE_ENCRYPTED) {
478 if (e4crypt_install_keyring()) { 499 if (e4crypt_install_keyring()) {
@@ -498,7 +519,7 @@ static Result<Success> queue_fs_event(int code) {
498 * This function might request a reboot, in which case it will 519 * This function might request a reboot, in which case it will
499 * not return. 520 * not return.
500 */ 521 */
501static Result<Success> do_mount_all(const std::vector<std::string>& args) { 522static Result<Success> do_mount_all(const BuiltinArguments& args) {
502 std::size_t na = 0; 523 std::size_t na = 0;
503 bool import_rc = true; 524 bool import_rc = true;
504 bool queue_event = true; 525 bool queue_event = true;
@@ -531,7 +552,7 @@ static Result<Success> do_mount_all(const std::vector<std::string>& args) {
531 552
532 if (import_rc) { 553 if (import_rc) {
533 /* Paths of .rc files are specified at the 2nd argument and beyond */ 554 /* Paths of .rc files are specified at the 2nd argument and beyond */
534 import_late(args, 2, path_arg_end); 555 import_late(args.args, 2, path_arg_end);
535 } 556 }
536 557
537 if (queue_event) { 558 if (queue_event) {
@@ -546,7 +567,7 @@ static Result<Success> do_mount_all(const std::vector<std::string>& args) {
546 return Success(); 567 return Success();
547} 568}
548 569
549static Result<Success> do_swapon_all(const std::vector<std::string>& args) { 570static Result<Success> do_swapon_all(const BuiltinArguments& args) {
550 struct fstab *fstab; 571 struct fstab *fstab;
551 int ret; 572 int ret;
552 573
@@ -558,13 +579,13 @@ static Result<Success> do_swapon_all(const std::vector<std::string>& args) {
558 return Success(); 579 return Success();
559} 580}
560 581
561static Result<Success> do_setprop(const std::vector<std::string>& args) { 582static Result<Success> do_setprop(const BuiltinArguments& args) {
562 property_set(args[1], args[2]); 583 property_set(args[1], args[2]);
563 return Success(); 584 return Success();
564} 585}
565 586
566static Result<Success> do_setrlimit(const std::vector<std::string>& args) { 587static Result<Success> do_setrlimit(const BuiltinArguments& args) {
567 auto rlimit = ParseRlimit(args); 588 auto rlimit = ParseRlimit(args.args);
568 if (!rlimit) return rlimit.error(); 589 if (!rlimit) return rlimit.error();
569 590
570 if (setrlimit(rlimit->first, &rlimit->second) == -1) { 591 if (setrlimit(rlimit->first, &rlimit->second) == -1) {
@@ -573,7 +594,7 @@ static Result<Success> do_setrlimit(const std::vector<std::string>& args) {
573 return Success(); 594 return Success();
574} 595}
575 596
576static Result<Success> do_start(const std::vector<std::string>& args) { 597static Result<Success> do_start(const BuiltinArguments& args) {
577 Service* svc = ServiceList::GetInstance().FindService(args[1]); 598 Service* svc = ServiceList::GetInstance().FindService(args[1]);
578 if (!svc) return Error() << "service " << args[1] << " not found"; 599 if (!svc) return Error() << "service " << args[1] << " not found";
579 if (auto result = svc->Start(); !result) { 600 if (auto result = svc->Start(); !result) {
@@ -582,26 +603,26 @@ static Result<Success> do_start(const std::vector<std::string>& args) {
582 return Success(); 603 return Success();
583} 604}
584 605
585static Result<Success> do_stop(const std::vector<std::string>& args) { 606static Result<Success> do_stop(const BuiltinArguments& args) {
586 Service* svc = ServiceList::GetInstance().FindService(args[1]); 607 Service* svc = ServiceList::GetInstance().FindService(args[1]);
587 if (!svc) return Error() << "service " << args[1] << " not found"; 608 if (!svc) return Error() << "service " << args[1] << " not found";
588 svc->Stop(); 609 svc->Stop();
589 return Success(); 610 return Success();
590} 611}
591 612
592static Result<Success> do_restart(const std::vector<std::string>& args) { 613static Result<Success> do_restart(const BuiltinArguments& args) {
593 Service* svc = ServiceList::GetInstance().FindService(args[1]); 614 Service* svc = ServiceList::GetInstance().FindService(args[1]);
594 if (!svc) return Error() << "service " << args[1] << " not found"; 615 if (!svc) return Error() << "service " << args[1] << " not found";
595 svc->Restart(); 616 svc->Restart();
596 return Success(); 617 return Success();
597} 618}
598 619
599static Result<Success> do_trigger(const std::vector<std::string>& args) { 620static Result<Success> do_trigger(const BuiltinArguments& args) {
600 ActionManager::GetInstance().QueueEventTrigger(args[1]); 621 ActionManager::GetInstance().QueueEventTrigger(args[1]);
601 return Success(); 622 return Success();
602} 623}
603 624
604static Result<Success> do_symlink(const std::vector<std::string>& args) { 625static Result<Success> do_symlink(const BuiltinArguments& args) {
605 if (symlink(args[1].c_str(), args[2].c_str()) < 0) { 626 if (symlink(args[1].c_str(), args[2].c_str()) < 0) {
606 // The symlink builtin is often used to create symlinks for older devices to be backwards 627 // The symlink builtin is often used to create symlinks for older devices to be backwards
607 // compatible with new paths, therefore we skip reporting this error. 628 // compatible with new paths, therefore we skip reporting this error.
@@ -613,21 +634,21 @@ static Result<Success> do_symlink(const std::vector<std::string>& args) {
613 return Success(); 634 return Success();
614} 635}
615 636
616static Result<Success> do_rm(const std::vector<std::string>& args) { 637static Result<Success> do_rm(const BuiltinArguments& args) {
617 if (unlink(args[1].c_str()) < 0) { 638 if (unlink(args[1].c_str()) < 0) {
618 return ErrnoError() << "unlink() failed"; 639 return ErrnoError() << "unlink() failed";
619 } 640 }
620 return Success(); 641 return Success();
621} 642}
622 643
623static Result<Success> do_rmdir(const std::vector<std::string>& args) { 644static Result<Success> do_rmdir(const BuiltinArguments& args) {
624 if (rmdir(args[1].c_str()) < 0) { 645 if (rmdir(args[1].c_str()) < 0) {
625 return ErrnoError() << "rmdir() failed"; 646 return ErrnoError() << "rmdir() failed";
626 } 647 }
627 return Success(); 648 return Success();
628} 649}
629 650
630static Result<Success> do_sysclktz(const std::vector<std::string>& args) { 651static Result<Success> do_sysclktz(const BuiltinArguments& args) {
631 struct timezone tz = {}; 652 struct timezone tz = {};
632 if (!android::base::ParseInt(args[1], &tz.tz_minuteswest)) { 653 if (!android::base::ParseInt(args[1], &tz.tz_minuteswest)) {
633 return Error() << "Unable to parse mins_west_of_gmt"; 654 return Error() << "Unable to parse mins_west_of_gmt";
@@ -639,7 +660,7 @@ static Result<Success> do_sysclktz(const std::vector<std::string>& args) {
639 return Success(); 660 return Success();
640} 661}
641 662
642static Result<Success> do_verity_load_state(const std::vector<std::string>& args) { 663static Result<Success> do_verity_load_state(const BuiltinArguments& args) {
643 int mode = -1; 664 int mode = -1;
644 bool loaded = fs_mgr_load_verity_state(&mode); 665 bool loaded = fs_mgr_load_verity_state(&mode);
645 if (loaded && mode != VERITY_MODE_DEFAULT) { 666 if (loaded && mode != VERITY_MODE_DEFAULT) {
@@ -655,14 +676,14 @@ static void verity_update_property(fstab_rec *fstab, const char *mount_point,
655 property_set("partition."s + mount_point + ".verified", std::to_string(mode)); 676 property_set("partition."s + mount_point + ".verified", std::to_string(mode));
656} 677}
657 678
658static Result<Success> do_verity_update_state(const std::vector<std::string>& args) { 679static Result<Success> do_verity_update_state(const BuiltinArguments& args) {
659 if (!fs_mgr_update_verity_state(verity_update_property)) { 680 if (!fs_mgr_update_verity_state(verity_update_property)) {
660 return Error() << "fs_mgr_update_verity_state() failed"; 681 return Error() << "fs_mgr_update_verity_state() failed";
661 } 682 }
662 return Success(); 683 return Success();
663} 684}
664 685
665static Result<Success> do_write(const std::vector<std::string>& args) { 686static Result<Success> do_write(const BuiltinArguments& args) {
666 if (auto result = WriteFile(args[1], args[2]); !result) { 687 if (auto result = WriteFile(args[1], args[2]); !result) {
667 return Error() << "Unable to write to file '" << args[1] << "': " << result.error(); 688 return Error() << "Unable to write to file '" << args[1] << "': " << result.error();
668 } 689 }
@@ -670,13 +691,40 @@ static Result<Success> do_write(const std::vector<std::string>& args) {
670 return Success(); 691 return Success();
671} 692}
672 693
673static Result<Success> do_readahead(const std::vector<std::string>& args) { 694static Result<Success> readahead_file(const std::string& filename, bool fully) {
695 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filename.c_str(), O_RDONLY)));
696 if (fd == -1) {
697 return ErrnoError() << "Error opening file";
698 }
699 if (posix_fadvise(fd, 0, 0, POSIX_FADV_WILLNEED)) {
700 return ErrnoError() << "Error posix_fadvise file";
701 }
702 if (readahead(fd, 0, std::numeric_limits<size_t>::max())) {
703 return ErrnoError() << "Error readahead file";
704 }
705 if (fully) {
706 char buf[BUFSIZ];
707 ssize_t n;
708 while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) {
709 }
710 if (n != 0) {
711 return ErrnoError() << "Error reading file";
712 }
713 }
714 return Success();
715}
716
717static Result<Success> do_readahead(const BuiltinArguments& args) {
674 struct stat sb; 718 struct stat sb;
675 719
676 if (stat(args[1].c_str(), &sb)) { 720 if (stat(args[1].c_str(), &sb)) {
677 return ErrnoError() << "Error opening " << args[1]; 721 return ErrnoError() << "Error opening " << args[1];
678 } 722 }
679 723
724 bool readfully = false;
725 if (args.size() == 3 && args[2] == "--fully") {
726 readfully = true;
727 }
680 // We will do readahead in a forked process in order not to block init 728 // We will do readahead in a forked process in order not to block init
681 // since it may block while it reads the 729 // since it may block while it reads the
682 // filesystem metadata needed to locate the requested blocks. This 730 // filesystem metadata needed to locate the requested blocks. This
@@ -685,15 +733,16 @@ static Result<Success> do_readahead(const std::vector<std::string>& args) {
685 // the requested data has been read. 733 // the requested data has been read.
686 pid_t pid = fork(); 734 pid_t pid = fork();
687 if (pid == 0) { 735 if (pid == 0) {
736 if (setpriority(PRIO_PROCESS, 0, static_cast<int>(ANDROID_PRIORITY_LOWEST)) != 0) {
737 PLOG(WARNING) << "setpriority failed";
738 }
739 if (android_set_ioprio(0, IoSchedClass_IDLE, 7)) {
740 PLOG(WARNING) << "ioprio_get failed";
741 }
688 android::base::Timer t; 742 android::base::Timer t;
689 if (S_ISREG(sb.st_mode)) { 743 if (S_ISREG(sb.st_mode)) {
690 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(args[1].c_str(), O_RDONLY))); 744 if (auto result = readahead_file(args[1], readfully); !result) {
691 if (fd == -1) { 745 LOG(WARNING) << "Unable to readahead '" << args[1] << "': " << result.error();
692 PLOG(ERROR) << "Error opening file: " << args[1];
693 _exit(EXIT_FAILURE);
694 }
695 if (readahead(fd, 0, std::numeric_limits<size_t>::max())) {
696 PLOG(ERROR) << "Error readahead file: " << args[1];
697 _exit(EXIT_FAILURE); 746 _exit(EXIT_FAILURE);
698 } 747 }
699 } else if (S_ISDIR(sb.st_mode)) { 748 } else if (S_ISDIR(sb.st_mode)) {
@@ -708,19 +757,15 @@ static Result<Success> do_readahead(const std::vector<std::string>& args) {
708 for (FTSENT* ftsent = fts_read(fts.get()); ftsent != nullptr; 757 for (FTSENT* ftsent = fts_read(fts.get()); ftsent != nullptr;
709 ftsent = fts_read(fts.get())) { 758 ftsent = fts_read(fts.get())) {
710 if (ftsent->fts_info & FTS_F) { 759 if (ftsent->fts_info & FTS_F) {
711 android::base::unique_fd fd( 760 const std::string filename = ftsent->fts_accpath;
712 TEMP_FAILURE_RETRY(open(ftsent->fts_accpath, O_RDONLY))); 761 if (auto result = readahead_file(filename, readfully); !result) {
713 if (fd == -1) { 762 LOG(WARNING)
714 PLOG(ERROR) << "Error opening file: " << args[1]; 763 << "Unable to readahead '" << filename << "': " << result.error();
715 continue;
716 }
717 if (readahead(fd, 0, std::numeric_limits<size_t>::max())) {
718 PLOG(ERROR) << "Unable to readahead on file: " << ftsent->fts_accpath;
719 } 764 }
720 } 765 }
721 } 766 }
722 } 767 }
723 LOG(INFO) << "Readahead " << args[1] << " took " << t; 768 LOG(INFO) << "Readahead " << args[1] << " took " << t << " asynchronously";
724 _exit(0); 769 _exit(0);
725 } else if (pid < 0) { 770 } else if (pid < 0) {
726 return ErrnoError() << "Fork failed"; 771 return ErrnoError() << "Fork failed";
@@ -728,7 +773,7 @@ static Result<Success> do_readahead(const std::vector<std::string>& args) {
728 return Success(); 773 return Success();
729} 774}
730 775
731static Result<Success> do_copy(const std::vector<std::string>& args) { 776static Result<Success> do_copy(const BuiltinArguments& args) {
732 auto file_contents = ReadFile(args[1]); 777 auto file_contents = ReadFile(args[1]);
733 if (!file_contents) { 778 if (!file_contents) {
734 return Error() << "Could not read input file '" << args[1] << "': " << file_contents.error(); 779 return Error() << "Could not read input file '" << args[1] << "': " << file_contents.error();
@@ -740,7 +785,7 @@ static Result<Success> do_copy(const std::vector<std::string>& args) {
740 return Success(); 785 return Success();
741} 786}
742 787
743static Result<Success> do_chown(const std::vector<std::string>& args) { 788static Result<Success> do_chown(const BuiltinArguments& args) {
744 auto uid = DecodeUid(args[1]); 789 auto uid = DecodeUid(args[1]);
745 if (!uid) { 790 if (!uid) {
746 return Error() << "Unable to decode UID for '" << args[1] << "': " << uid.error(); 791 return Error() << "Unable to decode UID for '" << args[1] << "': " << uid.error();
@@ -777,7 +822,7 @@ static mode_t get_mode(const char *s) {
777 return mode; 822 return mode;
778} 823}
779 824
780static Result<Success> do_chmod(const std::vector<std::string>& args) { 825static Result<Success> do_chmod(const BuiltinArguments& args) {
781 mode_t mode = get_mode(args[1].c_str()); 826 mode_t mode = get_mode(args[1].c_str());
782 if (fchmodat(AT_FDCWD, args[2].c_str(), mode, AT_SYMLINK_NOFOLLOW) < 0) { 827 if (fchmodat(AT_FDCWD, args[2].c_str(), mode, AT_SYMLINK_NOFOLLOW) < 0) {
783 return ErrnoError() << "fchmodat() failed"; 828 return ErrnoError() << "fchmodat() failed";
@@ -785,7 +830,7 @@ static Result<Success> do_chmod(const std::vector<std::string>& args) {
785 return Success(); 830 return Success();
786} 831}
787 832
788static Result<Success> do_restorecon(const std::vector<std::string>& args) { 833static Result<Success> do_restorecon(const BuiltinArguments& args) {
789 int ret = 0; 834 int ret = 0;
790 835
791 struct flag_type {const char* name; int value;}; 836 struct flag_type {const char* name; int value;};
@@ -827,13 +872,13 @@ static Result<Success> do_restorecon(const std::vector<std::string>& args) {
827 return Success(); 872 return Success();
828} 873}
829 874
830static Result<Success> do_restorecon_recursive(const std::vector<std::string>& args) { 875static Result<Success> do_restorecon_recursive(const BuiltinArguments& args) {
831 std::vector<std::string> non_const_args(args); 876 std::vector<std::string> non_const_args(args.args);
832 non_const_args.insert(std::next(non_const_args.begin()), "--recursive"); 877 non_const_args.insert(std::next(non_const_args.begin()), "--recursive");
833 return do_restorecon(non_const_args); 878 return do_restorecon({std::move(non_const_args), args.context});
834} 879}
835 880
836static Result<Success> do_loglevel(const std::vector<std::string>& args) { 881static Result<Success> do_loglevel(const BuiltinArguments& args) {
837 // TODO: support names instead/as well? 882 // TODO: support names instead/as well?
838 int log_level = -1; 883 int log_level = -1;
839 android::base::ParseInt(args[1], &log_level); 884 android::base::ParseInt(args[1], &log_level);
@@ -854,17 +899,17 @@ static Result<Success> do_loglevel(const std::vector<std::string>& args) {
854 return Success(); 899 return Success();
855} 900}
856 901
857static Result<Success> do_load_persist_props(const std::vector<std::string>& args) { 902static Result<Success> do_load_persist_props(const BuiltinArguments& args) {
858 load_persist_props(); 903 load_persist_props();
859 return Success(); 904 return Success();
860} 905}
861 906
862static Result<Success> do_load_system_props(const std::vector<std::string>& args) { 907static Result<Success> do_load_system_props(const BuiltinArguments& args) {
863 load_system_props(); 908 load_system_props();
864 return Success(); 909 return Success();
865} 910}
866 911
867static Result<Success> do_wait(const std::vector<std::string>& args) { 912static Result<Success> do_wait(const BuiltinArguments& args) {
868 auto timeout = kCommandRetryTimeout; 913 auto timeout = kCommandRetryTimeout;
869 if (args.size() == 3) { 914 if (args.size() == 3) {
870 int timeout_int; 915 int timeout_int;
@@ -881,7 +926,7 @@ static Result<Success> do_wait(const std::vector<std::string>& args) {
881 return Success(); 926 return Success();
882} 927}
883 928
884static Result<Success> do_wait_for_prop(const std::vector<std::string>& args) { 929static Result<Success> do_wait_for_prop(const BuiltinArguments& args) {
885 const char* name = args[1].c_str(); 930 const char* name = args[1].c_str();
886 const char* value = args[2].c_str(); 931 const char* value = args[2].c_str();
887 size_t value_len = strlen(value); 932 size_t value_len = strlen(value);
@@ -902,7 +947,7 @@ static bool is_file_crypto() {
902 return android::base::GetProperty("ro.crypto.type", "") == "file"; 947 return android::base::GetProperty("ro.crypto.type", "") == "file";
903} 948}
904 949
905static Result<Success> do_installkey(const std::vector<std::string>& args) { 950static Result<Success> do_installkey(const BuiltinArguments& args) {
906 if (!is_file_crypto()) return Success(); 951 if (!is_file_crypto()) return Success();
907 952
908 auto unencrypted_dir = args[1] + e4crypt_unencrypted_folder; 953 auto unencrypted_dir = args[1] + e4crypt_unencrypted_folder;
@@ -911,63 +956,66 @@ static Result<Success> do_installkey(const std::vector<std::string>& args) {
911 } 956 }
912 std::vector<std::string> exec_args = {"exec", "/system/bin/vdc", "--wait", "cryptfs", 957 std::vector<std::string> exec_args = {"exec", "/system/bin/vdc", "--wait", "cryptfs",
913 "enablefilecrypto"}; 958 "enablefilecrypto"};
914 return do_exec(exec_args); 959 return do_exec({std::move(exec_args), args.context});
915} 960}
916 961
917static Result<Success> do_init_user0(const std::vector<std::string>& args) { 962static Result<Success> do_init_user0(const BuiltinArguments& args) {
918 std::vector<std::string> exec_args = {"exec", "/system/bin/vdc", "--wait", "cryptfs", 963 std::vector<std::string> exec_args = {"exec", "/system/bin/vdc", "--wait", "cryptfs",
919 "init_user0"}; 964 "init_user0"};
920 return do_exec(exec_args); 965 return do_exec({std::move(exec_args), args.context});
921} 966}
922 967
923const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const { 968const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
924 constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max(); 969 constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
925 // clang-format off 970 // clang-format off
926 static const Map builtin_functions = { 971 static const Map builtin_functions = {
927 {"bootchart", {1, 1, do_bootchart}}, 972 {"bootchart", {1, 1, {false, do_bootchart}}},
928 {"chmod", {2, 2, do_chmod}}, 973 {"chmod", {2, 2, {true, do_chmod}}},
929 {"chown", {2, 3, do_chown}}, 974 {"chown", {2, 3, {true, do_chown}}},
930 {"class_reset", {1, 1, do_class_reset}}, 975 {"class_reset", {1, 1, {false, do_class_reset}}},
931 {"class_restart", {1, 1, do_class_restart}}, 976 {"class_restart", {1, 1, {false, do_class_restart}}},
932 {"class_start", {1, 1, do_class_start}}, 977 {"class_start", {1, 1, {false, do_class_start}}},
933 {"class_stop", {1, 1, do_class_stop}}, 978 {"class_stop", {1, 1, {false, do_class_stop}}},
934 {"copy", {2, 2, do_copy}}, 979 {"copy", {2, 2, {true, do_copy}}},
935 {"domainname", {1, 1, do_domainname}}, 980 {"domainname", {1, 1, {true, do_domainname}}},
936 {"enable", {1, 1, do_enable}}, 981 {"enable", {1, 1, {false, do_enable}}},
937 {"exec", {1, kMax, do_exec}}, 982 {"exec", {1, kMax, {false, do_exec}}},
938 {"exec_start", {1, 1, do_exec_start}}, 983 {"exec_background", {1, kMax, {false, do_exec_background}}},
939 {"export", {2, 2, do_export}}, 984 {"exec_start", {1, 1, {false, do_exec_start}}},
940 {"hostname", {1, 1, do_hostname}}, 985 {"export", {2, 2, {false, do_export}}},
941 {"ifup", {1, 1, do_ifup}}, 986 {"hostname", {1, 1, {true, do_hostname}}},
942 {"init_user0", {0, 0, do_init_user0}}, 987 {"ifup", {1, 1, {true, do_ifup}}},
943 {"insmod", {1, kMax, do_insmod}}, 988 {"init_user0", {0, 0, {false, do_init_user0}}},
944 {"installkey", {1, 1, do_installkey}}, 989 {"insmod", {1, kMax, {true, do_insmod}}},
945 {"load_persist_props", {0, 0, do_load_persist_props}}, 990 {"installkey", {1, 1, {false, do_installkey}}},
946 {"load_system_props", {0, 0, do_load_system_props}}, 991 {"load_persist_props", {0, 0, {false, do_load_persist_props}}},
947 {"loglevel", {1, 1, do_loglevel}}, 992 {"load_system_props", {0, 0, {false, do_load_system_props}}},
948 {"mkdir", {1, 4, do_mkdir}}, 993 {"loglevel", {1, 1, {false, do_loglevel}}},
949 {"mount_all", {1, kMax, do_mount_all}}, 994 {"mkdir", {1, 4, {true, do_mkdir}}},
950 {"mount", {3, kMax, do_mount}}, 995 {"mount_all", {1, kMax, {false, do_mount_all}}},
951 {"umount", {1, 1, do_umount}}, 996 {"mount", {3, kMax, {false, do_mount}}},
952 {"readahead", {1, 1, do_readahead}}, 997 {"umount", {1, 1, {false, do_umount}}},
953 {"restart", {1, 1, do_restart}}, 998 {"readahead", {1, 2, {true, do_readahead}}},
954 {"restorecon", {1, kMax, do_restorecon}}, 999 {"restart", {1, 1, {false, do_restart}}},
955 {"restorecon_recursive", {1, kMax, do_restorecon_recursive}}, 1000 {"restorecon", {1, kMax, {true, do_restorecon}}},
956 {"rm", {1, 1, do_rm}}, 1001 {"restorecon_recursive", {1, kMax, {true, do_restorecon_recursive}}},
957 {"rmdir", {1, 1, do_rmdir}}, 1002 {"rm", {1, 1, {true, do_rm}}},
958 {"setprop", {2, 2, do_setprop}}, 1003 {"rmdir", {1, 1, {true, do_rmdir}}},
959 {"setrlimit", {3, 3, do_setrlimit}}, 1004 // TODO: setprop should be run in the subcontext, but property service needs to be split
960 {"start", {1, 1, do_start}}, 1005 // out from init before that is possible.
961 {"stop", {1, 1, do_stop}}, 1006 {"setprop", {2, 2, {false, do_setprop}}},
962 {"swapon_all", {1, 1, do_swapon_all}}, 1007 {"setrlimit", {3, 3, {false, do_setrlimit}}},
963 {"symlink", {2, 2, do_symlink}}, 1008 {"start", {1, 1, {false, do_start}}},
964 {"sysclktz", {1, 1, do_sysclktz}}, 1009 {"stop", {1, 1, {false, do_stop}}},
965 {"trigger", {1, 1, do_trigger}}, 1010 {"swapon_all", {1, 1, {false, do_swapon_all}}},
966 {"verity_load_state", {0, 0, do_verity_load_state}}, 1011 {"symlink", {2, 2, {true, do_symlink}}},
967 {"verity_update_state", {0, 0, do_verity_update_state}}, 1012 {"sysclktz", {1, 1, {false, do_sysclktz}}},
968 {"wait", {1, 2, do_wait}}, 1013 {"trigger", {1, 1, {false, do_trigger}}},
969 {"wait_for_prop", {2, 2, do_wait_for_prop}}, 1014 {"verity_load_state", {0, 0, {false, do_verity_load_state}}},
970 {"write", {2, 2, do_write}}, 1015 {"verity_update_state", {0, 0, {false, do_verity_update_state}}},
1016 {"wait", {1, 2, {true, do_wait}}},
1017 {"wait_for_prop", {2, 2, {true, do_wait_for_prop}}},
1018 {"write", {2, 2, {true, do_write}}},
971 }; 1019 };
972 // clang-format on 1020 // clang-format on
973 return builtin_functions; 1021 return builtin_functions;
diff --git a/init/builtins.h b/init/builtins.h
index f66ae1940..814b2d558 100644
--- a/init/builtins.h
+++ b/init/builtins.h
@@ -22,14 +22,17 @@
22#include <string> 22#include <string>
23#include <vector> 23#include <vector>
24 24
25#include "builtin_arguments.h"
25#include "keyword_map.h" 26#include "keyword_map.h"
26#include "result.h" 27#include "result.h"
27 28
28namespace android { 29namespace android {
29namespace init { 30namespace init {
30 31
31using BuiltinFunction = std::function<Result<Success>(const std::vector<std::string>&)>; 32using BuiltinFunction = std::function<Result<Success>(const BuiltinArguments&)>;
32class BuiltinFunctionMap : public KeywordMap<BuiltinFunction> { 33
34using KeywordFunctionMap = KeywordMap<std::pair<bool, BuiltinFunction>>;
35class BuiltinFunctionMap : public KeywordFunctionMap {
33 public: 36 public:
34 BuiltinFunctionMap() {} 37 BuiltinFunctionMap() {}
35 38
diff --git a/init/init.cpp b/init/init.cpp
index 678f49f58..51a98a2ea 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -25,6 +25,7 @@
25#include <string.h> 25#include <string.h>
26#include <sys/epoll.h> 26#include <sys/epoll.h>
27#include <sys/mount.h> 27#include <sys/mount.h>
28#include <sys/signalfd.h>
28#include <sys/sysmacros.h> 29#include <sys/sysmacros.h>
29#include <sys/types.h> 30#include <sys/types.h>
30#include <unistd.h> 31#include <unistd.h>
@@ -51,7 +52,7 @@
51#include "reboot.h" 52#include "reboot.h"
52#include "security.h" 53#include "security.h"
53#include "selinux.h" 54#include "selinux.h"
54#include "signal_handler.h" 55#include "sigchld_handler.h"
55#include "ueventd.h" 56#include "ueventd.h"
56#include "util.h" 57#include "util.h"
57#include "watchdogd.h" 58#include "watchdogd.h"
@@ -72,14 +73,19 @@ static char qemu[32];
72std::string default_console = "/dev/console"; 73std::string default_console = "/dev/console";
73 74
74static int epoll_fd = -1; 75static int epoll_fd = -1;
76static int sigterm_signal_fd = -1;
75 77
76static std::unique_ptr<Timer> waiting_for_prop(nullptr); 78static std::unique_ptr<Timer> waiting_for_prop(nullptr);
77static std::string wait_prop_name; 79static std::string wait_prop_name;
78static std::string wait_prop_value; 80static std::string wait_prop_value;
79static bool shutting_down; 81static bool shutting_down;
82static std::string shutdown_command;
83static bool do_shutdown = false;
80 84
81std::vector<std::string> late_import_paths; 85std::vector<std::string> late_import_paths;
82 86
87static std::vector<Subcontext>* subcontexts;
88
83void DumpState() { 89void DumpState() {
84 ServiceList::GetInstance().DumpState(); 90 ServiceList::GetInstance().DumpState();
85 ActionManager::GetInstance().DumpState(); 91 ActionManager::GetInstance().DumpState();
@@ -88,8 +94,8 @@ void DumpState() {
88Parser CreateParser(ActionManager& action_manager, ServiceList& service_list) { 94Parser CreateParser(ActionManager& action_manager, ServiceList& service_list) {
89 Parser parser; 95 Parser parser;
90 96
91 parser.AddSectionParser("service", std::make_unique<ServiceParser>(&service_list)); 97 parser.AddSectionParser("service", std::make_unique<ServiceParser>(&service_list, subcontexts));
92 parser.AddSectionParser("on", std::make_unique<ActionParser>(&action_manager)); 98 parser.AddSectionParser("on", std::make_unique<ActionParser>(&action_manager, subcontexts));
93 parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser)); 99 parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));
94 100
95 return parser; 101 return parser;
@@ -155,9 +161,16 @@ void property_changed(const std::string& name, const std::string& value) {
155 // In non-thermal-shutdown case, 'shutdown' trigger will be fired to let device specific 161 // In non-thermal-shutdown case, 'shutdown' trigger will be fired to let device specific
156 // commands to be executed. 162 // commands to be executed.
157 if (name == "sys.powerctl") { 163 if (name == "sys.powerctl") {
158 if (HandlePowerctlMessage(value)) { 164 // Despite the above comment, we can't call HandlePowerctlMessage() in this function,
159 shutting_down = true; 165 // because it modifies the contents of the action queue, which can cause the action queue
160 } 166 // to get into a bad state if this function is called from a command being executed by the
167 // action queue. Instead we set this flag and ensure that shutdown happens before the next
168 // command is run in the main init loop.
169 // TODO: once property service is removed from init, this will never happen from a builtin,
170 // but rather from a callback from the property service socket, in which case this hack can
171 // go away.
172 shutdown_command = value;
173 do_shutdown = true;
161 } 174 }
162 175
163 if (property_triggers_enabled) ActionManager::GetInstance().QueuePropertyChange(name, value); 176 if (property_triggers_enabled) ActionManager::GetInstance().QueuePropertyChange(name, value);
@@ -209,7 +222,7 @@ void handle_control_message(const std::string& msg, const std::string& name) {
209 } 222 }
210} 223}
211 224
212static Result<Success> wait_for_coldboot_done_action(const std::vector<std::string>& args) { 225static Result<Success> wait_for_coldboot_done_action(const BuiltinArguments& args) {
213 Timer t; 226 Timer t;
214 227
215 LOG(VERBOSE) << "Waiting for " COLDBOOT_DONE "..."; 228 LOG(VERBOSE) << "Waiting for " COLDBOOT_DONE "...";
@@ -230,12 +243,12 @@ static Result<Success> wait_for_coldboot_done_action(const std::vector<std::stri
230 return Success(); 243 return Success();
231} 244}
232 245
233static Result<Success> keychord_init_action(const std::vector<std::string>& args) { 246static Result<Success> keychord_init_action(const BuiltinArguments& args) {
234 keychord_init(); 247 keychord_init();
235 return Success(); 248 return Success();
236} 249}
237 250
238static Result<Success> console_init_action(const std::vector<std::string>& args) { 251static Result<Success> console_init_action(const BuiltinArguments& args) {
239 std::string console = GetProperty("ro.boot.console", ""); 252 std::string console = GetProperty("ro.boot.console", "");
240 if (!console.empty()) { 253 if (!console.empty()) {
241 default_console = "/dev/" + console; 254 default_console = "/dev/" + console;
@@ -322,13 +335,13 @@ static void process_kernel_cmdline() {
322 if (qemu[0]) import_kernel_cmdline(true, import_kernel_nv); 335 if (qemu[0]) import_kernel_cmdline(true, import_kernel_nv);
323} 336}
324 337
325static Result<Success> property_enable_triggers_action(const std::vector<std::string>& args) { 338static Result<Success> property_enable_triggers_action(const BuiltinArguments& args) {
326 /* Enable property triggers. */ 339 /* Enable property triggers. */
327 property_triggers_enabled = 1; 340 property_triggers_enabled = 1;
328 return Success(); 341 return Success();
329} 342}
330 343
331static Result<Success> queue_property_triggers_action(const std::vector<std::string>& args) { 344static Result<Success> queue_property_triggers_action(const BuiltinArguments& args) {
332 ActionManager::GetInstance().QueueBuiltinAction(property_enable_triggers_action, "enable_property_trigger"); 345 ActionManager::GetInstance().QueueBuiltinAction(property_enable_triggers_action, "enable_property_trigger");
333 ActionManager::GetInstance().QueueAllPropertyActions(); 346 ActionManager::GetInstance().QueueAllPropertyActions();
334 return Success(); 347 return Success();
@@ -392,6 +405,40 @@ static void InstallRebootSignalHandlers() {
392 sigaction(SIGTRAP, &action, nullptr); 405 sigaction(SIGTRAP, &action, nullptr);
393} 406}
394 407
408static void HandleSigtermSignal() {
409 signalfd_siginfo siginfo;
410 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(sigterm_signal_fd, &siginfo, sizeof(siginfo)));
411 if (bytes_read != sizeof(siginfo)) {
412 PLOG(ERROR) << "Failed to read siginfo from sigterm_signal_fd";
413 return;
414 }
415
416 if (siginfo.ssi_pid != 0) {
417 // Drop any userspace SIGTERM requests.
418 LOG(DEBUG) << "Ignoring SIGTERM from pid " << siginfo.ssi_pid;
419 return;
420 }
421
422 HandlePowerctlMessage("shutdown,container");
423}
424
425static void InstallSigtermHandler() {
426 sigset_t mask;
427 sigemptyset(&mask);
428 sigaddset(&mask, SIGTERM);
429
430 if (sigprocmask(SIG_BLOCK, &mask, nullptr) == -1) {
431 PLOG(FATAL) << "failed to block SIGTERM";
432 }
433
434 sigterm_signal_fd = signalfd(-1, &mask, SFD_CLOEXEC);
435 if (sigterm_signal_fd == -1) {
436 PLOG(FATAL) << "failed to create signalfd for SIGTERM";
437 }
438
439 register_epoll_handler(sigterm_signal_fd, HandleSigtermSignal);
440}
441
395int main(int argc, char** argv) { 442int main(int argc, char** argv) {
396 if (!strcmp(basename(argv[0]), "ueventd")) { 443 if (!strcmp(basename(argv[0]), "ueventd")) {
397 return ueventd_main(argc, argv); 444 return ueventd_main(argc, argv);
@@ -401,6 +448,12 @@ int main(int argc, char** argv) {
401 return watchdogd_main(argc, argv); 448 return watchdogd_main(argc, argv);
402 } 449 }
403 450
451 if (argc > 1 && !strcmp(argv[1], "subcontext")) {
452 InitKernelLogging(argv);
453 const BuiltinFunctionMap function_map;
454 return SubcontextMain(argc, argv, &function_map);
455 }
456
404 if (REBOOT_BOOTLOADER_ON_PANIC) { 457 if (REBOOT_BOOTLOADER_ON_PANIC) {
405 InstallRebootSignalHandlers(); 458 InstallRebootSignalHandlers();
406 } 459 }
@@ -523,11 +576,16 @@ int main(int argc, char** argv) {
523 576
524 epoll_fd = epoll_create1(EPOLL_CLOEXEC); 577 epoll_fd = epoll_create1(EPOLL_CLOEXEC);
525 if (epoll_fd == -1) { 578 if (epoll_fd == -1) {
526 PLOG(ERROR) << "epoll_create1 failed"; 579 PLOG(FATAL) << "epoll_create1 failed";
527 exit(1);
528 } 580 }
529 581
530 signal_handler_init(); 582 sigchld_handler_init();
583
584 if (!IsRebootCapable()) {
585 // If init does not have the CAP_SYS_BOOT capability, it is running in a container.
586 // In that case, receiving SIGTERM will cause the system to shut down.
587 InstallSigtermHandler();
588 }
531 589
532 property_load_boot_defaults(); 590 property_load_boot_defaults();
533 export_oem_lock_status(); 591 export_oem_lock_status();
@@ -537,6 +595,8 @@ int main(int argc, char** argv) {
537 const BuiltinFunctionMap function_map; 595 const BuiltinFunctionMap function_map;
538 Action::set_function_map(&function_map); 596 Action::set_function_map(&function_map);
539 597
598 subcontexts = InitializeSubcontexts();
599
540 ActionManager& am = ActionManager::GetInstance(); 600 ActionManager& am = ActionManager::GetInstance();
541 ServiceList& sm = ServiceList::GetInstance(); 601 ServiceList& sm = ServiceList::GetInstance();
542 602
@@ -579,6 +639,13 @@ int main(int argc, char** argv) {
579 // By default, sleep until something happens. 639 // By default, sleep until something happens.
580 int epoll_timeout_ms = -1; 640 int epoll_timeout_ms = -1;
581 641
642 if (do_shutdown && !shutting_down) {
643 do_shutdown = false;
644 if (HandlePowerctlMessage(shutdown_command)) {
645 shutting_down = true;
646 }
647 }
648
582 if (!(waiting_for_prop || Service::is_exec_service_running())) { 649 if (!(waiting_for_prop || Service::is_exec_service_running())) {
583 am.ExecuteOneCommand(); 650 am.ExecuteOneCommand();
584 } 651 }
diff --git a/init/init_test.cpp b/init/init_test.cpp
index 27659f917..29a65abb9 100644
--- a/init/init_test.cpp
+++ b/init/init_test.cpp
@@ -25,33 +25,12 @@
25#include "import_parser.h" 25#include "import_parser.h"
26#include "keyword_map.h" 26#include "keyword_map.h"
27#include "parser.h" 27#include "parser.h"
28#include "test_function_map.h"
28#include "util.h" 29#include "util.h"
29 30
30namespace android { 31namespace android {
31namespace init { 32namespace init {
32 33
33class TestFunctionMap : public KeywordMap<BuiltinFunction> {
34 public:
35 // Helper for argument-less functions
36 using BuiltinFunctionNoArgs = std::function<void(void)>;
37 void Add(const std::string& name, const BuiltinFunctionNoArgs function) {
38 Add(name, 0, 0, [function](const std::vector<std::string>&) {
39 function();
40 return Success();
41 });
42 }
43
44 void Add(const std::string& name, std::size_t min_parameters, std::size_t max_parameters,
45 const BuiltinFunction function) {
46 builtin_functions_[name] = make_tuple(min_parameters, max_parameters, function);
47 }
48
49 private:
50 Map builtin_functions_ = {};
51
52 const Map& map() const override { return builtin_functions_; }
53};
54
55using ActionManagerCommand = std::function<void(ActionManager&)>; 34using ActionManagerCommand = std::function<void(ActionManager&)>;
56 35
57void TestInit(const std::string& init_script_file, const TestFunctionMap& test_function_map, 36void TestInit(const std::string& init_script_file, const TestFunctionMap& test_function_map,
@@ -61,7 +40,7 @@ void TestInit(const std::string& init_script_file, const TestFunctionMap& test_f
61 Action::set_function_map(&test_function_map); 40 Action::set_function_map(&test_function_map);
62 41
63 Parser parser; 42 Parser parser;
64 parser.AddSectionParser("on", std::make_unique<ActionParser>(&am)); 43 parser.AddSectionParser("on", std::make_unique<ActionParser>(&am, nullptr));
65 parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser)); 44 parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));
66 45
67 ASSERT_TRUE(parser.ParseConfig(init_script_file)); 46 ASSERT_TRUE(parser.ParseConfig(init_script_file));
@@ -171,14 +150,14 @@ TEST(init, EventTriggerOrderMultipleFiles) {
171 ASSERT_TRUE(android::base::WriteStringToFd(start_script, start.fd)); 150 ASSERT_TRUE(android::base::WriteStringToFd(start_script, start.fd));
172 151
173 int num_executed = 0; 152 int num_executed = 0;
174 auto execute_command = [&num_executed](const std::vector<std::string>& args) { 153 auto execute_command = [&num_executed](const BuiltinArguments& args) {
175 EXPECT_EQ(2U, args.size()); 154 EXPECT_EQ(2U, args.size());
176 EXPECT_EQ(++num_executed, std::stoi(args[1])); 155 EXPECT_EQ(++num_executed, std::stoi(args[1]));
177 return Success(); 156 return Success();
178 }; 157 };
179 158
180 TestFunctionMap test_function_map; 159 TestFunctionMap test_function_map;
181 test_function_map.Add("execute", 1, 1, execute_command); 160 test_function_map.Add("execute", 1, 1, false, execute_command);
182 161
183 ActionManagerCommand trigger_boot = [](ActionManager& am) { am.QueueEventTrigger("boot"); }; 162 ActionManagerCommand trigger_boot = [](ActionManager& am) { am.QueueEventTrigger("boot"); };
184 std::vector<ActionManagerCommand> commands{trigger_boot}; 163 std::vector<ActionManagerCommand> commands{trigger_boot};
diff --git a/init/persistent_properties.cpp b/init/persistent_properties.cpp
new file mode 100644
index 000000000..21adce914
--- /dev/null
+++ b/init/persistent_properties.cpp
@@ -0,0 +1,246 @@
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "persistent_properties.h"
18
19#include <dirent.h>
20#include <fcntl.h>
21#include <sys/stat.h>
22#include <sys/system_properties.h>
23#include <sys/types.h>
24
25#include <memory>
26
27#include <android-base/file.h>
28#include <android-base/logging.h>
29#include <android-base/strings.h>
30#include <android-base/unique_fd.h>
31
32#include "util.h"
33
34using android::base::ReadFdToString;
35using android::base::StartsWith;
36using android::base::WriteStringToFd;
37using android::base::unique_fd;
38
39namespace android {
40namespace init {
41
42std::string persistent_property_filename = "/data/property/persistent_properties";
43
44namespace {
45
46constexpr const char kLegacyPersistentPropertyDir[] = "/data/property";
47
48void AddPersistentProperty(const std::string& name, const std::string& value,
49 PersistentProperties* persistent_properties) {
50 auto persistent_property_record = persistent_properties->add_properties();
51 persistent_property_record->set_name(name);
52 persistent_property_record->set_value(value);
53}
54
55Result<PersistentProperties> LoadLegacyPersistentProperties() {
56 std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(kLegacyPersistentPropertyDir), closedir);
57 if (!dir) {
58 return ErrnoError() << "Unable to open persistent property directory \""
59 << kLegacyPersistentPropertyDir << "\"";
60 }
61
62 PersistentProperties persistent_properties;
63 dirent* entry;
64 while ((entry = readdir(dir.get())) != nullptr) {
65 if (!StartsWith(entry->d_name, "persist.")) {
66 continue;
67 }
68 if (entry->d_type != DT_REG) {
69 continue;
70 }
71
72 unique_fd fd(openat(dirfd(dir.get()), entry->d_name, O_RDONLY | O_NOFOLLOW));
73 if (fd == -1) {
74 PLOG(ERROR) << "Unable to open persistent property file \"" << entry->d_name << "\"";
75 continue;
76 }
77
78 struct stat sb;
79 if (fstat(fd, &sb) == -1) {
80 PLOG(ERROR) << "fstat on property file \"" << entry->d_name << "\" failed";
81 continue;
82 }
83
84 // File must not be accessible to others, be owned by root/root, and
85 // not be a hard link to any other file.
86 if (((sb.st_mode & (S_IRWXG | S_IRWXO)) != 0) || sb.st_uid != 0 || sb.st_gid != 0 ||
87 sb.st_nlink != 1) {
88 PLOG(ERROR) << "skipping insecure property file " << entry->d_name
89 << " (uid=" << sb.st_uid << " gid=" << sb.st_gid << " nlink=" << sb.st_nlink
90 << " mode=" << std::oct << sb.st_mode << ")";
91 continue;
92 }
93
94 std::string value;
95 if (ReadFdToString(fd, &value)) {
96 AddPersistentProperty(entry->d_name, value, &persistent_properties);
97 } else {
98 PLOG(ERROR) << "Unable to read persistent property file " << entry->d_name;
99 }
100 }
101 return persistent_properties;
102}
103
104void RemoveLegacyPersistentPropertyFiles() {
105 std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(kLegacyPersistentPropertyDir), closedir);
106 if (!dir) {
107 PLOG(ERROR) << "Unable to open persistent property directory \""
108 << kLegacyPersistentPropertyDir << "\"";
109 return;
110 }
111
112 dirent* entry;
113 while ((entry = readdir(dir.get())) != nullptr) {
114 if (!StartsWith(entry->d_name, "persist.")) {
115 continue;
116 }
117 if (entry->d_type != DT_REG) {
118 continue;
119 }
120 unlinkat(dirfd(dir.get()), entry->d_name, 0);
121 }
122}
123
124PersistentProperties LoadPersistentPropertiesFromMemory() {
125 PersistentProperties persistent_properties;
126 __system_property_foreach(
127 [](const prop_info* pi, void* cookie) {
128 __system_property_read_callback(
129 pi,
130 [](void* cookie, const char* name, const char* value, unsigned serial) {
131 if (StartsWith(name, "persist.")) {
132 auto properties = reinterpret_cast<PersistentProperties*>(cookie);
133 AddPersistentProperty(name, value, properties);
134 }
135 },
136 cookie);
137 },
138 &persistent_properties);
139 return persistent_properties;
140}
141
142Result<std::string> ReadPersistentPropertyFile() {
143 const std::string temp_filename = persistent_property_filename + ".tmp";
144 if (access(temp_filename.c_str(), F_OK) == 0) {
145 LOG(INFO)
146 << "Found temporary property file while attempting to persistent system properties"
147 " a previous persistent property write may have failed";
148 unlink(temp_filename.c_str());
149 }
150 auto file_contents = ReadFile(persistent_property_filename);
151 if (!file_contents) {
152 return Error() << "Unable to read persistent property file: " << file_contents.error();
153 }
154 return *file_contents;
155}
156
157} // namespace
158
159Result<PersistentProperties> LoadPersistentPropertyFile() {
160 auto file_contents = ReadPersistentPropertyFile();
161 if (!file_contents) return file_contents.error();
162
163 PersistentProperties persistent_properties;
164 if (persistent_properties.ParseFromString(*file_contents)) return persistent_properties;
165
166 // If the file cannot be parsed in either format, then we don't have any recovery
167 // mechanisms, so we delete it to allow for future writes to take place successfully.
168 unlink(persistent_property_filename.c_str());
169 return Error() << "Unable to parse persistent property file: Could not parse protobuf";
170}
171
172Result<Success> WritePersistentPropertyFile(const PersistentProperties& persistent_properties) {
173 const std::string temp_filename = persistent_property_filename + ".tmp";
174 unique_fd fd(TEMP_FAILURE_RETRY(
175 open(temp_filename.c_str(), O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC | O_CLOEXEC, 0600)));
176 if (fd == -1) {
177 return ErrnoError() << "Could not open temporary properties file";
178 }
179 std::string serialized_string;
180 if (!persistent_properties.SerializeToString(&serialized_string)) {
181 return Error() << "Unable to serialize properties";
182 }
183 if (!WriteStringToFd(serialized_string, fd)) {
184 return ErrnoError() << "Unable to write file contents";
185 }
186 fsync(fd);
187 fd.reset();
188
189 if (rename(temp_filename.c_str(), persistent_property_filename.c_str())) {
190 int saved_errno = errno;
191 unlink(temp_filename.c_str());
192 return Error(saved_errno) << "Unable to rename persistent property file";
193 }
194 return Success();
195}
196
197// Persistent properties are not written often, so we rather not keep any data in memory and read
198// then rewrite the persistent property file for each update.
199void WritePersistentProperty(const std::string& name, const std::string& value) {
200 auto persistent_properties = LoadPersistentPropertyFile();
201
202 if (!persistent_properties) {
203 LOG(ERROR) << "Recovering persistent properties from memory: "
204 << persistent_properties.error();
205 persistent_properties = LoadPersistentPropertiesFromMemory();
206 }
207 auto it = std::find_if(persistent_properties->mutable_properties()->begin(),
208 persistent_properties->mutable_properties()->end(),
209 [&name](const auto& record) { return record.name() == name; });
210 if (it != persistent_properties->mutable_properties()->end()) {
211 it->set_name(name);
212 it->set_value(value);
213 } else {
214 AddPersistentProperty(name, value, &persistent_properties.value());
215 }
216
217 if (auto result = WritePersistentPropertyFile(*persistent_properties); !result) {
218 LOG(ERROR) << "Could not store persistent property: " << result.error();
219 }
220}
221
222PersistentProperties LoadPersistentProperties() {
223 auto persistent_properties = LoadPersistentPropertyFile();
224
225 if (!persistent_properties) {
226 LOG(ERROR) << "Could not load single persistent property file, trying legacy directory: "
227 << persistent_properties.error();
228 persistent_properties = LoadLegacyPersistentProperties();
229 if (!persistent_properties) {
230 LOG(ERROR) << "Unable to load legacy persistent properties: "
231 << persistent_properties.error();
232 return {};
233 }
234 if (auto result = WritePersistentPropertyFile(*persistent_properties); result) {
235 RemoveLegacyPersistentPropertyFiles();
236 } else {
237 LOG(ERROR) << "Unable to write single persistent property file: " << result.error();
238 // Fall through so that we still set the properties that we've read.
239 }
240 }
241
242 return *persistent_properties;
243}
244
245} // namespace init
246} // namespace android
diff --git a/init/persistent_properties.h b/init/persistent_properties.h
new file mode 100644
index 000000000..5f4df85bd
--- /dev/null
+++ b/init/persistent_properties.h
@@ -0,0 +1,39 @@
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _INIT_PERSISTENT_PROPERTIES_H
18#define _INIT_PERSISTENT_PROPERTIES_H
19
20#include <string>
21
22#include "result.h"
23#include "system/core/init/persistent_properties.pb.h"
24
25namespace android {
26namespace init {
27
28PersistentProperties LoadPersistentProperties();
29void WritePersistentProperty(const std::string& name, const std::string& value);
30
31// Exposed only for testing
32Result<PersistentProperties> LoadPersistentPropertyFile();
33Result<Success> WritePersistentPropertyFile(const PersistentProperties& persistent_properties);
34extern std::string persistent_property_filename;
35
36} // namespace init
37} // namespace android
38
39#endif
diff --git a/init/persistent_properties.proto b/init/persistent_properties.proto
new file mode 100644
index 000000000..c8d2e3ae9
--- /dev/null
+++ b/init/persistent_properties.proto
@@ -0,0 +1,27 @@
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17syntax = "proto2";
18option optimize_for = LITE_RUNTIME;
19
20message PersistentProperties {
21 message PersistentPropertyRecord {
22 optional string name = 1;
23 optional string value = 2;
24 }
25
26 repeated PersistentPropertyRecord properties = 1;
27}
diff --git a/init/persistent_properties_test.cpp b/init/persistent_properties_test.cpp
new file mode 100644
index 000000000..872e9a1ff
--- /dev/null
+++ b/init/persistent_properties_test.cpp
@@ -0,0 +1,156 @@
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "persistent_properties.h"
18
19#include <errno.h>
20
21#include <vector>
22
23#include <android-base/test_utils.h>
24#include <gtest/gtest.h>
25
26#include "util.h"
27
28using namespace std::string_literals;
29
30namespace android {
31namespace init {
32
33PersistentProperties VectorToPersistentProperties(
34 const std::vector<std::pair<std::string, std::string>>& input_properties) {
35 PersistentProperties persistent_properties;
36
37 for (const auto& [name, value] : input_properties) {
38 auto persistent_property_record = persistent_properties.add_properties();
39 persistent_property_record->set_name(name);
40 persistent_property_record->set_value(value);
41 }
42
43 return persistent_properties;
44}
45
46void CheckPropertiesEqual(std::vector<std::pair<std::string, std::string>> expected,
47 const PersistentProperties& persistent_properties) {
48 for (const auto& persistent_property_record : persistent_properties.properties()) {
49 auto it = std::find_if(expected.begin(), expected.end(),
50 [persistent_property_record](const auto& entry) {
51 return entry.first == persistent_property_record.name() &&
52 entry.second == persistent_property_record.value();
53 });
54 ASSERT_TRUE(it != expected.end())
55 << "Found unexpected property (" << persistent_property_record.name() << ", "
56 << persistent_property_record.value() << ")";
57 expected.erase(it);
58 }
59 auto joiner = [](const std::vector<std::pair<std::string, std::string>>& vector) {
60 std::string result;
61 for (const auto& [name, value] : vector) {
62 result += " (" + name + ", " + value + ")";
63 }
64 return result;
65 };
66 EXPECT_TRUE(expected.empty()) << "Did not find expected properties:" << joiner(expected);
67}
68
69TEST(persistent_properties, EndToEnd) {
70 TemporaryFile tf;
71 ASSERT_TRUE(tf.fd != -1);
72 persistent_property_filename = tf.path;
73
74 std::vector<std::pair<std::string, std::string>> persistent_properties = {
75 {"persist.sys.locale", "en-US"},
76 {"persist.sys.timezone", "America/Los_Angeles"},
77 {"persist.test.empty.value", ""},
78 {"persist.test.new.line", "abc\n\n\nabc"},
79 {"persist.test.numbers", "1234567890"},
80 {"persist.test.non.ascii", "\x00\x01\x02\xFF\xFE\xFD\x7F\x8F\x9F"},
81 // We don't currently allow for non-ascii names for system properties, but this is a policy
82 // decision, not a technical limitation.
83 {"persist.\x00\x01\x02\xFF\xFE\xFD\x7F\x8F\x9F", "non-ascii-name"},
84 };
85
86 ASSERT_TRUE(WritePersistentPropertyFile(VectorToPersistentProperties(persistent_properties)));
87
88 auto read_back_properties = LoadPersistentProperties();
89 CheckPropertiesEqual(persistent_properties, read_back_properties);
90}
91
92TEST(persistent_properties, AddProperty) {
93 TemporaryFile tf;
94 ASSERT_TRUE(tf.fd != -1);
95 persistent_property_filename = tf.path;
96
97 std::vector<std::pair<std::string, std::string>> persistent_properties = {
98 {"persist.sys.timezone", "America/Los_Angeles"},
99 };
100 ASSERT_TRUE(WritePersistentPropertyFile(VectorToPersistentProperties(persistent_properties)));
101
102 WritePersistentProperty("persist.sys.locale", "pt-BR");
103
104 std::vector<std::pair<std::string, std::string>> persistent_properties_expected = {
105 {"persist.sys.timezone", "America/Los_Angeles"},
106 {"persist.sys.locale", "pt-BR"},
107 };
108
109 auto read_back_properties = LoadPersistentProperties();
110 CheckPropertiesEqual(persistent_properties_expected, read_back_properties);
111}
112
113TEST(persistent_properties, UpdateProperty) {
114 TemporaryFile tf;
115 ASSERT_TRUE(tf.fd != -1);
116 persistent_property_filename = tf.path;
117
118 std::vector<std::pair<std::string, std::string>> persistent_properties = {
119 {"persist.sys.locale", "en-US"},
120 {"persist.sys.timezone", "America/Los_Angeles"},
121 };
122 ASSERT_TRUE(WritePersistentPropertyFile(VectorToPersistentProperties(persistent_properties)));
123
124 WritePersistentProperty("persist.sys.locale", "pt-BR");
125
126 std::vector<std::pair<std::string, std::string>> persistent_properties_expected = {
127 {"persist.sys.locale", "pt-BR"},
128 {"persist.sys.timezone", "America/Los_Angeles"},
129 };
130
131 auto read_back_properties = LoadPersistentProperties();
132 CheckPropertiesEqual(persistent_properties_expected, read_back_properties);
133}
134
135TEST(persistent_properties, UpdatePropertyBadParse) {
136 TemporaryFile tf;
137 ASSERT_TRUE(tf.fd != -1);
138 persistent_property_filename = tf.path;
139
140 ASSERT_TRUE(WriteFile(tf.path, "ab"));
141
142 WritePersistentProperty("persist.sys.locale", "pt-BR");
143
144 auto read_back_properties = LoadPersistentProperties();
145 EXPECT_GT(read_back_properties.properties().size(), 0);
146
147 auto it =
148 std::find_if(read_back_properties.properties().begin(),
149 read_back_properties.properties().end(), [](const auto& entry) {
150 return entry.name() == "persist.sys.locale" && entry.value() == "pt-BR";
151 });
152 EXPECT_FALSE(it == read_back_properties.properties().end());
153}
154
155} // namespace init
156} // namespace android
diff --git a/init/property_service.cpp b/init/property_service.cpp
index f0e4d2e96..1a44fe305 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -17,7 +17,6 @@
17#include "property_service.h" 17#include "property_service.h"
18 18
19#include <ctype.h> 19#include <ctype.h>
20#include <dirent.h>
21#include <errno.h> 20#include <errno.h>
22#include <fcntl.h> 21#include <fcntl.h>
23#include <inttypes.h> 22#include <inttypes.h>
@@ -34,6 +33,7 @@
34#include <sys/types.h> 33#include <sys/types.h>
35#include <sys/un.h> 34#include <sys/un.h>
36#include <unistd.h> 35#include <unistd.h>
36#include <wchar.h>
37 37
38#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ 38#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
39#include <sys/_system_properties.h> 39#include <sys/_system_properties.h>
@@ -46,6 +46,7 @@
46#include <android-base/file.h> 46#include <android-base/file.h>
47#include <android-base/logging.h> 47#include <android-base/logging.h>
48#include <android-base/properties.h> 48#include <android-base/properties.h>
49#include <android-base/stringprintf.h>
49#include <android-base/strings.h> 50#include <android-base/strings.h>
50#include <bootimg.h> 51#include <bootimg.h>
51#include <fs_mgr.h> 52#include <fs_mgr.h>
@@ -54,17 +55,19 @@
54#include <selinux/selinux.h> 55#include <selinux/selinux.h>
55 56
56#include "init.h" 57#include "init.h"
58#include "persistent_properties.h"
57#include "util.h" 59#include "util.h"
58 60
61using android::base::StartsWith;
62using android::base::StringPrintf;
59using android::base::Timer; 63using android::base::Timer;
60 64
61#define PERSISTENT_PROPERTY_DIR "/data/property"
62#define RECOVERY_MOUNT_POINT "/recovery" 65#define RECOVERY_MOUNT_POINT "/recovery"
63 66
64namespace android { 67namespace android {
65namespace init { 68namespace init {
66 69
67static int persistent_properties_loaded = 0; 70static bool persistent_properties_loaded = false;
68 71
69static int property_set_fd = -1; 72static int property_set_fd = -1;
70 73
@@ -72,8 +75,7 @@ static struct selabel_handle* sehandle_prop;
72 75
73void property_init() { 76void property_init() {
74 if (__system_property_area_init()) { 77 if (__system_property_area_init()) {
75 LOG(ERROR) << "Failed to initialize property area"; 78 LOG(FATAL) << "Failed to initialize property area";
76 exit(1);
77 } 79 }
78} 80}
79 81
@@ -120,29 +122,6 @@ static int check_control_mac_perms(const char *name, char *sctx, struct ucred *c
120 return check_mac_perms(ctl_name, sctx, cr); 122 return check_mac_perms(ctl_name, sctx, cr);
121} 123}
122 124
123static void write_persistent_property(const char *name, const char *value)
124{
125 char tempPath[PATH_MAX];
126 char path[PATH_MAX];
127 int fd;
128
129 snprintf(tempPath, sizeof(tempPath), "%s/.temp.XXXXXX", PERSISTENT_PROPERTY_DIR);
130 fd = mkstemp(tempPath);
131 if (fd < 0) {
132 PLOG(ERROR) << "Unable to write persistent property to temp file " << tempPath;
133 return;
134 }
135 write(fd, value, strlen(value));
136 fsync(fd);
137 close(fd);
138
139 snprintf(path, sizeof(path), "%s/%s", PERSISTENT_PROPERTY_DIR, name);
140 if (rename(tempPath, path)) {
141 PLOG(ERROR) << "Unable to rename persistent property file " << tempPath << " to " << path;
142 unlink(tempPath);
143 }
144}
145
146bool is_legal_property_name(const std::string& name) { 125bool is_legal_property_name(const std::string& name) {
147 size_t namelen = name.size(); 126 size_t namelen = name.size();
148 127
@@ -176,16 +155,22 @@ static uint32_t PropertySetImpl(const std::string& name, const std::string& valu
176 return PROP_ERROR_INVALID_NAME; 155 return PROP_ERROR_INVALID_NAME;
177 } 156 }
178 157
179 if (valuelen >= PROP_VALUE_MAX) { 158 if (valuelen >= PROP_VALUE_MAX && !StartsWith(name, "ro.")) {
180 LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: " 159 LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: "
181 << "value too long"; 160 << "value too long";
182 return PROP_ERROR_INVALID_VALUE; 161 return PROP_ERROR_INVALID_VALUE;
183 } 162 }
184 163
164 if (mbstowcs(nullptr, value.data(), 0) == static_cast<std::size_t>(-1)) {
165 LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: "
166 << "value not a UTF8 encoded string";
167 return PROP_ERROR_INVALID_VALUE;
168 }
169
185 prop_info* pi = (prop_info*) __system_property_find(name.c_str()); 170 prop_info* pi = (prop_info*) __system_property_find(name.c_str());
186 if (pi != nullptr) { 171 if (pi != nullptr) {
187 // ro.* properties are actually "write-once". 172 // ro.* properties are actually "write-once".
188 if (android::base::StartsWith(name, "ro.")) { 173 if (StartsWith(name, "ro.")) {
189 LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: " 174 LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: "
190 << "property already set"; 175 << "property already set";
191 return PROP_ERROR_READ_ONLY_PROPERTY; 176 return PROP_ERROR_READ_ONLY_PROPERTY;
@@ -203,8 +188,8 @@ static uint32_t PropertySetImpl(const std::string& name, const std::string& valu
203 188
204 // Don't write properties to disk until after we have read all default 189 // Don't write properties to disk until after we have read all default
205 // properties to prevent them from being overwritten by default values. 190 // properties to prevent them from being overwritten by default values.
206 if (persistent_properties_loaded && android::base::StartsWith(name, "persist.")) { 191 if (persistent_properties_loaded && StartsWith(name, "persist.")) {
207 write_persistent_property(name.c_str(), value.c_str()); 192 WritePersistentProperty(name, value);
208 } 193 }
209 property_changed(name, value); 194 property_changed(name, value);
210 return PROP_SUCCESS; 195 return PROP_SUCCESS;
@@ -238,7 +223,7 @@ static void PropertyChildLaunch() {
238 LOG(ERROR) << "property_set_async(\"" << info.name << "\", \"" << info.value 223 LOG(ERROR) << "property_set_async(\"" << info.name << "\", \"" << info.value
239 << "\") failed"; 224 << "\") failed";
240 } 225 }
241 exit(0); 226 _exit(0);
242 } 227 }
243} 228}
244 229
@@ -424,7 +409,7 @@ static void handle_property_set(SocketConnection& socket,
424 char* source_ctx = nullptr; 409 char* source_ctx = nullptr;
425 getpeercon(socket.socket(), &source_ctx); 410 getpeercon(socket.socket(), &source_ctx);
426 411
427 if (android::base::StartsWith(name, "ctl.")) { 412 if (StartsWith(name, "ctl.")) {
428 if (check_control_mac_perms(value.c_str(), source_ctx, &cr)) { 413 if (check_control_mac_perms(value.c_str(), source_ctx, &cr)) {
429 handle_control_message(name.c_str() + 4, value.c_str()); 414 handle_control_message(name.c_str() + 4, value.c_str());
430 if (!legacy_protocol) { 415 if (!legacy_protocol) {
@@ -442,6 +427,20 @@ static void handle_property_set(SocketConnection& socket,
442 } 427 }
443 } else { 428 } else {
444 if (check_mac_perms(name, source_ctx, &cr)) { 429 if (check_mac_perms(name, source_ctx, &cr)) {
430 // sys.powerctl is a special property that is used to make the device reboot. We want to log
431 // any process that sets this property to be able to accurately blame the cause of a shutdown.
432 if (name == "sys.powerctl") {
433 std::string cmdline_path = StringPrintf("proc/%d/cmdline", cr.pid);
434 std::string process_cmdline;
435 std::string process_log_string;
436 if (android::base::ReadFileToString(cmdline_path, &process_cmdline)) {
437 // Since cmdline is null deliminated, .c_str() conveniently gives us just the process path.
438 process_log_string = StringPrintf(" (%s)", process_cmdline.c_str());
439 }
440 LOG(INFO) << "Received sys.powerctl='" << value << "' from pid: " << cr.pid
441 << process_log_string;
442 }
443
445 uint32_t result = property_set(name, value); 444 uint32_t result = property_set(name, value);
446 if (!legacy_protocol) { 445 if (!legacy_protocol) {
447 socket.SendUint32(result); 446 socket.SendUint32(result);
@@ -599,61 +598,6 @@ static void load_properties_from_file(const char* filename, const char* filter)
599 LOG(VERBOSE) << "(Loading properties from " << filename << " took " << t << ".)"; 598 LOG(VERBOSE) << "(Loading properties from " << filename << " took " << t << ".)";
600} 599}
601 600
602static void load_persistent_properties() {
603 persistent_properties_loaded = 1;
604
605 std::unique_ptr<DIR, int(*)(DIR*)> dir(opendir(PERSISTENT_PROPERTY_DIR), closedir);
606 if (!dir) {
607 PLOG(ERROR) << "Unable to open persistent property directory \""
608 << PERSISTENT_PROPERTY_DIR << "\"";
609 return;
610 }
611
612 struct dirent* entry;
613 while ((entry = readdir(dir.get())) != NULL) {
614 if (strncmp("persist.", entry->d_name, strlen("persist."))) {
615 continue;
616 }
617 if (entry->d_type != DT_REG) {
618 continue;
619 }
620
621 // Open the file and read the property value.
622 int fd = openat(dirfd(dir.get()), entry->d_name, O_RDONLY | O_NOFOLLOW);
623 if (fd == -1) {
624 PLOG(ERROR) << "Unable to open persistent property file \"" << entry->d_name << "\"";
625 continue;
626 }
627
628 struct stat sb;
629 if (fstat(fd, &sb) == -1) {
630 PLOG(ERROR) << "fstat on property file \"" << entry->d_name << "\" failed";
631 close(fd);
632 continue;
633 }
634
635 // File must not be accessible to others, be owned by root/root, and
636 // not be a hard link to any other file.
637 if (((sb.st_mode & (S_IRWXG | S_IRWXO)) != 0) || sb.st_uid != 0 || sb.st_gid != 0 || sb.st_nlink != 1) {
638 PLOG(ERROR) << "skipping insecure property file " << entry->d_name
639 << " (uid=" << sb.st_uid << " gid=" << sb.st_gid
640 << " nlink=" << sb.st_nlink << " mode=" << std::oct << sb.st_mode << ")";
641 close(fd);
642 continue;
643 }
644
645 char value[PROP_VALUE_MAX];
646 int length = read(fd, value, sizeof(value) - 1);
647 if (length >= 0) {
648 value[length] = 0;
649 property_set(entry->d_name, value);
650 } else {
651 PLOG(ERROR) << "Unable to read persistent property file " << entry->d_name;
652 }
653 close(fd);
654 }
655}
656
657// persist.sys.usb.config values can't be combined on build-time when property 601// persist.sys.usb.config values can't be combined on build-time when property
658// files are split into each partition. 602// files are split into each partition.
659// So we need to apply the same rule of build/make/tools/post_process_props.py 603// So we need to apply the same rule of build/make/tools/post_process_props.py
@@ -703,7 +647,11 @@ void load_persist_props(void) {
703 647
704 load_override_properties(); 648 load_override_properties();
705 /* Read persistent properties after all default values have been loaded. */ 649 /* Read persistent properties after all default values have been loaded. */
706 load_persistent_properties(); 650 auto persistent_properties = LoadPersistentProperties();
651 for (const auto& persistent_property_record : persistent_properties.properties()) {
652 property_set(persistent_property_record.name(), persistent_property_record.value());
653 }
654 persistent_properties_loaded = true;
707 property_set("ro.persistent_properties.ready", "true"); 655 property_set("ro.persistent_properties.ready", "true");
708} 656}
709 657
@@ -771,8 +719,7 @@ void start_property_service() {
771 property_set_fd = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 719 property_set_fd = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
772 false, 0666, 0, 0, nullptr); 720 false, 0666, 0, 0, nullptr);
773 if (property_set_fd == -1) { 721 if (property_set_fd == -1) {
774 PLOG(ERROR) << "start_property_service socket creation failed"; 722 PLOG(FATAL) << "start_property_service socket creation failed";
775 exit(1);
776 } 723 }
777 724
778 listen(property_set_fd, 8); 725 listen(property_set_fd, 8);
diff --git a/init/property_service_test.cpp b/init/property_service_test.cpp
index 3a64e0272..95dd34084 100644
--- a/init/property_service_test.cpp
+++ b/init/property_service_test.cpp
@@ -21,8 +21,11 @@
21#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ 21#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
22#include <sys/_system_properties.h> 22#include <sys/_system_properties.h>
23 23
24#include <android-base/properties.h>
24#include <gtest/gtest.h> 25#include <gtest/gtest.h>
25 26
27using android::base::SetProperty;
28
26namespace android { 29namespace android {
27namespace init { 30namespace init {
28 31
@@ -50,5 +53,19 @@ TEST(property_service, very_long_name_35166374) {
50 ASSERT_EQ(0, close(fd)); 53 ASSERT_EQ(0, close(fd));
51} 54}
52 55
56TEST(property_service, non_utf8_value) {
57 ASSERT_TRUE(SetProperty("property_service_utf8_test", "base_success"));
58 EXPECT_FALSE(SetProperty("property_service_utf8_test", "\x80"));
59 EXPECT_FALSE(SetProperty("property_service_utf8_test", "\xC2\x01"));
60 EXPECT_FALSE(SetProperty("property_service_utf8_test", "\xE0\xFF"));
61 EXPECT_FALSE(SetProperty("property_service_utf8_test", "\xE0\xA0\xFF"));
62 EXPECT_FALSE(SetProperty("property_service_utf8_test", "\xF0\x01\xFF"));
63 EXPECT_FALSE(SetProperty("property_service_utf8_test", "\xF0\x90\xFF"));
64 EXPECT_FALSE(SetProperty("property_service_utf8_test", "\xF0\x90\x80\xFF"));
65 EXPECT_FALSE(SetProperty("property_service_utf8_test", "\xF0\x90\x80"));
66 EXPECT_FALSE(SetProperty("property_service_utf8_test", "ab\xF0\x90\x80\x80qe\xF0\x90\x80"));
67 EXPECT_TRUE(SetProperty("property_service_utf8_test", "\xF0\x90\x80\x80"));
68}
69
53} // namespace init 70} // namespace init
54} // namespace android 71} // namespace android
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 891ca03c1..b17dbafa0 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -54,8 +54,9 @@
54#include "init.h" 54#include "init.h"
55#include "property_service.h" 55#include "property_service.h"
56#include "service.h" 56#include "service.h"
57#include "signal_handler.h" 57#include "sigchld_handler.h"
58 58
59using android::base::Split;
59using android::base::StringPrintf; 60using android::base::StringPrintf;
60using android::base::Timer; 61using android::base::Timer;
61 62
@@ -86,8 +87,8 @@ class MountEntry {
86 mnt_type_(entry.mnt_type), 87 mnt_type_(entry.mnt_type),
87 mnt_opts_(entry.mnt_opts) {} 88 mnt_opts_(entry.mnt_opts) {}
88 89
89 bool Umount() { 90 bool Umount(bool force) {
90 int r = umount2(mnt_dir_.c_str(), 0); 91 int r = umount2(mnt_dir_.c_str(), force ? MNT_FORCE : 0);
91 if (r == 0) { 92 if (r == 0) {
92 LOG(INFO) << "umounted " << mnt_fsname_ << ":" << mnt_dir_ << " opts " << mnt_opts_; 93 LOG(INFO) << "umounted " << mnt_fsname_ << ":" << mnt_dir_ << " opts " << mnt_opts_;
93 return true; 94 return true;
@@ -169,9 +170,7 @@ static void LogShutdownTime(UmountStat stat, Timer* t) {
169 << stat; 170 << stat;
170} 171}
171 172
172// Determines whether the system is capable of rebooting. This is conservative, 173bool IsRebootCapable() {
173// so if any of the attempts to determine this fail, it will still return true.
174static bool IsRebootCapable() {
175 if (!CAP_IS_SUPPORTED(CAP_SYS_BOOT)) { 174 if (!CAP_IS_SUPPORTED(CAP_SYS_BOOT)) {
176 PLOG(WARNING) << "CAP_SYS_BOOT is not supported"; 175 PLOG(WARNING) << "CAP_SYS_BOOT is not supported";
177 return true; 176 return true;
@@ -282,14 +281,15 @@ static UmountStat UmountPartitions(std::chrono::milliseconds timeout) {
282 bool unmount_done = true; 281 bool unmount_done = true;
283 if (emulated_devices.size() > 0) { 282 if (emulated_devices.size() > 0) {
284 unmount_done = std::all_of(emulated_devices.begin(), emulated_devices.end(), 283 unmount_done = std::all_of(emulated_devices.begin(), emulated_devices.end(),
285 [](auto& entry) { return entry.Umount(); }); 284 [](auto& entry) { return entry.Umount(false); });
286 if (unmount_done) { 285 if (unmount_done) {
287 sync(); 286 sync();
288 } 287 }
289 } 288 }
290 unmount_done = std::all_of(block_devices.begin(), block_devices.end(), 289 unmount_done =
291 [](auto& entry) { return entry.Umount(); }) && 290 std::all_of(block_devices.begin(), block_devices.end(),
292 unmount_done; 291 [&timeout](auto& entry) { return entry.Umount(timeout == 0ms); }) &&
292 unmount_done;
293 if (unmount_done) { 293 if (unmount_done) {
294 return UMOUNT_STAT_SUCCESS; 294 return UMOUNT_STAT_SUCCESS;
295 } 295 }
@@ -347,7 +347,16 @@ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& re
347 Timer t; 347 Timer t;
348 LOG(INFO) << "Reboot start, reason: " << reason << ", rebootTarget: " << rebootTarget; 348 LOG(INFO) << "Reboot start, reason: " << reason << ", rebootTarget: " << rebootTarget;
349 349
350 property_set(LAST_REBOOT_REASON_PROPERTY, reason.c_str()); 350 // Ensure last reboot reason is reduced to canonical
351 // alias reported in bootloader or system boot reason.
352 size_t skip = 0;
353 std::vector<std::string> reasons = Split(reason, ",");
354 if (reasons.size() >= 2 && reasons[0] == "reboot" &&
355 (reasons[1] == "recovery" || reasons[1] == "bootloader" || reasons[1] == "cold" ||
356 reasons[1] == "hard" || reasons[1] == "warm")) {
357 skip = strlen("reboot,");
358 }
359 property_set(LAST_REBOOT_REASON_PROPERTY, reason.c_str() + skip);
351 sync(); 360 sync();
352 361
353 bool is_thermal_shutdown = cmd == ANDROID_RB_THERMOFF; 362 bool is_thermal_shutdown = cmd == ANDROID_RB_THERMOFF;
@@ -470,7 +479,7 @@ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& re
470 479
471bool HandlePowerctlMessage(const std::string& command) { 480bool HandlePowerctlMessage(const std::string& command) {
472 unsigned int cmd = 0; 481 unsigned int cmd = 0;
473 std::vector<std::string> cmd_params = android::base::Split(command, ","); 482 std::vector<std::string> cmd_params = Split(command, ",");
474 std::string reboot_target = ""; 483 std::string reboot_target = "";
475 bool run_fsck = false; 484 bool run_fsck = false;
476 bool command_invalid = false; 485 bool command_invalid = false;
@@ -485,6 +494,8 @@ bool HandlePowerctlMessage(const std::string& command) {
485 // Run fsck once the file system is remounted in read-only mode. 494 // Run fsck once the file system is remounted in read-only mode.
486 run_fsck = true; 495 run_fsck = true;
487 } else if (cmd_params[1] == "thermal") { 496 } else if (cmd_params[1] == "thermal") {
497 // Turn off sources of heat immediately.
498 TurnOffBacklight();
488 // run_fsck is false to avoid delay 499 // run_fsck is false to avoid delay
489 cmd = ANDROID_RB_THERMOFF; 500 cmd = ANDROID_RB_THERMOFF;
490 } 501 }
@@ -521,8 +532,7 @@ bool HandlePowerctlMessage(const std::string& command) {
521 // Queue shutdown trigger first 532 // Queue shutdown trigger first
522 ActionManager::GetInstance().QueueEventTrigger("shutdown"); 533 ActionManager::GetInstance().QueueEventTrigger("shutdown");
523 // Queue built-in shutdown_done 534 // Queue built-in shutdown_done
524 auto shutdown_handler = [cmd, command, reboot_target, 535 auto shutdown_handler = [cmd, command, reboot_target, run_fsck](const BuiltinArguments&) {
525 run_fsck](const std::vector<std::string>&) {
526 DoReboot(cmd, command, reboot_target, run_fsck); 536 DoReboot(cmd, command, reboot_target, run_fsck);
527 return Success(); 537 return Success();
528 }; 538 };
diff --git a/init/reboot.h b/init/reboot.h
index ece407f0d..1c58bd134 100644
--- a/init/reboot.h
+++ b/init/reboot.h
@@ -38,6 +38,10 @@ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& re
38// Parses and handles a setprop sys.powerctl message. 38// Parses and handles a setprop sys.powerctl message.
39bool HandlePowerctlMessage(const std::string& command); 39bool HandlePowerctlMessage(const std::string& command);
40 40
41// Determines whether the system is capable of rebooting. This is conservative,
42// so if any of the attempts to determine this fail, it will still return true.
43bool IsRebootCapable();
44
41} // namespace init 45} // namespace init
42} // namespace android 46} // namespace android
43 47
diff --git a/init/result.h b/init/result.h
index 36c3b8324..fc0396245 100644
--- a/init/result.h
+++ b/init/result.h
@@ -153,8 +153,14 @@ inline Error ErrnoError() {
153template <typename T> 153template <typename T>
154class Result { 154class Result {
155 public: 155 public:
156 template <typename... U> 156 Result() {}
157 Result(U&&... result) : contents_(std::in_place_index_t<0>(), std::forward<U>(result)...) {} 157
158 template <typename U, typename... V,
159 typename = std::enable_if_t<!(std::is_same_v<std::decay_t<U>, Result<T>> &&
160 sizeof...(V) == 0)>>
161 Result(U&& result, V&&... results)
162 : contents_(std::in_place_index_t<0>(), std::forward<U>(result),
163 std::forward<V>(results)...) {}
158 164
159 Result(Error&& error) : contents_(std::in_place_index_t<1>(), error.str(), error.get_errno()) {} 165 Result(Error&& error) : contents_(std::in_place_index_t<1>(), error.str(), error.get_errno()) {}
160 Result(const ResultError& result_error) 166 Result(const ResultError& result_error)
diff --git a/init/result_test.cpp b/init/result_test.cpp
index 19caaf5b5..327b4444f 100644
--- a/init/result_test.cpp
+++ b/init/result_test.cpp
@@ -276,6 +276,49 @@ TEST(result, no_copy_on_return) {
276 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called); 276 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
277} 277}
278 278
279// Below two tests require that we do not hide the move constructor with our forwarding reference
280// constructor. This is done with by disabling the forwarding reference constructor if its first
281// and only type is Result<T>.
282TEST(result, result_result_with_success) {
283 auto return_result_result_with_success = []() -> Result<Result<Success>> {
284 return Result<Success>();
285 };
286 auto result = return_result_result_with_success();
287 ASSERT_TRUE(result);
288 ASSERT_TRUE(*result);
289
290 auto inner_result = result.value();
291 ASSERT_TRUE(inner_result);
292}
293
294TEST(result, result_result_with_failure) {
295 auto return_result_result_with_error = []() -> Result<Result<Success>> {
296 return Result<Success>(ResultError("failure string", 6));
297 };
298 auto result = return_result_result_with_error();
299 ASSERT_TRUE(result);
300 ASSERT_FALSE(*result);
301 EXPECT_EQ("failure string", result->error_string());
302 EXPECT_EQ(6, result->error_errno());
303}
304
305// This test requires that we disable the forwarding reference constructor if Result<T> is the
306// *only* type that we are forwarding. In otherwords, if we are forwarding Result<T>, int to
307// construct a Result<T>, then we still need the constructor.
308TEST(result, result_two_parameter_constructor_same_type) {
309 struct TestStruct {
310 TestStruct(int value) : value_(value) {}
311 TestStruct(Result<TestStruct> result, int value) : value_(result->value_ * value) {}
312 int value_;
313 };
314
315 auto return_test_struct = []() -> Result<TestStruct> { return {Result<TestStruct>(6), 6}; };
316
317 auto result = return_test_struct();
318 ASSERT_TRUE(result);
319 EXPECT_EQ(36, result->value_);
320}
321
279TEST(result, die_on_access_failed_result) { 322TEST(result, die_on_access_failed_result) {
280 Result<std::string> result = Error(); 323 Result<std::string> result = Error();
281 ASSERT_DEATH(*result, ""); 324 ASSERT_DEATH(*result, "");
diff --git a/init/security.cpp b/init/security.cpp
index aac8f2e74..a3494a280 100644
--- a/init/security.cpp
+++ b/init/security.cpp
@@ -43,7 +43,7 @@ namespace init {
43// devices/configurations where these I/O operations are blocking for a long 43// devices/configurations where these I/O operations are blocking for a long
44// time. We do not reboot or halt on failures, as this is a best-effort 44// time. We do not reboot or halt on failures, as this is a best-effort
45// attempt. 45// attempt.
46Result<Success> MixHwrngIntoLinuxRngAction(const std::vector<std::string>& args) { 46Result<Success> MixHwrngIntoLinuxRngAction(const BuiltinArguments&) {
47 unique_fd hwrandom_fd( 47 unique_fd hwrandom_fd(
48 TEMP_FAILURE_RETRY(open("/dev/hw_random", O_RDONLY | O_NOFOLLOW | O_CLOEXEC))); 48 TEMP_FAILURE_RETRY(open("/dev/hw_random", O_RDONLY | O_NOFOLLOW | O_CLOEXEC)));
49 if (hwrandom_fd == -1) { 49 if (hwrandom_fd == -1) {
@@ -147,7 +147,7 @@ static bool __attribute__((unused)) SetMmapRndBitsMin(int start, int min, bool c
147// 9e08f57d684a x86: mm: support ARCH_MMAP_RND_BITS 147// 9e08f57d684a x86: mm: support ARCH_MMAP_RND_BITS
148// ec9ee4acd97c drivers: char: random: add get_random_long() 148// ec9ee4acd97c drivers: char: random: add get_random_long()
149// 5ef11c35ce86 mm: ASLR: use get_random_long() 149// 5ef11c35ce86 mm: ASLR: use get_random_long()
150Result<Success> SetMmapRndBitsAction(const std::vector<std::string>& args) { 150Result<Success> SetMmapRndBitsAction(const BuiltinArguments&) {
151// values are arch-dependent 151// values are arch-dependent
152#if defined(USER_MODE_LINUX) 152#if defined(USER_MODE_LINUX)
153 // uml does not support mmap_rnd_bits 153 // uml does not support mmap_rnd_bits
@@ -187,7 +187,7 @@ Result<Success> SetMmapRndBitsAction(const std::vector<std::string>& args) {
187// Set kptr_restrict to the highest available level. 187// Set kptr_restrict to the highest available level.
188// 188//
189// Aborts if unable to set this to an acceptable value. 189// Aborts if unable to set this to an acceptable value.
190Result<Success> SetKptrRestrictAction(const std::vector<std::string>& args) { 190Result<Success> SetKptrRestrictAction(const BuiltinArguments&) {
191 std::string path = KPTR_RESTRICT_PATH; 191 std::string path = KPTR_RESTRICT_PATH;
192 192
193 if (!SetHighestAvailableOptionValue(path, KPTR_RESTRICT_MINVALUE, KPTR_RESTRICT_MAXVALUE)) { 193 if (!SetHighestAvailableOptionValue(path, KPTR_RESTRICT_MINVALUE, KPTR_RESTRICT_MAXVALUE)) {
diff --git a/init/security.h b/init/security.h
index 31e5790f0..6f6b94400 100644
--- a/init/security.h
+++ b/init/security.h
@@ -20,14 +20,15 @@
20#include <string> 20#include <string>
21#include <vector> 21#include <vector>
22 22
23#include "builtin_arguments.h"
23#include "result.h" 24#include "result.h"
24 25
25namespace android { 26namespace android {
26namespace init { 27namespace init {
27 28
28Result<Success> MixHwrngIntoLinuxRngAction(const std::vector<std::string>& args); 29Result<Success> MixHwrngIntoLinuxRngAction(const BuiltinArguments&);
29Result<Success> SetMmapRndBitsAction(const std::vector<std::string>& args); 30Result<Success> SetMmapRndBitsAction(const BuiltinArguments&);
30Result<Success> SetKptrRestrictAction(const std::vector<std::string>& args); 31Result<Success> SetKptrRestrictAction(const BuiltinArguments&);
31 32
32} // namespace init 33} // namespace init
33} // namespace android 34} // namespace android
diff --git a/init/selinux.cpp b/init/selinux.cpp
index ef59164e3..c4b01e648 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -198,9 +198,18 @@ bool ReadFirstLine(const char* file, std::string* line) {
198 198
199bool FindPrecompiledSplitPolicy(std::string* file) { 199bool FindPrecompiledSplitPolicy(std::string* file) {
200 file->clear(); 200 file->clear();
201 201 // If there is an odm partition, precompiled_sepolicy will be in
202 static constexpr const char precompiled_sepolicy[] = "/vendor/etc/selinux/precompiled_sepolicy"; 202 // odm/etc/selinux. Otherwise it will be in vendor/etc/selinux.
203 if (access(precompiled_sepolicy, R_OK) == -1) { 203 static constexpr const char vendor_precompiled_sepolicy[] =
204 "/vendor/etc/selinux/precompiled_sepolicy";
205 static constexpr const char odm_precompiled_sepolicy[] =
206 "/odm/etc/selinux/precompiled_sepolicy";
207 if (access(odm_precompiled_sepolicy, R_OK) == 0) {
208 *file = odm_precompiled_sepolicy;
209 } else if (access(vendor_precompiled_sepolicy, R_OK) == 0) {
210 *file = vendor_precompiled_sepolicy;
211 } else {
212 PLOG(INFO) << "No precompiled sepolicy";
204 return false; 213 return false;
205 } 214 }
206 std::string actual_plat_id; 215 std::string actual_plat_id;
@@ -209,19 +218,18 @@ bool FindPrecompiledSplitPolicy(std::string* file) {
209 "/system/etc/selinux/plat_and_mapping_sepolicy.cil.sha256"; 218 "/system/etc/selinux/plat_and_mapping_sepolicy.cil.sha256";
210 return false; 219 return false;
211 } 220 }
221
212 std::string precompiled_plat_id; 222 std::string precompiled_plat_id;
213 if (!ReadFirstLine("/vendor/etc/selinux/precompiled_sepolicy.plat_and_mapping.sha256", 223 std::string precompiled_sha256 = *file + ".plat_and_mapping.sha256";
214 &precompiled_plat_id)) { 224 if (!ReadFirstLine(precompiled_sha256.c_str(), &precompiled_plat_id)) {
215 PLOG(INFO) << "Failed to read " 225 PLOG(INFO) << "Failed to read " << precompiled_sha256;
216 "/vendor/etc/selinux/" 226 file->clear();
217 "precompiled_sepolicy.plat_and_mapping.sha256";
218 return false; 227 return false;
219 } 228 }
220 if ((actual_plat_id.empty()) || (actual_plat_id != precompiled_plat_id)) { 229 if ((actual_plat_id.empty()) || (actual_plat_id != precompiled_plat_id)) {
230 file->clear();
221 return false; 231 return false;
222 } 232 }
223
224 *file = precompiled_sepolicy;
225 return true; 233 return true;
226} 234}
227 235
@@ -293,24 +301,55 @@ bool LoadSplitPolicy() {
293 return false; 301 return false;
294 } 302 }
295 std::string mapping_file("/system/etc/selinux/mapping/" + vend_plat_vers + ".cil"); 303 std::string mapping_file("/system/etc/selinux/mapping/" + vend_plat_vers + ".cil");
304
305 // vendor_sepolicy.cil and nonplat_declaration.cil are the new design to replace
306 // nonplat_sepolicy.cil.
307 std::string nonplat_declaration_cil_file("/vendor/etc/selinux/nonplat_declaration.cil");
308 std::string vendor_policy_cil_file("/vendor/etc/selinux/vendor_sepolicy.cil");
309
310 if (access(vendor_policy_cil_file.c_str(), F_OK) == -1) {
311 // For backward compatibility.
312 // TODO: remove this after no device is using nonplat_sepolicy.cil.
313 vendor_policy_cil_file = "/vendor/etc/selinux/nonplat_sepolicy.cil";
314 nonplat_declaration_cil_file.clear();
315 } else if (access(nonplat_declaration_cil_file.c_str(), F_OK) == -1) {
316 LOG(ERROR) << "Missing " << nonplat_declaration_cil_file;
317 return false;
318 }
319
320 // odm_sepolicy.cil is default but optional.
321 std::string odm_policy_cil_file("/odm/etc/selinux/odm_sepolicy.cil");
322 if (access(odm_policy_cil_file.c_str(), F_OK) == -1) {
323 odm_policy_cil_file.clear();
324 }
296 const std::string version_as_string = std::to_string(max_policy_version); 325 const std::string version_as_string = std::to_string(max_policy_version);
297 326
298 // clang-format off 327 // clang-format off
299 const char* compile_args[] = { 328 std::vector<const char*> compile_args {
300 "/system/bin/secilc", 329 "/system/bin/secilc",
301 plat_policy_cil_file, 330 plat_policy_cil_file,
302 "-M", "true", "-G", "-N", 331 "-m", "-M", "true", "-G", "-N",
303 // Target the highest policy language version supported by the kernel 332 // Target the highest policy language version supported by the kernel
304 "-c", version_as_string.c_str(), 333 "-c", version_as_string.c_str(),
305 mapping_file.c_str(), 334 mapping_file.c_str(),
306 "/vendor/etc/selinux/nonplat_sepolicy.cil",
307 "-o", compiled_sepolicy, 335 "-o", compiled_sepolicy,
308 // We don't care about file_contexts output by the compiler 336 // We don't care about file_contexts output by the compiler
309 "-f", "/sys/fs/selinux/null", // /dev/null is not yet available 337 "-f", "/sys/fs/selinux/null", // /dev/null is not yet available
310 nullptr}; 338 };
311 // clang-format on 339 // clang-format on
312 340
313 if (!ForkExecveAndWaitForCompletion(compile_args[0], (char**)compile_args)) { 341 if (!nonplat_declaration_cil_file.empty()) {
342 compile_args.push_back(nonplat_declaration_cil_file.c_str());
343 }
344 if (!vendor_policy_cil_file.empty()) {
345 compile_args.push_back(vendor_policy_cil_file.c_str());
346 }
347 if (!odm_policy_cil_file.empty()) {
348 compile_args.push_back(odm_policy_cil_file.c_str());
349 }
350 compile_args.push_back(nullptr);
351
352 if (!ForkExecveAndWaitForCompletion(compile_args[0], (char**)compile_args.data())) {
314 unlink(compiled_sepolicy); 353 unlink(compiled_sepolicy);
315 return false; 354 return false;
316 } 355 }
diff --git a/init/service.cpp b/init/service.cpp
index 6f27a4bb6..b339bc0b6 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -135,29 +135,34 @@ static void SetUpPidNamespace(const std::string& service_name) {
135 } 135 }
136} 136}
137 137
138static void ExpandArgs(const std::vector<std::string>& args, std::vector<char*>* strs) { 138static bool ExpandArgsAndExecv(const std::vector<std::string>& args) {
139 std::vector<std::string> expanded_args; 139 std::vector<std::string> expanded_args;
140 std::vector<char*> c_strings;
141
140 expanded_args.resize(args.size()); 142 expanded_args.resize(args.size());
141 strs->push_back(const_cast<char*>(args[0].c_str())); 143 c_strings.push_back(const_cast<char*>(args[0].data()));
142 for (std::size_t i = 1; i < args.size(); ++i) { 144 for (std::size_t i = 1; i < args.size(); ++i) {
143 if (!expand_props(args[i], &expanded_args[i])) { 145 if (!expand_props(args[i], &expanded_args[i])) {
144 LOG(FATAL) << args[0] << ": cannot expand '" << args[i] << "'"; 146 LOG(FATAL) << args[0] << ": cannot expand '" << args[i] << "'";
145 } 147 }
146 strs->push_back(const_cast<char*>(expanded_args[i].c_str())); 148 c_strings.push_back(expanded_args[i].data());
147 } 149 }
148 strs->push_back(nullptr); 150 c_strings.push_back(nullptr);
151
152 return execv(c_strings[0], c_strings.data()) == 0;
149} 153}
150 154
151unsigned long Service::next_start_order_ = 1; 155unsigned long Service::next_start_order_ = 1;
152bool Service::is_exec_service_running_ = false; 156bool Service::is_exec_service_running_ = false;
153 157
154Service::Service(const std::string& name, const std::vector<std::string>& args) 158Service::Service(const std::string& name, Subcontext* subcontext_for_restart_commands,
155 : Service(name, 0, 0, 0, {}, 0, 0, "", args) {} 159 const std::vector<std::string>& args)
160 : Service(name, 0, 0, 0, {}, 0, 0, "", subcontext_for_restart_commands, args) {}
156 161
157Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid, 162Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
158 const std::vector<gid_t>& supp_gids, const CapSet& capabilities, 163 const std::vector<gid_t>& supp_gids, const CapSet& capabilities,
159 unsigned namespace_flags, const std::string& seclabel, 164 unsigned namespace_flags, const std::string& seclabel,
160 const std::vector<std::string>& args) 165 Subcontext* subcontext_for_restart_commands, const std::vector<std::string>& args)
161 : name_(name), 166 : name_(name),
162 classnames_({"default"}), 167 classnames_({"default"}),
163 flags_(flags), 168 flags_(flags),
@@ -169,7 +174,7 @@ Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
169 capabilities_(capabilities), 174 capabilities_(capabilities),
170 namespace_flags_(namespace_flags), 175 namespace_flags_(namespace_flags),
171 seclabel_(seclabel), 176 seclabel_(seclabel),
172 onrestart_(false, "<Service '" + name + "' onrestart>", 0), 177 onrestart_(false, subcontext_for_restart_commands, "<Service '" + name + "' onrestart>", 0),
173 keychord_id_(0), 178 keychord_id_(0),
174 ioprio_class_(IoSchedClass_NONE), 179 ioprio_class_(IoSchedClass_NONE),
175 ioprio_pri_(0), 180 ioprio_pri_(0),
@@ -785,10 +790,8 @@ Result<Success> Service::Start() {
785 // priority. Aborts on failure. 790 // priority. Aborts on failure.
786 SetProcessAttributes(); 791 SetProcessAttributes();
787 792
788 std::vector<char*> strs; 793 if (!ExpandArgsAndExecv(args_)) {
789 ExpandArgs(args_, &strs); 794 PLOG(ERROR) << "cannot execve('" << args_[0] << "')";
790 if (execv(strs[0], (char**)&strs[0]) < 0) {
791 PLOG(ERROR) << "cannot execve('" << strs[0] << "')";
792 } 795 }
793 796
794 _exit(127); 797 _exit(127);
@@ -1005,7 +1008,7 @@ std::unique_ptr<Service> Service::MakeTemporaryOneshotService(const std::vector<
1005 } 1008 }
1006 1009
1007 return std::make_unique<Service>(name, flags, *uid, *gid, supp_gids, no_capabilities, 1010 return std::make_unique<Service>(name, flags, *uid, *gid, supp_gids, no_capabilities,
1008 namespace_flags, seclabel, str_args); 1011 namespace_flags, seclabel, nullptr, str_args);
1009} 1012}
1010 1013
1011// Shutdown services in the opposite order that they were started. 1014// Shutdown services in the opposite order that they were started.
@@ -1053,8 +1056,18 @@ Result<Success> ServiceParser::ParseSection(std::vector<std::string>&& args,
1053 return Error() << "ignored duplicate definition of service '" << name << "'"; 1056 return Error() << "ignored duplicate definition of service '" << name << "'";
1054 } 1057 }
1055 1058
1059 Subcontext* restart_action_subcontext = nullptr;
1060 if (subcontexts_) {
1061 for (auto& subcontext : *subcontexts_) {
1062 if (StartsWith(filename, subcontext.path_prefix().c_str())) {
1063 restart_action_subcontext = &subcontext;
1064 break;
1065 }
1066 }
1067 }
1068
1056 std::vector<std::string> str_args(args.begin() + 2, args.end()); 1069 std::vector<std::string> str_args(args.begin() + 2, args.end());
1057 service_ = std::make_unique<Service>(name, str_args); 1070 service_ = std::make_unique<Service>(name, restart_action_subcontext, str_args);
1058 return Success(); 1071 return Success();
1059} 1072}
1060 1073
diff --git a/init/service.h b/init/service.h
index 67542ca92..89dd7806b 100644
--- a/init/service.h
+++ b/init/service.h
@@ -33,6 +33,7 @@
33#include "descriptors.h" 33#include "descriptors.h"
34#include "keyword_map.h" 34#include "keyword_map.h"
35#include "parser.h" 35#include "parser.h"
36#include "subcontext.h"
36 37
37#define SVC_DISABLED 0x001 // do not autostart with class 38#define SVC_DISABLED 0x001 // do not autostart with class
38#define SVC_ONESHOT 0x002 // do not restart on exit 39#define SVC_ONESHOT 0x002 // do not restart on exit
@@ -60,12 +61,13 @@ namespace init {
60 61
61class Service { 62class Service {
62 public: 63 public:
63 Service(const std::string& name, const std::vector<std::string>& args); 64 Service(const std::string& name, Subcontext* subcontext_for_restart_commands,
65 const std::vector<std::string>& args);
64 66
65 Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid, 67 Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
66 const std::vector<gid_t>& supp_gids, const CapSet& capabilities, 68 const std::vector<gid_t>& supp_gids, const CapSet& capabilities,
67 unsigned namespace_flags, const std::string& seclabel, 69 unsigned namespace_flags, const std::string& seclabel,
68 const std::vector<std::string>& args); 70 Subcontext* subcontext_for_restart_commands, const std::vector<std::string>& args);
69 71
70 static std::unique_ptr<Service> MakeTemporaryOneshotService(const std::vector<std::string>& args); 72 static std::unique_ptr<Service> MakeTemporaryOneshotService(const std::vector<std::string>& args);
71 73
@@ -237,7 +239,8 @@ class ServiceList {
237 239
238class ServiceParser : public SectionParser { 240class ServiceParser : public SectionParser {
239 public: 241 public:
240 ServiceParser(ServiceList* service_list) : service_list_(service_list), service_(nullptr) {} 242 ServiceParser(ServiceList* service_list, std::vector<Subcontext>* subcontexts)
243 : service_list_(service_list), subcontexts_(subcontexts), service_(nullptr) {}
241 Result<Success> ParseSection(std::vector<std::string>&& args, const std::string& filename, 244 Result<Success> ParseSection(std::vector<std::string>&& args, const std::string& filename,
242 int line) override; 245 int line) override;
243 Result<Success> ParseLineSection(std::vector<std::string>&& args, int line) override; 246 Result<Success> ParseLineSection(std::vector<std::string>&& args, int line) override;
@@ -247,6 +250,7 @@ class ServiceParser : public SectionParser {
247 bool IsValidName(const std::string& name) const; 250 bool IsValidName(const std::string& name) const;
248 251
249 ServiceList* service_list_; 252 ServiceList* service_list_;
253 std::vector<Subcontext>* subcontexts_;
250 std::unique_ptr<Service> service_; 254 std::unique_ptr<Service> service_;
251}; 255};
252 256
diff --git a/init/service_test.cpp b/init/service_test.cpp
index 98d876f51..b43c2e9b4 100644
--- a/init/service_test.cpp
+++ b/init/service_test.cpp
@@ -37,7 +37,8 @@ TEST(service, pod_initialized) {
37 } 37 }
38 38
39 std::vector<std::string> dummy_args{"/bin/test"}; 39 std::vector<std::string> dummy_args{"/bin/test"};
40 Service* service_in_old_memory = new (old_memory) Service("test_old_memory", dummy_args); 40 Service* service_in_old_memory =
41 new (old_memory) Service("test_old_memory", nullptr, dummy_args);
41 42
42 EXPECT_EQ(0U, service_in_old_memory->flags()); 43 EXPECT_EQ(0U, service_in_old_memory->flags());
43 EXPECT_EQ(0, service_in_old_memory->pid()); 44 EXPECT_EQ(0, service_in_old_memory->pid());
@@ -56,8 +57,8 @@ TEST(service, pod_initialized) {
56 old_memory[i] = 0xFF; 57 old_memory[i] = 0xFF;
57 } 58 }
58 59
59 Service* service_in_old_memory2 = new (old_memory) 60 Service* service_in_old_memory2 = new (old_memory) Service(
60 Service("test_old_memory", 0U, 0U, 0U, std::vector<gid_t>(), CapSet(), 0U, "", dummy_args); 61 "test_old_memory", 0U, 0U, 0U, std::vector<gid_t>(), CapSet(), 0U, "", nullptr, dummy_args);
61 62
62 EXPECT_EQ(0U, service_in_old_memory2->flags()); 63 EXPECT_EQ(0U, service_in_old_memory2->flags());
63 EXPECT_EQ(0, service_in_old_memory2->pid()); 64 EXPECT_EQ(0, service_in_old_memory2->pid());
diff --git a/init/signal_handler.cpp b/init/sigchld_handler.cpp
index 9e49c48a7..072a0fb0b 100644
--- a/init/signal_handler.cpp
+++ b/init/sigchld_handler.cpp
@@ -14,7 +14,7 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17#include "signal_handler.h" 17#include "sigchld_handler.h"
18 18
19#include <signal.h> 19#include <signal.h>
20#include <string.h> 20#include <string.h>
@@ -60,22 +60,28 @@ static bool ReapOneProcess() {
60 // want the pid to remain valid throughout that (and potentially future) usages. 60 // want the pid to remain valid throughout that (and potentially future) usages.
61 auto reaper = make_scope_guard([pid] { TEMP_FAILURE_RETRY(waitpid(pid, nullptr, WNOHANG)); }); 61 auto reaper = make_scope_guard([pid] { TEMP_FAILURE_RETRY(waitpid(pid, nullptr, WNOHANG)); });
62 62
63 if (PropertyChildReap(pid)) return true;
64
65 Service* service = ServiceList::GetInstance().FindService(pid, &Service::pid);
66
67 std::string name; 63 std::string name;
68 std::string wait_string; 64 std::string wait_string;
69 if (service) { 65 Service* service = nullptr;
70 name = StringPrintf("Service '%s' (pid %d)", service->name().c_str(), pid); 66
71 if (service->flags() & SVC_EXEC) { 67 if (PropertyChildReap(pid)) {
72 auto exec_duration = boot_clock::now() - service->time_started(); 68 name = "Async property child";
73 auto exec_duration_ms = 69 } else if (SubcontextChildReap(pid)) {
74 std::chrono::duration_cast<std::chrono::milliseconds>(exec_duration).count(); 70 name = "Subcontext";
75 wait_string = StringPrintf(" waiting took %f seconds", exec_duration_ms / 1000.0f);
76 }
77 } else { 71 } else {
78 name = StringPrintf("Untracked pid %d", pid); 72 service = ServiceList::GetInstance().FindService(pid, &Service::pid);
73
74 if (service) {
75 name = StringPrintf("Service '%s' (pid %d)", service->name().c_str(), pid);
76 if (service->flags() & SVC_EXEC) {
77 auto exec_duration = boot_clock::now() - service->time_started();
78 auto exec_duration_ms =
79 std::chrono::duration_cast<std::chrono::milliseconds>(exec_duration).count();
80 wait_string = StringPrintf(" waiting took %f seconds", exec_duration_ms / 1000.0f);
81 }
82 } else {
83 name = StringPrintf("Untracked pid %d", pid);
84 }
79 } 85 }
80 86
81 auto status = siginfo.si_status; 87 auto status = siginfo.si_status;
@@ -115,12 +121,11 @@ void ReapAnyOutstandingChildren() {
115 } 121 }
116} 122}
117 123
118void signal_handler_init() { 124void sigchld_handler_init() {
119 // Create a signalling mechanism for SIGCHLD. 125 // Create a signalling mechanism for SIGCHLD.
120 int s[2]; 126 int s[2];
121 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, s) == -1) { 127 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, s) == -1) {
122 PLOG(ERROR) << "socketpair failed"; 128 PLOG(FATAL) << "socketpair failed in sigchld_handler_init";
123 exit(1);
124 } 129 }
125 130
126 signal_write_fd = s[0]; 131 signal_write_fd = s[0];
diff --git a/init/signal_handler.h b/init/sigchld_handler.h
index 9362be532..c86dc8dd4 100644
--- a/init/signal_handler.h
+++ b/init/sigchld_handler.h
@@ -14,15 +14,15 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17#ifndef _INIT_SIGNAL_HANDLER_H_ 17#ifndef _INIT_SIGCHLD_HANDLER_H_
18#define _INIT_SIGNAL_HANDLER_H_ 18#define _INIT_SIGCHLD_HANDLER_H_
19 19
20namespace android { 20namespace android {
21namespace init { 21namespace init {
22 22
23void ReapAnyOutstandingChildren(); 23void ReapAnyOutstandingChildren();
24 24
25void signal_handler_init(void); 25void sigchld_handler_init(void);
26 26
27} // namespace init 27} // namespace init
28} // namespace android 28} // namespace android
diff --git a/init/subcontext.cpp b/init/subcontext.cpp
new file mode 100644
index 000000000..927953d67
--- /dev/null
+++ b/init/subcontext.cpp
@@ -0,0 +1,285 @@
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "subcontext.h"
18
19#include <fcntl.h>
20#include <poll.h>
21#include <sys/socket.h>
22#include <unistd.h>
23
24#include <android-base/file.h>
25#include <android-base/logging.h>
26#include <android-base/properties.h>
27#include <android-base/strings.h>
28#include <selinux/android.h>
29
30#include "action.h"
31#include "system/core/init/subcontext.pb.h"
32#include "util.h"
33
34using android::base::GetBoolProperty;
35using android::base::GetExecutablePath;
36using android::base::Join;
37using android::base::Socketpair;
38using android::base::Split;
39using android::base::StartsWith;
40using android::base::unique_fd;
41
42namespace android {
43namespace init {
44
45const std::string kInitContext = "u:r:init:s0";
46const std::string kVendorContext = "u:r:vendor_init:s0";
47
48namespace {
49
50constexpr size_t kBufferSize = 4096;
51
52Result<std::string> ReadMessage(int socket) {
53 char buffer[kBufferSize] = {};
54 auto result = TEMP_FAILURE_RETRY(recv(socket, buffer, sizeof(buffer), 0));
55 if (result <= 0) {
56 return ErrnoError();
57 }
58 return std::string(buffer, result);
59}
60
61template <typename T>
62Result<Success> SendMessage(int socket, const T& message) {
63 std::string message_string;
64 if (!message.SerializeToString(&message_string)) {
65 return Error() << "Unable to serialize message";
66 }
67
68 if (message_string.size() > kBufferSize) {
69 return Error() << "Serialized message too long to send";
70 }
71
72 if (auto result =
73 TEMP_FAILURE_RETRY(send(socket, message_string.c_str(), message_string.size(), 0));
74 result != static_cast<long>(message_string.size())) {
75 return ErrnoError() << "send() failed to send message contents";
76 }
77 return Success();
78}
79
80class SubcontextProcess {
81 public:
82 SubcontextProcess(const KeywordFunctionMap* function_map, std::string context, int init_fd)
83 : function_map_(function_map), context_(std::move(context)), init_fd_(init_fd){};
84 void MainLoop();
85
86 private:
87 void RunCommand(const SubcontextCommand::ExecuteCommand& execute_command,
88 SubcontextReply::ResultMessage* result_message) const;
89
90 const KeywordFunctionMap* function_map_;
91 const std::string context_;
92 const int init_fd_;
93};
94
95void SubcontextProcess::RunCommand(const SubcontextCommand::ExecuteCommand& execute_command,
96 SubcontextReply::ResultMessage* result_message) const {
97 // Need to use ArraySplice instead of this code.
98 auto args = std::vector<std::string>();
99 for (const auto& string : execute_command.args()) {
100 args.emplace_back(string);
101 }
102
103 auto map_result = function_map_->FindFunction(args);
104 Result<Success> result;
105 if (!map_result) {
106 result = Error() << "Cannot find command: " << map_result.error();
107 } else {
108 result = RunBuiltinFunction(map_result->second, args, context_);
109 }
110
111 if (result) {
112 result_message->set_success(true);
113 } else {
114 result_message->set_success(false);
115 result_message->set_error_string(result.error_string());
116 result_message->set_error_errno(result.error_errno());
117 }
118}
119
120void SubcontextProcess::MainLoop() {
121 pollfd ufd[1];
122 ufd[0].events = POLLIN;
123 ufd[0].fd = init_fd_;
124
125 while (true) {
126 ufd[0].revents = 0;
127 int nr = TEMP_FAILURE_RETRY(poll(ufd, arraysize(ufd), -1));
128 if (nr == 0) continue;
129 if (nr < 0) {
130 PLOG(FATAL) << "poll() of subcontext socket failed, continuing";
131 }
132
133 auto init_message = ReadMessage(init_fd_);
134 if (!init_message) {
135 LOG(FATAL) << "Could not read message from init: " << init_message.error();
136 }
137
138 auto subcontext_command = SubcontextCommand();
139 if (!subcontext_command.ParseFromString(*init_message)) {
140 LOG(FATAL) << "Unable to parse message from init";
141 }
142
143 auto reply = SubcontextReply();
144 switch (subcontext_command.command_case()) {
145 case SubcontextCommand::kExecuteCommand: {
146 RunCommand(subcontext_command.execute_command(), reply.mutable_result());
147 break;
148 }
149 default:
150 LOG(FATAL) << "Unknown message type from init: "
151 << subcontext_command.command_case();
152 }
153
154 if (auto result = SendMessage(init_fd_, reply); !result) {
155 LOG(FATAL) << "Failed to send message to init: " << result.error();
156 }
157 }
158}
159
160} // namespace
161
162int SubcontextMain(int argc, char** argv, const KeywordFunctionMap* function_map) {
163 if (argc < 4) LOG(FATAL) << "Fewer than 4 args specified to subcontext (" << argc << ")";
164
165 auto context = std::string(argv[2]);
166 auto init_fd = std::atoi(argv[3]);
167
168 auto subcontext_process = SubcontextProcess(function_map, context, init_fd);
169 subcontext_process.MainLoop();
170 return 0;
171}
172
173void Subcontext::Fork() {
174 unique_fd subcontext_socket;
175 if (!Socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, &socket_, &subcontext_socket)) {
176 LOG(FATAL) << "Could not create socket pair to communicate to subcontext";
177 return;
178 }
179
180 auto result = fork();
181
182 if (result == -1) {
183 LOG(FATAL) << "Could not fork subcontext";
184 } else if (result == 0) {
185 socket_.reset();
186
187 // We explicitly do not use O_CLOEXEC here, such that we can reference this FD by number
188 // in the subcontext process after we exec.
189 int child_fd = dup(subcontext_socket);
190 if (child_fd < 0) {
191 PLOG(FATAL) << "Could not dup child_fd";
192 }
193
194 if (setexeccon(context_.c_str()) < 0) {
195 PLOG(FATAL) << "Could not set execcon for '" << context_ << "'";
196 }
197
198 auto init_path = GetExecutablePath();
199 auto child_fd_string = std::to_string(child_fd);
200 const char* args[] = {init_path.c_str(), "subcontext", context_.c_str(),
201 child_fd_string.c_str(), nullptr};
202 execv(init_path.data(), const_cast<char**>(args));
203
204 PLOG(FATAL) << "Could not execv subcontext init";
205 } else {
206 subcontext_socket.reset();
207 pid_ = result;
208 LOG(INFO) << "Forked subcontext for '" << context_ << "' with pid " << pid_;
209 }
210}
211
212void Subcontext::Restart() {
213 LOG(ERROR) << "Restarting subcontext '" << context_ << "'";
214 if (pid_) {
215 kill(pid_, SIGKILL);
216 }
217 pid_ = 0;
218 socket_.reset();
219 Fork();
220}
221
222Result<Success> Subcontext::Execute(const std::vector<std::string>& args) {
223 auto subcontext_command = SubcontextCommand();
224 std::copy(
225 args.begin(), args.end(),
226 RepeatedPtrFieldBackInserter(subcontext_command.mutable_execute_command()->mutable_args()));
227
228 if (auto result = SendMessage(socket_, subcontext_command); !result) {
229 Restart();
230 return ErrnoError() << "Failed to send message to subcontext";
231 }
232
233 auto subcontext_message = ReadMessage(socket_);
234 if (!subcontext_message) {
235 Restart();
236 return Error() << "Failed to receive result from subcontext: " << subcontext_message.error();
237 }
238
239 auto subcontext_reply = SubcontextReply();
240 if (!subcontext_reply.ParseFromString(*subcontext_message)) {
241 Restart();
242 return Error() << "Unable to parse message from subcontext";
243 }
244
245 switch (subcontext_reply.reply_case()) {
246 case SubcontextReply::kResult: {
247 auto result = subcontext_reply.result();
248 if (result.success()) {
249 return Success();
250 } else {
251 return ResultError(result.error_string(), result.error_errno());
252 }
253 }
254 default:
255 return Error() << "Unknown message type from subcontext: "
256 << subcontext_reply.reply_case();
257 }
258}
259
260static std::vector<Subcontext> subcontexts;
261
262std::vector<Subcontext>* InitializeSubcontexts() {
263 if (GetBoolProperty("ro.init.subcontexts_enabled", false)) {
264 static const char* const paths_and_secontexts[][2] = {
265 {"/vendor", kVendorContext.c_str()},
266 };
267 for (const auto& [path_prefix, secontext] : paths_and_secontexts) {
268 subcontexts.emplace_back(path_prefix, secontext);
269 }
270 }
271 return &subcontexts;
272}
273
274bool SubcontextChildReap(pid_t pid) {
275 for (auto& subcontext : subcontexts) {
276 if (subcontext.pid() == pid) {
277 subcontext.Restart();
278 return true;
279 }
280 }
281 return false;
282}
283
284} // namespace init
285} // namespace android
diff --git a/init/subcontext.h b/init/subcontext.h
new file mode 100644
index 000000000..ac77e08a8
--- /dev/null
+++ b/init/subcontext.h
@@ -0,0 +1,80 @@
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _INIT_SUBCONTEXT_H
18#define _INIT_SUBCONTEXT_H
19
20#include <signal.h>
21
22#include <string>
23#include <vector>
24
25#include <android-base/unique_fd.h>
26
27#include "builtins.h"
28
29namespace android {
30namespace init {
31
32extern const std::string kInitContext;
33extern const std::string kVendorContext;
34
35class Subcontext {
36 public:
37 Subcontext(std::string path_prefix, std::string context)
38 : path_prefix_(path_prefix), context_(std::move(context)) {
39 Fork();
40 }
41
42 Result<Success> Execute(const std::vector<std::string>& command);
43 void Restart();
44
45 const std::string& path_prefix() const { return path_prefix_; }
46 const std::string& context() const { return context_; }
47 pid_t pid() const { return pid_; }
48
49 private:
50 void Fork();
51
52 std::string path_prefix_;
53 std::string context_;
54 pid_t pid_;
55 android::base::unique_fd socket_;
56};
57
58// For testing, to kill the subcontext after the test has completed.
59class SubcontextKiller {
60 public:
61 SubcontextKiller(const Subcontext& subcontext) : subcontext_(subcontext) {}
62 ~SubcontextKiller() {
63 if (subcontext_.pid() > 0) {
64 kill(subcontext_.pid(), SIGTERM);
65 kill(subcontext_.pid(), SIGKILL);
66 }
67 }
68
69 private:
70 const Subcontext& subcontext_;
71};
72
73int SubcontextMain(int argc, char** argv, const KeywordFunctionMap* function_map);
74std::vector<Subcontext>* InitializeSubcontexts();
75bool SubcontextChildReap(pid_t pid);
76
77} // namespace init
78} // namespace android
79
80#endif
diff --git a/init/subcontext.proto b/init/subcontext.proto
new file mode 100644
index 000000000..0d8973457
--- /dev/null
+++ b/init/subcontext.proto
@@ -0,0 +1,33 @@
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17syntax = "proto2";
18option optimize_for = LITE_RUNTIME;
19
20message SubcontextCommand {
21 message ExecuteCommand { repeated string args = 1; }
22 oneof command { ExecuteCommand execute_command = 1; }
23}
24
25message SubcontextReply {
26 message ResultMessage {
27 optional bool success = 1;
28 optional string error_string = 2;
29 optional int32 error_errno = 3;
30 }
31
32 oneof reply { ResultMessage result = 1; }
33} \ No newline at end of file
diff --git a/init/subcontext_benchmark.cpp b/init/subcontext_benchmark.cpp
new file mode 100644
index 000000000..a62b9592e
--- /dev/null
+++ b/init/subcontext_benchmark.cpp
@@ -0,0 +1,57 @@
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "subcontext.h"
18
19#include <benchmark/benchmark.h>
20
21#include "test_function_map.h"
22
23namespace android {
24namespace init {
25
26static void BenchmarkSuccess(benchmark::State& state) {
27 auto subcontext = Subcontext("path", kVendorContext);
28 auto subcontext_killer = SubcontextKiller(subcontext);
29
30 while (state.KeepRunning()) {
31 subcontext.Execute(std::vector<std::string>{"return_success"});
32 }
33}
34
35BENCHMARK(BenchmarkSuccess);
36
37TestFunctionMap BuildTestFunctionMap() {
38 TestFunctionMap test_function_map;
39 test_function_map.Add("return_success", 0, 0, true,
40 [](const BuiltinArguments& args) { return Success(); });
41
42 return test_function_map;
43}
44
45} // namespace init
46} // namespace android
47
48int main(int argc, char** argv) {
49 if (argc > 1 && !strcmp(basename(argv[1]), "subcontext")) {
50 auto test_function_map = android::init::BuildTestFunctionMap();
51 return android::init::SubcontextMain(argc, argv, &test_function_map);
52 }
53
54 ::benchmark::Initialize(&argc, argv);
55 if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1;
56 ::benchmark::RunSpecifiedBenchmarks();
57}
diff --git a/init/subcontext_test.cpp b/init/subcontext_test.cpp
new file mode 100644
index 000000000..60b45b9f7
--- /dev/null
+++ b/init/subcontext_test.cpp
@@ -0,0 +1,179 @@
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "subcontext.h"
18
19#include <unistd.h>
20
21#include <chrono>
22
23#include <android-base/properties.h>
24#include <android-base/strings.h>
25#include <gtest/gtest.h>
26
27#include "builtin_arguments.h"
28#include "test_function_map.h"
29
30using namespace std::literals;
31
32using android::base::GetProperty;
33using android::base::Join;
34using android::base::SetProperty;
35using android::base::Split;
36using android::base::WaitForProperty;
37
38namespace android {
39namespace init {
40
41TEST(subcontext, CheckDifferentPid) {
42 auto subcontext = Subcontext("path", kVendorContext);
43 auto subcontext_killer = SubcontextKiller(subcontext);
44
45 auto result = subcontext.Execute(std::vector<std::string>{"return_pids_as_error"});
46 ASSERT_FALSE(result);
47
48 auto pids = Split(result.error_string(), " ");
49 ASSERT_EQ(2U, pids.size());
50 auto our_pid = std::to_string(getpid());
51 EXPECT_NE(our_pid, pids[0]);
52 EXPECT_EQ(our_pid, pids[1]);
53}
54
55TEST(subcontext, SetProp) {
56 auto subcontext = Subcontext("path", kVendorContext);
57 auto subcontext_killer = SubcontextKiller(subcontext);
58
59 SetProperty("init.test.subcontext", "fail");
60 WaitForProperty("init.test.subcontext", "fail");
61
62 auto args = std::vector<std::string>{
63 "setprop",
64 "init.test.subcontext",
65 "success",
66 };
67 auto result = subcontext.Execute(args);
68 ASSERT_TRUE(result) << result.error();
69
70 EXPECT_TRUE(WaitForProperty("init.test.subcontext", "success", 10s));
71}
72
73TEST(subcontext, MultipleCommands) {
74 auto subcontext = Subcontext("path", kVendorContext);
75 auto subcontext_killer = SubcontextKiller(subcontext);
76
77 auto first_pid = subcontext.pid();
78
79 auto expected_words = std::vector<std::string>{
80 "this",
81 "is",
82 "a",
83 "test",
84 };
85
86 for (const auto& word : expected_words) {
87 auto args = std::vector<std::string>{
88 "add_word",
89 word,
90 };
91 auto result = subcontext.Execute(args);
92 ASSERT_TRUE(result) << result.error();
93 }
94
95 auto result = subcontext.Execute(std::vector<std::string>{"return_words_as_error"});
96 ASSERT_FALSE(result);
97 EXPECT_EQ(Join(expected_words, " "), result.error_string());
98 EXPECT_EQ(first_pid, subcontext.pid());
99}
100
101TEST(subcontext, RecoverAfterAbort) {
102 auto subcontext = Subcontext("path", kVendorContext);
103 auto subcontext_killer = SubcontextKiller(subcontext);
104
105 auto first_pid = subcontext.pid();
106
107 auto result = subcontext.Execute(std::vector<std::string>{"cause_log_fatal"});
108 ASSERT_FALSE(result);
109
110 auto result2 = subcontext.Execute(std::vector<std::string>{"generate_sane_error"});
111 ASSERT_FALSE(result2);
112 EXPECT_EQ("Sane error!", result2.error_string());
113 EXPECT_NE(subcontext.pid(), first_pid);
114}
115
116TEST(subcontext, ContextString) {
117 auto subcontext = Subcontext("path", kVendorContext);
118 auto subcontext_killer = SubcontextKiller(subcontext);
119
120 auto result = subcontext.Execute(std::vector<std::string>{"return_context_as_error"});
121 ASSERT_FALSE(result);
122 ASSERT_EQ(kVendorContext, result.error_string());
123}
124
125TestFunctionMap BuildTestFunctionMap() {
126 TestFunctionMap test_function_map;
127 // For CheckDifferentPid
128 test_function_map.Add("return_pids_as_error", 0, 0, true,
129 [](const BuiltinArguments& args) -> Result<Success> {
130 return Error() << getpid() << " " << getppid();
131 });
132
133 // For SetProp
134 test_function_map.Add("setprop", 2, 2, true, [](const BuiltinArguments& args) {
135 android::base::SetProperty(args[1], args[2]);
136 return Success();
137 });
138
139 // For MultipleCommands
140 // Using a shared_ptr to extend lifetime of words to both lambdas
141 auto words = std::make_shared<std::vector<std::string>>();
142 test_function_map.Add("add_word", 1, 1, true, [words](const BuiltinArguments& args) {
143 words->emplace_back(args[1]);
144 return Success();
145 });
146 test_function_map.Add("return_words_as_error", 0, 0, true,
147 [words](const BuiltinArguments& args) -> Result<Success> {
148 return Error() << Join(*words, " ");
149 });
150
151 // For RecoverAfterAbort
152 test_function_map.Add("cause_log_fatal", 0, 0, true,
153 [](const BuiltinArguments& args) -> Result<Success> {
154 return Error() << std::string(4097, 'f');
155 });
156 test_function_map.Add(
157 "generate_sane_error", 0, 0, true,
158 [](const BuiltinArguments& args) -> Result<Success> { return Error() << "Sane error!"; });
159
160 // For ContextString
161 test_function_map.Add(
162 "return_context_as_error", 0, 0, true,
163 [](const BuiltinArguments& args) -> Result<Success> { return Error() << args.context; });
164
165 return test_function_map;
166}
167
168} // namespace init
169} // namespace android
170
171int main(int argc, char** argv) {
172 if (argc > 1 && !strcmp(basename(argv[1]), "subcontext")) {
173 auto test_function_map = android::init::BuildTestFunctionMap();
174 return android::init::SubcontextMain(argc, argv, &test_function_map);
175 }
176
177 testing::InitGoogleTest(&argc, argv);
178 return RUN_ALL_TESTS();
179}
diff --git a/init/test_function_map.h b/init/test_function_map.h
new file mode 100644
index 000000000..583df1af8
--- /dev/null
+++ b/init/test_function_map.h
@@ -0,0 +1,55 @@
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _INIT_TEST_FUNCTION_MAP_H
18#define _INIT_TEST_FUNCTION_MAP_H
19
20#include <string>
21#include <vector>
22
23#include "builtin_arguments.h"
24#include "keyword_map.h"
25
26namespace android {
27namespace init {
28
29class TestFunctionMap : public KeywordFunctionMap {
30 public:
31 // Helper for argument-less functions
32 using BuiltinFunctionNoArgs = std::function<void(void)>;
33 void Add(const std::string& name, const BuiltinFunctionNoArgs function) {
34 Add(name, 0, 0, false, [function](const BuiltinArguments&) {
35 function();
36 return Success();
37 });
38 }
39
40 void Add(const std::string& name, std::size_t min_parameters, std::size_t max_parameters,
41 bool run_in_subcontext, const BuiltinFunction function) {
42 builtin_functions_[name] =
43 make_tuple(min_parameters, max_parameters, make_pair(run_in_subcontext, function));
44 }
45
46 private:
47 Map builtin_functions_ = {};
48
49 const Map& map() const override { return builtin_functions_; }
50};
51
52} // namespace init
53} // namespace android
54
55#endif
diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp
index e889bdd91..2f2068407 100644
--- a/libbacktrace/Android.bp
+++ b/libbacktrace/Android.bp
@@ -83,7 +83,7 @@ cc_library {
83 darwin: { 83 darwin: {
84 enabled: true, 84 enabled: true,
85 }, 85 },
86 linux: { 86 linux_glibc: {
87 srcs: libbacktrace_sources, 87 srcs: libbacktrace_sources,
88 88
89 shared_libs: [ 89 shared_libs: [
@@ -94,7 +94,6 @@ cc_library {
94 ], 94 ],
95 95
96 static_libs: ["libcutils"], 96 static_libs: ["libcutils"],
97 host_ldlibs: ["-lrt"],
98 }, 97 },
99 linux_bionic: { 98 linux_bionic: {
100 enabled: true, 99 enabled: true,
@@ -136,7 +135,7 @@ cc_library_shared {
136 srcs: ["backtrace_testlib.cpp"], 135 srcs: ["backtrace_testlib.cpp"],
137 136
138 target: { 137 target: {
139 linux: { 138 linux_glibc: {
140 shared_libs: [ 139 shared_libs: [
141 "libunwind", 140 "libunwind",
142 "libunwindstack", 141 "libunwindstack",
@@ -229,15 +228,11 @@ cc_test {
229 android: { 228 android: {
230 cflags: ["-DENABLE_PSS_TESTS"], 229 cflags: ["-DENABLE_PSS_TESTS"],
231 shared_libs: [ 230 shared_libs: [
232 "libdl",
233 "libutils", 231 "libutils",
234 ], 232 ],
235 }, 233 },
236 linux: { 234 linux_glibc: {
237 host_ldlibs: [ 235 host_ldlibs: [
238 "-lpthread",
239 "-lrt",
240 "-ldl",
241 "-lncurses", 236 "-lncurses",
242 ], 237 ],
243 static_libs: ["libutils"], 238 static_libs: ["libutils"],
diff --git a/libbacktrace/UnwindStack.cpp b/libbacktrace/UnwindStack.cpp
index 3b2f38e08..41153ce19 100644
--- a/libbacktrace/UnwindStack.cpp
+++ b/libbacktrace/UnwindStack.cpp
@@ -22,6 +22,7 @@
22#include <ucontext.h> 22#include <ucontext.h>
23 23
24#include <memory> 24#include <memory>
25#include <set>
25#include <string> 26#include <string>
26 27
27#if !defined(__ANDROID__) 28#if !defined(__ANDROID__)
@@ -37,12 +38,13 @@
37#include <unwindstack/Regs.h> 38#include <unwindstack/Regs.h>
38#include <unwindstack/RegsGetLocal.h> 39#include <unwindstack/RegsGetLocal.h>
39 40
41#include <unwindstack/Unwinder.h>
42
40#include "BacktraceLog.h" 43#include "BacktraceLog.h"
41#include "UnwindStack.h" 44#include "UnwindStack.h"
42#include "UnwindStackMap.h" 45#include "UnwindStackMap.h"
43 46
44static std::string GetFunctionName(pid_t pid, BacktraceMap* back_map, uintptr_t pc, 47static std::string GetFunctionName(BacktraceMap* back_map, uintptr_t pc, uintptr_t* offset) {
45 uintptr_t* offset) {
46 *offset = 0; 48 *offset = 0;
47 unwindstack::Maps* maps = reinterpret_cast<UnwindStackMap*>(back_map)->stack_maps(); 49 unwindstack::Maps* maps = reinterpret_cast<UnwindStackMap*>(back_map)->stack_maps();
48 50
@@ -52,7 +54,8 @@ static std::string GetFunctionName(pid_t pid, BacktraceMap* back_map, uintptr_t
52 return ""; 54 return "";
53 } 55 }
54 56
55 unwindstack::Elf* elf = map_info->GetElf(pid, true); 57 UnwindStackMap* stack_map = reinterpret_cast<UnwindStackMap*>(back_map);
58 unwindstack::Elf* elf = map_info->GetElf(stack_map->process_memory(), true);
56 59
57 std::string name; 60 std::string name;
58 uint64_t func_offset; 61 uint64_t func_offset;
@@ -63,93 +66,52 @@ static std::string GetFunctionName(pid_t pid, BacktraceMap* back_map, uintptr_t
63 return name; 66 return name;
64} 67}
65 68
66static bool IsUnwindLibrary(const std::string& map_name) { 69static bool Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
67 const std::string library(basename(map_name.c_str())); 70 std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames) {
68 return library == "libunwindstack.so" || library == "libbacktrace.so"; 71 static std::set<std::string> skip_names{"libunwindstack.so", "libbacktrace.so"};
69} 72 UnwindStackMap* stack_map = reinterpret_cast<UnwindStackMap*>(back_map);
73 auto process_memory = stack_map->process_memory();
74 unwindstack::Unwinder unwinder(MAX_BACKTRACE_FRAMES + num_ignore_frames, stack_map->stack_maps(),
75 regs, stack_map->process_memory());
76 unwinder.Unwind(&skip_names);
77
78 if (num_ignore_frames >= unwinder.NumFrames()) {
79 frames->resize(0);
80 return true;
81 }
70 82
71static bool Unwind(pid_t pid, unwindstack::Memory* memory, unwindstack::Regs* regs, 83 frames->resize(unwinder.NumFrames() - num_ignore_frames);
72 BacktraceMap* back_map, std::vector<backtrace_frame_data_t>* frames, 84 auto unwinder_frames = unwinder.frames();
73 size_t num_ignore_frames) { 85 size_t cur_frame = 0;
74 unwindstack::Maps* maps = reinterpret_cast<UnwindStackMap*>(back_map)->stack_maps(); 86 for (size_t i = num_ignore_frames; i < unwinder.NumFrames(); i++, cur_frame++) {
75 bool adjust_rel_pc = false; 87 auto frame = &unwinder_frames[i];
76 size_t num_frames = 0; 88 backtrace_frame_data_t* back_frame = &frames->at(cur_frame);
77 frames->clear();
78 while (num_frames < MAX_BACKTRACE_FRAMES) {
79 if (regs->pc() == 0) {
80 break;
81 }
82 unwindstack::MapInfo* map_info = maps->Find(regs->pc());
83 if (map_info == nullptr) {
84 break;
85 }
86 89
87 unwindstack::Elf* elf = map_info->GetElf(pid, true); 90 back_frame->num = frame->num;
88 uint64_t rel_pc = elf->GetRelPc(regs->pc(), map_info);
89
90 bool skip_frame = num_frames == 0 && IsUnwindLibrary(map_info->name);
91 if (num_ignore_frames == 0 && !skip_frame) {
92 uint64_t adjusted_rel_pc = rel_pc;
93 if (adjust_rel_pc) {
94 adjusted_rel_pc = regs->GetAdjustedPc(rel_pc, elf);
95 }
96 frames->resize(num_frames + 1);
97 backtrace_frame_data_t* frame = &frames->at(num_frames);
98 frame->num = num_frames;
99 // This will point to the adjusted absolute pc. regs->pc() is
100 // unaltered.
101 frame->pc = map_info->start + adjusted_rel_pc;
102 frame->sp = regs->sp();
103 frame->rel_pc = adjusted_rel_pc;
104 frame->stack_size = 0;
105
106 frame->map.start = map_info->start;
107 frame->map.end = map_info->end;
108 frame->map.offset = map_info->offset;
109 frame->map.load_bias = elf->GetLoadBias();
110 frame->map.flags = map_info->flags;
111 frame->map.name = map_info->name;
112
113 uint64_t func_offset = 0;
114 if (elf->GetFunctionName(adjusted_rel_pc, &frame->func_name, &func_offset)) {
115 frame->func_name = demangle(frame->func_name.c_str());
116 } else {
117 frame->func_name = "";
118 }
119 frame->func_offset = func_offset;
120 if (num_frames > 0) {
121 // Set the stack size for the previous frame.
122 backtrace_frame_data_t* prev = &frames->at(num_frames - 1);
123 prev->stack_size = frame->sp - prev->sp;
124 }
125 num_frames++;
126 } else if (!skip_frame && num_ignore_frames > 0) {
127 num_ignore_frames--;
128 }
129 adjust_rel_pc = true;
130 91
131 // Do not unwind through a device map. 92 back_frame->rel_pc = frame->rel_pc;
132 if (map_info->flags & PROT_DEVICE_MAP) { 93 back_frame->pc = frame->pc;
133 break; 94 back_frame->sp = frame->sp;
134 }
135 unwindstack::MapInfo* sp_info = maps->Find(regs->sp());
136 if (sp_info->flags & PROT_DEVICE_MAP) {
137 break;
138 }
139 95
140 if (!elf->Step(rel_pc + map_info->elf_offset, regs, memory)) { 96 back_frame->func_name = frame->function_name;
141 break; 97 back_frame->func_offset = frame->function_offset;
142 } 98
99 back_frame->map.name = frame->map_name;
100 back_frame->map.start = frame->map_start;
101 back_frame->map.end = frame->map_end;
102 back_frame->map.offset = frame->map_offset;
103 back_frame->map.load_bias = frame->map_load_bias;
104 back_frame->map.flags = frame->map_flags;
143 } 105 }
144 106
145 return true; 107 return true;
146} 108}
147 109
148UnwindStackCurrent::UnwindStackCurrent(pid_t pid, pid_t tid, BacktraceMap* map) 110UnwindStackCurrent::UnwindStackCurrent(pid_t pid, pid_t tid, BacktraceMap* map)
149 : BacktraceCurrent(pid, tid, map), memory_(new unwindstack::MemoryLocal) {} 111 : BacktraceCurrent(pid, tid, map) {}
150 112
151std::string UnwindStackCurrent::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) { 113std::string UnwindStackCurrent::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) {
152 return ::GetFunctionName(Pid(), GetMap(), pc, offset); 114 return ::GetFunctionName(GetMap(), pc, offset);
153} 115}
154 116
155bool UnwindStackCurrent::UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucontext) { 117bool UnwindStackCurrent::UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucontext) {
@@ -165,14 +127,14 @@ bool UnwindStackCurrent::UnwindFromContext(size_t num_ignore_frames, ucontext_t*
165 } 127 }
166 128
167 error_ = BACKTRACE_UNWIND_NO_ERROR; 129 error_ = BACKTRACE_UNWIND_NO_ERROR;
168 return ::Unwind(getpid(), memory_.get(), regs.get(), GetMap(), &frames_, num_ignore_frames); 130 return ::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames);
169} 131}
170 132
171UnwindStackPtrace::UnwindStackPtrace(pid_t pid, pid_t tid, BacktraceMap* map) 133UnwindStackPtrace::UnwindStackPtrace(pid_t pid, pid_t tid, BacktraceMap* map)
172 : BacktracePtrace(pid, tid, map), memory_(new unwindstack::MemoryRemote(pid)) {} 134 : BacktracePtrace(pid, tid, map) {}
173 135
174std::string UnwindStackPtrace::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) { 136std::string UnwindStackPtrace::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) {
175 return ::GetFunctionName(Pid(), GetMap(), pc, offset); 137 return ::GetFunctionName(GetMap(), pc, offset);
176} 138}
177 139
178bool UnwindStackPtrace::Unwind(size_t num_ignore_frames, ucontext_t* context) { 140bool UnwindStackPtrace::Unwind(size_t num_ignore_frames, ucontext_t* context) {
@@ -185,7 +147,7 @@ bool UnwindStackPtrace::Unwind(size_t num_ignore_frames, ucontext_t* context) {
185 } 147 }
186 148
187 error_ = BACKTRACE_UNWIND_NO_ERROR; 149 error_ = BACKTRACE_UNWIND_NO_ERROR;
188 return ::Unwind(Pid(), memory_.get(), regs.get(), GetMap(), &frames_, num_ignore_frames); 150 return ::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames);
189} 151}
190 152
191Backtrace* Backtrace::CreateNew(pid_t pid, pid_t tid, BacktraceMap* map) { 153Backtrace* Backtrace::CreateNew(pid_t pid, pid_t tid, BacktraceMap* map) {
diff --git a/libbacktrace/UnwindStack.h b/libbacktrace/UnwindStack.h
index 32d1f51ab..be9ef6313 100644
--- a/libbacktrace/UnwindStack.h
+++ b/libbacktrace/UnwindStack.h
@@ -35,9 +35,6 @@ class UnwindStackCurrent : public BacktraceCurrent {
35 std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) override; 35 std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) override;
36 36
37 bool UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucontext) override; 37 bool UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucontext) override;
38
39 private:
40 std::unique_ptr<unwindstack::Memory> memory_;
41}; 38};
42 39
43class UnwindStackPtrace : public BacktracePtrace { 40class UnwindStackPtrace : public BacktracePtrace {
@@ -48,9 +45,6 @@ class UnwindStackPtrace : public BacktracePtrace {
48 bool Unwind(size_t num_ignore_frames, ucontext_t* context) override; 45 bool Unwind(size_t num_ignore_frames, ucontext_t* context) override;
49 46
50 std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset); 47 std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset);
51
52 private:
53 std::unique_ptr<unwindstack::Memory> memory_;
54}; 48};
55 49
56#endif // _LIBBACKTRACE_UNWIND_STACK_H 50#endif // _LIBBACKTRACE_UNWIND_STACK_H
diff --git a/libbacktrace/UnwindStackMap.cpp b/libbacktrace/UnwindStackMap.cpp
index ba9fd87d7..d4a2444dc 100644
--- a/libbacktrace/UnwindStackMap.cpp
+++ b/libbacktrace/UnwindStackMap.cpp
@@ -36,6 +36,9 @@ bool UnwindStackMap::Build() {
36 stack_maps_.reset(new unwindstack::RemoteMaps(pid_)); 36 stack_maps_.reset(new unwindstack::RemoteMaps(pid_));
37 } 37 }
38 38
39 // Create the process memory object.
40 process_memory_ = unwindstack::Memory::CreateProcessMemory(pid_);
41
39 if (!stack_maps_->Parse()) { 42 if (!stack_maps_->Parse()) {
40 return false; 43 return false;
41 } 44 }
@@ -68,7 +71,7 @@ void UnwindStackMap::FillIn(uintptr_t addr, backtrace_map_t* map) {
68 if (map_info == nullptr) { 71 if (map_info == nullptr) {
69 return; 72 return;
70 } 73 }
71 unwindstack::Elf* elf = map_info->GetElf(pid_, true); 74 unwindstack::Elf* elf = map_info->GetElf(process_memory_, true);
72 map->load_bias = elf->GetLoadBias(); 75 map->load_bias = elf->GetLoadBias();
73} 76}
74 77
diff --git a/libbacktrace/UnwindStackMap.h b/libbacktrace/UnwindStackMap.h
index 7885b7428..b93b3403c 100644
--- a/libbacktrace/UnwindStackMap.h
+++ b/libbacktrace/UnwindStackMap.h
@@ -20,6 +20,8 @@
20#include <stdint.h> 20#include <stdint.h>
21#include <sys/types.h> 21#include <sys/types.h>
22 22
23#include <memory>
24
23#include <backtrace/BacktraceMap.h> 25#include <backtrace/BacktraceMap.h>
24#include <unwindstack/Maps.h> 26#include <unwindstack/Maps.h>
25 27
@@ -34,8 +36,11 @@ class UnwindStackMap : public BacktraceMap {
34 36
35 unwindstack::Maps* stack_maps() { return stack_maps_.get(); } 37 unwindstack::Maps* stack_maps() { return stack_maps_.get(); }
36 38
39 const std::shared_ptr<unwindstack::Memory>& process_memory() { return process_memory_; }
40
37 protected: 41 protected:
38 std::unique_ptr<unwindstack::Maps> stack_maps_; 42 std::unique_ptr<unwindstack::Maps> stack_maps_;
43 std::shared_ptr<unwindstack::Memory> process_memory_;
39}; 44};
40 45
41#endif // _LIBBACKTRACE_UNWINDSTACK_MAP_H 46#endif // _LIBBACKTRACE_UNWINDSTACK_MAP_H
diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp
index 9fe2d1cb5..e5eb9e34e 100644
--- a/libbacktrace/backtrace_test.cpp
+++ b/libbacktrace/backtrace_test.cpp
@@ -82,6 +82,14 @@ struct dump_thread_t {
82 int32_t done; 82 int32_t done;
83}; 83};
84 84
85typedef Backtrace* (*create_func_t)(pid_t, pid_t, BacktraceMap*);
86typedef BacktraceMap* (*map_create_func_t)(pid_t, bool);
87
88static void VerifyLevelDump(Backtrace* backtrace, create_func_t create_func = nullptr,
89 map_create_func_t map_func = nullptr);
90static void VerifyMaxDump(Backtrace* backtrace, create_func_t create_func = nullptr,
91 map_create_func_t map_func = nullptr);
92
85static uint64_t NanoTime() { 93static uint64_t NanoTime() {
86 struct timespec t = { 0, 0 }; 94 struct timespec t = { 0, 0 };
87 clock_gettime(CLOCK_MONOTONIC, &t); 95 clock_gettime(CLOCK_MONOTONIC, &t);
@@ -147,7 +155,7 @@ static bool ReadyLevelBacktrace(Backtrace* backtrace) {
147 return found; 155 return found;
148} 156}
149 157
150static void VerifyLevelDump(Backtrace* backtrace) { 158static void VerifyLevelDump(Backtrace* backtrace, create_func_t, map_create_func_t) {
151 ASSERT_GT(backtrace->NumFrames(), static_cast<size_t>(0)) 159 ASSERT_GT(backtrace->NumFrames(), static_cast<size_t>(0))
152 << DumpFrames(backtrace); 160 << DumpFrames(backtrace);
153 ASSERT_LT(backtrace->NumFrames(), static_cast<size_t>(MAX_BACKTRACE_FRAMES)) 161 ASSERT_LT(backtrace->NumFrames(), static_cast<size_t>(MAX_BACKTRACE_FRAMES))
@@ -189,7 +197,7 @@ static bool ReadyMaxBacktrace(Backtrace* backtrace) {
189 return (backtrace->NumFrames() == MAX_BACKTRACE_FRAMES); 197 return (backtrace->NumFrames() == MAX_BACKTRACE_FRAMES);
190} 198}
191 199
192static void VerifyMaxDump(Backtrace* backtrace) { 200static void VerifyMaxDump(Backtrace* backtrace, create_func_t, map_create_func_t) {
193 ASSERT_EQ(backtrace->NumFrames(), static_cast<size_t>(MAX_BACKTRACE_FRAMES)) 201 ASSERT_EQ(backtrace->NumFrames(), static_cast<size_t>(MAX_BACKTRACE_FRAMES))
194 << DumpFrames(backtrace); 202 << DumpFrames(backtrace);
195 // Verify that the last frame is our recursive call. 203 // Verify that the last frame is our recursive call.
@@ -251,10 +259,14 @@ TEST(libbacktrace, local_trace) {
251 259
252static void VerifyIgnoreFrames(Backtrace* bt_all, Backtrace* bt_ign1, Backtrace* bt_ign2, 260static void VerifyIgnoreFrames(Backtrace* bt_all, Backtrace* bt_ign1, Backtrace* bt_ign2,
253 const char* cur_proc) { 261 const char* cur_proc) {
254 EXPECT_EQ(bt_all->NumFrames(), bt_ign1->NumFrames() + 1) 262 ASSERT_EQ(bt_all->NumFrames(), bt_ign1->NumFrames() + 1) << "All backtrace:\n"
255 << "All backtrace:\n" << DumpFrames(bt_all) << "Ignore 1 backtrace:\n" << DumpFrames(bt_ign1); 263 << DumpFrames(bt_all)
256 EXPECT_EQ(bt_all->NumFrames(), bt_ign2->NumFrames() + 2) 264 << "Ignore 1 backtrace:\n"
257 << "All backtrace:\n" << DumpFrames(bt_all) << "Ignore 2 backtrace:\n" << DumpFrames(bt_ign2); 265 << DumpFrames(bt_ign1);
266 ASSERT_EQ(bt_all->NumFrames(), bt_ign2->NumFrames() + 2) << "All backtrace:\n"
267 << DumpFrames(bt_all)
268 << "Ignore 2 backtrace:\n"
269 << DumpFrames(bt_ign2);
258 270
259 // Check all of the frames are the same > the current frame. 271 // Check all of the frames are the same > the current frame.
260 bool check = (cur_proc == nullptr); 272 bool check = (cur_proc == nullptr);
@@ -305,9 +317,8 @@ TEST(libbacktrace, local_max_trace) {
305} 317}
306 318
307static void VerifyProcTest(pid_t pid, pid_t tid, bool (*ReadyFunc)(Backtrace*), 319static void VerifyProcTest(pid_t pid, pid_t tid, bool (*ReadyFunc)(Backtrace*),
308 void (*VerifyFunc)(Backtrace*), 320 void (*VerifyFunc)(Backtrace*, create_func_t, map_create_func_t),
309 Backtrace* (*back_func)(pid_t, pid_t, BacktraceMap*), 321 create_func_t create_func, map_create_func_t map_create_func) {
310 BacktraceMap* (*map_func)(pid_t, bool)) {
311 pid_t ptrace_tid; 322 pid_t ptrace_tid;
312 if (tid < 0) { 323 if (tid < 0) {
313 ptrace_tid = pid; 324 ptrace_tid = pid;
@@ -324,13 +335,13 @@ static void VerifyProcTest(pid_t pid, pid_t tid, bool (*ReadyFunc)(Backtrace*),
324 WaitForStop(ptrace_tid); 335 WaitForStop(ptrace_tid);
325 336
326 std::unique_ptr<BacktraceMap> map; 337 std::unique_ptr<BacktraceMap> map;
327 map.reset(map_func(pid, false)); 338 map.reset(map_create_func(pid, false));
328 std::unique_ptr<Backtrace> backtrace(back_func(pid, tid, map.get())); 339 std::unique_ptr<Backtrace> backtrace(create_func(pid, tid, map.get()));
329 ASSERT_TRUE(backtrace.get() != nullptr); 340 ASSERT_TRUE(backtrace.get() != nullptr);
330 ASSERT_TRUE(backtrace->Unwind(0)); 341 ASSERT_TRUE(backtrace->Unwind(0));
331 ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, backtrace->GetError()); 342 ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, backtrace->GetError());
332 if (ReadyFunc(backtrace.get())) { 343 if (ReadyFunc(backtrace.get())) {
333 VerifyFunc(backtrace.get()); 344 VerifyFunc(backtrace.get(), create_func, map_create_func);
334 verified = true; 345 verified = true;
335 } else { 346 } else {
336 last_dump = DumpFrames(backtrace.get()); 347 last_dump = DumpFrames(backtrace.get());
@@ -399,13 +410,15 @@ TEST(libbacktrace, ptrace_max_trace_new) {
399 ASSERT_EQ(waitpid(pid, &status, 0), pid); 410 ASSERT_EQ(waitpid(pid, &status, 0), pid);
400} 411}
401 412
402static void VerifyProcessIgnoreFrames(Backtrace* bt_all) { 413static void VerifyProcessIgnoreFrames(Backtrace* bt_all, create_func_t create_func,
403 std::unique_ptr<Backtrace> ign1(Backtrace::Create(bt_all->Pid(), BACKTRACE_CURRENT_THREAD)); 414 map_create_func_t map_create_func) {
415 std::unique_ptr<BacktraceMap> map(map_create_func(bt_all->Pid(), false));
416 std::unique_ptr<Backtrace> ign1(create_func(bt_all->Pid(), BACKTRACE_CURRENT_THREAD, map.get()));
404 ASSERT_TRUE(ign1.get() != nullptr); 417 ASSERT_TRUE(ign1.get() != nullptr);
405 ASSERT_TRUE(ign1->Unwind(1)); 418 ASSERT_TRUE(ign1->Unwind(1));
406 ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, ign1->GetError()); 419 ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, ign1->GetError());
407 420
408 std::unique_ptr<Backtrace> ign2(Backtrace::Create(bt_all->Pid(), BACKTRACE_CURRENT_THREAD)); 421 std::unique_ptr<Backtrace> ign2(create_func(bt_all->Pid(), BACKTRACE_CURRENT_THREAD, map.get()));
409 ASSERT_TRUE(ign2.get() != nullptr); 422 ASSERT_TRUE(ign2.get() != nullptr);
410 ASSERT_TRUE(ign2->Unwind(2)); 423 ASSERT_TRUE(ign2->Unwind(2));
411 ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, ign2->GetError()); 424 ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, ign2->GetError());
@@ -1702,9 +1715,8 @@ static void SetValueAndLoop(void* data) {
1702 ; 1715 ;
1703} 1716}
1704 1717
1705static void UnwindThroughSignal(bool use_action, 1718static void UnwindThroughSignal(bool use_action, create_func_t create_func,
1706 Backtrace* (*back_func)(pid_t, pid_t, BacktraceMap*), 1719 map_create_func_t map_create_func) {
1707 BacktraceMap* (*map_func)(pid_t, bool)) {
1708 volatile int value = 0; 1720 volatile int value = 0;
1709 pid_t pid; 1721 pid_t pid;
1710 if ((pid = fork()) == 0) { 1722 if ((pid = fork()) == 0) {
@@ -1730,8 +1742,8 @@ static void UnwindThroughSignal(bool use_action,
1730 1742
1731 WaitForStop(pid); 1743 WaitForStop(pid);
1732 1744
1733 std::unique_ptr<BacktraceMap> map(map_func(pid, false)); 1745 std::unique_ptr<BacktraceMap> map(map_create_func(pid, false));
1734 std::unique_ptr<Backtrace> backtrace(back_func(pid, pid, map.get())); 1746 std::unique_ptr<Backtrace> backtrace(create_func(pid, pid, map.get()));
1735 1747
1736 size_t bytes_read = backtrace->Read(reinterpret_cast<uintptr_t>(const_cast<int*>(&value)), 1748 size_t bytes_read = backtrace->Read(reinterpret_cast<uintptr_t>(const_cast<int*>(&value)),
1737 reinterpret_cast<uint8_t*>(&read_value), sizeof(read_value)); 1749 reinterpret_cast<uint8_t*>(&read_value), sizeof(read_value));
@@ -1758,9 +1770,9 @@ static void UnwindThroughSignal(bool use_action,
1758 1770
1759 WaitForStop(pid); 1771 WaitForStop(pid);
1760 1772
1761 map.reset(map_func(pid, false)); 1773 map.reset(map_create_func(pid, false));
1762 ASSERT_TRUE(map.get() != nullptr); 1774 ASSERT_TRUE(map.get() != nullptr);
1763 backtrace.reset(back_func(pid, pid, map.get())); 1775 backtrace.reset(create_func(pid, pid, map.get()));
1764 ASSERT_TRUE(backtrace->Unwind(0)); 1776 ASSERT_TRUE(backtrace->Unwind(0));
1765 bool found = false; 1777 bool found = false;
1766 for (frame_iter = backtrace->begin(); frame_iter != backtrace->end(); ++frame_iter) { 1778 for (frame_iter = backtrace->begin(); frame_iter != backtrace->end(); ++frame_iter) {
diff --git a/libbacktrace/include/backtrace/Backtrace.h b/libbacktrace/include/backtrace/Backtrace.h
index d67ea50c9..289fd0cef 100644
--- a/libbacktrace/include/backtrace/Backtrace.h
+++ b/libbacktrace/include/backtrace/Backtrace.h
@@ -127,7 +127,7 @@ public:
127 // Create a string representing the formatted line of backtrace information 127 // Create a string representing the formatted line of backtrace information
128 // for a single frame. 128 // for a single frame.
129 virtual std::string FormatFrameData(size_t frame_num); 129 virtual std::string FormatFrameData(size_t frame_num);
130 virtual std::string FormatFrameData(const backtrace_frame_data_t* frame); 130 static std::string FormatFrameData(const backtrace_frame_data_t* frame);
131 131
132 pid_t Pid() const { return pid_; } 132 pid_t Pid() const { return pid_; }
133 pid_t Tid() const { return tid_; } 133 pid_t Tid() const { return tid_; }
diff --git a/libbacktrace/include/backtrace/BacktraceMap.h b/libbacktrace/include/backtrace/BacktraceMap.h
index 963c34b64..6cf8b3fca 100644
--- a/libbacktrace/include/backtrace/BacktraceMap.h
+++ b/libbacktrace/include/backtrace/BacktraceMap.h
@@ -91,6 +91,8 @@ public:
91 const_iterator begin() const { return maps_.begin(); } 91 const_iterator begin() const { return maps_.begin(); }
92 const_iterator end() const { return maps_.end(); } 92 const_iterator end() const { return maps_.end(); }
93 93
94 size_t size() const { return maps_.size(); }
95
94 virtual bool Build(); 96 virtual bool Build();
95 97
96 static inline bool IsValid(const backtrace_map_t& map) { 98 static inline bool IsValid(const backtrace_map_t& map) {
diff --git a/libcrypto_utils/Android.bp b/libcrypto_utils/Android.bp
index 4a5f2a7ac..47de12ab0 100644
--- a/libcrypto_utils/Android.bp
+++ b/libcrypto_utils/Android.bp
@@ -17,6 +17,9 @@
17cc_library { 17cc_library {
18 name: "libcrypto_utils", 18 name: "libcrypto_utils",
19 vendor_available: true, 19 vendor_available: true,
20 vndk: {
21 enabled: true,
22 },
20 host_supported: true, 23 host_supported: true,
21 srcs: [ 24 srcs: [
22 "android_pubkey.c", 25 "android_pubkey.c",
diff --git a/libcutils/ashmem-dev.c b/libcutils/ashmem-dev.c
index b4abb79d8..95f2259ec 100644
--- a/libcutils/ashmem-dev.c
+++ b/libcutils/ashmem-dev.c
@@ -51,7 +51,7 @@ static int __ashmem_open_locked()
51 int ret; 51 int ret;
52 struct stat st; 52 struct stat st;
53 53
54 int fd = TEMP_FAILURE_RETRY(open(ASHMEM_DEVICE, O_RDWR)); 54 int fd = TEMP_FAILURE_RETRY(open(ASHMEM_DEVICE, O_RDWR | O_CLOEXEC));
55 if (fd < 0) { 55 if (fd < 0) {
56 return fd; 56 return fd;
57 } 57 }
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index bbaf5f435..d54eeaeb8 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -79,7 +79,6 @@ static const struct fs_path_config android_dirs[] = {
79 { 00775, AID_ROOT, AID_ROOT, 0, "data/preloads" }, 79 { 00775, AID_ROOT, AID_ROOT, 0, "data/preloads" },
80 { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data" }, 80 { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data" },
81 { 00755, AID_ROOT, AID_SYSTEM, 0, "mnt" }, 81 { 00755, AID_ROOT, AID_SYSTEM, 0, "mnt" },
82 { 00755, AID_ROOT, AID_ROOT, 0, "root" },
83 { 00750, AID_ROOT, AID_SHELL, 0, "sbin" }, 82 { 00750, AID_ROOT, AID_SHELL, 0, "sbin" },
84 { 00777, AID_ROOT, AID_ROOT, 0, "sdcard" }, 83 { 00777, AID_ROOT, AID_ROOT, 0, "sdcard" },
85 { 00751, AID_ROOT, AID_SDCARD_R, 0, "storage" }, 84 { 00751, AID_ROOT, AID_SDCARD_R, 0, "storage" },
@@ -174,6 +173,8 @@ static const struct fs_path_config android_files[] = {
174 CAP_MASK_LONG(CAP_AUDIT_CONTROL) | 173 CAP_MASK_LONG(CAP_AUDIT_CONTROL) |
175 CAP_MASK_LONG(CAP_SETGID), 174 CAP_MASK_LONG(CAP_SETGID),
176 "system/bin/logd" }, 175 "system/bin/logd" },
176 { 00550, AID_SYSTEM, AID_LOG, CAP_MASK_LONG(CAP_SYSLOG),
177 "system/bin/bootstat" },
177 { 00750, AID_ROOT, AID_SHELL, CAP_MASK_LONG(CAP_SETUID) | 178 { 00750, AID_ROOT, AID_SHELL, CAP_MASK_LONG(CAP_SETUID) |
178 CAP_MASK_LONG(CAP_SETGID), 179 CAP_MASK_LONG(CAP_SETGID),
179 "system/bin/run-as" }, 180 "system/bin/run-as" },
diff --git a/libdiskconfig/Android.bp b/libdiskconfig/Android.bp
index 088981a7c..b92f0863d 100644
--- a/libdiskconfig/Android.bp
+++ b/libdiskconfig/Android.bp
@@ -1,6 +1,9 @@
1cc_library { 1cc_library {
2 name: "libdiskconfig", 2 name: "libdiskconfig",
3 vendor_available: true, 3 vendor_available: true,
4 vndk: {
5 enabled: true,
6 },
4 srcs: [ 7 srcs: [
5 "diskconfig.c", 8 "diskconfig.c",
6 "diskutils.c", 9 "diskutils.c",
@@ -20,7 +23,7 @@ cc_library {
20 darwin: { 23 darwin: {
21 enabled: false, 24 enabled: false,
22 }, 25 },
23 linux: { 26 linux_glibc: {
24 cflags: [ 27 cflags: [
25 "-O2", 28 "-O2",
26 "-g", 29 "-g",
diff --git a/libgrallocusage/Android.bp b/libgrallocusage/Android.bp
index 54bfee5c4..cf03868d2 100644
--- a/libgrallocusage/Android.bp
+++ b/libgrallocusage/Android.bp
@@ -14,6 +14,7 @@
14 14
15cc_library_static { 15cc_library_static {
16 name: "libgrallocusage", 16 name: "libgrallocusage",
17 vendor_available: true,
17 cppflags: [ 18 cppflags: [
18 "-Weverything", 19 "-Weverything",
19 "-Werror", 20 "-Werror",
@@ -26,4 +27,5 @@ cc_library_static {
26 srcs: ["GrallocUsageConversion.cpp"], 27 srcs: ["GrallocUsageConversion.cpp"],
27 export_include_dirs: ["include"], 28 export_include_dirs: ["include"],
28 shared_libs: ["android.hardware.graphics.allocator@2.0"], 29 shared_libs: ["android.hardware.graphics.allocator@2.0"],
30 header_libs: ["libhardware_headers"],
29} 31}
diff --git a/libion/include/ion/ion.h b/libion/include/ion/ion.h
index f47793d27..a60d24eaf 100644
--- a/libion/include/ion/ion.h
+++ b/libion/include/ion/ion.h
@@ -41,6 +41,15 @@ int ion_map(int fd, ion_user_handle_t handle, size_t length, int prot,
41int ion_share(int fd, ion_user_handle_t handle, int *share_fd); 41int ion_share(int fd, ion_user_handle_t handle, int *share_fd);
42int ion_import(int fd, int share_fd, ion_user_handle_t *handle); 42int ion_import(int fd, int share_fd, ion_user_handle_t *handle);
43 43
44/**
45 * Add 4.12+ kernel ION interfaces here for forward compatibility
46 * This should be needed till the pre-4.12+ ION interfaces are backported.
47 */
48int ion_query_heap_cnt(int fd, int* cnt);
49int ion_query_get_heaps(int fd, int cnt, void* buffers);
50
51int ion_is_legacy(int fd);
52
44__END_DECLS 53__END_DECLS
45 54
46#endif /* __SYS_CORE_ION_H */ 55#endif /* __SYS_CORE_ION_H */
diff --git a/libion/ion.c b/libion/ion.c
index 9aaa6f28e..583612854 100644
--- a/libion/ion.c
+++ b/libion/ion.c
@@ -22,6 +22,7 @@
22#include <errno.h> 22#include <errno.h>
23#include <fcntl.h> 23#include <fcntl.h>
24#include <linux/ion.h> 24#include <linux/ion.h>
25#include <stdatomic.h>
25#include <stdio.h> 26#include <stdio.h>
26#include <string.h> 27#include <string.h>
27#include <sys/ioctl.h> 28#include <sys/ioctl.h>
@@ -30,81 +31,89 @@
30#include <unistd.h> 31#include <unistd.h>
31 32
32#include <ion/ion.h> 33#include <ion/ion.h>
34#include "ion_4.12.h"
35
33#include <log/log.h> 36#include <log/log.h>
34 37
35int ion_open() 38enum ion_version { ION_VERSION_UNKNOWN, ION_VERSION_MODERN, ION_VERSION_LEGACY };
36{ 39
40static atomic_int g_ion_version = ATOMIC_VAR_INIT(ION_VERSION_UNKNOWN);
41
42int ion_is_legacy(int fd) {
43 int version = atomic_load_explicit(&g_ion_version, memory_order_acquire);
44 if (version == ION_VERSION_UNKNOWN) {
45 /**
46 * Check for FREE IOCTL here; it is available only in the old
47 * kernels, not the new ones.
48 */
49 int err = ion_free(fd, (ion_user_handle_t)NULL);
50 version = (err == -ENOTTY) ? ION_VERSION_MODERN : ION_VERSION_LEGACY;
51 atomic_store_explicit(&g_ion_version, version, memory_order_release);
52 }
53 return version == ION_VERSION_LEGACY;
54}
55
56int ion_open() {
37 int fd = open("/dev/ion", O_RDONLY | O_CLOEXEC); 57 int fd = open("/dev/ion", O_RDONLY | O_CLOEXEC);
38 if (fd < 0) 58 if (fd < 0) ALOGE("open /dev/ion failed!\n");
39 ALOGE("open /dev/ion failed!\n"); 59
40 return fd; 60 return fd;
41} 61}
42 62
43int ion_close(int fd) 63int ion_close(int fd) {
44{
45 int ret = close(fd); 64 int ret = close(fd);
46 if (ret < 0) 65 if (ret < 0) return -errno;
47 return -errno;
48 return ret; 66 return ret;
49} 67}
50 68
51static int ion_ioctl(int fd, int req, void *arg) 69static int ion_ioctl(int fd, int req, void* arg) {
52{
53 int ret = ioctl(fd, req, arg); 70 int ret = ioctl(fd, req, arg);
54 if (ret < 0) { 71 if (ret < 0) {
55 ALOGE("ioctl %x failed with code %d: %s\n", req, 72 ALOGE("ioctl %x failed with code %d: %s\n", req, ret, strerror(errno));
56 ret, strerror(errno));
57 return -errno; 73 return -errno;
58 } 74 }
59 return ret; 75 return ret;
60} 76}
61 77
62int ion_alloc(int fd, size_t len, size_t align, unsigned int heap_mask, 78int ion_alloc(int fd, size_t len, size_t align, unsigned int heap_mask, unsigned int flags,
63 unsigned int flags, ion_user_handle_t *handle) 79 ion_user_handle_t* handle) {
64{ 80 int ret = 0;
65 int ret; 81
82 if ((handle == NULL) || (!ion_is_legacy(fd))) return -EINVAL;
83
66 struct ion_allocation_data data = { 84 struct ion_allocation_data data = {
67 .len = len, 85 .len = len, .align = align, .heap_id_mask = heap_mask, .flags = flags,
68 .align = align,
69 .heap_id_mask = heap_mask,
70 .flags = flags,
71 }; 86 };
72 87
73 if (handle == NULL)
74 return -EINVAL;
75
76 ret = ion_ioctl(fd, ION_IOC_ALLOC, &data); 88 ret = ion_ioctl(fd, ION_IOC_ALLOC, &data);
77 if (ret < 0) 89 if (ret < 0) return ret;
78 return ret; 90
79 *handle = data.handle; 91 *handle = data.handle;
92
80 return ret; 93 return ret;
81} 94}
82 95
83int ion_free(int fd, ion_user_handle_t handle) 96int ion_free(int fd, ion_user_handle_t handle) {
84{
85 struct ion_handle_data data = { 97 struct ion_handle_data data = {
86 .handle = handle, 98 .handle = handle,
87 }; 99 };
88 return ion_ioctl(fd, ION_IOC_FREE, &data); 100 return ion_ioctl(fd, ION_IOC_FREE, &data);
89} 101}
90 102
91int ion_map(int fd, ion_user_handle_t handle, size_t length, int prot, 103int ion_map(int fd, ion_user_handle_t handle, size_t length, int prot, int flags, off_t offset,
92 int flags, off_t offset, unsigned char **ptr, int *map_fd) 104 unsigned char** ptr, int* map_fd) {
93{ 105 if (!ion_is_legacy(fd)) return -EINVAL;
94 int ret; 106 int ret;
95 unsigned char *tmp_ptr; 107 unsigned char* tmp_ptr;
96 struct ion_fd_data data = { 108 struct ion_fd_data data = {
97 .handle = handle, 109 .handle = handle,
98 }; 110 };
99 111
100 if (map_fd == NULL) 112 if (map_fd == NULL) return -EINVAL;
101 return -EINVAL; 113 if (ptr == NULL) return -EINVAL;
102 if (ptr == NULL)
103 return -EINVAL;
104 114
105 ret = ion_ioctl(fd, ION_IOC_MAP, &data); 115 ret = ion_ioctl(fd, ION_IOC_MAP, &data);
106 if (ret < 0) 116 if (ret < 0) return ret;
107 return ret;
108 if (data.fd < 0) { 117 if (data.fd < 0) {
109 ALOGE("map ioctl returned negative fd\n"); 118 ALOGE("map ioctl returned negative fd\n");
110 return -EINVAL; 119 return -EINVAL;
@@ -119,19 +128,17 @@ int ion_map(int fd, ion_user_handle_t handle, size_t length, int prot,
119 return ret; 128 return ret;
120} 129}
121 130
122int ion_share(int fd, ion_user_handle_t handle, int *share_fd) 131int ion_share(int fd, ion_user_handle_t handle, int* share_fd) {
123{
124 int ret; 132 int ret;
125 struct ion_fd_data data = { 133 struct ion_fd_data data = {
126 .handle = handle, 134 .handle = handle,
127 }; 135 };
128 136
129 if (share_fd == NULL) 137 if (!ion_is_legacy(fd)) return -EINVAL;
130 return -EINVAL; 138 if (share_fd == NULL) return -EINVAL;
131 139
132 ret = ion_ioctl(fd, ION_IOC_SHARE, &data); 140 ret = ion_ioctl(fd, ION_IOC_SHARE, &data);
133 if (ret < 0) 141 if (ret < 0) return ret;
134 return ret;
135 if (data.fd < 0) { 142 if (data.fd < 0) {
136 ALOGE("share ioctl returned negative fd\n"); 143 ALOGE("share ioctl returned negative fd\n");
137 return -EINVAL; 144 return -EINVAL;
@@ -140,40 +147,75 @@ int ion_share(int fd, ion_user_handle_t handle, int *share_fd)
140 return ret; 147 return ret;
141} 148}
142 149
143int ion_alloc_fd(int fd, size_t len, size_t align, unsigned int heap_mask, 150int ion_alloc_fd(int fd, size_t len, size_t align, unsigned int heap_mask, unsigned int flags,
144 unsigned int flags, int *handle_fd) { 151 int* handle_fd) {
145 ion_user_handle_t handle; 152 ion_user_handle_t handle;
146 int ret; 153 int ret;
147 154
148 ret = ion_alloc(fd, len, align, heap_mask, flags, &handle); 155 if (!ion_is_legacy(fd)) {
149 if (ret < 0) 156 struct ion_new_allocation_data data = {
150 return ret; 157 .len = len,
151 ret = ion_share(fd, handle, handle_fd); 158 .heap_id_mask = heap_mask,
152 ion_free(fd, handle); 159 .flags = flags,
160 };
161
162 ret = ion_ioctl(fd, ION_IOC_NEW_ALLOC, &data);
163 if (ret < 0) return ret;
164 *handle_fd = data.fd;
165 } else {
166 ret = ion_alloc(fd, len, align, heap_mask, flags, &handle);
167 if (ret < 0) return ret;
168 ret = ion_share(fd, handle, handle_fd);
169 ion_free(fd, handle);
170 }
153 return ret; 171 return ret;
154} 172}
155 173
156int ion_import(int fd, int share_fd, ion_user_handle_t *handle) 174int ion_import(int fd, int share_fd, ion_user_handle_t* handle) {
157{
158 int ret; 175 int ret;
159 struct ion_fd_data data = { 176 struct ion_fd_data data = {
160 .fd = share_fd, 177 .fd = share_fd,
161 }; 178 };
162 179
163 if (handle == NULL) 180 if (!ion_is_legacy(fd)) return -EINVAL;
164 return -EINVAL; 181
182 if (handle == NULL) return -EINVAL;
165 183
166 ret = ion_ioctl(fd, ION_IOC_IMPORT, &data); 184 ret = ion_ioctl(fd, ION_IOC_IMPORT, &data);
167 if (ret < 0) 185 if (ret < 0) return ret;
168 return ret;
169 *handle = data.handle; 186 *handle = data.handle;
170 return ret; 187 return ret;
171} 188}
172 189
173int ion_sync_fd(int fd, int handle_fd) 190int ion_sync_fd(int fd, int handle_fd) {
174{
175 struct ion_fd_data data = { 191 struct ion_fd_data data = {
176 .fd = handle_fd, 192 .fd = handle_fd,
177 }; 193 };
194
195 if (!ion_is_legacy(fd)) return -EINVAL;
196
178 return ion_ioctl(fd, ION_IOC_SYNC, &data); 197 return ion_ioctl(fd, ION_IOC_SYNC, &data);
179} 198}
199
200int ion_query_heap_cnt(int fd, int* cnt) {
201 int ret;
202 struct ion_heap_query query;
203
204 memset(&query, 0, sizeof(query));
205
206 ret = ion_ioctl(fd, ION_IOC_HEAP_QUERY, &query);
207 if (ret < 0) return ret;
208
209 *cnt = query.cnt;
210 return ret;
211}
212
213int ion_query_get_heaps(int fd, int cnt, void* buffers) {
214 int ret;
215 struct ion_heap_query query = {
216 .cnt = cnt, .heaps = (uintptr_t)buffers,
217 };
218
219 ret = ion_ioctl(fd, ION_IOC_HEAP_QUERY, &query);
220 return ret;
221}
diff --git a/libion/ion_4.12.h b/libion/ion_4.12.h
new file mode 100644
index 000000000..6ae79d4e8
--- /dev/null
+++ b/libion/ion_4.12.h
@@ -0,0 +1,125 @@
1/*
2 * Adapted from drivers/staging/android/uapi/ion.h
3 *
4 * Copyright (C) 2011 Google, Inc.
5 *
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#ifndef _UAPI_LINUX_ION_NEW_H
18#define _UAPI_LINUX_ION_NEW_H
19
20#include <linux/ioctl.h>
21#include <linux/types.h>
22
23#define ION_NUM_HEAP_IDS (sizeof(unsigned int) * 8)
24
25/**
26 * DOC: Ion Userspace API
27 *
28 * create a client by opening /dev/ion
29 * most operations handled via following ioctls
30 *
31 */
32
33/**
34 * struct ion_new_allocation_data - metadata passed from userspace for allocations
35 * @len: size of the allocation
36 * @heap_id_mask: mask of heap ids to allocate from
37 * @flags: flags passed to heap
38 * @handle: pointer that will be populated with a cookie to use to
39 * refer to this allocation
40 *
41 * Provided by userspace as an argument to the ioctl - added _new to denote
42 * this belongs to the new ION interface.
43 */
44struct ion_new_allocation_data {
45 __u64 len;
46 __u32 heap_id_mask;
47 __u32 flags;
48 __u32 fd;
49 __u32 unused;
50};
51
52#define MAX_HEAP_NAME 32
53
54/**
55 * struct ion_heap_data - data about a heap
56 * @name - first 32 characters of the heap name
57 * @type - heap type
58 * @heap_id - heap id for the heap
59 */
60struct ion_heap_data {
61 char name[MAX_HEAP_NAME];
62 __u32 type;
63 __u32 heap_id;
64 __u32 reserved0;
65 __u32 reserved1;
66 __u32 reserved2;
67};
68
69/**
70 * struct ion_heap_query - collection of data about all heaps
71 * @cnt - total number of heaps to be copied
72 * @heaps - buffer to copy heap data
73 */
74struct ion_heap_query {
75 __u32 cnt; /* Total number of heaps to be copied */
76 __u32 reserved0; /* align to 64bits */
77 __u64 heaps; /* buffer to be populated */
78 __u32 reserved1;
79 __u32 reserved2;
80};
81
82#define ION_IOC_MAGIC 'I'
83
84/**
85 * DOC: ION_IOC_NEW_ALLOC - allocate memory
86 *
87 * Takes an ion_allocation_data struct and returns it with the handle field
88 * populated with the opaque handle for the allocation.
89 * TODO: This IOCTL will clash by design; however, only one of
90 * ION_IOC_ALLOC or ION_IOC_NEW_ALLOC paths will be exercised,
91 * so this should not conflict.
92 */
93#define ION_IOC_NEW_ALLOC _IOWR(ION_IOC_MAGIC, 0, struct ion_new_allocation_data)
94
95/**
96 * DOC: ION_IOC_FREE - free memory
97 *
98 * Takes an ion_handle_data struct and frees the handle.
99 *
100 * #define ION_IOC_FREE _IOWR(ION_IOC_MAGIC, 1, struct ion_handle_data)
101 * This will come from the older kernels, so don't redefine here
102 */
103
104/**
105 * DOC: ION_IOC_SHARE - creates a file descriptor to use to share an allocation
106 *
107 * Takes an ion_fd_data struct with the handle field populated with a valid
108 * opaque handle. Returns the struct with the fd field set to a file
109 * descriptor open in the current address space. This file descriptor
110 * can then be passed to another process. The corresponding opaque handle can
111 * be retrieved via ION_IOC_IMPORT.
112 *
113 * #define ION_IOC_SHARE _IOWR(ION_IOC_MAGIC, 4, struct ion_fd_data)
114 * This will come from the older kernels, so don't redefine here
115 */
116
117/**
118 * DOC: ION_IOC_HEAP_QUERY - information about available heaps
119 *
120 * Takes an ion_heap_query structure and populates information about
121 * available Ion heaps.
122 */
123#define ION_IOC_HEAP_QUERY _IOWR(ION_IOC_MAGIC, 8, struct ion_heap_query)
124
125#endif /* _UAPI_LINUX_ION_NEW_H */
diff --git a/liblog/Android.bp b/liblog/Android.bp
index e74aa8283..d5bb29ed0 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -42,6 +42,24 @@ liblog_target_sources = [
42 "logd_writer.c", 42 "logd_writer.c",
43] 43]
44 44
45cc_library_headers {
46 name: "liblog_headers",
47 host_supported: true,
48 vendor_available: true,
49 export_include_dirs: ["include"],
50 target: {
51 windows: {
52 enabled: true,
53 },
54 linux_bionic: {
55 enabled: true,
56 },
57 vendor: {
58 export_include_dirs: ["include_vndk"],
59 },
60 },
61}
62
45// Shared and static library for host and device 63// Shared and static library for host and device
46// ======================================================== 64// ========================================================
47cc_library { 65cc_library {
@@ -73,15 +91,13 @@ cc_library {
73 not_windows: { 91 not_windows: {
74 srcs: ["event_tag_map.cpp"], 92 srcs: ["event_tag_map.cpp"],
75 }, 93 },
76 linux: {
77 host_ldlibs: ["-lrt"],
78 },
79 linux_bionic: { 94 linux_bionic: {
80 enabled: true, 95 enabled: true,
81 }, 96 },
82 }, 97 },
83 98
84 export_include_dirs: ["include"], 99 header_libs: ["liblog_headers"],
100 export_header_lib_headers: ["liblog_headers"],
85 101
86 cflags: [ 102 cflags: [
87 "-Werror", 103 "-Werror",
@@ -100,7 +116,7 @@ cc_library {
100} 116}
101 117
102ndk_headers { 118ndk_headers {
103 name: "liblog_headers", 119 name: "liblog_ndk_headers",
104 from: "include/android", 120 from: "include/android",
105 to: "android", 121 to: "android",
106 srcs: ["include/android/log.h"], 122 srcs: ["include/android/log.h"],
diff --git a/liblog/include/log/log_main.h b/liblog/include/log/log_main.h
index 5a3f04ca8..339a06d86 100644
--- a/liblog/include/log/log_main.h
+++ b/liblog/include/log/log_main.h
@@ -18,10 +18,9 @@
18#define _LIBS_LOG_LOG_MAIN_H 18#define _LIBS_LOG_LOG_MAIN_H
19 19
20#include <android/log.h> 20#include <android/log.h>
21#include <sys/cdefs.h>
21 22
22#ifdef __cplusplus 23__BEGIN_DECLS
23extern "C" {
24#endif
25 24
26/* 25/*
27 * Normally we strip the effects of ALOGV (VERBOSE messages), 26 * Normally we strip the effects of ALOGV (VERBOSE messages),
@@ -385,8 +384,6 @@ int __android_log_is_loggable_len(int prio, const char* tag, size_t len,
385#pragma clang diagnostic pop 384#pragma clang diagnostic pop
386#endif 385#endif
387 386
388#ifdef __cplusplus 387__END_DECLS
389}
390#endif
391 388
392#endif /* _LIBS_LOG_LOG_MAIN_H */ 389#endif /* _LIBS_LOG_LOG_MAIN_H */
diff --git a/liblog/include/log/log_safetynet.h b/liblog/include/log/log_safetynet.h
index b8ca475ce..07e8c8ab1 100644
--- a/liblog/include/log/log_safetynet.h
+++ b/liblog/include/log/log_safetynet.h
@@ -10,6 +10,8 @@
10#ifndef _LIBS_LOG_SAFETYNET_H 10#ifndef _LIBS_LOG_SAFETYNET_H
11#define _LIBS_LOG_SAFETYNET_H 11#define _LIBS_LOG_SAFETYNET_H
12 12
13#include <stdint.h>
14
13#ifdef __cplusplus 15#ifdef __cplusplus
14extern "C" { 16extern "C" {
15#endif 17#endif
diff --git a/liblog/include/log/log_time.h b/liblog/include/log/log_time.h
index 3764faf75..309f5d12f 100644
--- a/liblog/include/log/log_time.h
+++ b/liblog/include/log/log_time.h
@@ -28,6 +28,10 @@
28#ifndef __struct_log_time_defined 28#ifndef __struct_log_time_defined
29#define __struct_log_time_defined 29#define __struct_log_time_defined
30 30
31#define LOG_TIME_SEC(t) ((t)->tv_sec)
32/* next power of two after NS_PER_SEC */
33#define LOG_TIME_NSEC(t) ((t)->tv_nsec & (UINT32_MAX >> 2))
34
31#ifdef __cplusplus 35#ifdef __cplusplus
32 36
33/* 37/*
@@ -167,15 +171,15 @@ struct log_time {
167#endif 171#endif
168} __attribute__((__packed__)); 172} __attribute__((__packed__));
169 173
170#else 174#else /* __cplusplus */
171 175
172typedef struct log_time { 176typedef struct log_time {
173 uint32_t tv_sec; 177 uint32_t tv_sec;
174 uint32_t tv_nsec; 178 uint32_t tv_nsec;
175} __attribute__((__packed__)) log_time; 179} __attribute__((__packed__)) log_time;
176 180
177#endif 181#endif /* __cplusplus */
178 182
179#endif 183#endif /* __struct_log_time_defined */
180 184
181#endif /* _LIBS_LOG_LOG_TIME_H */ 185#endif /* _LIBS_LOG_LOG_TIME_H */
diff --git a/liblog/include_vndk/log/log_time.h b/liblog/include_vndk/log/log_time.h
index abfe439ae..5a09959a7 120000..100644
--- a/liblog/include_vndk/log/log_time.h
+++ b/liblog/include_vndk/log/log_time.h
@@ -1 +1,47 @@
1../../include/log/log_time.h \ No newline at end of file 1/*
2 * Copyright (C) 2005-2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _LIBS_LOG_LOG_TIME_H
18#define _LIBS_LOG_LOG_TIME_H
19
20#include <stdint.h>
21
22/* struct log_time is a wire-format variant of struct timespec */
23#ifndef NS_PER_SEC
24#define NS_PER_SEC 1000000000ULL
25#endif
26#ifndef US_PER_SEC
27#define US_PER_SEC 1000000ULL
28#endif
29#ifndef MS_PER_SEC
30#define MS_PER_SEC 1000ULL
31#endif
32
33#ifndef __struct_log_time_defined
34#define __struct_log_time_defined
35
36#define LOG_TIME_SEC(t) ((t)->tv_sec)
37/* next power of two after NS_PER_SEC */
38#define LOG_TIME_NSEC(t) ((t)->tv_nsec & (UINT32_MAX >> 2))
39
40typedef struct log_time {
41 uint32_t tv_sec;
42 uint32_t tv_nsec;
43} __attribute__((__packed__)) log_time;
44
45#endif
46
47#endif /* _LIBS_LOG_LOG_TIME_H */
diff --git a/liblog/local_logger.c b/liblog/local_logger.c
index 522867d4f..563cb3f9b 100644
--- a/liblog/local_logger.c
+++ b/liblog/local_logger.c
@@ -222,6 +222,7 @@ static int LogBufferLog(struct LogBuffer* log,
222 log->last[logId] = node->prev; 222 log->last[logId] = node->prev;
223 } 223 }
224 list_remove(node); 224 list_remove(node);
225 LOG_ALWAYS_FATAL_IF(node == log->last[logId], "corrupted list");
225 free(e); 226 free(e);
226 } 227 }
227 /* add entry to list */ 228 /* add entry to list */
diff --git a/liblog/logprint.c b/liblog/logprint.c
index b62f8b446..a2839bfb6 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.c
@@ -250,6 +250,7 @@ LIBLOG_ABI_PUBLIC void android_log_format_free(AndroidLogFormat* p_format) {
250 while (!list_empty(&convertHead)) { 250 while (!list_empty(&convertHead)) {
251 struct listnode* node = list_head(&convertHead); 251 struct listnode* node = list_head(&convertHead);
252 list_remove(node); 252 list_remove(node);
253 LOG_ALWAYS_FATAL_IF(node == list_head(&convertHead), "corrupted list");
253 free(node); 254 free(node);
254 } 255 }
255} 256}
diff --git a/libmemtrack/Android.bp b/libmemtrack/Android.bp
index 68c580a45..095563384 100644
--- a/libmemtrack/Android.bp
+++ b/libmemtrack/Android.bp
@@ -2,6 +2,10 @@
2 2
3cc_library_shared { 3cc_library_shared {
4 name: "libmemtrack", 4 name: "libmemtrack",
5 vendor_available: true,
6 vndk: {
7 enabled: true,
8 },
5 srcs: ["memtrack.cpp"], 9 srcs: ["memtrack.cpp"],
6 export_include_dirs: ["include"], 10 export_include_dirs: ["include"],
7 local_include_dirs: ["include"], 11 local_include_dirs: ["include"],
diff --git a/libmemunreachable/tests/DisableMalloc_test.cpp b/libmemunreachable/tests/DisableMalloc_test.cpp
index c630049fc..f4467190c 100644
--- a/libmemunreachable/tests/DisableMalloc_test.cpp
+++ b/libmemunreachable/tests/DisableMalloc_test.cpp
@@ -73,15 +73,18 @@ TEST_F(DisableMallocTest, deadlock_allocate) {
73TEST_F(DisableMallocTest, deadlock_new) { 73TEST_F(DisableMallocTest, deadlock_new) {
74 ASSERT_DEATH( 74 ASSERT_DEATH(
75 { 75 {
76 char* ptr = new (char); 76 // C++ allows `new Foo` to be replaced with a stack allocation or merged
77 // with future `new Foo` expressions, provided certain conditions are
78 // met [expr.new/10]. None of this applies to `operator new(size_t)`.
79 void* ptr = ::operator new(1);
77 ASSERT_NE(ptr, nullptr); 80 ASSERT_NE(ptr, nullptr);
78 delete (ptr); 81 ::operator delete(ptr);
79 { 82 {
80 alarm(100ms); 83 alarm(100ms);
81 ScopedDisableMalloc disable_malloc; 84 ScopedDisableMalloc disable_malloc;
82 char* ptr = new (std::nothrow)(char); 85 void* ptr = ::operator new(1);
83 ASSERT_NE(ptr, nullptr); 86 ASSERT_NE(ptr, nullptr);
84 delete (ptr); 87 ::operator delete(ptr);
85 } 88 }
86 }, 89 },
87 ""); 90 "");
@@ -90,14 +93,12 @@ TEST_F(DisableMallocTest, deadlock_new) {
90TEST_F(DisableMallocTest, deadlock_delete) { 93TEST_F(DisableMallocTest, deadlock_delete) {
91 ASSERT_DEATH( 94 ASSERT_DEATH(
92 { 95 {
93 char* ptr = new (char); 96 void* ptr = ::operator new(1);
94 ASSERT_NE(ptr, nullptr); 97 ASSERT_NE(ptr, nullptr);
95 { 98 {
96 alarm(250ms); 99 alarm(250ms);
97 ScopedDisableMalloc disable_malloc; 100 ScopedDisableMalloc disable_malloc;
98 delete (ptr); 101 ::operator delete(ptr);
99 // Force ptr usage or this code gets optimized away by the arm64 compiler.
100 ASSERT_NE(ptr, nullptr);
101 } 102 }
102 }, 103 },
103 ""); 104 "");
diff --git a/libmemunreachable/tests/MemUnreachable_test.cpp b/libmemunreachable/tests/MemUnreachable_test.cpp
index ec8938885..87417f132 100644
--- a/libmemunreachable/tests/MemUnreachable_test.cpp
+++ b/libmemunreachable/tests/MemUnreachable_test.cpp
@@ -27,6 +27,9 @@ namespace android {
27 27
28class HiddenPointer { 28class HiddenPointer {
29 public: 29 public:
30 // Since we're doing such a good job of hiding it, the static analyzer
31 // thinks that we're leaking this `malloc`. This is probably related to
32 // https://bugs.llvm.org/show_bug.cgi?id=34198. NOLINTNEXTLINE
30 explicit HiddenPointer(size_t size = 256) { Set(malloc(size)); } 33 explicit HiddenPointer(size_t size = 256) { Set(malloc(size)); }
31 ~HiddenPointer() { Free(); } 34 ~HiddenPointer() { Free(); }
32 void* Get() { return reinterpret_cast<void*>(~ptr_); } 35 void* Get() { return reinterpret_cast<void*>(~ptr_); }
diff --git a/libmetricslogger/Android.bp b/libmetricslogger/Android.bp
index c692d1fa3..6549b8d56 100644
--- a/libmetricslogger/Android.bp
+++ b/libmetricslogger/Android.bp
@@ -18,11 +18,6 @@ cc_defaults {
18 "-Wall", 18 "-Wall",
19 "-Wextra", 19 "-Wextra",
20 "-Werror", 20 "-Werror",
21
22 // 524291 corresponds to sysui_histogram, from
23 // frameworks/base/core/java/com/android/internal/logging/EventLogTags.logtags
24 "-DHISTOGRAM_LOG_TAG=524292",
25 "-DCOUNT_LOG_TAG=524290",
26 ], 21 ],
27} 22}
28 23
diff --git a/libmetricslogger/include/metricslogger/metrics_logger.h b/libmetricslogger/include/metricslogger/metrics_logger.h
index 36e124d9c..189bc4b63 100644
--- a/libmetricslogger/include/metricslogger/metrics_logger.h
+++ b/libmetricslogger/include/metricslogger/metrics_logger.h
@@ -28,14 +28,26 @@ void LogHistogram(const std::string& event, int32_t data);
28// log buffer. 28// log buffer.
29void LogCounter(const std::string& name, int32_t val); 29void LogCounter(const std::string& name, int32_t val);
30 30
31// Logs a Tron multi_action with category|category| containing the string
32// |value| in the field |field|.
33void LogMultiAction(int32_t category, int32_t field, const std::string& value);
34
31// TODO: replace these with the metric_logger.proto definitions 35// TODO: replace these with the metric_logger.proto definitions
32enum { 36enum {
33 LOGBUILDER_CATEGORY = 757, 37 LOGBUILDER_CATEGORY = 757,
38 LOGBUILDER_TYPE = 758,
34 LOGBUILDER_NAME = 799, 39 LOGBUILDER_NAME = 799,
35 LOGBUILDER_BUCKET = 801, 40 LOGBUILDER_BUCKET = 801,
36 LOGBUILDER_VALUE = 802, 41 LOGBUILDER_VALUE = 802,
37 LOGBUILDER_COUNTER = 803, 42 LOGBUILDER_COUNTER = 803,
38 LOGBUILDER_HISTOGRAM = 804, 43 LOGBUILDER_HISTOGRAM = 804,
44
45 ACTION_BOOT = 1098,
46 FIELD_PLATFORM_REASON = 1099,
47};
48
49enum {
50 TYPE_ACTION = 4,
39}; 51};
40 52
41} // namespace metricslogger 53} // namespace metricslogger
diff --git a/libmetricslogger/metrics_logger.cpp b/libmetricslogger/metrics_logger.cpp
index 6f65e10f1..fdc44071b 100644
--- a/libmetricslogger/metrics_logger.cpp
+++ b/libmetricslogger/metrics_logger.cpp
@@ -18,24 +18,40 @@
18 18
19#include <cstdlib> 19#include <cstdlib>
20 20
21#include <log/event_tag_map.h>
21#include <log/log_event_list.h> 22#include <log/log_event_list.h>
22 23
24namespace {
25
26EventTagMap* kEventTagMap = android_openEventTagMap(nullptr);
27const int kSysuiMultiActionTag = android_lookupEventTagNum(
28 kEventTagMap, "sysui_multi_action", "(content|4)", ANDROID_LOG_UNKNOWN);
29
30} // namespace
31
23namespace android { 32namespace android {
24namespace metricslogger { 33namespace metricslogger {
25 34
26// Mirror com.android.internal.logging.MetricsLogger#histogram(). 35// Mirror com.android.internal.logging.MetricsLogger#histogram().
27void LogHistogram(const std::string& event, int32_t data) { 36void LogHistogram(const std::string& event, int32_t data) {
28 android_log_event_list log(HISTOGRAM_LOG_TAG); 37 android_log_event_list log(kSysuiMultiActionTag);
29 log << LOGBUILDER_CATEGORY << LOGBUILDER_HISTOGRAM << LOGBUILDER_NAME << event 38 log << LOGBUILDER_CATEGORY << LOGBUILDER_HISTOGRAM << LOGBUILDER_NAME << event
30 << LOGBUILDER_BUCKET << data << LOGBUILDER_VALUE << 1 << LOG_ID_EVENTS; 39 << LOGBUILDER_BUCKET << data << LOGBUILDER_VALUE << 1 << LOG_ID_EVENTS;
31} 40}
32 41
33// Mirror com.android.internal.logging.MetricsLogger#count(). 42// Mirror com.android.internal.logging.MetricsLogger#count().
34void LogCounter(const std::string& name, int32_t val) { 43void LogCounter(const std::string& name, int32_t val) {
35 android_log_event_list log(COUNT_LOG_TAG); 44 android_log_event_list log(kSysuiMultiActionTag);
36 log << LOGBUILDER_CATEGORY << LOGBUILDER_COUNTER << LOGBUILDER_NAME << name << LOGBUILDER_VALUE 45 log << LOGBUILDER_CATEGORY << LOGBUILDER_COUNTER << LOGBUILDER_NAME << name << LOGBUILDER_VALUE
37 << val << LOG_ID_EVENTS; 46 << val << LOG_ID_EVENTS;
38} 47}
39 48
49// Mirror com.android.internal.logging.MetricsLogger#action().
50void LogMultiAction(int32_t category, int32_t field, const std::string& value) {
51 android_log_event_list log(kSysuiMultiActionTag);
52 log << LOGBUILDER_CATEGORY << category << LOGBUILDER_TYPE << TYPE_ACTION
53 << field << value << LOG_ID_EVENTS;
54}
55
40} // namespace metricslogger 56} // namespace metricslogger
41} // namespace android 57} // namespace android
diff --git a/libnativebridge/Android.bp b/libnativebridge/Android.bp
index b3c42f072..089f3b825 100644
--- a/libnativebridge/Android.bp
+++ b/libnativebridge/Android.bp
@@ -22,13 +22,6 @@ cc_library {
22 cppflags: [ 22 cppflags: [
23 "-fvisibility=protected", 23 "-fvisibility=protected",
24 ], 24 ],
25
26 host_ldlibs: ["-ldl"],
27 target: {
28 android: {
29 shared_libs: ["libdl"],
30 },
31 },
32} 25}
33 26
34subdirs = ["tests"] 27subdirs = ["tests"]
diff --git a/libnativebridge/tests/Android.bp b/libnativebridge/tests/Android.bp
index e31dae086..9e2e641eb 100644
--- a/libnativebridge/tests/Android.bp
+++ b/libnativebridge/tests/Android.bp
@@ -25,14 +25,6 @@ cc_defaults {
25 ], 25 ],
26 header_libs: ["libnativebridge-dummy-headers"], 26 header_libs: ["libnativebridge-dummy-headers"],
27 cppflags: ["-fvisibility=protected"], 27 cppflags: ["-fvisibility=protected"],
28 target: {
29 android: {
30 shared_libs: ["libdl"],
31 },
32 host: {
33 host_ldlibs: ["-ldl"],
34 },
35 },
36} 28}
37 29
38cc_library_shared { 30cc_library_shared {
diff --git a/libnativeloader/Android.bp b/libnativeloader/Android.bp
index 13f974424..4b21edc46 100644
--- a/libnativeloader/Android.bp
+++ b/libnativeloader/Android.bp
@@ -11,14 +11,6 @@ cc_library {
11 "libnativebridge", 11 "libnativebridge",
12 "libbase", 12 "libbase",
13 ], 13 ],
14 target: {
15 android: {
16 shared_libs: ["libdl"],
17 },
18 host: {
19 host_ldlibs: ["-ldl"],
20 },
21 },
22 cflags: [ 14 cflags: [
23 "-Werror", 15 "-Werror",
24 "-Wall", 16 "-Wall",
@@ -27,5 +19,4 @@ cc_library {
27 "-fvisibility=hidden", 19 "-fvisibility=hidden",
28 ], 20 ],
29 export_include_dirs: ["include"], 21 export_include_dirs: ["include"],
30 local_include_dirs: ["include"],
31} 22}
diff --git a/libnetutils/Android.bp b/libnetutils/Android.bp
index 9967ef886..1d43775d6 100644
--- a/libnetutils/Android.bp
+++ b/libnetutils/Android.bp
@@ -1,6 +1,9 @@
1cc_library_shared { 1cc_library_shared {
2 name: "libnetutils", 2 name: "libnetutils",
3 vendor_available: true, 3 vendor_available: true,
4 vndk: {
5 enabled: true,
6 },
4 7
5 srcs: [ 8 srcs: [
6 "dhcpclient.c", 9 "dhcpclient.c",
diff --git a/libprocinfo/Android.bp b/libprocinfo/Android.bp
index aedaa3867..b568ee5da 100644
--- a/libprocinfo/Android.bp
+++ b/libprocinfo/Android.bp
@@ -23,6 +23,9 @@ libprocinfo_cppflags = [
23cc_library { 23cc_library {
24 name: "libprocinfo", 24 name: "libprocinfo",
25 vendor_available: true, 25 vendor_available: true,
26 vndk: {
27 enabled: true,
28 },
26 host_supported: true, 29 host_supported: true,
27 srcs: [ 30 srcs: [
28 "process.cpp", 31 "process.cpp",
diff --git a/libsparse/Android.bp b/libsparse/Android.bp
index 6ec0991c7..b8946563c 100644
--- a/libsparse/Android.bp
+++ b/libsparse/Android.bp
@@ -15,19 +15,11 @@ cc_library {
15 cflags: ["-Werror"], 15 cflags: ["-Werror"],
16 local_include_dirs: ["include"], 16 local_include_dirs: ["include"],
17 export_include_dirs: ["include"], 17 export_include_dirs: ["include"],
18 shared_libs: [
19 "libz",
20 "libbase",
21 ],
18 target: { 22 target: {
19 host: {
20 shared_libs: [
21 "libz-host",
22 "libbase",
23 ],
24 },
25 android: {
26 shared_libs: [
27 "libz",
28 "libbase",
29 ],
30 },
31 windows: { 23 windows: {
32 enabled: true, 24 enabled: true,
33 }, 25 },
diff --git a/libsparse/sparse_read.cpp b/libsparse/sparse_read.cpp
index bfb70c795..437963527 100644
--- a/libsparse/sparse_read.cpp
+++ b/libsparse/sparse_read.cpp
@@ -24,6 +24,7 @@
24#include <stdint.h> 24#include <stdint.h>
25#include <stdio.h> 25#include <stdio.h>
26#include <stdlib.h> 26#include <stdlib.h>
27#include <string.h>
27#include <string> 28#include <string>
28#include <unistd.h> 29#include <unistd.h>
29 30
diff --git a/libsuspend/Android.bp b/libsuspend/Android.bp
index 130800ed8..32f1e1ff8 100644
--- a/libsuspend/Android.bp
+++ b/libsuspend/Android.bp
@@ -3,6 +3,9 @@
3cc_library { 3cc_library {
4 name: "libsuspend", 4 name: "libsuspend",
5 vendor_available: true, 5 vendor_available: true,
6 vndk: {
7 enabled: true,
8 },
6 9
7 srcs: [ 10 srcs: [
8 "autosuspend.c", 11 "autosuspend.c",
diff --git a/libsync/Android.bp b/libsync/Android.bp
index 1646348a9..3fae5e669 100644
--- a/libsync/Android.bp
+++ b/libsync/Android.bp
@@ -22,10 +22,15 @@ cc_defaults {
22 22
23cc_library_shared { 23cc_library_shared {
24 name: "libsync", 24 name: "libsync",
25 vendor_available: true,
26 defaults: ["libsync_defaults"], 25 defaults: ["libsync_defaults"],
27} 26}
28 27
28llndk_library {
29 name: "libsync",
30 symbol_file: "libsync.map.txt",
31 export_include_dirs: ["include"],
32}
33
29// libsync_recovery is only intended for the recovery binary. 34// libsync_recovery is only intended for the recovery binary.
30// Future versions of the kernel WILL require an updated libsync, and will break 35// Future versions of the kernel WILL require an updated libsync, and will break
31// anything statically linked against the current libsync. 36// anything statically linked against the current libsync.
diff --git a/libsync/libsync.map.txt b/libsync/libsync.map.txt
index daa28ae92..53bb07a70 100644
--- a/libsync/libsync.map.txt
+++ b/libsync/libsync.map.txt
@@ -17,16 +17,12 @@
17LIBSYNC { 17LIBSYNC {
18 global: 18 global:
19 sync_merge; # introduced=26 19 sync_merge; # introduced=26
20 sync_get_fence_info; # introduced=26 20 sync_file_info; # introduced=26
21 sync_free_fence_info; # introduced=26 21 sync_file_info_free; # introduced=26
22 sync_wait; # vndk
23 sync_fence_info; # vndk
24 sync_pt_info; # vndk
25 sync_fence_info_free; # vndk
22 local: 26 local:
23 *; 27 *;
24}; 28};
25
26LIBSYNC_PLATFORM {
27 global:
28 sync_wait;
29 sync_fence_info;
30 sync_pt_info;
31 sync_fence_info_free;
32} LIBSYNC_PLATFORM;
diff --git a/libsync/sync.c b/libsync/sync.c
index baeccda47..6b187faed 100644
--- a/libsync/sync.c
+++ b/libsync/sync.c
@@ -217,6 +217,8 @@ static struct sync_file_info *modern_sync_file_info(int fd)
217 local_info.num_fences * sizeof(struct sync_fence_info)); 217 local_info.num_fences * sizeof(struct sync_fence_info));
218 if (!info) 218 if (!info)
219 return NULL; 219 return NULL;
220
221 info->num_fences = local_info.num_fences;
220 info->sync_fence_info = (__u64)(uintptr_t)(info + 1); 222 info->sync_fence_info = (__u64)(uintptr_t)(info + 1);
221 223
222 err = ioctl(fd, SYNC_IOC_FILE_INFO, info); 224 err = ioctl(fd, SYNC_IOC_FILE_INFO, info);
@@ -275,7 +277,6 @@ static struct sync_file_info* legacy_fence_info_to_sync_file_info(
275 info = calloc(1, sizeof(struct sync_file_info) + 277 info = calloc(1, sizeof(struct sync_file_info) +
276 num_fences * sizeof(struct sync_fence_info)); 278 num_fences * sizeof(struct sync_fence_info));
277 if (!info) { 279 if (!info) {
278 free(legacy_info);
279 return NULL; 280 return NULL;
280 } 281 }
281 info->sync_fence_info = (__u64)(uintptr_t)(info + 1); 282 info->sync_fence_info = (__u64)(uintptr_t)(info + 1);
diff --git a/libsync/tests/sync_test.cpp b/libsync/tests/sync_test.cpp
index f08e97e2c..0fb86d6fc 100644
--- a/libsync/tests/sync_test.cpp
+++ b/libsync/tests/sync_test.cpp
@@ -448,6 +448,41 @@ TEST(FenceTest, MultiTimelineWait) {
448 ASSERT_EQ(mergedFence.wait(100), 0); 448 ASSERT_EQ(mergedFence.wait(100), 0);
449} 449}
450 450
451TEST(FenceTest, GetInfoActive) {
452 SyncTimeline timeline;
453 ASSERT_TRUE(timeline.isValid());
454
455 SyncFence fence(timeline, 1);
456 ASSERT_TRUE(fence.isValid());
457
458 vector<SyncPointInfo> info = fence.getInfo();
459 ASSERT_EQ(info.size(), 1);
460
461 ASSERT_FALSE(info[0].driverName.empty());
462 ASSERT_FALSE(info[0].objectName.empty());
463 ASSERT_EQ(info[0].timeStampNs, 0);
464 ASSERT_EQ(info[0].status, 0);
465}
466
467TEST(FenceTest, GetInfoSignaled) {
468 SyncTimeline timeline;
469 ASSERT_TRUE(timeline.isValid());
470
471 SyncFence fence(timeline, 1);
472 ASSERT_TRUE(fence.isValid());
473
474 ASSERT_EQ(timeline.inc(1), 0);
475 ASSERT_EQ(fence.wait(), 0);
476
477 vector<SyncPointInfo> info = fence.getInfo();
478 ASSERT_EQ(info.size(), 1);
479
480 ASSERT_FALSE(info[0].driverName.empty());
481 ASSERT_FALSE(info[0].objectName.empty());
482 ASSERT_GT(info[0].timeStampNs, 0);
483 ASSERT_EQ(info[0].status, 1);
484}
485
451TEST(StressTest, TwoThreadsSharedTimeline) { 486TEST(StressTest, TwoThreadsSharedTimeline) {
452 const int iterations = 1 << 16; 487 const int iterations = 1 << 16;
453 int counter = 0; 488 int counter = 0;
diff --git a/libsysutils/Android.bp b/libsysutils/Android.bp
index 550ef4233..3a1229228 100644
--- a/libsysutils/Android.bp
+++ b/libsysutils/Android.bp
@@ -1,6 +1,9 @@
1cc_library_shared { 1cc_library_shared {
2 name: "libsysutils", 2 name: "libsysutils",
3 vendor_available: true, 3 vendor_available: true,
4 vndk: {
5 enabled: true,
6 },
4 7
5 srcs: [ 8 srcs: [
6 "src/SocketListener.cpp", 9 "src/SocketListener.cpp",
@@ -20,7 +23,6 @@ cc_library_shared {
20 "libbase", 23 "libbase",
21 "libcutils", 24 "libcutils",
22 "liblog", 25 "liblog",
23 "libnl",
24 ], 26 ],
25 27
26 export_include_dirs: ["include"], 28 export_include_dirs: ["include"],
diff --git a/libsysutils/include/sysutils/NetlinkEvent.h b/libsysutils/include/sysutils/NetlinkEvent.h
index b80f3ea44..f9fc11b2b 100644
--- a/libsysutils/include/sysutils/NetlinkEvent.h
+++ b/libsysutils/include/sysutils/NetlinkEvent.h
@@ -64,6 +64,7 @@ public:
64 bool parseNfPacketMessage(struct nlmsghdr *nh); 64 bool parseNfPacketMessage(struct nlmsghdr *nh);
65 bool parseRtMessage(const struct nlmsghdr *nh); 65 bool parseRtMessage(const struct nlmsghdr *nh);
66 bool parseNdUserOptMessage(const struct nlmsghdr *nh); 66 bool parseNdUserOptMessage(const struct nlmsghdr *nh);
67 struct nlattr* findNlAttr(const nlmsghdr* nl, size_t hdrlen, uint16_t attr);
67}; 68};
68 69
69#endif 70#endif
diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp
index 79bc88853..00b1ee228 100644
--- a/libsysutils/src/NetlinkEvent.cpp
+++ b/libsysutils/src/NetlinkEvent.cpp
@@ -17,6 +17,8 @@
17#define LOG_TAG "NetlinkEvent" 17#define LOG_TAG "NetlinkEvent"
18 18
19#include <arpa/inet.h> 19#include <arpa/inet.h>
20#include <limits.h>
21#include <linux/genetlink.h>
20#include <linux/if.h> 22#include <linux/if.h>
21#include <linux/if_addr.h> 23#include <linux/if_addr.h>
22#include <linux/if_link.h> 24#include <linux/if_link.h>
@@ -26,12 +28,8 @@
26#include <linux/netlink.h> 28#include <linux/netlink.h>
27#include <linux/rtnetlink.h> 29#include <linux/rtnetlink.h>
28#include <net/if.h> 30#include <net/if.h>
29#include <netinet/in.h>
30#include <netinet/icmp6.h> 31#include <netinet/icmp6.h>
31#include <netlink/attr.h> 32#include <netinet/in.h>
32#include <netlink/genl/genl.h>
33#include <netlink/handlers.h>
34#include <netlink/msg.h>
35#include <stdlib.h> 33#include <stdlib.h>
36#include <string.h> 34#include <string.h>
37#include <sys/socket.h> 35#include <sys/socket.h>
@@ -263,6 +261,18 @@ bool NetlinkEvent::parseUlogPacketMessage(const struct nlmsghdr *nh) {
263 return true; 261 return true;
264} 262}
265 263
264static size_t nlAttrLen(const nlattr* nla) {
265 return nla->nla_len - NLA_HDRLEN;
266}
267
268static const uint8_t* nlAttrData(const nlattr* nla) {
269 return reinterpret_cast<const uint8_t*>(nla) + NLA_HDRLEN;
270}
271
272static uint32_t nlAttrU32(const nlattr* nla) {
273 return *reinterpret_cast<const uint32_t*>(nlAttrData(nla));
274}
275
266/* 276/*
267 * Parse a LOCAL_NFLOG_PACKET message. 277 * Parse a LOCAL_NFLOG_PACKET message.
268 */ 278 */
@@ -271,17 +281,17 @@ bool NetlinkEvent::parseNfPacketMessage(struct nlmsghdr *nh) {
271 int len = 0; 281 int len = 0;
272 char* raw = NULL; 282 char* raw = NULL;
273 283
274 struct nlattr *uid_attr = nlmsg_find_attr(nh, sizeof(struct genlmsghdr), NFULA_UID); 284 struct nlattr* uid_attr = findNlAttr(nh, sizeof(struct genlmsghdr), NFULA_UID);
275 if (uid_attr) { 285 if (uid_attr) {
276 uid = ntohl(nla_get_u32(uid_attr)); 286 uid = ntohl(nlAttrU32(uid_attr));
277 } 287 }
278 288
279 struct nlattr *payload = nlmsg_find_attr(nh, sizeof(struct genlmsghdr), NFULA_PAYLOAD); 289 struct nlattr* payload = findNlAttr(nh, sizeof(struct genlmsghdr), NFULA_PAYLOAD);
280 if (payload) { 290 if (payload) {
281 /* First 256 bytes is plenty */ 291 /* First 256 bytes is plenty */
282 len = nla_len(payload); 292 len = nlAttrLen(payload);
283 if (len > 256) len = 256; 293 if (len > 256) len = 256;
284 raw = (char*) nla_data(payload); 294 raw = (char*)nlAttrData(payload);
285 } 295 }
286 296
287 char* hex = (char*) calloc(1, 5 + (len * 2)); 297 char* hex = (char*) calloc(1, 5 + (len * 2));
@@ -646,3 +656,26 @@ const char *NetlinkEvent::findParam(const char *paramName) {
646 SLOGE("NetlinkEvent::FindParam(): Parameter '%s' not found", paramName); 656 SLOGE("NetlinkEvent::FindParam(): Parameter '%s' not found", paramName);
647 return NULL; 657 return NULL;
648} 658}
659
660nlattr* NetlinkEvent::findNlAttr(const nlmsghdr* nh, size_t hdrlen, uint16_t attr) {
661 if (nh == nullptr || NLMSG_HDRLEN + NLMSG_ALIGN(hdrlen) > SSIZE_MAX) {
662 return nullptr;
663 }
664
665 // Skip header, padding, and family header.
666 const ssize_t NLA_START = NLMSG_HDRLEN + NLMSG_ALIGN(hdrlen);
667 ssize_t left = nh->nlmsg_len - NLA_START;
668 uint8_t* hdr = ((uint8_t*)nh) + NLA_START;
669
670 while (left >= NLA_HDRLEN) {
671 nlattr* nla = (nlattr*)hdr;
672 if (nla->nla_type == attr) {
673 return nla;
674 }
675
676 hdr += NLA_ALIGN(nla->nla_len);
677 left -= NLA_ALIGN(nla->nla_len);
678 }
679
680 return nullptr;
681}
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index b971a9eda..f40086e5d 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -29,12 +29,19 @@ cc_defaults {
29 darwin: { 29 darwin: {
30 enabled: false, 30 enabled: false,
31 }, 31 },
32 linux_bionic: {
33 enabled: true,
34 },
32 }, 35 },
33} 36}
34 37
35cc_library { 38cc_library {
36 name: "libunwindstack", 39 name: "libunwindstack",
37 vendor_available: true, 40 vendor_available: true,
41 vndk: {
42 enabled: true,
43 support_system_process: true,
44 },
38 defaults: ["libunwindstack_flags"], 45 defaults: ["libunwindstack_flags"],
39 export_include_dirs: ["include"], 46 export_include_dirs: ["include"],
40 47
@@ -54,9 +61,17 @@ cc_library {
54 "Maps.cpp", 61 "Maps.cpp",
55 "Memory.cpp", 62 "Memory.cpp",
56 "Regs.cpp", 63 "Regs.cpp",
64 "Unwinder.cpp",
57 "Symbols.cpp", 65 "Symbols.cpp",
58 ], 66 ],
59 67
68 target: {
69 // Always disable optimizations for host to make it easier to debug.
70 host: {
71 cflags: ["-O0", "-g"],
72 },
73 },
74
60 arch: { 75 arch: {
61 x86: { 76 x86: {
62 srcs: ["AsmGetRegsX86.S"], 77 srcs: ["AsmGetRegsX86.S"],
@@ -92,12 +107,12 @@ cc_test {
92 "tests/DwarfOpTest.cpp", 107 "tests/DwarfOpTest.cpp",
93 "tests/DwarfSectionTest.cpp", 108 "tests/DwarfSectionTest.cpp",
94 "tests/DwarfSectionImplTest.cpp", 109 "tests/DwarfSectionImplTest.cpp",
110 "tests/ElfFake.cpp",
95 "tests/ElfInterfaceArmTest.cpp", 111 "tests/ElfInterfaceArmTest.cpp",
96 "tests/ElfInterfaceTest.cpp", 112 "tests/ElfInterfaceTest.cpp",
97 "tests/ElfTest.cpp", 113 "tests/ElfTest.cpp",
98 "tests/ElfTestUtils.cpp", 114 "tests/ElfTestUtils.cpp",
99 "tests/LogFake.cpp", 115 "tests/LogFake.cpp",
100 "tests/MapInfoCreateMemoryTest.cpp",
101 "tests/MapInfoGetElfTest.cpp", 116 "tests/MapInfoGetElfTest.cpp",
102 "tests/MapsTest.cpp", 117 "tests/MapsTest.cpp",
103 "tests/MemoryBufferTest.cpp", 118 "tests/MemoryBufferTest.cpp",
@@ -111,6 +126,7 @@ cc_test {
111 "tests/RegsTest.cpp", 126 "tests/RegsTest.cpp",
112 "tests/SymbolsTest.cpp", 127 "tests/SymbolsTest.cpp",
113 "tests/UnwindTest.cpp", 128 "tests/UnwindTest.cpp",
129 "tests/UnwinderTest.cpp",
114 ], 130 ],
115 131
116 cflags: [ 132 cflags: [
@@ -129,14 +145,6 @@ cc_test {
129 "libgmock", 145 "libgmock",
130 ], 146 ],
131 147
132 target: {
133 linux: {
134 host_ldlibs: [
135 "-lrt",
136 ],
137 },
138 },
139
140 data: [ 148 data: [
141 "tests/files/elf32.xz", 149 "tests/files/elf32.xz",
142 "tests/files/elf64.xz", 150 "tests/files/elf64.xz",
@@ -164,14 +172,6 @@ cc_binary {
164 srcs: [ 172 srcs: [
165 "tools/unwind.cpp", 173 "tools/unwind.cpp",
166 ], 174 ],
167
168 target: {
169 linux: {
170 host_ldlibs: [
171 "-lrt",
172 ],
173 },
174 },
175} 175}
176 176
177cc_binary { 177cc_binary {
diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp
index 1234eb135..8b30b768d 100644
--- a/libunwindstack/DwarfSection.cpp
+++ b/libunwindstack/DwarfSection.cpp
@@ -47,7 +47,7 @@ const DwarfFde* DwarfSection::GetFdeFromPc(uint64_t pc) {
47 return nullptr; 47 return nullptr;
48} 48}
49 49
50bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory) { 50bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
51 last_error_ = DWARF_ERROR_NONE; 51 last_error_ = DWARF_ERROR_NONE;
52 const DwarfFde* fde = GetFdeFromPc(pc); 52 const DwarfFde* fde = GetFdeFromPc(pc);
53 if (fde == nullptr || fde->cie == nullptr) { 53 if (fde == nullptr || fde->cie == nullptr) {
@@ -62,7 +62,7 @@ bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory) {
62 } 62 }
63 63
64 // Now eval the actual registers. 64 // Now eval the actual registers.
65 return Eval(fde->cie, process_memory, loc_regs, regs); 65 return Eval(fde->cie, process_memory, loc_regs, regs, finished);
66} 66}
67 67
68template <typename AddressType> 68template <typename AddressType>
@@ -92,7 +92,8 @@ bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, uin
92 92
93template <typename AddressType> 93template <typename AddressType>
94bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_memory, 94bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_memory,
95 const dwarf_loc_regs_t& loc_regs, Regs* regs) { 95 const dwarf_loc_regs_t& loc_regs, Regs* regs,
96 bool* finished) {
96 RegsImpl<AddressType>* cur_regs = reinterpret_cast<RegsImpl<AddressType>*>(regs); 97 RegsImpl<AddressType>* cur_regs = reinterpret_cast<RegsImpl<AddressType>*>(regs);
97 if (cie->return_address_register >= cur_regs->total_regs()) { 98 if (cie->return_address_register >= cur_regs->total_regs()) {
98 last_error_ = DWARF_ERROR_ILLEGAL_VALUE; 99 last_error_ = DWARF_ERROR_ILLEGAL_VALUE;
@@ -224,12 +225,14 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me
224 // Find the return address location. 225 // Find the return address location.
225 if (return_address_undefined) { 226 if (return_address_undefined) {
226 cur_regs->set_pc(0); 227 cur_regs->set_pc(0);
228 *finished = true;
227 } else { 229 } else {
228 cur_regs->set_pc((*cur_regs)[cie->return_address_register]); 230 cur_regs->set_pc((*cur_regs)[cie->return_address_register]);
231 *finished = false;
229 } 232 }
230 cur_regs->set_sp(cfa); 233 cur_regs->set_sp(cfa);
231 // Stop if the cfa and pc are the same. 234 // Return false if the unwind is not finished or the cfa and pc didn't change.
232 return prev_cfa != cfa || prev_pc != cur_regs->pc(); 235 return *finished || prev_cfa != cfa || prev_pc != cur_regs->pc();
233} 236}
234 237
235template <typename AddressType> 238template <typename AddressType>
diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp
index 4fc7c679f..dc6591dec 100644
--- a/libunwindstack/Elf.cpp
+++ b/libunwindstack/Elf.cpp
@@ -95,11 +95,17 @@ bool Elf::GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offse
95 gnu_debugdata_interface_->GetFunctionName(addr, name, func_offset))); 95 gnu_debugdata_interface_->GetFunctionName(addr, name, func_offset)));
96} 96}
97 97
98bool Elf::Step(uint64_t rel_pc, Regs* regs, Memory* process_memory) { 98bool Elf::Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished) {
99 return valid_ && (regs->StepIfSignalHandler(rel_pc, this, process_memory) || 99 if (!valid_) {
100 interface_->Step(rel_pc, regs, process_memory) || 100 return false;
101 (gnu_debugdata_interface_ && 101 }
102 gnu_debugdata_interface_->Step(rel_pc, regs, process_memory))); 102 if (regs->StepIfSignalHandler(rel_pc, this, process_memory)) {
103 *finished = false;
104 return true;
105 }
106 return interface_->Step(rel_pc, regs, process_memory, finished) ||
107 (gnu_debugdata_interface_ &&
108 gnu_debugdata_interface_->Step(rel_pc, regs, process_memory, finished));
103} 109}
104 110
105uint64_t Elf::GetLoadBias() { 111uint64_t Elf::GetLoadBias() {
@@ -124,6 +130,28 @@ bool Elf::IsValidElf(Memory* memory) {
124 return true; 130 return true;
125} 131}
126 132
133void Elf::GetInfo(Memory* memory, bool* valid, uint64_t* size) {
134 if (!IsValidElf(memory)) {
135 *valid = false;
136 return;
137 }
138 *size = 0;
139 *valid = true;
140
141 // Now read the section header information.
142 uint8_t class_type;
143 if (!memory->Read(EI_CLASS, &class_type, 1)) {
144 return;
145 }
146 if (class_type == ELFCLASS32) {
147 ElfInterface32::GetMaxSize(memory, size);
148 } else if (class_type == ELFCLASS64) {
149 ElfInterface64::GetMaxSize(memory, size);
150 } else {
151 *valid = false;
152 }
153}
154
127ElfInterface* Elf::CreateInterfaceFromMemory(Memory* memory) { 155ElfInterface* Elf::CreateInterfaceFromMemory(Memory* memory) {
128 if (!IsValidElf(memory)) { 156 if (!IsValidElf(memory)) {
129 return nullptr; 157 return nullptr;
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index 75abc85f7..46a3f3f6c 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -348,7 +348,7 @@ bool ElfInterface::GetFunctionNameWithTemplate(uint64_t addr, std::string* name,
348 return false; 348 return false;
349} 349}
350 350
351bool ElfInterface::Step(uint64_t pc, Regs* regs, Memory* process_memory) { 351bool ElfInterface::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
352 // Need to subtract off the load_bias to get the correct pc. 352 // Need to subtract off the load_bias to get the correct pc.
353 if (pc < load_bias_) { 353 if (pc < load_bias_) {
354 return false; 354 return false;
@@ -357,19 +357,34 @@ bool ElfInterface::Step(uint64_t pc, Regs* regs, Memory* process_memory) {
357 357
358 // Try the eh_frame first. 358 // Try the eh_frame first.
359 DwarfSection* eh_frame = eh_frame_.get(); 359 DwarfSection* eh_frame = eh_frame_.get();
360 if (eh_frame != nullptr && eh_frame->Step(pc, regs, process_memory)) { 360 if (eh_frame != nullptr && eh_frame->Step(pc, regs, process_memory, finished)) {
361 return true; 361 return true;
362 } 362 }
363 363
364 // Try the debug_frame next. 364 // Try the debug_frame next.
365 DwarfSection* debug_frame = debug_frame_.get(); 365 DwarfSection* debug_frame = debug_frame_.get();
366 if (debug_frame != nullptr && debug_frame->Step(pc, regs, process_memory)) { 366 if (debug_frame != nullptr && debug_frame->Step(pc, regs, process_memory, finished)) {
367 return true; 367 return true;
368 } 368 }
369
370 return false; 369 return false;
371} 370}
372 371
372// This is an estimation of the size of the elf file using the location
373// of the section headers and size. This assumes that the section headers
374// are at the end of the elf file. If the elf has a load bias, the size
375// will be too large, but this is acceptable.
376template <typename EhdrType>
377void ElfInterface::GetMaxSizeWithTemplate(Memory* memory, uint64_t* size) {
378 EhdrType ehdr;
379 if (!memory->Read(0, &ehdr, sizeof(ehdr))) {
380 return;
381 }
382 if (ehdr.e_shnum == 0) {
383 return;
384 }
385 *size = ehdr.e_shoff + ehdr.e_shentsize * ehdr.e_shnum;
386}
387
373// Instantiate all of the needed template functions. 388// Instantiate all of the needed template functions.
374template void ElfInterface::InitHeadersWithTemplate<uint32_t>(); 389template void ElfInterface::InitHeadersWithTemplate<uint32_t>();
375template void ElfInterface::InitHeadersWithTemplate<uint64_t>(); 390template void ElfInterface::InitHeadersWithTemplate<uint64_t>();
@@ -391,4 +406,7 @@ template bool ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(uint64_t, std
391template bool ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(uint64_t, std::string*, 406template bool ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(uint64_t, std::string*,
392 uint64_t*); 407 uint64_t*);
393 408
409template void ElfInterface::GetMaxSizeWithTemplate<Elf32_Ehdr>(Memory*, uint64_t*);
410template void ElfInterface::GetMaxSizeWithTemplate<Elf64_Ehdr>(Memory*, uint64_t*);
411
394} // namespace unwindstack 412} // namespace unwindstack
diff --git a/libunwindstack/ElfInterfaceArm.cpp b/libunwindstack/ElfInterfaceArm.cpp
index 66bc51fb2..17364d0c5 100644
--- a/libunwindstack/ElfInterfaceArm.cpp
+++ b/libunwindstack/ElfInterfaceArm.cpp
@@ -99,22 +99,25 @@ bool ElfInterfaceArm::HandleType(uint64_t offset, uint32_t type) {
99 return true; 99 return true;
100} 100}
101 101
102bool ElfInterfaceArm::Step(uint64_t pc, Regs* regs, Memory* process_memory) { 102bool ElfInterfaceArm::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
103 // Dwarf unwind information is precise about whether a pc is covered or not, 103 // Dwarf unwind information is precise about whether a pc is covered or not,
104 // but arm unwind information only has ranges of pc. In order to avoid 104 // but arm unwind information only has ranges of pc. In order to avoid
105 // incorrectly doing a bad unwind using arm unwind information for a 105 // incorrectly doing a bad unwind using arm unwind information for a
106 // different function, always try and unwind with the dwarf information first. 106 // different function, always try and unwind with the dwarf information first.
107 return ElfInterface32::Step(pc, regs, process_memory) || StepExidx(pc, regs, process_memory); 107 return ElfInterface32::Step(pc, regs, process_memory, finished) ||
108 StepExidx(pc, regs, process_memory, finished);
108} 109}
109 110
110bool ElfInterfaceArm::StepExidx(uint64_t pc, Regs* regs, Memory* process_memory) { 111bool ElfInterfaceArm::StepExidx(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
111 RegsArm* regs_arm = reinterpret_cast<RegsArm*>(regs); 112 RegsArm* regs_arm = reinterpret_cast<RegsArm*>(regs);
112 uint64_t entry_offset; 113 uint64_t entry_offset;
113 if (!FindEntry(pc, &entry_offset)) { 114 if (!FindEntry(pc, &entry_offset)) {
114 return false; 115 return false;
115 } 116 }
117
116 ArmExidx arm(regs_arm, memory_, process_memory); 118 ArmExidx arm(regs_arm, memory_, process_memory);
117 arm.set_cfa(regs_arm->sp()); 119 arm.set_cfa(regs_arm->sp());
120 bool return_value = false;
118 if (arm.ExtractEntryData(entry_offset) && arm.Eval()) { 121 if (arm.ExtractEntryData(entry_offset) && arm.Eval()) {
119 // If the pc was not set, then use the LR registers for the PC. 122 // If the pc was not set, then use the LR registers for the PC.
120 if (!arm.pc_set()) { 123 if (!arm.pc_set()) {
@@ -125,9 +128,15 @@ bool ElfInterfaceArm::StepExidx(uint64_t pc, Regs* regs, Memory* process_memory)
125 } 128 }
126 regs_arm->set_sp(arm.cfa()); 129 regs_arm->set_sp(arm.cfa());
127 (*regs_arm)[ARM_REG_SP] = regs_arm->sp(); 130 (*regs_arm)[ARM_REG_SP] = regs_arm->sp();
131 *finished = false;
132 return_value = true;
133 }
134
135 if (arm.status() == ARM_STATUS_NO_UNWIND) {
136 *finished = true;
128 return true; 137 return true;
129 } 138 }
130 return false; 139 return return_value;
131} 140}
132 141
133} // namespace unwindstack 142} // namespace unwindstack
diff --git a/libunwindstack/ElfInterfaceArm.h b/libunwindstack/ElfInterfaceArm.h
index 1f4e8cb4e..bfe7704a6 100644
--- a/libunwindstack/ElfInterfaceArm.h
+++ b/libunwindstack/ElfInterfaceArm.h
@@ -70,9 +70,9 @@ class ElfInterfaceArm : public ElfInterface32 {
70 70
71 bool HandleType(uint64_t offset, uint32_t type) override; 71 bool HandleType(uint64_t offset, uint32_t type) override;
72 72
73 bool Step(uint64_t pc, Regs* regs, Memory* process_memory) override; 73 bool Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) override;
74 74
75 bool StepExidx(uint64_t pc, Regs* regs, Memory* process_memory); 75 bool StepExidx(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished);
76 76
77 uint64_t start_offset() { return start_offset_; } 77 uint64_t start_offset() { return start_offset_; }
78 78
diff --git a/libunwindstack/MapInfo.cpp b/libunwindstack/MapInfo.cpp
index d0e1216f3..96f2cb42b 100644
--- a/libunwindstack/MapInfo.cpp
+++ b/libunwindstack/MapInfo.cpp
@@ -14,6 +14,7 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17#include <sys/mman.h>
17#include <sys/types.h> 18#include <sys/types.h>
18#include <unistd.h> 19#include <unistd.h>
19 20
@@ -27,60 +28,88 @@
27 28
28namespace unwindstack { 29namespace unwindstack {
29 30
30Memory* MapInfo::CreateMemory(pid_t pid) { 31Memory* MapInfo::GetFileMemory() {
32 std::unique_ptr<MemoryFileAtOffset> memory(new MemoryFileAtOffset);
33 if (offset == 0) {
34 if (memory->Init(name, 0)) {
35 return memory.release();
36 }
37 return nullptr;
38 }
39
40 // There are two possibilities when the offset is non-zero.
41 // - There is an elf file embedded in a file.
42 // - The whole file is an elf file, and the offset needs to be saved.
43 //
44 // Map in just the part of the file for the map. If this is not
45 // a valid elf, then reinit as if the whole file is an elf file.
46 // If the offset is a valid elf, then determine the size of the map
47 // and reinit to that size. This is needed because the dynamic linker
48 // only maps in a portion of the original elf, and never the symbol
49 // file data.
50 uint64_t map_size = end - start;
51 if (!memory->Init(name, offset, map_size)) {
52 return nullptr;
53 }
54
55 bool valid;
56 uint64_t max_size;
57 Elf::GetInfo(memory.get(), &valid, &max_size);
58 if (!valid) {
59 // Init as if the whole file is an elf.
60 if (memory->Init(name, 0)) {
61 elf_offset = offset;
62 return memory.release();
63 }
64 return nullptr;
65 }
66
67 if (max_size > map_size) {
68 if (memory->Init(name, offset, max_size)) {
69 return memory.release();
70 }
71 // Try to reinit using the default map_size.
72 if (memory->Init(name, offset, map_size)) {
73 return memory.release();
74 }
75 return nullptr;
76 }
77 return memory.release();
78}
79
80Memory* MapInfo::CreateMemory(const std::shared_ptr<Memory>& process_memory) {
31 if (end <= start) { 81 if (end <= start) {
32 return nullptr; 82 return nullptr;
33 } 83 }
34 84
35 elf_offset = 0; 85 elf_offset = 0;
36 86
87 // Fail on device maps.
88 if (flags & MAPS_FLAGS_DEVICE_MAP) {
89 return nullptr;
90 }
91
37 // First try and use the file associated with the info. 92 // First try and use the file associated with the info.
38 if (!name.empty()) { 93 if (!name.empty()) {
39 // Fail on device maps. 94 Memory* memory = GetFileMemory();
40 if (flags & MAPS_FLAGS_DEVICE_MAP) { 95 if (memory != nullptr) {
41 return nullptr; 96 return memory;
42 }
43
44 std::unique_ptr<MemoryFileAtOffset> file_memory(new MemoryFileAtOffset);
45 uint64_t map_size;
46 if (offset != 0) {
47 // Only map in a piece of the file.
48 map_size = end - start;
49 } else {
50 map_size = UINT64_MAX;
51 }
52 if (file_memory->Init(name, offset, map_size)) {
53 // It's possible that a non-zero offset might not be pointing to
54 // valid elf data. Check if this is a valid elf, and if not assume
55 // that this was meant to incorporate the entire file.
56 if (offset != 0 && !Elf::IsValidElf(file_memory.get())) {
57 // Don't bother checking the validity that will happen on the elf init.
58 if (file_memory->Init(name, 0)) {
59 elf_offset = offset;
60 return file_memory.release();
61 }
62 // Fall through if the init fails.
63 } else {
64 return file_memory.release();
65 }
66 } 97 }
67 } 98 }
68 99
69 Memory* memory = nullptr; 100 // If the map isn't readable, don't bother trying to read from process memory.
70 if (pid == getpid()) { 101 if (!(flags & PROT_READ)) {
71 memory = new MemoryLocal(); 102 return nullptr;
72 } else {
73 memory = new MemoryRemote(pid);
74 } 103 }
75 return new MemoryRange(memory, start, end); 104 return new MemoryRange(process_memory, start, end);
76} 105}
77 106
78Elf* MapInfo::GetElf(pid_t pid, bool init_gnu_debugdata) { 107Elf* MapInfo::GetElf(const std::shared_ptr<Memory>& process_memory, bool init_gnu_debugdata) {
79 if (elf) { 108 if (elf) {
80 return elf; 109 return elf;
81 } 110 }
82 111
83 elf = new Elf(CreateMemory(pid)); 112 elf = new Elf(CreateMemory(process_memory));
84 if (elf->Init() && init_gnu_debugdata) { 113 if (elf->Init() && init_gnu_debugdata) {
85 elf->InitGnuDebugdata(); 114 elf->InitGnuDebugdata();
86 } 115 }
diff --git a/libunwindstack/Memory.cpp b/libunwindstack/Memory.cpp
index 8c36055c4..32753df6f 100644
--- a/libunwindstack/Memory.cpp
+++ b/libunwindstack/Memory.cpp
@@ -52,6 +52,13 @@ bool Memory::ReadString(uint64_t addr, std::string* string, uint64_t max_read) {
52 return false; 52 return false;
53} 53}
54 54
55std::shared_ptr<Memory> Memory::CreateProcessMemory(pid_t pid) {
56 if (pid == getpid()) {
57 return std::shared_ptr<Memory>(new MemoryLocal());
58 }
59 return std::shared_ptr<Memory>(new MemoryRemote(pid));
60}
61
55bool MemoryBuffer::Read(uint64_t addr, void* dst, size_t size) { 62bool MemoryBuffer::Read(uint64_t addr, void* dst, size_t size) {
56 uint64_t last_read_byte; 63 uint64_t last_read_byte;
57 if (__builtin_add_overflow(size, addr, &last_read_byte)) { 64 if (__builtin_add_overflow(size, addr, &last_read_byte)) {
@@ -249,7 +256,7 @@ bool MemoryOffline::Read(uint64_t addr, void* dst, size_t size) {
249 return true; 256 return true;
250} 257}
251 258
252MemoryRange::MemoryRange(Memory* memory, uint64_t begin, uint64_t end) 259MemoryRange::MemoryRange(const std::shared_ptr<Memory>& memory, uint64_t begin, uint64_t end)
253 : memory_(memory), begin_(begin), length_(end - begin) { 260 : memory_(memory), begin_(begin), length_(end - begin) {
254 CHECK(end > begin); 261 CHECK(end > begin);
255} 262}
diff --git a/libunwindstack/Regs.cpp b/libunwindstack/Regs.cpp
index 4d09c1b0c..69e6512dd 100644
--- a/libunwindstack/Regs.cpp
+++ b/libunwindstack/Regs.cpp
@@ -33,26 +33,6 @@
33 33
34namespace unwindstack { 34namespace unwindstack {
35 35
36template <typename AddressType>
37bool RegsImpl<AddressType>::GetReturnAddressFromDefault(Memory* memory, uint64_t* value) {
38 switch (return_loc_.type) {
39 case LOCATION_REGISTER:
40 CHECK(return_loc_.value < total_regs_);
41 *value = regs_[return_loc_.value];
42 return true;
43 case LOCATION_SP_OFFSET:
44 AddressType return_value;
45 if (!memory->Read(sp_ + return_loc_.value, &return_value, sizeof(return_value))) {
46 return false;
47 }
48 *value = return_value;
49 return true;
50 case LOCATION_UNKNOWN:
51 default:
52 return false;
53 }
54}
55
56RegsArm::RegsArm() 36RegsArm::RegsArm()
57 : RegsImpl<uint32_t>(ARM_REG_LAST, ARM_REG_SP, Location(LOCATION_REGISTER, ARM_REG_LR)) {} 37 : RegsImpl<uint32_t>(ARM_REG_LAST, ARM_REG_SP, Location(LOCATION_REGISTER, ARM_REG_LR)) {}
58 38
@@ -91,6 +71,15 @@ void RegsArm::SetFromRaw() {
91 set_sp(regs_[ARM_REG_SP]); 71 set_sp(regs_[ARM_REG_SP]);
92} 72}
93 73
74bool RegsArm::SetPcFromReturnAddress(Memory*) {
75 if (pc() == regs_[ARM_REG_LR]) {
76 return false;
77 }
78
79 set_pc(regs_[ARM_REG_LR]);
80 return true;
81}
82
94RegsArm64::RegsArm64() 83RegsArm64::RegsArm64()
95 : RegsImpl<uint64_t>(ARM64_REG_LAST, ARM64_REG_SP, Location(LOCATION_REGISTER, ARM64_REG_LR)) {} 84 : RegsImpl<uint64_t>(ARM64_REG_LAST, ARM64_REG_SP, Location(LOCATION_REGISTER, ARM64_REG_LR)) {}
96 85
@@ -114,6 +103,15 @@ void RegsArm64::SetFromRaw() {
114 set_sp(regs_[ARM64_REG_SP]); 103 set_sp(regs_[ARM64_REG_SP]);
115} 104}
116 105
106bool RegsArm64::SetPcFromReturnAddress(Memory*) {
107 if (pc() == regs_[ARM64_REG_LR]) {
108 return false;
109 }
110
111 set_pc(regs_[ARM64_REG_LR]);
112 return true;
113}
114
117RegsX86::RegsX86() 115RegsX86::RegsX86()
118 : RegsImpl<uint32_t>(X86_REG_LAST, X86_REG_SP, Location(LOCATION_SP_OFFSET, -4)) {} 116 : RegsImpl<uint32_t>(X86_REG_LAST, X86_REG_SP, Location(LOCATION_SP_OFFSET, -4)) {}
119 117
@@ -137,6 +135,17 @@ void RegsX86::SetFromRaw() {
137 set_sp(regs_[X86_REG_SP]); 135 set_sp(regs_[X86_REG_SP]);
138} 136}
139 137
138bool RegsX86::SetPcFromReturnAddress(Memory* process_memory) {
139 // Attempt to get the return address from the top of the stack.
140 uint32_t new_pc;
141 if (!process_memory->Read(sp_, &new_pc, sizeof(new_pc)) || new_pc == pc()) {
142 return false;
143 }
144
145 set_pc(new_pc);
146 return true;
147}
148
140RegsX86_64::RegsX86_64() 149RegsX86_64::RegsX86_64()
141 : RegsImpl<uint64_t>(X86_64_REG_LAST, X86_64_REG_SP, Location(LOCATION_SP_OFFSET, -8)) {} 150 : RegsImpl<uint64_t>(X86_64_REG_LAST, X86_64_REG_SP, Location(LOCATION_SP_OFFSET, -8)) {}
142 151
@@ -161,6 +170,17 @@ void RegsX86_64::SetFromRaw() {
161 set_sp(regs_[X86_64_REG_SP]); 170 set_sp(regs_[X86_64_REG_SP]);
162} 171}
163 172
173bool RegsX86_64::SetPcFromReturnAddress(Memory* process_memory) {
174 // Attempt to get the return address from the top of the stack.
175 uint64_t new_pc;
176 if (!process_memory->Read(sp_, &new_pc, sizeof(new_pc)) || new_pc == pc()) {
177 return false;
178 }
179
180 set_pc(new_pc);
181 return true;
182}
183
164static Regs* ReadArm(void* remote_data) { 184static Regs* ReadArm(void* remote_data) {
165 arm_user_regs* user = reinterpret_cast<arm_user_regs*>(remote_data); 185 arm_user_regs* user = reinterpret_cast<arm_user_regs*>(remote_data);
166 186
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp
new file mode 100644
index 000000000..e6489279d
--- /dev/null
+++ b/libunwindstack/Unwinder.cpp
@@ -0,0 +1,183 @@
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define _GNU_SOURCE 1
18#include <elf.h>
19#include <inttypes.h>
20#include <stdint.h>
21#include <string.h>
22#include <sys/types.h>
23#include <unistd.h>
24
25#include <android-base/stringprintf.h>
26
27#include <unwindstack/Elf.h>
28#include <unwindstack/MapInfo.h>
29#include <unwindstack/Unwinder.h>
30
31namespace unwindstack {
32
33void Unwinder::FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, bool adjust_pc) {
34 size_t frame_num = frames_.size();
35 frames_.resize(frame_num + 1);
36 FrameData* frame = &frames_.at(frame_num);
37 frame->num = frame_num;
38 frame->pc = regs_->pc();
39 frame->sp = regs_->sp();
40 frame->rel_pc = rel_pc;
41
42 if (map_info == nullptr) {
43 return;
44 }
45
46 if (adjust_pc) {
47 // Don't adjust the first frame pc.
48 frame->rel_pc = regs_->GetAdjustedPc(rel_pc, elf);
49
50 // Adjust the original pc.
51 frame->pc -= rel_pc - frame->rel_pc;
52 }
53
54 frame->map_name = map_info->name;
55 frame->map_offset = map_info->elf_offset;
56 frame->map_start = map_info->start;
57 frame->map_end = map_info->end;
58 frame->map_flags = map_info->flags;
59 frame->map_load_bias = elf->GetLoadBias();
60
61 if (!elf->GetFunctionName(frame->rel_pc, &frame->function_name, &frame->function_offset)) {
62 frame->function_name = "";
63 frame->function_offset = 0;
64 }
65}
66
67void Unwinder::Unwind(std::set<std::string>* initial_map_names_to_skip) {
68 frames_.clear();
69
70 bool return_address_attempt = false;
71 bool adjust_pc = false;
72 for (; frames_.size() < max_frames_;) {
73 MapInfo* map_info = maps_->Find(regs_->pc());
74
75 uint64_t rel_pc;
76 Elf* elf;
77 if (map_info == nullptr) {
78 rel_pc = regs_->pc();
79 } else {
80 elf = map_info->GetElf(process_memory_, true);
81 rel_pc = elf->GetRelPc(regs_->pc(), map_info);
82 }
83
84 if (map_info == nullptr || initial_map_names_to_skip == nullptr ||
85 initial_map_names_to_skip->find(basename(map_info->name.c_str())) ==
86 initial_map_names_to_skip->end()) {
87 FillInFrame(map_info, elf, rel_pc, adjust_pc);
88 // Once a frame is added, stop skipping frames.
89 initial_map_names_to_skip = nullptr;
90 }
91 adjust_pc = true;
92
93 bool stepped;
94 bool in_device_map = false;
95 if (map_info == nullptr) {
96 stepped = false;
97 } else {
98 if (map_info->flags & MAPS_FLAGS_DEVICE_MAP) {
99 // Do not stop here, fall through in case we are
100 // in the speculative unwind path and need to remove
101 // some of the speculative frames.
102 stepped = false;
103 in_device_map = true;
104 } else {
105 MapInfo* sp_info = maps_->Find(regs_->sp());
106 if (sp_info != nullptr && sp_info->flags & MAPS_FLAGS_DEVICE_MAP) {
107 // Do not stop here, fall through in case we are
108 // in the speculative unwind path and need to remove
109 // some of the speculative frames.
110 stepped = false;
111 in_device_map = true;
112 } else {
113 bool finished;
114 stepped =
115 elf->Step(rel_pc + map_info->elf_offset, regs_, process_memory_.get(), &finished);
116 if (stepped && finished) {
117 break;
118 }
119 }
120 }
121 }
122 if (!stepped) {
123 if (return_address_attempt) {
124 // Remove the speculative frame.
125 frames_.pop_back();
126 break;
127 } else if (in_device_map) {
128 // Do not attempt any other unwinding, pc or sp is in a device
129 // map.
130 break;
131 } else {
132 // Steping didn't work, try this secondary method.
133 if (!regs_->SetPcFromReturnAddress(process_memory_.get())) {
134 break;
135 }
136 return_address_attempt = true;
137 }
138 } else {
139 return_address_attempt = false;
140 }
141 }
142}
143
144std::string Unwinder::FormatFrame(size_t frame_num) {
145 if (frame_num >= frames_.size()) {
146 return "";
147 }
148 return FormatFrame(frames_[frame_num],
149 regs_->MachineType() == EM_ARM || regs_->MachineType() == EM_386);
150}
151
152std::string Unwinder::FormatFrame(const FrameData& frame, bool bits32) {
153 std::string data;
154
155 if (bits32) {
156 data += android::base::StringPrintf(" #%02zu pc %08" PRIx64, frame.num, frame.rel_pc);
157 } else {
158 data += android::base::StringPrintf(" #%02zu pc %016" PRIx64, frame.num, frame.rel_pc);
159 }
160
161 if (frame.map_offset != 0) {
162 data += android::base::StringPrintf(" (offset 0x%" PRIx64 ")", frame.map_offset);
163 }
164
165 if (frame.map_start == frame.map_end) {
166 // No valid map associated with this frame.
167 data += " <unknown>";
168 } else if (!frame.map_name.empty()) {
169 data += " " + frame.map_name;
170 } else {
171 data += android::base::StringPrintf(" <anonymous:%" PRIx64 ">", frame.map_start);
172 }
173 if (!frame.function_name.empty()) {
174 data += " (" + frame.function_name;
175 if (frame.function_offset != 0) {
176 data += android::base::StringPrintf("+%" PRId64, frame.function_offset);
177 }
178 data += ')';
179 }
180 return data;
181}
182
183} // namespace unwindstack
diff --git a/libunwindstack/include/unwindstack/DwarfSection.h b/libunwindstack/include/unwindstack/DwarfSection.h
index 26485ae88..1e843c359 100644
--- a/libunwindstack/include/unwindstack/DwarfSection.h
+++ b/libunwindstack/include/unwindstack/DwarfSection.h
@@ -76,7 +76,7 @@ class DwarfSection {
76 76
77 virtual bool Init(uint64_t offset, uint64_t size) = 0; 77 virtual bool Init(uint64_t offset, uint64_t size) = 0;
78 78
79 virtual bool Eval(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*) = 0; 79 virtual bool Eval(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*) = 0;
80 80
81 virtual bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) = 0; 81 virtual bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) = 0;
82 82
@@ -100,7 +100,7 @@ class DwarfSection {
100 100
101 virtual uint64_t AdjustPcFromFde(uint64_t pc) = 0; 101 virtual uint64_t AdjustPcFromFde(uint64_t pc) = 0;
102 102
103 bool Step(uint64_t pc, Regs* regs, Memory* process_memory); 103 bool Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished);
104 104
105 protected: 105 protected:
106 DwarfMemory memory_; 106 DwarfMemory memory_;
@@ -119,7 +119,7 @@ class DwarfSectionImpl : public DwarfSection {
119 virtual ~DwarfSectionImpl() = default; 119 virtual ~DwarfSectionImpl() = default;
120 120
121 bool Eval(const DwarfCie* cie, Memory* regular_memory, const dwarf_loc_regs_t& loc_regs, 121 bool Eval(const DwarfCie* cie, Memory* regular_memory, const dwarf_loc_regs_t& loc_regs,
122 Regs* regs) override; 122 Regs* regs, bool* finished) override;
123 123
124 const DwarfCie* GetCie(uint64_t offset); 124 const DwarfCie* GetCie(uint64_t offset);
125 bool FillInCie(DwarfCie* cie); 125 bool FillInCie(DwarfCie* cie);
diff --git a/libunwindstack/include/unwindstack/Elf.h b/libunwindstack/include/unwindstack/Elf.h
index d89a7464a..f246beba8 100644
--- a/libunwindstack/include/unwindstack/Elf.h
+++ b/libunwindstack/include/unwindstack/Elf.h
@@ -50,7 +50,7 @@ class Elf {
50 50
51 uint64_t GetRelPc(uint64_t pc, const MapInfo* map_info); 51 uint64_t GetRelPc(uint64_t pc, const MapInfo* map_info);
52 52
53 bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory); 53 bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished);
54 54
55 ElfInterface* CreateInterfaceFromMemory(Memory* memory); 55 ElfInterface* CreateInterfaceFromMemory(Memory* memory);
56 56
@@ -70,6 +70,8 @@ class Elf {
70 70
71 static bool IsValidElf(Memory* memory); 71 static bool IsValidElf(Memory* memory);
72 72
73 static void GetInfo(Memory* memory, bool* valid, uint64_t* size);
74
73 protected: 75 protected:
74 bool valid_ = false; 76 bool valid_ = false;
75 std::unique_ptr<ElfInterface> interface_; 77 std::unique_ptr<ElfInterface> interface_;
diff --git a/libunwindstack/include/unwindstack/ElfInterface.h b/libunwindstack/include/unwindstack/ElfInterface.h
index 5cac0d358..4fe966f78 100644
--- a/libunwindstack/include/unwindstack/ElfInterface.h
+++ b/libunwindstack/include/unwindstack/ElfInterface.h
@@ -59,7 +59,7 @@ class ElfInterface {
59 59
60 virtual bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* offset) = 0; 60 virtual bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* offset) = 0;
61 61
62 virtual bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory); 62 virtual bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished);
63 63
64 Memory* CreateGnuDebugdataMemory(); 64 Memory* CreateGnuDebugdataMemory();
65 65
@@ -102,6 +102,9 @@ class ElfInterface {
102 102
103 virtual bool HandleType(uint64_t, uint32_t) { return false; } 103 virtual bool HandleType(uint64_t, uint32_t) { return false; }
104 104
105 template <typename EhdrType>
106 static void GetMaxSizeWithTemplate(Memory* memory, uint64_t* size);
107
105 Memory* memory_; 108 Memory* memory_;
106 std::unordered_map<uint64_t, LoadInfo> pt_loads_; 109 std::unordered_map<uint64_t, LoadInfo> pt_loads_;
107 uint64_t load_bias_ = 0; 110 uint64_t load_bias_ = 0;
@@ -146,6 +149,10 @@ class ElfInterface32 : public ElfInterface {
146 bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) override { 149 bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) override {
147 return ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(addr, name, func_offset); 150 return ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(addr, name, func_offset);
148 } 151 }
152
153 static void GetMaxSize(Memory* memory, uint64_t* size) {
154 GetMaxSizeWithTemplate<Elf32_Ehdr>(memory, size);
155 }
149}; 156};
150 157
151class ElfInterface64 : public ElfInterface { 158class ElfInterface64 : public ElfInterface {
@@ -166,6 +173,10 @@ class ElfInterface64 : public ElfInterface {
166 bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) override { 173 bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) override {
167 return ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(addr, name, func_offset); 174 return ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(addr, name, func_offset);
168 } 175 }
176
177 static void GetMaxSize(Memory* memory, uint64_t* size) {
178 GetMaxSizeWithTemplate<Elf64_Ehdr>(memory, size);
179 }
169}; 180};
170 181
171} // namespace unwindstack 182} // namespace unwindstack
diff --git a/libunwindstack/include/unwindstack/MapInfo.h b/libunwindstack/include/unwindstack/MapInfo.h
index 185476799..f108766cf 100644
--- a/libunwindstack/include/unwindstack/MapInfo.h
+++ b/libunwindstack/include/unwindstack/MapInfo.h
@@ -40,9 +40,13 @@ struct MapInfo {
40 // instead of a portion of the file. 40 // instead of a portion of the file.
41 uint64_t elf_offset; 41 uint64_t elf_offset;
42 42
43 Memory* CreateMemory(pid_t pid);
44 // This function guarantees it will never return nullptr. 43 // This function guarantees it will never return nullptr.
45 Elf* GetElf(pid_t pid, bool init_gnu_debugdata = false); 44 Elf* GetElf(const std::shared_ptr<Memory>& process_memory, bool init_gnu_debugdata = false);
45
46 private:
47 Memory* GetFileMemory();
48
49 Memory* CreateMemory(const std::shared_ptr<Memory>& process_memory);
46}; 50};
47 51
48} // namespace unwindstack 52} // namespace unwindstack
diff --git a/libunwindstack/include/unwindstack/Memory.h b/libunwindstack/include/unwindstack/Memory.h
index 0c0526616..183b8993a 100644
--- a/libunwindstack/include/unwindstack/Memory.h
+++ b/libunwindstack/include/unwindstack/Memory.h
@@ -21,6 +21,7 @@
21#include <sys/types.h> 21#include <sys/types.h>
22#include <unistd.h> 22#include <unistd.h>
23 23
24#include <memory>
24#include <string> 25#include <string>
25#include <vector> 26#include <vector>
26 27
@@ -31,6 +32,8 @@ class Memory {
31 Memory() = default; 32 Memory() = default;
32 virtual ~Memory() = default; 33 virtual ~Memory() = default;
33 34
35 static std::shared_ptr<Memory> CreateProcessMemory(pid_t pid);
36
34 virtual bool ReadString(uint64_t addr, std::string* string, uint64_t max_read = UINT64_MAX); 37 virtual bool ReadString(uint64_t addr, std::string* string, uint64_t max_read = UINT64_MAX);
35 38
36 virtual bool Read(uint64_t addr, void* dst, size_t size) = 0; 39 virtual bool Read(uint64_t addr, void* dst, size_t size) = 0;
@@ -125,13 +128,13 @@ class MemoryLocal : public Memory {
125 128
126class MemoryRange : public Memory { 129class MemoryRange : public Memory {
127 public: 130 public:
128 MemoryRange(Memory* memory, uint64_t begin, uint64_t end); 131 MemoryRange(const std::shared_ptr<Memory>& memory, uint64_t begin, uint64_t end);
129 virtual ~MemoryRange() { delete memory_; } 132 virtual ~MemoryRange() = default;
130 133
131 bool Read(uint64_t addr, void* dst, size_t size) override; 134 bool Read(uint64_t addr, void* dst, size_t size) override;
132 135
133 private: 136 private:
134 Memory* memory_; 137 std::shared_ptr<Memory> memory_;
135 uint64_t begin_; 138 uint64_t begin_;
136 uint64_t length_; 139 uint64_t length_;
137}; 140};
diff --git a/libunwindstack/include/unwindstack/Regs.h b/libunwindstack/include/unwindstack/Regs.h
index ed4d38ae6..9d3150bf6 100644
--- a/libunwindstack/include/unwindstack/Regs.h
+++ b/libunwindstack/include/unwindstack/Regs.h
@@ -55,14 +55,14 @@ class Regs {
55 virtual uint64_t pc() = 0; 55 virtual uint64_t pc() = 0;
56 virtual uint64_t sp() = 0; 56 virtual uint64_t sp() = 0;
57 57
58 virtual bool GetReturnAddressFromDefault(Memory* memory, uint64_t* value) = 0;
59
60 virtual uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) = 0; 58 virtual uint64_t GetAdjustedPc(uint64_t rel_pc, Elf* elf) = 0;
61 59
62 virtual bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) = 0; 60 virtual bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) = 0;
63 61
64 virtual void SetFromRaw() = 0; 62 virtual void SetFromRaw() = 0;
65 63
64 virtual bool SetPcFromReturnAddress(Memory* process_memory) = 0;
65
66 uint16_t sp_reg() { return sp_reg_; } 66 uint16_t sp_reg() { return sp_reg_; }
67 uint16_t total_regs() { return total_regs_; } 67 uint16_t total_regs() { return total_regs_; }
68 68
@@ -84,8 +84,6 @@ class RegsImpl : public Regs {
84 : Regs(total_regs, sp_reg, return_loc), regs_(total_regs) {} 84 : Regs(total_regs, sp_reg, return_loc), regs_(total_regs) {}
85 virtual ~RegsImpl() = default; 85 virtual ~RegsImpl() = default;
86 86
87 bool GetReturnAddressFromDefault(Memory* memory, uint64_t* value) override;
88
89 uint64_t pc() override { return pc_; } 87 uint64_t pc() override { return pc_; }
90 uint64_t sp() override { return sp_; } 88 uint64_t sp() override { return sp_; }
91 89
@@ -113,6 +111,8 @@ class RegsArm : public RegsImpl<uint32_t> {
113 111
114 void SetFromRaw() override; 112 void SetFromRaw() override;
115 113
114 bool SetPcFromReturnAddress(Memory* process_memory) override;
115
116 bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override; 116 bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
117}; 117};
118 118
@@ -127,6 +127,8 @@ class RegsArm64 : public RegsImpl<uint64_t> {
127 127
128 void SetFromRaw() override; 128 void SetFromRaw() override;
129 129
130 bool SetPcFromReturnAddress(Memory* process_memory) override;
131
130 bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override; 132 bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
131}; 133};
132 134
@@ -141,6 +143,8 @@ class RegsX86 : public RegsImpl<uint32_t> {
141 143
142 void SetFromRaw() override; 144 void SetFromRaw() override;
143 145
146 bool SetPcFromReturnAddress(Memory* process_memory) override;
147
144 bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override; 148 bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
145 149
146 void SetFromUcontext(x86_ucontext_t* ucontext); 150 void SetFromUcontext(x86_ucontext_t* ucontext);
@@ -157,6 +161,8 @@ class RegsX86_64 : public RegsImpl<uint64_t> {
157 161
158 void SetFromRaw() override; 162 void SetFromRaw() override;
159 163
164 bool SetPcFromReturnAddress(Memory* process_memory) override;
165
160 bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override; 166 bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
161 167
162 void SetFromUcontext(x86_64_ucontext_t* ucontext); 168 void SetFromUcontext(x86_64_ucontext_t* ucontext);
diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h
new file mode 100644
index 000000000..71703b495
--- /dev/null
+++ b/libunwindstack/include/unwindstack/Unwinder.h
@@ -0,0 +1,84 @@
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _LIBUNWINDSTACK_UNWINDER_H
18#define _LIBUNWINDSTACK_UNWINDER_H
19
20#include <stdint.h>
21#include <sys/types.h>
22
23#include <memory>
24#include <set>
25#include <string>
26#include <vector>
27
28#include <unwindstack/Maps.h>
29#include <unwindstack/Memory.h>
30#include <unwindstack/Regs.h>
31
32namespace unwindstack {
33
34// Forward declarations.
35class Elf;
36
37struct FrameData {
38 size_t num;
39
40 uint64_t rel_pc;
41 uint64_t pc;
42 uint64_t sp;
43
44 std::string function_name;
45 uint64_t function_offset;
46
47 std::string map_name;
48 uint64_t map_offset;
49 uint64_t map_start;
50 uint64_t map_end;
51 uint64_t map_load_bias;
52 int map_flags;
53};
54
55class Unwinder {
56 public:
57 Unwinder(size_t max_frames, Maps* maps, Regs* regs, std::shared_ptr<Memory> process_memory)
58 : max_frames_(max_frames), maps_(maps), regs_(regs), process_memory_(process_memory) {
59 frames_.reserve(max_frames);
60 }
61 ~Unwinder() = default;
62
63 void Unwind(std::set<std::string>* initial_map_names_to_skip = nullptr);
64
65 size_t NumFrames() { return frames_.size(); }
66
67 const std::vector<FrameData>& frames() { return frames_; }
68
69 std::string FormatFrame(size_t frame_num);
70 static std::string FormatFrame(const FrameData& frame, bool bits32);
71
72 private:
73 void FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, bool adjust_pc);
74
75 size_t max_frames_;
76 Maps* maps_;
77 Regs* regs_;
78 std::vector<FrameData> frames_;
79 std::shared_ptr<Memory> process_memory_;
80};
81
82} // namespace unwindstack
83
84#endif // _LIBUNWINDSTACK_UNWINDER_H
diff --git a/libunwindstack/tests/DwarfDebugFrameTest.cpp b/libunwindstack/tests/DwarfDebugFrameTest.cpp
index 69813e5ce..90baabedc 100644
--- a/libunwindstack/tests/DwarfDebugFrameTest.cpp
+++ b/libunwindstack/tests/DwarfDebugFrameTest.cpp
@@ -25,7 +25,6 @@
25 25
26#include "LogFake.h" 26#include "LogFake.h"
27#include "MemoryFake.h" 27#include "MemoryFake.h"
28#include "RegsFake.h"
29 28
30namespace unwindstack { 29namespace unwindstack {
31 30
diff --git a/libunwindstack/tests/DwarfEhFrameTest.cpp b/libunwindstack/tests/DwarfEhFrameTest.cpp
index 07159b0e0..21114da8c 100644
--- a/libunwindstack/tests/DwarfEhFrameTest.cpp
+++ b/libunwindstack/tests/DwarfEhFrameTest.cpp
@@ -25,7 +25,6 @@
25 25
26#include "LogFake.h" 26#include "LogFake.h"
27#include "MemoryFake.h" 27#include "MemoryFake.h"
28#include "RegsFake.h"
29 28
30namespace unwindstack { 29namespace unwindstack {
31 30
diff --git a/libunwindstack/tests/DwarfOpTest.cpp b/libunwindstack/tests/DwarfOpTest.cpp
index 47a40cfde..2d5007b8f 100644
--- a/libunwindstack/tests/DwarfOpTest.cpp
+++ b/libunwindstack/tests/DwarfOpTest.cpp
@@ -1486,7 +1486,7 @@ TYPED_TEST_P(DwarfOpTest, op_breg) {
1486 } 1486 }
1487 this->op_memory_.SetMemory(0, opcode_buffer); 1487 this->op_memory_.SetMemory(0, opcode_buffer);
1488 1488
1489 RegsFake<TypeParam> regs(32, 10); 1489 RegsImplFake<TypeParam> regs(32, 10);
1490 for (size_t i = 0; i < 32; i++) { 1490 for (size_t i = 0; i < 32; i++) {
1491 regs[i] = i + 10; 1491 regs[i] = i + 10;
1492 } 1492 }
@@ -1518,7 +1518,7 @@ TYPED_TEST_P(DwarfOpTest, op_breg_invalid_register) {
1518 }; 1518 };
1519 this->op_memory_.SetMemory(0, opcode_buffer); 1519 this->op_memory_.SetMemory(0, opcode_buffer);
1520 1520
1521 RegsFake<TypeParam> regs(16, 10); 1521 RegsImplFake<TypeParam> regs(16, 10);
1522 for (size_t i = 0; i < 16; i++) { 1522 for (size_t i = 0; i < 16; i++) {
1523 regs[i] = i + 10; 1523 regs[i] = i + 10;
1524 } 1524 }
@@ -1544,7 +1544,7 @@ TYPED_TEST_P(DwarfOpTest, op_bregx) {
1544 0x92, 0x80, 0x15, 0x80, 0x02}; 1544 0x92, 0x80, 0x15, 0x80, 0x02};
1545 this->op_memory_.SetMemory(0, opcode_buffer); 1545 this->op_memory_.SetMemory(0, opcode_buffer);
1546 1546
1547 RegsFake<TypeParam> regs(10, 10); 1547 RegsImplFake<TypeParam> regs(10, 10);
1548 regs[5] = 0x45; 1548 regs[5] = 0x45;
1549 regs[6] = 0x190; 1549 regs[6] = 0x190;
1550 this->op_->set_regs(&regs); 1550 this->op_->set_regs(&regs);
diff --git a/libunwindstack/tests/DwarfSectionImplTest.cpp b/libunwindstack/tests/DwarfSectionImplTest.cpp
index b87153995..c701a295e 100644
--- a/libunwindstack/tests/DwarfSectionImplTest.cpp
+++ b/libunwindstack/tests/DwarfSectionImplTest.cpp
@@ -90,7 +90,7 @@ TYPED_TEST_CASE_P(DwarfSectionImplTest);
90 90
91TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_eval_fail) { 91TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_eval_fail) {
92 DwarfCie cie{.version = 3, .return_address_register = 5}; 92 DwarfCie cie{.version = 3, .return_address_register = 5};
93 RegsFake<TypeParam> regs(10, 9); 93 RegsImplFake<TypeParam> regs(10, 9);
94 dwarf_loc_regs_t loc_regs; 94 dwarf_loc_regs_t loc_regs;
95 95
96 regs.set_pc(0x100); 96 regs.set_pc(0x100);
@@ -98,13 +98,14 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_eval_fail) {
98 regs[5] = 0x20; 98 regs[5] = 0x20;
99 regs[9] = 0x3000; 99 regs[9] = 0x3000;
100 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}}; 100 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}};
101 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs)); 101 bool finished;
102 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
102 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error()); 103 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error());
103} 104}
104 105
105TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_no_stack) { 106TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_no_stack) {
106 DwarfCie cie{.version = 3, .return_address_register = 5}; 107 DwarfCie cie{.version = 3, .return_address_register = 5};
107 RegsFake<TypeParam> regs(10, 9); 108 RegsImplFake<TypeParam> regs(10, 9);
108 dwarf_loc_regs_t loc_regs; 109 dwarf_loc_regs_t loc_regs;
109 110
110 regs.set_pc(0x100); 111 regs.set_pc(0x100);
@@ -113,13 +114,14 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_no_stack) {
113 regs[9] = 0x3000; 114 regs[9] = 0x3000;
114 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x96, 0x96, 0x96}); 115 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x96, 0x96, 0x96});
115 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}}; 116 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}};
116 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs)); 117 bool finished;
118 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
117 EXPECT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->section_->last_error()); 119 EXPECT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->section_->last_error());
118} 120}
119 121
120TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr) { 122TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr) {
121 DwarfCie cie{.version = 3, .return_address_register = 5}; 123 DwarfCie cie{.version = 3, .return_address_register = 5};
122 RegsFake<TypeParam> regs(10, 9); 124 RegsImplFake<TypeParam> regs(10, 9);
123 dwarf_loc_regs_t loc_regs; 125 dwarf_loc_regs_t loc_regs;
124 126
125 regs.set_pc(0x100); 127 regs.set_pc(0x100);
@@ -130,14 +132,16 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr) {
130 TypeParam cfa_value = 0x12345; 132 TypeParam cfa_value = 0x12345;
131 this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value)); 133 this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value));
132 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5000}}; 134 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5000}};
133 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs)); 135 bool finished;
136 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
137 EXPECT_FALSE(finished);
134 EXPECT_EQ(0x12345U, regs.sp()); 138 EXPECT_EQ(0x12345U, regs.sp());
135 EXPECT_EQ(0x20U, regs.pc()); 139 EXPECT_EQ(0x20U, regs.pc());
136} 140}
137 141
138TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_val_expr) { 142TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_val_expr) {
139 DwarfCie cie{.version = 3, .return_address_register = 5}; 143 DwarfCie cie{.version = 3, .return_address_register = 5};
140 RegsFake<TypeParam> regs(10, 9); 144 RegsImplFake<TypeParam> regs(10, 9);
141 dwarf_loc_regs_t loc_regs; 145 dwarf_loc_regs_t loc_regs;
142 146
143 regs.set_pc(0x100); 147 regs.set_pc(0x100);
@@ -146,14 +150,16 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_val_expr) {
146 regs[9] = 0x3000; 150 regs[9] = 0x3000;
147 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80}); 151 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
148 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5000}}; 152 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5000}};
149 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs)); 153 bool finished;
154 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
155 ASSERT_FALSE(finished);
150 EXPECT_EQ(0x80000000U, regs.sp()); 156 EXPECT_EQ(0x80000000U, regs.sp());
151 EXPECT_EQ(0x20U, regs.pc()); 157 EXPECT_EQ(0x20U, regs.pc());
152} 158}
153 159
154TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_is_register) { 160TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_is_register) {
155 DwarfCie cie{.version = 3, .return_address_register = 5}; 161 DwarfCie cie{.version = 3, .return_address_register = 5};
156 RegsFake<TypeParam> regs(10, 9); 162 RegsImplFake<TypeParam> regs(10, 9);
157 dwarf_loc_regs_t loc_regs; 163 dwarf_loc_regs_t loc_regs;
158 164
159 regs.set_pc(0x100); 165 regs.set_pc(0x100);
@@ -162,59 +168,63 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_is_register) {
162 regs[9] = 0x3000; 168 regs[9] = 0x3000;
163 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x50, 0x96, 0x96}); 169 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x50, 0x96, 0x96});
164 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}}; 170 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}};
165 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs)); 171 bool finished;
172 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
166 EXPECT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->section_->last_error()); 173 EXPECT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->section_->last_error());
167} 174}
168 175
169TYPED_TEST_P(DwarfSectionImplTest, Eval_bad_regs) { 176TYPED_TEST_P(DwarfSectionImplTest, Eval_bad_regs) {
170 DwarfCie cie{.return_address_register = 60}; 177 DwarfCie cie{.return_address_register = 60};
171 RegsFake<TypeParam> regs(10, 9); 178 RegsImplFake<TypeParam> regs(10, 9);
172 dwarf_loc_regs_t loc_regs; 179 dwarf_loc_regs_t loc_regs;
173 180
174 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs)); 181 bool finished;
182 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
175 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error()); 183 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error());
176} 184}
177 185
178TYPED_TEST_P(DwarfSectionImplTest, Eval_no_cfa) { 186TYPED_TEST_P(DwarfSectionImplTest, Eval_no_cfa) {
179 DwarfCie cie{.return_address_register = 5}; 187 DwarfCie cie{.return_address_register = 5};
180 RegsFake<TypeParam> regs(10, 9); 188 RegsImplFake<TypeParam> regs(10, 9);
181 dwarf_loc_regs_t loc_regs; 189 dwarf_loc_regs_t loc_regs;
182 190
183 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs)); 191 bool finished;
192 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
184 EXPECT_EQ(DWARF_ERROR_CFA_NOT_DEFINED, this->section_->last_error()); 193 EXPECT_EQ(DWARF_ERROR_CFA_NOT_DEFINED, this->section_->last_error());
185} 194}
186 195
187TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_bad) { 196TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_bad) {
188 DwarfCie cie{.return_address_register = 5}; 197 DwarfCie cie{.return_address_register = 5};
189 RegsFake<TypeParam> regs(10, 9); 198 RegsImplFake<TypeParam> regs(10, 9);
190 dwarf_loc_regs_t loc_regs; 199 dwarf_loc_regs_t loc_regs;
191 200
192 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {20, 0}}; 201 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {20, 0}};
193 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs)); 202 bool finished;
203 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
194 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error()); 204 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error());
195 205
196 this->section_->TestClearError(); 206 this->section_->TestClearError();
197 loc_regs.erase(CFA_REG); 207 loc_regs.erase(CFA_REG);
198 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_INVALID, {0, 0}}; 208 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_INVALID, {0, 0}};
199 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs)); 209 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
200 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error()); 210 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error());
201 211
202 this->section_->TestClearError(); 212 this->section_->TestClearError();
203 loc_regs.erase(CFA_REG); 213 loc_regs.erase(CFA_REG);
204 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_OFFSET, {0, 0}}; 214 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_OFFSET, {0, 0}};
205 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs)); 215 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
206 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error()); 216 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error());
207 217
208 this->section_->TestClearError(); 218 this->section_->TestClearError();
209 loc_regs.erase(CFA_REG); 219 loc_regs.erase(CFA_REG);
210 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0, 0}}; 220 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0, 0}};
211 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs)); 221 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
212 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error()); 222 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error());
213} 223}
214 224
215TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_prev) { 225TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_prev) {
216 DwarfCie cie{.return_address_register = 5}; 226 DwarfCie cie{.return_address_register = 5};
217 RegsFake<TypeParam> regs(10, 9); 227 RegsImplFake<TypeParam> regs(10, 9);
218 dwarf_loc_regs_t loc_regs; 228 dwarf_loc_regs_t loc_regs;
219 229
220 regs.set_pc(0x100); 230 regs.set_pc(0x100);
@@ -222,14 +232,16 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_prev) {
222 regs[5] = 0x20; 232 regs[5] = 0x20;
223 regs[9] = 0x3000; 233 regs[9] = 0x3000;
224 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {9, 0}}; 234 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {9, 0}};
225 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs)); 235 bool finished;
236 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
237 EXPECT_FALSE(finished);
226 EXPECT_EQ(0x20U, regs.pc()); 238 EXPECT_EQ(0x20U, regs.pc());
227 EXPECT_EQ(0x2000U, regs.sp()); 239 EXPECT_EQ(0x2000U, regs.sp());
228} 240}
229 241
230TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_from_value) { 242TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_from_value) {
231 DwarfCie cie{.return_address_register = 5}; 243 DwarfCie cie{.return_address_register = 5};
232 RegsFake<TypeParam> regs(10, 9); 244 RegsImplFake<TypeParam> regs(10, 9);
233 dwarf_loc_regs_t loc_regs; 245 dwarf_loc_regs_t loc_regs;
234 246
235 regs.set_pc(0x100); 247 regs.set_pc(0x100);
@@ -238,14 +250,16 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_from_value) {
238 regs[6] = 0x4000; 250 regs[6] = 0x4000;
239 regs[9] = 0x3000; 251 regs[9] = 0x3000;
240 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {6, 0}}; 252 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {6, 0}};
241 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs)); 253 bool finished;
254 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
255 EXPECT_FALSE(finished);
242 EXPECT_EQ(0x20U, regs.pc()); 256 EXPECT_EQ(0x20U, regs.pc());
243 EXPECT_EQ(0x4000U, regs.sp()); 257 EXPECT_EQ(0x4000U, regs.sp());
244} 258}
245 259
246TYPED_TEST_P(DwarfSectionImplTest, Eval_double_indirection) { 260TYPED_TEST_P(DwarfSectionImplTest, Eval_double_indirection) {
247 DwarfCie cie{.return_address_register = 5}; 261 DwarfCie cie{.return_address_register = 5};
248 RegsFake<TypeParam> regs(10, 9); 262 RegsImplFake<TypeParam> regs(10, 9);
249 dwarf_loc_regs_t loc_regs; 263 dwarf_loc_regs_t loc_regs;
250 264
251 regs.set_pc(0x100); 265 regs.set_pc(0x100);
@@ -254,13 +268,14 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_double_indirection) {
254 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; 268 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
255 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {3, 0}}; 269 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {3, 0}};
256 loc_regs[9] = DwarfLocation{DWARF_LOCATION_REGISTER, {1, 0}}; 270 loc_regs[9] = DwarfLocation{DWARF_LOCATION_REGISTER, {1, 0}};
257 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs)); 271 bool finished;
272 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
258 EXPECT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->section_->last_error()); 273 EXPECT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->section_->last_error());
259} 274}
260 275
261TYPED_TEST_P(DwarfSectionImplTest, Eval_invalid_register) { 276TYPED_TEST_P(DwarfSectionImplTest, Eval_invalid_register) {
262 DwarfCie cie{.return_address_register = 5}; 277 DwarfCie cie{.return_address_register = 5};
263 RegsFake<TypeParam> regs(10, 9); 278 RegsImplFake<TypeParam> regs(10, 9);
264 dwarf_loc_regs_t loc_regs; 279 dwarf_loc_regs_t loc_regs;
265 280
266 regs.set_pc(0x100); 281 regs.set_pc(0x100);
@@ -268,13 +283,14 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_invalid_register) {
268 regs[8] = 0x10; 283 regs[8] = 0x10;
269 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; 284 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
270 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {10, 0}}; 285 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {10, 0}};
271 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs)); 286 bool finished;
287 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
272 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error()); 288 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error());
273} 289}
274 290
275TYPED_TEST_P(DwarfSectionImplTest, Eval_different_reg_locations) { 291TYPED_TEST_P(DwarfSectionImplTest, Eval_different_reg_locations) {
276 DwarfCie cie{.return_address_register = 5}; 292 DwarfCie cie{.return_address_register = 5};
277 RegsFake<TypeParam> regs(10, 9); 293 RegsImplFake<TypeParam> regs(10, 9);
278 dwarf_loc_regs_t loc_regs; 294 dwarf_loc_regs_t loc_regs;
279 295
280 if (sizeof(TypeParam) == sizeof(uint64_t)) { 296 if (sizeof(TypeParam) == sizeof(uint64_t)) {
@@ -292,7 +308,9 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_different_reg_locations) {
292 loc_regs[1] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0x100, 0}}; 308 loc_regs[1] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0x100, 0}};
293 loc_regs[2] = DwarfLocation{DWARF_LOCATION_OFFSET, {0x50, 0}}; 309 loc_regs[2] = DwarfLocation{DWARF_LOCATION_OFFSET, {0x50, 0}};
294 loc_regs[3] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}}; 310 loc_regs[3] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}};
295 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs)); 311 bool finished;
312 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
313 EXPECT_FALSE(finished);
296 EXPECT_EQ(0x10U, regs.pc()); 314 EXPECT_EQ(0x10U, regs.pc());
297 EXPECT_EQ(0x2100U, regs.sp()); 315 EXPECT_EQ(0x2100U, regs.sp());
298 EXPECT_EQ(0x2200U, regs[1]); 316 EXPECT_EQ(0x2200U, regs[1]);
@@ -306,7 +324,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_different_reg_locations) {
306 324
307TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address_undefined) { 325TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address_undefined) {
308 DwarfCie cie{.return_address_register = 5}; 326 DwarfCie cie{.return_address_register = 5};
309 RegsFake<TypeParam> regs(10, 9); 327 RegsImplFake<TypeParam> regs(10, 9);
310 dwarf_loc_regs_t loc_regs; 328 dwarf_loc_regs_t loc_regs;
311 329
312 regs.set_pc(0x100); 330 regs.set_pc(0x100);
@@ -315,14 +333,16 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address_undefined) {
315 regs[8] = 0x10; 333 regs[8] = 0x10;
316 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; 334 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
317 loc_regs[5] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}}; 335 loc_regs[5] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}};
318 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs)); 336 bool finished;
337 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
338 EXPECT_TRUE(finished);
319 EXPECT_EQ(0U, regs.pc()); 339 EXPECT_EQ(0U, regs.pc());
320 EXPECT_EQ(0x10U, regs.sp()); 340 EXPECT_EQ(0x10U, regs.sp());
321} 341}
322 342
323TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address) { 343TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address) {
324 DwarfCie cie{.return_address_register = 5}; 344 DwarfCie cie{.return_address_register = 5};
325 RegsFake<TypeParam> regs(10, 9); 345 RegsImplFake<TypeParam> regs(10, 9);
326 dwarf_loc_regs_t loc_regs; 346 dwarf_loc_regs_t loc_regs;
327 347
328 regs.set_pc(0x100); 348 regs.set_pc(0x100);
@@ -330,14 +350,16 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address) {
330 regs[5] = 0x20; 350 regs[5] = 0x20;
331 regs[8] = 0x10; 351 regs[8] = 0x10;
332 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; 352 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
333 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs)); 353 bool finished;
354 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
355 EXPECT_FALSE(finished);
334 EXPECT_EQ(0x20U, regs.pc()); 356 EXPECT_EQ(0x20U, regs.pc());
335 EXPECT_EQ(0x10U, regs.sp()); 357 EXPECT_EQ(0x10U, regs.sp());
336} 358}
337 359
338TYPED_TEST_P(DwarfSectionImplTest, Eval_ignore_large_reg_loc) { 360TYPED_TEST_P(DwarfSectionImplTest, Eval_ignore_large_reg_loc) {
339 DwarfCie cie{.return_address_register = 5}; 361 DwarfCie cie{.return_address_register = 5};
340 RegsFake<TypeParam> regs(10, 9); 362 RegsImplFake<TypeParam> regs(10, 9);
341 dwarf_loc_regs_t loc_regs; 363 dwarf_loc_regs_t loc_regs;
342 364
343 regs.set_pc(0x100); 365 regs.set_pc(0x100);
@@ -347,14 +369,16 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_ignore_large_reg_loc) {
347 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; 369 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
348 // This should not result in any errors. 370 // This should not result in any errors.
349 loc_regs[20] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; 371 loc_regs[20] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
350 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs)); 372 bool finished;
373 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
374 EXPECT_FALSE(finished);
351 EXPECT_EQ(0x20U, regs.pc()); 375 EXPECT_EQ(0x20U, regs.pc());
352 EXPECT_EQ(0x10U, regs.sp()); 376 EXPECT_EQ(0x10U, regs.sp());
353} 377}
354 378
355TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_expr) { 379TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_expr) {
356 DwarfCie cie{.version = 3, .return_address_register = 5}; 380 DwarfCie cie{.version = 3, .return_address_register = 5};
357 RegsFake<TypeParam> regs(10, 9); 381 RegsImplFake<TypeParam> regs(10, 9);
358 dwarf_loc_regs_t loc_regs; 382 dwarf_loc_regs_t loc_regs;
359 383
360 regs.set_pc(0x100); 384 regs.set_pc(0x100);
@@ -365,14 +389,16 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_expr) {
365 this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value)); 389 this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value));
366 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; 390 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
367 loc_regs[5] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5000}}; 391 loc_regs[5] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5000}};
368 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs)); 392 bool finished;
393 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
394 EXPECT_FALSE(finished);
369 EXPECT_EQ(0x3000U, regs.sp()); 395 EXPECT_EQ(0x3000U, regs.sp());
370 EXPECT_EQ(0x12345U, regs.pc()); 396 EXPECT_EQ(0x12345U, regs.pc());
371} 397}
372 398
373TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) { 399TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) {
374 DwarfCie cie{.version = 3, .return_address_register = 5}; 400 DwarfCie cie{.version = 3, .return_address_register = 5};
375 RegsFake<TypeParam> regs(10, 9); 401 RegsImplFake<TypeParam> regs(10, 9);
376 dwarf_loc_regs_t loc_regs; 402 dwarf_loc_regs_t loc_regs;
377 403
378 regs.set_pc(0x100); 404 regs.set_pc(0x100);
@@ -381,14 +407,16 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) {
381 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80}); 407 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
382 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; 408 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
383 loc_regs[5] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5000}}; 409 loc_regs[5] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5000}};
384 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs)); 410 bool finished;
411 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
412 EXPECT_FALSE(finished);
385 EXPECT_EQ(0x3000U, regs.sp()); 413 EXPECT_EQ(0x3000U, regs.sp());
386 EXPECT_EQ(0x80000000U, regs.pc()); 414 EXPECT_EQ(0x80000000U, regs.pc());
387} 415}
388 416
389TYPED_TEST_P(DwarfSectionImplTest, Eval_same_cfa_same_pc) { 417TYPED_TEST_P(DwarfSectionImplTest, Eval_same_cfa_same_pc) {
390 DwarfCie cie{.version = 3, .return_address_register = 5}; 418 DwarfCie cie{.version = 3, .return_address_register = 5};
391 RegsFake<TypeParam> regs(10, 9); 419 RegsImplFake<TypeParam> regs(10, 9);
392 dwarf_loc_regs_t loc_regs; 420 dwarf_loc_regs_t loc_regs;
393 421
394 regs.set_pc(0x100); 422 regs.set_pc(0x100);
@@ -396,7 +424,8 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_same_cfa_same_pc) {
396 regs[5] = 0x100; 424 regs[5] = 0x100;
397 regs[8] = 0x2000; 425 regs[8] = 0x2000;
398 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}}; 426 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
399 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs)); 427 bool finished;
428 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
400 EXPECT_EQ(0x2000U, regs.sp()); 429 EXPECT_EQ(0x2000U, regs.sp());
401 EXPECT_EQ(0x100U, regs.pc()); 430 EXPECT_EQ(0x100U, regs.pc());
402} 431}
diff --git a/libunwindstack/tests/DwarfSectionTest.cpp b/libunwindstack/tests/DwarfSectionTest.cpp
index fc67063c5..3fcd2b61f 100644
--- a/libunwindstack/tests/DwarfSectionTest.cpp
+++ b/libunwindstack/tests/DwarfSectionTest.cpp
@@ -32,7 +32,7 @@ class MockDwarfSection : public DwarfSection {
32 32
33 MOCK_METHOD4(Log, bool(uint8_t, uint64_t, uint64_t, const DwarfFde*)); 33 MOCK_METHOD4(Log, bool(uint8_t, uint64_t, uint64_t, const DwarfFde*));
34 34
35 MOCK_METHOD4(Eval, bool(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*)); 35 MOCK_METHOD5(Eval, bool(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*));
36 36
37 MOCK_METHOD3(GetCfaLocationInfo, bool(uint64_t, const DwarfFde*, dwarf_loc_regs_t*)); 37 MOCK_METHOD3(GetCfaLocationInfo, bool(uint64_t, const DwarfFde*, dwarf_loc_regs_t*));
38 38
@@ -104,7 +104,8 @@ TEST_F(DwarfSectionTest, Step_fail_fde) {
104 EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x1000, ::testing::_)) 104 EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x1000, ::testing::_))
105 .WillOnce(::testing::Return(false)); 105 .WillOnce(::testing::Return(false));
106 106
107 ASSERT_FALSE(mock_section.Step(0x1000, nullptr, nullptr)); 107 bool finished;
108 ASSERT_FALSE(mock_section.Step(0x1000, nullptr, nullptr, &finished));
108} 109}
109 110
110TEST_F(DwarfSectionTest, Step_fail_cie_null) { 111TEST_F(DwarfSectionTest, Step_fail_cie_null) {
@@ -118,7 +119,8 @@ TEST_F(DwarfSectionTest, Step_fail_cie_null) {
118 .WillOnce(::testing::Return(true)); 119 .WillOnce(::testing::Return(true));
119 EXPECT_CALL(mock_section, GetFdeFromOffset(::testing::_)).WillOnce(::testing::Return(&fde)); 120 EXPECT_CALL(mock_section, GetFdeFromOffset(::testing::_)).WillOnce(::testing::Return(&fde));
120 121
121 ASSERT_FALSE(mock_section.Step(0x1000, nullptr, nullptr)); 122 bool finished;
123 ASSERT_FALSE(mock_section.Step(0x1000, nullptr, nullptr, &finished));
122} 124}
123 125
124TEST_F(DwarfSectionTest, Step_fail_cfa_location) { 126TEST_F(DwarfSectionTest, Step_fail_cfa_location) {
@@ -136,7 +138,8 @@ TEST_F(DwarfSectionTest, Step_fail_cfa_location) {
136 EXPECT_CALL(mock_section, GetCfaLocationInfo(0x1000, &fde, ::testing::_)) 138 EXPECT_CALL(mock_section, GetCfaLocationInfo(0x1000, &fde, ::testing::_))
137 .WillOnce(::testing::Return(false)); 139 .WillOnce(::testing::Return(false));
138 140
139 ASSERT_FALSE(mock_section.Step(0x1000, nullptr, nullptr)); 141 bool finished;
142 ASSERT_FALSE(mock_section.Step(0x1000, nullptr, nullptr, &finished));
140} 143}
141 144
142TEST_F(DwarfSectionTest, Step_pass) { 145TEST_F(DwarfSectionTest, Step_pass) {
@@ -155,10 +158,11 @@ TEST_F(DwarfSectionTest, Step_pass) {
155 .WillOnce(::testing::Return(true)); 158 .WillOnce(::testing::Return(true));
156 159
157 MemoryFake process; 160 MemoryFake process;
158 EXPECT_CALL(mock_section, Eval(&cie, &process, ::testing::_, nullptr)) 161 EXPECT_CALL(mock_section, Eval(&cie, &process, ::testing::_, nullptr, ::testing::_))
159 .WillOnce(::testing::Return(true)); 162 .WillOnce(::testing::Return(true));
160 163
161 ASSERT_TRUE(mock_section.Step(0x1000, nullptr, &process)); 164 bool finished;
165 ASSERT_TRUE(mock_section.Step(0x1000, nullptr, &process, &finished));
162} 166}
163 167
164} // namespace unwindstack 168} // namespace unwindstack
diff --git a/libunwindstack/tests/ElfFake.cpp b/libunwindstack/tests/ElfFake.cpp
new file mode 100644
index 000000000..71f7f6b23
--- /dev/null
+++ b/libunwindstack/tests/ElfFake.cpp
@@ -0,0 +1,65 @@
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdint.h>
18
19#include <deque>
20#include <string>
21
22#include <unwindstack/Elf.h>
23#include <unwindstack/ElfInterface.h>
24#include <unwindstack/Memory.h>
25#include <unwindstack/Regs.h>
26
27#include "ElfFake.h"
28#include "RegsFake.h"
29
30namespace unwindstack {
31
32std::deque<FunctionData> ElfInterfaceFake::functions_;
33std::deque<StepData> ElfInterfaceFake::steps_;
34
35bool ElfInterfaceFake::GetFunctionName(uint64_t, std::string* name, uint64_t* offset) {
36 if (functions_.empty()) {
37 return false;
38 }
39 auto entry = functions_.front();
40 functions_.pop_front();
41 *name = entry.name;
42 *offset = entry.offset;
43 return true;
44}
45
46bool ElfInterfaceFake::Step(uint64_t, Regs* regs, Memory*, bool* finished) {
47 if (steps_.empty()) {
48 return false;
49 }
50 auto entry = steps_.front();
51 steps_.pop_front();
52
53 if (entry.pc == 0 && entry.sp == 0 && !entry.finished) {
54 // Pretend as though there is no frame.
55 return false;
56 }
57
58 RegsFake* fake_regs = reinterpret_cast<RegsFake*>(regs);
59 fake_regs->FakeSetPc(entry.pc);
60 fake_regs->FakeSetSp(entry.sp);
61 *finished = entry.finished;
62 return true;
63}
64
65} // namespace unwindstack
diff --git a/libunwindstack/tests/ElfFake.h b/libunwindstack/tests/ElfFake.h
new file mode 100644
index 000000000..4359bca4e
--- /dev/null
+++ b/libunwindstack/tests/ElfFake.h
@@ -0,0 +1,84 @@
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _LIBUNWINDSTACK_TESTS_ELF_FAKE_H
18#define _LIBUNWINDSTACK_TESTS_ELF_FAKE_H
19
20#include <stdint.h>
21
22#include <deque>
23#include <string>
24
25#include <unwindstack/Elf.h>
26#include <unwindstack/ElfInterface.h>
27#include <unwindstack/Memory.h>
28#include <unwindstack/Regs.h>
29
30namespace unwindstack {
31
32struct StepData {
33 StepData(uint64_t pc, uint64_t sp, bool finished) : pc(pc), sp(sp), finished(finished) {}
34 uint64_t pc;
35 uint64_t sp;
36 bool finished;
37};
38
39struct FunctionData {
40 FunctionData(std::string name, uint64_t offset) : name(name), offset(offset) {}
41
42 std::string name;
43 uint64_t offset;
44};
45
46class ElfFake : public Elf {
47 public:
48 ElfFake(Memory* memory) : Elf(memory) { valid_ = true; }
49 virtual ~ElfFake() = default;
50
51 void FakeSetInterface(ElfInterface* interface) { interface_.reset(interface); }
52};
53
54class ElfInterfaceFake : public ElfInterface {
55 public:
56 ElfInterfaceFake(Memory* memory) : ElfInterface(memory) {}
57 virtual ~ElfInterfaceFake() = default;
58
59 bool Init() override { return false; }
60 void InitHeaders() override {}
61 bool GetSoname(std::string*) override { return false; }
62
63 bool GetFunctionName(uint64_t, std::string*, uint64_t*) override;
64
65 bool Step(uint64_t, Regs*, Memory*, bool*) override;
66
67 void FakeSetLoadBias(uint64_t load_bias) { load_bias_ = load_bias; }
68
69 static void FakePushFunctionData(const FunctionData data) { functions_.push_back(data); }
70 static void FakePushStepData(const StepData data) { steps_.push_back(data); }
71
72 static void FakeClear() {
73 functions_.clear();
74 steps_.clear();
75 }
76
77 private:
78 static std::deque<FunctionData> functions_;
79 static std::deque<StepData> steps_;
80};
81
82} // namespace unwindstack
83
84#endif // _LIBUNWINDSTACK_TESTS_ELF_FAKE_H
diff --git a/libunwindstack/tests/ElfInterfaceArmTest.cpp b/libunwindstack/tests/ElfInterfaceArmTest.cpp
index c7ef4a1df..4df7e1c09 100644
--- a/libunwindstack/tests/ElfInterfaceArmTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceArmTest.cpp
@@ -322,7 +322,8 @@ TEST_F(ElfInterfaceArmTest, StepExidx) {
322 ElfInterfaceArm interface(&memory_); 322 ElfInterfaceArm interface(&memory_);
323 323
324 // FindEntry fails. 324 // FindEntry fails.
325 ASSERT_FALSE(interface.StepExidx(0x7000, nullptr, nullptr)); 325 bool finished;
326 ASSERT_FALSE(interface.StepExidx(0x7000, nullptr, nullptr, &finished));
326 327
327 // ExtractEntry should fail. 328 // ExtractEntry should fail.
328 interface.set_start_offset(0x1000); 329 interface.set_start_offset(0x1000);
@@ -335,15 +336,16 @@ TEST_F(ElfInterfaceArmTest, StepExidx) {
335 regs[ARM_REG_LR] = 0x20000; 336 regs[ARM_REG_LR] = 0x20000;
336 regs.set_sp(regs[ARM_REG_SP]); 337 regs.set_sp(regs[ARM_REG_SP]);
337 regs.set_pc(0x1234); 338 regs.set_pc(0x1234);
338 ASSERT_FALSE(interface.StepExidx(0x7000, &regs, &process_memory_)); 339 ASSERT_FALSE(interface.StepExidx(0x7000, &regs, &process_memory_, &finished));
339 340
340 // Eval should fail. 341 // Eval should fail.
341 memory_.SetData32(0x1004, 0x81000000); 342 memory_.SetData32(0x1004, 0x81000000);
342 ASSERT_FALSE(interface.StepExidx(0x7000, &regs, &process_memory_)); 343 ASSERT_FALSE(interface.StepExidx(0x7000, &regs, &process_memory_, &finished));
343 344
344 // Everything should pass. 345 // Everything should pass.
345 memory_.SetData32(0x1004, 0x80b0b0b0); 346 memory_.SetData32(0x1004, 0x80b0b0b0);
346 ASSERT_TRUE(interface.StepExidx(0x7000, &regs, &process_memory_)); 347 ASSERT_TRUE(interface.StepExidx(0x7000, &regs, &process_memory_, &finished));
348 ASSERT_FALSE(finished);
347 ASSERT_EQ(0x1000U, regs.sp()); 349 ASSERT_EQ(0x1000U, regs.sp());
348 ASSERT_EQ(0x1000U, regs[ARM_REG_SP]); 350 ASSERT_EQ(0x1000U, regs[ARM_REG_SP]);
349 ASSERT_EQ(0x20000U, regs.pc()); 351 ASSERT_EQ(0x20000U, regs.pc());
@@ -367,11 +369,57 @@ TEST_F(ElfInterfaceArmTest, StepExidx_pc_set) {
367 regs.set_pc(0x1234); 369 regs.set_pc(0x1234);
368 370
369 // Everything should pass. 371 // Everything should pass.
370 ASSERT_TRUE(interface.StepExidx(0x7000, &regs, &process_memory_)); 372 bool finished;
373 ASSERT_TRUE(interface.StepExidx(0x7000, &regs, &process_memory_, &finished));
374 ASSERT_FALSE(finished);
371 ASSERT_EQ(0x10004U, regs.sp()); 375 ASSERT_EQ(0x10004U, regs.sp());
372 ASSERT_EQ(0x10004U, regs[ARM_REG_SP]); 376 ASSERT_EQ(0x10004U, regs[ARM_REG_SP]);
373 ASSERT_EQ(0x10U, regs.pc()); 377 ASSERT_EQ(0x10U, regs.pc());
374 ASSERT_EQ(0x10U, regs[ARM_REG_PC]); 378 ASSERT_EQ(0x10U, regs[ARM_REG_PC]);
375} 379}
376 380
381TEST_F(ElfInterfaceArmTest, StepExidx_cant_unwind) {
382 ElfInterfaceArm interface(&memory_);
383
384 interface.set_start_offset(0x1000);
385 interface.set_total_entries(1);
386 memory_.SetData32(0x1000, 0x6000);
387 memory_.SetData32(0x1004, 1);
388
389 RegsArm regs;
390 regs[ARM_REG_SP] = 0x10000;
391 regs[ARM_REG_LR] = 0x20000;
392 regs.set_sp(regs[ARM_REG_SP]);
393 regs.set_pc(0x1234);
394
395 bool finished;
396 ASSERT_TRUE(interface.StepExidx(0x7000, &regs, &process_memory_, &finished));
397 ASSERT_TRUE(finished);
398 ASSERT_EQ(0x10000U, regs.sp());
399 ASSERT_EQ(0x10000U, regs[ARM_REG_SP]);
400 ASSERT_EQ(0x1234U, regs.pc());
401}
402
403TEST_F(ElfInterfaceArmTest, StepExidx_refuse_unwind) {
404 ElfInterfaceArm interface(&memory_);
405
406 interface.set_start_offset(0x1000);
407 interface.set_total_entries(1);
408 memory_.SetData32(0x1000, 0x6000);
409 memory_.SetData32(0x1004, 0x808000b0);
410
411 RegsArm regs;
412 regs[ARM_REG_SP] = 0x10000;
413 regs[ARM_REG_LR] = 0x20000;
414 regs.set_sp(regs[ARM_REG_SP]);
415 regs.set_pc(0x1234);
416
417 bool finished;
418 ASSERT_TRUE(interface.StepExidx(0x7000, &regs, &process_memory_, &finished));
419 ASSERT_TRUE(finished);
420 ASSERT_EQ(0x10000U, regs.sp());
421 ASSERT_EQ(0x10000U, regs[ARM_REG_SP]);
422 ASSERT_EQ(0x1234U, regs.pc());
423}
424
377} // namespace unwindstack 425} // namespace unwindstack
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp
index ed1be3b33..42a0246ae 100644
--- a/libunwindstack/tests/ElfTest.cpp
+++ b/libunwindstack/tests/ElfTest.cpp
@@ -129,7 +129,8 @@ TEST_F(ElfTest, elf_invalid) {
129 uint64_t func_offset; 129 uint64_t func_offset;
130 ASSERT_FALSE(elf.GetFunctionName(0, &name, &func_offset)); 130 ASSERT_FALSE(elf.GetFunctionName(0, &name, &func_offset));
131 131
132 ASSERT_FALSE(elf.Step(0, nullptr, nullptr)); 132 bool finished;
133 ASSERT_FALSE(elf.Step(0, nullptr, nullptr, &finished));
133} 134}
134 135
135TEST_F(ElfTest, elf32_invalid_machine) { 136TEST_F(ElfTest, elf32_invalid_machine) {
diff --git a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
index 9e45e7812..d2aad49fa 100644
--- a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
+++ b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
@@ -34,49 +34,78 @@
34#include <unwindstack/MapInfo.h> 34#include <unwindstack/MapInfo.h>
35#include <unwindstack/Memory.h> 35#include <unwindstack/Memory.h>
36 36
37#include "MemoryFake.h"
38
37namespace unwindstack { 39namespace unwindstack {
38 40
39class MapInfoCreateMemoryTest : public ::testing::Test { 41class MapInfoCreateMemoryTest : public ::testing::Test {
40 protected: 42 protected:
43 template <typename Ehdr, typename Shdr>
44 static void InitElf(int fd, uint64_t file_offset, uint64_t sh_offset, uint8_t class_type) {
45 std::vector<uint8_t> buffer(20000);
46 memset(buffer.data(), 0, buffer.size());
47
48 Ehdr ehdr;
49 memset(&ehdr, 0, sizeof(ehdr));
50 memcpy(ehdr.e_ident, ELFMAG, SELFMAG);
51 ehdr.e_ident[EI_CLASS] = class_type;
52 ehdr.e_shoff = sh_offset;
53 ehdr.e_shentsize = sizeof(Shdr) + 100;
54 ehdr.e_shnum = 4;
55 memcpy(&buffer[file_offset], &ehdr, sizeof(ehdr));
56
57 ASSERT_TRUE(android::base::WriteFully(fd, buffer.data(), buffer.size()));
58 }
59
41 static void SetUpTestCase() { 60 static void SetUpTestCase() {
42 std::vector<uint8_t> buffer(1024); 61 std::vector<uint8_t> buffer(1024);
62 memset(buffer.data(), 0, buffer.size());
43 memcpy(buffer.data(), ELFMAG, SELFMAG); 63 memcpy(buffer.data(), ELFMAG, SELFMAG);
44 for (size_t i = SELFMAG; i < buffer.size(); i++) { 64 buffer[EI_CLASS] = ELFCLASS32;
45 buffer[i] = i / 256 + 1;
46 }
47 ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size())); 65 ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
48 66
49 for (size_t i = 0; i < 0x100; i++) { 67 memset(buffer.data(), 0, buffer.size());
50 buffer[i] = i / 256 + 1;
51 }
52 memcpy(&buffer[0x100], ELFMAG, SELFMAG); 68 memcpy(&buffer[0x100], ELFMAG, SELFMAG);
53 for (size_t i = 0x100 + SELFMAG; i < buffer.size(); i++) { 69 buffer[0x100 + EI_CLASS] = ELFCLASS64;
54 buffer[i] = i / 256 + 1;
55 }
56 ASSERT_TRUE(android::base::WriteFully(elf_at_100_.fd, buffer.data(), buffer.size())); 70 ASSERT_TRUE(android::base::WriteFully(elf_at_100_.fd, buffer.data(), buffer.size()));
71
72 InitElf<Elf32_Ehdr, Elf32_Shdr>(elf32_at_map_.fd, 0x1000, 0x2000, ELFCLASS32);
73 InitElf<Elf64_Ehdr, Elf64_Shdr>(elf64_at_map_.fd, 0x2000, 0x3000, ELFCLASS64);
74 }
75
76 void SetUp() override {
77 memory_ = new MemoryFake;
78 process_memory_.reset(memory_);
57 } 79 }
58 80
81 MemoryFake* memory_;
82 std::shared_ptr<Memory> process_memory_;
83
59 static TemporaryFile elf_; 84 static TemporaryFile elf_;
60 85
61 static TemporaryFile elf_at_100_; 86 static TemporaryFile elf_at_100_;
87
88 static TemporaryFile elf32_at_map_;
89 static TemporaryFile elf64_at_map_;
62}; 90};
63TemporaryFile MapInfoCreateMemoryTest::elf_; 91TemporaryFile MapInfoCreateMemoryTest::elf_;
64TemporaryFile MapInfoCreateMemoryTest::elf_at_100_; 92TemporaryFile MapInfoCreateMemoryTest::elf_at_100_;
93TemporaryFile MapInfoCreateMemoryTest::elf32_at_map_;
94TemporaryFile MapInfoCreateMemoryTest::elf64_at_map_;
65 95
66TEST_F(MapInfoCreateMemoryTest, end_le_start) { 96TEST_F(MapInfoCreateMemoryTest, end_le_start) {
67 MapInfo info{.start = 0x100, .end = 0x100, .offset = 0, .name = elf_.path}; 97 MapInfo info{.start = 0x100, .end = 0x100, .offset = 0, .name = elf_.path};
68 98
69 std::unique_ptr<Memory> memory; 99 std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
70 memory.reset(info.CreateMemory(getpid()));
71 ASSERT_TRUE(memory.get() == nullptr); 100 ASSERT_TRUE(memory.get() == nullptr);
72 101
73 info.end = 0xff; 102 info.end = 0xff;
74 memory.reset(info.CreateMemory(getpid())); 103 memory.reset(info.CreateMemory(process_memory_));
75 ASSERT_TRUE(memory.get() == nullptr); 104 ASSERT_TRUE(memory.get() == nullptr);
76 105
77 // Make sure this test is valid. 106 // Make sure this test is valid.
78 info.end = 0x101; 107 info.end = 0x101;
79 memory.reset(info.CreateMemory(getpid())); 108 memory.reset(info.CreateMemory(process_memory_));
80 ASSERT_TRUE(memory.get() != nullptr); 109 ASSERT_TRUE(memory.get() != nullptr);
81} 110}
82 111
@@ -85,7 +114,7 @@ TEST_F(MapInfoCreateMemoryTest, end_le_start) {
85TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_full_file) { 114TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_full_file) {
86 MapInfo info{.start = 0x100, .end = 0x200, .offset = 0x100, .name = elf_.path}; 115 MapInfo info{.start = 0x100, .end = 0x200, .offset = 0x100, .name = elf_.path};
87 116
88 std::unique_ptr<Memory> memory(info.CreateMemory(getpid())); 117 std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
89 ASSERT_TRUE(memory.get() != nullptr); 118 ASSERT_TRUE(memory.get() != nullptr);
90 ASSERT_EQ(0x100U, info.elf_offset); 119 ASSERT_EQ(0x100U, info.elf_offset);
91 120
@@ -93,8 +122,9 @@ TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_full_file) {
93 std::vector<uint8_t> buffer(1024); 122 std::vector<uint8_t> buffer(1024);
94 ASSERT_TRUE(memory->Read(0, buffer.data(), 1024)); 123 ASSERT_TRUE(memory->Read(0, buffer.data(), 1024));
95 ASSERT_TRUE(memcmp(buffer.data(), ELFMAG, SELFMAG) == 0); 124 ASSERT_TRUE(memcmp(buffer.data(), ELFMAG, SELFMAG) == 0);
96 for (size_t i = SELFMAG; i < buffer.size(); i++) { 125 ASSERT_EQ(ELFCLASS32, buffer[EI_CLASS]);
97 ASSERT_EQ(i / 256 + 1, buffer[i]) << "Failed at byte " << i; 126 for (size_t i = EI_CLASS + 1; i < buffer.size(); i++) {
127 ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
98 } 128 }
99 129
100 ASSERT_FALSE(memory->Read(1024, buffer.data(), 1)); 130 ASSERT_FALSE(memory->Read(1024, buffer.data(), 1));
@@ -105,7 +135,7 @@ TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_full_file) {
105TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file) { 135TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file) {
106 MapInfo info{.start = 0x100, .end = 0x200, .offset = 0x100, .name = elf_at_100_.path}; 136 MapInfo info{.start = 0x100, .end = 0x200, .offset = 0x100, .name = elf_at_100_.path};
107 137
108 std::unique_ptr<Memory> memory(info.CreateMemory(getpid())); 138 std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
109 ASSERT_TRUE(memory.get() != nullptr); 139 ASSERT_TRUE(memory.get() != nullptr);
110 ASSERT_EQ(0U, info.elf_offset); 140 ASSERT_EQ(0U, info.elf_offset);
111 141
@@ -113,13 +143,50 @@ TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file) {
113 std::vector<uint8_t> buffer(0x100); 143 std::vector<uint8_t> buffer(0x100);
114 ASSERT_TRUE(memory->Read(0, buffer.data(), 0x100)); 144 ASSERT_TRUE(memory->Read(0, buffer.data(), 0x100));
115 ASSERT_TRUE(memcmp(buffer.data(), ELFMAG, SELFMAG) == 0); 145 ASSERT_TRUE(memcmp(buffer.data(), ELFMAG, SELFMAG) == 0);
116 for (size_t i = SELFMAG; i < buffer.size(); i++) { 146 ASSERT_EQ(ELFCLASS64, buffer[EI_CLASS]);
117 ASSERT_EQ(2, buffer[i]) << "Failed at byte " << i; 147 for (size_t i = EI_CLASS + 1; i < buffer.size(); i++) {
148 ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
118 } 149 }
119 150
120 ASSERT_FALSE(memory->Read(0x100, buffer.data(), 1)); 151 ASSERT_FALSE(memory->Read(0x100, buffer.data(), 1));
121} 152}
122 153
154// Verify that if the offset is non-zero and there is an elf at that
155// offset, that only part of the file is used. Further verify that if the
156// embedded elf is bigger than the initial map, the new object is larger
157// than the original map size. Do this for a 32 bit elf and a 64 bit elf.
158TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf32) {
159 MapInfo info{.start = 0x5000, .end = 0x6000, .offset = 0x1000, .name = elf32_at_map_.path};
160
161 std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
162 ASSERT_TRUE(memory.get() != nullptr);
163 ASSERT_EQ(0U, info.elf_offset);
164
165 // Verify the memory is a valid elf.
166 uint8_t e_ident[SELFMAG + 1];
167 ASSERT_TRUE(memory->Read(0, e_ident, SELFMAG));
168 ASSERT_EQ(0, memcmp(e_ident, ELFMAG, SELFMAG));
169
170 // Read past the end of what would normally be the size of the map.
171 ASSERT_TRUE(memory->Read(0x1000, e_ident, 1));
172}
173
174TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf64) {
175 MapInfo info{.start = 0x7000, .end = 0x8000, .offset = 0x2000, .name = elf64_at_map_.path};
176
177 std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
178 ASSERT_TRUE(memory.get() != nullptr);
179 ASSERT_EQ(0U, info.elf_offset);
180
181 // Verify the memory is a valid elf.
182 uint8_t e_ident[SELFMAG + 1];
183 ASSERT_TRUE(memory->Read(0, e_ident, SELFMAG));
184 ASSERT_EQ(0, memcmp(e_ident, ELFMAG, SELFMAG));
185
186 // Read past the end of what would normally be the size of the map.
187 ASSERT_TRUE(memory->Read(0x1000, e_ident, 1));
188}
189
123// Verify that device file names will never result in Memory object creation. 190// Verify that device file names will never result in Memory object creation.
124TEST_F(MapInfoCreateMemoryTest, check_device_maps) { 191TEST_F(MapInfoCreateMemoryTest, check_device_maps) {
125 // Set up some memory so that a valid local memory object would 192 // Set up some memory so that a valid local memory object would
@@ -129,81 +196,38 @@ TEST_F(MapInfoCreateMemoryTest, check_device_maps) {
129 info.start = reinterpret_cast<uint64_t>(buffer.data()); 196 info.start = reinterpret_cast<uint64_t>(buffer.data());
130 info.end = info.start + buffer.size(); 197 info.end = info.start + buffer.size();
131 info.offset = 0; 198 info.offset = 0;
132 std::unique_ptr<Memory> memory;
133 199
134 info.flags = 0x8000; 200 info.flags = 0x8000;
135 info.name = "/dev/something"; 201 info.name = "/dev/something";
136 memory.reset(info.CreateMemory(getpid())); 202 std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
137 ASSERT_TRUE(memory.get() == nullptr); 203 ASSERT_TRUE(memory.get() == nullptr);
138} 204}
139 205
140TEST_F(MapInfoCreateMemoryTest, local_memory) { 206TEST_F(MapInfoCreateMemoryTest, process_memory) {
141 // Set up some memory for a valid local memory object.
142 std::vector<uint8_t> buffer(1024);
143 for (size_t i = 0; i < buffer.size(); i++) {
144 buffer[i] = i % 256;
145 }
146
147 MapInfo info; 207 MapInfo info;
148 info.start = reinterpret_cast<uint64_t>(buffer.data()); 208 info.start = 0x2000;
149 info.end = info.start + buffer.size(); 209 info.end = 0x3000;
150 info.offset = 0; 210 info.offset = 0;
151 211
152 std::unique_ptr<Memory> memory; 212 // Verify that the the process_memory object is used, so seed it
153 memory.reset(info.CreateMemory(getpid())); 213 // with memory.
154 ASSERT_TRUE(memory.get() != nullptr);
155
156 std::vector<uint8_t> read_buffer(1024);
157 ASSERT_TRUE(memory->Read(0, read_buffer.data(), read_buffer.size()));
158 for (size_t i = 0; i < read_buffer.size(); i++) {
159 ASSERT_EQ(i % 256, read_buffer[i]) << "Failed at byte " << i;
160 }
161
162 ASSERT_FALSE(memory->Read(read_buffer.size(), read_buffer.data(), 1));
163}
164
165TEST_F(MapInfoCreateMemoryTest, remote_memory) {
166 std::vector<uint8_t> buffer(1024); 214 std::vector<uint8_t> buffer(1024);
167 memset(buffer.data(), 0xa, buffer.size()); 215 for (size_t i = 0; i < buffer.size(); i++) {
168 216 buffer[i] = i % 256;
169 pid_t pid;
170 if ((pid = fork()) == 0) {
171 while (true)
172 ;
173 exit(1);
174 }
175 ASSERT_LT(0, pid);
176
177 ASSERT_TRUE(ptrace(PTRACE_ATTACH, pid, 0, 0) != -1);
178 uint64_t iterations = 0;
179 siginfo_t si;
180 while (TEMP_FAILURE_RETRY(ptrace(PTRACE_GETSIGINFO, pid, 0, &si)) < 0 && errno == ESRCH) {
181 usleep(30);
182 iterations++;
183 ASSERT_LT(iterations, 500000000ULL);
184 } 217 }
218 memory_->SetMemory(info.start, buffer.data(), buffer.size());
185 219
186 MapInfo info; 220 std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
187 info.start = reinterpret_cast<uint64_t>(buffer.data());
188 info.end = info.start + buffer.size();
189 info.offset = 0;
190
191 std::unique_ptr<Memory> memory;
192 memory.reset(info.CreateMemory(pid));
193 ASSERT_TRUE(memory.get() != nullptr); 221 ASSERT_TRUE(memory.get() != nullptr);
194 // Set the local memory to a different value to guarantee we are reading
195 // from the remote process.
196 memset(buffer.data(), 0x1, buffer.size());
197 std::vector<uint8_t> read_buffer(1024);
198 ASSERT_TRUE(memory->Read(0, read_buffer.data(), read_buffer.size()));
199 for (size_t i = 0; i < read_buffer.size(); i++) {
200 ASSERT_EQ(0xaU, read_buffer[i]) << "Failed at byte " << i;
201 }
202 222
203 ASSERT_TRUE(ptrace(PTRACE_DETACH, pid, 0, 0) == 0); 223 memset(buffer.data(), 0, buffer.size());
224 ASSERT_TRUE(memory->Read(0, buffer.data(), buffer.size()));
225 for (size_t i = 0; i < buffer.size(); i++) {
226 ASSERT_EQ(i % 256, buffer[i]) << "Failed at byte " << i;
227 }
204 228
205 kill(pid, SIGKILL); 229 // Try to read outside of the map size.
206 ASSERT_EQ(pid, wait(nullptr)); 230 ASSERT_FALSE(memory->Read(buffer.size(), buffer.data(), 1));
207} 231}
208 232
209} // namespace unwindstack 233} // namespace unwindstack
diff --git a/libunwindstack/tests/MapInfoGetElfTest.cpp b/libunwindstack/tests/MapInfoGetElfTest.cpp
index abfa172aa..0b70d1337 100644
--- a/libunwindstack/tests/MapInfoGetElfTest.cpp
+++ b/libunwindstack/tests/MapInfoGetElfTest.cpp
@@ -32,43 +32,57 @@
32 32
33#include <unwindstack/Elf.h> 33#include <unwindstack/Elf.h>
34#include <unwindstack/MapInfo.h> 34#include <unwindstack/MapInfo.h>
35#include <unwindstack/Maps.h>
35#include <unwindstack/Memory.h> 36#include <unwindstack/Memory.h>
36 37
37#include "ElfTestUtils.h" 38#include "ElfTestUtils.h"
39#include "MemoryFake.h"
38 40
39namespace unwindstack { 41namespace unwindstack {
40 42
41class MapInfoGetElfTest : public ::testing::Test { 43class MapInfoGetElfTest : public ::testing::Test {
42 protected: 44 protected:
43 void SetUp() override { 45 void SetUp() override {
44 map_ = mmap(nullptr, kMapSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 46 memory_ = new MemoryFake;
45 ASSERT_NE(MAP_FAILED, map_); 47 process_memory_.reset(memory_);
46
47 uint64_t start = reinterpret_cast<uint64_t>(map_);
48 info_.reset(new MapInfo{.start = start, .end = start + 1024, .offset = 0, .name = ""});
49 } 48 }
50 49
51 void TearDown() override { munmap(map_, kMapSize); } 50 template <typename Ehdr, typename Shdr>
51 static void InitElf(uint64_t sh_offset, Ehdr* ehdr, uint8_t class_type, uint8_t machine_type) {
52 memset(ehdr, 0, sizeof(*ehdr));
53 memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
54 ehdr->e_ident[EI_CLASS] = class_type;
55 ehdr->e_machine = machine_type;
56 ehdr->e_shoff = sh_offset;
57 ehdr->e_shentsize = sizeof(Shdr) + 100;
58 ehdr->e_shnum = 4;
59 }
52 60
53 const size_t kMapSize = 4096; 61 const size_t kMapSize = 4096;
54 62
55 void* map_ = nullptr; 63 std::shared_ptr<Memory> process_memory_;
56 std::unique_ptr<MapInfo> info_; 64 MemoryFake* memory_;
65
66 TemporaryFile elf_;
57}; 67};
58 68
59TEST_F(MapInfoGetElfTest, invalid) { 69TEST_F(MapInfoGetElfTest, invalid) {
70 MapInfo info{.start = 0x1000, .end = 0x2000, .offset = 0, .flags = PROT_READ, .name = ""};
71
60 // The map is empty, but this should still create an invalid elf object. 72 // The map is empty, but this should still create an invalid elf object.
61 std::unique_ptr<Elf> elf(info_->GetElf(getpid(), false)); 73 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false));
62 ASSERT_TRUE(elf.get() != nullptr); 74 ASSERT_TRUE(elf.get() != nullptr);
63 ASSERT_FALSE(elf->valid()); 75 ASSERT_FALSE(elf->valid());
64} 76}
65 77
66TEST_F(MapInfoGetElfTest, valid32) { 78TEST_F(MapInfoGetElfTest, valid32) {
79 MapInfo info{.start = 0x3000, .end = 0x4000, .offset = 0, .flags = PROT_READ, .name = ""};
80
67 Elf32_Ehdr ehdr; 81 Elf32_Ehdr ehdr;
68 TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM); 82 TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
69 memcpy(map_, &ehdr, sizeof(ehdr)); 83 memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr));
70 84
71 std::unique_ptr<Elf> elf(info_->GetElf(getpid(), false)); 85 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false));
72 ASSERT_TRUE(elf.get() != nullptr); 86 ASSERT_TRUE(elf.get() != nullptr);
73 ASSERT_TRUE(elf->valid()); 87 ASSERT_TRUE(elf->valid());
74 EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type()); 88 EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
@@ -76,11 +90,13 @@ TEST_F(MapInfoGetElfTest, valid32) {
76} 90}
77 91
78TEST_F(MapInfoGetElfTest, valid64) { 92TEST_F(MapInfoGetElfTest, valid64) {
93 MapInfo info{.start = 0x8000, .end = 0x9000, .offset = 0, .flags = PROT_READ, .name = ""};
94
79 Elf64_Ehdr ehdr; 95 Elf64_Ehdr ehdr;
80 TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64); 96 TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
81 memcpy(map_, &ehdr, sizeof(ehdr)); 97 memory_->SetMemory(0x8000, &ehdr, sizeof(ehdr));
82 98
83 std::unique_ptr<Elf> elf(info_->GetElf(getpid(), false)); 99 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false));
84 ASSERT_TRUE(elf.get() != nullptr); 100 ASSERT_TRUE(elf.get() != nullptr);
85 ASSERT_TRUE(elf->valid()); 101 ASSERT_TRUE(elf->valid());
86 EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type()); 102 EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
@@ -88,12 +104,14 @@ TEST_F(MapInfoGetElfTest, valid64) {
88} 104}
89 105
90TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init32) { 106TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init32) {
91 TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>( 107 MapInfo info{.start = 0x4000, .end = 0x8000, .offset = 0, .flags = PROT_READ, .name = ""};
92 ELFCLASS32, EM_ARM, false, [&](uint64_t offset, const void* ptr, size_t size) { 108
93 memcpy(&reinterpret_cast<uint8_t*>(map_)[offset], ptr, size); 109 TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, false,
94 }); 110 [&](uint64_t offset, const void* ptr, size_t size) {
111 memory_->SetMemory(0x4000 + offset, ptr, size);
112 });
95 113
96 std::unique_ptr<Elf> elf(info_->GetElf(getpid(), false)); 114 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false));
97 ASSERT_TRUE(elf.get() != nullptr); 115 ASSERT_TRUE(elf.get() != nullptr);
98 ASSERT_TRUE(elf->valid()); 116 ASSERT_TRUE(elf->valid());
99 EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type()); 117 EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
@@ -102,12 +120,14 @@ TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init32) {
102} 120}
103 121
104TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init64) { 122TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init64) {
105 TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>( 123 MapInfo info{.start = 0x6000, .end = 0x8000, .offset = 0, .flags = PROT_READ, .name = ""};
106 ELFCLASS64, EM_AARCH64, false, [&](uint64_t offset, const void* ptr, size_t size) { 124
107 memcpy(&reinterpret_cast<uint8_t*>(map_)[offset], ptr, size); 125 TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, false,
108 }); 126 [&](uint64_t offset, const void* ptr, size_t size) {
127 memory_->SetMemory(0x6000 + offset, ptr, size);
128 });
109 129
110 std::unique_ptr<Elf> elf(info_->GetElf(getpid(), false)); 130 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false));
111 ASSERT_TRUE(elf.get() != nullptr); 131 ASSERT_TRUE(elf.get() != nullptr);
112 ASSERT_TRUE(elf->valid()); 132 ASSERT_TRUE(elf->valid());
113 EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type()); 133 EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
@@ -116,12 +136,14 @@ TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init64) {
116} 136}
117 137
118TEST_F(MapInfoGetElfTest, gnu_debugdata_init32) { 138TEST_F(MapInfoGetElfTest, gnu_debugdata_init32) {
119 TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>( 139 MapInfo info{.start = 0x2000, .end = 0x3000, .offset = 0, .flags = PROT_READ, .name = ""};
120 ELFCLASS32, EM_ARM, true, [&](uint64_t offset, const void* ptr, size_t size) {
121 memcpy(&reinterpret_cast<uint8_t*>(map_)[offset], ptr, size);
122 });
123 140
124 std::unique_ptr<Elf> elf(info_->GetElf(getpid(), true)); 141 TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, true,
142 [&](uint64_t offset, const void* ptr, size_t size) {
143 memory_->SetMemory(0x2000 + offset, ptr, size);
144 });
145
146 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, true));
125 ASSERT_TRUE(elf.get() != nullptr); 147 ASSERT_TRUE(elf.get() != nullptr);
126 ASSERT_TRUE(elf->valid()); 148 ASSERT_TRUE(elf->valid());
127 EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type()); 149 EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
@@ -130,12 +152,14 @@ TEST_F(MapInfoGetElfTest, gnu_debugdata_init32) {
130} 152}
131 153
132TEST_F(MapInfoGetElfTest, gnu_debugdata_init64) { 154TEST_F(MapInfoGetElfTest, gnu_debugdata_init64) {
133 TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>( 155 MapInfo info{.start = 0x5000, .end = 0x8000, .offset = 0, .flags = PROT_READ, .name = ""};
134 ELFCLASS64, EM_AARCH64, true, [&](uint64_t offset, const void* ptr, size_t size) { 156
135 memcpy(&reinterpret_cast<uint8_t*>(map_)[offset], ptr, size); 157 TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, true,
136 }); 158 [&](uint64_t offset, const void* ptr, size_t size) {
159 memory_->SetMemory(0x5000 + offset, ptr, size);
160 });
137 161
138 std::unique_ptr<Elf> elf(info_->GetElf(getpid(), true)); 162 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, true));
139 ASSERT_TRUE(elf.get() != nullptr); 163 ASSERT_TRUE(elf.get() != nullptr);
140 ASSERT_TRUE(elf->valid()); 164 ASSERT_TRUE(elf->valid());
141 EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type()); 165 EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
@@ -143,4 +167,195 @@ TEST_F(MapInfoGetElfTest, gnu_debugdata_init64) {
143 EXPECT_TRUE(elf->gnu_debugdata_interface() != nullptr); 167 EXPECT_TRUE(elf->gnu_debugdata_interface() != nullptr);
144} 168}
145 169
170TEST_F(MapInfoGetElfTest, end_le_start) {
171 MapInfo info{.start = 0x1000, .end = 0x1000, .offset = 0, .flags = PROT_READ, .name = elf_.path};
172
173 Elf32_Ehdr ehdr;
174 TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
175 ASSERT_TRUE(android::base::WriteFully(elf_.fd, &ehdr, sizeof(ehdr)));
176
177 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false));
178 ASSERT_FALSE(elf->valid());
179
180 info.elf = nullptr;
181 info.end = 0xfff;
182 elf.reset(info.GetElf(process_memory_, false));
183 ASSERT_FALSE(elf->valid());
184
185 // Make sure this test is valid.
186 info.elf = nullptr;
187 info.end = 0x2000;
188 elf.reset(info.GetElf(process_memory_, false));
189 ASSERT_TRUE(elf->valid());
190}
191
192// Verify that if the offset is non-zero but there is no elf at the offset,
193// that the full file is used.
194TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_full_file) {
195 MapInfo info{
196 .start = 0x1000, .end = 0x2000, .offset = 0x100, .flags = PROT_READ, .name = elf_.path};
197
198 std::vector<uint8_t> buffer(0x1000);
199 memset(buffer.data(), 0, buffer.size());
200 Elf32_Ehdr ehdr;
201 TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
202 memcpy(buffer.data(), &ehdr, sizeof(ehdr));
203 ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
204
205 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false));
206 ASSERT_TRUE(elf->valid());
207 ASSERT_TRUE(elf->memory() != nullptr);
208 ASSERT_EQ(0x100U, info.elf_offset);
209
210 // Read the entire file.
211 memset(buffer.data(), 0, buffer.size());
212 ASSERT_TRUE(elf->memory()->Read(0, buffer.data(), buffer.size()));
213 ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
214 for (size_t i = sizeof(ehdr); i < buffer.size(); i++) {
215 ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
216 }
217
218 ASSERT_FALSE(elf->memory()->Read(buffer.size(), buffer.data(), 1));
219}
220
221// Verify that if the offset is non-zero and there is an elf at that
222// offset, that only part of the file is used.
223TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file) {
224 MapInfo info{
225 .start = 0x1000, .end = 0x2000, .offset = 0x2000, .flags = PROT_READ, .name = elf_.path};
226
227 std::vector<uint8_t> buffer(0x4000);
228 memset(buffer.data(), 0, buffer.size());
229 Elf32_Ehdr ehdr;
230 TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
231 memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr));
232 ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
233
234 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false));
235 ASSERT_TRUE(elf->valid());
236 ASSERT_TRUE(elf->memory() != nullptr);
237 ASSERT_EQ(0U, info.elf_offset);
238
239 // Read the valid part of the file.
240 ASSERT_TRUE(elf->memory()->Read(0, buffer.data(), 0x1000));
241 ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
242 for (size_t i = sizeof(ehdr); i < 0x1000; i++) {
243 ASSERT_EQ(0, buffer[i]) << "Failed at byte " << i;
244 }
245
246 ASSERT_FALSE(elf->memory()->Read(0x1000, buffer.data(), 1));
247}
248
249// Verify that if the offset is non-zero and there is an elf at that
250// offset, that only part of the file is used. Further verify that if the
251// embedded elf is bigger than the initial map, the new object is larger
252// than the original map size. Do this for a 32 bit elf and a 64 bit elf.
253TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf32) {
254 MapInfo info{
255 .start = 0x5000, .end = 0x6000, .offset = 0x1000, .flags = PROT_READ, .name = elf_.path};
256
257 std::vector<uint8_t> buffer(0x4000);
258 memset(buffer.data(), 0, buffer.size());
259 Elf32_Ehdr ehdr;
260 TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
261 ehdr.e_shoff = 0x2000;
262 ehdr.e_shentsize = sizeof(Elf32_Shdr) + 100;
263 ehdr.e_shnum = 4;
264 memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr));
265 ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
266
267 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false));
268 ASSERT_TRUE(elf->valid());
269 ASSERT_TRUE(elf->memory() != nullptr);
270 ASSERT_EQ(0U, info.elf_offset);
271
272 // Verify the memory is a valid elf.
273 memset(buffer.data(), 0, buffer.size());
274 ASSERT_TRUE(elf->memory()->Read(0, buffer.data(), 0x1000));
275 ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
276
277 // Read past the end of what would normally be the size of the map.
278 ASSERT_TRUE(elf->memory()->Read(0x1000, buffer.data(), 1));
279}
280
281TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf64) {
282 MapInfo info{
283 .start = 0x7000, .end = 0x8000, .offset = 0x1000, .flags = PROT_READ, .name = elf_.path};
284
285 std::vector<uint8_t> buffer(0x4000);
286 memset(buffer.data(), 0, buffer.size());
287 Elf64_Ehdr ehdr;
288 TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
289 ehdr.e_shoff = 0x2000;
290 ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
291 ehdr.e_shnum = 4;
292 memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr));
293 ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
294
295 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false));
296 ASSERT_TRUE(elf->valid());
297 ASSERT_TRUE(elf->memory() != nullptr);
298 ASSERT_EQ(0U, info.elf_offset);
299
300 // Verify the memory is a valid elf.
301 memset(buffer.data(), 0, buffer.size());
302 ASSERT_TRUE(elf->memory()->Read(0, buffer.data(), 0x1000));
303 ASSERT_EQ(0, memcmp(buffer.data(), &ehdr, sizeof(ehdr)));
304
305 // Read past the end of what would normally be the size of the map.
306 ASSERT_TRUE(elf->memory()->Read(0x1000, buffer.data(), 1));
307}
308
309TEST_F(MapInfoGetElfTest, process_memory_not_read_only) {
310 MapInfo info{.start = 0x9000, .end = 0xa000, .offset = 0x1000, .flags = 0, .name = ""};
311
312 // Create valid elf data in process memory only.
313 Elf64_Ehdr ehdr;
314 TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
315 ehdr.e_shoff = 0x2000;
316 ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
317 ehdr.e_shnum = 4;
318 memory_->SetMemory(0x9000, &ehdr, sizeof(ehdr));
319
320 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false));
321 ASSERT_FALSE(elf->valid());
322
323 info.elf = nullptr;
324 info.flags = PROT_READ;
325 elf.reset(info.GetElf(process_memory_, false));
326 ASSERT_TRUE(elf->valid());
327}
328
329TEST_F(MapInfoGetElfTest, check_device_maps) {
330 MapInfo info{.start = 0x7000,
331 .end = 0x8000,
332 .offset = 0x1000,
333 .flags = PROT_READ | MAPS_FLAGS_DEVICE_MAP,
334 .name = "/dev/something"};
335
336 // Create valid elf data in process memory for this to verify that only
337 // the name is causing invalid elf data.
338 Elf64_Ehdr ehdr;
339 TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_X86_64);
340 ehdr.e_shoff = 0x2000;
341 ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
342 ehdr.e_shnum = 4;
343 memory_->SetMemory(0x7000, &ehdr, sizeof(ehdr));
344
345 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false));
346 ASSERT_FALSE(elf->valid());
347
348 // Set the name to nothing to verify that it still fails.
349 info.elf = nullptr;
350 info.name = "";
351 elf.reset(info.GetElf(process_memory_, false));
352 ASSERT_FALSE(elf->valid());
353
354 // Change the flags and verify the elf is valid now.
355 info.elf = nullptr;
356 info.flags = PROT_READ;
357 elf.reset(info.GetElf(process_memory_, false));
358 ASSERT_TRUE(elf->valid());
359}
360
146} // namespace unwindstack 361} // namespace unwindstack
diff --git a/libunwindstack/tests/MemoryRangeTest.cpp b/libunwindstack/tests/MemoryRangeTest.cpp
index 6d1366c84..680fae9c1 100644
--- a/libunwindstack/tests/MemoryRangeTest.cpp
+++ b/libunwindstack/tests/MemoryRangeTest.cpp
@@ -31,10 +31,11 @@ namespace unwindstack {
31TEST(MemoryRangeTest, read) { 31TEST(MemoryRangeTest, read) {
32 std::vector<uint8_t> src(1024); 32 std::vector<uint8_t> src(1024);
33 memset(src.data(), 0x4c, 1024); 33 memset(src.data(), 0x4c, 1024);
34 MemoryFake* memory = new MemoryFake; 34 MemoryFake* memory_fake = new MemoryFake;
35 memory->SetMemory(9001, src); 35 std::shared_ptr<Memory> process_memory(memory_fake);
36 memory_fake->SetMemory(9001, src);
36 37
37 MemoryRange range(memory, 9001, 9001 + src.size()); 38 MemoryRange range(process_memory, 9001, 9001 + src.size());
38 39
39 std::vector<uint8_t> dst(1024); 40 std::vector<uint8_t> dst(1024);
40 ASSERT_TRUE(range.Read(0, dst.data(), src.size())); 41 ASSERT_TRUE(range.Read(0, dst.data(), src.size()));
@@ -46,10 +47,11 @@ TEST(MemoryRangeTest, read) {
46TEST(MemoryRangeTest, read_near_limit) { 47TEST(MemoryRangeTest, read_near_limit) {
47 std::vector<uint8_t> src(4096); 48 std::vector<uint8_t> src(4096);
48 memset(src.data(), 0x4c, 4096); 49 memset(src.data(), 0x4c, 4096);
49 MemoryFake* memory = new MemoryFake; 50 MemoryFake* memory_fake = new MemoryFake;
50 memory->SetMemory(1000, src); 51 std::shared_ptr<Memory> process_memory(memory_fake);
52 memory_fake->SetMemory(1000, src);
51 53
52 MemoryRange range(memory, 1000, 2024); 54 MemoryRange range(process_memory, 1000, 2024);
53 55
54 std::vector<uint8_t> dst(1024); 56 std::vector<uint8_t> dst(1024);
55 ASSERT_TRUE(range.Read(1020, dst.data(), 4)); 57 ASSERT_TRUE(range.Read(1020, dst.data(), 4));
@@ -69,7 +71,8 @@ TEST(MemoryRangeTest, read_near_limit) {
69TEST(MemoryRangeTest, read_overflow) { 71TEST(MemoryRangeTest, read_overflow) {
70 std::vector<uint8_t> buffer(100); 72 std::vector<uint8_t> buffer(100);
71 73
72 std::unique_ptr<MemoryRange> overflow(new MemoryRange(new MemoryFakeAlwaysReadZero, 100, 200)); 74 std::shared_ptr<Memory> process_memory(new MemoryFakeAlwaysReadZero);
75 std::unique_ptr<MemoryRange> overflow(new MemoryRange(process_memory, 100, 200));
73 ASSERT_FALSE(overflow->Read(UINT64_MAX - 10, buffer.data(), 100)); 76 ASSERT_FALSE(overflow->Read(UINT64_MAX - 10, buffer.data(), 100));
74} 77}
75 78
diff --git a/libunwindstack/tests/MemoryRemoteTest.cpp b/libunwindstack/tests/MemoryRemoteTest.cpp
index f8965b2ce..a66d0c550 100644
--- a/libunwindstack/tests/MemoryRemoteTest.cpp
+++ b/libunwindstack/tests/MemoryRemoteTest.cpp
@@ -22,7 +22,6 @@
22#include <sys/mman.h> 22#include <sys/mman.h>
23#include <sys/ptrace.h> 23#include <sys/ptrace.h>
24#include <sys/types.h> 24#include <sys/types.h>
25#include <time.h>
26#include <unistd.h> 25#include <unistd.h>
27 26
28#include <vector> 27#include <vector>
@@ -34,32 +33,18 @@
34#include <unwindstack/Memory.h> 33#include <unwindstack/Memory.h>
35 34
36#include "MemoryFake.h" 35#include "MemoryFake.h"
36#include "TestUtils.h"
37 37
38namespace unwindstack { 38namespace unwindstack {
39 39
40class MemoryRemoteTest : public ::testing::Test { 40class MemoryRemoteTest : public ::testing::Test {
41 protected: 41 protected:
42 static uint64_t NanoTime() {
43 struct timespec t = { 0, 0 };
44 clock_gettime(CLOCK_MONOTONIC, &t);
45 return static_cast<uint64_t>(t.tv_sec * NS_PER_SEC + t.tv_nsec);
46 }
47
48 static bool Attach(pid_t pid) { 42 static bool Attach(pid_t pid) {
49 if (ptrace(PTRACE_ATTACH, pid, 0, 0) == -1) { 43 if (ptrace(PTRACE_ATTACH, pid, 0, 0) == -1) {
50 return false; 44 return false;
51 } 45 }
52 46
53 uint64_t start = NanoTime(); 47 return TestQuiescePid(pid);
54 siginfo_t si;
55 while (TEMP_FAILURE_RETRY(ptrace(PTRACE_GETSIGINFO, pid, 0, &si)) < 0 && errno == ESRCH) {
56 if ((NanoTime() - start) > 10 * NS_PER_SEC) {
57 printf("%d: Failed to stop after 10 seconds.\n", pid);
58 return false;
59 }
60 usleep(30);
61 }
62 return true;
63 } 48 }
64 49
65 static bool Detach(pid_t pid) { 50 static bool Detach(pid_t pid) {
@@ -79,6 +64,7 @@ TEST_F(MemoryRemoteTest, read) {
79 exit(1); 64 exit(1);
80 } 65 }
81 ASSERT_LT(0, pid); 66 ASSERT_LT(0, pid);
67 TestScopedPidReaper reap(pid);
82 68
83 ASSERT_TRUE(Attach(pid)); 69 ASSERT_TRUE(Attach(pid));
84 70
@@ -91,9 +77,6 @@ TEST_F(MemoryRemoteTest, read) {
91 } 77 }
92 78
93 ASSERT_TRUE(Detach(pid)); 79 ASSERT_TRUE(Detach(pid));
94
95 kill(pid, SIGKILL);
96 ASSERT_EQ(pid, wait(nullptr));
97} 80}
98 81
99TEST_F(MemoryRemoteTest, read_fail) { 82TEST_F(MemoryRemoteTest, read_fail) {
@@ -111,6 +94,7 @@ TEST_F(MemoryRemoteTest, read_fail) {
111 exit(1); 94 exit(1);
112 } 95 }
113 ASSERT_LT(0, pid); 96 ASSERT_LT(0, pid);
97 TestScopedPidReaper reap(pid);
114 98
115 ASSERT_TRUE(Attach(pid)); 99 ASSERT_TRUE(Attach(pid));
116 100
@@ -132,9 +116,6 @@ TEST_F(MemoryRemoteTest, read_fail) {
132 ASSERT_EQ(0, munmap(src, pagesize)); 116 ASSERT_EQ(0, munmap(src, pagesize));
133 117
134 ASSERT_TRUE(Detach(pid)); 118 ASSERT_TRUE(Detach(pid));
135
136 kill(pid, SIGKILL);
137 ASSERT_EQ(pid, wait(nullptr));
138} 119}
139 120
140TEST_F(MemoryRemoteTest, read_overflow) { 121TEST_F(MemoryRemoteTest, read_overflow) {
@@ -152,6 +133,7 @@ TEST_F(MemoryRemoteTest, read_illegal) {
152 exit(1); 133 exit(1);
153 } 134 }
154 ASSERT_LT(0, pid); 135 ASSERT_LT(0, pid);
136 TestScopedPidReaper reap(pid);
155 137
156 ASSERT_TRUE(Attach(pid)); 138 ASSERT_TRUE(Attach(pid));
157 139
@@ -162,9 +144,6 @@ TEST_F(MemoryRemoteTest, read_illegal) {
162 ASSERT_FALSE(remote.Read(0, dst.data(), 100)); 144 ASSERT_FALSE(remote.Read(0, dst.data(), 100));
163 145
164 ASSERT_TRUE(Detach(pid)); 146 ASSERT_TRUE(Detach(pid));
165
166 kill(pid, SIGKILL);
167 ASSERT_EQ(pid, wait(nullptr));
168} 147}
169 148
170} // namespace unwindstack 149} // namespace unwindstack
diff --git a/libunwindstack/tests/RegsFake.h b/libunwindstack/tests/RegsFake.h
index c76ecaaea..efcd029ab 100644
--- a/libunwindstack/tests/RegsFake.h
+++ b/libunwindstack/tests/RegsFake.h
@@ -24,19 +24,60 @@
24 24
25namespace unwindstack { 25namespace unwindstack {
26 26
27template <typename TypeParam> 27class RegsFake : public Regs {
28class RegsFake : public RegsImpl<TypeParam> {
29 public: 28 public:
30 RegsFake(uint16_t total_regs, uint16_t sp_reg) 29 RegsFake(uint16_t total_regs, uint16_t sp_reg)
31 : RegsImpl<TypeParam>(total_regs, sp_reg, Regs::Location(Regs::LOCATION_UNKNOWN, 0)) {} 30 : Regs(total_regs, sp_reg, Regs::Location(Regs::LOCATION_UNKNOWN, 0)) {}
32 virtual ~RegsFake() = default; 31 virtual ~RegsFake() = default;
33 32
33 uint32_t MachineType() override { return fake_type_; }
34 void* RawData() override { return nullptr; }
35 uint64_t pc() override { return fake_pc_; }
36 uint64_t sp() override { return fake_sp_; }
37 bool SetPcFromReturnAddress(Memory*) override {
38 if (!fake_return_address_valid_) {
39 return false;
40 }
41 fake_pc_ = fake_return_address_;
42 return true;
43 }
44
45 uint64_t GetAdjustedPc(uint64_t rel_pc, Elf*) override { return rel_pc - 2; }
46
47 bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; }
48
49 void SetFromRaw() override {}
50
51 void FakeSetMachineType(uint32_t type) { fake_type_ = type; }
52 void FakeSetPc(uint64_t pc) { fake_pc_ = pc; }
53 void FakeSetSp(uint64_t sp) { fake_sp_ = sp; }
54 void FakeSetReturnAddress(uint64_t return_address) { fake_return_address_ = return_address; }
55 void FakeSetReturnAddressValid(bool valid) { fake_return_address_valid_ = valid; }
56
57 private:
58 uint32_t fake_type_ = 0;
59 uint64_t fake_pc_ = 0;
60 uint64_t fake_sp_ = 0;
61 bool fake_return_address_valid_ = false;
62 uint64_t fake_return_address_ = 0;
63};
64
65template <typename TypeParam>
66class RegsImplFake : public RegsImpl<TypeParam> {
67 public:
68 RegsImplFake(uint16_t total_regs, uint16_t sp_reg)
69 : RegsImpl<TypeParam>(total_regs, sp_reg, Regs::Location(Regs::LOCATION_UNKNOWN, 0)) {}
70 virtual ~RegsImplFake() = default;
71
34 uint32_t MachineType() override { return 0; } 72 uint32_t MachineType() override { return 0; }
35 73
36 uint64_t GetAdjustedPc(uint64_t, Elf*) override { return 0; } 74 uint64_t GetAdjustedPc(uint64_t, Elf*) override { return 0; }
37 void SetFromRaw() override {} 75 void SetFromRaw() override {}
76 bool SetPcFromReturnAddress(Memory*) override { return false; }
38 bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; } 77 bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; }
39 bool GetReturnAddressFromDefault(Memory*, uint64_t*) { return false; } 78
79 void FakeSetPc(uint64_t pc) { this->pc_ = pc; }
80 void FakeSetSp(uint64_t sp) { this->sp_ = sp; }
40}; 81};
41 82
42} // namespace unwindstack 83} // namespace unwindstack
diff --git a/libunwindstack/tests/RegsTest.cpp b/libunwindstack/tests/RegsTest.cpp
index f549a50d6..3b9f92b01 100644
--- a/libunwindstack/tests/RegsTest.cpp
+++ b/libunwindstack/tests/RegsTest.cpp
@@ -23,67 +23,28 @@
23#include <unwindstack/MapInfo.h> 23#include <unwindstack/MapInfo.h>
24#include <unwindstack/Regs.h> 24#include <unwindstack/Regs.h>
25 25
26#include "ElfFake.h"
26#include "MemoryFake.h" 27#include "MemoryFake.h"
28#include "RegsFake.h"
27 29
28namespace unwindstack { 30namespace unwindstack {
29 31
30class ElfFake : public Elf {
31 public:
32 ElfFake(Memory* memory) : Elf(memory) { valid_ = true; }
33 virtual ~ElfFake() = default;
34
35 void set_elf_interface(ElfInterface* interface) { interface_.reset(interface); }
36};
37
38class ElfInterfaceFake : public ElfInterface {
39 public:
40 ElfInterfaceFake(Memory* memory) : ElfInterface(memory) {}
41 virtual ~ElfInterfaceFake() = default;
42
43 void set_load_bias(uint64_t load_bias) { load_bias_ = load_bias; }
44
45 bool Init() override { return false; }
46 void InitHeaders() override {}
47 bool GetSoname(std::string*) override { return false; }
48 bool GetFunctionName(uint64_t, std::string*, uint64_t*) override { return false; }
49 bool Step(uint64_t, Regs*, Memory*) override { return false; }
50};
51
52template <typename TypeParam>
53class RegsTestImpl : public RegsImpl<TypeParam> {
54 public:
55 RegsTestImpl(uint16_t total_regs, uint16_t regs_sp)
56 : RegsImpl<TypeParam>(total_regs, regs_sp, Regs::Location(Regs::LOCATION_UNKNOWN, 0)) {}
57 RegsTestImpl(uint16_t total_regs, uint16_t regs_sp, Regs::Location return_loc)
58 : RegsImpl<TypeParam>(total_regs, regs_sp, return_loc) {}
59 virtual ~RegsTestImpl() = default;
60
61 uint32_t MachineType() override { return 0; }
62
63 uint64_t GetAdjustedPc(uint64_t, Elf*) override { return 0; }
64 void SetFromRaw() override {}
65 bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; }
66};
67
68class RegsTest : public ::testing::Test { 32class RegsTest : public ::testing::Test {
69 protected: 33 protected:
70 void SetUp() override { 34 void SetUp() override {
71 memory_ = new MemoryFake; 35 memory_ = new MemoryFake;
72 elf_.reset(new ElfFake(memory_)); 36 elf_.reset(new ElfFake(memory_));
73 elf_interface_ = new ElfInterfaceFake(elf_->memory()); 37 elf_interface_ = new ElfInterfaceFake(elf_->memory());
74 elf_->set_elf_interface(elf_interface_); 38 elf_->FakeSetInterface(elf_interface_);
75 } 39 }
76 40
77 template <typename AddressType>
78 void RegsReturnAddressRegister();
79
80 ElfInterfaceFake* elf_interface_; 41 ElfInterfaceFake* elf_interface_;
81 MemoryFake* memory_; 42 MemoryFake* memory_;
82 std::unique_ptr<ElfFake> elf_; 43 std::unique_ptr<ElfFake> elf_;
83}; 44};
84 45
85TEST_F(RegsTest, regs32) { 46TEST_F(RegsTest, regs32) {
86 RegsTestImpl<uint32_t> regs32(50, 10); 47 RegsImplFake<uint32_t> regs32(50, 10);
87 ASSERT_EQ(50U, regs32.total_regs()); 48 ASSERT_EQ(50U, regs32.total_regs());
88 ASSERT_EQ(10U, regs32.sp_reg()); 49 ASSERT_EQ(10U, regs32.sp_reg());
89 50
@@ -106,7 +67,7 @@ TEST_F(RegsTest, regs32) {
106} 67}
107 68
108TEST_F(RegsTest, regs64) { 69TEST_F(RegsTest, regs64) {
109 RegsTestImpl<uint64_t> regs64(30, 12); 70 RegsImplFake<uint64_t> regs64(30, 12);
110 ASSERT_EQ(30U, regs64.total_regs()); 71 ASSERT_EQ(30U, regs64.total_regs());
111 ASSERT_EQ(12U, regs64.sp_reg()); 72 ASSERT_EQ(12U, regs64.sp_reg());
112 73
@@ -128,44 +89,6 @@ TEST_F(RegsTest, regs64) {
128 ASSERT_EQ(10U, regs64[8]); 89 ASSERT_EQ(10U, regs64[8]);
129} 90}
130 91
131template <typename AddressType>
132void RegsTest::RegsReturnAddressRegister() {
133 RegsTestImpl<AddressType> regs(20, 10, Regs::Location(Regs::LOCATION_REGISTER, 5));
134
135 regs[5] = 0x12345;
136 uint64_t value;
137 ASSERT_TRUE(regs.GetReturnAddressFromDefault(memory_, &value));
138 ASSERT_EQ(0x12345U, value);
139}
140
141TEST_F(RegsTest, regs32_return_address_register) {
142 RegsReturnAddressRegister<uint32_t>();
143}
144
145TEST_F(RegsTest, regs64_return_address_register) {
146 RegsReturnAddressRegister<uint64_t>();
147}
148
149TEST_F(RegsTest, regs32_return_address_sp_offset) {
150 RegsTestImpl<uint32_t> regs(20, 10, Regs::Location(Regs::LOCATION_SP_OFFSET, -2));
151
152 regs.set_sp(0x2002);
153 memory_->SetData32(0x2000, 0x12345678);
154 uint64_t value;
155 ASSERT_TRUE(regs.GetReturnAddressFromDefault(memory_, &value));
156 ASSERT_EQ(0x12345678U, value);
157}
158
159TEST_F(RegsTest, regs64_return_address_sp_offset) {
160 RegsTestImpl<uint64_t> regs(20, 10, Regs::Location(Regs::LOCATION_SP_OFFSET, -8));
161
162 regs.set_sp(0x2008);
163 memory_->SetData64(0x2000, 0x12345678aabbccddULL);
164 uint64_t value;
165 ASSERT_TRUE(regs.GetReturnAddressFromDefault(memory_, &value));
166 ASSERT_EQ(0x12345678aabbccddULL, value);
167}
168
169TEST_F(RegsTest, rel_pc) { 92TEST_F(RegsTest, rel_pc) {
170 RegsArm64 arm64; 93 RegsArm64 arm64;
171 ASSERT_EQ(0xcU, arm64.GetAdjustedPc(0x10, elf_.get())); 94 ASSERT_EQ(0xcU, arm64.GetAdjustedPc(0x10, elf_.get()));
@@ -192,7 +115,7 @@ TEST_F(RegsTest, rel_pc_arm) {
192 RegsArm arm; 115 RegsArm arm;
193 116
194 // Check fence posts. 117 // Check fence posts.
195 elf_interface_->set_load_bias(0); 118 elf_interface_->FakeSetLoadBias(0);
196 ASSERT_EQ(3U, arm.GetAdjustedPc(0x5, elf_.get())); 119 ASSERT_EQ(3U, arm.GetAdjustedPc(0x5, elf_.get()));
197 ASSERT_EQ(4U, arm.GetAdjustedPc(0x4, elf_.get())); 120 ASSERT_EQ(4U, arm.GetAdjustedPc(0x4, elf_.get()));
198 ASSERT_EQ(3U, arm.GetAdjustedPc(0x3, elf_.get())); 121 ASSERT_EQ(3U, arm.GetAdjustedPc(0x3, elf_.get()));
@@ -200,7 +123,7 @@ TEST_F(RegsTest, rel_pc_arm) {
200 ASSERT_EQ(1U, arm.GetAdjustedPc(0x1, elf_.get())); 123 ASSERT_EQ(1U, arm.GetAdjustedPc(0x1, elf_.get()));
201 ASSERT_EQ(0U, arm.GetAdjustedPc(0x0, elf_.get())); 124 ASSERT_EQ(0U, arm.GetAdjustedPc(0x0, elf_.get()));
202 125
203 elf_interface_->set_load_bias(0x100); 126 elf_interface_->FakeSetLoadBias(0x100);
204 ASSERT_EQ(0xffU, arm.GetAdjustedPc(0xff, elf_.get())); 127 ASSERT_EQ(0xffU, arm.GetAdjustedPc(0xff, elf_.get()));
205 ASSERT_EQ(0x103U, arm.GetAdjustedPc(0x105, elf_.get())); 128 ASSERT_EQ(0x103U, arm.GetAdjustedPc(0x105, elf_.get()));
206 ASSERT_EQ(0x104U, arm.GetAdjustedPc(0x104, elf_.get())); 129 ASSERT_EQ(0x104U, arm.GetAdjustedPc(0x104, elf_.get()));
@@ -210,13 +133,13 @@ TEST_F(RegsTest, rel_pc_arm) {
210 ASSERT_EQ(0x100U, arm.GetAdjustedPc(0x100, elf_.get())); 133 ASSERT_EQ(0x100U, arm.GetAdjustedPc(0x100, elf_.get()));
211 134
212 // Check thumb instructions handling. 135 // Check thumb instructions handling.
213 elf_interface_->set_load_bias(0); 136 elf_interface_->FakeSetLoadBias(0);
214 memory_->SetData32(0x2000, 0); 137 memory_->SetData32(0x2000, 0);
215 ASSERT_EQ(0x2003U, arm.GetAdjustedPc(0x2005, elf_.get())); 138 ASSERT_EQ(0x2003U, arm.GetAdjustedPc(0x2005, elf_.get()));
216 memory_->SetData32(0x2000, 0xe000f000); 139 memory_->SetData32(0x2000, 0xe000f000);
217 ASSERT_EQ(0x2001U, arm.GetAdjustedPc(0x2005, elf_.get())); 140 ASSERT_EQ(0x2001U, arm.GetAdjustedPc(0x2005, elf_.get()));
218 141
219 elf_interface_->set_load_bias(0x400); 142 elf_interface_->FakeSetLoadBias(0x400);
220 memory_->SetData32(0x2100, 0); 143 memory_->SetData32(0x2100, 0);
221 ASSERT_EQ(0x2503U, arm.GetAdjustedPc(0x2505, elf_.get())); 144 ASSERT_EQ(0x2503U, arm.GetAdjustedPc(0x2505, elf_.get()));
222 memory_->SetData32(0x2100, 0xf111f111); 145 memory_->SetData32(0x2100, 0xf111f111);
diff --git a/libunwindstack/tests/TestUtils.h b/libunwindstack/tests/TestUtils.h
new file mode 100644
index 000000000..8c31aa6e5
--- /dev/null
+++ b/libunwindstack/tests/TestUtils.h
@@ -0,0 +1,55 @@
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _LIBUNWINDSTACK_TESTS_TEST_UTILS_H
18#define _LIBUNWINDSTACK_TESTS_TEST_UTILS_H
19
20#include <signal.h>
21#include <sys/ptrace.h>
22#include <sys/types.h>
23#include <sys/wait.h>
24
25namespace unwindstack {
26
27class TestScopedPidReaper {
28 public:
29 TestScopedPidReaper(pid_t pid) : pid_(pid) {}
30 ~TestScopedPidReaper() {
31 kill(pid_, SIGKILL);
32 waitpid(pid_, nullptr, 0);
33 }
34
35 private:
36 pid_t pid_;
37};
38
39inline bool TestQuiescePid(pid_t pid) {
40 siginfo_t si;
41 bool ready = false;
42 // Wait for up to 5 seconds.
43 for (size_t i = 0; i < 5000; i++) {
44 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
45 ready = true;
46 break;
47 }
48 usleep(1000);
49 }
50 return ready;
51}
52
53} // namespace unwindstack
54
55#endif // _LIBUNWINDSTACK_TESTS_TEST_UTILS_H
diff --git a/libunwindstack/tests/UnwindTest.cpp b/libunwindstack/tests/UnwindTest.cpp
index 2fc3a3880..9f9ca8b52 100644
--- a/libunwindstack/tests/UnwindTest.cpp
+++ b/libunwindstack/tests/UnwindTest.cpp
@@ -15,10 +15,9 @@
15 */ 15 */
16 16
17#include <errno.h> 17#include <errno.h>
18#include <string.h>
19
20#include <signal.h> 18#include <signal.h>
21#include <stdint.h> 19#include <stdint.h>
20#include <string.h>
22#include <sys/ptrace.h> 21#include <sys/ptrace.h>
23#include <sys/syscall.h> 22#include <sys/syscall.h>
24#include <unistd.h> 23#include <unistd.h>
@@ -32,26 +31,37 @@
32#include <thread> 31#include <thread>
33#include <vector> 32#include <vector>
34 33
35#include <unwindstack/Elf.h> 34#include <android-base/stringprintf.h>
36#include <unwindstack/MapInfo.h> 35
37#include <unwindstack/Maps.h> 36#include <unwindstack/Maps.h>
38#include <unwindstack/Memory.h> 37#include <unwindstack/Memory.h>
39#include <unwindstack/Regs.h> 38#include <unwindstack/Regs.h>
40#include <unwindstack/RegsGetLocal.h> 39#include <unwindstack/RegsGetLocal.h>
40#include <unwindstack/Unwinder.h>
41
42#include "TestUtils.h"
41 43
42namespace unwindstack { 44namespace unwindstack {
43 45
44static std::atomic_bool g_ready(false); 46static std::atomic_bool g_ready;
45static volatile bool g_ready_for_remote = false; 47static volatile bool g_ready_for_remote;
46static volatile bool g_signal_ready_for_remote = false; 48static volatile bool g_signal_ready_for_remote;
47static std::atomic_bool g_finish(false); 49static std::atomic_bool g_finish;
48static std::atomic_uintptr_t g_ucontext; 50static std::atomic_uintptr_t g_ucontext;
49 51
50static std::vector<const char*> kFunctionOrder{"InnerFunction", "MiddleFunction", "OuterFunction"}; 52static void ResetGlobals() {
53 g_ready = false;
54 g_ready_for_remote = false;
55 g_signal_ready_for_remote = false;
56 g_finish = false;
57 g_ucontext = 0;
58}
59
60static std::vector<const char*> kFunctionOrder{"OuterFunction", "MiddleFunction", "InnerFunction"};
51 61
52static std::vector<const char*> kFunctionSignalOrder{"SignalInnerFunction", "SignalMiddleFunction", 62static std::vector<const char*> kFunctionSignalOrder{"OuterFunction", "MiddleFunction",
53 "SignalOuterFunction", "InnerFunction", 63 "InnerFunction", "SignalOuterFunction",
54 "MiddleFunction", "OuterFunction"}; 64 "SignalMiddleFunction", "SignalInnerFunction"};
55 65
56static void SignalHandler(int, siginfo_t*, void* sigcontext) { 66static void SignalHandler(int, siginfo_t*, void* sigcontext) {
57 g_ucontext = reinterpret_cast<uintptr_t>(sigcontext); 67 g_ucontext = reinterpret_cast<uintptr_t>(sigcontext);
@@ -77,127 +87,117 @@ static void SignalCallerHandler(int, siginfo_t*, void*) {
77 SignalOuterFunction(); 87 SignalOuterFunction();
78} 88}
79 89
80static std::string ErrorMsg(const std::vector<const char*>& function_names, size_t index, 90static std::string ErrorMsg(const std::vector<const char*>& function_names, Unwinder& unwinder) {
81 std::stringstream& unwind_stream) { 91 std::string unwind;
92 for (size_t i = 0; i < unwinder.NumFrames(); i++) {
93 unwind += unwinder.FormatFrame(i) + '\n';
94 }
95
82 return std::string( 96 return std::string(
83 "Unwind completed without finding all frames\n" 97 "Unwind completed without finding all frames\n"
84 " Looking for function: ") + 98 " Looking for function: ") +
85 function_names[index] + "\n" + "Unwind data:\n" + unwind_stream.str(); 99 function_names.front() + "\n" + "Unwind data:\n" + unwind;
86} 100}
87 101
88static void VerifyUnwind(pid_t pid, Memory* memory, Maps* maps, Regs* regs, 102static void VerifyUnwind(pid_t pid, Maps* maps, Regs* regs,
89 std::vector<const char*>& function_names) { 103 std::vector<const char*> expected_function_names) {
90 size_t function_name_index = 0; 104 auto process_memory(Memory::CreateProcessMemory(pid));
91 105
92 std::stringstream unwind_stream; 106 Unwinder unwinder(512, maps, regs, process_memory);
93 unwind_stream << std::hex; 107 unwinder.Unwind();
94 for (size_t frame_num = 0; frame_num < 64; frame_num++) { 108
95 ASSERT_NE(0U, regs->pc()) << ErrorMsg(function_names, function_name_index, unwind_stream); 109 std::string expected_function = expected_function_names.back();
96 MapInfo* map_info = maps->Find(regs->pc()); 110 expected_function_names.pop_back();
97 ASSERT_TRUE(map_info != nullptr) << ErrorMsg(function_names, function_name_index, unwind_stream); 111 for (auto& frame : unwinder.frames()) {
98 112 if (frame.function_name == expected_function) {
99 Elf* elf = map_info->GetElf(pid, true); 113 if (expected_function_names.empty()) {
100 uint64_t rel_pc = elf->GetRelPc(regs->pc(), map_info); 114 break;
101 uint64_t adjusted_rel_pc = rel_pc;
102 if (frame_num != 0) {
103 adjusted_rel_pc = regs->GetAdjustedPc(rel_pc, elf);
104 }
105 unwind_stream << " PC: 0x" << regs->pc() << " Rel: 0x" << adjusted_rel_pc;
106 unwind_stream << " Map: ";
107 if (!map_info->name.empty()) {
108 unwind_stream << map_info->name;
109 } else {
110 unwind_stream << " anonymous";
111 }
112 unwind_stream << "<" << map_info->start << "-" << map_info->end << ">";
113
114 std::string name;
115 uint64_t func_offset;
116 if (elf->GetFunctionName(adjusted_rel_pc, &name, &func_offset)) {
117 if (name == function_names[function_name_index]) {
118 if (++function_name_index == function_names.size()) {
119 return;
120 }
121 } 115 }
122 unwind_stream << " " << name; 116 expected_function = expected_function_names.back();
117 expected_function_names.pop_back();
123 } 118 }
124 unwind_stream << "\n";
125 ASSERT_TRUE(elf->Step(rel_pc + map_info->elf_offset, regs, memory))
126 << ErrorMsg(function_names, function_name_index, unwind_stream);
127 } 119 }
128 ASSERT_TRUE(false) << ErrorMsg(function_names, function_name_index, unwind_stream); 120
121 ASSERT_TRUE(expected_function_names.empty()) << ErrorMsg(expected_function_names, unwinder);
129} 122}
130 123
131// This test assumes that this code is compiled with optimizations turned 124// This test assumes that this code is compiled with optimizations turned
132// off. If this doesn't happen, then all of the calls will be optimized 125// off. If this doesn't happen, then all of the calls will be optimized
133// away. 126// away.
134extern "C" void InnerFunction(bool local) { 127extern "C" void InnerFunction(bool local, bool trigger_invalid_call) {
135 if (local) { 128 if (local) {
136 LocalMaps maps; 129 LocalMaps maps;
137 ASSERT_TRUE(maps.Parse()); 130 ASSERT_TRUE(maps.Parse());
138 std::unique_ptr<Regs> regs(Regs::CreateFromLocal()); 131 std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
139 RegsGetLocal(regs.get()); 132 RegsGetLocal(regs.get());
140 MemoryLocal memory;
141 133
142 VerifyUnwind(getpid(), &memory, &maps, regs.get(), kFunctionOrder); 134 VerifyUnwind(getpid(), &maps, regs.get(), kFunctionOrder);
143 } else { 135 } else {
144 g_ready_for_remote = true; 136 g_ready_for_remote = true;
145 g_ready = true; 137 g_ready = true;
138 if (trigger_invalid_call) {
139 void (*crash_func)() = nullptr;
140 crash_func();
141 }
146 while (!g_finish.load()) { 142 while (!g_finish.load()) {
147 } 143 }
148 } 144 }
149} 145}
150 146
151extern "C" void MiddleFunction(bool local) { 147extern "C" void MiddleFunction(bool local, bool trigger_invalid_call) {
152 InnerFunction(local); 148 InnerFunction(local, trigger_invalid_call);
153} 149}
154 150
155extern "C" void OuterFunction(bool local) { 151extern "C" void OuterFunction(bool local, bool trigger_invalid_call) {
156 MiddleFunction(local); 152 MiddleFunction(local, trigger_invalid_call);
157} 153}
158 154
159TEST(UnwindTest, local) { 155class UnwindTest : public ::testing::Test {
160 OuterFunction(true); 156 public:
157 void SetUp() override { ResetGlobals(); }
158};
159
160TEST_F(UnwindTest, local) {
161 OuterFunction(true, false);
161} 162}
162 163
163void WaitForRemote(pid_t pid, uint64_t addr, bool leave_attached, bool* completed) { 164void WaitForRemote(pid_t pid, uint64_t addr, bool leave_attached, bool* completed) {
164 *completed = false; 165 *completed = false;
165 // Need to sleep before attempting first ptrace. Without this, on the 166 // Need to sleep before attempting first ptrace. Without this, on the
166 // host it becomes impossible to attach and ptrace set errno to EPERM. 167 // host it becomes impossible to attach and ptrace sets errno to EPERM.
167 usleep(1000); 168 usleep(1000);
168 for (size_t i = 0; i < 100; i++) { 169 for (size_t i = 0; i < 1000; i++) {
169 ASSERT_EQ(0, ptrace(PTRACE_ATTACH, pid, 0, 0)); 170 if (ptrace(PTRACE_ATTACH, pid, 0, 0) == 0) {
170 for (size_t j = 0; j < 100; j++) { 171 ASSERT_TRUE(TestQuiescePid(pid))
171 siginfo_t si; 172 << "Waiting for process to quiesce failed: " << strerror(errno);
172 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) { 173
173 MemoryRemote memory(pid); 174 MemoryRemote memory(pid);
174 // Read the remote value to see if we are ready. 175 // Read the remote value to see if we are ready.
175 bool value; 176 bool value;
176 if (memory.Read(addr, &value, sizeof(value)) && value) { 177 if (memory.Read(addr, &value, sizeof(value)) && value) {
177 *completed = true; 178 *completed = true;
178 break;
179 }
180 } 179 }
181 usleep(1000); 180 if (!*completed || !leave_attached) {
182 } 181 ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0));
183 if (leave_attached && *completed) { 182 }
184 break; 183 if (*completed) {
185 } 184 break;
186 ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0)); 185 }
187 if (*completed) { 186 } else {
188 break; 187 ASSERT_EQ(ESRCH, errno) << "ptrace attach failed with unexpected error: " << strerror(errno);
189 } 188 }
190 usleep(1000); 189 usleep(5000);
191 } 190 }
192} 191}
193 192
194TEST(UnwindTest, remote) { 193TEST_F(UnwindTest, remote) {
195 pid_t pid; 194 pid_t pid;
196 if ((pid = fork()) == 0) { 195 if ((pid = fork()) == 0) {
197 OuterFunction(false); 196 OuterFunction(false, false);
198 exit(0); 197 exit(0);
199 } 198 }
200 ASSERT_NE(-1, pid); 199 ASSERT_NE(-1, pid);
200 TestScopedPidReaper reap(pid);
201 201
202 bool completed; 202 bool completed;
203 WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_ready_for_remote), true, &completed); 203 WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_ready_for_remote), true, &completed);
@@ -205,23 +205,20 @@ TEST(UnwindTest, remote) {
205 205
206 RemoteMaps maps(pid); 206 RemoteMaps maps(pid);
207 ASSERT_TRUE(maps.Parse()); 207 ASSERT_TRUE(maps.Parse());
208 MemoryRemote memory(pid);
209 std::unique_ptr<Regs> regs(Regs::RemoteGet(pid)); 208 std::unique_ptr<Regs> regs(Regs::RemoteGet(pid));
210 ASSERT_TRUE(regs.get() != nullptr); 209 ASSERT_TRUE(regs.get() != nullptr);
211 210
212 VerifyUnwind(pid, &memory, &maps, regs.get(), kFunctionOrder); 211 VerifyUnwind(pid, &maps, regs.get(), kFunctionOrder);
213
214 ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0));
215 212
216 kill(pid, SIGKILL); 213 ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0))
217 ASSERT_EQ(pid, wait(nullptr)); 214 << "ptrace detach failed with unexpected error: " << strerror(errno);
218} 215}
219 216
220TEST(UnwindTest, from_context) { 217TEST_F(UnwindTest, from_context) {
221 std::atomic_int tid(0); 218 std::atomic_int tid(0);
222 std::thread thread([&]() { 219 std::thread thread([&]() {
223 tid = syscall(__NR_gettid); 220 tid = syscall(__NR_gettid);
224 OuterFunction(false); 221 OuterFunction(false, false);
225 }); 222 });
226 223
227 struct sigaction act, oldact; 224 struct sigaction act, oldact;
@@ -254,9 +251,8 @@ TEST(UnwindTest, from_context) {
254 LocalMaps maps; 251 LocalMaps maps;
255 ASSERT_TRUE(maps.Parse()); 252 ASSERT_TRUE(maps.Parse());
256 std::unique_ptr<Regs> regs(Regs::CreateFromUcontext(Regs::CurrentMachineType(), ucontext)); 253 std::unique_ptr<Regs> regs(Regs::CreateFromUcontext(Regs::CurrentMachineType(), ucontext));
257 MemoryLocal memory;
258 254
259 VerifyUnwind(tid.load(), &memory, &maps, regs.get(), kFunctionOrder); 255 VerifyUnwind(getpid(), &maps, regs.get(), kFunctionOrder);
260 256
261 ASSERT_EQ(0, sigaction(SIGUSR1, &oldact, nullptr)); 257 ASSERT_EQ(0, sigaction(SIGUSR1, &oldact, nullptr));
262 258
@@ -264,51 +260,55 @@ TEST(UnwindTest, from_context) {
264 thread.join(); 260 thread.join();
265} 261}
266 262
267static void RemoteThroughSignal(unsigned int sa_flags) { 263static void RemoteThroughSignal(int signal, unsigned int sa_flags) {
268 g_ready = false;
269 g_signal_ready_for_remote = false;
270 g_finish = false;
271
272 pid_t pid; 264 pid_t pid;
273 if ((pid = fork()) == 0) { 265 if ((pid = fork()) == 0) {
274 struct sigaction act, oldact; 266 struct sigaction act, oldact;
275 memset(&act, 0, sizeof(act)); 267 memset(&act, 0, sizeof(act));
276 act.sa_sigaction = SignalCallerHandler; 268 act.sa_sigaction = SignalCallerHandler;
277 act.sa_flags = SA_RESTART | SA_ONSTACK | sa_flags; 269 act.sa_flags = SA_RESTART | SA_ONSTACK | sa_flags;
278 ASSERT_EQ(0, sigaction(SIGUSR1, &act, &oldact)); 270 ASSERT_EQ(0, sigaction(signal, &act, &oldact));
279 271
280 OuterFunction(false); 272 OuterFunction(false, signal == SIGSEGV);
281 exit(0); 273 exit(0);
282 } 274 }
283 ASSERT_NE(-1, pid); 275 ASSERT_NE(-1, pid);
276 TestScopedPidReaper reap(pid);
284 277
285 bool completed; 278 bool completed;
286 WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_ready_for_remote), false, &completed); 279 if (signal != SIGSEGV) {
287 ASSERT_TRUE(completed) << "Timed out waiting for remote process to be ready."; 280 WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_ready_for_remote), false, &completed);
288 ASSERT_EQ(0, kill(pid, SIGUSR1)); 281 ASSERT_TRUE(completed) << "Timed out waiting for remote process to be ready.";
282 ASSERT_EQ(0, kill(pid, SIGUSR1));
283 }
289 WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_signal_ready_for_remote), true, &completed); 284 WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_signal_ready_for_remote), true, &completed);
290 ASSERT_TRUE(completed) << "Timed out waiting for remote process to be in signal handler."; 285 ASSERT_TRUE(completed) << "Timed out waiting for remote process to be in signal handler.";
291 286
292 RemoteMaps maps(pid); 287 RemoteMaps maps(pid);
293 ASSERT_TRUE(maps.Parse()); 288 ASSERT_TRUE(maps.Parse());
294 MemoryRemote memory(pid);
295 std::unique_ptr<Regs> regs(Regs::RemoteGet(pid)); 289 std::unique_ptr<Regs> regs(Regs::RemoteGet(pid));
296 ASSERT_TRUE(regs.get() != nullptr); 290 ASSERT_TRUE(regs.get() != nullptr);
297 291
298 VerifyUnwind(pid, &memory, &maps, regs.get(), kFunctionSignalOrder); 292 VerifyUnwind(pid, &maps, regs.get(), kFunctionSignalOrder);
293
294 ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0))
295 << "ptrace detach failed with unexpected error: " << strerror(errno);
296}
299 297
300 ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0)); 298TEST_F(UnwindTest, remote_through_signal) {
299 RemoteThroughSignal(SIGUSR1, 0);
300}
301 301
302 kill(pid, SIGKILL); 302TEST_F(UnwindTest, remote_through_signal_sa_siginfo) {
303 ASSERT_EQ(pid, wait(nullptr)); 303 RemoteThroughSignal(SIGUSR1, SA_SIGINFO);
304} 304}
305 305
306TEST(UnwindTest, remote_through_signal) { 306TEST_F(UnwindTest, remote_through_signal_with_invalid_func) {
307 RemoteThroughSignal(0); 307 RemoteThroughSignal(SIGSEGV, 0);
308} 308}
309 309
310TEST(UnwindTest, remote_through_signal_sa_siginfo) { 310TEST_F(UnwindTest, remote_through_signal_sa_siginfo_with_invalid_func) {
311 RemoteThroughSignal(SA_SIGINFO); 311 RemoteThroughSignal(SIGSEGV, SA_SIGINFO);
312} 312}
313 313
314} // namespace unwindstack 314} // namespace unwindstack
diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp
new file mode 100644
index 000000000..4d0366ca5
--- /dev/null
+++ b/libunwindstack/tests/UnwinderTest.cpp
@@ -0,0 +1,576 @@
1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <elf.h>
18#include <stdint.h>
19#include <sys/mman.h>
20
21#include <memory>
22#include <set>
23#include <string>
24
25#include <gtest/gtest.h>
26
27#include <unwindstack/Elf.h>
28#include <unwindstack/Maps.h>
29#include <unwindstack/Memory.h>
30#include <unwindstack/Regs.h>
31#include <unwindstack/Unwinder.h>
32
33#include "ElfFake.h"
34#include "MemoryFake.h"
35#include "RegsFake.h"
36
37namespace unwindstack {
38
39class MapsFake : public Maps {
40 public:
41 MapsFake() = default;
42 virtual ~MapsFake() = default;
43
44 bool Parse() { return true; }
45
46 void FakeClear() { maps_.clear(); }
47
48 void FakeAddMapInfo(const MapInfo& map_info) { maps_.push_back(map_info); }
49};
50
51class UnwinderTest : public ::testing::Test {
52 protected:
53 static void SetUpTestCase() {
54 maps_.FakeClear();
55 MapInfo info;
56 info.name = "/system/fake/libc.so";
57 info.start = 0x1000;
58 info.end = 0x8000;
59 info.offset = 0;
60 info.flags = PROT_READ | PROT_WRITE;
61 ElfFake* elf = new ElfFake(nullptr);
62 info.elf = elf;
63 elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
64 info.elf_offset = 0;
65 maps_.FakeAddMapInfo(info);
66
67 info.name = "[stack]";
68 info.start = 0x10000;
69 info.end = 0x12000;
70 info.flags = PROT_READ | PROT_WRITE;
71 info.elf = nullptr;
72 maps_.FakeAddMapInfo(info);
73
74 info.name = "/dev/fake_device";
75 info.start = 0x13000;
76 info.end = 0x15000;
77 info.flags = PROT_READ | PROT_WRITE | MAPS_FLAGS_DEVICE_MAP;
78 info.elf = nullptr;
79 maps_.FakeAddMapInfo(info);
80
81 info.name = "/system/fake/libunwind.so";
82 info.start = 0x20000;
83 info.end = 0x22000;
84 info.flags = PROT_READ | PROT_WRITE;
85 elf = new ElfFake(nullptr);
86 info.elf = elf;
87 elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
88 maps_.FakeAddMapInfo(info);
89
90 info.name = "/fake/libanother.so";
91 info.start = 0x23000;
92 info.end = 0x24000;
93 info.flags = PROT_READ | PROT_WRITE;
94 elf = new ElfFake(nullptr);
95 info.elf = elf;
96 elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
97 maps_.FakeAddMapInfo(info);
98 }
99
100 void SetUp() override {
101 ElfInterfaceFake::FakeClear();
102 regs_.FakeSetMachineType(EM_ARM);
103 }
104
105 static MapsFake maps_;
106 static RegsFake regs_;
107 static std::shared_ptr<Memory> process_memory_;
108};
109
110MapsFake UnwinderTest::maps_;
111RegsFake UnwinderTest::regs_(5, 0);
112std::shared_ptr<Memory> UnwinderTest::process_memory_(nullptr);
113
114TEST_F(UnwinderTest, multiple_frames) {
115 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
116 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
117 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
118
119 regs_.FakeSetPc(0x1000);
120 regs_.FakeSetSp(0x10000);
121 ElfInterfaceFake::FakePushStepData(StepData(0x1102, 0x10010, false));
122 ElfInterfaceFake::FakePushStepData(StepData(0x1202, 0x10020, false));
123 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
124
125 Unwinder unwinder(64, &maps_, &regs_, process_memory_);
126 unwinder.Unwind();
127
128 ASSERT_EQ(3U, unwinder.NumFrames());
129
130 auto* frame = &unwinder.frames()[0];
131 EXPECT_EQ(0U, frame->num);
132 EXPECT_EQ(0U, frame->rel_pc);
133 EXPECT_EQ(0x1000U, frame->pc);
134 EXPECT_EQ(0x10000U, frame->sp);
135 EXPECT_EQ("Frame0", frame->function_name);
136 EXPECT_EQ(0U, frame->function_offset);
137 EXPECT_EQ("/system/fake/libc.so", frame->map_name);
138 EXPECT_EQ(0U, frame->map_offset);
139 EXPECT_EQ(0x1000U, frame->map_start);
140 EXPECT_EQ(0x8000U, frame->map_end);
141 EXPECT_EQ(0U, frame->map_load_bias);
142 EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
143
144 frame = &unwinder.frames()[1];
145 EXPECT_EQ(1U, frame->num);
146 EXPECT_EQ(0x100U, frame->rel_pc);
147 EXPECT_EQ(0x1100U, frame->pc);
148 EXPECT_EQ(0x10010U, frame->sp);
149 EXPECT_EQ("Frame1", frame->function_name);
150 EXPECT_EQ(1U, frame->function_offset);
151 EXPECT_EQ("/system/fake/libc.so", frame->map_name);
152 EXPECT_EQ(0U, frame->map_offset);
153 EXPECT_EQ(0x1000U, frame->map_start);
154 EXPECT_EQ(0x8000U, frame->map_end);
155 EXPECT_EQ(0U, frame->map_load_bias);
156 EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
157
158 frame = &unwinder.frames()[2];
159 EXPECT_EQ(2U, frame->num);
160 EXPECT_EQ(0x200U, frame->rel_pc);
161 EXPECT_EQ(0x1200U, frame->pc);
162 EXPECT_EQ(0x10020U, frame->sp);
163 EXPECT_EQ("Frame2", frame->function_name);
164 EXPECT_EQ(2U, frame->function_offset);
165 EXPECT_EQ("/system/fake/libc.so", frame->map_name);
166 EXPECT_EQ(0U, frame->map_offset);
167 EXPECT_EQ(0x1000U, frame->map_start);
168 EXPECT_EQ(0x8000U, frame->map_end);
169 EXPECT_EQ(0U, frame->map_load_bias);
170 EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
171}
172
173// Verify that no attempt to continue after the step indicates it is done.
174TEST_F(UnwinderTest, no_frames_after_finished) {
175 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
176 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
177 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
178 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame3", 3));
179 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame4", 4));
180
181 regs_.FakeSetPc(0x1000);
182 regs_.FakeSetSp(0x10000);
183 ElfInterfaceFake::FakePushStepData(StepData(0x1000, 0x10000, true));
184 ElfInterfaceFake::FakePushStepData(StepData(0x1102, 0x10010, false));
185 ElfInterfaceFake::FakePushStepData(StepData(0x1202, 0x10020, false));
186
187 Unwinder unwinder(64, &maps_, &regs_, process_memory_);
188 unwinder.Unwind();
189
190 ASSERT_EQ(1U, unwinder.NumFrames());
191
192 auto* frame = &unwinder.frames()[0];
193 EXPECT_EQ(0U, frame->num);
194 EXPECT_EQ(0U, frame->rel_pc);
195 EXPECT_EQ(0x1000U, frame->pc);
196 EXPECT_EQ(0x10000U, frame->sp);
197 EXPECT_EQ("Frame0", frame->function_name);
198 EXPECT_EQ(0U, frame->function_offset);
199 EXPECT_EQ("/system/fake/libc.so", frame->map_name);
200 EXPECT_EQ(0U, frame->map_offset);
201 EXPECT_EQ(0x1000U, frame->map_start);
202 EXPECT_EQ(0x8000U, frame->map_end);
203 EXPECT_EQ(0U, frame->map_load_bias);
204 EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
205}
206
207// Verify the maximum frames to save.
208TEST_F(UnwinderTest, max_frames) {
209 for (size_t i = 0; i < 30; i++) {
210 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame" + std::to_string(i), i));
211 ElfInterfaceFake::FakePushStepData(StepData(0x1102 + i * 0x100, 0x10010 + i * 0x10, false));
212 }
213
214 regs_.FakeSetPc(0x1000);
215 regs_.FakeSetSp(0x10000);
216
217 Unwinder unwinder(20, &maps_, &regs_, process_memory_);
218 unwinder.Unwind();
219
220 ASSERT_EQ(20U, unwinder.NumFrames());
221
222 for (size_t i = 0; i < 20; i++) {
223 auto* frame = &unwinder.frames()[i];
224 EXPECT_EQ(i, frame->num);
225 EXPECT_EQ(i * 0x100, frame->rel_pc) << "Failed at frame " << i;
226 EXPECT_EQ(0x1000 + i * 0x100, frame->pc) << "Failed at frame " << i;
227 EXPECT_EQ(0x10000 + 0x10 * i, frame->sp) << "Failed at frame " << i;
228 EXPECT_EQ("Frame" + std::to_string(i), frame->function_name) << "Failed at frame " << i;
229 EXPECT_EQ(i, frame->function_offset) << "Failed at frame " << i;
230 EXPECT_EQ("/system/fake/libc.so", frame->map_name) << "Failed at frame " << i;
231 EXPECT_EQ(0U, frame->map_offset) << "Failed at frame " << i;
232 EXPECT_EQ(0x1000U, frame->map_start) << "Failed at frame " << i;
233 EXPECT_EQ(0x8000U, frame->map_end) << "Failed at frame " << i;
234 EXPECT_EQ(0U, frame->map_load_bias) << "Failed at frame " << i;
235 EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags) << "Failed at frame " << i;
236 }
237}
238
239// Verify that initial map names frames are removed.
240TEST_F(UnwinderTest, verify_frames_skipped) {
241 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
242 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
243 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
244
245 regs_.FakeSetPc(0x20000);
246 regs_.FakeSetSp(0x10000);
247 ElfInterfaceFake::FakePushStepData(StepData(0x23002, 0x10010, false));
248 ElfInterfaceFake::FakePushStepData(StepData(0x23102, 0x10020, false));
249 ElfInterfaceFake::FakePushStepData(StepData(0x20002, 0x10030, false));
250 ElfInterfaceFake::FakePushStepData(StepData(0x21002, 0x10040, false));
251 ElfInterfaceFake::FakePushStepData(StepData(0x1002, 0x10050, false));
252 ElfInterfaceFake::FakePushStepData(StepData(0x21002, 0x10060, false));
253 ElfInterfaceFake::FakePushStepData(StepData(0x23002, 0x10070, false));
254 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
255
256 Unwinder unwinder(64, &maps_, &regs_, process_memory_);
257 std::set<std::string> skip_set{"libunwind.so", "libanother.so"};
258 unwinder.Unwind(&skip_set);
259
260 ASSERT_EQ(3U, unwinder.NumFrames());
261
262 auto* frame = &unwinder.frames()[0];
263 EXPECT_EQ(0U, frame->num);
264 EXPECT_EQ(0U, frame->rel_pc);
265 EXPECT_EQ(0x1000U, frame->pc);
266 EXPECT_EQ(0x10050U, frame->sp);
267 EXPECT_EQ("Frame0", frame->function_name);
268 EXPECT_EQ(0U, frame->function_offset);
269 EXPECT_EQ("/system/fake/libc.so", frame->map_name);
270 EXPECT_EQ(0U, frame->map_offset);
271 EXPECT_EQ(0x1000U, frame->map_start);
272 EXPECT_EQ(0x8000U, frame->map_end);
273 EXPECT_EQ(0U, frame->map_load_bias);
274 EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
275
276 frame = &unwinder.frames()[1];
277 EXPECT_EQ(1U, frame->num);
278 EXPECT_EQ(0x1000U, frame->rel_pc);
279 EXPECT_EQ(0x21000U, frame->pc);
280 EXPECT_EQ(0x10060U, frame->sp);
281 EXPECT_EQ("Frame1", frame->function_name);
282 EXPECT_EQ(1U, frame->function_offset);
283 EXPECT_EQ("/system/fake/libunwind.so", frame->map_name);
284 EXPECT_EQ(0U, frame->map_offset);
285 EXPECT_EQ(0x20000U, frame->map_start);
286 EXPECT_EQ(0x22000U, frame->map_end);
287 EXPECT_EQ(0U, frame->map_load_bias);
288 EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
289
290 frame = &unwinder.frames()[2];
291 EXPECT_EQ(2U, frame->num);
292 EXPECT_EQ(0U, frame->rel_pc);
293 EXPECT_EQ(0x23000U, frame->pc);
294 EXPECT_EQ(0x10070U, frame->sp);
295 EXPECT_EQ("Frame2", frame->function_name);
296 EXPECT_EQ(2U, frame->function_offset);
297 EXPECT_EQ("/fake/libanother.so", frame->map_name);
298 EXPECT_EQ(0U, frame->map_offset);
299 EXPECT_EQ(0x23000U, frame->map_start);
300 EXPECT_EQ(0x24000U, frame->map_end);
301 EXPECT_EQ(0U, frame->map_load_bias);
302 EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
303}
304
305// Verify SP in a non-existant map is okay.
306TEST_F(UnwinderTest, sp_not_in_map) {
307 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
308 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
309
310 regs_.FakeSetPc(0x1000);
311 regs_.FakeSetSp(0x53000);
312 ElfInterfaceFake::FakePushStepData(StepData(0x21002, 0x50020, false));
313 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
314
315 Unwinder unwinder(64, &maps_, &regs_, process_memory_);
316 unwinder.Unwind();
317
318 ASSERT_EQ(2U, unwinder.NumFrames());
319
320 auto* frame = &unwinder.frames()[0];
321 EXPECT_EQ(0U, frame->num);
322 EXPECT_EQ(0U, frame->rel_pc);
323 EXPECT_EQ(0x1000U, frame->pc);
324 EXPECT_EQ(0x53000U, frame->sp);
325 EXPECT_EQ("Frame0", frame->function_name);
326 EXPECT_EQ(0U, frame->function_offset);
327 EXPECT_EQ("/system/fake/libc.so", frame->map_name);
328 EXPECT_EQ(0U, frame->map_offset);
329 EXPECT_EQ(0x1000U, frame->map_start);
330 EXPECT_EQ(0x8000U, frame->map_end);
331 EXPECT_EQ(0U, frame->map_load_bias);
332 EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
333
334 frame = &unwinder.frames()[1];
335 EXPECT_EQ(1U, frame->num);
336 EXPECT_EQ(0x1000U, frame->rel_pc);
337 EXPECT_EQ(0x21000U, frame->pc);
338 EXPECT_EQ(0x50020U, frame->sp);
339 EXPECT_EQ("Frame1", frame->function_name);
340 EXPECT_EQ(1U, frame->function_offset);
341 EXPECT_EQ("/system/fake/libunwind.so", frame->map_name);
342 EXPECT_EQ(0U, frame->map_offset);
343 EXPECT_EQ(0x20000U, frame->map_start);
344 EXPECT_EQ(0x22000U, frame->map_end);
345 EXPECT_EQ(0U, frame->map_load_bias);
346 EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
347}
348
349// Verify PC in a device stops the unwind.
350TEST_F(UnwinderTest, pc_in_device_stops_unwind) {
351 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
352 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
353 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
354
355 regs_.FakeSetPc(0x13000);
356 regs_.FakeSetSp(0x10000);
357 ElfInterfaceFake::FakePushStepData(StepData(0x23002, 0x10010, false));
358 ElfInterfaceFake::FakePushStepData(StepData(0x23102, 0x10020, false));
359 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
360
361 Unwinder unwinder(64, &maps_, &regs_, process_memory_);
362 unwinder.Unwind();
363
364 ASSERT_EQ(1U, unwinder.NumFrames());
365}
366
367// Verify SP in a device stops the unwind.
368TEST_F(UnwinderTest, sp_in_device_stops_unwind) {
369 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
370 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
371 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
372
373 regs_.FakeSetPc(0x1000);
374 regs_.FakeSetSp(0x13000);
375 ElfInterfaceFake::FakePushStepData(StepData(0x23002, 0x10010, false));
376 ElfInterfaceFake::FakePushStepData(StepData(0x23102, 0x10020, false));
377 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
378
379 Unwinder unwinder(64, &maps_, &regs_, process_memory_);
380 unwinder.Unwind();
381
382 ASSERT_EQ(1U, unwinder.NumFrames());
383}
384
385// Verify a no map info frame gets a frame.
386TEST_F(UnwinderTest, pc_without_map) {
387 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
388
389 regs_.FakeSetPc(0x41000);
390 regs_.FakeSetSp(0x13000);
391
392 Unwinder unwinder(64, &maps_, &regs_, process_memory_);
393 unwinder.Unwind();
394
395 ASSERT_EQ(1U, unwinder.NumFrames());
396
397 auto* frame = &unwinder.frames()[0];
398 EXPECT_EQ(0U, frame->num);
399 EXPECT_EQ(0x41000U, frame->rel_pc);
400 EXPECT_EQ(0x41000U, frame->pc);
401 EXPECT_EQ(0x13000U, frame->sp);
402 EXPECT_EQ("", frame->function_name);
403 EXPECT_EQ(0U, frame->function_offset);
404 EXPECT_EQ("", frame->map_name);
405 EXPECT_EQ(0U, frame->map_offset);
406 EXPECT_EQ(0U, frame->map_start);
407 EXPECT_EQ(0U, frame->map_end);
408 EXPECT_EQ(0U, frame->map_load_bias);
409 EXPECT_EQ(0, frame->map_flags);
410}
411
412// Verify that a speculative frame is added.
413TEST_F(UnwinderTest, speculative_frame) {
414 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
415 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
416
417 // Fake as if code called a nullptr function.
418 regs_.FakeSetPc(0);
419 regs_.FakeSetSp(0x10000);
420 regs_.FakeSetReturnAddress(0x1202);
421 regs_.FakeSetReturnAddressValid(true);
422
423 ElfInterfaceFake::FakePushStepData(StepData(0x23102, 0x10020, false));
424 ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
425
426 Unwinder unwinder(64, &maps_, &regs_, process_memory_);
427 unwinder.Unwind();
428
429 ASSERT_EQ(3U, unwinder.NumFrames());
430
431 auto* frame = &unwinder.frames()[0];
432 EXPECT_EQ(0U, frame->num);
433 EXPECT_EQ(0U, frame->rel_pc);
434 EXPECT_EQ(0U, frame->pc);
435 EXPECT_EQ(0x10000U, frame->sp);
436 EXPECT_EQ("", frame->function_name);
437 EXPECT_EQ(0U, frame->function_offset);
438 EXPECT_EQ("", frame->map_name);
439 EXPECT_EQ(0U, frame->map_offset);
440 EXPECT_EQ(0U, frame->map_start);
441 EXPECT_EQ(0U, frame->map_end);
442 EXPECT_EQ(0U, frame->map_load_bias);
443 EXPECT_EQ(0, frame->map_flags);
444
445 frame = &unwinder.frames()[1];
446 EXPECT_EQ(1U, frame->num);
447 EXPECT_EQ(0x200U, frame->rel_pc);
448 EXPECT_EQ(0x1200U, frame->pc);
449 EXPECT_EQ(0x10000U, frame->sp);
450 EXPECT_EQ("Frame0", frame->function_name);
451 EXPECT_EQ(0U, frame->function_offset);
452 EXPECT_EQ("/system/fake/libc.so", frame->map_name);
453 EXPECT_EQ(0U, frame->map_offset);
454 EXPECT_EQ(0x1000U, frame->map_start);
455 EXPECT_EQ(0x8000U, frame->map_end);
456 EXPECT_EQ(0U, frame->map_load_bias);
457 EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
458
459 frame = &unwinder.frames()[2];
460 EXPECT_EQ(2U, frame->num);
461 EXPECT_EQ(0x100U, frame->rel_pc);
462 EXPECT_EQ(0x23100U, frame->pc);
463 EXPECT_EQ(0x10020U, frame->sp);
464 EXPECT_EQ("Frame1", frame->function_name);
465 EXPECT_EQ(1U, frame->function_offset);
466 EXPECT_EQ("/fake/libanother.so", frame->map_name);
467 EXPECT_EQ(0U, frame->map_offset);
468 EXPECT_EQ(0x23000U, frame->map_start);
469 EXPECT_EQ(0x24000U, frame->map_end);
470 EXPECT_EQ(0U, frame->map_load_bias);
471 EXPECT_EQ(PROT_READ | PROT_WRITE, frame->map_flags);
472}
473
474// Verify that a speculative frame is added then removed because no other
475// frames are added.
476TEST_F(UnwinderTest, speculative_frame_removed) {
477 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
478 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
479
480 // Fake as if code called a nullptr function.
481 regs_.FakeSetPc(0);
482 regs_.FakeSetSp(0x10000);
483 regs_.FakeSetReturnAddress(0x1202);
484 regs_.FakeSetReturnAddressValid(true);
485
486 Unwinder unwinder(64, &maps_, &regs_, process_memory_);
487 unwinder.Unwind();
488
489 ASSERT_EQ(1U, unwinder.NumFrames());
490
491 auto* frame = &unwinder.frames()[0];
492 EXPECT_EQ(0U, frame->num);
493 EXPECT_EQ(0U, frame->rel_pc);
494 EXPECT_EQ(0U, frame->pc);
495 EXPECT_EQ(0x10000U, frame->sp);
496 EXPECT_EQ("", frame->function_name);
497 EXPECT_EQ(0U, frame->function_offset);
498 EXPECT_EQ("", frame->map_name);
499 EXPECT_EQ(0U, frame->map_offset);
500 EXPECT_EQ(0U, frame->map_start);
501 EXPECT_EQ(0U, frame->map_end);
502 EXPECT_EQ(0U, frame->map_load_bias);
503 EXPECT_EQ(0, frame->map_flags);
504}
505
506// Verify format frame code.
507TEST_F(UnwinderTest, format_frame_static) {
508 FrameData frame;
509 frame.num = 1;
510 frame.rel_pc = 0x1000;
511 frame.pc = 0x4000;
512 frame.sp = 0x1000;
513 frame.function_name = "function";
514 frame.function_offset = 100;
515 frame.map_name = "/fake/libfake.so";
516 frame.map_offset = 0x2000;
517 frame.map_start = 0x3000;
518 frame.map_end = 0x6000;
519 frame.map_flags = PROT_READ;
520
521 EXPECT_EQ(" #01 pc 0000000000001000 (offset 0x2000) /fake/libfake.so (function+100)",
522 Unwinder::FormatFrame(frame, false));
523 EXPECT_EQ(" #01 pc 00001000 (offset 0x2000) /fake/libfake.so (function+100)",
524 Unwinder::FormatFrame(frame, true));
525
526 frame.map_offset = 0;
527 EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so (function+100)",
528 Unwinder::FormatFrame(frame, false));
529 EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (function+100)",
530 Unwinder::FormatFrame(frame, true));
531
532 frame.function_offset = 0;
533 EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so (function)",
534 Unwinder::FormatFrame(frame, false));
535 EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (function)", Unwinder::FormatFrame(frame, true));
536
537 frame.function_name = "";
538 EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so", Unwinder::FormatFrame(frame, false));
539 EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so", Unwinder::FormatFrame(frame, true));
540
541 frame.map_name = "";
542 EXPECT_EQ(" #01 pc 0000000000001000 <anonymous:3000>", Unwinder::FormatFrame(frame, false));
543 EXPECT_EQ(" #01 pc 00001000 <anonymous:3000>", Unwinder::FormatFrame(frame, true));
544
545 frame.map_start = 0;
546 frame.map_end = 0;
547 EXPECT_EQ(" #01 pc 0000000000001000 <unknown>", Unwinder::FormatFrame(frame, false));
548 EXPECT_EQ(" #01 pc 00001000 <unknown>", Unwinder::FormatFrame(frame, true));
549}
550
551// Verify format frame code.
552TEST_F(UnwinderTest, format_frame) {
553 ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 10));
554
555 regs_.FakeSetPc(0x2300);
556 regs_.FakeSetSp(0x10000);
557
558 Unwinder unwinder(64, &maps_, &regs_, process_memory_);
559 unwinder.Unwind();
560
561 ASSERT_EQ(1U, unwinder.NumFrames());
562
563 regs_.FakeSetMachineType(EM_ARM);
564 EXPECT_EQ(" #00 pc 00001300 /system/fake/libc.so (Frame0+10)", unwinder.FormatFrame(0));
565 regs_.FakeSetMachineType(EM_386);
566 EXPECT_EQ(" #00 pc 00001300 /system/fake/libc.so (Frame0+10)", unwinder.FormatFrame(0));
567
568 regs_.FakeSetMachineType(EM_AARCH64);
569 EXPECT_EQ(" #00 pc 0000000000001300 /system/fake/libc.so (Frame0+10)", unwinder.FormatFrame(0));
570 regs_.FakeSetMachineType(EM_X86_64);
571 EXPECT_EQ(" #00 pc 0000000000001300 /system/fake/libc.so (Frame0+10)", unwinder.FormatFrame(0));
572
573 EXPECT_EQ("", unwinder.FormatFrame(1));
574}
575
576} // namespace unwindstack
diff --git a/libunwindstack/tools/unwind.cpp b/libunwindstack/tools/unwind.cpp
index c1077f8b6..f2530d767 100644
--- a/libunwindstack/tools/unwind.cpp
+++ b/libunwindstack/tools/unwind.cpp
@@ -26,13 +26,11 @@
26#include <sys/types.h> 26#include <sys/types.h>
27#include <unistd.h> 27#include <unistd.h>
28 28
29#include <string>
30
31#include <unwindstack/Elf.h> 29#include <unwindstack/Elf.h>
32#include <unwindstack/MapInfo.h>
33#include <unwindstack/Maps.h> 30#include <unwindstack/Maps.h>
34#include <unwindstack/Memory.h> 31#include <unwindstack/Memory.h>
35#include <unwindstack/Regs.h> 32#include <unwindstack/Regs.h>
33#include <unwindstack/Unwinder.h>
36 34
37static bool Attach(pid_t pid) { 35static bool Attach(pid_t pid) {
38 if (ptrace(PTRACE_ATTACH, pid, 0, 0) == -1) { 36 if (ptrace(PTRACE_ATTACH, pid, 0, 0) == -1) {
@@ -51,10 +49,6 @@ static bool Attach(pid_t pid) {
51 return false; 49 return false;
52} 50}
53 51
54static bool Detach(pid_t pid) {
55 return ptrace(PTRACE_DETACH, pid, 0, 0) == 0;
56}
57
58void DoUnwind(pid_t pid) { 52void DoUnwind(pid_t pid) {
59 unwindstack::RemoteMaps remote_maps(pid); 53 unwindstack::RemoteMaps remote_maps(pid);
60 if (!remote_maps.Parse()) { 54 if (!remote_maps.Parse()) {
@@ -68,7 +62,6 @@ void DoUnwind(pid_t pid) {
68 return; 62 return;
69 } 63 }
70 64
71 bool bits32 = true;
72 printf("ABI: "); 65 printf("ABI: ");
73 switch (regs->MachineType()) { 66 switch (regs->MachineType()) {
74 case EM_ARM: 67 case EM_ARM:
@@ -79,11 +72,9 @@ void DoUnwind(pid_t pid) {
79 break; 72 break;
80 case EM_AARCH64: 73 case EM_AARCH64:
81 printf("arm64"); 74 printf("arm64");
82 bits32 = false;
83 break; 75 break;
84 case EM_X86_64: 76 case EM_X86_64:
85 printf("x86_64"); 77 printf("x86_64");
86 bits32 = false;
87 break; 78 break;
88 default: 79 default:
89 printf("unknown\n"); 80 printf("unknown\n");
@@ -91,53 +82,13 @@ void DoUnwind(pid_t pid) {
91 } 82 }
92 printf("\n"); 83 printf("\n");
93 84
94 unwindstack::MemoryRemote remote_memory(pid); 85 auto process_memory = unwindstack::Memory::CreateProcessMemory(pid);
95 for (size_t frame_num = 0; frame_num < 64; frame_num++) { 86 unwindstack::Unwinder unwinder(128, &remote_maps, regs, process_memory);
96 if (regs->pc() == 0) { 87 unwinder.Unwind();
97 break;
98 }
99 unwindstack::MapInfo* map_info = remote_maps.Find(regs->pc());
100 if (map_info == nullptr) {
101 printf("Failed to find map data for the pc\n");
102 break;
103 }
104
105 unwindstack::Elf* elf = map_info->GetElf(pid, true);
106 88
107 uint64_t rel_pc = elf->GetRelPc(regs->pc(), map_info); 89 // Print the frames.
108 uint64_t adjusted_rel_pc = rel_pc; 90 for (size_t i = 0; i < unwinder.NumFrames(); i++) {
109 // Don't need to adjust the first frame pc. 91 printf("%s\n", unwinder.FormatFrame(i).c_str());
110 if (frame_num != 0) {
111 adjusted_rel_pc = regs->GetAdjustedPc(rel_pc, elf);
112 }
113
114 std::string name;
115 if (bits32) {
116 printf(" #%02zu pc %08" PRIx64, frame_num, adjusted_rel_pc);
117 } else {
118 printf(" #%02zu pc %016" PRIx64, frame_num, adjusted_rel_pc);
119 }
120 if (!map_info->name.empty()) {
121 printf(" %s", map_info->name.c_str());
122 if (map_info->elf_offset != 0) {
123 printf(" (offset 0x%" PRIx64 ")", map_info->elf_offset);
124 }
125 } else {
126 printf(" <anonymous:%" PRIx64 ">", map_info->offset);
127 }
128 uint64_t func_offset;
129 if (elf->GetFunctionName(adjusted_rel_pc, &name, &func_offset)) {
130 printf(" (%s", name.c_str());
131 if (func_offset != 0) {
132 printf("+%" PRId64, func_offset);
133 }
134 printf(")");
135 }
136 printf("\n");
137
138 if (!elf->Step(rel_pc + map_info->elf_offset, regs, &remote_memory)) {
139 break;
140 }
141 } 92 }
142} 93}
143 94
@@ -155,7 +106,7 @@ int main(int argc, char** argv) {
155 106
156 DoUnwind(pid); 107 DoUnwind(pid);
157 108
158 Detach(pid); 109 ptrace(PTRACE_DETACH, pid, 0, 0);
159 110
160 return 0; 111 return 0;
161} 112}
diff --git a/libunwindstack/tools/unwind_symbols.cpp b/libunwindstack/tools/unwind_symbols.cpp
index b757c1e56..dc9ae5a06 100644
--- a/libunwindstack/tools/unwind_symbols.cpp
+++ b/libunwindstack/tools/unwind_symbols.cpp
@@ -28,8 +28,11 @@
28#include <unwindstack/Memory.h> 28#include <unwindstack/Memory.h>
29 29
30int main(int argc, char** argv) { 30int main(int argc, char** argv) {
31 if (argc != 2) { 31 if (argc != 2 && argc != 3) {
32 printf("Need to pass the name of an elf file to the program.\n"); 32 printf("Usage: unwind_symbols <ELF_FILE> [<FUNC_ADDRESS>]\n");
33 printf(" Dump all function symbols in ELF_FILE. If FUNC_ADDRESS is\n");
34 printf(" specified, then get the function at that address.\n");
35 printf(" FUNC_ADDRESS must be a hex number.\n");
33 return 1; 36 return 1;
34 } 37 }
35 38
@@ -43,6 +46,16 @@ int main(int argc, char** argv) {
43 return 1; 46 return 1;
44 } 47 }
45 48
49 uint64_t func_addr;
50 if (argc == 3) {
51 char* name;
52 func_addr = strtoull(argv[2], &name, 16);
53 if (*name != '\0') {
54 printf("%s is not a hex number.\n", argv[2]);
55 return 1;
56 }
57 }
58
46 // Send all log messages to stdout. 59 // Send all log messages to stdout.
47 unwindstack::log_to_stdout(true); 60 unwindstack::log_to_stdout(true);
48 61
@@ -76,9 +89,24 @@ int main(int argc, char** argv) {
76 return 1; 89 return 1;
77 } 90 }
78 91
79 // This is a crude way to get the symbols in order.
80 std::string name; 92 std::string name;
81 uint64_t load_bias = elf.interface()->load_bias(); 93 uint64_t load_bias = elf.interface()->load_bias();
94 if (argc == 3) {
95 std::string cur_name;
96 uint64_t func_offset;
97 if (!elf.GetFunctionName(func_addr, &cur_name, &func_offset)) {
98 printf("No known function at 0x%" PRIx64 "\n", func_addr);
99 return 1;
100 }
101 printf("<0x%" PRIx64 ">", func_addr - func_offset);
102 if (func_offset != 0) {
103 printf("+%" PRId64, func_offset);
104 }
105 printf(": %s\n", cur_name.c_str());
106 return 0;
107 }
108
109 // This is a crude way to get the symbols in order.
82 for (const auto& entry : elf.interface()->pt_loads()) { 110 for (const auto& entry : elf.interface()->pt_loads()) {
83 uint64_t start = entry.second.offset + load_bias; 111 uint64_t start = entry.second.offset + load_bias;
84 uint64_t end = entry.second.table_size + load_bias; 112 uint64_t end = entry.second.table_size + load_bias;
diff --git a/libusbhost/Android.bp b/libusbhost/Android.bp
index a0d6b9b85..fc6f305c0 100644
--- a/libusbhost/Android.bp
+++ b/libusbhost/Android.bp
@@ -16,6 +16,10 @@
16 16
17cc_library { 17cc_library {
18 name: "libusbhost", 18 name: "libusbhost",
19 vendor_available: true,
20 vndk: {
21 enabled: true,
22 },
19 host_supported: true, 23 host_supported: true,
20 srcs: ["usbhost.c"], 24 srcs: ["usbhost.c"],
21 cflags: ["-Werror"], 25 cflags: ["-Werror"],
diff --git a/libutils/Android.bp b/libutils/Android.bp
index adcde819c..30e6b49a8 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -18,10 +18,12 @@ cc_library_headers {
18 host_supported: true, 18 host_supported: true,
19 19
20 header_libs: [ 20 header_libs: [
21 "liblog_headers",
21 "libsystem_headers", 22 "libsystem_headers",
22 "libcutils_headers" 23 "libcutils_headers"
23 ], 24 ],
24 export_header_lib_headers: [ 25 export_header_lib_headers: [
26 "liblog_headers",
25 "libsystem_headers", 27 "libsystem_headers",
26 "libcutils_headers" 28 "libcutils_headers"
27 ], 29 ],
@@ -119,7 +121,7 @@ cc_library {
119 }, 121 },
120 }, 122 },
121 123
122 linux: { 124 linux_glibc: {
123 srcs: [ 125 srcs: [
124 "Looper.cpp", 126 "Looper.cpp",
125 "ProcessCallStack.cpp", 127 "ProcessCallStack.cpp",
diff --git a/libutils/RefBase.cpp b/libutils/RefBase.cpp
index 24737b985..f5f881fcc 100644
--- a/libutils/RefBase.cpp
+++ b/libutils/RefBase.cpp
@@ -442,6 +442,11 @@ void RefBase::decStrong(const void* id) const
442 // and all accesses to refs happen before its deletion in the final decWeak. 442 // and all accesses to refs happen before its deletion in the final decWeak.
443 // The destructor can safely access mRefs because either it's deleting 443 // The destructor can safely access mRefs because either it's deleting
444 // mRefs itself, or it's running entirely before the final mWeak decrement. 444 // mRefs itself, or it's running entirely before the final mWeak decrement.
445 //
446 // Since we're doing atomic loads of `flags`, the static analyzer assumes
447 // they can change between `delete this;` and `refs->decWeak(id);`. This is
448 // not the case. The analyzer may become more okay with this patten when
449 // https://bugs.llvm.org/show_bug.cgi?id=34365 gets resolved. NOLINTNEXTLINE
445 refs->decWeak(id); 450 refs->decWeak(id);
446} 451}
447 452
diff --git a/libutils/SystemClock.cpp b/libutils/SystemClock.cpp
index 28fc35145..73ec1be96 100644
--- a/libutils/SystemClock.cpp
+++ b/libutils/SystemClock.cpp
@@ -23,9 +23,9 @@
23 23
24#include <utils/SystemClock.h> 24#include <utils/SystemClock.h>
25 25
26#include <sys/time.h>
27#include <string.h> 26#include <string.h>
28#include <errno.h> 27#include <errno.h>
28#include <time.h>
29 29
30#include <cutils/compiler.h> 30#include <cutils/compiler.h>
31 31
diff --git a/libutils/include/utils/StrongPointer.h b/libutils/include/utils/StrongPointer.h
index 0c2060791..ae6d9c82e 100644
--- a/libutils/include/utils/StrongPointer.h
+++ b/libutils/include/utils/StrongPointer.h
@@ -82,9 +82,10 @@ public:
82 82
83 // Accessors 83 // Accessors
84 84
85 inline T& operator* () const { return *m_ptr; } 85 inline T& operator* () const { return *m_ptr; }
86 inline T* operator-> () const { return m_ptr; } 86 inline T* operator-> () const { return m_ptr; }
87 inline T* get() const { return m_ptr; } 87 inline T* get() const { return m_ptr; }
88 inline explicit operator bool () const { return m_ptr != nullptr; }
88 89
89 // Operators 90 // Operators
90 91
diff --git a/libutils/tests/Android.bp b/libutils/tests/Android.bp
index 08691756a..6911fc51b 100644
--- a/libutils/tests/Android.bp
+++ b/libutils/tests/Android.bp
@@ -44,10 +44,9 @@ cc_test {
44 "libcutils", 44 "libcutils",
45 "libutils", 45 "libutils",
46 "libbase", 46 "libbase",
47 "libdl",
48 ], 47 ],
49 }, 48 },
50 linux: { 49 linux_glibc: {
51 srcs: [ 50 srcs: [
52 "Looper_test.cpp", 51 "Looper_test.cpp",
53 "RefBase_test.cpp", 52 "RefBase_test.cpp",
@@ -59,7 +58,6 @@ cc_test {
59 "liblog", 58 "liblog",
60 "libbase", 59 "libbase",
61 ], 60 ],
62 host_ldlibs: ["-ldl"],
63 }, 61 },
64 }, 62 },
65 63
diff --git a/libziparchive/Android.bp b/libziparchive/Android.bp
index 333835c34..e3faee36c 100644
--- a/libziparchive/Android.bp
+++ b/libziparchive/Android.bp
@@ -58,6 +58,9 @@ cc_library {
58 name: "libziparchive", 58 name: "libziparchive",
59 host_supported: true, 59 host_supported: true,
60 vendor_available: true, 60 vendor_available: true,
61 vndk: {
62 enabled: true,
63 },
61 64
62 defaults: [ 65 defaults: [
63 "libziparchive_defaults", 66 "libziparchive_defaults",
@@ -66,11 +69,11 @@ cc_library {
66 shared_libs: [ 69 shared_libs: [
67 "liblog", 70 "liblog",
68 "libbase", 71 "libbase",
72 "libz",
69 ], 73 ],
70 target: { 74 target: {
71 android: { 75 android: {
72 shared_libs: [ 76 shared_libs: [
73 "libz",
74 "libutils", 77 "libutils",
75 ], 78 ],
76 }, 79 },
@@ -78,18 +81,8 @@ cc_library {
78 static_libs: ["libutils"], 81 static_libs: ["libutils"],
79 }, 82 },
80 linux_bionic: { 83 linux_bionic: {
81 static_libs: ["libz"],
82 enabled: true, 84 enabled: true,
83 }, 85 },
84 linux: {
85 shared_libs: ["libz-host"],
86 },
87 darwin: {
88 shared_libs: ["libz-host"],
89 },
90 windows: {
91 shared_libs: ["libz-host"],
92 },
93 }, 86 },
94} 87}
95 88
@@ -102,7 +95,7 @@ cc_library {
102 "libziparchive_defaults", 95 "libziparchive_defaults",
103 "libziparchive_flags", 96 "libziparchive_flags",
104 ], 97 ],
105 shared_libs: ["libz-host"], 98 shared_libs: ["libz"],
106 static_libs: ["libutils"], 99 static_libs: ["libutils"],
107} 100}
108 101
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index 8ee5ea10d..9e1541b8a 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -1099,7 +1099,7 @@ static pid_t sepolicy_rate(unsigned rate, unsigned num) {
1099 // and dac_read_search on every try to get past the message 1099 // and dac_read_search on every try to get past the message
1100 // de-duper. We will also rotate the file name in the directory 1100 // de-duper. We will also rotate the file name in the directory
1101 // as another measure. 1101 // as another measure.
1102 static const char file[] = "/data/backup/cannot_access_directory_%u"; 1102 static const char file[] = "/data/drm/cannot_access_directory_%u";
1103 static const unsigned avc_requests_per_access = 2; 1103 static const unsigned avc_requests_per_access = 2;
1104 1104
1105 rate /= avc_requests_per_access; 1105 rate /= avc_requests_per_access;
diff --git a/reboot/reboot.c b/reboot/reboot.c
index 007dfbaa4..fe763a882 100644
--- a/reboot/reboot.c
+++ b/reboot/reboot.c
@@ -21,13 +21,13 @@
21#include <cutils/android_reboot.h> 21#include <cutils/android_reboot.h>
22#include <unistd.h> 22#include <unistd.h>
23 23
24int main(int argc, char *argv[]) 24int main(int argc, char* argv[]) {
25{
26 int ret; 25 int ret;
27 size_t prop_len; 26 size_t prop_len;
28 char property_val[PROPERTY_VALUE_MAX]; 27 char property_val[PROPERTY_VALUE_MAX];
29 const char *cmd = "reboot"; 28 static const char reboot[] = "reboot";
30 char *optarg = ""; 29 const char* cmd = reboot;
30 char* optarg = "";
31 31
32 opterr = 0; 32 opterr = 0;
33 do { 33 do {
@@ -56,22 +56,27 @@ int main(int argc, char *argv[])
56 56
57 if (argc > optind) 57 if (argc > optind)
58 optarg = argv[optind]; 58 optarg = argv[optind];
59 if (!optarg || !optarg[0]) optarg = "shell";
59 60
60 prop_len = snprintf(property_val, sizeof(property_val), "%s,%s", cmd, optarg); 61 prop_len = snprintf(property_val, sizeof(property_val), "%s,%s", cmd, optarg);
61 if (prop_len >= sizeof(property_val)) { 62 if (prop_len >= sizeof(property_val)) {
62 fprintf(stderr, "reboot command too long: %s\n", optarg); 63 fprintf(stderr, "%s command too long: %s\n", cmd, optarg);
63 exit(EXIT_FAILURE); 64 exit(EXIT_FAILURE);
64 } 65 }
65 66
66 ret = property_set(ANDROID_RB_PROPERTY, property_val); 67 ret = property_set(ANDROID_RB_PROPERTY, property_val);
67 if(ret < 0) { 68 if (ret < 0) {
68 perror("reboot"); 69 perror(cmd);
69 exit(EXIT_FAILURE); 70 exit(EXIT_FAILURE);
70 } 71 }
71 72
72 // Don't return early. Give the reboot command time to take effect 73 // Don't return early. Give the reboot command time to take effect
73 // to avoid messing up scripts which do "adb shell reboot && adb wait-for-device" 74 // to avoid messing up scripts which do "adb shell reboot && adb wait-for-device"
74 while(1) { pause(); } 75 if (cmd == reboot) {
76 while (1) {
77 pause();
78 }
79 }
75 80
76 fprintf(stderr, "Done\n"); 81 fprintf(stderr, "Done\n");
77 return 0; 82 return 0;
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 48a46c606..e199ed406 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -127,7 +127,7 @@ endif
127# 127#
128# create some directories (some are mount points) and symlinks 128# create some directories (some are mount points) and symlinks
129LOCAL_POST_INSTALL_CMD := mkdir -p $(addprefix $(TARGET_ROOT_OUT)/, \ 129LOCAL_POST_INSTALL_CMD := mkdir -p $(addprefix $(TARGET_ROOT_OUT)/, \
130 sbin dev proc sys system data oem acct config storage mnt root $(BOARD_ROOT_EXTRA_FOLDERS)); \ 130 sbin dev proc sys system data oem acct config storage mnt $(BOARD_ROOT_EXTRA_FOLDERS)); \
131 ln -sf /system/etc $(TARGET_ROOT_OUT)/etc; \ 131 ln -sf /system/etc $(TARGET_ROOT_OUT)/etc; \
132 ln -sf /data/user_de/0/com.android.shell/files/bugreports $(TARGET_ROOT_OUT)/bugreports; \ 132 ln -sf /data/user_de/0/com.android.shell/files/bugreports $(TARGET_ROOT_OUT)/bugreports; \
133 ln -sf /sys/kernel/debug $(TARGET_ROOT_OUT)/d; \ 133 ln -sf /sys/kernel/debug $(TARGET_ROOT_OUT)/d; \
diff --git a/rootdir/init.rc b/rootdir/init.rc
index fb1fbd4f1..d503ffe4f 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -721,6 +721,7 @@ service console /system/bin/sh
721 user shell 721 user shell
722 group shell log readproc 722 group shell log readproc
723 seclabel u:r:shell:s0 723 seclabel u:r:shell:s0
724 setenv HOSTNAME console
724 725
725on property:ro.debuggable=1 726on property:ro.debuggable=1
726 # Give writes to anyone for the trace folder on debug builds. 727 # Give writes to anyone for the trace folder on debug builds.
diff --git a/rootdir/init.usb.rc b/rootdir/init.usb.rc
index 915d159a5..3168f40ba 100644
--- a/rootdir/init.usb.rc
+++ b/rootdir/init.usb.rc
@@ -12,7 +12,7 @@ on post-fs-data
12 mkdir /data/adb 0700 root root 12 mkdir /data/adb 0700 root root
13 13
14# adbd is controlled via property triggers in init.<platform>.usb.rc 14# adbd is controlled via property triggers in init.<platform>.usb.rc
15service adbd /sbin/adbd --root_seclabel=u:r:su:s0 15service adbd /system/bin/adbd --root_seclabel=u:r:su:s0
16 class core 16 class core
17 socket adbd stream 660 system system 17 socket adbd stream 660 system system
18 disabled 18 disabled
diff --git a/run-as/run-as.cpp b/run-as/run-as.cpp
index e7b8cc2c8..b27cfad7c 100644
--- a/run-as/run-as.cpp
+++ b/run-as/run-as.cpp
@@ -194,6 +194,7 @@ int main(int argc, char* argv[]) {
194 ScopedMinijail j(minijail_new()); 194 ScopedMinijail j(minijail_new());
195 minijail_change_uid(j.get(), uid); 195 minijail_change_uid(j.get(), uid);
196 minijail_change_gid(j.get(), gid); 196 minijail_change_gid(j.get(), gid);
197 minijail_keep_supplementary_gids(j.get());
197 minijail_enter(j.get()); 198 minijail_enter(j.get());
198 199
199 if (selinux_android_setcontext(uid, 0, info.seinfo, pkgname) < 0) { 200 if (selinux_android_setcontext(uid, 0, info.seinfo, pkgname) < 0) {
diff --git a/shell_and_utilities/README.md b/shell_and_utilities/README.md
index 5d10c18f1..c4e8aac91 100644
--- a/shell_and_utilities/README.md
+++ b/shell_and_utilities/README.md
@@ -4,20 +4,25 @@ Android's shell and utilities
4Since IceCreamSandwich Android has used 4Since IceCreamSandwich Android has used
5[mksh](https://www.mirbsd.org/mksh.htm) as its shell. Before then it used 5[mksh](https://www.mirbsd.org/mksh.htm) as its shell. Before then it used
6[ash](https://en.wikipedia.org/wiki/Almquist_shell) (which actually 6[ash](https://en.wikipedia.org/wiki/Almquist_shell) (which actually
7remained in the tree up to and including KitKat). 7remained unused in the tree up to and including KitKat).
8 8
9Initially Android had a very limited command-line provided by its 9Initially Android had a very limited command-line provided by its own
10own "toolbox" binary. These days almost everything is supplied by 10"toolbox" binary. Since Marshmallow almost everything is supplied by
11[toybox](http://landley.net/toybox/) instead. 11[toybox](http://landley.net/toybox/) instead.
12 12
13We started moving a few of the more important tools to full 13We started moving a few of the more important tools to full
14BSD implementations in JellyBean before we started in earnest in 14BSD implementations in JellyBean, and continued this work in
15Lollipop. Lollipop was a major break with the past in many ways (LP64 15Lollipop. Lollipop was a major break with the past in many ways (LP64
16support and the switch to ART both having lots of knock-on effects around 16support and the switch to ART both having lots of knock-on effects around
17the system), so although this was the beginning of the end of toolbox it 17the system), so although this was the beginning of the end of toolbox it
18(a) didn't stand out given all the other systems-level changes and (b) 18(a) didn't stand out given all the other systems-level changes and (b)
19in Marshmallow we changed direction and started the move to toybox. 19in Marshmallow we changed direction and started the move to toybox.
20 20
21Not everything is provided by toybox, though. We currently still use
22the BSD dd and grep (because the toybox versions are still unfinished),
23and for the bzip2 command-line tools we use the ones that are part of
24the bzip2 distribution.
25
21The lists below show what tools were provided and where they came from in 26The lists below show what tools were provided and where they came from in
22each release starting with Gingerbread. This doesn't tell the full story, 27each release starting with Gingerbread. This doesn't tell the full story,
23because the toolbox implementations did have bugs fixed and options added 28because the toolbox implementations did have bugs fixed and options added
@@ -25,6 +30,10 @@ over the years. Gingerbread's rm, for example, supported `-r`/`-R` but not
25`-f`. But this gives you an idea of what was available in any given release, 30`-f`. But this gives you an idea of what was available in any given release,
26and how usable it was likely to be. 31and how usable it was likely to be.
27 32
33Also note that in any given release `toybox` probably contains more
34commands than there are symlinks for in `/system/bin`. You can get the
35full list for a release by running `toybox` directly.
36
28 37
29Android 2.3 (Gingerbread) 38Android 2.3 (Gingerbread)
30------------------------- 39-------------------------
@@ -132,26 +141,26 @@ time timeout touch tr true truncate tty ulimit umount uname uniq unix2dos
132uptime usleep vmstat wc which whoami xargs xxd yes 141uptime usleep vmstat wc which whoami xargs xxd yes
133 142
134 143
135Current AOSP 144Android 8.0 (Oreo)
136------------ 145------------------
137 146
138BSD: dd grep 147BSD: dd grep
139 148
140bzip2: bzcat bzip2 bunzip2 149bzip2: bzcat bzip2 bunzip2
141 150
142toolbox: getevent gzip newfs\_msdos gunzip zcat 151toolbox: getevent newfs\_msdos
143 152
144toybox: acpi base64 basename blockdev cal cat chcon chgrp chmod chown 153toybox: acpi base64 basename blockdev cal cat chcon chgrp chmod chown
145chroot chrt cksum clear cmp comm cp cpio cut date df diff dirname dmesg 154chroot chrt cksum clear cmp comm cp cpio cut date df diff dirname dmesg
146dos2unix du echo env expand expr fallocate false file find flock free 155dos2unix du echo env expand expr fallocate false file find flock free
147getenforce getprop groups head hostname hwclock id ifconfig inotifyd 156getenforce getprop groups gunzip gzip head hostname hwclock id ifconfig
148insmod ionice iorenice kill killall ln load\_policy log logname losetup 157inotifyd insmod ionice iorenice kill killall ln load\_policy log logname
149ls lsmod lsof lsusb md5sum microcom mkdir mknod mkswap mktemp modinfo 158losetup ls lsmod lsof lspci lsusb md5sum microcom mkdir mkfifo mknod
150modprobe more mount mountpoint mv netstat nice nl nohup od paste patch 159mkswap mktemp modinfo modprobe more mount mountpoint mv netstat nice
151pgrep pidof pkill pmap printenv printf ps pwd readlink realpath renice 160nl nohup od paste patch pgrep pidof pkill pmap printenv printf ps pwd
152restorecon rm rmdir rmmod runcon sed sendevent seq setenforce setprop 161readlink realpath renice restorecon rm rmdir rmmod runcon sed sendevent
153setsid sha1sum sha224sum sha256sum sha384sum sha512sum sleep sort split 162seq setenforce setprop setsid sha1sum sha224sum sha256sum sha384sum
154start stat stop strings swapoff swapon sync sysctl tac tail tar taskset 163sha512sum sleep sort split start stat stop strings swapoff swapon sync
155tee time timeout top touch tr true truncate tty ulimit umount uname uniq 164sysctl tac tail tar taskset tee time timeout top touch tr true truncate
156unix2dos uptime usleep uudecode uuencode vmstat wc which whoami xargs 165tty ulimit umount uname uniq unix2dos uptime usleep uudecode uuencode
157xxd yes 166vmstat wc which whoami xargs xxd yes zcat
diff --git a/trusty/keymaster/Android.bp b/trusty/keymaster/Android.bp
index 3b6867cf1..6b9d72359 100644
--- a/trusty/keymaster/Android.bp
+++ b/trusty/keymaster/Android.bp
@@ -33,7 +33,8 @@ cc_binary {
33 shared_libs: [ 33 shared_libs: [
34 "libcrypto", 34 "libcrypto",
35 "libcutils", 35 "libcutils",
36 "libkeymaster1", 36 "libkeymaster_portable",
37 "libkeymaster_staging",
37 "libtrusty", 38 "libtrusty",
38 "libkeymaster_messages", 39 "libkeymaster_messages",
39 "libsoftkeymasterdevice", 40 "libsoftkeymasterdevice",
diff --git a/trusty/keymaster/trusty_keymaster_device_test.cpp b/trusty/keymaster/trusty_keymaster_device_test.cpp
index e8f5c0b69..922796492 100644
--- a/trusty/keymaster/trusty_keymaster_device_test.cpp
+++ b/trusty/keymaster/trusty_keymaster_device_test.cpp
@@ -15,9 +15,9 @@
15 */ 15 */
16#include <algorithm> 16#include <algorithm>
17#include <fstream> 17#include <fstream>
18#include <memory>
18 19
19#include <gtest/gtest.h> 20#include <gtest/gtest.h>
20#include <nativehelper/UniquePtr.h>
21#include <openssl/engine.h> 21#include <openssl/engine.h>
22 22
23#include <hardware/keymaster0.h> 23#include <hardware/keymaster0.h>
@@ -181,7 +181,7 @@ TEST_F(SigningTest, RsaSuccess) {
181 181
182 keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE}; 182 keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
183 size_t message_len = params.modulus_size / 8; 183 size_t message_len = params.modulus_size / 8;
184 UniquePtr<uint8_t[]> message(build_message(message_len)); 184 std::unique_ptr<uint8_t[]> message(build_message(message_len));
185 uint8_t* signature; 185 uint8_t* signature;
186 size_t siglen; 186 size_t siglen;
187 EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len, 187 EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len,
@@ -200,7 +200,7 @@ TEST_F(SigningTest, RsaShortMessage) {
200 200
201 keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE}; 201 keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
202 size_t message_len = params.modulus_size / 8 - 1; 202 size_t message_len = params.modulus_size / 8 - 1;
203 UniquePtr<uint8_t[]> message(build_message(message_len)); 203 std::unique_ptr<uint8_t[]> message(build_message(message_len));
204 uint8_t* signature; 204 uint8_t* signature;
205 size_t siglen; 205 size_t siglen;
206 EXPECT_EQ(KM_ERROR_UNKNOWN_ERROR, device.sign_data(&sig_params, ptr, size, message.get(), 206 EXPECT_EQ(KM_ERROR_UNKNOWN_ERROR, device.sign_data(&sig_params, ptr, size, message.get(),
@@ -217,7 +217,7 @@ TEST_F(SigningTest, RsaLongMessage) {
217 217
218 keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE}; 218 keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
219 size_t message_len = params.modulus_size / 8 + 1; 219 size_t message_len = params.modulus_size / 8 + 1;
220 UniquePtr<uint8_t[]> message(build_message(message_len)); 220 std::unique_ptr<uint8_t[]> message(build_message(message_len));
221 uint8_t* signature; 221 uint8_t* signature;
222 size_t siglen; 222 size_t siglen;
223 EXPECT_EQ(KM_ERROR_UNKNOWN_ERROR, device.sign_data(&sig_params, ptr, size, message.get(), 223 EXPECT_EQ(KM_ERROR_UNKNOWN_ERROR, device.sign_data(&sig_params, ptr, size, message.get(),
@@ -272,7 +272,7 @@ TEST_F(SigningTest, EcdsaLargeMessageSuccess) {
272 272
273 keymaster_ec_sign_params_t sig_params = {DIGEST_NONE}; 273 keymaster_ec_sign_params_t sig_params = {DIGEST_NONE};
274 size_t message_len = 1024 * 7; 274 size_t message_len = 1024 * 7;
275 UniquePtr<uint8_t[]> message(new uint8_t[message_len]); 275 std::unique_ptr<uint8_t[]> message(new uint8_t[message_len]);
276 // contents of message don't matter. 276 // contents of message don't matter.
277 uint8_t* signature; 277 uint8_t* signature;
278 size_t siglen; 278 size_t siglen;
@@ -294,7 +294,7 @@ TEST_F(VerificationTest, RsaSuccess) {
294 294
295 keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE}; 295 keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
296 size_t message_len = params.modulus_size / 8; 296 size_t message_len = params.modulus_size / 8;
297 UniquePtr<uint8_t[]> message(build_message(message_len)); 297 std::unique_ptr<uint8_t[]> message(build_message(message_len));
298 uint8_t* signature; 298 uint8_t* signature;
299 size_t siglen; 299 size_t siglen;
300 EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len, 300 EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len,
@@ -315,7 +315,7 @@ TEST_F(VerificationTest, RsaBadSignature) {
315 315
316 keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE}; 316 keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
317 size_t message_len = params.modulus_size / 8; 317 size_t message_len = params.modulus_size / 8;
318 UniquePtr<uint8_t[]> message(build_message(message_len)); 318 std::unique_ptr<uint8_t[]> message(build_message(message_len));
319 uint8_t* signature; 319 uint8_t* signature;
320 size_t siglen; 320 size_t siglen;
321 EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len, 321 EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len,
@@ -338,7 +338,7 @@ TEST_F(VerificationTest, RsaBadMessage) {
338 338
339 keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE}; 339 keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
340 size_t message_len = params.modulus_size / 8; 340 size_t message_len = params.modulus_size / 8;
341 UniquePtr<uint8_t[]> message(build_message(message_len)); 341 std::unique_ptr<uint8_t[]> message(build_message(message_len));
342 uint8_t* signature; 342 uint8_t* signature;
343 size_t siglen; 343 size_t siglen;
344 EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len, 344 EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len,
@@ -360,7 +360,7 @@ TEST_F(VerificationTest, RsaShortMessage) {
360 360
361 keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE}; 361 keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
362 size_t message_len = params.modulus_size / 8; 362 size_t message_len = params.modulus_size / 8;
363 UniquePtr<uint8_t[]> message(build_message(message_len)); 363 std::unique_ptr<uint8_t[]> message(build_message(message_len));
364 uint8_t* signature; 364 uint8_t* signature;
365 size_t siglen; 365 size_t siglen;
366 EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len, 366 EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len,
@@ -382,7 +382,7 @@ TEST_F(VerificationTest, RsaLongMessage) {
382 382
383 keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE}; 383 keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
384 size_t message_len = params.modulus_size / 8; 384 size_t message_len = params.modulus_size / 8;
385 UniquePtr<uint8_t[]> message(build_message(message_len + 1)); 385 std::unique_ptr<uint8_t[]> message(build_message(message_len + 1));
386 uint8_t* signature; 386 uint8_t* signature;
387 size_t siglen; 387 size_t siglen;
388 EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len, 388 EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len,
@@ -422,7 +422,7 @@ TEST_F(VerificationTest, EcdsaLargeMessageSuccess) {
422 422
423 keymaster_ec_sign_params_t sig_params = {DIGEST_NONE}; 423 keymaster_ec_sign_params_t sig_params = {DIGEST_NONE};
424 size_t message_len = 1024 * 7; 424 size_t message_len = 1024 * 7;
425 UniquePtr<uint8_t[]> message(new uint8_t[message_len]); 425 std::unique_ptr<uint8_t[]> message(new uint8_t[message_len]);
426 // contents of message don't matter. 426 // contents of message don't matter.
427 uint8_t* signature; 427 uint8_t* signature;
428 size_t siglen; 428 size_t siglen;
@@ -453,7 +453,7 @@ TEST_F(ImportKeyTest, RsaSuccess) {
453 453
454 keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE}; 454 keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
455 size_t message_size = 1024 /* key size */ / 8; 455 size_t message_size = 1024 /* key size */ / 8;
456 UniquePtr<uint8_t[]> message(new uint8_t[message_size]); 456 std::unique_ptr<uint8_t[]> message(new uint8_t[message_size]);
457 memset(message.get(), 'a', message_size); 457 memset(message.get(), 'a', message_size);
458 uint8_t* signature; 458 uint8_t* signature;
459 size_t siglen; 459 size_t siglen;
@@ -491,9 +491,9 @@ struct EVP_PKEY_CTX_Delete {
491 491
492static void VerifySignature(const uint8_t* key, size_t key_len, const uint8_t* signature, 492static void VerifySignature(const uint8_t* key, size_t key_len, const uint8_t* signature,
493 size_t signature_len, const uint8_t* message, size_t message_len) { 493 size_t signature_len, const uint8_t* message, size_t message_len) {
494 UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(d2i_PUBKEY(NULL, &key, key_len)); 494 std::unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(d2i_PUBKEY(NULL, &key, key_len));
495 ASSERT_TRUE(pkey.get() != NULL); 495 ASSERT_TRUE(pkey.get() != NULL);
496 UniquePtr<EVP_PKEY_CTX, EVP_PKEY_CTX_Delete> ctx(EVP_PKEY_CTX_new(pkey.get(), NULL)); 496 std::unique_ptr<EVP_PKEY_CTX, EVP_PKEY_CTX_Delete> ctx(EVP_PKEY_CTX_new(pkey.get(), NULL));
497 ASSERT_TRUE(ctx.get() != NULL); 497 ASSERT_TRUE(ctx.get() != NULL);
498 ASSERT_EQ(1, EVP_PKEY_verify_init(ctx.get())); 498 ASSERT_EQ(1, EVP_PKEY_verify_init(ctx.get()));
499 if (EVP_PKEY_type(pkey->type) == EVP_PKEY_RSA) 499 if (EVP_PKEY_type(pkey->type) == EVP_PKEY_RSA)
@@ -518,7 +518,7 @@ TEST_F(ExportKeyTest, RsaSuccess) {
518 // Sign a message so we can verify it with the exported pubkey. 518 // Sign a message so we can verify it with the exported pubkey.
519 keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE}; 519 keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
520 size_t message_len = params.modulus_size / 8; 520 size_t message_len = params.modulus_size / 8;
521 UniquePtr<uint8_t[]> message(build_message(message_len)); 521 std::unique_ptr<uint8_t[]> message(build_message(message_len));
522 uint8_t* signature; 522 uint8_t* signature;
523 size_t siglen; 523 size_t siglen;
524 EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len, 524 EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len,
diff --git a/trusty/nvram/trusty_nvram_device.cpp b/trusty/nvram/trusty_nvram_device.cpp
index 2c50915d4..82a122870 100644
--- a/trusty/nvram/trusty_nvram_device.cpp
+++ b/trusty/nvram/trusty_nvram_device.cpp
@@ -14,6 +14,8 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17#include <errno.h>
18
17#include <nvram/hal/nvram_device_adapter.h> 19#include <nvram/hal/nvram_device_adapter.h>
18 20
19#include "trusty_nvram_implementation.h" 21#include "trusty_nvram_implementation.h"