Merge "logd: always report the UID of a log message"
diff --git a/fs_mgr/libsnapshot/test_helpers.cpp b/fs_mgr/libsnapshot/test_helpers.cpp
index 1a6a593..539c5c5 100644
--- a/fs_mgr/libsnapshot/test_helpers.cpp
+++ b/fs_mgr/libsnapshot/test_helpers.cpp
@@ -92,21 +92,14 @@
}
std::optional<std::string> GetHash(const std::string& path) {
- unique_fd fd(open(path.c_str(), O_RDONLY));
- char buf[4096];
+ std::string content;
+ if (!android::base::ReadFileToString(path, &content, true)) {
+ PLOG(ERROR) << "Cannot access " << path;
+ return std::nullopt;
+ }
SHA256_CTX ctx;
SHA256_Init(&ctx);
- while (true) {
- ssize_t n = TEMP_FAILURE_RETRY(read(fd.get(), buf, sizeof(buf)));
- if (n < 0) {
- PLOG(ERROR) << "Cannot read " << path;
- return std::nullopt;
- }
- if (n == 0) {
- break;
- }
- SHA256_Update(&ctx, buf, n);
- }
+ SHA256_Update(&ctx, content.c_str(), content.size());
uint8_t out[32];
SHA256_Final(out, &ctx);
return ToHexString(out, sizeof(out));
diff --git a/libcutils/sched_policy_test.cpp b/libcutils/sched_policy_test.cpp
index a321c90..b9e2832 100644
--- a/libcutils/sched_policy_test.cpp
+++ b/libcutils/sched_policy_test.cpp
@@ -107,6 +107,18 @@
TEST(SchedPolicy, get_sched_policy_name) {
EXPECT_STREQ("bg", get_sched_policy_name(SP_BACKGROUND));
- EXPECT_STREQ("error", get_sched_policy_name(SchedPolicy(-2)));
- EXPECT_STREQ("error", get_sched_policy_name(SP_CNT));
+ EXPECT_EQ(nullptr, get_sched_policy_name(SchedPolicy(-2)));
+ EXPECT_EQ(nullptr, get_sched_policy_name(SP_CNT));
+}
+
+TEST(SchedPolicy, get_cpuset_policy_profile_name) {
+ EXPECT_STREQ("CPUSET_SP_BACKGROUND", get_cpuset_policy_profile_name(SP_BACKGROUND));
+ EXPECT_EQ(nullptr, get_cpuset_policy_profile_name(SchedPolicy(-2)));
+ EXPECT_EQ(nullptr, get_cpuset_policy_profile_name(SP_CNT));
+}
+
+TEST(SchedPolicy, get_sched_policy_profile_name) {
+ EXPECT_STREQ("SCHED_SP_BACKGROUND", get_sched_policy_profile_name(SP_BACKGROUND));
+ EXPECT_EQ(nullptr, get_sched_policy_profile_name(SchedPolicy(-2)));
+ EXPECT_EQ(nullptr, get_sched_policy_profile_name(SP_CNT));
}
diff --git a/liblog/include/log/event_tag_map.h b/liblog/include/log/event_tag_map.h
index 2687b3a..f7ec208 100644
--- a/liblog/include/log/event_tag_map.h
+++ b/liblog/include/log/event_tag_map.h
@@ -16,6 +16,8 @@
#pragma once
+#include <stddef.h>
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/liblog/include/log/log.h b/liblog/include/log/log.h
index 5928649..90d1e76 100644
--- a/liblog/include/log/log.h
+++ b/liblog/include/log/log.h
@@ -22,7 +22,6 @@
#endif
#include <stdint.h> /* uint16_t, int32_t */
#include <stdio.h>
-#include <sys/types.h>
#include <time.h>
#include <unistd.h>
@@ -65,21 +64,6 @@
#endif
#endif
-/* --------------------------------------------------------------------- */
-
-/*
- * This file uses ", ## __VA_ARGS__" zero-argument token pasting to
- * work around issues with debug-only syntax errors in assertions
- * that are missing format strings. See commit
- * 19299904343daf191267564fe32e6cd5c165cd42
- */
-#if defined(__clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
-#endif
-
-/* --------------------------------------------------------------------- */
-
/*
* Event logging.
*/
@@ -164,10 +148,6 @@
*/
void __android_log_close(void);
-#if defined(__clang__)
-#pragma clang diagnostic pop
-#endif
-
#ifdef __cplusplus
}
#endif
diff --git a/liblog/include/log/log_event_list.h b/liblog/include/log/log_event_list.h
index 636d417..deadf20 100644
--- a/liblog/include/log/log_event_list.h
+++ b/liblog/include/log/log_event_list.h
@@ -36,16 +36,11 @@
/*
* The opaque context used to manipulate lists of events.
*/
-#ifndef __android_log_context_defined
-#define __android_log_context_defined
typedef struct android_log_context_internal* android_log_context;
-#endif
/*
* Elements returned when reading a list of events.
*/
-#ifndef __android_log_list_element_defined
-#define __android_log_list_element_defined
typedef struct {
AndroidEventLogType type;
uint16_t complete;
@@ -57,7 +52,6 @@
float float32;
} data;
} android_log_list_element;
-#endif
/*
* Creates a context associated with an event tag to write elements to
@@ -104,8 +98,6 @@
int android_log_destroy(android_log_context* ctx);
#ifdef __cplusplus
-#ifndef __class_android_log_event_list_defined
-#define __class_android_log_event_list_defined
/* android_log_list C++ helpers */
extern "C++" {
class android_log_event_list {
@@ -280,7 +272,6 @@
};
}
#endif
-#endif
#ifdef __cplusplus
}
diff --git a/liblog/include/log/log_read.h b/liblog/include/log/log_read.h
index fdef306..2079e7a 100644
--- a/liblog/include/log/log_read.h
+++ b/liblog/include/log/log_read.h
@@ -53,8 +53,6 @@
/*
* The userspace structure for version 1 of the logger_entry ABI.
*/
-#ifndef __struct_logger_entry_defined
-#define __struct_logger_entry_defined
struct logger_entry {
uint16_t len; /* length of the payload */
uint16_t __pad; /* no matter what, we get 2 bytes of padding */
@@ -64,13 +62,10 @@
int32_t nsec; /* nanoseconds */
char msg[0]; /* the entry's payload */
};
-#endif
/*
* The userspace structure for version 2 of the logger_entry ABI.
*/
-#ifndef __struct_logger_entry_v2_defined
-#define __struct_logger_entry_v2_defined
struct logger_entry_v2 {
uint16_t len; /* length of the payload */
uint16_t hdr_size; /* sizeof(struct logger_entry_v2) */
@@ -81,13 +76,10 @@
uint32_t euid; /* effective UID of logger */
char msg[0]; /* the entry's payload */
} __attribute__((__packed__));
-#endif
/*
* The userspace structure for version 3 of the logger_entry ABI.
*/
-#ifndef __struct_logger_entry_v3_defined
-#define __struct_logger_entry_v3_defined
struct logger_entry_v3 {
uint16_t len; /* length of the payload */
uint16_t hdr_size; /* sizeof(struct logger_entry_v3) */
@@ -98,13 +90,10 @@
uint32_t lid; /* log id of the payload */
char msg[0]; /* the entry's payload */
} __attribute__((__packed__));
-#endif
/*
* The userspace structure for version 4 of the logger_entry ABI.
*/
-#ifndef __struct_logger_entry_v4_defined
-#define __struct_logger_entry_v4_defined
struct logger_entry_v4 {
uint16_t len; /* length of the payload */
uint16_t hdr_size; /* sizeof(struct logger_entry_v4) */
@@ -116,7 +105,6 @@
uint32_t uid; /* generating process's uid */
char msg[0]; /* the entry's payload */
};
-#endif
#pragma clang diagnostic pop
/*
@@ -133,8 +121,6 @@
*/
#define LOGGER_ENTRY_MAX_LEN (5 * 1024)
-#ifndef __struct_log_msg_defined
-#define __struct_log_msg_defined
struct log_msg {
union {
unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1];
@@ -191,7 +177,6 @@
}
#endif
};
-#endif
struct logger;
diff --git a/liblog/include/log/log_time.h b/liblog/include/log/log_time.h
index 1b33331..6b4458c 100644
--- a/liblog/include/log/log_time.h
+++ b/liblog/include/log/log_time.h
@@ -24,9 +24,6 @@
#define US_PER_SEC 1000000ULL
#define MS_PER_SEC 1000ULL
-#ifndef __struct_log_time_defined
-#define __struct_log_time_defined
-
#define LOG_TIME_SEC(t) ((t)->tv_sec)
/* next power of two after NS_PER_SEC */
#define LOG_TIME_NSEC(t) ((t)->tv_nsec & (UINT32_MAX >> 2))
@@ -164,5 +161,3 @@
} __attribute__((__packed__)) log_time;
#endif /* __cplusplus */
-
-#endif /* __struct_log_time_defined */
diff --git a/liblog/include/log/logprint.h b/liblog/include/log/logprint.h
index 8f4b187..7dfd914 100644
--- a/liblog/include/log/logprint.h
+++ b/liblog/include/log/logprint.h
@@ -16,7 +16,8 @@
#pragma once
-#include <pthread.h>
+#include <stdint.h>
+#include <sys/types.h>
#include <android/log.h>
#include <log/event_tag_map.h>
diff --git a/liblog/pmsg_reader.cpp b/liblog/pmsg_reader.cpp
index 9c5bc95..ce923f3 100644
--- a/liblog/pmsg_reader.cpp
+++ b/liblog/pmsg_reader.cpp
@@ -62,58 +62,9 @@
return -EBADF;
}
-/* Determine the credentials of the caller */
-static bool uid_has_log_permission(uid_t uid) {
- return (uid == AID_SYSTEM) || (uid == AID_LOG) || (uid == AID_ROOT) || (uid == AID_LOGD);
-}
-
-static uid_t get_best_effective_uid() {
- uid_t euid;
- uid_t uid;
- gid_t gid;
- ssize_t i;
- static uid_t last_uid = (uid_t)-1;
-
- if (last_uid != (uid_t)-1) {
- return last_uid;
- }
- uid = __android_log_uid();
- if (uid_has_log_permission(uid)) {
- return last_uid = uid;
- }
- euid = geteuid();
- if (uid_has_log_permission(euid)) {
- return last_uid = euid;
- }
- gid = getgid();
- if (uid_has_log_permission(gid)) {
- return last_uid = gid;
- }
- gid = getegid();
- if (uid_has_log_permission(gid)) {
- return last_uid = gid;
- }
- i = getgroups((size_t)0, NULL);
- if (i > 0) {
- gid_t list[i];
-
- getgroups(i, list);
- while (--i >= 0) {
- if (uid_has_log_permission(list[i])) {
- return last_uid = list[i];
- }
- }
- }
- return last_uid = uid;
-}
-
static int pmsgClear(struct android_log_logger* logger __unused,
struct android_log_transport_context* transp __unused) {
- if (uid_has_log_permission(get_best_effective_uid())) {
- return unlink("/sys/fs/pstore/pmsg-ramoops-0");
- }
- errno = EPERM;
- return -1;
+ return unlink("/sys/fs/pstore/pmsg-ramoops-0");
}
/*
@@ -128,14 +79,12 @@
struct android_log_transport_context* transp, struct log_msg* log_msg) {
ssize_t ret;
off_t current, next;
- uid_t uid;
struct __attribute__((__packed__)) {
android_pmsg_log_header_t p;
android_log_header_t l;
uint8_t prio;
} buf;
static uint8_t preread_count;
- bool is_system;
memset(log_msg, 0, sizeof(*log_msg));
@@ -195,37 +144,30 @@
((logger_list->start.tv_sec != buf.l.realtime.tv_sec) ||
(logger_list->start.tv_nsec <= buf.l.realtime.tv_nsec)))) &&
(!logger_list->pid || (logger_list->pid == buf.p.pid))) {
- uid = get_best_effective_uid();
- is_system = uid_has_log_permission(uid);
- if (is_system || (uid == buf.p.uid)) {
- char* msg = is_system ? log_msg->entry_v4.msg : log_msg->entry_v3.msg;
- *msg = buf.prio;
- fd = atomic_load(&transp->context.fd);
- if (fd <= 0) {
- return -EBADF;
- }
- ret = TEMP_FAILURE_RETRY(read(fd, msg + sizeof(buf.prio), buf.p.len - sizeof(buf)));
- if (ret < 0) {
- return -errno;
- }
- if (ret != (ssize_t)(buf.p.len - sizeof(buf))) {
- return -EIO;
- }
-
- log_msg->entry_v4.len = buf.p.len - sizeof(buf) + sizeof(buf.prio);
- log_msg->entry_v4.hdr_size =
- is_system ? sizeof(log_msg->entry_v4) : sizeof(log_msg->entry_v3);
- log_msg->entry_v4.pid = buf.p.pid;
- log_msg->entry_v4.tid = buf.l.tid;
- log_msg->entry_v4.sec = buf.l.realtime.tv_sec;
- log_msg->entry_v4.nsec = buf.l.realtime.tv_nsec;
- log_msg->entry_v4.lid = buf.l.id;
- if (is_system) {
- log_msg->entry_v4.uid = buf.p.uid;
- }
-
- return ret + sizeof(buf.prio) + log_msg->entry_v4.hdr_size;
+ char* msg = log_msg->entry_v4.msg;
+ *msg = buf.prio;
+ fd = atomic_load(&transp->context.fd);
+ if (fd <= 0) {
+ return -EBADF;
}
+ ret = TEMP_FAILURE_RETRY(read(fd, msg + sizeof(buf.prio), buf.p.len - sizeof(buf)));
+ if (ret < 0) {
+ return -errno;
+ }
+ if (ret != (ssize_t)(buf.p.len - sizeof(buf))) {
+ return -EIO;
+ }
+
+ log_msg->entry_v4.len = buf.p.len - sizeof(buf) + sizeof(buf.prio);
+ log_msg->entry_v4.hdr_size = sizeof(log_msg->entry_v4);
+ log_msg->entry_v4.pid = buf.p.pid;
+ log_msg->entry_v4.tid = buf.l.tid;
+ log_msg->entry_v4.sec = buf.l.realtime.tv_sec;
+ log_msg->entry_v4.nsec = buf.l.realtime.tv_nsec;
+ log_msg->entry_v4.lid = buf.l.id;
+ log_msg->entry_v4.uid = buf.p.uid;
+
+ return ret + sizeof(buf.prio) + log_msg->entry_v4.hdr_size;
}
fd = atomic_load(&transp->context.fd);
@@ -273,13 +215,7 @@
struct android_log_transport_context transp;
struct content {
struct listnode node;
- union {
- struct logger_entry_v4 entry;
- struct logger_entry_v4 entry_v4;
- struct logger_entry_v3 entry_v3;
- struct logger_entry_v2 entry_v2;
- struct logger_entry entry_v1;
- };
+ struct logger_entry_v4 entry;
} * content;
struct names {
struct listnode node;
diff --git a/liblog/tests/liblog_benchmark.cpp b/liblog/tests/liblog_benchmark.cpp
index 4642b9b..56892a2 100644
--- a/liblog/tests/liblog_benchmark.cpp
+++ b/liblog/tests/liblog_benchmark.cpp
@@ -17,6 +17,7 @@
#include <fcntl.h>
#include <inttypes.h>
#include <poll.h>
+#include <sched.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/types.h>
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 063c132..94c4fbb 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -62,6 +62,12 @@
_rc; \
})
+// std::unique_ptr doesn't let you provide a pointer to a deleter (android_logger_list_close()) if
+// the type (struct logger_list) is an incomplete type, so we create ListCloser instead.
+struct ListCloser {
+ void operator()(struct logger_list* list) { android_logger_list_close(list); }
+};
+
// This function is meant to be used for most log tests, it does the following:
// 1) Open the log_buffer with a blocking reader
// 2) Write the messages via write_messages
@@ -75,11 +81,6 @@
static void RunLogTests(log_id_t log_buffer, FWrite write_messages, FCheck check_message) {
pid_t pid = getpid();
- // std::unique_ptr doesn't let you provide a pointer to a deleter (android_logger_list_close()) if
- // the type (struct logger_list) is an incomplete type, so we create ListCloser instead.
- struct ListCloser {
- void operator()(struct logger_list* list) { android_logger_list_close(list); }
- };
auto logger_list = std::unique_ptr<struct logger_list, ListCloser>{
android_logger_list_open(log_buffer, ANDROID_LOG_RDONLY, 1000, pid)};
ASSERT_TRUE(logger_list);
@@ -946,7 +947,6 @@
when you depart from me, sorrow abides and happiness\n\
takes his leave.";
-#ifdef ENABLE_FLAKY_TESTS
TEST(liblog, max_payload) {
#ifdef __ANDROID__
static const char max_payload_tag[] = "TEST_max_payload_and_longish_tag_XXXX";
@@ -995,7 +995,6 @@
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-#endif // ENABLE_FLAKY_TESTS
TEST(liblog, __android_log_buf_print__maxtag) {
#ifdef __ANDROID__
@@ -1089,11 +1088,20 @@
#endif
}
-#ifdef ENABLE_FLAKY_TESTS
TEST(liblog, dual_reader) {
#ifdef __ANDROID__
+ static const int expected_count1 = 25;
+ static const int expected_count2 = 25;
- static const int num = 25;
+ pid_t pid = getpid();
+
+ auto logger_list1 = std::unique_ptr<struct logger_list, ListCloser>{
+ android_logger_list_open(LOG_ID_MAIN, ANDROID_LOG_RDONLY, expected_count1, pid)};
+ ASSERT_TRUE(logger_list1);
+
+ auto logger_list2 = std::unique_ptr<struct logger_list, ListCloser>{
+ android_logger_list_open(LOG_ID_MAIN, ANDROID_LOG_RDONLY, expected_count2, pid)};
+ ASSERT_TRUE(logger_list2);
for (int i = 25; i > 0; --i) {
static const char fmt[] = "dual_reader %02d";
@@ -1102,32 +1110,46 @@
LOG_FAILURE_RETRY(__android_log_buf_write(LOG_ID_MAIN, ANDROID_LOG_INFO,
"liblog", buffer));
}
- usleep(1000000);
- struct logger_list* logger_list1;
- ASSERT_TRUE(NULL != (logger_list1 = android_logger_list_open(
- LOG_ID_MAIN,
- ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, num, 0)));
+ alarm(2);
+ auto alarm_guard = android::base::make_scope_guard([] { alarm(0); });
- struct logger_list* logger_list2;
+ // Wait until we see all messages with the blocking reader.
+ int count1 = 0;
+ int count2 = 0;
- if (NULL == (logger_list2 = android_logger_list_open(
- LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
- num - 10, 0))) {
- android_logger_list_close(logger_list1);
- ASSERT_TRUE(NULL != logger_list2);
+ while (count1 != expected_count2 || count2 != expected_count2) {
+ log_msg log_msg;
+ if (count1 < expected_count1) {
+ ASSERT_GT(android_logger_list_read(logger_list1.get(), &log_msg), 0);
+ count1++;
+ }
+ if (count2 < expected_count2) {
+ ASSERT_GT(android_logger_list_read(logger_list2.get(), &log_msg), 0);
+ count2++;
+ }
}
- int count1 = 0;
+ // Test again with the nonblocking reader.
+ auto logger_list_non_block1 =
+ std::unique_ptr<struct logger_list, ListCloser>{android_logger_list_open(
+ LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, expected_count1, pid)};
+ ASSERT_TRUE(logger_list_non_block1);
+
+ auto logger_list_non_block2 =
+ std::unique_ptr<struct logger_list, ListCloser>{android_logger_list_open(
+ LOG_ID_MAIN, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, expected_count2, pid)};
+ ASSERT_TRUE(logger_list_non_block2);
+ count1 = 0;
+ count2 = 0;
bool done1 = false;
- int count2 = 0;
bool done2 = false;
- do {
+ while (!done1 || !done2) {
log_msg log_msg;
if (!done1) {
- if (android_logger_list_read(logger_list1, &log_msg) <= 0) {
+ if (android_logger_list_read(logger_list_non_block1.get(), &log_msg) <= 0) {
done1 = true;
} else {
++count1;
@@ -1135,26 +1157,21 @@
}
if (!done2) {
- if (android_logger_list_read(logger_list2, &log_msg) <= 0) {
+ if (android_logger_list_read(logger_list_non_block2.get(), &log_msg) <= 0) {
done2 = true;
} else {
++count2;
}
}
- } while ((!done1) || (!done2));
+ }
- android_logger_list_close(logger_list1);
- android_logger_list_close(logger_list2);
-
- EXPECT_EQ(num, count1);
- EXPECT_EQ(num - 10, count2);
+ EXPECT_EQ(expected_count1, count1);
+ EXPECT_EQ(expected_count2, count2);
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-#endif // ENABLE_FLAKY_TESTS
-#ifdef ENABLE_FLAKY_TESTS
static bool checkPriForTag(AndroidLogFormat* p_format, const char* tag,
android_LogPriority pri) {
return android_log_shouldPrintLine(p_format, tag, pri) &&
@@ -1230,7 +1247,6 @@
android_log_format_free(p_format);
}
-#endif // ENABLE_FLAKY_TESTS
#ifdef ENABLE_FLAKY_TESTS
TEST(liblog, is_loggable) {
@@ -2609,7 +2625,6 @@
#endif
}
-#ifdef ENABLE_FLAKY_TESTS
TEST(liblog, create_android_logger_overflow) {
android_log_context ctx;
@@ -2636,7 +2651,6 @@
EXPECT_LE(0, android_log_destroy(&ctx));
ASSERT_TRUE(NULL == ctx);
}
-#endif // ENABLE_FLAKY_TESTS
#ifdef ENABLE_FLAKY_TESTS
#ifdef __ANDROID__
@@ -2777,7 +2791,6 @@
}
#endif // ENABLE_FLAKY_TESTS
-#ifdef ENABLE_FLAKY_TESTS
TEST(liblog, android_lookupEventTagNum) {
#ifdef __ANDROID__
EventTagMap* map = android_openEventTagMap(NULL);
@@ -2794,4 +2807,3 @@
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-#endif // ENABLE_FLAKY_TESTS
diff --git a/libprocessgroup/include/processgroup/sched_policy.h b/libprocessgroup/include/processgroup/sched_policy.h
index 3c498da..945d90c 100644
--- a/libprocessgroup/include/processgroup/sched_policy.h
+++ b/libprocessgroup/include/processgroup/sched_policy.h
@@ -70,11 +70,22 @@
extern int get_sched_policy(int tid, SchedPolicy* policy);
/* Return a displayable string corresponding to policy.
- * Return value: non-NULL NUL-terminated name of unspecified length;
+ * Return value: NUL-terminated name of unspecified length, nullptr if invalid;
* the caller is responsible for displaying the useful part of the string.
*/
extern const char* get_sched_policy_name(SchedPolicy policy);
+/* Return the aggregated task profile name corresponding to cpuset policy.
+ * Return value: NUL-terminated name of unspecified length, nullptr if invalid;
+ * the caller could use it to call SetTaskProfiles.
+ */
+extern const char* get_cpuset_policy_profile_name(SchedPolicy policy);
+
+/* Return the aggregated task profile name corresponding to sched policy.
+ * Return value: NUL-terminated name of unspecified length, nullptr if invalid;
+ * the caller could use it to call SetTaskProfiles.
+ */
+extern const char* get_sched_policy_profile_name(SchedPolicy policy);
#ifdef __cplusplus
}
#endif
diff --git a/libprocessgroup/sched_policy.cpp b/libprocessgroup/sched_policy.cpp
index 6b0ab87..16339d3 100644
--- a/libprocessgroup/sched_policy.cpp
+++ b/libprocessgroup/sched_policy.cpp
@@ -212,7 +212,45 @@
};
static_assert(arraysize(kSchedPolicyNames) == SP_CNT, "missing name");
if (policy < SP_BACKGROUND || policy >= SP_CNT) {
- return "error";
+ return nullptr;
}
return kSchedPolicyNames[policy];
}
+
+const char* get_cpuset_policy_profile_name(SchedPolicy policy) {
+ /*
+ * cpuset profile array for:
+ * SP_DEFAULT(-1), SP_BACKGROUND(0), SP_FOREGROUND(1),
+ * SP_SYSTEM(2), SP_AUDIO_APP(3), SP_AUDIO_SYS(4),
+ * SP_TOP_APP(5), SP_RT_APP(6), SP_RESTRICTED(7)
+ * index is policy + 1
+ * this need keep in sync with SchedPolicy enum
+ */
+ static constexpr const char* kCpusetProfiles[SP_CNT + 1] = {
+ "CPUSET_SP_DEFAULT", "CPUSET_SP_BACKGROUND", "CPUSET_SP_FOREGROUND",
+ "CPUSET_SP_SYSTEM", "CPUSET_SP_FOREGROUND", "CPUSET_SP_FOREGROUND",
+ "CPUSET_SP_TOP_APP", "CPUSET_SP_DEFAULT", "CPUSET_SP_RESTRICTED"};
+ if (policy < SP_DEFAULT || policy >= SP_CNT) {
+ return nullptr;
+ }
+ return kCpusetProfiles[policy + 1];
+}
+
+const char* get_sched_policy_profile_name(SchedPolicy policy) {
+ /*
+ * sched profile array for:
+ * SP_DEFAULT(-1), SP_BACKGROUND(0), SP_FOREGROUND(1),
+ * SP_SYSTEM(2), SP_AUDIO_APP(3), SP_AUDIO_SYS(4),
+ * SP_TOP_APP(5), SP_RT_APP(6), SP_RESTRICTED(7)
+ * index is policy + 1
+ * this need keep in sync with SchedPolicy enum
+ */
+ static constexpr const char* kSchedProfiles[SP_CNT + 1] = {
+ "SCHED_SP_DEFAULT", "SCHED_SP_BACKGROUND", "SCHED_SP_FOREGROUND",
+ "SCHED_SP_DEFAULT", "SCHED_SP_FOREGROUND", "SCHED_SP_FOREGROUND",
+ "SCHED_SP_TOP_APP", "SCHED_SP_RT_APP", "SCHED_SP_DEFAULT"};
+ if (policy < SP_DEFAULT || policy >= SP_CNT) {
+ return nullptr;
+ }
+ return kSchedProfiles[policy + 1];
+}
diff --git a/libunwindstack/AndroidVersions.md b/libunwindstack/AndroidVersions.md
new file mode 100644
index 0000000..234f639
--- /dev/null
+++ b/libunwindstack/AndroidVersions.md
@@ -0,0 +1,116 @@
+# Unwinder Support Per Android Release
+This document describes the changes in the way the libunwindstack
+unwinder works on different Android versions. It does not describe
+every change in the code made between different versions, but is
+meant to allow an app developer to know what might be supported
+on different versions. It also describes the different way an unwind
+will display on different versions of Android.
+
+## Android P
+libunwindstack was first introduced in Android P.
+
+* Supports up to and including Dwarf 4 unwinding information.
+ See http://dwarfstd.org/ for Dwarf standards.
+* Supports Arm exidx unwinding.
+* Supports the gdb JIT unwinding interface, which is how ART creates unwinding
+ information for the JIT'd Java frames.
+* Supports special frames added to represent an ART Java interpreter frame.
+ ART has marked the dex pc using cfi information that the unwinder
+ understands and handles by adding a new frame in the stacktrace.
+
+## Note
+By default, lld creates two separate maps of the elf in memory, one read-only
+and one read/executable. The libunwindstack on P and the unwinder on older
+versions of Android will not unwind properly in this case. For apps that
+target Android P or older, make sure that `-Wl,--no-rosegment` is
+included in linker arguments when using lld.
+
+## Android Q
+* Fix bug (b/109824792) that handled load bias data incorrectly when
+ FDEs use pc relative addressing in the eh\_frame\_hdr.
+ Unfortunately, this wasn't fixed correctly in Q since it assumes
+ that the bias is coming from the program header for the executable
+ load. The real fix was to use the bias from the actual section data and
+ is not completely fixed until Android R. For apps targeting Android Q,
+ if it is being compiled with the llvm linker lld, it might be necessary
+ to add the linker option `-Wl,-zseparate-code` to avoid creating an elf
+ created this way.
+* Change the way the exidx section offset is found (b/110704153). Before
+ the p\_vaddr value from the program header minus the load bias was used
+ to find the start of the exidx data. Changed to use the p\_offset since
+ it doesn't require any load bias manipulations.
+* Fix bug handling of dwarf sections without any header (b/110235461).
+ Previously, the code assumed that FDEs are non-overlapping, and the FDEs
+ are always in sorted order from low pc to high pc. Thus the code would
+ read the entire set of CIEs/FDEs and then do a binary search to find
+ the appropriate FDE for a given pc. Now the code does a sequential read
+ and stops when it finds the FDE for a pc. It also understands the
+ overlapping FDEs, so find the first FDE that matches a pc. In practice,
+ elf files with this format only ever occurs if the file was generated
+ without an eh\_frame/eh\_frame\_hdr section and only a debug\_frame. The
+ other way this has been observed is when running simpleperf to unwind since
+ sometimes there is not enough information in the eh\_frame for all points
+ in the executable. On Android P, this would result in some incorrect
+ unwinds coming from simpleperf. Nearly all crashes from Android P should
+ be correct since the eh\_frame information was enough to do the unwind
+ properly.
+* Be permissive of badly formed elf files. Previously, any detected error
+ would result in unwinds stopping even if there is enough valid information
+ to do an unwind.
+ * The code now allows program header/section header offsets to point
+ to unreadable memory. As long as the code can find the unwind tables,
+ that is good enough.
+ * The code allows program headers/section headers to be missing.
+ * Allow a symbol table section header to point to invalid symbol table
+ values.
+* Support for the linker read-only segment option (b/109657296).
+ This is a feature of lld whereby there are two sections that
+ contain elf data. The first is read-only and contains the elf header data,
+ and the second is read-execute or execute only that
+ contains the executable code from the elf. Before this, the unwinder
+ always assumed that there was only a single read-execute section that
+ contained the elf header data and the executable code.
+* Build ID information for elf objects added. This will display the
+ NT\_GNU\_BUILD\_ID note found in elf files. This information can be used
+ to identify the exact version of a shared library to help get symbol
+ information when looking at a crash.
+* Add support for displaying the soname from an apk frame. Previously,
+ a frame map name would be only the apk, but now if the shared library
+ in the apk has set a soname, the map name will be `app.apk!libexample.so`
+ instead of only `app.apk`.
+* Minimal support for Dwarf 5. This merely treats a Dwarf 5 version
+ elf file as Dwarf 4. It does not support the new dwarf ops in Dwarf 5.
+ Since the new ops are not likely to be used very often, this allows
+ continuing to unwind even when encountering Dwarf 5 elf files.
+* Fix bug in pc handling of signal frames (b/130302288). In the previous
+ version, the pc would be wrong in the signal frame. The rest of the
+ unwind was correct, only the frame in the signal handler was incorrect
+ in Android P.
+* Detect when an elf file is not readable so that a message can be
+ displayed indicating that. This can happen when an app puts the shared
+ libraries in non-standard locations that are not readable due to
+ security restrictions (selinux rules).
+
+## Android R
+* Display the offsets for Java interpreter frames. If this frame came
+ from a non-zero offset map, no offset is printed. Previously, the
+ line would look like:
+
+ #17 pc 00500d7a GoogleCamera.apk (com.google.camera.AndroidPriorityThread.run+10)
+
+ to:
+
+ #17 pc 00500d7a GoogleCamera.apk (offset 0x11d0000) (com.google.camera.AndroidPriorityThread.run+10)
+* Fix bug where the load bias was set from the first PT\_LOAD program
+ header that has a zero p\_offset value. Now it is set from the first
+ executable PT\_LOAD program header. This has only ever been a problem
+ for host executables compiled for the x86\_64 architecture.
+* Switched to the libc++ demangler for function names. Previously, the
+ demangler used was not complete, so some less common demangled function
+ names would not be properly demangled or the function name would not be
+ demangled at all.
+* Fix bug in load bias handling. If the unwind information in the eh\_frame
+ or eh\_frame\_hdr does not have the same bias as the executable section,
+ and uses pc relative FDEs, the unwind will be incorrect. This tends
+ to truncate unwinds since the unwinder could not find the correct unwind
+ information for a given pc.