Merge "enable integer sanitizer for sdcard service"
diff --git a/debuggerd/backtrace.cpp b/debuggerd/backtrace.cpp
index 32843d8..8f4a53f 100644
--- a/debuggerd/backtrace.cpp
+++ b/debuggerd/backtrace.cpp
@@ -29,6 +29,7 @@
#include <sys/ptrace.h>
#include <memory>
+#include <string>
#include <backtrace/Backtrace.h>
@@ -96,11 +97,11 @@
}
}
-void dump_backtrace(int fd, int amfd, BacktraceMap* map, pid_t pid, pid_t tid,
- const std::set<pid_t>& siblings) {
+void dump_backtrace(int fd, BacktraceMap* map, pid_t pid, pid_t tid,
+ const std::set<pid_t>& siblings, std::string* amfd_data) {
log_t log;
log.tfd = fd;
- log.amfd = amfd;
+ log.amfd_data = amfd_data;
dump_process_header(&log, pid);
dump_thread(&log, map, pid, tid);
diff --git a/debuggerd/backtrace.h b/debuggerd/backtrace.h
index 98c433b..acd5eaa 100644
--- a/debuggerd/backtrace.h
+++ b/debuggerd/backtrace.h
@@ -20,6 +20,7 @@
#include <sys/types.h>
#include <set>
+#include <string>
#include "utility.h"
@@ -28,8 +29,8 @@
// Dumps a backtrace using a format similar to what Dalvik uses so that the result
// can be intermixed in a bug report.
-void dump_backtrace(int fd, int amfd, BacktraceMap* map, pid_t pid, pid_t tid,
- const std::set<pid_t>& siblings);
+void dump_backtrace(int fd, BacktraceMap* map, pid_t pid, pid_t tid,
+ const std::set<pid_t>& siblings, std::string* amfd_data);
/* Dumps the backtrace in the backtrace data structure to the log. */
void dump_backtrace_to_log(Backtrace* backtrace, log_t* log, const char* prefix);
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index 258bd76..d87594c 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <arpa/inet.h>
#include <dirent.h>
#include <elf.h>
#include <errno.h>
@@ -32,12 +33,15 @@
#include <sys/un.h>
#include <time.h>
+#include <memory>
#include <set>
+#include <string>
#include <selinux/android.h>
#include <log/logger.h>
+#include <android-base/file.h>
#include <android-base/unique_fd.h>
#include <cutils/debugger.h>
#include <cutils/properties.h>
@@ -287,6 +291,41 @@
return amfd.release();
}
+static void activity_manager_write(int pid, int signal, int amfd, const std::string& amfd_data) {
+ if (amfd == -1) {
+ return;
+ }
+
+ // Activity Manager protocol: binary 32-bit network-byte-order ints for the
+ // pid and signal number, followed by the raw text of the dump, culminating
+ // in a zero byte that marks end-of-data.
+ uint32_t datum = htonl(pid);
+ if (!android::base::WriteFully(amfd, &datum, 4)) {
+ ALOGE("AM pid write failed: %s\n", strerror(errno));
+ return;
+ }
+ datum = htonl(signal);
+ if (!android::base::WriteFully(amfd, &datum, 4)) {
+ ALOGE("AM signal write failed: %s\n", strerror(errno));
+ return;
+ }
+
+ if (!android::base::WriteFully(amfd, amfd_data.c_str(), amfd_data.size())) {
+ ALOGE("AM data write failed: %s\n", strerror(errno));
+ return;
+ }
+
+ // Send EOD to the Activity Manager, then wait for its ack to avoid racing
+ // ahead and killing the target out from under it.
+ uint8_t eodMarker = 0;
+ if (!android::base::WriteFully(amfd, &eodMarker, 1)) {
+ ALOGE("AM eod write failed: %s\n", strerror(errno));
+ return;
+ }
+ // 3 sec timeout reading the ack; we're fine if the read fails.
+ android::base::ReadFully(amfd, &eodMarker, 1);
+}
+
static bool should_attach_gdb(const debugger_request_t& request) {
if (request.action == DEBUGGER_ACTION_CRASH) {
return property_get_bool("debug.debuggerd.wait_for_gdb", false);
@@ -414,7 +453,7 @@
static bool perform_dump(const debugger_request_t& request, int fd, int tombstone_fd,
BacktraceMap* backtrace_map, const std::set<pid_t>& siblings,
- int* crash_signal, int amfd) {
+ int* crash_signal, std::string* amfd_data) {
if (TEMP_FAILURE_RETRY(write(fd, "\0", 1)) != 1) {
ALOGE("debuggerd: failed to respond to client: %s\n", strerror(errno));
return false;
@@ -432,10 +471,10 @@
if (request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) {
ALOGV("debuggerd: stopped -- dumping to tombstone");
engrave_tombstone(tombstone_fd, backtrace_map, request.pid, request.tid, siblings, signal,
- request.original_si_code, request.abort_msg_address, amfd);
+ request.original_si_code, request.abort_msg_address, amfd_data);
} else if (request.action == DEBUGGER_ACTION_DUMP_BACKTRACE) {
ALOGV("debuggerd: stopped -- dumping to fd");
- dump_backtrace(fd, -1, backtrace_map, request.pid, request.tid, siblings);
+ dump_backtrace(fd, backtrace_map, request.pid, request.tid, siblings, nullptr);
} else {
ALOGV("debuggerd: stopped -- continuing");
if (ptrace(PTRACE_CONT, request.tid, 0, 0) != 0) {
@@ -458,7 +497,7 @@
ALOGV("stopped -- fatal signal\n");
*crash_signal = signal;
engrave_tombstone(tombstone_fd, backtrace_map, request.pid, request.tid, siblings, signal,
- request.original_si_code, request.abort_msg_address, amfd);
+ request.original_si_code, request.abort_msg_address, amfd_data);
break;
default:
@@ -472,13 +511,21 @@
}
static bool drop_privileges() {
+ // AID_LOG: for reading the logs data associated with the crashing process.
+ // AID_READPROC: for reading /proc/<PID>/{comm,cmdline}.
+ gid_t groups[] = { AID_DEBUGGERD, AID_LOG, AID_READPROC };
+ if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
+ ALOGE("debuggerd: failed to setgroups: %s", strerror(errno));
+ return false;
+ }
+
if (setresgid(AID_DEBUGGERD, AID_DEBUGGERD, AID_DEBUGGERD) != 0) {
- ALOGE("debuggerd: failed to setresgid");
+ ALOGE("debuggerd: failed to setresgid: %s", strerror(errno));
return false;
}
if (setresuid(AID_DEBUGGERD, AID_DEBUGGERD, AID_DEBUGGERD) != 0) {
- ALOGE("debuggerd: failed to setresuid");
+ ALOGE("debuggerd: failed to setresuid: %s", strerror(errno));
return false;
}
@@ -545,9 +592,11 @@
std::unique_ptr<BacktraceMap> backtrace_map(BacktraceMap::Create(request.pid));
int amfd = -1;
+ std::unique_ptr<std::string> amfd_data;
if (request.action == DEBUGGER_ACTION_CRASH) {
// Connect to the activity manager before dropping privileges.
amfd = activity_manager_connect();
+ amfd_data.reset(new std::string);
}
bool succeeded = false;
@@ -560,11 +609,11 @@
int crash_signal = SIGKILL;
succeeded = perform_dump(request, fd, tombstone_fd, backtrace_map.get(), siblings,
- &crash_signal, amfd);
+ &crash_signal, amfd_data.get());
if (succeeded) {
if (request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) {
if (!tombstone_path.empty()) {
- write(fd, tombstone_path.c_str(), tombstone_path.length());
+ android::base::WriteFully(fd, tombstone_path.c_str(), tombstone_path.length());
}
}
}
@@ -577,6 +626,13 @@
}
}
+ if (!attach_gdb) {
+ // Tell the Activity Manager about the crashing process. If we are
+ // waiting for gdb to attach, do not send this or Activity Manager
+ // might kill the process before anyone can attach.
+ activity_manager_write(request.pid, crash_signal, amfd, *amfd_data.get());
+ }
+
if (ptrace(PTRACE_DETACH, request.tid, 0, 0) != 0) {
ALOGE("debuggerd: ptrace detach from %d failed: %s", request.tid, strerror(errno));
}
@@ -593,9 +649,12 @@
}
// Wait for gdb, if requested.
- if (attach_gdb && succeeded) {
+ if (attach_gdb) {
wait_for_user_action(request);
+ // Now tell the activity manager about this process.
+ activity_manager_write(request.pid, crash_signal, amfd, *amfd_data.get());
+
// Tell the signal process to send SIGCONT to the target.
if (!send_signal(request.pid, 0, SIGCONT)) {
ALOGE("debuggerd: failed to resume process %d: %s", request.pid, strerror(errno));
diff --git a/debuggerd/test/dump_memory_test.cpp b/debuggerd/test/dump_memory_test.cpp
index 2addd5d..49f3690 100644
--- a/debuggerd/test/dump_memory_test.cpp
+++ b/debuggerd/test/dump_memory_test.cpp
@@ -125,7 +125,7 @@
}
log_.tfd = tombstone_fd;
- log_.amfd = -1;
+ log_.amfd_data = nullptr;
log_.crashed_tid = 12;
log_.current_tid = 12;
log_.should_retrieve_logcat = false;
diff --git a/debuggerd/test/tombstone_test.cpp b/debuggerd/test/tombstone_test.cpp
index 96b3a7a..58d640e 100644
--- a/debuggerd/test/tombstone_test.cpp
+++ b/debuggerd/test/tombstone_test.cpp
@@ -68,7 +68,8 @@
}
log_.tfd = tombstone_fd;
- log_.amfd = -1;
+ amfd_data_.clear();
+ log_.amfd_data = &amfd_data_;
log_.crashed_tid = 12;
log_.current_tid = 12;
log_.should_retrieve_logcat = false;
@@ -90,6 +91,7 @@
std::unique_ptr<BacktraceMock> backtrace_mock_;
log_t log_;
+ std::string amfd_data_;
};
TEST_F(TombstoneTest, single_map) {
@@ -117,6 +119,8 @@
#endif
ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
+ ASSERT_STREQ("", amfd_data_.c_str());
+
// Verify that the log buf is empty, and no error messages.
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -150,6 +154,8 @@
#endif
ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
+ ASSERT_STREQ("", amfd_data_.c_str());
+
// Verify that the log buf is empty, and no error messages.
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -189,6 +195,8 @@
#endif
ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
+ ASSERT_STREQ("", amfd_data_.c_str());
+
// Verify that the log buf is empty, and no error messages.
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -251,6 +259,8 @@
#endif
ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
+ ASSERT_STREQ("", amfd_data_.c_str());
+
// Verify that the log buf is empty, and no error messages.
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -305,6 +315,8 @@
#endif
ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
+ ASSERT_STREQ("", amfd_data_.c_str());
+
// Verify that the log buf is empty, and no error messages.
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -359,6 +371,8 @@
#endif
ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
+ ASSERT_STREQ("", amfd_data_.c_str());
+
// Verify that the log buf is empty, and no error messages.
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -411,6 +425,8 @@
#endif
ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
+ ASSERT_STREQ("", amfd_data_.c_str());
+
// Verify that the log buf is empty, and no error messages.
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -469,6 +485,8 @@
#endif
ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
+ ASSERT_STREQ("", amfd_data_.c_str());
+
// Verify that the log buf is empty, and no error messages.
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -501,6 +519,8 @@
#endif
ASSERT_STREQ(expected_dump, tombstone_contents.c_str());
+ ASSERT_STREQ("", amfd_data_.c_str());
+
// Verify that the log buf is empty, and no error messages.
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("6 DEBUG Cannot get siginfo for 100: Bad address\n\n", getFakeLogPrint().c_str());
@@ -562,6 +582,8 @@
<< "Signal " << si.si_signo << " is not expected to include an address.";
}
+ ASSERT_STREQ("", amfd_data_.c_str());
+
// Verify that the log buf is empty, and no error messages.
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("", getFakeLogPrint().c_str());
@@ -582,6 +604,8 @@
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("6 DEBUG cannot get siginfo: Bad address\n\n", getFakeLogPrint().c_str());
+
+ ASSERT_STREQ("", amfd_data_.c_str());
}
TEST_F(TombstoneTest, dump_log_file_error) {
@@ -596,4 +620,14 @@
ASSERT_STREQ("", getFakeLogBuf().c_str());
ASSERT_STREQ("6 DEBUG Unable to open /fake/filename: Permission denied\n\n",
getFakeLogPrint().c_str());
+
+ ASSERT_STREQ("", amfd_data_.c_str());
+}
+
+TEST_F(TombstoneTest, dump_header_info) {
+ dump_header_info(&log_);
+
+ std::string expected = "Build fingerprint: 'unknown'\nRevision: 'unknown'\n";
+ expected += android::base::StringPrintf("ABI: '%s'\n", ABI_STRING);
+ ASSERT_STREQ(expected.c_str(), amfd_data_.c_str());
}
diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
index d802c8c..fa983fa 100644
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -16,7 +16,6 @@
#define LOG_TAG "DEBUG"
-#include <arpa/inet.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
@@ -202,7 +201,7 @@
static void dump_thread_info(log_t* log, pid_t pid, pid_t tid) {
char path[64];
char threadnamebuf[1024];
- char* threadname = NULL;
+ char* threadname = nullptr;
FILE *fp;
snprintf(path, sizeof(path), "/proc/%d/comm", tid);
@@ -218,13 +217,13 @@
}
// Blacklist logd, logd.reader, logd.writer, logd.auditd, logd.control ...
static const char logd[] = "logd";
- if (!strncmp(threadname, logd, sizeof(logd) - 1)
+ if (threadname != nullptr && !strncmp(threadname, logd, sizeof(logd) - 1)
&& (!threadname[sizeof(logd) - 1] || (threadname[sizeof(logd) - 1] == '.'))) {
log->should_retrieve_logcat = false;
}
char procnamebuf[1024];
- char* procname = NULL;
+ char* procname = nullptr;
snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
if ((fp = fopen(path, "r"))) {
@@ -613,16 +612,6 @@
property_get("ro.debuggable", value, "0");
bool want_logs = (value[0] == '1');
- if (log->amfd >= 0) {
- // Activity Manager protocol: binary 32-bit network-byte-order ints for the
- // pid and signal number, followed by the raw text of the dump, culminating
- // in a zero byte that marks end-of-data.
- uint32_t datum = htonl(pid);
- TEMP_FAILURE_RETRY( write(log->amfd, &datum, 4) );
- datum = htonl(signal);
- TEMP_FAILURE_RETRY( write(log->amfd, &datum, 4) );
- }
-
_LOG(log, logtype::HEADER,
"*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");
dump_header_info(log);
@@ -640,17 +629,6 @@
if (want_logs) {
dump_logs(log, pid, 0);
}
-
- // send EOD to the Activity Manager, then wait for its ack to avoid racing ahead
- // and killing the target out from under it
- if (log->amfd >= 0) {
- uint8_t eodMarker = 0;
- TEMP_FAILURE_RETRY( write(log->amfd, &eodMarker, 1) );
- // 3 sec timeout reading the ack; we're fine if that happens
- TEMP_FAILURE_RETRY( read(log->amfd, &eodMarker, 1) );
- }
-
- return;
}
// open_tombstone - find an available tombstone slot, if any, of the
@@ -708,7 +686,7 @@
void engrave_tombstone(int tombstone_fd, BacktraceMap* map, pid_t pid, pid_t tid,
const std::set<pid_t>& siblings, int signal, int original_si_code,
- uintptr_t abort_msg_address, int amfd) {
+ uintptr_t abort_msg_address, std::string* amfd_data) {
log_t log;
log.current_tid = tid;
log.crashed_tid = tid;
@@ -719,8 +697,6 @@
}
log.tfd = tombstone_fd;
- // Preserve amfd since it can be modified through the calls below without
- // being closed.
- log.amfd = amfd;
+ log.amfd_data = amfd_data;
dump_crash(&log, map, pid, tid, siblings, signal, original_si_code, abort_msg_address);
}
diff --git a/debuggerd/tombstone.h b/debuggerd/tombstone.h
index 7f3eebe..487d950 100644
--- a/debuggerd/tombstone.h
+++ b/debuggerd/tombstone.h
@@ -34,6 +34,6 @@
/* Creates a tombstone file and writes the crash dump to it. */
void engrave_tombstone(int tombstone_fd, BacktraceMap* map, pid_t pid, pid_t tid,
const std::set<pid_t>& siblings, int signal, int original_si_code,
- uintptr_t abort_msg_address, int amfd);
+ uintptr_t abort_msg_address, std::string* amfd_data);
#endif // _DEBUGGERD_TOMBSTONE_H
diff --git a/debuggerd/utility.cpp b/debuggerd/utility.cpp
index cd252ce..bd06095 100644
--- a/debuggerd/utility.cpp
+++ b/debuggerd/utility.cpp
@@ -25,7 +25,8 @@
#include <sys/ptrace.h>
#include <sys/wait.h>
-#include <android-base/file.h>
+#include <string>
+
#include <android-base/stringprintf.h>
#include <backtrace/Backtrace.h>
#include <log/log.h>
@@ -49,7 +50,6 @@
&& log->crashed_tid != -1
&& log->current_tid != -1
&& (log->crashed_tid == log->current_tid);
- bool write_to_activitymanager = (log->amfd != -1);
char buf[512];
va_list ap;
@@ -68,12 +68,8 @@
if (write_to_logcat) {
__android_log_buf_write(LOG_ID_CRASH, ANDROID_LOG_FATAL, LOG_TAG, buf);
- if (write_to_activitymanager) {
- if (!android::base::WriteFully(log->amfd, buf, len)) {
- // timeout or other failure on write; stop informing the activity manager
- ALOGE("AM write failed: %s", strerror(errno));
- log->amfd = -1;
- }
+ if (log->amfd_data != nullptr) {
+ *log->amfd_data += buf;
}
}
}
diff --git a/debuggerd/utility.h b/debuggerd/utility.h
index ed08ddc..cd01188 100644
--- a/debuggerd/utility.h
+++ b/debuggerd/utility.h
@@ -21,6 +21,8 @@
#include <stdbool.h>
#include <sys/types.h>
+#include <string>
+
#include <backtrace/Backtrace.h>
// Figure out the abi based on defined macros.
@@ -42,10 +44,10 @@
struct log_t{
- /* tombstone file descriptor */
+ // Tombstone file descriptor.
int tfd;
- /* Activity Manager socket file descriptor */
- int amfd;
+ // Data to be sent to the Activity Manager.
+ std::string* amfd_data;
// The tid of the thread that crashed.
pid_t crashed_tid;
// The tid of the thread we are currently working with.
@@ -54,7 +56,8 @@
bool should_retrieve_logcat;
log_t()
- : tfd(-1), amfd(-1), crashed_tid(-1), current_tid(-1), should_retrieve_logcat(true) {}
+ : tfd(-1), amfd_data(nullptr), crashed_tid(-1), current_tid(-1),
+ should_retrieve_logcat(true) {}
};
// List of types of logs to simplify the logging decision in _LOG
diff --git a/include/utils/ashmem.h b/include/utils/ashmem.h
deleted file mode 100644
index 0854775..0000000
--- a/include/utils/ashmem.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* utils/ashmem.h
- **
- ** Copyright 2008 The Android Open Source Project
- **
- ** This file is dual licensed. It may be redistributed and/or modified
- ** under the terms of the Apache 2.0 License OR version 2 of the GNU
- ** General Public License.
- */
-
-#ifndef _UTILS_ASHMEM_H
-#define _UTILS_ASHMEM_H
-
-#include <linux/limits.h>
-#include <linux/ioctl.h>
-
-#define ASHMEM_NAME_LEN 256
-
-#define ASHMEM_NAME_DEF "dev/ashmem"
-
-/* Return values from ASHMEM_PIN: Was the mapping purged while unpinned? */
-#define ASHMEM_NOT_REAPED 0
-#define ASHMEM_WAS_REAPED 1
-
-/* Return values from ASHMEM_UNPIN: Is the mapping now pinned or unpinned? */
-#define ASHMEM_NOW_UNPINNED 0
-#define ASHMEM_NOW_PINNED 1
-
-#define __ASHMEMIOC 0x77
-
-#define ASHMEM_SET_NAME _IOW(__ASHMEMIOC, 1, char[ASHMEM_NAME_LEN])
-#define ASHMEM_GET_NAME _IOR(__ASHMEMIOC, 2, char[ASHMEM_NAME_LEN])
-#define ASHMEM_SET_SIZE _IOW(__ASHMEMIOC, 3, size_t)
-#define ASHMEM_GET_SIZE _IO(__ASHMEMIOC, 4)
-#define ASHMEM_SET_PROT_MASK _IOW(__ASHMEMIOC, 5, unsigned long)
-#define ASHMEM_GET_PROT_MASK _IO(__ASHMEMIOC, 6)
-#define ASHMEM_PIN _IO(__ASHMEMIOC, 7)
-#define ASHMEM_UNPIN _IO(__ASHMEMIOC, 8)
-#define ASHMEM_ISPINNED _IO(__ASHMEMIOC, 9)
-#define ASHMEM_PURGE_ALL_CACHES _IO(__ASHMEMIOC, 10)
-
-#endif /* _UTILS_ASHMEM_H */
diff --git a/libnativeloader/include/nativeloader/native_loader.h b/libnativeloader/include/nativeloader/native_loader.h
index d606a76..2a6aaec 100644
--- a/libnativeloader/include/nativeloader/native_loader.h
+++ b/libnativeloader/include/nativeloader/native_loader.h
@@ -43,6 +43,9 @@
jobject class_loader,
jstring library_path);
+__attribute__((visibility("default")))
+bool CloseNativeLibrary(void* handle);
+
#if defined(__ANDROID__)
// Look up linker namespace by class_loader. Returns nullptr if
// there is no namespace associated with the class_loader.
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index 72152e7..7d9bb56 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -241,6 +241,10 @@
#endif
}
+bool CloseNativeLibrary(void* handle) {
+ return dlclose(handle) == 0;
+}
+
#if defined(__ANDROID__)
android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
std::lock_guard<std::mutex> guard(g_namespaces_mutex);
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index 85f9415..d151ad6 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -36,7 +36,6 @@
log \
nandread \
newfs_msdos \
- ps \
sendevent \
start \
stop \
diff --git a/toolbox/ps.c b/toolbox/ps.c
deleted file mode 100644
index c129110..0000000
--- a/toolbox/ps.c
+++ /dev/null
@@ -1,340 +0,0 @@
-#include <ctype.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <cutils/sched_policy.h>
-
-static char *nexttoksep(char **strp, char *sep)
-{
- char *p = strsep(strp,sep);
- return (p == 0) ? "" : p;
-}
-static char *nexttok(char **strp)
-{
- return nexttoksep(strp, " ");
-}
-
-#define SHOW_PRIO 1
-#define SHOW_TIME 2
-#define SHOW_POLICY 4
-#define SHOW_CPU 8
-#define SHOW_MACLABEL 16
-#define SHOW_NUMERIC_UID 32
-#define SHOW_ABI 64
-
-#if __LP64__
-#define PC_WIDTH 10 /* Realistically, the top bits will be 0, so don't waste space. */
-#else
-#define PC_WIDTH (2*sizeof(uintptr_t))
-#endif
-
-static int display_flags = 0;
-static int ppid_filter = 0;
-
-static void print_exe_abi(int pid);
-
-static int ps_line(int pid, int tid)
-{
- char statline[1024];
- char cmdline[1024];
- char macline[1024];
- char user[32];
- struct stat stats;
- int r;
- char *ptr, *name, *state;
- int ppid;
- unsigned rss, vss;
- uintptr_t eip;
- unsigned utime, stime;
- int prio, nice, rtprio, sched, psr;
- struct passwd *pw;
-
- snprintf(statline, sizeof(statline), "/proc/%d", tid ? tid : pid);
- stat(statline, &stats);
-
- if (tid) {
- snprintf(statline, sizeof(statline), "/proc/%d/task/%d/stat", pid, tid);
- cmdline[0] = 0;
- snprintf(macline, sizeof(macline), "/proc/%d/task/%d/attr/current", pid, tid);
- } else {
- snprintf(statline, sizeof(statline), "/proc/%d/stat", pid);
- snprintf(cmdline, sizeof(cmdline), "/proc/%d/cmdline", pid);
- snprintf(macline, sizeof(macline), "/proc/%d/attr/current", pid);
- int fd = open(cmdline, O_RDONLY);
- if (fd == 0) {
- r = 0;
- } else {
- r = read(fd, cmdline, 1023);
- close(fd);
- if (r < 0) r = 0;
- }
- cmdline[r] = 0;
- }
-
- int fd = open(statline, O_RDONLY);
- if (fd == 0) return -1;
- r = read(fd, statline, 1023);
- close(fd);
- if (r < 0) return -1;
- statline[r] = 0;
-
- ptr = statline;
- nexttok(&ptr); // skip pid
- ptr++; // skip "("
-
- name = ptr;
- ptr = strrchr(ptr, ')'); // Skip to *last* occurence of ')',
- *ptr++ = '\0'; // and null-terminate name.
-
- ptr++; // skip " "
- state = nexttok(&ptr);
- ppid = atoi(nexttok(&ptr));
- nexttok(&ptr); // pgrp
- nexttok(&ptr); // sid
- nexttok(&ptr); // tty
- nexttok(&ptr); // tpgid
- nexttok(&ptr); // flags
- nexttok(&ptr); // minflt
- nexttok(&ptr); // cminflt
- nexttok(&ptr); // majflt
- nexttok(&ptr); // cmajflt
-#if 1
- utime = atoi(nexttok(&ptr));
- stime = atoi(nexttok(&ptr));
-#else
- nexttok(&ptr); // utime
- nexttok(&ptr); // stime
-#endif
- nexttok(&ptr); // cutime
- nexttok(&ptr); // cstime
- prio = atoi(nexttok(&ptr));
- nice = atoi(nexttok(&ptr));
- nexttok(&ptr); // threads
- nexttok(&ptr); // itrealvalue
- nexttok(&ptr); // starttime
- vss = strtoul(nexttok(&ptr), 0, 10); // vsize
- rss = strtoul(nexttok(&ptr), 0, 10); // rss
- nexttok(&ptr); // rlim
- nexttok(&ptr); // startcode
- nexttok(&ptr); // endcode
- nexttok(&ptr); // startstack
- nexttok(&ptr); // kstkesp
- eip = strtoul(nexttok(&ptr), 0, 10); // kstkeip
- nexttok(&ptr); // signal
- nexttok(&ptr); // blocked
- nexttok(&ptr); // sigignore
- nexttok(&ptr); // sigcatch
- nexttok(&ptr); // wchan
- nexttok(&ptr); // nswap
- nexttok(&ptr); // cnswap
- nexttok(&ptr); // exit signal
- psr = atoi(nexttok(&ptr)); // processor
- rtprio = atoi(nexttok(&ptr)); // rt_priority
- sched = atoi(nexttok(&ptr)); // scheduling policy
-
- nexttok(&ptr); // tty
-
- if (tid != 0) {
- ppid = pid;
- pid = tid;
- }
-
- pw = getpwuid(stats.st_uid);
- if (pw == 0 || (display_flags & SHOW_NUMERIC_UID)) {
- snprintf(user, sizeof(user), "%d", (int)stats.st_uid);
- } else {
- snprintf(user, sizeof(user), "%s", pw->pw_name);
- }
-
- if (ppid_filter != 0 && ppid != ppid_filter) {
- return 0;
- }
-
- if (display_flags & SHOW_MACLABEL) {
- fd = open(macline, O_RDONLY);
- strcpy(macline, "-");
- if (fd >= 0) {
- r = read(fd, macline, sizeof(macline)-1);
- close(fd);
- if (r > 0)
- macline[r] = 0;
- }
- printf("%-30s ", macline);
- }
-
- printf("%-9s %-5d %-5d %-6d %-5d", user, pid, ppid, vss / 1024, rss * 4);
- if (display_flags & SHOW_CPU)
- printf(" %-2d", psr);
- if (display_flags & SHOW_PRIO)
- printf(" %-5d %-5d %-5d %-5d", prio, nice, rtprio, sched);
- if (display_flags & SHOW_POLICY) {
- SchedPolicy p;
- if (get_sched_policy(pid, &p) < 0)
- printf(" un ");
- else
- printf(" %.2s ", get_sched_policy_name(p));
- }
- char path[PATH_MAX];
- snprintf(path, sizeof(path), "/proc/%d/wchan", pid);
- char wchan[10];
- fd = open(path, O_RDONLY);
- ssize_t wchan_len = read(fd, wchan, sizeof(wchan));
- if (wchan_len == -1) {
- wchan[wchan_len = 0] = '\0';
- }
- close(fd);
- printf(" %10.*s %0*" PRIxPTR " %s ", (int) wchan_len, wchan, (int) PC_WIDTH, eip, state);
- if (display_flags & SHOW_ABI) {
- print_exe_abi(pid);
- }
- printf("%s", cmdline[0] ? cmdline : name);
- if (display_flags & SHOW_TIME)
- printf(" (u:%d, s:%d)", utime, stime);
-
- printf("\n");
- return 0;
-}
-
-static void print_exe_abi(int pid)
-{
- int fd, r;
- char exeline[1024];
-
- snprintf(exeline, sizeof(exeline), "/proc/%d/exe", pid);
- fd = open(exeline, O_RDONLY);
- if (fd == 0) {
- printf(" ");
- return;
- }
- r = read(fd, exeline, 5 /* 4 byte ELFMAG + 1 byte EI_CLASS */);
- close(fd);
- if (r < 0) {
- printf(" ");
- return;
- }
- if (memcmp("\177ELF", exeline, 4) != 0) {
- printf("?? ");
- return;
- }
- switch (exeline[4]) {
- case 1:
- printf("32 ");
- return;
- case 2:
- printf("64 ");
- return;
- default:
- printf("?? ");
- return;
- }
-}
-
-void ps_threads(int pid)
-{
- char tmp[128];
- DIR *d;
- struct dirent *de;
-
- snprintf(tmp,sizeof(tmp),"/proc/%d/task",pid);
- d = opendir(tmp);
- if (d == 0) return;
-
- while ((de = readdir(d)) != 0) {
- if (isdigit(de->d_name[0])) {
- int tid = atoi(de->d_name);
- if (tid == pid) continue;
- ps_line(pid, tid);
- }
- }
- closedir(d);
-}
-
-int ps_main(int argc, char **argv)
-{
- DIR *d;
- struct dirent *de;
- int pidfilter = 0;
- int threads = 0;
-
- while (argc > 1) {
- if (!strcmp(argv[1], "-t")) {
- threads = 1;
- } else if (!strcmp(argv[1], "-n")) {
- display_flags |= SHOW_NUMERIC_UID;
- } else if (!strcmp(argv[1], "-x")) {
- display_flags |= SHOW_TIME;
- } else if (!strcmp(argv[1], "-Z")) {
- display_flags |= SHOW_MACLABEL;
- } else if (!strcmp(argv[1], "-P")) {
- display_flags |= SHOW_POLICY;
- } else if (!strcmp(argv[1], "-p")) {
- display_flags |= SHOW_PRIO;
- } else if (!strcmp(argv[1], "-c")) {
- display_flags |= SHOW_CPU;
- } else if (!strcmp(argv[1], "--abi")) {
- display_flags |= SHOW_ABI;
- } else if (!strcmp(argv[1], "--ppid")) {
- if (argc < 3) {
- /* Bug 26554285: Use printf because some apps require at least
- * one line of output to stdout even for errors.
- */
- printf("no ppid\n");
- return 1;
- }
- ppid_filter = atoi(argv[2]);
- if (ppid_filter == 0) {
- /* Bug 26554285: Use printf because some apps require at least
- * one line of output to stdout even for errors.
- */
- printf("bad ppid '%s'\n", argv[2]);
- return 1;
- }
- argc--;
- argv++;
- } else {
- pidfilter = atoi(argv[1]);
- if (pidfilter == 0) {
- /* Bug 26554285: Use printf because some apps require at least
- * one line of output to stdout even for errors.
- */
- printf("bad pid '%s'\n", argv[1]);
- return 1;
- }
- }
- argc--;
- argv++;
- }
-
- if (display_flags & SHOW_MACLABEL) {
- printf("LABEL ");
- }
- printf("USER PID PPID VSIZE RSS %s%s %sWCHAN %*s %sNAME\n",
- (display_flags&SHOW_CPU)?"CPU ":"",
- (display_flags&SHOW_PRIO)?"PRIO NICE RTPRI SCHED ":"",
- (display_flags&SHOW_POLICY)?"PCY " : "",
- (int) PC_WIDTH, "PC",
- (display_flags&SHOW_ABI)?"ABI " : "");
-
- d = opendir("/proc");
- if (d == 0) return -1;
-
- while ((de = readdir(d)) != 0) {
- if (isdigit(de->d_name[0])) {
- int pid = atoi(de->d_name);
- if (!pidfilter || (pidfilter == pid)) {
- ps_line(pid, 0);
- if (threads) ps_threads(pid);
- }
- }
- }
- closedir(d);
- return 0;
-}