summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debuggerd/Android.bp27
-rw-r--r--debuggerd/TEST_MAPPING4
-rw-r--r--debuggerd/crash_dump.cpp190
-rw-r--r--debuggerd/crasher/crasher.cpp2
-rw-r--r--debuggerd/debuggerd_test.cpp42
-rw-r--r--debuggerd/libdebuggerd/include/libdebuggerd/scudo.h4
-rw-r--r--debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h8
-rw-r--r--debuggerd/libdebuggerd/include/libdebuggerd/types.h2
-rw-r--r--debuggerd/libdebuggerd/scudo.cpp4
-rw-r--r--debuggerd/libdebuggerd/test/dump_memory_test.cpp266
-rw-r--r--debuggerd/libdebuggerd/tombstone.cpp8
-rw-r--r--debuggerd/libdebuggerd/tombstone_proto.cpp40
-rw-r--r--debuggerd/libdebuggerd/tombstone_proto_to_text.cpp40
-rw-r--r--debuggerd/proto/tombstone.proto10
-rw-r--r--fs_mgr/fs_mgr.cpp13
-rw-r--r--fs_mgr/fs_mgr_format.cpp21
-rw-r--r--fs_mgr/libfstab/fstab.cpp36
-rw-r--r--fs_mgr/libfstab/include/fstab/fstab.h3
-rw-r--r--fs_mgr/liblp/fuzzer/Android.bp14
-rw-r--r--fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp3
-rw-r--r--init/Android.bp4
-rw-r--r--init/property_service.cpp13
-rw-r--r--init/test_upgrade_mte/AndroidTest.xml10
-rw-r--r--init/test_upgrade_mte/OWNERS5
-rw-r--r--init/test_upgrade_mte/mte_upgrade_test_helper.cpp3
-rw-r--r--init/util.cpp2
-rw-r--r--janitors/OWNERS1
-rw-r--r--libstats/socket_lazy/Android.bp11
-rw-r--r--libstats/socket_lazy/include/statssocket_lazy.h25
-rw-r--r--libstats/socket_lazy/libstatssocket_lazy.cpp13
-rw-r--r--libstats/socket_lazy/tests/libstatssocket_lazy_test.cpp6
-rw-r--r--libutils/binder/String16_test.cpp44
-rw-r--r--libutils/binder/String8_test.cpp46
-rw-r--r--libutils/binder/include/utils/String16.h36
-rw-r--r--libutils/binder/include/utils/String8.h36
-rw-r--r--mkbootfs/mkbootfs.c11
-rw-r--r--rootdir/Android.bp4
-rw-r--r--rootdir/init.rc5
-rw-r--r--trusty/utils/coverage-controller/controller.cpp1
-rw-r--r--trusty/utils/coverage-controller/controller.h2
40 files changed, 719 insertions, 296 deletions
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 2529516da..0c5543ed9 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -240,11 +240,16 @@ cc_library_static {
"libdebuggerd/backtrace.cpp",
"libdebuggerd/gwp_asan.cpp",
"libdebuggerd/open_files_list.cpp",
+ "libdebuggerd/scudo.cpp",
"libdebuggerd/tombstone.cpp",
"libdebuggerd/tombstone_proto.cpp",
"libdebuggerd/utility.cpp",
],
+ cflags: [
+ "-DUSE_SCUDO",
+ ],
+
local_include_dirs: ["libdebuggerd/include"],
export_include_dirs: ["libdebuggerd/include"],
@@ -256,6 +261,7 @@ cc_library_static {
"bionic_libc_platform_headers",
"gwp_asan_headers",
"liblog_headers",
+ "scudo_headers",
],
static_libs: [
@@ -273,6 +279,7 @@ cc_library_static {
"libtombstone_proto",
"libprocinfo",
"libprotobuf-cpp-lite",
+ "libscudo",
],
target: {
@@ -312,11 +319,9 @@ cc_library_static {
cflags: ["-DROOT_POSSIBLE"],
},
- malloc_not_svelte: {
- cflags: ["-DUSE_SCUDO"],
- whole_static_libs: ["libscudo"],
- srcs: ["libdebuggerd/scudo.cpp"],
- header_libs: ["scudo_headers"],
+ malloc_low_memory: {
+ cflags: ["-UUSE_SCUDO"],
+ exclude_static_libs: ["libscudo"],
},
},
apex_available: [
@@ -447,6 +452,7 @@ cc_binary {
header_libs: [
"bionic_libc_platform_headers",
+ "libnative_bridge_support_accessor_headers",
],
static_libs: [
@@ -456,6 +462,8 @@ cc_binary {
"libtombstone_proto",
"libprotobuf-cpp-lite",
+
+ "libnative_bridge_guest_state_accessor",
],
shared_libs: [
@@ -471,6 +479,15 @@ cc_binary {
// Required for tests.
required: ["crash_dump.policy"],
+
+ target: {
+ android: {
+ header_libs: [
+ "libnative_bridge_support_accessor_headers", // For dlext_namespaces.h
+ ],
+ shared_libs: ["libdl_android"], // For android_get_exported_namespace implementation
+ },
+ },
}
cc_binary {
diff --git a/debuggerd/TEST_MAPPING b/debuggerd/TEST_MAPPING
index 61d71550c..824d20a5a 100644
--- a/debuggerd/TEST_MAPPING
+++ b/debuggerd/TEST_MAPPING
@@ -4,6 +4,10 @@
"name": "debuggerd_test"
},
{
+ "name": "debuggerd_test",
+ "keywords": ["primary-device"]
+ },
+ {
"name": "libtombstoned_client_rust_test"
},
{
diff --git a/debuggerd/crash_dump.cpp b/debuggerd/crash_dump.cpp
index 203b4855b..77d4a07af 100644
--- a/debuggerd/crash_dump.cpp
+++ b/debuggerd/crash_dump.cpp
@@ -25,6 +25,7 @@
#include <sys/wait.h>
#include <unistd.h>
+#include <cstdint>
#include <limits>
#include <map>
#include <memory>
@@ -42,6 +43,7 @@
#include <android-base/unique_fd.h>
#include <bionic/macros.h>
#include <bionic/reserved_signals.h>
+#include <bionic/tls_defines.h>
#include <cutils/sockets.h>
#include <log/log.h>
#include <private/android_filesystem_config.h>
@@ -52,7 +54,18 @@
#include <unwindstack/AndroidUnwinder.h>
#include <unwindstack/Error.h>
+#include <unwindstack/MachineArm.h>
+#include <unwindstack/MachineArm64.h>
+#include <unwindstack/MachineRiscv64.h>
#include <unwindstack/Regs.h>
+#include <unwindstack/RegsArm.h>
+#include <unwindstack/RegsArm64.h>
+#include <unwindstack/RegsRiscv64.h>
+#include <unwindstack/UserArm.h>
+#include <unwindstack/UserArm64.h>
+#include <unwindstack/UserRiscv64.h>
+
+#include <native_bridge_support/guest_state_accessor/accessor.h>
#include "libdebuggerd/backtrace.h"
#include "libdebuggerd/tombstone.h"
@@ -68,6 +81,10 @@ using android::base::ErrnoRestorer;
using android::base::StringPrintf;
using android::base::unique_fd;
+// This stores guest architecture. When the architecture is supported, tombstone file will output
+// guest state information.
+static Architecture g_guest_arch;
+
static bool pid_contains_tid(int pid_proc_fd, pid_t tid) {
struct stat st;
std::string task_path = StringPrintf("task/%d", tid);
@@ -286,28 +303,27 @@ static void ReadCrashInfo(unique_fd& fd, siginfo_t* siginfo,
*recoverable_crash = false;
if (rc == -1) {
PLOG(FATAL) << "failed to read target ucontext";
- } else {
- ssize_t expected_size = 0;
- switch (crash_info->header.version) {
- case 1:
- case 2:
- case 3:
- expected_size = sizeof(CrashInfoHeader) + sizeof(CrashInfoDataStatic);
- break;
-
- case 4:
- expected_size = sizeof(CrashInfoHeader) + sizeof(CrashInfoDataDynamic);
- break;
-
- default:
- LOG(FATAL) << "unexpected CrashInfo version: " << crash_info->header.version;
- break;
- };
-
- if (rc < expected_size) {
- LOG(FATAL) << "read " << rc << " bytes when reading target crash information, expected "
- << expected_size;
- }
+ }
+ ssize_t expected_size = 0;
+ switch (crash_info->header.version) {
+ case 1:
+ case 2:
+ case 3:
+ expected_size = sizeof(CrashInfoHeader) + sizeof(CrashInfoDataStatic);
+ break;
+
+ case 4:
+ expected_size = sizeof(CrashInfoHeader) + sizeof(CrashInfoDataDynamic);
+ break;
+
+ default:
+ LOG(FATAL) << "unexpected CrashInfo version: " << crash_info->header.version;
+ break;
+ }
+
+ if (rc < expected_size) {
+ LOG(FATAL) << "read " << rc << " bytes when reading target crash information, expected "
+ << expected_size;
}
switch (crash_info->header.version) {
@@ -403,6 +419,107 @@ static void InstallSigPipeHandler() {
sigaction(SIGPIPE, &action, nullptr);
}
+static bool PtracePeek(int request, pid_t tid, uintptr_t addr, void* data, std::string_view err_msg,
+ uintptr_t* result) {
+ errno = 0;
+ *result = ptrace(request, tid, addr, data);
+ if (errno != 0) {
+ PLOG(ERROR) << err_msg;
+ return false;
+ }
+ return true;
+}
+
+static bool GetGuestRegistersFromCrashedProcess([[maybe_unused]] pid_t tid,
+ NativeBridgeGuestRegs* guest_regs) {
+ auto process_memory = unwindstack::Memory::CreateProcessMemoryCached(tid);
+
+ uintptr_t header_ptr = 0;
+ uintptr_t base = 0;
+#if defined(__x86_64__)
+ if (!PtracePeek(PTRACE_PEEKUSER, tid, offsetof(user_regs_struct, fs_base), nullptr,
+ "failed to read thread register for thread " + std::to_string(tid), &base)) {
+ return false;
+ }
+#elif defined(__aarch64__)
+ // base is implicitly casted to uint64_t.
+ struct iovec pt_iov {
+ .iov_base = &base, .iov_len = sizeof(base),
+ };
+
+ if (ptrace(PTRACE_GETREGSET, tid, NT_ARM_TLS, &pt_iov) != 0) {
+ PLOG(ERROR) << "failed to read thread register for thread " << tid;
+ }
+#else
+ // TODO(b/339287219): Add case for Riscv host.
+ return false;
+#endif
+ auto ptr_to_guest_slot = base + TLS_SLOT_NATIVE_BRIDGE_GUEST_STATE * sizeof(uintptr_t);
+ if (!process_memory->ReadFully(ptr_to_guest_slot, &header_ptr, sizeof(uintptr_t))) {
+ PLOG(ERROR) << "failed to get guest state TLS slot content for thread " << tid;
+ return false;
+ }
+
+ NativeBridgeGuestStateHeader header;
+ if (!process_memory->ReadFully(header_ptr, &header, sizeof(NativeBridgeGuestStateHeader))) {
+ PLOG(ERROR) << "failed to get the guest state header for thread " << tid;
+ return false;
+ }
+ if (header.signature != NATIVE_BRIDGE_GUEST_STATE_SIGNATURE) {
+ // Return when ptr points to unmapped memory or no valid guest state.
+ return false;
+ }
+ auto guest_state_data_copy = std::make_unique<unsigned char[]>(header.guest_state_data_size);
+ if (!process_memory->ReadFully(reinterpret_cast<uintptr_t>(header.guest_state_data),
+ guest_state_data_copy.get(), header.guest_state_data_size)) {
+ PLOG(ERROR) << "failed to read the guest state data for thread " << tid;
+ return false;
+ }
+
+ LoadGuestStateRegisters(guest_state_data_copy.get(), header.guest_state_data_size, guest_regs);
+ return true;
+}
+
+static void ReadGuestRegisters([[maybe_unused]] std::unique_ptr<unwindstack::Regs>* regs,
+ pid_t tid) {
+ // TODO: remove [[maybe_unused]], when the ARM32 case is removed from the native bridge support.
+ NativeBridgeGuestRegs guest_regs;
+ if (!GetGuestRegistersFromCrashedProcess(tid, &guest_regs)) {
+ return;
+ }
+
+ switch (guest_regs.guest_arch) {
+#if defined(__LP64__)
+ case NATIVE_BRIDGE_ARCH_ARM64: {
+ unwindstack::arm64_user_regs arm64_user_regs = {};
+ for (size_t i = 0; i < unwindstack::ARM64_REG_R31; i++) {
+ arm64_user_regs.regs[i] = guest_regs.regs_arm64.x[i];
+ }
+ arm64_user_regs.sp = guest_regs.regs_arm64.sp;
+ arm64_user_regs.pc = guest_regs.regs_arm64.ip;
+ regs->reset(unwindstack::RegsArm64::Read(&arm64_user_regs));
+
+ g_guest_arch = Architecture::ARM64;
+ break;
+ }
+ case NATIVE_BRIDGE_ARCH_RISCV64: {
+ unwindstack::riscv64_user_regs riscv64_user_regs = {};
+ // RISCV64_REG_PC is at the first position.
+ riscv64_user_regs.regs[0] = guest_regs.regs_riscv64.ip;
+ for (size_t i = 1; i < unwindstack::RISCV64_REG_REAL_COUNT; i++) {
+ riscv64_user_regs.regs[i] = guest_regs.regs_riscv64.x[i];
+ }
+ regs->reset(unwindstack::RegsRiscv64::Read(&riscv64_user_regs, tid));
+
+ g_guest_arch = Architecture::RISCV64;
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+}
+
int main(int argc, char** argv) {
DefuseSignalHandlers();
InstallSigPipeHandler();
@@ -551,6 +668,7 @@ int main(int argc, char** argv) {
continue;
}
}
+ ReadGuestRegisters(&info.guest_registers, thread);
thread_info[thread] = std::move(info);
}
@@ -660,8 +778,32 @@ int main(int argc, char** argv) {
{
ATRACE_NAME("engrave_tombstone");
- engrave_tombstone(std::move(g_output_fd), std::move(g_proto_fd), &unwinder, thread_info,
- g_target_thread, process_info, &open_files, &amfd_data);
+ unwindstack::ArchEnum regs_arch = unwindstack::ARCH_UNKNOWN;
+ switch (g_guest_arch) {
+ case Architecture::ARM32: {
+ regs_arch = unwindstack::ARCH_ARM;
+ break;
+ }
+ case Architecture::ARM64: {
+ regs_arch = unwindstack::ARCH_ARM64;
+ break;
+ }
+ case Architecture::RISCV64: {
+ regs_arch = unwindstack::ARCH_RISCV64;
+ break;
+ }
+ default: {
+ }
+ }
+ if (regs_arch == unwindstack::ARCH_UNKNOWN) {
+ engrave_tombstone(std::move(g_output_fd), std::move(g_proto_fd), &unwinder, thread_info,
+ g_target_thread, process_info, &open_files, &amfd_data);
+ } else {
+ unwindstack::AndroidRemoteUnwinder guest_unwinder(vm_pid, regs_arch);
+ engrave_tombstone(std::move(g_output_fd), std::move(g_proto_fd), &unwinder, thread_info,
+ g_target_thread, process_info, &open_files, &amfd_data, &g_guest_arch,
+ &guest_unwinder);
+ }
}
}
diff --git a/debuggerd/crasher/crasher.cpp b/debuggerd/crasher/crasher.cpp
index 3b52776d7..05143ed05 100644
--- a/debuggerd/crasher/crasher.cpp
+++ b/debuggerd/crasher/crasher.cpp
@@ -202,7 +202,9 @@ static int usage() {
fprintf(stderr, " fdsan_file close a file descriptor that's owned by a FILE*\n");
fprintf(stderr, " fdsan_dir close a file descriptor that's owned by a DIR*\n");
fprintf(stderr, " seccomp fail a seccomp check\n");
+#if defined(__LP64__)
fprintf(stderr, " xom read execute-only memory\n");
+#endif
fprintf(stderr, "\n");
fprintf(stderr, " LOG_ALWAYS_FATAL call liblog LOG_ALWAYS_FATAL\n");
fprintf(stderr, " LOG_ALWAYS_FATAL_IF call liblog LOG_ALWAYS_FATAL_IF\n");
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 7c52e6e50..baddf6578 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -332,12 +332,7 @@ TEST_F(CrasherTest, smoke) {
std::string result;
ConsumeFd(std::move(output_fd), &result);
-#ifdef __LP64__
- ASSERT_MATCH(result,
- R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x000000000000dead)");
-#else
- ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0000dead)");
-#endif
+ ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr 0x0+dead)");
if (mte_supported()) {
// Test that the default TAGGED_ADDR_CTRL value is set.
@@ -1667,6 +1662,9 @@ TEST_F(CrasherTest, seccomp_tombstone_thread_abort) {
std::string result;
ConsumeFd(std::move(output_fd), &result);
+ ASSERT_MATCH(
+ result,
+ R"(signal 6 \(SIGABRT\))");
ASSERT_BACKTRACE_FRAME(result, "abort");
}
@@ -1826,10 +1824,14 @@ GwpAsanTestParameters gwp_asan_tests[] = {
"Use After Free, 0 bytes into a 7-byte allocation"},
{/* alloc_size */ 15, /* free_before_access */ true, /* access_offset */ 1,
"Use After Free, 1 byte into a 15-byte allocation"},
- {/* alloc_size */ 4096, /* free_before_access */ false, /* access_offset */ 4098,
- "Buffer Overflow, 2 bytes right of a 4096-byte allocation"},
- {/* alloc_size */ 4096, /* free_before_access */ false, /* access_offset */ -1,
- "Buffer Underflow, 1 byte left of a 4096-byte allocation"},
+ {/* alloc_size */ static_cast<size_t>(getpagesize()), /* free_before_access */ false,
+ /* access_offset */ getpagesize() + 2,
+ android::base::StringPrintf("Buffer Overflow, 2 bytes right of a %d-byte allocation",
+ getpagesize())},
+ {/* alloc_size */ static_cast<size_t>(getpagesize()), /* free_before_access */ false,
+ /* access_offset */ -1,
+ android::base::StringPrintf("Buffer Underflow, 1 byte left of a %d-byte allocation",
+ getpagesize())},
};
INSTANTIATE_TEST_SUITE_P(
@@ -2974,30 +2976,34 @@ TEST_F(CrasherTest, verify_map_format) {
std::string match_str;
// Verify none.
match_str = android::base::StringPrintf(
- " %s-%s --- 0 1000\\n",
+ " %s-%s --- 0 %x\\n",
format_map_pointer(reinterpret_cast<uintptr_t>(none_map)).c_str(),
- format_map_pointer(reinterpret_cast<uintptr_t>(none_map) + getpagesize() - 1).c_str());
+ format_map_pointer(reinterpret_cast<uintptr_t>(none_map) + getpagesize() - 1).c_str(),
+ getpagesize());
ASSERT_MATCH(result, match_str);
// Verify read-only.
match_str = android::base::StringPrintf(
- " %s-%s r-- 0 1000\\n",
+ " %s-%s r-- 0 %x\\n",
format_map_pointer(reinterpret_cast<uintptr_t>(r_map)).c_str(),
- format_map_pointer(reinterpret_cast<uintptr_t>(r_map) + getpagesize() - 1).c_str());
+ format_map_pointer(reinterpret_cast<uintptr_t>(r_map) + getpagesize() - 1).c_str(),
+ getpagesize());
ASSERT_MATCH(result, match_str);
// Verify write-only.
match_str = android::base::StringPrintf(
- " %s-%s -w- 0 1000\\n",
+ " %s-%s -w- 0 %x\\n",
format_map_pointer(reinterpret_cast<uintptr_t>(w_map)).c_str(),
- format_map_pointer(reinterpret_cast<uintptr_t>(w_map) + getpagesize() - 1).c_str());
+ format_map_pointer(reinterpret_cast<uintptr_t>(w_map) + getpagesize() - 1).c_str(),
+ getpagesize());
ASSERT_MATCH(result, match_str);
// Verify exec-only.
match_str = android::base::StringPrintf(
- " %s-%s --x 0 1000\\n",
+ " %s-%s --x 0 %x\\n",
format_map_pointer(reinterpret_cast<uintptr_t>(x_map)).c_str(),
- format_map_pointer(reinterpret_cast<uintptr_t>(x_map) + getpagesize() - 1).c_str());
+ format_map_pointer(reinterpret_cast<uintptr_t>(x_map) + getpagesize() - 1).c_str(),
+ getpagesize());
ASSERT_MATCH(result, match_str);
// Verify file map with non-zero offset and a name.
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/scudo.h b/debuggerd/libdebuggerd/include/libdebuggerd/scudo.h
index a506859a4..89bf5a96d 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/scudo.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/scudo.h
@@ -16,6 +16,8 @@
#pragma once
+#if defined(USE_SCUDO)
+
#include "types.h"
#include "utility.h"
@@ -49,3 +51,5 @@ class ScudoCrashData {
void FillInCause(Cause* cause, const scudo_error_report* report,
unwindstack::AndroidUnwinder* unwinder) const;
};
+
+#endif // USE_SCUDO
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h b/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h
index be999e04e..dfdfabdff 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/tombstone.h
@@ -28,6 +28,7 @@
#include <android-base/unique_fd.h>
#include "open_files_list.h"
+#include "tombstone.pb.h"
#include "types.h"
// Forward declarations
@@ -54,14 +55,17 @@ void engrave_tombstone(android::base::unique_fd output_fd, android::base::unique
unwindstack::AndroidUnwinder* unwinder,
const std::map<pid_t, ThreadInfo>& thread_info, pid_t target_thread,
const ProcessInfo& process_info, OpenFilesList* open_files,
- std::string* amfd_data);
+ std::string* amfd_data, const Architecture* guest_arch = nullptr,
+ unwindstack::AndroidUnwinder* guest_unwinder = nullptr);
void engrave_tombstone_ucontext(int tombstone_fd, int proto_fd, uint64_t abort_msg_address,
siginfo_t* siginfo, ucontext_t* ucontext);
void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder,
const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
- const ProcessInfo& process_info, const OpenFilesList* open_files);
+ const ProcessInfo& process_info, const OpenFilesList* open_files,
+ const Architecture* guest_arch,
+ unwindstack::AndroidUnwinder* guest_unwinder);
bool tombstone_proto_to_text(
const Tombstone& tombstone,
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/types.h b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
index 4d69658e2..c799f2448 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/types.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
@@ -39,6 +39,8 @@ struct ThreadInfo {
int signo = 0;
siginfo_t* siginfo = nullptr;
+
+ std::unique_ptr<unwindstack::Regs> guest_registers;
};
// This struct is written into a pipe from inside the crashing process.
diff --git a/debuggerd/libdebuggerd/scudo.cpp b/debuggerd/libdebuggerd/scudo.cpp
index 3fa3bd032..4ee87c841 100644
--- a/debuggerd/libdebuggerd/scudo.cpp
+++ b/debuggerd/libdebuggerd/scudo.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#if defined(USE_SCUDO)
+
#include "libdebuggerd/scudo.h"
#include "libdebuggerd/tombstone.h"
@@ -141,3 +143,5 @@ void ScudoCrashData::AddCauseProtos(Tombstone* tombstone,
FillInCause(tombstone->add_causes(), &error_info_.reports[report_num++], unwinder);
}
}
+
+#endif // USE_SCUDO
diff --git a/debuggerd/libdebuggerd/test/dump_memory_test.cpp b/debuggerd/libdebuggerd/test/dump_memory_test.cpp
index 5be145aad..dee7b4827 100644
--- a/debuggerd/libdebuggerd/test/dump_memory_test.cpp
+++ b/debuggerd/libdebuggerd/test/dump_memory_test.cpp
@@ -20,6 +20,8 @@
#include <string>
#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
#include <gtest/gtest.h>
#include <unwindstack/Memory.h>
@@ -27,61 +29,64 @@
#include "log_fake.h"
-const char g_expected_full_dump[] =
-"\nmemory near r1:\n"
+std::string GetMemoryString(uintptr_t addr, const std::vector<uint64_t>& data) {
+ // Must be even number of data values.
+ CHECK((data.size() & 1) == 0);
+
+ std::string str;
+ for (size_t i = 0; i < data.size(); i += 2) {
+ str += " ";
+ std::string ascii_str = "";
+ for (size_t j = 0; j < 2; j++) {
+ for (size_t k = 0; k < 8; k++) {
+ uint8_t c = (data[i + j] >> (k * 8)) & 0xff;
+ if (c >= 0x20 && c < 0x7f) {
+ ascii_str += c;
+ } else {
+ ascii_str += '.';
+ }
+ }
+ }
#if defined(__LP64__)
-" 0000000012345650 0706050403020100 0f0e0d0c0b0a0908 ................\n"
-" 0000000012345660 1716151413121110 1f1e1d1c1b1a1918 ................\n"
-" 0000000012345670 2726252423222120 2f2e2d2c2b2a2928 !\"#$%&'()*+,-./\n"
-" 0000000012345680 3736353433323130 3f3e3d3c3b3a3938 0123456789:;<=>?\n"
-" 0000000012345690 4746454443424140 4f4e4d4c4b4a4948 @ABCDEFGHIJKLMNO\n"
-" 00000000123456a0 5756555453525150 5f5e5d5c5b5a5958 PQRSTUVWXYZ[\\]^_\n"
-" 00000000123456b0 6766656463626160 6f6e6d6c6b6a6968 `abcdefghijklmno\n"
-" 00000000123456c0 7776757473727170 7f7e7d7c7b7a7978 pqrstuvwxyz{|}~.\n"
-" 00000000123456d0 8786858483828180 8f8e8d8c8b8a8988 ................\n"
-" 00000000123456e0 9796959493929190 9f9e9d9c9b9a9998 ................\n"
-" 00000000123456f0 a7a6a5a4a3a2a1a0 afaeadacabaaa9a8 ................\n"
-" 0000000012345700 b7b6b5b4b3b2b1b0 bfbebdbcbbbab9b8 ................\n"
-" 0000000012345710 c7c6c5c4c3c2c1c0 cfcecdcccbcac9c8 ................\n"
-" 0000000012345720 d7d6d5d4d3d2d1d0 dfdedddcdbdad9d8 ................\n"
-" 0000000012345730 e7e6e5e4e3e2e1e0 efeeedecebeae9e8 ................\n"
-" 0000000012345740 f7f6f5f4f3f2f1f0 fffefdfcfbfaf9f8 ................\n";
+ str += android::base::StringPrintf("%016zx %016zx %016zx ", addr, data[i], data[i + 1]);
#else
-" 12345650 03020100 07060504 0b0a0908 0f0e0d0c ................\n"
-" 12345660 13121110 17161514 1b1a1918 1f1e1d1c ................\n"
-" 12345670 23222120 27262524 2b2a2928 2f2e2d2c !\"#$%&'()*+,-./\n"
-" 12345680 33323130 37363534 3b3a3938 3f3e3d3c 0123456789:;<=>?\n"
-" 12345690 43424140 47464544 4b4a4948 4f4e4d4c @ABCDEFGHIJKLMNO\n"
-" 123456a0 53525150 57565554 5b5a5958 5f5e5d5c PQRSTUVWXYZ[\\]^_\n"
-" 123456b0 63626160 67666564 6b6a6968 6f6e6d6c `abcdefghijklmno\n"
-" 123456c0 73727170 77767574 7b7a7978 7f7e7d7c pqrstuvwxyz{|}~.\n"
-" 123456d0 83828180 87868584 8b8a8988 8f8e8d8c ................\n"
-" 123456e0 93929190 97969594 9b9a9998 9f9e9d9c ................\n"
-" 123456f0 a3a2a1a0 a7a6a5a4 abaaa9a8 afaeadac ................\n"
-" 12345700 b3b2b1b0 b7b6b5b4 bbbab9b8 bfbebdbc ................\n"
-" 12345710 c3c2c1c0 c7c6c5c4 cbcac9c8 cfcecdcc ................\n"
-" 12345720 d3d2d1d0 d7d6d5d4 dbdad9d8 dfdedddc ................\n"
-" 12345730 e3e2e1e0 e7e6e5e4 ebeae9e8 efeeedec ................\n"
-" 12345740 f3f2f1f0 f7f6f5f4 fbfaf9f8 fffefdfc ................\n";
+ str += android::base::StringPrintf(
+ "%08zx %08zx %08zx %08zx %08zx ", addr, static_cast<uintptr_t>(data[i] & 0xffffffff),
+ static_cast<uintptr_t>(data[i] >> 32), static_cast<uintptr_t>(data[i + 1] & 0xffffffff),
+ static_cast<uintptr_t>(data[i + 1] >> 32));
#endif
+ str += ascii_str + "\n";
+ addr += 0x10;
+ }
+ return str;
+}
-const char g_expected_partial_dump[] = \
-"\nmemory near pc:\n"
-#if defined(__LP64__)
-" 00000000123455e0 0706050403020100 0f0e0d0c0b0a0908 ................\n"
-" 00000000123455f0 1716151413121110 1f1e1d1c1b1a1918 ................\n"
-" 0000000012345600 2726252423222120 2f2e2d2c2b2a2928 !\"#$%&'()*+,-./\n"
-" 0000000012345610 3736353433323130 3f3e3d3c3b3a3938 0123456789:;<=>?\n"
-" 0000000012345620 4746454443424140 4f4e4d4c4b4a4948 @ABCDEFGHIJKLMNO\n"
-" 0000000012345630 5756555453525150 5f5e5d5c5b5a5958 PQRSTUVWXYZ[\\]^_\n";
-#else
-" 123455e0 03020100 07060504 0b0a0908 0f0e0d0c ................\n"
-" 123455f0 13121110 17161514 1b1a1918 1f1e1d1c ................\n"
-" 12345600 23222120 27262524 2b2a2928 2f2e2d2c !\"#$%&'()*+,-./\n"
-" 12345610 33323130 37363534 3b3a3938 3f3e3d3c 0123456789:;<=>?\n"
-" 12345620 43424140 47464544 4b4a4948 4f4e4d4c @ABCDEFGHIJKLMNO\n"
-" 12345630 53525150 57565554 5b5a5958 5f5e5d5c PQRSTUVWXYZ[\\]^_\n";
-#endif
+const std::vector<uint64_t>& GetDefaultData() {
+ static std::vector<uint64_t> data(
+ {0x0706050403020100UL, 0x0f0e0d0c0b0a0908UL, 0x1716151413121110UL, 0x1f1e1d1c1b1a1918UL,
+ 0x2726252423222120UL, 0x2f2e2d2c2b2a2928UL, 0x3736353433323130UL, 0x3f3e3d3c3b3a3938UL,
+ 0x4746454443424140UL, 0x4f4e4d4c4b4a4948UL, 0x5756555453525150UL, 0x5f5e5d5c5b5a5958UL,
+ 0x6766656463626160UL, 0x6f6e6d6c6b6a6968UL, 0x7776757473727170UL, 0x7f7e7d7c7b7a7978UL,
+ 0x8786858483828180UL, 0x8f8e8d8c8b8a8988UL, 0x9796959493929190UL, 0x9f9e9d9c9b9a9998UL,
+ 0xa7a6a5a4a3a2a1a0UL, 0xafaeadacabaaa9a8UL, 0xb7b6b5b4b3b2b1b0UL, 0xbfbebdbcbbbab9b8UL,
+ 0xc7c6c5c4c3c2c1c0UL, 0xcfcecdcccbcac9c8UL, 0xd7d6d5d4d3d2d1d0UL, 0xdfdedddcdbdad9d8UL,
+ 0xe7e6e5e4e3e2e1e0UL, 0xefeeedecebeae9e8UL, 0xf7f6f5f4f3f2f1f0UL, 0xfffefdfcfbfaf9f8UL});
+ return data;
+}
+
+std::string GetFullDumpString() {
+ std::string str = "\nmemory near r1:\n";
+ str += GetMemoryString(0x12345650U, GetDefaultData());
+ return str;
+}
+
+std::string GetPartialDumpString() {
+ std::string str = "\nmemory near pc:\n";
+ std::vector<uint64_t> data = GetDefaultData();
+ data.resize(12);
+ str += GetMemoryString(0x123455e0U, data);
+ return str;
+}
class MemoryMock : public unwindstack::Memory {
public:
@@ -189,7 +194,7 @@ TEST_F(DumpMemoryTest, aligned_addr) {
std::string tombstone_contents;
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
- ASSERT_STREQ(g_expected_full_dump, tombstone_contents.c_str());
+ ASSERT_EQ(GetFullDumpString(), tombstone_contents);
// Verify that the log buf is empty, and no error messages.
ASSERT_STREQ("", getFakeLogBuf().c_str());
@@ -209,7 +214,7 @@ TEST_F(DumpMemoryTest, partial_read) {
std::string tombstone_contents;
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
- ASSERT_STREQ(g_expected_full_dump, tombstone_contents.c_str());
+ ASSERT_EQ(GetFullDumpString(), tombstone_contents);
// Verify that the log buf is empty, and no error messages.
ASSERT_STREQ("", getFakeLogBuf().c_str());
@@ -228,7 +233,7 @@ TEST_F(DumpMemoryTest, unaligned_addr) {
std::string tombstone_contents;
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
- ASSERT_STREQ(g_expected_full_dump, tombstone_contents.c_str());
+ ASSERT_EQ(GetFullDumpString(), tombstone_contents);
// Verify that the log buf is empty, and no error messages.
ASSERT_STREQ("", getFakeLogBuf().c_str());
@@ -260,7 +265,7 @@ TEST_F(DumpMemoryTest, memory_partially_unreadable) {
std::string tombstone_contents;
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
- ASSERT_STREQ(g_expected_partial_dump, tombstone_contents.c_str());
+ ASSERT_EQ(GetPartialDumpString(), tombstone_contents);
// Verify that the log buf is empty, and no error messages.
ASSERT_STREQ("", getFakeLogBuf().c_str());
@@ -280,7 +285,7 @@ TEST_F(DumpMemoryTest, memory_partially_unreadable_unaligned_return) {
std::string tombstone_contents;
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
- ASSERT_STREQ(g_expected_partial_dump, tombstone_contents.c_str());
+ ASSERT_EQ(GetPartialDumpString(), tombstone_contents);
#if defined(__LP64__)
ASSERT_STREQ("6 DEBUG Bytes read 102, is not a multiple of 8\n", getFakeLogPrint().c_str());
@@ -305,7 +310,7 @@ TEST_F(DumpMemoryTest, memory_partially_unreadable_two_unaligned_reads) {
std::string tombstone_contents;
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
- ASSERT_STREQ(g_expected_partial_dump, tombstone_contents.c_str());
+ ASSERT_EQ(GetPartialDumpString(), tombstone_contents);
#if defined(__LP64__)
ASSERT_STREQ("6 DEBUG Bytes read 45, is not a multiple of 8\n"
@@ -331,44 +336,9 @@ TEST_F(DumpMemoryTest, address_low_fence) {
std::string tombstone_contents;
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
- const char* expected_dump = \
-"\nmemory near r1:\n"
-#if defined(__LP64__)
-" 0000000000001000 0000000000000000 0000000000000000 ................\n"
-" 0000000000001010 0000000000000000 0000000000000000 ................\n"
-" 0000000000001020 0000000000000000 0000000000000000 ................\n"
-" 0000000000001030 0000000000000000 0000000000000000 ................\n"
-" 0000000000001040 0000000000000000 0000000000000000 ................\n"
-" 0000000000001050 0000000000000000 0000000000000000 ................\n"
-" 0000000000001060 0000000000000000 0000000000000000 ................\n"
-" 0000000000001070 0000000000000000 0000000000000000 ................\n"
-" 0000000000001080 0000000000000000 0000000000000000 ................\n"
-" 0000000000001090 0000000000000000 0000000000000000 ................\n"
-" 00000000000010a0 0000000000000000 0000000000000000 ................\n"
-" 00000000000010b0 0000000000000000 0000000000000000 ................\n"
-" 00000000000010c0 0000000000000000 0000000000000000 ................\n"
-" 00000000000010d0 0000000000000000 0000000000000000 ................\n"
-" 00000000000010e0 0000000000000000 0000000000000000 ................\n"
-" 00000000000010f0 0000000000000000 0000000000000000 ................\n";
-#else
-" 00001000 00000000 00000000 00000000 00000000 ................\n"
-" 00001010 00000000 00000000 00000000 00000000 ................\n"
-" 00001020 00000000 00000000 00000000 00000000 ................\n"
-" 00001030 00000000 00000000 00000000 00000000 ................\n"
-" 00001040 00000000 00000000 00000000 00000000 ................\n"
-" 00001050 00000000 00000000 00000000 00000000 ................\n"
-" 00001060 00000000 00000000 00000000 00000000 ................\n"
-" 00001070 00000000 00000000 00000000 00000000 ................\n"
-" 00001080 00000000 00000000 00000000 00000000 ................\n"
-" 00001090 00000000 00000000 00000000 00000000 ................\n"
-" 000010a0 00000000 00000000 00000000 00000000 ................\n"
-" 000010b0 00000000 00000000 00000000 00000000 ................\n"
-" 000010c0 00000000 00000000 00000000 00000000 ................\n"
-" 000010d0 00000000 00000000 00000000 00000000 ................\n"
-" 000010e0 00000000 00000000 00000000 00000000 ................\n"
-" 000010f0 00000000 00000000 00000000 00000000 ................\n";
-#endif
- ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
+ std::string expected_dump = "\nmemory near r1:\n";
+ expected_dump += GetMemoryString(0x1000, std::vector<uint64_t>(32, 0UL));
+ ASSERT_EQ(expected_dump, tombstone_contents);
// Verify that the log buf is empty, and no error messages.
ASSERT_STREQ("", getFakeLogBuf().c_str());
@@ -414,61 +384,17 @@ TEST_F(DumpMemoryTest, memory_address_nearly_too_high) {
std::string tombstone_contents;
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
- const char* expected_dump = \
-"\nmemory near r4:\n"
+ std::string expected_dump = "\nmemory near r4:\n";
+ uintptr_t addr;
#if defined(__aarch64__)
-" 00ffffffffffff00 0706050403020100 0f0e0d0c0b0a0908 ................\n"
-" 00ffffffffffff10 1716151413121110 1f1e1d1c1b1a1918 ................\n"
-" 00ffffffffffff20 2726252423222120 2f2e2d2c2b2a2928 !\"#$%&'()*+,-./\n"
-" 00ffffffffffff30 3736353433323130 3f3e3d3c3b3a3938 0123456789:;<=>?\n"
-" 00ffffffffffff40 4746454443424140 4f4e4d4c4b4a4948 @ABCDEFGHIJKLMNO\n"
-" 00ffffffffffff50 5756555453525150 5f5e5d5c5b5a5958 PQRSTUVWXYZ[\\]^_\n"
-" 00ffffffffffff60 6766656463626160 6f6e6d6c6b6a6968 `abcdefghijklmno\n"
-" 00ffffffffffff70 7776757473727170 7f7e7d7c7b7a7978 pqrstuvwxyz{|}~.\n"
-" 00ffffffffffff80 8786858483828180 8f8e8d8c8b8a8988 ................\n"
-" 00ffffffffffff90 9796959493929190 9f9e9d9c9b9a9998 ................\n"
-" 00ffffffffffffa0 a7a6a5a4a3a2a1a0 afaeadacabaaa9a8 ................\n"
-" 00ffffffffffffb0 b7b6b5b4b3b2b1b0 bfbebdbcbbbab9b8 ................\n"
-" 00ffffffffffffc0 c7c6c5c4c3c2c1c0 cfcecdcccbcac9c8 ................\n"
-" 00ffffffffffffd0 d7d6d5d4d3d2d1d0 dfdedddcdbdad9d8 ................\n"
-" 00ffffffffffffe0 e7e6e5e4e3e2e1e0 efeeedecebeae9e8 ................\n"
-" 00fffffffffffff0 f7f6f5f4f3f2f1f0 fffefdfcfbfaf9f8 ................\n";
+ addr = 0x00ffffffffffff00UL;
#elif defined(__LP64__)
-" ffffffffffffff00 0706050403020100 0f0e0d0c0b0a0908 ................\n"
-" ffffffffffffff10 1716151413121110 1f1e1d1c1b1a1918 ................\n"
-" ffffffffffffff20 2726252423222120 2f2e2d2c2b2a2928 !\"#$%&'()*+,-./\n"
-" ffffffffffffff30 3736353433323130 3f3e3d3c3b3a3938 0123456789:;<=>?\n"
-" ffffffffffffff40 4746454443424140 4f4e4d4c4b4a4948 @ABCDEFGHIJKLMNO\n"
-" ffffffffffffff50 5756555453525150 5f5e5d5c5b5a5958 PQRSTUVWXYZ[\\]^_\n"
-" ffffffffffffff60 6766656463626160 6f6e6d6c6b6a6968 `abcdefghijklmno\n"
-" ffffffffffffff70 7776757473727170 7f7e7d7c7b7a7978 pqrstuvwxyz{|}~.\n"
-" ffffffffffffff80 8786858483828180 8f8e8d8c8b8a8988 ................\n"
-" ffffffffffffff90 9796959493929190 9f9e9d9c9b9a9998 ................\n"
-" ffffffffffffffa0 a7a6a5a4a3a2a1a0 afaeadacabaaa9a8 ................\n"
-" ffffffffffffffb0 b7b6b5b4b3b2b1b0 bfbebdbcbbbab9b8 ................\n"
-" ffffffffffffffc0 c7c6c5c4c3c2c1c0 cfcecdcccbcac9c8 ................\n"
-" ffffffffffffffd0 d7d6d5d4d3d2d1d0 dfdedddcdbdad9d8 ................\n"
-" ffffffffffffffe0 e7e6e5e4e3e2e1e0 efeeedecebeae9e8 ................\n"
-" fffffffffffffff0 f7f6f5f4f3f2f1f0 fffefdfcfbfaf9f8 ................\n";
+ addr = 0xffffffffffffff00UL;
#else
-" ffffff00 03020100 07060504 0b0a0908 0f0e0d0c ................\n"
-" ffffff10 13121110 17161514 1b1a1918 1f1e1d1c ................\n"
-" ffffff20 23222120 27262524 2b2a2928 2f2e2d2c !\"#$%&'()*+,-./\n"
-" ffffff30 33323130 37363534 3b3a3938 3f3e3d3c 0123456789:;<=>?\n"
-" ffffff40 43424140 47464544 4b4a4948 4f4e4d4c @ABCDEFGHIJKLMNO\n"
-" ffffff50 53525150 57565554 5b5a5958 5f5e5d5c PQRSTUVWXYZ[\\]^_\n"
-" ffffff60 63626160 67666564 6b6a6968 6f6e6d6c `abcdefghijklmno\n"
-" ffffff70 73727170 77767574 7b7a7978 7f7e7d7c pqrstuvwxyz{|}~.\n"
-" ffffff80 83828180 87868584 8b8a8988 8f8e8d8c ................\n"
-" ffffff90 93929190 97969594 9b9a9998 9f9e9d9c ................\n"
-" ffffffa0 a3a2a1a0 a7a6a5a4 abaaa9a8 afaeadac ................\n"
-" ffffffb0 b3b2b1b0 b7b6b5b4 bbbab9b8 bfbebdbc ................\n"
-" ffffffc0 c3c2c1c0 c7c6c5c4 cbcac9c8 cfcecdcc ................\n"
-" ffffffd0 d3d2d1d0 d7d6d5d4 dbdad9d8 dfdedddc ................\n"
-" ffffffe0 e3e2e1e0 e7e6e5e4 ebeae9e8 efeeedec ................\n"
-" fffffff0 f3f2f1f0 f7f6f5f4 fbfaf9f8 fffefdfc ................\n";
+ addr = 0xffffff00UL;
#endif
- ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
+ expected_dump += GetMemoryString(addr, GetDefaultData());
+ ASSERT_EQ(expected_dump, tombstone_contents);
// Verify that the log buf is empty, and no error messages.
ASSERT_STREQ("", getFakeLogBuf().c_str());
@@ -490,30 +416,15 @@ TEST_F(DumpMemoryTest, first_read_empty) {
std::string tombstone_contents;
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
- const char* expected_dump = \
-"\nmemory near r4:\n"
-#if defined(__LP64__)
-R"( 0000000010001000 8786858483828180 8f8e8d8c8b8a8988 ................
- 0000000010001010 9796959493929190 9f9e9d9c9b9a9998 ................
- 0000000010001020 a7a6a5a4a3a2a1a0 afaeadacabaaa9a8 ................
- 0000000010001030 b7b6b5b4b3b2b1b0 bfbebdbcbbbab9b8 ................
- 0000000010001040 c7c6c5c4c3c2c1c0 cfcecdcccbcac9c8 ................
- 0000000010001050 d7d6d5d4d3d2d1d0 dfdedddcdbdad9d8 ................
- 0000000010001060 e7e6e5e4e3e2e1e0 efeeedecebeae9e8 ................
- 0000000010001070 f7f6f5f4f3f2f1f0 fffefdfcfbfaf9f8 ................
-)";
-#else
-R"( 10001000 83828180 87868584 8b8a8988 8f8e8d8c ................
- 10001010 93929190 97969594 9b9a9998 9f9e9d9c ................
- 10001020 a3a2a1a0 a7a6a5a4 abaaa9a8 afaeadac ................
- 10001030 b3b2b1b0 b7b6b5b4 bbbab9b8 bfbebdbc ................
- 10001040 c3c2c1c0 c7c6c5c4 cbcac9c8 cfcecdcc ................
- 10001050 d3d2d1d0 d7d6d5d4 dbdad9d8 dfdedddc ................
- 10001060 e3e2e1e0 e7e6e5e4 ebeae9e8 efeeedec ................
- 10001070 f3f2f1f0 f7f6f5f4 fbfaf9f8 fffefdfc ................
-)";
-#endif
- ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
+ std::string expected_dump = "\nmemory near r4:\n";
+ expected_dump += GetMemoryString(
+ 0x10000000 + page_size,
+ std::vector<uint64_t>{
+ 0x8786858483828180UL, 0x8f8e8d8c8b8a8988UL, 0x9796959493929190UL, 0x9f9e9d9c9b9a9998UL,
+ 0xa7a6a5a4a3a2a1a0UL, 0xafaeadacabaaa9a8UL, 0xb7b6b5b4b3b2b1b0UL, 0xbfbebdbcbbbab9b8UL,
+ 0xc7c6c5c4c3c2c1c0UL, 0xcfcecdcccbcac9c8UL, 0xd7d6d5d4d3d2d1d0UL, 0xdfdedddcdbdad9d8UL,
+ 0xe7e6e5e4e3e2e1e0UL, 0xefeeedecebeae9e8UL, 0xf7f6f5f4f3f2f1f0UL, 0xfffefdfcfbfaf9f8UL});
+ ASSERT_EQ(expected_dump, tombstone_contents);
// Verify that the log buf is empty, and no error messages.
ASSERT_STREQ("", getFakeLogBuf().c_str());
@@ -535,16 +446,11 @@ TEST_F(DumpMemoryTest, first_read_empty_second_read_stops) {
std::string tombstone_contents;
ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
- const char* expected_dump = \
-"\nmemory near r4:\n"
-#if defined(__LP64__)
-" 0000000010001000 c7c6c5c4c3c2c1c0 cfcecdcccbcac9c8 ................\n"
-" 0000000010001010 d7d6d5d4d3d2d1d0 dfdedddcdbdad9d8 ................\n";
-#else
-" 10001000 c3c2c1c0 c7c6c5c4 cbcac9c8 cfcecdcc ................\n"
-" 10001010 d3d2d1d0 d7d6d5d4 dbdad9d8 dfdedddc ................\n";
-#endif
- ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
+ std::string expected_dump = "\nmemory near r4:\n";
+ expected_dump += GetMemoryString(
+ 0x10000000 + page_size, std::vector<uint64_t>{0xc7c6c5c4c3c2c1c0UL, 0xcfcecdcccbcac9c8UL,
+ 0xd7d6d5d4d3d2d1d0UL, 0xdfdedddcdbdad9d8UL});
+ ASSERT_EQ(expected_dump, tombstone_contents);
// Verify that the log buf is empty, and no error messages.
ASSERT_STREQ("", getFakeLogBuf().c_str());
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index 375ed8a2c..0ce55738a 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -76,7 +76,7 @@ void engrave_tombstone_ucontext(int tombstone_fd, int proto_fd, uint64_t abort_m
threads[target_tid] = ThreadInfo {
.registers = std::move(regs), .uid = uid, .tid = target_tid,
.thread_name = std::move(thread_name), .pid = pid, .command_line = std::move(command_line),
- .selinux_label = std::move(selinux_label), .siginfo = siginfo,
+ .selinux_label = std::move(selinux_label), .siginfo = siginfo, .signo = siginfo->si_signo,
// Only supported on aarch64 for now.
#if defined(__aarch64__)
.tagged_addr_ctrl = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0),
@@ -125,10 +125,12 @@ void engrave_tombstone(unique_fd output_fd, unique_fd proto_fd,
unwindstack::AndroidUnwinder* unwinder,
const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
const ProcessInfo& process_info, OpenFilesList* open_files,
- std::string* amfd_data) {
+ std::string* amfd_data, const Architecture* guest_arch,
+ unwindstack::AndroidUnwinder* guest_unwinder) {
// Don't copy log messages to tombstone unless this is a development device.
Tombstone tombstone;
- engrave_tombstone_proto(&tombstone, unwinder, threads, target_thread, process_info, open_files);
+ engrave_tombstone_proto(&tombstone, unwinder, threads, target_thread, process_info, open_files,
+ guest_arch, guest_unwinder);
if (proto_fd != -1) {
if (!tombstone.SerializeToFileDescriptor(proto_fd.get())) {
diff --git a/debuggerd/libdebuggerd/tombstone_proto.cpp b/debuggerd/libdebuggerd/tombstone_proto.cpp
index 4cde98610..3e8ab6ea5 100644
--- a/debuggerd/libdebuggerd/tombstone_proto.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto.cpp
@@ -482,7 +482,8 @@ static void dump_thread_backtrace(std::vector<unwindstack::FrameData>& frames, T
}
static void dump_thread(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder,
- const ThreadInfo& thread_info, bool memory_dump = false) {
+ const ThreadInfo& thread_info, bool memory_dump = false,
+ unwindstack::AndroidUnwinder* guest_unwinder = nullptr) {
Thread thread;
thread.set_id(thread_info.tid);
@@ -509,6 +510,27 @@ static void dump_thread(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwi
auto& threads = *tombstone->mutable_threads();
threads[thread_info.tid] = thread;
+
+ if (guest_unwinder) {
+ if (!thread_info.guest_registers) {
+ async_safe_format_log(ANDROID_LOG_INFO, LOG_TAG,
+ "No guest state registers information for tid %d", thread_info.tid);
+ return;
+ }
+ Thread guest_thread;
+ unwindstack::AndroidUnwinderData guest_data;
+ guest_data.saved_initial_regs = std::make_optional<std::unique_ptr<unwindstack::Regs>>();
+ if (guest_unwinder->Unwind(thread_info.guest_registers.get(), guest_data)) {
+ dump_thread_backtrace(guest_data.frames, guest_thread);
+ } else {
+ async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
+ "Unwind guest state registers failed for tid %d: Error %s",
+ thread_info.tid, guest_data.GetErrorString().c_str());
+ }
+ dump_registers(guest_unwinder, *guest_data.saved_initial_regs, guest_thread, memory_dump);
+ auto& guest_threads = *tombstone->mutable_guest_threads();
+ guest_threads[thread_info.tid] = guest_thread;
+ }
}
static void dump_mappings(Tombstone* tombstone, unwindstack::Maps* maps,
@@ -686,10 +708,17 @@ static void dump_tags_around_fault_addr(Signal* signal, const Tombstone& tombsto
void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::AndroidUnwinder* unwinder,
const std::map<pid_t, ThreadInfo>& threads, pid_t target_tid,
- const ProcessInfo& process_info, const OpenFilesList* open_files) {
+ const ProcessInfo& process_info, const OpenFilesList* open_files,
+ const Architecture* guest_arch,
+ unwindstack::AndroidUnwinder* guest_unwinder) {
Tombstone result;
result.set_arch(get_arch());
+ if (guest_arch != nullptr) {
+ result.set_guest_arch(*guest_arch);
+ } else {
+ result.set_guest_arch(Architecture::NONE);
+ }
result.set_build_fingerprint(android::base::GetProperty("ro.build.fingerprint", "unknown"));
result.set_revision(android::base::GetProperty("ro.revision", "unknown"));
result.set_timestamp(get_timestamp());
@@ -714,6 +743,9 @@ void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::AndroidUnwinder*
error.c_str());
}
+ result.set_page_size(getpagesize());
+ result.set_has_been_16kb_mode(android::base::GetBoolProperty("ro.misctrl.16kb_before", false));
+
auto cmd_line = result.mutable_command_line();
for (const auto& arg : target_thread.command_line) {
*cmd_line->Add() = arg;
@@ -747,11 +779,11 @@ void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::AndroidUnwinder*
dump_abort_message(&result, unwinder->GetProcessMemory(), process_info);
dump_crash_details(&result, unwinder->GetProcessMemory(), process_info);
// Dump the target thread, but save the memory around the registers.
- dump_thread(&result, unwinder, target_thread, /* memory_dump */ true);
+ dump_thread(&result, unwinder, target_thread, /* memory_dump */ true, guest_unwinder);
for (const auto& [tid, thread_info] : threads) {
if (tid != target_tid) {
- dump_thread(&result, unwinder, thread_info);
+ dump_thread(&result, unwinder, thread_info, /* memory_dump */ false, guest_unwinder);
}
}
diff --git a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
index cefa2d62e..19007194e 100644
--- a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
@@ -79,8 +79,8 @@ static std::string describe_pac_enabled_keys(long value) {
return describe_end(value, desc);
}
-static const char* abi_string(const Tombstone& tombstone) {
- switch (tombstone.arch()) {
+static const char* abi_string(const Architecture& arch) {
+ switch (arch) {
case Architecture::ARM32:
return "arm";
case Architecture::ARM64:
@@ -578,14 +578,38 @@ void print_logs(CallbackType callback, const Tombstone& tombstone, int tail) {
}
}
+static void print_guest_thread(CallbackType callback, const Tombstone& tombstone,
+ const Thread& guest_thread, pid_t tid, bool should_log) {
+ CBS("--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---");
+ CBS("Guest thread information for tid: %d", tid);
+ print_thread_registers(callback, tombstone, guest_thread, should_log);
+
+ CBS("");
+ CB(true, "%d total frames", guest_thread.current_backtrace().size());
+ CB(true, "backtrace:");
+ print_backtrace(callback, tombstone, guest_thread.current_backtrace(), should_log);
+
+ print_thread_memory_dump(callback, tombstone, guest_thread);
+}
+
bool tombstone_proto_to_text(const Tombstone& tombstone, CallbackType callback) {
CBL("*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***");
CBL("Build fingerprint: '%s'", tombstone.build_fingerprint().c_str());
CBL("Revision: '%s'", tombstone.revision().c_str());
- CBL("ABI: '%s'", abi_string(tombstone));
+ CBL("ABI: '%s'", abi_string(tombstone.arch()));
+ if (tombstone.guest_arch() != Architecture::NONE) {
+ CBL("Guest architecture: '%s'", abi_string(tombstone.guest_arch()));
+ }
CBL("Timestamp: %s", tombstone.timestamp().c_str());
CBL("Process uptime: %ds", tombstone.process_uptime());
+ // only print this info if the page size is not 4k or has been in 16k mode
+ if (tombstone.page_size() != 4096) {
+ CBL("Page size: %d bytes", tombstone.page_size());
+ } else if (tombstone.has_been_16kb_mode()) {
+ CBL("Has been in 16kb mode: yes");
+ }
+
// Process header
const auto& threads = tombstone.threads();
auto main_thread_it = threads.find(tombstone.tid());
@@ -600,6 +624,12 @@ bool tombstone_proto_to_text(const Tombstone& tombstone, CallbackType callback)
print_logs(callback, tombstone, 50);
+ const auto& guest_threads = tombstone.guest_threads();
+ auto main_guest_thread_it = guest_threads.find(tombstone.tid());
+ if (main_guest_thread_it != threads.end()) {
+ print_guest_thread(callback, tombstone, main_guest_thread_it->second, tombstone.tid(), true);
+ }
+
// protobuf's map is unordered, so sort the keys first.
std::set<int> thread_ids;
for (const auto& [tid, _] : threads) {
@@ -611,6 +641,10 @@ bool tombstone_proto_to_text(const Tombstone& tombstone, CallbackType callback)
for (const auto& tid : thread_ids) {
CBS("--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---");
print_thread(callback, tombstone, threads.find(tid)->second);
+ auto guest_thread_it = guest_threads.find(tid);
+ if (guest_thread_it != guest_threads.end()) {
+ print_guest_thread(callback, tombstone, guest_thread_it->second, tid, false);
+ }
}
if (tombstone.open_fds().size() > 0) {
diff --git a/debuggerd/proto/tombstone.proto b/debuggerd/proto/tombstone.proto
index 214cbfb46..6f9cd9612 100644
--- a/debuggerd/proto/tombstone.proto
+++ b/debuggerd/proto/tombstone.proto
@@ -22,6 +22,7 @@ message CrashDetail {
message Tombstone {
Architecture arch = 1;
+ Architecture guest_arch = 24;
string build_fingerprint = 2;
string revision = 3;
string timestamp = 4;
@@ -42,11 +43,15 @@ message Tombstone {
repeated Cause causes = 15;
map<uint32, Thread> threads = 16;
+ map<uint32, Thread> guest_threads = 25;
repeated MemoryMapping memory_mappings = 17;
repeated LogBuffer log_buffers = 18;
repeated FD open_fds = 19;
- reserved 22 to 999;
+ uint32 page_size = 22;
+ bool has_been_16kb_mode = 23;
+
+ reserved 26 to 999;
}
enum Architecture {
@@ -55,8 +60,9 @@ enum Architecture {
X86 = 2;
X86_64 = 3;
RISCV64 = 4;
+ NONE = 5;
- reserved 5 to 999;
+ reserved 6 to 999;
}
message Signal {
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 8c0c1efe3..835a3e7f6 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -40,6 +40,7 @@
#include <functional>
#include <map>
#include <memory>
+#include <numeric>
#include <string>
#include <string_view>
#include <thread>
@@ -1553,7 +1554,9 @@ MountAllResult fs_mgr_mount_all(Fstab* fstab, int mount_mode) {
fs_mgr_set_blk_ro(attempted_entry.blk_device, false);
if (!call_vdc({"cryptfs", "encryptFstab", attempted_entry.blk_device,
attempted_entry.mount_point, wiped ? "true" : "false",
- attempted_entry.fs_type, attempted_entry.zoned_device},
+ attempted_entry.fs_type,
+ attempted_entry.fs_mgr_flags.is_zoned ? "true" : "false",
+ android::base::Join(attempted_entry.user_devices, ' ')},
nullptr)) {
LERROR << "Encryption failed";
set_type_property(encryptable);
@@ -1596,7 +1599,9 @@ MountAllResult fs_mgr_mount_all(Fstab* fstab, int mount_mode) {
if (!call_vdc({"cryptfs", "encryptFstab", current_entry.blk_device,
current_entry.mount_point, "true" /* shouldFormat */,
- current_entry.fs_type, current_entry.zoned_device},
+ current_entry.fs_type,
+ current_entry.fs_mgr_flags.is_zoned ? "true" : "false",
+ android::base::Join(current_entry.user_devices, ' ')},
nullptr)) {
LERROR << "Encryption failed";
} else {
@@ -1621,7 +1626,9 @@ MountAllResult fs_mgr_mount_all(Fstab* fstab, int mount_mode) {
if (mount_errno != EBUSY && mount_errno != EACCES &&
should_use_metadata_encryption(attempted_entry)) {
if (!call_vdc({"cryptfs", "mountFstab", attempted_entry.blk_device,
- attempted_entry.mount_point, attempted_entry.zoned_device},
+ attempted_entry.mount_point,
+ current_entry.fs_mgr_flags.is_zoned ? "true" : "false",
+ android::base::Join(current_entry.user_devices, ' ')},
nullptr)) {
++error_count;
} else if (current_entry.mount_point == "/data") {
diff --git a/fs_mgr/fs_mgr_format.cpp b/fs_mgr/fs_mgr_format.cpp
index 8e7615010..0dde1d374 100644
--- a/fs_mgr/fs_mgr_format.cpp
+++ b/fs_mgr/fs_mgr_format.cpp
@@ -125,7 +125,8 @@ static int format_ext4(const std::string& fs_blkdev, const std::string& fs_mnt_p
}
static int format_f2fs(const std::string& fs_blkdev, uint64_t dev_sz, bool needs_projid,
- bool needs_casefold, bool fs_compress, const std::string& zoned_device) {
+ bool needs_casefold, bool fs_compress, bool is_zoned,
+ const std::vector<std::string>& user_devices) {
if (!dev_sz) {
int rc = get_dev_sz(fs_blkdev, &dev_sz);
if (rc) {
@@ -159,16 +160,21 @@ static int format_f2fs(const std::string& fs_blkdev, uint64_t dev_sz, bool needs
args.push_back(block_size.c_str());
args.push_back("-b");
args.push_back(block_size.c_str());
- if (!zoned_device.empty()) {
- args.push_back("-c");
- args.push_back(zoned_device.c_str());
+
+ if (is_zoned) {
args.push_back("-m");
+ }
+ for (auto& device : user_devices) {
+ args.push_back("-c");
+ args.push_back(device.c_str());
+ }
+
+ if (user_devices.empty()) {
args.push_back(fs_blkdev.c_str());
+ args.push_back(size_str.c_str());
} else {
args.push_back(fs_blkdev.c_str());
- args.push_back(size_str.c_str());
}
-
return logwrap_fork_execvp(args.size(), args.data(), nullptr, false, LOG_KLOG, false, nullptr);
}
@@ -184,7 +190,8 @@ int fs_mgr_do_format(const FstabEntry& entry) {
if (entry.fs_type == "f2fs") {
return format_f2fs(entry.blk_device, entry.length, needs_projid, needs_casefold,
- entry.fs_mgr_flags.fs_compress, entry.zoned_device);
+ entry.fs_mgr_flags.fs_compress, entry.fs_mgr_flags.is_zoned,
+ entry.user_devices);
} else if (entry.fs_type == "ext4") {
return format_ext4(entry.blk_device, entry.mount_point, needs_projid,
entry.fs_mgr_flags.ext_meta_csum);
diff --git a/fs_mgr/libfstab/fstab.cpp b/fs_mgr/libfstab/fstab.cpp
index 6273ee2e8..f00e0dc26 100644
--- a/fs_mgr/libfstab/fstab.cpp
+++ b/fs_mgr/libfstab/fstab.cpp
@@ -147,6 +147,29 @@ void ParseMountFlags(const std::string& flags, FstabEntry* entry) {
entry->fs_options = std::move(fs_options);
}
+void ParseUserDevices(const std::string& arg, FstabEntry* entry) {
+ auto param = Split(arg, ":");
+ if (param.size() != 2) {
+ LWARNING << "Warning: device= malformed: " << arg;
+ return;
+ }
+
+ if (access(param[1].c_str(), F_OK) != 0) {
+ LWARNING << "Warning: device does not exist : " << param[1];
+ return;
+ }
+
+ if (param[0] == "zoned") {
+ // atgc in f2fs does not support a zoned device
+ auto options = Split(entry->fs_options, ",");
+ options.erase(std::remove(options.begin(), options.end(), "atgc"), options.end());
+ entry->fs_options = android::base::Join(options, ",");
+ LINFO << "Removed ATGC in fs_options as " << entry->fs_options << " for zoned device";
+ entry->fs_mgr_flags.is_zoned = true;
+ }
+ entry->user_devices.push_back(param[1]);
+}
+
bool ParseFsMgrFlags(const std::string& flags, FstabEntry* entry) {
for (const auto& flag : Split(flags, ",")) {
if (flag.empty() || flag == "defaults") continue;
@@ -311,17 +334,8 @@ bool ParseFsMgrFlags(const std::string& flags, FstabEntry* entry) {
if (!ParseByteCount(arg, &entry->zram_backingdev_size)) {
LWARNING << "Warning: zram_backingdev_size= flag malformed: " << arg;
}
- } else if (flag == "zoned_device") {
- if (access("/dev/block/by-name/zoned_device", F_OK) == 0) {
- entry->zoned_device = "/dev/block/by-name/zoned_device";
-
- // atgc in f2fs does not support a zoned device
- auto options = Split(entry->fs_options, ",");
- options.erase(std::remove(options.begin(), options.end(), "atgc"), options.end());
- entry->fs_options = android::base::Join(options, ",");
- LINFO << "Removed ATGC in fs_options as " << entry->fs_options
- << " for zoned device=" << entry->zoned_device;
- }
+ } else if (StartsWith(flag, "device=")) {
+ ParseUserDevices(arg, entry);
} else {
LWARNING << "Warning: unknown flag: " << flag;
}
diff --git a/fs_mgr/libfstab/include/fstab/fstab.h b/fs_mgr/libfstab/include/fstab/fstab.h
index dea723831..1696daff0 100644
--- a/fs_mgr/libfstab/include/fstab/fstab.h
+++ b/fs_mgr/libfstab/include/fstab/fstab.h
@@ -32,7 +32,7 @@ namespace fs_mgr {
struct FstabEntry {
std::string blk_device;
- std::string zoned_device;
+ std::vector<std::string> user_devices;
std::string logical_partition_name;
std::string mount_point;
std::string fs_type;
@@ -85,6 +85,7 @@ struct FstabEntry {
bool ext_meta_csum : 1;
bool fs_compress : 1;
bool overlayfs_remove_missing_lowerdir : 1;
+ bool is_zoned : 1;
} fs_mgr_flags = {};
bool is_encryptable() const { return fs_mgr_flags.crypt; }
diff --git a/fs_mgr/liblp/fuzzer/Android.bp b/fs_mgr/liblp/fuzzer/Android.bp
index a9e3509af..46bd03197 100644
--- a/fs_mgr/liblp/fuzzer/Android.bp
+++ b/fs_mgr/liblp/fuzzer/Android.bp
@@ -15,6 +15,10 @@
*
*/
+package {
+ default_team: "trendy_team_android_kernel",
+}
+
cc_defaults {
name: "liblp_fuzz_defaults",
header_libs: [
@@ -33,7 +37,7 @@ cc_defaults {
],
fuzz_config: {
cc: [
- "android-media-fuzzing-reports@google.com",
+ "android-systems-storage@google.com",
],
componentid: 59148,
hotlists: ["4593311"],
@@ -41,8 +45,8 @@ cc_defaults {
vector: "local_no_privileges_required",
service_privilege: "privileged",
users: "multi_user",
- fuzzed_code_usage: "shipped"
- }
+ fuzzed_code_usage: "shipped",
+ },
}
cc_fuzz {
@@ -196,6 +200,6 @@ cc_fuzz {
":test_vendor_boot_v4_with_frag",
],
cflags: [
- "-Wno-unused-parameter",
- ],
+ "-Wno-unused-parameter",
+ ],
}
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
index 95398e4b9..1117ec965 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
@@ -731,7 +731,8 @@ bool CowWriterV3::WriteOperation(std::span<const CowOperationV3> ops,
i += chunk;
}
if (total_written != total_data_size) {
- PLOG(ERROR) << "write failed for data of size: " << data.size()
+ PLOG(ERROR) << "write failed for data vector of size: " << data.size()
+ << " and total data length: " << total_data_size
<< " at offset: " << next_data_pos_ << " " << errno
<< ", only wrote: " << total_written;
return false;
diff --git a/init/Android.bp b/init/Android.bp
index dd1f9aa3d..6160a713d 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -96,7 +96,6 @@ soong_config_module_type {
config_namespace: "ANDROID",
bool_variables: [
"PRODUCT_INSTALL_DEBUG_POLICY_TO_SYSTEM_EXT",
- "release_write_appcompat_override_system_properties",
],
properties: [
"cflags",
@@ -160,9 +159,6 @@ libinit_cc_defaults {
"-DINSTALL_DEBUG_POLICY_TO_SYSTEM_EXT=1",
],
},
- release_write_appcompat_override_system_properties: {
- cflags: ["-DWRITE_APPCOMPAT_OVERRIDE_SYSTEM_PROPERTIES"],
- }
},
static_libs: [
"libavb",
diff --git a/init/property_service.cpp b/init/property_service.cpp
index d02ca1e49..cd5933d23 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -974,6 +974,17 @@ static std::string ConstructBuildFingerprint(bool legacy) {
std::string build_fingerprint = GetProperty("ro.product.brand", UNKNOWN);
build_fingerprint += '/';
build_fingerprint += GetProperty("ro.product.name", UNKNOWN);
+
+ // should be set in /product/etc/build.prop
+ // when we have a dev option device, and we've switched the kernel to 16kb mode
+ // we use the same system image, but we've switched out the kernel, so make it
+ // visible at a high level
+ bool has16KbDevOption =
+ android::base::GetBoolProperty("ro.product.build.16k_page.enabled", false);
+ if (has16KbDevOption && getpagesize() == 16384) {
+ build_fingerprint += "_16kb";
+ }
+
build_fingerprint += '/';
build_fingerprint += GetProperty("ro.product.device", UNKNOWN);
build_fingerprint += ':';
@@ -1312,14 +1323,12 @@ void CreateSerializedPropertyInfo() {
}
selinux_android_restorecon(PROP_TREE_FILE, 0);
-#ifdef WRITE_APPCOMPAT_OVERRIDE_SYSTEM_PROPERTIES
mkdir(APPCOMPAT_OVERRIDE_PROP_FOLDERNAME, S_IRWXU | S_IXGRP | S_IXOTH);
if (!WriteStringToFile(serialized_contexts, APPCOMPAT_OVERRIDE_PROP_TREE_FILE, 0444, 0, 0,
false)) {
PLOG(ERROR) << "Unable to write appcompat override property infos to file";
}
selinux_android_restorecon(APPCOMPAT_OVERRIDE_PROP_TREE_FILE, 0);
-#endif
}
static void ExportKernelBootProps() {
diff --git a/init/test_upgrade_mte/AndroidTest.xml b/init/test_upgrade_mte/AndroidTest.xml
index b89cde8df..e08afc087 100644
--- a/init/test_upgrade_mte/AndroidTest.xml
+++ b/init/test_upgrade_mte/AndroidTest.xml
@@ -20,11 +20,13 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="remount-system" value="true" />
- <option name="push" value="mte_upgrade_test.rc->/system/etc/init/mte_upgrade_test.rc" />
- <option name="push" value="mte_upgrade_test_helper->/system/bin/mte_upgrade_test_helper" />
- <option name="push" value="mte_upgrade_test_helper->/data/local/tmp/app_process64" />
+
+ <option name="push-file" key="mte_upgrade_test.rc" value="/system/etc/init/mte_upgrade_test.rc" />
+ <option name="push-file" key="mte_upgrade_test_helper" value="/system/bin/mte_upgrade_test_helper" />
+ <option name="push-file" key="mte_upgrade_test_helper" value="/data/local/tmp/app_process64" />
+ <option name="post-push" value="chmod 644 /system/etc/init/mte_upgrade_test.rc" />
</target_preparer>
<test class="com.android.tradefed.testtype.HostTest" >
<option name="jar" value="mte_upgrade_test.jar" />
</test>
-</configuration> \ No newline at end of file
+</configuration>
diff --git a/init/test_upgrade_mte/OWNERS b/init/test_upgrade_mte/OWNERS
new file mode 100644
index 000000000..79625dfb1
--- /dev/null
+++ b/init/test_upgrade_mte/OWNERS
@@ -0,0 +1,5 @@
+fmayer@google.com
+
+eugenis@google.com
+mitchp@google.com
+pcc@google.com
diff --git a/init/test_upgrade_mte/mte_upgrade_test_helper.cpp b/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
index 6728cc6d0..c4b175adc 100644
--- a/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
+++ b/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
@@ -22,6 +22,7 @@
#include <sys/prctl.h>
#include <time.h>
#include <unistd.h>
+
#include <memory>
int MaybeDowngrade() {
@@ -65,7 +66,5 @@ int main(int argc, char** argv) {
// This binary gets run by src/com/android/tests/init/MteUpgradeTest.java, which
// asserts that it crashes as expected.
f[17] = 'x';
- char buf[1];
- read(1, buf, 1);
return 0;
}
diff --git a/init/util.cpp b/init/util.cpp
index e5efc7da6..375e905d5 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -570,6 +570,8 @@ Result<std::pair<int, std::vector<std::string>>> ParseRestorecon(
{"--recursive", SELINUX_ANDROID_RESTORECON_RECURSE},
{"--skip-ce", SELINUX_ANDROID_RESTORECON_SKIPCE},
{"--cross-filesystems", SELINUX_ANDROID_RESTORECON_CROSS_FILESYSTEMS},
+ {"--force", SELINUX_ANDROID_RESTORECON_FORCE},
+ {"--data-data", SELINUX_ANDROID_RESTORECON_DATADATA},
{0, 0}};
int flag = 0;
diff --git a/janitors/OWNERS b/janitors/OWNERS
index a28737ebc..c25d9e465 100644
--- a/janitors/OWNERS
+++ b/janitors/OWNERS
@@ -3,4 +3,5 @@ ccross@google.com
cferris@google.com
dwillemsen@google.com
enh@google.com
+maco@google.com
sadafebrahimi@google.com
diff --git a/libstats/socket_lazy/Android.bp b/libstats/socket_lazy/Android.bp
index b2cd7b26b..241e87af3 100644
--- a/libstats/socket_lazy/Android.bp
+++ b/libstats/socket_lazy/Android.bp
@@ -7,6 +7,12 @@ package {
cc_library_static {
name: "libstatssocket_lazy",
+ local_include_dirs: [
+ "include",
+ ],
+ export_include_dirs: [
+ "include",
+ ],
header_libs: [
"libstatssocket_headers",
],
@@ -28,7 +34,10 @@ cc_test {
"-Wall",
"-Werror",
],
- test_suites: ["device-tests", "mts-statsd"],
+ test_suites: [
+ "device-tests",
+ "mts-statsd",
+ ],
test_config: "libstatssocket_lazy_test.xml",
// TODO(b/153588990): Remove when the build system properly separates.
// 32bit and 64bit architectures.
diff --git a/libstats/socket_lazy/include/statssocket_lazy.h b/libstats/socket_lazy/include/statssocket_lazy.h
new file mode 100644
index 000000000..7dda0bac4
--- /dev/null
+++ b/libstats/socket_lazy/include/statssocket_lazy.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+namespace android::statssocket::lazy {
+
+// See if libstatssocket.so is available. Early processes relying on _lazy might not have access
+// to libstatssocket.so when they start before the StatsD APEX is available.
+bool IsAvailable();
+
+} // namespace android::statssocket::lazy
diff --git a/libstats/socket_lazy/libstatssocket_lazy.cpp b/libstats/socket_lazy/libstatssocket_lazy.cpp
index fe94ef2d8..d907c7e27 100644
--- a/libstats/socket_lazy/libstatssocket_lazy.cpp
+++ b/libstats/socket_lazy/libstatssocket_lazy.cpp
@@ -23,8 +23,10 @@
#include "log/log.h"
-#include "stats_event.h"
-#include "stats_socket.h"
+#include <stats_event.h>
+#include <stats_socket.h>
+
+#include "statssocket_lazy.h"
// This file provides a lazy interface to libstatssocket.so to address early boot dependencies.
// Specifically bootanimation, surfaceflinger, and lmkd run before the statsd APEX is loaded and
@@ -77,6 +79,13 @@ static void* LoadLibstatssocket(int dlopen_flags) {
return dlopen("libstatssocket.so", dlopen_flags);
}
+namespace android::statssocket::lazy {
+bool IsAvailable() {
+ static const void* handle = LoadLibstatssocket(RTLD_NOW);
+ return handle != nullptr;
+}
+} // namespace android::statssocket::lazy
+
//
// Initialization and symbol binding.
diff --git a/libstats/socket_lazy/tests/libstatssocket_lazy_test.cpp b/libstats/socket_lazy/tests/libstatssocket_lazy_test.cpp
index 3de6cd762..733f1e41c 100644
--- a/libstats/socket_lazy/tests/libstatssocket_lazy_test.cpp
+++ b/libstats/socket_lazy/tests/libstatssocket_lazy_test.cpp
@@ -21,6 +21,8 @@
#include "stats_event.h"
#include "stats_socket.h"
+#include "statssocket_lazy.h"
+
// The tests here are just for the case when libstatssocket.so cannot be loaded by
// libstatssocket_lazy.
class LibstatssocketLazyTest : public ::testing::Test {
@@ -57,3 +59,7 @@ TEST_F(LibstatssocketLazyTest, NoLibstatssocketForStatsEvent) {
TEST_F(LibstatssocketLazyTest, NoLibstatssocketForStatsSocket) {
EXPECT_DEATH(AStatsSocket_close(), kLoadFailed);
}
+
+TEST_F(LibstatssocketLazyTest, IsAvailableFalse) {
+ EXPECT_FALSE(android::statssocket::lazy::IsAvailable());
+}
diff --git a/libutils/binder/String16_test.cpp b/libutils/binder/String16_test.cpp
index 6f4642e8f..83cc5990b 100644
--- a/libutils/binder/String16_test.cpp
+++ b/libutils/binder/String16_test.cpp
@@ -16,6 +16,8 @@
#include <utils/String16.h>
#include <utils/String8.h>
+#include <compare>
+#include <utility>
#include <gtest/gtest.h>
@@ -257,3 +259,45 @@ TEST(String16Test, insert) {
EXPECT_EQ(NO_MEMORY, s.insert(3, u"", SIZE_MAX));
EXPECT_STR16EQ(u"foo!bar", s.c_str());
}
+
+TEST(String16Test, comparisons) {
+ const char16_t* cstr1 = u"abc";
+ const char16_t* cstr2 = u"def";
+
+ // str1 and str1b will point to different blocks of memory but with equal contents.
+ String16 str1(cstr1);
+ String16 str1b(cstr1);
+ String16 str2(cstr2);
+
+ EXPECT_TRUE((str1 <=> str1b) == 0);
+ EXPECT_FALSE(str1 != str1b);
+ EXPECT_FALSE(str1 < str1b);
+ EXPECT_TRUE(str1 <= str1b);
+ EXPECT_TRUE(str1 == str1b);
+ EXPECT_TRUE(str1 >= str1b);
+ EXPECT_FALSE(str1 > str1b);
+
+ EXPECT_TRUE((str1 <=> str2) < 0);
+ EXPECT_TRUE((str2 <=> str1) > 0);
+ EXPECT_TRUE(str1 != str2);
+ EXPECT_TRUE(str1 < str2);
+ EXPECT_TRUE(str1 <= str2);
+ EXPECT_FALSE(str1 == str2);
+ EXPECT_FALSE(str1 >= str2);
+ EXPECT_FALSE(str1 > str2);
+
+ // Verify that pre-C++20 comparison operators work with a std::pair of a String8, which only
+ // provides <=> in C++20 and up. See b/339775405.
+
+ std::pair<String16, int> pair1(str1, 13);
+ std::pair<String16, int> pair1b(str1b, 13);
+ std::pair<String16, int> pair2(str2, 13);
+
+ EXPECT_TRUE(pair1 == pair1b);
+ EXPECT_FALSE(pair1 < pair1b);
+ EXPECT_FALSE(pair1 > pair1b);
+
+ EXPECT_TRUE(pair1 != pair2);
+ EXPECT_TRUE(pair1 < pair2);
+ EXPECT_FALSE(pair1 > pair2);
+}
diff --git a/libutils/binder/String8_test.cpp b/libutils/binder/String8_test.cpp
index 6f7882a38..fc3c32941 100644
--- a/libutils/binder/String8_test.cpp
+++ b/libutils/binder/String8_test.cpp
@@ -17,8 +17,10 @@
#define LOG_TAG "String8_test"
#include <log/log.h>
-#include <utils/String8.h>
#include <utils/String16.h>
+#include <utils/String8.h>
+#include <compare>
+#include <utility>
#include <gtest/gtest.h>
@@ -132,3 +134,45 @@ TEST_F(String8Test, removeAll) {
EXPECT_TRUE(s.removeAll("o"));
EXPECT_STREQ("Hell, wrld!", s.c_str());
}
+
+TEST_F(String8Test, comparisons) {
+ const char* cstr1 = "abc";
+ const char* cstr2 = "def";
+
+ // str1 and str1b will point to different blocks of memory but with equal contents.
+ String8 str1(cstr1);
+ String8 str1b(cstr1);
+ String8 str2(cstr2);
+
+ EXPECT_TRUE((str1 <=> str1b) == 0);
+ EXPECT_FALSE(str1 != str1b);
+ EXPECT_FALSE(str1 < str1b);
+ EXPECT_TRUE(str1 <= str1b);
+ EXPECT_TRUE(str1 == str1b);
+ EXPECT_TRUE(str1 >= str1b);
+ EXPECT_FALSE(str1 > str1b);
+
+ EXPECT_TRUE((str1 <=> str2) < 0);
+ EXPECT_TRUE((str2 <=> str1) > 0);
+ EXPECT_TRUE(str1 != str2);
+ EXPECT_TRUE(str1 < str2);
+ EXPECT_TRUE(str1 <= str2);
+ EXPECT_FALSE(str1 == str2);
+ EXPECT_FALSE(str1 >= str2);
+ EXPECT_FALSE(str1 > str2);
+
+ // Verify that pre-C++20 comparison operators work with a std::pair of a String8, which only
+ // provides <=> in C++20 and up. See b/339775405.
+
+ std::pair<String8, int> pair1(str1, 13);
+ std::pair<String8, int> pair1b(str1b, 13);
+ std::pair<String8, int> pair2(str2, 13);
+
+ EXPECT_TRUE(pair1 == pair1b);
+ EXPECT_FALSE(pair1 < pair1b);
+ EXPECT_FALSE(pair1 > pair1b);
+
+ EXPECT_TRUE(pair1 != pair2);
+ EXPECT_TRUE(pair1 < pair2);
+ EXPECT_FALSE(pair1 > pair2);
+}
diff --git a/libutils/binder/include/utils/String16.h b/libutils/binder/include/utils/String16.h
index c7135766b..867dbac34 100644
--- a/libutils/binder/include/utils/String16.h
+++ b/libutils/binder/include/utils/String16.h
@@ -29,6 +29,10 @@
#define HAS_STRING_VIEW
#endif
+#if __cplusplus >= 202002L
+#include <compare>
+#endif
+
// ---------------------------------------------------------------------------
namespace android {
@@ -105,6 +109,9 @@ public:
inline bool operator!=(const String16& other) const;
inline bool operator>=(const String16& other) const;
inline bool operator>(const String16& other) const;
+#if __cplusplus >= 202002L
+ inline std::strong_ordering operator<=>(const String16& other) const;
+#endif
inline bool operator<(const char16_t* other) const;
inline bool operator<=(const char16_t* other) const;
@@ -112,6 +119,9 @@ public:
inline bool operator!=(const char16_t* other) const;
inline bool operator>=(const char16_t* other) const;
inline bool operator>(const char16_t* other) const;
+#if __cplusplus >= 202002L
+ inline std::strong_ordering operator<=>(const char16_t* other) const;
+#endif
inline operator const char16_t*() const;
@@ -334,6 +344,19 @@ inline bool String16::operator>(const String16& other) const
return strzcmp16(mString, size(), other.mString, other.size()) > 0;
}
+#if __cplusplus >= 202002L
+inline std::strong_ordering String16::operator<=>(const String16& other) const {
+ int result = strzcmp16(mString, size(), other.mString, other.size());
+ if (result == 0) {
+ return std::strong_ordering::equal;
+ } else if (result < 0) {
+ return std::strong_ordering::less;
+ } else {
+ return std::strong_ordering::greater;
+ }
+}
+#endif
+
inline bool String16::operator<(const char16_t* other) const
{
return strcmp16(mString, other) < 0;
@@ -364,6 +387,19 @@ inline bool String16::operator>(const char16_t* other) const
return strcmp16(mString, other) > 0;
}
+#if __cplusplus >= 202002L
+inline std::strong_ordering String16::operator<=>(const char16_t* other) const {
+ int result = strcmp16(mString, other);
+ if (result == 0) {
+ return std::strong_ordering::equal;
+ } else if (result < 0) {
+ return std::strong_ordering::less;
+ } else {
+ return std::strong_ordering::greater;
+ }
+}
+#endif
+
inline String16::operator const char16_t*() const
{
return mString;
diff --git a/libutils/binder/include/utils/String8.h b/libutils/binder/include/utils/String8.h
index 6d250723b..e0d7588f6 100644
--- a/libutils/binder/include/utils/String8.h
+++ b/libutils/binder/include/utils/String8.h
@@ -36,6 +36,10 @@
#define HAS_STRING_VIEW
#endif
+#if __cplusplus >= 202002L
+#include <compare>
+#endif
+
// ---------------------------------------------------------------------------
namespace android {
@@ -106,6 +110,9 @@ public:
inline bool operator!=(const String8& other) const;
inline bool operator>=(const String8& other) const;
inline bool operator>(const String8& other) const;
+#if __cplusplus >= 202002L
+ inline std::strong_ordering operator<=>(const String8& other) const;
+#endif
inline bool operator<(const char* other) const;
inline bool operator<=(const char* other) const;
@@ -113,6 +120,9 @@ public:
inline bool operator!=(const char* other) const;
inline bool operator>=(const char* other) const;
inline bool operator>(const char* other) const;
+#if __cplusplus >= 202002L
+ inline std::strong_ordering operator<=>(const char* other) const;
+#endif
inline operator const char*() const;
@@ -302,6 +312,19 @@ inline bool String8::operator>(const String8& other) const
return strcmp(mString, other.mString) > 0;
}
+#if __cplusplus >= 202002L
+inline std::strong_ordering String8::operator<=>(const String8& other) const {
+ int result = strcmp(mString, other.mString);
+ if (result == 0) {
+ return std::strong_ordering::equal;
+ } else if (result < 0) {
+ return std::strong_ordering::less;
+ } else {
+ return std::strong_ordering::greater;
+ }
+}
+#endif
+
inline bool String8::operator<(const char* other) const
{
return strcmp(mString, other) < 0;
@@ -332,6 +355,19 @@ inline bool String8::operator>(const char* other) const
return strcmp(mString, other) > 0;
}
+#if __cplusplus >= 202002L
+inline std::strong_ordering String8::operator<=>(const char* other) const {
+ int result = strcmp(mString, other);
+ if (result == 0) {
+ return std::strong_ordering::equal;
+ } else if (result < 0) {
+ return std::strong_ordering::less;
+ } else {
+ return std::strong_ordering::greater;
+ }
+}
+#endif
+
inline String8::operator const char*() const
{
return mString;
diff --git a/mkbootfs/mkbootfs.c b/mkbootfs/mkbootfs.c
index d3922bf1a..84a0a4eee 100644
--- a/mkbootfs/mkbootfs.c
+++ b/mkbootfs/mkbootfs.c
@@ -402,7 +402,7 @@ static const struct option long_options[] = {
static void usage(void)
{
fprintf(stderr,
- "Usage: mkbootfs [-n FILE] [-d DIR|-F FILE] DIR...\n"
+ "Usage: mkbootfs [-n FILE] [-d DIR|-f FILE] DIR...\n"
"\n"
"\t-d, --dirname=DIR: fs-config directory\n"
"\t-f, --file=FILE: Canned configuration file\n"
@@ -410,11 +410,11 @@ static void usage(void)
"\t-n, --nodes=FILE: Dev nodes description file\n"
"\n"
"Dev nodes description:\n"
- "\t[dir|nod] [perms] [uid] [gid] [c|b] [minor] [major]\n"
+ "\t[dir|nod] [perms] [uid] [gid] [c|b] [major] [minor]\n"
"\tExample:\n"
"\t\t# My device nodes\n"
"\t\tdir dev 0755 0 0\n"
- "\t\tnod dev/null 0600 0 0 c 1 5\n"
+ "\t\tnod dev/null 0600 0 0 c 1 3\n"
);
}
@@ -445,11 +445,6 @@ int main(int argc, char *argv[])
int num_dirs = argc - optind;
argv += optind;
- if (num_dirs <= 0) {
- usage();
- errx(1, "no directories to process?!");
- }
-
while(num_dirs-- > 0){
char *x = strchr(*argv, '=');
if(x != 0) {
diff --git a/rootdir/Android.bp b/rootdir/Android.bp
index 06227c318..108c7c2e7 100644
--- a/rootdir/Android.bp
+++ b/rootdir/Android.bp
@@ -113,3 +113,7 @@ prebuilt_etc {
src: "init-debug.rc",
sub_dir: "init",
}
+
+llndk_libraries_txt {
+ name: "llndk.libraries.txt",
+}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index f7f0cc385..e8b737d07 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -640,8 +640,7 @@ on post-fs
mkdir /metadata/aconfig/boot 0775 root system
mkdir /metadata/aconfig_test_missions 0775 root system
- exec_start aconfigd-init
- start aconfigd
+ exec_start aconfigd-platform-init
on late-fs
# Ensure that tracefs has the correct permissions.
@@ -1031,6 +1030,8 @@ on post-fs-data
# Wait for apexd to finish activating APEXes before starting more processes.
wait_for_prop apexd.status activated
perform_apex_config
+ exec_start aconfigd-mainline-init
+ start aconfigd
# Create directories for boot animation.
mkdir /data/misc/bootanim 0755 system system
diff --git a/trusty/utils/coverage-controller/controller.cpp b/trusty/utils/coverage-controller/controller.cpp
index 381a45285..f5d70b16d 100644
--- a/trusty/utils/coverage-controller/controller.cpp
+++ b/trusty/utils/coverage-controller/controller.cpp
@@ -60,6 +60,7 @@ void Controller::run(std::string output_dir) {
filename.insert(0, output_dir);
android::base::Result<void> res = record_list_[index]->SaveFile(filename);
counters[index]++;
+ WRITE_ONCE(control->read_buffer_cnt, counters[index]);
}
if(complete_cnt == counters[index] &&
!(flags & FLAG_RUN)) {
diff --git a/trusty/utils/coverage-controller/controller.h b/trusty/utils/coverage-controller/controller.h
index f7789bfed..841a1aeb1 100644
--- a/trusty/utils/coverage-controller/controller.h
+++ b/trusty/utils/coverage-controller/controller.h
@@ -35,9 +35,9 @@
struct control {
/* Written by controller, read by instrumented TA */
uint64_t cntrl_flags;
+ uint64_t read_buffer_cnt;
/* Written by instrumented TA, read by controller */
- uint64_t oper_flags;
uint64_t write_buffer_start_count;
uint64_t write_buffer_complete_count;
};