Merge "init: load /product selinux mapping file"
diff --git a/adb/client/adb_client.cpp b/adb/client/adb_client.cpp
index eda4b77..9a25d10 100644
--- a/adb/client/adb_client.cpp
+++ b/adb/client/adb_client.cpp
@@ -144,53 +144,51 @@
}
std::string reason;
- int fd = socket_spec_connect(__adb_server_socket_spec, &reason);
- if (fd < 0) {
+ unique_fd fd;
+ if (!socket_spec_connect(&fd, __adb_server_socket_spec, nullptr, nullptr, &reason)) {
*error = android::base::StringPrintf("cannot connect to daemon at %s: %s",
__adb_server_socket_spec, reason.c_str());
return -2;
}
- if (memcmp(&service[0], "host", 4) != 0 && switch_socket_transport(fd, error)) {
+ if (memcmp(&service[0], "host", 4) != 0 && switch_socket_transport(fd.get(), error)) {
return -1;
}
- if (!SendProtocolString(fd, service)) {
+ if (!SendProtocolString(fd.get(), service)) {
*error = perror_str("write failure during connection");
- adb_close(fd);
return -1;
}
- if (!adb_status(fd, error)) {
- adb_close(fd);
+ if (!adb_status(fd.get(), error)) {
return -1;
}
- D("_adb_connect: return fd %d", fd);
- return fd;
+ D("_adb_connect: return fd %d", fd.get());
+ return fd.release();
}
bool adb_kill_server() {
D("adb_kill_server");
std::string reason;
- int fd = socket_spec_connect(__adb_server_socket_spec, &reason);
- if (fd < 0) {
+ unique_fd fd;
+ if (!socket_spec_connect(&fd, __adb_server_socket_spec, nullptr, nullptr, &reason)) {
fprintf(stderr, "cannot connect to daemon at %s: %s\n", __adb_server_socket_spec,
reason.c_str());
return true;
}
- if (!SendProtocolString(fd, "host:kill")) {
+ if (!SendProtocolString(fd.get(), "host:kill")) {
fprintf(stderr, "error: write failure during connection: %s\n", strerror(errno));
return false;
}
// The server might send OKAY, so consume that.
char buf[4];
- ReadFdExactly(fd, buf, 4);
+ ReadFdExactly(fd.get(), buf, 4);
// Now that no more data is expected, wait for socket orderly shutdown or error, indicating
// server death.
- ReadOrderlyShutdown(fd);
+ ReadOrderlyShutdown(fd.get());
return true;
}
diff --git a/adb/client/adb_install.cpp b/adb/client/adb_install.cpp
index bd5508c..21e0874 100644
--- a/adb/client/adb_install.cpp
+++ b/adb/client/adb_install.cpp
@@ -24,12 +24,14 @@
#include <string>
#include <vector>
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+
#include "adb.h"
#include "adb_client.h"
+#include "adb_unique_fd.h"
#include "adb_utils.h"
-#include "android-base/file.h"
-#include "android-base/stringprintf.h"
-#include "android-base/strings.h"
#include "client/file_sync_client.h"
#include "commandline.h"
#include "fastdeploy.h"
@@ -179,8 +181,8 @@
return 1;
}
- int localFd = adb_open(file, O_RDONLY);
- if (localFd < 0) {
+ unique_fd local_fd(adb_open(file, O_RDONLY | O_CLOEXEC));
+ if (local_fd < 0) {
fprintf(stderr, "adb: failed to open %s: %s\n", file, strerror(errno));
return 1;
}
@@ -201,19 +203,15 @@
cmd += " --apex";
}
- int remoteFd = adb_connect(cmd, &error);
- if (remoteFd < 0) {
+ unique_fd remote_fd(adb_connect(cmd, &error));
+ if (remote_fd < 0) {
fprintf(stderr, "adb: connect error for write: %s\n", error.c_str());
- adb_close(localFd);
return 1;
}
char buf[BUFSIZ];
- copy_to_file(localFd, remoteFd);
- read_status_line(remoteFd, buf, sizeof(buf));
-
- adb_close(localFd);
- adb_close(remoteFd);
+ copy_to_file(local_fd.get(), remote_fd.get());
+ read_status_line(remote_fd.get(), buf, sizeof(buf));
if (!strncmp("Success", buf, 7)) {
fputs(buf, stdout);
@@ -410,14 +408,15 @@
// Create install session
std::string error;
- int fd = adb_connect(cmd, &error);
- if (fd < 0) {
- fprintf(stderr, "adb: connect error for create: %s\n", error.c_str());
- return EXIT_FAILURE;
- }
char buf[BUFSIZ];
- read_status_line(fd, buf, sizeof(buf));
- adb_close(fd);
+ {
+ unique_fd fd(adb_connect(cmd, &error));
+ if (fd < 0) {
+ fprintf(stderr, "adb: connect error for create: %s\n", error.c_str());
+ return EXIT_FAILURE;
+ }
+ read_status_line(fd.get(), buf, sizeof(buf));
+ }
int session_id = -1;
if (!strncmp("Success", buf, 7)) {
@@ -450,27 +449,23 @@
install_cmd.c_str(), static_cast<uint64_t>(sb.st_size),
session_id, android::base::Basename(file).c_str());
- int localFd = adb_open(file, O_RDONLY);
- if (localFd < 0) {
+ unique_fd local_fd(adb_open(file, O_RDONLY | O_CLOEXEC));
+ if (local_fd < 0) {
fprintf(stderr, "adb: failed to open %s: %s\n", file, strerror(errno));
success = 0;
goto finalize_session;
}
std::string error;
- int remoteFd = adb_connect(cmd, &error);
- if (remoteFd < 0) {
+ unique_fd remote_fd(adb_connect(cmd, &error));
+ if (remote_fd < 0) {
fprintf(stderr, "adb: connect error for write: %s\n", error.c_str());
- adb_close(localFd);
success = 0;
goto finalize_session;
}
- copy_to_file(localFd, remoteFd);
- read_status_line(remoteFd, buf, sizeof(buf));
-
- adb_close(localFd);
- adb_close(remoteFd);
+ copy_to_file(local_fd.get(), remote_fd.get());
+ read_status_line(remote_fd.get(), buf, sizeof(buf));
if (strncmp("Success", buf, 7)) {
fprintf(stderr, "adb: failed to write %s\n", file);
@@ -484,13 +479,14 @@
// Commit session if we streamed everything okay; otherwise abandon
std::string service = android::base::StringPrintf("%s install-%s %d", install_cmd.c_str(),
success ? "commit" : "abandon", session_id);
- fd = adb_connect(service, &error);
- if (fd < 0) {
- fprintf(stderr, "adb: connect error for finalize: %s\n", error.c_str());
- return EXIT_FAILURE;
+ {
+ unique_fd fd(adb_connect(service, &error));
+ if (fd < 0) {
+ fprintf(stderr, "adb: connect error for finalize: %s\n", error.c_str());
+ return EXIT_FAILURE;
+ }
+ read_status_line(fd.get(), buf, sizeof(buf));
}
- read_status_line(fd, buf, sizeof(buf));
- adb_close(fd);
if (!strncmp("Success", buf, 7)) {
fputs(buf, stdout);
@@ -504,17 +500,22 @@
int install_multi_package(int argc, const char** argv) {
// Find all APK arguments starting at end.
// All other arguments passed through verbatim.
- int first_apk = -1;
+ bool apex_found = false;
+ int first_package = -1;
for (int i = argc - 1; i >= 0; i--) {
const char* file = argv[i];
- if (android::base::EndsWithIgnoreCase(file, ".apk")) {
- first_apk = i;
+ if (android::base::EndsWithIgnoreCase(file, ".apk") ||
+ android::base::EndsWithIgnoreCase(file, ".apex")) {
+ first_package = i;
+ if (android::base::EndsWithIgnoreCase(file, ".apex")) {
+ apex_found = true;
+ }
} else {
break;
}
}
- if (first_apk == -1) error_exit("need APK file on command line");
+ if (first_package == -1) error_exit("need APK or APEX files on command line");
if (use_legacy_install()) {
fprintf(stderr, "adb: multi-package install is not supported on this device\n");
@@ -524,17 +525,21 @@
std::string multi_package_cmd =
android::base::StringPrintf("%s install-create --multi-package", install_cmd.c_str());
+ if (apex_found) {
+ multi_package_cmd += " --staged";
+ }
// Create multi-package install session
std::string error;
- int fd = adb_connect(multi_package_cmd, &error);
- if (fd < 0) {
- fprintf(stderr, "adb: connect error for create multi-package: %s\n", error.c_str());
- return EXIT_FAILURE;
- }
char buf[BUFSIZ];
- read_status_line(fd, buf, sizeof(buf));
- adb_close(fd);
+ {
+ unique_fd fd(adb_connect(multi_package_cmd, &error));
+ if (fd < 0) {
+ fprintf(stderr, "adb: connect error for create multi-package: %s\n", error.c_str());
+ return EXIT_FAILURE;
+ }
+ read_status_line(fd.get(), buf, sizeof(buf));
+ }
int parent_session_id = -1;
if (!strncmp("Success", buf, 7)) {
@@ -560,20 +565,31 @@
std::string individual_cmd =
android::base::StringPrintf("%s install-create", install_cmd.c_str());
std::string all_session_ids = "";
- for (int i = 1; i < first_apk; i++) {
+ for (int i = 1; i < first_package; i++) {
individual_cmd += " " + escape_arg(argv[i]);
}
+ if (apex_found) {
+ individual_cmd += " --staged";
+ }
+ std::string individual_apex_cmd = individual_cmd + " --apex";
std::string cmd = "";
- for (int i = first_apk; i < argc; i++) {
- // Create individual install session
- fd = adb_connect(individual_cmd, &error);
- if (fd < 0) {
- fprintf(stderr, "adb: connect error for create: %s\n", error.c_str());
- goto finalize_multi_package_session;
- }
+ for (int i = first_package; i < argc; i++) {
+ const char* file = argv[i];
char buf[BUFSIZ];
- read_status_line(fd, buf, sizeof(buf));
- adb_close(fd);
+ {
+ unique_fd fd;
+ // Create individual install session
+ if (android::base::EndsWithIgnoreCase(file, ".apex")) {
+ fd.reset(adb_connect(individual_apex_cmd, &error));
+ } else {
+ fd.reset(adb_connect(individual_cmd, &error));
+ }
+ if (fd < 0) {
+ fprintf(stderr, "adb: connect error for create: %s\n", error.c_str());
+ goto finalize_multi_package_session;
+ }
+ read_status_line(fd.get(), buf, sizeof(buf));
+ }
int session_id = -1;
if (!strncmp("Success", buf, 7)) {
@@ -593,7 +609,6 @@
fprintf(stdout, "Created child session ID %d.\n", session_id);
session_ids.push_back(session_id);
- const char* file = argv[i];
struct stat sb;
if (stat(file, &sb) == -1) {
fprintf(stderr, "adb: failed to stat %s: %s\n", file, strerror(errno));
@@ -605,25 +620,21 @@
install_cmd.c_str(), static_cast<uint64_t>(sb.st_size),
session_id, i, android::base::Basename(file).c_str());
- int localFd = adb_open(file, O_RDONLY);
- if (localFd < 0) {
+ unique_fd local_fd(adb_open(file, O_RDONLY | O_CLOEXEC));
+ if (local_fd < 0) {
fprintf(stderr, "adb: failed to open %s: %s\n", file, strerror(errno));
goto finalize_multi_package_session;
}
std::string error;
- int remoteFd = adb_connect(cmd, &error);
- if (remoteFd < 0) {
+ unique_fd remote_fd(adb_connect(cmd, &error));
+ if (remote_fd < 0) {
fprintf(stderr, "adb: connect error for write: %s\n", error.c_str());
- adb_close(localFd);
goto finalize_multi_package_session;
}
- copy_to_file(localFd, remoteFd);
- read_status_line(remoteFd, buf, sizeof(buf));
-
- adb_close(localFd);
- adb_close(remoteFd);
+ copy_to_file(local_fd.get(), remote_fd.get());
+ read_status_line(remote_fd.get(), buf, sizeof(buf));
if (strncmp("Success", buf, 7)) {
fprintf(stderr, "adb: failed to write %s\n", file);
@@ -636,13 +647,14 @@
cmd = android::base::StringPrintf("%s install-add-session %d%s", install_cmd.c_str(),
parent_session_id, all_session_ids.c_str());
- fd = adb_connect(cmd, &error);
- if (fd < 0) {
- fprintf(stderr, "adb: connect error for create: %s\n", error.c_str());
- goto finalize_multi_package_session;
+ {
+ unique_fd fd(adb_connect(cmd, &error));
+ if (fd < 0) {
+ fprintf(stderr, "adb: connect error for install-add-session: %s\n", error.c_str());
+ goto finalize_multi_package_session;
+ }
+ read_status_line(fd.get(), buf, sizeof(buf));
}
- read_status_line(fd, buf, sizeof(buf));
- adb_close(fd);
if (strncmp("Success", buf, 7)) {
fprintf(stderr, "adb: failed to link sessions (%s)\n", cmd.c_str());
@@ -658,13 +670,14 @@
std::string service =
android::base::StringPrintf("%s install-%s %d", install_cmd.c_str(),
success == 0 ? "commit" : "abandon", parent_session_id);
- fd = adb_connect(service, &error);
- if (fd < 0) {
- fprintf(stderr, "adb: connect error for finalize: %s\n", error.c_str());
- return EXIT_FAILURE;
+ {
+ unique_fd fd(adb_connect(service, &error));
+ if (fd < 0) {
+ fprintf(stderr, "adb: connect error for finalize: %s\n", error.c_str());
+ return EXIT_FAILURE;
+ }
+ read_status_line(fd.get(), buf, sizeof(buf));
}
- read_status_line(fd, buf, sizeof(buf));
- adb_close(fd);
if (!strncmp("Success", buf, 7)) {
fputs(buf, stdout);
@@ -681,13 +694,12 @@
service = android::base::StringPrintf("%s install-abandon %d", install_cmd.c_str(),
session_ids[i]);
fprintf(stderr, "Attempting to abandon session ID %d\n", session_ids[i]);
- fd = adb_connect(service, &error);
+ unique_fd fd(adb_connect(service, &error));
if (fd < 0) {
fprintf(stderr, "adb: connect error for finalize: %s\n", error.c_str());
continue;
}
- read_status_line(fd, buf, sizeof(buf));
- adb_close(fd);
+ read_status_line(fd.get(), buf, sizeof(buf));
}
return EXIT_FAILURE;
}
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 9bc42e1..e963e3d 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -762,6 +762,17 @@
}
static int adb_abb(int argc, const char** argv) {
+ FeatureSet features;
+ std::string error_message;
+ if (!adb_get_feature_set(&features, &error_message)) {
+ fprintf(stderr, "error: %s\n", error_message.c_str());
+ return 1;
+ }
+
+ if (!CanUseFeature(features, kFeatureAbb)) {
+ error_exit("abb is not supported by the device");
+ }
+
// Defaults.
constexpr char escape_char = '~'; // -e
constexpr bool use_shell_protocol = true;
diff --git a/adb/fastdeploy/Android.bp b/adb/fastdeploy/Android.bp
index 400b12f..1ba0de0 100644
--- a/adb/fastdeploy/Android.bp
+++ b/adb/fastdeploy/Android.bp
@@ -22,6 +22,9 @@
wrapper: "deployagent/deployagent.sh",
proto: {
type: "lite",
+ },
+ dex_preopt: {
+ enabled: false,
}
}
diff --git a/adb/services.cpp b/adb/services.cpp
index 8636657..73fed09 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -72,24 +72,23 @@
}
int service_to_fd(std::string_view name, atransport* transport) {
- int ret = -1;
+ unique_fd ret;
if (is_socket_spec(name)) {
std::string error;
- ret = socket_spec_connect(name, &error);
- if (ret < 0) {
+ if (!socket_spec_connect(&ret, name, nullptr, nullptr, &error)) {
LOG(ERROR) << "failed to connect to socket '" << name << "': " << error;
}
} else {
#if !ADB_HOST
- ret = daemon_service_to_fd(name, transport).release();
+ ret = daemon_service_to_fd(name, transport);
#endif
}
if (ret >= 0) {
close_on_exec(ret);
}
- return ret;
+ return ret.release();
}
#if ADB_HOST
diff --git a/adb/socket_spec.cpp b/adb/socket_spec.cpp
index 4cddc84..cc67b6b 100644
--- a/adb/socket_spec.cpp
+++ b/adb/socket_spec.cpp
@@ -67,7 +67,7 @@
});
bool parse_tcp_socket_spec(std::string_view spec, std::string* hostname, int* port,
- std::string* error) {
+ std::string* serial, std::string* error) {
if (!spec.starts_with("tcp:")) {
*error = "specification is not tcp: ";
*error += spec;
@@ -92,7 +92,7 @@
// FIXME: ParseNetAddress rejects port 0. This currently doesn't hurt, because listening
// on an address that isn't 'localhost' is unsupported.
- if (!android::base::ParseNetAddress(addr, &hostname_value, &port_value, nullptr, error)) {
+ if (!android::base::ParseNetAddress(addr, &hostname_value, &port_value, serial, error)) {
return false;
}
@@ -139,63 +139,68 @@
std::string error;
std::string hostname;
- if (!parse_tcp_socket_spec(spec, &hostname, nullptr, &error)) {
+ if (!parse_tcp_socket_spec(spec, &hostname, nullptr, nullptr, &error)) {
return false;
}
return tcp_host_is_local(hostname);
}
-int socket_spec_connect(std::string_view spec, std::string* error) {
- if (spec.starts_with("tcp:")) {
+bool socket_spec_connect(unique_fd* fd, std::string_view address, int* port, std::string* serial,
+ std::string* error) {
+ if (address.starts_with("tcp:")) {
std::string hostname;
- int port;
- if (!parse_tcp_socket_spec(spec, &hostname, &port, error)) {
- return -1;
+ int port_value = port ? *port : 0;
+ if (!parse_tcp_socket_spec(address, &hostname, &port_value, serial, error)) {
+ return false;
}
- int result;
if (tcp_host_is_local(hostname)) {
- result = network_loopback_client(port, SOCK_STREAM, error);
+ fd->reset(network_loopback_client(port_value, SOCK_STREAM, error));
} else {
#if ADB_HOST
- result = network_connect(hostname, port, SOCK_STREAM, 0, error);
+ fd->reset(network_connect(hostname, port_value, SOCK_STREAM, 0, error));
#else
// Disallow arbitrary connections in adbd.
*error = "adbd does not support arbitrary tcp connections";
- return -1;
+ return false;
#endif
}
- if (result >= 0) {
- disable_tcp_nagle(result);
+ if (fd->get() > 0) {
+ disable_tcp_nagle(fd->get());
+ if (port) {
+ *port = port_value;
+ }
+ return true;
}
- return result;
+ return false;
}
for (const auto& it : kLocalSocketTypes) {
std::string prefix = it.first + ":";
- if (spec.starts_with(prefix)) {
+ if (address.starts_with(prefix)) {
if (!it.second.available) {
*error = StringPrintf("socket type %s is unavailable on this platform",
it.first.c_str());
- return -1;
+ return false;
}
- return network_local_client(&spec[prefix.length()], it.second.socket_namespace,
- SOCK_STREAM, error);
+ fd->reset(network_local_client(&address[prefix.length()], it.second.socket_namespace,
+ SOCK_STREAM, error));
+ return true;
}
}
*error = "unknown socket specification: ";
- *error += spec;
- return -1;
+ *error += address;
+ return false;
}
int socket_spec_listen(std::string_view spec, std::string* error, int* resolved_tcp_port) {
if (spec.starts_with("tcp:")) {
std::string hostname;
int port;
- if (!parse_tcp_socket_spec(spec, &hostname, &port, error)) {
+ if (!parse_tcp_socket_spec(spec, &hostname, &port, nullptr, error)) {
return -1;
}
diff --git a/adb/socket_spec.h b/adb/socket_spec.h
index 5b06973..687d751 100644
--- a/adb/socket_spec.h
+++ b/adb/socket_spec.h
@@ -17,14 +17,18 @@
#pragma once
#include <string>
+#include <tuple>
+
+#include "adb_unique_fd.h"
// Returns true if the argument starts with a plausible socket prefix.
bool is_socket_spec(std::string_view spec);
bool is_local_socket_spec(std::string_view spec);
-int socket_spec_connect(std::string_view spec, std::string* error);
+bool socket_spec_connect(unique_fd* fd, std::string_view address, int* port, std::string* serial,
+ std::string* error);
int socket_spec_listen(std::string_view spec, std::string* error, int* resolved_tcp_port = nullptr);
// Exposed for testing.
bool parse_tcp_socket_spec(std::string_view spec, std::string* hostname, int* port,
- std::string* error);
+ std::string* serial, std::string* error);
diff --git a/adb/socket_spec_test.cpp b/adb/socket_spec_test.cpp
index 40ce21c..f5ec0f1 100644
--- a/adb/socket_spec_test.cpp
+++ b/adb/socket_spec_test.cpp
@@ -21,34 +21,37 @@
#include <gtest/gtest.h>
TEST(socket_spec, parse_tcp_socket_spec) {
- std::string hostname, error;
+ std::string hostname, error, serial;
int port;
- EXPECT_TRUE(parse_tcp_socket_spec("tcp:5037", &hostname, &port, &error));
+ EXPECT_TRUE(parse_tcp_socket_spec("tcp:5037", &hostname, &port, &serial, &error));
EXPECT_EQ("", hostname);
EXPECT_EQ(5037, port);
+ EXPECT_EQ("", serial);
// Bad ports:
- EXPECT_FALSE(parse_tcp_socket_spec("tcp:", &hostname, &port, &error));
- EXPECT_FALSE(parse_tcp_socket_spec("tcp:-1", &hostname, &port, &error));
- EXPECT_FALSE(parse_tcp_socket_spec("tcp:65536", &hostname, &port, &error));
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:", &hostname, &port, &serial, &error));
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:-1", &hostname, &port, &serial, &error));
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:65536", &hostname, &port, &serial, &error));
- EXPECT_TRUE(parse_tcp_socket_spec("tcp:localhost:1234", &hostname, &port, &error));
+ EXPECT_TRUE(parse_tcp_socket_spec("tcp:localhost:1234", &hostname, &port, &serial, &error));
EXPECT_EQ("localhost", hostname);
EXPECT_EQ(1234, port);
+ EXPECT_EQ("localhost:1234", serial);
- EXPECT_FALSE(parse_tcp_socket_spec("tcp:localhost", &hostname, &port, &error));
- EXPECT_FALSE(parse_tcp_socket_spec("tcp:localhost:", &hostname, &port, &error));
- EXPECT_FALSE(parse_tcp_socket_spec("tcp:localhost:-1", &hostname, &port, &error));
- EXPECT_FALSE(parse_tcp_socket_spec("tcp:localhost:65536", &hostname, &port, &error));
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:localhost", &hostname, &port, &serial, &error));
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:localhost:", &hostname, &port, &serial, &error));
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:localhost:-1", &hostname, &port, &serial, &error));
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:localhost:65536", &hostname, &port, &serial, &error));
// IPv6:
- EXPECT_TRUE(parse_tcp_socket_spec("tcp:[::1]:1234", &hostname, &port, &error));
+ EXPECT_TRUE(parse_tcp_socket_spec("tcp:[::1]:1234", &hostname, &port, &serial, &error));
EXPECT_EQ("::1", hostname);
EXPECT_EQ(1234, port);
+ EXPECT_EQ("[::1]:1234", serial);
- EXPECT_FALSE(parse_tcp_socket_spec("tcp:[::1]", &hostname, &port, &error));
- EXPECT_FALSE(parse_tcp_socket_spec("tcp:[::1]:", &hostname, &port, &error));
- EXPECT_FALSE(parse_tcp_socket_spec("tcp:[::1]:-1", &hostname, &port, &error));
- EXPECT_FALSE(parse_tcp_socket_spec("tcp:::1", &hostname, &port, &error));
- EXPECT_FALSE(parse_tcp_socket_spec("tcp:::1:1234", &hostname, &port, &error));
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:[::1]", &hostname, &port, &serial, &error));
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:[::1]:", &hostname, &port, &serial, &error));
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:[::1]:-1", &hostname, &port, &serial, &error));
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:::1", &hostname, &port, &serial, &error));
+ EXPECT_FALSE(parse_tcp_socket_spec("tcp:::1:1234", &hostname, &port, &serial, &error));
}
diff --git a/adb/transport.cpp b/adb/transport.cpp
index f59a135..ae53597 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -68,6 +68,7 @@
const char* const kFeaturePushSync = "push_sync";
const char* const kFeatureApex = "apex";
const char* const kFeatureFixedPushMkdir = "fixed_push_mkdir";
+const char* const kFeatureAbb = "abb";
namespace {
@@ -1013,7 +1014,8 @@
const FeatureSet& supported_features() {
// Local static allocation to avoid global non-POD variables.
static const FeatureSet* features = new FeatureSet{
- kFeatureShell2, kFeatureCmd, kFeatureStat2, kFeatureFixedPushMkdir, kFeatureApex
+ kFeatureShell2, kFeatureCmd, kFeatureStat2,
+ kFeatureFixedPushMkdir, kFeatureApex, kFeatureAbb,
// Increment ADB_SERVER_VERSION when adding a feature that adbd needs
// to know about. Otherwise, the client can be stuck running an old
// version of the server even after upgrading their copy of adb.
diff --git a/adb/transport.h b/adb/transport.h
index 790004f..6f53e6ec 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -64,6 +64,8 @@
extern const char* const kFeatureApex;
// adbd has b/110953234 fixed.
extern const char* const kFeatureFixedPushMkdir;
+// adbd supports android binder bridge (abb).
+extern const char* const kFeatureAbb;
TransportId NextTransportId();
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index dc87ac7..b384085 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -45,6 +45,7 @@
#include "adb_io.h"
#include "adb_unique_fd.h"
#include "adb_utils.h"
+#include "socket_spec.h"
#include "sysdeps/chrono.h"
#if ADB_HOST
@@ -70,32 +71,17 @@
std::tuple<unique_fd, int, std::string> tcp_connect(const std::string& address,
std::string* response) {
- std::string serial;
- std::string host;
+ unique_fd fd;
int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
- if (!android::base::ParseNetAddress(address, &host, &port, &serial, response)) {
- D("failed to parse address: '%s'", address.c_str());
- return std::make_tuple(unique_fd(), port, serial);
- }
-
- std::string error;
- unique_fd fd(network_connect(host.c_str(), port, SOCK_STREAM, 10, &error));
- if (fd == -1) {
- *response = android::base::StringPrintf("unable to connect to %s: %s",
- serial.c_str(), error.c_str());
+ std::string serial;
+ if (socket_spec_connect(&fd, "tcp:" + address, &port, &serial, response)) {
+ close_on_exec(fd);
+ if (!set_tcp_keepalive(fd, 1)) {
+ D("warning: failed to configure TCP keepalives (%s)", strerror(errno));
+ }
return std::make_tuple(std::move(fd), port, serial);
}
-
- D("client: connected %s remote on fd %d", serial.c_str(), fd.get());
- close_on_exec(fd);
- disable_tcp_nagle(fd);
-
- // Send a TCP keepalive ping to the device every second so we can detect disconnects.
- if (!set_tcp_keepalive(fd, 1)) {
- D("warning: failed to configure TCP keepalives (%s)", strerror(errno));
- }
-
- return std::make_tuple(std::move(fd), port, serial);
+ return std::make_tuple(unique_fd(), 0, "");
}
void connect_device(const std::string& address, std::string* response) {
@@ -251,8 +237,9 @@
adb_thread_setname("server socket");
D("transport: server_socket_thread() starting");
while (serverfd == -1) {
+ std::string spec = android::base::StringPrintf("tcp:%d", port);
std::string error;
- serverfd.reset(network_inaddr_any_server(port, SOCK_STREAM, &error));
+ serverfd.reset(socket_spec_listen(spec, &error));
if (serverfd < 0) {
D("server: cannot bind socket yet: %s", error.c_str());
std::this_thread::sleep_for(1s);
diff --git a/base/include/android-base/unique_fd.h b/base/include/android-base/unique_fd.h
index c8d12cf..2c890b4 100644
--- a/base/include/android-base/unique_fd.h
+++ b/base/include/android-base/unique_fd.h
@@ -161,22 +161,35 @@
// Inline functions, so that they can be used header-only.
template <typename Closer>
-inline bool Pipe(unique_fd_impl<Closer>* read, unique_fd_impl<Closer>* write) {
+inline bool Pipe(unique_fd_impl<Closer>* read, unique_fd_impl<Closer>* write,
+ int flags = O_CLOEXEC) {
int pipefd[2];
#if defined(__linux__)
- if (pipe2(pipefd, O_CLOEXEC) != 0) {
+ if (pipe2(pipefd, flags) != 0) {
return false;
}
#else // defined(__APPLE__)
+ if (flags & ~(O_CLOEXEC | O_NONBLOCK)) {
+ return false;
+ }
if (pipe(pipefd) != 0) {
return false;
}
- if (fcntl(pipefd[0], F_SETFD, FD_CLOEXEC) != 0 || fcntl(pipefd[1], F_SETFD, FD_CLOEXEC) != 0) {
- close(pipefd[0]);
- close(pipefd[1]);
- return false;
+ if (flags & O_CLOEXEC) {
+ if (fcntl(pipefd[0], F_SETFD, FD_CLOEXEC) != 0 || fcntl(pipefd[1], F_SETFD, FD_CLOEXEC) != 0) {
+ close(pipefd[0]);
+ close(pipefd[1]);
+ return false;
+ }
+ }
+ if (flags & O_NONBLOCK) {
+ if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) != 0 || fcntl(pipefd[1], F_SETFL, O_NONBLOCK) != 0) {
+ close(pipefd[0]);
+ close(pipefd[1]);
+ return false;
+ }
}
#endif
diff --git a/fastboot/Android.bp b/fastboot/Android.bp
index ead2105..716fe95 100644
--- a/fastboot/Android.bp
+++ b/fastboot/Android.bp
@@ -132,6 +132,7 @@
"libext2_uuid",
"libext4_utils",
"libfs_mgr",
+ "libgsi",
"libhidlbase",
"libhidltransport",
"libhwbinder",
diff --git a/fastboot/constants.h b/fastboot/constants.h
index 81f0560..8a72627 100644
--- a/fastboot/constants.h
+++ b/fastboot/constants.h
@@ -33,6 +33,7 @@
#define FB_CMD_RESIZE_PARTITION "resize-logical-partition"
#define FB_CMD_UPDATE_SUPER "update-super"
#define FB_CMD_OEM "oem"
+#define FB_CMD_GSI "gsi"
#define RESPONSE_OKAY "OKAY"
#define RESPONSE_FAIL "FAIL"
diff --git a/fastboot/device/commands.cpp b/fastboot/device/commands.cpp
index e91598d..a2336bf 100644
--- a/fastboot/device/commands.cpp
+++ b/fastboot/device/commands.cpp
@@ -28,6 +28,7 @@
#include <cutils/android_reboot.h>
#include <ext4_utils/wipe.h>
#include <fs_mgr.h>
+#include <libgsi/libgsi.h>
#include <liblp/builder.h>
#include <liblp/liblp.h>
#include <uuid/uuid.h>
@@ -460,3 +461,22 @@
bool wipe = (args.size() >= 3 && args[2] == "wipe");
return UpdateSuper(device, args[1], wipe);
}
+
+bool GsiHandler(FastbootDevice* device, const std::vector<std::string>& args) {
+ if (!android::gsi::IsGsiInstalled()) {
+ return device->WriteStatus(FastbootResult::FAIL, "No GSI is installed");
+ }
+ if (args.size() != 2) {
+ return device->WriteFail("Invalid arguments");
+ }
+ if (args[1] == "wipe") {
+ if (!android::gsi::UninstallGsi()) {
+ return device->WriteStatus(FastbootResult::FAIL, strerror(errno));
+ }
+ } else if (args[1] == "disable") {
+ if (!android::gsi::DisableGsi()) {
+ return device->WriteStatus(FastbootResult::FAIL, strerror(errno));
+ }
+ }
+ return device->WriteStatus(FastbootResult::OKAY, "Success");
+}
diff --git a/fastboot/device/commands.h b/fastboot/device/commands.h
index bb1f988..afd6d08 100644
--- a/fastboot/device/commands.h
+++ b/fastboot/device/commands.h
@@ -48,3 +48,4 @@
bool ResizePartitionHandler(FastbootDevice* device, const std::vector<std::string>& args);
bool UpdateSuperHandler(FastbootDevice* device, const std::vector<std::string>& args);
bool OemCmdHandler(FastbootDevice* device, const std::vector<std::string>& args);
+bool GsiHandler(FastbootDevice* device, const std::vector<std::string>& args);
diff --git a/fastboot/device/fastboot_device.cpp b/fastboot/device/fastboot_device.cpp
index 7be721a..56fafab 100644
--- a/fastboot/device/fastboot_device.cpp
+++ b/fastboot/device/fastboot_device.cpp
@@ -53,6 +53,7 @@
{FB_CMD_RESIZE_PARTITION, ResizePartitionHandler},
{FB_CMD_UPDATE_SUPER, UpdateSuperHandler},
{FB_CMD_OEM, OemCmdHandler},
+ {FB_CMD_GSI, GsiHandler},
}),
transport_(std::make_unique<ClientUsbTransport>()),
boot_control_hal_(IBootControl::getService()),
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 0b8d9b2..d753f0f 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -387,6 +387,7 @@
" Format a flash partition.\n"
" set_active SLOT Set the active slot.\n"
" oem [COMMAND...] Execute OEM-specific command.\n"
+ " gsi wipe|disable Wipe or disable a GSI installation (fastbootd only).\n"
"\n"
"boot image:\n"
" boot KERNEL [RAMDISK [SECOND]]\n"
@@ -1926,6 +1927,16 @@
std::string partition = next_arg(&args);
std::string size = next_arg(&args);
fb->ResizePartition(partition, size);
+ } else if (command == "gsi") {
+ if (args.empty()) {
+ syntax_error("missing 'wipe' or 'disable' argument");
+ } else if (args.size() == 1 && args[0] == "wipe") {
+ fb->RawCommand("gsi:wipe", "wiping GSI");
+ } else if (args.size() == 1 && args[0] == "disable") {
+ fb->RawCommand("gsi:disable", "disabling GSI");
+ } else {
+ syntax_error("expected 'wipe' or 'disable'");
+ }
} else {
syntax_error("unknown command %s", command.c_str());
}
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index d9f2837..974e13e 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -59,6 +59,7 @@
"libfs_avb",
"libfstab",
"libdm",
+ "libgsi",
],
export_static_lib_headers: [
"libfs_avb",
@@ -105,5 +106,8 @@
},
},
export_include_dirs: ["include_fstab"],
- header_libs: ["libbase_headers"],
+ header_libs: [
+ "libbase_headers",
+ "libgsi_headers",
+ ],
}
diff --git a/fs_mgr/OWNERS b/fs_mgr/OWNERS
index 817a0b8..cbbd3bc 100644
--- a/fs_mgr/OWNERS
+++ b/fs_mgr/OWNERS
@@ -1,2 +1,3 @@
bowgotsai@google.com
+dvander@google.com
tomcherry@google.com
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 785f9a2..ded3678 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -79,6 +79,9 @@
#define ZRAM_CONF_DEV "/sys/block/zram0/disksize"
#define ZRAM_CONF_MCS "/sys/block/zram0/max_comp_streams"
+#define ZRAM_BACK_DEV "/sys/block/zram0/backing_dev"
+
+#define SYSFS_EXT4_VERITY "/sys/fs/ext4/features/verity"
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
@@ -109,6 +112,7 @@
FS_STAT_TOGGLE_QUOTAS_FAILED = 0x10000,
FS_STAT_SET_RESERVED_BLOCKS_FAILED = 0x20000,
FS_STAT_ENABLE_ENCRYPTION_FAILED = 0x40000,
+ FS_STAT_ENABLE_VERITY_FAILED = 0x80000,
};
// TODO: switch to inotify()
@@ -439,6 +443,43 @@
}
}
+// Enable fs-verity if needed.
+static void tune_verity(const std::string& blk_device, const FstabEntry& entry,
+ const struct ext4_super_block* sb, int* fs_stat) {
+ bool has_verity = (sb->s_feature_ro_compat & cpu_to_le32(EXT4_FEATURE_RO_COMPAT_VERITY)) != 0;
+ bool want_verity = entry.fs_mgr_flags.fs_verity;
+
+ if (has_verity || !want_verity) {
+ return;
+ }
+
+ std::string verity_support;
+ if (!android::base::ReadFileToString(SYSFS_EXT4_VERITY, &verity_support)) {
+ LERROR << "Failed to open " << SYSFS_EXT4_VERITY;
+ return;
+ }
+
+ if (!(android::base::Trim(verity_support) == "supported")) {
+ LERROR << "Current ext4 verity not supported by kernel";
+ return;
+ }
+
+ if (!tune2fs_available()) {
+ LERROR << "Unable to enable ext4 verity on " << blk_device
+ << " because " TUNE2FS_BIN " is missing";
+ return;
+ }
+
+ LINFO << "Enabling ext4 verity on " << blk_device;
+
+ const char* argv[] = {TUNE2FS_BIN, "-O", "verity", blk_device.c_str()};
+ if (!run_tune2fs(argv, ARRAY_SIZE(argv))) {
+ LERROR << "Failed to run " TUNE2FS_BIN " to enable "
+ << "ext4 verity on " << blk_device;
+ *fs_stat |= FS_STAT_ENABLE_VERITY_FAILED;
+ }
+}
+
// Read the primary superblock from an f2fs filesystem. On failure return
// false. If it's not an f2fs filesystem, also set FS_STAT_INVALID_MAGIC.
#define F2FS_BLKSIZE 4096
@@ -510,12 +551,14 @@
}
if (is_extfs(entry.fs_type) &&
- (entry.fs_mgr_flags.reserved_size || entry.fs_mgr_flags.file_encryption)) {
+ (entry.fs_mgr_flags.reserved_size || entry.fs_mgr_flags.file_encryption ||
+ entry.fs_mgr_flags.fs_verity)) {
struct ext4_super_block sb;
if (read_ext4_superblock(blk_device, &sb, &fs_stat)) {
tune_reserved_size(blk_device, entry, &sb, &fs_stat);
tune_encrypt(blk_device, entry, &sb, &fs_stat);
+ tune_verity(blk_device, entry, &sb, &fs_stat);
}
}
@@ -556,9 +599,17 @@
mkdir(target.c_str(), 0755);
errno = 0;
unsigned long mountflags = entry.flags;
- int ret = mount(source.c_str(), target.c_str(), entry.fs_type.c_str(), mountflags,
+ int ret = 0;
+ int save_errno = 0;
+ do {
+ if (save_errno == EAGAIN) {
+ PINFO << "Retrying mount (source=" << source << ",target=" << target
+ << ",type=" << entry.fs_type << ")=" << ret << "(" << save_errno << ")";
+ }
+ ret = mount(source.c_str(), target.c_str(), entry.fs_type.c_str(), mountflags,
entry.fs_options.c_str());
- int save_errno = errno;
+ save_errno = errno;
+ } while (ret && save_errno == EAGAIN);
const char* target_missing = "";
const char* source_missing = "";
if (save_errno == ENOENT) {
@@ -1365,6 +1416,70 @@
return 0;
}
+static bool InstallZramDevice(const std::string& device) {
+ if (!android::base::WriteStringToFile(device, ZRAM_BACK_DEV)) {
+ PERROR << "Cannot write " << device << " in: " << ZRAM_BACK_DEV;
+ return false;
+ }
+ LINFO << "Success to set " << device << " to " << ZRAM_BACK_DEV;
+ return true;
+}
+
+static bool PrepareZramDevice(const std::string& loop, off64_t size, const std::string& bdev) {
+ if (loop.empty() && bdev.empty()) return true;
+
+ if (bdev.length()) {
+ return InstallZramDevice(bdev);
+ }
+
+ // Get free loopback
+ unique_fd loop_fd(TEMP_FAILURE_RETRY(open("/dev/loop-control", O_RDWR | O_CLOEXEC)));
+ if (loop_fd.get() == -1) {
+ PERROR << "Cannot open loop-control";
+ return false;
+ }
+
+ int num = ioctl(loop_fd.get(), LOOP_CTL_GET_FREE);
+ if (num == -1) {
+ PERROR << "Cannot get free loop slot";
+ return false;
+ }
+
+ // Prepare target path
+ unique_fd target_fd(TEMP_FAILURE_RETRY(open(loop.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0664)));
+ if (target_fd.get() == -1) {
+ PERROR << "Cannot open target path: " << loop;
+ return false;
+ }
+ if (fallocate(target_fd.get(), 0, 0, size) < 0) {
+ PERROR << "Cannot truncate target path: " << loop;
+ return false;
+ }
+
+ // Connect loopback (device_fd) to target path (target_fd)
+ std::string device = android::base::StringPrintf("/dev/block/loop%d", num);
+ unique_fd device_fd(TEMP_FAILURE_RETRY(open(device.c_str(), O_RDWR | O_CLOEXEC)));
+ if (device_fd.get() == -1) {
+ PERROR << "Cannot open /dev/block/loop" << num;
+ return false;
+ }
+
+ if (ioctl(device_fd.get(), LOOP_SET_FD, target_fd.get())) {
+ PERROR << "Cannot set loopback to target path";
+ return false;
+ }
+
+ // set block size & direct IO
+ if (ioctl(device_fd.get(), LOOP_SET_BLOCK_SIZE, 4096)) {
+ PWARNING << "Cannot set 4KB blocksize to /dev/block/loop" << num;
+ }
+ if (ioctl(device_fd.get(), LOOP_SET_DIRECT_IO, 1)) {
+ PWARNING << "Cannot set direct_io to /dev/block/loop" << num;
+ }
+
+ return InstallZramDevice(device);
+}
+
bool fs_mgr_swapon_all(const Fstab& fstab) {
bool ret = true;
for (const auto& entry : fstab) {
@@ -1373,6 +1488,10 @@
continue;
}
+ if (!PrepareZramDevice(entry.zram_loopback_path, entry.zram_loopback_size, entry.zram_backing_dev_path)) {
+ LERROR << "Skipping losetup for '" << entry.blk_device << "'";
+ }
+
if (entry.zram_size > 0) {
// A zram_size was specified, so we need to configure the
// device. There is no point in having multiple zram devices
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 53b47be..9d4f280 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -28,8 +28,10 @@
#include <vector>
#include <android-base/file.h>
+#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
+#include <libgsi/libgsi.h>
#include "fs_mgr_priv.h"
@@ -43,6 +45,9 @@
std::string key_dir;
std::string verity_loc;
std::string sysfs_path;
+ std::string zram_loopback_path;
+ uint64_t zram_loopback_size = 512 * 1024 * 1024; // 512MB by default
+ std::string zram_backing_dev_path;
off64_t part_length = 0;
std::string label;
int partnum = -1;
@@ -117,6 +122,10 @@
{"checkpoint=block", MF_CHECKPOINT_BLK},
{"checkpoint=fs", MF_CHECKPOINT_FS},
{"slotselect_other", MF_SLOTSELECT_OTHER},
+ {"zram_loopback_path=", MF_ZRAM_LOOPBACK_PATH},
+ {"zram_loopback_size=", MF_ZRAM_LOOPBACK_SIZE},
+ {"zram_backing_dev_path=", MF_ZRAM_BACKING_DEV_PATH},
+ {"fsverity", MF_FS_VERITY},
{0, 0},
};
@@ -344,6 +353,16 @@
} else if (flag == MF_SYSFS) {
/* The path to trigger device gc by idle-maint of vold. */
flag_vals->sysfs_path = arg;
+ } else if (flag == MF_ZRAM_LOOPBACK_PATH) {
+ /* The path to use loopback for zram. */
+ flag_vals->zram_loopback_path = arg;
+ } else if (flag == MF_ZRAM_LOOPBACK_SIZE) {
+ if (!android::base::ParseByteCount(arg, &flag_vals->zram_loopback_size)) {
+ LERROR << "Warning: zram_loopback_size = flag malformed";
+ }
+ } else if (flag == MF_ZRAM_BACKING_DEV_PATH) {
+ /* The path to use loopback for zram. */
+ flag_vals->zram_backing_dev_path = arg;
}
break;
}
@@ -569,6 +588,9 @@
entry.logical_blk_size = flag_vals.logical_blk_size;
entry.sysfs_path = std::move(flag_vals.sysfs_path);
entry.vbmeta_partition = std::move(flag_vals.vbmeta_partition);
+ entry.zram_loopback_path = std::move(flag_vals.zram_loopback_path);
+ entry.zram_loopback_size = std::move(flag_vals.zram_loopback_size);
+ entry.zram_backing_dev_path = std::move(flag_vals.zram_backing_dev_path);
if (entry.fs_mgr_flags.logical) {
entry.logical_partition_name = entry.blk_device;
}
@@ -638,6 +660,35 @@
return boot_devices;
}
+static void EraseFstabEntry(Fstab* fstab, const std::string& mount_point) {
+ auto iter = std::remove_if(fstab->begin(), fstab->end(),
+ [&](const auto& entry) { return entry.mount_point == mount_point; });
+ fstab->erase(iter, fstab->end());
+}
+
+static void TransformFstabForGsi(Fstab* fstab) {
+ EraseFstabEntry(fstab, "/system");
+ EraseFstabEntry(fstab, "/data");
+
+ fstab->emplace_back(BuildGsiSystemFstabEntry());
+
+ constexpr uint32_t kFlags = MS_NOATIME | MS_NOSUID | MS_NODEV;
+
+ FstabEntry userdata = {
+ .blk_device = "userdata_gsi",
+ .mount_point = "/data",
+ .fs_type = "ext4",
+ .flags = kFlags,
+ .reserved_size = 128 * 1024 * 1024,
+ };
+ userdata.fs_mgr_flags.wait = true;
+ userdata.fs_mgr_flags.check = true;
+ userdata.fs_mgr_flags.logical = true;
+ userdata.fs_mgr_flags.quota = true;
+ userdata.fs_mgr_flags.late_mount = true;
+ fstab->emplace_back(userdata);
+}
+
bool ReadFstabFromFile(const std::string& path, Fstab* fstab) {
auto fstab_file = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
if (!fstab_file) {
@@ -645,10 +696,15 @@
return false;
}
- if (!fs_mgr_read_fstab_file(fstab_file.get(), path == "/proc/mounts", fstab)) {
+ bool is_proc_mounts = path == "/proc/mounts";
+
+ if (!fs_mgr_read_fstab_file(fstab_file.get(), is_proc_mounts, fstab)) {
LERROR << __FUNCTION__ << "(): failed to load fstab from : '" << path << "'";
return false;
}
+ if (!is_proc_mounts && !access(android::gsi::kGsiBootedIndicatorFile, F_OK)) {
+ TransformFstabForGsi(fstab);
+ }
return true;
}
@@ -776,6 +832,8 @@
free(fstab->recs[i].key_dir);
free(fstab->recs[i].label);
free(fstab->recs[i].sysfs_path);
+ free(fstab->recs[i].zram_loopback_path);
+ free(fstab->recs[i].zram_backing_dev_path);
}
/* Free the fstab_recs array created by calloc(3) */
@@ -873,6 +931,9 @@
entry.erase_blk_size = fstab_rec->erase_blk_size;
entry.logical_blk_size = fstab_rec->logical_blk_size;
entry.sysfs_path = fstab_rec->sysfs_path;
+ entry.zram_loopback_path = fstab_rec->zram_loopback_path;
+ entry.zram_loopback_size = fstab_rec->zram_loopback_size;
+ entry.zram_backing_dev_path = fstab_rec->zram_backing_dev_path;
return entry;
}
@@ -916,6 +977,9 @@
legacy_fstab->recs[i].erase_blk_size = fstab[i].erase_blk_size;
legacy_fstab->recs[i].logical_blk_size = fstab[i].logical_blk_size;
legacy_fstab->recs[i].sysfs_path = strdup(fstab[i].sysfs_path.c_str());
+ legacy_fstab->recs[i].zram_loopback_path = strdup(fstab[i].zram_loopback_path.c_str());
+ legacy_fstab->recs[i].zram_loopback_size = fstab[i].zram_loopback_size;
+ legacy_fstab->recs[i].zram_backing_dev_path = strdup(fstab[i].zram_backing_dev_path.c_str());
}
return legacy_fstab;
}
@@ -1023,3 +1087,21 @@
int fs_mgr_is_checkpoint_blk(const struct fstab_rec* fstab) {
return fstab->fs_mgr_flags & MF_CHECKPOINT_BLK;
}
+
+int fs_mgr_is_fs_verity(const struct fstab_rec* fstab) {
+ return fstab->fs_mgr_flags & MF_FS_VERITY;
+}
+
+FstabEntry BuildGsiSystemFstabEntry() {
+ FstabEntry system = {
+ .blk_device = "system_gsi",
+ .mount_point = "/system",
+ .fs_type = "ext4",
+ .flags = MS_RDONLY,
+ .fs_options = "barrier=1",
+ };
+ system.fs_mgr_flags.wait = true;
+ system.fs_mgr_flags.logical = true;
+ system.fs_mgr_flags.first_stage_mount = true;
+ return system;
+}
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 6364ca9..0f89467 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -48,6 +48,7 @@
#include <fs_mgr_overlayfs.h>
#include <fstab/fstab.h>
#include <libdm/dm.h>
+#include <libgsi/libgsi.h>
#include <liblp/builder.h>
#include <liblp/liblp.h>
@@ -802,8 +803,9 @@
bool fs_mgr_overlayfs_invalid() {
if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) return true;
- // in recovery or fastbootd mode, not allowed!
+ // in recovery, fastbootd, or gsi mode, not allowed!
if (fs_mgr_access("/system/bin/recovery")) return true;
+ if (android::gsi::IsGsiRunning()) return true;
return false;
}
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 7842ca2..3b9ddee 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -122,6 +122,14 @@
0x80000000
#define MF_SLOTSELECT_OTHER \
0x100000000
+#define MF_ZRAM_LOOPBACK_PATH \
+ 0x200000000
+#define MF_ZRAM_LOOPBACK_SIZE \
+ 0x400000000
+#define MF_ZRAM_BACKING_DEV_PATH \
+ 0x800000000
+#define MF_FS_VERITY \
+ 0x1000000000
// clang-format on
#define DM_BUF_SIZE 4096
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index 0997254..4a05949 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -59,6 +59,9 @@
off64_t erase_blk_size;
off64_t logical_blk_size;
char* sysfs_path;
+ char* zram_loopback_path;
+ uint64_t zram_loopback_size;
+ char* zram_backing_dev_path;
};
struct fstab* fs_mgr_read_fstab_default();
@@ -92,6 +95,7 @@
int fs_mgr_is_checkpoint_fs(const struct fstab_rec* fstab);
int fs_mgr_is_checkpoint_blk(const struct fstab_rec* fstab);
int fs_mgr_has_sysfs_path(const struct fstab_rec* fstab);
+int fs_mgr_is_fs_verity(const struct fstab_rec* fstab);
std::string fs_mgr_get_slot_suffix();
std::set<std::string> fs_mgr_get_boot_devices();
@@ -119,6 +123,9 @@
off64_t logical_blk_size = 0;
std::string sysfs_path;
std::string vbmeta_partition;
+ std::string zram_loopback_path;
+ uint64_t zram_loopback_size;
+ std::string zram_backing_dev_path;
// TODO: Remove this union once fstab_rec is deprecated. It only serves as a
// convenient way to convert between fstab_rec::fs_mgr_flags and these bools.
@@ -168,6 +175,10 @@
// bit 32
bool slot_select_other : 1;
+ bool zram_loopback_path : 1;
+ bool zram_loopback_size : 1;
+ bool zram_backing_dev_path : 1;
+ bool fs_verity : 1;
};
} fs_mgr_flags;
@@ -187,3 +198,6 @@
FstabEntry FstabRecToFstabEntry(const fstab_rec* fstab_rec);
Fstab LegacyFstabToFstab(const struct fstab* legacy_fstab);
fstab* FstabToLegacyFstab(const Fstab& fstab);
+
+// Helper method to build a GSI fstab entry for mounting /system.
+FstabEntry BuildGsiSystemFstabEntry();
diff --git a/fs_mgr/libdm/Android.bp b/fs_mgr/libdm/Android.bp
index fc1aafb..c8c2d83 100644
--- a/fs_mgr/libdm/Android.bp
+++ b/fs_mgr/libdm/Android.bp
@@ -33,6 +33,11 @@
"libbase_headers",
"liblog_headers",
],
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
}
cc_test {
diff --git a/fs_mgr/libfiemap_writer/fiemap_writer.cpp b/fs_mgr/libfiemap_writer/fiemap_writer.cpp
index 4a0d4b5..71b39a9 100644
--- a/fs_mgr/libfiemap_writer/fiemap_writer.cpp
+++ b/fs_mgr/libfiemap_writer/fiemap_writer.cpp
@@ -304,7 +304,6 @@
return true;
}
-#if 0
static bool IsFilePinned(int file_fd, const std::string& file_path, uint32_t fs_type) {
if (fs_type == EXT4_SUPER_MAGIC) {
// No pinning necessary for ext4. The blocks, once allocated, are expected
@@ -345,7 +344,6 @@
}
return moved_blocks_nr == 0;
}
-#endif
static void LogExtent(uint32_t num, const struct fiemap_extent& ext) {
LOG(INFO) << "Extent #" << num;
@@ -477,13 +475,15 @@
if (create) {
if (!AllocateFile(file_fd, abs_path, blocksz, file_size)) {
+ LOG(ERROR) << "Failed to allocate file: " << abs_path << " of size: " << file_size
+ << " bytes";
cleanup(abs_path, create);
return nullptr;
}
}
// f2fs may move the file blocks around.
- if (!PinFile(file_fd, file_path, fs_type)) {
+ if (!PinFile(file_fd, abs_path, fs_type)) {
cleanup(abs_path, create);
LOG(ERROR) << "Failed to pin the file in storage";
return nullptr;
@@ -538,13 +538,11 @@
return false;
}
-#if 0
- // TODO(b/122138114): check why this fails.
if (!IsFilePinned(file_fd_, file_path_, fs_type_)) {
LOG(ERROR) << "Failed write: file " << file_path_ << " is not pinned";
return false;
}
-#endif
+
// find extents that must be written to and then write one at a time.
uint32_t num_extent = 1;
uint32_t buffer_offset = 0;
diff --git a/fs_mgr/libfs_avb/avb_ops.cpp b/fs_mgr/libfs_avb/avb_ops.cpp
index 3b0ef0b..3efa794 100644
--- a/fs_mgr/libfs_avb/avb_ops.cpp
+++ b/fs_mgr/libfs_avb/avb_ops.cpp
@@ -186,6 +186,7 @@
avb_slot_verify(&avb_ops_, requested_partitions, ab_suffix.c_str(), flags,
AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, &avb_slot_data);
+ if (!avb_slot_data) return verify_result;
// Copies avb_slot_data->vbmeta_images[].
for (size_t i = 0; i < avb_slot_data->num_vbmeta_images; i++) {
out_vbmeta_images->emplace_back(VBMetaData(avb_slot_data->vbmeta_images[i].vbmeta_data,
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index b99ff8f..110d56e 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -269,6 +269,11 @@
}
static bool VerifyDeviceProperties(const BlockDeviceInfo& device_info) {
+ if (device_info.logical_block_size == 0) {
+ LERROR << "Block device " << device_info.partition_name
+ << " logical block size must not be zero.";
+ return false;
+ }
if (device_info.logical_block_size % LP_SECTOR_SIZE != 0) {
LERROR << "Block device " << device_info.partition_name
<< " logical block size must be a multiple of 512.";
@@ -335,7 +340,7 @@
out.alignment = device_info.alignment;
out.alignment_offset = device_info.alignment_offset;
out.size = device_info.size;
- if (device_info.partition_name.size() >= sizeof(out.partition_name)) {
+ if (device_info.partition_name.size() > sizeof(out.partition_name)) {
LERROR << "Partition name " << device_info.partition_name << " exceeds maximum length.";
return false;
}
diff --git a/fs_mgr/liblp/include/liblp/metadata_format.h b/fs_mgr/liblp/include/liblp/metadata_format.h
index 9c5ec5c..8934aaf 100644
--- a/fs_mgr/liblp/include/liblp/metadata_format.h
+++ b/fs_mgr/liblp/include/liblp/metadata_format.h
@@ -127,7 +127,7 @@
* num_entries, and the result must not overflow a 32-bit signed integer.
*/
typedef struct LpMetadataTableDescriptor {
- /* 0: Location of the table, relative to the metadata header. */
+ /* 0: Location of the table, relative to end of the metadata header. */
uint32_t offset;
/* 4: Number of entries in the table. */
uint32_t num_entries;
@@ -272,7 +272,7 @@
/* 40: Maximum size in bytes. If 0, the group has no maximum size. */
uint64_t maximum_size;
-} LpMetadataPartitionGroup;
+} __attribute__((packed)) LpMetadataPartitionGroup;
/* This flag is only intended to be used with super_empty.img and super.img on
* retrofit devices. If set, the group needs a slot suffix to be interpreted
@@ -323,7 +323,7 @@
/* 60: Flags (see LP_BLOCK_DEVICE_* flags below). */
uint32_t flags;
-} LpMetadataBlockDevice;
+} __attribute__((packed)) LpMetadataBlockDevice;
/* This flag is only intended to be used with super_empty.img and super.img on
* retrofit devices. On these devices there are A and B super partitions, and
diff --git a/fs_mgr/liblp/reader.cpp b/fs_mgr/liblp/reader.cpp
index 24c6b2c..dcee6d2 100644
--- a/fs_mgr/liblp/reader.cpp
+++ b/fs_mgr/liblp/reader.cpp
@@ -256,6 +256,10 @@
LERROR << "Logical partition has invalid attribute set.";
return nullptr;
}
+ if (partition.first_extent_index + partition.num_extents < partition.first_extent_index) {
+ LERROR << "Logical partition first_extent_index + num_extents overflowed.";
+ return nullptr;
+ }
if (partition.first_extent_index + partition.num_extents > header.extents.num_entries) {
LERROR << "Logical partition has invalid extent list.";
return nullptr;
diff --git a/fs_mgr/liblp/writer.cpp b/fs_mgr/liblp/writer.cpp
index 54a1883..bffcb7e 100644
--- a/fs_mgr/liblp/writer.cpp
+++ b/fs_mgr/liblp/writer.cpp
@@ -373,11 +373,11 @@
// safety.
std::string old_blob;
if (!ValidateAndSerializeMetadata(opener, *backup.get(), slot_suffix, &old_blob)) {
- LERROR << "Error serializing primary metadata to repair corrupted backup";
+ LERROR << "Error serializing backup metadata to repair corrupted primary";
return false;
}
if (!WritePrimaryMetadata(fd, metadata, slot_number, old_blob, writer)) {
- LERROR << "Error writing primary metadata to repair corrupted backup";
+ LERROR << "Error writing backup metadata to repair corrupted primary";
return false;
}
}
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index 825109f..0765f04 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -164,12 +164,26 @@
Returns: true if device in root state" ]
adb_root() {
+ [ `adb_sh echo '${USER}'` != root ] || return 0
adb root >/dev/null </dev/null 2>/dev/null
sleep 2
adb_wait 2m &&
[ `adb_sh echo '${USER}'` = root ]
}
+[ "USAGE: adb_unroot
+
+NB: This can be flakey on devices due to USB state
+
+Returns: true if device in un root state" ]
+adb_unroot() {
+ [ `adb_sh echo '${USER}'` = root ] || return 0
+ adb unroot >/dev/null </dev/null 2>/dev/null
+ sleep 2
+ adb_wait 2m &&
+ [ `adb_sh echo '${USER}'` != root ]
+}
+
[ "USAGE: fastboot_getvar var expected
Returns: true if var output matches expected" ]
@@ -194,6 +208,15 @@
echo ${O} >&2
}
+[ "USAGE: cleanup
+
+Do nothing: should be redefined when necessary
+
+Returns: cleans up any latent resources, reverses configurations" ]
+cleanup () {
+ :
+}
+
[ "USAGE: die [-d|-t <epoch>] [message] >/dev/stderr
If -d, or -t <epoch> argument is supplied, dump logcat.
@@ -212,6 +235,7 @@
shift 2
fi
echo "${RED}[ FAILED ]${NORMAL} ${@}" >&2
+ cleanup
exit 1
}
@@ -558,6 +582,7 @@
echo "${GREEN}[ OK ]${NORMAL} /system content remains after reboot" >&2
# Only root can read vendor if sepolicy permissions are as expected
if ${enforcing}; then
+ adb_unroot
B="`adb_cat /vendor/hello`" &&
die "re-read /vendor/hello after reboot w/o root"
check_eq "cat: /vendor/hello: Permission denied" "${B}" vendor after reboot w/o root
diff --git a/init/Android.bp b/init/Android.bp
index c920dc2..9f5d17d 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -19,7 +19,6 @@
cpp_std: "experimental",
sanitize: {
misc_undefined: ["signed-integer-overflow"],
- address: false, // TODO(b/120561310): Fix ASAN to work without /proc mounted and re-enable.
},
cflags: [
"-DLOG_UEVENTS=0",
@@ -77,6 +76,7 @@
"libext4_utils",
"libfs_mgr",
"libfscrypt",
+ "libgsi",
"libhidl-gen-utils",
"libkeyutils",
"liblog",
diff --git a/init/Android.mk b/init/Android.mk
index bdd0301..69c63e1 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -91,6 +91,7 @@
libz \
libselinux \
libcap \
+ libgsi \
LOCAL_SANITIZE := signed-integer-overflow
# First stage init is weird: it may start without stdout/stderr, and no /proc.
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 43a520f..169edbe 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -54,6 +54,7 @@
#include <fs_mgr.h>
#include <fscrypt/fscrypt.h>
#include <fscrypt/fscrypt_init_extensions.h>
+#include <libgsi/libgsi.h>
#include <selinux/android.h>
#include <selinux/label.h>
#include <selinux/selinux.h>
@@ -520,6 +521,9 @@
return Success();
} else if (code == FS_MGR_MNTALL_DEV_NEEDS_RECOVERY) {
/* Setup a wipe via recovery, and reboot into recovery */
+ if (android::gsi::IsGsiRunning()) {
+ return Error() << "cannot wipe within GSI";
+ }
PLOG(ERROR) << "fs_mgr_mount_all suggested recovery, so wiping data via recovery.";
const std::vector<std::string> options = {"--wipe_data", "--reason=fs_mgr_mount_all" };
return reboot_into_recovery(options);
@@ -1022,7 +1026,8 @@
}
service->AddReapCallback([reboot_reason](const siginfo_t& siginfo) {
if (siginfo.si_code != CLD_EXITED || siginfo.si_status != 0) {
- if (fscrypt_is_native()) {
+ // TODO (b/122850122): support this in gsi
+ if (fscrypt_is_native() && !android::gsi::IsGsiRunning()) {
LOG(ERROR) << "Rebooting into recovery, reason: " << reboot_reason;
if (auto result = reboot_into_recovery(
{"--prompt_and_wipe_data", "--reason="s + reboot_reason});
@@ -1093,86 +1098,6 @@
}
}
-static Result<Success> bind_mount_file(const char* source, const char* mount_point,
- bool remount_private) {
- if (remount_private && mount(nullptr, mount_point, nullptr, MS_PRIVATE, nullptr) == -1) {
- return ErrnoError() << "Could not change " << mount_point << " to a private mount point";
- }
- if (mount(source, mount_point, nullptr, MS_BIND, nullptr) == -1) {
- return ErrnoError() << "Could not bind-mount " << source << " to " << mount_point;
- }
- return Success();
-}
-
-static Result<Success> bind_mount_bionic(const char* linker_source, const char* lib_dir_source,
- const char* linker_mount_point, const char* lib_mount_dir,
- bool remount_private) {
- if (access(linker_source, F_OK) != 0) {
- return Success();
- }
- if (auto result = bind_mount_file(linker_source, linker_mount_point, remount_private);
- !result) {
- return result;
- }
- for (auto libname : kBionicLibFileNames) {
- std::string mount_point = lib_mount_dir + libname;
- std::string source = lib_dir_source + libname;
- if (auto result = bind_mount_file(source.c_str(), mount_point.c_str(), remount_private);
- !result) {
- return result;
- }
- }
- return Success();
-}
-
-// The bootstrap bionic libs and the bootstrap linker are bind-mounted to
-// the mount points for pre-apexd processes.
-static Result<Success> do_prepare_bootstrap_bionic(const BuiltinArguments& args) {
- static bool prepare_bootstrap_bionic_done = false;
- if (prepare_bootstrap_bionic_done) {
- return Error() << "prepare_bootstrap_bionic was already executed. Cannot be executed again";
- }
- if (auto result = bind_mount_bionic(kBootstrapLinkerPath, kBootstrapBionicLibsDir,
- kLinkerMountPoint, kBionicLibsMountPointDir, false);
- !result) {
- return result;
- }
- if (auto result = bind_mount_bionic(kBootstrapLinkerPath64, kBootstrapBionicLibsDir64,
- kLinkerMountPoint64, kBionicLibsMountPointDir64, false);
- !result) {
- return result;
- }
-
- LOG(INFO) << "prepare_bootstrap_bionic done";
- prepare_bootstrap_bionic_done = true;
- return Success();
-}
-
-// The bionic libs and the dynamic linker from the runtime APEX are bind-mounted
-// to the mount points. As a result, the previous mounts done by
-// prepare_bootstrap_bionic become hidden.
-static Result<Success> do_setup_runtime_bionic(const BuiltinArguments& args) {
- static bool setup_runtime_bionic_done = false;
- if (setup_runtime_bionic_done) {
- return Error() << "setup_runtime_bionic was already executed. Cannot be executed again";
- }
- if (auto result = bind_mount_bionic(kRuntimeLinkerPath, kRuntimeBionicLibsDir,
- kLinkerMountPoint, kBionicLibsMountPointDir, true);
- !result) {
- return result;
- }
- if (auto result = bind_mount_bionic(kRuntimeLinkerPath64, kRuntimeBionicLibsDir64,
- kLinkerMountPoint64, kBionicLibsMountPointDir64, true);
- !result) {
- return result;
- }
-
- ServiceList::GetInstance().MarkRuntimeAvailable();
- LOG(INFO) << "setup_runtime_bionic done";
- setup_runtime_bionic_done = true;
- return Success();
-}
-
// Builtin-function-map start
const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
@@ -1211,7 +1136,6 @@
{"mount_all", {1, kMax, {false, do_mount_all}}},
{"mount", {3, kMax, {false, do_mount}}},
{"parse_apex_configs", {0, 0, {false, do_parse_apex_configs}}},
- {"prepare_bootstrap_bionic",{0, 0, {false, do_prepare_bootstrap_bionic}}},
{"umount", {1, 1, {false, do_umount}}},
{"readahead", {1, 2, {true, do_readahead}}},
{"restart", {1, 1, {false, do_restart}}},
@@ -1220,7 +1144,6 @@
{"rm", {1, 1, {true, do_rm}}},
{"rmdir", {1, 1, {true, do_rmdir}}},
{"setprop", {2, 2, {true, do_setprop}}},
- {"setup_runtime_bionic", {0, 0, {false, do_setup_runtime_bionic}}},
{"setrlimit", {3, 3, {false, do_setrlimit}}},
{"start", {1, 1, {false, do_start}}},
{"stop", {1, 1, {false, do_stop}}},
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 71fe401..affa39e 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -34,6 +34,7 @@
#include <fs_mgr.h>
#include <fs_mgr_dm_linear.h>
#include <fs_mgr_overlayfs.h>
+#include <libgsi/libgsi.h>
#include <liblp/liblp.h>
#include "devices.h"
@@ -79,6 +80,7 @@
bool IsDmLinearEnabled();
bool GetDmLinearMetadataDevice();
bool InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata);
+ void UseGsiIfPresent();
ListenerAction UeventCallback(const Uevent& uevent);
@@ -207,6 +209,8 @@
}
required_devices_partition_names_.emplace(super_partition_name_);
+ // When booting from live GSI images, userdata is the super device.
+ required_devices_partition_names_.emplace("userdata");
return true;
}
@@ -410,6 +414,16 @@
// this case, we mount system first then pivot to it. From that point on,
// we are effectively identical to a system-as-root device.
bool FirstStageMount::TrySwitchSystemAsRoot() {
+ auto metadata_partition = std::find_if(fstab_.begin(), fstab_.end(), [](const auto& entry) {
+ return entry.mount_point == "/metadata";
+ });
+ if (metadata_partition != fstab_.end()) {
+ if (MountPartition(&(*metadata_partition))) {
+ fstab_.erase(metadata_partition);
+ UseGsiIfPresent();
+ }
+ }
+
auto system_partition = std::find_if(fstab_.begin(), fstab_.end(), [](const auto& entry) {
return entry.mount_point == "/system";
});
@@ -513,6 +527,40 @@
return true;
}
+void FirstStageMount::UseGsiIfPresent() {
+ std::string metadata_file, error;
+
+ if (!android::gsi::CanBootIntoGsi(&metadata_file, &error)) {
+ LOG(INFO) << "GSI " << error << ", proceeding with normal boot";
+ return;
+ }
+
+ auto metadata = android::fs_mgr::ReadFromImageFile(metadata_file.c_str());
+ if (!metadata) {
+ LOG(ERROR) << "GSI partition layout could not be read";
+ return;
+ }
+
+ if (!android::fs_mgr::CreateLogicalPartitions(*metadata.get(), "/dev/block/by-name/userdata")) {
+ LOG(ERROR) << "GSI partition layout could not be instantiated";
+ return;
+ }
+
+ if (!android::gsi::MarkSystemAsGsi()) {
+ PLOG(ERROR) << "GSI indicator file could not be written";
+ return;
+ }
+
+ // Replace the existing system fstab entry.
+ auto system_partition = std::find_if(fstab_.begin(), fstab_.end(), [](const auto& entry) {
+ return entry.mount_point == "/system";
+ });
+ if (system_partition != fstab_.end()) {
+ fstab_.erase(system_partition);
+ }
+ fstab_.emplace_back(BuildGsiSystemFstabEntry());
+}
+
bool FirstStageMountVBootV1::GetDmVerityDevices() {
std::string verity_loc_device;
need_dm_verity_ = false;
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 45dc6d3..5b90969 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -20,9 +20,11 @@
#include <fcntl.h>
#include <linux/fs.h>
#include <mntent.h>
+#include <linux/loop.h>
#include <sys/cdefs.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
+#include <sys/swap.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
@@ -55,9 +57,11 @@
#include "service.h"
#include "sigchld_handler.h"
+using android::base::GetBoolProperty;
using android::base::Split;
using android::base::StringPrintf;
using android::base::Timer;
+using android::base::unique_fd;
namespace android {
namespace init {
@@ -103,13 +107,17 @@
int st;
if (IsF2Fs()) {
const char* f2fs_argv[] = {
- "/system/bin/fsck.f2fs", "-f", mnt_fsname_.c_str(),
+ "/system/bin/fsck.f2fs",
+ "-a",
+ mnt_fsname_.c_str(),
};
android_fork_execvp_ext(arraysize(f2fs_argv), (char**)f2fs_argv, &st, true, LOG_KLOG,
true, nullptr, nullptr, 0);
} else if (IsExt4()) {
const char* ext4_argv[] = {
- "/system/bin/e2fsck", "-f", "-y", mnt_fsname_.c_str(),
+ "/system/bin/e2fsck",
+ "-y",
+ mnt_fsname_.c_str(),
};
android_fork_execvp_ext(arraysize(ext4_argv), (char**)ext4_argv, &st, true, LOG_KLOG,
true, nullptr, nullptr, 0);
@@ -189,7 +197,7 @@
return true;
}
-static void DumpUmountDebuggingInfo(bool dump_all) {
+static void DumpUmountDebuggingInfo() {
int status;
if (!security_getenforce()) {
LOG(INFO) << "Run lsof";
@@ -198,10 +206,9 @@
true, nullptr, nullptr, 0);
}
FindPartitionsToUmount(nullptr, nullptr, true);
- if (dump_all) {
- // dump current tasks, this log can be lengthy, so only dump with dump_all
- android::base::WriteStringToFile("t", "/proc/sysrq-trigger");
- }
+ // dump current CPU stack traces and uninterruptible tasks
+ android::base::WriteStringToFile("l", "/proc/sysrq-trigger");
+ android::base::WriteStringToFile("w", "/proc/sysrq-trigger");
}
static UmountStat UmountPartitions(std::chrono::milliseconds timeout) {
@@ -264,11 +271,11 @@
UmountStat stat = UmountPartitions(timeout - t.duration());
if (stat != UMOUNT_STAT_SUCCESS) {
LOG(INFO) << "umount timeout, last resort, kill all and try";
- if (DUMP_ON_UMOUNT_FAILURE) DumpUmountDebuggingInfo(true);
+ if (DUMP_ON_UMOUNT_FAILURE) DumpUmountDebuggingInfo();
KillAllProcesses();
// even if it succeeds, still it is timeout and do not run fsck with all processes killed
UmountStat st = UmountPartitions(0ms);
- if ((st != UMOUNT_STAT_SUCCESS) && DUMP_ON_UMOUNT_FAILURE) DumpUmountDebuggingInfo(false);
+ if ((st != UMOUNT_STAT_SUCCESS) && DUMP_ON_UMOUNT_FAILURE) DumpUmountDebuggingInfo();
}
if (stat == UMOUNT_STAT_SUCCESS && runFsck) {
@@ -281,6 +288,48 @@
return stat;
}
+// zram is able to use backing device on top of a loopback device.
+// In order to unmount /data successfully, we have to kill the loopback device first
+#define ZRAM_DEVICE "/dev/block/zram0"
+#define ZRAM_RESET "/sys/block/zram0/reset"
+#define ZRAM_BACK_DEV "/sys/block/zram0/backing_dev"
+static void KillZramBackingDevice() {
+ std::string backing_dev;
+ if (!android::base::ReadFileToString(ZRAM_BACK_DEV, &backing_dev)) return;
+
+ if (!android::base::StartsWith(backing_dev, "/dev/block/loop")) return;
+
+ // cut the last "\n"
+ backing_dev.erase(backing_dev.length() - 1);
+
+ // shutdown zram handle
+ Timer swap_timer;
+ LOG(INFO) << "swapoff() start...";
+ if (swapoff(ZRAM_DEVICE) == -1) {
+ LOG(ERROR) << "zram_backing_dev: swapoff (" << backing_dev << ")" << " failed";
+ return;
+ }
+ LOG(INFO) << "swapoff() took " << swap_timer;;
+
+ if (!android::base::WriteStringToFile("1", ZRAM_RESET)) {
+ LOG(ERROR) << "zram_backing_dev: reset (" << backing_dev << ")" << " failed";
+ return;
+ }
+
+ // clear loopback device
+ unique_fd loop(TEMP_FAILURE_RETRY(open(backing_dev.c_str(), O_RDWR | O_CLOEXEC)));
+ if (loop.get() < 0) {
+ LOG(ERROR) << "zram_backing_dev: open(" << backing_dev << ")" << " failed";
+ return;
+ }
+
+ if (ioctl(loop.get(), LOOP_CLR_FD, 0) < 0) {
+ LOG(ERROR) << "zram_backing_dev: loop_clear (" << backing_dev << ")" << " failed";
+ return;
+ }
+ LOG(INFO) << "zram_backing_dev: `" << backing_dev << "` is cleared successfully.";
+}
+
//* Reboot / shutdown the system.
// cmd ANDROID_RB_* as defined in android_reboot.h
// reason Reason string like "reboot", "shutdown,userrequested"
@@ -350,9 +399,31 @@
Service* bootAnim = ServiceList::GetInstance().FindService("bootanim");
Service* surfaceFlinger = ServiceList::GetInstance().FindService("surfaceflinger");
if (bootAnim != nullptr && surfaceFlinger != nullptr && surfaceFlinger->IsRunning()) {
- // will not check animation class separately
+ bool do_shutdown_animation = GetBoolProperty("ro.init.shutdown_animation", false);
+
+ if (do_shutdown_animation) {
+ property_set("service.bootanim.exit", "0");
+ // Could be in the middle of animation. Stop and start so that it can pick
+ // up the right mode.
+ bootAnim->Stop();
+ }
+
for (const auto& service : ServiceList::GetInstance()) {
- if (service->classnames().count("animation")) service->SetShutdownCritical();
+ if (service->classnames().count("animation") == 0) {
+ continue;
+ }
+
+ // start all animation classes if stopped.
+ if (do_shutdown_animation) {
+ service->Start().IgnoreError();
+ }
+ service->SetShutdownCritical(); // will not check animation class separately
+ }
+
+ if (do_shutdown_animation) {
+ bootAnim->Start().IgnoreError();
+ surfaceFlinger->SetShutdownCritical();
+ bootAnim->SetShutdownCritical();
}
}
@@ -423,6 +494,9 @@
sync();
LOG(INFO) << "sync() before umount took" << sync_timer;
}
+ // 5. drop caches and disable zram backing device, if exist
+ KillZramBackingDevice();
+
UmountStat stat = TryUmountAndFsck(runFsck, shutdown_timeout - t.duration());
// Follow what linux shutdown is doing: one more sync with little bit delay
{
diff --git a/init/selinux.cpp b/init/selinux.cpp
index ad399ae..d93e9ec 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -442,12 +442,6 @@
selinux_android_restorecon("/dev/block", SELINUX_ANDROID_RESTORECON_RECURSE);
selinux_android_restorecon("/dev/device-mapper", 0);
-
- selinux_android_restorecon("/sbin/mke2fs_static", 0);
- selinux_android_restorecon("/sbin/e2fsdroid_static", 0);
-
- selinux_android_restorecon("/sbin/mkfs.f2fs", 0);
- selinux_android_restorecon("/sbin/sload.f2fs", 0);
}
int SelinuxKlogCallback(int type, const char* fmt, ...) {
diff --git a/init/service.cpp b/init/service.cpp
index f3eafe4..272809f 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -140,43 +140,6 @@
return Success();
}
-Result<Success> Service::SetUpPreApexdMounts() const {
- // If a pre-apexd service is 're' launched after the runtime APEX is
- // available, unmount the linker and bionic libs which are currently
- // bind mounted to the files in the runtime APEX. This will reveal
- // the hidden mount points (targetting the bootstrap ones in the
- // system partition) which were setup before the runtime APEX was
- // started. Note that these unmounts are done in a separate mount namespace
- // for the process. It does not affect other processes including the init.
- if (pre_apexd_ && ServiceList::GetInstance().IsRuntimeAvailable()) {
- if (access(kLinkerMountPoint, F_OK) == 0) {
- if (umount(kLinkerMountPoint) == -1) {
- return ErrnoError() << "Could not umount " << kLinkerMountPoint;
- }
- for (const auto& libname : kBionicLibFileNames) {
- std::string mount_point = kBionicLibsMountPointDir + libname;
- if (umount(mount_point.c_str()) == -1) {
- return ErrnoError() << "Could not umount " << mount_point;
- }
- }
- }
-
- if (access(kLinkerMountPoint64, F_OK) == 0) {
- if (umount(kLinkerMountPoint64) == -1) {
- return ErrnoError() << "Could not umount " << kLinkerMountPoint64;
- }
- for (const auto& libname : kBionicLibFileNames) {
- std::string mount_point = kBionicLibsMountPointDir64 + libname;
- std::string source = kBootstrapBionicLibsDir64 + libname;
- if (umount(mount_point.c_str()) == -1) {
- return ErrnoError() << "Could not umount " << mount_point;
- }
- }
- }
- }
- return Success();
-}
-
Result<Success> Service::SetUpPidNamespace() const {
if (prctl(PR_SET_NAME, name_.c_str()) == -1) {
return ErrnoError() << "Could not set name";
@@ -406,7 +369,7 @@
// If we crash > 4 times in 4 minutes, reboot into bootloader or set crashing property
boot_clock::time_point now = boot_clock::now();
- if (((flags_ & SVC_CRITICAL) || !pre_apexd_) && !(flags_ & SVC_RESTART)) {
+ if (((flags_ & SVC_CRITICAL) || classnames_.count("updatable")) && !(flags_ & SVC_RESTART)) {
if (now < time_crashed_ + 4min) {
if (++crash_count_ > 4) {
if (flags_ & SVC_CRITICAL) {
@@ -966,14 +929,6 @@
scon = *result;
}
- if (!ServiceList::GetInstance().IsRuntimeAvailable() && !pre_apexd_) {
- // If this service is started before the runtime APEX gets available,
- // mark it as pre-apexd one. Note that this marking is permanent. So
- // for example, if the service is re-launched (e.g., due to crash),
- // it is still recognized as pre-apexd... for consistency.
- pre_apexd_ = true;
- }
-
LOG(INFO) << "starting service '" << name_ << "'...";
pid_t pid = -1;
@@ -990,37 +945,6 @@
LOG(FATAL) << "Service '" << name_ << "' could not enter namespaces: " << result.error();
}
- // b/122559956: mount namespace is not cloned for the devices that don't support
- // the update of bionic libraries via APEX. In that case, because the bionic
- // libraries in the runtime APEX and the bootstrap bionic libraries are
- // identical, it doesn't matter which libs are used. This is also to avoid the
- // bug in sdcardfs which is triggered when we have multiple mount namespaces
- // across vold and the others. BIONIC_UPDATABLE shall be true only for the
- // devices where kernel has the fix for the sdcardfs bug (see the commit message
- // for the fix).
- static bool bionic_updatable =
- android::base::GetBoolProperty("ro.apex.bionic_updatable", false);
-
- if (bionic_updatable && pre_apexd_) {
- // pre-apexd process gets a private copy of the mount namespace.
- // However, this does not mean that mount/unmount events are not
- // shared across pre-apexd processes and post-apexd processes.
- // *Most* of the events are still shared because the propagation
- // type of / is set to 'shared'. (see `mount rootfs rootfs /shared
- // rec` in init.rc)
- //
- // This unsharing is required to not propagate the mount events
- // under /system/lib/{libc|libdl|libm}.so and /system/bin/linker(64)
- // whose propagation type is set to private. With this,
- // bind-mounting the bionic libs and the dynamic linker from the
- // runtime APEX to the mount points does not affect pre-apexd
- // processes which should use the bootstrap ones.
- if (unshare(CLONE_NEWNS) != 0) {
- LOG(FATAL) << "Creating a new mount namespace for service"
- << " '" << name_ << "' failed: " << strerror(errno);
- }
- }
-
if (namespace_flags_ & CLONE_NEWNS) {
if (auto result = SetUpMountNamespace(); !result) {
LOG(FATAL) << "Service '" << name_
@@ -1028,14 +952,6 @@
}
}
- // b/122559956: same as above
- if (bionic_updatable && pre_apexd_ && ServiceList::GetInstance().IsRuntimeAvailable()) {
- if (auto result = SetUpPreApexdMounts(); !result) {
- LOG(FATAL) << "Pre-apexd service '" << name_
- << "' could not setup the mount points: " << result.error();
- }
- }
-
if (namespace_flags_ & CLONE_NEWPID) {
// This will fork again to run an init process inside the PID
// namespace.
@@ -1408,10 +1324,6 @@
delayed_service_names_.clear();
}
-void ServiceList::MarkRuntimeAvailable() {
- runtime_available_ = true;
-}
-
void ServiceList::DelayService(const Service& service) {
if (services_update_finished_) {
LOG(ERROR) << "Cannot delay the start of service '" << service.name()
diff --git a/init/service.h b/init/service.h
index 676111f..56e75b0 100644
--- a/init/service.h
+++ b/init/service.h
@@ -62,24 +62,6 @@
namespace android {
namespace init {
-static constexpr const char* kLinkerMountPoint = "/system/bin/linker";
-static constexpr const char* kBootstrapLinkerPath = "/system/bin/linker";
-static constexpr const char* kRuntimeLinkerPath = "/apex/com.android.runtime/bin/linker";
-
-static constexpr const char* kBionicLibsMountPointDir = "/system/lib/";
-static constexpr const char* kBootstrapBionicLibsDir = "/system/lib/";
-static constexpr const char* kRuntimeBionicLibsDir = "/apex/com.android.runtime/lib/bionic/";
-
-static constexpr const char* kLinkerMountPoint64 = "/system/bin/linker64";
-static constexpr const char* kBootstrapLinkerPath64 = "/system/bin/linker64";
-static constexpr const char* kRuntimeLinkerPath64 = "/apex/com.android.runtime/bin/linker64";
-
-static constexpr const char* kBionicLibsMountPointDir64 = "/system/lib64/";
-static constexpr const char* kBootstrapBionicLibsDir64 = "/system/lib64/";
-static constexpr const char* kRuntimeBionicLibsDir64 = "/apex/com.android.runtime/lib64/bionic/";
-
-static const std::vector<std::string> kBionicLibFileNames = {"libc.so", "libm.so", "libdl.so"};
-
class Service {
public:
Service(const std::string& name, Subcontext* subcontext_for_restart_commands,
@@ -142,7 +124,6 @@
std::optional<std::chrono::seconds> timeout_period() const { return timeout_period_; }
const std::vector<std::string>& args() const { return args_; }
bool is_updatable() const { return updatable_; }
- bool is_pre_apexd() const { return pre_apexd_; }
private:
using OptionParser = Result<Success> (Service::*)(std::vector<std::string>&& args);
@@ -151,7 +132,6 @@
Result<Success> SetUpMountNamespace() const;
Result<Success> SetUpPidNamespace() const;
Result<Success> EnterNamespaces() const;
- Result<Success> SetUpPreApexdMounts() const;
void NotifyStateChange(const std::string& new_state) const;
void StopOrReset(int how);
void ZapStdio() const;
@@ -262,8 +242,6 @@
std::vector<std::string> args_;
std::vector<std::function<void(const siginfo_t& siginfo)>> reap_callbacks_;
-
- bool pre_apexd_ = false;
};
class ServiceList {
@@ -306,16 +284,13 @@
const std::vector<Service*> services_in_shutdown_order() const;
void MarkServicesUpdate();
- void MarkRuntimeAvailable();
bool IsServicesUpdated() const { return services_update_finished_; }
- bool IsRuntimeAvailable() const { return runtime_available_; }
void DelayService(const Service& service);
private:
std::vector<std::unique_ptr<Service>> services_;
bool services_update_finished_ = false;
- bool runtime_available_ = false;
std::vector<std::string> delayed_service_names_;
};
diff --git a/libcutils/include/private/android_filesystem_config.h b/libcutils/include/private/android_filesystem_config.h
index 0723612..03edfb5 100644
--- a/libcutils/include/private/android_filesystem_config.h
+++ b/libcutils/include/private/android_filesystem_config.h
@@ -190,7 +190,8 @@
*/
#define AID_OVERFLOWUID 65534 /* unmapped user in the user namespace */
-#define AID_ISOLATED_START 99000 /* start of uids for fully isolated sandboxed processes */
+/* use the ranges below to determine whether a process is isolated */
+#define AID_ISOLATED_START 90000 /* start of uids for fully isolated sandboxed processes */
#define AID_ISOLATED_END 99999 /* end of uids for fully isolated sandboxed processes */
#define AID_USER 100000 /* TODO: switch users over to AID_USER_OFFSET */
diff --git a/liblog/Android.bp b/liblog/Android.bp
index 619a94b..4fd36f5 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -15,30 +15,29 @@
//
liblog_sources = [
- "config_read.c",
- "config_write.c",
- "log_event_list.c",
- "log_event_write.c",
- "log_ratelimit.cpp",
- "logger_lock.c",
- "logger_name.c",
- "logger_read.c",
- "logger_write.c",
- "logprint.c",
- "stderr_write.c",
+ "config_read.cpp",
+ "config_write.cpp",
+ "log_event_list.cpp",
+ "log_event_write.cpp",
+ "logger_lock.cpp",
+ "logger_name.cpp",
+ "logger_read.cpp",
+ "logger_write.cpp",
+ "logprint.cpp",
+ "stderr_write.cpp",
]
liblog_host_sources = [
- "fake_log_device.c",
- "fake_writer.c",
+ "fake_log_device.cpp",
+ "fake_writer.cpp",
]
liblog_target_sources = [
"event_tag_map.cpp",
"log_time.cpp",
- "properties.c",
- "pmsg_reader.c",
- "pmsg_writer.c",
- "logd_reader.c",
- "logd_writer.c",
+ "properties.cpp",
+ "pmsg_reader.cpp",
+ "pmsg_writer.cpp",
+ "logd_reader.cpp",
+ "logd_writer.cpp",
]
cc_library_headers {
@@ -86,7 +85,6 @@
ldflags: ["-Wl,--hash-style=both"],
},
windows: {
- srcs: ["uio.c"],
enabled: true,
},
not_windows: {
diff --git a/liblog/config_read.c b/liblog/config_read.cpp
similarity index 68%
rename from liblog/config_read.c
rename to liblog/config_read.cpp
index 51ffff6..80177a4 100644
--- a/liblog/config_read.c
+++ b/liblog/config_read.cpp
@@ -19,23 +19,21 @@
#include "config_read.h"
#include "logger.h"
-LIBLOG_HIDDEN struct listnode __android_log_transport_read = {
- &__android_log_transport_read, &__android_log_transport_read
-};
-LIBLOG_HIDDEN struct listnode __android_log_persist_read = {
- &__android_log_persist_read, &__android_log_persist_read
-};
+LIBLOG_HIDDEN struct listnode __android_log_transport_read = {&__android_log_transport_read,
+ &__android_log_transport_read};
+LIBLOG_HIDDEN struct listnode __android_log_persist_read = {&__android_log_persist_read,
+ &__android_log_persist_read};
-static void __android_log_add_transport(
- struct listnode* list, struct android_log_transport_read* transport) {
- size_t i;
+static void __android_log_add_transport(struct listnode* list,
+ struct android_log_transport_read* transport) {
+ uint32_t i;
/* Try to keep one functioning transport for each log buffer id */
for (i = LOG_ID_MIN; i < LOG_ID_MAX; i++) {
struct android_log_transport_read* transp;
if (list_empty(list)) {
- if (!transport->available || ((*transport->available)(i) >= 0)) {
+ if (!transport->available || ((*transport->available)(static_cast<log_id_t>(i)) >= 0)) {
list_add_tail(list, &transport->node);
return;
}
@@ -44,8 +42,8 @@
if (!transp->available) {
return;
}
- if (((*transp->available)(i) < 0) &&
- (!transport->available || ((*transport->available)(i) >= 0))) {
+ if (((*transp->available)(static_cast<log_id_t>(i)) < 0) &&
+ (!transport->available || ((*transport->available)(static_cast<log_id_t>(i)) >= 0))) {
list_add_tail(list, &transport->node);
return;
}
@@ -56,8 +54,7 @@
LIBLOG_HIDDEN void __android_log_config_read() {
#if (FAKE_LOG_DEVICE == 0)
- if ((__android_log_transport == LOGGER_DEFAULT) ||
- (__android_log_transport & LOGGER_LOGD)) {
+ if ((__android_log_transport == LOGGER_DEFAULT) || (__android_log_transport & LOGGER_LOGD)) {
extern struct android_log_transport_read logdLoggerRead;
extern struct android_log_transport_read pmsgLoggerRead;
diff --git a/liblog/config_read.h b/liblog/config_read.h
index 7b29fa4..00ea453 100644
--- a/liblog/config_read.h
+++ b/liblog/config_read.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _LIBLOG_CONFIG_READ_H__
-#define _LIBLOG_CONFIG_READ_H__
+#pragma once
#include <cutils/list.h>
@@ -51,5 +50,3 @@
LIBLOG_HIDDEN void __android_log_config_read_close();
__END_DECLS
-
-#endif /* _LIBLOG_CONFIG_READ_H__ */
diff --git a/liblog/config_write.c b/liblog/config_write.cpp
similarity index 69%
rename from liblog/config_write.c
rename to liblog/config_write.cpp
index 003ec8f..e65c238 100644
--- a/liblog/config_write.c
+++ b/liblog/config_write.cpp
@@ -19,23 +19,21 @@
#include "config_write.h"
#include "logger.h"
-LIBLOG_HIDDEN struct listnode __android_log_transport_write = {
- &__android_log_transport_write, &__android_log_transport_write
-};
-LIBLOG_HIDDEN struct listnode __android_log_persist_write = {
- &__android_log_persist_write, &__android_log_persist_write
-};
+LIBLOG_HIDDEN struct listnode __android_log_transport_write = {&__android_log_transport_write,
+ &__android_log_transport_write};
+LIBLOG_HIDDEN struct listnode __android_log_persist_write = {&__android_log_persist_write,
+ &__android_log_persist_write};
-static void __android_log_add_transport(
- struct listnode* list, struct android_log_transport_write* transport) {
- size_t i;
+static void __android_log_add_transport(struct listnode* list,
+ struct android_log_transport_write* transport) {
+ uint32_t i;
/* Try to keep one functioning transport for each log buffer id */
for (i = LOG_ID_MIN; i < LOG_ID_MAX; i++) {
struct android_log_transport_write* transp;
if (list_empty(list)) {
- if (!transport->available || ((*transport->available)(i) >= 0)) {
+ if (!transport->available || ((*transport->available)(static_cast<log_id_t>(i)) >= 0)) {
list_add_tail(list, &transport->node);
return;
}
@@ -44,8 +42,8 @@
if (!transp->available) {
return;
}
- if (((*transp->available)(i) < 0) &&
- (!transport->available || ((*transport->available)(i) >= 0))) {
+ if (((*transp->available)(static_cast<log_id_t>(i)) < 0) &&
+ (!transport->available || ((*transport->available)(static_cast<log_id_t>(i)) >= 0))) {
list_add_tail(list, &transport->node);
return;
}
@@ -55,20 +53,17 @@
}
LIBLOG_HIDDEN void __android_log_config_write() {
- if ((__android_log_transport == LOGGER_DEFAULT) ||
- (__android_log_transport & LOGGER_LOGD)) {
+ if ((__android_log_transport == LOGGER_DEFAULT) || (__android_log_transport & LOGGER_LOGD)) {
#if (FAKE_LOG_DEVICE == 0)
extern struct android_log_transport_write logdLoggerWrite;
extern struct android_log_transport_write pmsgLoggerWrite;
- __android_log_add_transport(&__android_log_transport_write,
- &logdLoggerWrite);
+ __android_log_add_transport(&__android_log_transport_write, &logdLoggerWrite);
__android_log_add_transport(&__android_log_persist_write, &pmsgLoggerWrite);
#else
extern struct android_log_transport_write fakeLoggerWrite;
- __android_log_add_transport(&__android_log_transport_write,
- &fakeLoggerWrite);
+ __android_log_add_transport(&__android_log_transport_write, &fakeLoggerWrite);
#endif
}
@@ -81,8 +76,7 @@
* Remember we can be called here if we are already initialized.
*/
if (list_empty(&__android_log_transport_write)) {
- __android_log_add_transport(&__android_log_transport_write,
- &stderrLoggerWrite);
+ __android_log_add_transport(&__android_log_transport_write, &stderrLoggerWrite);
} else {
struct android_log_transport_write* transp;
write_transport_for_each(transp, &__android_log_transport_write) {
@@ -90,8 +84,7 @@
return;
}
}
- __android_log_add_transport(&__android_log_persist_write,
- &stderrLoggerWrite);
+ __android_log_add_transport(&__android_log_persist_write, &stderrLoggerWrite);
}
}
}
diff --git a/liblog/config_write.h b/liblog/config_write.h
index db1a083..e3be445 100644
--- a/liblog/config_write.h
+++ b/liblog/config_write.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _LIBLOG_CONFIG_WRITE_H__
-#define _LIBLOG_CONFIG_WRITE_H__
+#pragma once
#include <cutils/list.h>
@@ -51,5 +50,3 @@
LIBLOG_HIDDEN void __android_log_config_write_close();
__END_DECLS
-
-#endif /* _LIBLOG_CONFIG_WRITE_H__ */
diff --git a/liblog/fake_log_device.c b/liblog/fake_log_device.cpp
similarity index 88%
rename from liblog/fake_log_device.c
rename to liblog/fake_log_device.cpp
index 1483c24..5daae41 100644
--- a/liblog/fake_log_device.c
+++ b/liblog/fake_log_device.cpp
@@ -17,6 +17,9 @@
* Intercepts log messages intended for the Android log device.
* Messages are printed to stderr.
*/
+
+#include "fake_log_device.h"
+
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
@@ -30,9 +33,7 @@
#include <time.h>
#include <android/log.h>
-#include <log/uio.h>
-#include "fake_log_device.h"
#include "log_portability.h"
#define kMaxTagLen 16 /* from the long-dead utils/Log.cpp */
@@ -181,8 +182,7 @@
logState->debugName[sizeof(logState->debugName) - 1] = '\0';
/* identify binary logs */
- if (!strcmp(pathName + kDevLogLen, "events") ||
- !strcmp(pathName + kDevLogLen, "security")) {
+ if (!strcmp(pathName + kDevLogLen, "events") || !strcmp(pathName + kDevLogLen, "security")) {
logState->isBinary = 1;
}
@@ -204,8 +204,7 @@
while (isspace(*tags)) tags++;
i = 0;
- while (*tags != '\0' && !isspace(*tags) && *tags != ':' &&
- i < kMaxTagLen) {
+ while (*tags != '\0' && !isspace(*tags) && *tags != ':' && i < kMaxTagLen) {
tagName[i++] = *tags++;
}
if (i == kMaxTagLen) {
@@ -313,13 +312,11 @@
*/
static const char* getPriorityString(int priority) {
/* the first character of each string should be unique */
- static const char* priorityStrings[] = { "Verbose", "Debug", "Info",
- "Warn", "Error", "Assert" };
+ static const char* priorityStrings[] = {"Verbose", "Debug", "Info", "Warn", "Error", "Assert"};
int idx;
idx = (int)priority - (int)ANDROID_LOG_VERBOSE;
- if (idx < 0 ||
- idx >= (int)(sizeof(priorityStrings) / sizeof(priorityStrings[0])))
+ if (idx < 0 || idx >= (int)(sizeof(priorityStrings) / sizeof(priorityStrings[0])))
return "?unknown?";
return priorityStrings[idx];
}
@@ -351,8 +348,7 @@
*
* Log format parsing taken from the long-dead utils/Log.cpp.
*/
-static void showLog(LogState* state, int logPrio, const char* tag,
- const char* msg) {
+static void showLog(LogState* state, int logPrio, const char* tag, const char* msg) {
#if !defined(_WIN32)
struct tm tmBuf;
#endif
@@ -397,19 +393,16 @@
switch (state->outputFormat) {
case FORMAT_TAG:
- prefixLen =
- snprintf(prefixBuf, sizeof(prefixBuf), "%c/%-8s: ", priChar, tag);
+ prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), "%c/%-8s: ", priChar, tag);
strcpy(suffixBuf, "\n");
suffixLen = 1;
break;
case FORMAT_PROCESS:
- prefixLen =
- snprintf(prefixBuf, sizeof(prefixBuf), "%c(%5d) ", priChar, pid);
+ prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), "%c(%5d) ", priChar, pid);
suffixLen = snprintf(suffixBuf, sizeof(suffixBuf), " (%s)\n", tag);
break;
case FORMAT_THREAD:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), "%c(%5d:%5d) ",
- priChar, pid, tid);
+ prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), "%c(%5d:%5d) ", priChar, pid, tid);
strcpy(suffixBuf, "\n");
suffixLen = 1;
break;
@@ -420,28 +413,24 @@
suffixLen = 1;
break;
case FORMAT_TIME:
- prefixLen =
- snprintf(prefixBuf, sizeof(prefixBuf), "%s %-8s\n\t", timeBuf, tag);
+ prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), "%s %-8s\n\t", timeBuf, tag);
strcpy(suffixBuf, "\n");
suffixLen = 1;
break;
case FORMAT_THREADTIME:
- prefixLen =
- snprintf(prefixBuf, sizeof(prefixBuf), "%s %5d %5d %c %-8s \n\t",
- timeBuf, pid, tid, priChar, tag);
+ prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), "%s %5d %5d %c %-8s \n\t", timeBuf, pid,
+ tid, priChar, tag);
strcpy(suffixBuf, "\n");
suffixLen = 1;
break;
case FORMAT_LONG:
- prefixLen =
- snprintf(prefixBuf, sizeof(prefixBuf), "[ %s %5d:%5d %c/%-8s ]\n",
- timeBuf, pid, tid, priChar, tag);
+ prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), "[ %s %5d:%5d %c/%-8s ]\n", timeBuf, pid,
+ tid, priChar, tag);
strcpy(suffixBuf, "\n\n");
suffixLen = 2;
break;
default:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
- "%c/%-8s(%5d): ", priChar, tag, pid);
+ prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), "%c/%-8s(%5d): ", priChar, tag, pid);
strcpy(suffixBuf, "\n");
suffixLen = 1;
break;
@@ -559,8 +548,7 @@
* tag (N bytes -- null-terminated ASCII string)
* message (N bytes -- null-terminated ASCII string)
*/
-LIBLOG_HIDDEN ssize_t fakeLogWritev(int fd, const struct iovec* vector,
- int count) {
+LIBLOG_HIDDEN ssize_t fakeLogWritev(int fd, const struct iovec* vector, int count) {
LogState* state;
/* Make sure that no-one frees the LogState while we're using it.
@@ -572,17 +560,24 @@
state = fdToLogState(fd);
if (state == NULL) {
errno = EBADF;
- goto error;
+ unlock();
+ return -1;
}
if (state->isBinary) {
TRACE("%s: ignoring binary log\n", state->debugName);
- goto bail;
+ unlock();
+ int len = 0;
+ for (int i = 0; i < count; ++i) {
+ len += vector[i].iov_len;
+ }
+ return len;
}
if (count != 3) {
TRACE("%s: writevLog with count=%d not expected\n", state->debugName, count);
- goto error;
+ unlock();
+ return -1;
}
/* pull out the three fields */
@@ -598,7 +593,6 @@
break; /* reached end of configured values */
if (strcmp(state->tagSet[i].tag, tag) == 0) {
- // TRACE("MATCH tag '%s'\n", tag);
minPrio = state->tagSet[i].minPriority;
break;
}
@@ -606,21 +600,14 @@
if (logPrio >= minPrio) {
showLog(state, logPrio, tag, msg);
- } else {
- // TRACE("+++ NOLOG(%d): %s %s", logPrio, tag, msg);
}
-bail:
unlock();
int len = 0;
for (i = 0; i < count; ++i) {
len += vector[i].iov_len;
}
return len;
-
-error:
- unlock();
- return -1;
}
/*
@@ -663,22 +650,16 @@
return fd;
}
-LIBLOG_HIDDEN ssize_t __send_log_msg(char* buf __unused,
- size_t buf_size __unused) {
+LIBLOG_HIDDEN ssize_t __send_log_msg(char*, size_t) {
return -ENODEV;
}
-LIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio,
- const char* tag __unused,
- int def) {
+LIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio, const char*, int def) {
int logLevel = def;
return logLevel >= 0 && prio >= logLevel;
}
-LIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio,
- const char* tag __unused,
- size_t len __unused,
- int def) {
+LIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio, const char*, size_t, int def) {
int logLevel = def;
return logLevel >= 0 && prio >= logLevel;
}
diff --git a/liblog/fake_log_device.h b/liblog/fake_log_device.h
index 7b0e745..ef0beb6 100644
--- a/liblog/fake_log_device.h
+++ b/liblog/fake_log_device.h
@@ -14,18 +14,25 @@
* limitations under the License.
*/
-#ifndef _LIBLOG_FAKE_LOG_DEVICE_H
-#define _LIBLOG_FAKE_LOG_DEVICE_H
+#pragma once
#include <sys/types.h>
#include "log_portability.h"
+#include "uio.h"
struct iovec;
+__BEGIN_DECLS
+
LIBLOG_HIDDEN int fakeLogOpen(const char* pathName);
LIBLOG_HIDDEN int fakeLogClose(int fd);
LIBLOG_HIDDEN ssize_t fakeLogWritev(int fd, const struct iovec* vector,
int count);
-#endif // _LIBLOG_FAKE_LOG_DEVICE_H
+LIBLOG_HIDDEN ssize_t __send_log_msg(char*, size_t);
+LIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio, const char*, int def);
+LIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio, const char*, size_t, int def);
+LIBLOG_ABI_PRIVATE int __android_log_is_debuggable();
+
+__END_DECLS
diff --git a/liblog/fake_writer.c b/liblog/fake_writer.cpp
similarity index 82%
rename from liblog/fake_writer.c
rename to liblog/fake_writer.cpp
index 403dc72..46d171b 100644
--- a/liblog/fake_writer.c
+++ b/liblog/fake_writer.cpp
@@ -27,19 +27,18 @@
static int fakeOpen();
static void fakeClose();
-static int fakeWrite(log_id_t log_id, struct timespec* ts, struct iovec* vec,
- size_t nr);
+static int fakeWrite(log_id_t log_id, struct timespec* ts, struct iovec* vec, size_t nr);
-static int logFds[(int)LOG_ID_MAX] = { -1, -1, -1, -1, -1, -1 };
+static int logFds[(int)LOG_ID_MAX] = {-1, -1, -1, -1, -1, -1};
LIBLOG_HIDDEN struct android_log_transport_write fakeLoggerWrite = {
- .node = { &fakeLoggerWrite.node, &fakeLoggerWrite.node },
- .context.priv = &logFds,
- .name = "fake",
- .available = NULL,
- .open = fakeOpen,
- .close = fakeClose,
- .write = fakeWrite,
+ .node = {&fakeLoggerWrite.node, &fakeLoggerWrite.node},
+ .context.priv = &logFds,
+ .name = "fake",
+ .available = NULL,
+ .open = fakeOpen,
+ .close = fakeClose,
+ .write = fakeWrite,
};
static int fakeOpen() {
@@ -54,7 +53,7 @@
if (logFds[i] >= 0) {
continue;
}
- snprintf(buf, sizeof(buf), "/dev/log_%s", android_log_id_to_name(i));
+ snprintf(buf, sizeof(buf), "/dev/log_%s", android_log_id_to_name(static_cast<log_id_t>(i)));
logFds[i] = fakeLogOpen(buf);
if (logFds[i] < 0) {
fprintf(stderr, "fakeLogOpen(%s) failed\n", buf);
@@ -72,8 +71,7 @@
}
}
-static int fakeWrite(log_id_t log_id, struct timespec* ts __unused,
- struct iovec* vec, size_t nr) {
+static int fakeWrite(log_id_t log_id, struct timespec*, struct iovec* vec, size_t nr) {
ssize_t ret;
size_t i;
int logFd, len;
diff --git a/liblog/include/log/event_tag_map.h b/liblog/include/log/event_tag_map.h
index 8dd9157..2687b3a 100644
--- a/liblog/include/log/event_tag_map.h
+++ b/liblog/include/log/event_tag_map.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _LIBS_CUTILS_EVENTTAGMAP_H
-#define _LIBS_CUTILS_EVENTTAGMAP_H
+#pragma once
#ifdef __cplusplus
extern "C" {
@@ -69,5 +68,3 @@
#ifdef __cplusplus
}
#endif
-
-#endif /*_LIBS_CUTILS_EVENTTAGMAP_H*/
diff --git a/liblog/include/log/log.h b/liblog/include/log/log.h
index 3813e6e..5928649 100644
--- a/liblog/include/log/log.h
+++ b/liblog/include/log/log.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _LIBS_LOG_LOG_H
-#define _LIBS_LOG_LOG_H
+#pragma once
/* Too many in the ecosystem assume these are included */
#if !defined(_WIN32)
@@ -35,7 +34,6 @@
#include <log/log_safetynet.h>
#include <log/log_system.h>
#include <log/log_time.h>
-#include <log/uio.h> /* helper to define iovec for portability */
#ifdef __cplusplus
extern "C" {
@@ -152,35 +150,12 @@
#ifdef __linux__
-#ifndef __ANDROID_USE_LIBLOG_CLOCK_INTERFACE
-#ifndef __ANDROID_API__
-#define __ANDROID_USE_LIBLOG_CLOCK_INTERFACE 1
-#elif __ANDROID_API__ > 22 /* > Lollipop */
-#define __ANDROID_USE_LIBLOG_CLOCK_INTERFACE 1
-#else
-#define __ANDROID_USE_LIBLOG_CLOCK_INTERFACE 0
-#endif
-#endif
-
-#if __ANDROID_USE_LIBLOG_CLOCK_INTERFACE
clockid_t android_log_clockid(void);
-#endif
#endif /* __linux__ */
/* --------------------------------------------------------------------- */
-#ifndef __ANDROID_USE_LIBLOG_CLOSE_INTERFACE
-#ifndef __ANDROID_API__
-#define __ANDROID_USE_LIBLOG_CLOSE_INTERFACE 1
-#elif __ANDROID_API__ > 18 /* > JellyBean */
-#define __ANDROID_USE_LIBLOG_CLOSE_INTERFACE 1
-#else
-#define __ANDROID_USE_LIBLOG_CLOSE_INTERFACE 0
-#endif
-#endif
-
-#if __ANDROID_USE_LIBLOG_CLOSE_INTERFACE
/*
* Release any logger resources (a new log write will immediately re-acquire)
*
@@ -188,54 +163,6 @@
* all O_CLOEXEC so wil self clean on exec().
*/
void __android_log_close(void);
-#endif
-
-#ifndef __ANDROID_USE_LIBLOG_RATELIMIT_INTERFACE
-#ifndef __ANDROID_API__
-#define __ANDROID_USE_LIBLOG_RATELIMIT_INTERFACE 1
-#elif __ANDROID_API__ > 25 /* > OC */
-#define __ANDROID_USE_LIBLOG_RATELIMIT_INTERFACE 1
-#else
-#define __ANDROID_USE_LIBLOG_RATELIMIT_INTERFACE 0
-#endif
-#endif
-
-#if __ANDROID_USE_LIBLOG_RATELIMIT_INTERFACE
-
-/*
- * if last is NULL, caller _must_ provide a consistent value for seconds.
- *
- * Return -1 if we can not acquire a lock, which below will permit the logging,
- * error on allowing a log message through.
- */
-int __android_log_ratelimit(time_t seconds, time_t* last);
-
-/*
- * Usage:
- *
- * // Global default and state
- * IF_ALOG_RATELIMIT() {
- * ALOG*(...);
- * }
- *
- * // local state, 10 seconds ratelimit
- * static time_t local_state;
- * IF_ALOG_RATELIMIT_LOCAL(10, &local_state) {
- * ALOG*(...);
- * }
- */
-
-#define IF_ALOG_RATELIMIT() if (__android_log_ratelimit(0, NULL) > 0)
-#define IF_ALOG_RATELIMIT_LOCAL(seconds, state) \
- if (__android_log_ratelimit(seconds, state) > 0)
-
-#else
-
-/* No ratelimiting as API unsupported */
-#define IF_ALOG_RATELIMIT() if (1)
-#define IF_ALOG_RATELIMIT_LOCAL(...) if (1)
-
-#endif
#if defined(__clang__)
#pragma clang diagnostic pop
@@ -244,5 +171,3 @@
#ifdef __cplusplus
}
#endif
-
-#endif /* _LIBS_LOG_LOG_H */
diff --git a/liblog/include/log/log_event_list.h b/liblog/include/log/log_event_list.h
index 1b7c377..636d417 100644
--- a/liblog/include/log/log_event_list.h
+++ b/liblog/include/log/log_event_list.h
@@ -14,16 +14,13 @@
* limitations under the License.
*/
-#ifndef _LIBS_LOG_EVENT_LIST_H
-#define _LIBS_LOG_EVENT_LIST_H
+#pragma once
#include <errno.h>
#include <stdint.h>
-#if (defined(__cplusplus) && defined(_USING_LIBCXX))
-extern "C++" {
+#ifdef __cplusplus
#include <string>
-}
#endif
#include <log/log.h>
@@ -32,18 +29,6 @@
extern "C" {
#endif
-#ifndef __ANDROID_USE_LIBLOG_EVENT_INTERFACE
-#ifndef __ANDROID_API__
-#define __ANDROID_USE_LIBLOG_EVENT_INTERFACE 1
-#elif __ANDROID_API__ > 23 /* > Marshmallow */
-#define __ANDROID_USE_LIBLOG_EVENT_INTERFACE 1
-#else
-#define __ANDROID_USE_LIBLOG_EVENT_INTERFACE 0
-#endif
-#endif
-
-#if __ANDROID_USE_LIBLOG_EVENT_INTERFACE
-
/* For manipulating lists of events. */
#define ANDROID_MAX_LIST_NEST_DEPTH 8
@@ -124,8 +109,6 @@
/* android_log_list C++ helpers */
extern "C++" {
class android_log_event_list {
- friend class __android_log_event_list;
-
private:
android_log_context ctx;
int ret;
@@ -137,10 +120,6 @@
explicit android_log_event_list(int tag) : ret(0) {
ctx = create_android_logger(static_cast<uint32_t>(tag));
}
- explicit android_log_event_list(log_msg& log_msg) : ret(0) {
- ctx = create_android_log_parser(log_msg.msg() + sizeof(uint32_t),
- log_msg.entry.len - sizeof(uint32_t));
- }
~android_log_event_list() {
android_log_destroy(&ctx);
}
@@ -208,14 +187,12 @@
return *this;
}
-#if defined(_USING_LIBCXX)
android_log_event_list& operator<<(const std::string& value) {
int retval =
android_log_write_string8_len(ctx, value.data(), value.length());
if (retval < 0) ret = retval;
return *this;
}
-#endif
android_log_event_list& operator<<(float value) {
int retval = android_log_write_float32(ctx, value);
@@ -269,7 +246,6 @@
return ret >= 0;
}
-#if defined(_USING_LIBCXX)
bool AppendString(const std::string& value) {
int retval =
android_log_write_string8_len(ctx, value.data(), value.length());
@@ -283,7 +259,6 @@
if (retval < 0) ret = retval;
return ret;
}
-#endif
bool AppendFloat(float value) {
int retval = android_log_write_float32(ctx, value);
@@ -302,22 +277,11 @@
if (retval < 0) ret = retval;
return ret >= 0;
}
-
- android_log_list_element read() {
- return android_log_read_next(ctx);
- }
- android_log_list_element peek() {
- return android_log_peek_next(ctx);
- }
};
}
#endif
#endif
-#endif /* __ANDROID_USE_LIBLOG_EVENT_INTERFACE */
-
#ifdef __cplusplus
}
#endif
-
-#endif /* _LIBS_LOG_EVENT_LIST_H */
diff --git a/liblog/include/log/log_id.h b/liblog/include/log/log_id.h
index c44f5a2..c052a50 100644
--- a/liblog/include/log/log_id.h
+++ b/liblog/include/log/log_id.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _LIBS_LOG_LOG_ID_H
-#define _LIBS_LOG_LOG_ID_H
+#pragma once
#ifdef __cplusplus
extern "C" {
@@ -62,5 +61,3 @@
#ifdef __cplusplus
}
#endif
-
-#endif /* _LIBS_LOG_LOG_ID_H */
diff --git a/liblog/include/log/log_main.h b/liblog/include/log/log_main.h
index 53653de..64791c2 100644
--- a/liblog/include/log/log_main.h
+++ b/liblog/include/log/log_main.h
@@ -14,13 +14,13 @@
* limitations under the License.
*/
-#ifndef _LIBS_LOG_LOG_MAIN_H
-#define _LIBS_LOG_LOG_MAIN_H
+#pragma once
#include <stdbool.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
#include <android/log.h>
-#include <sys/cdefs.h>
__BEGIN_DECLS
@@ -349,20 +349,6 @@
* over Android.
*/
-#ifndef __ANDROID_USE_LIBLOG_LOGGABLE_INTERFACE
-#ifndef __ANDROID_API__
-#define __ANDROID_USE_LIBLOG_LOGGABLE_INTERFACE 2
-#elif __ANDROID_API__ > 24 /* > Nougat */
-#define __ANDROID_USE_LIBLOG_LOGGABLE_INTERFACE 2
-#elif __ANDROID_API__ > 22 /* > Lollipop */
-#define __ANDROID_USE_LIBLOG_LOGGABLE_INTERFACE 1
-#else
-#define __ANDROID_USE_LIBLOG_LOGGABLE_INTERFACE 0
-#endif
-#endif
-
-#if __ANDROID_USE_LIBLOG_LOGGABLE_INTERFACE
-
/*
* Use the per-tag properties "log.tag.<tagname>" to generate a runtime
* result of non-zero to expose a log. prio is ANDROID_LOG_VERBOSE to
@@ -370,12 +356,7 @@
* any other value.
*/
int __android_log_is_loggable(int prio, const char* tag, int default_prio);
-
-#if __ANDROID_USE_LIBLOG_LOGGABLE_INTERFACE > 1
-#include <sys/types.h>
-
-int __android_log_is_loggable_len(int prio, const char* tag, size_t len,
- int default_prio);
+int __android_log_is_loggable_len(int prio, const char* tag, size_t len, int default_prio);
#if LOG_NDEBUG /* Production */
#define android_testLog(prio, tag) \
@@ -387,28 +368,8 @@
ANDROID_LOG_VERBOSE) != 0)
#endif
-#else
-
-#if LOG_NDEBUG /* Production */
-#define android_testLog(prio, tag) \
- (__android_log_is_loggable(prio, tag, ANDROID_LOG_DEBUG) != 0)
-#else
-#define android_testLog(prio, tag) \
- (__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE) != 0)
-#endif
-
-#endif
-
-#else /* __ANDROID_USE_LIBLOG_LOGGABLE_INTERFACE */
-
-#define android_testLog(prio, tag) (1)
-
-#endif /* !__ANDROID_USE_LIBLOG_LOGGABLE_INTERFACE */
-
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
__END_DECLS
-
-#endif /* _LIBS_LOG_LOG_MAIN_H */
diff --git a/liblog/include/log/log_properties.h b/liblog/include/log/log_properties.h
index 7d398a6..3a8af6d 100644
--- a/liblog/include/log/log_properties.h
+++ b/liblog/include/log/log_properties.h
@@ -7,29 +7,14 @@
** General Public License.
*/
-#ifndef _LIBS_LOG_PROPERTIES_H
-#define _LIBS_LOG_PROPERTIES_H
+#pragma once
#ifdef __cplusplus
extern "C" {
#endif
-#ifndef __ANDROID_USE_LIBLOG_IS_DEBUGGABLE_INTERFACE
-#ifndef __ANDROID_API__
-#define __ANDROID_USE_LIBLOG_IS_DEBUGGABLE_INTERFACE 1
-#elif __ANDROID_API__ > 24 /* > Nougat */
-#define __ANDROID_USE_LIBLOG_IS_DEBUGGABLE_INTERFACE 1
-#else
-#define __ANDROID_USE_LIBLOG_IS_DEBUGGABLE_INTERFACE 0
-#endif
-#endif
-
-#if __ANDROID_USE_LIBLOG_IS_DEBUGGABLE_INTERFACE
int __android_log_is_debuggable();
-#endif
#ifdef __cplusplus
}
#endif
-
-#endif /* _LIBS_LOG_PROPERTIES_H */
diff --git a/liblog/include/log/log_radio.h b/liblog/include/log/log_radio.h
index bd629fe..8b8a362 100644
--- a/liblog/include/log/log_radio.h
+++ b/liblog/include/log/log_radio.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _LIBS_LOG_LOG_RADIO_H
-#define _LIBS_LOG_LOG_RADIO_H
+#pragma once
#include <android/log.h>
#include <log/log_id.h>
@@ -140,5 +139,3 @@
LOG_TAG, __VA_ARGS__)) \
: (void)0)
#endif
-
-#endif /* _LIBS_LOG_LOG_RADIO_H */
diff --git a/liblog/include/log/log_read.h b/liblog/include/log/log_read.h
index 93b9d4e..fdef306 100644
--- a/liblog/include/log/log_read.h
+++ b/liblog/include/log/log_read.h
@@ -14,8 +14,9 @@
* limitations under the License.
*/
-#ifndef _LIBS_LOG_LOG_READ_H
-#define _LIBS_LOG_LOG_READ_H
+#pragma once
+
+#include <sys/types.h>
/* deal with possible sys/cdefs.h conflict with fcntl.h */
#ifdef __unused
@@ -47,6 +48,8 @@
* access to raw information, or parsing is an issue.
*/
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wzero-length-array"
/*
* The userspace structure for version 1 of the logger_entry ABI.
*/
@@ -59,9 +62,7 @@
int32_t tid; /* generating process's tid */
int32_t sec; /* seconds since Epoch */
int32_t nsec; /* nanoseconds */
-#ifndef __cplusplus
char msg[0]; /* the entry's payload */
-#endif
};
#endif
@@ -78,9 +79,7 @@
int32_t sec; /* seconds since Epoch */
int32_t nsec; /* nanoseconds */
uint32_t euid; /* effective UID of logger */
-#ifndef __cplusplus
char msg[0]; /* the entry's payload */
-#endif
} __attribute__((__packed__));
#endif
@@ -97,9 +96,7 @@
int32_t sec; /* seconds since Epoch */
int32_t nsec; /* nanoseconds */
uint32_t lid; /* log id of the payload */
-#ifndef __cplusplus
char msg[0]; /* the entry's payload */
-#endif
} __attribute__((__packed__));
#endif
@@ -117,11 +114,10 @@
uint32_t nsec; /* nanoseconds */
uint32_t lid; /* log id of the payload, bottom 4 bits currently */
uint32_t uid; /* generating process's uid */
-#ifndef __cplusplus
char msg[0]; /* the entry's payload */
-#endif
};
#endif
+#pragma clang diagnostic pop
/*
* The maximum size of the log entry payload that can be
@@ -197,22 +193,6 @@
};
#endif
-#ifndef __ANDROID_USE_LIBLOG_READER_INTERFACE
-#ifndef __ANDROID_API__
-#define __ANDROID_USE_LIBLOG_READER_INTERFACE 3
-#elif __ANDROID_API__ > 23 /* > Marshmallow */
-#define __ANDROID_USE_LIBLOG_READER_INTERFACE 3
-#elif __ANDROID_API__ > 22 /* > Lollipop */
-#define __ANDROID_USE_LIBLOG_READER_INTERFACE 2
-#elif __ANDROID_API__ > 19 /* > KitKat */
-#define __ANDROID_USE_LIBLOG_READER_INTERFACE 1
-#else
-#define __ANDROID_USE_LIBLOG_READER_INTERFACE 0
-#endif
-#endif
-
-#if __ANDROID_USE_LIBLOG_READER_INTERFACE
-
struct logger;
log_id_t android_logger_get_id(struct logger* logger);
@@ -225,14 +205,12 @@
struct logger_list;
-#if __ANDROID_USE_LIBLOG_READER_INTERFACE > 1
ssize_t android_logger_get_statistics(struct logger_list* logger_list,
char* buf, size_t len);
ssize_t android_logger_get_prune_list(struct logger_list* logger_list,
char* buf, size_t len);
int android_logger_set_prune_list(struct logger_list* logger_list, char* buf,
size_t len);
-#endif
#define ANDROID_LOG_RDONLY O_RDONLY
#define ANDROID_LOG_WRONLY O_WRONLY
@@ -243,13 +221,9 @@
#else
#define ANDROID_LOG_NONBLOCK O_NONBLOCK
#endif
-#if __ANDROID_USE_LIBLOG_READER_INTERFACE > 2
#define ANDROID_LOG_WRAP 0x40000000 /* Block until buffer about to wrap */
#define ANDROID_LOG_WRAP_DEFAULT_TIMEOUT 7200 /* 2 hour default */
-#endif
-#if __ANDROID_USE_LIBLOG_READER_INTERFACE > 1
#define ANDROID_LOG_PSTORE 0x80000000
-#endif
struct logger_list* android_logger_list_alloc(int mode, unsigned int tail,
pid_t pid);
@@ -268,10 +242,6 @@
unsigned int tail, pid_t pid);
#define android_logger_list_close android_logger_list_free
-#endif /* __ANDROID_USE_LIBLOG_READER_INTERFACE */
-
#ifdef __cplusplus
}
#endif
-
-#endif /* _LIBS_LOG_LOG_H */
diff --git a/liblog/include/log/log_safetynet.h b/liblog/include/log/log_safetynet.h
index 07e8c8a..d3e9b19 100644
--- a/liblog/include/log/log_safetynet.h
+++ b/liblog/include/log/log_safetynet.h
@@ -7,8 +7,7 @@
** General Public License.
*/
-#ifndef _LIBS_LOG_SAFETYNET_H
-#define _LIBS_LOG_SAFETYNET_H
+#pragma once
#include <stdint.h>
@@ -16,18 +15,6 @@
extern "C" {
#endif
-#ifndef _ANDROID_USE_LIBLOG_SAFETYNET_INTERFACE
-#ifndef __ANDROID_API__
-#define __ANDROID_USE_LIBLOG_SAFETYNET_INTERFACE 1
-#elif __ANDROID_API__ > 22 /* > Lollipop */
-#define __ANDROID_USE_LIBLOG_SAFETYNET_INTERFACE 1
-#else
-#define __ANDROID_USE_LIBLOG_SAFETYNET_INTERFACE 0
-#endif
-#endif
-
-#if __ANDROID_USE_LIBLOG_SAFETYNET_INTERFACE
-
#define android_errorWriteLog(tag, subTag) \
__android_log_error_write(tag, subTag, -1, NULL, 0)
@@ -37,10 +24,6 @@
int __android_log_error_write(int tag, const char* subTag, int32_t uid,
const char* data, uint32_t dataLen);
-#endif /* __ANDROID_USE_LIBLOG_SAFETYNET_INTERFACE */
-
#ifdef __cplusplus
}
#endif
-
-#endif /* _LIBS_LOG_SAFETYNET_H */
diff --git a/liblog/include/log/log_system.h b/liblog/include/log/log_system.h
index 3b5ae22..eaec741 100644
--- a/liblog/include/log/log_system.h
+++ b/liblog/include/log/log_system.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _LIBS_LOG_LOG_SYSTEM_H
-#define _LIBS_LOG_LOG_SYSTEM_H
+#pragma once
#include <android/log.h>
#include <log/log_id.h>
@@ -138,5 +137,3 @@
LOG_TAG, __VA_ARGS__)) \
: (void)0)
#endif
-
-#endif /* _LIBS_LOG_LOG_SYSTEM_H */
diff --git a/liblog/include/log/log_time.h b/liblog/include/log/log_time.h
index 309f5d1..09c9910 100644
--- a/liblog/include/log/log_time.h
+++ b/liblog/include/log/log_time.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _LIBS_LOG_LOG_TIME_H
-#define _LIBS_LOG_LOG_TIME_H
+#pragma once
#include <stdint.h>
#include <time.h>
@@ -34,6 +33,8 @@
#ifdef __cplusplus
+extern "C" {
+
/*
* NB: we did NOT define a copy constructor. This will result in structure
* no longer being compatible with pass-by-value which is desired
@@ -41,25 +42,19 @@
*/
struct log_time {
public:
- uint32_t tv_sec; /* good to Feb 5 2106 */
- uint32_t tv_nsec;
+ uint32_t tv_sec = 0; /* good to Feb 5 2106 */
+ uint32_t tv_nsec = 0;
static const uint32_t tv_sec_max = 0xFFFFFFFFUL;
static const uint32_t tv_nsec_max = 999999999UL;
+ static const timespec EPOCH;
- log_time(const timespec& T)
- : tv_sec(static_cast<uint32_t>(T.tv_sec)),
- tv_nsec(static_cast<uint32_t>(T.tv_nsec)) {
- }
+ log_time() {}
+ explicit log_time(const timespec& T)
+ : tv_sec(static_cast<uint32_t>(T.tv_sec)), tv_nsec(static_cast<uint32_t>(T.tv_nsec)) {}
explicit log_time(uint32_t sec, uint32_t nsec = 0)
: tv_sec(sec), tv_nsec(nsec) {
}
-#ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_
-#define __struct_log_time_private_defined
- static const timespec EPOCH;
-#endif
- log_time() {
- }
#ifdef __linux__
explicit log_time(clockid_t id) {
timespec T;
@@ -103,7 +98,6 @@
return !(*this > T);
}
-#ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_
log_time operator-=(const timespec& T);
log_time operator-(const timespec& T) const {
log_time local(*this);
@@ -114,7 +108,6 @@
log_time local(*this);
return local += T;
}
-#endif
/* log_time */
bool operator==(const log_time& T) const {
@@ -138,7 +131,6 @@
return !(*this > T);
}
-#ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_
log_time operator-=(const log_time& T);
log_time operator-(const log_time& T) const {
log_time local(*this);
@@ -149,7 +141,6 @@
log_time local(*this);
return local += T;
}
-#endif
uint64_t nsec() const {
return static_cast<uint64_t>(tv_sec) * NS_PER_SEC + tv_nsec;
@@ -163,13 +154,12 @@
tv_nsec / (NS_PER_SEC / MS_PER_SEC);
}
-#ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_
static const char default_format[];
/* Add %#q for the fraction of a second to the standard library functions */
char* strptime(const char* s, const char* format = default_format);
-#endif
} __attribute__((__packed__));
+}
#else /* __cplusplus */
@@ -181,5 +171,3 @@
#endif /* __cplusplus */
#endif /* __struct_log_time_defined */
-
-#endif /* _LIBS_LOG_LOG_TIME_H */
diff --git a/liblog/include/log/log_transport.h b/liblog/include/log/log_transport.h
index 8b02995..b48761a 100644
--- a/liblog/include/log/log_transport.h
+++ b/liblog/include/log/log_transport.h
@@ -7,8 +7,7 @@
** General Public License.
*/
-#ifndef _LIBS_LOG_TRANSPORT_H
-#define _LIBS_LOG_TRANSPORT_H
+#pragma once
#ifdef __cplusplus
extern "C" {
@@ -33,5 +32,3 @@
#ifdef __cplusplus
}
#endif
-
-#endif /* _LIBS_LOG_TRANSPORT_H */
diff --git a/liblog/include/log/logd.h b/liblog/include/log/logd.h
deleted file mode 100644
index 77400ca..0000000
--- a/liblog/include/log/logd.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#ifndef _LIBS_LOG_LOGD_H
-#define _LIBS_LOG_LOGD_H
-#include <log/log.h>
-#warning "Deprecated: do not include log/logd.h, use log/log.h instead"
-#endif /*_LIBS_LOG_LOGD_H*/
diff --git a/liblog/include/log/logger.h b/liblog/include/log/logger.h
deleted file mode 100644
index 1bf2d17..0000000
--- a/liblog/include/log/logger.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#ifndef _LIBS_LOG_LOGGER_H
-#define _LIBS_LOG_LOGGER_H
-#include <log/log.h>
-#warning "Deprecated: do not include log/logger.h, use log/log.h instead"
-#endif /*_LIBS_LOG_LOGGER_H*/
diff --git a/liblog/include/log/logprint.h b/liblog/include/log/logprint.h
index ca58bc7..8f4b187 100644
--- a/liblog/include/log/logprint.h
+++ b/liblog/include/log/logprint.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _LOGPRINT_H
-#define _LOGPRINT_H
+#pragma once
#include <pthread.h>
@@ -158,5 +157,3 @@
#ifdef __cplusplus
}
#endif
-
-#endif /*_LOGPRINT_H*/
diff --git a/liblog/include/private/android_logger.h b/liblog/include/private/android_logger.h
index b927b46..5e04148 100644
--- a/liblog/include/private/android_logger.h
+++ b/liblog/include/private/android_logger.h
@@ -16,8 +16,7 @@
/* This file is used to define the internal protocol for the Android Logger */
-#ifndef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_
-#define _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_
+#pragma once
/* Android private interfaces */
@@ -25,10 +24,8 @@
#include <stdint.h>
#include <sys/types.h>
-#if (defined(__cplusplus) && defined(_USING_LIBCXX))
-extern "C++" {
+#ifdef __cplusplus
#include <string>
-}
#endif
#include <log/log.h>
@@ -153,41 +150,6 @@
/* Retrieve the composed event buffer */
int android_log_write_list_buffer(android_log_context ctx, const char** msg);
-#ifdef __cplusplus
-#ifdef __class_android_log_event_list_defined
-#ifndef __class_android_log_event_list_private_defined
-#define __class_android_log_event_list_private_defined
-/* android_log_context C++ helpers */
-extern "C++" {
-class __android_log_event_list : public android_log_event_list {
- __android_log_event_list(const android_log_event_list&) = delete;
- void operator=(const __android_log_event_list&) = delete;
-
- public:
- explicit __android_log_event_list(int tag) : android_log_event_list(tag) {
- }
- explicit __android_log_event_list(log_msg& log_msg)
- : android_log_event_list(log_msg) {
- }
-
-#if defined(_USING_LIBCXX)
- operator std::string() {
- if (ret) return std::string("");
- const char* cp = nullptr;
- ssize_t len = android_log_write_list_buffer(ctx, &cp);
- if (len < 0) ret = len;
- if (!cp || (len <= 0)) return std::string("");
- return std::string(cp, len);
- }
-#endif
-};
-}
-#endif
-#endif
-#endif
-
#if defined(__cplusplus)
}
#endif
-
-#endif /* _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_ */
diff --git a/liblog/include_vndk/log/log_event_list.h b/liblog/include_vndk/log/log_event_list.h
index 9f74534..1f3dd37 100644
--- a/liblog/include_vndk/log/log_event_list.h
+++ b/liblog/include_vndk/log/log_event_list.h
@@ -27,8 +27,6 @@
extern "C" {
#endif
-#define __ANDROID_USE_LIBLOG_EVENT_INTERFACE 1
-
/*
* The opaque context used to manipulate lists of events.
*/
diff --git a/liblog/log_event_list.c b/liblog/log_event_list.cpp
similarity index 88%
rename from liblog/log_event_list.c
rename to liblog/log_event_list.cpp
index 14002ce..088ea94 100644
--- a/liblog/log_event_list.c
+++ b/liblog/log_event_list.cpp
@@ -29,21 +29,26 @@
#define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(int32_t))
-typedef struct {
+enum ReadWriteFlag {
+ kAndroidLoggerRead = 1,
+ kAndroidLoggerWrite = 2,
+};
+
+struct android_log_context_internal {
uint32_t tag;
- unsigned pos; /* Read/write position into buffer */
+ unsigned pos; /* Read/write position into buffer */
unsigned count[ANDROID_MAX_LIST_NEST_DEPTH + 1]; /* Number of elements */
unsigned list[ANDROID_MAX_LIST_NEST_DEPTH + 1]; /* pos for list counter */
unsigned list_nest_depth;
unsigned len; /* Length or raw buffer. */
bool overflow;
bool list_stop; /* next call decrement list_nest_depth and issue a stop */
- enum {
- kAndroidLoggerRead = 1,
- kAndroidLoggerWrite = 2,
- } read_write_flag;
+ ReadWriteFlag read_write_flag;
uint8_t storage[LOGGER_ENTRY_MAX_PAYLOAD];
-} android_log_context_internal;
+};
+
+// TODO(tomcherry): real C++ structs.
+typedef struct android_log_context_internal android_log_context_internal;
static void init_context(android_log_context_internal* context, uint32_t tag) {
size_t needed;
@@ -60,8 +65,8 @@
context->pos += needed;
}
-static void init_parser_context(android_log_context_internal* context,
- const char* msg, size_t len) {
+static void init_parser_context(android_log_context_internal* context, const char* msg,
+ size_t len) {
len = (len <= MAX_EVENT_PAYLOAD) ? len : MAX_EVENT_PAYLOAD;
context->len = len;
memcpy(context->storage, msg, len);
@@ -71,7 +76,8 @@
LIBLOG_ABI_PUBLIC android_log_context create_android_logger(uint32_t tag) {
android_log_context_internal* context;
- context = calloc(1, sizeof(android_log_context_internal));
+ context =
+ static_cast<android_log_context_internal*>(calloc(1, sizeof(android_log_context_internal)));
if (!context) {
return NULL;
}
@@ -80,12 +86,12 @@
return (android_log_context)context;
}
-LIBLOG_ABI_PUBLIC android_log_context create_android_log_parser(const char* msg,
- size_t len) {
+LIBLOG_ABI_PUBLIC android_log_context create_android_log_parser(const char* msg, size_t len) {
android_log_context_internal* context;
size_t i;
- context = calloc(1, sizeof(android_log_context_internal));
+ context =
+ static_cast<android_log_context_internal*>(calloc(1, sizeof(android_log_context_internal)));
if (!context) {
return NULL;
}
@@ -123,8 +129,8 @@
return 0;
}
-LIBLOG_ABI_PUBLIC int android_log_parser_reset(android_log_context ctx,
- const char* msg, size_t len) {
+LIBLOG_ABI_PUBLIC int android_log_parser_reset(android_log_context ctx, const char* msg,
+ size_t len) {
android_log_context_internal* context;
context = (android_log_context_internal*)ctx;
@@ -138,7 +144,6 @@
return 0;
}
-
LIBLOG_ABI_PUBLIC int android_log_write_list_begin(android_log_context ctx) {
size_t needed;
android_log_context_internal* context;
@@ -180,8 +185,7 @@
buf[3] = (val >> 24) & 0xFF;
}
-LIBLOG_ABI_PUBLIC int android_log_write_int32(android_log_context ctx,
- int32_t value) {
+LIBLOG_ABI_PUBLIC int android_log_write_int32(android_log_context ctx, int32_t value) {
size_t needed;
android_log_context_internal* context;
@@ -215,8 +219,7 @@
buf[7] = (val >> 56) & 0xFF;
}
-LIBLOG_ABI_PUBLIC int android_log_write_int64(android_log_context ctx,
- int64_t value) {
+LIBLOG_ABI_PUBLIC int android_log_write_int64(android_log_context ctx, int64_t value) {
size_t needed;
android_log_context_internal* context;
@@ -239,8 +242,7 @@
return 0;
}
-LIBLOG_ABI_PUBLIC int android_log_write_string8_len(android_log_context ctx,
- const char* value,
+LIBLOG_ABI_PUBLIC int android_log_write_string8_len(android_log_context ctx, const char* value,
size_t maxlen) {
size_t needed;
ssize_t len;
@@ -276,13 +278,11 @@
return len;
}
-LIBLOG_ABI_PUBLIC int android_log_write_string8(android_log_context ctx,
- const char* value) {
+LIBLOG_ABI_PUBLIC int android_log_write_string8(android_log_context ctx, const char* value) {
return android_log_write_string8_len(ctx, value, MAX_EVENT_PAYLOAD);
}
-LIBLOG_ABI_PUBLIC int android_log_write_float32(android_log_context ctx,
- float value) {
+LIBLOG_ABI_PUBLIC int android_log_write_float32(android_log_context ctx, float value) {
size_t needed;
uint32_t ivalue;
android_log_context_internal* context;
@@ -337,8 +337,7 @@
/*
* Logs the list of elements to the event log.
*/
-LIBLOG_ABI_PUBLIC int android_log_write_list(android_log_context ctx,
- log_id_t id) {
+LIBLOG_ABI_PUBLIC int android_log_write_list(android_log_context ctx, log_id_t id) {
android_log_context_internal* context;
const char* msg;
ssize_t len;
@@ -368,13 +367,11 @@
}
return (id == LOG_ID_EVENTS)
? __android_log_bwrite(context->tag, msg, len)
- : ((id == LOG_ID_STATS)
- ? __android_log_stats_bwrite(context->tag, msg, len)
- : __android_log_security_bwrite(context->tag, msg, len));
+ : ((id == LOG_ID_STATS) ? __android_log_stats_bwrite(context->tag, msg, len)
+ : __android_log_security_bwrite(context->tag, msg, len));
}
-LIBLOG_ABI_PRIVATE int android_log_write_list_buffer(android_log_context ctx,
- const char** buffer) {
+LIBLOG_ABI_PRIVATE int android_log_write_list_buffer(android_log_context ctx, const char** buffer) {
android_log_context_internal* context;
const char* msg;
ssize_t len;
@@ -428,8 +425,7 @@
* this and continues to call this function, the behavior is undefined
* (although it won't crash).
*/
-static android_log_list_element android_log_read_next_internal(
- android_log_context ctx, int peek) {
+static android_log_list_element android_log_read_next_internal(android_log_context ctx, int peek) {
android_log_list_element elem;
unsigned pos;
android_log_context_internal* context;
@@ -444,9 +440,9 @@
(context->count[context->list_nest_depth] >=
(MAX_EVENT_PAYLOAD / (sizeof(uint8_t) + sizeof(uint8_t))))) {
elem.type = EVENT_TYPE_UNKNOWN;
- if (context && (context->list_stop ||
- ((context->list_nest_depth <= ANDROID_MAX_LIST_NEST_DEPTH) &&
- !context->count[context->list_nest_depth]))) {
+ if (context &&
+ (context->list_stop || ((context->list_nest_depth <= ANDROID_MAX_LIST_NEST_DEPTH) &&
+ !context->count[context->list_nest_depth]))) {
elem.type = EVENT_TYPE_LIST_STOP;
}
elem.complete = true;
@@ -460,9 +456,8 @@
pos = context->pos;
if (context->list_stop) {
elem.type = EVENT_TYPE_LIST_STOP;
- elem.complete = !context->count[0] &&
- (!context->list_nest_depth ||
- ((context->list_nest_depth == 1) && !context->count[1]));
+ elem.complete = !context->count[0] && (!context->list_nest_depth ||
+ ((context->list_nest_depth == 1) && !context->count[1]));
if (!peek) {
/* Suck in superfluous stop */
if (context->storage[pos] == EVENT_TYPE_LIST_STOP) {
@@ -485,7 +480,7 @@
return elem;
}
- elem.type = context->storage[pos++];
+ elem.type = static_cast<AndroidEventLogType>(context->storage[pos++]);
switch ((int)elem.type) {
case EVENT_TYPE_FLOAT:
/* Rely on union to translate elem.data.int32 into elem.data.float32 */
@@ -598,12 +593,10 @@
}
}
-LIBLOG_ABI_PUBLIC android_log_list_element
-android_log_read_next(android_log_context ctx) {
+LIBLOG_ABI_PUBLIC android_log_list_element android_log_read_next(android_log_context ctx) {
return android_log_read_next_internal(ctx, 0);
}
-LIBLOG_ABI_PUBLIC android_log_list_element
-android_log_peek_next(android_log_context ctx) {
+LIBLOG_ABI_PUBLIC android_log_list_element android_log_peek_next(android_log_context ctx) {
return android_log_read_next_internal(ctx, 1);
}
diff --git a/liblog/log_event_write.c b/liblog/log_event_write.cpp
similarity index 89%
rename from liblog/log_event_write.c
rename to liblog/log_event_write.cpp
index 45a6f37..e644a3b 100644
--- a/liblog/log_event_write.c
+++ b/liblog/log_event_write.cpp
@@ -24,9 +24,8 @@
#define MAX_SUBTAG_LEN 32
-LIBLOG_ABI_PUBLIC int __android_log_error_write(int tag, const char* subTag,
- int32_t uid, const char* data,
- uint32_t dataLen) {
+LIBLOG_ABI_PUBLIC int __android_log_error_write(int tag, const char* subTag, int32_t uid,
+ const char* data, uint32_t dataLen) {
int ret = -EINVAL;
if (subTag && (data || !dataLen)) {
diff --git a/liblog/log_portability.h b/liblog/log_portability.h
index 88805c7..b9fb1d2 100644
--- a/liblog/log_portability.h
+++ b/liblog/log_portability.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _LIBLOG_PORTABILITY_H__
-#define _LIBLOG_PORTABILITY_H__
+#pragma once
#include <sys/cdefs.h>
#include <unistd.h>
@@ -46,7 +45,7 @@
#if defined(_WIN32)
#define LIBLOG_WEAK static /* Accept that it is totally private */
#else
-#define LIBLOG_WEAK __attribute__((weak, visibility("default")))
+#define LIBLOG_WEAK extern "C" __attribute__((weak, visibility("default")))
#endif
/* possible missing definitions in sys/cdefs.h */
@@ -62,11 +61,6 @@
#endif
#endif
-/* Unused argument. For C code only, remove symbol name for C++ */
-#ifndef __unused
-#define __unused __attribute__((__unused__))
-#endif
-
/* possible missing definitions in unistd.h */
#ifndef TEMP_FAILURE_RETRY
@@ -80,5 +74,3 @@
_rc; \
})
#endif
-
-#endif /* _LIBLOG_PORTABILITY_H__ */
diff --git a/liblog/log_ratelimit.cpp b/liblog/log_ratelimit.cpp
deleted file mode 100644
index 33770dd..0000000
--- a/liblog/log_ratelimit.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
-** Copyright 2016, 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 <errno.h>
-#include <pthread.h>
-#include <time.h>
-
-#include <log/log.h>
-
-#include "log_portability.h"
-
-// Global default if 'last' argument in __android_log_ratelimit is NULL
-static time_t g_last_clock;
-// Global above can not deal well with callers playing games with the
-// seconds argument, so we will also hold on to the maximum value
-// ever provided and use that to gain consistency. If the caller
-// provides their own 'last' argument, then they can play such games
-// of varying the 'seconds' argument to their pleasure.
-static time_t g_last_seconds;
-static const time_t last_seconds_default = 10;
-static const time_t last_seconds_max = 24 * 60 * 60; // maximum of a day
-static const time_t last_seconds_min = 2; // granularity
-// Lock to protect last_clock and last_seconds, but also 'last'
-// argument (not NULL) as supplied to __android_log_ratelimit.
-static pthread_mutex_t lock_ratelimit = PTHREAD_MUTEX_INITIALIZER;
-
-// if last is NULL, caller _must_ provide a consistent value for
-// seconds, otherwise we will take the maximum ever issued and hold
-// on to that. Preserves value of non-zero errno. Return -1 if we
-// can not acquire a lock, 0 if we are not to log a message, and 1
-// if we are ok to log a message. Caller should check > 0 for true.
-LIBLOG_ABI_PUBLIC int __android_log_ratelimit(time_t seconds, time_t* last) {
- int save_errno = errno;
-
- // Two reasons for trylock failure:
- // 1. In a signal handler. Must prevent deadlock
- // 2. Too many threads calling __android_log_ratelimit.
- // Bonus to not print if they race here because that
- // dovetails the goal of ratelimiting. One may print
- // and the others will wait their turn ...
- if (pthread_mutex_trylock(&lock_ratelimit)) {
- if (save_errno) errno = save_errno;
- return -1;
- }
-
- if (seconds == 0) {
- seconds = last_seconds_default;
- } else if (seconds < last_seconds_min) {
- seconds = last_seconds_min;
- } else if (seconds > last_seconds_max) {
- seconds = last_seconds_max;
- }
-
- if (!last) {
- if (g_last_seconds > seconds) {
- seconds = g_last_seconds;
- } else if (g_last_seconds < seconds) {
- g_last_seconds = seconds;
- }
- last = &g_last_clock;
- }
-
- time_t now = time(NULL);
- if ((now == (time_t)-1) || ((*last + seconds) > now)) {
- pthread_mutex_unlock(&lock_ratelimit);
- if (save_errno) errno = save_errno;
- return 0;
- }
- *last = now;
- pthread_mutex_unlock(&lock_ratelimit);
- if (save_errno) errno = save_errno;
- return 1;
-}
diff --git a/liblog/log_time.cpp b/liblog/log_time.cpp
index ae376be..77bb94f 100644
--- a/liblog/log_time.cpp
+++ b/liblog/log_time.cpp
@@ -137,7 +137,7 @@
LIBLOG_ABI_PRIVATE log_time log_time::operator-=(const timespec& T) {
// No concept of negative time, clamp to EPOCH
if (*this <= T) {
- return *this = EPOCH;
+ return *this = log_time(EPOCH);
}
if (this->tv_nsec < (unsigned long int)T.tv_nsec) {
@@ -165,7 +165,7 @@
LIBLOG_ABI_PRIVATE log_time log_time::operator-=(const log_time& T) {
// No concept of negative time, clamp to EPOCH
if (*this <= T) {
- return *this = EPOCH;
+ return *this = log_time(EPOCH);
}
if (this->tv_nsec < T.tv_nsec) {
diff --git a/liblog/logd_reader.c b/liblog/logd_reader.cpp
similarity index 86%
rename from liblog/logd_reader.c
rename to liblog/logd_reader.cpp
index 603ba24..05bbcbc 100644
--- a/liblog/logd_reader.c
+++ b/liblog/logd_reader.cpp
@@ -47,8 +47,7 @@
static int logdVersion(struct android_log_logger* logger,
struct android_log_transport_context* transp);
static int logdRead(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp,
- struct log_msg* log_msg);
+ struct android_log_transport_context* transp, struct log_msg* log_msg);
static int logdPoll(struct android_log_logger_list* logger_list,
struct android_log_transport_context* transp);
static void logdClose(struct android_log_logger_list* logger_list,
@@ -56,37 +55,33 @@
static int logdClear(struct android_log_logger* logger,
struct android_log_transport_context* transp);
static ssize_t logdSetSize(struct android_log_logger* logger,
- struct android_log_transport_context* transp,
- size_t size);
+ struct android_log_transport_context* transp, size_t size);
static ssize_t logdGetSize(struct android_log_logger* logger,
struct android_log_transport_context* transp);
static ssize_t logdGetReadableSize(struct android_log_logger* logger,
struct android_log_transport_context* transp);
static ssize_t logdGetPrune(struct android_log_logger_list* logger,
- struct android_log_transport_context* transp,
- char* buf, size_t len);
+ struct android_log_transport_context* transp, char* buf, size_t len);
static ssize_t logdSetPrune(struct android_log_logger_list* logger,
- struct android_log_transport_context* transp,
- char* buf, size_t len);
+ struct android_log_transport_context* transp, char* buf, size_t len);
static ssize_t logdGetStats(struct android_log_logger_list* logger,
- struct android_log_transport_context* transp,
- char* buf, size_t len);
+ struct android_log_transport_context* transp, char* buf, size_t len);
LIBLOG_HIDDEN struct android_log_transport_read logdLoggerRead = {
- .node = { &logdLoggerRead.node, &logdLoggerRead.node },
- .name = "logd",
- .available = logdAvailable,
- .version = logdVersion,
- .read = logdRead,
- .poll = logdPoll,
- .close = logdClose,
- .clear = logdClear,
- .getSize = logdGetSize,
- .setSize = logdSetSize,
- .getReadableSize = logdGetReadableSize,
- .getPrune = logdGetPrune,
- .setPrune = logdSetPrune,
- .getStats = logdGetStats,
+ .node = {&logdLoggerRead.node, &logdLoggerRead.node},
+ .name = "logd",
+ .available = logdAvailable,
+ .version = logdVersion,
+ .read = logdRead,
+ .poll = logdPoll,
+ .close = logdClose,
+ .clear = logdClear,
+ .getSize = logdGetSize,
+ .setSize = logdSetSize,
+ .getReadableSize = logdGetReadableSize,
+ .getPrune = logdGetPrune,
+ .setPrune = logdSetPrune,
+ .getStats = logdGetStats,
};
static int logdAvailable(log_id_t logId) {
@@ -109,8 +104,7 @@
#if defined(_WIN32)
-LIBLOG_WEAK int socket_local_client(const char* name, int namespaceId,
- int type) {
+LIBLOG_WEAK int socket_local_client(const char* name, int namespaceId, int type) {
errno = ENOSYS;
return -ENOSYS;
}
@@ -131,8 +125,7 @@
/* Documented in header file. */
LIBLOG_WEAK int socket_make_sockaddr_un(const char* name, int namespaceId,
- struct sockaddr_un* p_addr,
- socklen_t* alen) {
+ struct sockaddr_un* p_addr, socklen_t* alen) {
memset(p_addr, 0, sizeof(*p_addr));
size_t namelen;
@@ -158,8 +151,7 @@
namelen = strlen(name) + strlen(FILESYSTEM_SOCKET_PREFIX);
/* unix_path_max appears to be missing on linux */
- if (namelen >
- sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) {
+ if (namelen > sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) {
goto error;
}
@@ -171,8 +163,7 @@
case ANDROID_SOCKET_NAMESPACE_RESERVED:
namelen = strlen(name) + strlen(ANDROID_RESERVED_SOCKET_PREFIX);
/* unix_path_max appears to be missing on linux */
- if (namelen >
- sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) {
+ if (namelen > sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) {
goto error;
}
@@ -183,8 +174,7 @@
case ANDROID_SOCKET_NAMESPACE_FILESYSTEM:
namelen = strlen(name);
/* unix_path_max appears to be missing on linux */
- if (namelen >
- sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) {
+ if (namelen > sizeof(*p_addr) - offsetof(struct sockaddr_un, sun_path) - 1) {
goto error;
}
@@ -210,8 +200,8 @@
*
* Used by AndroidSocketImpl
*/
-LIBLOG_WEAK int socket_local_client_connect(int fd, const char* name,
- int namespaceId, int type __unused) {
+LIBLOG_WEAK int socket_local_client_connect(int fd, const char* name, int namespaceId,
+ int type __unused) {
struct sockaddr_un addr;
socklen_t alen;
int err;
@@ -236,8 +226,7 @@
* connect to peer named "name"
* returns fd or -1 on error
*/
-LIBLOG_WEAK int socket_local_client(const char* name, int namespaceId,
- int type) {
+LIBLOG_WEAK int socket_local_client(const char* name, int namespaceId, int type) {
int s;
s = socket(AF_LOCAL, type, 0);
@@ -255,14 +244,13 @@
/* End of ../libcutils/socket_local_client.c */
/* worker for sending the command to the logger */
-static ssize_t send_log_msg(struct android_log_logger* logger, const char* msg,
- char* buf, size_t buf_size) {
+static ssize_t send_log_msg(struct android_log_logger* logger, const char* msg, char* buf,
+ size_t buf_size) {
ssize_t ret;
size_t len;
char* cp;
int errno_save = 0;
- int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED,
- SOCK_STREAM);
+ int sock = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
if (sock < 0) {
return sock;
}
@@ -342,8 +330,7 @@
struct android_log_transport_context* transp __unused) {
char buf[512];
- return check_log_success(buf,
- send_log_msg(logger, "clear %d", buf, sizeof(buf)));
+ return check_log_success(buf, send_log_msg(logger, "clear %d", buf, sizeof(buf)));
}
/* returns the total size of the log's ring buffer */
@@ -364,8 +351,7 @@
}
static ssize_t logdSetSize(struct android_log_logger* logger,
- struct android_log_transport_context* transp __unused,
- size_t size) {
+ struct android_log_transport_context* transp __unused, size_t size) {
char buf[512];
snprintf(buf, sizeof(buf), "setLogSize %d %zu", logger->logId, size);
@@ -378,8 +364,7 @@
* log consumed)
*/
static ssize_t logdGetReadableSize(struct android_log_logger* logger,
- struct android_log_transport_context* transp
- __unused) {
+ struct android_log_transport_context* transp __unused) {
char buf[512];
ssize_t ret = send_log_msg(logger, "getLogSizeUsed %d", buf, sizeof(buf));
@@ -407,8 +392,8 @@
* returns statistics
*/
static ssize_t logdGetStats(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp __unused,
- char* buf, size_t len) {
+ struct android_log_transport_context* transp __unused, char* buf,
+ size_t len) {
struct android_log_logger* logger;
char* cp = buf;
size_t remaining = len;
@@ -434,14 +419,14 @@
}
static ssize_t logdGetPrune(struct android_log_logger_list* logger_list __unused,
- struct android_log_transport_context* transp __unused,
- char* buf, size_t len) {
+ struct android_log_transport_context* transp __unused, char* buf,
+ size_t len) {
return send_log_msg(NULL, "getPruneList", buf, len);
}
static ssize_t logdSetPrune(struct android_log_logger_list* logger_list __unused,
- struct android_log_transport_context* transp __unused,
- char* buf, size_t len) {
+ struct android_log_transport_context* transp __unused, char* buf,
+ size_t len) {
const char cmd[] = "setPruneList ";
const size_t cmdlen = sizeof(cmd) - 1;
@@ -455,8 +440,7 @@
return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
}
-static void caught_signal(int signum __unused) {
-}
+static void caught_signal(int signum __unused) {}
static int logdOpen(struct android_log_logger_list* logger_list,
struct android_log_transport_context* transp) {
@@ -476,12 +460,10 @@
return sock;
}
- sock = socket_local_client("logdr", ANDROID_SOCKET_NAMESPACE_RESERVED,
- SOCK_SEQPACKET);
+ sock = socket_local_client("logdr", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET);
if (sock == 0) {
/* Guarantee not file descriptor zero */
- int newsock = socket_local_client(
- "logdr", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET);
+ int newsock = socket_local_client("logdr", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET);
close(sock);
sock = newsock;
}
@@ -492,8 +474,7 @@
return sock;
}
- strcpy(buffer, (logger_list->mode & ANDROID_LOG_NONBLOCK) ? "dumpAndClose"
- : "stream");
+ strcpy(buffer, (logger_list->mode & ANDROID_LOG_NONBLOCK) ? "dumpAndClose" : "stream");
cp = buffer + strlen(buffer);
strcpy(cp, " lids");
@@ -518,14 +499,13 @@
if (logger_list->start.tv_sec || logger_list->start.tv_nsec) {
if (logger_list->mode & ANDROID_LOG_WRAP) {
// ToDo: alternate API to allow timeout to be adjusted.
- ret = snprintf(cp, remaining, " timeout=%u",
- ANDROID_LOG_WRAP_DEFAULT_TIMEOUT);
+ ret = snprintf(cp, remaining, " timeout=%u", ANDROID_LOG_WRAP_DEFAULT_TIMEOUT);
ret = min(ret, remaining);
remaining -= ret;
cp += ret;
}
- ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32,
- logger_list->start.tv_sec, logger_list->start.tv_nsec);
+ ret = snprintf(cp, remaining, " start=%" PRIu32 ".%09" PRIu32, logger_list->start.tv_sec,
+ logger_list->start.tv_nsec);
ret = min(ret, remaining);
remaining -= ret;
cp += ret;
@@ -576,8 +556,7 @@
/* Read from the selected logs */
static int logdRead(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp,
- struct log_msg* log_msg) {
+ struct android_log_transport_context* transp, struct log_msg* log_msg) {
int ret, e;
struct sigaction ignore;
struct sigaction old_sigaction;
diff --git a/liblog/logd_reader.h b/liblog/logd_reader.h
index 8ebb1ae..0bba7cf 100644
--- a/liblog/logd_reader.h
+++ b/liblog/logd_reader.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _LIBLOG_LOGD_READER_H__
-#define _LIBLOG_LOGD_READER_H__
+#pragma once
#include <unistd.h>
@@ -26,5 +25,3 @@
LIBLOG_HIDDEN ssize_t __send_log_msg(char* buf, size_t buf_size);
__END_DECLS
-
-#endif /* _LIBLOG_LOGD_READER_H__ */
diff --git a/liblog/logd_writer.c b/liblog/logd_writer.cpp
similarity index 85%
rename from liblog/logd_writer.c
rename to liblog/logd_writer.cpp
index e0e3eca..ed906b3 100644
--- a/liblog/logd_writer.c
+++ b/liblog/logd_writer.cpp
@@ -38,6 +38,7 @@
#include "config_write.h"
#include "log_portability.h"
#include "logger.h"
+#include "uio.h"
/* branchless on many architectures. */
#define min(x, y) ((y) ^ (((x) ^ (y)) & -((x) < (y))))
@@ -45,17 +46,16 @@
static int logdAvailable(log_id_t LogId);
static int logdOpen();
static void logdClose();
-static int logdWrite(log_id_t logId, struct timespec* ts, struct iovec* vec,
- size_t nr);
+static int logdWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr);
LIBLOG_HIDDEN struct android_log_transport_write logdLoggerWrite = {
- .node = { &logdLoggerWrite.node, &logdLoggerWrite.node },
- .context.sock = -EBADF,
- .name = "logd",
- .available = logdAvailable,
- .open = logdOpen,
- .close = logdClose,
- .write = logdWrite,
+ .node = {&logdLoggerWrite.node, &logdLoggerWrite.node},
+ .context.sock = -EBADF,
+ .name = "logd",
+ .available = logdAvailable,
+ .open = logdOpen,
+ .close = logdClose,
+ .write = logdWrite,
};
/* log_init_lock assumed */
@@ -64,8 +64,7 @@
i = atomic_load(&logdLoggerWrite.context.sock);
if (i < 0) {
- int sock = TEMP_FAILURE_RETRY(
- socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
+ int sock = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
if (sock < 0) {
ret = -errno;
} else {
@@ -74,15 +73,15 @@
un.sun_family = AF_UNIX;
strcpy(un.sun_path, "/dev/socket/logdw");
- if (TEMP_FAILURE_RETRY(connect(sock, (struct sockaddr*)&un,
- sizeof(struct sockaddr_un))) < 0) {
+ if (TEMP_FAILURE_RETRY(connect(sock, (struct sockaddr*)&un, sizeof(struct sockaddr_un))) <
+ 0) {
ret = -errno;
switch (ret) {
case -ENOTCONN:
case -ECONNREFUSED:
case -ENOENT:
i = atomic_exchange(&logdLoggerWrite.context.sock, ret);
- /* FALLTHRU */
+ [[fallthrough]];
default:
break;
}
@@ -124,16 +123,15 @@
return 1;
}
-static int logdWrite(log_id_t logId, struct timespec* ts, struct iovec* vec,
- size_t nr) {
+static int logdWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr) {
ssize_t ret;
int sock;
static const unsigned headerLength = 1;
struct iovec newVec[nr + headerLength];
android_log_header_t header;
size_t i, payloadSize;
- static atomic_int_fast32_t dropped;
- static atomic_int_fast32_t droppedSecurity;
+ static atomic_int dropped;
+ static atomic_int droppedSecurity;
sock = atomic_load(&logdLoggerWrite.context.sock);
if (sock < 0) switch (sock) {
@@ -181,8 +179,7 @@
newVec[0].iov_len = sizeof(header);
if (sock >= 0) {
- int32_t snapshot =
- atomic_exchange_explicit(&droppedSecurity, 0, memory_order_relaxed);
+ int32_t snapshot = atomic_exchange_explicit(&droppedSecurity, 0, memory_order_relaxed);
if (snapshot) {
android_log_event_int_t buffer;
@@ -196,14 +193,12 @@
ret = TEMP_FAILURE_RETRY(writev(sock, newVec, 2));
if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
- atomic_fetch_add_explicit(&droppedSecurity, snapshot,
- memory_order_relaxed);
+ atomic_fetch_add_explicit(&droppedSecurity, snapshot, memory_order_relaxed);
}
}
snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed);
- if (snapshot &&
- __android_log_is_loggable_len(ANDROID_LOG_INFO, "liblog",
- strlen("liblog"), ANDROID_LOG_VERBOSE)) {
+ if (snapshot && __android_log_is_loggable_len(ANDROID_LOG_INFO, "liblog", strlen("liblog"),
+ ANDROID_LOG_VERBOSE)) {
android_log_event_int_t buffer;
header.id = LOG_ID_EVENTS;
@@ -267,12 +262,11 @@
return ret;
}
- ret = TEMP_FAILURE_RETRY(
- writev(atomic_load(&logdLoggerWrite.context.sock), newVec, i));
+ ret = TEMP_FAILURE_RETRY(writev(atomic_load(&logdLoggerWrite.context.sock), newVec, i));
if (ret < 0) {
ret = -errno;
}
- /* FALLTHRU */
+ [[fallthrough]];
default:
break;
}
diff --git a/liblog/logger.h b/liblog/logger.h
index af83228..b2479d2 100644
--- a/liblog/logger.h
+++ b/liblog/logger.h
@@ -14,22 +14,21 @@
* limitations under the License.
*/
-#ifndef _LIBLOG_LOGGER_H__
-#define _LIBLOG_LOGGER_H__
+#pragma once
#include <stdatomic.h>
#include <stdbool.h>
#include <cutils/list.h>
#include <log/log.h>
-#include <log/uio.h>
#include "log_portability.h"
+#include "uio.h"
__BEGIN_DECLS
/* Union, sock or fd of zero is not allowed unless static initialized */
-union android_log_context {
+union android_log_context_union {
void* priv;
atomic_int sock;
atomic_int fd;
@@ -41,7 +40,7 @@
struct listnode node;
const char* name; /* human name to describe the transport */
unsigned logMask; /* mask cache of available() success */
- union android_log_context context; /* Initialized by static allocation */
+ union android_log_context_union context; /* Initialized by static allocation */
int (*available)(log_id_t logId); /* Does not cause resources to be taken */
int (*open)(); /* can be called multiple times, reusing current resources */
@@ -115,7 +114,7 @@
struct android_log_transport_context {
struct listnode node;
- union android_log_context context; /* zero init per-transport context */
+ union android_log_context_union context; /* zero init per-transport context */
struct android_log_logger_list* parent;
struct android_log_transport_read* transport;
@@ -161,8 +160,6 @@
LIBLOG_HIDDEN int __android_log_trylock();
LIBLOG_HIDDEN void __android_log_unlock();
-LIBLOG_HIDDEN int __android_log_transport;
+extern LIBLOG_HIDDEN int __android_log_transport;
__END_DECLS
-
-#endif /* _LIBLOG_LOGGER_H__ */
diff --git a/liblog/logger_lock.c b/liblog/logger_lock.cpp
similarity index 100%
rename from liblog/logger_lock.c
rename to liblog/logger_lock.cpp
diff --git a/liblog/logger_name.c b/liblog/logger_name.cpp
similarity index 79%
rename from liblog/logger_name.c
rename to liblog/logger_name.cpp
index 479bbfe..c6f3cb7 100644
--- a/liblog/logger_name.c
+++ b/liblog/logger_name.cpp
@@ -15,6 +15,7 @@
*/
#include <string.h>
+#include <type_traits>
#include <log/log.h>
@@ -22,7 +23,7 @@
/* In the future, we would like to make this list extensible */
static const char* LOG_NAME[LOG_ID_MAX] = {
- /* clang-format off */
+ /* clang-format off */
[LOG_ID_MAIN] = "main",
[LOG_ID_RADIO] = "radio",
[LOG_ID_EVENTS] = "events",
@@ -31,7 +32,7 @@
[LOG_ID_STATS] = "stats",
[LOG_ID_SECURITY] = "security",
[LOG_ID_KERNEL] = "kernel",
- /* clang-format on */
+ /* clang-format on */
};
LIBLOG_ABI_PUBLIC const char* android_log_id_to_name(log_id_t log_id) {
@@ -41,12 +42,15 @@
return LOG_NAME[log_id];
}
+static_assert(std::is_same<std::underlying_type<log_id_t>::type, uint32_t>::value,
+ "log_id_t must be an unsigned int");
+
LIBLOG_ABI_PUBLIC log_id_t android_name_to_log_id(const char* logName) {
const char* b;
- int ret;
+ unsigned int ret;
if (!logName) {
- return -1; /* NB: log_id_t is unsigned */
+ return static_cast<log_id_t>(0xFFFFFFFF);
}
b = strrchr(logName, '/');
if (!b) {
@@ -58,8 +62,8 @@
for (ret = LOG_ID_MIN; ret < LOG_ID_MAX; ++ret) {
const char* l = LOG_NAME[ret];
if (l && !strcmp(b, l)) {
- return ret;
+ return static_cast<log_id_t>(ret);
}
}
- return -1; /* should never happen */
+ return static_cast<log_id_t>(0xFFFFFFFF); /* should never happen */
}
diff --git a/liblog/logger_read.c b/liblog/logger_read.cpp
similarity index 76%
rename from liblog/logger_read.c
rename to liblog/logger_read.cpp
index 29ebaf7..e429c36 100644
--- a/liblog/logger_read.c
+++ b/liblog/logger_read.cpp
@@ -14,6 +14,8 @@
** limitations under the License.
*/
+#include "log/log_read.h"
+
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
@@ -34,8 +36,7 @@
/* android_logger_alloc unimplemented, no use case */
/* android_logger_free not exported */
static void android_logger_free(struct logger* logger) {
- struct android_log_logger* logger_internal =
- (struct android_log_logger*)logger;
+ struct android_log_logger* logger_internal = (struct android_log_logger*)logger;
if (!logger_internal) {
return;
@@ -71,15 +72,13 @@
__android_log_lock();
/* mini __write_to_log_initialize() to populate transports */
- if (list_empty(&__android_log_transport_read) &&
- list_empty(&__android_log_persist_read)) {
+ if (list_empty(&__android_log_transport_read) && list_empty(&__android_log_persist_read)) {
__android_log_config_read();
}
__android_log_unlock();
- node = (logger_list->mode & ANDROID_LOG_PSTORE)
- ? &__android_log_persist_read
- : &__android_log_transport_read;
+ node = (logger_list->mode & ANDROID_LOG_PSTORE) ? &__android_log_persist_read
+ : &__android_log_transport_read;
read_transport_for_each(transport, node) {
struct android_log_transport_context* transp;
@@ -92,15 +91,14 @@
if ((logId == LOG_ID_SECURITY) && (__android_log_uid() != AID_SYSTEM)) {
continue;
}
- if (transport->read &&
- (!transport->available || (transport->available(logId) >= 0))) {
+ if (transport->read && (!transport->available || (transport->available(logId) >= 0))) {
logMask |= 1 << logId;
}
}
if (!logMask) {
continue;
}
- transp = calloc(1, sizeof(*transp));
+ transp = static_cast<android_log_transport_context*>(calloc(1, sizeof(*transp)));
if (!transp) {
return -ENOMEM;
}
@@ -116,31 +114,29 @@
return 0;
}
-#define LOGGER_FUNCTION(logger, def, func, args...) \
- ssize_t ret = -EINVAL; \
- struct android_log_transport_context* transp; \
- struct android_log_logger* logger_internal = \
- (struct android_log_logger*)(logger); \
- \
- if (!logger_internal) { \
- return ret; \
- } \
- ret = init_transport_context(logger_internal->parent); \
- if (ret < 0) { \
- return ret; \
- } \
- \
- ret = (def); \
- transport_context_for_each(transp, logger_internal->parent) { \
- if ((transp->logMask & (1 << logger_internal->logId)) && \
- transp->transport && transp->transport->func) { \
- ssize_t retval = \
- (transp->transport->func)(logger_internal, transp, ##args); \
- if ((ret >= 0) || (ret == (def))) { \
- ret = retval; \
- } \
- } \
- } \
+#define LOGGER_FUNCTION(logger, def, func, args...) \
+ ssize_t ret = -EINVAL; \
+ struct android_log_transport_context* transp; \
+ struct android_log_logger* logger_internal = (struct android_log_logger*)(logger); \
+ \
+ if (!logger_internal) { \
+ return ret; \
+ } \
+ ret = init_transport_context(logger_internal->parent); \
+ if (ret < 0) { \
+ return ret; \
+ } \
+ \
+ ret = (def); \
+ transport_context_for_each(transp, logger_internal->parent) { \
+ if ((transp->logMask & (1 << logger_internal->logId)) && transp->transport && \
+ transp->transport->func) { \
+ ssize_t retval = (transp->transport->func)(logger_internal, transp, ##args); \
+ if ((ret >= 0) || (ret == (def))) { \
+ ret = retval; \
+ } \
+ } \
+ } \
return ret
LIBLOG_ABI_PUBLIC int android_logger_clear(struct logger* logger) {
@@ -152,8 +148,7 @@
LOGGER_FUNCTION(logger, -ENODEV, getSize);
}
-LIBLOG_ABI_PUBLIC int android_logger_set_log_size(struct logger* logger,
- unsigned long size) {
+LIBLOG_ABI_PUBLIC int android_logger_set_log_size(struct logger* logger, unsigned long size) {
LOGGER_FUNCTION(logger, -ENODEV, setSize, size);
}
@@ -161,8 +156,7 @@
* returns the readable size of the log's ring buffer (that is, amount of the
* log consumed)
*/
-LIBLOG_ABI_PUBLIC long android_logger_get_log_readable_size(
- struct logger* logger) {
+LIBLOG_ABI_PUBLIC long android_logger_get_log_readable_size(struct logger* logger) {
LOGGER_FUNCTION(logger, -ENODEV, getReadableSize);
}
@@ -173,51 +167,50 @@
LOGGER_FUNCTION(logger, 4, version);
}
-#define LOGGER_LIST_FUNCTION(logger_list, def, func, args...) \
- struct android_log_transport_context* transp; \
- struct android_log_logger_list* logger_list_internal = \
- (struct android_log_logger_list*)(logger_list); \
- \
- ssize_t ret = init_transport_context(logger_list_internal); \
- if (ret < 0) { \
- return ret; \
- } \
- \
- ret = (def); \
- transport_context_for_each(transp, logger_list_internal) { \
- if (transp->transport && (transp->transport->func)) { \
- ssize_t retval = \
- (transp->transport->func)(logger_list_internal, transp, ##args); \
- if ((ret >= 0) || (ret == (def))) { \
- ret = retval; \
- } \
- } \
- } \
+#define LOGGER_LIST_FUNCTION(logger_list, def, func, args...) \
+ struct android_log_transport_context* transp; \
+ struct android_log_logger_list* logger_list_internal = \
+ (struct android_log_logger_list*)(logger_list); \
+ \
+ ssize_t ret = init_transport_context(logger_list_internal); \
+ if (ret < 0) { \
+ return ret; \
+ } \
+ \
+ ret = (def); \
+ transport_context_for_each(transp, logger_list_internal) { \
+ if (transp->transport && (transp->transport->func)) { \
+ ssize_t retval = (transp->transport->func)(logger_list_internal, transp, ##args); \
+ if ((ret >= 0) || (ret == (def))) { \
+ ret = retval; \
+ } \
+ } \
+ } \
return ret
/*
* returns statistics
*/
-LIBLOG_ABI_PUBLIC ssize_t android_logger_get_statistics(
- struct logger_list* logger_list, char* buf, size_t len) {
+LIBLOG_ABI_PUBLIC ssize_t android_logger_get_statistics(struct logger_list* logger_list, char* buf,
+ size_t len) {
LOGGER_LIST_FUNCTION(logger_list, -ENODEV, getStats, buf, len);
}
-LIBLOG_ABI_PUBLIC ssize_t android_logger_get_prune_list(
- struct logger_list* logger_list, char* buf, size_t len) {
+LIBLOG_ABI_PUBLIC ssize_t android_logger_get_prune_list(struct logger_list* logger_list, char* buf,
+ size_t len) {
LOGGER_LIST_FUNCTION(logger_list, -ENODEV, getPrune, buf, len);
}
-LIBLOG_ABI_PUBLIC int android_logger_set_prune_list(
- struct logger_list* logger_list, char* buf, size_t len) {
+LIBLOG_ABI_PUBLIC int android_logger_set_prune_list(struct logger_list* logger_list, char* buf,
+ size_t len) {
LOGGER_LIST_FUNCTION(logger_list, -ENODEV, setPrune, buf, len);
}
-LIBLOG_ABI_PUBLIC struct logger_list* android_logger_list_alloc(
- int mode, unsigned int tail, pid_t pid) {
+LIBLOG_ABI_PUBLIC struct logger_list* android_logger_list_alloc(int mode, unsigned int tail,
+ pid_t pid) {
struct android_log_logger_list* logger_list;
- logger_list = calloc(1, sizeof(*logger_list));
+ logger_list = static_cast<android_log_logger_list*>(calloc(1, sizeof(*logger_list)));
if (!logger_list) {
return NULL;
}
@@ -231,11 +224,11 @@
return (struct logger_list*)logger_list;
}
-LIBLOG_ABI_PUBLIC struct logger_list* android_logger_list_alloc_time(
- int mode, log_time start, pid_t pid) {
+LIBLOG_ABI_PUBLIC struct logger_list* android_logger_list_alloc_time(int mode, log_time start,
+ pid_t pid) {
struct android_log_logger_list* logger_list;
- logger_list = calloc(1, sizeof(*logger_list));
+ logger_list = static_cast<android_log_logger_list*>(calloc(1, sizeof(*logger_list)));
if (!logger_list) {
return NULL;
}
@@ -253,8 +246,8 @@
/* android_logger_list_unregister unimplemented, no use case */
/* Open the named log and add it to the logger list */
-LIBLOG_ABI_PUBLIC struct logger* android_logger_open(
- struct logger_list* logger_list, log_id_t logId) {
+LIBLOG_ABI_PUBLIC struct logger* android_logger_open(struct logger_list* logger_list,
+ log_id_t logId) {
struct android_log_logger_list* logger_list_internal =
(struct android_log_logger_list*)logger_list;
struct android_log_logger* logger;
@@ -269,7 +262,7 @@
}
}
- logger = calloc(1, sizeof(*logger));
+ logger = static_cast<android_log_logger*>(calloc(1, sizeof(*logger)));
if (!logger) {
goto err;
}
@@ -296,8 +289,8 @@
}
/* Open the single named log and make it part of a new logger list */
-LIBLOG_ABI_PUBLIC struct logger_list* android_logger_list_open(
- log_id_t logId, int mode, unsigned int tail, pid_t pid) {
+LIBLOG_ABI_PUBLIC struct logger_list* android_logger_list_open(log_id_t logId, int mode,
+ unsigned int tail, pid_t pid) {
struct logger_list* logger_list = android_logger_list_alloc(mode, tail, pid);
if (!logger_list) {
@@ -364,8 +357,8 @@
}
/* at least one transport */
- transp = node_to_item(logger_list_internal->transport.next,
- struct android_log_transport_context, node);
+ transp = node_to_item(logger_list_internal->transport.next, struct android_log_transport_context,
+ node);
/* more than one transport? */
if (transp->node.next != &logger_list_internal->transport) {
@@ -386,11 +379,9 @@
retval = transp->ret = 0;
} else if ((logger_list_internal->mode & ANDROID_LOG_NONBLOCK) ||
!transp->transport->poll) {
- retval = android_transport_read(logger_list_internal, transp,
- &transp->logMsg);
+ retval = android_transport_read(logger_list_internal, transp, &transp->logMsg);
} else {
- int pollval =
- (*transp->transport->poll)(logger_list_internal, transp);
+ int pollval = (*transp->transport->poll)(logger_list_internal, transp);
if (pollval <= 0) {
sched_yield();
pollval = (*transp->transport->poll)(logger_list_internal, transp);
@@ -402,8 +393,7 @@
}
retval = transp->ret = pollval;
} else if (pollval > 0) {
- retval = android_transport_read(logger_list_internal, transp,
- &transp->logMsg);
+ retval = android_transport_read(logger_list_internal, transp, &transp->logMsg);
}
}
}
@@ -416,11 +406,9 @@
(oldest->logMsg.entry.nsec > transp->logMsg.entry.nsec)))) {
oldest = transp;
}
- transp = node_to_item(transp->node.next,
- struct android_log_transport_context, node);
+ transp = node_to_item(transp->node.next, struct android_log_transport_context, node);
} while (transp != node_to_item(&logger_list_internal->transport,
- struct android_log_transport_context,
- node));
+ struct android_log_transport_context, node));
if (!oldest && (logger_list_internal->mode & ANDROID_LOG_NONBLOCK)) {
return (ret < 0) ? ret : -EAGAIN;
}
@@ -434,10 +422,10 @@
ret = oldest->ret;
if (ret < oldest->logMsg.entry.hdr_size) {
// zero truncated header fields.
- memset(log_msg, 0,
- (oldest->logMsg.entry.hdr_size > sizeof(oldest->logMsg)
- ? sizeof(oldest->logMsg)
- : oldest->logMsg.entry.hdr_size));
+ memset(
+ log_msg, 0,
+ (oldest->logMsg.entry.hdr_size > sizeof(oldest->logMsg) ? sizeof(oldest->logMsg)
+ : oldest->logMsg.entry.hdr_size));
}
memcpy(log_msg, &oldest->logMsg, ret);
oldest->logMsg.entry.len = 0; /* Mark it as copied */
@@ -471,8 +459,7 @@
while (!list_empty(&logger_list_internal->logger)) {
struct listnode* node = list_head(&logger_list_internal->logger);
- struct android_log_logger* logger =
- node_to_item(node, struct android_log_logger, node);
+ struct android_log_logger* logger = node_to_item(node, struct android_log_logger, node);
android_logger_free((struct logger*)logger);
}
diff --git a/liblog/logger_write.c b/liblog/logger_write.cpp
similarity index 88%
rename from liblog/logger_write.c
rename to liblog/logger_write.cpp
index 6dcda9b..af8cb2d 100644
--- a/liblog/logger_write.c
+++ b/liblog/logger_write.cpp
@@ -33,23 +33,19 @@
#include "config_write.h"
#include "log_portability.h"
#include "logger.h"
+#include "uio.h"
#define LOG_BUF_SIZE 1024
static int __write_to_log_init(log_id_t, struct iovec* vec, size_t nr);
-static int (*write_to_log)(log_id_t, struct iovec* vec,
- size_t nr) = __write_to_log_init;
+static int (*write_to_log)(log_id_t, struct iovec* vec, size_t nr) = __write_to_log_init;
/*
* This is used by the C++ code to decide if it should write logs through
* the C code. Basically, if /dev/socket/logd is available, we're running in
* the simulator rather than a desktop tool and want to use the device.
*/
-static enum {
- kLogUninitialized,
- kLogNotAvailable,
- kLogAvailable
-} g_log_status = kLogUninitialized;
+static enum { kLogUninitialized, kLogNotAvailable, kLogAvailable } g_log_status = kLogUninitialized;
static int check_log_uid_permissions() {
#if defined(__ANDROID__)
@@ -70,7 +66,7 @@
if (num_groups <= 0) {
return -EPERM;
}
- groups = calloc(num_groups, sizeof(gid_t));
+ groups = static_cast<gid_t*>(calloc(num_groups, sizeof(gid_t)));
if (!groups) {
return -ENOMEM;
}
@@ -93,9 +89,8 @@
return 0;
}
-static void __android_log_cache_available(
- struct android_log_transport_write* node) {
- size_t i;
+static void __android_log_cache_available(struct android_log_transport_write* node) {
+ uint32_t i;
if (node->logMask) {
return;
@@ -104,13 +99,13 @@
for (i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
if (node->write && (i != LOG_ID_KERNEL) &&
((i != LOG_ID_SECURITY) || (check_log_uid_permissions() == 0)) &&
- (!node->available || ((*node->available)(i) >= 0))) {
+ (!node->available || ((*node->available)(static_cast<log_id_t>(i)) >= 0))) {
node->logMask |= 1 << i;
}
}
}
-LIBLOG_ABI_PUBLIC int __android_log_dev_available() {
+LIBLOG_ABI_PUBLIC extern "C" int __android_log_dev_available() {
struct android_log_transport_write* node;
if (list_empty(&__android_log_transport_write)) {
@@ -308,10 +303,9 @@
}
}
if (m && (m != (EventTagMap*)(uintptr_t)-1LL)) {
- tag = android_lookupEventTag_len(m, &len, get4LE(vec[0].iov_base));
+ tag = android_lookupEventTag_len(m, &len, get4LE(static_cast<uint8_t*>(vec[0].iov_base)));
}
- ret = __android_log_is_loggable_len(ANDROID_LOG_INFO, tag, len,
- ANDROID_LOG_VERBOSE);
+ ret = __android_log_is_loggable_len(ANDROID_LOG_INFO, tag, len, ANDROID_LOG_VERBOSE);
if (f) { /* local copy marked for close */
android_closeEventTagMap(f);
}
@@ -322,7 +316,7 @@
} else {
/* Validate the incoming tag, tag content can not split across iovec */
char prio = ANDROID_LOG_VERBOSE;
- const char* tag = vec[0].iov_base;
+ const char* tag = static_cast<const char*>(vec[0].iov_base);
size_t len = vec[0].iov_len;
if (!tag) {
len = 0;
@@ -408,13 +402,12 @@
return ret;
}
-LIBLOG_ABI_PUBLIC int __android_log_write(int prio, const char* tag,
- const char* msg) {
+LIBLOG_ABI_PUBLIC int __android_log_write(int prio, const char* tag, const char* msg) {
return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);
}
-LIBLOG_ABI_PUBLIC int __android_log_buf_write(int bufID, int prio,
- const char* tag, const char* msg) {
+LIBLOG_ABI_PUBLIC int __android_log_buf_write(int bufID, int prio, const char* tag,
+ const char* msg) {
struct iovec vec[3];
char tmp_tag[32];
@@ -457,7 +450,7 @@
bufID = LOG_ID_RADIO;
snprintf(tmp_tag, sizeof(tmp_tag), "use-Rlog/RLOG-%s", tag);
tag = tmp_tag;
- /* FALLTHRU */
+ [[fallthrough]];
default:
break;
}
@@ -476,11 +469,10 @@
vec[2].iov_base = (void*)msg;
vec[2].iov_len = strlen(msg) + 1;
- return write_to_log(bufID, vec, 3);
+ return write_to_log(static_cast<log_id_t>(bufID), vec, 3);
}
-LIBLOG_ABI_PUBLIC int __android_log_vprint(int prio, const char* tag,
- const char* fmt, va_list ap) {
+LIBLOG_ABI_PUBLIC int __android_log_vprint(int prio, const char* tag, const char* fmt, va_list ap) {
char buf[LOG_BUF_SIZE];
vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
@@ -488,8 +480,7 @@
return __android_log_write(prio, tag, buf);
}
-LIBLOG_ABI_PUBLIC int __android_log_print(int prio, const char* tag,
- const char* fmt, ...) {
+LIBLOG_ABI_PUBLIC int __android_log_print(int prio, const char* tag, const char* fmt, ...) {
va_list ap;
char buf[LOG_BUF_SIZE];
@@ -500,8 +491,7 @@
return __android_log_write(prio, tag, buf);
}
-LIBLOG_ABI_PUBLIC int __android_log_buf_print(int bufID, int prio,
- const char* tag, const char* fmt,
+LIBLOG_ABI_PUBLIC int __android_log_buf_print(int bufID, int prio, const char* tag, const char* fmt,
...) {
va_list ap;
char buf[LOG_BUF_SIZE];
@@ -513,8 +503,8 @@
return __android_log_buf_write(bufID, prio, tag, buf);
}
-LIBLOG_ABI_PUBLIC void __android_log_assert(const char* cond, const char* tag,
- const char* fmt, ...) {
+LIBLOG_ABI_PUBLIC void __android_log_assert(const char* cond, const char* tag, const char* fmt,
+ ...) {
char buf[LOG_BUF_SIZE];
if (fmt) {
@@ -535,18 +525,15 @@
// Log assertion failures to stderr for the benefit of "adb shell" users
// and gtests (http://b/23675822).
- struct iovec iov[2] = {
- { buf, strlen(buf) }, { (char*)"\n", 1 },
- };
- TEMP_FAILURE_RETRY(writev(2, iov, 2));
+ TEMP_FAILURE_RETRY(write(2, buf, strlen(buf)));
+ TEMP_FAILURE_RETRY(write(2, "\n", 1));
__android_log_write(ANDROID_LOG_FATAL, tag, buf);
abort(); /* abort so we have a chance to debug the situation */
/* NOTREACHED */
}
-LIBLOG_ABI_PUBLIC int __android_log_bwrite(int32_t tag, const void* payload,
- size_t len) {
+LIBLOG_ABI_PUBLIC int __android_log_bwrite(int32_t tag, const void* payload, size_t len) {
struct iovec vec[2];
vec[0].iov_base = &tag;
@@ -557,9 +544,7 @@
return write_to_log(LOG_ID_EVENTS, vec, 2);
}
-LIBLOG_ABI_PUBLIC int __android_log_stats_bwrite(int32_t tag,
- const void* payload,
- size_t len) {
+LIBLOG_ABI_PUBLIC int __android_log_stats_bwrite(int32_t tag, const void* payload, size_t len) {
struct iovec vec[2];
vec[0].iov_base = &tag;
@@ -570,9 +555,7 @@
return write_to_log(LOG_ID_STATS, vec, 2);
}
-LIBLOG_ABI_PUBLIC int __android_log_security_bwrite(int32_t tag,
- const void* payload,
- size_t len) {
+LIBLOG_ABI_PUBLIC int __android_log_security_bwrite(int32_t tag, const void* payload, size_t len) {
struct iovec vec[2];
vec[0].iov_base = &tag;
@@ -588,8 +571,8 @@
* for the general case where we're generating lists of stuff, but very
* handy if we just want to dump an integer into the log.
*/
-LIBLOG_ABI_PUBLIC int __android_log_btwrite(int32_t tag, char type,
- const void* payload, size_t len) {
+LIBLOG_ABI_PUBLIC int __android_log_btwrite(int32_t tag, char type, const void* payload,
+ size_t len) {
struct iovec vec[3];
vec[0].iov_base = &tag;
@@ -627,8 +610,7 @@
* Like __android_log_security_bwrite, but used for writing strings to the
* security log.
*/
-LIBLOG_ABI_PUBLIC int __android_log_security_bswrite(int32_t tag,
- const char* payload) {
+LIBLOG_ABI_PUBLIC int __android_log_security_bswrite(int32_t tag, const char* payload) {
struct iovec vec[4];
char type = EVENT_TYPE_STRING;
uint32_t len = strlen(payload);
@@ -695,8 +677,7 @@
write_to_log = __write_to_log_init;
/* generically we only expect these two values for write_to_log */
- } else if ((write_to_log != __write_to_log_init) &&
- (write_to_log != __write_to_log_daemon)) {
+ } else if ((write_to_log != __write_to_log_init) && (write_to_log != __write_to_log_daemon)) {
write_to_log = __write_to_log_init;
}
@@ -716,8 +697,7 @@
} else {
__android_log_transport &= LOGGER_LOGD | LOGGER_STDERR;
ret = __android_log_transport;
- if ((write_to_log != __write_to_log_init) &&
- (write_to_log != __write_to_log_daemon)) {
+ if ((write_to_log != __write_to_log_init) && (write_to_log != __write_to_log_daemon)) {
ret = -EINVAL;
}
}
diff --git a/liblog/logprint.c b/liblog/logprint.cpp
similarity index 90%
rename from liblog/logprint.c
rename to liblog/logprint.cpp
index 7937cb1..798b089 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.cpp
@@ -15,7 +15,6 @@
** limitations under the License.
*/
-#define _GNU_SOURCE /* for asprintf */
#ifndef __MINGW32__
#define HAVE_STRSEP
#endif
@@ -154,7 +153,7 @@
case ANDROID_LOG_DEFAULT:
case ANDROID_LOG_UNKNOWN:
default: return '?';
- /* clang-format on */
+ /* clang-format on */
}
}
@@ -172,16 +171,14 @@
case ANDROID_LOG_DEFAULT:
case ANDROID_LOG_UNKNOWN:
default: return ANDROID_COLOR_DEFAULT;
- /* clang-format on */
+ /* clang-format on */
}
}
-static android_LogPriority filterPriForTag(AndroidLogFormat* p_format,
- const char* tag) {
+static android_LogPriority filterPriForTag(AndroidLogFormat* p_format, const char* tag) {
FilterInfo* p_curFilter;
- for (p_curFilter = p_format->filters; p_curFilter != NULL;
- p_curFilter = p_curFilter->p_next) {
+ for (p_curFilter = p_format->filters; p_curFilter != NULL; p_curFilter = p_curFilter->p_next) {
if (0 == strcmp(tag, p_curFilter->mTag)) {
if (p_curFilter->mPri == ANDROID_LOG_DEFAULT) {
return p_format->global_pri;
@@ -198,8 +195,7 @@
* returns 1 if this log line should be printed based on its priority
* and tag, and 0 if it should not
*/
-LIBLOG_ABI_PUBLIC int android_log_shouldPrintLine(AndroidLogFormat* p_format,
- const char* tag,
+LIBLOG_ABI_PUBLIC int android_log_shouldPrintLine(AndroidLogFormat* p_format, const char* tag,
android_LogPriority pri) {
return pri >= filterPriForTag(p_format, tag);
}
@@ -207,7 +203,7 @@
LIBLOG_ABI_PUBLIC AndroidLogFormat* android_log_format_new() {
AndroidLogFormat* p_ret;
- p_ret = calloc(1, sizeof(AndroidLogFormat));
+ p_ret = static_cast<AndroidLogFormat*>(calloc(1, sizeof(AndroidLogFormat)));
p_ret->global_pri = ANDROID_LOG_VERBOSE;
p_ret->format = FORMAT_BRIEF;
@@ -302,8 +298,7 @@
/**
* Returns FORMAT_OFF on invalid string
*/
-LIBLOG_ABI_PUBLIC AndroidLogPrintFormat
-android_log_formatFromString(const char* formatString) {
+LIBLOG_ABI_PUBLIC AndroidLogPrintFormat android_log_formatFromString(const char* formatString) {
static AndroidLogPrintFormat format;
/* clang-format off */
@@ -326,7 +321,7 @@
else if (!strcmp(formatString, "monotonic")) format = FORMAT_MODIFIER_MONOTONIC;
else if (!strcmp(formatString, "uid")) format = FORMAT_MODIFIER_UID;
else if (!strcmp(formatString, "descriptive")) format = FORMAT_MODIFIER_DESCRIPT;
- /* clang-format on */
+ /* clang-format on */
#ifndef __MINGW32__
else {
@@ -344,9 +339,8 @@
*/
tzset();
if (!tzname[0] ||
- ((!strcmp(tzname[0], utc) || !strcmp(tzname[0], gmt)) /* error? */
- && strcasecmp(formatString, utc) &&
- strcasecmp(formatString, gmt))) { /* ok */
+ ((!strcmp(tzname[0], utc) || !strcmp(tzname[0], gmt)) /* error? */
+ && strcasecmp(formatString, utc) && strcasecmp(formatString, gmt))) { /* ok */
if (cp) {
setenv(tz, cp, 1);
} else {
@@ -581,7 +575,7 @@
msg[msgEnd] = '\0';
}
- entry->priority = msg[0];
+ entry->priority = static_cast<android_LogPriority>(msg[0]);
entry->tag = msg + 1;
entry->tagLen = msgStart - 1;
entry->message = msg + msgStart;
@@ -643,9 +637,8 @@
TYPE_MONOTONIC = 's'
};
-static int android_log_printBinaryEvent(const unsigned char** pEventData,
- size_t* pEventDataLen, char** pOutBuf,
- size_t* pOutBufLen, const char** fmtStr,
+static int android_log_printBinaryEvent(const unsigned char** pEventData, size_t* pEventDataLen,
+ char** pOutBuf, size_t* pOutBufLen, const char** fmtStr,
size_t* fmtLen) {
const unsigned char* eventData = *pEventData;
size_t eventDataLen = *pEventDataLen;
@@ -729,13 +722,10 @@
}
if (findChar(&cp, &len, '|') && findChar(&cp, &len, INT_MAX)) {
- static const unsigned char typeTable[] = {
- EVENT_TYPE_INT, EVENT_TYPE_LONG, EVENT_TYPE_STRING, EVENT_TYPE_LIST,
- EVENT_TYPE_FLOAT
- };
+ static const unsigned char typeTable[] = {EVENT_TYPE_INT, EVENT_TYPE_LONG, EVENT_TYPE_STRING,
+ EVENT_TYPE_LIST, EVENT_TYPE_FLOAT};
- if ((*cp >= '1') &&
- (*cp < (char)('1' + (sizeof(typeTable) / sizeof(typeTable[0])))) &&
+ if ((*cp >= '1') && (*cp < (char)('1' + (sizeof(typeTable) / sizeof(typeTable[0])))) &&
(type != typeTable[(size_t)(*cp - '1')]))
len = 0;
@@ -858,8 +848,8 @@
outBufLen--;
for (i = 0; i < count; i++) {
- result = android_log_printBinaryEvent(
- &eventData, &eventDataLen, &outBuf, &outBufLen, fmtStr, fmtLen);
+ result = android_log_printBinaryEvent(&eventData, &eventDataLen, &outBuf, &outBufLen,
+ fmtStr, fmtLen);
if (result != 0) goto bail;
if (i < (count - 1)) {
@@ -889,24 +879,21 @@
case TYPE_BYTES:
if ((lval != 0) && ((lval % 1024) == 0)) {
/* repaint with multiplier */
- static const char suffixTable[] = { 'K', 'M', 'G', 'T' };
+ static const char suffixTable[] = {'K', 'M', 'G', 'T'};
size_t idx = 0;
outBuf -= outCount;
outBufLen += outCount;
do {
lval /= 1024;
if ((lval % 1024) != 0) break;
- } while (++idx <
- ((sizeof(suffixTable) / sizeof(suffixTable[0])) - 1));
- outCount = snprintf(outBuf, outBufLen, "%" PRId64 "%cB", lval,
- suffixTable[idx]);
+ } while (++idx < ((sizeof(suffixTable) / sizeof(suffixTable[0])) - 1));
+ outCount = snprintf(outBuf, outBufLen, "%" PRId64 "%cB", lval, suffixTable[idx]);
} else {
outCount = snprintf(outBuf, outBufLen, "B");
}
break;
case TYPE_MILLISECONDS:
- if (((lval <= -1000) || (1000 <= lval)) &&
- (outBufLen || (outBuf[-1] == '0'))) {
+ if (((lval <= -1000) || (1000 <= lval)) && (outBufLen || (outBuf[-1] == '0'))) {
/* repaint as (fractional) seconds, possibly saving space */
if (outBufLen) outBuf[0] = outBuf[-1];
outBuf[-1] = outBuf[-2];
@@ -943,22 +930,19 @@
}
if (val >= minute) {
if (val >= hour) {
- outCount = snprintf(outBuf, outBufLen, "%" PRIu64 ":",
- (val / hour) % (day / hour));
+ outCount = snprintf(outBuf, outBufLen, "%" PRIu64 ":", (val / hour) % (day / hour));
if (outCount >= outBufLen) break;
outBuf += outCount;
outBufLen -= outCount;
}
outCount =
- snprintf(outBuf, outBufLen,
- (val >= hour) ? "%02" PRIu64 ":" : "%" PRIu64 ":",
+ snprintf(outBuf, outBufLen, (val >= hour) ? "%02" PRIu64 ":" : "%" PRIu64 ":",
(val / minute) % (hour / minute));
if (outCount >= outBufLen) break;
outBuf += outCount;
outBufLen -= outCount;
}
- outCount = snprintf(outBuf, outBufLen,
- (val >= minute) ? "%02" PRIu64 : "%" PRIu64 "s",
+ outCount = snprintf(outBuf, outBufLen, (val >= minute) ? "%02" PRIu64 : "%" PRIu64 "s",
val % minute);
} break;
case TYPE_ALLOCATIONS:
@@ -1015,7 +999,7 @@
*/
LIBLOG_ABI_PUBLIC int android_log_processBinaryLogBuffer(
struct logger_entry* buf, AndroidLogEntry* entry,
- const EventTagMap* map __unused, /* only on !__ANDROID__ */
+ [[maybe_unused]] const EventTagMap* map, /* only on !__ANDROID__ */
char* messageBuf, int messageBufLen) {
size_t inCount;
uint32_t tagIndex;
@@ -1100,8 +1084,8 @@
int result = 0;
if ((inCount > 0) || fmtLen) {
- result = android_log_printBinaryEvent(&eventData, &inCount, &outBuf,
- &outRemaining, &fmtStr, &fmtLen);
+ result = android_log_printBinaryEvent(&eventData, &inCount, &outBuf, &outRemaining, &fmtStr,
+ &fmtLen);
}
if ((result == 1) && fmtStr) {
/* We overflowed :-(, let's repaint the line w/o format dressings */
@@ -1112,8 +1096,7 @@
eventData += 4;
outBuf = messageBuf;
outRemaining = messageBufLen - 1;
- result = android_log_printBinaryEvent(&eventData, &inCount, &outBuf,
- &outRemaining, NULL, NULL);
+ result = android_log_printBinaryEvent(&eventData, &inCount, &outBuf, &outRemaining, NULL, NULL);
}
if (result < 0) {
fprintf(stderr, "Binary log entry conversion failed\n");
@@ -1187,8 +1170,7 @@
}
for (utf32 = 1, num_to_read = 1, mask = 0x40, to_ignore_mask = 0x80;
- num_to_read < 5 && (first_char & mask);
- num_to_read++, to_ignore_mask |= mask, mask >>= 1) {
+ num_to_read < 5 && (first_char & mask); num_to_read++, to_ignore_mask |= mask, mask >>= 1) {
if (num_to_read > len) {
return -1;
}
@@ -1226,8 +1208,7 @@
len = utf8_character_length(message, len);
if (len < 0) {
- snprintf(buf, sizeof(buf),
- ((messageLen > 1) && isdigit(message[1])) ? "\\%03o" : "\\%o",
+ snprintf(buf, sizeof(buf), ((messageLen > 1) && isdigit(message[1])) ? "\\%03o" : "\\%o",
*message & 0377);
len = 1;
} else {
@@ -1281,8 +1262,7 @@
return p;
}
-static struct timespec* sumTimespec(struct timespec* left,
- struct timespec* right) {
+static struct timespec* sumTimespec(struct timespec* left, struct timespec* right) {
left->tv_nsec += right->tv_nsec;
left->tv_sec += right->tv_sec;
if (left->tv_nsec >= (long)NS_PER_SEC) {
@@ -1292,8 +1272,7 @@
return left;
}
-static struct timespec* subTimespec(struct timespec* result,
- struct timespec* left,
+static struct timespec* subTimespec(struct timespec* result, struct timespec* left,
struct timespec* right) {
result->tv_nsec = left->tv_nsec - right->tv_nsec;
result->tv_sec = left->tv_sec - right->tv_sec;
@@ -1309,8 +1288,7 @@
}
#ifdef __ANDROID__
-static void convertMonotonic(struct timespec* result,
- const AndroidLogEntry* entry) {
+static void convertMonotonic(struct timespec* result, const AndroidLogEntry* entry) {
struct listnode* node;
struct conversionList {
struct listnode node; /* first */
@@ -1322,8 +1300,8 @@
/* If we do not have a conversion list, build one up */
if (list_empty(&convertHead)) {
bool suspended_pending = false;
- struct timespec suspended_monotonic = { 0, 0 };
- struct timespec suspended_diff = { 0, 0 };
+ struct timespec suspended_monotonic = {0, 0};
+ struct timespec suspended_diff = {0, 0};
/*
* Read dmesg for _some_ synchronization markers and insert
@@ -1413,15 +1391,14 @@
} else {
unsetenv(tz);
}
- list = calloc(1, sizeof(struct conversionList));
+ list = static_cast<conversionList*>(calloc(1, sizeof(conversionList)));
list_init(&list->node);
list->time = time;
subTimespec(&list->convert, &time, &monotonic);
list_add_tail(&convertHead, &list->node);
}
if (suspended_pending && !list_empty(&convertHead)) {
- list = node_to_item(list_tail(&convertHead), struct conversionList,
- node);
+ list = node_to_item(list_tail(&convertHead), struct conversionList, node);
if (subTimespec(&time, subTimespec(&time, &list->time, &list->convert),
&suspended_monotonic)
->tv_sec > 0) {
@@ -1434,13 +1411,13 @@
time = suspended_monotonic;
sumTimespec(&time, &convert);
/* breakpoint just before sleep */
- list = calloc(1, sizeof(struct conversionList));
+ list = static_cast<conversionList*>(calloc(1, sizeof(conversionList)));
list_init(&list->node);
list->time = time;
list->convert = convert;
list_add_tail(&convertHead, &list->node);
/* breakpoint just after sleep */
- list = calloc(1, sizeof(struct conversionList));
+ list = static_cast<conversionList*>(calloc(1, sizeof(conversionList)));
list_init(&list->node);
list->time = time;
sumTimespec(&list->time, &suspended_diff);
@@ -1453,7 +1430,7 @@
pclose(p);
}
/* last entry is our current time conversion */
- list = calloc(1, sizeof(struct conversionList));
+ list = static_cast<conversionList*>(calloc(1, sizeof(conversionList)));
list_init(&list->node);
clock_gettime(CLOCK_REALTIME, &list->time);
clock_gettime(CLOCK_MONOTONIC, &convert);
@@ -1469,7 +1446,7 @@
time = suspended_monotonic;
sumTimespec(&time, &convert);
/* breakpoint just after sleep */
- list = calloc(1, sizeof(struct conversionList));
+ list = static_cast<conversionList*>(calloc(1, sizeof(conversionList)));
list_init(&list->node);
list->time = time;
sumTimespec(&list->time, &suspended_diff);
@@ -1477,7 +1454,7 @@
sumTimespec(&list->convert, &suspended_diff);
list_add_head(&convertHead, &list->node);
/* breakpoint just before sleep */
- list = calloc(1, sizeof(struct conversionList));
+ list = static_cast<conversionList*>(calloc(1, sizeof(conversionList)));
list_init(&list->node);
list->time = time;
list->convert = convert;
@@ -1548,8 +1525,7 @@
* Returns NULL on malloc error
*/
-LIBLOG_ABI_PUBLIC char* android_log_formatLogLine(AndroidLogFormat* p_format,
- char* defaultBuffer,
+LIBLOG_ABI_PUBLIC char* android_log_formatLogLine(AndroidLogFormat* p_format, char* defaultBuffer,
size_t defaultBufferSize,
const AndroidLogEntry* entry,
size_t* p_outLength) {
@@ -1600,26 +1576,23 @@
}
if (p_format->epoch_output || p_format->monotonic_output) {
ptm = NULL;
- snprintf(timeBuf, sizeof(timeBuf),
- p_format->monotonic_output ? "%6lld" : "%19lld", (long long)now);
+ snprintf(timeBuf, sizeof(timeBuf), p_format->monotonic_output ? "%6lld" : "%19lld",
+ (long long)now);
} else {
#if !defined(_WIN32)
ptm = localtime_r(&now, &tmBuf);
#else
ptm = localtime(&now);
#endif
- strftime(timeBuf, sizeof(timeBuf),
- &"%Y-%m-%d %H:%M:%S"[p_format->year_output ? 0 : 3], ptm);
+ strftime(timeBuf, sizeof(timeBuf), &"%Y-%m-%d %H:%M:%S"[p_format->year_output ? 0 : 3], ptm);
}
len = strlen(timeBuf);
if (p_format->nsec_time_output) {
len += snprintf(timeBuf + len, sizeof(timeBuf) - len, ".%09ld", nsec);
} else if (p_format->usec_time_output) {
- len += snprintf(timeBuf + len, sizeof(timeBuf) - len, ".%06ld",
- nsec / US_PER_NSEC);
+ len += snprintf(timeBuf + len, sizeof(timeBuf) - len, ".%06ld", nsec / US_PER_NSEC);
} else {
- len += snprintf(timeBuf + len, sizeof(timeBuf) - len, ".%03ld",
- nsec / MS_PER_NSEC);
+ len += snprintf(timeBuf + len, sizeof(timeBuf) - len, ".%03ld", nsec / MS_PER_NSEC);
}
if (p_format->zone_output && ptm) {
strftime(timeBuf + len, sizeof(timeBuf) - len, " %z", ptm);
@@ -1629,8 +1602,8 @@
* Construct a buffer containing the log header and log message.
*/
if (p_format->colored_output) {
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf), "\x1B[38;5;%dm",
- colorFromPri(entry->priority));
+ prefixLen =
+ snprintf(prefixBuf, sizeof(prefixBuf), "\x1B[38;5;%dm", colorFromPri(entry->priority));
prefixLen = MIN(prefixLen, sizeof(prefixBuf));
const char suffixContents[] = "\x1B[0m";
@@ -1649,8 +1622,7 @@
#if !defined(__MINGW32__)
#if (FAKE_LOG_DEVICE == 0)
#ifndef __BIONIC__
-#warning \
- "This code assumes that getpwuid is thread safe, only true with Bionic!"
+#warning "This code assumes that getpwuid is thread safe, only true with Bionic!"
#endif
#endif
struct passwd* pwd = getpwuid(entry->uid);
@@ -1669,21 +1641,21 @@
switch (p_format->format) {
case FORMAT_TAG:
- len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
- "%c/%-8.*s: ", priChar, (int)entry->tagLen, entry->tag);
+ len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen, "%c/%-8.*s: ", priChar,
+ (int)entry->tagLen, entry->tag);
strcpy(suffixBuf + suffixLen, "\n");
++suffixLen;
break;
case FORMAT_PROCESS:
- len = snprintf(suffixBuf + suffixLen, sizeof(suffixBuf) - suffixLen,
- " (%.*s)\n", (int)entry->tagLen, entry->tag);
+ len = snprintf(suffixBuf + suffixLen, sizeof(suffixBuf) - suffixLen, " (%.*s)\n",
+ (int)entry->tagLen, entry->tag);
suffixLen += MIN(len, sizeof(suffixBuf) - suffixLen);
- len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
- "%c(%s%5d) ", priChar, uid, entry->pid);
+ len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen, "%c(%s%5d) ", priChar,
+ uid, entry->pid);
break;
case FORMAT_THREAD:
- len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
- "%c(%s%5d:%5d) ", priChar, uid, entry->pid, entry->tid);
+ len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen, "%c(%s%5d:%5d) ",
+ priChar, uid, entry->pid, entry->tid);
strcpy(suffixBuf + suffixLen, "\n");
++suffixLen;
break;
@@ -1695,8 +1667,8 @@
break;
case FORMAT_TIME:
len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
- "%s %c/%-8.*s(%s%5d): ", timeBuf, priChar,
- (int)entry->tagLen, entry->tag, uid, entry->pid);
+ "%s %c/%-8.*s(%s%5d): ", timeBuf, priChar, (int)entry->tagLen, entry->tag, uid,
+ entry->pid);
strcpy(suffixBuf + suffixLen, "\n");
++suffixLen;
break;
@@ -1706,24 +1678,24 @@
*ret = ' ';
}
len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
- "%s %s%5d %5d %c %-8.*s: ", timeBuf, uid, entry->pid,
- entry->tid, priChar, (int)entry->tagLen, entry->tag);
+ "%s %s%5d %5d %c %-8.*s: ", timeBuf, uid, entry->pid, entry->tid, priChar,
+ (int)entry->tagLen, entry->tag);
strcpy(suffixBuf + suffixLen, "\n");
++suffixLen;
break;
case FORMAT_LONG:
len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
- "[ %s %s%5d:%5d %c/%-8.*s ]\n", timeBuf, uid, entry->pid,
- entry->tid, priChar, (int)entry->tagLen, entry->tag);
+ "[ %s %s%5d:%5d %c/%-8.*s ]\n", timeBuf, uid, entry->pid, entry->tid, priChar,
+ (int)entry->tagLen, entry->tag);
strcpy(suffixBuf + suffixLen, "\n\n");
suffixLen += 2;
prefixSuffixIsHeaderFooter = 1;
break;
case FORMAT_BRIEF:
default:
- len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
- "%c/%-8.*s(%s%5d): ", priChar, (int)entry->tagLen,
- entry->tag, uid, entry->pid);
+ len =
+ snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
+ "%c/%-8.*s(%s%5d): ", priChar, (int)entry->tagLen, entry->tag, uid, entry->pid);
strcpy(suffixBuf + suffixLen, "\n");
++suffixLen;
break;
@@ -1847,16 +1819,15 @@
* Returns count bytes written
*/
-LIBLOG_ABI_PUBLIC int android_log_printLogLine(AndroidLogFormat* p_format,
- int fd,
+LIBLOG_ABI_PUBLIC int android_log_printLogLine(AndroidLogFormat* p_format, int fd,
const AndroidLogEntry* entry) {
int ret;
char defaultBuffer[512];
char* outBuffer = NULL;
size_t totalLen;
- outBuffer = android_log_formatLogLine(
- p_format, defaultBuffer, sizeof(defaultBuffer), entry, &totalLen);
+ outBuffer =
+ android_log_formatLogLine(p_format, defaultBuffer, sizeof(defaultBuffer), entry, &totalLen);
if (!outBuffer) return -1;
diff --git a/liblog/pmsg_reader.c b/liblog/pmsg_reader.cpp
similarity index 84%
rename from liblog/pmsg_reader.c
rename to liblog/pmsg_reader.cpp
index bf0e4fe..7bc6e4a 100644
--- a/liblog/pmsg_reader.c
+++ b/liblog/pmsg_reader.cpp
@@ -32,28 +32,27 @@
static int pmsgVersion(struct android_log_logger* logger,
struct android_log_transport_context* transp);
static int pmsgRead(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp,
- struct log_msg* log_msg);
+ struct android_log_transport_context* transp, struct log_msg* log_msg);
static void pmsgClose(struct android_log_logger_list* logger_list,
struct android_log_transport_context* transp);
static int pmsgClear(struct android_log_logger* logger,
struct android_log_transport_context* transp);
LIBLOG_HIDDEN struct android_log_transport_read pmsgLoggerRead = {
- .node = { &pmsgLoggerRead.node, &pmsgLoggerRead.node },
- .name = "pmsg",
- .available = pmsgAvailable,
- .version = pmsgVersion,
- .read = pmsgRead,
- .poll = NULL,
- .close = pmsgClose,
- .clear = pmsgClear,
- .setSize = NULL,
- .getSize = NULL,
- .getReadableSize = NULL,
- .getPrune = NULL,
- .setPrune = NULL,
- .getStats = NULL,
+ .node = {&pmsgLoggerRead.node, &pmsgLoggerRead.node},
+ .name = "pmsg",
+ .available = pmsgAvailable,
+ .version = pmsgVersion,
+ .read = pmsgRead,
+ .poll = NULL,
+ .close = pmsgClose,
+ .clear = pmsgClear,
+ .setSize = NULL,
+ .getSize = NULL,
+ .getReadableSize = NULL,
+ .getPrune = NULL,
+ .setPrune = NULL,
+ .getStats = NULL,
};
static int pmsgAvailable(log_id_t logId) {
@@ -68,8 +67,7 @@
/* 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);
+ return (uid == AID_SYSTEM) || (uid == AID_LOG) || (uid == AID_ROOT) || (uid == AID_LOGD);
}
static uid_t get_best_effective_uid() {
@@ -130,8 +128,7 @@
}
static int pmsgRead(struct android_log_logger_list* logger_list,
- struct android_log_transport_context* transp,
- struct log_msg* log_msg) {
+ struct android_log_transport_context* transp, struct log_msg* log_msg) {
ssize_t ret;
off_t current, next;
uid_t uid;
@@ -174,8 +171,7 @@
if (fd <= 0) {
return -EBADF;
}
- ret = TEMP_FAILURE_RETRY(
- read(fd, &buf.p.magic + preread_count, sizeof(buf) - preread_count));
+ ret = TEMP_FAILURE_RETRY(read(fd, &buf.p.magic + preread_count, sizeof(buf) - preread_count));
if (ret < 0) {
return -errno;
}
@@ -185,11 +181,10 @@
return preread_count ? -EIO : -EAGAIN;
}
if ((buf.p.magic != LOGGER_MAGIC) || (buf.p.len <= sizeof(buf)) ||
- (buf.p.len > (sizeof(buf) + LOGGER_ENTRY_MAX_PAYLOAD)) ||
- (buf.l.id >= LOG_ID_MAX) || (buf.l.realtime.tv_nsec >= NS_PER_SEC) ||
+ (buf.p.len > (sizeof(buf) + LOGGER_ENTRY_MAX_PAYLOAD)) || (buf.l.id >= LOG_ID_MAX) ||
+ (buf.l.realtime.tv_nsec >= NS_PER_SEC) ||
((buf.l.id != LOG_ID_EVENTS) && (buf.l.id != LOG_ID_SECURITY) &&
- ((buf.prio == ANDROID_LOG_UNKNOWN) ||
- (buf.prio == ANDROID_LOG_DEFAULT) ||
+ ((buf.prio == ANDROID_LOG_UNKNOWN) || (buf.prio == ANDROID_LOG_DEFAULT) ||
(buf.prio >= ANDROID_LOG_SILENT)))) {
do {
memmove(&buf.p.magic, &buf.p.magic + 1, --preread_count);
@@ -213,8 +208,7 @@
if (fd <= 0) {
return -EBADF;
}
- ret = TEMP_FAILURE_RETRY(
- read(fd, msg + sizeof(buf.prio), buf.p.len - sizeof(buf)));
+ ret = TEMP_FAILURE_RETRY(read(fd, msg + sizeof(buf.prio), buf.p.len - sizeof(buf)));
if (ret < 0) {
return -errno;
}
@@ -250,8 +244,7 @@
if (fd <= 0) {
return -EBADF;
}
- next = TEMP_FAILURE_RETRY(
- lseek(fd, (off_t)(buf.p.len - sizeof(buf)), SEEK_CUR));
+ next = TEMP_FAILURE_RETRY(lseek(fd, (off_t)(buf.p.len - sizeof(buf)), SEEK_CUR));
if (next < 0) {
return -errno;
}
@@ -277,9 +270,10 @@
return result;
}
-LIBLOG_ABI_PRIVATE ssize_t
-__android_log_pmsg_file_read(log_id_t logId, char prio, const char* prefix,
- __android_log_pmsg_file_read_fn fn, void* arg) {
+LIBLOG_ABI_PRIVATE ssize_t __android_log_pmsg_file_read(log_id_t logId, char prio,
+ const char* prefix,
+ __android_log_pmsg_file_read_fn fn,
+ void* arg) {
ssize_t ret;
struct android_log_logger_list logger_list;
struct android_log_transport_context transp;
@@ -312,14 +306,12 @@
memset(&logger_list, 0, sizeof(logger_list));
memset(&transp, 0, sizeof(transp));
- logger_list.mode =
- ANDROID_LOG_PSTORE | ANDROID_LOG_NONBLOCK | ANDROID_LOG_RDONLY;
+ logger_list.mode = ANDROID_LOG_PSTORE | ANDROID_LOG_NONBLOCK | ANDROID_LOG_RDONLY;
transp.logMask = (unsigned)-1;
if (logId != LOG_ID_ANY) {
transp.logMask = (1 << logId);
}
- transp.logMask &=
- ~((1 << LOG_ID_KERNEL) | (1 << LOG_ID_EVENTS) | (1 << LOG_ID_SECURITY));
+ transp.logMask &= ~((1 << LOG_ID_KERNEL) | (1 << LOG_ID_EVENTS) | (1 << LOG_ID_SECURITY));
if (!transp.logMask) {
return -EINVAL;
}
@@ -346,15 +338,13 @@
/* Read the file content */
while (pmsgRead(&logger_list, &transp, &transp.logMsg) > 0) {
- char* cp;
- size_t hdr_size = transp.logMsg.entry.hdr_size
- ? transp.logMsg.entry.hdr_size
- : sizeof(transp.logMsg.entry_v1);
+ const char* cp;
+ size_t hdr_size = transp.logMsg.entry.hdr_size ? transp.logMsg.entry.hdr_size
+ : sizeof(transp.logMsg.entry_v1);
char* msg = (char*)&transp.logMsg + hdr_size;
- char* split = NULL;
+ const char* split = NULL;
- if ((hdr_size < sizeof(transp.logMsg.entry_v1)) ||
- (hdr_size > sizeof(transp.logMsg.entry))) {
+ if ((hdr_size < sizeof(transp.logMsg.entry_v1)) || (hdr_size > sizeof(transp.logMsg.entry))) {
continue;
}
/* Check for invalid sequence number */
@@ -366,8 +356,7 @@
/* Determine if it has <dirbase>:<filebase> format for tag */
len = transp.logMsg.entry.len - sizeof(prio);
- for (cp = msg + sizeof(prio); *cp && isprint(*cp) && !isspace(*cp) && --len;
- ++cp) {
+ for (cp = msg + sizeof(prio); *cp && isprint(*cp) && !isspace(*cp) && --len; ++cp) {
if (*cp == ':') {
if (split) {
break;
@@ -395,13 +384,12 @@
continue;
}
offset = split - prefix;
- if ((msg[offset + sizeof(prio)] != ':') ||
- strncmp(msg + sizeof(prio), prefix, offset)) {
+ if ((msg[offset + sizeof(prio)] != ':') || strncmp(msg + sizeof(prio), prefix, offset)) {
continue;
}
++offset;
- if ((prefix_len > offset) && strncmp(&msg[offset + sizeof(prio)],
- split + 1, prefix_len - offset)) {
+ if ((prefix_len > offset) &&
+ strncmp(&msg[offset + sizeof(prio)], split + 1, prefix_len - offset)) {
continue;
}
}
@@ -413,8 +401,8 @@
/* check if there is an existing entry */
list_for_each(node, &name_list) {
names = node_to_item(node, struct names, node);
- if (!strcmp(names->name, msg + sizeof(prio)) &&
- (names->id == transp.logMsg.entry.lid) && (names->prio == *msg)) {
+ if (!strcmp(names->name, msg + sizeof(prio)) && (names->id == transp.logMsg.entry.lid) &&
+ (names->prio == *msg)) {
break;
}
}
@@ -425,13 +413,13 @@
unsigned long long nl;
len = strlen(msg + sizeof(prio)) + 1;
- names = calloc(1, sizeof(*names) + len);
+ names = static_cast<struct names*>(calloc(1, sizeof(*names) + len));
if (!names) {
ret = -ENOMEM;
break;
}
strcpy(names->name, msg + sizeof(prio));
- names->id = transp.logMsg.entry.lid;
+ names->id = static_cast<log_id_t>(transp.logMsg.entry.lid);
names->prio = *msg;
list_init(&names->content);
/*
@@ -491,19 +479,17 @@
}
/* Add content */
- content =
- calloc(1, sizeof(content->node) + hdr_size + transp.logMsg.entry.len);
+ content = static_cast<struct content*>(
+ calloc(1, sizeof(content->node) + hdr_size + transp.logMsg.entry.len));
if (!content) {
ret = -ENOMEM;
break;
}
- memcpy(&content->entry, &transp.logMsg.entry,
- hdr_size + transp.logMsg.entry.len);
+ memcpy(&content->entry, &transp.logMsg.entry, hdr_size + transp.logMsg.entry.len);
/* Insert in sequence number sorted order, to ease reconstruction */
list_for_each_reverse(node, &names->content) {
- if ((node_to_item(node, struct content, node))->entry.nsec <
- transp.logMsg.entry.nsec) {
+ if ((node_to_item(node, struct content, node))->entry.nsec < transp.logMsg.entry.nsec) {
break;
}
}
@@ -536,7 +522,7 @@
}
if (!buf) {
- buf = malloc(sizeof(char));
+ buf = static_cast<char*>(malloc(sizeof(char)));
if (!buf) {
ret = -ENOMEM;
list_remove(content_node);
@@ -549,7 +535,7 @@
/* Missing sequence numbers */
while (sequence < content->entry.nsec) {
/* plus space for enforced nul */
- buf = realloc_or_free(buf, len + sizeof(char) + sizeof(char));
+ buf = static_cast<char*>(realloc_or_free(buf, len + sizeof(char) + sizeof(char)));
if (!buf) {
break;
}
@@ -564,16 +550,14 @@
continue;
}
/* plus space for enforced nul */
- buf = realloc_or_free(buf, len + add_len + sizeof(char));
+ buf = static_cast<char*>(realloc_or_free(buf, len + add_len + sizeof(char)));
if (!buf) {
ret = -ENOMEM;
list_remove(content_node);
free(content);
continue;
}
- memcpy(buf + len,
- (char*)&content->entry + content->entry.hdr_size + tag_len +
- sizeof(prio),
+ memcpy(buf + len, (char*)&content->entry + content->entry.hdr_size + tag_len + sizeof(prio),
add_len);
len += add_len;
buf[len] = '\0'; /* enforce trailing hidden nul */
diff --git a/liblog/pmsg_writer.c b/liblog/pmsg_writer.cpp
similarity index 88%
rename from liblog/pmsg_writer.c
rename to liblog/pmsg_writer.cpp
index dc42856..b2fc6d0 100644
--- a/liblog/pmsg_writer.c
+++ b/liblog/pmsg_writer.cpp
@@ -33,21 +33,21 @@
#include "config_write.h"
#include "log_portability.h"
#include "logger.h"
+#include "uio.h"
static int pmsgOpen();
static void pmsgClose();
static int pmsgAvailable(log_id_t logId);
-static int pmsgWrite(log_id_t logId, struct timespec* ts, struct iovec* vec,
- size_t nr);
+static int pmsgWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr);
LIBLOG_HIDDEN struct android_log_transport_write pmsgLoggerWrite = {
- .node = { &pmsgLoggerWrite.node, &pmsgLoggerWrite.node },
- .context.fd = -1,
- .name = "pmsg",
- .available = pmsgAvailable,
- .open = pmsgOpen,
- .close = pmsgClose,
- .write = pmsgWrite,
+ .node = {&pmsgLoggerWrite.node, &pmsgLoggerWrite.node},
+ .context.fd = -1,
+ .name = "pmsg",
+ .available = pmsgAvailable,
+ .open = pmsgOpen,
+ .close = pmsgClose,
+ .write = pmsgWrite,
};
static int pmsgOpen() {
@@ -76,8 +76,7 @@
if (logId > LOG_ID_SECURITY) {
return -EINVAL;
}
- if ((logId != LOG_ID_SECURITY) && (logId != LOG_ID_EVENTS) &&
- !__android_log_is_debuggable()) {
+ if ((logId != LOG_ID_SECURITY) && (logId != LOG_ID_EVENTS) && !__android_log_is_debuggable()) {
return -EINVAL;
}
if (atomic_load(&pmsgLoggerWrite.context.fd) < 0) {
@@ -96,8 +95,7 @@
return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
}
-static int pmsgWrite(log_id_t logId, struct timespec* ts, struct iovec* vec,
- size_t nr) {
+static int pmsgWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr) {
static const unsigned headerLength = 2;
struct iovec newVec[nr + headerLength];
android_log_header_t header;
@@ -110,7 +108,7 @@
return -EINVAL;
}
- if (SNET_EVENT_LOG_TAG != get4LE(vec[0].iov_base)) {
+ if (SNET_EVENT_LOG_TAG != get4LE(static_cast<uint8_t*>(vec[0].iov_base))) {
return -EPERM;
}
}
@@ -169,8 +167,7 @@
}
pmsgHeader.len += payloadSize;
- ret = TEMP_FAILURE_RETRY(
- writev(atomic_load(&pmsgLoggerWrite.context.fd), newVec, i));
+ ret = TEMP_FAILURE_RETRY(writev(atomic_load(&pmsgLoggerWrite.context.fd), newVec, i));
if (ret < 0) {
ret = errno ? -errno : -ENOTCONN;
}
@@ -203,10 +200,8 @@
}
/* Write a buffer as filename references (tag = <basedir>:<basename>) */
-LIBLOG_ABI_PRIVATE ssize_t __android_log_pmsg_file_write(log_id_t logId,
- char prio,
- const char* filename,
- const char* buf,
+LIBLOG_ABI_PRIVATE ssize_t __android_log_pmsg_file_write(log_id_t logId, char prio,
+ const char* filename, const char* buf,
size_t len) {
bool weOpened;
size_t length, packet_len;
@@ -249,13 +244,11 @@
vec[1].iov_len = length;
weOpened = false;
- for (ts.tv_nsec = 0, length = len; length;
- ts.tv_nsec += ANDROID_LOG_PMSG_FILE_SEQUENCE) {
+ for (ts.tv_nsec = 0, length = len; length; ts.tv_nsec += ANDROID_LOG_PMSG_FILE_SEQUENCE) {
ssize_t ret;
size_t transfer;
- if ((ts.tv_nsec / ANDROID_LOG_PMSG_FILE_SEQUENCE) >=
- ANDROID_LOG_PMSG_FILE_MAX_SEQUENCE) {
+ if ((ts.tv_nsec / ANDROID_LOG_PMSG_FILE_SEQUENCE) >= ANDROID_LOG_PMSG_FILE_MAX_SEQUENCE) {
len -= length;
break;
}
diff --git a/liblog/properties.c b/liblog/properties.cpp
similarity index 86%
rename from liblog/properties.c
rename to liblog/properties.cpp
index 11be827..764877e 100644
--- a/liblog/properties.c
+++ b/liblog/properties.cpp
@@ -14,9 +14,10 @@
** limitations under the License.
*/
+#include <log/log_properties.h>
+
#include <ctype.h>
#include <pthread.h>
-#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
@@ -160,11 +161,11 @@
}
if (!last_tag || !last_tag[0]) {
if (!last_tag) {
- last_tag = calloc(1, len + 1);
+ last_tag = static_cast<char*>(calloc(1, len + 1));
last_tag_len = 0;
if (last_tag) last_tag_len = len + 1;
} else if (len >= last_tag_len) {
- last_tag = realloc(last_tag, len + 1);
+ last_tag = static_cast<char*>(realloc(last_tag, len + 1));
last_tag_len = 0;
if (last_tag) last_tag_len = len + 1;
}
@@ -258,22 +259,19 @@
case 'A': return ANDROID_LOG_FATAL;
case BOOLEAN_FALSE: /* FALLTHRU */ /* Not Officially supported */
case 'S': return -1; /* ANDROID_LOG_SUPPRESS */
- /* clang-format on */
+ /* clang-format on */
}
return default_prio;
}
-LIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio, const char* tag,
- size_t len,
+LIBLOG_ABI_PUBLIC int __android_log_is_loggable_len(int prio, const char* tag, size_t len,
int default_prio) {
int logLevel = __android_log_level(tag, len, default_prio);
return logLevel >= 0 && prio >= logLevel;
}
-LIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio, const char* tag,
- int default_prio) {
- int logLevel =
- __android_log_level(tag, (tag && *tag) ? strlen(tag) : 0, default_prio);
+LIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio, const char* tag, int default_prio) {
+ int logLevel = __android_log_level(tag, (tag && *tag) ? strlen(tag) : 0, default_prio);
return logLevel >= 0 && prio >= logLevel;
}
@@ -286,7 +284,7 @@
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, -1 }, '\0' };
+ struct cache_char temp_cache = {{NULL, 0xFFFFFFFF}, '\0'};
refresh_cache(&temp_cache, key);
ret = temp_cache.c == '1';
} else {
@@ -332,8 +330,7 @@
return self->evaluate(self);
}
- change_detected = check_cache(&self->cache_persist.cache) ||
- check_cache(&self->cache_ro.cache);
+ 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;
@@ -365,15 +362,12 @@
* to handle developer requirements.
*/
LIBLOG_ABI_PUBLIC clockid_t android_log_clockid() {
- static struct cache2_char clockid = {
- PTHREAD_MUTEX_INITIALIZER, 0,
- "persist.logd.timestamp", { { NULL, -1 }, '\0' },
- "ro.logd.timestamp", { { NULL, -1 }, '\0' },
- evaluate_persist_ro
- };
+ static struct cache2_char clockid = {PTHREAD_MUTEX_INITIALIZER, 0,
+ "persist.logd.timestamp", {{NULL, 0xFFFFFFFF}, '\0'},
+ "ro.logd.timestamp", {{NULL, 0xFFFFFFFF}, '\0'},
+ evaluate_persist_ro};
- return (tolower(do_cache2_char(&clockid)) == 'm') ? CLOCK_MONOTONIC
- : CLOCK_REALTIME;
+ return (tolower(do_cache2_char(&clockid)) == 'm') ? CLOCK_MONOTONIC : CLOCK_REALTIME;
}
/*
@@ -388,11 +382,10 @@
LIBLOG_ABI_PUBLIC int __android_log_security() {
static struct cache2_char security = {
- PTHREAD_MUTEX_INITIALIZER, 0,
- "persist.logd.security", { { NULL, -1 }, BOOLEAN_FALSE },
- "ro.device_owner", { { NULL, -1 }, BOOLEAN_FALSE },
- evaluate_security
- };
+ PTHREAD_MUTEX_INITIALIZER, 0,
+ "persist.logd.security", {{NULL, 0xFFFFFFFF}, BOOLEAN_FALSE},
+ "ro.device_owner", {{NULL, 0xFFFFFFFF}, BOOLEAN_FALSE},
+ evaluate_security};
return do_cache2_char(&security);
}
@@ -423,8 +416,7 @@
char property[PROP_VALUE_MAX];
};
-static void refresh_cache_property(struct cache_property* cache,
- const char* key) {
+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) {
@@ -436,19 +428,18 @@
}
/* get boolean with the logger twist that supports eng adjustments */
-LIBLOG_ABI_PRIVATE bool __android_logger_property_get_bool(const char* key,
- int flag) {
- struct cache_property property = { { NULL, -1 }, { 0 } };
+LIBLOG_ABI_PRIVATE 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 = -1;
+ property.cache.serial = 0xFFFFFFFF;
snprintf(newkey, sizeof(newkey), "persist.%s", key);
refresh_cache_property(&property, newkey);
property.cache.pinfo = NULL;
- property.cache.serial = -1;
+ property.cache.serial = 0xFFFFFFFF;
}
refresh_cache_property(&property, key);
@@ -477,8 +468,7 @@
}
if ((flag & BOOL_DEFAULT_FLAG_SVELTE) &&
- __android_logger_property_get_bool("ro.config.low_ram",
- BOOL_DEFAULT_FALSE)) {
+ __android_logger_property_get_bool("ro.config.low_ram", BOOL_DEFAULT_FALSE)) {
return false;
}
if ((flag & BOOL_DEFAULT_FLAG_ENG) && !__android_log_is_debuggable()) {
@@ -531,8 +521,7 @@
unsigned long (*const evaluate)(const struct cache2_property_size* self);
};
-static inline unsigned long do_cache2_property_size(
- 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;
@@ -542,8 +531,7 @@
return self->evaluate(self);
}
- change_detected = check_cache(&self->cache_persist.cache) ||
- check_cache(&self->cache_ro.cache);
+ 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;
@@ -560,8 +548,7 @@
return v;
}
-static unsigned long property_get_size_from_cache(
- const struct cache_property* cache) {
+static unsigned long property_get_size_from_cache(const struct cache_property* cache) {
char* cp;
unsigned long value = strtoul(cache->property, &cp, 10);
@@ -569,11 +556,11 @@
case 'm':
case 'M':
value *= 1024;
- /* FALLTHRU */
+ [[fallthrough]];
case 'k':
case 'K':
value *= 1024;
- /* FALLTHRU */
+ [[fallthrough]];
case '\0':
break;
@@ -588,8 +575,7 @@
return value;
}
-static unsigned long evaluate_property_get_size(
- const struct cache2_property_size* self) {
+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;
@@ -601,37 +587,35 @@
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 */
+ /* clang-format off */
PTHREAD_MUTEX_INITIALIZER, 0,
- global_tunable, { { NULL, -1 }, {} },
- global_default, { { NULL, -1 }, {} },
+ global_tunable, { { NULL, 0xFFFFFFFF }, {} },
+ global_default, { { NULL, 0xFFFFFFFF }, {} },
evaluate_property_get_size
- /* clang-format on */
+ /* 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 */
+ /* clang-format off */
PTHREAD_MUTEX_INITIALIZER, 0,
- key_persist, { { NULL, -1 }, {} },
- key_ro, { { NULL, -1 }, {} },
+ key_persist, { { NULL, 0xFFFFFFFF }, {} },
+ key_ro, { { NULL, 0xFFFFFFFF }, {} },
evaluate_property_get_size
- /* clang-format on */
+ /* 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)
+ 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));
+ 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) {
diff --git a/liblog/stderr_write.c b/liblog/stderr_write.cpp
similarity index 90%
rename from liblog/stderr_write.c
rename to liblog/stderr_write.cpp
index dbe5309..28195aa 100644
--- a/liblog/stderr_write.c
+++ b/liblog/stderr_write.cpp
@@ -37,16 +37,15 @@
#include <log/event_tag_map.h>
#include <log/log.h>
#include <log/logprint.h>
-#include <log/uio.h>
#include "log_portability.h"
#include "logger.h"
+#include "uio.h"
static int stderrOpen();
static void stderrClose();
static int stderrAvailable(log_id_t logId);
-static int stderrWrite(log_id_t logId, struct timespec* ts, struct iovec* vec,
- size_t nr);
+static int stderrWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr);
struct stderrContext {
AndroidLogFormat* logformat;
@@ -56,13 +55,13 @@
};
LIBLOG_HIDDEN struct android_log_transport_write stderrLoggerWrite = {
- .node = { &stderrLoggerWrite.node, &stderrLoggerWrite.node },
- .context.priv = NULL,
- .name = "stderr",
- .available = stderrAvailable,
- .open = stderrOpen,
- .close = stderrClose,
- .write = stderrWrite,
+ .node = {&stderrLoggerWrite.node, &stderrLoggerWrite.node},
+ .context.priv = NULL,
+ .name = "stderr",
+ .available = stderrAvailable,
+ .open = stderrOpen,
+ .close = stderrClose,
+ .write = stderrWrite,
};
static int stderrOpen() {
@@ -78,7 +77,7 @@
return fileno(stderr);
}
- ctx = calloc(1, sizeof(struct stderrContext));
+ ctx = static_cast<stderrContext*>(calloc(1, sizeof(stderrContext)));
if (!ctx) {
return -ENOMEM;
}
@@ -123,7 +122,7 @@
}
static void stderrClose() {
- struct stderrContext* ctx = stderrLoggerWrite.context.priv;
+ stderrContext* ctx = static_cast<stderrContext*>(stderrLoggerWrite.context.priv);
if (ctx) {
stderrLoggerWrite.context.priv = NULL;
@@ -147,14 +146,13 @@
return 1;
}
-static int stderrWrite(log_id_t logId, struct timespec* ts, struct iovec* vec,
- size_t nr) {
+static int stderrWrite(log_id_t logId, struct timespec* ts, struct iovec* vec, size_t nr) {
struct log_msg log_msg;
AndroidLogEntry entry;
char binaryMsgBuf[1024];
int err;
size_t i;
- struct stderrContext* ctx = stderrLoggerWrite.context.priv;
+ stderrContext* ctx = static_cast<stderrContext*>(stderrLoggerWrite.context.priv);
if (!ctx) return -EBADF;
if (!vec || !nr) return -EINVAL;
diff --git a/liblog/tests/Android.bp b/liblog/tests/Android.bp
index 2c47fd6..4ab2acb 100644
--- a/liblog/tests/Android.bp
+++ b/liblog/tests/Android.bp
@@ -29,10 +29,10 @@
"-fno-builtin",
],
shared_libs: [
- "liblog",
"libm",
"libbase",
],
+ static_libs: ["liblog"],
srcs: ["liblog_benchmark.cpp"],
}
@@ -63,10 +63,10 @@
"log_wrap_test.cpp",
],
shared_libs: [
- "liblog",
"libcutils",
"libbase",
],
+ static_libs: ["liblog"],
}
// Build tests for the device (with .so). Run with:
diff --git a/liblog/tests/liblog_benchmark.cpp b/liblog/tests/liblog_benchmark.cpp
index c2f3f83..c8ac321 100644
--- a/liblog/tests/liblog_benchmark.cpp
+++ b/liblog/tests/liblog_benchmark.cpp
@@ -21,6 +21,7 @@
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/types.h>
+#include <sys/uio.h>
#include <unistd.h>
#include <unordered_set>
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 2d0fc9b..83f0fa9 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -3160,41 +3160,6 @@
}
#endif // USING_LOGGER_DEFAULT
-#ifdef USING_LOGGER_DEFAULT // Do not retest ratelimit
-TEST(liblog, __android_log_ratelimit) {
- time_t state = 0;
-
- errno = 42;
- // Prime
- __android_log_ratelimit(3, &state);
- EXPECT_EQ(errno, 42);
- // Check
- EXPECT_FALSE(__android_log_ratelimit(3, &state));
- sleep(1);
- EXPECT_FALSE(__android_log_ratelimit(3, &state));
- sleep(4);
- EXPECT_TRUE(__android_log_ratelimit(3, &state));
- sleep(5);
- EXPECT_TRUE(__android_log_ratelimit(3, &state));
-
- // API checks
- IF_ALOG_RATELIMIT_LOCAL(3, &state) {
- EXPECT_FALSE(0 != "IF_ALOG_RATELIMIT_LOCAL(3, &state)");
- }
-
- IF_ALOG_RATELIMIT() {
- ;
- }
- else {
- EXPECT_TRUE(0 == "IF_ALOG_RATELIMIT()");
- }
- IF_ALOG_RATELIMIT() {
- EXPECT_FALSE(0 != "IF_ALOG_RATELIMIT()");
- }
- // Do not test default seconds, to allow liblog to tune freely
-}
-#endif // USING_LOGGER_DEFAULT
-
#ifdef USING_LOGGER_DEFAULT // Do not retest event mapping functionality
TEST(liblog, android_lookupEventTagNum) {
#ifdef __ANDROID__
diff --git a/liblog/tests/log_time_test.cpp b/liblog/tests/log_time_test.cpp
index 0ae1d18..47fe594 100644
--- a/liblog/tests/log_time_test.cpp
+++ b/liblog/tests/log_time_test.cpp
@@ -21,12 +21,6 @@
#include <log/log_time.h>
TEST(liblog, log_time) {
-#ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_
- log_time(CLOCK_MONOTONIC);
-
- EXPECT_EQ(log_time, log_time::EPOCH);
-#endif
-
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
log_time tl(ts);
diff --git a/liblog/uio.c b/liblog/uio.c
deleted file mode 100644
index e127202..0000000
--- a/liblog/uio.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2007-2014 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.
- */
-
-#if defined(_WIN32)
-
-#include <unistd.h>
-
-#include <log/uio.h>
-
-#include "log_portability.h"
-
-LIBLOG_ABI_PUBLIC int readv(int fd, struct iovec* vecs, int count) {
- int total = 0;
-
- for (; count > 0; count--, vecs++) {
- char* buf = vecs->iov_base;
- int len = vecs->iov_len;
-
- while (len > 0) {
- int ret = read(fd, buf, len);
- if (ret < 0) {
- if (total == 0) total = -1;
- goto Exit;
- }
- if (ret == 0) goto Exit;
-
- total += ret;
- buf += ret;
- len -= ret;
- }
- }
-Exit:
- return total;
-}
-
-LIBLOG_ABI_PUBLIC int writev(int fd, const struct iovec* vecs, int count) {
- int total = 0;
-
- for (; count > 0; count--, vecs++) {
- const char* buf = vecs->iov_base;
- int len = vecs->iov_len;
-
- while (len > 0) {
- int ret = write(fd, buf, len);
- if (ret < 0) {
- if (total == 0) total = -1;
- goto Exit;
- }
- if (ret == 0) goto Exit;
-
- total += ret;
- buf += ret;
- len -= ret;
- }
- }
-Exit:
- return total;
-}
-
-#endif
diff --git a/liblog/include/log/uio.h b/liblog/uio.h
similarity index 62%
rename from liblog/include/log/uio.h
rename to liblog/uio.h
index a492bae..c85893c 100644
--- a/liblog/include/log/uio.h
+++ b/liblog/uio.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2014 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,37 +14,14 @@
* limitations under the License.
*/
-#ifndef _LIBS_CUTILS_UIO_H
-#define _LIBS_CUTILS_UIO_H
+#pragma once
-#if !defined(_WIN32)
-
-#include <sys/uio.h>
-
-#else
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//
-// Implementation of sys/uio.h for Win32.
-//
-
+#if defined(_WIN32)
#include <stddef.h>
-
struct iovec {
void* iov_base;
size_t iov_len;
};
-
-extern int readv(int fd, struct iovec* vecs, int count);
-extern int writev(int fd, const struct iovec* vecs, int count);
-
-#ifdef __cplusplus
-}
+#else
+#include <sys/uio.h>
#endif
-
-#endif
-
-#endif /* _LIBS_UTILS_UIO_H */
diff --git a/libmeminfo/tools/Android.bp b/libmeminfo/tools/Android.bp
index c852bbb..24054c6 100644
--- a/libmeminfo/tools/Android.bp
+++ b/libmeminfo/tools/Android.bp
@@ -13,7 +13,7 @@
// limitations under the License.
cc_binary {
- name: "librank2",
+ name: "librank",
cflags: [
"-Wall",
"-Werror",
@@ -27,7 +27,7 @@
}
cc_binary {
- name: "procmem2",
+ name: "procmem",
cflags: [
"-Wall",
"-Werror",
@@ -41,7 +41,7 @@
}
cc_binary {
- name: "procrank2",
+ name: "procrank",
cflags: [
"-Wall",
"-Werror",
@@ -55,7 +55,7 @@
}
cc_binary {
- name: "showmap2",
+ name: "showmap",
cflags: [
"-Wall",
"-Werror",
diff --git a/libmemtrack/.clang-format b/libmemtrack/.clang-format
new file mode 120000
index 0000000..1af4f51
--- /dev/null
+++ b/libmemtrack/.clang-format
@@ -0,0 +1 @@
+../.clang-format-4
\ No newline at end of file
diff --git a/libmemtrack/Android.bp b/libmemtrack/Android.bp
index 0955633..4e4554a 100644
--- a/libmemtrack/Android.bp
+++ b/libmemtrack/Android.bp
@@ -28,10 +28,11 @@
cc_binary {
name: "memtrack_test",
- srcs: ["memtrack_test.c"],
+ srcs: ["memtrack_test.cpp"],
+ static_libs: ["libc++fs"],
shared_libs: [
+ "libbase",
"libmemtrack",
- "libpagemap",
],
cflags: [
"-Wall",
diff --git a/libmemtrack/memtrack_test.c b/libmemtrack/memtrack_test.c
deleted file mode 100644
index 77c935e..0000000
--- a/libmemtrack/memtrack_test.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2013 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-
-#include <memtrack/memtrack.h>
-
-#include <pagemap/pagemap.h>
-
-#define DIV_ROUND_UP(x,y) (((x) + (y) - 1) / (y))
-
-static int getprocname(pid_t pid, char *buf, int len) {
- char *filename;
- FILE *f;
- int rc = 0;
- static const char* unknown_cmdline = "<unknown>";
-
- if (len <= 0) {
- return -1;
- }
-
- if (asprintf(&filename, "/proc/%d/cmdline", pid) < 0) {
- rc = 1;
- goto exit;
- }
-
- f = fopen(filename, "r");
- if (f == NULL) {
- rc = 2;
- goto releasefilename;
- }
-
- if (fgets(buf, len, f) == NULL) {
- rc = 3;
- goto closefile;
- }
-
-closefile:
- (void) fclose(f);
-releasefilename:
- free(filename);
-exit:
- if (rc != 0) {
- /*
- * The process went away before we could read its process name. Try
- * to give the user "<unknown>" here, but otherwise they get to look
- * at a blank.
- */
- if (strlcpy(buf, unknown_cmdline, (size_t)len) >= (size_t)len) {
- rc = 4;
- }
- }
-
- return rc;
-}
-
-int main(int argc, char *argv[])
-{
- int ret;
- pm_kernel_t *ker;
- size_t num_procs;
- pid_t *pids;
- struct memtrack_proc *p;
- size_t i;
-
- (void)argc;
- (void)argv;
-
- ret = pm_kernel_create(&ker);
- if (ret) {
- fprintf(stderr, "Error creating kernel interface -- "
- "does this kernel have pagemap?\n");
- exit(EXIT_FAILURE);
- }
-
- ret = pm_kernel_pids(ker, &pids, &num_procs);
- if (ret) {
- fprintf(stderr, "Error listing processes.\n");
- exit(EXIT_FAILURE);
- }
-
- p = memtrack_proc_new();
- if (ret) {
- fprintf(stderr, "failed to create memtrack process handle\n");
- exit(EXIT_FAILURE);
- }
-
- for (i = 0; i < num_procs; i++) {
- pid_t pid = pids[i];
- char cmdline[256];
- size_t v1;
- size_t v2;
- size_t v3;
- size_t v4;
- size_t v5;
- size_t v6;
-
- getprocname(pid, cmdline, (int)sizeof(cmdline));
-
- ret = memtrack_proc_get(p, pid);
- if (ret) {
- fprintf(stderr, "failed to get memory info for pid %d: %s (%d)\n",
- pid, strerror(-ret), ret);
- continue;
- }
-
- v1 = DIV_ROUND_UP(memtrack_proc_graphics_total(p), 1024);
- v2 = DIV_ROUND_UP(memtrack_proc_graphics_pss(p), 1024);
- v3 = DIV_ROUND_UP(memtrack_proc_gl_total(p), 1024);
- v4 = DIV_ROUND_UP(memtrack_proc_gl_pss(p), 1024);
- v5 = DIV_ROUND_UP(memtrack_proc_other_total(p), 1024);
- v6 = DIV_ROUND_UP(memtrack_proc_other_pss(p), 1024);
-
- if (v1 | v2 | v3 | v4 | v5 | v6) {
- printf("%5d %6zu %6zu %6zu %6zu %6zu %6zu %s\n", pid,
- v1, v2, v3, v4, v5, v6, cmdline);
- }
- }
-
- memtrack_proc_destroy(p);
-
- return 0;
-}
diff --git a/libmemtrack/memtrack_test.cpp b/libmemtrack/memtrack_test.cpp
new file mode 100644
index 0000000..aeeaf24
--- /dev/null
+++ b/libmemtrack/memtrack_test.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2013 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <filesystem>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/parseint.h>
+#include <android-base/stringprintf.h>
+#include <memtrack/memtrack.h>
+
+#define DIV_ROUND_UP(x, y) (((x) + (y)-1) / (y))
+
+static void getprocname(pid_t pid, std::string* name) {
+ std::string fname = ::android::base::StringPrintf("/proc/%d/cmdline", pid);
+ if (!::android::base::ReadFileToString(fname, name)) {
+ fprintf(stderr, "Failed to read cmdline from: %s\n", fname.c_str());
+ *name = "<unknown>";
+ }
+}
+
+int main(int /* argc */, char** /* argv */) {
+ int ret;
+ struct memtrack_proc* p;
+ std::vector<pid_t> pids;
+
+ p = memtrack_proc_new();
+ if (p == nullptr) {
+ fprintf(stderr, "failed to create memtrack process handle\n");
+ exit(EXIT_FAILURE);
+ }
+
+ for (auto& de : std::filesystem::directory_iterator("/proc")) {
+ if (!std::filesystem::is_directory(de.status())) {
+ continue;
+ }
+
+ pid_t pid;
+ if (!::android::base::ParseInt(de.path().filename().string(), &pid)) {
+ continue;
+ }
+ pids.emplace_back(pid);
+ }
+
+ for (auto& pid : pids) {
+ size_t v1;
+ size_t v2;
+ size_t v3;
+ size_t v4;
+ size_t v5;
+ size_t v6;
+ std::string cmdline;
+
+ getprocname(pid, &cmdline);
+
+ ret = memtrack_proc_get(p, pid);
+ if (ret) {
+ fprintf(stderr, "failed to get memory info for pid %d: %s (%d)\n", pid, strerror(-ret),
+ ret);
+ continue;
+ }
+
+ v1 = DIV_ROUND_UP(memtrack_proc_graphics_total(p), 1024);
+ v2 = DIV_ROUND_UP(memtrack_proc_graphics_pss(p), 1024);
+ v3 = DIV_ROUND_UP(memtrack_proc_gl_total(p), 1024);
+ v4 = DIV_ROUND_UP(memtrack_proc_gl_pss(p), 1024);
+ v5 = DIV_ROUND_UP(memtrack_proc_other_total(p), 1024);
+ v6 = DIV_ROUND_UP(memtrack_proc_other_pss(p), 1024);
+
+ if (v1 | v2 | v3 | v4 | v5 | v6) {
+ fprintf(stdout, "%5d %6zu %6zu %6zu %6zu %6zu %6zu %s\n", pid, v1, v2, v3, v4, v5, v6,
+ cmdline.c_str());
+ }
+ }
+
+ memtrack_proc_destroy(p);
+
+ return ret;
+}
diff --git a/libnativeloader/Android.bp b/libnativeloader/Android.bp
index 17983bc..2802d36 100644
--- a/libnativeloader/Android.bp
+++ b/libnativeloader/Android.bp
@@ -24,3 +24,10 @@
"vndksp.libraries.txt",
],
}
+
+cc_library_headers {
+ name: "libnativeloader-dummy-headers",
+
+ host_supported: true,
+ export_include_dirs: ["include"],
+}
diff --git a/libnativeloader/OWNERS b/libnativeloader/OWNERS
index 5c28a9f..f735653 100644
--- a/libnativeloader/OWNERS
+++ b/libnativeloader/OWNERS
@@ -1,2 +1,6 @@
dimitry@google.com
jiyong@google.com
+ngeoffray@google.com
+oth@google.com
+mast@google.com
+rpl@google.com
diff --git a/libnativeloader/include/nativeloader/dlext_namespaces.h b/libnativeloader/include/nativeloader/dlext_namespaces.h
index 43c9329..2d6ce85 100644
--- a/libnativeloader/include/nativeloader/dlext_namespaces.h
+++ b/libnativeloader/include/nativeloader/dlext_namespaces.h
@@ -18,6 +18,7 @@
#define __ANDROID_DLEXT_NAMESPACES_H__
#include <android/dlext.h>
+#include <stdbool.h>
__BEGIN_DECLS
@@ -84,12 +85,9 @@
* If a library or any of its dependencies are outside of the permitted_when_isolated_path
* and search_path, and it is not part of the public namespace dlopen will fail.
*/
-extern struct android_namespace_t* android_create_namespace(const char* name,
- const char* ld_library_path,
- const char* default_library_path,
- uint64_t type,
- const char* permitted_when_isolated_path,
- android_namespace_t* parent);
+extern struct android_namespace_t* android_create_namespace(
+ const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type,
+ const char* permitted_when_isolated_path, struct android_namespace_t* parent);
/*
* Creates a link between namespaces. Every link has list of sonames of
@@ -107,24 +105,11 @@
* step will not go deeper into linked namespaces for this library but
* will do so for DT_NEEDED libraries.
*/
-extern bool android_link_namespaces(android_namespace_t* from,
- android_namespace_t* to,
+extern bool android_link_namespaces(struct android_namespace_t* from,
+ struct android_namespace_t* to,
const char* shared_libs_sonames);
-/*
- * Get the default library search path.
- * The path will be copied into buffer, which must have space for at least
- * buffer_size chars. Elements are separated with ':', and the path will always
- * be null-terminated.
- *
- * If buffer_size is too small to hold the entire default search path and the
- * null terminator, this function will abort. There is currently no way to find
- * out what the required buffer size is. At the time of this writing, PATH_MAX
- * is sufficient and used by all callers of this function.
- */
-extern void android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size);
-
-extern android_namespace_t* android_get_exported_namespace(const char* name);
+extern struct android_namespace_t* android_get_exported_namespace(const char* name);
__END_DECLS
diff --git a/libnativeloader/include/nativeloader/native_loader.h b/libnativeloader/include/nativeloader/native_loader.h
index c1d9d2a..260f655 100644
--- a/libnativeloader/include/nativeloader/native_loader.h
+++ b/libnativeloader/include/nativeloader/native_loader.h
@@ -17,14 +17,21 @@
#ifndef NATIVE_LOADER_H_
#define NATIVE_LOADER_H_
-#include "jni.h"
+#include <stdbool.h>
#include <stdint.h>
-#include <string>
+#include "jni.h"
#if defined(__ANDROID__)
#include <android/dlext.h>
#endif
+#ifdef __cplusplus
namespace android {
+extern "C" {
+#endif // __cplusplus
+
+// README: the char** error message parameter being passed
+// to the methods below need to be freed through calling NativeLoaderFreeErrorMessage.
+// It's the caller's responsibility to call that method.
__attribute__((visibility("default")))
void InitializeNativeLoader();
@@ -38,42 +45,39 @@
jstring library_path,
jstring permitted_path);
-__attribute__((visibility("default")))
-void* OpenNativeLibrary(JNIEnv* env,
- int32_t target_sdk_version,
- const char* path,
- jobject class_loader,
- jstring library_path,
- bool* needs_native_bridge,
- std::string* error_msg);
+__attribute__((visibility("default"))) void* OpenNativeLibrary(
+ JNIEnv* env, int32_t target_sdk_version, const char* path, jobject class_loader,
+ const char* caller_location, jstring library_path, bool* needs_native_bridge, char** error_msg);
__attribute__((visibility("default"))) bool CloseNativeLibrary(void* handle,
const bool needs_native_bridge,
- std::string* error_msg);
+ char** error_msg);
+
+__attribute__((visibility("default"))) void NativeLoaderFreeErrorMessage(char* msg);
#if defined(__ANDROID__)
// Look up linker namespace by class_loader. Returns nullptr if
// there is no namespace associated with the class_loader.
// TODO(b/79940628): move users to FindNativeLoaderNamespaceByClassLoader and remove this function.
-__attribute__((visibility("default")))
-android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader);
-// That version works with native bridge namespaces, but requires use of OpenNativeLibrary.
-class NativeLoaderNamespace;
-__attribute__((visibility("default")))
-NativeLoaderNamespace* FindNativeLoaderNamespaceByClassLoader(
+__attribute__((visibility("default"))) struct android_namespace_t* FindNamespaceByClassLoader(
JNIEnv* env, jobject class_loader);
+// That version works with native bridge namespaces, but requires use of OpenNativeLibrary.
+struct NativeLoaderNamespace;
+__attribute__((visibility("default"))) struct NativeLoaderNamespace*
+FindNativeLoaderNamespaceByClassLoader(JNIEnv* env, jobject class_loader);
// Load library. Unlinke OpenNativeLibrary above couldn't create namespace on demand, but does
// not require access to JNIEnv either.
-__attribute__((visibility("default")))
-void* OpenNativeLibrary(NativeLoaderNamespace* ns,
- const char* path,
- bool* needs_native_bridge,
- std::string* error_msg);
+__attribute__((visibility("default"))) void* OpenNativeLibraryInNamespace(
+ struct NativeLoaderNamespace* ns, const char* path, bool* needs_native_bridge,
+ char** error_msg);
#endif
__attribute__((visibility("default")))
void ResetNativeLoader();
-}; // namespace android
+#ifdef __cplusplus
+} // extern "C"
+} // namespace android
+#endif // __cplusplus
#endif // NATIVE_BRIDGE_H_
diff --git a/libnativeloader/libnativeloader.map.txt b/libnativeloader/libnativeloader.map.txt
new file mode 100644
index 0000000..40c30bd
--- /dev/null
+++ b/libnativeloader/libnativeloader.map.txt
@@ -0,0 +1,31 @@
+#
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# TODO(b/122710865): Prune these uses once the runtime APEX is complete.
+LIBNATIVELOADER_1 {
+ global:
+ OpenNativeLibrary;
+ InitializeNativeLoader;
+ ResetNativeLoader;
+ CloseNativeLibrary;
+ OpenNativeLibraryInNamespace;
+ FindNamespaceByClassLoader;
+ FindNativeLoaderNamespaceByClassLoader;
+ CreateClassLoaderNamespace;
+ NativeLoaderFreeErrorMessage;
+ local:
+ *;
+};
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index de7ea08..ab17b29 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -43,6 +43,10 @@
#include <android-base/properties.h>
#endif
+extern "C" {
+struct android_namespace_t* android_get_exported_namespace(const char*);
+}
+
#define CHECK(predicate) LOG_ALWAYS_FATAL_IF(!(predicate),\
"%s:%d: %s CHECK '" #predicate "' failed.",\
__FILE__, __LINE__, __FUNCTION__)
@@ -52,7 +56,7 @@
namespace android {
#if defined(__ANDROID__)
-class NativeLoaderNamespace {
+struct NativeLoaderNamespace {
public:
NativeLoaderNamespace()
: android_ns_(nullptr), native_bridge_ns_(nullptr) { }
@@ -119,6 +123,8 @@
// This list includes all directories app is allowed to access this way.
static constexpr const char* kWhitelistedDirectories = "/data:/mnt/expand";
+static constexpr const char* kApexPath = "/apex/";
+
static bool is_debuggable() {
char debuggable[PROP_VALUE_MAX];
property_get("ro.debuggable", debuggable, "0");
@@ -151,14 +157,9 @@
public:
LibraryNamespaces() : initialized_(false) { }
- NativeLoaderNamespace* Create(JNIEnv* env,
- uint32_t target_sdk_version,
- jobject class_loader,
- bool is_shared,
- bool is_for_vendor,
- jstring java_library_path,
- jstring java_permitted_path,
- std::string* error_msg) {
+ NativeLoaderNamespace* Create(JNIEnv* env, uint32_t target_sdk_version, jobject class_loader,
+ bool is_shared, bool is_for_vendor, jstring java_library_path,
+ jstring java_permitted_path, std::string* error_msg) {
std::string library_path; // empty string by default.
if (java_library_path != nullptr) {
@@ -628,20 +629,54 @@
return nullptr;
}
-void* OpenNativeLibrary(JNIEnv* env,
- int32_t target_sdk_version,
- const char* path,
- jobject class_loader,
- jstring library_path,
- bool* needs_native_bridge,
- std::string* error_msg) {
+#if defined(__ANDROID__)
+static android_namespace_t* FindExportedNamespace(const char* caller_location) {
+ std::string location = caller_location;
+ // Lots of implicit assumptions here: we expect `caller_location` to be of the form:
+ // /apex/com.android...modulename/...
+ //
+ // And we extract from it 'modulename', which is the name of the linker namespace.
+ if (android::base::StartsWith(location, kApexPath)) {
+ size_t slash_index = location.find_first_of('/', strlen(kApexPath));
+ LOG_ALWAYS_FATAL_IF((slash_index == std::string::npos),
+ "Error finding namespace of apex: no slash in path %s", caller_location);
+ size_t dot_index = location.find_last_of('.', slash_index);
+ LOG_ALWAYS_FATAL_IF((dot_index == std::string::npos),
+ "Error finding namespace of apex: no dot in apex name %s", caller_location);
+ std::string name = location.substr(dot_index + 1, slash_index - dot_index - 1);
+ android_namespace_t* boot_namespace = android_get_exported_namespace(name.c_str());
+ LOG_ALWAYS_FATAL_IF((boot_namespace == nullptr),
+ "Error finding namespace of apex: no namespace called %s", name.c_str());
+ return boot_namespace;
+ }
+ return nullptr;
+}
+#endif
+
+void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
+ jobject class_loader, const char* caller_location, jstring library_path,
+ bool* needs_native_bridge, char** error_msg) {
#if defined(__ANDROID__)
UNUSED(target_sdk_version);
if (class_loader == nullptr) {
*needs_native_bridge = false;
+ if (caller_location != nullptr) {
+ android_namespace_t* boot_namespace = FindExportedNamespace(caller_location);
+ if (boot_namespace != nullptr) {
+ const android_dlextinfo dlextinfo = {
+ .flags = ANDROID_DLEXT_USE_NAMESPACE,
+ .library_namespace = boot_namespace,
+ };
+ void* handle = android_dlopen_ext(path, RTLD_NOW, &dlextinfo);
+ if (handle == nullptr) {
+ *error_msg = strdup(dlerror());
+ }
+ return handle;
+ }
+ }
void* handle = dlopen(path, RTLD_NOW);
if (handle == nullptr) {
- *error_msg = dlerror();
+ *error_msg = strdup(dlerror());
}
return handle;
}
@@ -652,21 +687,18 @@
if ((ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader)) == nullptr) {
// This is the case where the classloader was not created by ApplicationLoaders
// In this case we create an isolated not-shared namespace for it.
- if ((ns = g_namespaces->Create(env,
- target_sdk_version,
- class_loader,
- false /* is_shared */,
- false /* is_for_vendor */,
- library_path,
- nullptr,
- error_msg)) == nullptr) {
+ std::string create_error_msg;
+ if ((ns = g_namespaces->Create(env, target_sdk_version, class_loader, false /* is_shared */,
+ false /* is_for_vendor */, library_path, nullptr,
+ &create_error_msg)) == nullptr) {
+ *error_msg = strdup(create_error_msg.c_str());
return nullptr;
}
}
- return OpenNativeLibrary(ns, path, needs_native_bridge, error_msg);
+ return OpenNativeLibraryInNamespace(ns, path, needs_native_bridge, error_msg);
#else
- UNUSED(env, target_sdk_version, class_loader);
+ UNUSED(env, target_sdk_version, class_loader, caller_location);
// Do some best effort to emulate library-path support. It will not
// work for dependencies.
@@ -705,35 +737,40 @@
if (handle != nullptr) {
return handle;
}
- *error_msg = NativeBridgeGetError();
+ *error_msg = strdup(NativeBridgeGetError());
} else {
- *error_msg = dlerror();
+ *error_msg = strdup(dlerror());
}
}
return nullptr;
#endif
}
-bool CloseNativeLibrary(void* handle, const bool needs_native_bridge, std::string* error_msg) {
+bool CloseNativeLibrary(void* handle, const bool needs_native_bridge, char** error_msg) {
bool success;
if (needs_native_bridge) {
success = (NativeBridgeUnloadLibrary(handle) == 0);
if (!success) {
- *error_msg = NativeBridgeGetError();
+ *error_msg = strdup(NativeBridgeGetError());
}
} else {
success = (dlclose(handle) == 0);
if (!success) {
- *error_msg = dlerror();
+ *error_msg = strdup(dlerror());
}
}
return success;
}
+void NativeLoaderFreeErrorMessage(char* msg) {
+ // The error messages get allocated through strdup, so we must call free on them.
+ free(msg);
+}
+
#if defined(__ANDROID__)
-void* OpenNativeLibrary(NativeLoaderNamespace* ns, const char* path, bool* needs_native_bridge,
- std::string* error_msg) {
+void* OpenNativeLibraryInNamespace(NativeLoaderNamespace* ns, const char* path,
+ bool* needs_native_bridge, char** error_msg) {
if (ns->is_android_namespace()) {
android_dlextinfo extinfo;
extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
@@ -741,14 +778,14 @@
void* handle = android_dlopen_ext(path, RTLD_NOW, &extinfo);
if (handle == nullptr) {
- *error_msg = dlerror();
+ *error_msg = strdup(dlerror());
}
*needs_native_bridge = false;
return handle;
} else {
void* handle = NativeBridgeLoadLibraryExt(path, RTLD_NOW, ns->get_native_bridge_ns());
if (handle == nullptr) {
- *error_msg = NativeBridgeGetError();
+ *error_msg = strdup(NativeBridgeGetError());
}
*needs_native_bridge = true;
return handle;
diff --git a/libnativeloader/test/Android.bp b/libnativeloader/test/Android.bp
index d528f30..1464e39 100644
--- a/libnativeloader/test/Android.bp
+++ b/libnativeloader/test/Android.bp
@@ -69,3 +69,14 @@
"libbase",
],
}
+
+// Build the test for the C API.
+cc_test {
+ name: "libnativeloader-api-tests",
+ host_supported: true,
+ test_per_src: true,
+ srcs: [
+ "api_test.c",
+ ],
+ header_libs: ["libnativeloader-dummy-headers"],
+}
diff --git a/libnativeloader/test/api_test.c b/libnativeloader/test/api_test.c
new file mode 100644
index 0000000..e7025fd
--- /dev/null
+++ b/libnativeloader/test/api_test.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* The main purpose of this test is to ensure this C header compiles in C, so
+ * that no C++ features inadvertently leak into the C ABI. */
+#include "nativeloader/native_loader.h"
+
+int main(int argc, char** argv) {
+ (void)argc;
+ (void)argv;
+ return 0;
+}
diff --git a/libstats/include/stats_event_list.h b/libstats/include/stats_event_list.h
index 162d1cf..b5bc5af 100644
--- a/libstats/include/stats_event_list.h
+++ b/libstats/include/stats_event_list.h
@@ -51,10 +51,6 @@
explicit stats_event_list(int tag) : ret(0) {
ctx = create_android_logger(static_cast<uint32_t>(tag));
}
- explicit stats_event_list(log_msg& log_msg) : ret(0) {
- ctx = create_android_log_parser(log_msg.msg() + sizeof(uint32_t),
- log_msg.entry.len - sizeof(uint32_t));
- }
~stats_event_list() { android_log_destroy(&ctx); }
int close() {
@@ -251,9 +247,6 @@
}
return ret >= 0;
}
-
- android_log_list_element read() { return android_log_read_next(ctx); }
- android_log_list_element peek() { return android_log_peek_next(ctx); }
};
#endif
diff --git a/libstats/statsd_writer.c b/libstats/statsd_writer.c
index f00fc2d..f5be95c 100644
--- a/libstats/statsd_writer.c
+++ b/libstats/statsd_writer.c
@@ -31,6 +31,7 @@
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/uio.h>
#include <sys/un.h>
#include <time.h>
#include <unistd.h>
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index e267f58..d1b8271 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -127,6 +127,10 @@
},
},
+ whole_static_libs: [
+ "libdemangle"
+ ],
+
static_libs: [
"libprocinfo",
],
@@ -187,8 +191,10 @@
"tests/LocalUnwinderTest.cpp",
"tests/LogFake.cpp",
"tests/MapInfoCreateMemoryTest.cpp",
+ "tests/MapInfoGetBuildIDTest.cpp",
"tests/MapInfoGetElfTest.cpp",
"tests/MapInfoGetLoadBiasTest.cpp",
+ "tests/MapInfoTest.cpp",
"tests/MapsTest.cpp",
"tests/MemoryBufferTest.cpp",
"tests/MemoryCacheTest.cpp",
@@ -338,6 +344,7 @@
],
shared_libs: [
+ "libbase",
"libunwindstack",
],
}
diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp
index 5b586a2..2f5eed9 100644
--- a/libunwindstack/Elf.cpp
+++ b/libunwindstack/Elf.cpp
@@ -140,8 +140,11 @@
return true;
}
-bool Elf::GetBuildID(std::string* build_id) {
- return valid_ && interface_->GetBuildID(build_id);
+std::string Elf::GetBuildID() {
+ if (!valid_) {
+ return "";
+ }
+ return interface_->GetBuildID();
}
void Elf::GetLastError(ErrorData* data) {
@@ -384,4 +387,22 @@
return false;
}
+std::string Elf::GetBuildID(Memory* memory) {
+ if (!IsValidElf(memory)) {
+ return "";
+ }
+
+ uint8_t class_type;
+ if (!memory->Read(EI_CLASS, &class_type, 1)) {
+ return "";
+ }
+
+ if (class_type == ELFCLASS32) {
+ return ElfInterface::ReadBuildIDFromMemory<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr>(memory);
+ } else if (class_type == ELFCLASS64) {
+ return ElfInterface::ReadBuildIDFromMemory<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr>(memory);
+ }
+ return "";
+}
+
} // namespace unwindstack
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index d0af94a..c1b98d9 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -177,14 +177,14 @@
template <typename EhdrType, typename PhdrType>
uint64_t ElfInterface::GetLoadBias(Memory* memory) {
EhdrType ehdr;
- if (!memory->Read(0, &ehdr, sizeof(ehdr))) {
+ if (!memory->ReadFully(0, &ehdr, sizeof(ehdr))) {
return false;
}
uint64_t offset = ehdr.e_phoff;
for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) {
PhdrType phdr;
- if (!memory->Read(offset, &phdr, sizeof(phdr))) {
+ if (!memory->ReadFully(offset, &phdr, sizeof(phdr))) {
return 0;
}
if (phdr.p_type == PT_LOAD && phdr.p_offset == 0) {
@@ -238,31 +238,31 @@
}
template <typename NhdrType>
-bool ElfInterface::ReadBuildID(std::string* build_id) {
+std::string ElfInterface::ReadBuildID() {
// Ensure there is no overflow in any of the calulations below.
uint64_t tmp;
if (__builtin_add_overflow(gnu_build_id_offset_, gnu_build_id_size_, &tmp)) {
- return false;
+ return "";
}
uint64_t offset = 0;
while (offset < gnu_build_id_size_) {
if (gnu_build_id_size_ - offset < sizeof(NhdrType)) {
- return false;
+ return "";
}
NhdrType hdr;
if (!memory_->ReadFully(gnu_build_id_offset_ + offset, &hdr, sizeof(hdr))) {
- return false;
+ return "";
}
offset += sizeof(hdr);
if (gnu_build_id_size_ - offset < hdr.n_namesz) {
- return false;
+ return "";
}
if (hdr.n_namesz > 0) {
std::string name(hdr.n_namesz, '\0');
if (!memory_->ReadFully(gnu_build_id_offset_ + offset, &(name[0]), hdr.n_namesz)) {
- return false;
+ return "";
}
// Trim trailing \0 as GNU is stored as a C string in the ELF file.
@@ -273,18 +273,20 @@
offset += (hdr.n_namesz + 3) & ~3;
if (name == "GNU" && hdr.n_type == NT_GNU_BUILD_ID) {
- if (gnu_build_id_size_ - offset < hdr.n_descsz) {
- return false;
+ if (gnu_build_id_size_ - offset < hdr.n_descsz || hdr.n_descsz == 0) {
+ return "";
}
- build_id->resize(hdr.n_descsz);
- return memory_->ReadFully(gnu_build_id_offset_ + offset, &(*build_id)[0],
- hdr.n_descsz);
+ std::string build_id(hdr.n_descsz - 1, '\0');
+ if (memory_->ReadFully(gnu_build_id_offset_ + offset, &build_id[0], hdr.n_descsz)) {
+ return build_id;
+ }
+ return "";
}
}
// Align hdr.n_descsz to next power multiple of 4. See man 5 elf.
offset += (hdr.n_descsz + 3) & ~3;
}
- return false;
+ return "";
}
template <typename EhdrType, typename ShdrType>
@@ -308,7 +310,7 @@
// Skip the first header, it's always going to be NULL.
offset += ehdr.e_shentsize;
for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) {
- if (!memory_->Read(offset, &shdr, sizeof(shdr))) {
+ if (!memory_->ReadFully(offset, &shdr, sizeof(shdr))) {
return;
}
@@ -320,7 +322,7 @@
continue;
}
uint64_t str_offset = ehdr.e_shoff + shdr.sh_link * ehdr.e_shentsize;
- if (!memory_->Read(str_offset, &str_shdr, sizeof(str_shdr))) {
+ if (!memory_->ReadFully(str_offset, &str_shdr, sizeof(str_shdr))) {
continue;
}
if (str_shdr.sh_type != SHT_STRTAB) {
@@ -536,6 +538,103 @@
*size = ehdr.e_shoff + ehdr.e_shentsize * ehdr.e_shnum;
}
+template <typename EhdrType, typename ShdrType>
+bool GetBuildIDInfo(Memory* memory, uint64_t* build_id_offset, uint64_t* build_id_size) {
+ EhdrType ehdr;
+ if (!memory->ReadFully(0, &ehdr, sizeof(ehdr))) {
+ return false;
+ }
+
+ uint64_t offset = ehdr.e_shoff;
+ uint64_t sec_offset;
+ uint64_t sec_size;
+ ShdrType shdr;
+ if (ehdr.e_shstrndx >= ehdr.e_shnum) {
+ return false;
+ }
+
+ uint64_t sh_offset = offset + ehdr.e_shstrndx * ehdr.e_shentsize;
+ if (!memory->ReadFully(sh_offset, &shdr, sizeof(shdr))) {
+ return false;
+ }
+ sec_offset = shdr.sh_offset;
+ sec_size = shdr.sh_size;
+
+ // Skip the first header, it's always going to be NULL.
+ offset += ehdr.e_shentsize;
+ for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) {
+ if (!memory->ReadFully(offset, &shdr, sizeof(shdr))) {
+ return false;
+ }
+ std::string name;
+ if (shdr.sh_type == SHT_NOTE && shdr.sh_name < sec_size &&
+ memory->ReadString(sec_offset + shdr.sh_name, &name) && name == ".note.gnu.build-id") {
+ *build_id_offset = shdr.sh_offset;
+ *build_id_size = shdr.sh_size;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+template <typename EhdrType, typename ShdrType, typename NhdrType>
+std::string ElfInterface::ReadBuildIDFromMemory(Memory* memory) {
+ uint64_t note_offset;
+ uint64_t note_size;
+ if (!GetBuildIDInfo<EhdrType, ShdrType>(memory, ¬e_offset, ¬e_size)) {
+ return "";
+ }
+
+ // Ensure there is no overflow in any of the calculations below.
+ uint64_t tmp;
+ if (__builtin_add_overflow(note_offset, note_size, &tmp)) {
+ return "";
+ }
+
+ uint64_t offset = 0;
+ while (offset < note_size) {
+ if (note_size - offset < sizeof(NhdrType)) {
+ return "";
+ }
+ NhdrType hdr;
+ if (!memory->ReadFully(note_offset + offset, &hdr, sizeof(hdr))) {
+ return "";
+ }
+ offset += sizeof(hdr);
+
+ if (note_size - offset < hdr.n_namesz) {
+ return "";
+ }
+ if (hdr.n_namesz > 0) {
+ std::string name(hdr.n_namesz, '\0');
+ if (!memory->ReadFully(note_offset + offset, &(name[0]), hdr.n_namesz)) {
+ return "";
+ }
+
+ // Trim trailing \0 as GNU is stored as a C string in the ELF file.
+ if (name.back() == '\0') name.resize(name.size() - 1);
+
+ // Align hdr.n_namesz to next power multiple of 4. See man 5 elf.
+ offset += (hdr.n_namesz + 3) & ~3;
+
+ if (name == "GNU" && hdr.n_type == NT_GNU_BUILD_ID) {
+ if (note_size - offset < hdr.n_descsz || hdr.n_descsz == 0) {
+ return "";
+ }
+ std::string build_id(hdr.n_descsz - 1, '\0');
+ if (memory->ReadFully(note_offset + offset, &build_id[0], hdr.n_descsz)) {
+ return build_id;
+ }
+ return "";
+ }
+ }
+ // Align hdr.n_descsz to next power multiple of 4. See man 5 elf.
+ offset += (hdr.n_descsz + 3) & ~3;
+ }
+ return "";
+}
+
// Instantiate all of the needed template functions.
template void ElfInterface::InitHeadersWithTemplate<uint32_t>(uint64_t);
template void ElfInterface::InitHeadersWithTemplate<uint64_t>(uint64_t);
@@ -551,8 +650,8 @@
template void ElfInterface::ReadSectionHeaders<Elf32_Ehdr, Elf32_Shdr>(const Elf32_Ehdr&);
template void ElfInterface::ReadSectionHeaders<Elf64_Ehdr, Elf64_Shdr>(const Elf64_Ehdr&);
-template bool ElfInterface::ReadBuildID<Elf32_Nhdr>(std::string*);
-template bool ElfInterface::ReadBuildID<Elf64_Nhdr>(std::string*);
+template std::string ElfInterface::ReadBuildID<Elf32_Nhdr>();
+template std::string ElfInterface::ReadBuildID<Elf64_Nhdr>();
template bool ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(std::string*);
template bool ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(std::string*);
@@ -571,4 +670,9 @@
template uint64_t ElfInterface::GetLoadBias<Elf32_Ehdr, Elf32_Phdr>(Memory*);
template uint64_t ElfInterface::GetLoadBias<Elf64_Ehdr, Elf64_Phdr>(Memory*);
+template std::string ElfInterface::ReadBuildIDFromMemory<Elf32_Ehdr, Elf32_Shdr, Elf32_Nhdr>(
+ Memory*);
+template std::string ElfInterface::ReadBuildIDFromMemory<Elf64_Ehdr, Elf64_Shdr, Elf64_Nhdr>(
+ Memory*);
+
} // namespace unwindstack
diff --git a/libunwindstack/MapInfo.cpp b/libunwindstack/MapInfo.cpp
index 39a09cf..f319971 100644
--- a/libunwindstack/MapInfo.cpp
+++ b/libunwindstack/MapInfo.cpp
@@ -146,6 +146,10 @@
}
}
+ if (process_memory == nullptr) {
+ return nullptr;
+ }
+
// Need to verify that this elf is valid. It's possible that
// only part of the elf file to be mapped into memory is in the executable
// map. In this case, there will be another read-only map that includes the
@@ -221,6 +225,19 @@
return elf.get();
}
+bool MapInfo::GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) {
+ {
+ // Make sure no other thread is trying to update this elf object.
+ std::lock_guard<std::mutex> guard(mutex_);
+ if (elf == nullptr) {
+ return false;
+ }
+ }
+ // No longer need the lock, once the elf object is created, it is not deleted
+ // until this object is deleted.
+ return elf->GetFunctionName(addr, name, func_offset);
+}
+
uint64_t MapInfo::GetLoadBias(const std::shared_ptr<Memory>& process_memory) {
uint64_t cur_load_bias = load_bias.load();
if (cur_load_bias != static_cast<uint64_t>(-1)) {
@@ -250,4 +267,48 @@
return cur_load_bias;
}
+MapInfo::~MapInfo() {
+ uintptr_t id = build_id.load();
+ if (id != 0) {
+ delete reinterpret_cast<std::string*>(id);
+ }
+}
+
+std::string MapInfo::GetBuildID() {
+ uintptr_t id = build_id.load();
+ if (build_id != 0) {
+ return *reinterpret_cast<std::string*>(id);
+ }
+
+ // No need to lock, at worst if multiple threads do this at the same
+ // time it should be detected and only one thread should win and
+ // save the data.
+ std::unique_ptr<std::string> cur_build_id(new std::string);
+
+ // Now need to see if the elf object exists.
+ // Make sure no other thread is trying to add the elf to this map.
+ mutex_.lock();
+ Elf* elf_obj = elf.get();
+ mutex_.unlock();
+ if (elf_obj != nullptr) {
+ *cur_build_id = elf_obj->GetBuildID();
+ } else {
+ // This will only work if we can get the file associated with this memory.
+ // If this is only available in memory, then the section name information
+ // is not present and we will not be able to find the build id info.
+ std::unique_ptr<Memory> memory(GetFileMemory());
+ if (memory != nullptr) {
+ *cur_build_id = Elf::GetBuildID(memory.get());
+ }
+ }
+
+ id = reinterpret_cast<uintptr_t>(cur_build_id.get());
+ uintptr_t expected_id = 0;
+ if (build_id.compare_exchange_weak(expected_id, id)) {
+ // Value saved, so make sure the memory is not freed.
+ cur_build_id.release();
+ }
+ return *reinterpret_cast<std::string*>(id);
+}
+
} // namespace unwindstack
diff --git a/libunwindstack/RegsMips.cpp b/libunwindstack/RegsMips.cpp
index 14a4e31..f330fe0 100644
--- a/libunwindstack/RegsMips.cpp
+++ b/libunwindstack/RegsMips.cpp
@@ -135,7 +135,7 @@
Memory* elf_memory = elf->memory();
// Read from elf memory since it is usually more expensive to read from
// process memory.
- if (!elf_memory->Read(rel_pc, &data, sizeof(data))) {
+ if (!elf_memory->ReadFully(rel_pc, &data, sizeof(data))) {
return false;
}
@@ -160,7 +160,7 @@
// read sc_pc and sc_regs[32] from stack
uint64_t values[MIPS_REG_LAST];
- if (!process_memory->Read(regs_[MIPS_REG_SP] + offset, values, sizeof(values))) {
+ if (!process_memory->ReadFully(regs_[MIPS_REG_SP] + offset, values, sizeof(values))) {
return false;
}
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp
index 8133639..57207de 100644
--- a/libunwindstack/Unwinder.cpp
+++ b/libunwindstack/Unwinder.cpp
@@ -26,10 +26,13 @@
#include <android-base/stringprintf.h>
+#include <demangle.h>
+
#include <unwindstack/Elf.h>
#include <unwindstack/JitDebug.h>
#include <unwindstack/MapInfo.h>
#include <unwindstack/Maps.h>
+#include <unwindstack/Memory.h>
#include <unwindstack/Unwinder.h>
#if !defined(NO_LIBDEXFILE_SUPPORT)
@@ -306,7 +309,7 @@
}
if (!frame.function_name.empty()) {
- data += " (" + frame.function_name;
+ data += " (" + demangle(frame.function_name.c_str());
if (frame.function_offset != 0) {
data += android::base::StringPrintf("+%" PRId64, frame.function_offset);
}
@@ -327,4 +330,29 @@
}
#endif
+bool UnwinderFromPid::Init(ArchEnum arch) {
+ if (pid_ == getpid()) {
+ maps_ptr_.reset(new LocalMaps());
+ } else {
+ maps_ptr_.reset(new RemoteMaps(pid_));
+ }
+ if (!maps_ptr_->Parse()) {
+ return false;
+ }
+ maps_ = maps_ptr_.get();
+
+ process_memory_ = Memory::CreateProcessMemoryCached(pid_);
+
+ jit_debug_ptr_.reset(new JitDebug(process_memory_));
+ jit_debug_ = jit_debug_ptr_.get();
+ SetJitDebug(jit_debug_, arch);
+#if !defined(NO_LIBDEXFILE_SUPPORT)
+ dex_files_ptr_.reset(new DexFiles(process_memory_));
+ dex_files_ = dex_files_ptr_.get();
+ SetDexFiles(dex_files_, arch);
+#endif
+
+ return true;
+}
+
} // namespace unwindstack
diff --git a/libunwindstack/benchmarks/unwind_benchmarks.cpp b/libunwindstack/benchmarks/unwind_benchmarks.cpp
index db0fb54..8caecc7 100644
--- a/libunwindstack/benchmarks/unwind_benchmarks.cpp
+++ b/libunwindstack/benchmarks/unwind_benchmarks.cpp
@@ -20,6 +20,9 @@
#include <benchmark/benchmark.h>
+#include <android-base/strings.h>
+
+#include <unwindstack/Elf.h>
#include <unwindstack/Maps.h>
#include <unwindstack/Memory.h>
#include <unwindstack/Regs.h>
@@ -80,4 +83,63 @@
}
BENCHMARK(BM_cached_unwind);
+static void Initialize(benchmark::State& state, unwindstack::Maps& maps,
+ unwindstack::MapInfo** build_id_map_info) {
+ if (!maps.Parse()) {
+ state.SkipWithError("Failed to parse local maps.");
+ return;
+ }
+
+ // Find the libc.so share library and use that for benchmark purposes.
+ *build_id_map_info = nullptr;
+ for (unwindstack::MapInfo* map_info : maps) {
+ if (map_info->offset == 0 && map_info->GetBuildID() != "") {
+ *build_id_map_info = map_info;
+ break;
+ }
+ }
+
+ if (*build_id_map_info == nullptr) {
+ state.SkipWithError("Failed to find a map with a BuildID.");
+ }
+}
+
+static void BM_get_build_id_from_elf(benchmark::State& state) {
+ unwindstack::LocalMaps maps;
+ unwindstack::MapInfo* build_id_map_info;
+ Initialize(state, maps, &build_id_map_info);
+
+ unwindstack::Elf* elf = build_id_map_info->GetElf(std::shared_ptr<unwindstack::Memory>(),
+ unwindstack::Regs::CurrentArch());
+ if (!elf->valid()) {
+ state.SkipWithError("Cannot get valid elf from map.");
+ }
+
+ for (auto _ : state) {
+ uintptr_t id = build_id_map_info->build_id;
+ if (id != 0) {
+ delete reinterpret_cast<std::string*>(id);
+ build_id_map_info->build_id = 0;
+ }
+ benchmark::DoNotOptimize(build_id_map_info->GetBuildID());
+ }
+}
+BENCHMARK(BM_get_build_id_from_elf);
+
+static void BM_get_build_id_from_file(benchmark::State& state) {
+ unwindstack::LocalMaps maps;
+ unwindstack::MapInfo* build_id_map_info;
+ Initialize(state, maps, &build_id_map_info);
+
+ for (auto _ : state) {
+ uintptr_t id = build_id_map_info->build_id;
+ if (id != 0) {
+ delete reinterpret_cast<std::string*>(id);
+ build_id_map_info->build_id = 0;
+ }
+ benchmark::DoNotOptimize(build_id_map_info->GetBuildID());
+ }
+}
+BENCHMARK(BM_get_build_id_from_file);
+
BENCHMARK_MAIN();
diff --git a/libunwindstack/include/unwindstack/Elf.h b/libunwindstack/include/unwindstack/Elf.h
index 27f7201..00a249f 100644
--- a/libunwindstack/include/unwindstack/Elf.h
+++ b/libunwindstack/include/unwindstack/Elf.h
@@ -65,8 +65,6 @@
bool GetGlobalVariable(const std::string& name, uint64_t* memory_address);
- bool GetBuildID(std::string* build_id);
-
uint64_t GetRelPc(uint64_t pc, const MapInfo* map_info);
bool Step(uint64_t rel_pc, uint64_t adjusted_rel_pc, Regs* regs, Memory* process_memory,
@@ -74,6 +72,8 @@
ElfInterface* CreateInterfaceFromMemory(Memory* memory);
+ std::string GetBuildID();
+
uint64_t GetLoadBias() { return load_bias_; }
bool IsValidPc(uint64_t pc);
@@ -102,6 +102,8 @@
static uint64_t GetLoadBias(Memory* memory);
+ static std::string GetBuildID(Memory* memory);
+
static void SetCachingEnabled(bool enable);
static bool CachingEnabled() { return cache_enabled_; }
diff --git a/libunwindstack/include/unwindstack/ElfInterface.h b/libunwindstack/include/unwindstack/ElfInterface.h
index 52992d9..d41bb13 100644
--- a/libunwindstack/include/unwindstack/ElfInterface.h
+++ b/libunwindstack/include/unwindstack/ElfInterface.h
@@ -62,7 +62,7 @@
virtual bool GetGlobalVariable(const std::string& name, uint64_t* memory_address) = 0;
- virtual bool GetBuildID(std::string* build_id) = 0;
+ virtual std::string GetBuildID() = 0;
virtual bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished);
@@ -100,6 +100,9 @@
template <typename EhdrType, typename PhdrType>
static uint64_t GetLoadBias(Memory* memory);
+ template <typename EhdrType, typename ShdrType, typename NhdrType>
+ static std::string ReadBuildIDFromMemory(Memory* memory);
+
protected:
template <typename AddressType>
void InitHeadersWithTemplate(uint64_t load_bias);
@@ -128,7 +131,7 @@
static void GetMaxSizeWithTemplate(Memory* memory, uint64_t* size);
template <typename NhdrType>
- bool ReadBuildID(std::string* build_id);
+ std::string ReadBuildID();
Memory* memory_;
std::unordered_map<uint64_t, LoadInfo> pt_loads_;
@@ -192,9 +195,7 @@
return ElfInterface::GetGlobalVariableWithTemplate<Elf32_Sym>(name, memory_address);
}
- bool GetBuildID(std::string* build_id) {
- return ElfInterface::ReadBuildID<Elf32_Nhdr>(build_id);
- }
+ std::string GetBuildID() override { return ElfInterface::ReadBuildID<Elf32_Nhdr>(); }
static void GetMaxSize(Memory* memory, uint64_t* size) {
GetMaxSizeWithTemplate<Elf32_Ehdr>(memory, size);
@@ -226,9 +227,7 @@
return ElfInterface::GetGlobalVariableWithTemplate<Elf64_Sym>(name, memory_address);
}
- bool GetBuildID(std::string* build_id) {
- return ElfInterface::ReadBuildID<Elf64_Nhdr>(build_id);
- }
+ std::string GetBuildID() override { return ElfInterface::ReadBuildID<Elf64_Nhdr>(); }
static void GetMaxSize(Memory* memory, uint64_t* size) {
GetMaxSizeWithTemplate<Elf64_Ehdr>(memory, size);
diff --git a/libunwindstack/include/unwindstack/MapInfo.h b/libunwindstack/include/unwindstack/MapInfo.h
index 5e3d6f6..5143ff1 100644
--- a/libunwindstack/include/unwindstack/MapInfo.h
+++ b/libunwindstack/include/unwindstack/MapInfo.h
@@ -38,7 +38,8 @@
flags(flags),
name(name),
prev_map(map_info),
- load_bias(static_cast<uint64_t>(-1)) {}
+ load_bias(static_cast<uint64_t>(-1)),
+ build_id(0) {}
MapInfo(MapInfo* map_info, uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
const std::string& name)
: start(start),
@@ -47,8 +48,9 @@
flags(flags),
name(name),
prev_map(map_info),
- load_bias(static_cast<uint64_t>(-1)) {}
- ~MapInfo() = default;
+ load_bias(static_cast<uint64_t>(-1)),
+ build_id(0) {}
+ ~MapInfo();
uint64_t start = 0;
uint64_t end = 0;
@@ -68,6 +70,11 @@
std::atomic_uint64_t load_bias;
+ // This is a pointer to a new'd std::string.
+ // Using an atomic value means that we don't need to lock and will
+ // make it easier to move to a fine grained lock in the future.
+ std::atomic_uintptr_t build_id;
+
// This function guarantees it will never return nullptr.
Elf* GetElf(const std::shared_ptr<Memory>& process_memory, ArchEnum expected_arch);
@@ -75,6 +82,10 @@
Memory* CreateMemory(const std::shared_ptr<Memory>& process_memory);
+ bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset);
+
+ std::string GetBuildID();
+
private:
MapInfo(const MapInfo&) = delete;
void operator=(const MapInfo&) = delete;
diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h
index d7bbd9d..ab239c1 100644
--- a/libunwindstack/include/unwindstack/Unwinder.h
+++ b/libunwindstack/include/unwindstack/Unwinder.h
@@ -24,7 +24,9 @@
#include <string>
#include <vector>
+#include <unwindstack/DexFiles.h>
#include <unwindstack/Error.h>
+#include <unwindstack/JitDebug.h>
#include <unwindstack/Maps.h>
#include <unwindstack/Memory.h>
#include <unwindstack/Regs.h>
@@ -32,9 +34,7 @@
namespace unwindstack {
// Forward declarations.
-class DexFiles;
class Elf;
-class JitDebug;
enum ArchEnum : uint8_t;
struct FrameData {
@@ -67,6 +67,11 @@
: max_frames_(max_frames), maps_(maps), regs_(regs), process_memory_(process_memory) {
frames_.reserve(max_frames);
}
+ Unwinder(size_t max_frames, Maps* maps, std::shared_ptr<Memory> process_memory)
+ : max_frames_(max_frames), maps_(maps), process_memory_(process_memory) {
+ frames_.reserve(max_frames);
+ }
+
~Unwinder() = default;
void Unwind(const std::vector<std::string>* initial_map_names_to_skip = nullptr,
@@ -81,6 +86,10 @@
void SetJitDebug(JitDebug* jit_debug, ArchEnum arch);
+ void SetRegs(Regs* regs) { regs_ = regs; }
+ Maps* GetMaps() { return maps_; }
+ std::shared_ptr<Memory>& GetProcessMemory() { return process_memory_; }
+
// Disabling the resolving of names results in the function name being
// set to an empty string and the function offset being set to zero.
void SetResolveNames(bool resolve) { resolve_names_ = resolve; }
@@ -92,7 +101,9 @@
ErrorCode LastErrorCode() { return last_error_.code; }
uint64_t LastErrorAddress() { return last_error_.address; }
- private:
+ protected:
+ Unwinder(size_t max_frames) : max_frames_(max_frames) { frames_.reserve(max_frames); }
+
void FillInDexFrame();
void FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, uint64_t func_pc,
uint64_t pc_adjustment);
@@ -110,6 +121,22 @@
ErrorData last_error_;
};
+class UnwinderFromPid : public Unwinder {
+ public:
+ UnwinderFromPid(size_t max_frames, pid_t pid) : Unwinder(max_frames), pid_(pid) {}
+ ~UnwinderFromPid() = default;
+
+ bool Init(ArchEnum arch);
+
+ private:
+ pid_t pid_;
+ std::unique_ptr<Maps> maps_ptr_;
+ std::unique_ptr<JitDebug> jit_debug_ptr_;
+#if !defined(NO_LIBDEXFILE_SUPPORT)
+ std::unique_ptr<DexFiles> dex_files_ptr_;
+#endif
+};
+
} // namespace unwindstack
#endif // _LIBUNWINDSTACK_UNWINDER_H
diff --git a/libunwindstack/tests/ElfFake.h b/libunwindstack/tests/ElfFake.h
index c2bd0f6..946bc3c 100644
--- a/libunwindstack/tests/ElfFake.h
+++ b/libunwindstack/tests/ElfFake.h
@@ -72,9 +72,7 @@
bool GetFunctionName(uint64_t, std::string*, uint64_t*) override;
bool GetGlobalVariable(const std::string&, uint64_t*) override;
- bool GetBuildID(std::string*) override {
- return false;
- }
+ std::string GetBuildID() override { return fake_build_id_; }
bool Step(uint64_t, Regs*, Memory*, bool*) override;
@@ -82,6 +80,9 @@
globals_[global] = offset;
}
+ void FakeSetBuildID(std::string& build_id) { fake_build_id_ = build_id; }
+ void FakeSetBuildID(const char* build_id) { fake_build_id_ = build_id; }
+
static void FakePushFunctionData(const FunctionData data) { functions_.push_back(data); }
static void FakePushStepData(const StepData data) { steps_.push_back(data); }
@@ -96,6 +97,7 @@
private:
std::unordered_map<std::string, uint64_t> globals_;
+ std::string fake_build_id_;
static std::deque<FunctionData> functions_;
static std::deque<StepData> steps_;
diff --git a/libunwindstack/tests/ElfInterfaceTest.cpp b/libunwindstack/tests/ElfInterfaceTest.cpp
index 6023dc4..7239749 100644
--- a/libunwindstack/tests/ElfInterfaceTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceTest.cpp
@@ -1228,9 +1228,7 @@
uint64_t load_bias = 0;
ASSERT_TRUE(elf->Init(&load_bias));
- std::string build_id;
- ASSERT_TRUE(elf->GetBuildID(&build_id));
- EXPECT_STREQ(build_id.c_str(), "BUILDID");
+ ASSERT_EQ("BUILDID", elf->GetBuildID());
}
template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
@@ -1292,9 +1290,7 @@
uint64_t load_bias = 0;
ASSERT_TRUE(elf->Init(&load_bias));
- std::string build_id;
- ASSERT_TRUE(elf->GetBuildID(&build_id));
- EXPECT_STREQ(build_id.c_str(), "BUILDID");
+ ASSERT_EQ("BUILDID", elf->GetBuildID());
}
template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
@@ -1346,8 +1342,7 @@
uint64_t load_bias = 0;
ASSERT_TRUE(elf->Init(&load_bias));
- std::string build_id;
- ASSERT_FALSE(elf->GetBuildID(&build_id));
+ ASSERT_EQ("", elf->GetBuildID());
}
template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
@@ -1399,8 +1394,7 @@
uint64_t load_bias = 0;
ASSERT_TRUE(elf->Init(&load_bias));
- std::string build_id;
- ASSERT_FALSE(elf->GetBuildID(&build_id));
+ ASSERT_EQ("", elf->GetBuildID());
}
template <typename Ehdr, typename Shdr, typename Nhdr, typename ElfInterfaceType>
@@ -1452,8 +1446,7 @@
uint64_t load_bias = 0;
ASSERT_TRUE(elf->Init(&load_bias));
- std::string build_id;
- ASSERT_FALSE(elf->GetBuildID(&build_id));
+ ASSERT_EQ("", elf->GetBuildID());
}
TEST_F(ElfInterfaceTest, build_id32) {
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp
index f7689ce..1ff2306 100644
--- a/libunwindstack/tests/ElfTest.cpp
+++ b/libunwindstack/tests/ElfTest.cpp
@@ -311,7 +311,7 @@
void InitHeaders(uint64_t) override {}
bool GetSoname(std::string*) override { return false; }
bool GetFunctionName(uint64_t, std::string*, uint64_t*) override { return false; }
- bool GetBuildID(std::string*) override { return false; }
+ std::string GetBuildID() override { return ""; }
MOCK_METHOD4(Step, bool(uint64_t, Regs*, Memory*, bool*));
MOCK_METHOD2(GetGlobalVariable, bool(const std::string&, uint64_t*));
diff --git a/libunwindstack/tests/MapInfoGetBuildIDTest.cpp b/libunwindstack/tests/MapInfoGetBuildIDTest.cpp
new file mode 100644
index 0000000..3b89c59
--- /dev/null
+++ b/libunwindstack/tests/MapInfoGetBuildIDTest.cpp
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <elf.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include <atomic>
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+
+#include <android-base/test_utils.h>
+
+#include <gtest/gtest.h>
+
+#include <unwindstack/Elf.h>
+#include <unwindstack/MapInfo.h>
+#include <unwindstack/Maps.h>
+#include <unwindstack/Memory.h>
+
+#include "ElfFake.h"
+#include "ElfTestUtils.h"
+#include "MemoryFake.h"
+
+namespace unwindstack {
+
+class MapInfoGetBuildIDTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ tf_.reset(new TemporaryFile);
+
+ memory_ = new MemoryFake;
+ elf_ = new ElfFake(new MemoryFake);
+ elf_interface_ = new ElfInterfaceFake(memory_);
+ elf_->FakeSetInterface(elf_interface_);
+ elf_container_.reset(elf_);
+ map_info_.reset(new MapInfo(nullptr, 0x1000, 0x20000, 0, PROT_READ | PROT_WRITE, tf_->path));
+ }
+
+ void MultipleThreadTest(std::string expected_build_id);
+
+ MemoryFake* memory_;
+ ElfFake* elf_;
+ ElfInterfaceFake* elf_interface_;
+ std::unique_ptr<ElfFake> elf_container_;
+ std::unique_ptr<MapInfo> map_info_;
+ std::unique_ptr<TemporaryFile> tf_;
+};
+
+TEST_F(MapInfoGetBuildIDTest, no_elf_and_no_valid_elf_in_memory) {
+ MapInfo info(nullptr, 0x1000, 0x2000, 0, PROT_READ, "");
+
+ EXPECT_EQ("", info.GetBuildID());
+}
+
+TEST_F(MapInfoGetBuildIDTest, from_elf) {
+ map_info_->elf.reset(elf_container_.release());
+ elf_interface_->FakeSetBuildID("FAKE_BUILD_ID");
+
+ EXPECT_EQ("FAKE_BUILD_ID", map_info_->GetBuildID());
+}
+
+void MapInfoGetBuildIDTest::MultipleThreadTest(std::string expected_build_id) {
+ static constexpr size_t kNumConcurrentThreads = 100;
+
+ std::string build_id_values[kNumConcurrentThreads];
+ std::vector<std::thread*> threads;
+
+ std::atomic_bool wait;
+ wait = true;
+ // Create all of the threads and have them do the GetLoadBias at the same time
+ // to make it likely that a race will occur.
+ for (size_t i = 0; i < kNumConcurrentThreads; i++) {
+ std::thread* thread = new std::thread([i, this, &wait, &build_id_values]() {
+ while (wait)
+ ;
+ build_id_values[i] = map_info_->GetBuildID();
+ });
+ threads.push_back(thread);
+ }
+
+ // Set them all going and wait for the threads to finish.
+ wait = false;
+ for (auto thread : threads) {
+ thread->join();
+ delete thread;
+ }
+
+ // Now verify that all of the elf files are exactly the same and valid.
+ for (size_t i = 0; i < kNumConcurrentThreads; i++) {
+ EXPECT_EQ(expected_build_id, build_id_values[i]) << "Thread " << i << " mismatched.";
+ }
+}
+
+TEST_F(MapInfoGetBuildIDTest, multiple_thread_elf_exists) {
+ map_info_->elf.reset(elf_container_.release());
+ elf_interface_->FakeSetBuildID("FAKE_BUILD_ID");
+
+ MultipleThreadTest("FAKE_BUILD_ID");
+}
+
+static void InitElfData(int fd) {
+ Elf32_Ehdr ehdr;
+ TestInitEhdr(&ehdr, ELFCLASS32, EM_ARM);
+ ehdr.e_shoff = 0x2000;
+ ehdr.e_shnum = 3;
+ ehdr.e_shentsize = sizeof(Elf32_Shdr);
+ ehdr.e_shstrndx = 2;
+ off_t offset = 0;
+ ASSERT_EQ(offset, lseek(fd, offset, SEEK_SET));
+ ASSERT_EQ(static_cast<ssize_t>(sizeof(ehdr)), write(fd, &ehdr, sizeof(ehdr)));
+
+ char note_section[128];
+ Elf32_Nhdr note_header = {};
+ note_header.n_namesz = 4; // "GNU"
+ note_header.n_descsz = 12; // "ELF_BUILDID"
+ note_header.n_type = NT_GNU_BUILD_ID;
+ memcpy(¬e_section, ¬e_header, sizeof(note_header));
+ size_t note_offset = sizeof(note_header);
+ memcpy(¬e_section[note_offset], "GNU", sizeof("GNU"));
+ note_offset += sizeof("GNU");
+ memcpy(¬e_section[note_offset], "ELF_BUILDID", sizeof("ELF_BUILDID"));
+ note_offset += sizeof("ELF_BUILDID");
+
+ Elf32_Shdr shdr = {};
+ shdr.sh_type = SHT_NOTE;
+ shdr.sh_name = 0x500;
+ shdr.sh_offset = 0xb000;
+ shdr.sh_size = sizeof(note_section);
+ offset += ehdr.e_shoff + sizeof(shdr);
+ ASSERT_EQ(offset, lseek(fd, offset, SEEK_SET));
+ ASSERT_EQ(static_cast<ssize_t>(sizeof(shdr)), write(fd, &shdr, sizeof(shdr)));
+
+ // The string data for section header names.
+ memset(&shdr, 0, sizeof(shdr));
+ shdr.sh_type = SHT_STRTAB;
+ shdr.sh_name = 0x20000;
+ shdr.sh_offset = 0xf000;
+ shdr.sh_size = 0x1000;
+ offset += sizeof(shdr);
+ ASSERT_EQ(offset, lseek(fd, offset, SEEK_SET));
+ ASSERT_EQ(static_cast<ssize_t>(sizeof(shdr)), write(fd, &shdr, sizeof(shdr)));
+
+ offset = 0xf500;
+ ASSERT_EQ(offset, lseek(fd, offset, SEEK_SET));
+ ASSERT_EQ(static_cast<ssize_t>(sizeof(".note.gnu.build-id")),
+ write(fd, ".note.gnu.build-id", sizeof(".note.gnu.build-id")));
+
+ offset = 0xb000;
+ ASSERT_EQ(offset, lseek(fd, offset, SEEK_SET));
+ ASSERT_EQ(static_cast<ssize_t>(sizeof(note_section)),
+ write(fd, note_section, sizeof(note_section)));
+}
+
+TEST_F(MapInfoGetBuildIDTest, from_memory) {
+ InitElfData(tf_->fd);
+
+ EXPECT_EQ("ELF_BUILDID", map_info_->GetBuildID());
+}
+
+TEST_F(MapInfoGetBuildIDTest, multiple_thread_elf_exists_in_memory) {
+ InitElfData(tf_->fd);
+
+ MultipleThreadTest("ELF_BUILDID");
+}
+
+} // namespace unwindstack
diff --git a/libunwindstack/tests/MapInfoGetElfTest.cpp b/libunwindstack/tests/MapInfoGetElfTest.cpp
index 99f8fa3..d7b8485 100644
--- a/libunwindstack/tests/MapInfoGetElfTest.cpp
+++ b/libunwindstack/tests/MapInfoGetElfTest.cpp
@@ -88,6 +88,12 @@
ASSERT_TRUE(elf->valid());
EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
EXPECT_EQ(ELFCLASS32, elf->class_type());
+
+ // Now verify that an empty process memory returns an invalid elf object.
+ info.elf.reset();
+ elf = info.GetElf(std::shared_ptr<Memory>(), ARCH_ARM);
+ ASSERT_TRUE(elf != nullptr);
+ ASSERT_FALSE(elf->valid());
}
TEST_F(MapInfoGetElfTest, valid64) {
diff --git a/libunwindstack/tests/MapInfoTest.cpp b/libunwindstack/tests/MapInfoTest.cpp
new file mode 100644
index 0000000..e2cbb98
--- /dev/null
+++ b/libunwindstack/tests/MapInfoTest.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+
+#include <gtest/gtest.h>
+
+#include <unwindstack/MapInfo.h>
+#include <unwindstack/Maps.h>
+
+#include "ElfFake.h"
+
+namespace unwindstack {
+
+TEST(MapInfoTest, maps_constructor_const_char) {
+ MapInfo prev_map(nullptr, 0, 0, 0, 0, "");
+ MapInfo map_info(&prev_map, 1, 2, 3, 4, "map");
+
+ EXPECT_EQ(&prev_map, map_info.prev_map);
+ EXPECT_EQ(1UL, map_info.start);
+ EXPECT_EQ(2UL, map_info.end);
+ EXPECT_EQ(3UL, map_info.offset);
+ EXPECT_EQ(4UL, map_info.flags);
+ EXPECT_EQ("map", map_info.name);
+ EXPECT_EQ(static_cast<uint64_t>(-1), map_info.load_bias);
+ EXPECT_EQ(0UL, map_info.elf_offset);
+ EXPECT_TRUE(map_info.elf.get() == nullptr);
+}
+
+TEST(MapInfoTest, maps_constructor_string) {
+ std::string name("string_map");
+ MapInfo prev_map(nullptr, 0, 0, 0, 0, "");
+ MapInfo map_info(&prev_map, 1, 2, 3, 4, name);
+
+ EXPECT_EQ(&prev_map, map_info.prev_map);
+ EXPECT_EQ(1UL, map_info.start);
+ EXPECT_EQ(2UL, map_info.end);
+ EXPECT_EQ(3UL, map_info.offset);
+ EXPECT_EQ(4UL, map_info.flags);
+ EXPECT_EQ("string_map", map_info.name);
+ EXPECT_EQ(static_cast<uint64_t>(-1), map_info.load_bias);
+ EXPECT_EQ(0UL, map_info.elf_offset);
+ EXPECT_TRUE(map_info.elf.get() == nullptr);
+}
+
+TEST(MapInfoTest, get_function_name) {
+ ElfFake* elf = new ElfFake(nullptr);
+ ElfInterfaceFake* interface = new ElfInterfaceFake(nullptr);
+ elf->FakeSetInterface(interface);
+ interface->FakePushFunctionData(FunctionData("function", 1000));
+
+ MapInfo map_info(nullptr, 1, 2, 3, 4, "");
+ map_info.elf.reset(elf);
+
+ std::string name;
+ uint64_t offset;
+ ASSERT_TRUE(map_info.GetFunctionName(1000, &name, &offset));
+ EXPECT_EQ("function", name);
+ EXPECT_EQ(1000UL, offset);
+}
+
+} // namespace unwindstack
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
index aab9ec2..0588a84 100644
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -210,8 +210,8 @@
ASSERT_EQ(4U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
EXPECT_EQ(
" #00 pc 0001a9f8 libc.so (abort+64)\n"
- " #01 pc 00006a1b libbase.so (_ZN7android4base14DefaultAborterEPKc+6)\n"
- " #02 pc 00007441 libbase.so (_ZN7android4base10LogMessageD2Ev+748)\n"
+ " #01 pc 00006a1b libbase.so (android::base::DefaultAborter(char const*)+6)\n"
+ " #02 pc 00007441 libbase.so (android::base::LogMessage::~LogMessage()+748)\n"
" #03 pc 00015147 /does/not/exist/libhidlbase.so\n",
frame_info);
EXPECT_EQ(0xf31ea9f8U, unwinder.frames()[0].pc);
@@ -234,9 +234,10 @@
ASSERT_EQ(2U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
EXPECT_EQ(
" #00 pc 0006dc49 libandroid_runtime.so "
- "(_ZN7android14AndroidRuntime15javaThreadShellEPv+80)\n"
+ "(android::AndroidRuntime::javaThreadShell(void*)+80)\n"
" #01 pc 0006dce5 libandroid_runtime.so "
- "(_ZN7android14AndroidRuntime19javaCreateThreadEtcEPFiPvES1_PKcijPS1_)\n",
+ "(android::AndroidRuntime::javaCreateThreadEtc(int (*)(void*), void*, char const*, int, "
+ "unsigned int, void**))\n",
frame_info);
EXPECT_EQ(0xf1f6dc49U, unwinder.frames()[0].pc);
EXPECT_EQ(0xd8fe6930U, unwinder.frames()[0].sp);
@@ -257,10 +258,10 @@
" #01 pc 000000000042a078 libunwindstack_test (SignalMiddleFunction+8)\n"
" #02 pc 000000000042a08c libunwindstack_test (SignalOuterFunction+8)\n"
" #03 pc 000000000042d8fc libunwindstack_test "
- "(_ZN11unwindstackL19RemoteThroughSignalEij+20)\n"
+ "(unwindstack::RemoteThroughSignal(int, unsigned int)+20)\n"
" #04 pc 000000000042d8d8 libunwindstack_test "
- "(_ZN11unwindstack37UnwindTest_remote_through_signal_Test8TestBodyEv+32)\n"
- " #05 pc 0000000000455d70 libunwindstack_test (_ZN7testing4Test3RunEv+392)\n",
+ "(unwindstack::UnwindTest_remote_through_signal_Test::TestBody()+32)\n"
+ " #05 pc 0000000000455d70 libunwindstack_test (testing::Test::Run()+392)\n",
frame_info);
EXPECT_EQ(0x64d09d4fd8U, unwinder.frames()[0].pc);
EXPECT_EQ(0x7fe0d84040U, unwinder.frames()[0].sp);
@@ -296,54 +297,57 @@
std::string frame_info(DumpFrames(unwinder));
ASSERT_EQ(69U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
EXPECT_EQ(
- " #00 pc 00068fb8 libarttestd.so (_ZN3artL13CauseSegfaultEv+72)\n"
+ " #00 pc 00068fb8 libarttestd.so (art::CauseSegfault()+72)\n"
" #01 pc 00067f00 libarttestd.so (Java_Main_unwindInProcess+10032)\n"
" #02 pc 000021a8 137-cfi.odex (offset 0x2000) (boolean Main.unwindInProcess(boolean, int, "
"boolean)+136)\n"
" #03 pc 0000fe80 anonymous:ee74c000 (boolean Main.bar(boolean)+64)\n"
" #04 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n"
" #05 pc 00146ab5 libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+885)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+885)\n"
" #06 pc 0039cf0d libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+653)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
" #07 pc 00392552 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+354)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+354)\n"
" #08 pc 0039399a libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+234)\n"
" #09 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
" #10 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
" #11 pc 0000fe03 anonymous:ee74c000 (int Main.compare(Main, Main)+51)\n"
" #12 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n"
" #13 pc 00146ab5 libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+885)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+885)\n"
" #14 pc 0039cf0d libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+653)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
" #15 pc 00392552 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+354)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+354)\n"
" #16 pc 0039399a libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+234)\n"
" #17 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
" #18 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
" #19 pc 0000fd3b anonymous:ee74c000 (int Main.compare(java.lang.Object, "
"java.lang.Object)+107)\n"
" #20 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n"
" #21 pc 00146ab5 libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+885)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+885)\n"
" #22 pc 0039cf0d libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+653)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
" #23 pc 00392552 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+354)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+354)\n"
" #24 pc 0039399a libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+234)\n"
" #25 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
" #26 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
" #27 pc 0000fbdb anonymous:ee74c000 (int "
@@ -351,81 +355,86 @@
"java.util.Comparator)+331)\n"
" #28 pc 006ad6a2 libartd.so (art_quick_invoke_static_stub+418)\n"
" #29 pc 00146acb libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+907)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+907)\n"
" #30 pc 0039cf0d libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+653)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
" #31 pc 00392552 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+354)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+354)\n"
" #32 pc 0039399a libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+234)\n"
" #33 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
" #34 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
" #35 pc 0000f624 anonymous:ee74c000 (boolean Main.foo()+164)\n"
" #36 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n"
" #37 pc 00146ab5 libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+885)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+885)\n"
" #38 pc 0039cf0d libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+653)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
" #39 pc 00392552 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+354)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+354)\n"
" #40 pc 0039399a libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+234)\n"
" #41 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
" #42 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
" #43 pc 0000eedb anonymous:ee74c000 (void Main.runPrimary()+59)\n"
" #44 pc 006ad4d2 libartd.so (art_quick_invoke_stub+338)\n"
" #45 pc 00146ab5 libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+885)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+885)\n"
" #46 pc 0039cf0d libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+653)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
" #47 pc 00392552 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+354)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+354)\n"
" #48 pc 0039399a libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+234)\n"
" #49 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
" #50 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
" #51 pc 0000ac21 anonymous:ee74c000 (void Main.main(java.lang.String[])+97)\n"
" #52 pc 006ad6a2 libartd.so (art_quick_invoke_static_stub+418)\n"
" #53 pc 00146acb libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+907)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+907)\n"
" #54 pc 0039cf0d libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+653)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+653)\n"
" #55 pc 00392552 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+354)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+354)\n"
" #56 pc 0039399a libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+234)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+234)\n"
" #57 pc 00684362 libartd.so (artQuickToInterpreterBridge+1058)\n"
" #58 pc 006b35bd libartd.so (art_quick_to_interpreter_bridge+77)\n"
" #59 pc 006ad6a2 libartd.so (art_quick_invoke_static_stub+418)\n"
" #60 pc 00146acb libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+907)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+907)\n"
" #61 pc 005aac95 libartd.so "
- "(_ZN3artL18InvokeWithArgArrayERKNS_33ScopedObjectAccessAlreadyRunnableEPNS_9ArtMethodEPNS_"
- "8ArgArrayEPNS_6JValueEPKc+85)\n"
+ "(art::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, "
+ "art::ArgArray*, art::JValue*, char const*)+85)\n"
" #62 pc 005aab5a libartd.so "
- "(_ZN3art17InvokeWithVarArgsERKNS_33ScopedObjectAccessAlreadyRunnableEP8_jobjectP10_"
- "jmethodIDPc+362)\n"
+ "(art::InvokeWithVarArgs(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, "
+ "_jmethodID*, char*)+362)\n"
" #63 pc 0048a3dd libartd.so "
- "(_ZN3art3JNI21CallStaticVoidMethodVEP7_JNIEnvP7_jclassP10_jmethodIDPc+125)\n"
+ "(art::JNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, char*)+125)\n"
" #64 pc 0018448c libartd.so "
- "(_ZN3art8CheckJNI11CallMethodVEPKcP7_JNIEnvP8_jobjectP7_jclassP10_jmethodIDPcNS_"
- "9Primitive4TypeENS_10InvokeTypeE+1964)\n"
+ "(art::CheckJNI::CallMethodV(char const*, _JNIEnv*, _jobject*, _jclass*, _jmethodID*, char*, "
+ "art::Primitive::Type, art::InvokeType)+1964)\n"
" #65 pc 0017cf06 libartd.so "
- "(_ZN3art8CheckJNI21CallStaticVoidMethodVEP7_JNIEnvP7_jclassP10_jmethodIDPc+70)\n"
+ "(art::CheckJNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, char*)+70)\n"
" #66 pc 00001d8c dalvikvm32 "
- "(_ZN7_JNIEnv20CallStaticVoidMethodEP7_jclassP10_jmethodIDz+60)\n"
+ "(_JNIEnv::CallStaticVoidMethod(_jclass*, _jmethodID*, ...)+60)\n"
" #67 pc 00001a80 dalvikvm32 (main+1312)\n"
" #68 pc 00018275 libc.so\n",
frame_info);
@@ -597,32 +606,34 @@
" #03 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
" #04 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n"
" #05 pc 000bf7a9 libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+864)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+864)\n"
" #06 pc 00247833 libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+382)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
" #07 pc 0022e935 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+244)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+244)\n"
" #08 pc 0022f71d libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+128)\n"
" #09 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
" #10 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
" #11 pc 00011c31 anonymous:e2796000 (int Main.compare(Main, Main)+64)\n"
" #12 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
" #13 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n"
" #14 pc 000bf7a9 libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+864)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+864)\n"
" #15 pc 00247833 libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+382)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
" #16 pc 0022e935 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+244)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+244)\n"
" #17 pc 0022f71d libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+128)\n"
" #18 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
" #19 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
" #20 pc 00011b77 anonymous:e2796000 (int Main.compare(java.lang.Object, "
@@ -630,16 +641,17 @@
" #21 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
" #22 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n"
" #23 pc 000bf7a9 libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+864)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+864)\n"
" #24 pc 00247833 libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+382)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
" #25 pc 0022e935 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+244)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+244)\n"
" #26 pc 0022f71d libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+128)\n"
" #27 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
" #28 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
" #29 pc 00011a29 anonymous:e2796000 (int "
@@ -648,85 +660,90 @@
" #30 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
" #31 pc 0046722f libartd.so (art_quick_invoke_static_stub+226)\n"
" #32 pc 000bf7bb libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+882)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+882)\n"
" #33 pc 00247833 libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+382)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
" #34 pc 0022e935 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+244)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+244)\n"
" #35 pc 0022f71d libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+128)\n"
" #36 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
" #37 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
" #38 pc 0001139b anonymous:e2796000 (boolean Main.foo()+178)\n"
" #39 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
" #40 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n"
" #41 pc 000bf7a9 libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+864)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+864)\n"
" #42 pc 00247833 libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+382)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
" #43 pc 0022e935 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+244)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+244)\n"
" #44 pc 0022f71d libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+128)\n"
" #45 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
" #46 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
" #47 pc 00010aa7 anonymous:e2796000 (void Main.runPrimary()+70)\n"
" #48 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
" #49 pc 00467129 libartd.so (art_quick_invoke_stub+228)\n"
" #50 pc 000bf7a9 libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+864)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+864)\n"
" #51 pc 00247833 libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+382)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
" #52 pc 0022e935 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+244)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+244)\n"
" #53 pc 0022f71d libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+128)\n"
" #54 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
" #55 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
" #56 pc 0000ba99 anonymous:e2796000 (void Main.main(java.lang.String[])+144)\n"
" #57 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
" #58 pc 0046722f libartd.so (art_quick_invoke_static_stub+226)\n"
" #59 pc 000bf7bb libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+882)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+882)\n"
" #60 pc 00247833 libartd.so "
- "(_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPNS_"
- "11ShadowFrameEtPNS_6JValueE+382)\n"
+ "(art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, "
+ "art::ShadowFrame*, unsigned short, art::JValue*)+382)\n"
" #61 pc 0022e935 libartd.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+244)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+244)\n"
" #62 pc 0022f71d libartd.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+128)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+128)\n"
" #63 pc 00442865 libartd.so (artQuickToInterpreterBridge+796)\n"
" #64 pc 004666ff libartd.so (art_quick_to_interpreter_bridge+30)\n"
" #65 pc 00462175 libartd.so (art_quick_invoke_stub_internal+68)\n"
" #66 pc 0046722f libartd.so (art_quick_invoke_static_stub+226)\n"
" #67 pc 000bf7bb libartd.so "
- "(_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+882)\n"
+ "(art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char "
+ "const*)+882)\n"
" #68 pc 003b292d libartd.so "
- "(_ZN3artL18InvokeWithArgArrayERKNS_33ScopedObjectAccessAlreadyRunnableEPNS_9ArtMethodEPNS_"
- "8ArgArrayEPNS_6JValueEPKc+52)\n"
+ "(art::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, "
+ "art::ArgArray*, art::JValue*, char const*)+52)\n"
" #69 pc 003b26c3 libartd.so "
- "(_ZN3art17InvokeWithVarArgsERKNS_33ScopedObjectAccessAlreadyRunnableEP8_jobjectP10_"
- "jmethodIDSt9__va_list+210)\n"
+ "(art::InvokeWithVarArgs(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, "
+ "_jmethodID*, std::__va_list)+210)\n"
" #70 pc 00308411 libartd.so "
- "(_ZN3art3JNI21CallStaticVoidMethodVEP7_JNIEnvP7_jclassP10_jmethodIDSt9__va_list+76)\n"
+ "(art::JNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, std::__va_list)+76)\n"
" #71 pc 000e6a9f libartd.so "
- "(_ZN3art8CheckJNI11CallMethodVEPKcP7_JNIEnvP8_jobjectP7_jclassP10_jmethodIDSt9__va_listNS_"
- "9Primitive4TypeENS_10InvokeTypeE+1486)\n"
+ "(art::CheckJNI::CallMethodV(char const*, _JNIEnv*, _jobject*, _jclass*, _jmethodID*, "
+ "std::__va_list, art::Primitive::Type, art::InvokeType)+1486)\n"
" #72 pc 000e19b9 libartd.so "
- "(_ZN3art8CheckJNI21CallStaticVoidMethodVEP7_JNIEnvP7_jclassP10_jmethodIDSt9__va_list+40)\n"
+ "(art::CheckJNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, std::__va_list)+40)\n"
" #73 pc 0000159f dalvikvm32 "
- "(_ZN7_JNIEnv20CallStaticVoidMethodEP7_jclassP10_jmethodIDz+30)\n"
+ "(_JNIEnv::CallStaticVoidMethod(_jclass*, _jmethodID*, ...)+30)\n"
" #74 pc 00001349 dalvikvm32 (main+896)\n"
" #75 pc 000850c9 libc.so\n",
frame_info);
@@ -997,41 +1014,44 @@
"(com.example.simpleperf.simpleperfexamplewithnative.MixActivity$1.run+60)\n"
" #02 pc 004135bb libart.so (art_quick_osr_stub+42)\n"
" #03 pc 002657a5 libart.so "
- "(_ZN3art3jit3Jit25MaybeDoOnStackReplacementEPNS_6ThreadEPNS_9ArtMethodEjiPNS_6JValueE+876)\n"
+ "(art::jit::Jit::MaybeDoOnStackReplacement(art::Thread*, art::ArtMethod*, unsigned int, int, "
+ "art::JValue*)+876)\n"
" #04 pc 004021a7 libart.so (MterpMaybeDoOnStackReplacement+86)\n"
" #05 pc 00412474 libart.so (ExecuteMterpImpl+66164)\n"
" #06 pc cd8365b0 <unknown>\n" // symbol in dex file
" #07 pc 001d7f1b libart.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+374)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+374)\n"
" #08 pc 001dc593 libart.so "
- "(_ZN3art11interpreter33ArtInterpreterToInterpreterBridgeEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameEPNS_6JValueE+154)\n"
+ "(art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, "
+ "art::CodeItemDataAccessor const&, art::ShadowFrame*, art::JValue*)+154)\n"
" #09 pc 001f4d01 libart.so "
- "(_ZN3art11interpreter6DoCallILb0ELb0EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_"
- "11InstructionEtPNS_6JValueE+732)\n"
+ "(bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, "
+ "art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*)+732)\n"
" #10 pc 003fe427 libart.so (MterpInvokeInterface+1354)\n"
" #11 pc 00405b94 libart.so (ExecuteMterpImpl+14740)\n"
" #12 pc 7004873e <unknown>\n" // symbol in dex file
" #13 pc 001d7f1b libart.so "
- "(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
- "6JValueEb+374)\n"
+ "(art::interpreter::Execute(art::Thread*, art::CodeItemDataAccessor const&, "
+ "art::ShadowFrame&, art::JValue, bool)+374)\n"
" #14 pc 001dc4d5 libart.so "
- "(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
- "20CodeItemDataAccessorEPNS_11ShadowFrameE+92)\n"
+ "(art::interpreter::EnterInterpreterFromEntryPoint(art::Thread*, art::CodeItemDataAccessor "
+ "const&, art::ShadowFrame*)+92)\n"
" #15 pc 003f25ab libart.so (artQuickToInterpreterBridge+970)\n"
" #16 pc 00417aff libart.so (art_quick_to_interpreter_bridge+30)\n"
" #17 pc 00413575 libart.so (art_quick_invoke_stub_internal+68)\n"
" #18 pc 00418531 libart.so (art_quick_invoke_stub+236)\n"
- " #19 pc 000b468d libart.so (_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+136)\n"
+ " #19 pc 000b468d libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned "
+ "int, art::JValue*, char const*)+136)\n"
" #20 pc 00362f49 libart.so "
- "(_ZN3art12_GLOBAL__N_118InvokeWithArgArrayERKNS_33ScopedObjectAccessAlreadyRunnableEPNS_"
- "9ArtMethodEPNS0_8ArgArrayEPNS_6JValueEPKc+52)\n"
+ "(art::(anonymous namespace)::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable "
+ "const&, art::ArtMethod*, art::(anonymous namespace)::ArgArray*, art::JValue*, char "
+ "const*)+52)\n"
" #21 pc 00363cd9 libart.so "
- "(_ZN3art35InvokeVirtualOrInterfaceWithJValuesERKNS_33ScopedObjectAccessAlreadyRunnableEP8_"
- "jobjectP10_jmethodIDP6jvalue+332)\n"
- " #22 pc 003851dd libart.so (_ZN3art6Thread14CreateCallbackEPv+868)\n"
- " #23 pc 00062925 libc.so (_ZL15__pthread_startPv+22)\n"
+ "(art::InvokeVirtualOrInterfaceWithJValues(art::ScopedObjectAccessAlreadyRunnable const&, "
+ "_jobject*, _jmethodID*, jvalue*)+332)\n"
+ " #22 pc 003851dd libart.so (art::Thread::CreateCallback(void*)+868)\n"
+ " #23 pc 00062925 libc.so (__pthread_start(void*)+22)\n"
" #24 pc 0001de39 libc.so (__start_thread+24)\n",
frame_info);
EXPECT_EQ(0xd025c788U, unwinder.frames()[0].pc);
@@ -1107,8 +1127,8 @@
"(com.example.simpleperf.simpleperfexamplewithnative.MixActivity$1.run+60)\n"
" #02 pc 004135bb libart.so (art_quick_osr_stub+42)\n"
- " #03 pc 003851dd libart.so (_ZN3art6Thread14CreateCallbackEPv+868)\n"
- " #04 pc 00062925 libc.so (_ZL15__pthread_startPv+22)\n"
+ " #03 pc 003851dd libart.so (art::Thread::CreateCallback(void*)+868)\n"
+ " #04 pc 00062925 libc.so (__pthread_start(void*)+22)\n"
" #05 pc 0001de39 libc.so (__start_thread+24)\n",
frame_info);
@@ -1139,22 +1159,22 @@
" #01 pc 0032bfeb libunwindstack_test (SignalMiddleFunction+2)\n"
" #02 pc 0032bff3 libunwindstack_test (SignalOuterFunction+2)\n"
" #03 pc 0032fed3 libunwindstack_test "
- "(_ZN11unwindstackL19SignalCallerHandlerEiP7siginfoPv+26)\n"
+ "(unwindstack::SignalCallerHandler(int, siginfo*, void*)+26)\n"
" #04 pc 00026528 libc.so\n"
" #05 pc 00000000 <unknown>\n"
" #06 pc 0032c2d9 libunwindstack_test (InnerFunction+736)\n"
" #07 pc 0032cc4f libunwindstack_test (MiddleFunction+42)\n"
" #08 pc 0032cc81 libunwindstack_test (OuterFunction+42)\n"
" #09 pc 0032e547 libunwindstack_test "
- "(_ZN11unwindstackL19RemoteThroughSignalEij+270)\n"
+ "(unwindstack::RemoteThroughSignal(int, unsigned int)+270)\n"
" #10 pc 0032ed99 libunwindstack_test "
- "(_ZN11unwindstack55UnwindTest_remote_through_signal_with_invalid_func_Test8TestBodyEv+16)\n"
- " #11 pc 00354453 libunwindstack_test (_ZN7testing4Test3RunEv+154)\n"
- " #12 pc 00354de7 libunwindstack_test (_ZN7testing8TestInfo3RunEv+194)\n"
- " #13 pc 00355105 libunwindstack_test (_ZN7testing8TestCase3RunEv+180)\n"
+ "(unwindstack::UnwindTest_remote_through_signal_with_invalid_func_Test::TestBody()+16)\n"
+ " #11 pc 00354453 libunwindstack_test (testing::Test::Run()+154)\n"
+ " #12 pc 00354de7 libunwindstack_test (testing::TestInfo::Run()+194)\n"
+ " #13 pc 00355105 libunwindstack_test (testing::TestCase::Run()+180)\n"
" #14 pc 0035a215 libunwindstack_test "
- "(_ZN7testing8internal12UnitTestImpl11RunAllTestsEv+664)\n"
- " #15 pc 00359f4f libunwindstack_test (_ZN7testing8UnitTest3RunEv+110)\n"
+ "(testing::internal::UnitTestImpl::RunAllTests()+664)\n"
+ " #15 pc 00359f4f libunwindstack_test (testing::UnitTest::Run()+110)\n"
" #16 pc 0034d3db libunwindstack_test (main+38)\n"
" #17 pc 00092c0d libc.so (__libc_init+48)\n"
" #18 pc 0004202f libunwindstack_test (_start_main+38)\n",
@@ -1213,9 +1233,9 @@
EXPECT_EQ(
" #00 pc 0005138c libc.so (__ioctl+8)\n"
" #01 pc 0002140f libc.so (ioctl+30)\n"
- " #02 pc 00039535 libbinder.so (_ZN7android14IPCThreadState14talkWithDriverEb+204)\n"
- " #03 pc 00039633 libbinder.so (_ZN7android14IPCThreadState20getAndExecuteCommandEv+10)\n"
- " #04 pc 00039b57 libbinder.so (_ZN7android14IPCThreadState14joinThreadPoolEb+38)\n"
+ " #02 pc 00039535 libbinder.so (android::IPCThreadState::talkWithDriver(bool)+204)\n"
+ " #03 pc 00039633 libbinder.so (android::IPCThreadState::getAndExecuteCommand()+10)\n"
+ " #04 pc 00039b57 libbinder.so (android::IPCThreadState::joinThreadPool(bool)+38)\n"
" #05 pc 00000c21 mediaserver (main+104)\n"
" #06 pc 00084b89 libc.so (__libc_init+48)\n"
" #07 pc 00000b77 mediaserver (_start_main+38)\n",
diff --git a/libunwindstack/tests/UnwindTest.cpp b/libunwindstack/tests/UnwindTest.cpp
index ea992c7..a91bd95 100644
--- a/libunwindstack/tests/UnwindTest.cpp
+++ b/libunwindstack/tests/UnwindTest.cpp
@@ -44,6 +44,13 @@
namespace unwindstack {
+enum TestTypeEnum : uint8_t {
+ TEST_TYPE_LOCAL_UNWINDER = 0,
+ TEST_TYPE_LOCAL_UNWINDER_FROM_PID,
+ TEST_TYPE_REMOTE,
+ TEST_TYPE_REMOTE_WITH_INVALID_CALL,
+};
+
static std::atomic_bool g_ready;
static volatile bool g_ready_for_remote;
static volatile bool g_signal_ready_for_remote;
@@ -88,10 +95,10 @@
SignalOuterFunction();
}
-static std::string ErrorMsg(const std::vector<const char*>& function_names, Unwinder& unwinder) {
+static std::string ErrorMsg(const std::vector<const char*>& function_names, Unwinder* unwinder) {
std::string unwind;
- for (size_t i = 0; i < unwinder.NumFrames(); i++) {
- unwind += unwinder.FormatFrame(i) + '\n';
+ for (size_t i = 0; i < unwinder->NumFrames(); i++) {
+ unwind += unwinder->FormatFrame(i) + '\n';
}
return std::string(
@@ -100,14 +107,10 @@
function_names.front() + "\n" + "Unwind data:\n" + unwind;
}
-static void VerifyUnwind(pid_t pid, Maps* maps, Regs* regs,
- std::vector<const char*> expected_function_names) {
- auto process_memory(Memory::CreateProcessMemory(pid));
+static void VerifyUnwind(Unwinder* unwinder, std::vector<const char*> expected_function_names) {
+ unwinder->Unwind();
- Unwinder unwinder(512, maps, regs, process_memory);
- unwinder.Unwind();
-
- for (auto& frame : unwinder.frames()) {
+ for (auto& frame : unwinder->frames()) {
if (frame.function_name == expected_function_names.back()) {
expected_function_names.pop_back();
if (expected_function_names.empty()) {
@@ -119,35 +122,55 @@
ASSERT_TRUE(expected_function_names.empty()) << ErrorMsg(expected_function_names, unwinder);
}
+static void VerifyUnwind(pid_t pid, Maps* maps, Regs* regs,
+ std::vector<const char*> expected_function_names) {
+ auto process_memory(Memory::CreateProcessMemory(pid));
+
+ Unwinder unwinder(512, maps, regs, process_memory);
+ VerifyUnwind(&unwinder, expected_function_names);
+}
+
// This test assumes that this code is compiled with optimizations turned
// off. If this doesn't happen, then all of the calls will be optimized
// away.
-extern "C" void InnerFunction(bool local, bool trigger_invalid_call) {
- if (local) {
- LocalMaps maps;
- ASSERT_TRUE(maps.Parse());
- std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
- RegsGetLocal(regs.get());
-
- VerifyUnwind(getpid(), &maps, regs.get(), kFunctionOrder);
- } else {
+extern "C" void InnerFunction(TestTypeEnum test_type) {
+ if (test_type == TEST_TYPE_REMOTE || test_type == TEST_TYPE_REMOTE_WITH_INVALID_CALL) {
g_ready_for_remote = true;
g_ready = true;
- if (trigger_invalid_call) {
+ if (test_type == TEST_TYPE_REMOTE_WITH_INVALID_CALL) {
void (*crash_func)() = nullptr;
crash_func();
}
while (!g_finish.load()) {
}
+ return;
}
+
+ std::unique_ptr<Unwinder> unwinder;
+ std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
+ RegsGetLocal(regs.get());
+ std::unique_ptr<Maps> maps;
+
+ if (test_type == TEST_TYPE_LOCAL_UNWINDER) {
+ maps.reset(new LocalMaps());
+ ASSERT_TRUE(maps->Parse());
+ auto process_memory(Memory::CreateProcessMemory(getpid()));
+ unwinder.reset(new Unwinder(512, maps.get(), regs.get(), process_memory));
+ } else {
+ UnwinderFromPid* unwinder_from_pid = new UnwinderFromPid(512, getpid());
+ ASSERT_TRUE(unwinder_from_pid->Init(regs->Arch()));
+ unwinder_from_pid->SetRegs(regs.get());
+ unwinder.reset(unwinder_from_pid);
+ }
+ VerifyUnwind(unwinder.get(), kFunctionOrder);
}
-extern "C" void MiddleFunction(bool local, bool trigger_invalid_call) {
- InnerFunction(local, trigger_invalid_call);
+extern "C" void MiddleFunction(TestTypeEnum test_type) {
+ InnerFunction(test_type);
}
-extern "C" void OuterFunction(bool local, bool trigger_invalid_call) {
- MiddleFunction(local, trigger_invalid_call);
+extern "C" void OuterFunction(TestTypeEnum test_type) {
+ MiddleFunction(test_type);
}
class UnwindTest : public ::testing::Test {
@@ -156,7 +179,11 @@
};
TEST_F(UnwindTest, local) {
- OuterFunction(true, false);
+ OuterFunction(TEST_TYPE_LOCAL_UNWINDER);
+}
+
+TEST_F(UnwindTest, local_use_from_pid) {
+ OuterFunction(TEST_TYPE_LOCAL_UNWINDER_FROM_PID);
}
void WaitForRemote(pid_t pid, uint64_t addr, bool leave_attached, bool* completed) {
@@ -191,7 +218,7 @@
TEST_F(UnwindTest, remote) {
pid_t pid;
if ((pid = fork()) == 0) {
- OuterFunction(false, false);
+ OuterFunction(TEST_TYPE_REMOTE);
exit(0);
}
ASSERT_NE(-1, pid);
@@ -212,11 +239,39 @@
<< "ptrace detach failed with unexpected error: " << strerror(errno);
}
+TEST_F(UnwindTest, unwind_from_pid_remote) {
+ pid_t pid;
+ if ((pid = fork()) == 0) {
+ OuterFunction(TEST_TYPE_REMOTE);
+ exit(0);
+ }
+ ASSERT_NE(-1, pid);
+ TestScopedPidReaper reap(pid);
+
+ bool completed;
+ WaitForRemote(pid, reinterpret_cast<uint64_t>(&g_ready_for_remote), true, &completed);
+ ASSERT_TRUE(completed) << "Timed out waiting for remote process to be ready.";
+
+ std::unique_ptr<Regs> regs(Regs::RemoteGet(pid));
+ ASSERT_TRUE(regs.get() != nullptr);
+
+ UnwinderFromPid unwinder(512, pid);
+ ASSERT_TRUE(unwinder.Init(regs->Arch()));
+ unwinder.SetRegs(regs.get());
+
+ VerifyUnwind(&unwinder, kFunctionOrder);
+
+ // Verify that calling the same object works again.
+
+ ASSERT_EQ(0, ptrace(PTRACE_DETACH, pid, 0, 0))
+ << "ptrace detach failed with unexpected error: " << strerror(errno);
+}
+
TEST_F(UnwindTest, from_context) {
std::atomic_int tid(0);
std::thread thread([&]() {
tid = syscall(__NR_gettid);
- OuterFunction(false, false);
+ OuterFunction(TEST_TYPE_REMOTE);
});
struct sigaction act, oldact;
@@ -266,7 +321,7 @@
act.sa_flags = SA_RESTART | SA_ONSTACK | sa_flags;
ASSERT_EQ(0, sigaction(signal, &act, &oldact));
- OuterFunction(false, signal == SIGSEGV);
+ OuterFunction(signal != SIGSEGV ? TEST_TYPE_REMOTE : TEST_TYPE_REMOTE_WITH_INVALID_CALL);
exit(0);
}
ASSERT_NE(-1, pid);
diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp
index 1fdeee5..49aeeb3 100644
--- a/libunwindstack/tests/UnwinderTest.cpp
+++ b/libunwindstack/tests/UnwinderTest.cpp
@@ -1080,6 +1080,12 @@
Unwinder::FormatFrame(frame, false));
EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (function)", Unwinder::FormatFrame(frame, true));
+ // Verify the function name is demangled.
+ frame.function_name = "_ZN4funcEv";
+ EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so (func())",
+ Unwinder::FormatFrame(frame, false));
+ EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so (func())", Unwinder::FormatFrame(frame, true));
+
frame.function_name = "";
EXPECT_EQ(" #01 pc 0000000000001000 /fake/libfake.so", Unwinder::FormatFrame(frame, false));
EXPECT_EQ(" #01 pc 00001000 /fake/libfake.so", Unwinder::FormatFrame(frame, true));
diff --git a/libunwindstack/tools/unwind.cpp b/libunwindstack/tools/unwind.cpp
index e729453..1812e50 100644
--- a/libunwindstack/tools/unwind.cpp
+++ b/libunwindstack/tools/unwind.cpp
@@ -57,12 +57,6 @@
}
void DoUnwind(pid_t pid) {
- unwindstack::RemoteMaps remote_maps(pid);
- if (!remote_maps.Parse()) {
- printf("Failed to parse map data.\n");
- return;
- }
-
unwindstack::Regs* regs = unwindstack::Regs::RemoteGet(pid);
if (regs == nullptr) {
printf("Unable to get remote reg data\n");
@@ -95,15 +89,13 @@
}
printf("\n");
- auto process_memory = unwindstack::Memory::CreateProcessMemory(pid);
- unwindstack::Unwinder unwinder(128, &remote_maps, regs, process_memory);
+ unwindstack::UnwinderFromPid unwinder(1024, pid);
+ if (!unwinder.Init(regs->Arch())) {
+ printf("Failed to init unwinder object.\n");
+ return;
+ }
- unwindstack::JitDebug jit_debug(process_memory);
- unwinder.SetJitDebug(&jit_debug, regs->Arch());
-
- unwindstack::DexFiles dex_files(process_memory);
- unwinder.SetDexFiles(&dex_files, regs->Arch());
-
+ unwinder.SetRegs(regs);
unwinder.Unwind();
// Print the frames.
diff --git a/libunwindstack/tools/unwind_for_offline.cpp b/libunwindstack/tools/unwind_for_offline.cpp
index 5ae8874..4f67d67 100644
--- a/libunwindstack/tools/unwind_for_offline.cpp
+++ b/libunwindstack/tools/unwind_for_offline.cpp
@@ -240,12 +240,6 @@
return 1;
}
- unwindstack::RemoteMaps maps(pid);
- if (!maps.Parse()) {
- printf("Unable to parse maps.\n");
- return 1;
- }
-
// Save the current state of the registers.
if (!SaveRegs(regs)) {
return 1;
@@ -253,35 +247,38 @@
// Do an unwind so we know how much of the stack to save, and what
// elf files are involved.
+ unwindstack::UnwinderFromPid unwinder(1024, pid);
+ if (!unwinder.Init(regs->Arch())) {
+ printf("Unable to init unwinder object.\n");
+ return 1;
+ }
+ unwinder.SetRegs(regs);
uint64_t sp = regs->sp();
- auto process_memory = unwindstack::Memory::CreateProcessMemory(pid);
- unwindstack::JitDebug jit_debug(process_memory);
- unwindstack::Unwinder unwinder(1024, &maps, regs, process_memory);
- unwinder.SetJitDebug(&jit_debug, regs->Arch());
unwinder.Unwind();
std::unordered_map<uint64_t, map_info_t> maps_by_start;
std::vector<std::pair<uint64_t, uint64_t>> stacks;
+ unwindstack::Maps* maps = unwinder.GetMaps();
uint64_t sp_map_start = 0;
- unwindstack::MapInfo* map_info = maps.Find(sp);
+ unwindstack::MapInfo* map_info = maps->Find(sp);
if (map_info != nullptr) {
stacks.emplace_back(std::make_pair(sp, map_info->end));
sp_map_start = map_info->start;
}
for (const auto& frame : unwinder.frames()) {
- map_info = maps.Find(frame.sp);
+ map_info = maps->Find(frame.sp);
if (map_info != nullptr && sp_map_start != map_info->start) {
stacks.emplace_back(std::make_pair(frame.sp, map_info->end));
sp_map_start = map_info->start;
}
if (maps_by_start.count(frame.map_start) == 0) {
- map_info = maps.Find(frame.map_start);
+ map_info = maps->Find(frame.map_start);
auto info = FillInAndGetMapInfo(maps_by_start, map_info);
bool file_copied = false;
- SaveMapInformation(process_memory, info, &file_copied);
+ SaveMapInformation(unwinder.GetProcessMemory(), info, &file_copied);
// If you are using a a linker that creates two maps (one read-only, one
// read-executable), it's necessary to capture the previous map
@@ -291,7 +288,7 @@
prev_map->flags == PROT_READ && map_info->name == prev_map->name &&
maps_by_start.count(prev_map->start) == 0) {
info = FillInAndGetMapInfo(maps_by_start, prev_map);
- SaveMapInformation(process_memory, info, &file_copied);
+ SaveMapInformation(unwinder.GetProcessMemory(), info, &file_copied);
}
}
}
diff --git a/libunwindstack/tools/unwind_info.cpp b/libunwindstack/tools/unwind_info.cpp
index 3f2dfb0..3f5b88b 100644
--- a/libunwindstack/tools/unwind_info.cpp
+++ b/libunwindstack/tools/unwind_info.cpp
@@ -123,8 +123,8 @@
printf("Soname: %s\n", soname.c_str());
}
- std::string build_id;
- if (elf.GetBuildID(&build_id)) {
+ std::string build_id = elf.GetBuildID();
+ if (!build_id.empty()) {
printf("Build ID: ");
for (size_t i = 0; i < build_id.size(); ++i) {
printf("%02hhx", build_id[i]);
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 7794f81..ca78c38 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -16,6 +16,7 @@
#define LOG_TAG "lowmemorykiller"
+#include <dirent.h>
#include <errno.h>
#include <inttypes.h>
#include <pwd.h>
@@ -28,18 +29,22 @@
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <sys/mman.h>
+#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/sysinfo.h>
+#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <cutils/properties.h>
+#include <cutils/sched_policy.h>
#include <cutils/sockets.h>
#include <lmkd.h>
#include <log/log.h>
#include <log/log_event_list.h>
#include <log/log_time.h>
+#include <system/thread_defs.h>
#ifdef LMKD_LOG_STATS
#include "statslog.h"
@@ -1261,6 +1266,41 @@
return maxprocp;
}
+static void set_process_group_and_prio(int pid, SchedPolicy sp, int prio) {
+ DIR* d;
+ char proc_path[PATH_MAX];
+ struct dirent* de;
+
+ snprintf(proc_path, sizeof(proc_path), "/proc/%d/task", pid);
+ if (!(d = opendir(proc_path))) {
+ ALOGW("Failed to open %s; errno=%d: process pid(%d) might have died", proc_path, errno,
+ pid);
+ return;
+ }
+
+ while ((de = readdir(d))) {
+ int t_pid;
+
+ if (de->d_name[0] == '.') continue;
+ t_pid = atoi(de->d_name);
+
+ if (!t_pid) {
+ ALOGW("Failed to get t_pid for '%s' of pid(%d)", de->d_name, pid);
+ continue;
+ }
+
+ if (setpriority(PRIO_PROCESS, t_pid, prio) && errno != ESRCH) {
+ ALOGW("Unable to raise priority of killing t_pid (%d): errno=%d", t_pid, errno);
+ }
+
+ if (set_cpuset_policy(t_pid, sp)) {
+ ALOGW("Failed to set_cpuset_policy on pid(%d) t_pid(%d) to %d", pid, t_pid, (int)sp);
+ continue;
+ }
+ }
+ closedir(d);
+}
+
static int last_killed_pid = -1;
/* Kill one process specified by procp. Returns the size of the process killed */
@@ -1301,6 +1341,9 @@
/* CAP_KILL required */
r = kill(pid, SIGKILL);
+
+ set_process_group_and_prio(pid, SP_FOREGROUND, ANDROID_PRIORITY_HIGHEST);
+
inc_killcnt(procp->oomadj);
ALOGI("Kill '%s' (%d), uid %d, oom_adj %d to free %ldkB",
taskname, pid, uid, procp->oomadj, tasksize * page_k);
diff --git a/logcat/Android.bp b/logcat/Android.bp
index b0563a6..0543aba 100644
--- a/logcat/Android.bp
+++ b/logcat/Android.bp
@@ -25,9 +25,9 @@
shared_libs: [
"libbase",
"libcutils",
- "liblog",
"libpcrecpp",
],
+ static_libs: ["liblog"],
logtags: ["event.logtags"],
}
diff --git a/logcat/tests/Android.bp b/logcat/tests/Android.bp
index e1f4d6f..ab84150 100644
--- a/logcat/tests/Android.bp
+++ b/logcat/tests/Android.bp
@@ -48,10 +48,8 @@
cc_test {
name: "logcat-unit-tests",
defaults: ["logcat-tests-defaults"],
- shared_libs: [
- "liblog",
- "libbase",
- ],
+ shared_libs: ["libbase"],
+ static_libs: ["liblog"],
srcs: [
"logcat_test.cpp",
"logcatd_test.cpp",
diff --git a/logd/.clang-format b/logd/.clang-format
deleted file mode 100644
index 393c309..0000000
--- a/logd/.clang-format
+++ /dev/null
@@ -1,11 +0,0 @@
-BasedOnStyle: Google
-AllowShortFunctionsOnASingleLine: false
-
-CommentPragmas: NOLINT:.*
-DerivePointerAlignment: false
-IndentWidth: 4
-PointerAlignment: Left
-TabWidth: 4
-PenaltyExcessCharacter: 32
-
-Cpp11BracedListStyle: false
diff --git a/logd/.clang-format b/logd/.clang-format
new file mode 120000
index 0000000..1af4f51
--- /dev/null
+++ b/logd/.clang-format
@@ -0,0 +1 @@
+../.clang-format-4
\ No newline at end of file
diff --git a/logd/Android.bp b/logd/Android.bp
index 5c79976..3abfc21 100644
--- a/logd/Android.bp
+++ b/logd/Android.bp
@@ -63,11 +63,13 @@
srcs: ["main.cpp"],
- static_libs: ["liblogd"],
+ static_libs: [
+ "liblog",
+ "liblogd",
+ ],
shared_libs: [
"libsysutils",
- "liblog",
"libcutils",
"libbase",
"libpackagelistparser",
diff --git a/logd/Android.mk b/logd/Android.mk
index b3ce560..aafa28d 100644
--- a/logd/Android.mk
+++ b/logd/Android.mk
@@ -5,7 +5,6 @@
LOCAL_MODULE := logtagd.rc
LOCAL_SRC_FILES := $(LOCAL_MODULE)
LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := debug
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/init
include $(BUILD_PREBUILT)
diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp
index 18d5287..470ffed 100644
--- a/logd/LogAudit.cpp
+++ b/logd/LogAudit.cpp
@@ -300,7 +300,7 @@
return 0;
}
- log_time now;
+ log_time now(log_time::EPOCH);
static const char audit_str[] = " audit(";
char* timeptr = strstr(str, audit_str);
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index fbdbf79..9cbc7c4 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -399,7 +399,7 @@
((*it)->getLogId() != LOG_ID_KERNEL))) {
mLogElements.push_back(elem);
} else {
- log_time end = log_time::EPOCH;
+ log_time end(log_time::EPOCH);
bool end_set = false;
bool end_always = false;
diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp
index 513c0c3..edd326a 100644
--- a/logd/LogKlog.cpp
+++ b/logd/LogKlog.cpp
@@ -197,10 +197,9 @@
// NOTREACHED
}
-log_time LogKlog::correction =
- (log_time(CLOCK_REALTIME) < log_time(CLOCK_MONOTONIC))
- ? log_time::EPOCH
- : (log_time(CLOCK_REALTIME) - log_time(CLOCK_MONOTONIC));
+log_time LogKlog::correction = (log_time(CLOCK_REALTIME) < log_time(CLOCK_MONOTONIC))
+ ? log_time(log_time::EPOCH)
+ : (log_time(CLOCK_REALTIME) - log_time(CLOCK_MONOTONIC));
LogKlog::LogKlog(LogBuffer* buf, LogReader* reader, int fdWrite, int fdRead,
bool auditd)
@@ -268,7 +267,7 @@
static const char real_format[] = "%Y-%m-%d %H:%M:%S.%09q UTC";
if (len < (ssize_t)(strlen(real_format) + 5)) return;
- log_time real;
+ log_time real(log_time::EPOCH);
const char* ep = real.strptime(real_string, real_format);
if (!ep || (ep > &real_string[len]) || (real > log_time(CLOCK_REALTIME))) {
return;
@@ -282,20 +281,20 @@
tm.tm_isdst = -1;
localtime_r(&now, &tm);
if ((tm.tm_gmtoff < 0) && ((-tm.tm_gmtoff) > (long)real.tv_sec)) {
- real = log_time::EPOCH;
+ real = log_time(log_time::EPOCH);
} else {
real.tv_sec += tm.tm_gmtoff;
}
if (monotonic > real) {
- correction = log_time::EPOCH;
+ correction = log_time(log_time::EPOCH);
} else {
correction = real - monotonic;
}
}
-void LogKlog::sniffTime(log_time& now, const char*& buf, ssize_t len,
- bool reverse) {
- if (len <= 0) return;
+log_time LogKlog::sniffTime(const char*& buf, ssize_t len, bool reverse) {
+ log_time now(log_time::EPOCH);
+ if (len <= 0) return now;
const char* cp = nullptr;
if ((len > 10) && (*buf == '[')) {
@@ -310,7 +309,7 @@
}
buf = cp;
- if (isMonotonic()) return;
+ if (isMonotonic()) return now;
const char* b;
if (((b = android::strnstr(cp, len, suspendStr))) &&
@@ -329,11 +328,11 @@
// trigger a check for ntp-induced or hardware clock drift.
log_time real(CLOCK_REALTIME);
log_time mono(CLOCK_MONOTONIC);
- correction = (real < mono) ? log_time::EPOCH : (real - mono);
+ correction = (real < mono) ? log_time(log_time::EPOCH) : (real - mono);
} else if (((b = android::strnstr(cp, len, suspendedStr))) &&
(((b += strlen(suspendStr)) - cp) < len)) {
len -= b - cp;
- log_time real;
+ log_time real(log_time::EPOCH);
char* endp;
real.tv_sec = strtol(b, &endp, 10);
if ((*endp == '.') && ((endp - b) < len)) {
@@ -345,7 +344,7 @@
}
if (reverse) {
if (real > correction) {
- correction = log_time::EPOCH;
+ correction = log_time(log_time::EPOCH);
} else {
correction -= real;
}
@@ -363,6 +362,7 @@
now = log_time(CLOCK_REALTIME);
}
}
+ return now;
}
pid_t LogKlog::sniffPid(const char*& buf, ssize_t len) {
@@ -451,8 +451,7 @@
}
parseKernelPrio(cp, len - (cp - buf));
- log_time now;
- sniffTime(now, cp, len - (cp - buf), true);
+ log_time now = sniffTime(cp, len - (cp - buf), true);
const char* suspended = android::strnstr(buf, len, suspendedStr);
if (!suspended || (suspended > cp)) {
@@ -468,7 +467,7 @@
}
parseKernelPrio(cp, len - (cp - buf));
- sniffTime(now, cp, len - (cp - buf), true);
+ sniffTime(cp, len - (cp - buf), true);
}
// Convert kernel log priority number into an Android Logger priority number
@@ -548,8 +547,7 @@
const char* p = buf;
int pri = parseKernelPrio(p, len);
- log_time now;
- sniffTime(now, p, len - (p - buf), false);
+ log_time now = sniffTime(p, len - (p - buf), false);
// sniff for start marker
const char* start = android::strnstr(p, len - (p - buf), klogdStr);
diff --git a/logd/LogKlog.h b/logd/LogKlog.h
index bb92dd2..6bfd6a8 100644
--- a/logd/LogKlog.h
+++ b/logd/LogKlog.h
@@ -55,11 +55,10 @@
}
protected:
- void sniffTime(log_time& now, const char*& buf, ssize_t len, bool reverse);
- pid_t sniffPid(const char*& buf, ssize_t len);
- void calculateCorrection(const log_time& monotonic, const char* real_string,
- ssize_t len);
- virtual bool onDataAvailable(SocketClient* cli);
+ log_time sniffTime(const char*& buf, ssize_t len, bool reverse);
+ pid_t sniffPid(const char*& buf, ssize_t len);
+ void calculateCorrection(const log_time& monotonic, const char* real_string, ssize_t len);
+ virtual bool onDataAvailable(SocketClient* cli);
};
#endif
diff --git a/logd/LogTags.cpp b/logd/LogTags.cpp
index 1ab9dd1..f19e7b0 100644
--- a/logd/LogTags.cpp
+++ b/logd/LogTags.cpp
@@ -30,6 +30,7 @@
#include <android-base/file.h>
#include <android-base/macros.h>
+#include <android-base/scopeguard.h>
#include <android-base/stringprintf.h>
#include <log/log_event_list.h>
#include <log/log_properties.h>
@@ -38,6 +39,8 @@
#include "LogTags.h"
#include "LogUtils.h"
+using android::base::make_scope_guard;
+
static LogTags* logtags;
const char LogTags::system_event_log_tags[] = "/system/etc/event-log-tags";
@@ -316,27 +319,29 @@
std::string Format;
android_log_list_element elem;
{
- android_log_event_list ctx(log_msg);
- elem = ctx.read();
+ auto ctx = create_android_log_parser(log_msg.msg() + sizeof(uint32_t),
+ log_msg.entry.len - sizeof(uint32_t));
+ auto guard = make_scope_guard([&ctx]() { android_log_destroy(&ctx); });
+ elem = android_log_read_next(ctx);
if (elem.type != EVENT_TYPE_LIST) {
continue;
}
- elem = ctx.read();
+ elem = android_log_read_next(ctx);
if (elem.type != EVENT_TYPE_INT) {
continue;
}
Tag = elem.data.int32;
- elem = ctx.read();
+ elem = android_log_read_next(ctx);
if (elem.type != EVENT_TYPE_STRING) {
continue;
}
Name = std::string(elem.data.string, elem.len);
- elem = ctx.read();
+ elem = android_log_read_next(ctx);
if (elem.type != EVENT_TYPE_STRING) {
continue;
}
Format = std::string(elem.data.string, elem.len);
- elem = ctx.read();
+ elem = android_log_read_next(ctx);
}
if ((elem.type != EVENT_TYPE_LIST_STOP) || !elem.complete) continue;
@@ -524,10 +529,22 @@
tag2format_const_iterator iform = tag2format.find(tag);
std::string Format = (iform != tag2format.end()) ? iform->second : "";
- __android_log_event_list ctx(TAG_DEF_LOG_TAG);
- ctx << tag << Name << Format;
- std::string buffer(ctx);
- if (buffer.length() <= 0) return; // unlikely
+ auto ctx = create_android_logger(TAG_DEF_LOG_TAG);
+ auto guard = make_scope_guard([&ctx]() { android_log_destroy(&ctx); });
+ if (android_log_write_int32(ctx, static_cast<int32_t>(tag) < 0) ||
+ android_log_write_string8_len(ctx, Name.c_str(), Name.size()) < 0 ||
+ android_log_write_string8_len(ctx, Format.c_str(), Format.size()) < 0) {
+ return;
+ }
+
+ const char* cp = nullptr;
+ ssize_t len = android_log_write_list_buffer(ctx, &cp);
+
+ if (len <= 0 || cp == nullptr) {
+ return;
+ }
+
+ std::string buffer(cp, len);
/*
* struct {
diff --git a/logd/tests/Android.bp b/logd/tests/Android.bp
index f15beb2..83a194f 100644
--- a/logd/tests/Android.bp
+++ b/logd/tests/Android.bp
@@ -38,9 +38,9 @@
shared_libs: [
"libbase",
"libcutils",
- "liblog",
"libselinux",
],
+ static_libs: ["liblog"],
}
// Build tests for the logger. Run with:
diff --git a/property_service/libpropertyinfoparser/Android.bp b/property_service/libpropertyinfoparser/Android.bp
index 6637deb..5c57d69 100644
--- a/property_service/libpropertyinfoparser/Android.bp
+++ b/property_service/libpropertyinfoparser/Android.bp
@@ -13,5 +13,6 @@
],
stl: "none",
system_shared_libs: [],
+ header_libs: ["libc_headers"],
export_include_dirs: ["include"],
}
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index f88f6b9..85c7e9e 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -22,7 +22,6 @@
LOCAL_MODULE := init-debug.rc
LOCAL_SRC_FILES := $(LOCAL_MODULE)
LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_TAGS := debug
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/init
include $(BUILD_PREBUILT)
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 2dda648..3804c86 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -28,7 +28,7 @@
dir.postinstall = /postinstall
[system]
-additional.namespaces = runtime,sphal,vndk,rs
+additional.namespaces = runtime,conscrypt,media,sphal,vndk,rs
###############################################################################
# "default" namespace
@@ -129,6 +129,36 @@
namespace.runtime.link.default.allow_all_shared_libs = true
###############################################################################
+# "media" APEX namespace
+#
+# This namespace is for libraries within the media APEX.
+###############################################################################
+namespace.media.isolated = true
+namespace.media.visible = true
+
+namespace.media.search.paths = /apex/com.android.media/${LIB}
+
+namespace.media.links = default
+namespace.media.link.default.shared_libs = %LLNDK_LIBRARIES%
+namespace.media.link.default.shared_libs += libandroid.so
+namespace.media.link.default.shared_libs += libbinder_ndk.so
+namespace.media.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
+
+###############################################################################
+# "conscrypt" APEX namespace
+#
+# This namespace is for libraries within the conscrypt APEX.
+###############################################################################
+namespace.conscrypt.isolated = true
+namespace.conscrypt.visible = true
+
+namespace.conscrypt.search.paths = /apex/com.android.conscrypt/${LIB}
+namespace.conscrypt.links = default
+# TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library
+# when it exists.
+namespace.conscrypt.link.default.allow_all_shared_libs = true
+
+###############################################################################
# "sphal" namespace
#
# SP-HAL(Sameprocess-HAL)s are the only vendor libraries that are allowed to be
diff --git a/rootdir/etc/ld.config.vndk_lite.txt b/rootdir/etc/ld.config.vndk_lite.txt
index 33b4698..2ce25b5 100644
--- a/rootdir/etc/ld.config.vndk_lite.txt
+++ b/rootdir/etc/ld.config.vndk_lite.txt
@@ -28,7 +28,7 @@
dir.postinstall = /postinstall
[system]
-additional.namespaces = runtime,sphal,vndk,rs
+additional.namespaces = runtime,conscrypt,media,sphal,vndk,rs
###############################################################################
# "default" namespace
@@ -76,6 +76,36 @@
namespace.runtime.link.default.allow_all_shared_libs = true
###############################################################################
+# "media" APEX namespace
+#
+# This namespace is for libraries within the media APEX.
+###############################################################################
+namespace.media.isolated = true
+namespace.media.visible = true
+
+namespace.media.search.paths = /apex/com.android.media/${LIB}
+
+namespace.media.links = default
+namespace.media.link.default.shared_libs = %LLNDK_LIBRARIES%
+namespace.media.link.default.shared_libs += libandroid.so
+namespace.media.link.default.shared_libs += libbinder_ndk.so
+namespace.media.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
+
+###############################################################################
+# "conscrypt" APEX namespace
+#
+# This namespace is for libraries within the conscrypt APEX.
+###############################################################################
+namespace.conscrypt.isolated = true
+namespace.conscrypt.visible = true
+
+namespace.conscrypt.search.paths = /apex/com.android.conscrypt/${LIB}
+namespace.conscrypt.links = default
+# TODO(b/119867084): Restrict to Bionic dlopen dependencies and PALette library
+# when it exists.
+namespace.conscrypt.link.default.allow_all_shared_libs = true
+
+###############################################################################
# "sphal" namespace
#
# SP-HAL(Sameprocess-HAL)s are the only vendor libraries that are allowed to be
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 9b20964..537bf86 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -12,12 +12,6 @@
import /init.${ro.zygote}.rc
on early-init
- # Mount shared so changes propagate into child namespaces
- # Do this before other processes are started from init. Otherwise,
- # processes launched while the propagation type of / is 'private'
- # won't get mount events from others.
- mount rootfs rootfs / shared rec
-
# Set init and its forked children's oom_adj.
write /proc/1/oom_score_adj -1000
@@ -46,8 +40,6 @@
# cgroup for system_server and surfaceflinger
mkdir /dev/memcg/system 0550 system system
- prepare_bootstrap_bionic
-
start ueventd
on init
@@ -117,6 +109,8 @@
mkdir /mnt/runtime/read/self 0755 root root
mkdir /mnt/runtime/write 0755 root root
mkdir /mnt/runtime/write/self 0755 root root
+ mkdir /mnt/runtime/full 0755 root root
+ mkdir /mnt/runtime/full/self 0755 root root
# Symlink to keep legacy apps working in multi-user world
symlink /storage/self/primary /sdcard
@@ -352,6 +346,8 @@
# Once everything is setup, no need to modify /.
# The bind+remount combination allows this to work in containers.
mount rootfs rootfs / remount bind ro nodev
+ # Mount shared so changes propagate into child namespaces
+ mount rootfs rootfs / shared rec
# Mount default storage into root namespace
mount none /mnt/runtime/default /storage bind rec
mount none none /storage slave rec
@@ -587,14 +583,6 @@
# Check any timezone data in /data is newer than the copy in the runtime module, delete if not.
exec - system system -- /system/bin/tzdatacheck /apex/com.android.runtime/etc/tz /data/misc/zoneinfo
- # Wait for apexd to finish activating APEXes before starting more processes.
- # This certainly reduces the parallelism but is required to make as many processes
- # as possible to use the bionic libs from the runtime APEX. This takes less than 50ms
- # so the impact on the booting time is not significant.
- wait_for_prop apexd.status ready
- setup_runtime_bionic
- parse_apex_configs
-
# If there is no post-fs-data action in the init.<device>.rc file, you
# must uncomment this line, otherwise encrypted filesystems
# won't work.
@@ -816,3 +804,6 @@
service flash_recovery /system/bin/install-recovery.sh
class main
oneshot
+
+on property:apexd.status=ready
+ parse_apex_configs
diff --git a/rootdir/init.zygote32.rc b/rootdir/init.zygote32.rc
index ac87979..2e95687 100644
--- a/rootdir/init.zygote32.rc
+++ b/rootdir/init.zygote32.rc
@@ -4,6 +4,7 @@
user root
group root readproc reserved_disk
socket zygote stream 660 root system
+ updatable
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
diff --git a/rootdir/init.zygote32_64.rc b/rootdir/init.zygote32_64.rc
index a535846..1cfc3d6 100644
--- a/rootdir/init.zygote32_64.rc
+++ b/rootdir/init.zygote32_64.rc
@@ -4,6 +4,7 @@
user root
group root readproc reserved_disk
socket zygote stream 660 root system
+ updatable
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
@@ -19,5 +20,6 @@
user root
group root readproc reserved_disk
socket zygote_secondary stream 660 root system
+ updatable
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks
diff --git a/rootdir/init.zygote64.rc b/rootdir/init.zygote64.rc
index 6fc810b..8ab012d 100644
--- a/rootdir/init.zygote64.rc
+++ b/rootdir/init.zygote64.rc
@@ -4,6 +4,7 @@
user root
group root readproc reserved_disk
socket zygote stream 660 root system
+ updatable
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
diff --git a/rootdir/init.zygote64_32.rc b/rootdir/init.zygote64_32.rc
index 7ddd52e..5abf149 100644
--- a/rootdir/init.zygote64_32.rc
+++ b/rootdir/init.zygote64_32.rc
@@ -4,6 +4,7 @@
user root
group root readproc reserved_disk
socket zygote stream 660 root system
+ updatable
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
@@ -19,5 +20,6 @@
user root
group root readproc reserved_disk
socket zygote_secondary stream 660 root system
+ updatable
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks
diff --git a/sdcard/sdcard.cpp b/sdcard/sdcard.cpp
index dc36596..e1de130 100644
--- a/sdcard/sdcard.cpp
+++ b/sdcard/sdcard.cpp
@@ -160,6 +160,7 @@
std::string dest_path_default = "/mnt/runtime/default/" + label;
std::string dest_path_read = "/mnt/runtime/read/" + label;
std::string dest_path_write = "/mnt/runtime/write/" + label;
+ std::string dest_path_full = "/mnt/runtime/full/" + label;
umask(0);
if (multi_user) {
@@ -172,7 +173,10 @@
default_normal, use_esdfs) ||
!sdcardfs_setup_secondary(dest_path_default, source_path, dest_path_write, uid, gid,
multi_user, userid, AID_EVERYBODY, full_write ? 0007 : 0027,
- derive_gid, default_normal, use_esdfs)) {
+ derive_gid, default_normal, use_esdfs) ||
+ !sdcardfs_setup_secondary(dest_path_default, source_path, dest_path_full, uid, gid,
+ multi_user, userid, AID_EVERYBODY, 0007, derive_gid,
+ default_normal, use_esdfs)) {
LOG(FATAL) << "failed to sdcardfs_setup";
}
} else {
@@ -186,7 +190,10 @@
derive_gid, default_normal, use_esdfs) ||
!sdcardfs_setup_secondary(dest_path_default, source_path, dest_path_write, uid, gid,
multi_user, userid, AID_EVERYBODY, full_write ? 0007 : 0022,
- derive_gid, default_normal, use_esdfs)) {
+ derive_gid, default_normal, use_esdfs) ||
+ !sdcardfs_setup_secondary(dest_path_default, source_path, dest_path_full, uid, gid,
+ multi_user, userid, AID_EVERYBODY, 0007, derive_gid,
+ default_normal, use_esdfs)) {
LOG(FATAL) << "failed to sdcardfs_setup";
}
}
diff --git a/shell_and_utilities/Android.bp b/shell_and_utilities/Android.bp
index 2d4a26f..cb5c5cb 100644
--- a/shell_and_utilities/Android.bp
+++ b/shell_and_utilities/Android.bp
@@ -18,6 +18,7 @@
"newfs_msdos",
"reboot",
"sh",
+ "simpleperf",
"tcpdump",
"toolbox",
"toybox",
diff --git a/storaged/storaged.cpp b/storaged/storaged.cpp
index 77c6167..6897663 100644
--- a/storaged/storaged.cpp
+++ b/storaged/storaged.cpp
@@ -341,20 +341,14 @@
if (mConfig.event_time_check_usec &&
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_ts) < 0) {
check_time = false;
- static time_t state_a;
- IF_ALOG_RATELIMIT_LOCAL(300, &state_a) {
- PLOG_TO(SYSTEM, ERROR) << "clock_gettime() failed";
- }
+ PLOG_TO(SYSTEM, ERROR) << "clock_gettime() failed";
}
event();
if (mConfig.event_time_check_usec && check_time) {
if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end_ts) < 0) {
- static time_t state_b;
- IF_ALOG_RATELIMIT_LOCAL(300, &state_b) {
- PLOG_TO(SYSTEM, ERROR) << "clock_gettime() failed";
- }
+ PLOG_TO(SYSTEM, ERROR) << "clock_gettime() failed";
return;
}
int64_t cost = (end_ts.tv_sec - start_ts.tv_sec) * SEC_TO_USEC +
diff --git a/toolbox/getevent.c b/toolbox/getevent.c
index 39033ad..e2c77c3 100644
--- a/toolbox/getevent.c
+++ b/toolbox/getevent.c
@@ -530,6 +530,9 @@
const char *device = NULL;
const char *device_path = "/dev/input";
+ /* disable buffering on stdout */
+ setbuf(stdout, NULL);
+
opterr = 0;
do {
c = getopt(argc, argv, "tns:Sv::dpilqc:rh");
diff --git a/trusty/libtrusty/tipc-test/Android.bp b/trusty/libtrusty/tipc-test/Android.bp
index 32499e3..9676b79 100644
--- a/trusty/libtrusty/tipc-test/Android.bp
+++ b/trusty/libtrusty/tipc-test/Android.bp
@@ -17,12 +17,10 @@
vendor: true,
srcs: ["tipc_test.c"],
- static_libs: [
- "libtrusty",
- ],
shared_libs: [
"libc",
"liblog",
+ "libtrusty",
],
gtest: false,
cflags: [