Merge "Fix checks for reading and writing FuseMessage."
diff --git a/adb/Android.mk b/adb/Android.mk
index be04cfa..16ed991 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -50,6 +50,7 @@
fdevent.cpp \
sockets.cpp \
socket_spec.cpp \
+ sysdeps/errno.cpp \
transport.cpp \
transport_local.cpp \
transport_usb.cpp \
@@ -88,10 +89,12 @@
LIBADB_windows_SRC_FILES := \
sysdeps_win32.cpp \
+ sysdeps/win32/errno.cpp \
sysdeps/win32/stat.cpp \
usb_windows.cpp \
LIBADB_TEST_windows_SRCS := \
+ sysdeps/win32/errno_test.cpp \
sysdeps_win32_test.cpp \
include $(CLEAR_VARS)
diff --git a/adb/adb.h b/adb/adb.h
index df59aaa..19f09a3 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -51,7 +51,7 @@
std::string adb_version();
// Increment this when we want to force users to start a new adb server.
-#define ADB_SERVER_VERSION 37
+#define ADB_SERVER_VERSION 38
class atransport;
struct usb_handle;
diff --git a/adb/adb_trace.h b/adb/adb_trace.h
index 5206a99..aaffa29 100644
--- a/adb/adb_trace.h
+++ b/adb/adb_trace.h
@@ -58,4 +58,8 @@
void adb_trace_init(char**);
void adb_trace_enable(AdbTrace trace_tag);
+#define ATRACE_TAG ATRACE_TAG_ADB
+#include <cutils/trace.h>
+#include <utils/Trace.h>
+
#endif /* __ADB_TRACE_H */
diff --git a/adb/bugreport.cpp b/adb/bugreport.cpp
index 143c62a..9b59d05 100644
--- a/adb/bugreport.cpp
+++ b/adb/bugreport.cpp
@@ -21,7 +21,6 @@
#include <string>
#include <vector>
-#include <android-base/parseint.h>
#include <android-base/strings.h>
#include "sysdeps.h"
@@ -144,11 +143,9 @@
//
size_t idx1 = line.rfind(BUGZ_PROGRESS_PREFIX) + strlen(BUGZ_PROGRESS_PREFIX);
size_t idx2 = line.rfind(BUGZ_PROGRESS_SEPARATOR);
- int progress, total;
- if (android::base::ParseInt(line.substr(idx1, (idx2 - idx1)), &progress) &&
- android::base::ParseInt(line.substr(idx2 + 1), &total)) {
- br_->UpdateProgress(line_message_, progress, total);
- }
+ int progress = std::stoi(line.substr(idx1, (idx2 - idx1)));
+ int total = std::stoi(line.substr(idx2 + 1));
+ br_->UpdateProgress(line_message_, progress, total);
} else {
invalid_lines_.push_back(line);
}
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index 4ec0fc2..d583516 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -23,6 +23,8 @@
#include <stdlib.h>
#include <unistd.h>
+#include <thread>
+
#include <android-base/errors.h>
#include <android-base/file.h>
#include <android-base/logging.h>
@@ -33,6 +35,7 @@
#include "adb_listeners.h"
#include "adb_utils.h"
#include "commandline.h"
+#include "sysdeps/chrono.h"
#include "transport.h"
static std::string GetLogFilePath() {
@@ -113,8 +116,18 @@
local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
std::string error;
- if (install_listener(socket_spec, "*smartsocket*", nullptr, 0, nullptr, &error)) {
- fatal("could not install *smartsocket* listener: %s", error.c_str());
+
+ auto start = std::chrono::steady_clock::now();
+
+ // If we told a previous adb server to quit because of version mismatch, we can get to this
+ // point before it's finished exiting. Retry for a while to give it some time.
+ while (install_listener(socket_spec, "*smartsocket*", nullptr, 0, nullptr, &error) !=
+ INSTALL_STATUS_OK) {
+ if (std::chrono::steady_clock::now() - start > 0.5s) {
+ fatal("could not install *smartsocket* listener: %s", error.c_str());
+ }
+
+ std::this_thread::sleep_for(100ms);
}
if (is_daemon) {
diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp
index caa7a5f..76119ef 100644
--- a/adb/file_sync_client.cpp
+++ b/adb/file_sync_client.cpp
@@ -15,12 +15,10 @@
*/
#include <dirent.h>
-#include <errno.h>
#include <inttypes.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
@@ -43,6 +41,7 @@
#include "adb_utils.h"
#include "file_sync_service.h"
#include "line_printer.h"
+#include "sysdeps/errno.h"
#include "sysdeps/stat.h"
#include <android-base/file.h>
@@ -75,8 +74,8 @@
struct copyinfo {
std::string lpath;
std::string rpath;
- unsigned int time = 0;
- unsigned int mode;
+ int64_t time = 0;
+ uint32_t mode;
uint64_t size = 0;
bool skip = false;
@@ -203,9 +202,16 @@
max = SYNC_DATA_MAX; // TODO: decide at runtime.
std::string error;
- fd = adb_connect("sync:", &error);
- if (fd < 0) {
- Error("connect failed: %s", error.c_str());
+ FeatureSet features;
+ if (!adb_get_feature_set(&features, &error)) {
+ fd = -1;
+ Error("failed to get feature set: %s", error.c_str());
+ } else {
+ have_stat_v2_ = CanUseFeature(features, kFeatureStat2);
+ fd = adb_connect("sync:", &error);
+ if (fd < 0) {
+ Error("connect failed: %s", error.c_str());
+ }
}
}
@@ -292,6 +298,77 @@
return WriteFdExactly(fd, &buf[0], buf.size());
}
+ bool SendStat(const char* path_and_mode) {
+ if (!have_stat_v2_) {
+ errno = ENOTSUP;
+ return false;
+ }
+ return SendRequest(ID_STAT_V2, path_and_mode);
+ }
+
+ bool SendLstat(const char* path_and_mode) {
+ if (have_stat_v2_) {
+ return SendRequest(ID_LSTAT_V2, path_and_mode);
+ } else {
+ return SendRequest(ID_LSTAT_V1, path_and_mode);
+ }
+ }
+
+ bool FinishStat(struct stat* st) {
+ syncmsg msg;
+
+ memset(st, 0, sizeof(*st));
+ if (have_stat_v2_) {
+ if (!ReadFdExactly(fd, &msg.stat_v2, sizeof(msg.stat_v2))) {
+ fatal_errno("protocol fault: failed to read stat response");
+ }
+
+ if (msg.stat_v2.id != ID_LSTAT_V2 && msg.stat_v2.id != ID_STAT_V2) {
+ fatal_errno("protocol fault: stat response has wrong message id: %" PRIx32,
+ msg.stat_v2.id);
+ }
+
+ if (msg.stat_v2.error != 0) {
+ errno = errno_from_wire(msg.stat_v2.error);
+ return false;
+ }
+
+ st->st_dev = msg.stat_v2.dev;
+ st->st_ino = msg.stat_v2.ino;
+ st->st_mode = msg.stat_v2.mode;
+ st->st_nlink = msg.stat_v2.nlink;
+ st->st_uid = msg.stat_v2.uid;
+ st->st_gid = msg.stat_v2.gid;
+ st->st_size = msg.stat_v2.size;
+ st->st_atime = msg.stat_v2.atime;
+ st->st_mtime = msg.stat_v2.mtime;
+ st->st_ctime = msg.stat_v2.ctime;
+ return true;
+ } else {
+ if (!ReadFdExactly(fd, &msg.stat_v1, sizeof(msg.stat_v1))) {
+ fatal_errno("protocol fault: failed to read stat response");
+ }
+
+ if (msg.stat_v1.id != ID_LSTAT_V1) {
+ fatal_errno("protocol fault: stat response has wrong message id: %" PRIx32,
+ msg.stat_v1.id);
+ }
+
+ if (msg.stat_v1.mode == 0 && msg.stat_v1.size == 0 && msg.stat_v1.time == 0) {
+ // There's no way for us to know what the error was.
+ errno = ENOPROTOOPT;
+ return false;
+ }
+
+ st->st_mode = msg.stat_v1.mode;
+ st->st_size = msg.stat_v1.size;
+ st->st_ctime = msg.stat_v1.time;
+ st->st_mtime = msg.stat_v1.time;
+ }
+
+ return true;
+ }
+
// Sending header, payload, and footer in a single write makes a huge
// difference to "adb sync" performance.
bool SendSmallFile(const char* path_and_mode,
@@ -429,7 +506,7 @@
return false;
}
buf[msg.status.msglen] = 0;
- Error("failed to copy '%s' to '%s': %s", from, to, &buf[0]);
+ Error("failed to copy '%s' to '%s': remote %s", from, to, &buf[0]);
return false;
}
@@ -500,6 +577,7 @@
private:
bool expect_done_;
+ bool have_stat_v2_;
TransferLedger global_ledger_;
TransferLedger current_ledger_;
@@ -555,25 +633,47 @@
}
}
-static bool sync_finish_stat(SyncConnection& sc, unsigned int* timestamp,
- unsigned int* mode, unsigned int* size) {
- syncmsg msg;
- if (!ReadFdExactly(sc.fd, &msg.stat, sizeof(msg.stat)) || msg.stat.id != ID_STAT) {
+static bool sync_stat(SyncConnection& sc, const char* path, struct stat* st) {
+ return sc.SendStat(path) && sc.FinishStat(st);
+}
+
+static bool sync_lstat(SyncConnection& sc, const char* path, struct stat* st) {
+ return sc.SendLstat(path) && sc.FinishStat(st);
+}
+
+static bool sync_stat_fallback(SyncConnection& sc, const char* path, struct stat* st) {
+ if (sync_stat(sc, path, st)) {
+ return true;
+ }
+
+ if (errno != ENOTSUP) {
return false;
}
- if (timestamp) *timestamp = msg.stat.time;
- if (mode) *mode = msg.stat.mode;
- if (size) *size = msg.stat.size;
+ // Try to emulate the parts we can when talking to older adbds.
+ bool lstat_result = sync_lstat(sc, path, st);
+ if (!lstat_result) {
+ return false;
+ }
+ if (S_ISLNK(st->st_mode)) {
+ // If the target is a symlink, figure out whether it's a file or a directory.
+ // Also, zero out the st_size field, since no one actually cares what the path length is.
+ st->st_size = 0;
+ std::string dir_path = path;
+ dir_path.push_back('/');
+ struct stat tmp_st;
+
+ st->st_mode &= ~S_IFMT;
+ if (sync_lstat(sc, dir_path.c_str(), &tmp_st)) {
+ st->st_mode |= S_IFDIR;
+ } else {
+ st->st_mode |= S_IFREG;
+ }
+ }
return true;
}
-static bool sync_stat(SyncConnection& sc, const char* path,
- unsigned int* timestamp, unsigned int* mode, unsigned int* size) {
- return sc.SendRequest(ID_STAT, path) && sync_finish_stat(sc, timestamp, mode, size);
-}
-
static bool sync_send(SyncConnection& sc, const char* lpath, const char* rpath,
unsigned mtime, mode_t mode)
{
@@ -621,8 +721,11 @@
static bool sync_recv(SyncConnection& sc, const char* rpath, const char* lpath,
const char* name=nullptr) {
- unsigned size = 0;
- if (!sync_stat(sc, rpath, nullptr, nullptr, &size)) return false;
+ struct stat st;
+ if (!sync_stat_fallback(sc, rpath, &st)) {
+ sc.Error("stat failed when trying to receive %s: %s", rpath, strerror(errno));
+ return false;
+ }
if (!sc.SendRequest(ID_RECV, rpath)) return false;
@@ -675,7 +778,7 @@
bytes_copied += msg.data.size;
sc.RecordBytesTransferred(msg.data.size);
- sc.ReportProgress(name != nullptr ? name : rpath, bytes_copied, size);
+ sc.ReportProgress(name != nullptr ? name : rpath, bytes_copied, st.st_size);
}
sc.RecordFilesTransferred(1);
@@ -778,20 +881,20 @@
if (check_timestamps) {
for (const copyinfo& ci : file_list) {
- if (!sc.SendRequest(ID_STAT, ci.rpath.c_str())) {
+ if (!sc.SendLstat(ci.rpath.c_str())) {
+ sc.Error("failed to send lstat");
return false;
}
}
for (copyinfo& ci : file_list) {
- unsigned int timestamp, mode, size;
- if (!sync_finish_stat(sc, ×tamp, &mode, &size)) {
- return false;
- }
- if (size == ci.size) {
- // For links, we cannot update the atime/mtime.
- if ((S_ISREG(ci.mode & mode) && timestamp == ci.time) ||
- (S_ISLNK(ci.mode & mode) && timestamp >= ci.time)) {
- ci.skip = true;
+ struct stat st;
+ if (sc.FinishStat(&st)) {
+ if (st.st_size == static_cast<off_t>(ci.size)) {
+ // For links, we cannot update the atime/mtime.
+ if ((S_ISREG(ci.mode & st.st_mode) && st.st_mtime == ci.time) ||
+ (S_ISLNK(ci.mode & st.st_mode) && st.st_mtime >= ci.time)) {
+ ci.skip = true;
+ }
}
}
}
@@ -823,10 +926,22 @@
if (!sc.IsValid()) return false;
bool success = true;
- unsigned dst_mode;
- if (!sync_stat(sc, dst, nullptr, &dst_mode, nullptr)) return false;
- bool dst_exists = (dst_mode != 0);
- bool dst_isdir = S_ISDIR(dst_mode);
+ bool dst_exists;
+ bool dst_isdir;
+
+ struct stat st;
+ if (sync_stat_fallback(sc, dst, &st)) {
+ dst_exists = true;
+ dst_isdir = S_ISDIR(st.st_mode);
+ } else {
+ if (errno == ENOENT || errno == ENOPROTOOPT) {
+ dst_exists = false;
+ dst_isdir = false;
+ } else {
+ sc.Error("stat failed when trying to push to %s: %s", dst, strerror(errno));
+ return false;
+ }
+ }
if (!dst_isdir) {
if (srcs.size() > 1) {
@@ -871,8 +986,7 @@
dst_dir.append(adb_basename(src_path));
}
- success &= copy_local_dir_remote(sc, src_path, dst_dir.c_str(),
- false, false);
+ success &= copy_local_dir_remote(sc, src_path, dst_dir.c_str(), false, false);
continue;
} else if (!should_push_file(st.st_mode)) {
sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, st.st_mode);
@@ -901,17 +1015,6 @@
return success;
}
-static bool remote_symlink_isdir(SyncConnection& sc, const std::string& rpath) {
- unsigned mode;
- std::string dir_path = rpath;
- dir_path.push_back('/');
- if (!sync_stat(sc, dir_path.c_str(), nullptr, &mode, nullptr)) {
- sc.Error("failed to stat remote symlink '%s'", dir_path.c_str());
- return false;
- }
- return S_ISDIR(mode);
-}
-
static bool remote_build_list(SyncConnection& sc, std::vector<copyinfo>* file_list,
const std::string& rpath, const std::string& lpath) {
std::vector<copyinfo> dirlist;
@@ -949,7 +1052,13 @@
// Check each symlink we found to see whether it's a file or directory.
for (copyinfo& link_ci : linklist) {
- if (remote_symlink_isdir(sc, link_ci.rpath)) {
+ struct stat st;
+ if (!sync_stat_fallback(sc, link_ci.rpath.c_str(), &st)) {
+ sc.Warning("stat failed for path %s: %s", link_ci.rpath.c_str(), strerror(errno));
+ continue;
+ }
+
+ if (S_ISDIR(st.st_mode)) {
dirlist.emplace_back(std::move(link_ci));
} else {
file_list->emplace_back(std::move(link_ci));
@@ -1075,22 +1184,19 @@
for (const char* src_path : srcs) {
const char* dst_path = dst;
- unsigned src_mode, src_time, src_size;
- if (!sync_stat(sc, src_path, &src_time, &src_mode, &src_size)) {
- sc.Error("failed to stat remote object '%s'", src_path);
- return false;
- }
- if (src_mode == 0) {
- sc.Error("remote object '%s' does not exist", src_path);
+ struct stat src_st;
+ if (!sync_stat_fallback(sc, src_path, &src_st)) {
+ if (errno == ENOPROTOOPT) {
+ sc.Error("remote object '%s' does not exist", src_path);
+ } else {
+ sc.Error("failed to stat remote object '%s': %s", src_path, strerror(errno));
+ }
+
success = false;
continue;
}
- bool src_isdir = S_ISDIR(src_mode);
- if (S_ISLNK(src_mode)) {
- src_isdir = remote_symlink_isdir(sc, src_path);
- }
-
+ bool src_isdir = S_ISDIR(src_st.st_mode);
if (src_isdir) {
std::string dst_dir = dst;
@@ -1109,8 +1215,8 @@
success &= copy_remote_dir_local(sc, src_path, dst_dir.c_str(), copy_attrs);
continue;
- } else if (!should_pull_file(src_mode)) {
- sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, src_mode);
+ } else if (!should_pull_file(src_st.st_mode)) {
+ sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, src_st.st_mode);
continue;
}
@@ -1125,13 +1231,13 @@
}
sc.NewTransfer();
- sc.SetExpectedTotalBytes(src_size);
+ sc.SetExpectedTotalBytes(src_st.st_size);
if (!sync_recv(sc, src_path, dst_path, name)) {
success = false;
continue;
}
- if (copy_attrs && set_time_and_mode(dst_path, src_time, src_mode) != 0) {
+ if (copy_attrs && set_time_and_mode(dst_path, src_st.st_mtime, src_st.st_mode) != 0) {
success = false;
continue;
}
diff --git a/adb/file_sync_service.cpp b/adb/file_sync_service.cpp
index 7a92d2e..e667bf8 100644
--- a/adb/file_sync_service.cpp
+++ b/adb/file_sync_service.cpp
@@ -39,8 +39,12 @@
#include "adb.h"
#include "adb_io.h"
+#include "adb_trace.h"
#include "adb_utils.h"
#include "security_log_tags.h"
+#include "sysdeps/errno.h"
+
+using android::base::StringPrintf;
static bool should_use_fs_config(const std::string& path) {
// TODO: use fs_config to configure permissions on /data.
@@ -98,18 +102,47 @@
return true;
}
-static bool do_stat(int s, const char* path) {
- syncmsg msg;
- msg.stat.id = ID_STAT;
+static bool do_lstat_v1(int s, const char* path) {
+ syncmsg msg = {};
+ msg.stat_v1.id = ID_LSTAT_V1;
struct stat st = {};
- // TODO: add a way to report that the stat failed!
lstat(path, &st);
- msg.stat.mode = st.st_mode;
- msg.stat.size = st.st_size;
- msg.stat.time = st.st_mtime;
+ msg.stat_v1.mode = st.st_mode;
+ msg.stat_v1.size = st.st_size;
+ msg.stat_v1.time = st.st_mtime;
+ return WriteFdExactly(s, &msg.stat_v1, sizeof(msg.stat_v1));
+}
- return WriteFdExactly(s, &msg.stat, sizeof(msg.stat));
+static bool do_stat_v2(int s, uint32_t id, const char* path) {
+ syncmsg msg = {};
+ msg.stat_v2.id = id;
+
+ decltype(&stat) stat_fn;
+ if (id == ID_STAT_V2) {
+ stat_fn = stat;
+ } else {
+ stat_fn = lstat;
+ }
+
+ struct stat st = {};
+ int rc = stat_fn(path, &st);
+ if (rc == -1) {
+ msg.stat_v2.error = errno_to_wire(errno);
+ } else {
+ msg.stat_v2.dev = st.st_dev;
+ msg.stat_v2.ino = st.st_ino;
+ msg.stat_v2.mode = st.st_mode;
+ msg.stat_v2.nlink = st.st_nlink;
+ msg.stat_v2.uid = st.st_uid;
+ msg.stat_v2.gid = st.st_gid;
+ msg.stat_v2.size = st.st_size;
+ msg.stat_v2.atime = st.st_atime;
+ msg.stat_v2.mtime = st.st_mtime;
+ msg.stat_v2.ctime = st.st_ctime;
+ }
+
+ return WriteFdExactly(s, &msg.stat_v2, sizeof(msg.stat_v2));
}
static bool do_list(int s, const char* path) {
@@ -122,7 +155,7 @@
if (!d) goto done;
while ((de = readdir(d.get()))) {
- std::string filename(android::base::StringPrintf("%s/%s", path, de->d_name));
+ std::string filename(StringPrintf("%s/%s", path, de->d_name));
struct stat st;
if (lstat(filename.c_str(), &st) == 0) {
@@ -161,7 +194,7 @@
}
static bool SendSyncFailErrno(int fd, const std::string& reason) {
- return SendSyncFail(fd, android::base::StringPrintf("%s: %s", reason.c_str(), strerror(errno)));
+ return SendSyncFail(fd, StringPrintf("%s: %s", reason.c_str(), strerror(errno)));
}
static bool handle_send_file(int s, const char* path, uid_t uid, gid_t gid, uint64_t capabilities,
@@ -403,9 +436,31 @@
return WriteFdExactly(s, &msg.data, sizeof(msg.data));
}
+static const char* sync_id_to_name(uint32_t id) {
+ switch (id) {
+ case ID_LSTAT_V1:
+ return "lstat_v1";
+ case ID_LSTAT_V2:
+ return "lstat_v2";
+ case ID_STAT_V2:
+ return "stat_v2";
+ case ID_LIST:
+ return "list";
+ case ID_SEND:
+ return "send";
+ case ID_RECV:
+ return "recv";
+ case ID_QUIT:
+ return "quit";
+ default:
+ return "???";
+ }
+}
+
static bool handle_sync_command(int fd, std::vector<char>& buffer) {
D("sync: waiting for request");
+ ATRACE_CALL();
SyncRequest request;
if (!ReadFdExactly(fd, &request, sizeof(request))) {
SendSyncFail(fd, "command read failure");
@@ -423,34 +478,39 @@
}
name[path_length] = 0;
- const char* id = reinterpret_cast<const char*>(&request.id);
- D("sync: '%.4s' '%s'", id, name);
+ std::string id_name = sync_id_to_name(request.id);
+ std::string trace_name = StringPrintf("%s(%s)", id_name.c_str(), name);
+ ATRACE_NAME(trace_name.c_str());
+ D("sync: %s('%s')", id_name.c_str(), name);
switch (request.id) {
- case ID_STAT:
- if (!do_stat(fd, name)) return false;
- break;
- case ID_LIST:
- if (!do_list(fd, name)) return false;
- break;
- case ID_SEND:
- if (!do_send(fd, name, buffer)) return false;
- break;
- case ID_RECV:
- if (!do_recv(fd, name, buffer)) return false;
- break;
- case ID_QUIT:
- return false;
- default:
- SendSyncFail(fd, android::base::StringPrintf("unknown command '%.4s' (%08x)",
- id, request.id));
- return false;
+ case ID_LSTAT_V1:
+ if (!do_lstat_v1(fd, name)) return false;
+ break;
+ case ID_LSTAT_V2:
+ case ID_STAT_V2:
+ if (!do_stat_v2(fd, request.id, name)) return false;
+ break;
+ case ID_LIST:
+ if (!do_list(fd, name)) return false;
+ break;
+ case ID_SEND:
+ if (!do_send(fd, name, buffer)) return false;
+ break;
+ case ID_RECV:
+ if (!do_recv(fd, name, buffer)) return false;
+ break;
+ case ID_QUIT:
+ return false;
+ default:
+ SendSyncFail(fd, StringPrintf("unknown command %08x", request.id));
+ return false;
}
return true;
}
-void file_sync_service(int fd, void* cookie) {
+void file_sync_service(int fd, void*) {
std::vector<char> buffer(SYNC_DATA_MAX);
while (handle_sync_command(fd, buffer)) {
diff --git a/adb/file_sync_service.h b/adb/file_sync_service.h
index 0e25974..90f1965 100644
--- a/adb/file_sync_service.h
+++ b/adb/file_sync_service.h
@@ -22,7 +22,9 @@
#define MKID(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
-#define ID_STAT MKID('S','T','A','T')
+#define ID_LSTAT_V1 MKID('S','T','A','T')
+#define ID_STAT_V2 MKID('S','T','A','2')
+#define ID_LSTAT_V2 MKID('L','S','T','2')
#define ID_LIST MKID('L','I','S','T')
#define ID_SEND MKID('S','E','N','D')
#define ID_RECV MKID('R','E','C','V')
@@ -45,7 +47,21 @@
uint32_t mode;
uint32_t size;
uint32_t time;
- } stat;
+ } stat_v1;
+ struct __attribute__((packed)) {
+ uint32_t id;
+ uint32_t error;
+ uint64_t dev;
+ uint64_t ino;
+ uint32_t mode;
+ uint32_t nlink;
+ uint32_t uid;
+ uint32_t gid;
+ uint64_t size;
+ int64_t atime;
+ int64_t mtime;
+ int64_t ctime;
+ } stat_v2;
struct __attribute__((packed)) {
uint32_t id;
uint32_t mode;
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 05d9fde..654072c 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -34,6 +34,7 @@
#include <android-base/unique_fd.h>
#include <android-base/utf8.h>
+#include "sysdeps/errno.h"
#include "sysdeps/stat.h"
/*
@@ -361,9 +362,6 @@
#define getcwd adb_getcwd
-char* adb_strerror(int err);
-#define strerror adb_strerror
-
// Helper class to convert UTF-16 argv from wmain() to UTF-8 args that can be
// passed to main().
class NarrowArgs {
diff --git a/adb/sysdeps/errno.cpp b/adb/sysdeps/errno.cpp
new file mode 100644
index 0000000..6869947
--- /dev/null
+++ b/adb/sysdeps/errno.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 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 "sysdeps/errno.h"
+
+#include <errno.h>
+
+#include <thread>
+#include <unordered_map>
+#include <utility>
+
+#include "adb.h"
+
+#if defined(_WIN32)
+#define ETXTBSY EBUSY
+#endif
+
+// Use the linux asm-generic values for errno (which are used on all android archs but mips).
+#define ERRNO_VALUES() \
+ ERRNO_VALUE(EACCES, 13); \
+ ERRNO_VALUE(EEXIST, 17); \
+ ERRNO_VALUE(EFAULT, 14); \
+ ERRNO_VALUE(EFBIG, 27); \
+ ERRNO_VALUE(EINTR, 4); \
+ ERRNO_VALUE(EINVAL, 22); \
+ ERRNO_VALUE(EIO, 5); \
+ ERRNO_VALUE(EISDIR, 21); \
+ ERRNO_VALUE(ELOOP, 40); \
+ ERRNO_VALUE(EMFILE, 24); \
+ ERRNO_VALUE(ENAMETOOLONG, 36); \
+ ERRNO_VALUE(ENFILE, 23); \
+ ERRNO_VALUE(ENOENT, 2); \
+ ERRNO_VALUE(ENOMEM, 12); \
+ ERRNO_VALUE(ENOSPC, 28); \
+ ERRNO_VALUE(ENOTDIR, 20); \
+ ERRNO_VALUE(EOVERFLOW, 75); \
+ ERRNO_VALUE(EPERM, 1); \
+ ERRNO_VALUE(EROFS, 30); \
+ ERRNO_VALUE(ETXTBSY, 26)
+
+// Make sure these values are actually correct.
+#if defined(__linux__) && !defined(__mips__)
+#define ERRNO_VALUE(error_name, wire_value) static_assert((error_name) == (wire_value), "")
+ERRNO_VALUES();
+#undef ERRNO_VALUE
+#endif
+
+static std::unordered_map<int, int>* generate_host_to_wire() {
+ auto result = new std::unordered_map<int, int>();
+#define ERRNO_VALUE(error_name, wire_value) \
+ result->insert(std::make_pair((error_name), (wire_value)))
+ ERRNO_VALUES();
+#undef ERRNO_VALUE
+ return result;
+}
+
+static std::unordered_map<int, int>* generate_wire_to_host() {
+ auto result = new std::unordered_map<int, int>();
+#define ERRNO_VALUE(error_name, wire_value) \
+ result->insert(std::make_pair((wire_value), (error_name)))
+ ERRNO_VALUES();
+#undef ERRNO_VALUE
+ return result;
+}
+
+static std::unordered_map<int, int>& host_to_wire = *generate_host_to_wire();
+static std::unordered_map<int, int>& wire_to_host = *generate_wire_to_host();
+
+int errno_to_wire(int error) {
+ auto it = host_to_wire.find(error);
+ if (it == host_to_wire.end()) {
+ LOG(ERROR) << "failed to convert errno " << error << " (" << strerror(error) << ") to wire";
+
+ // Return EIO;
+ return 5;
+ }
+ return it->second;
+}
+
+int errno_from_wire(int error) {
+ auto it = host_to_wire.find(error);
+ if (it == host_to_wire.end()) {
+ LOG(ERROR) << "failed to convert errno " << error << " from wire";
+ return EIO;
+ }
+ return it->second;
+}
diff --git a/adb/sysdeps/errno.h b/adb/sysdeps/errno.h
new file mode 100644
index 0000000..72816b1
--- /dev/null
+++ b/adb/sysdeps/errno.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#pragma once
+
+#include <errno.h>
+#include <string.h>
+
+#if defined(_WIN32)
+char* adb_strerror(int err);
+#define strerror adb_strerror
+#endif
+
+// errno values differ between operating systems and between Linux architectures.
+// Arbitrarily select the Linux asm-generic values to use in the wire protocol.
+int errno_to_wire(int error);
+int errno_from_wire(int error);
diff --git a/adb/sysdeps/win32/errno.cpp b/adb/sysdeps/win32/errno.cpp
new file mode 100644
index 0000000..a3b9d9b
--- /dev/null
+++ b/adb/sysdeps/win32/errno.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 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 "sysdeps/errno.h"
+
+#include <windows.h>
+
+#include <string>
+
+// Overrides strerror() to handle error codes not supported by the Windows C
+// Runtime (MSVCRT.DLL).
+char* adb_strerror(int err) {
+// sysdeps.h defines strerror to adb_strerror, but in this function, we
+// want to call the real C Runtime strerror().
+#pragma push_macro("strerror")
+#undef strerror
+ const int saved_err = errno; // Save because we overwrite it later.
+
+ // Lookup the string for an unknown error.
+ char* errmsg = strerror(-1);
+ const std::string unknown_error = (errmsg == nullptr) ? "" : errmsg;
+
+ // Lookup the string for this error to see if the C Runtime has it.
+ errmsg = strerror(err);
+ if (errmsg != nullptr && unknown_error != errmsg) {
+ // The CRT returned an error message and it is different than the error
+ // message for an unknown error, so it is probably valid, so use it.
+ } else {
+ // Check if we have a string for this error code.
+ const char* custom_msg = nullptr;
+ switch (err) {
+#pragma push_macro("ERR")
+#undef ERR
+#define ERR(errnum, desc) case errnum: custom_msg = desc; break
+ // These error strings are from AOSP bionic/libc/include/sys/_errdefs.h.
+ // Note that these cannot be longer than 94 characters because we
+ // pass this to _strerror() which has that requirement.
+ ERR(ECONNRESET, "Connection reset by peer");
+ ERR(EHOSTUNREACH, "No route to host");
+ ERR(ENETDOWN, "Network is down");
+ ERR(ENETRESET, "Network dropped connection because of reset");
+ ERR(ENOBUFS, "No buffer space available");
+ ERR(ENOPROTOOPT, "Protocol not available");
+ ERR(ENOTCONN, "Transport endpoint is not connected");
+ ERR(ENOTSOCK, "Socket operation on non-socket");
+ ERR(EOPNOTSUPP, "Operation not supported on transport endpoint");
+#pragma pop_macro("ERR")
+ }
+
+ if (custom_msg != nullptr) {
+ // Use _strerror() to write our string into the writable per-thread
+ // buffer used by strerror()/_strerror(). _strerror() appends the
+ // msg for the current value of errno, so set errno to a consistent
+ // value for every call so that our code-path is always the same.
+ errno = 0;
+ errmsg = _strerror(custom_msg);
+ const size_t custom_msg_len = strlen(custom_msg);
+ // Just in case _strerror() returned a read-only string, check if
+ // the returned string starts with our custom message because that
+ // implies that the string is not read-only.
+ if ((errmsg != nullptr) && !strncmp(custom_msg, errmsg, custom_msg_len)) {
+ // _strerror() puts other text after our custom message, so
+ // remove that by terminating after our message.
+ errmsg[custom_msg_len] = '\0';
+ } else {
+ // For some reason nullptr was returned or a pointer to a
+ // read-only string was returned, so fallback to whatever
+ // strerror() can muster (probably "Unknown error" or some
+ // generic CRT error string).
+ errmsg = strerror(err);
+ }
+ } else {
+ // We don't have a custom message, so use whatever strerror(err)
+ // returned earlier.
+ }
+ }
+
+ errno = saved_err; // restore
+
+ return errmsg;
+#pragma pop_macro("strerror")
+}
diff --git a/adb/sysdeps/win32/errno_test.cpp b/adb/sysdeps/win32/errno_test.cpp
new file mode 100644
index 0000000..09ec52c
--- /dev/null
+++ b/adb/sysdeps/win32/errno_test.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 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 "sysdeps/errno.h"
+
+#include <string>
+
+#include <gtest/gtest.h>
+
+void TestAdbStrError(int err, const char* expected) {
+ errno = 12345;
+ const char* result = adb_strerror(err);
+ // Check that errno is not overwritten.
+ EXPECT_EQ(12345, errno);
+ EXPECT_STREQ(expected, result);
+}
+
+TEST(sysdeps_win32, adb_strerror) {
+ // Test an error code that should not have a mapped string. Use an error
+ // code that is not used by the internal implementation of adb_strerror().
+ TestAdbStrError(-2, "Unknown error");
+ // adb_strerror() uses -1 internally, so test that it can still be passed
+ // as a parameter.
+ TestAdbStrError(-1, "Unknown error");
+ // Test very big, positive unknown error.
+ TestAdbStrError(1000000, "Unknown error");
+
+ // Test success case.
+ // Wine returns "Success" for strerror(0), Windows returns "No error", so accept both.
+ std::string success = adb_strerror(0);
+ EXPECT_TRUE(success == "Success" || success == "No error") << "strerror(0) = " << success;
+
+ // Test error that regular strerror() should have a string for.
+ TestAdbStrError(EPERM, "Operation not permitted");
+ // Test error that regular strerror() doesn't have a string for, but that
+ // adb_strerror() returns.
+ TestAdbStrError(ECONNRESET, "Connection reset by peer");
+}
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index 4dd549d..a4b5e69 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -477,81 +477,6 @@
return 0;
}
-// Overrides strerror() to handle error codes not supported by the Windows C
-// Runtime (MSVCRT.DLL).
-char* adb_strerror(int err) {
- // sysdeps.h defines strerror to adb_strerror, but in this function, we
- // want to call the real C Runtime strerror().
-#pragma push_macro("strerror")
-#undef strerror
- const int saved_err = errno; // Save because we overwrite it later.
-
- // Lookup the string for an unknown error.
- char* errmsg = strerror(-1);
- const std::string unknown_error = (errmsg == nullptr) ? "" : errmsg;
-
- // Lookup the string for this error to see if the C Runtime has it.
- errmsg = strerror(err);
- if (errmsg != nullptr && unknown_error != errmsg) {
- // The CRT returned an error message and it is different than the error
- // message for an unknown error, so it is probably valid, so use it.
- } else {
- // Check if we have a string for this error code.
- const char* custom_msg = nullptr;
- switch (err) {
-#pragma push_macro("ERR")
-#undef ERR
-#define ERR(errnum, desc) case errnum: custom_msg = desc; break
- // These error strings are from AOSP bionic/libc/include/sys/_errdefs.h.
- // Note that these cannot be longer than 94 characters because we
- // pass this to _strerror() which has that requirement.
- ERR(ECONNRESET, "Connection reset by peer");
- ERR(EHOSTUNREACH, "No route to host");
- ERR(ENETDOWN, "Network is down");
- ERR(ENETRESET, "Network dropped connection because of reset");
- ERR(ENOBUFS, "No buffer space available");
- ERR(ENOPROTOOPT, "Protocol not available");
- ERR(ENOTCONN, "Transport endpoint is not connected");
- ERR(ENOTSOCK, "Socket operation on non-socket");
- ERR(EOPNOTSUPP, "Operation not supported on transport endpoint");
-#pragma pop_macro("ERR")
- }
-
- if (custom_msg != nullptr) {
- // Use _strerror() to write our string into the writable per-thread
- // buffer used by strerror()/_strerror(). _strerror() appends the
- // msg for the current value of errno, so set errno to a consistent
- // value for every call so that our code-path is always the same.
- errno = 0;
- errmsg = _strerror(custom_msg);
- const size_t custom_msg_len = strlen(custom_msg);
- // Just in case _strerror() returned a read-only string, check if
- // the returned string starts with our custom message because that
- // implies that the string is not read-only.
- if ((errmsg != nullptr) &&
- !strncmp(custom_msg, errmsg, custom_msg_len)) {
- // _strerror() puts other text after our custom message, so
- // remove that by terminating after our message.
- errmsg[custom_msg_len] = '\0';
- } else {
- // For some reason nullptr was returned or a pointer to a
- // read-only string was returned, so fallback to whatever
- // strerror() can muster (probably "Unknown error" or some
- // generic CRT error string).
- errmsg = strerror(err);
- }
- } else {
- // We don't have a custom message, so use whatever strerror(err)
- // returned earlier.
- }
- }
-
- errno = saved_err; // restore
-
- return errmsg;
-#pragma pop_macro("strerror")
-}
-
/**************************************************************************/
/**************************************************************************/
/***** *****/
@@ -565,7 +490,7 @@
static void _socket_set_errno( const DWORD err ) {
// Because the Windows C Runtime (MSVCRT.DLL) strerror() does not support a
// lot of POSIX and socket error codes, some of the resulting error codes
- // are mapped to strings by adb_strerror() above.
+ // are mapped to strings by adb_strerror().
switch ( err ) {
case 0: errno = 0; break;
// Don't map WSAEINTR since that is only for Winsock 1.1 which we don't use.
diff --git a/adb/sysdeps_win32_test.cpp b/adb/sysdeps_win32_test.cpp
old mode 100755
new mode 100644
index c3a3fd7..529b212
--- a/adb/sysdeps_win32_test.cpp
+++ b/adb/sysdeps_win32_test.cpp
@@ -70,36 +70,6 @@
}
}
-void TestAdbStrError(int err, const char* expected) {
- errno = 12345;
- const char* result = adb_strerror(err);
- // Check that errno is not overwritten.
- EXPECT_EQ(12345, errno);
- EXPECT_STREQ(expected, result);
-}
-
-TEST(sysdeps_win32, adb_strerror) {
- // Test an error code that should not have a mapped string. Use an error
- // code that is not used by the internal implementation of adb_strerror().
- TestAdbStrError(-2, "Unknown error");
- // adb_strerror() uses -1 internally, so test that it can still be passed
- // as a parameter.
- TestAdbStrError(-1, "Unknown error");
- // Test very big, positive unknown error.
- TestAdbStrError(1000000, "Unknown error");
-
- // Test success case.
- // Wine returns "Success" for strerror(0), Windows returns "No error", so accept both.
- std::string success = adb_strerror(0);
- EXPECT_TRUE(success == "Success" || success == "No error") << "strerror(0) = " << success;
-
- // Test error that regular strerror() should have a string for.
- TestAdbStrError(EPERM, "Operation not permitted");
- // Test error that regular strerror() doesn't have a string for, but that
- // adb_strerror() returns.
- TestAdbStrError(ECONNRESET, "Connection reset by peer");
-}
-
TEST(sysdeps_win32, unix_isatty) {
// stdin and stdout should be consoles. Use CONIN$ and CONOUT$ special files
// so that we can test this even if stdin/stdout have been redirected. Read
diff --git a/adb/trace.sh b/adb/trace.sh
new file mode 100755
index 0000000..49e5026
--- /dev/null
+++ b/adb/trace.sh
@@ -0,0 +1,17 @@
+set -e
+
+if ! [ -e $ANDROID_BUILD_TOP/external/chromium-trace/systrace.py ]; then
+ echo "error: can't find systrace.py at \$ANDROID_BUILD_TOP/external/chromium-trace/systrace.py"
+ exit 1
+fi
+
+adb shell "sleep 1; atrace -b 65536 --async_start adb sched power freq idle disk mmc load"
+adb shell killall adbd
+adb wait-for-device
+echo "press enter to finish..."
+read
+TRACE_TEMP=`mktemp /tmp/trace.XXXXXX`
+echo Saving trace to ${TRACE_TEMP}, html file to ${TRACE_TEMP}.html
+adb shell atrace --async_stop -z > ${TRACE_TEMP}
+$ANDROID_BUILD_TOP/external/chromium-trace/systrace.py --from-file=${TRACE_TEMP} -o ${TRACE_TEMP}.html
+chrome ${TRACE_TEMP}.html
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 132702d..60f3b5c 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -37,6 +37,7 @@
#include "adb.h"
#include "adb_auth.h"
+#include "adb_trace.h"
#include "adb_utils.h"
#include "diagnose_usb.h"
@@ -49,18 +50,18 @@
const char* const kFeatureShell2 = "shell_v2";
const char* const kFeatureCmd = "cmd";
+const char* const kFeatureStat2 = "stat_v2";
static std::string dump_packet(const char* name, const char* func, apacket* p) {
- unsigned command = p->msg.command;
- int len = p->msg.data_length;
- char cmd[9];
- char arg0[12], arg1[12];
- int n;
+ unsigned command = p->msg.command;
+ int len = p->msg.data_length;
+ char cmd[9];
+ char arg0[12], arg1[12];
+ int n;
for (n = 0; n < 4; n++) {
- int b = (command >> (n*8)) & 255;
- if (b < 32 || b >= 127)
- break;
+ int b = (command >> (n * 8)) & 255;
+ if (b < 32 || b >= 127) break;
cmd[n] = (char)b;
}
if (n == 4) {
@@ -81,25 +82,24 @@
else
snprintf(arg1, sizeof arg1, "0x%x", p->msg.arg1);
- std::string result = android::base::StringPrintf("%s: %s: [%s] arg0=%s arg1=%s (len=%d) ",
- name, func, cmd, arg0, arg1, len);
+ std::string result = android::base::StringPrintf("%s: %s: [%s] arg0=%s arg1=%s (len=%d) ", name,
+ func, cmd, arg0, arg1, len);
result += dump_hex(p->data, len);
return result;
}
-static int
-read_packet(int fd, const char* name, apacket** ppacket)
-{
+static int read_packet(int fd, const char* name, apacket** ppacket) {
+ ATRACE_NAME("read_packet");
char buff[8];
if (!name) {
snprintf(buff, sizeof buff, "fd=%d", fd);
name = buff;
}
- char* p = reinterpret_cast<char*>(ppacket); /* really read a packet address */
+ char* p = reinterpret_cast<char*>(ppacket); /* really read a packet address */
int len = sizeof(apacket*);
- while(len > 0) {
+ while (len > 0) {
int r = adb_read(fd, p, len);
- if(r > 0) {
+ if (r > 0) {
len -= r;
p += r;
} else {
@@ -112,20 +112,19 @@
return 0;
}
-static int
-write_packet(int fd, const char* name, apacket** ppacket)
-{
+static int write_packet(int fd, const char* name, apacket** ppacket) {
+ ATRACE_NAME("write_packet");
char buff[8];
if (!name) {
snprintf(buff, sizeof buff, "fd=%d", fd);
name = buff;
}
VLOG(TRANSPORT) << dump_packet(name, "to remote", *ppacket);
- char* p = reinterpret_cast<char*>(ppacket); /* we really write the packet address */
+ char* p = reinterpret_cast<char*>(ppacket); /* we really write the packet address */
int len = sizeof(apacket*);
- while(len > 0) {
+ while (len > 0) {
int r = adb_write(fd, p, len);
- if(r > 0) {
+ if (r > 0) {
len -= r;
p += r;
} else {
@@ -136,16 +135,15 @@
return 0;
}
-static void transport_socket_events(int fd, unsigned events, void *_t)
-{
- atransport *t = reinterpret_cast<atransport*>(_t);
+static void transport_socket_events(int fd, unsigned events, void* _t) {
+ atransport* t = reinterpret_cast<atransport*>(_t);
D("transport_socket_events(fd=%d, events=%04x,...)", fd, events);
- if(events & FDE_READ){
- apacket *p = 0;
- if(read_packet(fd, t->serial, &p)){
+ if (events & FDE_READ) {
+ apacket* p = 0;
+ if (read_packet(fd, t->serial, &p)) {
D("%s: failed to read packet from transport socket on fd %d", t->serial, fd);
} else {
- handle_packet(p, (atransport *) _t);
+ handle_packet(p, (atransport*)_t);
}
}
}
@@ -179,40 +177,43 @@
// read_transport thread reads data from a transport (representing a usb/tcp connection),
// and makes the main thread call handle_packet().
static void read_transport_thread(void* _t) {
- atransport *t = reinterpret_cast<atransport*>(_t);
- apacket *p;
+ atransport* t = reinterpret_cast<atransport*>(_t);
+ apacket* p;
- adb_thread_setname(android::base::StringPrintf("<-%s",
- (t->serial != nullptr ? t->serial : "transport")));
- D("%s: starting read_transport thread on fd %d, SYNC online (%d)",
- t->serial, t->fd, t->sync_token + 1);
+ adb_thread_setname(
+ android::base::StringPrintf("<-%s", (t->serial != nullptr ? t->serial : "transport")));
+ D("%s: starting read_transport thread on fd %d, SYNC online (%d)", t->serial, t->fd,
+ t->sync_token + 1);
p = get_apacket();
p->msg.command = A_SYNC;
p->msg.arg0 = 1;
p->msg.arg1 = ++(t->sync_token);
p->msg.magic = A_SYNC ^ 0xffffffff;
- if(write_packet(t->fd, t->serial, &p)) {
+ if (write_packet(t->fd, t->serial, &p)) {
put_apacket(p);
D("%s: failed to write SYNC packet", t->serial);
goto oops;
}
D("%s: data pump started", t->serial);
- for(;;) {
+ for (;;) {
+ ATRACE_NAME("read_transport loop");
p = get_apacket();
- if(t->read_from_remote(p, t) == 0){
- D("%s: received remote packet, sending to transport",
- t->serial);
- if(write_packet(t->fd, t->serial, &p)){
+ {
+ ATRACE_NAME("read_transport read_remote");
+ if (t->read_from_remote(p, t) != 0) {
+ D("%s: remote read failed for transport", t->serial);
put_apacket(p);
- D("%s: failed to write apacket to transport", t->serial);
- goto oops;
+ break;
}
- } else {
- D("%s: remote read failed for transport", t->serial);
+ }
+
+ D("%s: received remote packet, sending to transport", t->serial);
+ if (write_packet(t->fd, t->serial, &p)) {
put_apacket(p);
- break;
+ D("%s: failed to write apacket to transport", t->serial);
+ goto oops;
}
}
@@ -222,7 +223,7 @@
p->msg.arg0 = 0;
p->msg.arg1 = 0;
p->msg.magic = A_SYNC ^ 0xffffffff;
- if(write_packet(t->fd, t->serial, &p)) {
+ if (write_packet(t->fd, t->serial, &p)) {
put_apacket(p);
D("%s: failed to write SYNC apacket to transport", t->serial);
}
@@ -236,38 +237,38 @@
// write_transport thread gets packets sent by the main thread (through send_packet()),
// and writes to a transport (representing a usb/tcp connection).
static void write_transport_thread(void* _t) {
- atransport *t = reinterpret_cast<atransport*>(_t);
- apacket *p;
+ atransport* t = reinterpret_cast<atransport*>(_t);
+ apacket* p;
int active = 0;
- adb_thread_setname(android::base::StringPrintf("->%s",
- (t->serial != nullptr ? t->serial : "transport")));
- D("%s: starting write_transport thread, reading from fd %d",
- t->serial, t->fd);
+ adb_thread_setname(
+ android::base::StringPrintf("->%s", (t->serial != nullptr ? t->serial : "transport")));
+ D("%s: starting write_transport thread, reading from fd %d", t->serial, t->fd);
- for(;;){
- if(read_packet(t->fd, t->serial, &p)) {
- D("%s: failed to read apacket from transport on fd %d",
- t->serial, t->fd );
+ for (;;) {
+ ATRACE_NAME("write_transport loop");
+ if (read_packet(t->fd, t->serial, &p)) {
+ D("%s: failed to read apacket from transport on fd %d", t->serial, t->fd);
break;
}
- if(p->msg.command == A_SYNC){
- if(p->msg.arg0 == 0) {
+
+ if (p->msg.command == A_SYNC) {
+ if (p->msg.arg0 == 0) {
D("%s: transport SYNC offline", t->serial);
put_apacket(p);
break;
} else {
- if(p->msg.arg1 == t->sync_token) {
+ if (p->msg.arg1 == t->sync_token) {
D("%s: transport SYNC online", t->serial);
active = 1;
} else {
- D("%s: transport ignoring SYNC %d != %d",
- t->serial, p->msg.arg1, t->sync_token);
+ D("%s: transport ignoring SYNC %d != %d", t->serial, p->msg.arg1, t->sync_token);
}
}
} else {
- if(active) {
+ if (active) {
D("%s: transport got packet, sending to remote", t->serial);
+ ATRACE_NAME("write_transport write_remote");
t->write_to_remote(p, t);
} else {
D("%s: transport ignoring packet while offline", t->serial);
@@ -295,7 +296,6 @@
static int transport_registration_recv = -1;
static fdevent transport_registration_fde;
-
#if ADB_HOST
/* this adds support required by the 'track-devices' service.
@@ -304,19 +304,17 @@
* live TCP connection
*/
struct device_tracker {
- asocket socket;
- int update_needed;
- device_tracker* next;
+ asocket socket;
+ int update_needed;
+ device_tracker* next;
};
/* linked list of all device trackers */
-static device_tracker* device_tracker_list;
+static device_tracker* device_tracker_list;
-static void
-device_tracker_remove( device_tracker* tracker )
-{
- device_tracker** pnode = &device_tracker_list;
- device_tracker* node = *pnode;
+static void device_tracker_remove(device_tracker* tracker) {
+ device_tracker** pnode = &device_tracker_list;
+ device_tracker* node = *pnode;
std::lock_guard<std::mutex> lock(transport_lock);
while (node) {
@@ -325,17 +323,15 @@
break;
}
pnode = &node->next;
- node = *pnode;
+ node = *pnode;
}
}
-static void
-device_tracker_close( asocket* socket )
-{
- device_tracker* tracker = (device_tracker*) socket;
- asocket* peer = socket->peer;
+static void device_tracker_close(asocket* socket) {
+ device_tracker* tracker = (device_tracker*)socket;
+ asocket* peer = socket->peer;
- D( "device tracker %p removed", tracker);
+ D("device tracker %p removed", tracker);
if (peer) {
peer->peer = NULL;
peer->close(peer);
@@ -344,9 +340,7 @@
free(tracker);
}
-static int
-device_tracker_enqueue( asocket* socket, apacket* p )
-{
+static int device_tracker_enqueue(asocket* socket, apacket* p) {
/* you can't read from a device tracker, close immediately */
put_apacket(p);
device_tracker_close(socket);
@@ -376,26 +370,23 @@
}
}
-asocket*
-create_device_tracker(void)
-{
+asocket* create_device_tracker(void) {
device_tracker* tracker = reinterpret_cast<device_tracker*>(calloc(1, sizeof(*tracker)));
if (tracker == nullptr) fatal("cannot allocate device tracker");
- D( "device tracker %p created", tracker);
+ D("device tracker %p created", tracker);
tracker->socket.enqueue = device_tracker_enqueue;
- tracker->socket.ready = device_tracker_ready;
- tracker->socket.close = device_tracker_close;
- tracker->update_needed = 1;
+ tracker->socket.ready = device_tracker_ready;
+ tracker->socket.close = device_tracker_close;
+ tracker->update_needed = 1;
- tracker->next = device_tracker_list;
+ tracker->next = device_tracker_list;
device_tracker_list = tracker;
return &tracker->socket;
}
-
// Call this function each time the transport list has changed.
void update_transports() {
std::string transports = list_transports(false);
@@ -415,26 +406,23 @@
// Nothing to do on the device side.
}
-#endif // ADB_HOST
+#endif // ADB_HOST
-struct tmsg
-{
- atransport *transport;
- int action;
+struct tmsg {
+ atransport* transport;
+ int action;
};
-static int
-transport_read_action(int fd, struct tmsg* m)
-{
- char *p = (char*)m;
- int len = sizeof(*m);
- int r;
+static int transport_read_action(int fd, struct tmsg* m) {
+ char* p = (char*)m;
+ int len = sizeof(*m);
+ int r;
- while(len > 0) {
+ while (len > 0) {
r = adb_read(fd, p, len);
- if(r > 0) {
+ if (r > 0) {
len -= r;
- p += r;
+ p += r;
} else {
D("transport_read_action: on fd %d: %s", fd, strerror(errno));
return -1;
@@ -443,18 +431,16 @@
return 0;
}
-static int
-transport_write_action(int fd, struct tmsg* m)
-{
- char *p = (char*)m;
- int len = sizeof(*m);
- int r;
+static int transport_write_action(int fd, struct tmsg* m) {
+ char* p = (char*)m;
+ int len = sizeof(*m);
+ int r;
- while(len > 0) {
+ while (len > 0) {
r = adb_write(fd, p, len);
- if(r > 0) {
+ if (r > 0) {
len -= r;
- p += r;
+ p += r;
} else {
D("transport_write_action: on fd %d: %s", fd, strerror(errno));
return -1;
@@ -463,17 +449,16 @@
return 0;
}
-static void transport_registration_func(int _fd, unsigned ev, void *data)
-{
+static void transport_registration_func(int _fd, unsigned ev, void* data) {
tmsg m;
int s[2];
- atransport *t;
+ atransport* t;
- if(!(ev & FDE_READ)) {
+ if (!(ev & FDE_READ)) {
return;
}
- if(transport_read_action(_fd, &m)) {
+ if (transport_read_action(_fd, &m)) {
fatal_errno("cannot read transport registration socket");
}
@@ -482,9 +467,9 @@
if (m.action == 0) {
D("transport: %s removing and free'ing %d", t->serial, t->transport_socket);
- /* IMPORTANT: the remove closes one half of the
- ** socket pair. The close closes the other half.
- */
+ /* IMPORTANT: the remove closes one half of the
+ ** socket pair. The close closes the other half.
+ */
fdevent_remove(&(t->transport_fde));
adb_close(t->fd);
@@ -493,16 +478,11 @@
transport_list.remove(t);
}
- if (t->product)
- free(t->product);
- if (t->serial)
- free(t->serial);
- if (t->model)
- free(t->model);
- if (t->device)
- free(t->device);
- if (t->devpath)
- free(t->devpath);
+ if (t->product) free(t->product);
+ if (t->serial) free(t->serial);
+ if (t->model) free(t->model);
+ if (t->device) free(t->device);
+ if (t->devpath) free(t->devpath);
delete t;
@@ -524,10 +504,7 @@
t->transport_socket = s[0];
t->fd = s[1];
- fdevent_install(&(t->transport_fde),
- t->transport_socket,
- transport_socket_events,
- t);
+ fdevent_install(&(t->transport_fde), t->transport_socket, transport_socket_events, t);
fdevent_set(&(t->transport_fde), FDE_READ);
@@ -549,11 +526,10 @@
update_transports();
}
-void init_transport_registration(void)
-{
+void init_transport_registration(void) {
int s[2];
- if(adb_socketpair(s)){
+ if (adb_socketpair(s)) {
fatal_errno("cannot open transport registration socketpair");
}
D("socketpair: (%d,%d)", s[0], s[1]);
@@ -561,38 +537,33 @@
transport_registration_send = s[0];
transport_registration_recv = s[1];
- fdevent_install(&transport_registration_fde,
- transport_registration_recv,
- transport_registration_func,
- 0);
+ fdevent_install(&transport_registration_fde, transport_registration_recv,
+ transport_registration_func, 0);
fdevent_set(&transport_registration_fde, FDE_READ);
}
/* the fdevent select pump is single threaded */
-static void register_transport(atransport *transport)
-{
+static void register_transport(atransport* transport) {
tmsg m;
m.transport = transport;
m.action = 1;
D("transport: %s registered", transport->serial);
- if(transport_write_action(transport_registration_send, &m)) {
+ if (transport_write_action(transport_registration_send, &m)) {
fatal_errno("cannot write transport registration socket\n");
}
}
-static void remove_transport(atransport *transport)
-{
+static void remove_transport(atransport* transport) {
tmsg m;
m.transport = transport;
m.action = 0;
D("transport: %s removed", transport->serial);
- if(transport_write_action(transport_registration_send, &m)) {
+ if (transport_write_action(transport_registration_send, &m)) {
fatal_errno("cannot write transport registration socket\n");
}
}
-
static void transport_unref(atransport* t) {
CHECK(t != nullptr);
@@ -608,37 +579,31 @@
}
}
-static int qual_match(const char *to_test,
- const char *prefix, const char *qual, bool sanitize_qual)
-{
- if (!to_test || !*to_test)
- /* Return true if both the qual and to_test are null strings. */
+static int qual_match(const char* to_test, const char* prefix, const char* qual,
+ bool sanitize_qual) {
+ if (!to_test || !*to_test) /* Return true if both the qual and to_test are null strings. */
return !qual || !*qual;
- if (!qual)
- return 0;
+ if (!qual) return 0;
if (prefix) {
while (*prefix) {
- if (*prefix++ != *to_test++)
- return 0;
+ if (*prefix++ != *to_test++) return 0;
}
}
while (*qual) {
char ch = *qual++;
- if (sanitize_qual && !isalnum(ch))
- ch = '_';
- if (ch != *to_test++)
- return 0;
+ if (sanitize_qual && !isalnum(ch)) ch = '_';
+ if (ch != *to_test++) return 0;
}
/* Everything matched so far. Return true if *to_test is a NUL. */
return !*to_test;
}
-atransport* acquire_one_transport(TransportType type, const char* serial,
- bool* is_ambiguous, std::string* error_out) {
+atransport* acquire_one_transport(TransportType type, const char* serial, bool* is_ambiguous,
+ std::string* error_out) {
atransport* result = nullptr;
if (serial) {
@@ -736,15 +701,24 @@
const std::string atransport::connection_state_name() const {
switch (connection_state) {
- case kCsOffline: return "offline";
- case kCsBootloader: return "bootloader";
- case kCsDevice: return "device";
- case kCsHost: return "host";
- case kCsRecovery: return "recovery";
- case kCsNoPerm: return UsbNoPermissionsShortHelpText();
- case kCsSideload: return "sideload";
- case kCsUnauthorized: return "unauthorized";
- default: return "unknown";
+ case kCsOffline:
+ return "offline";
+ case kCsBootloader:
+ return "bootloader";
+ case kCsDevice:
+ return "device";
+ case kCsHost:
+ return "host";
+ case kCsRecovery:
+ return "recovery";
+ case kCsNoPerm:
+ return UsbNoPermissionsShortHelpText();
+ case kCsSideload:
+ return "sideload";
+ case kCsUnauthorized:
+ return "unauthorized";
+ default:
+ return "unknown";
}
}
@@ -770,8 +744,7 @@
const FeatureSet& supported_features() {
// Local static allocation to avoid global non-POD variables.
static const FeatureSet* features = new FeatureSet{
- kFeatureShell2,
- kFeatureCmd
+ kFeatureShell2, kFeatureCmd, kFeatureStat2,
// Increment ADB_SERVER_VERSION whenever the feature list changes to
// make sure that the adb client and server features stay in sync
// (http://b/24370690).
@@ -789,14 +762,12 @@
return FeatureSet();
}
- auto names = android::base::Split(features_string,
- {kFeatureStringDelimiter});
+ auto names = android::base::Split(features_string, {kFeatureStringDelimiter});
return FeatureSet(names.begin(), names.end());
}
bool CanUseFeature(const FeatureSet& feature_set, const std::string& feature) {
- return feature_set.count(feature) > 0 &&
- supported_features().count(feature) > 0;
+ return feature_set.count(feature) > 0 && supported_features().count(feature) > 0;
}
bool atransport::has_feature(const std::string& feature) const {
@@ -832,21 +803,20 @@
// For fastboot compatibility, ignore protocol prefixes.
if (android::base::StartsWith(target, "tcp:") ||
- android::base::StartsWith(target, "udp:")) {
+ android::base::StartsWith(target, "udp:")) {
local_target_ptr += 4;
}
// Parse our |serial| and the given |target| to check if the hostnames and ports match.
std::string serial_host, error;
int serial_port = -1;
- if (android::base::ParseNetAddress(serial, &serial_host, &serial_port, nullptr,
- &error)) {
+ if (android::base::ParseNetAddress(serial, &serial_host, &serial_port, nullptr, &error)) {
// |target| may omit the port to default to ours.
std::string target_host;
int target_port = serial_port;
if (android::base::ParseNetAddress(local_target_ptr, &target_host, &target_port,
nullptr, &error) &&
- serial_host == target_host && serial_port == target_port) {
+ serial_host == target_host && serial_port == target_port) {
return true;
}
}
@@ -861,8 +831,8 @@
#if ADB_HOST
-static void append_transport_info(std::string* result, const char* key,
- const char* value, bool sanitize) {
+static void append_transport_info(std::string* result, const char* key, const char* value,
+ bool sanitize) {
if (value == nullptr || *value == '\0') {
return;
}
@@ -875,8 +845,7 @@
}
}
-static void append_transport(const atransport* t, std::string* result,
- bool long_listing) {
+static void append_transport(const atransport* t, std::string* result, bool long_listing) {
const char* serial = t->serial;
if (!serial || !serial[0]) {
serial = "(no serial number)";
@@ -887,8 +856,7 @@
*result += '\t';
*result += t->connection_state_name();
} else {
- android::base::StringAppendF(result, "%-22s %s", serial,
- t->connection_state_name().c_str());
+ android::base::StringAppendF(result, "%-22s %s", serial, t->connection_state_name().c_str());
append_transport_info(result, "", t->devpath, false);
append_transport_info(result, "product:", t->product, false);
@@ -921,9 +889,9 @@
void close_usb_devices() {
close_usb_devices([](const atransport*) { return true; });
}
-#endif // ADB_HOST
+#endif // ADB_HOST
-int register_socket_transport(int s, const char *serial, int port, int local) {
+int register_socket_transport(int s, const char* serial, int port, int local) {
atransport* t = new atransport();
if (!serial) {
@@ -942,7 +910,7 @@
for (const auto& transport : pending_list) {
if (transport->serial && strcmp(serial, transport->serial) == 0) {
VLOG(TRANSPORT) << "socket transport " << transport->serial
- << " is already in pending_list and fails to register";
+ << " is already in pending_list and fails to register";
delete t;
return -1;
}
@@ -951,7 +919,7 @@
for (const auto& transport : transport_list) {
if (transport->serial && strcmp(serial, transport->serial) == 0) {
VLOG(TRANSPORT) << "socket transport " << transport->serial
- << " is already in transport_list and fails to register";
+ << " is already in transport_list and fails to register";
delete t;
return -1;
}
@@ -967,7 +935,7 @@
}
#if ADB_HOST
-atransport *find_transport(const char *serial) {
+atransport* find_transport(const char* serial) {
atransport* result = nullptr;
std::lock_guard<std::mutex> lock(transport_lock);
@@ -996,14 +964,13 @@
#endif
-void register_usb_transport(usb_handle* usb, const char* serial,
- const char* devpath, unsigned writeable) {
+void register_usb_transport(usb_handle* usb, const char* serial, const char* devpath,
+ unsigned writeable) {
atransport* t = new atransport();
- D("transport: %p init'ing for usb_handle %p (sn='%s')", t, usb,
- serial ? serial : "");
+ D("transport: %p init'ing for usb_handle %p (sn='%s')", t, usb, serial ? serial : "");
init_usb_transport(t, usb, (writeable ? kCsOffline : kCsNoPerm));
- if(serial) {
+ if (serial) {
t->serial = strdup(serial);
}
@@ -1020,23 +987,21 @@
}
// This should only be used for transports with connection_state == kCsNoPerm.
-void unregister_usb_transport(usb_handle *usb) {
+void unregister_usb_transport(usb_handle* usb) {
std::lock_guard<std::mutex> lock(transport_lock);
- transport_list.remove_if([usb](atransport* t) {
- return t->usb == usb && t->connection_state == kCsNoPerm;
- });
+ transport_list.remove_if(
+ [usb](atransport* t) { return t->usb == usb && t->connection_state == kCsNoPerm; });
}
-int check_header(apacket *p, atransport *t)
-{
- if(p->msg.magic != (p->msg.command ^ 0xffffffff)) {
+int check_header(apacket* p, atransport* t) {
+ if (p->msg.magic != (p->msg.command ^ 0xffffffff)) {
VLOG(RWX) << "check_header(): invalid magic";
return -1;
}
- if(p->msg.data_length > t->get_max_payload()) {
- VLOG(RWX) << "check_header(): " << p->msg.data_length << " atransport::max_payload = "
- << t->get_max_payload();
+ if (p->msg.data_length > t->get_max_payload()) {
+ VLOG(RWX) << "check_header(): " << p->msg.data_length
+ << " atransport::max_payload = " << t->get_max_payload();
return -1;
}
diff --git a/adb/transport.h b/adb/transport.h
index b2df838..3306388 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -46,6 +46,7 @@
extern const char* const kFeatureShell2;
// The 'cmd' command is available
extern const char* const kFeatureCmd;
+extern const char* const kFeatureStat2;
class atransport {
public:
diff --git a/base/include/android-base/memory.h b/base/include/android-base/memory.h
index 3a2f8fa..9971226 100644
--- a/base/include/android-base/memory.h
+++ b/base/include/android-base/memory.h
@@ -20,25 +20,19 @@
namespace android {
namespace base {
-// Use packed structures for access to unaligned data on targets with alignment
+// Use memcpy for access to unaligned data on targets with alignment
// restrictions. The compiler will generate appropriate code to access these
// structures without generating alignment exceptions.
template <typename T>
-static inline T get_unaligned(const T* address) {
- struct unaligned {
- T v;
- } __attribute__((packed));
- const unaligned* p = reinterpret_cast<const unaligned*>(address);
- return p->v;
+static inline T get_unaligned(const void* address) {
+ T result;
+ memcpy(&result, address, sizeof(T));
+ return result;
}
template <typename T>
-static inline void put_unaligned(T* address, T v) {
- struct unaligned {
- T v;
- } __attribute__((packed));
- unaligned* p = reinterpret_cast<unaligned*>(address);
- p->v = v;
+static inline void put_unaligned(void* address, T v) {
+ memcpy(address, &v, sizeof(T));
}
} // namespace base
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index 272fbf6..9b82f64 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -185,6 +185,16 @@
return allowed;
}
+static bool pid_contains_tid(pid_t pid, pid_t tid) {
+ char task_path[PATH_MAX];
+ if (snprintf(task_path, PATH_MAX, "/proc/%d/task/%d", pid, tid) >= PATH_MAX) {
+ ALOGE("debuggerd: task path overflow (pid = %d, tid = %d)\n", pid, tid);
+ exit(1);
+ }
+
+ return access(task_path, F_OK) == 0;
+}
+
static int read_request(int fd, debugger_request_t* out_request) {
ucred cr;
socklen_t len = sizeof(cr);
@@ -227,16 +237,13 @@
if (msg.action == DEBUGGER_ACTION_CRASH) {
// Ensure that the tid reported by the crashing process is valid.
- char buf[64];
- struct stat s;
- snprintf(buf, sizeof buf, "/proc/%d/task/%d", out_request->pid, out_request->tid);
- if (stat(buf, &s)) {
- ALOGE("tid %d does not exist in pid %d. ignoring debug request\n",
- out_request->tid, out_request->pid);
+ // This check needs to happen again after ptracing the requested thread to prevent a race.
+ if (!pid_contains_tid(out_request->pid, out_request->tid)) {
+ ALOGE("tid %d does not exist in pid %d. ignoring debug request\n", out_request->tid,
+ out_request->pid);
return -1;
}
- } else if (cr.uid == 0
- || (cr.uid == AID_SYSTEM && msg.action == DEBUGGER_ACTION_DUMP_BACKTRACE)) {
+ } else if (cr.uid == 0 || (cr.uid == AID_SYSTEM && msg.action == DEBUGGER_ACTION_DUMP_BACKTRACE)) {
// Only root or system can ask us to attach to any process and dump it explicitly.
// However, system is only allowed to collect backtraces but cannot dump tombstones.
status = get_process_info(out_request->tid, &out_request->pid,
@@ -413,10 +420,31 @@
}
#endif
-static void ptrace_siblings(pid_t pid, pid_t main_tid, pid_t ignore_tid, std::set<pid_t>& tids) {
- char task_path[64];
+// Attach to a thread, and verify that it's still a member of the given process
+static bool ptrace_attach_thread(pid_t pid, pid_t tid) {
+ if (ptrace(PTRACE_ATTACH, tid, 0, 0) != 0) {
+ return false;
+ }
- snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid);
+ // Make sure that the task we attached to is actually part of the pid we're dumping.
+ if (!pid_contains_tid(pid, tid)) {
+ if (ptrace(PTRACE_DETACH, tid, 0, 0) != 0) {
+ ALOGE("debuggerd: failed to detach from thread '%d'", tid);
+ exit(1);
+ }
+ return false;
+ }
+
+ return true;
+}
+
+static void ptrace_siblings(pid_t pid, pid_t main_tid, pid_t ignore_tid, std::set<pid_t>& tids) {
+ char task_path[PATH_MAX];
+
+ if (snprintf(task_path, PATH_MAX, "/proc/%d/task", pid) >= PATH_MAX) {
+ ALOGE("debuggerd: task path overflow (pid = %d)\n", pid);
+ abort();
+ }
std::unique_ptr<DIR, int (*)(DIR*)> d(opendir(task_path), closedir);
@@ -443,7 +471,7 @@
continue;
}
- if (ptrace(PTRACE_ATTACH, tid, 0, 0) < 0) {
+ if (!ptrace_attach_thread(pid, tid)) {
ALOGE("debuggerd: ptrace attach to %d failed: %s", tid, strerror(errno));
continue;
}
@@ -572,11 +600,33 @@
// debugger_signal_handler().
// Attach to the target process.
- if (ptrace(PTRACE_ATTACH, request.tid, 0, 0) != 0) {
+ if (!ptrace_attach_thread(request.pid, request.tid)) {
ALOGE("debuggerd: ptrace attach failed: %s", strerror(errno));
exit(1);
}
+ // DEBUGGER_ACTION_CRASH requests can come from arbitrary processes and the tid field in the
+ // request is sent from the other side. If an attacker can cause a process to be spawned with the
+ // pid of their process, they could trick debuggerd into dumping that process by exiting after
+ // sending the request. Validate the trusted request.uid/gid to defend against this.
+ if (request.action == DEBUGGER_ACTION_CRASH) {
+ pid_t pid;
+ uid_t uid;
+ gid_t gid;
+ if (get_process_info(request.tid, &pid, &uid, &gid) != 0) {
+ ALOGE("debuggerd: failed to get process info for tid '%d'", request.tid);
+ exit(1);
+ }
+
+ if (pid != request.pid || uid != request.uid || gid != request.gid) {
+ ALOGE(
+ "debuggerd: attached task %d does not match request: "
+ "expected pid=%d,uid=%d,gid=%d, actual pid=%d,uid=%d,gid=%d",
+ request.tid, request.pid, request.uid, request.gid, pid, uid, gid);
+ exit(1);
+ }
+ }
+
// Don't attach to the sibling threads if we want to attach gdb.
// Supposedly, it makes the process less reliable.
bool attach_gdb = should_attach_gdb(request);
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index f682216..740720b 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -22,7 +22,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/swap.h>
@@ -39,7 +38,6 @@
#include <ext4_utils/ext4_sb.h>
#include <ext4_utils/ext4_utils.h>
#include <ext4_utils/wipe.h>
-#include <linux/fs.h>
#include <linux/loop.h>
#include <logwrap/logwrap.h>
#include <private/android_filesystem_config.h>
@@ -52,9 +50,8 @@
#define KEY_IN_FOOTER "footer"
#define E2FSCK_BIN "/system/bin/e2fsck"
-#define F2FS_FSCK_BIN "/system/bin/fsck.f2fs"
+#define F2FS_FSCK_BIN "/system/bin/fsck.f2fs"
#define MKSWAP_BIN "/system/bin/mkswap"
-#define TUNE2FS_BIN "/system/bin/tune2fs"
#define FSCK_LOG_FILE "/dev/fscklogs/log"
@@ -183,99 +180,6 @@
return;
}
-/* Function to read the primary superblock */
-static int read_super_block(int fd, struct ext4_super_block *sb)
-{
- off64_t ret;
-
- ret = lseek64(fd, 1024, SEEK_SET);
- if (ret < 0)
- return ret;
-
- ret = read(fd, sb, sizeof(*sb));
- if (ret < 0)
- return ret;
- if (ret != sizeof(*sb))
- return ret;
-
- return 0;
-}
-
-static ext4_fsblk_t ext4_blocks_count(struct ext4_super_block *es)
-{
- return ((ext4_fsblk_t)le32_to_cpu(es->s_blocks_count_hi) << 32) |
- le32_to_cpu(es->s_blocks_count_lo);
-}
-
-static ext4_fsblk_t ext4_r_blocks_count(struct ext4_super_block *es)
-{
- return ((ext4_fsblk_t)le32_to_cpu(es->s_r_blocks_count_hi) << 32) |
- le32_to_cpu(es->s_r_blocks_count_lo);
-}
-
-static void do_reserved_size(char *blk_device, char *fs_type, struct fstab_rec *rec)
-{
- /* Check for the types of filesystems we know how to check */
- if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !strcmp(fs_type, "ext4")) {
- /*
- * Some system images do not have tune2fs for licensing reasons
- * Detect these and skip reserve blocks.
- */
- if (access(TUNE2FS_BIN, X_OK)) {
- ERROR("Not running %s on %s (executable not in system image)\n",
- TUNE2FS_BIN, blk_device);
- } else {
- INFO("Running %s on %s\n", TUNE2FS_BIN, blk_device);
-
- int status = 0;
- int ret = 0;
- unsigned long reserved_blocks = 0;
- int fd = TEMP_FAILURE_RETRY(open(blk_device, O_RDONLY | O_CLOEXEC));
- if (fd >= 0) {
- struct ext4_super_block sb;
- ret = read_super_block(fd, &sb);
- if (ret < 0) {
- ERROR("Can't read '%s' super block: %s\n", blk_device, strerror(errno));
- goto out;
- }
- reserved_blocks = rec->reserved_size / EXT4_BLOCK_SIZE(&sb);
- unsigned long reserved_threshold = ext4_blocks_count(&sb) * 0.02;
- if (reserved_threshold < reserved_blocks) {
- WARNING("Reserved blocks %lu is too large\n", reserved_blocks);
- reserved_blocks = reserved_threshold;
- }
-
- if (ext4_r_blocks_count(&sb) == reserved_blocks) {
- INFO("Have reserved same blocks\n");
- goto out;
- }
- } else {
- ERROR("Failed to open '%s': %s\n", blk_device, strerror(errno));
- return;
- }
-
- char buf[16] = {0};
- snprintf(buf, sizeof (buf), "-r %lu", reserved_blocks);
- char *tune2fs_argv[] = {
- TUNE2FS_BIN,
- buf,
- blk_device,
- };
-
- ret = android_fork_execvp_ext(ARRAY_SIZE(tune2fs_argv), tune2fs_argv,
- &status, true, LOG_KLOG | LOG_FILE,
- true, NULL, NULL, 0);
-
- if (ret < 0) {
- /* No need to check for error in fork, we can't really handle it now */
- ERROR("Failed trying to run %s\n", TUNE2FS_BIN);
- }
- out:
- close(fd);
- }
- }
-}
-
static void remove_trailing_slashes(char *n)
{
int len;
@@ -338,7 +242,7 @@
return ret;
}
-static int fs_match(const char *in1, const char *in2)
+static int fs_match(char *in1, char *in2)
{
char *n1;
char *n2;
@@ -421,12 +325,6 @@
check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
fstab->recs[i].mount_point);
}
-
- if (fstab->recs[i].fs_mgr_flags & MF_RESERVEDSIZE) {
- do_reserved_size(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
- &fstab->recs[i]);
- }
-
if (!__mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point, &fstab->recs[i])) {
*attempted_idx = i;
mounted = 1;
@@ -754,7 +652,7 @@
* If multiple fstab entries are to be mounted on "n_name", it will try to mount each one
* in turn, and stop on 1st success, or no more match.
*/
-int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device,
+int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device,
char *tmp_mount_point)
{
int i = 0;
@@ -792,10 +690,6 @@
fstab->recs[i].mount_point);
}
- if (fstab->recs[i].fs_mgr_flags & MF_RESERVEDSIZE) {
- do_reserved_size(n_blk_device, fstab->recs[i].fs_type, &fstab->recs[i]);
- }
-
if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
int rc = fs_mgr_setup_verity(&fstab->recs[i]);
if (__android_log_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c
index 472b421..0bc8bef 100644
--- a/fs_mgr/fs_mgr_fstab.c
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -33,12 +33,12 @@
int swap_prio;
int max_comp_streams;
unsigned int zram_size;
- uint64_t reserved_size;
+ unsigned int file_encryption_mode;
};
struct flag_list {
const char *name;
- unsigned flag;
+ unsigned int flag;
};
static struct flag_list mount_flags[] = {
@@ -65,7 +65,7 @@
{ "check", MF_CHECK },
{ "encryptable=",MF_CRYPT },
{ "forceencrypt=",MF_FORCECRYPT },
- { "fileencryption",MF_FILEENCRYPTION },
+ { "fileencryption=",MF_FILEENCRYPTION },
{ "forcefdeorfbe=",MF_FORCEFDEORFBE },
{ "nonremovable",MF_NONREMOVABLE },
{ "voldmanaged=",MF_VOLDMANAGED},
@@ -81,11 +81,19 @@
{ "slotselect", MF_SLOTSELECT },
{ "nofail", MF_NOFAIL },
{ "latemount", MF_LATEMOUNT },
- { "reservedsize=", MF_RESERVEDSIZE },
{ "defaults", 0 },
{ 0, 0 },
};
+#define EM_SOFTWARE 1
+#define EM_ICE 2
+
+static struct flag_list encryption_modes[] = {
+ {"software", EM_SOFTWARE},
+ {"ice", EM_ICE},
+ {0, 0}
+};
+
static uint64_t calculate_zram_size(unsigned int percentage)
{
uint64_t total;
@@ -99,20 +107,6 @@
return total;
}
-static uint64_t parse_size(const char *arg)
-{
- char *endptr;
- uint64_t size = strtoull(arg, &endptr, 10);
- if (*endptr == 'k' || *endptr == 'K')
- size *= 1024LL;
- else if (*endptr == 'm' || *endptr == 'M')
- size *= 1024LL * 1024LL;
- else if (*endptr == 'g' || *endptr == 'G')
- size *= 1024LL * 1024LL * 1024LL;
-
- return size;
-}
-
static int parse_flags(char *flags, struct flag_list *fl,
struct fs_mgr_flag_values *flag_vals,
char *fs_options, int fs_options_len)
@@ -166,6 +160,21 @@
* location of the keys. Get it and return it.
*/
flag_vals->key_loc = strdup(strchr(p, '=') + 1);
+ flag_vals->file_encryption_mode = EM_SOFTWARE;
+ } else if ((fl[i].flag == MF_FILEENCRYPTION) && flag_vals) {
+ /* The fileencryption flag is followed by an = and the
+ * type of the encryption. Get it and return it.
+ */
+ const struct flag_list *j;
+ const char *mode = strchr(p, '=') + 1;
+ for (j = encryption_modes; j->name; ++j) {
+ if (!strcmp(mode, j->name)) {
+ flag_vals->file_encryption_mode = j->flag;
+ }
+ }
+ if (flag_vals->file_encryption_mode == 0) {
+ ERROR("Unknown file encryption mode: %s\n", mode);
+ }
} else if ((fl[i].flag == MF_LENGTH) && flag_vals) {
/* The length flag is followed by an = and the
* size of the partition. Get it and return it.
@@ -207,11 +216,6 @@
flag_vals->zram_size = calculate_zram_size(val);
else
flag_vals->zram_size = val;
- } else if ((fl[i].flag == MF_RESERVEDSIZE) && flag_vals) {
- /* The reserved flag is followed by an = and the
- * reserved size of the partition. Get it and return it.
- */
- flag_vals->reserved_size = parse_size(strchr(p, '=') + 1);
}
break;
}
@@ -356,7 +360,7 @@
fstab->recs[cnt].swap_prio = flag_vals.swap_prio;
fstab->recs[cnt].max_comp_streams = flag_vals.max_comp_streams;
fstab->recs[cnt].zram_size = flag_vals.zram_size;
- fstab->recs[cnt].reserved_size = flag_vals.reserved_size;
+ fstab->recs[cnt].file_encryption_mode = flag_vals.file_encryption_mode;
cnt++;
}
/* If an A/B partition, modify block device to be the real block device */
@@ -515,6 +519,17 @@
return fstab->fs_mgr_flags & MF_FILEENCRYPTION;
}
+const char* fs_mgr_get_file_encryption_mode(const struct fstab_rec *fstab)
+{
+ const struct flag_list *j;
+ for (j = encryption_modes; j->name; ++j) {
+ if (fstab->file_encryption_mode == j->flag) {
+ return j->name;
+ }
+ }
+ return NULL;
+}
+
int fs_mgr_is_convertible_to_fbe(const struct fstab_rec *fstab)
{
return fstab->fs_mgr_flags & MF_FORCEFDEORFBE;
diff --git a/fs_mgr/fs_mgr_main.c b/fs_mgr/fs_mgr_main.c
index 4bfe202..33a7496 100644
--- a/fs_mgr/fs_mgr_main.c
+++ b/fs_mgr/fs_mgr_main.c
@@ -14,17 +14,12 @@
* limitations under the License.
*/
-#define _GNU_SOURCE
-
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <libgen.h>
#include "fs_mgr_priv.h"
-#ifdef _LIBGEN_H
-#warning "libgen.h must not be included"
-#endif
-
char *me = "";
static void usage(void)
@@ -37,10 +32,10 @@
* and exit the program, do not return to the caller.
* Return the number of argv[] entries consumed.
*/
-static void parse_options(int argc, char * const argv[], int *a_flag, int *u_flag, int *n_flag,
- const char **n_name, const char **n_blk_dev)
+static void parse_options(int argc, char *argv[], int *a_flag, int *u_flag, int *n_flag,
+ char **n_name, char **n_blk_dev)
{
- me = basename(argv[0]);
+ me = basename(strdup(argv[0]));
if (argc <= 1) {
usage();
@@ -80,14 +75,14 @@
return;
}
-int main(int argc, char * const argv[])
+int main(int argc, char *argv[])
{
int a_flag=0;
int u_flag=0;
int n_flag=0;
- const char *n_name=NULL;
- const char *n_blk_dev=NULL;
- const char *fstab_file=NULL;
+ char *n_name=NULL;
+ char *n_blk_dev=NULL;
+ char *fstab_file=NULL;
struct fstab *fstab=NULL;
klog_set_level(6);
@@ -102,7 +97,7 @@
if (a_flag) {
return fs_mgr_mount_all(fstab, MOUNT_MODE_DEFAULT);
} else if (n_flag) {
- return fs_mgr_do_mount(fstab, n_name, (char *)n_blk_dev, 0);
+ return fs_mgr_do_mount(fstab, n_name, n_blk_dev, 0);
} else if (u_flag) {
return fs_mgr_unmount_all(fstab);
} else {
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 23c97e4..741f5e9 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -86,7 +86,6 @@
#define MF_LATEMOUNT 0x20000
#define MF_NOFAIL 0x40000
#define MF_MAX_COMP_STREAMS 0x100000
-#define MF_RESERVEDSIZE 0x200000
#define DM_BUF_SIZE 4096
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index 67104cc..031b042 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -181,7 +181,7 @@
return -1;
}
-static void verity_ioctl_init(struct dm_ioctl *io, char *name, unsigned flags)
+static void verity_ioctl_init(struct dm_ioctl *io, const char *name, unsigned flags)
{
memset(io, 0, DM_BUF_SIZE);
io->data_size = DM_BUF_SIZE;
@@ -784,8 +784,9 @@
int fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback)
{
alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
+ bool system_root = false;
char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
- char *mount_point;
+ const char *mount_point;
char propbuf[PROPERTY_VALUE_MAX];
char *status;
int fd = -1;
@@ -813,6 +814,9 @@
property_get("ro.hardware", propbuf, "");
snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf);
+ property_get("ro.build.system_root_image", propbuf, "");
+ system_root = !strcmp(propbuf, "true");
+
fstab = fs_mgr_read_fstab(fstab_filename);
if (!fstab) {
@@ -825,7 +829,12 @@
continue;
}
- mount_point = basename(fstab->recs[i].mount_point);
+ if (system_root && !strcmp(fstab->recs[i].mount_point, "/")) {
+ mount_point = "system";
+ } else {
+ mount_point = basename(fstab->recs[i].mount_point);
+ }
+
verity_ioctl_init(io, mount_point, 0);
if (ioctl(fd, DM_TABLE_STATUS, io)) {
@@ -836,7 +845,9 @@
status = &buffer[io->data_start + sizeof(struct dm_target_spec)];
- callback(&fstab->recs[i], mount_point, mode, *status);
+ if (*status == 'C' || *status == 'V') {
+ callback(&fstab->recs[i], mount_point, mode, *status);
+ }
}
rc = 0;
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 43aef20..9323069 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -75,7 +75,7 @@
int swap_prio;
int max_comp_streams;
unsigned int zram_size;
- uint64_t reserved_size;
+ unsigned int file_encryption_mode;
};
// Callback function for verity status
@@ -97,7 +97,8 @@
#define FS_MGR_DOMNT_FAILED (-1)
#define FS_MGR_DOMNT_BUSY (-2)
-int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device,
+
+int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device,
char *tmp_mount_point);
int fs_mgr_do_tmpfs_mount(char *n_name);
int fs_mgr_unmount_all(struct fstab *fstab);
@@ -114,6 +115,7 @@
int fs_mgr_is_verified(const struct fstab_rec *fstab);
int fs_mgr_is_encryptable(const struct fstab_rec *fstab);
int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab);
+const char* fs_mgr_get_file_encryption_mode(const struct fstab_rec *fstab);
int fs_mgr_is_convertible_to_fbe(const struct fstab_rec *fstab);
int fs_mgr_is_noemulatedsd(const struct fstab_rec *fstab);
int fs_mgr_is_notrim(struct fstab_rec *fstab);
diff --git a/gatekeeperd/SoftGateKeeper.h b/gatekeeperd/SoftGateKeeper.h
index 8b15d72..cb02a6f 100644
--- a/gatekeeperd/SoftGateKeeper.h
+++ b/gatekeeperd/SoftGateKeeper.h
@@ -152,7 +152,7 @@
}
bool DoVerify(const password_handle_t *expected_handle, const SizedBuffer &password) {
- uint64_t user_id = android::base::get_unaligned(&expected_handle->user_id);
+ uint64_t user_id = android::base::get_unaligned<secure_id_t>(&expected_handle->user_id);
FastHashMap::const_iterator it = fast_hash_map_.find(user_id);
if (it != fast_hash_map_.end() && VerifyFast(it->second, password)) {
return true;
diff --git a/healthd/Android.mk b/healthd/Android.mk
index deebed5..7c5e35b 100644
--- a/healthd/Android.mk
+++ b/healthd/Android.mk
@@ -21,6 +21,36 @@
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
+LOCAL_SRC_FILES := \
+ healthd_mode_android.cpp \
+ healthd_mode_charger.cpp \
+ AnimationParser.cpp \
+ BatteryPropertiesRegistrar.cpp \
+
+LOCAL_MODULE := libhealthd_internal
+LOCAL_C_INCLUDES := bootable/recovery
+LOCAL_EXPORT_C_INCLUDE_DIRS := \
+ $(LOCAL_PATH) \
+ $(LOCAL_PATH)/include \
+
+LOCAL_STATIC_LIBRARIES := \
+ libbatterymonitor \
+ libbatteryservice \
+ libbinder \
+ libminui \
+ libpng \
+ libz \
+ libutils \
+ libbase \
+ libcutils \
+ liblog \
+ libm \
+ libc \
+
+include $(BUILD_STATIC_LIBRARY)
+
+
+include $(CLEAR_VARS)
ifeq ($(strip $(BOARD_CHARGER_NO_UI)),true)
LOCAL_CHARGER_NO_UI := true
@@ -32,7 +62,7 @@
LOCAL_SRC_FILES := \
healthd.cpp \
healthd_mode_android.cpp \
- BatteryPropertiesRegistrar.cpp
+ BatteryPropertiesRegistrar.cpp \
ifneq ($(strip $(LOCAL_CHARGER_NO_UI)),true)
LOCAL_SRC_FILES += healthd_mode_charger.cpp
@@ -60,13 +90,28 @@
LOCAL_C_INCLUDES := bootable/recovery $(LOCAL_PATH)/include
-LOCAL_STATIC_LIBRARIES := libbatterymonitor libbatteryservice libbinder libbase
+LOCAL_STATIC_LIBRARIES := \
+ libhealthd_internal \
+ libbatterymonitor \
+ libbatteryservice \
+ libbinder \
+ libbase \
ifneq ($(strip $(LOCAL_CHARGER_NO_UI)),true)
-LOCAL_STATIC_LIBRARIES += libminui libpng libz
+LOCAL_STATIC_LIBRARIES += \
+ libminui \
+ libpng \
+ libz \
+
endif
-LOCAL_STATIC_LIBRARIES += libutils libcutils liblog libm libc
+
+LOCAL_STATIC_LIBRARIES += \
+ libutils \
+ libcutils \
+ liblog \
+ libm \
+ libc \
ifeq ($(strip $(BOARD_CHARGER_ENABLE_SUSPEND)),true)
LOCAL_STATIC_LIBRARIES += libsuspend
@@ -84,7 +129,7 @@
ifneq ($(strip $(LOCAL_CHARGER_NO_UI)),true)
define _add-charger-image
include $$(CLEAR_VARS)
-LOCAL_MODULE := system_core_charger_$(notdir $(1))
+LOCAL_MODULE := system_core_charger_res_images_$(notdir $(1))
LOCAL_MODULE_STEM := $(notdir $(1))
_img_modules += $$(LOCAL_MODULE)
LOCAL_SRC_FILES := $1
diff --git a/healthd/AnimationParser.cpp b/healthd/AnimationParser.cpp
new file mode 100644
index 0000000..864038b
--- /dev/null
+++ b/healthd/AnimationParser.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 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 "AnimationParser.h"
+
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+
+#include <cutils/klog.h>
+
+#include "animation.h"
+
+#define LOGE(x...) do { KLOG_ERROR("charger", x); } while (0)
+#define LOGW(x...) do { KLOG_WARNING("charger", x); } while (0)
+#define LOGV(x...) do { KLOG_DEBUG("charger", x); } while (0)
+
+namespace android {
+
+// Lines consisting of only whitespace or whitespace followed by '#' can be ignored.
+bool can_ignore_line(const char* str) {
+ for (int i = 0; str[i] != '\0' && str[i] != '#'; i++) {
+ if (!isspace(str[i])) return false;
+ }
+ return true;
+}
+
+bool remove_prefix(const std::string& line, const char* prefix, const char** rest) {
+ const char* str = line.c_str();
+ int start;
+ char c;
+
+ std::string format = base::StringPrintf(" %s%%n%%c", prefix);
+ if (sscanf(str, format.c_str(), &start, &c) != 1) {
+ return false;
+ }
+
+ *rest = &str[start];
+ return true;
+}
+
+bool parse_text_field(const char* in, animation::text_field* field) {
+ int* x = &field->pos_x;
+ int* y = &field->pos_y;
+ int* r = &field->color_r;
+ int* g = &field->color_g;
+ int* b = &field->color_b;
+ int* a = &field->color_a;
+
+ int start = 0, end = 0;
+
+ if (sscanf(in, "c c %d %d %d %d %n%*s%n", r, g, b, a, &start, &end) == 4) {
+ *x = CENTER_VAL;
+ *y = CENTER_VAL;
+ } else if (sscanf(in, "c %d %d %d %d %d %n%*s%n", y, r, g, b, a, &start, &end) == 5) {
+ *x = CENTER_VAL;
+ } else if (sscanf(in, "%d c %d %d %d %d %n%*s%n", x, r, g, b, a, &start, &end) == 5) {
+ *y = CENTER_VAL;
+ } else if (sscanf(in, "%d %d %d %d %d %d %n%*s%n", x, y, r, g, b, a, &start, &end) != 6) {
+ return false;
+ }
+
+ if (end == 0) return false;
+
+ field->font_file.assign(&in[start], end - start);
+
+ return true;
+}
+
+bool parse_animation_desc(const std::string& content, animation* anim) {
+ static constexpr const char* animation_prefix = "animation: ";
+ static constexpr const char* fail_prefix = "fail: ";
+ static constexpr const char* clock_prefix = "clock_display: ";
+ static constexpr const char* percent_prefix = "percent_display: ";
+ static constexpr const char* frame_prefix = "frame: ";
+
+ std::vector<animation::frame> frames;
+
+ for (const auto& line : base::Split(content, "\n")) {
+ animation::frame frame;
+ const char* rest;
+
+ if (can_ignore_line(line.c_str())) {
+ continue;
+ } else if (remove_prefix(line, animation_prefix, &rest)) {
+ int start = 0, end = 0;
+ if (sscanf(rest, "%d %d %n%*s%n", &anim->num_cycles, &anim->first_frame_repeats,
+ &start, &end) != 2 ||
+ end == 0) {
+ LOGE("Bad animation format: %s\n", line.c_str());
+ return false;
+ } else {
+ anim->animation_file.assign(&rest[start], end - start);
+ }
+ } else if (remove_prefix(line, fail_prefix, &rest)) {
+ anim->fail_file.assign(rest);
+ } else if (remove_prefix(line, clock_prefix, &rest)) {
+ if (!parse_text_field(rest, &anim->text_clock)) {
+ LOGE("Bad clock_display format: %s\n", line.c_str());
+ return false;
+ }
+ } else if (remove_prefix(line, percent_prefix, &rest)) {
+ if (!parse_text_field(rest, &anim->text_percent)) {
+ LOGE("Bad percent_display format: %s\n", line.c_str());
+ return false;
+ }
+ } else if (sscanf(line.c_str(), " frame: %d %d %d",
+ &frame.disp_time, &frame.min_level, &frame.max_level) == 3) {
+ frames.push_back(std::move(frame));
+ } else {
+ LOGE("Malformed animation description line: %s\n", line.c_str());
+ return false;
+ }
+ }
+
+ if (anim->animation_file.empty() || frames.empty()) {
+ LOGE("Bad animation description. Provide the 'animation: ' line and at least one 'frame: ' "
+ "line.\n");
+ return false;
+ }
+
+ anim->num_frames = frames.size();
+ anim->frames = new animation::frame[frames.size()];
+ std::copy(frames.begin(), frames.end(), anim->frames);
+
+ return true;
+}
+
+} // namespace android
diff --git a/healthd/AnimationParser.h b/healthd/AnimationParser.h
new file mode 100644
index 0000000..bc00845
--- /dev/null
+++ b/healthd/AnimationParser.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef HEALTHD_ANIMATION_PARSER_H
+#define HEALTHD_ANIMATION_PARSER_H
+
+#include "animation.h"
+
+namespace android {
+
+bool parse_animation_desc(const std::string& content, animation* anim);
+
+bool can_ignore_line(const char* str);
+bool remove_prefix(const std::string& str, const char* prefix, const char** rest);
+bool parse_text_field(const char* in, animation::text_field* field);
+} // namespace android
+
+#endif // HEALTHD_ANIMATION_PARSER_H
diff --git a/healthd/animation.h b/healthd/animation.h
new file mode 100644
index 0000000..562b689
--- /dev/null
+++ b/healthd/animation.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#ifndef HEALTHD_ANIMATION_H
+#define HEALTHD_ANIMATION_H
+
+#include <inttypes.h>
+#include <string>
+
+struct GRSurface;
+struct GRFont;
+
+namespace android {
+
+#define CENTER_VAL INT_MAX
+
+struct animation {
+ struct frame {
+ int disp_time;
+ int min_level;
+ int max_level;
+
+ GRSurface* surface;
+ };
+
+ struct text_field {
+ std::string font_file;
+ int pos_x;
+ int pos_y;
+ int color_r;
+ int color_g;
+ int color_b;
+ int color_a;
+
+ GRFont* font;
+ };
+
+ std::string animation_file;
+ std::string fail_file;
+
+ text_field text_clock;
+ text_field text_percent;
+
+ bool run;
+
+ frame* frames;
+ int cur_frame;
+ int num_frames;
+ int first_frame_repeats; // Number of times to repeat the first frame in the current cycle
+
+ int cur_cycle;
+ int num_cycles; // Number of cycles to complete before blanking the screen
+
+ int cur_level; // current battery level being animated (0-100)
+ int cur_status; // current battery status - see BatteryService.h for BATTERY_STATUS_*
+};
+
+}
+
+#endif // HEALTHD_ANIMATION_H
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index 857bcb2..36c4664 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -30,6 +30,9 @@
#include <time.h>
#include <unistd.h>
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+
#include <sys/socket.h>
#include <linux/netlink.h>
@@ -44,10 +47,14 @@
#include <suspend/autosuspend.h>
#endif
+#include "animation.h"
+#include "AnimationParser.h"
#include "minui/minui.h"
#include <healthd/healthd.h>
+using namespace android;
+
char *locale;
#ifndef max
@@ -67,8 +74,6 @@
#define POWER_ON_KEY_TIME (2 * MSEC_PER_SEC)
#define UNPLUGGED_SHUTDOWN_TIME (10 * MSEC_PER_SEC)
-#define BATTERY_FULL_THRESH 95
-
#define LAST_KMSG_PATH "/proc/last_kmsg"
#define LAST_KMSG_PSTORE_PATH "/sys/fs/pstore/console-ramoops"
#define LAST_KMSG_MAX_SZ (32 * 1024)
@@ -77,34 +82,14 @@
#define LOGW(x...) do { KLOG_WARNING("charger", x); } while (0)
#define LOGV(x...) do { KLOG_DEBUG("charger", x); } while (0)
+static constexpr const char* animation_desc_path = "/res/values/charger/animation.txt";
+
struct key_state {
bool pending;
bool down;
int64_t timestamp;
};
-struct frame {
- int disp_time;
- int min_capacity;
- bool level_only;
-
- GRSurface* surface;
-};
-
-struct animation {
- bool run;
-
- struct frame *frames;
- int cur_frame;
- int num_frames;
-
- int cur_cycle;
- int num_cycles;
-
- /* current capacity being animated */
- int capacity;
-};
-
struct charger {
bool have_battery_state;
bool charger_connected;
@@ -119,54 +104,83 @@
int boot_min_cap;
};
-static struct frame batt_anim_frames[] = {
+static const struct animation BASE_ANIMATION = {
+ .text_clock = {
+ .pos_x = 0,
+ .pos_y = 0,
+
+ .color_r = 255,
+ .color_g = 255,
+ .color_b = 255,
+ .color_a = 255,
+
+ .font = nullptr,
+ },
+ .text_percent = {
+ .pos_x = 0,
+ .pos_y = 0,
+
+ .color_r = 255,
+ .color_g = 255,
+ .color_b = 255,
+ .color_a = 255,
+ },
+
+ .run = false,
+
+ .frames = nullptr,
+ .cur_frame = 0,
+ .num_frames = 0,
+ .first_frame_repeats = 2,
+
+ .cur_cycle = 0,
+ .num_cycles = 3,
+
+ .cur_level = 0,
+ .cur_status = BATTERY_STATUS_UNKNOWN,
+};
+
+
+static struct animation::frame default_animation_frames[] = {
{
.disp_time = 750,
- .min_capacity = 0,
- .level_only = false,
+ .min_level = 0,
+ .max_level = 19,
.surface = NULL,
},
{
.disp_time = 750,
- .min_capacity = 20,
- .level_only = false,
+ .min_level = 0,
+ .max_level = 39,
.surface = NULL,
},
{
.disp_time = 750,
- .min_capacity = 40,
- .level_only = false,
+ .min_level = 0,
+ .max_level = 59,
.surface = NULL,
},
{
.disp_time = 750,
- .min_capacity = 60,
- .level_only = false,
+ .min_level = 0,
+ .max_level = 79,
.surface = NULL,
},
{
.disp_time = 750,
- .min_capacity = 80,
- .level_only = true,
+ .min_level = 80,
+ .max_level = 95,
.surface = NULL,
},
{
.disp_time = 750,
- .min_capacity = BATTERY_FULL_THRESH,
- .level_only = false,
+ .min_level = 0,
+ .max_level = 100,
.surface = NULL,
},
};
-static struct animation battery_animation = {
- .run = false,
- .frames = batt_anim_frames,
- .cur_frame = 0,
- .num_frames = ARRAY_SIZE(batt_anim_frames),
- .cur_cycle = 0,
- .num_cycles = 3,
- .capacity = 0,
-};
+static struct animation battery_animation = BASE_ANIMATION;
static struct charger charger_state;
static struct healthd_config *healthd_config;
@@ -273,8 +287,79 @@
gr_color(0xa4, 0xc6, 0x39, 255);
}
+// Negative x or y coordinates position the text away from the opposite edge that positive ones do.
+void determine_xy(const animation::text_field& field, const int length, int* x, int* y)
+{
+ *x = field.pos_x;
+ *y = field.pos_y;
+
+ int str_len_px = length * field.font->char_width;
+ if (field.pos_x == CENTER_VAL) {
+ *x = (gr_fb_width() - str_len_px) / 2;
+ } else if (field.pos_x >= 0) {
+ *x = field.pos_x;
+ } else { // position from max edge
+ *x = gr_fb_width() + field.pos_x - str_len_px;
+ }
+
+ if (field.pos_y == CENTER_VAL) {
+ *y = (gr_fb_height() - field.font->char_height) / 2;
+ } else if (field.pos_y >= 0) {
+ *y = field.pos_y;
+ } else { // position from max edge
+ *y = gr_fb_height() + field.pos_y - field.font->char_height;
+ }
+}
+
+static void draw_clock(const animation& anim)
+{
+ static constexpr char CLOCK_FORMAT[] = "%H:%M";
+ static constexpr int CLOCK_LENGTH = 6;
+
+ const animation::text_field& field = anim.text_clock;
+
+ if (field.font == nullptr || field.font->char_width == 0 || field.font->char_height == 0) return;
+
+ time_t rawtime;
+ time(&rawtime);
+ struct tm* time_info = localtime(&rawtime);
+
+ char clock_str[CLOCK_LENGTH];
+ size_t length = strftime(clock_str, CLOCK_LENGTH, CLOCK_FORMAT, time_info);
+ if (length != CLOCK_LENGTH - 1) {
+ LOGE("Could not format time\n");
+ return;
+ }
+
+ int x, y;
+ determine_xy(field, length, &x, &y);
+
+ LOGV("drawing clock %s %d %d\n", clock_str, x, y);
+ gr_color(field.color_r, field.color_g, field.color_b, field.color_a);
+ gr_text(field.font, x, y, clock_str, false);
+}
+
+static void draw_percent(const animation& anim)
+{
+ if (anim.cur_level <= 0 || anim.cur_status != BATTERY_STATUS_CHARGING) return;
+
+ const animation::text_field& field = anim.text_percent;
+ if (field.font == nullptr || field.font->char_width == 0 || field.font->char_height == 0) {
+ return;
+ }
+
+ std::string str = base::StringPrintf("%d%%", anim.cur_level);
+
+ int x, y;
+ determine_xy(field, str.size(), &x, &y);
+
+ LOGV("drawing percent %s %d %d\n", str.c_str(), x, y);
+ gr_color(field.color_r, field.color_g, field.color_b, field.color_a);
+ gr_text(field.font, x, y, str.c_str(), false);
+}
+
/* returns the last y-offset of where the surface ends */
-static int draw_surface_centered(struct charger* /*charger*/, GRSurface* surface)
+static int draw_surface_centered(GRSurface* surface)
{
int w;
int h;
@@ -295,7 +380,7 @@
{
int y;
if (charger->surf_unknown) {
- draw_surface_centered(charger, charger->surf_unknown);
+ draw_surface_centered(charger->surf_unknown);
} else {
android_green();
y = draw_text("Charging!", -1, -1);
@@ -303,17 +388,19 @@
}
}
-static void draw_battery(struct charger *charger)
+static void draw_battery(const struct charger* charger)
{
- struct animation *batt_anim = charger->batt_anim;
- struct frame *frame = &batt_anim->frames[batt_anim->cur_frame];
+ const struct animation& anim = *charger->batt_anim;
+ const struct animation::frame& frame = anim.frames[anim.cur_frame];
- if (batt_anim->num_frames != 0) {
- draw_surface_centered(charger, frame->surface);
+ if (anim.num_frames != 0) {
+ draw_surface_centered(frame.surface);
LOGV("drawing frame #%d min_cap=%d time=%d\n",
- batt_anim->cur_frame, frame->min_capacity,
- frame->disp_time);
+ anim.cur_frame, frame.min_level,
+ frame.disp_time);
}
+ draw_clock(anim);
+ draw_percent(anim);
}
static void redraw_screen(struct charger *charger)
@@ -323,7 +410,7 @@
clear_screen();
/* try to display *something* */
- if (batt_anim->capacity < 0 || batt_anim->num_frames == 0)
+ if (batt_anim->cur_level < 0 || batt_anim->num_frames == 0)
draw_unknown(charger);
else
draw_battery(charger);
@@ -342,16 +429,33 @@
anim->run = false;
}
+static void init_status_display(struct animation* anim)
+{
+ int res;
+
+ if (!anim->text_clock.font_file.empty()) {
+ if ((res =
+ gr_init_font(anim->text_clock.font_file.c_str(), &anim->text_clock.font)) < 0) {
+ LOGE("Could not load time font (%d)\n", res);
+ }
+ }
+
+ if (!anim->text_percent.font_file.empty()) {
+ if ((res =
+ gr_init_font(anim->text_percent.font_file.c_str(), &anim->text_percent.font)) < 0) {
+ LOGE("Could not load percent font (%d)\n", res);
+ }
+ }
+}
+
static void update_screen_state(struct charger *charger, int64_t now)
{
struct animation *batt_anim = charger->batt_anim;
int disp_time;
- if (!batt_anim->run || now < charger->next_screen_transition)
- return;
+ if (!batt_anim->run || now < charger->next_screen_transition) return;
if (!minui_inited) {
-
if (healthd_config && healthd_config->screen_on) {
if (!healthd_config->screen_on(batt_prop)) {
LOGV("[%" PRId64 "] leave screen off\n", now);
@@ -365,6 +469,7 @@
gr_init();
gr_font_size(gr_sys_font(), &char_width, &char_height);
+ init_status_display(batt_anim);
#ifndef CHARGER_DISABLE_INIT_BLANK
gr_fb_blank(true);
@@ -373,7 +478,7 @@
}
/* animation is over, blank screen and leave */
- if (batt_anim->cur_cycle == batt_anim->num_cycles) {
+ if (batt_anim->num_cycles > 0 && batt_anim->cur_cycle == batt_anim->num_cycles) {
reset_animation(batt_anim);
charger->next_screen_transition = -1;
gr_fb_blank(true);
@@ -389,21 +494,24 @@
if (batt_anim->cur_frame == 0) {
LOGV("[%" PRId64 "] animation starting\n", now);
- if (batt_prop && batt_prop->batteryLevel >= 0 && batt_anim->num_frames != 0) {
- int i;
+ if (batt_prop) {
+ batt_anim->cur_level = batt_prop->batteryLevel;
+ batt_anim->cur_status = batt_prop->batteryStatus;
+ if (batt_prop->batteryLevel >= 0 && batt_anim->num_frames != 0) {
+ /* find first frame given current battery level */
+ for (int i = 0; i < batt_anim->num_frames; i++) {
+ if (batt_anim->cur_level >= batt_anim->frames[i].min_level &&
+ batt_anim->cur_level <= batt_anim->frames[i].max_level) {
+ batt_anim->cur_frame = i;
+ break;
+ }
+ }
- /* find first frame given current capacity */
- for (i = 1; i < batt_anim->num_frames; i++) {
- if (batt_prop->batteryLevel < batt_anim->frames[i].min_capacity)
- break;
+ // repeat the first frame first_frame_repeats times
+ disp_time = batt_anim->frames[batt_anim->cur_frame].disp_time *
+ batt_anim->first_frame_repeats;
}
- batt_anim->cur_frame = i - 1;
-
- /* show the first frame for twice as long */
- disp_time = batt_anim->frames[batt_anim->cur_frame].disp_time * 2;
}
- if (batt_prop)
- batt_anim->capacity = batt_prop->batteryLevel;
}
/* unblank the screen on first cycle */
@@ -416,8 +524,8 @@
/* if we don't have anim frames, we only have one image, so just bump
* the cycle counter and exit
*/
- if (batt_anim->num_frames == 0 || batt_anim->capacity < 0) {
- LOGV("[%" PRId64 "] animation missing or unknown battery status\n", now);
+ if (batt_anim->num_frames == 0 || batt_anim->cur_level < 0) {
+ LOGW("[%" PRId64 "] animation missing or unknown battery status\n", now);
charger->next_screen_transition = now + BATTERY_UNKNOWN_TIME;
batt_anim->cur_cycle++;
return;
@@ -432,12 +540,11 @@
if (charger->charger_connected) {
batt_anim->cur_frame++;
- /* if the frame is used for level-only, that is only show it when it's
- * the current level, skip it during the animation.
- */
while (batt_anim->cur_frame < batt_anim->num_frames &&
- batt_anim->frames[batt_anim->cur_frame].level_only)
+ (batt_anim->cur_level < batt_anim->frames[batt_anim->cur_frame].min_level ||
+ batt_anim->cur_level > batt_anim->frames[batt_anim->cur_frame].max_level)) {
batt_anim->cur_frame++;
+ }
if (batt_anim->cur_frame >= batt_anim->num_frames) {
batt_anim->cur_cycle++;
batt_anim->cur_frame = 0;
@@ -521,7 +628,7 @@
LOGW("[%" PRId64 "] booting from charger mode\n", now);
property_set("sys.boot_from_charger_mode", "1");
} else {
- if (charger->batt_anim->capacity >= charger->boot_min_cap) {
+ if (charger->batt_anim->cur_level >= charger->boot_min_cap) {
LOGW("[%" PRId64 "] rebooting\n", now);
android_reboot(ANDROID_RB_RESTART, 0, 0);
} else {
@@ -672,6 +779,52 @@
ev_dispatch();
}
+animation* init_animation()
+{
+ bool parse_success;
+
+ std::string content;
+ if (base::ReadFileToString(animation_desc_path, &content)) {
+ parse_success = parse_animation_desc(content, &battery_animation);
+ } else {
+ LOGW("Could not open animation description at %s\n", animation_desc_path);
+ parse_success = false;
+ }
+
+ if (!parse_success) {
+ LOGW("Could not parse animation description. Using default animation.\n");
+ battery_animation = BASE_ANIMATION;
+ battery_animation.animation_file.assign("charger/battery_scale");
+ battery_animation.frames = default_animation_frames;
+ battery_animation.num_frames = ARRAY_SIZE(default_animation_frames);
+ }
+ if (battery_animation.fail_file.empty()) {
+ battery_animation.fail_file.assign("charger/battery_fail");
+ }
+
+ LOGV("Animation Description:\n");
+ LOGV(" animation: %d %d '%s' (%d)\n",
+ battery_animation.num_cycles, battery_animation.first_frame_repeats,
+ battery_animation.animation_file.c_str(), battery_animation.num_frames);
+ LOGV(" fail_file: '%s'\n", battery_animation.fail_file.c_str());
+ LOGV(" clock: %d %d %d %d %d %d '%s'\n",
+ battery_animation.text_clock.pos_x, battery_animation.text_clock.pos_y,
+ battery_animation.text_clock.color_r, battery_animation.text_clock.color_g,
+ battery_animation.text_clock.color_b, battery_animation.text_clock.color_a,
+ battery_animation.text_clock.font_file.c_str());
+ LOGV(" percent: %d %d %d %d %d %d '%s'\n",
+ battery_animation.text_percent.pos_x, battery_animation.text_percent.pos_y,
+ battery_animation.text_percent.color_r, battery_animation.text_percent.color_g,
+ battery_animation.text_percent.color_b, battery_animation.text_percent.color_a,
+ battery_animation.text_percent.font_file.c_str());
+ for (int i = 0; i < battery_animation.num_frames; i++) {
+ LOGV(" frame %.2d: %d %d %d\n", i, battery_animation.frames[i].disp_time,
+ battery_animation.frames[i].min_level, battery_animation.frames[i].max_level);
+ }
+
+ return &battery_animation;
+}
+
void healthd_mode_charger_init(struct healthd_config* config)
{
int ret;
@@ -689,35 +842,39 @@
healthd_register_event(epollfd, charger_event_handler);
}
- ret = res_create_display_surface("charger/battery_fail", &charger->surf_unknown);
- if (ret < 0) {
- LOGE("Cannot load battery_fail image\n");
- charger->surf_unknown = NULL;
- }
+ struct animation* anim = init_animation();
+ charger->batt_anim = anim;
- charger->batt_anim = &battery_animation;
+ ret = res_create_display_surface(anim->fail_file.c_str(), &charger->surf_unknown);
+ if (ret < 0) {
+ LOGE("Cannot load custom battery_fail image. Reverting to built in.\n");
+ ret = res_create_display_surface("charger/battery_fail", &charger->surf_unknown);
+ if (ret < 0) {
+ LOGE("Cannot load built in battery_fail image\n");
+ charger->surf_unknown = NULL;
+ }
+ }
GRSurface** scale_frames;
int scale_count;
int scale_fps; // Not in use (charger/battery_scale doesn't have FPS text
// chunk). We are using hard-coded frame.disp_time instead.
- ret = res_create_multi_display_surface("charger/battery_scale", &scale_count, &scale_fps,
- &scale_frames);
+ ret = res_create_multi_display_surface(anim->animation_file.c_str(),
+ &scale_count, &scale_fps, &scale_frames);
if (ret < 0) {
LOGE("Cannot load battery_scale image\n");
- charger->batt_anim->num_frames = 0;
- charger->batt_anim->num_cycles = 1;
- } else if (scale_count != charger->batt_anim->num_frames) {
+ anim->num_frames = 0;
+ anim->num_cycles = 1;
+ } else if (scale_count != anim->num_frames) {
LOGE("battery_scale image has unexpected frame count (%d, expected %d)\n",
- scale_count, charger->batt_anim->num_frames);
- charger->batt_anim->num_frames = 0;
- charger->batt_anim->num_cycles = 1;
+ scale_count, anim->num_frames);
+ anim->num_frames = 0;
+ anim->num_cycles = 1;
} else {
- for (i = 0; i < charger->batt_anim->num_frames; i++) {
- charger->batt_anim->frames[i].surface = scale_frames[i];
+ for (i = 0; i < anim->num_frames; i++) {
+ anim->frames[i].surface = scale_frames[i];
}
}
-
ev_sync_key_state(set_key_callback, charger);
charger->next_screen_transition = -1;
diff --git a/healthd/tests/Android.mk b/healthd/tests/Android.mk
new file mode 100644
index 0000000..87e8862
--- /dev/null
+++ b/healthd/tests/Android.mk
@@ -0,0 +1,21 @@
+# Copyright 2016 The Android Open Source Project
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ AnimationParser_test.cpp \
+
+LOCAL_MODULE := healthd_test
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_STATIC_LIBRARIES := \
+ libhealthd_internal \
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libbase \
+ libcutils \
+
+include $(BUILD_NATIVE_TEST)
diff --git a/healthd/tests/AnimationParser_test.cpp b/healthd/tests/AnimationParser_test.cpp
new file mode 100644
index 0000000..2fc3185
--- /dev/null
+++ b/healthd/tests/AnimationParser_test.cpp
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 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 "AnimationParser.h"
+
+#include <gtest/gtest.h>
+
+using namespace android;
+
+TEST(AnimationParserTest, Test_can_ignore_line) {
+ EXPECT_TRUE(can_ignore_line(""));
+ EXPECT_TRUE(can_ignore_line(" "));
+ EXPECT_TRUE(can_ignore_line("#"));
+ EXPECT_TRUE(can_ignore_line(" # comment"));
+
+ EXPECT_FALSE(can_ignore_line("text"));
+ EXPECT_FALSE(can_ignore_line("text # comment"));
+ EXPECT_FALSE(can_ignore_line(" text"));
+ EXPECT_FALSE(can_ignore_line(" text # comment"));
+}
+
+TEST(AnimationParserTest, Test_remove_prefix) {
+ static const char TEST_STRING[] = "abcdef";
+ const char* rest = nullptr;
+ EXPECT_FALSE(remove_prefix(TEST_STRING, "def", &rest));
+ // Ignore strings that only consist of the prefix
+ EXPECT_FALSE(remove_prefix(TEST_STRING, TEST_STRING, &rest));
+
+ EXPECT_TRUE(remove_prefix(TEST_STRING, "abc", &rest));
+ EXPECT_STREQ("def", rest);
+
+ EXPECT_TRUE(remove_prefix(" abcdef", "abc", &rest));
+ EXPECT_STREQ("def", rest);
+}
+
+TEST(AnimationParserTest, Test_parse_text_field) {
+ static const char TEST_FILE_NAME[] = "font_file";
+ static const int TEST_X = 3;
+ static const int TEST_Y = 6;
+ static const int TEST_R = 1;
+ static const int TEST_G = 2;
+ static const int TEST_B = 4;
+ static const int TEST_A = 8;
+
+ static const char TEST_XCENT_YCENT[] = "c c 1 2 4 8 font_file ";
+ static const char TEST_XCENT_YVAL[] = "c 6 1 2 4 8 font_file ";
+ static const char TEST_XVAL_YCENT[] = "3 c 1 2 4 8 font_file ";
+ static const char TEST_XVAL_YVAL[] = "3 6 1 2 4 8 font_file ";
+ static const char TEST_BAD_MISSING[] = "c c 1 2 4 font_file";
+ static const char TEST_BAD_NO_FILE[] = "c c 1 2 4 8";
+
+ animation::text_field out;
+
+ EXPECT_TRUE(parse_text_field(TEST_XCENT_YCENT, &out));
+ EXPECT_EQ(CENTER_VAL, out.pos_x);
+ EXPECT_EQ(CENTER_VAL, out.pos_y);
+ EXPECT_EQ(TEST_R, out.color_r);
+ EXPECT_EQ(TEST_G, out.color_g);
+ EXPECT_EQ(TEST_B, out.color_b);
+ EXPECT_EQ(TEST_A, out.color_a);
+ EXPECT_STREQ(TEST_FILE_NAME, out.font_file.c_str());
+
+ EXPECT_TRUE(parse_text_field(TEST_XCENT_YVAL, &out));
+ EXPECT_EQ(CENTER_VAL, out.pos_x);
+ EXPECT_EQ(TEST_Y, out.pos_y);
+ EXPECT_EQ(TEST_R, out.color_r);
+ EXPECT_EQ(TEST_G, out.color_g);
+ EXPECT_EQ(TEST_B, out.color_b);
+ EXPECT_EQ(TEST_A, out.color_a);
+ EXPECT_STREQ(TEST_FILE_NAME, out.font_file.c_str());
+
+ EXPECT_TRUE(parse_text_field(TEST_XVAL_YCENT, &out));
+ EXPECT_EQ(TEST_X, out.pos_x);
+ EXPECT_EQ(CENTER_VAL, out.pos_y);
+ EXPECT_EQ(TEST_R, out.color_r);
+ EXPECT_EQ(TEST_G, out.color_g);
+ EXPECT_EQ(TEST_B, out.color_b);
+ EXPECT_EQ(TEST_A, out.color_a);
+ EXPECT_STREQ(TEST_FILE_NAME, out.font_file.c_str());
+
+ EXPECT_TRUE(parse_text_field(TEST_XVAL_YVAL, &out));
+ EXPECT_EQ(TEST_X, out.pos_x);
+ EXPECT_EQ(TEST_Y, out.pos_y);
+ EXPECT_EQ(TEST_R, out.color_r);
+ EXPECT_EQ(TEST_G, out.color_g);
+ EXPECT_EQ(TEST_B, out.color_b);
+ EXPECT_EQ(TEST_A, out.color_a);
+ EXPECT_STREQ(TEST_FILE_NAME, out.font_file.c_str());
+
+ EXPECT_FALSE(parse_text_field(TEST_BAD_MISSING, &out));
+ EXPECT_FALSE(parse_text_field(TEST_BAD_NO_FILE, &out));
+}
+
+TEST(AnimationParserTest, Test_parse_animation_desc_basic) {
+ static const char TEST_ANIMATION[] = R"desc(
+ # Basic animation
+ animation: 5 1 test/animation_file
+ frame: 1000 0 100
+ )desc";
+ animation anim;
+
+ EXPECT_TRUE(parse_animation_desc(TEST_ANIMATION, &anim));
+}
+
+TEST(AnimationParserTest, Test_parse_animation_desc_bad_no_animation_line) {
+ static const char TEST_ANIMATION[] = R"desc(
+ # Bad animation
+ frame: 1000 90 10
+ )desc";
+ animation anim;
+
+ EXPECT_FALSE(parse_animation_desc(TEST_ANIMATION, &anim));
+}
+
+TEST(AnimationParserTest, Test_parse_animation_desc_bad_no_frame) {
+ static const char TEST_ANIMATION[] = R"desc(
+ # Bad animation
+ animation: 5 1 test/animation_file
+ )desc";
+ animation anim;
+
+ EXPECT_FALSE(parse_animation_desc(TEST_ANIMATION, &anim));
+}
+
+TEST(AnimationParserTest, Test_parse_animation_desc_bad_animation_line_format) {
+ static const char TEST_ANIMATION[] = R"desc(
+ # Bad animation
+ animation: 5 1
+ frame: 1000 90 10
+ )desc";
+ animation anim;
+
+ EXPECT_FALSE(parse_animation_desc(TEST_ANIMATION, &anim));
+}
+
+TEST(AnimationParserTest, Test_parse_animation_desc_full) {
+ static const char TEST_ANIMATION[] = R"desc(
+ # Full animation
+ animation: 5 1 test/animation_file
+ clock_display: 11 12 13 14 15 16 test/time_font
+ percent_display: 21 22 23 24 25 26 test/percent_font
+
+ frame: 10 20 30
+ frame: 40 50 60
+ )desc";
+ animation anim;
+
+ EXPECT_TRUE(parse_animation_desc(TEST_ANIMATION, &anim));
+
+ EXPECT_EQ(5, anim.num_cycles);
+ EXPECT_EQ(1, anim.first_frame_repeats);
+ EXPECT_STREQ("test/animation_file", anim.animation_file.c_str());
+
+ EXPECT_EQ(11, anim.text_clock.pos_x);
+ EXPECT_EQ(12, anim.text_clock.pos_y);
+ EXPECT_EQ(13, anim.text_clock.color_r);
+ EXPECT_EQ(14, anim.text_clock.color_g);
+ EXPECT_EQ(15, anim.text_clock.color_b);
+ EXPECT_EQ(16, anim.text_clock.color_a);
+ EXPECT_STREQ("test/time_font", anim.text_clock.font_file.c_str());
+
+ EXPECT_EQ(21, anim.text_percent.pos_x);
+ EXPECT_EQ(22, anim.text_percent.pos_y);
+ EXPECT_EQ(23, anim.text_percent.color_r);
+ EXPECT_EQ(24, anim.text_percent.color_g);
+ EXPECT_EQ(25, anim.text_percent.color_b);
+ EXPECT_EQ(26, anim.text_percent.color_a);
+ EXPECT_STREQ("test/percent_font", anim.text_percent.font_file.c_str());
+
+ EXPECT_EQ(2, anim.num_frames);
+
+ EXPECT_EQ(10, anim.frames[0].disp_time);
+ EXPECT_EQ(20, anim.frames[0].min_level);
+ EXPECT_EQ(30, anim.frames[0].max_level);
+
+ EXPECT_EQ(40, anim.frames[1].disp_time);
+ EXPECT_EQ(50, anim.frames[1].min_level);
+ EXPECT_EQ(60, anim.frames[1].max_level);
+}
diff --git a/include/cutils/trace.h b/include/cutils/trace.h
index dc3833f..fcbdc9b 100644
--- a/include/cutils/trace.h
+++ b/include/cutils/trace.h
@@ -70,7 +70,9 @@
#define ATRACE_TAG_PACKAGE_MANAGER (1<<18)
#define ATRACE_TAG_SYSTEM_SERVER (1<<19)
#define ATRACE_TAG_DATABASE (1<<20)
-#define ATRACE_TAG_LAST ATRACE_TAG_DATABASE
+#define ATRACE_TAG_NETWORK (1<<21)
+#define ATRACE_TAG_ADB (1<<22)
+#define ATRACE_TAG_LAST ATRACE_TAG_ADB
// Reserved for initialization.
#define ATRACE_TAG_NOT_READY (1ULL<<63)
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index c9e1923..3031562 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -19,6 +19,33 @@
** by the device side of adb.
*/
+/*
+ * This file is consumed by build/tools/fs_config and is used
+ * for generating various files. Anything #define AID_<name>
+ * becomes the mapping for getpwnam/getpwuid, etc. The <name>
+ * field is lowercased.
+ * For example:
+ * #define AID_FOO_BAR 6666 becomes a friendly name of "foo_bar"
+ *
+ * The above holds true with the exception of:
+ * mediacodec
+ * mediaex
+ * mediadrm
+ * Whose friendly names do not match the #define statements.
+ *
+ * Additionally, AID_OEM_RESERVED_START and AID_OEM_RESERVED_END
+ * can be used to define reserved OEM ranges used for sanity checks
+ * during the build process. The rules are, they must end with START/END
+ * The proper convention is incrementing a number like so:
+ * AID_OEM_RESERVED_START
+ * AID_OEM_RESERVED_1_START
+ * AID_OEM_RESERVED_2_START
+ * ...
+ * The same applies to the END.
+ * They are not required to be in order, but must not overlap each other and
+ * must define a START and END'ing range. START must be smaller than END.
+ */
+
#ifndef _ANDROID_FILESYSTEM_CONFIG_H_
#define _ANDROID_FILESYSTEM_CONFIG_H_
diff --git a/include/system/window.h b/include/system/window.h
index 49ab4dc..f439705 100644
--- a/include/system/window.h
+++ b/include/system/window.h
@@ -287,6 +287,16 @@
* age will be 0.
*/
NATIVE_WINDOW_BUFFER_AGE = 13,
+
+ /*
+ * Returns the duration of the last dequeueBuffer call in microseconds
+ */
+ NATIVE_WINDOW_LAST_DEQUEUE_DURATION = 14,
+
+ /*
+ * Returns the duration of the last queueBuffer call in microseconds
+ */
+ NATIVE_WINDOW_LAST_QUEUE_DURATION = 15,
};
/* Valid operations for the (*perform)() hook.
@@ -323,6 +333,7 @@
NATIVE_WINDOW_SET_SURFACE_DAMAGE = 20, /* private */
NATIVE_WINDOW_SET_SHARED_BUFFER_MODE = 21,
NATIVE_WINDOW_SET_AUTO_REFRESH = 22,
+ NATIVE_WINDOW_GET_FRAME_TIMESTAMPS = 23,
};
/* parameter for NATIVE_WINDOW_[API_][DIS]CONNECT */
@@ -985,6 +996,18 @@
return window->perform(window, NATIVE_WINDOW_SET_AUTO_REFRESH, autoRefresh);
}
+static inline int native_window_get_frame_timestamps(
+ struct ANativeWindow* window, uint32_t framesAgo,
+ int64_t* outPostedTime, int64_t* outAcquireTime,
+ int64_t* outRefreshStartTime, int64_t* outGlCompositionDoneTime,
+ int64_t* outDisplayRetireTime, int64_t* outReleaseTime)
+{
+ return window->perform(window, NATIVE_WINDOW_GET_FRAME_TIMESTAMPS,
+ framesAgo, outPostedTime, outAcquireTime, outRefreshStartTime,
+ outGlCompositionDoneTime, outDisplayRetireTime, outReleaseTime);
+}
+
+
__END_DECLS
#endif /* SYSTEM_CORE_INCLUDE_ANDROID_WINDOW_H */
diff --git a/include/sysutils/FrameworkListener.h b/include/sysutils/FrameworkListener.h
index 18049cd..2137069 100644
--- a/include/sysutils/FrameworkListener.h
+++ b/include/sysutils/FrameworkListener.h
@@ -32,6 +32,7 @@
int mCommandCount;
bool mWithSeq;
FrameworkCommandCollection *mCommands;
+ bool mSkipToNextNullByte;
public:
FrameworkListener(const char *socketName);
diff --git a/include/utils/FastStrcmp.h b/include/utils/FastStrcmp.h
new file mode 100644
index 0000000..3844e7d
--- /dev/null
+++ b/include/utils/FastStrcmp.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2014-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.
+ */
+
+#ifndef _ANDROID_UTILS_FASTSTRCMP_H__
+#define _ANDROID_UTILS_FASTSTRCMP_H__
+
+#ifdef __cplusplus
+
+// Optimized for instruction cache locality
+//
+// Template class fastcmp used to create more time-efficient str*cmp
+// functions by pre-checking the first character before resorting
+// to calling the underlying string function. Profiled with a
+// measurable speedup when used in hot code. Usage is of the form:
+//
+// fastcmp<strncmp>(str1, str2, len)
+//
+// NB: Does not work for the case insensitive str*cmp functions.
+// NB: Returns boolean, do not use if expecting to check negative value.
+// Thus not semantically identical to the expected function behavior.
+
+template <int (*cmp)(const char *l, const char *r, const size_t s)>
+static inline int fastcmp(const char *l, const char *r, const size_t s) {
+ return (*l != *r) || cmp(l + 1, r + 1, s - 1);
+}
+
+template <int (*cmp)(const void *l, const void *r, const size_t s)>
+static inline int fastcmp(const void *lv, const void *rv, const size_t s) {
+ const char *l = static_cast<const char *>(lv);
+ const char *r = static_cast<const char *>(rv);
+ return (*l != *r) || cmp(l + 1, r + 1, s - 1);
+}
+
+template <int (*cmp)(const char *l, const char *r)>
+static inline int fastcmp(const char *l, const char *r) {
+ return (*l != *r) || cmp(l + 1, r + 1);
+}
+
+#endif
+
+#endif // _ANDROID_UTILS_FASTSTRCMP_H__
diff --git a/include/utils/Mutex.h b/include/utils/Mutex.h
index 8c4683c..d106185 100644
--- a/include/utils/Mutex.h
+++ b/include/utils/Mutex.h
@@ -64,13 +64,18 @@
status_t tryLock();
#if defined(__ANDROID__)
- // lock the mutex, but don't wait longer than timeoutMilliseconds.
+ // Lock the mutex, but don't wait longer than timeoutNs (relative time).
// Returns 0 on success, TIMED_OUT for failure due to timeout expiration.
//
// OSX doesn't have pthread_mutex_timedlock() or equivalent. To keep
// capabilities consistent across host OSes, this method is only available
// when building Android binaries.
- status_t timedLock(nsecs_t timeoutMilliseconds);
+ //
+ // FIXME?: pthread_mutex_timedlock is based on CLOCK_REALTIME,
+ // which is subject to NTP adjustments, and includes time during suspend,
+ // so a timeout may occur even though no processes could run.
+ // Not holding a partial wakelock may lead to a system suspend.
+ status_t timedLock(nsecs_t timeoutNs);
#endif
// Manages the mutex automatically. It'll be locked when Autolock is
@@ -134,6 +139,7 @@
}
#if defined(__ANDROID__)
inline status_t Mutex::timedLock(nsecs_t timeoutNs) {
+ timeoutNs += systemTime(SYSTEM_TIME_REALTIME);
const struct timespec ts = {
/* .tv_sec = */ static_cast<time_t>(timeoutNs / 1000000000),
/* .tv_nsec = */ static_cast<long>(timeoutNs % 1000000000),
diff --git a/include/utils/Trace.h b/include/utils/Trace.h
index 6ba68f6..eeba40d 100644
--- a/include/utils/Trace.h
+++ b/include/utils/Trace.h
@@ -33,10 +33,10 @@
// See <cutils/trace.h> for more ATRACE_* macros.
-// ATRACE_NAME traces the beginning and end of the current scope. To trace
-// the correct start and end times this macro should be declared first in the
-// scope body.
-#define ATRACE_NAME(name) android::ScopedTrace ___tracer(ATRACE_TAG, name)
+// ATRACE_NAME traces from its location until the end of its enclosing scope.
+#define _PASTE(x, y) x ## y
+#define PASTE(x, y) _PASTE(x,y)
+#define ATRACE_NAME(name) android::ScopedTrace PASTE(___tracer, __LINE__) (ATRACE_TAG, name)
// ATRACE_CALL is an ATRACE_NAME that uses the current function name.
#define ATRACE_CALL() ATRACE_NAME(__FUNCTION__)
diff --git a/init/Android.mk b/init/Android.mk
index 442a5f3..ecdf5db 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -126,7 +126,6 @@
LOCAL_SHARED_LIBRARIES += \
libcutils \
libbase \
- libselinux \
LOCAL_STATIC_LIBRARIES := libinit
LOCAL_SANITIZE := integer
diff --git a/init/action.cpp b/init/action.cpp
index 0ea7e14..65bf292 100644
--- a/init/action.cpp
+++ b/init/action.cpp
@@ -121,7 +121,7 @@
Timer t;
int result = command.InvokeFunc();
- double duration_ms = t.duration() * 1000;
+ double duration_ms = t.duration_s() * 1000;
// Any action longer than 50ms will be warned to user as slow operation
if (duration_ms > 50.0 ||
android::base::GetMinimumLogSeverity() <= android::base::DEBUG) {
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 6d58754..42dd0c6 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -146,8 +146,7 @@
LOG(ERROR) << "failed to set bootloader message: " << err;
return -1;
}
- android_reboot(ANDROID_RB_RESTART2, 0, "recovery");
- while (1) { pause(); } // never reached
+ reboot("recovery");
}
static void unmount_and_fsck(const struct mntent *entry) {
@@ -346,6 +345,11 @@
return 0;
}
+/* umount <path> */
+static int do_umount(const std::vector<std::string>& args) {
+ return umount(args[1].c_str());
+}
+
static struct {
const char *name;
unsigned flag;
@@ -727,7 +731,7 @@
ServiceManager::GetInstance().ForEachService(
[] (Service* s) { s->Terminate(); });
- while (t.duration() < delay) {
+ while (t.duration_s() < delay) {
ServiceManager::GetInstance().ReapAnyOutstandingChildren();
int service_count = 0;
@@ -751,11 +755,10 @@
// Wait a bit before recounting the number or running services.
std::this_thread::sleep_for(50ms);
}
- LOG(VERBOSE) << "Terminating running services took " << t.duration() << " seconds";
+ LOG(VERBOSE) << "Terminating running services took " << t;
}
- return android_reboot_with_callback(cmd, 0, reboot_target,
- callback_on_ro_remount);
+ return android_reboot_with_callback(cmd, 0, reboot_target, callback_on_ro_remount);
}
static int do_trigger(const std::vector<std::string>& args) {
@@ -1047,6 +1050,7 @@
{"mkdir", {1, 4, do_mkdir}},
{"mount_all", {1, kMax, do_mount_all}},
{"mount", {3, kMax, do_mount}},
+ {"umount", {1, 1, do_umount}},
{"powerctl", {1, 1, do_powerctl}},
{"restart", {1, 1, do_restart}},
{"restorecon", {1, kMax, do_restorecon}},
diff --git a/init/descriptors.cpp b/init/descriptors.cpp
index 429a76e..6e457cd 100644
--- a/init/descriptors.cpp
+++ b/init/descriptors.cpp
@@ -23,6 +23,7 @@
#include <unistd.h>
#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
#include <cutils/android_get_control_file.h>
#include <cutils/sockets.h>
@@ -89,14 +90,34 @@
FileInfo::FileInfo(const std::string& name, const std::string& type, uid_t uid,
gid_t gid, int perm, const std::string& context)
+ // defaults OK for uid,..., they are ignored for this class.
: DescriptorInfo(name, type, uid, gid, perm, context) {
}
-int FileInfo::Create(const std::string& context) const {
- int flags = ((type() == "r" ? O_RDONLY :
- (type() == "w" ? (O_WRONLY | O_CREAT) :
- (O_RDWR | O_CREAT))));
- return create_file(name().c_str(), flags, perm(), uid(), gid(), context.c_str());
+int FileInfo::Create(const std::string&) const {
+ int flags = (type() == "r") ? O_RDONLY :
+ (type() == "w") ? O_WRONLY :
+ O_RDWR;
+
+ // Make sure we do not block on open (eg: devices can chose to block on
+ // carrier detect). Our intention is never to delay launch of a service
+ // for such a condition. The service can perform its own blocking on
+ // carrier detect.
+ android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(name().c_str(),
+ flags | O_NONBLOCK)));
+
+ if (fd < 0) {
+ PLOG(ERROR) << "Failed to open file '" << name().c_str() << "'";
+ return -1;
+ }
+
+ // Fixup as we set O_NONBLOCK for open, the intent for fd is to block reads.
+ fcntl(fd, F_SETFL, flags);
+
+ LOG(INFO) << "Opened file '" << name().c_str() << "'"
+ << ", flags " << std::oct << flags << std::dec;
+
+ return fd.release();
}
const std::string FileInfo::key() const {
diff --git a/init/devices.cpp b/init/devices.cpp
index 2db24b7..6af237c 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -868,7 +868,7 @@
if (pid == 0) {
Timer t;
process_firmware_event(uevent);
- LOG(INFO) << "loading " << uevent->path << " took " << t.duration() << "s";
+ LOG(INFO) << "loading " << uevent->path << " took " << t;
_exit(EXIT_SUCCESS);
} else if (pid == -1) {
PLOG(ERROR) << "could not fork to process firmware event for " << uevent->firmware;
@@ -1043,7 +1043,7 @@
coldboot("/sys/block");
coldboot("/sys/devices");
close(open(COLDBOOT_DONE, O_WRONLY|O_CREAT|O_CLOEXEC, 0000));
- LOG(INFO) << "Coldboot took " << t.duration() << "s.";
+ LOG(INFO) << "Coldboot took " << t;
}
int get_device_fd() {
diff --git a/init/init.cpp b/init/init.cpp
index ef6f37c..95cb62f 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -43,7 +43,6 @@
#include <android-base/file.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
-#include <cutils/android_reboot.h>
#include <cutils/fs.h>
#include <cutils/iosched_policy.h>
#include <cutils/list.h>
@@ -163,14 +162,21 @@
Timer t;
LOG(VERBOSE) << "Waiting for " COLDBOOT_DONE "...";
- // Any longer than 1s is an unreasonable length of time to delay booting.
- // If you're hitting this timeout, check that you didn't make your
- // sepolicy regular expressions too expensive (http://b/19899875).
- if (wait_for_file(COLDBOOT_DONE, 1s)) {
+
+ // Historically we had a 1s timeout here because we weren't otherwise
+ // tracking boot time, and many OEMs made their sepolicy regular
+ // expressions too expensive (http://b/19899875).
+
+ // Now we're tracking boot time, just log the time taken to a system
+ // property. We still panic if it takes more than a minute though,
+ // because any build that slow isn't likely to boot at all, and we'd
+ // rather any test lab devices fail back to the bootloader.
+ if (wait_for_file(COLDBOOT_DONE, 60s) < 0) {
LOG(ERROR) << "Timed out waiting for " COLDBOOT_DONE;
+ panic();
}
- LOG(VERBOSE) << "Waiting for " COLDBOOT_DONE " took " << t.duration() << "s.";
+ property_set("ro.boottime.init.cold_boot_wait", std::to_string(t.duration_ns()).c_str());
return 0;
}
@@ -409,9 +415,8 @@
}
static void security_failure() {
- LOG(ERROR) << "Security failure; rebooting into recovery mode...";
- android_reboot(ANDROID_RB_RESTART2, 0, "recovery");
- while (true) { pause(); } // never reached
+ LOG(ERROR) << "Security failure...";
+ panic();
}
static void selinux_initialize(bool in_kernel_domain) {
@@ -443,8 +448,8 @@
security_failure();
}
- LOG(INFO) << "(Initializing SELinux " << (is_enforcing ? "enforcing" : "non-enforcing")
- << " took " << t.duration() << "s.)";
+ // init's first stage can't set properties, so pass the time to the second stage.
+ setenv("INIT_SELINUX_TOOK", std::to_string(t.duration_ns()).c_str(), 1);
} else {
selinux_init_all_handles();
}
@@ -650,7 +655,13 @@
export_kernel_boot_props();
// Make the time that init started available for bootstat to log.
- property_set("init.start", getenv("INIT_STARTED_AT"));
+ property_set("ro.boottime.init", getenv("INIT_STARTED_AT"));
+ property_set("ro.boottime.init.selinux", getenv("INIT_SELINUX_TOOK"));
+
+ // Clean up our environment.
+ unsetenv("INIT_SECOND_STAGE");
+ unsetenv("INIT_STARTED_AT");
+ unsetenv("INIT_SELINUX_TOOK");
// Now set up SELinux for second stage.
selinux_initialize(false);
diff --git a/init/init_parser.cpp b/init/init_parser.cpp
index d017390..406b339 100644
--- a/init/init_parser.cpp
+++ b/init/init_parser.cpp
@@ -110,7 +110,7 @@
// Nexus 9 boot time, so it's disabled by default.
if (false) DumpState();
- LOG(VERBOSE) << "(Parsing " << path << " took " << t.duration() << "s.)";
+ LOG(VERBOSE) << "(Parsing " << path << " took " << t << ".)";
return true;
}
diff --git a/init/keychords.cpp b/init/keychords.cpp
index 1cfdd80..3dbb2f0 100644
--- a/init/keychords.cpp
+++ b/init/keychords.cpp
@@ -78,11 +78,13 @@
if (adb_enabled == "running") {
Service* svc = ServiceManager::GetInstance().FindServiceByKeychord(id);
if (svc) {
- LOG(INFO) << "Starting service " << svc->name() << " from keychord...";
+ LOG(INFO) << "Starting service " << svc->name() << " from keychord " << id;
svc->Start();
} else {
- LOG(ERROR) << "service for keychord " << id << " not found";
+ LOG(ERROR) << "Service for keychord " << id << " not found";
}
+ } else {
+ LOG(WARNING) << "Not starting service for keychord " << id << " because ADB is disabled";
}
}
diff --git a/init/property_service.cpp b/init/property_service.cpp
index e198297..498a5a1 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -169,11 +169,18 @@
return true;
}
-static int property_set_impl(const char* name, const char* value) {
+int property_set(const char* name, const char* value) {
size_t valuelen = strlen(value);
- if (!is_legal_property_name(name)) return -1;
- if (valuelen >= PROP_VALUE_MAX) return -1;
+ if (!is_legal_property_name(name)) {
+ LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: bad name";
+ return -1;
+ }
+ if (valuelen >= PROP_VALUE_MAX) {
+ LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: "
+ << "value too long";
+ return -1;
+ }
if (strcmp("selinux.restorecon_recursive", name) == 0 && valuelen > 0) {
if (restorecon(value, SELINUX_ANDROID_RESTORECON_RECURSE) != 0) {
@@ -182,49 +189,33 @@
}
prop_info* pi = (prop_info*) __system_property_find(name);
-
- if(pi != 0) {
- /* ro.* properties may NEVER be modified once set */
- if(!strncmp(name, "ro.", 3)) return -1;
+ if (pi != nullptr) {
+ // ro.* properties are actually "write-once".
+ if (!strncmp(name, "ro.", 3)) {
+ LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: "
+ << "property already set";
+ return -1;
+ }
__system_property_update(pi, value, valuelen);
} else {
int rc = __system_property_add(name, strlen(name), value, valuelen);
if (rc < 0) {
+ LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed: "
+ << "__system_property_add failed";
return rc;
}
}
- /* If name starts with "net." treat as a DNS property. */
- if (strncmp("net.", name, strlen("net.")) == 0) {
- if (strcmp("net.change", name) == 0) {
- return 0;
- }
- /*
- * The 'net.change' property is a special property used track when any
- * 'net.*' property name is updated. It is _ONLY_ updated here. Its value
- * contains the last updated 'net.*' property.
- */
- property_set("net.change", name);
- } else if (persistent_properties_loaded &&
- strncmp("persist.", name, strlen("persist.")) == 0) {
- /*
- * Don't write properties to disk until after we have read all default properties
- * to prevent them from being overwritten by default values.
- */
+
+ // Don't write properties to disk until after we have read all default
+ // properties to prevent them from being overwritten by default values.
+ if (persistent_properties_loaded && strncmp("persist.", name, strlen("persist.")) == 0) {
write_persistent_property(name, value);
}
property_changed(name, value);
return 0;
}
-int property_set(const char* name, const char* value) {
- int rc = property_set_impl(name, value);
- if (rc == -1) {
- LOG(ERROR) << "property_set(\"" << name << "\", \"" << value << "\") failed";
- }
- return rc;
-}
-
static void handle_property_set_fd()
{
prop_msg msg;
@@ -388,7 +379,7 @@
}
data.push_back('\n');
load_properties(&data[0], filter);
- LOG(VERBOSE) << "(Loading properties from " << filename << " took " << t.duration() << "s.)";
+ LOG(VERBOSE) << "(Loading properties from " << filename << " took " << t << ".)";
}
static void load_persistent_properties() {
diff --git a/init/readme.txt b/init/readme.txt
index 7e9d21b..6f40d6b 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -148,13 +148,10 @@
seclabel or computed based on the service executable file security context.
For native executables see libcutils android_get_control_socket().
-file <path> <type> <perm> [ <user> [ <group> [ <seclabel> ] ] ]
- Open/Create a file path and pass its fd to the launched process. <type> must
- be "r", "w" or "rw". User and group default to 0. 'seclabel' is the SELinux
- security context for the file if it must be created. It defaults to the
- service security context, as specified by seclabel or computed based on the
- service executable file security context. For native executables see
- libcutils android_get_control_file().
+file <path> <type>
+ Open a file path and pass its fd to the launched process. <type> must be
+ "r", "w" or "rw". For native executables see libcutils
+ android_get_control_file().
user <username>
Change to 'username' before exec'ing this service.
@@ -398,6 +395,9 @@
Trigger an event. Used to queue an action from another
action.
+umount <path>
+ Unmount the filesystem mounted at that path.
+
verity_load_state
Internal implementation detail used to load dm-verity state.
@@ -440,16 +440,27 @@
Init provides information about the services that it is responsible
for via the below properties.
-init.start
- Time after boot in ns (via the CLOCK_BOOTTIME clock) at which the first
- stage of init started.
-
init.svc.<name>
State of a named service ("stopped", "stopping", "running", "restarting")
-init.svc.<name>.start
+
+Boot timing
+-----------
+Init records some boot timing information in system properties.
+
+ro.boottime.init
+ Time after boot in ns (via the CLOCK_BOOTTIME clock) at which the first
+ stage of init started.
+
+ro.boottime.init.selinux
+ How long it took the first stage to initialize SELinux.
+
+ro.boottime.init.cold_boot_wait
+ How long init waited for ueventd's coldboot phase to end.
+
+ro.boottime.<service-name>
Time after boot in ns (via the CLOCK_BOOTTIME clock) that the service was
- most recently started.
+ first started.
Bootcharting
diff --git a/init/service.cpp b/init/service.cpp
index 1f53a1b..e967a7c 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -36,7 +36,6 @@
#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
-#include <cutils/android_reboot.h>
#include <system/thread_defs.h>
#include <processgroup/processgroup.h>
@@ -190,9 +189,9 @@
property_set(prop_name.c_str(), new_state.c_str());
if (new_state == "running") {
- prop_name += ".start";
uint64_t start_ns = time_started_.time_since_epoch().count();
- property_set(prop_name.c_str(), StringPrintf("%" PRIu64, start_ns).c_str());
+ property_set(StringPrintf("ro.boottime.%s", name_.c_str()).c_str(),
+ StringPrintf("%" PRIu64, start_ns).c_str());
}
}
@@ -283,10 +282,8 @@
if ((flags_ & SVC_CRITICAL) && !(flags_ & SVC_RESTART)) {
if (now < time_crashed_ + 4min) {
if (++crash_count_ > 4) {
- LOG(ERROR) << "critical process '" << name_ << "' exited 4 times in 4 minutes; "
- << "rebooting into recovery mode";
- android_reboot(ANDROID_RB_RESTART2, 0, "recovery");
- return false;
+ LOG(ERROR) << "critical process '" << name_ << "' exited 4 times in 4 minutes";
+ panic();
}
} else {
time_crashed_ = now;
@@ -529,7 +526,7 @@
{"seclabel", {1, 1, &Service::ParseSeclabel}},
{"setenv", {2, 2, &Service::ParseSetenv}},
{"socket", {3, 6, &Service::ParseSocket}},
- {"file", {2, 6, &Service::ParseFile}},
+ {"file", {2, 2, &Service::ParseFile}},
{"user", {1, 1, &Service::ParseUser}},
{"writepid", {1, kMax, &Service::ParseWritepid}},
};
@@ -570,9 +567,9 @@
console_ = default_console;
}
- bool have_console = (open(console_.c_str(), O_RDWR | O_CLOEXEC) != -1);
+ bool have_console = (access(console_.c_str(), R_OK | W_OK) != -1);
if (!have_console) {
- PLOG(ERROR) << "service '" << name_ << "' couldn't open console '" << console_ << "'";
+ PLOG(ERROR) << "service '" << name_ << "' cannot gain read/write access to console '" << console_ << "'";
flags_ |= SVC_DISABLED;
return false;
}
diff --git a/init/signal_handler.cpp b/init/signal_handler.cpp
index 0dea3e0..1041b82 100644
--- a/init/signal_handler.cpp
+++ b/init/signal_handler.cpp
@@ -24,7 +24,6 @@
#include <unistd.h>
#include <android-base/stringprintf.h>
-#include <cutils/android_reboot.h>
#include <cutils/list.h>
#include <cutils/sockets.h>
diff --git a/init/util.cpp b/init/util.cpp
index 5205ea0..a79a419 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -41,6 +41,8 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
+
+#include <cutils/android_reboot.h>
/* for ANDROID_SOCKET_* */
#include <cutils/sockets.h>
@@ -158,69 +160,6 @@
return -1;
}
-/*
- * create_file - opens and creates a file as dictated in init.rc.
- * This file is inherited by the daemon. We communicate the file
- * descriptor's value via the environment variable ANDROID_FILE_<basename>
- */
-int create_file(const char *path, int flags, mode_t perm, uid_t uid,
- gid_t gid, const char *filecon)
-{
- char *secontext = NULL;
-
- if (filecon) {
- if (setsockcreatecon(filecon) == -1) {
- PLOG(ERROR) << "setsockcreatecon(\"" << filecon << "\") failed";
- return -1;
- }
- } else if (sehandle) {
- if (selabel_lookup(sehandle, &secontext, path, perm) != -1) {
- if (setfscreatecon(secontext) == -1) {
- freecon(secontext); // does not upset errno value
- PLOG(ERROR) << "setfscreatecon(\"" << secontext << "\") failed";
- return -1;
- }
- }
- }
-
- android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path, flags | O_NDELAY, perm)));
- int savederrno = errno;
-
- if (filecon) {
- setsockcreatecon(NULL);
- lsetfilecon(path, filecon);
- } else {
- setfscreatecon(NULL);
- freecon(secontext);
- }
-
- if (fd < 0) {
- errno = savederrno;
- PLOG(ERROR) << "Failed to open/create file '" << path << "'";
- return -1;
- }
-
- if (!(flags & O_NDELAY)) fcntl(fd, F_SETFD, flags);
-
- if (lchown(path, uid, gid)) {
- PLOG(ERROR) << "Failed to lchown file '" << path << "'";
- return -1;
- }
- if (perm != static_cast<mode_t>(-1)) {
- if (fchmodat(AT_FDCWD, path, perm, AT_SYMLINK_NOFOLLOW)) {
- PLOG(ERROR) << "Failed to fchmodat file '" << path << "'";
- return -1;
- }
- }
-
- LOG(INFO) << "Created file '" << path << "'"
- << ", mode " << std::oct << perm << std::dec
- << ", user " << uid
- << ", group " << gid;
-
- return fd.release();
-}
-
bool read_file(const char* path, std::string* content) {
content->clear();
@@ -472,3 +411,22 @@
return true;
}
+
+void reboot(const char* destination) {
+ android_reboot(ANDROID_RB_RESTART2, 0, destination);
+ // We're init, so android_reboot will actually have been a syscall so there's nothing
+ // to wait for. If android_reboot returns, just abort so that the kernel will reboot
+ // itself when init dies.
+ PLOG(FATAL) << "reboot failed";
+ abort();
+}
+
+void panic() {
+ LOG(ERROR) << "panic: rebooting to bootloader";
+ reboot("bootloader");
+}
+
+std::ostream& operator<<(std::ostream& os, const Timer& t) {
+ os << t.duration_s() << " seconds";
+ return os;
+}
diff --git a/init/util.h b/init/util.h
index d56da39..e63c469 100644
--- a/init/util.h
+++ b/init/util.h
@@ -21,8 +21,9 @@
#include <sys/types.h>
#include <chrono>
-#include <string>
#include <functional>
+#include <ostream>
+#include <string>
#define COLDBOOT_DONE "/dev/.coldboot_done"
@@ -30,8 +31,6 @@
int create_socket(const char *name, int type, mode_t perm,
uid_t uid, gid_t gid, const char *socketcon);
-int create_file(const char *path, int mode, mode_t perm,
- uid_t uid, gid_t gid, const char *filecon);
bool read_file(const char* path, std::string* content);
int write_file(const char* path, const char* content);
@@ -51,15 +50,21 @@
Timer() : start_(boot_clock::now()) {
}
- double duration() {
+ double duration_s() const {
typedef std::chrono::duration<double> double_duration;
return std::chrono::duration_cast<double_duration>(boot_clock::now() - start_).count();
}
+ int64_t duration_ns() const {
+ return (boot_clock::now() - start_).count();
+ }
+
private:
boot_clock::time_point start_;
};
+std::ostream& operator<<(std::ostream& os, const Timer& t);
+
unsigned int decode_uid(const char *s);
int mkdir_recursive(const char *pathname, mode_t mode);
@@ -72,4 +77,8 @@
std::string bytes_to_hex(const uint8_t *bytes, size_t bytes_len);
bool is_dir(const char* pathname);
bool expand_props(const std::string& src, std::string* dst);
+
+void reboot(const char* destination) __attribute__((__noreturn__));
+void panic() __attribute__((__noreturn__));
+
#endif
diff --git a/init/util_test.cpp b/init/util_test.cpp
index e9f164d..24c75c4 100644
--- a/init/util_test.cpp
+++ b/init/util_test.cpp
@@ -16,19 +16,9 @@
#include "util.h"
-#include <ctype.h>
#include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <android-base/stringprintf.h>
-#include <android-base/test_utils.h>
-#include <cutils/android_get_control_file.h>
#include <gtest/gtest.h>
-#include <selinux/android.h>
TEST(util, read_file_ENOENT) {
std::string s("hello");
@@ -52,54 +42,3 @@
EXPECT_EQ(UINT_MAX, decode_uid("toot"));
EXPECT_EQ(123U, decode_uid("123"));
}
-
-struct selabel_handle *sehandle;
-
-TEST(util, create_file) {
- if (!sehandle) sehandle = selinux_android_file_context_handle();
-
- TemporaryFile tf;
- close(tf.fd);
- EXPECT_GE(unlink(tf.path), 0);
-
- std::string key(ANDROID_FILE_ENV_PREFIX);
- key += tf.path;
-
- std::for_each(key.begin(), key.end(), [] (char& c) { c = isalnum(c) ? c : '_'; });
-
- EXPECT_EQ(unsetenv(key.c_str()), 0);
-
- uid_t uid = decode_uid("logd");
- gid_t gid = decode_uid("system");
- mode_t perms = S_IRWXU | S_IWGRP | S_IRGRP | S_IROTH;
- static const char context[] = "u:object_r:misc_logd_file:s0";
- EXPECT_GE(tf.fd = create_file(tf.path, O_RDWR | O_CREAT, perms, uid, gid, context), 0);
- if (tf.fd < 0) return;
- static const char hello[] = "hello world\n";
- static const ssize_t len = strlen(hello);
- EXPECT_EQ(write(tf.fd, hello, len), len);
- char buffer[sizeof(hello) + 1];
- memset(buffer, 0, sizeof(buffer));
- EXPECT_GE(lseek(tf.fd, 0, SEEK_SET), 0);
- EXPECT_EQ(read(tf.fd, buffer, sizeof(buffer)), len);
- EXPECT_EQ(std::string(hello), buffer);
- EXPECT_EQ(android_get_control_file(tf.path), -1);
- EXPECT_EQ(setenv(key.c_str(), android::base::StringPrintf("%d", tf.fd).c_str(), true), 0);
- EXPECT_EQ(android_get_control_file(tf.path), tf.fd);
- close(tf.fd);
- EXPECT_EQ(android_get_control_file(tf.path), -1);
- EXPECT_EQ(unsetenv(key.c_str()), 0);
- struct stat st;
- EXPECT_EQ(stat(tf.path, &st), 0);
- EXPECT_EQ(st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO), perms);
- EXPECT_EQ(st.st_uid, uid);
- EXPECT_EQ(st.st_gid, gid);
- security_context_t con;
- EXPECT_GE(getfilecon(tf.path, &con), 0);
- EXPECT_NE(con, static_cast<security_context_t>(NULL));
- if (con) {
- EXPECT_EQ(context, std::string(con));
- }
- freecon(con);
- EXPECT_EQ(unlink(tf.path), 0);
-}
diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp
index 5c72234..200b6d6 100644
--- a/libbacktrace/Android.bp
+++ b/libbacktrace/Android.bp
@@ -117,4 +117,17 @@
},
cflags: ["-O0"],
srcs: ["backtrace_testlib.c"],
-}
+
+ target: {
+ linux: {
+ shared_libs: [
+ "libunwind",
+ ],
+ },
+ android: {
+ shared_libs: [
+ "libunwind",
+ ],
+ },
+ }
+}
\ No newline at end of file
diff --git a/libbacktrace/Android.mk b/libbacktrace/Android.mk
index 0f01872..f4976e9 100644
--- a/libbacktrace/Android.mk
+++ b/libbacktrace/Android.mk
@@ -111,8 +111,6 @@
backtrace_test_ldlibs_host += \
-ldl \
-backtrace_test_strip_module := false
-
module := backtrace_test
module_tag := debug
build_type := target
diff --git a/libbacktrace/BacktraceOffline.cpp b/libbacktrace/BacktraceOffline.cpp
index a05a6d8..9e95563 100644
--- a/libbacktrace/BacktraceOffline.cpp
+++ b/libbacktrace/BacktraceOffline.cpp
@@ -50,6 +50,48 @@
#include "BacktraceLog.h"
+struct EhFrame {
+ uint64_t hdr_vaddr;
+ uint64_t vaddr;
+ uint64_t fde_table_offset;
+ uintptr_t min_func_vaddr;
+ std::vector<uint8_t> hdr_data;
+ std::vector<uint8_t> data;
+};
+
+struct ArmIdxEntry {
+ uint32_t func_offset;
+ uint32_t value;
+};
+
+struct ArmExidx {
+ uint64_t exidx_vaddr;
+ uint64_t extab_vaddr;
+ std::vector<ArmIdxEntry> exidx_data;
+ std::vector<uint8_t> extab_data;
+ // There is a one-to-one map from exidx_data.func_offset to func_vaddr_array.
+ std::vector<uint32_t> func_vaddr_array;
+};
+
+struct DebugFrameInfo {
+ bool has_arm_exidx;
+ bool has_eh_frame;
+ bool has_debug_frame;
+ bool has_gnu_debugdata;
+
+ EhFrame eh_frame;
+ ArmExidx arm_exidx;
+
+ uint64_t min_vaddr;
+ uint64_t text_end_vaddr;
+
+ DebugFrameInfo() : has_arm_exidx(false), has_eh_frame(false),
+ has_debug_frame(false), has_gnu_debugdata(false) { }
+};
+
+static std::unordered_map<std::string, std::unique_ptr<DebugFrameInfo>>& g_debug_frames =
+ *new std::unordered_map<std::string, std::unique_ptr<DebugFrameInfo>>;
+
void Space::Clear() {
start = 0;
end = 0;
@@ -207,23 +249,18 @@
if (read_size != 0) {
return read_size;
}
+ read_size = arm_exidx_space_.Read(addr, buffer, bytes);
+ if (read_size != 0) {
+ return read_size;
+ }
+ read_size = arm_extab_space_.Read(addr, buffer, bytes);
+ if (read_size != 0) {
+ return read_size;
+ }
read_size = stack_space_.Read(addr, buffer, bytes);
return read_size;
}
-static bool FileOffsetToVaddr(
- const std::vector<DebugFrameInfo::EhFrame::ProgramHeader>& program_headers,
- uint64_t file_offset, uint64_t* vaddr) {
- for (auto& header : program_headers) {
- if (file_offset >= header.file_offset && file_offset < header.file_offset + header.file_size) {
- // TODO: Consider load_bias?
- *vaddr = file_offset - header.file_offset + header.vaddr;
- return true;
- }
- }
- return false;
-}
-
bool BacktraceOffline::FindProcInfo(unw_addr_space_t addr_space, uint64_t ip,
unw_proc_info_t* proc_info, int need_unwind_info) {
backtrace_map_t map;
@@ -236,45 +273,90 @@
if (debug_frame == nullptr) {
return false;
}
- if (debug_frame->is_eh_frame) {
- uint64_t ip_offset = ip - map.start + map.offset;
- uint64_t ip_vaddr; // vaddr in the elf file.
- bool result = FileOffsetToVaddr(debug_frame->eh_frame.program_headers, ip_offset, &ip_vaddr);
- if (!result) {
- return false;
- }
- // Calculate the addresses where .eh_frame_hdr and .eh_frame stay when the process was running.
- eh_frame_hdr_space_.start = (ip - ip_vaddr) + debug_frame->eh_frame.eh_frame_hdr_vaddr;
- eh_frame_hdr_space_.end =
- eh_frame_hdr_space_.start + debug_frame->eh_frame.eh_frame_hdr_data.size();
- eh_frame_hdr_space_.data = debug_frame->eh_frame.eh_frame_hdr_data.data();
-
- eh_frame_space_.start = (ip - ip_vaddr) + debug_frame->eh_frame.eh_frame_vaddr;
- eh_frame_space_.end = eh_frame_space_.start + debug_frame->eh_frame.eh_frame_data.size();
- eh_frame_space_.data = debug_frame->eh_frame.eh_frame_data.data();
-
- unw_dyn_info di;
- memset(&di, '\0', sizeof(di));
- di.start_ip = map.start;
- di.end_ip = map.end;
- di.format = UNW_INFO_FORMAT_REMOTE_TABLE;
- di.u.rti.name_ptr = 0;
- di.u.rti.segbase = eh_frame_hdr_space_.start;
- di.u.rti.table_data =
- eh_frame_hdr_space_.start + debug_frame->eh_frame.fde_table_offset_in_eh_frame_hdr;
- di.u.rti.table_len = (eh_frame_hdr_space_.end - di.u.rti.table_data) / sizeof(unw_word_t);
- int ret = dwarf_search_unwind_table(addr_space, ip, &di, proc_info, need_unwind_info, this);
- return ret == 0;
- }
eh_frame_hdr_space_.Clear();
eh_frame_space_.Clear();
- unw_dyn_info_t di;
- unw_word_t segbase = map.start - map.offset;
- int found = dwarf_find_debug_frame(0, &di, ip, segbase, filename.c_str(), map.start, map.end);
- if (found == 1) {
- int ret = dwarf_search_unwind_table(addr_space, ip, &di, proc_info, need_unwind_info, this);
- return ret == 0;
+ arm_exidx_space_.Clear();
+ arm_extab_space_.Clear();
+
+ // vaddr in the elf file.
+ uint64_t ip_vaddr = ip - map.start + debug_frame->min_vaddr;
+ if (debug_frame->has_arm_exidx) {
+ auto& func_vaddrs = debug_frame->arm_exidx.func_vaddr_array;
+ if (ip_vaddr >= func_vaddrs[0] && ip_vaddr < debug_frame->text_end_vaddr) {
+ // Use binary search to find the correct function.
+ auto it = std::upper_bound(func_vaddrs.begin(), func_vaddrs.end(),
+ static_cast<uint32_t>(ip_vaddr));
+ if (it != func_vaddrs.begin()) {
+ --it;
+ // Found the exidx entry.
+ size_t index = it - func_vaddrs.begin();
+
+ proc_info->format = UNW_INFO_FORMAT_ARM_EXIDX;
+ proc_info->unwind_info = reinterpret_cast<void*>(
+ static_cast<uintptr_t>(index * sizeof(ArmIdxEntry) +
+ debug_frame->arm_exidx.exidx_vaddr +
+ debug_frame->min_vaddr));
+
+ // Prepare arm_exidx space and arm_extab space.
+ arm_exidx_space_.start = debug_frame->min_vaddr + debug_frame->arm_exidx.exidx_vaddr;
+ arm_exidx_space_.end = arm_exidx_space_.start +
+ debug_frame->arm_exidx.exidx_data.size() * sizeof(ArmIdxEntry);
+ arm_exidx_space_.data = reinterpret_cast<const uint8_t*>(
+ debug_frame->arm_exidx.exidx_data.data());
+
+ arm_extab_space_.start = debug_frame->min_vaddr + debug_frame->arm_exidx.extab_vaddr;
+ arm_extab_space_.end = arm_extab_space_.start +
+ debug_frame->arm_exidx.extab_data.size();
+ arm_extab_space_.data = debug_frame->arm_exidx.extab_data.data();
+ return true;
+ }
+ }
+ }
+
+ if (debug_frame->has_eh_frame) {
+ if (ip_vaddr >= debug_frame->eh_frame.min_func_vaddr &&
+ ip_vaddr < debug_frame->text_end_vaddr) {
+ // Prepare eh_frame_hdr space and eh_frame space.
+ eh_frame_hdr_space_.start = ip - ip_vaddr + debug_frame->eh_frame.hdr_vaddr;
+ eh_frame_hdr_space_.end =
+ eh_frame_hdr_space_.start + debug_frame->eh_frame.hdr_data.size();
+ eh_frame_hdr_space_.data = debug_frame->eh_frame.hdr_data.data();
+
+ eh_frame_space_.start = ip - ip_vaddr + debug_frame->eh_frame.vaddr;
+ eh_frame_space_.end = eh_frame_space_.start + debug_frame->eh_frame.data.size();
+ eh_frame_space_.data = debug_frame->eh_frame.data.data();
+
+ unw_dyn_info di;
+ memset(&di, '\0', sizeof(di));
+ di.start_ip = map.start;
+ di.end_ip = map.end;
+ di.format = UNW_INFO_FORMAT_REMOTE_TABLE;
+ di.u.rti.name_ptr = 0;
+ di.u.rti.segbase = eh_frame_hdr_space_.start;
+ di.u.rti.table_data =
+ eh_frame_hdr_space_.start + debug_frame->eh_frame.fde_table_offset;
+ di.u.rti.table_len = (eh_frame_hdr_space_.end - di.u.rti.table_data) / sizeof(unw_word_t);
+ // TODO: Do it ourselves is more efficient than calling this function.
+ int ret = dwarf_search_unwind_table(addr_space, ip, &di, proc_info, need_unwind_info, this);
+ if (ret == 0) {
+ return true;
+ }
+ }
+ }
+
+ if (debug_frame->has_debug_frame || debug_frame->has_gnu_debugdata) {
+ unw_dyn_info_t di;
+ unw_word_t segbase = map.start - map.offset;
+ // TODO: http://b/32916571
+ // TODO: Do it ourselves is more efficient than calling libunwind functions.
+ int found = dwarf_find_debug_frame(0, &di, ip, segbase, filename.c_str(), map.start, map.end);
+ if (found == 1) {
+ int ret = dwarf_search_unwind_table(addr_space, ip, &di, proc_info, need_unwind_info, this);
+ if (ret == 0) {
+ return true;
+ }
+ }
}
return false;
}
@@ -462,33 +544,18 @@
return "";
}
-std::unordered_map<std::string, std::unique_ptr<DebugFrameInfo>> BacktraceOffline::debug_frames_;
-std::unordered_set<std::string> BacktraceOffline::debug_frame_missing_files_;
-
static DebugFrameInfo* ReadDebugFrameFromFile(const std::string& filename);
DebugFrameInfo* BacktraceOffline::GetDebugFrameInFile(const std::string& filename) {
if (cache_file_) {
- auto it = debug_frames_.find(filename);
- if (it != debug_frames_.end()) {
+ auto it = g_debug_frames.find(filename);
+ if (it != g_debug_frames.end()) {
return it->second.get();
}
- if (debug_frame_missing_files_.find(filename) != debug_frame_missing_files_.end()) {
- return nullptr;
- }
}
DebugFrameInfo* debug_frame = ReadDebugFrameFromFile(filename);
if (cache_file_) {
- if (debug_frame != nullptr) {
- debug_frames_.emplace(filename, std::unique_ptr<DebugFrameInfo>(debug_frame));
- } else {
- debug_frame_missing_files_.insert(filename);
- }
- } else {
- if (last_debug_frame_ != nullptr) {
- delete last_debug_frame_;
- }
- last_debug_frame_ = debug_frame;
+ g_debug_frames.emplace(filename, std::unique_ptr<DebugFrameInfo>(debug_frame));
}
return debug_frame;
}
@@ -556,72 +623,106 @@
return true;
}
-using ProgramHeader = DebugFrameInfo::EhFrame::ProgramHeader;
-
template <class ELFT>
DebugFrameInfo* ReadDebugFrameFromELFFile(const llvm::object::ELFFile<ELFT>* elf) {
+ DebugFrameInfo* result = new DebugFrameInfo;
+ result->text_end_vaddr = std::numeric_limits<uint64_t>::max();
+
bool has_eh_frame_hdr = false;
- uint64_t eh_frame_hdr_vaddr = 0;
- std::vector<uint8_t> eh_frame_hdr_data;
bool has_eh_frame = false;
- uint64_t eh_frame_vaddr = 0;
- std::vector<uint8_t> eh_frame_data;
for (auto it = elf->section_begin(); it != elf->section_end(); ++it) {
llvm::ErrorOr<llvm::StringRef> name = elf->getSectionName(&*it);
if (name) {
- if (name.get() == ".debug_frame") {
- DebugFrameInfo* debug_frame = new DebugFrameInfo;
- debug_frame->is_eh_frame = false;
- return debug_frame;
- }
- if (name.get() == ".eh_frame_hdr") {
- has_eh_frame_hdr = true;
- eh_frame_hdr_vaddr = it->sh_addr;
+ std::string s = name.get();
+ if (s == ".debug_frame") {
+ result->has_debug_frame = true;
+ } else if (s == ".gnu_debugdata") {
+ result->has_gnu_debugdata = true;
+ } else if (s == ".eh_frame_hdr") {
+ result->eh_frame.hdr_vaddr = it->sh_addr;
llvm::ErrorOr<llvm::ArrayRef<uint8_t>> data = elf->getSectionContents(&*it);
if (data) {
- eh_frame_hdr_data.insert(eh_frame_hdr_data.begin(), data->data(),
- data->data() + data->size());
- } else {
- return nullptr;
+ result->eh_frame.hdr_data.insert(result->eh_frame.hdr_data.end(),
+ data->data(), data->data() + data->size());
+
+ uint64_t fde_table_offset;
+ if (GetFdeTableOffsetInEhFrameHdr(result->eh_frame.hdr_data,
+ &fde_table_offset)) {
+ result->eh_frame.fde_table_offset = fde_table_offset;
+ // Make sure we have at least one entry in fde_table.
+ if (fde_table_offset + 2 * sizeof(int32_t) <= data->size()) {
+ intptr_t eh_frame_hdr_vaddr = it->sh_addr;
+ int32_t sdata;
+ uint8_t* p = result->eh_frame.hdr_data.data() + fde_table_offset;
+ memcpy(&sdata, p, sizeof(sdata));
+ result->eh_frame.min_func_vaddr = eh_frame_hdr_vaddr + sdata;
+ has_eh_frame_hdr = true;
+ }
+ }
}
- } else if (name.get() == ".eh_frame") {
- has_eh_frame = true;
- eh_frame_vaddr = it->sh_addr;
+ } else if (s == ".eh_frame") {
+ result->eh_frame.vaddr = it->sh_addr;
llvm::ErrorOr<llvm::ArrayRef<uint8_t>> data = elf->getSectionContents(&*it);
if (data) {
- eh_frame_data.insert(eh_frame_data.begin(), data->data(), data->data() + data->size());
- } else {
- return nullptr;
+ result->eh_frame.data.insert(result->eh_frame.data.end(),
+ data->data(), data->data() + data->size());
+ has_eh_frame = true;
}
+ } else if (s == ".ARM.exidx") {
+ result->arm_exidx.exidx_vaddr = it->sh_addr;
+ llvm::ErrorOr<llvm::ArrayRef<uint8_t>> data = elf->getSectionContents(&*it);
+ if (data) {
+ size_t entry_count = data->size() / sizeof(ArmIdxEntry);
+ result->arm_exidx.exidx_data.resize(entry_count);
+ memcpy(result->arm_exidx.exidx_data.data(), data->data(),
+ entry_count * sizeof(ArmIdxEntry));
+ if (entry_count > 0u) {
+ // Change IdxEntry.func_offset into vaddr.
+ result->arm_exidx.func_vaddr_array.reserve(entry_count);
+ uint32_t vaddr = it->sh_addr;
+ for (auto& entry : result->arm_exidx.exidx_data) {
+ uint32_t func_offset = entry.func_offset + vaddr;
+ // Clear bit 31 for the prel31 offset.
+ // Arm sets bit 0 to mark it as thumb code, remove the flag.
+ result->arm_exidx.func_vaddr_array.push_back(
+ func_offset & 0x7ffffffe);
+ vaddr += 8;
+ }
+ result->has_arm_exidx = true;
+ }
+ }
+ } else if (s == ".ARM.extab") {
+ result->arm_exidx.extab_vaddr = it->sh_addr;
+ llvm::ErrorOr<llvm::ArrayRef<uint8_t>> data = elf->getSectionContents(&*it);
+ if (data) {
+ result->arm_exidx.extab_data.insert(result->arm_exidx.extab_data.end(),
+ data->data(), data->data() + data->size());
+ }
+ } else if (s == ".text") {
+ result->text_end_vaddr = it->sh_addr + it->sh_size;
}
}
}
- if (!(has_eh_frame_hdr && has_eh_frame)) {
- return nullptr;
- }
- uint64_t fde_table_offset;
- if (!GetFdeTableOffsetInEhFrameHdr(eh_frame_hdr_data, &fde_table_offset)) {
- return nullptr;
+
+ if (has_eh_frame_hdr && has_eh_frame) {
+ result->has_eh_frame = true;
}
- std::vector<ProgramHeader> program_headers;
+ result->min_vaddr = std::numeric_limits<uint64_t>::max();
for (auto it = elf->program_header_begin(); it != elf->program_header_end(); ++it) {
- ProgramHeader header;
- header.vaddr = it->p_vaddr;
- header.file_offset = it->p_offset;
- header.file_size = it->p_filesz;
- program_headers.push_back(header);
+ if ((it->p_type == llvm::ELF::PT_LOAD) && (it->p_flags & llvm::ELF::PF_X)) {
+ if (it->p_vaddr < result->min_vaddr) {
+ result->min_vaddr = it->p_vaddr;
+ }
+ }
}
- DebugFrameInfo* debug_frame = new DebugFrameInfo;
- debug_frame->is_eh_frame = true;
- debug_frame->eh_frame.eh_frame_hdr_vaddr = eh_frame_hdr_vaddr;
- debug_frame->eh_frame.eh_frame_vaddr = eh_frame_vaddr;
- debug_frame->eh_frame.fde_table_offset_in_eh_frame_hdr = fde_table_offset;
- debug_frame->eh_frame.eh_frame_hdr_data = std::move(eh_frame_hdr_data);
- debug_frame->eh_frame.eh_frame_data = std::move(eh_frame_data);
- debug_frame->eh_frame.program_headers = program_headers;
- return debug_frame;
+ if (!result->has_eh_frame && !result->has_arm_exidx && !result->has_debug_frame &&
+ !result->has_gnu_debugdata) {
+ delete result;
+ return nullptr;
+ }
+ return result;
}
static bool IsValidElfPath(const std::string& filename) {
diff --git a/libbacktrace/BacktraceOffline.h b/libbacktrace/BacktraceOffline.h
index 42f826d..c0b686e 100644
--- a/libbacktrace/BacktraceOffline.h
+++ b/libbacktrace/BacktraceOffline.h
@@ -40,22 +40,7 @@
size_t Read(uint64_t addr, uint8_t* buffer, size_t size);
};
-struct DebugFrameInfo {
- bool is_eh_frame;
- struct EhFrame {
- uint64_t eh_frame_hdr_vaddr;
- uint64_t eh_frame_vaddr;
- uint64_t fde_table_offset_in_eh_frame_hdr;
- std::vector<uint8_t> eh_frame_hdr_data;
- std::vector<uint8_t> eh_frame_data;
- struct ProgramHeader {
- uint64_t vaddr;
- uint64_t file_offset;
- uint64_t file_size;
- };
- std::vector<ProgramHeader> program_headers;
- } eh_frame;
-};
+struct DebugFrameInfo;
class BacktraceOffline : public Backtrace {
public:
@@ -63,18 +48,13 @@
bool cache_file)
: Backtrace(pid, tid, map),
cache_file_(cache_file),
- context_(nullptr),
- last_debug_frame_(nullptr) {
+ context_(nullptr) {
stack_space_.start = stack.start;
stack_space_.end = stack.end;
stack_space_.data = stack.data;
}
- virtual ~BacktraceOffline() {
- if (last_debug_frame_ != nullptr) {
- delete last_debug_frame_;
- }
- }
+ virtual ~BacktraceOffline() = default;
bool Unwind(size_t num_ignore_frames, ucontext_t* context) override;
@@ -91,15 +71,13 @@
std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) override;
DebugFrameInfo* GetDebugFrameInFile(const std::string& filename);
- static std::unordered_map<std::string, std::unique_ptr<DebugFrameInfo>> debug_frames_;
- static std::unordered_set<std::string> debug_frame_missing_files_;
-
bool cache_file_;
ucontext_t* context_;
Space eh_frame_hdr_space_;
Space eh_frame_space_;
+ Space arm_extab_space_;
+ Space arm_exidx_space_;
Space stack_space_;
- DebugFrameInfo* last_debug_frame_;
};
#endif // _LIBBACKTRACE_BACKTRACE_OFFLINE_H
diff --git a/libbacktrace/backtrace_offline_test.cpp b/libbacktrace/backtrace_offline_test.cpp
index d6dc2c9..49fcb29 100644
--- a/libbacktrace/backtrace_offline_test.cpp
+++ b/libbacktrace/backtrace_offline_test.cpp
@@ -1,3 +1,20 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <inttypes.h>
#include <libunwind.h>
#include <pthread.h>
#include <stdint.h>
@@ -9,6 +26,9 @@
#include <utility>
#include <vector>
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include <backtrace/Backtrace.h>
#include <backtrace/BacktraceMap.h>
#include <cutils/threads.h>
@@ -22,29 +42,7 @@
int test_level_three(int, int, int, int, void (*)(void*), void*);
int test_level_four(int, int, int, int, void (*)(void*), void*);
int test_recursive_call(int, void (*)(void*), void*);
-}
-
-static volatile bool g_exit_flag = false;
-
-static void GetContextAndExit(void* arg) {
- unw_context_t* unw_context = reinterpret_cast<unw_context_t*>(arg);
- unw_getcontext(unw_context);
- // Don't touch the stack anymore.
- while (!g_exit_flag) {
- }
-}
-
-struct OfflineThreadArg {
- unw_context_t unw_context;
- pid_t tid;
- std::function<int(void (*)(void*), void*)> function;
-};
-
-static void* OfflineThreadFunc(void* arg) {
- OfflineThreadArg* fn_arg = reinterpret_cast<OfflineThreadArg*>(arg);
- fn_arg->tid = gettid();
- fn_arg->function(GetContextAndExit, &fn_arg->unw_context);
- return nullptr;
+void test_get_context_and_wait(unw_context_t* unw_context, volatile int* exit_flag);
}
static ucontext_t GetUContextFromUnwContext(const unw_context_t& unw_context) {
@@ -73,11 +71,68 @@
return ucontext;
}
-static void OfflineBacktraceFunctionCall(const std::function<int(void (*)(void*), void*)>& function,
- std::vector<uintptr_t>* pc_values) {
+struct FunctionSymbol {
+ std::string name;
+ uintptr_t start;
+ uintptr_t end;
+};
+
+static std::vector<FunctionSymbol> GetFunctionSymbols() {
+ std::vector<FunctionSymbol> symbols = {
+ {"unknown_start", 0, 0},
+ {"test_level_one", reinterpret_cast<uintptr_t>(&test_level_one), 0},
+ {"test_level_two", reinterpret_cast<uintptr_t>(&test_level_two), 0},
+ {"test_level_three", reinterpret_cast<uintptr_t>(&test_level_three), 0},
+ {"test_level_four", reinterpret_cast<uintptr_t>(&test_level_four), 0},
+ {"test_recursive_call", reinterpret_cast<uintptr_t>(&test_recursive_call), 0},
+ {"test_get_context_and_wait", reinterpret_cast<uintptr_t>(&test_get_context_and_wait), 0},
+ {"unknown_end", static_cast<uintptr_t>(-1), static_cast<uintptr_t>(-1)},
+ };
+ std::sort(
+ symbols.begin(), symbols.end(),
+ [](const FunctionSymbol& s1, const FunctionSymbol& s2) { return s1.start < s2.start; });
+ for (size_t i = 0; i + 1 < symbols.size(); ++i) {
+ symbols[i].end = symbols[i + 1].start;
+ }
+ return symbols;
+}
+
+static std::string RawDataToHexString(const void* data, size_t size) {
+ const uint8_t* p = static_cast<const uint8_t*>(data);
+ std::string s;
+ for (size_t i = 0; i < size; ++i) {
+ s += android::base::StringPrintf("%02x", p[i]);
+ }
+ return s;
+}
+
+static void HexStringToRawData(const char* s, void* data, size_t size) {
+ uint8_t* p = static_cast<uint8_t*>(data);
+ for (size_t i = 0; i < size; ++i) {
+ int value;
+ sscanf(s, "%02x", &value);
+ *p++ = static_cast<uint8_t>(value);
+ s += 2;
+ }
+}
+
+struct OfflineThreadArg {
+ unw_context_t unw_context;
+ pid_t tid;
+ volatile int exit_flag;
+};
+
+static void* OfflineThreadFunc(void* arg) {
+ OfflineThreadArg* fn_arg = reinterpret_cast<OfflineThreadArg*>(arg);
+ fn_arg->tid = gettid();
+ test_get_context_and_wait(&fn_arg->unw_context, &fn_arg->exit_flag);
+ return nullptr;
+}
+
+// This test is disable because it is for generating test data.
+TEST(libbacktrace, DISABLED_generate_offline_testdata) {
// Create a thread to generate the needed stack and registers information.
- g_exit_flag = false;
- const size_t stack_size = 1024 * 1024;
+ const size_t stack_size = 16 * 1024;
void* stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
ASSERT_NE(MAP_FAILED, stack);
uintptr_t stack_addr = reinterpret_cast<uintptr_t>(stack);
@@ -86,18 +141,17 @@
ASSERT_EQ(0, pthread_attr_setstack(&attr, reinterpret_cast<void*>(stack), stack_size));
pthread_t thread;
OfflineThreadArg arg;
- arg.function = function;
+ arg.exit_flag = 0;
ASSERT_EQ(0, pthread_create(&thread, &attr, OfflineThreadFunc, &arg));
// Wait for the offline thread to generate the stack and unw_context information.
sleep(1);
// Copy the stack information.
std::vector<uint8_t> stack_data(reinterpret_cast<uint8_t*>(stack),
reinterpret_cast<uint8_t*>(stack) + stack_size);
- g_exit_flag = true;
+ arg.exit_flag = 1;
ASSERT_EQ(0, pthread_join(thread, nullptr));
ASSERT_EQ(0, munmap(stack, stack_size));
- // Do offline backtrace.
std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(getpid()));
ASSERT_TRUE(map != nullptr);
@@ -106,47 +160,44 @@
stack_info.end = stack_addr + stack_size;
stack_info.data = stack_data.data();
- std::unique_ptr<Backtrace> backtrace(
- Backtrace::CreateOffline(getpid(), arg.tid, map.get(), stack_info));
- ASSERT_TRUE(backtrace != nullptr);
-
- ucontext_t ucontext = GetUContextFromUnwContext(arg.unw_context);
- ASSERT_TRUE(backtrace->Unwind(0, &ucontext));
-
- // Collect pc values of the call stack frames.
- for (size_t i = 0; i < backtrace->NumFrames(); ++i) {
- pc_values->push_back(backtrace->GetFrame(i)->pc);
+ // Generate offline testdata.
+ std::string testdata;
+ // 1. Dump pid, tid
+ testdata += android::base::StringPrintf("pid: %d tid: %d\n", getpid(), arg.tid);
+ // 2. Dump maps
+ for (auto it = map->begin(); it != map->end(); ++it) {
+ testdata += android::base::StringPrintf(
+ "map: start: %" PRIxPTR " end: %" PRIxPTR " offset: %" PRIxPTR
+ " load_base: %" PRIxPTR " flags: %d name: %s\n",
+ it->start, it->end, it->offset, it->load_base, it->flags, it->name.c_str());
}
+ // 3. Dump registers
+ testdata += android::base::StringPrintf("registers: %zu ", sizeof(arg.unw_context));
+ testdata += RawDataToHexString(&arg.unw_context, sizeof(arg.unw_context));
+ testdata.push_back('\n');
+
+ // 4. Dump stack
+ testdata += android::base::StringPrintf(
+ "stack: start: %" PRIx64 " end: %" PRIx64 " size: %zu ",
+ stack_info.start, stack_info.end, stack_data.size());
+ testdata += RawDataToHexString(stack_data.data(), stack_data.size());
+ testdata.push_back('\n');
+
+ // 5. Dump function symbols
+ std::vector<FunctionSymbol> function_symbols = GetFunctionSymbols();
+ for (const auto& symbol : function_symbols) {
+ testdata += android::base::StringPrintf(
+ "function: start: %" PRIxPTR " end: %" PRIxPTR" name: %s\n",
+ symbol.start, symbol.end, symbol.name.c_str());
+ }
+
+ ASSERT_TRUE(android::base::WriteStringToFile(testdata, "offline_testdata"));
}
// Return the name of the function which matches the address. Although we don't know the
// exact end of each function, it is accurate enough for the tests.
-static std::string FunctionNameForAddress(uintptr_t addr) {
- struct FunctionSymbol {
- std::string name;
- uintptr_t start;
- uintptr_t end;
- };
-
- static std::vector<FunctionSymbol> symbols;
- if (symbols.empty()) {
- symbols = std::vector<FunctionSymbol>{
- {"unknown_start", 0, 0},
- {"test_level_one", reinterpret_cast<uintptr_t>(&test_level_one), 0},
- {"test_level_two", reinterpret_cast<uintptr_t>(&test_level_two), 0},
- {"test_level_three", reinterpret_cast<uintptr_t>(&test_level_three), 0},
- {"test_level_four", reinterpret_cast<uintptr_t>(&test_level_four), 0},
- {"test_recursive_call", reinterpret_cast<uintptr_t>(&test_recursive_call), 0},
- {"GetContextAndExit", reinterpret_cast<uintptr_t>(&GetContextAndExit), 0},
- {"unknown_end", static_cast<uintptr_t>(-1), static_cast<uintptr_t>(-1)},
- };
- std::sort(
- symbols.begin(), symbols.end(),
- [](const FunctionSymbol& s1, const FunctionSymbol& s2) { return s1.start < s2.start; });
- for (size_t i = 0; i + 1 < symbols.size(); ++i) {
- symbols[i].end = symbols[i + 1].start;
- }
- }
+static std::string FunctionNameForAddress(uintptr_t addr,
+ const std::vector<FunctionSymbol>& symbols) {
for (auto& symbol : symbols) {
if (addr >= symbol.start && addr < symbol.end) {
return symbol.name;
@@ -155,35 +206,136 @@
return "";
}
-TEST(libbacktrace, offline) {
- std::function<int(void (*)(void*), void*)> function =
- std::bind(test_level_one, 1, 2, 3, 4, std::placeholders::_1, std::placeholders::_2);
+static std::string GetArch() {
+#if defined(__arm__)
+ return "arm";
+#elif defined(__aarch64__)
+ return "aarch64";
+#elif defined(__i386__)
+ return "x86";
+#elif defined(__x86_64__)
+ return "x86_64";
+#else
+ return "";
+#endif
+}
+
+static void BacktraceOfflineTest(const std::string& testlib_name) {
+ const std::string arch = GetArch();
+ if (arch.empty()) {
+ GTEST_LOG_(INFO) << "This test does nothing on current arch.";
+ return;
+ }
+ const std::string offline_testdata_path = "testdata/" + arch + "/offline_testdata";
+ std::string testdata;
+ ASSERT_TRUE(android::base::ReadFileToString(offline_testdata_path, &testdata));
+
+ const std::string testlib_path = "testdata/" + arch + "/" + testlib_name;
+ struct stat st;
+ if (stat(testlib_path.c_str(), &st) == -1) {
+ GTEST_LOG_(INFO) << "This test is skipped as " << testlib_path << " doesn't exist.";
+ return;
+ }
+
+ // Parse offline_testdata.
+ std::vector<std::string> lines = android::base::Split(testdata, "\n");
+ int pid;
+ int tid;
+ std::vector<backtrace_map_t> maps;
+ unw_context_t unw_context;
+ backtrace_stackinfo_t stack_info;
+ std::vector<uint8_t> stack;
+ std::vector<FunctionSymbol> symbols;
+ for (const auto& line : lines) {
+ if (android::base::StartsWith(line, "pid:")) {
+ sscanf(line.c_str(), "pid: %d tid: %d", &pid, &tid);
+ } else if (android::base::StartsWith(line, "map:")) {
+ maps.resize(maps.size() + 1);
+ int pos;
+ sscanf(line.c_str(),
+ "map: start: %" SCNxPTR " end: %" SCNxPTR " offset: %" SCNxPTR
+ " load_base: %" SCNxPTR " flags: %d name: %n",
+ &maps.back().start, &maps.back().end, &maps.back().offset,
+ &maps.back().load_base, &maps.back().flags, &pos);
+ maps.back().name = android::base::Trim(line.substr(pos));
+ } else if (android::base::StartsWith(line, "registers:")) {
+ size_t size;
+ int pos;
+ sscanf(line.c_str(), "registers: %zu %n", &size, &pos);
+ ASSERT_EQ(sizeof(unw_context), size);
+ HexStringToRawData(&line[pos], &unw_context, size);
+ } else if (android::base::StartsWith(line, "stack:")) {
+ size_t size;
+ int pos;
+ sscanf(line.c_str(),
+ "stack: start: %" SCNx64 " end: %" SCNx64 " size: %zu %n",
+ &stack_info.start, &stack_info.end, &size, &pos);
+ stack.resize(size);
+ HexStringToRawData(&line[pos], &stack[0], size);
+ stack_info.data = stack.data();
+ } else if (android::base::StartsWith(line, "function:")) {
+ symbols.resize(symbols.size() + 1);
+ int pos;
+ sscanf(line.c_str(),
+ "function: start: %" SCNxPTR " end: %" SCNxPTR " name: %n",
+ &symbols.back().start, &symbols.back().end,
+ &pos);
+ symbols.back().name = line.substr(pos);
+ }
+ }
+
+ // Fix path of libbacktrace_testlib.so.
+ for (auto& map : maps) {
+ if (map.name.find("libbacktrace_test.so") != std::string::npos) {
+ map.name = testlib_path;
+ }
+ }
+
+ // Do offline backtrace.
+ std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(pid, maps));
+ ASSERT_TRUE(map != nullptr);
+
+ std::unique_ptr<Backtrace> backtrace(
+ Backtrace::CreateOffline(pid, tid, map.get(), stack_info));
+ ASSERT_TRUE(backtrace != nullptr);
+
+ ucontext_t ucontext = GetUContextFromUnwContext(unw_context);
+ ASSERT_TRUE(backtrace->Unwind(0, &ucontext));
+
+
+ // Collect pc values of the call stack frames.
std::vector<uintptr_t> pc_values;
- OfflineBacktraceFunctionCall(function, &pc_values);
- ASSERT_FALSE(pc_values.empty());
- ASSERT_LE(pc_values.size(), static_cast<size_t>(MAX_BACKTRACE_FRAMES));
+ for (size_t i = 0; i < backtrace->NumFrames(); ++i) {
+ pc_values.push_back(backtrace->GetFrame(i)->pc);
+ }
size_t test_one_index = 0;
for (size_t i = 0; i < pc_values.size(); ++i) {
- if (FunctionNameForAddress(pc_values[i]) == "test_level_one") {
+ if (FunctionNameForAddress(pc_values[i], symbols) == "test_level_one") {
test_one_index = i;
break;
}
}
ASSERT_GE(test_one_index, 3u);
- ASSERT_EQ("test_level_one", FunctionNameForAddress(pc_values[test_one_index]));
- ASSERT_EQ("test_level_two", FunctionNameForAddress(pc_values[test_one_index - 1]));
- ASSERT_EQ("test_level_three", FunctionNameForAddress(pc_values[test_one_index - 2]));
- ASSERT_EQ("test_level_four", FunctionNameForAddress(pc_values[test_one_index - 3]));
+ ASSERT_EQ("test_level_one", FunctionNameForAddress(pc_values[test_one_index], symbols));
+ ASSERT_EQ("test_level_two", FunctionNameForAddress(pc_values[test_one_index - 1], symbols));
+ ASSERT_EQ("test_level_three", FunctionNameForAddress(pc_values[test_one_index - 2], symbols));
+ ASSERT_EQ("test_level_four", FunctionNameForAddress(pc_values[test_one_index - 3], symbols));
}
-TEST(libbacktrace, offline_max_trace) {
- std::function<int(void (*)(void*), void*)> function = std::bind(
- test_recursive_call, MAX_BACKTRACE_FRAMES + 10, std::placeholders::_1, std::placeholders::_2);
- std::vector<uintptr_t> pc_values;
- OfflineBacktraceFunctionCall(function, &pc_values);
- ASSERT_FALSE(pc_values.empty());
- ASSERT_EQ(static_cast<size_t>(MAX_BACKTRACE_FRAMES), pc_values.size());
- ASSERT_EQ("test_recursive_call", FunctionNameForAddress(pc_values.back()));
+TEST(libbacktrace, offline_eh_frame) {
+ BacktraceOfflineTest("libbacktrace_test_eh_frame.so");
+}
+
+TEST(libbacktrace, offline_debug_frame) {
+ BacktraceOfflineTest("libbacktrace_test_debug_frame.so");
+}
+
+TEST(libbacktrace, offline_gnu_debugdata) {
+ BacktraceOfflineTest("libbacktrace_test_gnu_debugdata.so");
+}
+
+TEST(libbacktrace, offline_arm_exidx) {
+ BacktraceOfflineTest("libbacktrace_test_arm_exidx.so");
}
diff --git a/libbacktrace/backtrace_testlib.c b/libbacktrace/backtrace_testlib.c
index d4d15db..6f6b535 100644
--- a/libbacktrace/backtrace_testlib.c
+++ b/libbacktrace/backtrace_testlib.c
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <libunwind.h>
#include <stdio.h>
int test_level_four(int one, int two, int three, int four,
@@ -53,3 +54,23 @@
}
return 0;
}
+
+typedef struct {
+ unw_context_t* unw_context;
+ volatile int* exit_flag;
+} GetContextArg;
+
+static void GetContextAndExit(void* data) {
+ GetContextArg* arg = (GetContextArg*)data;
+ unw_getcontext(arg->unw_context);
+ // Don't touch the stack anymore.
+ while (*arg->exit_flag == 0) {
+ }
+}
+
+void test_get_context_and_wait(unw_context_t* unw_context, volatile int* exit_flag) {
+ GetContextArg arg;
+ arg.unw_context = unw_context;
+ arg.exit_flag = exit_flag;
+ test_level_one(1, 2, 3, 4, GetContextAndExit, &arg);
+}
diff --git a/libbacktrace/testdata/aarch64/libbacktrace_test_eh_frame.so b/libbacktrace/testdata/aarch64/libbacktrace_test_eh_frame.so
new file mode 100755
index 0000000..880f337
--- /dev/null
+++ b/libbacktrace/testdata/aarch64/libbacktrace_test_eh_frame.so
Binary files differ
diff --git a/libbacktrace/testdata/aarch64/offline_testdata b/libbacktrace/testdata/aarch64/offline_testdata
new file mode 100644
index 0000000..ba44e09
--- /dev/null
+++ b/libbacktrace/testdata/aarch64/offline_testdata
@@ -0,0 +1,107 @@
+pid: 32438 tid: 32439
+map: start: 557066e000 end: 55706ee000 offset: 0 load_base: 0 flags: 5 name: /data/backtrace_test64
+map: start: 55706ef000 end: 55706f2000 offset: 80000 load_base: 0 flags: 1 name: /data/backtrace_test64
+map: start: 55706f2000 end: 55706f3000 offset: 83000 load_base: 0 flags: 3 name: /data/backtrace_test64
+map: start: 7014200000 end: 7014600000 offset: 0 load_base: 0 flags: 3 name: [anon:libc_malloc]
+map: start: 701464c000 end: 701465c000 offset: 0 load_base: 0 flags: 5 name: /system/lib64/libcutils.so
+map: start: 701465c000 end: 701465d000 offset: 0 load_base: 0 flags: 0 name:
+map: start: 701465d000 end: 701465e000 offset: 10000 load_base: 0 flags: 1 name: /system/lib64/libcutils.so
+map: start: 701465e000 end: 701465f000 offset: 11000 load_base: 0 flags: 3 name: /system/lib64/libcutils.so
+map: start: 7014691000 end: 70146b5000 offset: 0 load_base: 0 flags: 5 name: /system/lib64/liblzma.so
+map: start: 70146b5000 end: 70146b6000 offset: 23000 load_base: 0 flags: 1 name: /system/lib64/liblzma.so
+map: start: 70146b6000 end: 70146b7000 offset: 24000 load_base: 0 flags: 3 name: /system/lib64/liblzma.so
+map: start: 70146b7000 end: 70146bc000 offset: 0 load_base: 0 flags: 3 name: [anon:.bss]
+map: start: 70146c9000 end: 70158b5000 offset: 0 load_base: af000 flags: 5 name: /system/lib64/libLLVM.so
+map: start: 70158b5000 end: 701596b000 offset: 11eb000 load_base: 0 flags: 1 name: /system/lib64/libLLVM.so
+map: start: 701596b000 end: 701596c000 offset: 12a1000 load_base: 0 flags: 3 name: /system/lib64/libLLVM.so
+map: start: 701596c000 end: 701599f000 offset: 0 load_base: 0 flags: 3 name: [anon:.bss]
+map: start: 70159c2000 end: 70159f9000 offset: 0 load_base: 0 flags: 5 name: /system/lib64/libm.so
+map: start: 70159f9000 end: 70159fa000 offset: 36000 load_base: 0 flags: 1 name: /system/lib64/libm.so
+map: start: 70159fa000 end: 70159fb000 offset: 37000 load_base: 0 flags: 3 name: /system/lib64/libm.so
+map: start: 7015a1e000 end: 7015a2e000 offset: 0 load_base: 0 flags: 5 name: /system/lib64/libbacktrace.so
+map: start: 7015a2e000 end: 7015a2f000 offset: f000 load_base: 0 flags: 1 name: /system/lib64/libbacktrace.so
+map: start: 7015a2f000 end: 7015a30000 offset: 10000 load_base: 0 flags: 3 name: /system/lib64/libbacktrace.so
+map: start: 7015a5e000 end: 7015a7d000 offset: 0 load_base: 1000 flags: 5 name: /system/lib64/libutils.so
+map: start: 7015a7d000 end: 7015a7e000 offset: 0 load_base: 0 flags: 0 name:
+map: start: 7015a7e000 end: 7015a7f000 offset: 1f000 load_base: 0 flags: 1 name: /system/lib64/libutils.so
+map: start: 7015a7f000 end: 7015a80000 offset: 20000 load_base: 0 flags: 3 name: /system/lib64/libutils.so
+map: start: 7015a99000 end: 7015b6d000 offset: 0 load_base: 9000 flags: 5 name: /system/lib64/libc++.so
+map: start: 7015b6d000 end: 7015b6e000 offset: 0 load_base: 0 flags: 0 name:
+map: start: 7015b6e000 end: 7015b76000 offset: d4000 load_base: 0 flags: 1 name: /system/lib64/libc++.so
+map: start: 7015b76000 end: 7015b77000 offset: dc000 load_base: 0 flags: 3 name: /system/lib64/libc++.so
+map: start: 7015b77000 end: 7015b7a000 offset: 0 load_base: 0 flags: 3 name: [anon:.bss]
+map: start: 7015b81000 end: 7015b92000 offset: 0 load_base: 0 flags: 5 name: /system/lib64/liblog.so
+map: start: 7015b92000 end: 7015b93000 offset: 10000 load_base: 0 flags: 1 name: /system/lib64/liblog.so
+map: start: 7015b93000 end: 7015b94000 offset: 11000 load_base: 0 flags: 3 name: /system/lib64/liblog.so
+map: start: 7015be3000 end: 7015ca3000 offset: 0 load_base: 0 flags: 5 name: /system/lib64/libc.so
+map: start: 7015ca3000 end: 7015ca9000 offset: bf000 load_base: 0 flags: 1 name: /system/lib64/libc.so
+map: start: 7015ca9000 end: 7015cab000 offset: c5000 load_base: 0 flags: 3 name: /system/lib64/libc.so
+map: start: 7015cab000 end: 7015cac000 offset: 0 load_base: 0 flags: 3 name: [anon:.bss]
+map: start: 7015cac000 end: 7015cad000 offset: 0 load_base: 0 flags: 1 name: [anon:.bss]
+map: start: 7015cad000 end: 7015cb4000 offset: 0 load_base: 0 flags: 3 name: [anon:.bss]
+map: start: 7015cf5000 end: 7015cf6000 offset: 0 load_base: 0 flags: 5 name: /data/libbacktrace_test.so
+map: start: 7015cf6000 end: 7015cf7000 offset: 0 load_base: 0 flags: 1 name: /data/libbacktrace_test.so
+map: start: 7015cf7000 end: 7015cf8000 offset: 1000 load_base: 0 flags: 3 name: /data/libbacktrace_test.so
+map: start: 7015d1f000 end: 7015d39000 offset: 0 load_base: 0 flags: 5 name: /system/lib64/libunwind.so
+map: start: 7015d39000 end: 7015d3a000 offset: 19000 load_base: 0 flags: 1 name: /system/lib64/libunwind.so
+map: start: 7015d3a000 end: 7015d3b000 offset: 1a000 load_base: 0 flags: 3 name: /system/lib64/libunwind.so
+map: start: 7015d3b000 end: 7015da4000 offset: 0 load_base: 0 flags: 3 name: [anon:.bss]
+map: start: 7015de8000 end: 7015df7000 offset: 0 load_base: 0 flags: 5 name: /system/lib64/libbase.so
+map: start: 7015df7000 end: 7015df8000 offset: 0 load_base: 0 flags: 0 name:
+map: start: 7015df8000 end: 7015df9000 offset: f000 load_base: 0 flags: 1 name: /system/lib64/libbase.so
+map: start: 7015df9000 end: 7015dfa000 offset: 10000 load_base: 0 flags: 3 name: /system/lib64/libbase.so
+map: start: 7015e35000 end: 7015e36000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc]
+map: start: 7015e4f000 end: 7015e50000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc_small_objects]
+map: start: 7015f11000 end: 7015f13000 offset: 0 load_base: 0 flags: 5 name: /system/lib64/libnetd_client.so
+map: start: 7015f13000 end: 7015f14000 offset: 1000 load_base: 0 flags: 1 name: /system/lib64/libnetd_client.so
+map: start: 7015f14000 end: 7015f15000 offset: 2000 load_base: 0 flags: 3 name: /system/lib64/libnetd_client.so
+map: start: 7015f6c000 end: 7015f79000 offset: 0 load_base: 0 flags: 3 name:
+map: start: 7015f79000 end: 7015f99000 offset: 0 load_base: 0 flags: 32769 name: /dev/__properties__/u:object_r:default_prop:s0
+map: start: 7015f99000 end: 7015f9a000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc_vector]
+map: start: 7015f9a000 end: 7015f9b000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc_small_objects]
+map: start: 7015fa6000 end: 7015fa7000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc_vector]
+map: start: 7015fa8000 end: 7015fa9000 offset: 0 load_base: 0 flags: 1 name: [anon:linker_alloc]
+map: start: 7015faf000 end: 7015fcf000 offset: 0 load_base: 0 flags: 32769 name: /dev/__properties__/properties_serial
+map: start: 7015fcf000 end: 7015fd0000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc_vector]
+map: start: 7015fd0000 end: 7015fd1000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc_small_objects]
+map: start: 7015fd1000 end: 7015fd2000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc_vector]
+map: start: 7015fd4000 end: 7015fd7000 offset: 0 load_base: 0 flags: 3 name:
+map: start: 7015fd7000 end: 7015fdb000 offset: 0 load_base: 0 flags: 1 name: [anon:atexit handlers]
+map: start: 7015fdb000 end: 7015fdc000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc]
+map: start: 7015fdc000 end: 7015fdd000 offset: 0 load_base: 0 flags: 3 name:
+map: start: 7015fdd000 end: 7015fde000 offset: 0 load_base: 0 flags: 1 name: [anon:linker_alloc]
+map: start: 7015fde000 end: 7015ffe000 offset: 0 load_base: 0 flags: 32769 name: /dev/__properties__/u:object_r:debug_prop:s0
+map: start: 7015ffe000 end: 701601e000 offset: 0 load_base: 0 flags: 32769 name: /dev/__properties__/properties_serial
+map: start: 701601e000 end: 701601f000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc_vector]
+map: start: 701601f000 end: 7016020000 offset: 0 load_base: 0 flags: 0 name:
+map: start: 7016020000 end: 7016021000 offset: 0 load_base: 0 flags: 3 name:
+map: start: 7016021000 end: 7016022000 offset: 0 load_base: 0 flags: 0 name:
+map: start: 7016022000 end: 7016023000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc_lob]
+map: start: 7016023000 end: 7016025000 offset: 0 load_base: 0 flags: 1 name: [anon:linker_alloc]
+map: start: 7016025000 end: 7016026000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc_small_objects]
+map: start: 7016026000 end: 7016027000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc_vector]
+map: start: 7016027000 end: 7016028000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc_small_objects]
+map: start: 7016028000 end: 7016029000 offset: 0 load_base: 0 flags: 3 name: [anon:arc4random data]
+map: start: 7016029000 end: 701602a000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc_small_objects]
+map: start: 701602a000 end: 701602b000 offset: 0 load_base: 0 flags: 1 name: [anon:atexit handlers]
+map: start: 701602b000 end: 701602c000 offset: 0 load_base: 0 flags: 0 name: [anon:thread signal stack guard page]
+map: start: 701602c000 end: 7016030000 offset: 0 load_base: 0 flags: 3 name: [anon:thread signal stack]
+map: start: 7016030000 end: 7016031000 offset: 0 load_base: 0 flags: 3 name: [anon:arc4random data]
+map: start: 7016031000 end: 7016033000 offset: 0 load_base: 0 flags: 5 name: [vdso]
+map: start: 7016033000 end: 70160dd000 offset: 0 load_base: 0 flags: 5 name: /system/bin/linker64
+map: start: 70160dd000 end: 70160e0000 offset: a9000 load_base: 0 flags: 1 name: /system/bin/linker64
+map: start: 70160e0000 end: 70160e1000 offset: ac000 load_base: 0 flags: 3 name: /system/bin/linker64
+map: start: 70160e1000 end: 70160e4000 offset: 0 load_base: 0 flags: 3 name:
+map: start: 70160e4000 end: 70160e5000 offset: 0 load_base: 0 flags: 1 name:
+map: start: 70160e5000 end: 70160e8000 offset: 0 load_base: 0 flags: 3 name:
+map: start: 7fd8baf000 end: 7fd8be6000 offset: 0 load_base: 0 flags: 3 name: [stack]
+registers: 4560 679a0b1670000000f3eb6d705500000090f56e7055000000000000000000000000206f705500000014e0677055000000d038bed87f0000004cde67705500000041000000000000001900000000000000c00f241470000000d3aec914588f4bcd0400000000000000e493af157000000090f56e7055000000060000000000000023c00b1670000000b1d1fd15700000003039bed87f000000c898041670000000304cbed87f000000b8130e1670000000303cbed87f000000f838bed87f0000000e0000000000000015000000000000001c00000000000000ec59cf1570000000b863fd15700000005064fd15700000000000000000000000ec59cf15700000000200000000000000b863fd1570000000144abed87f0000006064fd15700000005064fd157000000000010000000000005826bed87f000000d86fcf15700000006057cf157000000000000000000000005064fd15700000005064fd15700000005064fd1570000000b67e00000000000040fd677055000000d064fd15700000000030fd157000000002000000000000000100000000000000fcb58a56000000000063fd15700000009857cf1570000000c062fd15700000001c5acf157000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000003003167000000001000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000033000000000000000300000000000000003303167000000008330316700000000000000006000000f8320316700000005839bed87f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000c84cbed87f000000e84cbed87f000000984dbed87f00000078170e167000000002fd0000000000001400000000000000ff8100000100000000000000000000000000000000000000000000000000000078145700000000000010000000000000902b000000000000bdd04058000000000000000000000000bdd04058000000000000000000000000ccb58a560000000042487408000000000000000000000000cc57041670000000004704167000000010c0fd157000000010c0fd157000000090c0fd15700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000010000000000000002f48bed87f000000d3aec914588f4bcd2045bed87f0000002045bed87f0000002f48bed87f00000001000000000000002f000080000000005045bed87f0000000045bed87f000000c0a0c315700000006045bed87f0000006045bed87f000000010000000000000001000000000000000344bed87f00000001000000100000009c3fbed87f0000009b3fbed87f0000000344bed87f0000009a3fbed87f0000000100000000000000953fbed87f0000004344bed80100000001000000010000002c48bed87f0000000444bed87f0000004344bed80100000000000000000000000100000000000000b03fbed87f000000000000000200000000000000000000000000000000000000d3aec914588f4bcd000000000100000000000000000000000100000000000000f03fbed87f000000000000000200000000000000000000000000000000000000d3aec914588f4bcd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a03fbed87f0000000000000000000000000000000000000000000000000000000000000000000000d3aec914588f4bcd08226f70550000000000000000000000000000000000000000000000000000001048bed87f0000008047bed87f0000006047bed87f000000e0ffffff80ffffff03000000000000000000000000000000891d6e7055000000d3aec914588f4bcd5047bed87f0000005047bed87f000000861d6e705500000003000000000000002f00008000000000f0a6ca15700000004047bed87f000000c0a0c31570000000891d6e7055000000d3aec914000000000100000000000000a047bed800000000f9006e70550000000100000000000000dc41bed87f000000db41bed87f0000004346bed87f000000da41bed87f0000000100000000000000d541bed87f00000001000000010000000100000001000000861d6e70550000004446bed87f0000002c42bed80300000000000000000000000100000000000000f041bed87f0000009b1e6e700100000000000000000000000000000000000000d3aec914588f4bcd8e1e6e70550000000d000000000000002f00008000000000f0a6ca15700000003048bed87f000000c0a0c31570000000661e6e700100000000000000000000002f000000000000001000000000000000e21e6e7055000000d3aec914588f4bcdb048bed87f000000b048bed87f000000e21e6e70550000002f000000000000002f00008000000000f0a6ca1570000000a048bed87f000000c0a0c315700000008e1e6e7055000000000000000000000022000000000000000000000000000000205827147000000022000000000000003c43bed87f0000003b43bed87f000000a347bed87f0000003a43bed87f00000001000000000000003543bed87f000000f048bed8010000000100000001000000dd1e6e7055000000a447bed87f0000008c43bed82f000000000000000000000001000000000000005043bed87f000000861d6e700300000000000000000000000000000000000000d3aec914588f4bcd721e6e7055000000f447bed87f000000981123141800000000000000000000000100000000000000a043bed87f000000861d6e70030000000000000000000000d042bed87f0000000000000000000000981123147000000098112314700000009811231470000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000504abed87f000000b049bed87f0000008049bed87f00000000000000000000004043bed87f0000000000000000000000991123147000000000000000000000008e1e6e70550000000d00000000000000a04abed87f000000000000000000000000000000000000000000000000000000504abed87f000000e049bed87f000000a049bed87f000000c8ffffff80ffffff591e6e70550000000d0000000000000098112314700000000000000000000000df1e6e7055000000010000000000000020582714700000002200000000000000f049bed87f000000c8ffffff80ffffff9811231470000000980023147000000098112314700000009811231470000000741e6e7055000000060000000000000009f12914700000000c00000000000000b049bed87f000000b049bed87f000000b049bed87f000000b049bed87f000000b049bed87f000000b049bed87f000000b049bed87f000000b049bed87f000000b149bed87f000000b149bed87f000000f049be317f000000f049bed87f000000f049bed87f000000b149bed87f000000b049bed87f000000b049bed87f000000b049bed87f000000b049bed87f000000b049bed87f000000b049bed87f000000b049bed87f000000f149bed87f000000f049bed87f000000d3aec914588f4bcdfcb58a56000000006cbb687055000000160000000000000098112314700000009911231470000000991123147000000098112314700000009911231470000000fcb58a5600000000010000000000000000000000000000000100000000000000604a050000000000e845bed87f0000006048bed87f000000a046bed87f00000017000000000000002c48bed87f0000009046bed87f000000ac73c515700000009911231470000000d3aec914588f4bcd1048bed87f0000008047bed87f0000006047bed87f000000e8ffffff80ffffffffffffffffffffff99112314700000006148bed87f000000981123141500000008020000ffffffff6048bed87f000000160000000000000058112314700000001700000000000000a849bed87f0000000000000000000000284abed87f0000001700000000000000284abed87f000000284abed87f000000d249bed87f00000001000000000000009a112314700000001600000000000000284abed87f000000ffffffffffffffff284abed87f000000284abed87f000000284abed87f000000284abed87f0000001700000000000000ffffffffffffffff284abed87f000000284abed87f000000ff49bed87f000000284abed87f00000000000000000000000000000000000000d049bed87f000000d049bed87f000000004abed87f000000d049bed87f0000000100000000000000d049bed87f000000d049bed87f000000d049bed87f00000017000000000000000100000000000000ffffffffffffffff991123147000000001000000000000003448bed87f0000009911231470000000b0ca687055000000ffffffffffffffff010000000000000099112314700000007047bed87f000000d3aec914588f4bcdfcb58a56000000000100000000000000000000000000000050226f70550000000000000000000000b44b05000000000000102a1470000000861d6e70550000000300000000000000f0a6ca1570000000a047bed87f0000006c79c31570000000f048bed87f0000008048bed87f0000004048bed87f000000c8ffffff80ffffff0000000000000000d3aec914588f4bcdf849bed87f000000f0a6ca15700000000200000000000000085b0e1670000000e048bed87f0000002c6fc515700000009048bed87f000000d3aec914588f4bcd0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a89912314700000000000000000000000e9216f70550000008991231470000000e449bed87f0000008991231470000000000000000000000000000000000000008891231470000000899123147000000089912314700000008891231470000000170000000000000088912314700000008891231470000000d3aec914588f4bcd899123147000000016000000000000000000000000000000e9216f705500000088912314700000008891231470000000889123147000000088912314700000008891231470000000f0a6ca15700000000049bed87f0000006c79c31570000000889123147000000088912314700000008891231470000000889123147000000088912314700000008891231470000000889123147000000089912314700000008991231470000000085b0e1670000000404abed87f0000002c6fc51570000000c80a6f7055000000d3aec914588f4bcd0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a3b3325736d001b5b6d002c20776865726520002573203d202573000a526570650000000000000000000000000000000000000000000000008891231470000000000000000000000088912314700000008891231470000000889123147000000088912314700000000000000000000000889123147000000088912314700000008891231470000000470000000000000000502a1470000000d3aec914588f4bcdf05727147000000000b2221470000000604abed87f0000005c716c7055000000fcb58a56000000007c706c7055000000fcb58a5600000000ea4b050000000000
+stack: start: 7015fd3000 end: 7015fd7000 size: 16384 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f838bed87f0000004038bed87f000000b863fd1570000000b863fd1570000000b863fd1570000000ec59cf15700000001c000000150000000e000000070000003063fd15700000001c58cf1570000000b863fd1570000000ec59cf1570000000100000000c00000008000000040000006063fd15700000007c58cf1570000000b863fd1570000000ec59cf1570000000080000000600000004000000020000009063fd1570000000dc58cf1570000000b863fd1570000000ec59cf157000000004000000030000000200000001000000d063fd1570000000c459cf15700000000100000000000000144abed87f0000004038bed87f0000004038bed87f000000144abed87f000000d3aec914588f4bcd1064fd157000000074fd6770550000004038bed87f0000004038bed87f000000ec84c41570000000e484c41570000000c484c4157000000000000000000000004064fd15700000004015c01570000000b67e0000000000000000000000000000705a0e1670000000185b0e167000000000000000000000000000000000000000705a0e16700000000000000000000000b77e0000b67e000000000000550000000030fd157000000050340000000000000010000000000000000000000000000000b222147000000000102a14700000000000000000000000000000000000000040fd6770550000004038bed87f000000000000000000000000a0fa1570000000010000000000000000000000000000000000000000000000e864fd15700000005064fd1570000000000000000000000000000000000000000000000000000000d3aec914588f4bcd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+function: start: 0 end: 7015cf5760 name: unknown_start
+function: start: 7015cf5760 end: 7015cf57cc name: test_level_four
+function: start: 7015cf57cc end: 7015cf582c name: test_level_three
+function: start: 7015cf582c end: 7015cf588c name: test_level_two
+function: start: 7015cf588c end: 7015cf58ec name: test_level_one
+function: start: 7015cf58ec end: 7015cf5968 name: test_recursive_call
+function: start: 7015cf5968 end: ffffffffffffffff name: test_get_context_and_wait
+function: start: ffffffffffffffff end: ffffffffffffffff name: unknown_end
diff --git a/libbacktrace/testdata/arm/libbacktrace_test_arm_exidx.so b/libbacktrace/testdata/arm/libbacktrace_test_arm_exidx.so
new file mode 100755
index 0000000..454b032
--- /dev/null
+++ b/libbacktrace/testdata/arm/libbacktrace_test_arm_exidx.so
Binary files differ
diff --git a/libbacktrace/testdata/arm/libbacktrace_test_debug_frame.so b/libbacktrace/testdata/arm/libbacktrace_test_debug_frame.so
new file mode 100755
index 0000000..787f2cb
--- /dev/null
+++ b/libbacktrace/testdata/arm/libbacktrace_test_debug_frame.so
Binary files differ
diff --git a/libbacktrace/testdata/arm/libbacktrace_test_gnu_debugdata.so b/libbacktrace/testdata/arm/libbacktrace_test_gnu_debugdata.so
new file mode 100755
index 0000000..9340d98
--- /dev/null
+++ b/libbacktrace/testdata/arm/libbacktrace_test_gnu_debugdata.so
Binary files differ
diff --git a/libbacktrace/testdata/arm/offline_testdata b/libbacktrace/testdata/arm/offline_testdata
new file mode 100644
index 0000000..43d305a
--- /dev/null
+++ b/libbacktrace/testdata/arm/offline_testdata
@@ -0,0 +1,105 @@
+pid: 32232 tid: 32233
+map: start: aad19000 end: aad6c000 offset: 0 load_base: 0 flags: 5 name: /data/backtrace_test32
+map: start: aad6c000 end: aad6e000 offset: 52000 load_base: 0 flags: 1 name: /data/backtrace_test32
+map: start: aad6e000 end: aad6f000 offset: 54000 load_base: 0 flags: 3 name: /data/backtrace_test32
+map: start: e7380000 end: e7400000 offset: 0 load_base: 0 flags: 3 name: [anon:libc_malloc]
+map: start: e745f000 end: e7463000 offset: 0 load_base: 0 flags: 5 name: /system/lib/libnetd_client.so
+map: start: e7463000 end: e7464000 offset: 3000 load_base: 0 flags: 1 name: /system/lib/libnetd_client.so
+map: start: e7464000 end: e7465000 offset: 4000 load_base: 0 flags: 3 name: /system/lib/libnetd_client.so
+map: start: e7480000 end: e7500000 offset: 0 load_base: 0 flags: 3 name: [anon:libc_malloc]
+map: start: e7558000 end: e756c000 offset: 0 load_base: 0 flags: 5 name: /system/lib/libunwind.so
+map: start: e756c000 end: e756d000 offset: 0 load_base: 0 flags: 0 name:
+map: start: e756d000 end: e756e000 offset: 14000 load_base: 0 flags: 1 name: /system/lib/libunwind.so
+map: start: e756e000 end: e756f000 offset: 15000 load_base: 0 flags: 3 name: /system/lib/libunwind.so
+map: start: e756f000 end: e75b5000 offset: 0 load_base: 0 flags: 3 name: [anon:.bss]
+map: start: e75d4000 end: e75e1000 offset: 0 load_base: 0 flags: 5 name: /system/lib/libbase.so
+map: start: e75e1000 end: e75e2000 offset: c000 load_base: 0 flags: 1 name: /system/lib/libbase.so
+map: start: e75e2000 end: e75e3000 offset: d000 load_base: 0 flags: 3 name: /system/lib/libbase.so
+map: start: e7600000 end: e7616000 offset: 0 load_base: 0 flags: 5 name: /system/lib/liblzma.so
+map: start: e7616000 end: e7617000 offset: 15000 load_base: 0 flags: 1 name: /system/lib/liblzma.so
+map: start: e7617000 end: e7618000 offset: 16000 load_base: 0 flags: 3 name: /system/lib/liblzma.so
+map: start: e7618000 end: e761d000 offset: 0 load_base: 0 flags: 3 name: [anon:.bss]
+map: start: e7647000 end: e7656000 offset: 0 load_base: 0 flags: 5 name: /system/lib/liblog.so
+map: start: e7656000 end: e7657000 offset: e000 load_base: 0 flags: 1 name: /system/lib/liblog.so
+map: start: e7657000 end: e7658000 offset: f000 load_base: 0 flags: 3 name: /system/lib/liblog.so
+map: start: e7681000 end: e76a2000 offset: 0 load_base: 0 flags: 5 name: /system/lib/libm.so
+map: start: e76a2000 end: e76a3000 offset: 20000 load_base: 0 flags: 1 name: /system/lib/libm.so
+map: start: e76a3000 end: e76a4000 offset: 21000 load_base: 0 flags: 3 name: /system/lib/libm.so
+map: start: e76eb000 end: e76ee000 offset: 0 load_base: 0 flags: 5 name: /data/libbacktrace_test.so
+map: start: e76ee000 end: e76ef000 offset: 2000 load_base: 0 flags: 1 name: /data/libbacktrace_test.so
+map: start: e76ef000 end: e76f0000 offset: 3000 load_base: 0 flags: 3 name: /data/libbacktrace_test.so
+map: start: e7712000 end: e771f000 offset: 0 load_base: 0 flags: 5 name: /system/lib/libbacktrace.so
+map: start: e771f000 end: e7720000 offset: 0 load_base: 0 flags: 0 name:
+map: start: e7720000 end: e7721000 offset: d000 load_base: 0 flags: 1 name: /system/lib/libbacktrace.so
+map: start: e7721000 end: e7722000 offset: e000 load_base: 0 flags: 3 name: /system/lib/libbacktrace.so
+map: start: e7761000 end: e7778000 offset: 0 load_base: 0 flags: 5 name: /system/lib/libutils.so
+map: start: e7778000 end: e7779000 offset: 16000 load_base: 0 flags: 1 name: /system/lib/libutils.so
+map: start: e7779000 end: e777a000 offset: 17000 load_base: 0 flags: 3 name: /system/lib/libutils.so
+map: start: e77a5000 end: e782d000 offset: 0 load_base: 0 flags: 5 name: /system/lib/libc.so
+map: start: e782d000 end: e7831000 offset: 87000 load_base: 0 flags: 1 name: /system/lib/libc.so
+map: start: e7831000 end: e7833000 offset: 8b000 load_base: 0 flags: 3 name: /system/lib/libc.so
+map: start: e7833000 end: e7834000 offset: 0 load_base: 0 flags: 3 name: [anon:.bss]
+map: start: e7834000 end: e7835000 offset: 0 load_base: 0 flags: 1 name: [anon:.bss]
+map: start: e7835000 end: e783b000 offset: 0 load_base: 0 flags: 3 name: [anon:.bss]
+map: start: e7845000 end: e8437000 offset: 0 load_base: 2b000 flags: 5 name: /system/lib/libLLVM.so
+map: start: e8437000 end: e8438000 offset: 0 load_base: 0 flags: 0 name:
+map: start: e8438000 end: e848a000 offset: bf2000 load_base: 0 flags: 1 name: /system/lib/libLLVM.so
+map: start: e848a000 end: e848b000 offset: c44000 load_base: 0 flags: 3 name: /system/lib/libLLVM.so
+map: start: e848b000 end: e84a1000 offset: 0 load_base: 0 flags: 3 name: [anon:.bss]
+map: start: e84eb000 end: e84f7000 offset: 0 load_base: 0 flags: 5 name: /system/lib/libcutils.so
+map: start: e84f7000 end: e84f8000 offset: 0 load_base: 0 flags: 0 name:
+map: start: e84f8000 end: e84f9000 offset: c000 load_base: 0 flags: 1 name: /system/lib/libcutils.so
+map: start: e84f9000 end: e84fa000 offset: d000 load_base: 0 flags: 3 name: /system/lib/libcutils.so
+map: start: e852e000 end: e85b3000 offset: 0 load_base: 2000 flags: 5 name: /system/lib/libc++.so
+map: start: e85b3000 end: e85b4000 offset: 0 load_base: 0 flags: 0 name:
+map: start: e85b4000 end: e85b8000 offset: 85000 load_base: 0 flags: 1 name: /system/lib/libc++.so
+map: start: e85b8000 end: e85b9000 offset: 89000 load_base: 0 flags: 3 name: /system/lib/libc++.so
+map: start: e85b9000 end: e85ba000 offset: 0 load_base: 0 flags: 3 name: [anon:.bss]
+map: start: e85ce000 end: e85cf000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc]
+map: start: e85e4000 end: e85e5000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc_small_objects]
+map: start: e8607000 end: e8608000 offset: 0 load_base: 0 flags: 1 name: [anon:linker_alloc]
+map: start: e8680000 end: e8700000 offset: 0 load_base: 0 flags: 3 name: [anon:libc_malloc]
+map: start: e870d000 end: e8719000 offset: 0 load_base: 0 flags: 3 name:
+map: start: e8719000 end: e871b000 offset: 0 load_base: 0 flags: 1 name: [anon:atexit handlers]
+map: start: e871b000 end: e873b000 offset: 0 load_base: 0 flags: 32769 name: /dev/__properties__/u:object_r:default_prop:s0
+map: start: e873b000 end: e875b000 offset: 0 load_base: 0 flags: 32769 name: /dev/__properties__/properties_serial
+map: start: e875b000 end: e875c000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc_vector]
+map: start: e875c000 end: e875d000 offset: 0 load_base: 0 flags: 3 name: [anon:arc4random data]
+map: start: e875d000 end: e875e000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc]
+map: start: e875e000 end: e875f000 offset: 0 load_base: 0 flags: 1 name: [anon:linker_alloc]
+map: start: e875f000 end: e877f000 offset: 0 load_base: 0 flags: 32769 name: /dev/__properties__/u:object_r:debug_prop:s0
+map: start: e877f000 end: e879f000 offset: 0 load_base: 0 flags: 32769 name: /dev/__properties__/properties_serial
+map: start: e879f000 end: e87a0000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc_vector]
+map: start: e87a0000 end: e87a1000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc_small_objects]
+map: start: e87a1000 end: e87a2000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc_vector]
+map: start: e87a2000 end: e87a3000 offset: 0 load_base: 0 flags: 0 name:
+map: start: e87a3000 end: e87a4000 offset: 0 load_base: 0 flags: 3 name:
+map: start: e87a4000 end: e87a5000 offset: 0 load_base: 0 flags: 0 name:
+map: start: e87a5000 end: e87a6000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc_lob]
+map: start: e87a6000 end: e87a7000 offset: 0 load_base: 0 flags: 1 name: [anon:linker_alloc]
+map: start: e87a7000 end: e87a8000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc_vector]
+map: start: e87a8000 end: e87a9000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc_small_objects]
+map: start: e87a9000 end: e87aa000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc_vector]
+map: start: e87aa000 end: e87ab000 offset: 0 load_base: 0 flags: 3 name: [anon:linker_alloc_small_objects]
+map: start: e87ab000 end: e87ac000 offset: 0 load_base: 0 flags: 1 name: [anon:atexit handlers]
+map: start: e87ac000 end: e87ad000 offset: 0 load_base: 0 flags: 0 name: [anon:thread signal stack guard page]
+map: start: e87ad000 end: e87af000 offset: 0 load_base: 0 flags: 3 name: [anon:thread signal stack]
+map: start: e87af000 end: e87b0000 offset: 0 load_base: 0 flags: 3 name: [anon:arc4random data]
+map: start: e87b0000 end: e880d000 offset: 0 load_base: 0 flags: 5 name: /system/bin/linker
+map: start: e880d000 end: e880f000 offset: 5c000 load_base: 0 flags: 1 name: /system/bin/linker
+map: start: e880f000 end: e8810000 offset: 5e000 load_base: 0 flags: 3 name: /system/bin/linker
+map: start: e8810000 end: e8812000 offset: 0 load_base: 0 flags: 3 name:
+map: start: e8812000 end: e8813000 offset: 0 load_base: 0 flags: 1 name:
+map: start: e8813000 end: e8815000 offset: 0 load_base: 0 flags: 3 name:
+map: start: ff886000 end: ff8a9000 offset: 0 load_base: 0 flags: 3 name: [stack]
+map: start: ffff0000 end: ffff1000 offset: 0 load_base: 0 flags: 5 name: [vectors]
+registers: 64 34868affdc8871e8150000001c0000001c000000150000000e00000007000000e08771e834868aff2354d2aa24f9ffffdc8871e88c8771e875b86ee778ba6ee7
+stack: start: e8715000 end: e8719000 size: 16384 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dc8871e87dba6ee734868affdc8871e8dc8871e85dba6ee7070000000e000000150000001c000000dc8871e85dba6ee71c000000150000000e00000007000000100000000c0000000800000004000000ddb86ee75dba6ee7dc8871e804000000080000000c00000010000000dc8871e85dba6ee7100000000c000000080000000400000008000000060000000400000002000000288871e835b96ee75dba6ee7dc8871e802000000040000000600000008000000dc8871e85dba6ee70800000006000000040000000200000004000000030000000200000001000000708871e88db96ee75dba6ee7dc8871e801000000020000000300000004000000dc8871e85dba6ee70400000003000000020000000100000004000000208971e8208971e878000000e87d00003dba6ee75dba6ee7dc8871e878000000c5807ce7fc7183e734868aff78868aff78868aff34868aff34868aff78868affe0879437208971e84154d2aa0020000034868aff34868aff34868aff78000000c9b87ee7b1b87ee7a3f47be7288971e8b1b87ee7208971e800000000f83481e800000000e97d0000e87d000000000000005071e82039000000100000000000000000000000000000000000002354d2aa34868aff00000000002071e801000000000000000000000000000000708971e8208971e8000000000000000000000000e0879437000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+function: start: 0 end: e76eb835 name: unknown_start
+function: start: e76eb835 end: e76eb88d name: test_level_four
+function: start: e76eb88d end: e76eb8e5 name: test_level_three
+function: start: e76eb8e5 end: e76eb93d name: test_level_two
+function: start: e76eb93d end: e76eb995 name: test_level_one
+function: start: e76eb995 end: e76eb9f1 name: test_recursive_call
+function: start: e76eb9f1 end: ffffffff name: test_get_context_and_wait
+function: start: ffffffff end: ffffffff name: unknown_end
diff --git a/libbacktrace/testdata/x86/libbacktrace_test_debug_frame.so b/libbacktrace/testdata/x86/libbacktrace_test_debug_frame.so
new file mode 100755
index 0000000..a6f3b29
--- /dev/null
+++ b/libbacktrace/testdata/x86/libbacktrace_test_debug_frame.so
Binary files differ
diff --git a/libbacktrace/testdata/x86/libbacktrace_test_gnu_debugdata.so b/libbacktrace/testdata/x86/libbacktrace_test_gnu_debugdata.so
new file mode 100755
index 0000000..ea58dfb
--- /dev/null
+++ b/libbacktrace/testdata/x86/libbacktrace_test_gnu_debugdata.so
Binary files differ
diff --git a/libbacktrace/testdata/x86/offline_testdata b/libbacktrace/testdata/x86/offline_testdata
new file mode 100644
index 0000000..3e4e06c
--- /dev/null
+++ b/libbacktrace/testdata/x86/offline_testdata
@@ -0,0 +1,82 @@
+pid: 34545 tid: 34546
+map: start: f705a000 end: f705c000 offset: 0 load_base: 0 flags: 3 name:
+map: start: f705c000 end: f707f000 offset: 0 load_base: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib/liblzma.so
+map: start: f707f000 end: f7080000 offset: 22000 load_base: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib/liblzma.so
+map: start: f7080000 end: f7081000 offset: 23000 load_base: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib/liblzma.so
+map: start: f7081000 end: f7088000 offset: 0 load_base: 0 flags: 3 name:
+map: start: f7088000 end: f7230000 offset: 0 load_base: 0 flags: 5 name: /lib/i386-linux-gnu/libc-2.19.so
+map: start: f7230000 end: f7231000 offset: 1a8000 load_base: 0 flags: 0 name: /lib/i386-linux-gnu/libc-2.19.so
+map: start: f7231000 end: f7233000 offset: 1a8000 load_base: 0 flags: 1 name: /lib/i386-linux-gnu/libc-2.19.so
+map: start: f7233000 end: f7234000 offset: 1aa000 load_base: 0 flags: 3 name: /lib/i386-linux-gnu/libc-2.19.so
+map: start: f7234000 end: f7237000 offset: 0 load_base: 0 flags: 3 name:
+map: start: f7237000 end: f727b000 offset: 0 load_base: 0 flags: 5 name: /lib/i386-linux-gnu/libm-2.19.so
+map: start: f727b000 end: f727c000 offset: 43000 load_base: 0 flags: 1 name: /lib/i386-linux-gnu/libm-2.19.so
+map: start: f727c000 end: f727d000 offset: 44000 load_base: 0 flags: 3 name: /lib/i386-linux-gnu/libm-2.19.so
+map: start: f727d000 end: f7299000 offset: 0 load_base: 0 flags: 5 name: /lib/i386-linux-gnu/libgcc_s.so.1
+map: start: f7299000 end: f729a000 offset: 1b000 load_base: 0 flags: 3 name: /lib/i386-linux-gnu/libgcc_s.so.1
+map: start: f729a000 end: f72b8000 offset: 0 load_base: 0 flags: 5 name: /lib/i386-linux-gnu/libtinfo.so.5.9
+map: start: f72b8000 end: f72b9000 offset: 1e000 load_base: 0 flags: 0 name: /lib/i386-linux-gnu/libtinfo.so.5.9
+map: start: f72b9000 end: f72bb000 offset: 1e000 load_base: 0 flags: 1 name: /lib/i386-linux-gnu/libtinfo.so.5.9
+map: start: f72bb000 end: f72bc000 offset: 20000 load_base: 0 flags: 3 name: /lib/i386-linux-gnu/libtinfo.so.5.9
+map: start: f72bc000 end: f72bd000 offset: 0 load_base: 0 flags: 3 name:
+map: start: f72bd000 end: f72e0000 offset: 0 load_base: 0 flags: 5 name: /lib/i386-linux-gnu/libncurses.so.5.9
+map: start: f72e0000 end: f72e1000 offset: 22000 load_base: 0 flags: 1 name: /lib/i386-linux-gnu/libncurses.so.5.9
+map: start: f72e1000 end: f72e2000 offset: 23000 load_base: 0 flags: 3 name: /lib/i386-linux-gnu/libncurses.so.5.9
+map: start: f72e2000 end: f72e5000 offset: 0 load_base: 0 flags: 5 name: /lib/i386-linux-gnu/libdl-2.19.so
+map: start: f72e5000 end: f72e6000 offset: 2000 load_base: 0 flags: 1 name: /lib/i386-linux-gnu/libdl-2.19.so
+map: start: f72e6000 end: f72e7000 offset: 3000 load_base: 0 flags: 3 name: /lib/i386-linux-gnu/libdl-2.19.so
+map: start: f72e7000 end: f72ee000 offset: 0 load_base: 0 flags: 5 name: /lib/i386-linux-gnu/librt-2.19.so
+map: start: f72ee000 end: f72ef000 offset: 6000 load_base: 0 flags: 1 name: /lib/i386-linux-gnu/librt-2.19.so
+map: start: f72ef000 end: f72f0000 offset: 7000 load_base: 0 flags: 3 name: /lib/i386-linux-gnu/librt-2.19.so
+map: start: f72f0000 end: f7308000 offset: 0 load_base: 0 flags: 5 name: /lib/i386-linux-gnu/libpthread-2.19.so
+map: start: f7308000 end: f7309000 offset: 18000 load_base: 0 flags: 1 name: /lib/i386-linux-gnu/libpthread-2.19.so
+map: start: f7309000 end: f730a000 offset: 19000 load_base: 0 flags: 3 name: /lib/i386-linux-gnu/libpthread-2.19.so
+map: start: f730a000 end: f730c000 offset: 0 load_base: 0 flags: 3 name:
+map: start: f732f000 end: f7331000 offset: 0 load_base: 0 flags: 3 name:
+map: start: f7331000 end: f7425000 offset: 0 load_base: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libc++.so
+map: start: f7425000 end: f7426000 offset: f4000 load_base: 0 flags: 0 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libc++.so
+map: start: f7426000 end: f742a000 offset: f4000 load_base: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libc++.so
+map: start: f742a000 end: f742b000 offset: f8000 load_base: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libc++.so
+map: start: f742b000 end: f742d000 offset: 0 load_base: 0 flags: 3 name:
+map: start: f742d000 end: f7446000 offset: 0 load_base: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libunwind.so
+map: start: f7446000 end: f7447000 offset: 18000 load_base: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libunwind.so
+map: start: f7447000 end: f7448000 offset: 19000 load_base: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libunwind.so
+map: start: f7448000 end: f7457000 offset: 0 load_base: 0 flags: 3 name:
+map: start: f7457000 end: f745c000 offset: 0 load_base: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib/liblog.so
+map: start: f745c000 end: f745d000 offset: 4000 load_base: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib/liblog.so
+map: start: f745d000 end: f745e000 offset: 5000 load_base: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib/liblog.so
+map: start: f745e000 end: f7467000 offset: 0 load_base: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libcutils.so
+map: start: f7467000 end: f7468000 offset: 9000 load_base: 0 flags: 0 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libcutils.so
+map: start: f7468000 end: f7469000 offset: 9000 load_base: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libcutils.so
+map: start: f7469000 end: f746a000 offset: a000 load_base: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libcutils.so
+map: start: f746a000 end: f7477000 offset: 0 load_base: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbase.so
+map: start: f7477000 end: f7478000 offset: c000 load_base: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbase.so
+map: start: f7478000 end: f7479000 offset: d000 load_base: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbase.so
+map: start: f7479000 end: f7489000 offset: 0 load_base: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbacktrace.so
+map: start: f7489000 end: f748a000 offset: f000 load_base: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbacktrace.so
+map: start: f748a000 end: f748b000 offset: 10000 load_base: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbacktrace.so
+map: start: f748b000 end: f748c000 offset: 0 load_base: 0 flags: 3 name:
+map: start: f748c000 end: f748d000 offset: 0 load_base: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbacktrace_test.so
+map: start: f748d000 end: f748e000 offset: 0 load_base: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbacktrace_test.so
+map: start: f748e000 end: f748f000 offset: 1000 load_base: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib/libbacktrace_test.so
+map: start: f748f000 end: f7491000 offset: 0 load_base: 0 flags: 3 name:
+map: start: f7491000 end: f74b1000 offset: 0 load_base: 0 flags: 5 name: /lib/i386-linux-gnu/ld-2.19.so
+map: start: f74b1000 end: f74b2000 offset: 1f000 load_base: 0 flags: 1 name: /lib/i386-linux-gnu/ld-2.19.so
+map: start: f74b2000 end: f74b3000 offset: 20000 load_base: 0 flags: 3 name: /lib/i386-linux-gnu/ld-2.19.so
+map: start: f74b3000 end: f77c6000 offset: 0 load_base: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/nativetest/backtrace_test/backtrace_test32
+map: start: f77c6000 end: f77c7000 offset: 0 load_base: ffffe000 flags: 5 name: [vdso]
+map: start: f77c7000 end: f77d4000 offset: 313000 load_base: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/nativetest/backtrace_test/backtrace_test32
+map: start: f77d4000 end: f77d5000 offset: 320000 load_base: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/nativetest/backtrace_test/backtrace_test32
+map: start: f77d5000 end: f77d6000 offset: 0 load_base: 0 flags: 3 name:
+map: start: f7ec6000 end: f7ee7000 offset: 0 load_base: 0 flags: 3 name: [heap]
+map: start: ffe4e000 end: ffe70000 offset: 0 load_base: 0 flags: 3 name: [stack]
+registers: 348 00000000abdae6fff83b7df704000000a6ec77f7abdae6ff00000000afdae6ff78dae6ff150000001c000000b8f132f7a0f132f7d0df48f7a0ca48f728d9e6ff000000008c8decf78c8decf7ceca48f7a8dae6ff8d8decf70a0000000000000014dae6ff8c8decf78c8decf78c8decf78c8decf78c8decf7a9dae6ff06000000c03a23f78c8decf78c8decf78c8decf78c8decf78c8decf78c8decf78c8decf78d8decf78d8decf7c03a23f7543b23f7000033f75f5f0ff7c03a23f7503423f77000000098000000020000000f2700006c0000000e00000080000000000000008c8decf7000000008c8decf77f03ffff0000ffffffffffff0000000000000000000000000000ffff040000000f27000008000000003023f78d8decf7f069ec000046bdaa308decf715537df7f83b7df78c8decf74c1c71f78c8decf715537df70000000000000000f069ecf7f83b7df75064ecf792e671f7f069ecf7
+stack: start: f732c000 end: f7330000 size: 16384 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009d9d49f761b009f71e382ff7000000000000000000000000000000000000000002000000f6372ff704c82bf70000000000204bf7f0a908f7ceca48f728d9e6fff4a449f70000000020f332f720f332f7d0df48f7f8f132f794c748f720f332f70c144205978142a8d4be08f7d0df48f720f332f7a0ca48f71c000000150000000e000000070000001c000000a0ca48f7d0df48f748f232f739c848f7070000000e000000150000001c000000a0ca48f720f332f70000000000000000d0df48f720f332f7a0ca48f7100000000c000000080000000400000010000000a0ca48f7d0df48f798f232f7c9c848f704000000080000000c00000010000000a0ca48f720f332f70000000000000000d0df48f720f332f7a0ca48f70800000006000000040000000200000008000000a0ca48f7d0df48f7e8f232f759c948f702000000040000000600000008000000a0ca48f720f332f70000000000000000d0df48f720f332f7a0ca48f7040000000300000002000000010000000046bdaa00000000d0df48f738f332f77cca48f701000000020000000300000004000000a0ca48f720f332f700000000f83b7df7696d4df7d0df48f788dae6ff28d9e6ff28d9e6ff88dae6ff58f332f70046bdaa40fb32f7f83b7df758f332f78d6d4df728d9e6ff88dae6fff83b7df728d9e6ff28d9e6ff009030f728f432f7726f2ff728d9e6ff40fb32f740fb32f740fb32f790f332f700000000000000000000000000000000000000000000000000000000009030f740fb32f7000f3d0028f432f703b12c75032f144e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a06e2ff700000000000f3d00000000008e3f17f740fb32f7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a03823f7c4fd32f700000000e0341df7e02e1df7e03d1df70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040fb32f7188eecf740fb32f70100000030647cf70046bdaa28658876000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060a705f7a4b130f7f2860000f1860000b0fb32f7ecffffff000000000000000090f332f7000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ccfb32f70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000c2638cfa7f3e1d0000000000000000000000000000000000406d4df728d9e6ff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c032f7004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+function: start: 0 end: f748c740 name: unknown_start
+function: start: f748c740 end: f748c7c0 name: test_level_four
+function: start: f748c7c0 end: f748c850 name: test_level_three
+function: start: f748c850 end: f748c8e0 name: test_level_two
+function: start: f748c8e0 end: f748c970 name: test_level_one
+function: start: f748c970 end: f748ca10 name: test_recursive_call
+function: start: f748ca10 end: ffffffff name: test_get_context_and_wait
+function: start: ffffffff end: ffffffff name: unknown_end
diff --git a/libbacktrace/testdata/x86_64/libbacktrace_test_eh_frame.so b/libbacktrace/testdata/x86_64/libbacktrace_test_eh_frame.so
new file mode 100755
index 0000000..f116658
--- /dev/null
+++ b/libbacktrace/testdata/x86_64/libbacktrace_test_eh_frame.so
Binary files differ
diff --git a/libbacktrace/testdata/x86_64/offline_testdata b/libbacktrace/testdata/x86_64/offline_testdata
new file mode 100644
index 0000000..baf6450
--- /dev/null
+++ b/libbacktrace/testdata/x86_64/offline_testdata
@@ -0,0 +1,93 @@
+pid: 25683 tid: 25692
+map: start: 7fd5aa784000 end: 7fd5aa93e000 offset: 0 load_base: 0 flags: 5 name: /lib/x86_64-linux-gnu/libc-2.19.so
+map: start: 7fd5aa93e000 end: 7fd5aab3e000 offset: 1ba000 load_base: 0 flags: 0 name: /lib/x86_64-linux-gnu/libc-2.19.so
+map: start: 7fd5aab3e000 end: 7fd5aab42000 offset: 1ba000 load_base: 0 flags: 1 name: /lib/x86_64-linux-gnu/libc-2.19.so
+map: start: 7fd5aab42000 end: 7fd5aab44000 offset: 1be000 load_base: 0 flags: 3 name: /lib/x86_64-linux-gnu/libc-2.19.so
+map: start: 7fd5aab44000 end: 7fd5aab49000 offset: 0 load_base: 0 flags: 3 name:
+map: start: 7fd5aab49000 end: 7fd5aac4e000 offset: 0 load_base: 0 flags: 5 name: /lib/x86_64-linux-gnu/libm-2.19.so
+map: start: 7fd5aac4e000 end: 7fd5aae4d000 offset: 105000 load_base: 0 flags: 0 name: /lib/x86_64-linux-gnu/libm-2.19.so
+map: start: 7fd5aae4d000 end: 7fd5aae4e000 offset: 104000 load_base: 0 flags: 1 name: /lib/x86_64-linux-gnu/libm-2.19.so
+map: start: 7fd5aae4e000 end: 7fd5aae4f000 offset: 105000 load_base: 0 flags: 3 name: /lib/x86_64-linux-gnu/libm-2.19.so
+map: start: 7fd5aae4f000 end: 7fd5aae65000 offset: 0 load_base: 0 flags: 5 name: /lib/x86_64-linux-gnu/libgcc_s.so.1
+map: start: 7fd5aae65000 end: 7fd5ab064000 offset: 16000 load_base: 0 flags: 0 name: /lib/x86_64-linux-gnu/libgcc_s.so.1
+map: start: 7fd5ab064000 end: 7fd5ab065000 offset: 15000 load_base: 0 flags: 3 name: /lib/x86_64-linux-gnu/libgcc_s.so.1
+map: start: 7fd5ab065000 end: 7fd5ab08a000 offset: 0 load_base: 0 flags: 5 name: /lib/x86_64-linux-gnu/libtinfo.so.5.9
+map: start: 7fd5ab08a000 end: 7fd5ab289000 offset: 25000 load_base: 0 flags: 0 name: /lib/x86_64-linux-gnu/libtinfo.so.5.9
+map: start: 7fd5ab289000 end: 7fd5ab28d000 offset: 24000 load_base: 0 flags: 1 name: /lib/x86_64-linux-gnu/libtinfo.so.5.9
+map: start: 7fd5ab28d000 end: 7fd5ab28e000 offset: 28000 load_base: 0 flags: 3 name: /lib/x86_64-linux-gnu/libtinfo.so.5.9
+map: start: 7fd5ab28e000 end: 7fd5ab2b0000 offset: 0 load_base: 0 flags: 5 name: /lib/x86_64-linux-gnu/libncurses.so.5.9
+map: start: 7fd5ab2b0000 end: 7fd5ab4af000 offset: 22000 load_base: 0 flags: 0 name: /lib/x86_64-linux-gnu/libncurses.so.5.9
+map: start: 7fd5ab4af000 end: 7fd5ab4b0000 offset: 21000 load_base: 0 flags: 1 name: /lib/x86_64-linux-gnu/libncurses.so.5.9
+map: start: 7fd5ab4b0000 end: 7fd5ab4b1000 offset: 22000 load_base: 0 flags: 3 name: /lib/x86_64-linux-gnu/libncurses.so.5.9
+map: start: 7fd5ab4b1000 end: 7fd5ab4b4000 offset: 0 load_base: 0 flags: 5 name: /lib/x86_64-linux-gnu/libdl-2.19.so
+map: start: 7fd5ab4b4000 end: 7fd5ab6b3000 offset: 3000 load_base: 0 flags: 0 name: /lib/x86_64-linux-gnu/libdl-2.19.so
+map: start: 7fd5ab6b3000 end: 7fd5ab6b4000 offset: 2000 load_base: 0 flags: 1 name: /lib/x86_64-linux-gnu/libdl-2.19.so
+map: start: 7fd5ab6b4000 end: 7fd5ab6b5000 offset: 3000 load_base: 0 flags: 3 name: /lib/x86_64-linux-gnu/libdl-2.19.so
+map: start: 7fd5ab6b5000 end: 7fd5ab6bc000 offset: 0 load_base: 0 flags: 5 name: /lib/x86_64-linux-gnu/librt-2.19.so
+map: start: 7fd5ab6bc000 end: 7fd5ab8bb000 offset: 7000 load_base: 0 flags: 0 name: /lib/x86_64-linux-gnu/librt-2.19.so
+map: start: 7fd5ab8bb000 end: 7fd5ab8bc000 offset: 6000 load_base: 0 flags: 1 name: /lib/x86_64-linux-gnu/librt-2.19.so
+map: start: 7fd5ab8bc000 end: 7fd5ab8bd000 offset: 7000 load_base: 0 flags: 3 name: /lib/x86_64-linux-gnu/librt-2.19.so
+map: start: 7fd5ab8bd000 end: 7fd5ab8d6000 offset: 0 load_base: 0 flags: 5 name: /lib/x86_64-linux-gnu/libpthread-2.19.so
+map: start: 7fd5ab8d6000 end: 7fd5abad5000 offset: 19000 load_base: 0 flags: 0 name: /lib/x86_64-linux-gnu/libpthread-2.19.so
+map: start: 7fd5abad5000 end: 7fd5abad6000 offset: 18000 load_base: 0 flags: 1 name: /lib/x86_64-linux-gnu/libpthread-2.19.so
+map: start: 7fd5abad6000 end: 7fd5abad7000 offset: 19000 load_base: 0 flags: 3 name: /lib/x86_64-linux-gnu/libpthread-2.19.so
+map: start: 7fd5abad7000 end: 7fd5abadb000 offset: 0 load_base: 0 flags: 3 name:
+map: start: 7fd5abadb000 end: 7fd5abafe000 offset: 0 load_base: 0 flags: 5 name: /lib/x86_64-linux-gnu/ld-2.19.so
+map: start: 7fd5abb17000 end: 7fd5abb1a000 offset: 0 load_base: 0 flags: 3 name:
+map: start: 7fd5abb1a000 end: 7fd5abb40000 offset: 0 load_base: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/liblzma.so
+map: start: 7fd5abb40000 end: 7fd5abb41000 offset: 25000 load_base: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/liblzma.so
+map: start: 7fd5abb41000 end: 7fd5abb42000 offset: 26000 load_base: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/liblzma.so
+map: start: 7fd5abb42000 end: 7fd5abb4b000 offset: 0 load_base: 0 flags: 3 name:
+map: start: 7fd5abb6a000 end: 7fd5abb70000 offset: 0 load_base: 0 flags: 3 name:
+map: start: 7fd5abb70000 end: 7fd5abc62000 offset: 0 load_base: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libc++.so
+map: start: 7fd5abc62000 end: 7fd5abc63000 offset: f2000 load_base: 0 flags: 0 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libc++.so
+map: start: 7fd5abc63000 end: 7fd5abc6b000 offset: f2000 load_base: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libc++.so
+map: start: 7fd5abc6b000 end: 7fd5abc6c000 offset: fa000 load_base: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libc++.so
+map: start: 7fd5abc6c000 end: 7fd5abc70000 offset: 0 load_base: 0 flags: 3 name:
+map: start: 7fd5abc70000 end: 7fd5abc8d000 offset: 0 load_base: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libunwind.so
+map: start: 7fd5abc8d000 end: 7fd5abc8e000 offset: 1c000 load_base: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libunwind.so
+map: start: 7fd5abc8e000 end: 7fd5abc8f000 offset: 1d000 load_base: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libunwind.so
+map: start: 7fd5abc8f000 end: 7fd5abcb8000 offset: 0 load_base: 0 flags: 3 name:
+map: start: 7fd5abcb8000 end: 7fd5abcbe000 offset: 0 load_base: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/liblog.so
+map: start: 7fd5abcbe000 end: 7fd5abcbf000 offset: 6000 load_base: 0 flags: 0 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/liblog.so
+map: start: 7fd5abcbf000 end: 7fd5abcc0000 offset: 6000 load_base: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/liblog.so
+map: start: 7fd5abcc0000 end: 7fd5abcc1000 offset: 7000 load_base: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/liblog.so
+map: start: 7fd5abcc1000 end: 7fd5abcc2000 offset: 0 load_base: 0 flags: 3 name:
+map: start: 7fd5abcc2000 end: 7fd5abccd000 offset: 0 load_base: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libcutils.so
+map: start: 7fd5abccd000 end: 7fd5abcce000 offset: b000 load_base: 0 flags: 0 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libcutils.so
+map: start: 7fd5abcce000 end: 7fd5abccf000 offset: b000 load_base: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libcutils.so
+map: start: 7fd5abccf000 end: 7fd5abcd0000 offset: c000 load_base: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libcutils.so
+map: start: 7fd5abcd0000 end: 7fd5abcdf000 offset: 0 load_base: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbase.so
+map: start: 7fd5abcdf000 end: 7fd5abce0000 offset: f000 load_base: 0 flags: 0 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbase.so
+map: start: 7fd5abce0000 end: 7fd5abce1000 offset: f000 load_base: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbase.so
+map: start: 7fd5abce1000 end: 7fd5abce2000 offset: 10000 load_base: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbase.so
+map: start: 7fd5abce2000 end: 7fd5abcf5000 offset: 0 load_base: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbacktrace.so
+map: start: 7fd5abcf5000 end: 7fd5abcf6000 offset: 12000 load_base: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbacktrace.so
+map: start: 7fd5abcf6000 end: 7fd5abcf7000 offset: 13000 load_base: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbacktrace.so
+map: start: 7fd5abcf7000 end: 7fd5abcf8000 offset: 0 load_base: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbacktrace_test.so
+map: start: 7fd5abcf8000 end: 7fd5abcf9000 offset: 1000 load_base: 0 flags: 0 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbacktrace_test.so
+map: start: 7fd5abcf9000 end: 7fd5abcfa000 offset: 1000 load_base: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbacktrace_test.so
+map: start: 7fd5abcfa000 end: 7fd5abcfb000 offset: 2000 load_base: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/lib64/libbacktrace_test.so
+map: start: 7fd5abcfb000 end: 7fd5abcfd000 offset: 0 load_base: 0 flags: 3 name:
+map: start: 7fd5abcfd000 end: 7fd5abcfe000 offset: 22000 load_base: 0 flags: 1 name: /lib/x86_64-linux-gnu/ld-2.19.so
+map: start: 7fd5abcfe000 end: 7fd5abcff000 offset: 23000 load_base: 0 flags: 3 name: /lib/x86_64-linux-gnu/ld-2.19.so
+map: start: 7fd5abcff000 end: 7fd5abd00000 offset: 0 load_base: 0 flags: 3 name:
+map: start: 7fd5abd00000 end: 7fd5ac053000 offset: 0 load_base: 0 flags: 5 name: /ssd/android/aosp_master/out/host/linux-x86/nativetest64/backtrace_test/backtrace_test64
+map: start: 7fd5ac053000 end: 7fd5ac054000 offset: 0 load_base: 0 flags: 3 name:
+map: start: 7fd5ac054000 end: 7fd5ac06f000 offset: 353000 load_base: 0 flags: 1 name: /ssd/android/aosp_master/out/host/linux-x86/nativetest64/backtrace_test/backtrace_test64
+map: start: 7fd5ac06f000 end: 7fd5ac070000 offset: 36e000 load_base: 0 flags: 3 name: /ssd/android/aosp_master/out/host/linux-x86/nativetest64/backtrace_test/backtrace_test64
+map: start: 7fd5ac070000 end: 7fd5ac071000 offset: 0 load_base: 0 flags: 3 name:
+map: start: 7fd5ad54e000 end: 7fd5ad56f000 offset: 0 load_base: 0 flags: 3 name: [heap]
+map: start: 7ffcf47ed000 end: 7ffcf480f000 offset: 0 load_base: 0 flags: 3 name: [stack]
+map: start: 7ffcf48d5000 end: 7ffcf48d7000 offset: 0 load_base: ffffffffff700000 flags: 5 name: [vdso]
+map: start: ffffffffff600000 end: ffffffffff601000 offset: 0 load_base: 0 flags: 5 name: [vsyscall]
+registers: 936 010000000000000028b480f4fc7f000028b480f4fc7f000028b480f4fc7f0000b92455add57f0000b07bcfabd57f000098deb6abd57f0000b82455add57f0000010000000000000000000000000000000000000000000000c0e354add57f000000e7b6abd57f0000c8b080f4fc7f00000e0000000000000080ddb6abd57f000000000000000000001500000000000000b07bcfabd57f00001c0000000000000060ddb6abd57f0000d07bcfabd57f0000a0b180f4fc7f000028b480f4fc7f000028b480f4fc7f000028b480f4fc7f000078b480f4fc7f000078b480f4fc7f00007f03ffff0000ffffffffffff000000000000000000000000801f0000fc7f000078b480f4fc7f000060b280f4fc7f000000006a80f3f73cf110b480f4fc7f0000de66d6abd57f00000000000000000000000000000000000000006a80f3f73cf128b480f4fc7f0000782455add57f0000fd96d6abd57f0000092555add57f0000000000000000000057b480f4fc7f0000092555add57f000060b480f4fc7f00006994d6abd57f0000b0e0c6abd57f000071b280f4fc7f000070b280f4fc7f0000256c640000000000a8b180f4fc7f000090b480f4fc7f0000082555add57f0000092555add57f0000092555add57f0000082555add57f00001700000000000000082555add57f0000082555add57f0000f93cfcabd57f0000092555add57f000016000000000000000000000000000000090c07acd57f0000082555add57f0000082555add57f0000082555add57f0000082555add57f0000082555add57f000010b380f4fc7f000078b480f4fc7f00000000000000000000082555add57f0000082555add57f0000082555add57f0000082555add57f0000082555add57f0000082555add57f0000082555add57f0000092555add57f0000092555add57f0000b92455add57f000028b480f4fc7f0000c800000000000000014c7f0b0380ffff0d000000fc7f0000030000000000000033000000d57f000000b480f4fc7f00000000000000000000a0e154ad5b000000000000000000000000000000000000006e000000770000000000000000000000082555add57f00000000000000000000082555add57f0000082555add57f0000082555add57f0000082555add57f00000000000000000000082555add57f0000082555add57f0000082555add57f00006027b4aad57f0000c800000000000000a0e154add57f0000c0e354add57f0000092555add57f000000006a80f3f73cf1e0e054add57f0000e0e554add57f0000d14df6abd57f0000
+stack: start: 7fd5abb6b000 end: 7fd5abb6f000 size: 16384 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c4eaeabd57f00000000000000000000978142a8000000000f0000000000000012000000000000003888b4abd57f0000e657aeabd57f00000000000000000000a0dcb6abd57f0000307d78aad57f0000b0ddb6abd57f000028d978aad57f0000060aa10200000000a0ddb6abd57f0000000000000000000000000000000000002091b1abd57f0000e094b4abd57f000017008cabd57f0000c84d79aad57f000028e28babd57f00000000000005000000d503000001000000000000000000000068deb6abd57f000040deb6abd57f00002091b1abd57f00000100000000000000e0f3c6abd57f000088f0c6abd57f00006159aeabd57f000000000000000000002091b1abd57f000005000000000000000000000000000000010000000000000088f0c6abd57f00000000000000000000d07bcfabd57f00000000000000000000000000000000000098deb6abd57f000098deb6abd57f0000b0ddb6abd57f00006179cfabd57f000098deb6abd57f0000b07bcfabd57f00001c000000150000000e00000007000000f0ddb6abd57f0000e179cfabd57f00000000000000000000150000001c00000098deb6abd57f0000b07bcfabd57f0000100000000c000000080000000400000030deb6abd57f0000417acfabd57f000000000000000000000c0000001000000098deb6abd57f0000b07bcfabd57f00000800000006000000040000000200000070deb6abd57f0000a17acfabd57f00000000000000000000060000000800000098deb6abd57f0000b07bcfabd57f000004000000030000000200000001000000b0deb6abd57f0000817bcfabd57f0000000000000000000074b480f4fc7f0000c8b080f4fc7f0000c8b080f4fc7f000074b480f4fc7f000000006a80f3f73cf1d0deb6abd57f00002a52d5abd57f0000c8b080f4fc7f0000c8b080f4fc7f0000000000000000000084518cabd57f0000000000000000000000e7b6abd57f000000e7b6abd57f00008f990b1e3bad5a6700000000000000000000000000000000c0e354add57f000000e7b6abd57f00008f99cba356faf1988f9991bc23faf1980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e7b6abd57f00007de387aad57f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006030b4aad57f0000b8edb6abd57f00000000000000000000000000000000000080b88eaad57f0000000000000000000080b28eaad57f0000000000000000000080c18eaad57f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e7b6abd57f0000402555add57f000000e7b6abd57f00000100000000000000000000000000000000006a80f3f73cf1058f9d56adb3c7cc000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000407ab1abd57f000030a3adabd57f00005c64000053640000e0e9b6abd57f0000e0e9b6abd57f0000e0ffffffffffffff00000000000000000000000000000000f0deb6abd57f00000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010eab6abd57f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000c46ad90f52391d00000000000000000000000000000000000000000000000000f051d5abd57f0000c8b080f4fc7f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b0b6abd57f000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+function: start: 0 end: 7fd5abcf7930 name: unknown_start
+function: start: 7fd5abcf7930 end: 7fd5abcf7990 name: test_level_four
+function: start: 7fd5abcf7990 end: 7fd5abcf79f0 name: test_level_three
+function: start: 7fd5abcf79f0 end: 7fd5abcf7a50 name: test_level_two
+function: start: 7fd5abcf7a50 end: 7fd5abcf7ab0 name: test_level_one
+function: start: 7fd5abcf7ab0 end: 7fd5abcf7b30 name: test_recursive_call
+function: start: 7fd5abcf7b30 end: ffffffffffffffff name: test_get_context_and_wait
+function: start: ffffffffffffffff end: ffffffffffffffff name: unknown_end
diff --git a/libcutils/fs_config.c b/libcutils/fs_config.c
index 60a389b..032e361 100644
--- a/libcutils/fs_config.c
+++ b/libcutils/fs_config.c
@@ -91,6 +91,7 @@
{ 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/Music" },
{ 00750, AID_ROOT, AID_SHELL, 0, "data/nativetest" },
{ 00750, AID_ROOT, AID_SHELL, 0, "data/nativetest64" },
+ { 00775, AID_ROOT, AID_ROOT, 0, "data/preloads" },
{ 00771, AID_SYSTEM, AID_SYSTEM, 0, "data" },
{ 00755, AID_ROOT, AID_SYSTEM, 0, "mnt" },
{ 00755, AID_ROOT, AID_ROOT, 0, "root" },
@@ -149,6 +150,9 @@
{ 00700, AID_SYSTEM, AID_SHELL, CAP_MASK_LONG(CAP_BLOCK_SUSPEND),
"system/bin/inputflinger" },
+ /* Support FIFO scheduling mode in SurfaceFlinger. */
+ { 00755, AID_SYSTEM, AID_GRAPHICS, CAP_MASK_LONG(CAP_SYS_NICE), "system/bin/surfaceflinger" },
+
/* Support hostapd administering a network interface. */
{ 00755, AID_WIFI, AID_WIFI, CAP_MASK_LONG(CAP_NET_ADMIN) |
CAP_MASK_LONG(CAP_NET_RAW),
diff --git a/libcutils/sched_policy.c b/libcutils/sched_policy.c
index cab9263..5c5f3a5 100644
--- a/libcutils/sched_policy.c
+++ b/libcutils/sched_policy.c
@@ -64,9 +64,12 @@
static int bg_cpuset_fd = -1;
static int fg_cpuset_fd = -1;
static int ta_cpuset_fd = -1; // special cpuset for top app
+#endif
+
+// File descriptors open to /dev/stune/../tasks, setup by initialize, or -1 on error
static int bg_schedboost_fd = -1;
static int fg_schedboost_fd = -1;
-#endif
+static int ta_schedboost_fd = -1;
/* Add tid to the scheduling group defined by the policy */
static int add_tid_to_cgroup(int tid, int fd)
@@ -136,9 +139,11 @@
ta_cpuset_fd = open(filename, O_WRONLY | O_CLOEXEC);
#ifdef USE_SCHEDBOOST
+ filename = "/dev/stune/top-app/tasks";
+ ta_schedboost_fd = open(filename, O_WRONLY | O_CLOEXEC);
filename = "/dev/stune/foreground/tasks";
fg_schedboost_fd = open(filename, O_WRONLY | O_CLOEXEC);
- filename = "/dev/stune/tasks";
+ filename = "/dev/stune/background/tasks";
bg_schedboost_fd = open(filename, O_WRONLY | O_CLOEXEC);
#endif
}
@@ -300,11 +305,10 @@
break;
case SP_TOP_APP :
fd = ta_cpuset_fd;
- boost_fd = fg_schedboost_fd;
+ boost_fd = ta_schedboost_fd;
break;
case SP_SYSTEM:
fd = system_bg_cpuset_fd;
- boost_fd = bg_schedboost_fd;
break;
default:
boost_fd = fd = -1;
@@ -316,10 +320,12 @@
return -errno;
}
+#ifdef USE_SCHEDBOOST
if (boost_fd > 0 && add_tid_to_cgroup(tid, boost_fd) != 0) {
if (errno != ESRCH && errno != ENOENT)
return -errno;
}
+#endif
return 0;
#endif
@@ -391,19 +397,26 @@
#endif
if (__sys_supports_schedgroups) {
- int fd;
+ int fd = -1;
+ int boost_fd = -1;
switch (policy) {
case SP_BACKGROUND:
fd = bg_cgroup_fd;
+ boost_fd = bg_schedboost_fd;
break;
case SP_FOREGROUND:
case SP_AUDIO_APP:
case SP_AUDIO_SYS:
+ fd = fg_cgroup_fd;
+ boost_fd = fg_schedboost_fd;
+ break;
case SP_TOP_APP:
fd = fg_cgroup_fd;
+ boost_fd = ta_schedboost_fd;
break;
default:
fd = -1;
+ boost_fd = -1;
break;
}
@@ -412,6 +425,13 @@
if (errno != ESRCH && errno != ENOENT)
return -errno;
}
+
+#ifdef USE_SCHEDBOOST
+ if (boost_fd > 0 && add_tid_to_cgroup(tid, boost_fd) != 0) {
+ if (errno != ESRCH && errno != ENOENT)
+ return -errno;
+ }
+#endif
} else {
struct sched_param param;
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index d80f8b2..d07d774 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -539,6 +539,7 @@
bool set_persist = false;
bool allow_security = false;
+ setuid(AID_SYSTEM); // only one that can read security buffer
if (__android_log_security()) {
allow_security = true;
} else {
@@ -1762,12 +1763,10 @@
#endif
}
-TEST(liblog, android_errorWriteWithInfoLog__android_logger_list_read__typical) {
#ifdef __ANDROID__
- const int TAG = 123456781;
- const char SUBTAG[] = "test-subtag";
- const int UID = -1;
- const int DATA_LEN = 200;
+static void android_errorWriteWithInfoLog_helper(int TAG, const char* SUBTAG,
+ int UID, const char* payload,
+ int DATA_LEN, int& count) {
struct logger_list *logger_list;
pid_t pid = getpid();
@@ -1775,100 +1774,17 @@
ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
- ASSERT_LT(0, android_errorWriteWithInfoLog(
- TAG, SUBTAG, UID, max_payload_buf, DATA_LEN));
-
- sleep(2);
-
- int count = 0;
-
- for (;;) {
- log_msg log_msg;
- if (android_logger_list_read(logger_list, &log_msg) <= 0) {
- break;
- }
-
- char *eventData = log_msg.msg();
- if (!eventData) {
- continue;
- }
-
- // Tag
- int tag = get4LE(eventData);
- eventData += 4;
-
- if (tag != TAG) {
- continue;
- }
-
- // List type
- ASSERT_EQ(EVENT_TYPE_LIST, eventData[0]);
- eventData++;
-
- // Number of elements in list
- ASSERT_EQ(3, eventData[0]);
- eventData++;
-
- // Element #1: string type for subtag
- ASSERT_EQ(EVENT_TYPE_STRING, eventData[0]);
- eventData++;
-
- ASSERT_EQ((int) strlen(SUBTAG), get4LE(eventData));
- eventData +=4;
-
- if (memcmp(SUBTAG, eventData, strlen(SUBTAG))) {
- continue;
- }
- eventData += strlen(SUBTAG);
-
- // Element #2: int type for uid
- ASSERT_EQ(EVENT_TYPE_INT, eventData[0]);
- eventData++;
-
- ASSERT_EQ(UID, get4LE(eventData));
- eventData += 4;
-
- // Element #3: string type for data
- ASSERT_EQ(EVENT_TYPE_STRING, eventData[0]);
- eventData++;
-
- ASSERT_EQ(DATA_LEN, get4LE(eventData));
- eventData += 4;
-
- if (memcmp(max_payload_buf, eventData, DATA_LEN)) {
- continue;
- }
-
- ++count;
+ int retval_android_errorWriteWithinInfoLog = android_errorWriteWithInfoLog(
+ TAG, SUBTAG, UID, payload, DATA_LEN);
+ if (payload) {
+ ASSERT_LT(0, retval_android_errorWriteWithinInfoLog);
+ } else {
+ ASSERT_GT(0, retval_android_errorWriteWithinInfoLog);
}
- EXPECT_EQ(1, count);
-
- android_logger_list_close(logger_list);
-#else
- GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif
-}
-
-TEST(liblog, android_errorWriteWithInfoLog__android_logger_list_read__data_too_large) {
-#ifdef __ANDROID__
- const int TAG = 123456782;
- const char SUBTAG[] = "test-subtag";
- const int UID = -1;
- const int DATA_LEN = sizeof(max_payload_buf);
- struct logger_list *logger_list;
-
- pid_t pid = getpid();
-
- ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
- LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
-
- ASSERT_LT(0, android_errorWriteWithInfoLog(
- TAG, SUBTAG, UID, max_payload_buf, DATA_LEN));
-
sleep(2);
- int count = 0;
+ count = 0;
for (;;) {
log_msg log_msg;
@@ -1891,6 +1807,12 @@
continue;
}
+ if (!payload) {
+ // This tag should not have been written because the data was null
+ ++count;
+ break;
+ }
+
// List type
ASSERT_EQ(EVENT_TYPE_LIST, eventData[0]);
eventData++;
@@ -1903,13 +1825,15 @@
ASSERT_EQ(EVENT_TYPE_STRING, eventData[0]);
eventData++;
- ASSERT_EQ((int) strlen(SUBTAG), get4LE(eventData));
+ int subtag_len = strlen(SUBTAG);
+ if (subtag_len > 32) subtag_len = 32;
+ ASSERT_EQ(subtag_len, get4LE(eventData));
eventData +=4;
- if (memcmp(SUBTAG, eventData, strlen(SUBTAG))) {
+ if (memcmp(SUBTAG, eventData, subtag_len)) {
continue;
}
- eventData += strlen(SUBTAG);
+ eventData += subtag_len;
// Element #2: int type for uid
ASSERT_EQ(EVENT_TYPE_INT, eventData[0]);
@@ -1924,22 +1848,53 @@
size_t dataLen = get4LE(eventData);
eventData += 4;
+ if (DATA_LEN < 512) ASSERT_EQ(DATA_LEN, (int)dataLen);
- if (memcmp(max_payload_buf, eventData, dataLen)) {
+ if (memcmp(payload, eventData, dataLen)) {
continue;
}
- eventData += dataLen;
- // 4 bytes for the tag, and max_payload_buf should be truncated.
- ASSERT_LE(4 + 512, eventData - original); // worst expectations
- ASSERT_GT(4 + DATA_LEN, eventData - original); // must be truncated
+ if (DATA_LEN >= 512) {
+ eventData += dataLen;
+ // 4 bytes for the tag, and max_payload_buf should be truncated.
+ ASSERT_LE(4 + 512, eventData - original); // worst expectations
+ ASSERT_GT(4 + DATA_LEN, eventData - original); // must be truncated
+ }
++count;
}
- EXPECT_EQ(1, count);
-
android_logger_list_close(logger_list);
+}
+#endif
+
+TEST(liblog, android_errorWriteWithInfoLog__android_logger_list_read__typical) {
+#ifdef __ANDROID__
+ int count;
+ android_errorWriteWithInfoLog_helper(
+ 123456781,
+ "test-subtag",
+ -1,
+ max_payload_buf,
+ 200,
+ count);
+ EXPECT_EQ(1, count);
+#else
+ GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+}
+
+TEST(liblog, android_errorWriteWithInfoLog__android_logger_list_read__data_too_large) {
+#ifdef __ANDROID__
+ int count;
+ android_errorWriteWithInfoLog_helper(
+ 123456782,
+ "test-subtag",
+ -1,
+ max_payload_buf,
+ sizeof(max_payload_buf),
+ count);
+ EXPECT_EQ(1, count);
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
@@ -1947,49 +1902,15 @@
TEST(liblog, android_errorWriteWithInfoLog__android_logger_list_read__null_data) {
#ifdef __ANDROID__
- const int TAG = 123456783;
- const char SUBTAG[] = "test-subtag";
- const int UID = -1;
- const int DATA_LEN = 200;
- struct logger_list *logger_list;
-
- pid_t pid = getpid();
-
- ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
- LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
-
- ASSERT_GT(0, android_errorWriteWithInfoLog(
- TAG, SUBTAG, UID, NULL, DATA_LEN));
-
- sleep(2);
-
- int count = 0;
-
- for (;;) {
- log_msg log_msg;
- if (android_logger_list_read(logger_list, &log_msg) <= 0) {
- break;
- }
-
- char *eventData = log_msg.msg();
- if (!eventData) {
- continue;
- }
-
- // Tag
- int tag = get4LE(eventData);
- eventData += 4;
-
- if (tag == TAG) {
- // This tag should not have been written because the data was null
- count++;
- break;
- }
- }
-
+ int count;
+ android_errorWriteWithInfoLog_helper(
+ 123456783,
+ "test-subtag",
+ -1,
+ NULL,
+ 200,
+ count);
EXPECT_EQ(0, count);
-
- android_logger_list_close(logger_list);
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
@@ -1997,88 +1918,15 @@
TEST(liblog, android_errorWriteWithInfoLog__android_logger_list_read__subtag_too_long) {
#ifdef __ANDROID__
- const int TAG = 123456784;
- const char SUBTAG[] = "abcdefghijklmnopqrstuvwxyz now i know my abc";
- const int UID = -1;
- const int DATA_LEN = 200;
- struct logger_list *logger_list;
-
- pid_t pid = getpid();
-
- ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
- LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
-
- ASSERT_LT(0, android_errorWriteWithInfoLog(
- TAG, SUBTAG, UID, max_payload_buf, DATA_LEN));
-
- sleep(2);
-
- int count = 0;
-
- for (;;) {
- log_msg log_msg;
- if (android_logger_list_read(logger_list, &log_msg) <= 0) {
- break;
- }
-
- char *eventData = log_msg.msg();
- if (!eventData) {
- continue;
- }
-
- // Tag
- int tag = get4LE(eventData);
- eventData += 4;
-
- if (tag != TAG) {
- continue;
- }
-
- // List type
- ASSERT_EQ(EVENT_TYPE_LIST, eventData[0]);
- eventData++;
-
- // Number of elements in list
- ASSERT_EQ(3, eventData[0]);
- eventData++;
-
- // Element #1: string type for subtag
- ASSERT_EQ(EVENT_TYPE_STRING, eventData[0]);
- eventData++;
-
- // The subtag is longer than 32 and should be truncated to that.
- ASSERT_EQ(32, get4LE(eventData));
- eventData +=4;
-
- if (memcmp(SUBTAG, eventData, 32)) {
- continue;
- }
- eventData += 32;
-
- // Element #2: int type for uid
- ASSERT_EQ(EVENT_TYPE_INT, eventData[0]);
- eventData++;
-
- ASSERT_EQ(UID, get4LE(eventData));
- eventData += 4;
-
- // Element #3: string type for data
- ASSERT_EQ(EVENT_TYPE_STRING, eventData[0]);
- eventData++;
-
- ASSERT_EQ(DATA_LEN, get4LE(eventData));
- eventData += 4;
-
- if (memcmp(max_payload_buf, eventData, DATA_LEN)) {
- continue;
- }
-
- ++count;
- }
-
+ int count;
+ android_errorWriteWithInfoLog_helper(
+ 123456784,
+ "abcdefghijklmnopqrstuvwxyz now i know my abc",
+ -1,
+ max_payload_buf,
+ 200,
+ count);
EXPECT_EQ(1, count);
-
- android_logger_list_close(logger_list);
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
@@ -2092,10 +1940,8 @@
buf_write_test(max_payload_buf);
}
-TEST(liblog, android_errorWriteLog__android_logger_list_read__success) {
#ifdef __ANDROID__
- const int TAG = 123456785;
- const char SUBTAG[] = "test-subtag";
+static void android_errorWriteLog_helper(int TAG, const char *SUBTAG, int& count) {
struct logger_list *logger_list;
pid_t pid = getpid();
@@ -2103,11 +1949,16 @@
ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
- ASSERT_LT(0, android_errorWriteLog(TAG, SUBTAG));
+ int retval_android_errorWriteLog = android_errorWriteLog(TAG, SUBTAG);
+ if (SUBTAG) {
+ ASSERT_LT(0, retval_android_errorWriteLog);
+ } else {
+ ASSERT_GT(0, retval_android_errorWriteLog);
+ }
sleep(2);
- int count = 0;
+ count = 0;
for (;;) {
log_msg log_msg;
@@ -2128,6 +1979,12 @@
continue;
}
+ if (!SUBTAG) {
+ // This tag should not have been written because the data was null
+ ++count;
+ break;
+ }
+
// List type
ASSERT_EQ(EVENT_TYPE_LIST, eventData[0]);
eventData++;
@@ -2149,9 +2006,15 @@
++count;
}
- EXPECT_EQ(1, count);
-
android_logger_list_close(logger_list);
+}
+#endif
+
+TEST(liblog, android_errorWriteLog__android_logger_list_read__success) {
+#ifdef __ANDROID__
+ int count;
+ android_errorWriteLog_helper(123456785, "test-subtag", count);
+ EXPECT_EQ(1, count);
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
@@ -2159,45 +2022,9 @@
TEST(liblog, android_errorWriteLog__android_logger_list_read__null_subtag) {
#ifdef __ANDROID__
- const int TAG = 123456786;
- struct logger_list *logger_list;
-
- pid_t pid = getpid();
-
- ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
- LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 1000, pid)));
-
- ASSERT_GT(0, android_errorWriteLog(TAG, NULL));
-
- sleep(2);
-
- int count = 0;
-
- for (;;) {
- log_msg log_msg;
- if (android_logger_list_read(logger_list, &log_msg) <= 0) {
- break;
- }
-
- char *eventData = log_msg.msg();
- if (!eventData) {
- continue;
- }
-
- // Tag
- int tag = get4LE(eventData);
- eventData += 4;
-
- if (tag == TAG) {
- // This tag should not have been written because the data was null
- count++;
- break;
- }
- }
-
+ int count;
+ android_errorWriteLog_helper(123456786, NULL, count);
EXPECT_EQ(0, count);
-
- android_logger_list_close(logger_list);
#else
GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
diff --git a/libsuspend/autosuspend_wakeup_count.c b/libsuspend/autosuspend_wakeup_count.c
index d3fb45f..3457d5b 100644
--- a/libsuspend/autosuspend_wakeup_count.c
+++ b/libsuspend/autosuspend_wakeup_count.c
@@ -24,6 +24,7 @@
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
+#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
@@ -35,12 +36,24 @@
#define SYS_POWER_STATE "/sys/power/state"
#define SYS_POWER_WAKEUP_COUNT "/sys/power/wakeup_count"
+#define BASE_SLEEP_TIME 100000
+
static int state_fd;
static int wakeup_count_fd;
static pthread_t suspend_thread;
static sem_t suspend_lockout;
static const char *sleep_state = "mem";
static void (*wakeup_func)(bool success) = NULL;
+static int sleep_time = BASE_SLEEP_TIME;
+
+static void update_sleep_time(bool success) {
+ if (success) {
+ sleep_time = BASE_SLEEP_TIME;
+ return;
+ }
+ // double sleep time after each failure up to one minute
+ sleep_time = MIN(sleep_time * 2, 60000000);
+}
static void *suspend_thread_func(void *arg __attribute__((unused)))
{
@@ -48,10 +61,12 @@
char wakeup_count[20];
int wakeup_count_len;
int ret;
- bool success;
+ bool success = true;
while (1) {
- usleep(100000);
+ update_sleep_time(success);
+ usleep(sleep_time);
+ success = false;
ALOGV("%s: read wakeup_count\n", __func__);
lseek(wakeup_count_fd, 0, SEEK_SET);
wakeup_count_len = TEMP_FAILURE_RETRY(read(wakeup_count_fd, wakeup_count,
@@ -75,7 +90,6 @@
continue;
}
- success = true;
ALOGV("%s: write %*s to wakeup_count\n", __func__, wakeup_count_len, wakeup_count);
ret = TEMP_FAILURE_RETRY(write(wakeup_count_fd, wakeup_count, wakeup_count_len));
if (ret < 0) {
@@ -84,8 +98,8 @@
} else {
ALOGV("%s: write %s to %s\n", __func__, sleep_state, SYS_POWER_STATE);
ret = TEMP_FAILURE_RETRY(write(state_fd, sleep_state, strlen(sleep_state)));
- if (ret < 0) {
- success = false;
+ if (ret >= 0) {
+ success = true;
}
void (*func)(bool success) = wakeup_func;
if (func != NULL) {
diff --git a/libsync/sync.c b/libsync/sync.c
index 169dc36..6281b20 100644
--- a/libsync/sync.c
+++ b/libsync/sync.c
@@ -21,8 +21,6 @@
#include <stdint.h>
#include <string.h>
-#include <linux/sw_sync.h>
-
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -42,6 +40,16 @@
#define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 1, struct sync_merge_data)
#define SYNC_IOC_FENCE_INFO _IOWR(SYNC_IOC_MAGIC, 2, struct sync_fence_info_data)
+struct sw_sync_create_fence_data {
+ __u32 value;
+ char name[32];
+ __s32 fence;
+};
+
+#define SW_SYNC_IOC_MAGIC 'W'
+#define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0, struct sw_sync_create_fence_data)
+#define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32)
+
int sync_wait(int fd, int timeout)
{
__s32 to = timeout;
diff --git a/libsysutils/src/FrameworkListener.cpp b/libsysutils/src/FrameworkListener.cpp
index 52f28af..1b6076f 100644
--- a/libsysutils/src/FrameworkListener.cpp
+++ b/libsysutils/src/FrameworkListener.cpp
@@ -50,6 +50,7 @@
errorRate = 0;
mCommandCount = 0;
mWithSeq = withSeq;
+ mSkipToNextNullByte = false;
}
bool FrameworkListener::onDataAvailable(SocketClient *c) {
@@ -60,10 +61,15 @@
if (len < 0) {
SLOGE("read() failed (%s)", strerror(errno));
return false;
- } else if (!len)
+ } else if (!len) {
return false;
- if(buffer[len-1] != '\0')
+ } else if (buffer[len-1] != '\0') {
SLOGW("String is not zero-terminated");
+ android_errorWriteLog(0x534e4554, "29831647");
+ c->sendMsg(500, "Command too large for buffer", false);
+ mSkipToNextNullByte = true;
+ return false;
+ }
int offset = 0;
int i;
@@ -71,11 +77,16 @@
for (i = 0; i < len; i++) {
if (buffer[i] == '\0') {
/* IMPORTANT: dispatchCommand() expects a zero-terminated string */
- dispatchCommand(c, buffer + offset);
+ if (mSkipToNextNullByte) {
+ mSkipToNextNullByte = false;
+ } else {
+ dispatchCommand(c, buffer + offset);
+ }
offset = i + 1;
}
}
+ mSkipToNextNullByte = false;
return true;
}
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index e6e0276..0ac6f2c 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -267,9 +267,14 @@
* Grab the CD offset and size, and the number of entries in the
* archive and verify that they look reasonable.
*/
- if (eocd->cd_start_offset + eocd->cd_size > eocd_offset) {
+ if (static_cast<off64_t>(eocd->cd_start_offset) + eocd->cd_size > eocd_offset) {
ALOGW("Zip: bad offsets (dir %" PRIu32 ", size %" PRIu32 ", eocd %" PRId64 ")",
eocd->cd_start_offset, eocd->cd_size, static_cast<int64_t>(eocd_offset));
+#if defined(__ANDROID__)
+ if (eocd->cd_start_offset + eocd->cd_size <= eocd_offset) {
+ android_errorWriteLog(0x534e4554, "31251826");
+ }
+#endif
return kInvalidOffset;
}
if (eocd->num_records == 0) {
diff --git a/logcat/logcatd.rc b/logcat/logcatd.rc
index 1da1942..b082a64 100644
--- a/logcat/logcatd.rc
+++ b/logcat/logcatd.rc
@@ -35,7 +35,8 @@
# all exec/services are called with umask(077), so no gain beyond 0700
mkdir /data/misc/logd 0700 logd log
# logd for write to /data/misc/logd, log group for read from pstore (-L)
- exec - logd log -- /system/bin/logcat -L -b ${logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${logd.logpersistd.size:-256} --id=${ro.build.id}
+ # b/28788401 b/30041146 b/30612424
+ # exec - logd log -- /system/bin/logcat -L -b ${logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${logd.logpersistd.size:-256} --id=${ro.build.id}
start logcatd
# stop logcatd service and clear data
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index f5c60c7..ec91f2a 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -89,7 +89,7 @@
size_t name_len = strlen(name);
// KISS: ToDo: Only checks prefix truncated, not suffix, or both
if ((retval_len < name_len)
- && !fast<strcmp>(retval, name + name_len - retval_len)) {
+ && !fastcmp<strcmp>(retval, name + name_len - retval_len)) {
free(retval);
retval = name;
} else {
diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp
index fe08846..0b49fc1 100644
--- a/logd/LogKlog.cpp
+++ b/logd/LogKlog.cpp
@@ -321,7 +321,7 @@
}
--len;
} while (*s++ != c);
- } while (fast<memcmp>(s, needle, needleLen));
+ } while (fastcmp<memcmp>(s, needle, needleLen));
s--;
}
return s;
@@ -402,7 +402,32 @@
}
}
-pid_t LogKlog::sniffPid(const char *cp, size_t len) {
+pid_t LogKlog::sniffPid(const char **buf, size_t len) {
+ const char *cp = *buf;
+ // HTC kernels with modified printk "c0 1648 "
+ if ((len > 9) &&
+ (cp[0] == 'c') &&
+ isdigit(cp[1]) &&
+ (isdigit(cp[2]) || (cp[2] == ' ')) &&
+ (cp[3] == ' ')) {
+ bool gotDigit = false;
+ int i;
+ for (i = 4; i < 9; ++i) {
+ if (isdigit(cp[i])) {
+ gotDigit = true;
+ } else if (gotDigit || (cp[i] != ' ')) {
+ break;
+ }
+ }
+ if ((i == 9) && (cp[i] == ' ')) {
+ int pid = 0;
+ char dummy;
+ if (sscanf(cp + 4, "%d%c", &pid, &dummy) == 2) {
+ *buf = cp + 10; // skip-it-all
+ return pid;
+ }
+ }
+ }
while (len) {
// Mediatek kernels with modified printk
if (*cp == '[') {
@@ -588,7 +613,7 @@
}
// Parse pid, tid and uid
- const pid_t pid = sniffPid(p, len - (p - buf));
+ const pid_t pid = sniffPid(&p, len - (p - buf));
const pid_t tid = pid;
uid_t uid = AID_ROOT;
if (pid) {
@@ -615,7 +640,7 @@
static const char infoBrace[] = "[INFO]";
static const size_t infoBraceLen = strlen(infoBrace);
- if ((taglen >= infoBraceLen) && !fast<strncmp>(p, infoBrace, infoBraceLen)) {
+ if ((taglen >= infoBraceLen) && !fastcmp<strncmp>(p, infoBrace, infoBraceLen)) {
// <PRI>[<TIME>] "[INFO]"<tag> ":" message
bt = p + infoBraceLen;
taglen -= infoBraceLen;
@@ -650,7 +675,7 @@
p = cp + 1;
} else if ((taglen > size) && (tolower(*bt) == tolower(*cp))) {
// clean up any tag stutter
- if (!fast<strncasecmp>(bt + 1, cp + 1, size - 1)) { // no match
+ if (!fastcmp<strncasecmp>(bt + 1, cp + 1, size - 1)) { // no match
// <PRI>[<TIME>] <tag> <tag> : message
// <PRI>[<TIME>] <tag> <tag>: message
// <PRI>[<TIME>] <tag> '<tag>.<num>' : message
@@ -672,8 +697,8 @@
static const char host[] = "_host";
static const size_t hostlen = strlen(host);
if ((size > hostlen) &&
- !fast<strncmp>(bt + size - hostlen, host, hostlen) &&
- !fast<strncmp>(bt + 1, cp + 1, size - hostlen - 1)) {
+ !fastcmp<strncmp>(bt + size - hostlen, host, hostlen) &&
+ !fastcmp<strncmp>(bt + 1, cp + 1, size - hostlen - 1)) {
const char *b = cp;
cp += size - hostlen;
taglen -= size - hostlen;
@@ -721,10 +746,10 @@
// register names like x18 but not driver names like en0
|| ((size == 3) && (isdigit(tag[1]) && isdigit(tag[2])))
// blacklist
- || ((size == cpuLen) && !fast<strncmp>(tag, cpu, cpuLen))
- || ((size == warningLen) && !fast<strncasecmp>(tag, warning, warningLen))
- || ((size == errorLen) && !fast<strncasecmp>(tag, error, errorLen))
- || ((size == infoLen) && !fast<strncasecmp>(tag, info, infoLen))) {
+ || ((size == cpuLen) && !fastcmp<strncmp>(tag, cpu, cpuLen))
+ || ((size == warningLen) && !fastcmp<strncasecmp>(tag, warning, warningLen))
+ || ((size == errorLen) && !fastcmp<strncasecmp>(tag, error, errorLen))
+ || ((size == infoLen) && !fastcmp<strncasecmp>(tag, info, infoLen))) {
p = start;
etag = tag = "";
}
@@ -736,7 +761,7 @@
const char *mp = strnrchr(tag, ']', taglen);
if (mp && (++mp < etag)) {
size_t s = etag - mp;
- if (((s + s) < taglen) && !fast<memcmp>(mp, mp - 1 - s, s)) {
+ if (((s + s) < taglen) && !fastcmp<memcmp>(mp, mp - 1 - s, s)) {
taglen = mp - tag;
}
}
diff --git a/logd/LogKlog.h b/logd/LogKlog.h
index d812436..11d88af 100644
--- a/logd/LogKlog.h
+++ b/logd/LogKlog.h
@@ -51,7 +51,7 @@
protected:
void sniffTime(log_time &now, const char **buf, size_t len, bool reverse);
- pid_t sniffPid(const char *buf, size_t len);
+ pid_t sniffPid(const char **buf, size_t len);
void calculateCorrection(const log_time &monotonic,
const char *real_string, size_t len);
virtual bool onDataAvailable(SocketClient *cli);
diff --git a/logd/LogReader.cpp b/logd/LogReader.cpp
index 61d4c49..1b50b4e 100644
--- a/logd/LogReader.cpp
+++ b/logd/LogReader.cpp
@@ -108,7 +108,7 @@
}
bool nonBlock = false;
- if (!fast<strncmp>(buffer, "dumpAndClose", 12)) {
+ if (!fastcmp<strncmp>(buffer, "dumpAndClose", 12)) {
// Allow writer to get some cycles, and wait for pending notifications
sched_yield();
LogTimeEntry::lock();
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index d4b48ef..bab87ba 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -53,7 +53,7 @@
if (ret > 0) {
buffer[sizeof(buffer)-1] = '\0';
// frameworks intermediate state
- if (fast<strcmp>(buffer, "<pre-initialized>")) {
+ if (fastcmp<strcmp>(buffer, "<pre-initialized>")) {
retval = strdup(buffer);
}
}
@@ -209,7 +209,7 @@
if (nameTmp) {
if (!name) {
name = strdup(nameTmp);
- } else if (fast<strcmp>(name, nameTmp)) {
+ } else if (fastcmp<strcmp>(name, nameTmp)) {
free(const_cast<char *>(name));
name = NULL;
break;
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 1f598af..cb7ae2b 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -307,7 +307,7 @@
const char*getName() const { return name; }
inline void add(pid_t newPid) {
- if (name && !fast<strncmp>(name, "zygote", 6)) {
+ if (name && !fastcmp<strncmp>(name, "zygote", 6)) {
free(name);
name = NULL;
}
@@ -368,7 +368,7 @@
const char*getName() const { return name; }
inline void add(pid_t incomingTid) {
- if (name && !fast<strncmp>(name, "zygote", 6)) {
+ if (name && !fastcmp<strncmp>(name, "zygote", 6)) {
free(name);
name = NULL;
}
diff --git a/logd/LogUtils.h b/logd/LogUtils.h
index 44ac742..ec68062 100644
--- a/logd/LogUtils.h
+++ b/logd/LogUtils.h
@@ -20,6 +20,7 @@
#include <sys/cdefs.h>
#include <sys/types.h>
+#include <utils/FastStrcmp.h>
#include <private/android_logger.h>
#include <sysutils/SocketClient.h>
@@ -50,21 +51,4 @@
(id == LOG_ID_RADIO) || (id == LOG_ID_EVENTS);
}
-template <int (*cmp)(const char *l, const char *r, const size_t s)>
-static inline int fast(const char *l, const char *r, const size_t s) {
- return (*l != *r) || cmp(l + 1, r + 1, s - 1);
-}
-
-template <int (*cmp)(const void *l, const void *r, const size_t s)>
-static inline int fast(const void *lv, const void *rv, const size_t s) {
- const char *l = static_cast<const char *>(lv);
- const char *r = static_cast<const char *>(rv);
- return (*l != *r) || cmp(l + 1, r + 1, s - 1);
-}
-
-template <int (*cmp)(const char *l, const char *r)>
-static inline int fast(const char *l, const char *r) {
- return (*l != *r) || cmp(l + 1, r + 1);
-}
-
#endif // _LOGD_LOG_UTILS_H__
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 0fc701a..7d0c87d 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -26,6 +26,7 @@
#######################################
# asan.options
ifneq ($(filter address,$(SANITIZE_TARGET)),)
+
include $(CLEAR_VARS)
LOCAL_MODULE := asan.options
@@ -34,6 +35,72 @@
LOCAL_MODULE_PATH := $(TARGET_OUT)
include $(BUILD_PREBUILT)
+
+# Modules for asan.options.X files.
+
+ASAN_OPTIONS_FILES :=
+
+define create-asan-options-module
+include $$(CLEAR_VARS)
+LOCAL_MODULE := asan.options.$(1)
+ASAN_OPTIONS_FILES += asan.options.$(1)
+LOCAL_MODULE_CLASS := ETC
+# The asan.options.off.template tries to turn off as much of ASAN as is possible.
+LOCAL_SRC_FILES := asan.options.off.template
+LOCAL_MODULE_PATH := $(TARGET_OUT)
+include $$(BUILD_PREBUILT)
+endef
+
+# Pretty comprehensive set of native services. This list is helpful if all that's to be checked is an
+# app.
+ifeq ($(SANITIZE_LITE),true)
+SANITIZE_ASAN_OPTIONS_FOR := \
+ adbd \
+ ATFWD-daemon \
+ audioserver \
+ bridgemgrd \
+ cameraserver \
+ cnd \
+ debuggerd \
+ debuggerd64 \
+ dex2oat \
+ drmserver \
+ fingerprintd \
+ gatekeeperd \
+ installd \
+ keystore \
+ lmkd \
+ logcat \
+ logd \
+ lowi-server \
+ media.codec \
+ mediadrmserver \
+ media.extractor \
+ mediaserver \
+ mm-qcamera-daemon \
+ mpdecision \
+ netmgrd \
+ perfd \
+ perfprofd \
+ qmuxd \
+ qseecomd \
+ rild \
+ sdcard \
+ servicemanager \
+ slim_daemon \
+ surfaceflinger \
+ thermal-engine \
+ time_daemon \
+ update_engine \
+ vold \
+ wpa_supplicant \
+ zip
+endif
+
+ifneq ($(SANITIZE_ASAN_OPTIONS_FOR),)
+ $(foreach binary, $(SANITIZE_ASAN_OPTIONS_FOR), $(eval $(call create-asan-options-module,$(binary))))
+endif
+
endif
#######################################
@@ -47,14 +114,14 @@
EXPORT_GLOBAL_ASAN_OPTIONS :=
ifneq ($(filter address,$(SANITIZE_TARGET)),)
EXPORT_GLOBAL_ASAN_OPTIONS := export ASAN_OPTIONS include=/system/asan.options
- LOCAL_REQUIRED_MODULES := asan.options
+ LOCAL_REQUIRED_MODULES := asan.options $(ASAN_OPTIONS_FILES)
endif
# Put it here instead of in init.rc module definition,
# because init.rc is conditionally included.
#
# create some directories (some are mount points) and symlinks
LOCAL_POST_INSTALL_CMD := mkdir -p $(addprefix $(TARGET_ROOT_OUT)/, \
- sbin dev proc sys system data oem acct cache config storage mnt root $(BOARD_ROOT_EXTRA_FOLDERS)); \
+ sbin dev proc sys system data oem acct config storage mnt root $(BOARD_ROOT_EXTRA_FOLDERS)); \
ln -sf /system/etc $(TARGET_ROOT_OUT)/etc; \
ln -sf /data/user_de/0/com.android.shell/files/bugreports $(TARGET_ROOT_OUT)/bugreports; \
ln -sf /sys/kernel/debug $(TARGET_ROOT_OUT)/d; \
@@ -64,6 +131,11 @@
else
LOCAL_POST_INSTALL_CMD += ; ln -sf /system/vendor $(TARGET_ROOT_OUT)/vendor
endif
+ifdef BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE
+ LOCAL_POST_INSTALL_CMD += ; mkdir -p $(TARGET_ROOT_OUT)/cache
+else
+ LOCAL_POST_INSTALL_CMD += ; ln -sf /data/cache $(TARGET_ROOT_OUT)/cache
+endif
ifdef BOARD_ROOT_EXTRA_SYMLINKS
# BOARD_ROOT_EXTRA_SYMLINKS is a list of <target>:<link_name>.
LOCAL_POST_INSTALL_CMD += $(foreach s, $(BOARD_ROOT_EXTRA_SYMLINKS),\
diff --git a/rootdir/asan.options b/rootdir/asan.options
index 43896a1..d728f12 100644
--- a/rootdir/asan.options
+++ b/rootdir/asan.options
@@ -3,3 +3,5 @@
alloc_dealloc_mismatch=0
allocator_may_return_null=1
detect_container_overflow=0
+abort_on_error=1
+include_if_exists=/system/asan.options.%b
diff --git a/rootdir/asan.options.off.template b/rootdir/asan.options.off.template
new file mode 100644
index 0000000..59a1249
--- /dev/null
+++ b/rootdir/asan.options.off.template
@@ -0,0 +1,7 @@
+quarantine_size_mb=0
+max_redzone=16
+poison_heap=false
+poison_partial=false
+poison_array_cookie=false
+alloc_dealloc_mismatch=false
+new_delete_type_mismatch=false
diff --git a/rootdir/init.rc b/rootdir/init.rc
index ecc3ccd..8903255 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -50,12 +50,20 @@
mkdir /dev/stune
mount cgroup none /dev/stune schedtune
mkdir /dev/stune/foreground
+ mkdir /dev/stune/background
+ mkdir /dev/stune/top-app
chown system system /dev/stune
chown system system /dev/stune/foreground
+ chown system system /dev/stune/background
+ chown system system /dev/stune/top-app
chown system system /dev/stune/tasks
chown system system /dev/stune/foreground/tasks
+ chown system system /dev/stune/background/tasks
+ chown system system /dev/stune/top-app/tasks
chmod 0664 /dev/stune/tasks
chmod 0664 /dev/stune/foreground/tasks
+ chmod 0664 /dev/stune/background/tasks
+ chmod 0664 /dev/stune/top-app/tasks
# Mount staging areas for devices managed by vold
# See storage config details at http://source.android.com/tech/storage/
@@ -134,16 +142,17 @@
chown system system /dev/cpuctl
chown system system /dev/cpuctl/tasks
chmod 0666 /dev/cpuctl/tasks
- write /dev/cpuctl/cpu.rt_runtime_us 800000
write /dev/cpuctl/cpu.rt_period_us 1000000
+ write /dev/cpuctl/cpu.rt_runtime_us 950000
mkdir /dev/cpuctl/bg_non_interactive
chown system system /dev/cpuctl/bg_non_interactive/tasks
chmod 0666 /dev/cpuctl/bg_non_interactive/tasks
# 5.0 %
write /dev/cpuctl/bg_non_interactive/cpu.shares 52
- write /dev/cpuctl/bg_non_interactive/cpu.rt_runtime_us 700000
write /dev/cpuctl/bg_non_interactive/cpu.rt_period_us 1000000
+ # active FIFO threads will never be in BG
+ write /dev/cpuctl/bg_non_interactive/cpu.rt_runtime_us 10000
# sets up initial cpusets for ActivityManager
mkdir /dev/cpuset
@@ -225,6 +234,8 @@
# expecting it to point to /proc/self/fd
symlink /proc/self/fd /dev/fd
+ export DOWNLOAD_CACHE /data/cache
+
# set RLIMIT_NICE to allow priorities from 19 to -20
setrlimit 13 40 40
@@ -412,6 +423,10 @@
# create the A/B OTA directory, so as to enforce our permissions
mkdir /data/ota 0771 root root
+ # create the OTA package directory. It will be accessed by GmsCore (cache
+ # group), update_engine and update_verifier.
+ mkdir /data/ota_package 0770 system cache
+
# create resource-cache and double-check the perms
mkdir /data/resource-cache 0771 system system
chown system system /data/resource-cache
@@ -452,6 +467,11 @@
mkdir /data/media 0770 media_rw media_rw
mkdir /data/media/obb 0770 media_rw media_rw
+ mkdir /data/cache 0770 system cache
+ mkdir /data/cache/recovery 0770 system cache
+ mkdir /data/cache/backup_stage 0700 system system
+ mkdir /data/cache/backup 0700 system system
+
init_user0
# Set SELinux security contexts on upgrade or policy update.
diff --git a/rootdir/init.usb.rc b/rootdir/init.usb.rc
index 1fd1e2a..915d159 100644
--- a/rootdir/init.usb.rc
+++ b/rootdir/init.usb.rc
@@ -103,7 +103,7 @@
# Used to set USB configuration at boot and to switch the configuration
# when changing the default configuration
-on property:persist.sys.usb.config=*
+on boot && property:persist.sys.usb.config=*
setprop sys.usb.config ${persist.sys.usb.config}
#
diff --git a/rootdir/init.zygote32.rc b/rootdir/init.zygote32.rc
index bfddcfa..eedeba8 100644
--- a/rootdir/init.zygote32.rc
+++ b/rootdir/init.zygote32.rc
@@ -10,4 +10,4 @@
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
- writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
+ writepid /dev/cpuset/foreground/tasks
diff --git a/rootdir/init.zygote32_64.rc b/rootdir/init.zygote32_64.rc
index 1bbb007..84a907f 100644
--- a/rootdir/init.zygote32_64.rc
+++ b/rootdir/init.zygote32_64.rc
@@ -19,4 +19,4 @@
group root readproc
socket zygote_secondary stream 660 root system
onrestart restart zygote
- writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
+ writepid /dev/cpuset/foreground/tasks
diff --git a/rootdir/init.zygote64.rc b/rootdir/init.zygote64.rc
index 6742127..76e2b79 100644
--- a/rootdir/init.zygote64.rc
+++ b/rootdir/init.zygote64.rc
@@ -10,4 +10,4 @@
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
- writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
+ writepid /dev/cpuset/foreground/tasks
diff --git a/rootdir/init.zygote64_32.rc b/rootdir/init.zygote64_32.rc
index 81a7609..e918b67 100644
--- a/rootdir/init.zygote64_32.rc
+++ b/rootdir/init.zygote64_32.rc
@@ -19,4 +19,4 @@
group root readproc
socket zygote_secondary stream 660 root system
onrestart restart zygote
- writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
+ writepid /dev/cpuset/foreground/tasks
diff --git a/sdcard/fuse.cpp b/sdcard/fuse.cpp
index 9393846..3f0f95f 100644
--- a/sdcard/fuse.cpp
+++ b/sdcard/fuse.cpp
@@ -1026,7 +1026,13 @@
}
out.fh = ptr_to_id(h);
out.open_flags = 0;
+
+#ifdef FUSE_SHORTCIRCUIT
+ out.lower_fd = h->fd;
+#else
out.padding = 0;
+#endif
+
fuse_reply(fuse, hdr->unique, &out, sizeof(out));
return NO_STATUS;
}
@@ -1190,7 +1196,13 @@
}
out.fh = ptr_to_id(h);
out.open_flags = 0;
+
+#ifdef FUSE_SHORTCIRCUIT
+ out.lower_fd = -1;
+#else
out.padding = 0;
+#endif
+
fuse_reply(fuse, hdr->unique, &out, sizeof(out));
return NO_STATUS;
}
@@ -1270,6 +1282,11 @@
out.major = FUSE_KERNEL_VERSION;
out.max_readahead = req->max_readahead;
out.flags = FUSE_ATOMIC_O_TRUNC | FUSE_BIG_WRITES;
+
+#ifdef FUSE_SHORTCIRCUIT
+ out.flags |= FUSE_SHORTCIRCUIT;
+#endif
+
out.max_background = 32;
out.congestion_threshold = 32;
out.max_write = MAX_WRITE;