Merge "support f2fs casefolding formatting tool"
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 7933629..89bd66a 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -16,16 +16,25 @@
"name": "adb_tls_connection_test"
},
{
+ "name": "CtsFsMgrTestCases"
+ },
+ {
"name": "CtsInitTestCases"
},
{
+ "name": "CtsLiblogTestCases"
+ },
+ {
+ "name": "CtsLogdTestCases"
+ },
+ {
"name": "debuggerd_test"
},
{
- "name": "CtsFsMgrTestCases"
+ "name": "fs_mgr_vendor_overlay_test"
},
{
- "name": "fs_mgr_vendor_overlay_test"
+ "name": "init_kill_services_test"
},
{
"name": "libpackagelistparser_test"
@@ -58,5 +67,10 @@
{
"name": "propertyinfoserializer_tests"
}
+ ],
+ "imports": [
+ {
+ "path": "frameworks/base/tests/StagedInstallTest"
+ }
]
}
diff --git a/adb/Android.bp b/adb/Android.bp
index 2fc205f..87ac54d 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -12,6 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+tidy_errors = [
+ "-*",
+ "bugprone-inaccurate-erase",
+]
+
cc_defaults {
name: "adb_defaults",
@@ -73,6 +78,10 @@
],
},
},
+
+ tidy: true,
+ tidy_checks: tidy_errors,
+ tidy_checks_as_errors: tidy_errors,
}
cc_defaults {
diff --git a/adb/adb_utils.h b/adb/adb_utils.h
index 66cba12..e72d8b6 100644
--- a/adb/adb_utils.h
+++ b/adb/adb_utils.h
@@ -55,7 +55,7 @@
bool set_file_block_mode(borrowed_fd fd, bool block);
-// Given forward/reverse targets, returns true if they look sane. If an error is found, fills
+// Given forward/reverse targets, returns true if they look valid. If an error is found, fills
// |error| and returns false.
// Currently this only checks "tcp:" targets. Additional checking could be added for other targets
// if needed.
diff --git a/adb/client/incremental.cpp b/adb/client/incremental.cpp
index 3033059..60735f8 100644
--- a/adb/client/incremental.cpp
+++ b/adb/client/incremental.cpp
@@ -55,9 +55,10 @@
return {};
}
- std::vector<char> invalid_signature;
+ auto [signature, tree_size] = read_id_sig_headers(fd);
- if (st.st_size > kMaxSignatureSize) {
+ std::vector<char> invalid_signature;
+ if (signature.size() > kMaxSignatureSize) {
if (!silent) {
fprintf(stderr, "Signature is too long. Max allowed is %d. Abort.\n",
kMaxSignatureSize);
@@ -65,7 +66,6 @@
return {std::move(fd), std::move(invalid_signature)};
}
- auto [signature, tree_size] = read_id_sig_headers(fd);
if (auto expected = verity_tree_size_for_file(file_size); tree_size != expected) {
if (!silent) {
fprintf(stderr,
diff --git a/adb/fdevent/fdevent_test.h b/adb/fdevent/fdevent_test.h
index ecda4da..fcbf181 100644
--- a/adb/fdevent/fdevent_test.h
+++ b/adb/fdevent/fdevent_test.h
@@ -65,7 +65,7 @@
ASSERT_EQ(0u, fdevent_installed_count());
}
- // Register a dummy socket used to wake up the fdevent loop to tell it to die.
+ // Register a placeholder socket used to wake up the fdevent loop to tell it to die.
void PrepareThread() {
int dummy_fds[2];
if (adb_socketpair(dummy_fds) != 0) {
@@ -84,7 +84,7 @@
}
size_t GetAdditionalLocalSocketCount() {
- // dummy socket installed in PrepareThread()
+ // placeholder socket installed in PrepareThread()
return 1;
}
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index 13a4737..33b9524 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -856,7 +856,7 @@
s->peer->shutdown = nullptr;
s->peer->close = local_socket_close_notify;
s->peer->peer = nullptr;
- /* give him our transport and upref it */
+ /* give them our transport and upref it */
s->peer->transport = s->transport;
connect_to_remote(s->peer, std::string_view(s->smart_socket_data).substr(4));
diff --git a/bootstat/boot_reason_test.sh b/bootstat/boot_reason_test.sh
index 2f2919f..7cff7dc 100755
--- a/bootstat/boot_reason_test.sh
+++ b/bootstat/boot_reason_test.sh
@@ -1331,7 +1331,7 @@
shift
fi
- # Check if all conditions for the script are sane
+ # Check if all conditions for the script are valid
if [ -z "${ANDROID_SERIAL}" ]; then
ndev=`(
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 31c2d5d..ad10a1f 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -253,7 +253,6 @@
"libcutils",
"libdebuggerd_client",
"liblog",
- "libminijail",
"libnativehelper",
"libunwindstack",
],
@@ -261,6 +260,7 @@
static_libs: [
"libdebuggerd",
"libgmock",
+ "libminijail",
],
header_libs: [
diff --git a/debuggerd/client/debuggerd_client.cpp b/debuggerd/client/debuggerd_client.cpp
index 5c02738..6bfb5f2 100644
--- a/debuggerd/client/debuggerd_client.cpp
+++ b/debuggerd/client/debuggerd_client.cpp
@@ -70,36 +70,6 @@
tv->tv_usec = static_cast<long>(microseconds.count());
}
-static void get_wchan_header(pid_t pid, std::stringstream& buffer) {
- struct tm now;
- time_t t = time(nullptr);
- localtime_r(&t, &now);
- char timestamp[32];
- strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", &now);
- std::string time_now(timestamp);
-
- std::string path = "/proc/" + std::to_string(pid) + "/cmdline";
-
- char proc_name_buf[1024];
- const char* proc_name = nullptr;
- std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(path.c_str(), "r"), &fclose);
-
- if (fp) {
- proc_name = fgets(proc_name_buf, sizeof(proc_name_buf), fp.get());
- }
-
- if (!proc_name) {
- proc_name = "<unknown>";
- }
-
- buffer << "\n----- Waiting Channels: pid " << pid << " at " << time_now << " -----\n"
- << "Cmd line: " << proc_name << "\n";
-}
-
-static void get_wchan_footer(pid_t pid, std::stringstream& buffer) {
- buffer << "----- end " << std::to_string(pid) << " -----\n";
-}
-
/**
* Returns the wchan data for each thread in the process,
* or empty string if unable to obtain any data.
@@ -125,9 +95,10 @@
}
if (std::string str = data.str(); !str.empty()) {
- get_wchan_header(pid, buffer);
+ buffer << "\n----- Waiting Channels: pid " << pid << " at " << get_timestamp() << " -----\n"
+ << "Cmd line: " << get_process_name(pid) << "\n";
buffer << "\n" << str << "\n";
- get_wchan_footer(pid, buffer);
+ buffer << "----- end " << std::to_string(pid) << " -----\n";
buffer << "\n";
}
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 9d7658e..108787e 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -18,6 +18,7 @@
#include <fcntl.h>
#include <stdlib.h>
#include <sys/capability.h>
+#include <sys/mman.h>
#include <sys/prctl.h>
#include <sys/ptrace.h>
#include <sys/resource.h>
@@ -172,6 +173,8 @@
void StartCrasher(const std::string& crash_type);
void FinishCrasher();
void AssertDeath(int signo);
+
+ static void Trap(void* ptr);
};
CrasherTest::CrasherTest() {
@@ -334,6 +337,48 @@
R"(signal 11 \(SIGSEGV\), code 1 \(SEGV_MAPERR\), fault addr (0x100000000000dead|0xdead))");
}
+// Marked as weak to prevent the compiler from removing the malloc in the caller. In theory, the
+// compiler could still clobber the argument register before trapping, but that's unlikely.
+__attribute__((weak)) void CrasherTest::Trap(void* ptr ATTRIBUTE_UNUSED) {
+ __builtin_trap();
+}
+
+TEST_F(CrasherTest, heap_addr_in_register) {
+#if defined(__i386__)
+ GTEST_SKIP() << "architecture does not pass arguments in registers";
+#endif
+ int intercept_result;
+ unique_fd output_fd;
+ StartProcess([]() {
+ // Crash with a heap pointer in the first argument register.
+ Trap(malloc(1));
+ });
+
+ StartIntercept(&output_fd);
+ FinishCrasher();
+ int status;
+ ASSERT_EQ(crasher_pid, TIMEOUT(30, waitpid(crasher_pid, &status, 0)));
+ ASSERT_TRUE(WIFSIGNALED(status)) << "crasher didn't terminate via a signal";
+ // Don't test the signal number because different architectures use different signals for
+ // __builtin_trap().
+ FinishIntercept(&intercept_result);
+
+ ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+ std::string result;
+ ConsumeFd(std::move(output_fd), &result);
+
+#if defined(__aarch64__)
+ ASSERT_MATCH(result, "memory near x0");
+#elif defined(__arm__)
+ ASSERT_MATCH(result, "memory near r0");
+#elif defined(__x86_64__)
+ ASSERT_MATCH(result, "memory near rdi");
+#else
+ ASSERT_TRUE(false) << "unsupported architecture";
+#endif
+}
+
#if defined(__aarch64__) && defined(ANDROID_EXPERIMENTAL_MTE)
static void SetTagCheckingLevelSync() {
int tagged_addr_ctrl = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
@@ -512,6 +557,55 @@
#endif
}
+#if defined(__aarch64__) && defined(ANDROID_EXPERIMENTAL_MTE)
+static uintptr_t CreateTagMapping() {
+ uintptr_t mapping =
+ reinterpret_cast<uintptr_t>(mmap(nullptr, getpagesize(), PROT_READ | PROT_WRITE | PROT_MTE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
+ if (reinterpret_cast<void*>(mapping) == MAP_FAILED) {
+ return 0;
+ }
+ __asm__ __volatile__(".arch_extension mte; stg %0, [%0]"
+ :
+ : "r"(mapping + (1ULL << 56))
+ : "memory");
+ return mapping;
+}
+#endif
+
+TEST_F(CrasherTest, mte_tag_dump) {
+#if defined(__aarch64__) && defined(ANDROID_EXPERIMENTAL_MTE)
+ if (!mte_supported()) {
+ GTEST_SKIP() << "Requires MTE";
+ }
+
+ int intercept_result;
+ unique_fd output_fd;
+ StartProcess([&]() {
+ SetTagCheckingLevelSync();
+ Trap(reinterpret_cast<void *>(CreateTagMapping()));
+ });
+
+ StartIntercept(&output_fd);
+ FinishCrasher();
+ AssertDeath(SIGTRAP);
+ FinishIntercept(&intercept_result);
+
+ ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+ std::string result;
+ ConsumeFd(std::move(output_fd), &result);
+
+ ASSERT_MATCH(result, R"(memory near x0:
+.*
+.*
+ 01.............0 0000000000000000 0000000000000000 ................
+ 00.............0)");
+#else
+ GTEST_SKIP() << "Requires aarch64 + ANDROID_EXPERIMENTAL_MTE";
+#endif
+}
+
TEST_F(CrasherTest, LD_PRELOAD) {
int intercept_result;
unique_fd output_fd;
diff --git a/debuggerd/libdebuggerd/backtrace.cpp b/debuggerd/libdebuggerd/backtrace.cpp
index c606970..f5a873c 100644
--- a/debuggerd/libdebuggerd/backtrace.cpp
+++ b/debuggerd/libdebuggerd/backtrace.cpp
@@ -27,7 +27,6 @@
#include <string.h>
#include <sys/ptrace.h>
#include <sys/types.h>
-#include <time.h>
#include <unistd.h>
#include <map>
@@ -40,14 +39,10 @@
#include "libdebuggerd/types.h"
#include "libdebuggerd/utility.h"
+#include "util.h"
static void dump_process_header(log_t* log, pid_t pid, const char* process_name) {
- time_t t = time(NULL);
- struct tm tm;
- localtime_r(&t, &tm);
- char timestr[64];
- strftime(timestr, sizeof(timestr), "%F %T", &tm);
- _LOG(log, logtype::BACKTRACE, "\n\n----- pid %d at %s -----\n", pid, timestr);
+ _LOG(log, logtype::BACKTRACE, "\n\n----- pid %d at %s -----\n", pid, get_timestamp().c_str());
if (process_name) {
_LOG(log, logtype::BACKTRACE, "Cmd line: %s\n", process_name);
@@ -106,9 +101,8 @@
log.tfd = output_fd;
log.amfd_data = nullptr;
- char process_name[128];
- read_with_default("/proc/self/cmdline", process_name, sizeof(process_name), "<unknown>");
- dump_process_header(&log, getpid(), process_name);
+ pid_t pid = getpid();
+ dump_process_header(&log, pid, get_process_name(pid).c_str());
}
void dump_backtrace_footer(int output_fd) {
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
index 7bfcf5d..76155b1 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
@@ -83,8 +83,6 @@
void dump_memory(log_t* log, unwindstack::Memory* backtrace, uint64_t addr, const std::string&);
-void read_with_default(const char* path, char* buf, size_t len, const char* default_value);
-
void drop_capabilities();
bool signal_has_sender(const siginfo_t*, pid_t caller_pid);
diff --git a/debuggerd/libdebuggerd/test/dump_memory_test.cpp b/debuggerd/libdebuggerd/test/dump_memory_test.cpp
index be39582..f16f578 100644
--- a/debuggerd/libdebuggerd/test/dump_memory_test.cpp
+++ b/debuggerd/libdebuggerd/test/dump_memory_test.cpp
@@ -30,39 +30,39 @@
const char g_expected_full_dump[] =
"\nmemory near r1:\n"
#if defined(__LP64__)
-" 0000000012345658 0706050403020100 0f0e0d0c0b0a0908 ................\n"
-" 0000000012345668 1716151413121110 1f1e1d1c1b1a1918 ................\n"
-" 0000000012345678 2726252423222120 2f2e2d2c2b2a2928 !\"#$%&'()*+,-./\n"
-" 0000000012345688 3736353433323130 3f3e3d3c3b3a3938 0123456789:;<=>?\n"
-" 0000000012345698 4746454443424140 4f4e4d4c4b4a4948 @ABCDEFGHIJKLMNO\n"
-" 00000000123456a8 5756555453525150 5f5e5d5c5b5a5958 PQRSTUVWXYZ[\\]^_\n"
-" 00000000123456b8 6766656463626160 6f6e6d6c6b6a6968 `abcdefghijklmno\n"
-" 00000000123456c8 7776757473727170 7f7e7d7c7b7a7978 pqrstuvwxyz{|}~.\n"
-" 00000000123456d8 8786858483828180 8f8e8d8c8b8a8988 ................\n"
-" 00000000123456e8 9796959493929190 9f9e9d9c9b9a9998 ................\n"
-" 00000000123456f8 a7a6a5a4a3a2a1a0 afaeadacabaaa9a8 ................\n"
-" 0000000012345708 b7b6b5b4b3b2b1b0 bfbebdbcbbbab9b8 ................\n"
-" 0000000012345718 c7c6c5c4c3c2c1c0 cfcecdcccbcac9c8 ................\n"
-" 0000000012345728 d7d6d5d4d3d2d1d0 dfdedddcdbdad9d8 ................\n"
-" 0000000012345738 e7e6e5e4e3e2e1e0 efeeedecebeae9e8 ................\n"
-" 0000000012345748 f7f6f5f4f3f2f1f0 fffefdfcfbfaf9f8 ................\n";
+" 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";
#else
-" 12345658 03020100 07060504 0b0a0908 0f0e0d0c ................\n"
-" 12345668 13121110 17161514 1b1a1918 1f1e1d1c ................\n"
-" 12345678 23222120 27262524 2b2a2928 2f2e2d2c !\"#$%&'()*+,-./\n"
-" 12345688 33323130 37363534 3b3a3938 3f3e3d3c 0123456789:;<=>?\n"
-" 12345698 43424140 47464544 4b4a4948 4f4e4d4c @ABCDEFGHIJKLMNO\n"
-" 123456a8 53525150 57565554 5b5a5958 5f5e5d5c PQRSTUVWXYZ[\\]^_\n"
-" 123456b8 63626160 67666564 6b6a6968 6f6e6d6c `abcdefghijklmno\n"
-" 123456c8 73727170 77767574 7b7a7978 7f7e7d7c pqrstuvwxyz{|}~.\n"
-" 123456d8 83828180 87868584 8b8a8988 8f8e8d8c ................\n"
-" 123456e8 93929190 97969594 9b9a9998 9f9e9d9c ................\n"
-" 123456f8 a3a2a1a0 a7a6a5a4 abaaa9a8 afaeadac ................\n"
-" 12345708 b3b2b1b0 b7b6b5b4 bbbab9b8 bfbebdbc ................\n"
-" 12345718 c3c2c1c0 c7c6c5c4 cbcac9c8 cfcecdcc ................\n"
-" 12345728 d3d2d1d0 d7d6d5d4 dbdad9d8 dfdedddc ................\n"
-" 12345738 e3e2e1e0 e7e6e5e4 ebeae9e8 efeeedec ................\n"
-" 12345748 f3f2f1f0 f7f6f5f4 fbfaf9f8 fffefdfc ................\n";
+" 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";
#endif
const char g_expected_partial_dump[] = \
@@ -112,7 +112,10 @@
if (last_read_addr_ > 0) {
offset = addr - last_read_addr_;
}
- size_t bytes_available = buffer_.size() - offset;
+ size_t bytes_available = 0;
+ if (offset < buffer_.size()) {
+ bytes_available = buffer_.size() - offset;
+ }
if (partial_read_) {
bytes = std::min(bytes, bytes_partial_read_);
@@ -258,44 +261,7 @@
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 pc:\n"
-#if defined(__LP64__)
-" 00000000a2345658 ---------------- ---------------- ................\n"
-" 00000000a2345668 ---------------- ---------------- ................\n"
-" 00000000a2345678 ---------------- ---------------- ................\n"
-" 00000000a2345688 ---------------- ---------------- ................\n"
-" 00000000a2345698 ---------------- ---------------- ................\n"
-" 00000000a23456a8 ---------------- ---------------- ................\n"
-" 00000000a23456b8 ---------------- ---------------- ................\n"
-" 00000000a23456c8 ---------------- ---------------- ................\n"
-" 00000000a23456d8 ---------------- ---------------- ................\n"
-" 00000000a23456e8 ---------------- ---------------- ................\n"
-" 00000000a23456f8 ---------------- ---------------- ................\n"
-" 00000000a2345708 ---------------- ---------------- ................\n"
-" 00000000a2345718 ---------------- ---------------- ................\n"
-" 00000000a2345728 ---------------- ---------------- ................\n"
-" 00000000a2345738 ---------------- ---------------- ................\n"
-" 00000000a2345748 ---------------- ---------------- ................\n";
-#else
-" a2345658 -------- -------- -------- -------- ................\n"
-" a2345668 -------- -------- -------- -------- ................\n"
-" a2345678 -------- -------- -------- -------- ................\n"
-" a2345688 -------- -------- -------- -------- ................\n"
-" a2345698 -------- -------- -------- -------- ................\n"
-" a23456a8 -------- -------- -------- -------- ................\n"
-" a23456b8 -------- -------- -------- -------- ................\n"
-" a23456c8 -------- -------- -------- -------- ................\n"
-" a23456d8 -------- -------- -------- -------- ................\n"
-" a23456e8 -------- -------- -------- -------- ................\n"
-" a23456f8 -------- -------- -------- -------- ................\n"
-" a2345708 -------- -------- -------- -------- ................\n"
-" a2345718 -------- -------- -------- -------- ................\n"
-" a2345728 -------- -------- -------- -------- ................\n"
-" a2345738 -------- -------- -------- -------- ................\n"
-" a2345748 -------- -------- -------- -------- ................\n";
-#endif
- ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
+ ASSERT_STREQ("", tombstone_contents.c_str());
// Verify that the log buf is empty, and no error messages.
ASSERT_STREQ("", getFakeLogBuf().c_str());
@@ -429,57 +395,17 @@
ASSERT_STREQ("", getFakeLogPrint().c_str());
}
-TEST_F(DumpMemoryTest, memory_address_too_low) {
- uint8_t buffer[256];
- memset(buffer, 0, sizeof(buffer));
- memory_mock_->SetReadData(buffer, sizeof(buffer));
-
- dump_memory(&log_, memory_mock_.get(), 0, "memory near r1");
-
- std::string tombstone_contents;
- ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
- ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
- ASSERT_STREQ("", tombstone_contents.c_str());
-
- // Verify that the log buf is empty, and no error messages.
- ASSERT_STREQ("", getFakeLogBuf().c_str());
- ASSERT_STREQ("", getFakeLogPrint().c_str());
-}
-
TEST_F(DumpMemoryTest, memory_address_too_high) {
uint8_t buffer[256];
memset(buffer, 0, sizeof(buffer));
memory_mock_->SetReadData(buffer, sizeof(buffer));
#if defined(__LP64__)
- dump_memory(&log_, memory_mock_.get(), 0x4000000000000000UL, "memory near r1");
- dump_memory(&log_, memory_mock_.get(), 0x4000000000000000UL - 32, "memory near r1");
- dump_memory(&log_, memory_mock_.get(), 0x4000000000000000UL - 216, "memory near r1");
+ dump_memory(&log_, memory_mock_.get(), -32, "memory near r1");
+ dump_memory(&log_, memory_mock_.get(), -208, "memory near r1");
#else
- dump_memory(&log_, memory_mock_.get(), 0xffff0000, "memory near r1");
- dump_memory(&log_, memory_mock_.get(), 0xffff0000 - 32, "memory near r1");
- dump_memory(&log_, memory_mock_.get(), 0xffff0000 - 220, "memory near r1");
-#endif
-
- std::string tombstone_contents;
- ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
- ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
- ASSERT_STREQ("", tombstone_contents.c_str());
-
- // Verify that the log buf is empty, and no error messages.
- ASSERT_STREQ("", getFakeLogBuf().c_str());
- ASSERT_STREQ("", getFakeLogPrint().c_str());
-}
-
-TEST_F(DumpMemoryTest, memory_address_would_overflow) {
- uint8_t buffer[256];
- memset(buffer, 0, sizeof(buffer));
- memory_mock_->SetReadData(buffer, sizeof(buffer));
-
-#if defined(__LP64__)
- dump_memory(&log_, memory_mock_.get(), 0xfffffffffffffff0, "memory near r1");
-#else
- dump_memory(&log_, memory_mock_.get(), 0xfffffff0, "memory near r1");
+ dump_memory(&log_, memory_mock_.get(), 0x100000000 - 32, "memory near r1");
+ dump_memory(&log_, memory_mock_.get(), 0x100000000 - 208, "memory near r1");
#endif
std::string tombstone_contents;
@@ -500,9 +426,9 @@
memory_mock_->SetReadData(buffer, sizeof(buffer));
#if defined(__LP64__)
- dump_memory(&log_, memory_mock_.get(), 0x4000000000000000UL - 224, "memory near r4");
+ dump_memory(&log_, memory_mock_.get(), -224, "memory near r4");
#else
- dump_memory(&log_, memory_mock_.get(), 0xffff0000 - 224, "memory near r4");
+ dump_memory(&log_, memory_mock_.get(), 0x100000000 - 224, "memory near r4");
#endif
std::string tombstone_contents;
@@ -510,40 +436,57 @@
ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
const char* expected_dump = \
"\nmemory near r4:\n"
-#if defined(__LP64__)
-" 3fffffffffffff00 0706050403020100 0f0e0d0c0b0a0908 ................\n"
-" 3fffffffffffff10 1716151413121110 1f1e1d1c1b1a1918 ................\n"
-" 3fffffffffffff20 2726252423222120 2f2e2d2c2b2a2928 !\"#$%&'()*+,-./\n"
-" 3fffffffffffff30 3736353433323130 3f3e3d3c3b3a3938 0123456789:;<=>?\n"
-" 3fffffffffffff40 4746454443424140 4f4e4d4c4b4a4948 @ABCDEFGHIJKLMNO\n"
-" 3fffffffffffff50 5756555453525150 5f5e5d5c5b5a5958 PQRSTUVWXYZ[\\]^_\n"
-" 3fffffffffffff60 6766656463626160 6f6e6d6c6b6a6968 `abcdefghijklmno\n"
-" 3fffffffffffff70 7776757473727170 7f7e7d7c7b7a7978 pqrstuvwxyz{|}~.\n"
-" 3fffffffffffff80 8786858483828180 8f8e8d8c8b8a8988 ................\n"
-" 3fffffffffffff90 9796959493929190 9f9e9d9c9b9a9998 ................\n"
-" 3fffffffffffffa0 a7a6a5a4a3a2a1a0 afaeadacabaaa9a8 ................\n"
-" 3fffffffffffffb0 b7b6b5b4b3b2b1b0 bfbebdbcbbbab9b8 ................\n"
-" 3fffffffffffffc0 c7c6c5c4c3c2c1c0 cfcecdcccbcac9c8 ................\n"
-" 3fffffffffffffd0 d7d6d5d4d3d2d1d0 dfdedddcdbdad9d8 ................\n"
-" 3fffffffffffffe0 e7e6e5e4e3e2e1e0 efeeedecebeae9e8 ................\n"
-" 3ffffffffffffff0 f7f6f5f4f3f2f1f0 fffefdfcfbfaf9f8 ................\n";
+#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";
+#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";
#else
-" fffeff00 03020100 07060504 0b0a0908 0f0e0d0c ................\n"
-" fffeff10 13121110 17161514 1b1a1918 1f1e1d1c ................\n"
-" fffeff20 23222120 27262524 2b2a2928 2f2e2d2c !\"#$%&'()*+,-./\n"
-" fffeff30 33323130 37363534 3b3a3938 3f3e3d3c 0123456789:;<=>?\n"
-" fffeff40 43424140 47464544 4b4a4948 4f4e4d4c @ABCDEFGHIJKLMNO\n"
-" fffeff50 53525150 57565554 5b5a5958 5f5e5d5c PQRSTUVWXYZ[\\]^_\n"
-" fffeff60 63626160 67666564 6b6a6968 6f6e6d6c `abcdefghijklmno\n"
-" fffeff70 73727170 77767574 7b7a7978 7f7e7d7c pqrstuvwxyz{|}~.\n"
-" fffeff80 83828180 87868584 8b8a8988 8f8e8d8c ................\n"
-" fffeff90 93929190 97969594 9b9a9998 9f9e9d9c ................\n"
-" fffeffa0 a3a2a1a0 a7a6a5a4 abaaa9a8 afaeadac ................\n"
-" fffeffb0 b3b2b1b0 b7b6b5b4 bbbab9b8 bfbebdbc ................\n"
-" fffeffc0 c3c2c1c0 c7c6c5c4 cbcac9c8 cfcecdcc ................\n"
-" fffeffd0 d3d2d1d0 d7d6d5d4 dbdad9d8 dfdedddc ................\n"
-" fffeffe0 e3e2e1e0 e7e6e5e4 ebeae9e8 efeeedec ................\n"
-" fffefff0 f3f2f1f0 f7f6f5f4 fbfaf9f8 fffefdfc ................\n";
+" 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";
#endif
ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
@@ -570,39 +513,41 @@
const char* expected_dump = \
"\nmemory near r4:\n"
#if defined(__LP64__)
-" 0000000010000f88 ---------------- ---------------- ................\n"
-" 0000000010000f98 ---------------- ---------------- ................\n"
-" 0000000010000fa8 ---------------- ---------------- ................\n"
-" 0000000010000fb8 ---------------- ---------------- ................\n"
-" 0000000010000fc8 ---------------- ---------------- ................\n"
-" 0000000010000fd8 ---------------- ---------------- ................\n"
-" 0000000010000fe8 ---------------- ---------------- ................\n"
-" 0000000010000ff8 ---------------- 7f7e7d7c7b7a7978 ........xyz{|}~.\n"
-" 0000000010001008 8786858483828180 8f8e8d8c8b8a8988 ................\n"
-" 0000000010001018 9796959493929190 9f9e9d9c9b9a9998 ................\n"
-" 0000000010001028 a7a6a5a4a3a2a1a0 afaeadacabaaa9a8 ................\n"
-" 0000000010001038 b7b6b5b4b3b2b1b0 bfbebdbcbbbab9b8 ................\n"
-" 0000000010001048 c7c6c5c4c3c2c1c0 cfcecdcccbcac9c8 ................\n"
-" 0000000010001058 d7d6d5d4d3d2d1d0 dfdedddcdbdad9d8 ................\n"
-" 0000000010001068 e7e6e5e4e3e2e1e0 efeeedecebeae9e8 ................\n"
-" 0000000010001078 f7f6f5f4f3f2f1f0 fffefdfcfbfaf9f8 ................\n";
+R"( 0000000010000f80 ---------------- ---------------- ................
+ 0000000010000f90 ---------------- ---------------- ................
+ 0000000010000fa0 ---------------- ---------------- ................
+ 0000000010000fb0 ---------------- ---------------- ................
+ 0000000010000fc0 ---------------- ---------------- ................
+ 0000000010000fd0 ---------------- ---------------- ................
+ 0000000010000fe0 ---------------- ---------------- ................
+ 0000000010000ff0 ---------------- ---------------- ................
+ 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
-" 10000f88 -------- -------- -------- -------- ................\n"
-" 10000f98 -------- -------- -------- -------- ................\n"
-" 10000fa8 -------- -------- -------- -------- ................\n"
-" 10000fb8 -------- -------- -------- -------- ................\n"
-" 10000fc8 -------- -------- -------- -------- ................\n"
-" 10000fd8 -------- -------- -------- -------- ................\n"
-" 10000fe8 -------- -------- -------- -------- ................\n"
-" 10000ff8 -------- -------- 7b7a7978 7f7e7d7c ........xyz{|}~.\n"
-" 10001008 83828180 87868584 8b8a8988 8f8e8d8c ................\n"
-" 10001018 93929190 97969594 9b9a9998 9f9e9d9c ................\n"
-" 10001028 a3a2a1a0 a7a6a5a4 abaaa9a8 afaeadac ................\n"
-" 10001038 b3b2b1b0 b7b6b5b4 bbbab9b8 bfbebdbc ................\n"
-" 10001048 c3c2c1c0 c7c6c5c4 cbcac9c8 cfcecdcc ................\n"
-" 10001058 d3d2d1d0 d7d6d5d4 dbdad9d8 dfdedddc ................\n"
-" 10001068 e3e2e1e0 e7e6e5e4 ebeae9e8 efeeedec ................\n"
-" 10001078 f3f2f1f0 f7f6f5f4 fbfaf9f8 fffefdfc ................\n";
+R"( 10000f80 -------- -------- -------- -------- ................
+ 10000f90 -------- -------- -------- -------- ................
+ 10000fa0 -------- -------- -------- -------- ................
+ 10000fb0 -------- -------- -------- -------- ................
+ 10000fc0 -------- -------- -------- -------- ................
+ 10000fd0 -------- -------- -------- -------- ................
+ 10000fe0 -------- -------- -------- -------- ................
+ 10000ff0 -------- -------- -------- -------- ................
+ 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());
@@ -684,44 +629,7 @@
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__)
-" 0000000010000000 ---------------- ---------------- ................\n"
-" 0000000010000010 ---------------- ---------------- ................\n"
-" 0000000010000020 ---------------- ---------------- ................\n"
-" 0000000010000030 ---------------- ---------------- ................\n"
-" 0000000010000040 ---------------- ---------------- ................\n"
-" 0000000010000050 ---------------- ---------------- ................\n"
-" 0000000010000060 ---------------- ---------------- ................\n"
-" 0000000010000070 ---------------- ---------------- ................\n"
-" 0000000010000080 ---------------- ---------------- ................\n"
-" 0000000010000090 ---------------- ---------------- ................\n"
-" 00000000100000a0 ---------------- ---------------- ................\n"
-" 00000000100000b0 ---------------- ---------------- ................\n"
-" 00000000100000c0 ---------------- ---------------- ................\n"
-" 00000000100000d0 ---------------- ---------------- ................\n"
-" 00000000100000e0 ---------------- ---------------- ................\n"
-" 00000000100000f0 ---------------- ---------------- ................\n";
-#else
-" 10000000 -------- -------- -------- -------- ................\n"
-" 10000010 -------- -------- -------- -------- ................\n"
-" 10000020 -------- -------- -------- -------- ................\n"
-" 10000030 -------- -------- -------- -------- ................\n"
-" 10000040 -------- -------- -------- -------- ................\n"
-" 10000050 -------- -------- -------- -------- ................\n"
-" 10000060 -------- -------- -------- -------- ................\n"
-" 10000070 -------- -------- -------- -------- ................\n"
-" 10000080 -------- -------- -------- -------- ................\n"
-" 10000090 -------- -------- -------- -------- ................\n"
-" 100000a0 -------- -------- -------- -------- ................\n"
-" 100000b0 -------- -------- -------- -------- ................\n"
-" 100000c0 -------- -------- -------- -------- ................\n"
-" 100000d0 -------- -------- -------- -------- ................\n"
-" 100000e0 -------- -------- -------- -------- ................\n"
-" 100000f0 -------- -------- -------- -------- ................\n";
-#endif
- ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
+ ASSERT_STREQ("", tombstone_contents.c_str());
// Verify that the log buf is empty, and no error messages.
ASSERT_STREQ("", getFakeLogBuf().c_str());
@@ -744,44 +652,7 @@
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__)
-" 0000000010000f00 ---------------- ---------------- ................\n"
-" 0000000010000f10 ---------------- ---------------- ................\n"
-" 0000000010000f20 ---------------- ---------------- ................\n"
-" 0000000010000f30 ---------------- ---------------- ................\n"
-" 0000000010000f40 ---------------- ---------------- ................\n"
-" 0000000010000f50 ---------------- ---------------- ................\n"
-" 0000000010000f60 ---------------- ---------------- ................\n"
-" 0000000010000f70 ---------------- ---------------- ................\n"
-" 0000000010000f80 ---------------- ---------------- ................\n"
-" 0000000010000f90 ---------------- ---------------- ................\n"
-" 0000000010000fa0 ---------------- ---------------- ................\n"
-" 0000000010000fb0 ---------------- ---------------- ................\n"
-" 0000000010000fc0 ---------------- ---------------- ................\n"
-" 0000000010000fd0 ---------------- ---------------- ................\n"
-" 0000000010000fe0 ---------------- ---------------- ................\n"
-" 0000000010000ff0 ---------------- ---------------- ................\n";
-#else
-" 10000f00 -------- -------- -------- -------- ................\n"
-" 10000f10 -------- -------- -------- -------- ................\n"
-" 10000f20 -------- -------- -------- -------- ................\n"
-" 10000f30 -------- -------- -------- -------- ................\n"
-" 10000f40 -------- -------- -------- -------- ................\n"
-" 10000f50 -------- -------- -------- -------- ................\n"
-" 10000f60 -------- -------- -------- -------- ................\n"
-" 10000f70 -------- -------- -------- -------- ................\n"
-" 10000f80 -------- -------- -------- -------- ................\n"
-" 10000f90 -------- -------- -------- -------- ................\n"
-" 10000fa0 -------- -------- -------- -------- ................\n"
-" 10000fb0 -------- -------- -------- -------- ................\n"
-" 10000fc0 -------- -------- -------- -------- ................\n"
-" 10000fd0 -------- -------- -------- -------- ................\n"
-" 10000fe0 -------- -------- -------- -------- ................\n"
-" 10000ff0 -------- -------- -------- -------- ................\n";
-#endif
- ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
+ ASSERT_STREQ("", tombstone_contents.c_str());
// Verify that the log buf is empty, and no error messages.
ASSERT_STREQ("", getFakeLogBuf().c_str());
diff --git a/debuggerd/libdebuggerd/test/tombstone_test.cpp b/debuggerd/libdebuggerd/test/tombstone_test.cpp
index aec8c60..b42d70c 100644
--- a/debuggerd/libdebuggerd/test/tombstone_test.cpp
+++ b/debuggerd/libdebuggerd/test/tombstone_test.cpp
@@ -359,13 +359,6 @@
ASSERT_STREQ(expected.c_str(), amfd_data_.c_str());
}
-TEST_F(TombstoneTest, dump_timestamp) {
- setenv("TZ", "UTC", 1);
- tzset();
- dump_timestamp(&log_, 0);
- ASSERT_STREQ("Timestamp: 1970-01-01 00:00:00+0000\n", amfd_data_.c_str());
-}
-
class GwpAsanCrashDataTest : public GwpAsanCrashData {
public:
GwpAsanCrashDataTest(
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index ab65dd1..7af99c9 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -58,6 +58,7 @@
#include "libdebuggerd/open_files_list.h"
#include "libdebuggerd/scudo.h"
#include "libdebuggerd/utility.h"
+#include "util.h"
#include "gwp_asan/common.h"
#include "gwp_asan/crash_handler.h"
@@ -80,15 +81,6 @@
_LOG(log, logtype::HEADER, "ABI: '%s'\n", ABI_STRING);
}
-static void dump_timestamp(log_t* log, time_t time) {
- struct tm tm;
- localtime_r(&time, &tm);
-
- char buf[strlen("1970-01-01 00:00:00+0830") + 1];
- strftime(buf, sizeof(buf), "%F %T%z", &tm);
- _LOG(log, logtype::HEADER, "Timestamp: %s\n", buf);
-}
-
static std::string get_stack_overflow_cause(uint64_t fault_addr, uint64_t sp,
unwindstack::Maps* maps) {
static constexpr uint64_t kMaxDifferenceBytes = 256;
@@ -182,12 +174,8 @@
}
static void dump_thread_info(log_t* log, const ThreadInfo& thread_info) {
- // Blacklist logd, logd.reader, logd.writer, logd.auditd, logd.control ...
- // TODO: Why is this controlled by thread name?
- if (thread_info.thread_name == "logd" ||
- android::base::StartsWith(thread_info.thread_name, "logd.")) {
- log->should_retrieve_logcat = false;
- }
+ // Don't try to collect logs from the threads that implement the logging system itself.
+ if (thread_info.uid == AID_LOGD) log->should_retrieve_logcat = false;
_LOG(log, logtype::HEADER, "pid: %d, tid: %d, name: %s >>> %s <<<\n", thread_info.pid,
thread_info.tid, thread_info.thread_name.c_str(), thread_info.process_name.c_str());
@@ -507,10 +495,9 @@
// (although in this case the pid is redundant).
char timeBuf[32];
time_t sec = static_cast<time_t>(log_entry.entry.sec);
- struct tm tmBuf;
- struct tm* ptm;
- ptm = localtime_r(&sec, &tmBuf);
- strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", ptm);
+ tm tm;
+ localtime_r(&sec, &tm);
+ strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", &tm);
char* msg = log_entry.msg();
if (msg == nullptr) {
@@ -571,23 +558,20 @@
log.tfd = tombstone_fd;
log.amfd_data = nullptr;
- char thread_name[16];
- char process_name[128];
-
- read_with_default("/proc/self/comm", thread_name, sizeof(thread_name), "<unknown>");
- read_with_default("/proc/self/cmdline", process_name, sizeof(process_name), "<unknown>");
+ std::string thread_name = get_thread_name(tid);
+ std::string process_name = get_process_name(pid);
std::unique_ptr<unwindstack::Regs> regs(
unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(), ucontext));
std::map<pid_t, ThreadInfo> threads;
- threads[gettid()] = ThreadInfo{
+ threads[tid] = ThreadInfo{
.registers = std::move(regs),
.uid = uid,
.tid = tid,
- .thread_name = thread_name,
+ .thread_name = thread_name.c_str(),
.pid = pid,
- .process_name = process_name,
+ .process_name = process_name.c_str(),
.siginfo = siginfo,
};
@@ -606,8 +590,8 @@
const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
const ProcessInfo& process_info, OpenFilesList* open_files,
std::string* amfd_data) {
- // don't copy log messages to tombstone unless this is a dev device
- bool want_logs = android::base::GetBoolProperty("ro.debuggable", false);
+ // Don't copy log messages to tombstone unless this is a development device.
+ bool want_logs = GetBoolProperty("ro.debuggable", false);
log_t log;
log.current_tid = target_thread;
@@ -617,7 +601,7 @@
_LOG(&log, logtype::HEADER, "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");
dump_header_info(&log);
- dump_timestamp(&log, time(nullptr));
+ _LOG(&log, logtype::HEADER, "Timestamp: %s\n", get_timestamp().c_str());
auto it = threads.find(target_thread);
if (it == threads.end()) {
diff --git a/debuggerd/libdebuggerd/utility.cpp b/debuggerd/libdebuggerd/utility.cpp
index c8a3431..4e6df09 100644
--- a/debuggerd/libdebuggerd/utility.cpp
+++ b/debuggerd/libdebuggerd/utility.cpp
@@ -44,7 +44,6 @@
using android::base::unique_fd;
-// Whitelist output desired in the logcat output.
bool is_allowed_in_logcat(enum logtype ltype) {
if ((ltype == HEADER)
|| (ltype == REGISTERS)
@@ -129,24 +128,23 @@
#define MEMORY_BYTES_PER_LINE 16
void dump_memory(log_t* log, unwindstack::Memory* memory, uint64_t addr, const std::string& label) {
- // Align the address to sizeof(long) and start 32 bytes before the address.
- addr &= ~(sizeof(long) - 1);
+ // Align the address to the number of bytes per line to avoid confusing memory tag output if
+ // memory is tagged and we start from a misaligned address. Start 32 bytes before the address.
+ addr &= ~(MEMORY_BYTES_PER_LINE - 1);
if (addr >= 4128) {
addr -= 32;
}
- // Don't bother if the address looks too low, or looks too high.
- if (addr < 4096 ||
-#if defined(__LP64__)
- addr > 0x4000000000000000UL - MEMORY_BYTES_TO_DUMP) {
-#else
- addr > 0xffff0000 - MEMORY_BYTES_TO_DUMP) {
-#endif
+ // We don't want the address tag to appear in the addresses in the memory dump.
+ addr = untag_address(addr);
+
+ // Don't bother if the address would overflow, taking tag bits into account. Note that
+ // untag_address truncates to 32 bits on 32-bit platforms as a side effect of returning a
+ // uintptr_t, so this also checks for 32-bit overflow.
+ if (untag_address(addr + MEMORY_BYTES_TO_DUMP - 1) < addr) {
return;
}
- _LOG(log, logtype::MEMORY, "\n%s:\n", label.c_str());
-
// Dump 256 bytes
uintptr_t data[MEMORY_BYTES_TO_DUMP/sizeof(uintptr_t)];
memset(data, 0, MEMORY_BYTES_TO_DUMP);
@@ -187,6 +185,15 @@
}
}
+ // If we were unable to read anything, it probably means that the register doesn't contain a
+ // valid pointer. In that case, skip the output for this register entirely rather than emitting 16
+ // lines of dashes.
+ if (bytes == 0) {
+ return;
+ }
+
+ _LOG(log, logtype::MEMORY, "\n%s:\n", label.c_str());
+
// Dump the code around memory as:
// addr contents ascii
// 0000000000008d34 ef000000e8bd0090 e1b00000512fff1e ............../Q
@@ -197,8 +204,13 @@
size_t current = 0;
size_t total_bytes = start + bytes;
for (size_t line = 0; line < MEMORY_BYTES_TO_DUMP / MEMORY_BYTES_PER_LINE; line++) {
+ uint64_t tagged_addr = addr;
+ long tag = memory->ReadTag(addr);
+ if (tag >= 0) {
+ tagged_addr |= static_cast<uint64_t>(tag) << 56;
+ }
std::string logline;
- android::base::StringAppendF(&logline, " %" PRIPTR, addr);
+ android::base::StringAppendF(&logline, " %" PRIPTR, tagged_addr);
addr += MEMORY_BYTES_PER_LINE;
std::string ascii;
@@ -226,23 +238,6 @@
}
}
-void read_with_default(const char* path, char* buf, size_t len, const char* default_value) {
- unique_fd fd(open(path, O_RDONLY | O_CLOEXEC));
- if (fd != -1) {
- int rc = TEMP_FAILURE_RETRY(read(fd.get(), buf, len - 1));
- if (rc != -1) {
- buf[rc] = '\0';
-
- // Trim trailing newlines.
- if (rc > 0 && buf[rc - 1] == '\n') {
- buf[rc - 1] = '\0';
- }
- return;
- }
- }
- strcpy(buf, default_value);
-}
-
void drop_capabilities() {
__user_cap_header_struct capheader;
memset(&capheader, 0, sizeof(capheader));
diff --git a/debuggerd/util.cpp b/debuggerd/util.cpp
index a37b3b9..9d09210 100644
--- a/debuggerd/util.cpp
+++ b/debuggerd/util.cpp
@@ -17,6 +17,7 @@
#include "util.h"
#include <sys/socket.h>
+#include <time.h>
#include <string>
#include <utility>
@@ -38,3 +39,19 @@
android::base::ReadFileToString(android::base::StringPrintf("/proc/%d/comm", tid), &result);
return android::base::Trim(result);
}
+
+std::string get_timestamp() {
+ timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+
+ tm tm;
+ localtime_r(&ts.tv_sec, &tm);
+
+ char buf[strlen("1970-01-01 00:00:00.123456789+0830") + 1];
+ char* s = buf;
+ size_t sz = sizeof(buf), n;
+ n = strftime(s, sz, "%F %H:%M", &tm), s += n, sz -= n;
+ n = snprintf(s, sz, ":%02d.%09ld", tm.tm_sec, ts.tv_nsec), s += n, sz -= n;
+ n = strftime(s, sz, "%z", &tm), s += n, sz -= n;
+ return buf;
+}
diff --git a/debuggerd/util.h b/debuggerd/util.h
index e964423..07e7e99 100644
--- a/debuggerd/util.h
+++ b/debuggerd/util.h
@@ -23,3 +23,5 @@
std::string get_process_name(pid_t pid);
std::string get_thread_name(pid_t tid);
+
+std::string get_timestamp();
diff --git a/diagnose_usb/diagnose_usb.cpp b/diagnose_usb/diagnose_usb.cpp
index 5695ece..35edb5e 100644
--- a/diagnose_usb/diagnose_usb.cpp
+++ b/diagnose_usb/diagnose_usb.cpp
@@ -49,7 +49,7 @@
// additionally just to be sure.
if (group_member(plugdev_group->gr_gid) || getegid() == plugdev_group->gr_gid) {
// The user is in plugdev so the problem is likely with the udev rules.
- return "user in plugdev group; are your udev rules wrong?";
+ return "missing udev rules? user is in the plugdev group";
}
passwd* pwd = getpwuid(getuid());
return android::base::StringPrintf("user %s is not in the plugdev group",
diff --git a/fastboot/fastboot.bash b/fastboot/fastboot.bash
index cc1366c..406e8b8 100644
--- a/fastboot/fastboot.bash
+++ b/fastboot/fastboot.bash
@@ -109,7 +109,7 @@
cur="${COMP_WORDS[COMP_CWORD]}"
if [[ $i -eq $COMP_CWORD ]]; then
- partitions="boot bootloader dtbo modem odm oem product radio recovery system vbmeta vendor vendor_dlkm"
+ partitions="boot bootloader dtbo modem odm odm_dlkm oem product radio recovery system vbmeta vendor vendor_dlkm"
COMPREPLY=( $(compgen -W "$partitions" -- $cur) )
else
_fastboot_util_complete_local_file "${cur}" '!*.img'
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 4ca6a6a..d33c987 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -145,6 +145,7 @@
{ "dtbo", "dtbo.img", "dtbo.sig", "dtbo", true, ImageType::BootCritical },
{ "dts", "dt.img", "dt.sig", "dts", true, ImageType::BootCritical },
{ "odm", "odm.img", "odm.sig", "odm", true, ImageType::Normal },
+ { "odm_dlkm", "odm_dlkm.img", "odm_dlkm.sig", "odm_dlkm", true, ImageType::Normal },
{ "product", "product.img", "product.sig", "product", true, ImageType::Normal },
{ "recovery", "recovery.img", "recovery.sig", "recovery", true, ImageType::BootCritical },
{ "super", "super.img", "super.sig", "super", true, ImageType::Extra },
diff --git a/fastboot/fuzzy_fastboot/main.cpp b/fastboot/fuzzy_fastboot/main.cpp
index e7f785b..34ab32c 100644
--- a/fastboot/fuzzy_fastboot/main.cpp
+++ b/fastboot/fuzzy_fastboot/main.cpp
@@ -1286,7 +1286,7 @@
ASSERT_TRUE(PartitionHash(fb.get(), "userdata", &hash_buf, &retcode, &err_msg)) << err_msg;
ASSERT_EQ(retcode, 0) << err_msg;
- // Sanity check of hash
+ // Validity check of hash
EXPECT_NE(hash_before, hash_buf)
<< "Writing a random buffer to 'userdata' had the same hash as after erasing it";
SetLockState(true); // Lock the device
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 0ae5787..88bb234 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -607,7 +607,7 @@
LINFO << "Enabling ext4 metadata_csum on " << blk_device;
- // requires to give last_fsck_time to current to avoid insane time.
+ // Must give `-T now` to prevent last_fsck_time from growing too large,
// otherwise, tune2fs won't enable metadata_csum.
const char* tune2fs_args[] = {TUNE2FS_BIN, "-O", "metadata_csum,64bit,extent",
"-T", "now", blk_device.c_str()};
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 1fa1aa1..a7704de 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -809,15 +809,26 @@
entry.fs_type = mnt_type;
if ((mnt_type == "f2fs") && !f2fs) entry.fs_type = "ext4";
if ((mnt_type == "ext4") && !ext4) entry.fs_type = "f2fs";
- entry.flags = MS_NOATIME;
- if (readonly) {
- entry.flags |= MS_RDONLY;
- } else {
+ entry.flags = MS_NOATIME | MS_RDONLY;
+ auto mounted = true;
+ if (!readonly) {
+ if (entry.fs_type == "ext4") {
+ // check if ext4 de-dupe
+ entry.flags |= MS_RDONLY;
+ auto save_errno = errno;
+ mounted = fs_mgr_do_mount_one(entry) == 0;
+ if (mounted) {
+ mounted = !fs_mgr_has_shared_blocks(entry.mount_point, entry.blk_device);
+ fs_mgr_overlayfs_umount_scratch();
+ }
+ errno = save_errno;
+ }
+ entry.flags &= ~MS_RDONLY;
fs_mgr_set_blk_ro(device_path, false);
}
entry.fs_mgr_flags.check = true;
auto save_errno = errno;
- auto mounted = fs_mgr_do_mount_one(entry) == 0;
+ if (mounted) mounted = fs_mgr_do_mount_one(entry) == 0;
if (!mounted) {
if ((entry.fs_type == "f2fs") && ext4) {
entry.fs_type = "ext4";
diff --git a/fs_mgr/libdm/Android.bp b/fs_mgr/libdm/Android.bp
index 58241b3..e425284 100644
--- a/fs_mgr/libdm/Android.bp
+++ b/fs_mgr/libdm/Android.bp
@@ -42,6 +42,7 @@
enabled: false,
},
},
+ ramdisk_available: true,
}
filegroup {
diff --git a/fs_mgr/libfiemap/fiemap_writer.cpp b/fs_mgr/libfiemap/fiemap_writer.cpp
index 4dd4bcc..621031a 100644
--- a/fs_mgr/libfiemap/fiemap_writer.cpp
+++ b/fs_mgr/libfiemap/fiemap_writer.cpp
@@ -45,7 +45,7 @@
using namespace android::dm;
-// We cap the maximum number of extents as a sanity measure.
+// We cap the maximum number of extents as a robustness measure.
static constexpr uint32_t kMaxExtents = 50000;
// TODO: Fallback to using fibmap if FIEMAP_EXTENT_MERGED is set.
diff --git a/fs_mgr/libfiemap/split_fiemap_writer.cpp b/fs_mgr/libfiemap/split_fiemap_writer.cpp
index 12c7397..36bb3df 100644
--- a/fs_mgr/libfiemap/split_fiemap_writer.cpp
+++ b/fs_mgr/libfiemap/split_fiemap_writer.cpp
@@ -266,7 +266,7 @@
cursor_file_pos_ += bytes_to_write;
}
- // If we've reached the end of the current file, close it for sanity.
+ // If we've reached the end of the current file, close it.
if (cursor_file_pos_ == file->size()) {
cursor_fd_ = {};
}
diff --git a/fs_mgr/libfiemap/utility.cpp b/fs_mgr/libfiemap/utility.cpp
index bbb0510..c189855 100644
--- a/fs_mgr/libfiemap/utility.cpp
+++ b/fs_mgr/libfiemap/utility.cpp
@@ -139,8 +139,7 @@
}
*bdev_name = ::android::base::Basename(sysfs_bdev);
- // Paranoid sanity check to make sure we just didn't get the
- // input in return as-is.
+ // Check that the symlink doesn't point to itself.
if (sysfs_bdev == *bdev_name) {
LOG(ERROR) << "Malformed symlink for block device: " << sysfs_bdev;
return false;
diff --git a/fs_mgr/libfs_avb/avb_ops.cpp b/fs_mgr/libfs_avb/avb_ops.cpp
index c192bf5..46072bb 100644
--- a/fs_mgr/libfs_avb/avb_ops.cpp
+++ b/fs_mgr/libfs_avb/avb_ops.cpp
@@ -52,16 +52,16 @@
partition, offset, num_bytes, buffer, out_num_read);
}
-static AvbIOResult dummy_read_rollback_index(AvbOps* ops ATTRIBUTE_UNUSED,
- size_t rollback_index_location ATTRIBUTE_UNUSED,
- uint64_t* out_rollback_index) {
+static AvbIOResult no_op_read_rollback_index(AvbOps* ops ATTRIBUTE_UNUSED,
+ size_t rollback_index_location ATTRIBUTE_UNUSED,
+ uint64_t* out_rollback_index) {
// rollback_index has been checked in bootloader phase.
// In user-space, returns the smallest value 0 to pass the check.
*out_rollback_index = 0;
return AVB_IO_RESULT_OK;
}
-static AvbIOResult dummy_validate_vbmeta_public_key(
+static AvbIOResult no_op_validate_vbmeta_public_key(
AvbOps* ops ATTRIBUTE_UNUSED, const uint8_t* public_key_data ATTRIBUTE_UNUSED,
size_t public_key_length ATTRIBUTE_UNUSED,
const uint8_t* public_key_metadata ATTRIBUTE_UNUSED,
@@ -76,8 +76,8 @@
return AVB_IO_RESULT_OK;
}
-static AvbIOResult dummy_read_is_device_unlocked(AvbOps* ops ATTRIBUTE_UNUSED,
- bool* out_is_unlocked) {
+static AvbIOResult no_op_read_is_device_unlocked(AvbOps* ops ATTRIBUTE_UNUSED,
+ bool* out_is_unlocked) {
// The function is for bootloader to update the value into
// androidboot.vbmeta.device_state in kernel cmdline.
// In user-space, returns true as we don't need to update it anymore.
@@ -85,9 +85,9 @@
return AVB_IO_RESULT_OK;
}
-static AvbIOResult dummy_get_unique_guid_for_partition(AvbOps* ops ATTRIBUTE_UNUSED,
- const char* partition ATTRIBUTE_UNUSED,
- char* guid_buf, size_t guid_buf_size) {
+static AvbIOResult no_op_get_unique_guid_for_partition(AvbOps* ops ATTRIBUTE_UNUSED,
+ const char* partition ATTRIBUTE_UNUSED,
+ char* guid_buf, size_t guid_buf_size) {
// The function is for bootloader to set the correct UUID
// for a given partition in kernel cmdline.
// In user-space, returns a faking one as we don't need to update
@@ -96,9 +96,9 @@
return AVB_IO_RESULT_OK;
}
-static AvbIOResult dummy_get_size_of_partition(AvbOps* ops ATTRIBUTE_UNUSED,
- const char* partition ATTRIBUTE_UNUSED,
- uint64_t* out_size_num_byte) {
+static AvbIOResult no_op_get_size_of_partition(AvbOps* ops ATTRIBUTE_UNUSED,
+ const char* partition ATTRIBUTE_UNUSED,
+ uint64_t* out_size_num_byte) {
// The function is for bootloader to load entire content of AVB HASH partitions.
// In user-space, returns 0 as we only need to set up AVB HASHTHREE partitions.
*out_size_num_byte = 0;
@@ -123,15 +123,15 @@
// We only need to provide the implementation of read_from_partition()
// operation since that's all what is being used by the avb_slot_verify().
// Other I/O operations are only required in bootloader but not in
- // user-space so we set them as dummy operations. Also zero the entire
+ // user-space so we set them as no-op operations. Also zero the entire
// struct so operations added in the future will be set to NULL.
memset(&avb_ops_, 0, sizeof(AvbOps));
avb_ops_.read_from_partition = read_from_partition;
- avb_ops_.read_rollback_index = dummy_read_rollback_index;
- avb_ops_.validate_vbmeta_public_key = dummy_validate_vbmeta_public_key;
- avb_ops_.read_is_device_unlocked = dummy_read_is_device_unlocked;
- avb_ops_.get_unique_guid_for_partition = dummy_get_unique_guid_for_partition;
- avb_ops_.get_size_of_partition = dummy_get_size_of_partition;
+ avb_ops_.read_rollback_index = no_op_read_rollback_index;
+ avb_ops_.validate_vbmeta_public_key = no_op_validate_vbmeta_public_key;
+ avb_ops_.read_is_device_unlocked = no_op_read_is_device_unlocked;
+ avb_ops_.get_unique_guid_for_partition = no_op_get_unique_guid_for_partition;
+ avb_ops_.get_size_of_partition = no_op_get_size_of_partition;
// Sets user_data for GetInstanceFromAvbOps() to convert it back to FsManagerAvbOps.
avb_ops_.user_data = this;
diff --git a/fs_mgr/libfs_avb/fs_avb.cpp b/fs_mgr/libfs_avb/fs_avb.cpp
index 5d504ab..49333a1 100644
--- a/fs_mgr/libfs_avb/fs_avb.cpp
+++ b/fs_mgr/libfs_avb/fs_avb.cpp
@@ -226,7 +226,7 @@
return nullptr;
}
- // Sanity check here because we have to use vbmeta_images_[0] below.
+ // Validity check here because we have to use vbmeta_images_[0] below.
if (avb_handle->vbmeta_images_.size() < 1) {
LERROR << "LoadAndVerifyVbmetaByPartition failed, no vbmeta loaded";
return nullptr;
@@ -405,11 +405,11 @@
// - AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION (UNLOCKED only).
// Might occur in either the top-level vbmeta or a chained vbmeta.
// - AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED (UNLOCKED only).
- // Could only occur in a chained vbmeta. Because we have *dummy* operations in
+ // Could only occur in a chained vbmeta. Because we have *no-op* operations in
// FsManagerAvbOps such that avb_ops->validate_vbmeta_public_key() used to validate
// the public key of the top-level vbmeta always pass in userspace here.
//
- // The following verify result won't happen, because the *dummy* operation
+ // The following verify result won't happen, because the *no-op* operation
// avb_ops->read_rollback_index() always returns the minimum value zero. So rollbacked
// vbmeta images, which should be caught in the bootloader stage, won't be detected here.
// - AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX
diff --git a/fs_mgr/libfs_avb/tests/util_test.cpp b/fs_mgr/libfs_avb/tests/util_test.cpp
index 5c388aa..a52a00d 100644
--- a/fs_mgr/libfs_avb/tests/util_test.cpp
+++ b/fs_mgr/libfs_avb/tests/util_test.cpp
@@ -222,7 +222,7 @@
base::FilePath test_dir;
ASSERT_TRUE(base::CreateTemporaryDirInDir(tmp_dir, "list-file-tests.", &test_dir));
- // Generates dummy files to list.
+ // Generates test files to list.
base::FilePath file_path_1 = test_dir.Append("1.txt");
ASSERT_TRUE(base::WriteFile(file_path_1, "1", 1));
base::FilePath file_path_2 = test_dir.Append("2.txt");
@@ -253,7 +253,7 @@
base::FilePath test_dir;
ASSERT_TRUE(base::CreateTemporaryDirInDir(tmp_dir, "list-file-tests.", &test_dir));
- // Generates dummy files to list.
+ // Generates test files to list.
base::FilePath file_path_1 = test_dir.Append("1.txt");
ASSERT_TRUE(base::WriteFile(file_path_1, "1", 1));
base::FilePath file_path_2 = test_dir.Append("2.txt");
@@ -281,7 +281,7 @@
base::FilePath tmp_dir;
ASSERT_TRUE(GetTempDir(&tmp_dir));
- // Generates dummy files to list.
+ // Generates test files to list.
base::FilePath no_such_dir = tmp_dir.Append("not_such_dir");
auto fail = ListFiles(no_such_dir.value());
diff --git a/fs_mgr/liblp/builder_test.cpp b/fs_mgr/liblp/builder_test.cpp
index a21e09e..e4b617a 100644
--- a/fs_mgr/liblp/builder_test.cpp
+++ b/fs_mgr/liblp/builder_test.cpp
@@ -234,7 +234,7 @@
EXPECT_EQ(lba, aligned_lba);
}
- // Sanity check one extent.
+ // Check one extent.
EXPECT_EQ(exported->extents.back().target_data, 3072);
}
diff --git a/fs_mgr/liblp/device_test.cpp b/fs_mgr/liblp/device_test.cpp
index 6af9d94..236fd8d 100644
--- a/fs_mgr/liblp/device_test.cpp
+++ b/fs_mgr/liblp/device_test.cpp
@@ -47,7 +47,7 @@
BlockDeviceInfo device_info;
ASSERT_TRUE(opener.GetInfo(fs_mgr_get_super_partition_name(), &device_info));
- // Sanity check that the device doesn't give us some weird inefficient
+ // Check that the device doesn't give us some weird inefficient
// alignment.
EXPECT_EQ(device_info.alignment % LP_SECTOR_SIZE, 0);
EXPECT_EQ(device_info.logical_block_size % LP_SECTOR_SIZE, 0);
diff --git a/fs_mgr/liblp/partition_opener.cpp b/fs_mgr/liblp/partition_opener.cpp
index 1d4db85..3d3dde6 100644
--- a/fs_mgr/liblp/partition_opener.cpp
+++ b/fs_mgr/liblp/partition_opener.cpp
@@ -49,7 +49,7 @@
// Dynamic System Update is installed to an sdcard, which won't be in
// the boot device list.
//
- // We whitelist because most devices in /dev/block are not valid for
+ // mmcblk* is allowed because most devices in /dev/block are not valid for
// storing fiemaps.
if (android::base::StartsWith(path, "mmcblk")) {
return "/dev/block/" + path;
diff --git a/fs_mgr/liblp/reader.cpp b/fs_mgr/liblp/reader.cpp
index e6fd9f7..24ccc0f 100644
--- a/fs_mgr/liblp/reader.cpp
+++ b/fs_mgr/liblp/reader.cpp
@@ -174,7 +174,7 @@
return false;
}
- // Do basic sanity checks before computing the checksum.
+ // Do basic validity checks before computing the checksum.
if (header.magic != LP_METADATA_HEADER_MAGIC) {
LERROR << "Logical partition metadata has invalid magic value.";
return false;
@@ -255,7 +255,7 @@
LpMetadataHeader& header = metadata->header;
- // Sanity check the table size.
+ // Check the table size.
if (header.tables_size > geometry.metadata_max_size) {
LERROR << "Invalid partition metadata header table size.";
return nullptr;
diff --git a/fs_mgr/liblp/writer.cpp b/fs_mgr/liblp/writer.cpp
index 8bf1ee9..2708efa 100644
--- a/fs_mgr/liblp/writer.cpp
+++ b/fs_mgr/liblp/writer.cpp
@@ -81,8 +81,8 @@
return header_blob + tables;
}
-// Perform sanity checks so we don't accidentally overwrite valid metadata
-// with potentially invalid metadata, or random partition data with metadata.
+// Perform checks so we don't accidentally overwrite valid metadata with
+// potentially invalid metadata, or random partition data with metadata.
static bool ValidateAndSerializeMetadata([[maybe_unused]] const IPartitionOpener& opener,
const LpMetadata& metadata, const std::string& slot_suffix,
std::string* blob) {
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index 95301ff..eaef180 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -310,3 +310,36 @@
auto_gen_config: true,
require_root: true,
}
+
+cc_defaults {
+ name: "snapuserd_defaults",
+ srcs: [
+ "snapuserd.cpp",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror"
+ ],
+
+ static_libs: [
+ "libbase",
+ "liblog",
+ "libdm",
+ ],
+}
+
+cc_binary {
+ name: "snapuserd",
+ defaults: ["snapuserd_defaults"],
+}
+
+cc_binary {
+ name: "snapuserd_ramdisk",
+ stem: "snapuserd",
+ defaults: ["snapuserd_defaults"],
+
+ ramdisk: true,
+ static_executable: true,
+ system_shared_libs: [],
+}
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 3c2c776..a4a3150 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -553,9 +553,8 @@
// This should only be called in recovery.
bool UnmapAllPartitions();
- // Sanity check no snapshot overflows. Note that this returns false negatives if the snapshot
- // overflows, then is remapped and not written afterwards. Hence, the function may only serve
- // as a sanity check.
+ // Check no snapshot overflows. Note that this returns false negatives if the snapshot
+ // overflows, then is remapped and not written afterwards.
bool EnsureNoOverflowSnapshot(LockedFile* lock);
enum class Slot { Unknown, Source, Target };
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 7488bda..b49f99e 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -300,9 +300,9 @@
LOG(ERROR) << "SnapshotStatus has no name.";
return false;
}
- // Sanity check these sizes. Like liblp, we guarantee the partition size
- // is respected, which means it has to be sector-aligned. (This guarantee
- // is useful for locating avb footers correctly). The COW file size, however,
+ // Check these sizes. Like liblp, we guarantee the partition size is
+ // respected, which means it has to be sector-aligned. (This guarantee is
+ // useful for locating avb footers correctly). The COW file size, however,
// can be arbitrarily larger than specified, so we can safely round it up.
if (status->device_size() % kSectorSize != 0) {
LOG(ERROR) << "Snapshot " << status->name()
@@ -351,7 +351,6 @@
}
// The COW file size should have been rounded up to the nearest sector in CreateSnapshot.
- // Sanity check this.
if (status.cow_file_size() % kSectorSize != 0) {
LOG(ERROR) << "Snapshot " << name << " COW file size is not a multiple of the sector size: "
<< status.cow_file_size();
diff --git a/fs_mgr/libsnapshot/snapshot_fuzz.cpp b/fs_mgr/libsnapshot/snapshot_fuzz.cpp
index 5b145c3..aced3ed 100644
--- a/fs_mgr/libsnapshot/snapshot_fuzz.cpp
+++ b/fs_mgr/libsnapshot/snapshot_fuzz.cpp
@@ -141,7 +141,7 @@
const RecoveryCreateSnapshotDevicesArgs& args) {
std::unique_ptr<AutoDevice> device;
if (args.has_metadata_device_object()) {
- device = std::make_unique<DummyAutoDevice>(args.metadata_mounted());
+ device = std::make_unique<NoOpAutoDevice>(args.metadata_mounted());
}
return snapshot->RecoveryCreateSnapshotDevices(device);
}
diff --git a/fs_mgr/libsnapshot/snapshot_fuzz_utils.h b/fs_mgr/libsnapshot/snapshot_fuzz_utils.h
index fa327b8..5319e69 100644
--- a/fs_mgr/libsnapshot/snapshot_fuzz_utils.h
+++ b/fs_mgr/libsnapshot/snapshot_fuzz_utils.h
@@ -35,9 +35,9 @@
class AutoMemBasedDir;
class SnapshotFuzzDeviceInfo;
-class DummyAutoDevice : public AutoDevice {
+class NoOpAutoDevice : public AutoDevice {
public:
- DummyAutoDevice(bool mounted) : AutoDevice(mounted ? "dummy" : "") {}
+ NoOpAutoDevice(bool mounted) : AutoDevice(mounted ? "no_op" : "") {}
};
struct SnapshotTestModule {
diff --git a/fs_mgr/libsnapshot/snapshot_metadata_updater.cpp b/fs_mgr/libsnapshot/snapshot_metadata_updater.cpp
index 051584c..17a0c96 100644
--- a/fs_mgr/libsnapshot/snapshot_metadata_updater.cpp
+++ b/fs_mgr/libsnapshot/snapshot_metadata_updater.cpp
@@ -39,6 +39,8 @@
SnapshotMetadataUpdater::SnapshotMetadataUpdater(MetadataBuilder* builder, uint32_t target_slot,
const DeltaArchiveManifest& manifest)
: builder_(builder), target_suffix_(SlotSuffixForSlotNumber(target_slot)) {
+ partial_update_ = manifest.partial_update();
+
if (!manifest.has_dynamic_partition_metadata()) {
return;
}
@@ -63,7 +65,6 @@
}
}
- partial_update_ = manifest.partial_update();
}
bool SnapshotMetadataUpdater::ShrinkPartitions() const {
@@ -173,9 +174,9 @@
if (iter != groups_.end()) {
continue;
}
- // Update package metadata doesn't have this group. Before deleting it, sanity check that it
- // doesn't have any partitions left. Update metadata shouldn't assign any partitions to this
- // group, so all partitions that originally belong to this group should be moved by
+ // Update package metadata doesn't have this group. Before deleting it, check that it
+ // doesn't have any partitions left. Update metadata shouldn't assign any partitions to
+ // this group, so all partitions that originally belong to this group should be moved by
// MovePartitionsToDefault at this point.
auto existing_partitions_in_group = builder_->ListPartitionsInGroup(existing_group_name);
if (!existing_partitions_in_group.empty()) {
diff --git a/fs_mgr/libsnapshot/snapuserd.cpp b/fs_mgr/libsnapshot/snapuserd.cpp
new file mode 100644
index 0000000..a6ff4fd
--- /dev/null
+++ b/fs_mgr/libsnapshot/snapuserd.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <linux/types.h>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
+#include <libdm/dm.h>
+
+using android::base::unique_fd;
+
+#define DM_USER_MAP_READ 0
+#define DM_USER_MAP_WRITE 1
+
+struct dm_user_message {
+ __u64 seq;
+ __u64 type;
+ __u64 flags;
+ __u64 sector;
+ __u64 len;
+ __u8 buf[];
+};
+
+using namespace android::dm;
+
+static int daemon_main(const std::string& device) {
+ unique_fd block_fd(open(device.c_str(), O_RDWR));
+ if (block_fd < 0) {
+ PLOG(ERROR) << "Unable to open " << device;
+ return 1;
+ }
+
+ unique_fd ctrl_fd(open("/dev/dm-user", O_RDWR));
+ if (ctrl_fd < 0) {
+ PLOG(ERROR) << "Unable to open /dev/dm-user";
+ return 1;
+ }
+
+ size_t buf_size = 1UL << 16;
+ auto buf = std::make_unique<char>(buf_size);
+
+ /* Just keeps pumping messages between userspace and the kernel. We won't
+ * actually be doing anything, but the sequence numbers line up so it'll at
+ * least make forward progress. */
+ while (true) {
+ struct dm_user_message* msg = (struct dm_user_message*)buf.get();
+
+ memset(buf.get(), 0, buf_size);
+
+ ssize_t readed = read(ctrl_fd.get(), buf.get(), buf_size);
+ if (readed < 0) {
+ PLOG(ERROR) << "Control read failed, trying with more space";
+ buf_size *= 2;
+ buf = std::make_unique<char>(buf_size);
+ continue;
+ }
+
+ LOG(DEBUG) << android::base::StringPrintf("read() from dm-user returned %d bytes:",
+ (int)readed);
+ LOG(DEBUG) << android::base::StringPrintf(" msg->seq: 0x%016llx", msg->seq);
+ LOG(DEBUG) << android::base::StringPrintf(" msg->type: 0x%016llx", msg->type);
+ LOG(DEBUG) << android::base::StringPrintf(" msg->flags: 0x%016llx", msg->flags);
+ LOG(DEBUG) << android::base::StringPrintf(" msg->sector: 0x%016llx", msg->sector);
+ LOG(DEBUG) << android::base::StringPrintf(" msg->len: 0x%016llx", msg->len);
+
+ switch (msg->type) {
+ case DM_USER_MAP_READ: {
+ LOG(DEBUG) << android::base::StringPrintf(
+ "Responding to read of sector %lld with %lld bytes data", msg->sector,
+ msg->len);
+
+ if ((sizeof(*msg) + msg->len) > buf_size) {
+ auto old_buf = std::move(buf);
+ buf_size = sizeof(*msg) + msg->len;
+ buf = std::make_unique<char>(buf_size);
+ memcpy(buf.get(), old_buf.get(), sizeof(*msg));
+ msg = (struct dm_user_message*)buf.get();
+ }
+
+ if (lseek(block_fd.get(), msg->sector * 512, SEEK_SET) < 0) {
+ PLOG(ERROR) << "lseek failed: " << device;
+ return 7;
+ }
+ if (!android::base::ReadFully(block_fd.get(), msg->buf, msg->len)) {
+ PLOG(ERROR) << "read failed: " << device;
+ return 7;
+ }
+
+ if (!android::base::WriteFully(ctrl_fd.get(), buf.get(), sizeof(*msg) + msg->len)) {
+ PLOG(ERROR) << "write control failed";
+ return 3;
+ }
+ break;
+ }
+
+ case DM_USER_MAP_WRITE:
+ abort();
+ break;
+ }
+
+ LOG(DEBUG) << "read() finished, next message";
+ }
+
+ return 0;
+}
+
+int main([[maybe_unused]] int argc, char** argv) {
+ android::base::InitLogging(argv, &android::base::KernelLogger);
+ daemon_main(argv[1]);
+ return 0;
+}
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index 82c4262..d56f7f2 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -15,13 +15,17 @@
adb remount tests
---color Dress output with highlighting colors
---help This help
---no-wait-screen Do not wait for display screen to settle
---print-time Report the test duration
---serial Specify device (must if multiple are present)
---wait-adb <duration> adb wait timeout
---wait-fastboot <duration> fastboot wait timeout
+-c --color Dress output with highlighting colors
+-h --help This help
+-D --no-wait-screen Do not wait for display screen to settle
+-t --print-time Report the test duration
+-s --serial Specify device (must if multiple are present)"
+if [ -n "`which timeout`" ]; then
+ USAGE="${USAGE}
+-a --wait-adb <duration> adb wait timeout
+-f --wait-fastboot <duration> fastboot wait timeout"
+fi
+USAGE="${USAGE}
Conditions:
- Must be a userdebug build.
@@ -46,10 +50,10 @@
ESCAPE="`echo | tr '\n' '\033'`"
# A _real_ embedded carriage return character
CR="`echo | tr '\n' '\r'`"
-GREEN="${ESCAPE}[38;5;40m"
-RED="${ESCAPE}[38;5;196m"
-ORANGE="${ESCAPE}[38;5;255:165:0m"
-BLUE="${ESCAPE}[35m"
+GREEN="${ESCAPE}[32m"
+RED="${ESCAPE}[31m"
+YELLOW="${ESCAPE}[33m"
+BLUE="${ESCAPE}[34m"
NORMAL="${ESCAPE}[0m"
TMPDIR=${TMPDIR:-/tmp}
print_time=false
@@ -72,7 +76,7 @@
if [ -n "${ANDROID_SERIAL}" ]; then
grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null
else
- wc -l | grep '^1$' >/dev/null
+ wc -l | grep "^[${SPACE}${TAB}]*1\$" >/dev/null
fi
}
@@ -85,7 +89,7 @@
if [ -n "${ANDROID_SERIAL}" ]; then
grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null
else
- wc -l | grep '^1$' >/dev/null
+ wc -l | grep "^[${SPACE}${TAB}]*1\$" >/dev/null
fi
}
@@ -100,7 +104,7 @@
grep "^${ANDROID_SERIAL}[${SPACE}${TAB}][${SPACE}${TAB}]*recovery\$" >/dev/null
return ${?}
fi
- if echo "${list}" | wc -l | grep '^1$' >/dev/null; then
+ if echo "${list}" | wc -l | grep "^[${SPACE}${TAB}]*1\$" >/dev/null; then
echo "${list}" |
grep "[${SPACE}${TAB}]recovery\$" >/dev/null
return ${?}
@@ -143,7 +147,7 @@
adb logcat "${@}" </dev/null |
tr -d '\r' |
grep -v 'logd : logdr: UID=' |
- sed -e '${/------- beginning of kernel/d}' -e 's/^[0-1][0-9]-[0-3][0-9] //'
+ sed -e '${ /------- beginning of kernel/d }' -e 's/^[0-1][0-9]-[0-3][0-9] //'
}
[ "USAGE: avc_check >/dev/stderr
@@ -160,7 +164,7 @@
if [ -z "${L}" ]; then
return
fi
- echo "${ORANGE}[ WARNING ]${NORMAL} unlabeled sepolicy violations:" >&2
+ echo "${YELLOW}[ WARNING ]${NORMAL} unlabeled sepolicy violations:" >&2
echo "${L}" | sed "s/^/${INDENT}/" >&2
}
@@ -284,7 +288,7 @@
local start=`date +%s`
local duration=
local ret
- if [ -n "${1}" ]; then
+ if [ -n "${1}" -a -n "`which timeout`" ]; then
USB_DEVICE=`usb_devnum --next`
duration=`format_duration ${1}`
echo -n ". . . waiting ${duration}" ${ANDROID_SERIAL} ${USB_ADDRESS} ${USB_DEVICE} "${CR}"
@@ -299,7 +303,7 @@
if [ 0 = ${ret} -a -n "${ACTIVE_SLOT}" ]; then
local active_slot=`get_active_slot`
if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then
- echo "${ORANGE}[ WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}" >&2
+ echo "${YELLOW}[ WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}" >&2
fi
fi
local end=`date +%s`
@@ -359,18 +363,22 @@
echo "(In adb mode `adb_user`)"
else
echo "(USB stack borken for ${USB_ADDRESS})"
- USB_DEVICE=`usb_devnum`
- if [ -n "${USB_DEVICE}" ]; then
- echo "# lsusb -v -s ${USB_DEVICE#dev}"
- local D=`lsusb -v -s ${USB_DEVICE#dev} 2>&1`
- if [ -n "${D}" ]; then
- echo "${D}"
- else
- lsusb -v
+ if [ -n "`which usb_devnum`" ]; then
+ USB_DEVICE=`usb_devnum`
+ if [ -n "`which lsusb`" ]; then
+ if [ -n "${USB_DEVICE}" ]; then
+ echo "# lsusb -v -s ${USB_DEVICE#dev}"
+ local D=`lsusb -v -s ${USB_DEVICE#dev} 2>&1`
+ if [ -n "${D}" ]; then
+ echo "${D}"
+ else
+ lsusb -v
+ fi
+ else
+ echo "# lsusb -v (expected device missing)"
+ lsusb -v
+ fi
fi
- else
- echo "# lsusb -v (expected device missing)"
- lsusb -v
fi >&2
fi
}
@@ -382,7 +390,7 @@
local ret
# fastboot has no wait-for-device, but it does an automatic
# wait and requires (even a nonsensical) command to do so.
- if [ -n "${1}" ]; then
+ if [ -n "${1}" -a -n "`which timeout`" ]; then
USB_DEVICE=`usb_devnum --next`
echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} ${USB_DEVICE} "${CR}"
timeout --preserve-status --signal=KILL ${1} fastboot wait-for-device >/dev/null 2>/dev/null
@@ -398,7 +406,7 @@
if [ 0 = ${ret} -a -n "${ACTIVE_SLOT}" ]; then
local active_slot=`get_active_slot`
if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then
- echo "${ORANGE}[ WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}"
+ echo "${YELLOW}[ WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}"
fi >&2
fi
return ${ret}
@@ -409,7 +417,7 @@
Returns: waits until the device has returned for recovery or optional timeout" ]
recovery_wait() {
local ret
- if [ -n "${1}" ]; then
+ if [ -n "${1}" -a -n "`which timeout`" ]; then
USB_DEVICE=`usb_devnum --next`
echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} ${USB_DEVICE} "${CR}"
timeout --preserve-status --signal=KILL ${1} adb wait-for-recovery 2>/dev/null
@@ -423,7 +431,7 @@
if [ 0 = ${ret} -a -n "${ACTIVE_SLOT}" ]; then
local active_slot=`get_active_slot`
if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then
- echo "${ORANGE}[ WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}"
+ echo "${YELLOW}[ WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}"
fi >&2
fi
return ${ret}
@@ -732,6 +740,7 @@
grep -v \
-e "^\(overlay\|tmpfs\|none\|sysfs\|proc\|selinuxfs\|debugfs\|bpf\) " \
-e "^\(binfmt_misc\|cg2_bpf\|pstore\|tracefs\|adb\|mtp\|ptp\|devpts\) " \
+ -e "^\(ramdumpfs\) " \
-e " functionfs " \
-e "^\(/data/media\|/dev/block/loop[0-9]*\) " \
-e "^rootfs / rootfs rw," \
@@ -753,13 +762,28 @@
## MAINLINE
##
-OPTIONS=`getopt --alternative --unquoted \
- --longoptions help,serial:,colour,color,no-colour,no-color \
- --longoptions wait-adb:,wait-fastboot: \
- --longoptions wait-screen,wait-display \
- --longoptions no-wait-screen,no-wait-display \
- --longoptions gtest_print_time,print-time \
- -- "?hs:" ${*}` ||
+HOSTOS=`uname`
+GETOPTS="--alternative --unquoted
+ --longoptions help,serial:,colour,color,no-colour,no-color
+ --longoptions wait-adb:,wait-fastboot:
+ --longoptions wait-screen,wait-display
+ --longoptions no-wait-screen,no-wait-display
+ --longoptions gtest_print_time,print-time
+ --"
+if [ "Darwin" = "${HOSTOS}" ]; then
+ GETOPTS=
+ USAGE="`echo \"${USAGE}\" |
+ sed 's/--color/ /g
+ 1s/--help/-h/
+ s/--help/ /g
+ s/--no-wait-screen/ /g
+ s/--print-time/ /g
+ 1s/--serial/-s/
+ s/--serial/ /g
+ s/--wait-adb/ /g
+ s/--wait-fastboot/ /g'`"
+fi
+OPTIONS=`getopt ${GETOPTS} "?a:cCdDf:hs:t" ${*}` ||
( echo "${USAGE}" >&2 ; false ) ||
die "getopt failure"
set -- ${OPTIONS}
@@ -775,26 +799,26 @@
export ANDROID_SERIAL=${2}
shift
;;
- --color | --colour)
+ -c | --color | --colour)
color=true
;;
- --no-color | --no-colour)
+ -C | --no-color | --no-colour)
color=false
;;
- --no-wait-display | --no-wait-screen)
+ -D | --no-wait-display | --no-wait-screen)
screen_wait=false
;;
- --wait-display | --wait-screen)
+ -d | --wait-display | --wait-screen)
screen_wait=true
;;
- --print-time | --gtest_print_time)
+ -t | --print-time | --gtest_print_time)
print_time=true
;;
- --wait-adb)
+ -a | --wait-adb)
ADB_WAIT=${2}
shift
;;
- --wait-fastboot)
+ -f | --wait-fastboot)
FASTBOOT_WAIT=${2}
shift
;;
@@ -815,7 +839,7 @@
if ! ${color}; then
GREEN=""
RED=""
- ORANGE=""
+ YELLOW=""
BLUE=""
NORMAL=""
fi
@@ -827,14 +851,14 @@
inFastboot && die "device in fastboot mode"
inRecovery && die "device in recovery mode"
if ! inAdb; then
- echo "${ORANGE}[ WARNING ]${NORMAL} device not in adb mode" >&2
+ echo "${YELLOW}[ WARNING ]${NORMAL} device not in adb mode" >&2
adb_wait ${ADB_WAIT}
fi
inAdb || die "specified device not in adb mode"
isDebuggable || die "device not a debug build"
enforcing=true
if ! adb_su getenforce </dev/null | grep 'Enforcing' >/dev/null; then
- echo "${ORANGE}[ WARNING ]${NORMAL} device does not have sepolicy in enforcing mode" >&2
+ echo "${YELLOW}[ WARNING ]${NORMAL} device does not have sepolicy in enforcing mode" >&2
enforcing=false
fi
@@ -846,9 +870,13 @@
[ -n "${D}" ] || D=`get_property ro.boot.serialno`
[ -z "${D}" -o -n "${ANDROID_SERIAL}" ] || ANDROID_SERIAL=${D}
USB_SERIAL=
-[ -z "${ANDROID_SERIAL}" ] || USB_SERIAL=`find /sys/devices -name serial |
- grep usb |
- xargs -r grep -l ${ANDROID_SERIAL}`
+if [ -n "${ANDROID_SERIAL}" -a "Darwin" != "${HOSTOS}" ]; then
+ USB_SERIAL="`find /sys/devices -name serial | grep usb`"
+ if [ -n "${USB_SERIAL}" ]; then
+ USB_SERIAL=`echo "${USB_SERIAL}" |
+ xargs grep -l ${ANDROID_SERIAL}`
+ fi
+fi
USB_ADDRESS=
if [ -n "${USB_SERIAL}" ]; then
USB_ADDRESS=${USB_SERIAL%/serial}
@@ -860,13 +888,16 @@
BUILD_DESCRIPTION=`get_property ro.build.description`
[ -z "${BUILD_DESCRIPTION}" ] ||
echo "${BLUE}[ INFO ]${NORMAL} ${BUILD_DESCRIPTION}" >&2
+KERNEL_VERSION="`adb_su cat /proc/version </dev/null 2>/dev/null`"
+[ -z "${KERNEL_VERSION}" ] ||
+ echo "${BLUE}[ INFO ]${NORMAL} ${KERNEL_VERSION}" >&2
ACTIVE_SLOT=`get_active_slot`
[ -z "${ACTIVE_SLOT}" ] ||
echo "${BLUE}[ INFO ]${NORMAL} active slot is ${ACTIVE_SLOT}" >&2
# Acquire list of system partitions
-PARTITIONS=`adb_su cat /vendor/etc/fstab* |
+PARTITIONS=`adb_su cat /vendor/etc/fstab* </dev/null |
skip_administrative_mounts |
sed -n "s@^\([^ ${TAB}/][^ ${TAB}/]*\)[ ${TAB}].*[, ${TAB}]ro[, ${TAB}].*@\1@p" |
sort -u |
@@ -903,9 +934,12 @@
done
# If reboot too soon after fresh flash, could trip device update failure logic
+if ${screen_wait}; then
+ echo "${YELLOW}[ WARNING ]${NORMAL} waiting for screen to come up. Consider --no-wait-screen option" >&2
+fi
if ! wait_for_screen && ${screen_wait}; then
screen_wait=false
- echo "${ORANGE}[ WARNING ]${NORMAL} not healthy, no launcher, skipping wait for screen" >&2
+ echo "${YELLOW}[ WARNING ]${NORMAL} not healthy, no launcher, skipping wait for screen" >&2
fi
# Can we test remount -R command?
@@ -954,7 +988,7 @@
adb_su remount -R system </dev/null
err=${?}
if [ "${err}" != 0 ]; then
- echo "${ORANGE}[ WARNING ]${NORMAL} adb shell su root remount -R system = ${err}, likely did not reboot!" >&2
+ echo "${YELLOW}[ WARNING ]${NORMAL} adb shell su root remount -R system = ${err}, likely did not reboot!" >&2
T="-t ${T}"
else
# Rebooted, logcat will be meaningless, and last logcat will likely be clear
@@ -980,7 +1014,7 @@
adb_sh grep "nodev${TAB}overlay" /proc/filesystems </dev/null >/dev/null 2>/dev/null &&
echo "${GREEN}[ OK ]${NORMAL} overlay module present" >&2 ||
(
- echo "${ORANGE}[ WARNING ]${NORMAL} overlay module not present" >&2 &&
+ echo "${YELLOW}[ WARNING ]${NORMAL} overlay module not present" >&2 &&
false
) ||
overlayfs_supported=false
@@ -989,7 +1023,7 @@
echo "${GREEN}[ OK ]${NORMAL} overlay module supports override_creds" >&2 ||
case `adb_sh uname -r </dev/null` in
4.[456789].* | 4.[1-9][0-9]* | [56789].*)
- echo "${ORANGE}[ WARNING ]${NORMAL} overlay module does not support override_creds" >&2 &&
+ echo "${YELLOW}[ WARNING ]${NORMAL} overlay module does not support override_creds" >&2 &&
overlayfs_supported=false
;;
*)
@@ -1011,14 +1045,14 @@
reboot=false
for d in ${OVERLAYFS_BACKING}; do
if adb_sh ls -d /${d}/overlay </dev/null >/dev/null 2>/dev/null; then
- echo "${ORANGE}[ WARNING ]${NORMAL} /${d}/overlay is setup, surgically wiping" >&2
+ echo "${YELLOW}[ WARNING ]${NORMAL} /${d}/overlay is setup, surgically wiping" >&2
adb_sh rm -rf /${d}/overlay </dev/null ||
die "/${d}/overlay wipe"
reboot=true
fi
done
if ${reboot}; then
- echo "${ORANGE}[ WARNING ]${NORMAL} rebooting before test" >&2
+ echo "${YELLOW}[ WARNING ]${NORMAL} rebooting before test" >&2
adb_reboot &&
adb_wait ${ADB_WAIT} ||
die "lost device after reboot after wipe `usb_status`"
@@ -1030,7 +1064,7 @@
D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay "` &&
echo "${H}" &&
echo "${D}" &&
- echo "${ORANGE}[ WARNING ]${NORMAL} overlays present before setup" >&2 ||
+ echo "${YELLOW}[ WARNING ]${NORMAL} overlays present before setup" >&2 ||
echo "${GREEN}[ OK ]${NORMAL} no overlay present before setup" >&2
overlayfs_needed=true
D=`adb_sh cat /proc/mounts </dev/null |
@@ -1083,7 +1117,7 @@
if [ X"${D}" != X"${H}" ]; then
echo "${H}"
if [ X"${D}" != X"${D##*setup failed}" ]; then
- echo "${ORANGE}[ WARNING ]${NORMAL} overlayfs setup whined" >&2
+ echo "${YELLOW}[ WARNING ]${NORMAL} overlayfs setup whined" >&2
fi
D=`adb_sh df -k </dev/null` &&
H=`echo "${D}" | head -1` &&
@@ -1130,7 +1164,7 @@
elif ${rebooted}; then
echo "${GREEN}[ OK ]${NORMAL} verity already disabled" >&2
else
- echo "${ORANGE}[ WARNING ]${NORMAL} verity already disabled" >&2
+ echo "${YELLOW}[ WARNING ]${NORMAL} verity already disabled" >&2
fi
echo "${GREEN}[ RUN ]${NORMAL} remount" >&2
@@ -1160,7 +1194,7 @@
die -t ${T} "overlay takeover failed"
fi
echo "${D}" | grep "^overlay .* /system\$" >/dev/null ||
- echo "${ORANGE}[ WARNING ]${NORMAL} overlay takeover not complete" >&2
+ echo "${YELLOW}[ WARNING ]${NORMAL} overlay takeover not complete" >&2
if [ -z "${virtual_ab}" ]; then
scratch_partition=scratch
fi
@@ -1292,7 +1326,7 @@
fixup_from_recovery() {
inRecovery || return 1
- echo "${ORANGE}[ ERROR ]${NORMAL} Device in recovery" >&2
+ echo "${YELLOW}[ ERROR ]${NORMAL} Device in recovery" >&2
adb reboot </dev/null
adb_wait ${ADB_WAIT}
}
@@ -1312,7 +1346,7 @@
adb_su sed -n '1,/overlay \/system/p' /proc/mounts </dev/null |
skip_administrative_mounts |
grep -v ' \(erofs\|squashfs\|ext4\|f2fs\|vfat\) ' &&
- echo "${ORANGE}[ WARNING ]${NORMAL} overlay takeover after first stage init" >&2 ||
+ echo "${YELLOW}[ WARNING ]${NORMAL} overlay takeover after first stage init" >&2 ||
echo "${GREEN}[ OK ]${NORMAL} overlay takeover in first stage init" >&2
fi
@@ -1373,20 +1407,20 @@
is_userspace_fastboot=false
if ! ${is_bootloader_fastboot}; then
- echo "${ORANGE}[ WARNING ]${NORMAL} does not support fastboot, skipping"
+ echo "${YELLOW}[ WARNING ]${NORMAL} does not support fastboot, skipping"
elif [ -z "${ANDROID_PRODUCT_OUT}" ]; then
- echo "${ORANGE}[ WARNING ]${NORMAL} build tree not setup, skipping"
+ echo "${YELLOW}[ WARNING ]${NORMAL} build tree not setup, skipping"
elif [ ! -s "${ANDROID_PRODUCT_OUT}/vendor.img" ]; then
- echo "${ORANGE}[ WARNING ]${NORMAL} vendor image missing, skipping"
+ echo "${YELLOW}[ WARNING ]${NORMAL} vendor image missing, skipping"
elif [ "${ANDROID_PRODUCT_OUT}" = "${ANDROID_PRODUCT_OUT%*/${H}}" ]; then
- echo "${ORANGE}[ WARNING ]${NORMAL} wrong vendor image, skipping"
+ echo "${YELLOW}[ WARNING ]${NORMAL} wrong vendor image, skipping"
elif [ -z "${ANDROID_HOST_OUT}" ]; then
- echo "${ORANGE}[ WARNING ]${NORMAL} please run lunch, skipping"
+ echo "${YELLOW}[ WARNING ]${NORMAL} please run lunch, skipping"
elif ! (
adb_cat /vendor/build.prop |
cmp -s ${ANDROID_PRODUCT_OUT}/vendor/build.prop
) >/dev/null 2>/dev/null; then
- echo "${ORANGE}[ WARNING ]${NORMAL} vendor image signature mismatch, skipping"
+ echo "${YELLOW}[ WARNING ]${NORMAL} vendor image signature mismatch, skipping"
else
wait_for_screen
avc_check
@@ -1432,7 +1466,7 @@
fi
fastboot reboot ||
die "can not reboot out of fastboot"
- echo "${ORANGE}[ WARNING ]${NORMAL} adb after fastboot"
+ echo "${YELLOW}[ WARNING ]${NORMAL} adb after fastboot"
adb_wait ${ADB_WAIT} ||
fixup_from_recovery ||
die "did not reboot after formatting ${scratch_partition} `usb_status`"
@@ -1449,8 +1483,8 @@
if ${is_userspace_fastboot}; then
die "overlay supposed to be minus /vendor takeover after flash vendor"
else
- echo "${ORANGE}[ WARNING ]${NORMAL} user fastboot missing required to invalidate, ignoring a failure" >&2
- echo "${ORANGE}[ WARNING ]${NORMAL} overlay supposed to be minus /vendor takeover after flash vendor" >&2
+ echo "${YELLOW}[ WARNING ]${NORMAL} user fastboot missing required to invalidate, ignoring a failure" >&2
+ echo "${YELLOW}[ WARNING ]${NORMAL} overlay supposed to be minus /vendor takeover after flash vendor" >&2
fi
fi
B="`adb_cat /system/hello`"
@@ -1468,7 +1502,7 @@
check_eq "cat: /vendor/hello: No such file or directory" "${B}" \
vendor content after flash vendor
else
- echo "${ORANGE}[ WARNING ]${NORMAL} user fastboot missing required to invalidate, ignoring a failure" >&2
+ echo "${YELLOW}[ WARNING ]${NORMAL} user fastboot missing required to invalidate, ignoring a failure" >&2
check_eq "cat: /vendor/hello: No such file or directory" "${B}" \
--warning vendor content after flash vendor
fi
@@ -1489,7 +1523,7 @@
L=
D="${H%?Now reboot your device for settings to take effect*}"
if [ X"${H}" != X"${D}" ]; then
- echo "${ORANGE}[ WARNING ]${NORMAL} adb remount requires a reboot after partial flash (legacy avb)"
+ echo "${YELLOW}[ WARNING ]${NORMAL} adb remount requires a reboot after partial flash (legacy avb)"
L=`adb_logcat -b all -v nsec -t ${T} 2>&1`
adb_reboot &&
adb_wait ${ADB_WAIT} &&
@@ -1547,7 +1581,7 @@
err=${?}
if [ X"${D}" != "${D%?Now reboot your device for settings to take effect*}" ]
then
- echo "${ORANGE}[ WARNING ]${NORMAL} adb disable-verity requires a reboot after partial flash"
+ echo "${YELLOW}[ WARNING ]${NORMAL} adb disable-verity requires a reboot after partial flash"
adb_reboot &&
adb_wait ${ADB_WAIT} &&
adb_root ||
@@ -1580,9 +1614,9 @@
if [ -n "${ACTIVE_SLOT}" ]; then
local active_slot=`get_active_slot`
if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then
- echo "${ORANGE}[ ERROR ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}"
+ echo "${YELLOW}[ ERROR ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}"
else
- echo "${ORANGE}[ ERROR ]${NORMAL} Active slot to be set to ${ACTIVE_SLOT}"
+ echo "${YELLOW}[ ERROR ]${NORMAL} Active slot to be set to ${ACTIVE_SLOT}"
fi >&2
fastboot --set-active=${ACTIVE_SLOT}
fi
diff --git a/init/block_dev_initializer.cpp b/init/block_dev_initializer.cpp
index b423f86..8db9793 100644
--- a/init/block_dev_initializer.cpp
+++ b/init/block_dev_initializer.cpp
@@ -37,7 +37,15 @@
}
bool BlockDevInitializer::InitDeviceMapper() {
- const std::string dm_path = "/devices/virtual/misc/device-mapper";
+ return InitMiscDevice("device-mapper");
+}
+
+bool BlockDevInitializer::InitDmUser() {
+ return InitMiscDevice("dm-user");
+}
+
+bool BlockDevInitializer::InitMiscDevice(const std::string& name) {
+ const std::string dm_path = "/devices/virtual/misc/" + name;
bool found = false;
auto dm_callback = [this, &dm_path, &found](const Uevent& uevent) {
if (uevent.path == dm_path) {
@@ -49,13 +57,13 @@
};
uevent_listener_.RegenerateUeventsForPath("/sys" + dm_path, dm_callback);
if (!found) {
- LOG(INFO) << "device-mapper device not found in /sys, waiting for its uevent";
+ LOG(INFO) << name << " device not found in /sys, waiting for its uevent";
Timer t;
uevent_listener_.Poll(dm_callback, 10s);
- LOG(INFO) << "Wait for device-mapper returned after " << t;
+ LOG(INFO) << "Wait for " << name << " returned after " << t;
}
if (!found) {
- LOG(ERROR) << "device-mapper device not found after polling timeout";
+ LOG(ERROR) << name << " device not found after polling timeout";
return false;
}
return true;
diff --git a/init/block_dev_initializer.h b/init/block_dev_initializer.h
index 0d4c6e9..b8dd3f1 100644
--- a/init/block_dev_initializer.h
+++ b/init/block_dev_initializer.h
@@ -27,12 +27,15 @@
BlockDevInitializer();
bool InitDeviceMapper();
+ bool InitDmUser();
bool InitDevices(std::set<std::string> devices);
bool InitDmDevice(const std::string& device);
private:
ListenerAction HandleUevent(const Uevent& uevent, std::set<std::string>* devices);
+ bool InitMiscDevice(const std::string& name);
+
std::unique_ptr<DeviceHandler> device_handler_;
UeventListener uevent_listener_;
};
diff --git a/init/init.cpp b/init/init.cpp
index ba880ea..cb5bbba 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -18,6 +18,7 @@
#include <dirent.h>
#include <fcntl.h>
+#include <paths.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
@@ -727,6 +728,12 @@
InitSecondStageLogging(argv);
LOG(INFO) << "init second stage started!";
+ // Update $PATH in the case the second stage init is newer than first stage init, where it is
+ // first set.
+ if (setenv("PATH", _PATH_DEFPATH, 1) != 0) {
+ PLOG(FATAL) << "Could not set $PATH to '" << _PATH_DEFPATH << "' in second stage";
+ }
+
// Init should not crash because of a dependence on any other process, therefore we ignore
// SIGPIPE and handle EPIPE at the call site directly. Note that setting a signal to SIG_IGN
// is inherited across exec, but custom signal handlers are not. Since we do not want to
diff --git a/init/mount_namespace.cpp b/init/mount_namespace.cpp
index f8359bc..59cc140 100644
--- a/init/mount_namespace.cpp
+++ b/init/mount_namespace.cpp
@@ -44,50 +44,17 @@
namespace init {
namespace {
-static bool BindMount(const std::string& source, const std::string& mount_point,
- bool recursive = false) {
- unsigned long mountflags = MS_BIND;
- if (recursive) {
- mountflags |= MS_REC;
- }
- if (mount(source.c_str(), mount_point.c_str(), nullptr, mountflags, nullptr) == -1) {
+static bool BindMount(const std::string& source, const std::string& mount_point) {
+ if (mount(source.c_str(), mount_point.c_str(), nullptr, MS_BIND | MS_REC, nullptr) == -1) {
PLOG(ERROR) << "Failed to bind mount " << source;
return false;
}
return true;
}
-static bool MakeShared(const std::string& mount_point, bool recursive = false) {
- unsigned long mountflags = MS_SHARED;
- if (recursive) {
- mountflags |= MS_REC;
- }
+static bool ChangeMount(const std::string& mount_point, unsigned long mountflags) {
if (mount(nullptr, mount_point.c_str(), nullptr, mountflags, nullptr) == -1) {
- PLOG(ERROR) << "Failed to change propagation type to shared";
- return false;
- }
- return true;
-}
-
-static bool MakeSlave(const std::string& mount_point, bool recursive = false) {
- unsigned long mountflags = MS_SLAVE;
- if (recursive) {
- mountflags |= MS_REC;
- }
- if (mount(nullptr, mount_point.c_str(), nullptr, mountflags, nullptr) == -1) {
- PLOG(ERROR) << "Failed to change propagation type to slave";
- return false;
- }
- return true;
-}
-
-static bool MakePrivate(const std::string& mount_point, bool recursive = false) {
- unsigned long mountflags = MS_PRIVATE;
- if (recursive) {
- mountflags |= MS_REC;
- }
- if (mount(nullptr, mount_point.c_str(), nullptr, mountflags, nullptr) == -1) {
- PLOG(ERROR) << "Failed to change propagation type to private";
+ PLOG(ERROR) << "Failed to remount " << mount_point << " as " << std::hex << mountflags;
return false;
}
return true;
@@ -225,17 +192,17 @@
// needed for /foo/bar, then we will make /foo/bar as a mount point (by
// bind-mounting by to itself) and set the propagation type of the mount
// point to private.
- if (!MakeShared("/", true /*recursive*/)) return false;
+ if (!ChangeMount("/", MS_SHARED | MS_REC)) return false;
// /apex is a private mountpoint to give different sets of APEXes for
// the bootstrap and default mount namespaces. The processes running with
// the bootstrap namespace get APEXes from the read-only partition.
- if (!(MakePrivate("/apex"))) return false;
+ if (!(ChangeMount("/apex", MS_PRIVATE))) return false;
// /linkerconfig is a private mountpoint to give a different linker configuration
// based on the mount namespace. Subdirectory will be bind-mounted based on current mount
// namespace
- if (!(MakePrivate("/linkerconfig"))) return false;
+ if (!(ChangeMount("/linkerconfig", MS_PRIVATE))) return false;
// The two mount namespaces present challenges for scoped storage, because
// vold, which is responsible for most of the mounting, lives in the
@@ -266,15 +233,15 @@
if (!mkdir_recursive("/mnt/user", 0755)) return false;
if (!mkdir_recursive("/mnt/installer", 0755)) return false;
if (!mkdir_recursive("/mnt/androidwritable", 0755)) return false;
- if (!(BindMount("/mnt/user", "/mnt/installer", true))) return false;
- if (!(BindMount("/mnt/user", "/mnt/androidwritable", true))) return false;
+ if (!(BindMount("/mnt/user", "/mnt/installer"))) return false;
+ if (!(BindMount("/mnt/user", "/mnt/androidwritable"))) return false;
// First, make /mnt/installer and /mnt/androidwritable a slave bind mount
- if (!(MakeSlave("/mnt/installer"))) return false;
- if (!(MakeSlave("/mnt/androidwritable"))) return false;
+ if (!(ChangeMount("/mnt/installer", MS_SLAVE))) return false;
+ if (!(ChangeMount("/mnt/androidwritable", MS_SLAVE))) return false;
// Then, make it shared again - effectively creating a new peer group, that
// will be inherited by new mount namespaces.
- if (!(MakeShared("/mnt/installer"))) return false;
- if (!(MakeShared("/mnt/androidwritable"))) return false;
+ if (!(ChangeMount("/mnt/installer", MS_SHARED))) return false;
+ if (!(ChangeMount("/mnt/androidwritable", MS_SHARED))) return false;
bootstrap_ns_fd.reset(OpenMountNamespace());
bootstrap_ns_id = GetMountNamespaceId();
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 0c4a3c4..a1e0969 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -632,10 +632,11 @@
char *key, *value, *eol, *sol, *tmp, *fn;
size_t flen = 0;
- static constexpr const char* const kVendorPathPrefixes[3] = {
+ static constexpr const char* const kVendorPathPrefixes[4] = {
"/vendor",
"/odm",
"/vendor_dlkm",
+ "/odm_dlkm",
};
const char* context = kInitContext;
@@ -941,6 +942,7 @@
// }
load_properties_from_file("/vendor/build.prop", nullptr, &properties);
load_properties_from_file("/vendor_dlkm/etc/build.prop", nullptr, &properties);
+ load_properties_from_file("/odm_dlkm/etc/build.prop", nullptr, &properties);
load_properties_from_partition("odm", /* support_legacy_path_until */ 28);
load_properties_from_partition("product", /* support_legacy_path_until */ 30);
@@ -992,7 +994,7 @@
&property_infos)) {
return;
}
- // Don't check for failure here, so we always have a sane list of properties.
+ // Don't check for failure here, since we don't always have all of these partitions.
// E.g. In case of recovery, the vendor partition will not have mounted and we
// still need the system / platform properties to function.
if (access("/system_ext/etc/selinux/system_ext_property_contexts", R_OK) != -1) {
diff --git a/init/service_utils.cpp b/init/service_utils.cpp
index 05e632b..f2383d7 100644
--- a/init/service_utils.cpp
+++ b/init/service_utils.cpp
@@ -60,13 +60,14 @@
Result<void> SetUpMountNamespace(bool remount_proc, bool remount_sys) {
constexpr unsigned int kSafeFlags = MS_NODEV | MS_NOEXEC | MS_NOSUID;
- // Recursively remount / as slave like zygote does so unmounting and mounting /proc
- // doesn't interfere with the parent namespace's /proc mount. This will also
- // prevent any other mounts/unmounts initiated by the service from interfering
- // with the parent namespace but will still allow mount events from the parent
+ // Recursively remount / as MS_SLAVE like zygote does so that
+ // unmounting and mounting /proc doesn't interfere with the parent
+ // namespace's /proc mount. This will also prevent any other
+ // mounts/unmounts initiated by the service from interfering with the
+ // parent namespace but will still allow mount events from the parent
// namespace to propagate to the child.
if (mount("rootfs", "/", nullptr, (MS_SLAVE | MS_REC), nullptr) == -1) {
- return ErrnoError() << "Could not remount(/) recursively as slave";
+ return ErrnoError() << "Could not remount(/) recursively as MS_SLAVE";
}
// umount() then mount() /proc and/or /sys
diff --git a/init/test_kill_services/init_kill_services_test.cpp b/init/test_kill_services/init_kill_services_test.cpp
index 7e543f2..66a3328 100644
--- a/init/test_kill_services/init_kill_services_test.cpp
+++ b/init/test_kill_services/init_kill_services_test.cpp
@@ -54,7 +54,7 @@
TEST_P(InitKillServicesTest, KillCriticalProcesses) {
ExpectKillingServiceRecovers(GetParam());
- // sanity check init is still responding
+ // Ensure that init is still responding
EXPECT_TRUE(SetProperty("test.death.test", "asdf"));
EXPECT_EQ(GetProperty("test.death.test", ""), "asdf");
EXPECT_TRUE(SetProperty("test.death.test", ""));
diff --git a/init/uevent_listener.cpp b/init/uevent_listener.cpp
index d8d9b36..7cd396a 100644
--- a/init/uevent_listener.cpp
+++ b/init/uevent_listener.cpp
@@ -95,20 +95,18 @@
fcntl(device_fd_, F_SETFL, O_NONBLOCK);
}
-bool UeventListener::ReadUevent(Uevent* uevent) const {
+ReadUeventResult UeventListener::ReadUevent(Uevent* uevent) const {
char msg[UEVENT_MSG_LEN + 2];
int n = uevent_kernel_multicast_recv(device_fd_, msg, UEVENT_MSG_LEN);
if (n <= 0) {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
PLOG(ERROR) << "Error reading from Uevent Fd";
}
- return false;
+ return ReadUeventResult::kFailed;
}
if (n >= UEVENT_MSG_LEN) {
LOG(ERROR) << "Uevent overflowed buffer, discarding";
- // Return true here even if we discard as we may have more uevents pending and we
- // want to keep processing them.
- return true;
+ return ReadUeventResult::kInvalid;
}
msg[n] = '\0';
@@ -116,7 +114,7 @@
ParseEvent(msg, uevent);
- return true;
+ return ReadUeventResult::kSuccess;
}
// RegenerateUevents*() walks parts of the /sys tree and pokes the uevent files to cause the kernel
@@ -137,7 +135,10 @@
close(fd);
Uevent uevent;
- while (ReadUevent(&uevent)) {
+ ReadUeventResult result;
+ while ((result = ReadUevent(&uevent)) != ReadUeventResult::kFailed) {
+ // Skip processing the uevent if it is invalid.
+ if (result == ReadUeventResult::kInvalid) continue;
if (callback(uevent) == ListenerAction::kStop) return ListenerAction::kStop;
}
}
@@ -212,7 +213,10 @@
// We're non-blocking, so if we receive a poll event keep processing until
// we have exhausted all uevent messages.
Uevent uevent;
- while (ReadUevent(&uevent)) {
+ ReadUeventResult result;
+ while ((result = ReadUevent(&uevent)) != ReadUeventResult::kFailed) {
+ // Skip processing the uevent if it is invalid.
+ if (result == ReadUeventResult::kInvalid) continue;
if (callback(uevent) == ListenerAction::kStop) return;
}
}
diff --git a/init/uevent_listener.h b/init/uevent_listener.h
index aea094e..2772860 100644
--- a/init/uevent_listener.h
+++ b/init/uevent_listener.h
@@ -27,7 +27,7 @@
#include "uevent.h"
-#define UEVENT_MSG_LEN 2048
+#define UEVENT_MSG_LEN 8192
namespace android {
namespace init {
@@ -37,6 +37,12 @@
kContinue, // Continue regenerating uevents as we haven't seen the one(s) we're interested in.
};
+enum class ReadUeventResult {
+ kSuccess = 0, // Uevent was successfully read.
+ kFailed, // Uevent reading has failed.
+ kInvalid, // An Invalid Uevent was read (like say, the msg received is >= UEVENT_MSG_LEN).
+};
+
using ListenerCallback = std::function<ListenerAction(const Uevent&)>;
class UeventListener {
@@ -50,7 +56,7 @@
const std::optional<std::chrono::milliseconds> relative_timeout = {}) const;
private:
- bool ReadUevent(Uevent* uevent) const;
+ ReadUeventResult ReadUevent(Uevent* uevent) const;
ListenerAction RegenerateUeventsForDir(DIR* d, const ListenerCallback& callback) const;
android::base::unique_fd device_fd_;
diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp
index f4191b9..cc32b6d 100644
--- a/libbacktrace/backtrace_test.cpp
+++ b/libbacktrace/backtrace_test.cpp
@@ -1584,7 +1584,7 @@
// Verify the flag is set.
ASSERT_EQ(PROT_DEVICE_MAP, map.flags & PROT_DEVICE_MAP);
- // Quick sanity checks.
+ // Quick basic checks of functionality.
uint64_t offset;
ASSERT_EQ(std::string(""), backtrace->GetFunctionName(device_map_uint, &offset));
ASSERT_EQ(std::string(""), backtrace->GetFunctionName(device_map_uint, &offset, &map));
diff --git a/libcutils/ashmem-dev.cpp b/libcutils/ashmem-dev.cpp
index 8c232f0..20cd659 100644
--- a/libcutils/ashmem-dev.cpp
+++ b/libcutils/ashmem-dev.cpp
@@ -122,7 +122,8 @@
return true;
}
- /* If its not a number, assume string, but check if its a sane string */
+ // Non-numeric should be a single ASCII character. Characters after the
+ // first are ignored.
if (tolower(vndk_version[0]) < 'a' || tolower(vndk_version[0]) > 'z') {
ALOGE("memfd: ro.vndk.version not defined or invalid (%s), this is mandated since P.\n",
vndk_version.c_str());
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index 5805a4d..b9fc82e 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -203,6 +203,7 @@
{ 00755, AID_ROOT, AID_ROOT, 0, "first_stage_ramdisk/system/bin/e2fsck" },
{ 00755, AID_ROOT, AID_ROOT, 0, "first_stage_ramdisk/system/bin/tune2fs" },
{ 00755, AID_ROOT, AID_ROOT, 0, "first_stage_ramdisk/system/bin/resize2fs" },
+ { 00755, AID_ROOT, AID_ROOT, 0, "first_stage_ramdisk/system/bin/snapuserd" },
// generic defaults
{ 00755, AID_ROOT, AID_ROOT, 0, "bin/*" },
{ 00640, AID_ROOT, AID_SHELL, 0, "fstab.*" },
diff --git a/libcutils/include/private/android_filesystem_config.h b/libcutils/include/private/android_filesystem_config.h
index e4f45a8..b4fe2e6 100644
--- a/libcutils/include/private/android_filesystem_config.h
+++ b/libcutils/include/private/android_filesystem_config.h
@@ -36,7 +36,7 @@
#pragma once
-/* This is the master Users and Groups config for the platform.
+/* This is the main Users and Groups config for the platform.
* DO NOT EVER RENUMBER
*/
diff --git a/libcutils/qtaguid.cpp b/libcutils/qtaguid.cpp
index b94d134..2fe877c 100644
--- a/libcutils/qtaguid.cpp
+++ b/libcutils/qtaguid.cpp
@@ -38,24 +38,24 @@
int (*netdDeleteTagData)(uint32_t, uid_t);
};
-int dummyTagSocket(int, uint32_t, uid_t) {
+int stubTagSocket(int, uint32_t, uid_t) {
return -EREMOTEIO;
}
-int dummyUntagSocket(int) {
+int stubUntagSocket(int) {
return -EREMOTEIO;
}
-int dummySetCounterSet(uint32_t, uid_t) {
+int stubSetCounterSet(uint32_t, uid_t) {
return -EREMOTEIO;
}
-int dummyDeleteTagData(uint32_t, uid_t) {
+int stubDeleteTagData(uint32_t, uid_t) {
return -EREMOTEIO;
}
netdHandler initHandler(void) {
- netdHandler handler = {dummyTagSocket, dummyUntagSocket, dummySetCounterSet, dummyDeleteTagData};
+ netdHandler handler = {stubTagSocket, stubUntagSocket, stubSetCounterSet, stubDeleteTagData};
void* netdClientHandle = dlopen("libnetd_client.so", RTLD_NOW);
if (!netdClientHandle) {
diff --git a/libkeyutils/keyutils_test.cpp b/libkeyutils/keyutils_test.cpp
index d41c91b..d03747b 100644
--- a/libkeyutils/keyutils_test.cpp
+++ b/libkeyutils/keyutils_test.cpp
@@ -33,7 +33,7 @@
#include <gtest/gtest.h>
TEST(keyutils, smoke) {
- // Check that the exported type is sane.
+ // Check that the exported type is the right size.
ASSERT_EQ(4U, sizeof(key_serial_t));
// Check that all the functions actually exist.
diff --git a/liblog/Android.bp b/liblog/Android.bp
index 6051ac7..3a91969 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -17,6 +17,7 @@
liblog_sources = [
"log_event_list.cpp",
"log_event_write.cpp",
+ "log_size.cpp",
"logger_name.cpp",
"logger_read.cpp",
"logger_write.cpp",
diff --git a/liblog/include/log/log_properties.h b/liblog/include/log/log_properties.h
index 3497d63..2a0230f 100644
--- a/liblog/include/log/log_properties.h
+++ b/liblog/include/log/log_properties.h
@@ -20,6 +20,7 @@
extern "C" {
#endif
+/* Returns `1` if the device is debuggable or `0` if not. */
int __android_log_is_debuggable();
#ifdef __cplusplus
diff --git a/liblog/include/private/android_logger.h b/liblog/include/private/android_logger.h
index d3b72bc..de4c430 100644
--- a/liblog/include/private/android_logger.h
+++ b/liblog/include/private/android_logger.h
@@ -144,14 +144,6 @@
int __android_log_security_bswrite(int32_t tag, const char* payload);
int __android_log_security(); /* Device Owner is present */
-#define BOOL_DEFAULT_FLAG_TRUE_FALSE 0x1
-#define BOOL_DEFAULT_FALSE 0x0 /* false if property not present */
-#define BOOL_DEFAULT_TRUE 0x1 /* true if property not present */
-#define BOOL_DEFAULT_FLAG_PERSIST 0x2 /* <key>, persist.<key>, ro.<key> */
-#define BOOL_DEFAULT_FLAG_ENG 0x4 /* off for user */
-#define BOOL_DEFAULT_FLAG_SVELTE 0x8 /* off for low_ram */
-bool __android_logger_property_get_bool(const char* key, int flag);
-
#define LOG_BUFFER_SIZE (256 * 1024) /* Tuned with ro.logd.size per-platform \
*/
#define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
diff --git a/liblog/liblog.map.txt b/liblog/liblog.map.txt
index 161fcf1..2e01101 100644
--- a/liblog/liblog.map.txt
+++ b/liblog/liblog.map.txt
@@ -85,7 +85,6 @@
__android_log_pmsg_file_read;
__android_log_pmsg_file_write;
__android_logger_get_buffer_size;
- __android_logger_property_get_bool;
android_openEventTagMap;
android_log_processBinaryLogBuffer;
android_log_processLogBuffer;
diff --git a/liblog/log_size.cpp b/liblog/log_size.cpp
new file mode 100644
index 0000000..7f13c8c
--- /dev/null
+++ b/liblog/log_size.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <private/android_logger.h>
+
+#include <array>
+#include <optional>
+#include <string>
+
+#include <android-base/parseint.h>
+
+#ifdef __ANDROID__
+#include <sys/system_properties.h>
+#endif
+
+bool __android_logger_valid_buffer_size(unsigned long value) {
+ return LOG_BUFFER_MIN_SIZE <= value && value <= LOG_BUFFER_MAX_SIZE;
+}
+
+#ifdef __ANDROID__
+
+static std::optional<unsigned long> GetBufferSizeProperty(const std::string& key) {
+ char value[PROP_VALUE_MAX] = {};
+ if (__system_property_get(key.c_str(), value) <= 0) {
+ return {};
+ }
+
+ uint32_t size;
+ if (!android::base::ParseByteCount(value, &size)) {
+ return {};
+ }
+
+ if (!__android_logger_valid_buffer_size(size)) {
+ return {};
+ }
+
+ return size;
+}
+
+unsigned long __android_logger_get_buffer_size(log_id_t log_id) {
+ std::string buffer_name = android_log_id_to_name(log_id);
+ std::array<std::string, 4> properties = {
+ "persist.logd.size." + buffer_name,
+ "ro.logd.size." + buffer_name,
+ "persist.logd.size",
+ "ro.logd.size",
+ };
+
+ for (const auto& property : properties) {
+ if (auto size = GetBufferSizeProperty(property)) {
+ return *size;
+ }
+ }
+
+ char value[PROP_VALUE_MAX] = {};
+ if (__system_property_get("ro.config.low_ram", value) > 0 && !strcmp(value, "true")) {
+ return LOG_BUFFER_MIN_SIZE;
+ }
+
+ return LOG_BUFFER_SIZE;
+}
+
+#else
+
+// Default to 1MB for host.
+unsigned long __android_logger_get_buffer_size(log_id_t) {
+ return 1024 * 1024;
+}
+
+#endif
\ No newline at end of file
diff --git a/liblog/properties.cpp b/liblog/properties.cpp
index 2392112..88f0bf1 100644
--- a/liblog/properties.cpp
+++ b/liblog/properties.cpp
@@ -294,33 +294,12 @@
}
int __android_log_is_debuggable() {
- static uint32_t serial;
- static struct cache_char tag_cache;
- static const char key[] = "ro.debuggable";
- int ret;
+ static int is_debuggable = [] {
+ char value[PROP_VALUE_MAX] = {};
+ return __system_property_get("ro.debuggable", value) > 0 && !strcmp(value, "1");
+ }();
- if (tag_cache.c) { /* ro property does not change after set */
- ret = tag_cache.c == '1';
- } else if (lock()) {
- struct cache_char temp_cache = {{NULL, 0xFFFFFFFF}, '\0'};
- refresh_cache(&temp_cache, key);
- ret = temp_cache.c == '1';
- } else {
- int change_detected = check_cache(&tag_cache.cache);
- uint32_t current_serial = __system_property_area_serial();
- if (current_serial != serial) {
- change_detected = 1;
- }
- if (change_detected) {
- refresh_cache(&tag_cache, key);
- serial = current_serial;
- }
- ret = tag_cache.c == '1';
-
- unlock();
- }
-
- return ret;
+ return is_debuggable;
}
/*
@@ -385,216 +364,6 @@
return do_cache2_char(&security);
}
-/*
- * Interface that represents the logd buffer size determination so that others
- * need not guess our intentions.
- */
-
-/* Property helper */
-static bool check_flag(const char* prop, const char* flag) {
- const char* cp = strcasestr(prop, flag);
- if (!cp) {
- return false;
- }
- /* We only will document comma (,) */
- static const char sep[] = ",:;|+ \t\f";
- if ((cp != prop) && !strchr(sep, cp[-1])) {
- return false;
- }
- cp += strlen(flag);
- return !*cp || !!strchr(sep, *cp);
-}
-
-/* cache structure */
-struct cache_property {
- struct cache cache;
- char property[PROP_VALUE_MAX];
-};
-
-static void refresh_cache_property(struct cache_property* cache, const char* key) {
- if (!cache->cache.pinfo) {
- cache->cache.pinfo = __system_property_find(key);
- if (!cache->cache.pinfo) {
- return;
- }
- }
- cache->cache.serial = __system_property_serial(cache->cache.pinfo);
- __system_property_read(cache->cache.pinfo, 0, cache->property);
-}
-
-/* get boolean with the logger twist that supports eng adjustments */
-bool __android_logger_property_get_bool(const char* key, int flag) {
- struct cache_property property = {{NULL, 0xFFFFFFFF}, {0}};
- if (flag & BOOL_DEFAULT_FLAG_PERSIST) {
- char newkey[strlen("persist.") + strlen(key) + 1];
- snprintf(newkey, sizeof(newkey), "ro.%s", key);
- refresh_cache_property(&property, newkey);
- property.cache.pinfo = NULL;
- property.cache.serial = 0xFFFFFFFF;
- snprintf(newkey, sizeof(newkey), "persist.%s", key);
- refresh_cache_property(&property, newkey);
- property.cache.pinfo = NULL;
- property.cache.serial = 0xFFFFFFFF;
- }
-
- refresh_cache_property(&property, key);
-
- if (check_flag(property.property, "true")) {
- return true;
- }
- if (check_flag(property.property, "false")) {
- return false;
- }
- if (property.property[0]) {
- flag &= ~(BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE);
- }
- if (check_flag(property.property, "eng")) {
- flag |= BOOL_DEFAULT_FLAG_ENG;
- }
- /* this is really a "not" flag */
- if (check_flag(property.property, "svelte")) {
- flag |= BOOL_DEFAULT_FLAG_SVELTE;
- }
-
- /* Sanity Check */
- if (flag & (BOOL_DEFAULT_FLAG_SVELTE | BOOL_DEFAULT_FLAG_ENG)) {
- flag &= ~BOOL_DEFAULT_FLAG_TRUE_FALSE;
- flag |= BOOL_DEFAULT_TRUE;
- }
-
- if ((flag & BOOL_DEFAULT_FLAG_SVELTE) &&
- __android_logger_property_get_bool("ro.config.low_ram", BOOL_DEFAULT_FALSE)) {
- return false;
- }
- if ((flag & BOOL_DEFAULT_FLAG_ENG) && !__android_log_is_debuggable()) {
- return false;
- }
-
- return (flag & BOOL_DEFAULT_FLAG_TRUE_FALSE) != BOOL_DEFAULT_FALSE;
-}
-
-bool __android_logger_valid_buffer_size(unsigned long value) {
- return LOG_BUFFER_MIN_SIZE <= value && value <= LOG_BUFFER_MAX_SIZE;
-}
-
-struct cache2_property_size {
- pthread_mutex_t lock;
- uint32_t serial;
- const char* key_persist;
- struct cache_property cache_persist;
- const char* key_ro;
- struct cache_property cache_ro;
- unsigned long (*const evaluate)(const struct cache2_property_size* self);
-};
-
-static inline unsigned long do_cache2_property_size(struct cache2_property_size* self) {
- uint32_t current_serial;
- int change_detected;
- unsigned long v;
-
- if (pthread_mutex_trylock(&self->lock)) {
- /* We are willing to accept some race in this context */
- return self->evaluate(self);
- }
-
- change_detected = check_cache(&self->cache_persist.cache) || check_cache(&self->cache_ro.cache);
- current_serial = __system_property_area_serial();
- if (current_serial != self->serial) {
- change_detected = 1;
- }
- if (change_detected) {
- refresh_cache_property(&self->cache_persist, self->key_persist);
- refresh_cache_property(&self->cache_ro, self->key_ro);
- self->serial = current_serial;
- }
- v = self->evaluate(self);
-
- pthread_mutex_unlock(&self->lock);
-
- return v;
-}
-
-static unsigned long property_get_size_from_cache(const struct cache_property* cache) {
- char* cp;
- unsigned long value = strtoul(cache->property, &cp, 10);
-
- switch (*cp) {
- case 'm':
- case 'M':
- value *= 1024;
- [[fallthrough]];
- case 'k':
- case 'K':
- value *= 1024;
- [[fallthrough]];
- case '\0':
- break;
-
- default:
- value = 0;
- }
-
- if (!__android_logger_valid_buffer_size(value)) {
- value = 0;
- }
-
- return value;
-}
-
-static unsigned long evaluate_property_get_size(const struct cache2_property_size* self) {
- unsigned long size = property_get_size_from_cache(&self->cache_persist);
- if (size) {
- return size;
- }
- return property_get_size_from_cache(&self->cache_ro);
-}
-
-unsigned long __android_logger_get_buffer_size(log_id_t logId) {
- static const char global_tunable[] = "persist.logd.size"; /* Settings App */
- static const char global_default[] = "ro.logd.size"; /* BoardConfig.mk */
- static struct cache2_property_size global = {
- /* clang-format off */
- PTHREAD_MUTEX_INITIALIZER, 0,
- global_tunable, { { NULL, 0xFFFFFFFF }, {} },
- global_default, { { NULL, 0xFFFFFFFF }, {} },
- evaluate_property_get_size
- /* clang-format on */
- };
- char key_persist[strlen(global_tunable) + strlen(".security") + 1];
- char key_ro[strlen(global_default) + strlen(".security") + 1];
- struct cache2_property_size local = {
- /* clang-format off */
- PTHREAD_MUTEX_INITIALIZER, 0,
- key_persist, { { NULL, 0xFFFFFFFF }, {} },
- key_ro, { { NULL, 0xFFFFFFFF }, {} },
- evaluate_property_get_size
- /* clang-format on */
- };
- unsigned long property_size, default_size;
-
- default_size = do_cache2_property_size(&global);
- if (!default_size) {
- default_size = __android_logger_property_get_bool("ro.config.low_ram", BOOL_DEFAULT_FALSE)
- ? LOG_BUFFER_MIN_SIZE /* 64K */
- : LOG_BUFFER_SIZE; /* 256K */
- }
-
- snprintf(key_persist, sizeof(key_persist), "%s.%s", global_tunable,
- android_log_id_to_name(logId));
- snprintf(key_ro, sizeof(key_ro), "%s.%s", global_default, android_log_id_to_name(logId));
- property_size = do_cache2_property_size(&local);
-
- if (!property_size) {
- property_size = default_size;
- }
-
- if (!property_size) {
- property_size = LOG_BUFFER_SIZE;
- }
-
- return property_size;
-}
-
#else
int __android_log_is_loggable(int prio, const char*, int) {
@@ -613,4 +382,4 @@
return 1;
}
-#endif
\ No newline at end of file
+#endif
diff --git a/liblog/tests/Android.bp b/liblog/tests/Android.bp
index 2a6424b..a17d90c 100644
--- a/liblog/tests/Android.bp
+++ b/liblog/tests/Android.bp
@@ -97,6 +97,7 @@
cflags: ["-DNO_PSTORE"],
test_suites: [
"cts",
+ "device-tests",
"vts10",
],
}
diff --git a/liblog/tests/liblog_global_state.cpp b/liblog/tests/liblog_global_state.cpp
index 3508818..1d7ff9f 100644
--- a/liblog/tests/liblog_global_state.cpp
+++ b/liblog/tests/liblog_global_state.cpp
@@ -153,56 +153,65 @@
message_seen = false;
}
+static std::string UniqueLogTag() {
+ std::string tag = LOG_TAG;
+ tag += "-" + std::to_string(getpid());
+ return tag;
+}
+
TEST(liblog_global_state, is_loggable_both_default) {
- EXPECT_EQ(0, __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_INFO, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, LOG_TAG, ANDROID_LOG_INFO));
+ auto tag = UniqueLogTag();
+ EXPECT_EQ(0, __android_log_is_loggable(ANDROID_LOG_DEBUG, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_INFO, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, tag.c_str(), ANDROID_LOG_INFO));
}
TEST(liblog_global_state, is_loggable_minimum_log_priority_only) {
- EXPECT_EQ(0, __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_INFO, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, LOG_TAG, ANDROID_LOG_INFO));
+ auto tag = UniqueLogTag();
+ EXPECT_EQ(0, __android_log_is_loggable(ANDROID_LOG_DEBUG, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_INFO, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, tag.c_str(), ANDROID_LOG_INFO));
EXPECT_EQ(ANDROID_LOG_DEFAULT, __android_log_set_minimum_priority(ANDROID_LOG_DEBUG));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_INFO, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, LOG_TAG, ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_DEBUG, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_INFO, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, tag.c_str(), ANDROID_LOG_INFO));
EXPECT_EQ(ANDROID_LOG_DEBUG, __android_log_set_minimum_priority(ANDROID_LOG_WARN));
- EXPECT_EQ(0, __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(0, __android_log_is_loggable(ANDROID_LOG_INFO, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, LOG_TAG, ANDROID_LOG_INFO));
+ EXPECT_EQ(0, __android_log_is_loggable(ANDROID_LOG_DEBUG, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(0, __android_log_is_loggable(ANDROID_LOG_INFO, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, tag.c_str(), ANDROID_LOG_INFO));
EXPECT_EQ(android::base::WARNING, android::base::SetMinimumLogSeverity(android::base::DEBUG));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_INFO, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, LOG_TAG, ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_DEBUG, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_INFO, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, tag.c_str(), ANDROID_LOG_INFO));
EXPECT_EQ(android::base::DEBUG, android::base::SetMinimumLogSeverity(android::base::WARNING));
- EXPECT_EQ(0, __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(0, __android_log_is_loggable(ANDROID_LOG_INFO, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, LOG_TAG, ANDROID_LOG_INFO));
+ EXPECT_EQ(0, __android_log_is_loggable(ANDROID_LOG_DEBUG, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(0, __android_log_is_loggable(ANDROID_LOG_INFO, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, tag.c_str(), ANDROID_LOG_INFO));
}
TEST(liblog_global_state, is_loggable_tag_log_priority_only) {
#ifdef __ANDROID__
- EXPECT_EQ(0, __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_INFO, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, LOG_TAG, ANDROID_LOG_INFO));
+ auto tag = UniqueLogTag();
+ EXPECT_EQ(0, __android_log_is_loggable(ANDROID_LOG_DEBUG, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_INFO, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, tag.c_str(), ANDROID_LOG_INFO));
- auto log_tag_property = std::string("log.tag.") + LOG_TAG;
- android::base::SetProperty(log_tag_property, "d");
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_INFO, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, LOG_TAG, ANDROID_LOG_INFO));
+ auto log_tag_property = std::string("log.tag.") + tag;
+ ASSERT_TRUE(android::base::SetProperty(log_tag_property, "d"));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_DEBUG, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_INFO, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, tag.c_str(), ANDROID_LOG_INFO));
- android::base::SetProperty(log_tag_property, "w");
- EXPECT_EQ(0, __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(0, __android_log_is_loggable(ANDROID_LOG_INFO, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, LOG_TAG, ANDROID_LOG_INFO));
+ ASSERT_TRUE(android::base::SetProperty(log_tag_property, "w"));
+ EXPECT_EQ(0, __android_log_is_loggable(ANDROID_LOG_DEBUG, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(0, __android_log_is_loggable(ANDROID_LOG_INFO, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, tag.c_str(), ANDROID_LOG_INFO));
- android::base::SetProperty(log_tag_property, "");
+ ASSERT_TRUE(android::base::SetProperty(log_tag_property, ""));
#else
GTEST_SKIP() << "No log tag properties on host";
#endif
@@ -210,39 +219,40 @@
TEST(liblog_global_state, is_loggable_both_set) {
#ifdef __ANDROID__
- EXPECT_EQ(0, __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_INFO, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, LOG_TAG, ANDROID_LOG_INFO));
+ auto tag = UniqueLogTag();
+ EXPECT_EQ(0, __android_log_is_loggable(ANDROID_LOG_DEBUG, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_INFO, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, tag.c_str(), ANDROID_LOG_INFO));
// When both a tag and a minimum priority are set, we use the lower value of the two.
// tag = warning, minimum_priority = debug, expect 'debug'
- auto log_tag_property = std::string("log.tag.") + LOG_TAG;
- android::base::SetProperty(log_tag_property, "w");
+ auto log_tag_property = std::string("log.tag.") + tag;
+ ASSERT_TRUE(android::base::SetProperty(log_tag_property, "w"));
EXPECT_EQ(ANDROID_LOG_DEFAULT, __android_log_set_minimum_priority(ANDROID_LOG_DEBUG));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_INFO, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, LOG_TAG, ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_DEBUG, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_INFO, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, tag.c_str(), ANDROID_LOG_INFO));
// tag = warning, minimum_priority = warning, expect 'warning'
EXPECT_EQ(ANDROID_LOG_DEBUG, __android_log_set_minimum_priority(ANDROID_LOG_WARN));
- EXPECT_EQ(0, __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(0, __android_log_is_loggable(ANDROID_LOG_INFO, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, LOG_TAG, ANDROID_LOG_INFO));
+ EXPECT_EQ(0, __android_log_is_loggable(ANDROID_LOG_DEBUG, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(0, __android_log_is_loggable(ANDROID_LOG_INFO, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, tag.c_str(), ANDROID_LOG_INFO));
// tag = debug, minimum_priority = warning, expect 'debug'
- android::base::SetProperty(log_tag_property, "d");
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_INFO, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, LOG_TAG, ANDROID_LOG_INFO));
+ ASSERT_TRUE(android::base::SetProperty(log_tag_property, "d"));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_DEBUG, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_INFO, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, tag.c_str(), ANDROID_LOG_INFO));
// tag = debug, minimum_priority = debug, expect 'debug'
EXPECT_EQ(ANDROID_LOG_WARN, __android_log_set_minimum_priority(ANDROID_LOG_DEBUG));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_INFO, LOG_TAG, ANDROID_LOG_INFO));
- EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, LOG_TAG, ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_DEBUG, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_INFO, tag.c_str(), ANDROID_LOG_INFO));
+ EXPECT_EQ(1, __android_log_is_loggable(ANDROID_LOG_WARN, tag.c_str(), ANDROID_LOG_INFO));
- android::base::SetProperty(log_tag_property, "");
+ ASSERT_TRUE(android::base::SetProperty(log_tag_property, ""));
#else
GTEST_SKIP() << "No log tag properties on host";
#endif
diff --git a/liblog/tests/log_read_test.cpp b/liblog/tests/log_read_test.cpp
index 3e09617..7acd363 100644
--- a/liblog/tests/log_read_test.cpp
+++ b/liblog/tests/log_read_test.cpp
@@ -20,6 +20,7 @@
#include <string>
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android/log.h> // minimal logging API
#include <gtest/gtest.h>
@@ -29,6 +30,8 @@
// Do not use anything in log/log_time.h despite side effects of the above.
#include <private/android_logger.h>
+using android::base::GetBoolProperty;
+
TEST(liblog, android_logger_get_) {
#ifdef __ANDROID__
// This test assumes the log buffers are filled with noise from
@@ -38,31 +41,27 @@
for (int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
log_id_t id = static_cast<log_id_t>(i);
- const char* name = android_log_id_to_name(id);
- if (id != android_name_to_log_id(name)) {
- continue;
- }
- fprintf(stderr, "log buffer %s\r", name);
+ std::string name = android_log_id_to_name(id);
+ fprintf(stderr, "log buffer %s\r", name.c_str());
struct logger* logger;
EXPECT_TRUE(NULL != (logger = android_logger_open(logger_list, id)));
EXPECT_EQ(id, android_logger_get_id(logger));
ssize_t get_log_size = android_logger_get_log_size(logger);
/* security buffer is allowed to be denied */
- if (strcmp("security", name)) {
- EXPECT_LT(0, get_log_size);
+ if (name != "security") {
+ EXPECT_GT(get_log_size, 0);
// crash buffer is allowed to be empty, that is actually healthy!
- // kernel buffer is allowed to be empty on "user" builds
- // stats buffer is allowed to be empty TEMPORARILY.
- // TODO: remove stats buffer from here once we start to use it in
- // framework (b/68266385).
- EXPECT_LE( // boolean 1 or 0 depending on expected content or empty
- !!((strcmp("crash", name) != 0) &&
- ((strcmp("kernel", name) != 0) ||
- __android_logger_property_get_bool(
- "ro.logd.kernel", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_ENG |
- BOOL_DEFAULT_FLAG_SVELTE)) &&
- (strcmp("stats", name) != 0)),
- android_logger_get_log_readable_size(logger));
+ // stats buffer is no longer in use.
+ if (name == "crash" || name == "stats") {
+ continue;
+ }
+
+ // kernel buffer is empty if ro.logd.kernel is false
+ if (name == "kernel" && !GetBoolProperty("ro.logd.kernel", false)) {
+ continue;
+ }
+
+ EXPECT_LE(0, android_logger_get_log_readable_size(logger));
} else {
EXPECT_NE(0, get_log_size);
if (get_log_size < 0) {
@@ -71,7 +70,6 @@
EXPECT_LE(0, android_logger_get_log_readable_size(logger));
}
}
- EXPECT_LT(0, android_logger_get_log_version(logger));
}
android_logger_list_close(logger_list);
diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp
index 9c1621b..3b6cfd8 100644
--- a/libsysutils/src/NetlinkEvent.cpp
+++ b/libsysutils/src/NetlinkEvent.cpp
@@ -185,7 +185,6 @@
if (!checkRtNetlinkLength(nh, sizeof(*ifaddr)))
return false;
- // Sanity check.
int type = nh->nlmsg_type;
if (type != RTM_NEWADDR && type != RTM_DELADDR) {
SLOGE("parseIfAddrMessage on incorrect message type 0x%x\n", type);
@@ -349,7 +348,6 @@
uint8_t type = nh->nlmsg_type;
const char *msgname = rtMessageName(type);
- // Sanity check.
if (type != RTM_NEWROUTE && type != RTM_DELROUTE) {
SLOGE("%s: incorrect message type %d (%s)\n", __func__, type, msgname);
return false;
diff --git a/libsysutils/src/SocketClient.cpp b/libsysutils/src/SocketClient.cpp
index fe2f3d6..e90afcd 100644
--- a/libsysutils/src/SocketClient.cpp
+++ b/libsysutils/src/SocketClient.cpp
@@ -201,50 +201,31 @@
return 0;
}
- int ret = 0;
- int e = 0; // SLOGW and sigaction are not inert regarding errno
int current = 0;
- struct sigaction new_action, old_action;
- memset(&new_action, 0, sizeof(new_action));
- new_action.sa_handler = SIG_IGN;
- sigaction(SIGPIPE, &new_action, &old_action);
-
for (;;) {
- ssize_t rc = TEMP_FAILURE_RETRY(
- writev(mSocket, iov + current, iovcnt - current));
-
- if (rc > 0) {
- size_t written = rc;
- while ((current < iovcnt) && (written >= iov[current].iov_len)) {
- written -= iov[current].iov_len;
- current++;
- }
- if (current == iovcnt) {
- break;
- }
- iov[current].iov_base = (char *)iov[current].iov_base + written;
- iov[current].iov_len -= written;
- continue;
- }
+ ssize_t rc = TEMP_FAILURE_RETRY(writev(mSocket, iov + current, iovcnt - current));
if (rc == 0) {
- e = EIO;
+ errno = EIO;
SLOGW("0 length write :(");
- } else {
- e = errno;
- SLOGW("write error (%s)", strerror(e));
+ return -1;
+ } else if (rc < 0) {
+ SLOGW("write error (%s)", strerror(errno));
+ return -1;
}
- ret = -1;
- break;
- }
- sigaction(SIGPIPE, &old_action, &new_action);
-
- if (e != 0) {
- errno = e;
+ size_t written = rc;
+ while (current < iovcnt && written >= iov[current].iov_len) {
+ written -= iov[current].iov_len;
+ current++;
+ }
+ if (current == iovcnt) {
+ return 0;
+ }
+ iov[current].iov_base = (char*)iov[current].iov_base + written;
+ iov[current].iov_len -= written;
}
- return ret;
}
void SocketClient::incRef() {
diff --git a/libunwindstack/DwarfCfa.cpp b/libunwindstack/DwarfCfa.cpp
index c128b9b..c6db209 100644
--- a/libunwindstack/DwarfCfa.cpp
+++ b/libunwindstack/DwarfCfa.cpp
@@ -26,7 +26,9 @@
#include <unwindstack/DwarfError.h>
#include <unwindstack/DwarfLocation.h>
+#include <unwindstack/Elf.h>
#include <unwindstack/Log.h>
+#include <unwindstack/MachineArm64.h>
#include "DwarfCfa.h"
#include "DwarfEncoding.h"
@@ -204,8 +206,12 @@
bool DwarfCfa<AddressType>::LogInstruction(uint32_t indent, uint64_t cfa_offset, uint8_t op,
uint64_t* cur_pc) {
const auto* cfa = &DwarfCfaInfo::kTable[op];
- if (cfa->name[0] == '\0') {
- log(indent, "Illegal");
+ if (cfa->name[0] == '\0' || (arch_ != ARCH_ARM64 && op == 0x2d)) {
+ if (op == 0x2d) {
+ log(indent, "Illegal (Only valid on aarch64)");
+ } else {
+ log(indent, "Illegal");
+ }
log(indent, "Raw Data: 0x%02x", op);
return true;
}
@@ -514,6 +520,24 @@
return true;
}
+template <typename AddressType>
+bool DwarfCfa<AddressType>::cfa_aarch64_negate_ra_state(dwarf_loc_regs_t* loc_regs) {
+ // Only supported on aarch64.
+ if (arch_ != ARCH_ARM64) {
+ last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
+ return false;
+ }
+
+ auto cfa_location = loc_regs->find(Arm64Reg::ARM64_PREG_RA_SIGN_STATE);
+ if (cfa_location == loc_regs->end()) {
+ (*loc_regs)[Arm64Reg::ARM64_PREG_RA_SIGN_STATE] = {.type = DWARF_LOCATION_PSEUDO_REGISTER,
+ .values = {1}};
+ } else {
+ cfa_location->second.values[0] ^= 1;
+ }
+ return true;
+}
+
const DwarfCfaInfo::Info DwarfCfaInfo::kTable[64] = {
{
// 0x00 DW_CFA_nop
@@ -699,7 +723,13 @@
{"", 0, 0, {}, {}}, // 0x2a illegal cfa
{"", 0, 0, {}, {}}, // 0x2b illegal cfa
{"", 0, 0, {}, {}}, // 0x2c illegal cfa
- {"", 0, 0, {}, {}}, // 0x2d DW_CFA_GNU_window_save (Treat as illegal)
+ {
+ "DW_CFA_AARCH64_negate_ra_state", // 0x2d DW_CFA_AARCH64_negate_ra_state
+ 3,
+ 0,
+ {},
+ {},
+ },
{
"DW_CFA_GNU_args_size", // 0x2e DW_CFA_GNU_args_size
2,
diff --git a/libunwindstack/DwarfCfa.h b/libunwindstack/DwarfCfa.h
index 569c17c..d627e15 100644
--- a/libunwindstack/DwarfCfa.h
+++ b/libunwindstack/DwarfCfa.h
@@ -31,6 +31,9 @@
namespace unwindstack {
+// Forward declarations.
+enum ArchEnum : uint8_t;
+
// DWARF Standard home: http://dwarfstd.org/
// This code is based on DWARF 4: http://http://dwarfstd.org/doc/DWARF4.pdf
// See section 6.4.2.1 for a description of the DW_CFA_xxx values.
@@ -72,7 +75,8 @@
typedef typename std::make_signed<AddressType>::type SignedType;
public:
- DwarfCfa(DwarfMemory* memory, const DwarfFde* fde) : memory_(memory), fde_(fde) {}
+ DwarfCfa(DwarfMemory* memory, const DwarfFde* fde, ArchEnum arch)
+ : memory_(memory), fde_(fde), arch_(arch) {}
virtual ~DwarfCfa() = default;
bool GetLocationInfo(uint64_t pc, uint64_t start_offset, uint64_t end_offset,
@@ -99,6 +103,7 @@
DwarfErrorData last_error_;
DwarfMemory* memory_;
const DwarfFde* fde_;
+ ArchEnum arch_;
AddressType cur_pc_;
const dwarf_loc_regs_t* cie_loc_regs_ = nullptr;
@@ -128,6 +133,7 @@
bool cfa_val_offset_sf(dwarf_loc_regs_t*);
bool cfa_val_expression(dwarf_loc_regs_t*);
bool cfa_gnu_negative_offset_extended(dwarf_loc_regs_t*);
+ bool cfa_aarch64_negate_ra_state(dwarf_loc_regs_t*);
using process_func = bool (DwarfCfa::*)(dwarf_loc_regs_t*);
constexpr static process_func kCallbackTable[64] = {
@@ -221,8 +227,9 @@
nullptr,
// 0x2c illegal cfa
nullptr,
- // 0x2d DW_CFA_GNU_window_save (Treat this as illegal)
- nullptr,
+ // 0x2d DW_CFA_AARCH64_negate_ra_state (aarch64 only)
+ // DW_CFA_GNU_window_save on other architectures.
+ &DwarfCfa::cfa_aarch64_negate_ra_state,
// 0x2e DW_CFA_GNU_args_size
&DwarfCfa::cfa_nop,
// 0x2f DW_CFA_GNU_negative_offset_extended
diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp
index 18bd490..9e2a3cd 100644
--- a/libunwindstack/DwarfSection.cpp
+++ b/libunwindstack/DwarfSection.cpp
@@ -21,6 +21,7 @@
#include <unwindstack/DwarfMemory.h>
#include <unwindstack/DwarfSection.h>
#include <unwindstack/DwarfStructs.h>
+#include <unwindstack/Elf.h>
#include <unwindstack/Log.h>
#include <unwindstack/Memory.h>
#include <unwindstack/Regs.h>
@@ -49,7 +50,7 @@
// Now get the location information for this pc.
dwarf_loc_regs_t loc_regs;
- if (!GetCfaLocationInfo(pc, fde, &loc_regs)) {
+ if (!GetCfaLocationInfo(pc, fde, &loc_regs, regs->Arch())) {
return false;
}
loc_regs.cie = fde->cie;
@@ -464,6 +465,13 @@
eval_info->return_address_undefined = true;
}
break;
+ case DWARF_LOCATION_PSEUDO_REGISTER: {
+ if (!eval_info->regs_info.regs->SetPseudoRegister(reg, loc->values[0])) {
+ last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
+ return false;
+ }
+ break;
+ }
default:
break;
}
@@ -491,6 +499,10 @@
// Always set the dex pc to zero when evaluating.
cur_regs->set_dex_pc(0);
+ // Reset necessary pseudo registers before evaluation.
+ // This is needed for ARM64, for example.
+ regs->ResetPseudoRegisters();
+
EvalInfo<AddressType> eval_info{.loc_regs = &loc_regs,
.cie = cie,
.regular_memory = regular_memory,
@@ -527,8 +539,10 @@
AddressType* reg_ptr;
if (reg >= cur_regs->total_regs()) {
- // Skip this unknown register.
- continue;
+ if (entry.second.type != DWARF_LOCATION_PSEUDO_REGISTER) {
+ // Skip this unknown register.
+ continue;
+ }
}
reg_ptr = eval_info.regs_info.Save(reg);
@@ -554,8 +568,8 @@
template <typename AddressType>
bool DwarfSectionImpl<AddressType>::GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde,
- dwarf_loc_regs_t* loc_regs) {
- DwarfCfa<AddressType> cfa(&memory_, fde);
+ dwarf_loc_regs_t* loc_regs, ArchEnum arch) {
+ DwarfCfa<AddressType> cfa(&memory_, fde, arch);
// Look for the cached copy of the cie data.
auto reg_entry = cie_loc_regs_.find(fde->cie_offset);
@@ -576,8 +590,9 @@
}
template <typename AddressType>
-bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, const DwarfFde* fde) {
- DwarfCfa<AddressType> cfa(&memory_, fde);
+bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, const DwarfFde* fde,
+ ArchEnum arch) {
+ DwarfCfa<AddressType> cfa(&memory_, fde, arch);
// Always print the cie information.
const DwarfCie* cie = fde->cie;
diff --git a/libunwindstack/RegsArm64.cpp b/libunwindstack/RegsArm64.cpp
index 5b7431a..b496187 100644
--- a/libunwindstack/RegsArm64.cpp
+++ b/libunwindstack/RegsArm64.cpp
@@ -30,7 +30,10 @@
namespace unwindstack {
RegsArm64::RegsArm64()
- : RegsImpl<uint64_t>(ARM64_REG_LAST, Location(LOCATION_REGISTER, ARM64_REG_LR)) {}
+ : RegsImpl<uint64_t>(ARM64_REG_LAST, Location(LOCATION_REGISTER, ARM64_REG_LR)) {
+ ResetPseudoRegisters();
+ pac_mask_ = 0;
+}
ArchEnum RegsArm64::Arch() {
return ARCH_ARM64;
@@ -45,6 +48,23 @@
}
void RegsArm64::set_pc(uint64_t pc) {
+ // If the target is aarch64 then the return address may have been
+ // signed using the Armv8.3-A Pointer Authentication extension. The
+ // original return address can be restored by stripping out the
+ // authentication code using a mask or xpaclri. xpaclri is a NOP on
+ // pre-Armv8.3-A architectures.
+ if ((0 != pc) && IsRASigned()) {
+ if (pac_mask_) {
+ pc &= ~pac_mask_;
+#if defined(__aarch64__)
+ } else {
+ register uint64_t x30 __asm("x30") = pc;
+ // This is XPACLRI.
+ asm("hint 0x7" : "+r"(x30));
+ pc = x30;
+#endif
+ }
+ }
regs_[ARM64_REG_PC] = pc;
}
@@ -144,6 +164,37 @@
return true;
}
+void RegsArm64::ResetPseudoRegisters(void) {
+ // DWARF for AArch64 says RA_SIGN_STATE should be initialized to 0.
+ this->SetPseudoRegister(Arm64Reg::ARM64_PREG_RA_SIGN_STATE, 0);
+}
+
+bool RegsArm64::SetPseudoRegister(uint16_t id, uint64_t value) {
+ if ((id >= Arm64Reg::ARM64_PREG_FIRST) && (id < Arm64Reg::ARM64_PREG_LAST)) {
+ pseudo_regs_[id - Arm64Reg::ARM64_PREG_FIRST] = value;
+ return true;
+ }
+ return false;
+}
+
+bool RegsArm64::GetPseudoRegister(uint16_t id, uint64_t* value) {
+ if ((id >= Arm64Reg::ARM64_PREG_FIRST) && (id < Arm64Reg::ARM64_PREG_LAST)) {
+ *value = pseudo_regs_[id - Arm64Reg::ARM64_PREG_FIRST];
+ return true;
+ }
+ return false;
+}
+
+bool RegsArm64::IsRASigned() {
+ uint64_t value;
+ auto result = this->GetPseudoRegister(Arm64Reg::ARM64_PREG_RA_SIGN_STATE, &value);
+ return (result && (value != 0));
+}
+
+void RegsArm64::SetPACMask(uint64_t mask) {
+ pac_mask_ = mask;
+}
+
Regs* RegsArm64::Clone() {
return new RegsArm64(*this);
}
diff --git a/libunwindstack/include/unwindstack/DwarfLocation.h b/libunwindstack/include/unwindstack/DwarfLocation.h
index 3d50ccf..bf45bc7 100644
--- a/libunwindstack/include/unwindstack/DwarfLocation.h
+++ b/libunwindstack/include/unwindstack/DwarfLocation.h
@@ -33,6 +33,7 @@
DWARF_LOCATION_REGISTER,
DWARF_LOCATION_EXPRESSION,
DWARF_LOCATION_VAL_EXPRESSION,
+ DWARF_LOCATION_PSEUDO_REGISTER,
};
struct DwarfLocation {
diff --git a/libunwindstack/include/unwindstack/DwarfSection.h b/libunwindstack/include/unwindstack/DwarfSection.h
index c244749..af823da 100644
--- a/libunwindstack/include/unwindstack/DwarfSection.h
+++ b/libunwindstack/include/unwindstack/DwarfSection.h
@@ -31,6 +31,7 @@
namespace unwindstack {
// Forward declarations.
+enum ArchEnum : uint8_t;
class Memory;
class Regs;
template <typename AddressType>
@@ -90,13 +91,14 @@
virtual bool Eval(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*) = 0;
- virtual bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde) = 0;
+ virtual bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde, ArchEnum arch) = 0;
virtual void GetFdes(std::vector<const DwarfFde*>* fdes) = 0;
virtual const DwarfFde* GetFdeFromPc(uint64_t pc) = 0;
- virtual bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs) = 0;
+ virtual bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs,
+ ArchEnum arch) = 0;
virtual uint64_t GetCieOffsetFromFde32(uint32_t pointer) = 0;
@@ -140,9 +142,10 @@
bool Eval(const DwarfCie* cie, Memory* regular_memory, const dwarf_loc_regs_t& loc_regs,
Regs* regs, bool* finished) override;
- bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs) override;
+ bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs,
+ ArchEnum arch) override;
- bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde) override;
+ bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde, ArchEnum arch) override;
protected:
bool GetNextCieOrFde(const DwarfFde** fde_entry);
diff --git a/libunwindstack/include/unwindstack/MachineArm64.h b/libunwindstack/include/unwindstack/MachineArm64.h
index e953335..358e3d9 100644
--- a/libunwindstack/include/unwindstack/MachineArm64.h
+++ b/libunwindstack/include/unwindstack/MachineArm64.h
@@ -60,6 +60,13 @@
ARM64_REG_SP = ARM64_REG_R31,
ARM64_REG_LR = ARM64_REG_R30,
+
+ // Pseudo registers. These are not machine registers.
+
+ // AARCH64 Return address signed state pseudo-register
+ ARM64_PREG_RA_SIGN_STATE = 34,
+ ARM64_PREG_FIRST = ARM64_PREG_RA_SIGN_STATE,
+ ARM64_PREG_LAST,
};
} // namespace unwindstack
diff --git a/libunwindstack/include/unwindstack/Regs.h b/libunwindstack/include/unwindstack/Regs.h
index a367e6c..5f42565 100644
--- a/libunwindstack/include/unwindstack/Regs.h
+++ b/libunwindstack/include/unwindstack/Regs.h
@@ -64,6 +64,10 @@
uint64_t dex_pc() { return dex_pc_; }
void set_dex_pc(uint64_t dex_pc) { dex_pc_ = dex_pc; }
+ virtual void ResetPseudoRegisters() {}
+ virtual bool SetPseudoRegister(uint16_t, uint64_t) { return false; }
+ virtual bool GetPseudoRegister(uint16_t, uint64_t*) { return false; }
+
virtual bool StepIfSignalHandler(uint64_t elf_offset, Elf* elf, Memory* process_memory) = 0;
virtual bool SetPcFromReturnAddress(Memory* process_memory) = 0;
diff --git a/libunwindstack/include/unwindstack/RegsArm64.h b/libunwindstack/include/unwindstack/RegsArm64.h
index 2b3ddeb..bf7ab15 100644
--- a/libunwindstack/include/unwindstack/RegsArm64.h
+++ b/libunwindstack/include/unwindstack/RegsArm64.h
@@ -22,6 +22,7 @@
#include <functional>
#include <unwindstack/Elf.h>
+#include <unwindstack/MachineArm64.h>
#include <unwindstack/Regs.h>
namespace unwindstack {
@@ -48,11 +49,25 @@
void set_pc(uint64_t pc) override;
void set_sp(uint64_t sp) override;
+ void ResetPseudoRegisters() override;
+
+ bool SetPseudoRegister(uint16_t id, uint64_t value) override;
+
+ bool GetPseudoRegister(uint16_t id, uint64_t* value) override;
+
+ bool IsRASigned();
+
+ void SetPACMask(uint64_t mask);
+
Regs* Clone() override final;
static Regs* Read(void* data);
static Regs* CreateFromUcontext(void* ucontext);
+
+ protected:
+ uint64_t pseudo_regs_[Arm64Reg::ARM64_PREG_LAST - Arm64Reg::ARM64_PREG_FIRST];
+ uint64_t pac_mask_;
};
} // namespace unwindstack
diff --git a/libunwindstack/tests/DwarfCfaLogTest.cpp b/libunwindstack/tests/DwarfCfaLogTest.cpp
index def4088..2b5a8dc 100644
--- a/libunwindstack/tests/DwarfCfaLogTest.cpp
+++ b/libunwindstack/tests/DwarfCfaLogTest.cpp
@@ -26,6 +26,7 @@
#include <unwindstack/DwarfLocation.h>
#include <unwindstack/DwarfMemory.h>
#include <unwindstack/DwarfStructs.h>
+#include <unwindstack/Elf.h>
#include <unwindstack/Log.h>
#include "DwarfCfa.h"
@@ -57,7 +58,7 @@
fde_.pc_end = 0x2000;
fde_.pc_end = 0x10000;
fde_.cie = &cie_;
- cfa_.reset(new DwarfCfa<TypeParam>(dmem_.get(), &fde_));
+ cfa_.reset(new DwarfCfa<TypeParam>(dmem_.get(), &fde_, ARCH_UNKNOWN));
}
MemoryFake memory_;
@@ -72,8 +73,8 @@
TYPED_TEST_P(DwarfCfaLogTest, cfa_illegal) {
for (uint8_t i = 0x17; i < 0x3f; i++) {
- if (i == 0x2e || i == 0x2f) {
- // Skip gnu extension ops.
+ if (i == 0x2d || i == 0x2e || i == 0x2f) {
+ // Skip gnu extension ops and aarch64 specialized op.
continue;
}
this->memory_.SetMemory(0x2000, std::vector<uint8_t>{i});
@@ -763,6 +764,26 @@
ASSERT_EQ("", GetFakeLogBuf());
}
+TYPED_TEST_P(DwarfCfaLogTest, cfa_aarch64_negate_ra_state) {
+ // Verify that if the cfa op is handled properly depending on aarch.
+ this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x2d});
+
+ ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2000, 0x2001));
+ std::string expected = "4 unwind Illegal (Only valid on aarch64)\n";
+ expected += "4 unwind Raw Data: 0x2d\n";
+ ASSERT_EQ(expected, GetFakeLogPrint());
+ ASSERT_EQ("", GetFakeLogBuf());
+
+ ResetLogs();
+ this->cfa_.reset(new DwarfCfa<TypeParam>(this->dmem_.get(), &this->fde_, ARCH_ARM64));
+
+ ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2000, 0x2001));
+ expected = "4 unwind DW_CFA_AARCH64_negate_ra_state\n";
+ expected += "4 unwind Raw Data: 0x2d\n";
+ ASSERT_EQ(expected, GetFakeLogPrint());
+ ASSERT_EQ("", GetFakeLogBuf());
+}
+
REGISTER_TYPED_TEST_SUITE_P(DwarfCfaLogTest, cfa_illegal, cfa_nop, cfa_offset, cfa_offset_extended,
cfa_offset_extended_sf, cfa_restore, cfa_restore_extended, cfa_set_loc,
cfa_advance_loc, cfa_advance_loc1, cfa_advance_loc2, cfa_advance_loc4,
@@ -771,7 +792,8 @@
cfa_def_cfa_register, cfa_def_cfa_offset, cfa_def_cfa_offset_sf,
cfa_def_cfa_expression, cfa_expression, cfa_val_offset,
cfa_val_offset_sf, cfa_val_expression, cfa_gnu_args_size,
- cfa_gnu_negative_offset_extended, cfa_register_override);
+ cfa_gnu_negative_offset_extended, cfa_register_override,
+ cfa_aarch64_negate_ra_state);
typedef ::testing::Types<uint32_t, uint64_t> DwarfCfaLogTestTypes;
INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfCfaLogTest, DwarfCfaLogTestTypes);
diff --git a/libunwindstack/tests/DwarfCfaTest.cpp b/libunwindstack/tests/DwarfCfaTest.cpp
index 9c6ab05..ea7e708 100644
--- a/libunwindstack/tests/DwarfCfaTest.cpp
+++ b/libunwindstack/tests/DwarfCfaTest.cpp
@@ -25,7 +25,9 @@
#include <unwindstack/DwarfLocation.h>
#include <unwindstack/DwarfMemory.h>
#include <unwindstack/DwarfStructs.h>
+#include <unwindstack/Elf.h>
#include <unwindstack/Log.h>
+#include <unwindstack/MachineArm64.h>
#include "DwarfCfa.h"
@@ -55,7 +57,7 @@
fde_.pc_start = 0x2000;
fde_.cie = &cie_;
- cfa_.reset(new DwarfCfa<TypeParam>(dmem_.get(), &fde_));
+ cfa_.reset(new DwarfCfa<TypeParam>(dmem_.get(), &fde_, ARCH_UNKNOWN));
}
MemoryFake memory_;
@@ -70,8 +72,8 @@
TYPED_TEST_P(DwarfCfaTest, cfa_illegal) {
for (uint8_t i = 0x17; i < 0x3f; i++) {
- if (i == 0x2e || i == 0x2f) {
- // Skip gnu extension ops.
+ if (i == 0x2d || i == 0x2e || i == 0x2f) {
+ // Skip gnu extension ops and aarch64 specialized op.
continue;
}
this->memory_.SetMemory(0x2000, std::vector<uint8_t>{i});
@@ -952,6 +954,57 @@
ASSERT_EQ("", GetFakeLogBuf());
}
+TYPED_TEST_P(DwarfCfaTest, cfa_aarch64_negate_ra_state) {
+ this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x2d});
+ dwarf_loc_regs_t loc_regs;
+
+ ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs));
+ ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->cfa_->LastErrorCode());
+ ASSERT_EQ(0x2001U, this->dmem_->cur_offset());
+
+ ASSERT_EQ("", GetFakeLogPrint());
+ ASSERT_EQ("", GetFakeLogBuf());
+
+ ResetLogs();
+ this->cfa_.reset(new DwarfCfa<TypeParam>(this->dmem_.get(), &this->fde_, ARCH_ARM64));
+ ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs));
+ ASSERT_EQ(0x2001U, this->dmem_->cur_offset());
+
+ auto location = loc_regs.find(Arm64Reg::ARM64_PREG_RA_SIGN_STATE);
+ ASSERT_NE(loc_regs.end(), location);
+ ASSERT_EQ(DWARF_LOCATION_PSEUDO_REGISTER, location->second.type);
+ ASSERT_EQ(1U, location->second.values[0]);
+
+ ASSERT_EQ("", GetFakeLogPrint());
+ ASSERT_EQ("", GetFakeLogBuf());
+
+ // Verify that the value is set to 0 after another evaluation.
+ ResetLogs();
+ ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs));
+ ASSERT_EQ(0x2001U, this->dmem_->cur_offset());
+
+ location = loc_regs.find(Arm64Reg::ARM64_PREG_RA_SIGN_STATE);
+ ASSERT_NE(loc_regs.end(), location);
+ ASSERT_EQ(DWARF_LOCATION_PSEUDO_REGISTER, location->second.type);
+ ASSERT_EQ(0U, location->second.values[0]);
+
+ ASSERT_EQ("", GetFakeLogPrint());
+ ASSERT_EQ("", GetFakeLogBuf());
+
+ // Verify that the value is set to 1 again after a third op.
+ ResetLogs();
+ ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs));
+ ASSERT_EQ(0x2001U, this->dmem_->cur_offset());
+
+ location = loc_regs.find(Arm64Reg::ARM64_PREG_RA_SIGN_STATE);
+ ASSERT_NE(loc_regs.end(), location);
+ ASSERT_EQ(DWARF_LOCATION_PSEUDO_REGISTER, location->second.type);
+ ASSERT_EQ(1U, location->second.values[0]);
+
+ ASSERT_EQ("", GetFakeLogPrint());
+ ASSERT_EQ("", GetFakeLogBuf());
+}
+
REGISTER_TYPED_TEST_SUITE_P(DwarfCfaTest, cfa_illegal, cfa_nop, cfa_offset, cfa_offset_extended,
cfa_offset_extended_sf, cfa_restore, cfa_restore_extended, cfa_set_loc,
cfa_advance_loc1, cfa_advance_loc2, cfa_advance_loc4, cfa_undefined,
@@ -960,7 +1013,7 @@
cfa_def_cfa_offset_sf, cfa_def_cfa_expression, cfa_expression,
cfa_val_offset, cfa_val_offset_sf, cfa_val_expression,
cfa_gnu_args_size, cfa_gnu_negative_offset_extended,
- cfa_register_override);
+ cfa_register_override, cfa_aarch64_negate_ra_state);
typedef ::testing::Types<uint32_t, uint64_t> DwarfCfaTestTypes;
INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfCfaTest, DwarfCfaTestTypes);
diff --git a/libunwindstack/tests/DwarfSectionImplTest.cpp b/libunwindstack/tests/DwarfSectionImplTest.cpp
index cac59b7..d57cd33 100644
--- a/libunwindstack/tests/DwarfSectionImplTest.cpp
+++ b/libunwindstack/tests/DwarfSectionImplTest.cpp
@@ -20,6 +20,7 @@
#include <unwindstack/DwarfError.h>
#include <unwindstack/DwarfSection.h>
+#include <unwindstack/Elf.h>
#include "DwarfEncoding.h"
@@ -505,7 +506,7 @@
this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0x09, 0x04, 0x03});
dwarf_loc_regs_t loc_regs;
- ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs));
+ ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs, ARCH_UNKNOWN));
ASSERT_EQ(2U, loc_regs.size());
auto entry = loc_regs.find(2);
@@ -535,7 +536,7 @@
this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0x09, 0x04, 0x03});
dwarf_loc_regs_t loc_regs;
- ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs));
+ ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs, ARCH_UNKNOWN));
ASSERT_EQ(2U, loc_regs.size());
auto entry = loc_regs.find(6);
@@ -560,7 +561,7 @@
this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x00});
this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0xc2});
- ASSERT_TRUE(this->section_->Log(2, 0x1000, &fde));
+ ASSERT_TRUE(this->section_->Log(2, 0x1000, &fde, ARCH_UNKNOWN));
ASSERT_EQ(
"4 unwind DW_CFA_nop\n"
diff --git a/libunwindstack/tests/DwarfSectionTest.cpp b/libunwindstack/tests/DwarfSectionTest.cpp
index 953dc75..febd6d3 100644
--- a/libunwindstack/tests/DwarfSectionTest.cpp
+++ b/libunwindstack/tests/DwarfSectionTest.cpp
@@ -20,8 +20,10 @@
#include <gtest/gtest.h>
#include <unwindstack/DwarfSection.h>
+#include <unwindstack/Elf.h>
#include "MemoryFake.h"
+#include "RegsFake.h"
namespace unwindstack {
@@ -35,13 +37,14 @@
MOCK_METHOD(bool, Eval, (const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*),
(override));
- MOCK_METHOD(bool, Log, (uint8_t, uint64_t, const DwarfFde*), (override));
+ MOCK_METHOD(bool, Log, (uint8_t, uint64_t, const DwarfFde*, ArchEnum arch), (override));
MOCK_METHOD(void, GetFdes, (std::vector<const DwarfFde*>*), (override));
MOCK_METHOD(const DwarfFde*, GetFdeFromPc, (uint64_t), (override));
- MOCK_METHOD(bool, GetCfaLocationInfo, (uint64_t, const DwarfFde*, dwarf_loc_regs_t*), (override));
+ MOCK_METHOD(bool, GetCfaLocationInfo,
+ (uint64_t, const DwarfFde*, dwarf_loc_regs_t*, ArchEnum arch), (override));
MOCK_METHOD(uint64_t, GetCieOffsetFromFde32, (uint32_t), (override));
@@ -56,8 +59,11 @@
MemoryFake memory_;
std::unique_ptr<MockDwarfSection> section_;
+ static RegsFake regs_;
};
+RegsFake DwarfSectionTest::regs_(10);
+
TEST_F(DwarfSectionTest, Step_fail_fde) {
EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(nullptr));
@@ -73,7 +79,7 @@
EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde));
bool finished;
- ASSERT_FALSE(section_->Step(0x1000, nullptr, nullptr, &finished));
+ ASSERT_FALSE(section_->Step(0x1000, ®s_, nullptr, &finished));
}
TEST_F(DwarfSectionTest, Step_fail_cfa_location) {
@@ -83,11 +89,11 @@
fde.cie = &cie;
EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde));
- EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde, ::testing::_))
+ EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde, ::testing::_, ::testing::_))
.WillOnce(::testing::Return(false));
bool finished;
- ASSERT_FALSE(section_->Step(0x1000, nullptr, nullptr, &finished));
+ ASSERT_FALSE(section_->Step(0x1000, ®s_, nullptr, &finished));
}
TEST_F(DwarfSectionTest, Step_pass) {
@@ -97,19 +103,19 @@
fde.cie = &cie;
EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde));
- EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde, ::testing::_))
+ EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde, ::testing::_, ::testing::_))
.WillOnce(::testing::Return(true));
MemoryFake process;
- EXPECT_CALL(*section_, Eval(&cie, &process, ::testing::_, nullptr, ::testing::_))
+ EXPECT_CALL(*section_, Eval(&cie, &process, ::testing::_, ®s_, ::testing::_))
.WillOnce(::testing::Return(true));
bool finished;
- ASSERT_TRUE(section_->Step(0x1000, nullptr, &process, &finished));
+ ASSERT_TRUE(section_->Step(0x1000, ®s_, &process, &finished));
}
static bool MockGetCfaLocationInfo(::testing::Unused, const DwarfFde* fde,
- dwarf_loc_regs_t* loc_regs) {
+ dwarf_loc_regs_t* loc_regs, ArchEnum) {
loc_regs->pc_start = fde->pc_start;
loc_regs->pc_end = fde->pc_end;
return true;
@@ -123,17 +129,17 @@
fde.cie = &cie;
EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde));
- EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde, ::testing::_))
+ EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde, ::testing::_, ::testing::_))
.WillOnce(::testing::Invoke(MockGetCfaLocationInfo));
MemoryFake process;
- EXPECT_CALL(*section_, Eval(&cie, &process, ::testing::_, nullptr, ::testing::_))
+ EXPECT_CALL(*section_, Eval(&cie, &process, ::testing::_, ®s_, ::testing::_))
.WillRepeatedly(::testing::Return(true));
bool finished;
- ASSERT_TRUE(section_->Step(0x1000, nullptr, &process, &finished));
- ASSERT_TRUE(section_->Step(0x1000, nullptr, &process, &finished));
- ASSERT_TRUE(section_->Step(0x1500, nullptr, &process, &finished));
+ ASSERT_TRUE(section_->Step(0x1000, ®s_, &process, &finished));
+ ASSERT_TRUE(section_->Step(0x1000, ®s_, &process, &finished));
+ ASSERT_TRUE(section_->Step(0x1500, ®s_, &process, &finished));
}
TEST_F(DwarfSectionTest, Step_cache_not_in_pc) {
@@ -143,26 +149,26 @@
fde0.pc_end = 0x2000;
fde0.cie = &cie;
EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde0));
- EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde0, ::testing::_))
+ EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde0, ::testing::_, ::testing::_))
.WillOnce(::testing::Invoke(MockGetCfaLocationInfo));
MemoryFake process;
- EXPECT_CALL(*section_, Eval(&cie, &process, ::testing::_, nullptr, ::testing::_))
+ EXPECT_CALL(*section_, Eval(&cie, &process, ::testing::_, ®s_, ::testing::_))
.WillRepeatedly(::testing::Return(true));
bool finished;
- ASSERT_TRUE(section_->Step(0x1000, nullptr, &process, &finished));
+ ASSERT_TRUE(section_->Step(0x1000, ®s_, &process, &finished));
DwarfFde fde1{};
fde1.pc_start = 0x500;
fde1.pc_end = 0x800;
fde1.cie = &cie;
EXPECT_CALL(*section_, GetFdeFromPc(0x600)).WillOnce(::testing::Return(&fde1));
- EXPECT_CALL(*section_, GetCfaLocationInfo(0x600, &fde1, ::testing::_))
+ EXPECT_CALL(*section_, GetCfaLocationInfo(0x600, &fde1, ::testing::_, ::testing::_))
.WillOnce(::testing::Invoke(MockGetCfaLocationInfo));
- ASSERT_TRUE(section_->Step(0x600, nullptr, &process, &finished));
- ASSERT_TRUE(section_->Step(0x700, nullptr, &process, &finished));
+ ASSERT_TRUE(section_->Step(0x600, ®s_, &process, &finished));
+ ASSERT_TRUE(section_->Step(0x700, ®s_, &process, &finished));
}
} // namespace unwindstack
diff --git a/libunwindstack/tests/RegsTest.cpp b/libunwindstack/tests/RegsTest.cpp
index e4fc6f0..acf72de 100644
--- a/libunwindstack/tests/RegsTest.cpp
+++ b/libunwindstack/tests/RegsTest.cpp
@@ -247,6 +247,14 @@
EXPECT_EQ(0xc200000000U, mips64.pc());
}
+TEST_F(RegsTest, arm64_strip_pac_mask) {
+ RegsArm64 arm64;
+ arm64.SetPseudoRegister(Arm64Reg::ARM64_PREG_RA_SIGN_STATE, 1);
+ arm64.SetPACMask(0x007fff8000000000ULL);
+ arm64.set_pc(0x0020007214bb3a04ULL);
+ EXPECT_EQ(0x0000007214bb3a04ULL, arm64.pc());
+}
+
TEST_F(RegsTest, machine_type) {
RegsArm arm_regs;
EXPECT_EQ(ARCH_ARM, arm_regs.Arch());
diff --git a/libunwindstack/tests/VerifyBionicTerminationTest.cpp b/libunwindstack/tests/VerifyBionicTerminationTest.cpp
index 6a3e91a..eb2b01d 100644
--- a/libunwindstack/tests/VerifyBionicTerminationTest.cpp
+++ b/libunwindstack/tests/VerifyBionicTerminationTest.cpp
@@ -55,7 +55,7 @@
return DWARF_LOCATION_INVALID;
}
dwarf_loc_regs_t regs;
- if (!section->GetCfaLocationInfo(rel_pc, fde, ®s)) {
+ if (!section->GetCfaLocationInfo(rel_pc, fde, ®s, ARCH_UNKNOWN)) {
return DWARF_LOCATION_INVALID;
}
diff --git a/libunwindstack/tools/unwind_info.cpp b/libunwindstack/tools/unwind_info.cpp
index 7a6d8ba..a5002f2 100644
--- a/libunwindstack/tools/unwind_info.cpp
+++ b/libunwindstack/tools/unwind_info.cpp
@@ -96,7 +96,7 @@
printf(" <%s>", name.c_str());
}
printf("\n");
- if (!section->Log(2, UINT64_MAX, fde)) {
+ if (!section->Log(2, UINT64_MAX, fde, elf->arch())) {
printf("Failed to process cfa information for entry at 0x%" PRIx64 "\n", fde->pc_start);
}
}
diff --git a/libunwindstack/tools/unwind_reg_info.cpp b/libunwindstack/tools/unwind_reg_info.cpp
index 0cbcac5..68e0273 100644
--- a/libunwindstack/tools/unwind_reg_info.cpp
+++ b/libunwindstack/tools/unwind_reg_info.cpp
@@ -64,7 +64,8 @@
}
}
-void PrintRegInformation(DwarfSection* section, Memory* memory, uint64_t pc, uint8_t class_type) {
+void PrintRegInformation(DwarfSection* section, Memory* memory, uint64_t pc, uint8_t class_type,
+ ArchEnum arch) {
const DwarfFde* fde = section->GetFdeFromPc(pc);
if (fde == nullptr) {
printf(" No fde found.\n");
@@ -72,7 +73,7 @@
}
dwarf_loc_regs_t regs;
- if (!section->GetCfaLocationInfo(pc, fde, ®s)) {
+ if (!section->GetCfaLocationInfo(pc, fde, ®s, arch)) {
printf(" Cannot get location information.\n");
return;
}
@@ -128,6 +129,11 @@
break;
}
+ case DWARF_LOCATION_PSEUDO_REGISTER: {
+ printf("%" PRId64 " (pseudo)\n", loc->values[0]);
+ break;
+ }
+
case DWARF_LOCATION_UNDEFINED:
printf("undefine\n");
break;
@@ -199,7 +205,7 @@
DwarfSection* section = interface->eh_frame();
if (section != nullptr) {
printf("\neh_frame:\n");
- PrintRegInformation(section, elf.memory(), pc, elf.class_type());
+ PrintRegInformation(section, elf.memory(), pc, elf.class_type(), elf.arch());
} else {
printf("\nno eh_frame information\n");
}
@@ -207,7 +213,7 @@
section = interface->debug_frame();
if (section != nullptr) {
printf("\ndebug_frame:\n");
- PrintRegInformation(section, elf.memory(), pc, elf.class_type());
+ PrintRegInformation(section, elf.memory(), pc, elf.class_type(), elf.arch());
printf("\n");
} else {
printf("\nno debug_frame information\n");
@@ -219,7 +225,8 @@
section = gnu_debugdata_interface->eh_frame();
if (section != nullptr) {
printf("\ngnu_debugdata (eh_frame):\n");
- PrintRegInformation(section, gnu_debugdata_interface->memory(), pc, elf.class_type());
+ PrintRegInformation(section, gnu_debugdata_interface->memory(), pc, elf.class_type(),
+ elf.arch());
printf("\n");
} else {
printf("\nno gnu_debugdata (eh_frame)\n");
@@ -228,7 +235,8 @@
section = gnu_debugdata_interface->debug_frame();
if (section != nullptr) {
printf("\ngnu_debugdata (debug_frame):\n");
- PrintRegInformation(section, gnu_debugdata_interface->memory(), pc, elf.class_type());
+ PrintRegInformation(section, gnu_debugdata_interface->memory(), pc, elf.class_type(),
+ elf.arch());
printf("\n");
} else {
printf("\nno gnu_debugdata (debug_frame)\n");
diff --git a/libutils/Unicode.cpp b/libutils/Unicode.cpp
index b08e061..b6e457b 100644
--- a/libutils/Unicode.cpp
+++ b/libutils/Unicode.cpp
@@ -162,9 +162,9 @@
if (index >= src_len) {
return -1;
}
- size_t dummy_index;
+ size_t unused_index;
if (next_index == nullptr) {
- next_index = &dummy_index;
+ next_index = &unused_index;
}
size_t num_read;
int32_t ret = utf32_at_internal(src + index, &num_read);
diff --git a/libutils/include/utils/Vector.h b/libutils/include/utils/Vector.h
index ddf71de..be35ea2 100644
--- a/libutils/include/utils/Vector.h
+++ b/libutils/include/utils/Vector.h
@@ -23,15 +23,13 @@
#include <log/log.h>
#include <utils/TypeHelpers.h>
#include <utils/VectorImpl.h>
-
-/*
- * Used to blacklist some functions from CFI.
- *
- */
#ifndef __has_attribute
#define __has_attribute(x) 0
#endif
+/*
+ * Used to exclude some functions from CFI.
+ */
#if __has_attribute(no_sanitize)
#define UTILS_VECTOR_NO_CFI __attribute__((no_sanitize("cfi")))
#else
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index d15fa2b..c7d1634 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -616,15 +616,15 @@
if (long_options[option_index].name == wrap_str) {
mode |= ANDROID_LOG_WRAP | ANDROID_LOG_NONBLOCK;
// ToDo: implement API that supports setting a wrap timeout
- size_t dummy = ANDROID_LOG_WRAP_DEFAULT_TIMEOUT;
- if (optarg && (!ParseUint(optarg, &dummy) || dummy < 1)) {
+ size_t timeout = ANDROID_LOG_WRAP_DEFAULT_TIMEOUT;
+ if (optarg && (!ParseUint(optarg, &timeout) || timeout < 1)) {
error(EXIT_FAILURE, 0, "%s %s out of range.",
long_options[option_index].name, optarg);
}
- if (dummy != ANDROID_LOG_WRAP_DEFAULT_TIMEOUT) {
+ if (timeout != ANDROID_LOG_WRAP_DEFAULT_TIMEOUT) {
fprintf(stderr, "WARNING: %s %u seconds, ignoring %zu\n",
long_options[option_index].name, ANDROID_LOG_WRAP_DEFAULT_TIMEOUT,
- dummy);
+ timeout);
}
break;
}
diff --git a/logd/Android.bp b/logd/Android.bp
index 036cb7e..265e19e 100644
--- a/logd/Android.bp
+++ b/logd/Android.bp
@@ -177,6 +177,27 @@
},
test_suites: [
"cts",
+ "device-tests",
"vts10",
],
}
+
+cc_binary {
+ name: "replay_messages",
+ defaults: ["logd_defaults"],
+ host_supported: true,
+
+ srcs: [
+ "ReplayMessages.cpp",
+ ],
+
+ static_libs: [
+ "libbase",
+ "libcutils",
+ "liblog",
+ "liblogd",
+ "libselinux",
+ "libz",
+ "libzstd",
+ ],
+}
diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp
index 0ce9796..0e17476 100644
--- a/logd/LogAudit.cpp
+++ b/logd/LogAudit.cpp
@@ -32,7 +32,7 @@
#include <sstream>
#include <android-base/macros.h>
-#include <log/log_properties.h>
+#include <android-base/properties.h>
#include <private/android_filesystem_config.h>
#include <private/android_logger.h>
@@ -40,6 +40,8 @@
#include "LogUtils.h"
#include "libaudit.h"
+using android::base::GetBoolProperty;
+
#define KMSG_PRIORITY(PRI) \
'<', '0' + LOG_MAKEPRI(LOG_AUTH, LOG_PRI(PRI)) / 10, \
'0' + LOG_MAKEPRI(LOG_AUTH, LOG_PRI(PRI)) % 10, '>'
@@ -48,8 +50,8 @@
: SocketListener(getLogSocket(), false),
logbuf(buf),
fdDmesg(fdDmesg),
- main(__android_logger_property_get_bool("ro.logd.auditd.main", BOOL_DEFAULT_TRUE)),
- events(__android_logger_property_get_bool("ro.logd.auditd.events", BOOL_DEFAULT_TRUE)),
+ main(GetBoolProperty("ro.logd.auditd.main", true)),
+ events(GetBoolProperty("ro.logd.auditd.events", true)),
initialized(false),
stats_(stats) {
static const char auditd_message[] = { KMSG_PRIORITY(LOG_INFO),
diff --git a/logd/LogBufferTest.cpp b/logd/LogBufferTest.cpp
index 47d2a2f..1911105 100644
--- a/logd/LogBufferTest.cpp
+++ b/logd/LogBufferTest.cpp
@@ -34,16 +34,6 @@
using android::base::Split;
using android::base::StringPrintf;
-#ifndef __ANDROID__
-unsigned long __android_logger_get_buffer_size(log_id_t) {
- return 1024 * 1024;
-}
-
-bool __android_logger_valid_buffer_size(unsigned long) {
- return true;
-}
-#endif
-
char* android::uidToName(uid_t) {
return nullptr;
}
diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp
index dbdf7fd..d6c7d25 100644
--- a/logd/LogKlog.cpp
+++ b/logd/LogKlog.cpp
@@ -381,8 +381,8 @@
}
if ((i == 9) && (cp[i] == ' ')) {
int pid = 0;
- char dummy;
- if (sscanf(cp + 4, "%d%c", &pid, &dummy) == 2) {
+ char placeholder;
+ if (sscanf(cp + 4, "%d%c", &pid, &placeholder) == 2) {
buf = cp + 10; // skip-it-all
return pid;
}
@@ -392,8 +392,8 @@
// Mediatek kernels with modified printk
if (*cp == '[') {
int pid = 0;
- char dummy;
- if (sscanf(cp, "[%d:%*[a-z_./0-9:A-Z]]%c", &pid, &dummy) == 2) {
+ char placeholder;
+ if (sscanf(cp, "[%d:%*[a-z_./0-9:A-Z]]%c", &pid, &placeholder) == 2) {
return pid;
}
break; // Only the first one
@@ -703,7 +703,7 @@
p = " ";
b = 1;
}
- // paranoid sanity check, can not happen ...
+ // This shouldn't happen, but clamp the size if it does.
if (b > LOGGER_ENTRY_MAX_PAYLOAD) {
b = LOGGER_ENTRY_MAX_PAYLOAD;
}
@@ -712,7 +712,7 @@
}
// calculate buffer copy requirements
ssize_t n = 1 + taglen + 1 + b + 1;
- // paranoid sanity check, first two just can not happen ...
+ // Extra checks for likely impossible cases.
if ((taglen > n) || (b > n) || (n > (ssize_t)USHRT_MAX) || (n <= 0)) {
return -EINVAL;
}
@@ -722,7 +722,7 @@
// If we malloc'd this buffer, we could get away without n's USHRT_MAX
// test above, but we would then required a max(n, USHRT_MAX) as
// truncating length argument to logbuf->log() below. Gain is protection
- // of stack sanity and speedup, loss is truncated long-line content.
+ // against stack corruption and speedup, loss is truncated long-line content.
char newstr[n];
char* np = newstr;
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index 1705d48..87069b3 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -26,8 +26,10 @@
#include <unistd.h>
#include <list>
+#include <vector>
#include <android-base/logging.h>
+#include <android-base/strings.h>
#include <private/android_logger.h>
#include "LogBufferElement.h"
@@ -61,7 +63,8 @@
return std::string(msg, len);
}
-LogStatistics::LogStatistics(bool enable_statistics, bool track_total_size)
+LogStatistics::LogStatistics(bool enable_statistics, bool track_total_size,
+ std::optional<log_time> start_time)
: enable(enable_statistics), track_total_size_(track_total_size) {
log_time now(CLOCK_REALTIME);
log_id_for_each(id) {
@@ -70,8 +73,13 @@
mDroppedElements[id] = 0;
mSizesTotal[id] = 0;
mElementsTotal[id] = 0;
- mOldest[id] = now;
- mNewest[id] = now;
+ if (start_time) {
+ mOldest[id] = *start_time;
+ mNewest[id] = *start_time;
+ } else {
+ mOldest[id] = now;
+ mNewest[id] = now;
+ }
mNewestDropped[id] = now;
}
}
@@ -784,6 +792,31 @@
return output;
}
+std::string LogStatistics::ReportInteresting() const {
+ auto lock = std::lock_guard{lock_};
+
+ std::vector<std::string> items;
+
+ log_id_for_each(i) { items.emplace_back(std::to_string(mElements[i])); }
+
+ log_id_for_each(i) { items.emplace_back(std::to_string(mSizes[i])); }
+
+ log_id_for_each(i) {
+ items.emplace_back(std::to_string(overhead_[i] ? *overhead_[i] : mSizes[i]));
+ }
+
+ log_id_for_each(i) {
+ uint64_t oldest = mOldest[i].msec() / 1000;
+ uint64_t newest = mNewest[i].msec() / 1000;
+
+ int span = newest - oldest;
+
+ items.emplace_back(std::to_string(span));
+ }
+
+ return android::base::Join(items, ",");
+}
+
std::string LogStatistics::Format(uid_t uid, pid_t pid, unsigned int logMask) const {
auto lock = std::lock_guard{lock_};
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index d440a8c..e222d3f 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -515,7 +515,8 @@
}
public:
- LogStatistics(bool enable_statistics, bool track_total_size);
+ LogStatistics(bool enable_statistics, bool track_total_size,
+ std::optional<log_time> start_time = {});
void AddTotal(log_id_t log_id, uint16_t size) EXCLUDES(lock_);
@@ -556,6 +557,7 @@
return SizesTotal;
}
+ std::string ReportInteresting() const EXCLUDES(lock_);
std::string Format(uid_t uid, pid_t pid, unsigned int logMask) const EXCLUDES(lock_);
const char* PidToName(pid_t pid) const EXCLUDES(lock_);
diff --git a/logd/README.property b/logd/README.property
index 1d7d990..8fd7f48 100644
--- a/logd/README.property
+++ b/logd/README.property
@@ -7,8 +7,8 @@
ro.logd.auditd.events bool true selinux audit messages sent to events.
persist.logd.security bool false Enable security buffer.
ro.organization_owned bool false Override persist.logd.security to false
-ro.logd.kernel bool+ svelte+ Enable klogd daemon
-ro.logd.statistics bool+ svelte+ Enable logcat -S statistics.
+ro.logd.kernel bool svelte+ Enable klogd daemon
+logd.statistics bool svelte+ Enable logcat -S statistics.
ro.debuggable number if not "1", logd.statistics &
ro.logd.kernel default false.
logd.logpersistd.enable bool auto Safe to start logpersist daemon service
@@ -57,11 +57,8 @@
NB:
- auto - managed by /init
-- bool+ - "true", "false" and comma separated list of "eng" (forced false if
- ro.debuggable is not "1") or "svelte" (forced false if ro.config.low_ram is
- true).
- svelte - see ro.config.low_ram for details.
-- svelte+ - see ro.config.low_ram and ro.debuggable for details.
+- svelte+ - If empty, default to true if `ro.config.low_ram == false && ro.debuggable == true`
- ro - <base property> temporary override, ro.<base property> platform default.
- persist - <base property> override, persist.<base property> platform default.
- build - VERBOSE for native, DEBUG for jvm isLoggable, or developer option.
diff --git a/logd/README.replay.md b/logd/README.replay.md
new file mode 100644
index 0000000..5f7ec9e
--- /dev/null
+++ b/logd/README.replay.md
@@ -0,0 +1,46 @@
+logd can record and replay log messages for offline analysis.
+
+Recording Messages
+------------------
+
+logd has a `RecordingLogBuffer` buffer that records messages to /data/misc/logd/recorded-messages.
+It stores messages in memory until that file is accessible, in order to capture all messages since
+the beginning of boot. It is only meant for logging developers to use and must be manually enabled
+in by adding `RecordingLogBuffer.cpp` to `Android.bp` and setting
+`log_buffer = new SimpleLogBuffer(&reader_list, &log_tags, &log_statistics);` in `main.cpp`.
+
+Recording messages may delay the Log() function from completing and it is highly recommended to make
+the logd socket in `liblog` blocking, by removing `SOCK_NONBLOCK` from the `socket()` call in
+`liblog/logd_writer.cpp`.
+
+Replaying Messages
+------------------
+
+Recorded messages can be replayed offline with the `replay_messages` tool. It runs on host and
+device and supports the following options:
+
+1. `interesting` - this prints 'interesting' statistics for each of the log buffer types (simple,
+ chatty, serialized). The statistics are:
+ 1. Log Entry Count
+ 2. Size (the uncompressed size of the log messages in bytes)
+ 3. Overhead (the total cost of the log messages in memory in bytes)
+ 4. Range (the range of time that the logs cover in seconds)
+2. `memory_usage BUFFER_TYPE` - this prints the memory usage (sum of private dirty pages of the
+ `replay_messages` process). Note that the input file is mmap()'ed as RO/Shared so it does not
+ appear in these dirty pages, and a baseline is taken before allocating the log buffers, so only
+ their contributions are measured. The tool outputs the memory usage every 100,000 messages.
+3. `latency BUFFER_TYPE` - this prints statistics of the latency of the Log() function for the given
+ buffer type. It specifically prints the 1st, 2nd, and 3rd quartiles; the 95th, 99th, and 99.99th
+ percentiles; and the maximum latency.
+4. `print_logs BUFFER_TYPE [buffers] [print_point]` - this prints the logs as processed by the given
+ buffer_type from the buffers specified by `buffers` starting after the number of logs specified by
+ `print_point` have been logged. This acts as if a user called `logcat` immediately after the
+ specified logs have been logged, which is particularly useful since it will show the chatty
+ pruning messages at that point. It additionally prints the statistics from `logcat -S` after the
+ logs.
+ `buffers` is a comma separated list of the numeric buffer id values from `<android/log.h>`. For
+ example, `0,1,3` represents the main, radio, and system buffers. It can can also be `all`.
+ `print_point` is an positive integer. If it is unspecified, logs are printed after the entire
+ input file is consumed.
+5. `nothing BUFFER_TYPE` - this does nothing other than read the input file and call Log() for the
+ given buffer type. This is used for profiling CPU usage of strictly the log buffer.
diff --git a/trusty/libtrusty/tipc_ioctl.h b/logd/RecordedLogMessage.h
similarity index 65%
rename from trusty/libtrusty/tipc_ioctl.h
rename to logd/RecordedLogMessage.h
index 27da56a..f18c422 100644
--- a/trusty/libtrusty/tipc_ioctl.h
+++ b/logd/RecordedLogMessage.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,13 +14,17 @@
* limitations under the License.
*/
-#ifndef _TIPC_IOCTL_H
-#define _TIPC_IOCTL_H
+#pragma once
-#include <linux/ioctl.h>
-#include <linux/types.h>
+#include <inttypes.h>
-#define TIPC_IOC_MAGIC 'r'
-#define TIPC_IOC_CONNECT _IOW(TIPC_IOC_MAGIC, 0x80, char *)
+#include <log/log_time.h>
-#endif
+struct __attribute__((packed)) RecordedLogMessage {
+ uint32_t uid;
+ uint32_t pid;
+ uint32_t tid;
+ log_time realtime;
+ uint16_t msg_len;
+ uint8_t log_id;
+};
diff --git a/logd/RecordingLogBuffer.cpp b/logd/RecordingLogBuffer.cpp
new file mode 100644
index 0000000..f5991f3
--- /dev/null
+++ b/logd/RecordingLogBuffer.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "RecordingLogBuffer.h"
+
+#include <android-base/file.h>
+
+static void WriteLogMessage(int fd, const RecordedLogMessage& meta, const std::string& msg) {
+ android::base::WriteFully(fd, &meta, sizeof(meta));
+ android::base::WriteFully(fd, msg.c_str(), meta.msg_len);
+}
+
+void RecordingLogBuffer::RecordLogMessage(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
+ pid_t tid, const char* msg, uint16_t len) {
+ auto lock = std::lock_guard{lock_};
+ if (len > LOGGER_ENTRY_MAX_PAYLOAD) {
+ len = LOGGER_ENTRY_MAX_PAYLOAD;
+ }
+
+ RecordedLogMessage recorded_log_message = {
+ .uid = uid,
+ .pid = static_cast<uint32_t>(pid),
+ .tid = static_cast<uint32_t>(tid),
+ .realtime = realtime,
+ .msg_len = len,
+ .log_id = static_cast<uint8_t>(log_id),
+ };
+
+ if (!fd_.ok()) {
+ fd_.reset(open("/data/misc/logd/recorded-messages",
+ O_WRONLY | O_CREAT | O_APPEND | O_CLOEXEC, 0666));
+ if (!fd_.ok()) {
+ since_boot_messages_.emplace_back(recorded_log_message, std::string(msg, len));
+ return;
+ } else {
+ for (const auto& [meta, msg] : since_boot_messages_) {
+ WriteLogMessage(fd_.get(), meta, msg);
+ }
+ }
+ }
+
+ WriteLogMessage(fd_.get(), recorded_log_message, std::string(msg, len));
+}
+
+int RecordingLogBuffer::Log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid,
+ const char* msg, uint16_t len) {
+ RecordLogMessage(log_id, realtime, uid, pid, tid, msg, len);
+ return SimpleLogBuffer::Log(log_id, realtime, uid, pid, tid, msg, len);
+}
\ No newline at end of file
diff --git a/logd/RecordingLogBuffer.h b/logd/RecordingLogBuffer.h
new file mode 100644
index 0000000..49a0aba
--- /dev/null
+++ b/logd/RecordingLogBuffer.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "SimpleLogBuffer.h"
+
+#include <string>
+#include <tuple>
+#include <vector>
+
+#include <android-base/unique_fd.h>
+
+#include "RecordedLogMessage.h"
+
+class RecordingLogBuffer : public SimpleLogBuffer {
+ public:
+ RecordingLogBuffer(LogReaderList* reader_list, LogTags* tags, LogStatistics* stats)
+ : SimpleLogBuffer(reader_list, tags, stats) {}
+
+ int Log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid, const char* msg,
+ uint16_t len) override;
+
+ private:
+ void RecordLogMessage(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid,
+ const char* msg, uint16_t len);
+
+ std::vector<std::pair<RecordedLogMessage, std::string>> since_boot_messages_;
+ android::base::unique_fd fd_;
+};
diff --git a/logd/ReplayMessages.cpp b/logd/ReplayMessages.cpp
new file mode 100644
index 0000000..56509ec
--- /dev/null
+++ b/logd/ReplayMessages.cpp
@@ -0,0 +1,472 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <inttypes.h>
+
+#include <chrono>
+#include <map>
+
+#include <android-base/file.h>
+#include <android-base/mapped_file.h>
+#include <android-base/parseint.h>
+#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
+#include <android/log.h>
+#include <log/log_time.h>
+#include <log/logprint.h>
+
+#include "ChattyLogBuffer.h"
+#include "LogBuffer.h"
+#include "LogStatistics.h"
+#include "RecordedLogMessage.h"
+#include "SerializedLogBuffer.h"
+#include "SimpleLogBuffer.h"
+
+using android::base::MappedFile;
+using android::base::ParseInt;
+using android::base::ParseUint;
+using android::base::Split;
+
+char* android::uidToName(uid_t) {
+ return nullptr;
+}
+
+static size_t GetPrivateDirty() {
+ // Allocate once and hope that we don't need to reallocate >40000, to prevent heap fragmentation
+ static std::string smaps(40000, '\0');
+ android::base::ReadFileToString("/proc/self/smaps", &smaps);
+
+ size_t result = 0;
+ size_t base = 0;
+ size_t found;
+ while (true) {
+ found = smaps.find("Private_Dirty:", base);
+ if (found == smaps.npos) break;
+
+ found += sizeof("Private_Dirty:");
+
+ result += atoi(&smaps[found]);
+
+ base = found + 1;
+ }
+
+ return result;
+}
+
+static AndroidLogFormat* GetLogFormat() {
+ static AndroidLogFormat* format = [] {
+ auto* format = android_log_format_new();
+ android_log_setPrintFormat(format, android_log_formatFromString("threadtime"));
+ android_log_setPrintFormat(format, android_log_formatFromString("uid"));
+ return format;
+ }();
+ return format;
+}
+
+static void PrintMessage(struct log_msg* buf) {
+ bool is_binary =
+ buf->id() == LOG_ID_EVENTS || buf->id() == LOG_ID_STATS || buf->id() == LOG_ID_SECURITY;
+
+ AndroidLogEntry entry;
+ int err;
+ if (is_binary) {
+ char binaryMsgBuf[1024];
+ err = android_log_processBinaryLogBuffer(&buf->entry, &entry, nullptr, binaryMsgBuf,
+ sizeof(binaryMsgBuf));
+ } else {
+ err = android_log_processLogBuffer(&buf->entry, &entry);
+ }
+ if (err < 0) {
+ fprintf(stderr, "Error parsing log message\n");
+ }
+
+ android_log_printLogLine(GetLogFormat(), STDOUT_FILENO, &entry);
+}
+
+static log_time GetFirstTimeStamp(const MappedFile& recorded_messages) {
+ if (sizeof(RecordedLogMessage) >= recorded_messages.size()) {
+ fprintf(stderr, "At least one log message must be present in the input\n");
+ exit(1);
+ }
+
+ auto* meta = reinterpret_cast<RecordedLogMessage*>(recorded_messages.data());
+ return meta->realtime;
+}
+
+static LogMask BuffersToLogMask(const char* buffers) {
+ if (buffers == nullptr || !strcmp(buffers, "all")) {
+ return kLogMaskAll;
+ }
+ auto string_ids = Split(buffers, ",");
+ LogMask log_mask = 0;
+ for (const auto& string_id : string_ids) {
+ int buffer_id;
+ if (!ParseInt(string_id, &buffer_id, 0, 7)) {
+ fprintf(stderr, "Could not parse buffer_id '%s'\n", string_id.c_str());
+ exit(1);
+ }
+ log_mask |= 1 << buffer_id;
+ }
+ return log_mask;
+}
+
+class StdoutWriter : public LogWriter {
+ public:
+ StdoutWriter() : LogWriter(0, true) {}
+ bool Write(const logger_entry& entry, const char* message) override {
+ struct log_msg log_msg;
+ log_msg.entry = entry;
+ if (log_msg.entry.len > LOGGER_ENTRY_MAX_PAYLOAD) {
+ fprintf(stderr, "payload too large %" PRIu16, log_msg.entry.len);
+ exit(1);
+ }
+ memcpy(log_msg.msg(), message, log_msg.entry.len);
+
+ PrintMessage(&log_msg);
+
+ return true;
+ }
+
+ void Shutdown() override {
+ fprintf(stderr, "LogWriter::Shutdown() called\n");
+ exit(1);
+ }
+
+ std::string name() const override { return "stdout writer"; }
+};
+
+class Operation {
+ public:
+ virtual ~Operation() {}
+
+ virtual void Begin() {}
+ virtual void Log(const RecordedLogMessage& meta, const char* msg) = 0;
+ virtual void End() {}
+};
+
+class PrintInteresting : public Operation {
+ public:
+ PrintInteresting(log_time first_log_timestamp)
+ : stats_simple_{false, false, first_log_timestamp},
+ stats_chatty_{false, false, first_log_timestamp},
+ stats_serialized_{false, true, first_log_timestamp} {}
+
+ void Begin() override {
+ printf("message_count,simple_main_lines,simple_radio_lines,simple_events_lines,simple_"
+ "system_lines,simple_crash_lines,simple_stats_lines,simple_security_lines,simple_"
+ "kernel_lines,simple_main_size,simple_radio_size,simple_events_size,simple_system_"
+ "size,simple_crash_size,simple_stats_size,simple_security_size,simple_kernel_size,"
+ "simple_main_overhead,simple_radio_overhead,simple_events_overhead,simple_system_"
+ "overhead,simple_crash_overhead,simple_stats_overhead,simple_security_overhead,"
+ "simple_kernel_overhead,simple_main_range,simple_radio_range,simple_events_range,"
+ "simple_system_range,simple_crash_range,simple_stats_range,simple_security_range,"
+ "simple_kernel_range,chatty_main_lines,chatty_radio_lines,chatty_events_lines,"
+ "chatty_system_lines,chatty_crash_lines,chatty_stats_lines,chatty_security_lines,"
+ "chatty_"
+ "kernel_lines,chatty_main_size,chatty_radio_size,chatty_events_size,chatty_system_"
+ "size,chatty_crash_size,chatty_stats_size,chatty_security_size,chatty_kernel_size,"
+ "chatty_main_overhead,chatty_radio_overhead,chatty_events_overhead,chatty_system_"
+ "overhead,chatty_crash_overhead,chatty_stats_overhead,chatty_security_overhead,"
+ "chatty_kernel_overhead,chatty_main_range,chatty_radio_range,chatty_events_range,"
+ "chatty_system_range,chatty_crash_range,chatty_stats_range,chatty_security_range,"
+ "chatty_kernel_range,serialized_main_lines,serialized_radio_lines,serialized_events_"
+ "lines,serialized_"
+ "system_lines,serialized_crash_lines,serialized_stats_lines,serialized_security_"
+ "lines,serialized_"
+ "kernel_lines,serialized_main_size,serialized_radio_size,serialized_events_size,"
+ "serialized_system_"
+ "size,serialized_crash_size,serialized_stats_size,serialized_security_size,"
+ "serialized_kernel_size,"
+ "serialized_main_overhead,serialized_radio_overhead,serialized_events_overhead,"
+ "serialized_system_"
+ "overhead,serialized_crash_overhead,serialized_stats_overhead,serialized_security_"
+ "overhead,"
+ "serialized_kernel_overhead,serialized_main_range,serialized_radio_range,serialized_"
+ "events_range,"
+ "serialized_system_range,serialized_crash_range,serialized_stats_range,serialized_"
+ "security_range,"
+ "serialized_kernel_range\n");
+ }
+
+ void Log(const RecordedLogMessage& meta, const char* msg) override {
+ simple_log_buffer_.Log(static_cast<log_id_t>(meta.log_id), meta.realtime, meta.uid,
+ meta.pid, meta.tid, msg, meta.msg_len);
+
+ chatty_log_buffer_.Log(static_cast<log_id_t>(meta.log_id), meta.realtime, meta.uid,
+ meta.pid, meta.tid, msg, meta.msg_len);
+
+ serialized_log_buffer_.Log(static_cast<log_id_t>(meta.log_id), meta.realtime, meta.uid,
+ meta.pid, meta.tid, msg, meta.msg_len);
+
+ if (num_message_ % 10000 == 0) {
+ printf("%" PRIu64 ",%s,%s,%s\n", num_message_,
+ stats_simple_.ReportInteresting().c_str(),
+ stats_chatty_.ReportInteresting().c_str(),
+ stats_serialized_.ReportInteresting().c_str());
+ }
+
+ num_message_++;
+ }
+
+ private:
+ uint64_t num_message_ = 1;
+
+ LogReaderList reader_list_;
+ LogTags tags_;
+ PruneList prune_list_;
+
+ LogStatistics stats_simple_;
+ SimpleLogBuffer simple_log_buffer_{&reader_list_, &tags_, &stats_simple_};
+
+ LogStatistics stats_chatty_;
+ ChattyLogBuffer chatty_log_buffer_{&reader_list_, &tags_, &prune_list_, &stats_chatty_};
+
+ LogStatistics stats_serialized_;
+ SerializedLogBuffer serialized_log_buffer_{&reader_list_, &tags_, &stats_serialized_};
+};
+
+class SingleBufferOperation : public Operation {
+ public:
+ SingleBufferOperation(log_time first_log_timestamp, const char* buffer) {
+ if (!strcmp(buffer, "simple")) {
+ stats_.reset(new LogStatistics{false, false, first_log_timestamp});
+ log_buffer_.reset(new SimpleLogBuffer(&reader_list_, &tags_, stats_.get()));
+ } else if (!strcmp(buffer, "chatty")) {
+ stats_.reset(new LogStatistics{false, false, first_log_timestamp});
+ log_buffer_.reset(
+ new ChattyLogBuffer(&reader_list_, &tags_, &prune_list_, stats_.get()));
+ } else if (!strcmp(buffer, "serialized")) {
+ stats_.reset(new LogStatistics{false, true, first_log_timestamp});
+ log_buffer_.reset(new SerializedLogBuffer(&reader_list_, &tags_, stats_.get()));
+ } else {
+ fprintf(stderr, "invalid log buffer type '%s'\n", buffer);
+ abort();
+ }
+ }
+
+ void Log(const RecordedLogMessage& meta, const char* msg) override {
+ PreOperation();
+ log_buffer_->Log(static_cast<log_id_t>(meta.log_id), meta.realtime, meta.uid, meta.pid,
+ meta.tid, msg, meta.msg_len);
+
+ Operation();
+
+ num_message_++;
+ }
+
+ virtual void PreOperation() {}
+ virtual void Operation() {}
+
+ protected:
+ uint64_t num_message_ = 1;
+
+ LogReaderList reader_list_;
+ LogTags tags_;
+ PruneList prune_list_;
+
+ std::unique_ptr<LogStatistics> stats_;
+ std::unique_ptr<LogBuffer> log_buffer_;
+};
+
+class PrintMemory : public SingleBufferOperation {
+ public:
+ PrintMemory(log_time first_log_timestamp, const char* buffer)
+ : SingleBufferOperation(first_log_timestamp, buffer) {}
+
+ void Operation() override {
+ if (num_message_ % 100000 == 0) {
+ printf("%" PRIu64 ",%s\n", num_message_,
+ std::to_string(GetPrivateDirty() - baseline_memory_).c_str());
+ }
+ }
+
+ private:
+ size_t baseline_memory_ = GetPrivateDirty();
+};
+
+class PrintLogs : public SingleBufferOperation {
+ public:
+ PrintLogs(log_time first_log_timestamp, const char* buffer, const char* buffers,
+ const char* print_point)
+ : SingleBufferOperation(first_log_timestamp, buffer) {
+ mask_ = BuffersToLogMask(buffers);
+ if (print_point != nullptr) {
+ uint64_t result = 0;
+ if (!ParseUint(print_point, &result)) {
+ fprintf(stderr, "Could not parse print point '%s'\n", print_point);
+ exit(1);
+ }
+ print_point_ = result;
+ }
+ }
+
+ void Operation() override {
+ if (print_point_ && num_message_ >= *print_point_) {
+ End();
+ exit(0);
+ }
+ }
+
+ void End() override {
+ std::unique_ptr<LogWriter> test_writer(new StdoutWriter());
+ std::unique_ptr<FlushToState> flush_to_state = log_buffer_->CreateFlushToState(1, mask_);
+ log_buffer_->FlushTo(test_writer.get(), *flush_to_state, nullptr);
+
+ auto stats_string = stats_->Format(0, 0, mask_);
+ printf("%s\n", stats_string.c_str());
+ }
+
+ private:
+ LogMask mask_ = kLogMaskAll;
+ std::optional<uint64_t> print_point_;
+};
+
+class PrintLatency : public SingleBufferOperation {
+ public:
+ PrintLatency(log_time first_log_timestamp, const char* buffer)
+ : SingleBufferOperation(first_log_timestamp, buffer) {}
+
+ void PreOperation() override { operation_start_ = std::chrono::steady_clock::now(); }
+
+ void Operation() override {
+ auto end = std::chrono::steady_clock::now();
+ auto duration = (end - operation_start_).count();
+ durations_.emplace_back(duration);
+ }
+
+ void End() override {
+ std::sort(durations_.begin(), durations_.end());
+ auto q1 = durations_.size() / 4;
+ auto q2 = durations_.size() / 2;
+ auto q3 = 3 * durations_.size() / 4;
+
+ auto p95 = 95 * durations_.size() / 100;
+ auto p99 = 99 * durations_.size() / 100;
+ auto p9999 = 9999 * durations_.size() / 10000;
+
+ printf("q1: %lld q2: %lld q3: %lld p95: %lld p99: %lld p99.99: %lld max: %lld\n",
+ durations_[q1], durations_[q2], durations_[q3], durations_[p95], durations_[p99],
+ durations_[p9999], durations_.back());
+ }
+
+ private:
+ std::chrono::steady_clock::time_point operation_start_;
+ std::vector<long long> durations_;
+};
+
+class PrintAllLogs : public SingleBufferOperation {
+ public:
+ PrintAllLogs(log_time first_log_timestamp, const char* buffer, const char* buffers)
+ : SingleBufferOperation(first_log_timestamp, buffer) {
+ LogMask mask = BuffersToLogMask(buffers);
+ auto lock = std::unique_lock{reader_list_.reader_threads_lock()};
+ std::unique_ptr<LogWriter> stdout_writer(new StdoutWriter());
+ std::unique_ptr<LogReaderThread> log_reader(
+ new LogReaderThread(log_buffer_.get(), &reader_list_, std::move(stdout_writer),
+ false, 0, mask, 0, {}, 1, {}));
+ reader_list_.reader_threads().emplace_back(std::move(log_reader));
+ }
+
+ void Operation() override {
+ // If the rate of reading logs is slower than the rate of incoming logs, then the reader
+ // thread is disconnected to not overflow log buffers, therefore we artificially slow down
+ // the incoming log rate.
+ usleep(100);
+ }
+};
+
+int main(int argc, char** argv) {
+ if (argc < 3) {
+ fprintf(stderr, "Usage: %s FILE OPERATION [BUFFER] [OPTIONS]\n", argv[0]);
+ return 1;
+ }
+
+ if (strcmp(argv[2], "interesting") != 0 && argc < 4) {
+ fprintf(stderr, "Operations other than 'interesting' require a BUFFER argument\n");
+ return 1;
+ }
+
+ int recorded_messages_fd = open(argv[1], O_RDONLY);
+ if (recorded_messages_fd == -1) {
+ fprintf(stderr, "Couldn't open input file\n");
+ return 1;
+ }
+ struct stat fd_stat;
+ if (fstat(recorded_messages_fd, &fd_stat) != 0) {
+ fprintf(stderr, "Couldn't fstat input file\n");
+ return 1;
+ }
+ auto recorded_messages = MappedFile::FromFd(recorded_messages_fd, 0,
+ static_cast<size_t>(fd_stat.st_size), PROT_READ);
+ if (recorded_messages == nullptr) {
+ fprintf(stderr, "Couldn't mmap input file\n");
+ return 1;
+ }
+
+ // LogStatistics typically uses 'now()' to initialize its log range state, but this doesn't work
+ // when replaying older logs, so we instead give it the timestamp from the first log.
+ log_time first_log_timestamp = GetFirstTimeStamp(*recorded_messages);
+
+ std::unique_ptr<Operation> operation;
+ if (!strcmp(argv[2], "interesting")) {
+ operation.reset(new PrintInteresting(first_log_timestamp));
+ } else if (!strcmp(argv[2], "memory_usage")) {
+ operation.reset(new PrintMemory(first_log_timestamp, argv[3]));
+ } else if (!strcmp(argv[2], "latency")) {
+ operation.reset(new PrintLatency(first_log_timestamp, argv[3]));
+ } else if (!strcmp(argv[2], "print_logs")) {
+ operation.reset(new PrintLogs(first_log_timestamp, argv[3], argc > 4 ? argv[4] : nullptr,
+ argc > 5 ? argv[5] : nullptr));
+ } else if (!strcmp(argv[2], "print_all_logs")) {
+ operation.reset(
+ new PrintAllLogs(first_log_timestamp, argv[3], argc > 4 ? argv[4] : nullptr));
+ } else if (!strcmp(argv[2], "nothing")) {
+ operation.reset(new SingleBufferOperation(first_log_timestamp, argv[3]));
+ } else {
+ fprintf(stderr, "unknown operation '%s'\n", argv[2]);
+ return 1;
+ }
+
+ // LogBuffer::Log() won't log without this on host.
+ __android_log_set_minimum_priority(ANDROID_LOG_VERBOSE);
+ // But we still want to suppress messages <= error to not interrupt the rest of the output.
+ __android_log_set_logger([](const struct __android_log_message* log_message) {
+ if (log_message->priority < ANDROID_LOG_ERROR) {
+ return;
+ }
+ __android_log_stderr_logger(log_message);
+ });
+
+ operation->Begin();
+
+ uint64_t read_position = 0;
+ while (read_position + sizeof(RecordedLogMessage) < recorded_messages->size()) {
+ auto* meta =
+ reinterpret_cast<RecordedLogMessage*>(recorded_messages->data() + read_position);
+ if (read_position + sizeof(RecordedLogMessage) + meta->msg_len >=
+ recorded_messages->size()) {
+ break;
+ }
+ char* msg = recorded_messages->data() + read_position + sizeof(RecordedLogMessage);
+ read_position += sizeof(RecordedLogMessage) + meta->msg_len;
+
+ operation->Log(*meta, msg);
+ }
+
+ operation->End();
+
+ return 0;
+}
diff --git a/logd/SerializedFlushToState.cpp b/logd/SerializedFlushToState.cpp
index 2633348..b02ccc3 100644
--- a/logd/SerializedFlushToState.cpp
+++ b/logd/SerializedFlushToState.cpp
@@ -31,7 +31,7 @@
SerializedFlushToState::~SerializedFlushToState() {
log_id_for_each(i) {
if (log_positions_[i]) {
- log_positions_[i]->buffer_it->DecReaderRefCount(true);
+ log_positions_[i]->buffer_it->DecReaderRefCount();
}
}
}
@@ -78,7 +78,7 @@
logs_needed_from_next_position_[log_id] = true;
} else {
// Otherwise, if there is another buffer piece, move to that and do the same check.
- buffer_it->DecReaderRefCount(true);
+ buffer_it->DecReaderRefCount();
++buffer_it;
buffer_it->IncReaderRefCount();
log_positions_[log_id]->read_offset = 0;
@@ -134,7 +134,7 @@
}
// // Decrease the ref count since we're deleting our reference.
- buffer_it->DecReaderRefCount(false);
+ buffer_it->DecReaderRefCount();
// Delete in the reference.
log_positions_[log_id].reset();
diff --git a/logd/SerializedLogBuffer.cpp b/logd/SerializedLogBuffer.cpp
index a626d30..972a3f3 100644
--- a/logd/SerializedLogBuffer.cpp
+++ b/logd/SerializedLogBuffer.cpp
@@ -123,7 +123,7 @@
stats_->Subtract(entry->ToLogStatisticsElement(log_id));
read_offset += entry->total_len();
}
- chunk.DecReaderRefCount(false);
+ chunk.DecReaderRefCount();
}
void SerializedLogBuffer::NotifyReadersOfPrune(
diff --git a/logd/SerializedLogChunk.cpp b/logd/SerializedLogChunk.cpp
index e444856..de641d6 100644
--- a/logd/SerializedLogChunk.cpp
+++ b/logd/SerializedLogChunk.cpp
@@ -31,7 +31,6 @@
<< " size used: " << write_offset_
<< " compressed size: " << compressed_log_.size();
}
- contents_.Resize(0);
}
// TODO: Develop a better reference counting strategy to guard against the case where the writer is
@@ -44,13 +43,13 @@
CompressionEngine::GetInstance().Decompress(compressed_log_, contents_);
}
-void SerializedLogChunk::DecReaderRefCount(bool compress) {
+void SerializedLogChunk::DecReaderRefCount() {
CHECK_NE(reader_ref_count_, 0U);
if (--reader_ref_count_ != 0) {
return;
}
- if (compress && !writer_active_) {
- Compress();
+ if (!writer_active_) {
+ contents_.Resize(0);
}
}
@@ -83,18 +82,19 @@
}
if (new_write_offset == 0) {
- DecReaderRefCount(false);
+ DecReaderRefCount();
return true;
}
- // Clear the old compressed logs and set write_offset_ appropriately for DecReaderRefCount()
- // to compress the new partially cleared log.
+ // Clear the old compressed logs and set write_offset_ appropriately to compress the new
+ // partially cleared log.
if (new_write_offset != write_offset_) {
compressed_log_.Resize(0);
write_offset_ = new_write_offset;
+ Compress();
}
- DecReaderRefCount(true);
+ DecReaderRefCount();
return false;
}
diff --git a/logd/SerializedLogChunk.h b/logd/SerializedLogChunk.h
index 50bae63..0991eac 100644
--- a/logd/SerializedLogChunk.h
+++ b/logd/SerializedLogChunk.h
@@ -30,9 +30,7 @@
void Compress();
void IncReaderRefCount();
- // Decrease the reader ref count and compress the log if appropriate. `compress` should only be
- // set to false in the case that the log buffer will be deleted afterwards.
- void DecReaderRefCount(bool compress);
+ void DecReaderRefCount();
// Must have no readers referencing this. Return true if there are no logs left in this chunk.
bool ClearUidLogs(uid_t uid, log_id_t log_id, LogStatistics* stats);
@@ -50,8 +48,9 @@
void FinishWriting() {
writer_active_ = false;
+ Compress();
if (reader_ref_count_ == 0) {
- Compress();
+ contents_.Resize(0);
}
}
diff --git a/logd/SerializedLogChunkTest.cpp b/logd/SerializedLogChunkTest.cpp
index 2b478a3..f10b9c6 100644
--- a/logd/SerializedLogChunkTest.cpp
+++ b/logd/SerializedLogChunkTest.cpp
@@ -113,8 +113,7 @@
TEST(SerializedLogChunk, catch_DecCompressedRef_CHECK) {
size_t chunk_size = 10 * 4096;
auto chunk = SerializedLogChunk{chunk_size};
- EXPECT_DEATH({ chunk.DecReaderRefCount(true); }, "");
- EXPECT_DEATH({ chunk.DecReaderRefCount(false); }, "");
+ EXPECT_DEATH({ chunk.DecReaderRefCount(); }, "");
}
// Check that the CHECK() in ClearUidLogs() if the ref count is greater than 0 is caught.
@@ -123,7 +122,7 @@
auto chunk = SerializedLogChunk{chunk_size};
chunk.IncReaderRefCount();
EXPECT_DEATH({ chunk.ClearUidLogs(1000, LOG_ID_MAIN, nullptr); }, "");
- chunk.DecReaderRefCount(false);
+ chunk.DecReaderRefCount();
}
class UidClearTest : public testing::TestWithParam<bool> {
@@ -144,7 +143,7 @@
check(chunk_);
if (finish_writing) {
- chunk_.DecReaderRefCount(false);
+ chunk_.DecReaderRefCount();
}
}
diff --git a/logd/fuzz/log_buffer_log_fuzzer.cpp b/logd/fuzz/log_buffer_log_fuzzer.cpp
index 8309f95..d71a2f9 100644
--- a/logd/fuzz/log_buffer_log_fuzzer.cpp
+++ b/logd/fuzz/log_buffer_log_fuzzer.cpp
@@ -30,16 +30,6 @@
#define MIN_TAG_ID 1000
#define TAG_MOD 10
-#ifndef __ANDROID__
-unsigned long __android_logger_get_buffer_size(log_id_t) {
- return 1024 * 1024;
-}
-
-bool __android_logger_valid_buffer_size(unsigned long) {
- return true;
-}
-#endif
-
char* android::uidToName(uid_t) {
return strdup("fake");
}
diff --git a/logd/logd_test.cpp b/logd/logd_test.cpp
index ed34ea4..5a0585a 100644
--- a/logd/logd_test.cpp
+++ b/logd/logd_test.cpp
@@ -162,6 +162,7 @@
}
#endif
+#ifdef LOGD_ENABLE_FLAKY_TESTS
TEST(logd, statistics) {
#ifdef __ANDROID__
size_t len;
@@ -237,6 +238,7 @@
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
+#endif
#ifdef __ANDROID__
static void caught_signal(int /* signum */) {
@@ -720,6 +722,7 @@
}
#endif
+#ifdef LOGD_ENABLE_FLAKY_TESTS
// b/27242723 confirmed fixed
TEST(logd, SNDTIMEO) {
#ifdef __ANDROID__
@@ -777,6 +780,7 @@
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
+#endif
TEST(logd, getEventTag_list) {
#ifdef __ANDROID__
@@ -832,127 +836,3 @@
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-
-#ifdef __ANDROID__
-static inline uint32_t get4LE(const uint8_t* src) {
- return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
-}
-
-static inline uint32_t get4LE(const char* src) {
- return get4LE(reinterpret_cast<const uint8_t*>(src));
-}
-#endif
-
-void __android_log_btwrite_multiple__helper(int count) {
-#ifdef __ANDROID__
- log_time ts(CLOCK_MONOTONIC);
- usleep(100);
- log_time ts1(CLOCK_MONOTONIC);
-
- // We fork to create a unique pid for the submitted log messages
- // so that we do not collide with the other _multiple_ tests.
-
- pid_t pid = fork();
-
- if (pid == 0) {
- // child
- for (int i = count; i; --i) {
- ASSERT_LT(
- 0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
- usleep(100);
- }
- ASSERT_LT(0,
- __android_log_btwrite(0, EVENT_TYPE_LONG, &ts1, sizeof(ts1)));
- usleep(1000000);
-
- _exit(0);
- }
-
- siginfo_t info = {};
- ASSERT_EQ(0, TEMP_FAILURE_RETRY(waitid(P_PID, pid, &info, WEXITED)));
- ASSERT_EQ(0, info.si_status);
-
- struct logger_list* logger_list;
- ASSERT_TRUE(nullptr != (logger_list = android_logger_list_open(LOG_ID_EVENTS,
- ANDROID_LOG_NONBLOCK, 0, pid)));
-
- int expected_count = (count < 2) ? count : 2;
- int expected_chatty_count = (count <= 2) ? 0 : 1;
- int expected_identical_count = (count < 2) ? 0 : (count - 2);
- static const int expected_expire_count = 0;
-
- count = 0;
- int second_count = 0;
- int chatty_count = 0;
- int identical_count = 0;
- int expire_count = 0;
-
- for (;;) {
- log_msg log_msg;
- if (android_logger_list_read(logger_list, &log_msg) <= 0) break;
-
- if ((log_msg.entry.pid != pid) || (log_msg.entry.len < (4 + 1 + 8)) ||
- (log_msg.id() != LOG_ID_EVENTS))
- continue;
-
- char* eventData = log_msg.msg();
- if (!eventData) continue;
-
- uint32_t tag = get4LE(eventData);
-
- if ((eventData[4] == EVENT_TYPE_LONG) &&
- (log_msg.entry.len == (4 + 1 + 8))) {
- if (tag != 0) continue;
-
- log_time* tx = reinterpret_cast<log_time*>(eventData + 4 + 1);
- if (ts == *tx) {
- ++count;
- } else if (ts1 == *tx) {
- ++second_count;
- }
- } else if (eventData[4] == EVENT_TYPE_STRING) {
- if (tag != CHATTY_LOG_TAG) continue;
- ++chatty_count;
- // int len = get4LE(eventData + 4 + 1);
- log_msg.buf[LOGGER_ENTRY_MAX_LEN] = '\0';
- const char* cp;
- if ((cp = strstr(eventData + 4 + 1 + 4, " identical "))) {
- unsigned val = 0;
- sscanf(cp, " identical %u lines", &val);
- identical_count += val;
- } else if ((cp = strstr(eventData + 4 + 1 + 4, " expire "))) {
- unsigned val = 0;
- sscanf(cp, " expire %u lines", &val);
- expire_count += val;
- }
- }
- }
-
- android_logger_list_close(logger_list);
-
- EXPECT_EQ(expected_count, count);
- EXPECT_EQ(1, second_count);
- EXPECT_EQ(expected_chatty_count, chatty_count);
- EXPECT_EQ(expected_identical_count, identical_count);
- EXPECT_EQ(expected_expire_count, expire_count);
-#else
- count = 0;
- GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif
-}
-
-TEST(logd, multiple_test_1) {
- __android_log_btwrite_multiple__helper(1);
-}
-
-TEST(logd, multiple_test_2) {
- __android_log_btwrite_multiple__helper(2);
-}
-
-TEST(logd, multiple_test_3) {
- __android_log_btwrite_multiple__helper(3);
-}
-
-TEST(logd, multiple_test_10) {
- __android_log_btwrite_multiple__helper(10);
-}
diff --git a/logd/main.cpp b/logd/main.cpp
index 897e11e..c92c5b7 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -62,7 +62,9 @@
#include "SerializedLogBuffer.h"
#include "SimpleLogBuffer.h"
+using android::base::GetBoolProperty;
using android::base::GetProperty;
+using android::base::SetProperty;
#define KMSG_PRIORITY(PRI) \
'<', '0' + LOG_MAKEPRI(LOG_DAEMON, LOG_PRI(PRI)) / 10, \
@@ -82,9 +84,10 @@
PLOG(FATAL) << "failed to set batch scheduler";
}
- if (!__android_logger_property_get_bool("ro.debuggable", BOOL_DEFAULT_FALSE) &&
- prctl(PR_SET_DUMPABLE, 0) == -1) {
- PLOG(FATAL) << "failed to clear PR_SET_DUMPABLE";
+ if (!GetBoolProperty("ro.debuggable", false)) {
+ if (prctl(PR_SET_DUMPABLE, 0) == -1) {
+ PLOG(FATAL) << "failed to clear PR_SET_DUMPABLE";
+ }
}
std::unique_ptr<struct _cap_struct, int (*)(void*)> caps(cap_init(), cap_free);
@@ -110,6 +113,14 @@
}
}
+// GetBoolProperty that defaults to true if `ro.debuggable == true && ro.config.low_rawm == false`.
+static bool GetBoolPropertyEngSvelteDefault(const std::string& name) {
+ bool default_value =
+ GetBoolProperty("ro.debuggable", false) && !GetBoolProperty("ro.config.low_ram", false);
+
+ return GetBoolProperty(name, default_value);
+}
+
char* android::uidToName(uid_t u) {
struct Userdata {
uid_t uid;
@@ -207,6 +218,8 @@
// logging plugins like auditd and restart control. Additional
// transitory per-client threads are created for each reader.
int main(int argc, char* argv[]) {
+ // We want EPIPE when a reader disconnects, not to terminate logd.
+ signal(SIGPIPE, SIG_IGN);
// logd is written under the assumption that the timezone is UTC.
// If TZ is not set, persist.sys.timezone is looked up in some time utility
// libc functions, including mktime. It confuses the logd time handling,
@@ -236,10 +249,9 @@
}
int fdPmesg = -1;
- bool klogd = __android_logger_property_get_bool(
- "ro.logd.kernel",
- BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE);
+ bool klogd = GetBoolPropertyEngSvelteDefault("ro.logd.kernel");
if (klogd) {
+ SetProperty("ro.logd.kernel", "true");
static const char proc_kmsg[] = "/proc/kmsg";
fdPmesg = android_get_control_file(proc_kmsg);
if (fdPmesg < 0) {
@@ -249,7 +261,7 @@
if (fdPmesg < 0) PLOG(ERROR) << "Failed to open " << proc_kmsg;
}
- bool auditd = __android_logger_property_get_bool("ro.logd.auditd", BOOL_DEFAULT_TRUE);
+ bool auditd = GetBoolProperty("ro.logd.auditd", true);
DropPrivs(klogd, auditd);
// A cache of event log tags
@@ -258,13 +270,11 @@
// Pruning configuration.
PruneList prune_list;
- std::string buffer_type = GetProperty("logd.buffer_type", "chatty");
+ std::string buffer_type = GetProperty("logd.buffer_type", "serialized");
// Partial (required for chatty) or full logging statistics.
- bool enable_full_log_statistics = __android_logger_property_get_bool(
- "logd.statistics", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_PERSIST |
- BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE);
- LogStatistics log_statistics(enable_full_log_statistics, buffer_type == "serialized");
+ LogStatistics log_statistics(GetBoolPropertyEngSvelteDefault("logd.statistics"),
+ buffer_type == "serialized");
// Serves the purpose of managing the last logs times read on a socket connection, and as a
// reader lock on a range of log entries.
@@ -309,9 +319,7 @@
// and LogReader is notified to send updates to connected clients.
LogAudit* al = nullptr;
if (auditd) {
- int dmesg_fd = __android_logger_property_get_bool("ro.logd.auditd.dmesg", BOOL_DEFAULT_TRUE)
- ? fdDmesg
- : -1;
+ int dmesg_fd = GetBoolProperty("ro.logd.auditd.dmesg", true) ? fdDmesg : -1;
al = new LogAudit(log_buffer, dmesg_fd, &log_statistics);
}
diff --git a/property_service/libpropertyinfoserializer/property_info_serializer_test.cpp b/property_service/libpropertyinfoserializer/property_info_serializer_test.cpp
index a643062..3907413 100644
--- a/property_service/libpropertyinfoserializer/property_info_serializer_test.cpp
+++ b/property_service/libpropertyinfoserializer/property_info_serializer_test.cpp
@@ -139,7 +139,7 @@
auto property_info_area = reinterpret_cast<const PropertyInfoArea*>(serialized_trie.data());
- // Sanity check
+ // Smoke test
auto root_node = property_info_area->root_node();
EXPECT_STREQ("root", root_node.name());
EXPECT_STREQ("default", property_info_area->context(root_node.context_index()));
diff --git a/qemu_pipe/qemu_pipe.cpp b/qemu_pipe/qemu_pipe.cpp
index beeccb0..03afb21 100644
--- a/qemu_pipe/qemu_pipe.cpp
+++ b/qemu_pipe/qemu_pipe.cpp
@@ -35,7 +35,6 @@
#endif
int qemu_pipe_open(const char* pipeName) {
- // Sanity check.
if (!pipeName) {
errno = EINVAL;
return -1;
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index ac8e847..77fa94e 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -131,6 +131,16 @@
# via /vendor/lib/modules directly.
LOCAL_POST_INSTALL_CMD += ; ln -sf /vendor/vendor_dlkm/etc $(TARGET_ROOT_OUT)/vendor_dlkm/etc
+# For /odm_dlkm partition.
+LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/odm_dlkm
+# For Treble Generic System Image (GSI), system-as-root GSI needs to work on
+# both devices with and without /odm_dlkm partition. Those symlinks are for
+# devices without /odm_dlkm partition. For devices with /odm_dlkm
+# partition, mount odm_dlkm.img under /odm_dlkm will hide those symlinks.
+# Note that /odm_dlkm/lib is omitted because odm DLKMs should be accessed
+# via /odm/lib/modules directly.
+LOCAL_POST_INSTALL_CMD += ; ln -sf /odm/odm_dlkm/etc $(TARGET_ROOT_OUT)/odm_dlkm/etc
+
ifdef BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/cache
else
diff --git a/rootdir/init.rc b/rootdir/init.rc
index fb6f1be..6ef3bdc 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -81,6 +81,11 @@
# Mount tracefs
mount tracefs tracefs /sys/kernel/tracing
+ # create sys dirctory
+ mkdir /dev/sys 0755 system system
+ mkdir /dev/sys/fs 0755 system system
+ mkdir /dev/sys/block 0755 system system
+
# Run boringssl self test for each ABI so that later processes can skip it. http://b/139348610
on early-init && property:ro.product.cpu.abilist32=*
exec_start boringssl_self_test32
@@ -867,17 +872,26 @@
chown root system /sys/block/zram0/writeback
chmod 0664 /sys/block/zram0/writeback
+ # to access F2FS sysfs on dm-<num> directly
+ mkdir /dev/sys/fs/by-name 0755 system system
+ symlink /sys/fs/f2fs/${dev.mnt.blk.data} /dev/sys/fs/by-name/userdata
+
+ # to access dm-<num> sysfs
+ mkdir /dev/sys/block/by-name 0755 system system
+ symlink /sys/devices/virtual/block/${dev.mnt.blk.data} /dev/sys/block/by-name/userdata
+
# F2FS tuning. Set cp_interval larger than dirty_expire_centisecs, 30 secs,
# to avoid power consumption when system becomes mostly idle. Be careful
# to make it too large, since it may bring userdata loss, if they
# are not aware of using fsync()/sync() to prepare sudden power-cut.
- write /sys/fs/f2fs/${dev.mnt.blk.data}/cp_interval 200
- write /sys/fs/f2fs/${dev.mnt.blk.data}/gc_urgent_sleep_time 50
+ write /dev/sys/fs/by-name/userdata/cp_interval 200
+ write /dev/sys/fs/by-name/userdata/gc_urgent_sleep_time 50
+ write /dev/sys/fs/by-name/userdata/iostat_enable 1
# limit discard size to 128MB in order to avoid long IO latency
# for filesystem tuning first (dm or sda)
# Note that, if dm-<num> is used, sda/mmcblk0 should be tuned in vendor/init.rc
- write /sys/devices/virtual/block/${dev.mnt.blk.data}/queue/discard_max_bytes 134217728
+ write /dev/sys/block/by-name/userdata/queue/discard_max_bytes 134217728
# Permissions for System Server and daemons.
chown system system /sys/power/autosleep
diff --git a/trusty/confirmationui/NotSoSecureInput.cpp b/trusty/confirmationui/NotSoSecureInput.cpp
index 3d9a2d6..18e45cd 100644
--- a/trusty/confirmationui/NotSoSecureInput.cpp
+++ b/trusty/confirmationui/NotSoSecureInput.cpp
@@ -82,7 +82,7 @@
/**
* This is an implementation of the SecureInput protocol in unserspace. This is
- * just an example and should not be used as is. The protocol implemented her
+ * just an example and should not be used as is. The protocol implemented here
* should be used by a trusted input device that can assert user events with
* high assurance even if the HLOS kernel is compromised. A confirmationui HAL
* that links directly against this implementation is not secure and shal not be
diff --git a/trusty/gatekeeper/trusty_gatekeeper.cpp b/trusty/gatekeeper/trusty_gatekeeper.cpp
index d149664..e416fb2 100644
--- a/trusty/gatekeeper/trusty_gatekeeper.cpp
+++ b/trusty/gatekeeper/trusty_gatekeeper.cpp
@@ -56,9 +56,9 @@
SizedBuffer hidl_vec2sized_buffer(const hidl_vec<uint8_t>& vec) {
if (vec.size() == 0 || vec.size() > std::numeric_limits<uint32_t>::max()) return {};
- auto dummy = new uint8_t[vec.size()];
- std::copy(vec.begin(), vec.end(), dummy);
- return {dummy, static_cast<uint32_t>(vec.size())};
+ auto buffer = new uint8_t[vec.size()];
+ std::copy(vec.begin(), vec.end(), buffer);
+ return {buffer, static_cast<uint32_t>(vec.size())};
}
Return<void> TrustyGateKeeperDevice::enroll(uint32_t uid,
diff --git a/trusty/keymaster/TrustyKeymaster.cpp b/trusty/keymaster/TrustyKeymaster.cpp
index f3ef747..750a9d7 100644
--- a/trusty/keymaster/TrustyKeymaster.cpp
+++ b/trusty/keymaster/TrustyKeymaster.cpp
@@ -173,7 +173,7 @@
}
GetHmacSharingParametersResponse TrustyKeymaster::GetHmacSharingParameters() {
- // Dummy empty buffer to allow ForwardCommand to have something to serialize
+ // Empty buffer to allow ForwardCommand to have something to serialize
Buffer request;
GetHmacSharingParametersResponse response;
ForwardCommand(KM_GET_HMAC_SHARING_PARAMETERS, request, &response);
diff --git a/trusty/libtrusty/include/trusty/ipc.h b/trusty/libtrusty/include/trusty/ipc.h
new file mode 100644
index 0000000..1fa6fe4
--- /dev/null
+++ b/trusty/libtrusty/include/trusty/ipc.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _UAPI_LINUX_TRUSTY_IPC_H_
+#define _UAPI_LINUX_TRUSTY_IPC_H_
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+#include <linux/uio.h>
+
+/**
+ * enum transfer_kind - How to send an fd to Trusty
+ * @TRUSTY_SHARE: Memory will be accessible by Linux and Trusty. On ARM it will
+ * be mapped as nonsecure. Suitable for shared memory. The paired
+ * fd must be a "memfd".
+ * @TRUSTY_LEND: Memory will be accessible only to Trusty. On ARM it will be
+ * transitioned to "Secure" memory if Trusty is in TrustZone.
+ * This transfer kind is suitable for donating video buffers or
+ * other similar resources. The paired fd may need to come from a
+ * platform-specific allocator for memory that may be
+ * transitioned to "Secure".
+ *
+ * Describes how the user would like the resource in question to be sent to
+ * Trusty. Options may be valid only for certain kinds of fds.
+ */
+enum transfer_kind {
+ TRUSTY_SHARE = 0,
+ TRUSTY_LEND = 1,
+};
+
+/**
+ * struct trusty_shm - Describes a transfer of memory to Trusty
+ * @fd: The fd to transfer
+ * @transfer: How to transfer it - see &enum transfer_kind
+ */
+struct trusty_shm {
+ __s32 fd;
+ __u32 transfer;
+};
+
+/**
+ * struct tipc_send_msg_req - Request struct for @TIPC_IOC_SEND_MSG
+ * @iov: Pointer to an array of &struct iovec describing data to be sent
+ * @shm: Pointer to an array of &struct trusty_shm describing any file
+ * descriptors to be transferred.
+ * @iov_cnt: Number of elements in the @iov array
+ * @shm_cnt: Number of elements in the @shm array
+ */
+struct tipc_send_msg_req {
+ __u64 iov;
+ __u64 shm;
+ __u64 iov_cnt;
+ __u64 shm_cnt;
+};
+
+#define TIPC_IOC_MAGIC 'r'
+#define TIPC_IOC_CONNECT _IOW(TIPC_IOC_MAGIC, 0x80, char*)
+#define TIPC_IOC_SEND_MSG _IOW(TIPC_IOC_MAGIC, 0x81, struct tipc_send_msg_req)
+
+#if defined(CONFIG_COMPAT)
+#define TIPC_IOC_CONNECT_COMPAT _IOW(TIPC_IOC_MAGIC, 0x80, compat_uptr_t)
+#endif
+
+#endif
diff --git a/trusty/libtrusty/include/trusty/tipc.h b/trusty/libtrusty/include/trusty/tipc.h
index a3f2a3f..b44afd3 100644
--- a/trusty/libtrusty/include/trusty/tipc.h
+++ b/trusty/libtrusty/include/trusty/tipc.h
@@ -21,7 +21,11 @@
extern "C" {
#endif
+#include <sys/uio.h>
+#include <trusty/ipc.h>
+
int tipc_connect(const char *dev_name, const char *srv_name);
+ssize_t tipc_send(int fd, const struct iovec* iov, int iovcnt, struct trusty_shm* shm, int shmcnt);
int tipc_close(int fd);
#ifdef __cplusplus
diff --git a/trusty/libtrusty/tipc-test/tipc_test.c b/trusty/libtrusty/tipc-test/tipc_test.c
index d20d4ee..ca581dc 100644
--- a/trusty/libtrusty/tipc-test/tipc_test.c
+++ b/trusty/libtrusty/tipc-test/tipc_test.c
@@ -21,6 +21,8 @@
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
+#define __USE_GNU
+#include <sys/mman.h>
#include <sys/uio.h>
#include <trusty/tipc.h>
@@ -39,6 +41,7 @@
static const char *closer2_name = "com.android.ipc-unittest.srv.closer2";
static const char *closer3_name = "com.android.ipc-unittest.srv.closer3";
static const char *main_ctrl_name = "com.android.ipc-unittest.ctrl";
+static const char* receiver_name = "com.android.trusty.memref.receiver";
static const char *_sopts = "hsvD:t:r:m:b:";
static const struct option _lopts[] = {
@@ -66,25 +69,25 @@
"\n"
;
-static const char *usage_long =
-"\n"
-"The following tests are available:\n"
-" connect - connect to datasink service\n"
-" connect_foo - connect to non existing service\n"
-" burst_write - send messages to datasink service\n"
-" echo - send/receive messages to echo service\n"
-" select - test select call\n"
-" blocked_read - test blocked read\n"
-" closer1 - connection closed by remote (test1)\n"
-" closer2 - connection closed by remote (test2)\n"
-" closer3 - connection closed by remote (test3)\n"
-" ta2ta-ipc - execute TA to TA unittest\n"
-" dev-uuid - print device uuid\n"
-" ta-access - test ta-access flags\n"
-" writev - writev test\n"
-" readv - readv test\n"
-"\n"
-;
+static const char* usage_long =
+ "\n"
+ "The following tests are available:\n"
+ " connect - connect to datasink service\n"
+ " connect_foo - connect to non existing service\n"
+ " burst_write - send messages to datasink service\n"
+ " echo - send/receive messages to echo service\n"
+ " select - test select call\n"
+ " blocked_read - test blocked read\n"
+ " closer1 - connection closed by remote (test1)\n"
+ " closer2 - connection closed by remote (test2)\n"
+ " closer3 - connection closed by remote (test3)\n"
+ " ta2ta-ipc - execute TA to TA unittest\n"
+ " dev-uuid - print device uuid\n"
+ " ta-access - test ta-access flags\n"
+ " writev - writev test\n"
+ " readv - readv test\n"
+ " send-fd - transmit memfd to trusty, use as shm\n"
+ "\n";
static uint opt_repeat = 1;
static uint opt_msgsize = 32;
@@ -885,6 +888,66 @@
return 0;
}
+static int send_fd_test(void) {
+ int ret;
+ int memfd = -1;
+ int fd = -1;
+ volatile char* buf = MAP_FAILED;
+
+ fd = tipc_connect(dev_name, receiver_name);
+ if (fd < 0) {
+ fprintf(stderr, "Failed to connect to test support TA - is it missing?\n");
+ ret = -1;
+ goto cleanup;
+ }
+
+ memfd = memfd_create("tipc-send-fd", 0);
+ if (memfd < 0) {
+ fprintf(stderr, "Failed to create memfd: %s\n", strerror(errno));
+ ret = -1;
+ goto cleanup;
+ }
+
+ if (ftruncate(memfd, PAGE_SIZE) < 0) {
+ fprintf(stderr, "Failed to resize memfd: %s\n", strerror(errno));
+ ret = -1;
+ goto cleanup;
+ }
+
+ buf = mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, 0);
+ if (buf == MAP_FAILED) {
+ fprintf(stderr, "Failed to map memfd: %s\n", strerror(errno));
+ ret = -1;
+ goto cleanup;
+ }
+
+ strcpy((char*)buf, "From NS");
+
+ struct trusty_shm shm = {
+ .fd = memfd,
+ .transfer = TRUSTY_SHARE,
+ };
+
+ ssize_t rc = tipc_send(fd, NULL, 0, &shm, 1);
+ if (rc < 0) {
+ fprintf(stderr, "tipc_send failed\n");
+ ret = rc;
+ goto cleanup;
+ }
+ char c;
+ read(fd, &c, 1);
+ tipc_close(fd);
+
+ ret = strcmp("Hello from Trusty!", (const char*)buf) ? (-1) : 0;
+
+cleanup:
+ if (buf != MAP_FAILED) {
+ munmap((char*)buf, PAGE_SIZE);
+ }
+ close(memfd);
+ tipc_close(fd);
+ return ret;
+}
int main(int argc, char **argv)
{
@@ -933,10 +996,12 @@
rc = writev_test(opt_repeat, opt_msgsize, opt_variable);
} else if (strcmp(test_name, "readv") == 0) {
rc = readv_test(opt_repeat, opt_msgsize, opt_variable);
- } else {
- fprintf(stderr, "Unrecognized test name '%s'\n", test_name);
- print_usage_and_exit(argv[0], EXIT_FAILURE, true);
- }
+ } else if (strcmp(test_name, "send-fd") == 0) {
+ rc = send_fd_test();
+ } else {
+ fprintf(stderr, "Unrecognized test name '%s'\n", test_name);
+ print_usage_and_exit(argv[0], EXIT_FAILURE, true);
+ }
- return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+ return rc == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
diff --git a/trusty/libtrusty/trusty.c b/trusty/libtrusty/trusty.c
index a6238af..ad4d8cd 100644
--- a/trusty/libtrusty/trusty.c
+++ b/trusty/libtrusty/trusty.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -27,7 +27,7 @@
#include <log/log.h>
-#include "tipc_ioctl.h"
+#include <trusty/ipc.h>
int tipc_connect(const char *dev_name, const char *srv_name)
{
@@ -55,6 +55,22 @@
return fd;
}
+ssize_t tipc_send(int fd, const struct iovec* iov, int iovcnt, struct trusty_shm* shms,
+ int shmcnt) {
+ struct tipc_send_msg_req req;
+ req.iov = (__u64)iov;
+ req.iov_cnt = (__u64)iovcnt;
+ req.shm = (__u64)shms;
+ req.shm_cnt = (__u64)shmcnt;
+
+ int rc = ioctl(fd, TIPC_IOC_SEND_MSG, &req);
+ if (rc < 0) {
+ ALOGE("%s: failed to send message (err=%d)\n", __func__, rc);
+ }
+
+ return rc;
+}
+
void tipc_close(int fd)
{
close(fd);
diff --git a/trusty/trusty-test.mk b/trusty/trusty-test.mk
new file mode 100644
index 0000000..fd353d1
--- /dev/null
+++ b/trusty/trusty-test.mk
@@ -0,0 +1,16 @@
+# Copyright (C) 2020 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.
+
+PRODUCT_PACKAGES += \
+ spiproxyd \
diff --git a/trusty/utils/spiproxyd/Android.bp b/trusty/utils/spiproxyd/Android.bp
new file mode 100644
index 0000000..c1d0987
--- /dev/null
+++ b/trusty/utils/spiproxyd/Android.bp
@@ -0,0 +1,36 @@
+// Copyright (C) 2020 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.
+
+cc_binary {
+ name: "spiproxyd",
+ vendor: true,
+
+ srcs: [
+ "main.c",
+ ],
+
+ shared_libs: [
+ "liblog",
+ "libtrusty",
+ ],
+
+ init_rc: [
+ "proxy.rc",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+}
diff --git a/trusty/utils/spiproxyd/main.c b/trusty/utils/spiproxyd/main.c
new file mode 100644
index 0000000..c10866b
--- /dev/null
+++ b/trusty/utils/spiproxyd/main.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "spiproxyd"
+
+#include <assert.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <log/log.h>
+#include <stdlib.h>
+#include <string.h>
+#include <trusty/tipc.h>
+#include <unistd.h>
+
+int handle_msg(int trusty_dev_fd, int spi_dev_fd) {
+ int rc;
+ uint8_t msg_buf[4096];
+ size_t msg_len;
+
+ /* read request from SPI Trusty app */
+ rc = read(trusty_dev_fd, &msg_buf, sizeof(msg_buf));
+ if (rc < 0) {
+ ALOGE("failed (%d) to read request from TA\n", rc);
+ return rc;
+ }
+ msg_len = rc;
+
+ /* forward request to SPI host device */
+ rc = write(spi_dev_fd, &msg_buf, msg_len);
+ if (rc < 0 || (size_t)rc != msg_len) {
+ ALOGE("failed (%d) to forward request to host\n", rc);
+ return rc < 0 ? rc : -1;
+ }
+
+ /* read response from SPI host device */
+ rc = read(spi_dev_fd, &msg_buf, sizeof(msg_buf));
+ if (rc < 0) {
+ ALOGE("failed (%d) to read response from host\n", rc);
+ return rc;
+ }
+ msg_len = rc;
+
+ /* forward response to SPI Trusty app */
+ rc = write(trusty_dev_fd, &msg_buf, msg_len);
+ if (rc < 0 || (size_t)rc != msg_len) {
+ ALOGE("failed (%d) to forward response to TA\n", rc);
+ return rc < 0 ? rc : -1;
+ }
+
+ return 0;
+}
+
+int event_loop(int trusty_dev_fd, int spi_dev_fd) {
+ while (true) {
+ int rc = handle_msg(trusty_dev_fd, spi_dev_fd);
+ if (rc < 0) {
+ ALOGE("exiting event loop\n");
+ return EXIT_FAILURE;
+ }
+ }
+}
+
+static void show_usage() {
+ ALOGE("usage: spiproxyd -t TRUSTY_DEVICE -s SPI_DEVICE -p SPI_PROXY_PORT\n");
+}
+
+static void parse_args(int argc, char* argv[], const char** trusty_dev_name,
+ const char** spi_dev_name, const char** spi_proxy_port) {
+ int opt;
+ while ((opt = getopt(argc, argv, "ht:s:p:")) != -1) {
+ switch (opt) {
+ case 'h':
+ show_usage();
+ exit(EXIT_SUCCESS);
+ break;
+ case 't':
+ *trusty_dev_name = strdup(optarg);
+ break;
+ case 's':
+ *spi_dev_name = strdup(optarg);
+ break;
+ case 'p':
+ *spi_proxy_port = strdup(optarg);
+ break;
+ default:
+ show_usage();
+ exit(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ if (!*trusty_dev_name || !*spi_dev_name || !*spi_proxy_port) {
+ show_usage();
+ exit(EXIT_FAILURE);
+ }
+}
+
+int main(int argc, char* argv[]) {
+ int rc;
+ const char* trusty_dev_name = NULL;
+ const char* spi_dev_name = NULL;
+ const char* spi_proxy_port = NULL;
+ int trusty_dev_fd;
+ int spi_dev_fd;
+
+ parse_args(argc, argv, &trusty_dev_name, &spi_dev_name, &spi_proxy_port);
+
+ rc = tipc_connect(trusty_dev_name, spi_proxy_port);
+ if (rc < 0) {
+ ALOGE("failed (%d) to connect to SPI proxy port\n", rc);
+ return rc;
+ }
+ trusty_dev_fd = rc;
+
+ rc = open(spi_dev_name, O_RDWR, 0);
+ if (rc < 0) {
+ ALOGE("failed (%d) to open SPI device\n", rc);
+ return rc;
+ }
+ spi_dev_fd = rc;
+
+ return event_loop(trusty_dev_fd, spi_dev_fd);
+}
diff --git a/trusty/utils/spiproxyd/proxy.rc b/trusty/utils/spiproxyd/proxy.rc
new file mode 100644
index 0000000..7d63e6a
--- /dev/null
+++ b/trusty/utils/spiproxyd/proxy.rc
@@ -0,0 +1,20 @@
+# Copyright (C) 2020 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.
+
+service spiproxyd /vendor/bin/spiproxyd -t /dev/trusty-ipc-dev0 \
+ -s /dev/vport3p2 -p com.android.trusty.spi.proxy
+ class main
+ user system
+ group system
+ oneshot