Merge "toolbox: turn on -Werror"
diff --git a/adb/services.c b/adb/services.c
index 5b63a43..2d3423b 100644
--- a/adb/services.c
+++ b/adb/services.c
@@ -460,7 +460,7 @@
snprintf(serial, sizeof(serial), "%s:%d", hostbuf, port);
- fd = socket_network_client(hostbuf, port, SOCK_STREAM);
+ fd = socket_network_client_timeout(hostbuf, port, SOCK_STREAM, 10);
if (fd < 0) {
snprintf(buffer, buffer_size, "unable to connect to %s:%d", host, port);
return;
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 4033b72..ba4306f 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -169,6 +169,8 @@
/* normally provided by <cutils/sockets.h> */
extern int socket_loopback_client(int port, int type);
extern int socket_network_client(const char *host, int port, int type);
+extern int socket_network_client_timeout(const char *host, int port, int type,
+ int timeout);
extern int socket_loopback_server(int port, int type);
extern int socket_inaddr_any_server(int port, int type);
diff --git a/adb/sysdeps_win32.c b/adb/sysdeps_win32.c
index b0cb048..29f58ec 100644
--- a/adb/sysdeps_win32.c
+++ b/adb/sysdeps_win32.c
@@ -701,6 +701,13 @@
}
+int socket_network_client_timeout(const char *host, int port, int type, int timeout)
+{
+ // TODO: implement timeouts for Windows.
+ return socket_network_client(host, port, type);
+}
+
+
int socket_inaddr_any_server(int port, int type)
{
FH f = _fh_alloc( &_fh_socket_class );
diff --git a/adf/libadf/adf.c b/adf/libadf/adf.c
index 871629e..1d19152 100644
--- a/adf/libadf/adf.c
+++ b/adf/libadf/adf.c
@@ -768,7 +768,7 @@
const __u32 *formats, size_t n_formats,
adf_id_t *interface, adf_id_t *overlay_engine)
{
- adf_id_t *intfs;
+ adf_id_t *intfs = NULL;
ssize_t n_intfs = adf_interfaces(dev, &intfs);
if (n_intfs < 0)
diff --git a/debuggerd/crasher.c b/debuggerd/crasher.c
index 01ce0be..4721da9 100644
--- a/debuggerd/crasher.c
+++ b/debuggerd/crasher.c
@@ -144,6 +144,9 @@
close(pipe_fds[0]);
write(pipe_fds[1], "oops", 4);
return EXIT_SUCCESS;
+ } else if (!strcmp(arg, "SIGTRAP")) {
+ raise(SIGTRAP);
+ return EXIT_SUCCESS;
} else if (!strcmp(arg, "heap-usage")) {
abuse_heap();
}
@@ -164,6 +167,7 @@
fprintf(stderr, " LOG_ALWAYS_FATAL_IF call LOG_ALWAYS_FATAL\n");
fprintf(stderr, " SIGPIPE cause a SIGPIPE\n");
fprintf(stderr, " SIGSEGV cause a SIGSEGV (synonym: crash)\n");
+ fprintf(stderr, " SIGTRAP cause a SIGTRAP\n");
fprintf(stderr, "prefix any of the above with 'thread-' to not run\n");
fprintf(stderr, "on the process' main thread.\n");
return EXIT_SUCCESS;
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index 76bd7a3..3726c38 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -54,97 +54,56 @@
int32_t original_si_code;
};
-static int write_string(const char* file, const char* string) {
- int len;
- int fd;
- ssize_t amt;
- fd = open(file, O_RDWR);
- len = strlen(string);
- if (fd < 0)
- return -errno;
- amt = write(fd, string, len);
- close(fd);
- return amt >= 0 ? 0 : -errno;
-}
-
-static void init_debug_led() {
- // trout leds
- write_string("/sys/class/leds/red/brightness", "0");
- write_string("/sys/class/leds/green/brightness", "0");
- write_string("/sys/class/leds/blue/brightness", "0");
- write_string("/sys/class/leds/red/device/blink", "0");
- // sardine leds
- write_string("/sys/class/leds/left/cadence", "0,0");
-}
-
-static void enable_debug_led() {
- // trout leds
- write_string("/sys/class/leds/red/brightness", "255");
- // sardine leds
- write_string("/sys/class/leds/left/cadence", "1,0");
-}
-
-static void disable_debug_led() {
- // trout leds
- write_string("/sys/class/leds/red/brightness", "0");
- // sardine leds
- write_string("/sys/class/leds/left/cadence", "0,0");
-}
-
static void wait_for_user_action(pid_t pid) {
- // First log a helpful message
+ // Find out the name of the process that crashed.
+ char path[64];
+ snprintf(path, sizeof(path), "/proc/%d/exe", pid);
+
+ char exe[PATH_MAX];
+ int count;
+ if ((count = readlink(path, exe, sizeof(exe) - 1)) == -1) {
+ LOG("readlink('%s') failed: %s", path, strerror(errno));
+ strlcpy(exe, "unknown", sizeof(exe));
+ } else {
+ exe[count] = '\0';
+ }
+
+ // Turn "/system/bin/app_process" into "app_process".
+ // gdbserver doesn't cope with full paths (though we should fix that
+ // and remove this).
+ char* name = strrchr(exe, '/');
+ if (name == NULL) {
+ name = exe; // No '/' found.
+ } else {
+ ++name; // Skip the '/'.
+ }
+
+ // Explain how to attach the debugger.
LOG( "********************************************************\n"
- "* Process %d has been suspended while crashing. To\n"
- "* attach gdbserver for a gdb connection on port 5039\n"
+ "* Process %d has been suspended while crashing.\n"
+ "* To attach gdbserver for a gdb connection on port 5039\n"
"* and start gdbclient:\n"
"*\n"
- "* gdbclient app_process :5039 %d\n"
+ "* gdbclient %s :5039 %d\n"
"*\n"
- "* Wait for gdb to start, then press HOME or VOLUME DOWN key\n"
+ "* Wait for gdb to start, then press the VOLUME DOWN key\n"
"* to let the process continue crashing.\n"
"********************************************************\n",
- pid, pid);
+ pid, name, pid);
- // wait for HOME or VOLUME DOWN key
+ // Wait for VOLUME DOWN.
if (init_getevent() == 0) {
- int ms = 1200 / 10;
- int dit = 1;
- int dah = 3*dit;
- int _ = -dit;
- int ___ = 3*_;
- int _______ = 7*_;
- const int codes[] = {
- dit,_,dit,_,dit,___,dah,_,dah,_,dah,___,dit,_,dit,_,dit,_______
- };
- size_t s = 0;
- input_event e;
- bool done = false;
- init_debug_led();
- enable_debug_led();
- do {
- int timeout = abs(codes[s]) * ms;
- int res = get_event(&e, timeout);
- if (res == 0) {
- if (e.type == EV_KEY
- && (e.code == KEY_HOME || e.code == KEY_VOLUMEDOWN)
- && e.value == 0) {
- done = true;
- }
- } else if (res == 1) {
- if (++s >= sizeof(codes)/sizeof(*codes))
- s = 0;
- if (codes[s] > 0) {
- enable_debug_led();
- } else {
- disable_debug_led();
+ while (true) {
+ input_event e;
+ if (get_event(&e, -1) == 0) {
+ if (e.type == EV_KEY && e.code == KEY_VOLUMEDOWN && e.value == 0) {
+ break;
}
}
- } while (!done);
+ }
uninit_getevent();
}
- // don't forget to turn debug led off
- disable_debug_led();
LOG("debuggerd resuming process %d", pid);
}
@@ -322,15 +281,16 @@
}
break;
- case SIGILL:
case SIGABRT:
case SIGBUS:
case SIGFPE:
- case SIGSEGV:
+ case SIGILL:
case SIGPIPE:
+ case SIGSEGV:
#ifdef SIGSTKFLT
case SIGSTKFLT:
#endif
+ case SIGTRAP:
XLOG("stopped -- fatal signal\n");
// Send a SIGSTOP to the process to make all of
// the non-signaled threads stop moving. Without
@@ -406,38 +366,36 @@
}
static int do_server() {
- int s;
- struct sigaction act;
- int logsocket = -1;
-
- // debuggerd crashes can't be reported to debuggerd. Reset all of the
- // crash handlers.
- signal(SIGILL, SIG_DFL);
+ // debuggerd crashes can't be reported to debuggerd.
+ // Reset all of the crash handlers.
signal(SIGABRT, SIG_DFL);
signal(SIGBUS, SIG_DFL);
signal(SIGFPE, SIG_DFL);
+ signal(SIGILL, SIG_DFL);
signal(SIGSEGV, SIG_DFL);
#ifdef SIGSTKFLT
signal(SIGSTKFLT, SIG_DFL);
#endif
+ signal(SIGTRAP, SIG_DFL);
// Ignore failed writes to closed sockets
signal(SIGPIPE, SIG_IGN);
- logsocket = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_DGRAM);
+ int logsocket = socket_local_client("logd", ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_DGRAM);
if (logsocket < 0) {
logsocket = -1;
} else {
fcntl(logsocket, F_SETFD, FD_CLOEXEC);
}
+ struct sigaction act;
act.sa_handler = SIG_DFL;
sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask,SIGCHLD);
act.sa_flags = SA_NOCLDWAIT;
sigaction(SIGCHLD, &act, 0);
- s = socket_local_server(DEBUGGER_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
+ int s = socket_local_server(DEBUGGER_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
if (s < 0)
return 1;
fcntl(s, F_SETFD, FD_CLOEXEC);
diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
index d0cefc7..1a00146 100755
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -31,9 +31,10 @@
#include <private/android_filesystem_config.h>
+#include <cutils/properties.h>
#include <log/log.h>
#include <log/logger.h>
-#include <cutils/properties.h>
+#include <log/logprint.h>
#include <backtrace/Backtrace.h>
#include <backtrace/BacktraceMap.h>
@@ -57,10 +58,10 @@
static bool signal_has_si_addr(int sig) {
switch (sig) {
- case SIGILL:
- case SIGFPE:
- case SIGSEGV:
case SIGBUS:
+ case SIGFPE:
+ case SIGILL:
+ case SIGSEGV:
return true;
default:
return false;
@@ -69,16 +70,17 @@
static const char* get_signame(int sig) {
switch(sig) {
- case SIGILL: return "SIGILL";
case SIGABRT: return "SIGABRT";
case SIGBUS: return "SIGBUS";
case SIGFPE: return "SIGFPE";
- case SIGSEGV: return "SIGSEGV";
+ case SIGILL: return "SIGILL";
case SIGPIPE: return "SIGPIPE";
+ case SIGSEGV: return "SIGSEGV";
#if defined(SIGSTKFLT)
case SIGSTKFLT: return "SIGSTKFLT";
#endif
case SIGSTOP: return "SIGSTOP";
+ case SIGTRAP: return "SIGTRAP";
default: return "?";
}
}
@@ -459,6 +461,8 @@
// that don't match the specified pid, and writes them to the tombstone file.
//
// If "tail" is set, we only print the last few lines.
+static EventTagMap* g_eventTagMap = NULL;
+
static void dump_log_file(log_t* log, pid_t pid, const char* filename,
unsigned int tail) {
bool first = true;
@@ -521,7 +525,28 @@
if (!hdr_size) {
hdr_size = sizeof(log_entry.entry_v1);
}
- char* msg = (char *)log_entry.buf + hdr_size;
+ char* msg = reinterpret_cast<char*>(log_entry.buf) + hdr_size;
+
+ char timeBuf[32];
+ time_t sec = static_cast<time_t>(entry->sec);
+ struct tm tmBuf;
+ struct tm* ptm;
+ ptm = localtime_r(&sec, &tmBuf);
+ strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", ptm);
+
+ if (log_entry.id() == LOG_ID_EVENTS) {
+ if (!g_eventTagMap) {
+ g_eventTagMap = android_openEventTagMap(EVENT_TAG_MAP_FILE);
+ }
+ AndroidLogEntry e;
+ char buf[512];
+ android_log_processBinaryLogBuffer(entry, &e, g_eventTagMap, buf, sizeof(buf));
+ _LOG(log, 0, "%s.%03d %5d %5d %c %-8s: %s\n",
+ timeBuf, entry->nsec / 1000000, entry->pid, entry->tid,
+ 'I', e.tag, e.message);
+ continue;
+ }
+
unsigned char prio = msg[0];
char* tag = msg + 1;
msg = tag + strlen(tag) + 1;
@@ -534,13 +559,6 @@
char prioChar = (prio < strlen(kPrioChars) ? kPrioChars[prio] : '?');
- char timeBuf[32];
- time_t sec = static_cast<time_t>(entry->sec);
- struct tm tmBuf;
- struct tm* ptm;
- ptm = localtime_r(&sec, &tmBuf);
- strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", ptm);
-
// Look for line breaks ('\n') and display each text line
// on a separate line, prefixed with the header, like logcat does.
do {
@@ -565,6 +583,7 @@
static void dump_logs(log_t* log, pid_t pid, unsigned tail) {
dump_log_file(log, pid, "system", tail);
dump_log_file(log, pid, "main", tail);
+ dump_log_file(log, pid, "events", tail);
}
static void dump_abort_message(Backtrace* backtrace, log_t* log, uintptr_t address) {
diff --git a/fastboot/fastboot.c b/fastboot/fastboot.c
index 3a140ab..9c04c21 100644
--- a/fastboot/fastboot.c
+++ b/fastboot/fastboot.c
@@ -32,6 +32,7 @@
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
+#include <inttypes.h>
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
@@ -576,7 +577,7 @@
if (!status) {
limit = strtoul(response, NULL, 0);
if (limit > 0) {
- fprintf(stderr, "target reported max download size of %lld bytes\n",
+ fprintf(stderr, "target reported max download size of %" PRId64 " bytes\n",
limit);
}
}
diff --git a/include/cutils/sockets.h b/include/cutils/sockets.h
index 19cae0c..daf43ec 100644
--- a/include/cutils/sockets.h
+++ b/include/cutils/sockets.h
@@ -86,6 +86,8 @@
extern int socket_loopback_client(int port, int type);
extern int socket_network_client(const char *host, int port, int type);
+extern int socket_network_client_timeout(const char *host, int port, int type,
+ int timeout);
extern int socket_loopback_server(int port, int type);
extern int socket_local_server(const char *name, int namespaceId, int type);
extern int socket_local_server_bind(int s, const char *name, int namespaceId);
diff --git a/include/netd_client/FwmarkCommands.h b/include/netd_client/FwmarkCommands.h
new file mode 100644
index 0000000..0d22f02
--- /dev/null
+++ b/include/netd_client/FwmarkCommands.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NETD_CLIENT_FWMARK_COMMANDS_H
+#define NETD_CLIENT_FWMARK_COMMANDS_H
+
+#include <stdint.h>
+
+// Commands sent from clients to the fwmark server to mark sockets (i.e., set their SO_MARK).
+const uint8_t FWMARK_COMMAND_ON_CREATE = 0;
+const uint8_t FWMARK_COMMAND_ON_CONNECT = 1;
+const uint8_t FWMARK_COMMAND_ON_ACCEPT = 2;
+const uint8_t FWMARK_COMMAND_SELECT_NETWORK = 3;
+const uint8_t FWMARK_COMMAND_PROTECT_FROM_VPN = 4;
+
+#endif // NETD_CLIENT_FWMARK_COMMANDS_H
diff --git a/init/builtins.c b/init/builtins.c
index d973a6b..d9f7bbe 100644
--- a/init/builtins.c
+++ b/init/builtins.c
@@ -33,7 +33,6 @@
#include <linux/loop.h>
#include <cutils/partition_utils.h>
#include <cutils/android_reboot.h>
-#include <sys/system_properties.h>
#include <fs_mgr.h>
#include <selinux/selinux.h>
diff --git a/init/init.c b/init/init.c
index fc20198..1538aa6 100644
--- a/init/init.c
+++ b/init/init.c
@@ -46,8 +46,6 @@
#include <private/android_filesystem_config.h>
#include <termios.h>
-#include <sys/system_properties.h>
-
#include "devices.h"
#include "init.h"
#include "log.h"
diff --git a/init/init_parser.c b/init/init_parser.c
index 02e5bdc..7800082 100644
--- a/init/init_parser.c
+++ b/init/init_parser.c
@@ -760,7 +760,7 @@
break;
case K_setenv: { /* name value */
struct svcenvinfo *ei;
- if (nargs < 2) {
+ if (nargs < 3) {
parse_error(state, "setenv option requires name and value arguments\n");
break;
}
diff --git a/init/property_service.c b/init/property_service.c
index 7e8d79a..4bcf883 100644
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -90,6 +90,7 @@
{ "log.", AID_SHELL, 0 },
{ "service.adb.root", AID_SHELL, 0 },
{ "service.adb.tcp.port", AID_SHELL, 0 },
+ { "persist.logd.size",AID_SYSTEM, 0 },
{ "persist.sys.", AID_SYSTEM, 0 },
{ "persist.service.", AID_SYSTEM, 0 },
{ "persist.security.", AID_SYSTEM, 0 },
diff --git a/libbacktrace/Android.build.mk b/libbacktrace/Android.build.mk
index 3c80cc2..dc73f9f 100644
--- a/libbacktrace/Android.build.mk
+++ b/libbacktrace/Android.build.mk
@@ -60,7 +60,11 @@
$($(module)_ldlibs_$(build_type)) \
ifeq ($(build_type),target)
- include external/stlport/libstlport.mk
+ ifneq ($($(module)_libc++),)
+ include external/libcxx/libcxx.mk
+ else
+ include external/stlport/libstlport.mk
+ endif
include $(BUILD_$(build_target))
endif
diff --git a/libbacktrace/Android.mk b/libbacktrace/Android.mk
index fa79221..5a0bc7f 100755
--- a/libbacktrace/Android.mk
+++ b/libbacktrace/Android.mk
@@ -72,6 +72,50 @@
build_type := host
include $(LOCAL_PATH)/Android.build.mk
+# Don't build for unbundled branches
+ifeq (,$(TARGET_BUILD_APPS))
+#-------------------------------------------------------------------------
+# The libbacktrace library (libc++)
+#-------------------------------------------------------------------------
+libbacktrace_libc++_src_files := \
+ BacktraceImpl.cpp \
+ BacktraceMap.cpp \
+ BacktraceThread.cpp \
+ thread_utils.c \
+
+libbacktrace_libc++_shared_libraries_target := \
+ libcutils \
+ libgccdemangle \
+
+libbacktrace_libc++_src_files += \
+ UnwindCurrent.cpp \
+ UnwindMap.cpp \
+ UnwindPtrace.cpp \
+
+libbacktrace_libc++_c_includes := \
+ external/libunwind/include \
+
+libbacktrace_libc++_shared_libraries := \
+ libunwind \
+ libunwind-ptrace \
+
+libbacktrace_libc++_shared_libraries_host := \
+ liblog \
+
+libbacktrace_libc++_static_libraries_host := \
+ libcutils \
+
+libbacktrace_libc++_libc++ := true
+
+module := libbacktrace_libc++
+module_tag := optional
+build_type := target
+build_target := SHARED_LIBRARY
+include $(LOCAL_PATH)/Android.build.mk
+build_type := host
+include $(LOCAL_PATH)/Android.build.mk
+endif
+
#-------------------------------------------------------------------------
# The libbacktrace_test library needed by backtrace_test.
#-------------------------------------------------------------------------
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index 945ebdd..e1d6f49 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -27,13 +27,6 @@
hashmap.c \
atomic.c.arm \
native_handle.c \
- socket_inaddr_any_server.c \
- socket_local_client.c \
- socket_local_server.c \
- socket_loopback_client.c \
- socket_loopback_server.c \
- socket_network_client.c \
- sockets.c \
config_utils.c \
cpu_info.c \
load_file.c \
@@ -67,7 +60,15 @@
ifneq ($(WINDOWS_HOST_ONLY),1)
commonSources += \
fs.c \
- multiuser.c
+ multiuser.c \
+ socket_inaddr_any_server.c \
+ socket_local_client.c \
+ socket_local_server.c \
+ socket_loopback_client.c \
+ socket_loopback_server.c \
+ socket_network_client.c \
+ sockets.c \
+
endif
diff --git a/libcutils/socket_network_client.c b/libcutils/socket_network_client.c
index c52013d..4826033 100644
--- a/libcutils/socket_network_client.c
+++ b/libcutils/socket_network_client.c
@@ -15,18 +15,17 @@
*/
#include <errno.h>
+#include <fcntl.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#ifndef HAVE_WINSOCK
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
-#endif
#include <cutils/sockets.h>
@@ -36,27 +35,92 @@
*/
int socket_network_client(const char *host, int port, int type)
{
+ return socket_network_client_timeout(host, port, type, 0);
+}
+
+/* Connect to port on the IP interface. type is SOCK_STREAM or SOCK_DGRAM.
+ * timeout in seconds return is a file descriptor or -1 on error
+ */
+int socket_network_client_timeout(const char *host, int port, int type, int timeout)
+{
struct hostent *hp;
struct sockaddr_in addr;
+ socklen_t alen;
int s;
+ int flags = 0, error = 0, ret = 0;
+ fd_set rset, wset;
+ socklen_t len = sizeof(error);
+ struct timeval ts;
+
+ ts.tv_sec = timeout;
+ ts.tv_usec = 0;
hp = gethostbyname(host);
- if(hp == 0) return -1;
-
+ if (hp == 0) return -1;
+
memset(&addr, 0, sizeof(addr));
addr.sin_family = hp->h_addrtype;
addr.sin_port = htons(port);
memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
s = socket(hp->h_addrtype, type, 0);
- if(s < 0) return -1;
+ if (s < 0) return -1;
- if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ if ((flags = fcntl(s, F_GETFL, 0)) < 0) {
+ close(s);
+ return -1;
+ }
+
+ if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) {
+ close(s);
+ return -1;
+ }
+
+ if ((ret = connect(s, (struct sockaddr *) &addr, sizeof(addr))) < 0) {
+ if (errno != EINPROGRESS) {
+ close(s);
+ return -1;
+ }
+ }
+
+ if (ret == 0)
+ goto done;
+
+ FD_ZERO(&rset);
+ FD_SET(s, &rset);
+ wset = rset;
+
+ if ((ret = select(s + 1, &rset, &wset, NULL, (timeout) ? &ts : NULL)) < 0) {
+ close(s);
+ return -1;
+ }
+ if (ret == 0) { // we had a timeout
+ errno = ETIMEDOUT;
+ close(s);
+ return -1;
+ }
+
+ if (FD_ISSET(s, &rset) || FD_ISSET(s, &wset)) {
+ if (getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
+ close(s);
+ return -1;
+ }
+ } else {
+ close(s);
+ return -1;
+ }
+
+ if (error) { // check if we had a socket error
+ errno = error;
+ close(s);
+ return -1;
+ }
+
+done:
+ if (fcntl(s, F_SETFL, flags) < 0) {
close(s);
return -1;
}
return s;
-
}
-
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index ec35e45..393e2cd 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -544,7 +544,7 @@
EXPECT_LE(LOGGER_ENTRY_MAX_PAYLOAD - sizeof(big_payload_tag),
static_cast<size_t>(max_len));
- EXPECT_EQ(ret, max_len + sizeof(big_payload_tag));
+ EXPECT_EQ(ret, max_len + static_cast<ssize_t>(sizeof(big_payload_tag)));
}
TEST(liblog, dual_reader) {
diff --git a/libnetd_client/Android.mk b/libnetd_client/Android.mk
new file mode 100644
index 0000000..2b75626
--- /dev/null
+++ b/libnetd_client/Android.mk
@@ -0,0 +1,22 @@
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libnetd_client
+LOCAL_SRC_FILES := FwmarkClient.cpp NetdClient.cpp
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/libnetd_client/FwmarkClient.cpp b/libnetd_client/FwmarkClient.cpp
new file mode 100644
index 0000000..e360b4e
--- /dev/null
+++ b/libnetd_client/FwmarkClient.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FwmarkClient.h"
+
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+namespace {
+
+const sockaddr_un FWMARK_SERVER_PATH = {AF_UNIX, "/dev/socket/fwmarkd"};
+
+} // namespace
+
+bool FwmarkClient::shouldSetFwmark(int sockfd, const sockaddr* addr) {
+ return sockfd >= 0 && addr && (addr->sa_family == AF_INET || addr->sa_family == AF_INET6) &&
+ !getenv("ANDROID_NO_USE_FWMARK_CLIENT");
+}
+
+FwmarkClient::FwmarkClient() : mChannel(-1) {
+}
+
+FwmarkClient::~FwmarkClient() {
+ if (mChannel >= 0) {
+ // We don't care about errors while closing the channel, so restore any previous error.
+ int error = errno;
+ close(mChannel);
+ errno = error;
+ }
+}
+
+bool FwmarkClient::send(void* data, size_t len, int fd) {
+ mChannel = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (mChannel == -1) {
+ return false;
+ }
+
+ if (TEMP_FAILURE_RETRY(connect(mChannel, reinterpret_cast<const sockaddr*>(&FWMARK_SERVER_PATH),
+ sizeof(FWMARK_SERVER_PATH))) == -1) {
+ // If we are unable to connect to the fwmark server, assume there's no error. This protects
+ // against future changes if the fwmark server goes away.
+ errno = 0;
+ return true;
+ }
+
+ iovec iov;
+ iov.iov_base = data;
+ iov.iov_len = len;
+
+ msghdr message;
+ memset(&message, 0, sizeof(message));
+ message.msg_iov = &iov;
+ message.msg_iovlen = 1;
+
+ union {
+ cmsghdr cmh;
+ char cmsg[CMSG_SPACE(sizeof(fd))];
+ } cmsgu;
+
+ memset(cmsgu.cmsg, 0, sizeof(cmsgu.cmsg));
+ message.msg_control = cmsgu.cmsg;
+ message.msg_controllen = sizeof(cmsgu.cmsg);
+
+ cmsghdr* const cmsgh = CMSG_FIRSTHDR(&message);
+ cmsgh->cmsg_len = CMSG_LEN(sizeof(fd));
+ cmsgh->cmsg_level = SOL_SOCKET;
+ cmsgh->cmsg_type = SCM_RIGHTS;
+ memcpy(CMSG_DATA(cmsgh), &fd, sizeof(fd));
+
+ if (TEMP_FAILURE_RETRY(sendmsg(mChannel, &message, 0)) == -1) {
+ return false;
+ }
+
+ int error = 0;
+ if (TEMP_FAILURE_RETRY(recv(mChannel, &error, sizeof(error), 0)) == -1) {
+ return false;
+ }
+
+ errno = error;
+ return !error;
+}
diff --git a/libnetd_client/FwmarkClient.h b/libnetd_client/FwmarkClient.h
new file mode 100644
index 0000000..4cf0cc0
--- /dev/null
+++ b/libnetd_client/FwmarkClient.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NETD_CLIENT_FWMARK_CLIENT_H
+#define NETD_CLIENT_FWMARK_CLIENT_H
+
+#include <sys/socket.h>
+
+class FwmarkClient {
+public:
+ // Returns true if |sockfd| should be sent to the fwmark server to have its SO_MARK set.
+ static bool shouldSetFwmark(int sockfd, const sockaddr* addr);
+
+ FwmarkClient();
+ ~FwmarkClient();
+
+ // Sends |data| to the fwmark server, along with |fd| as ancillary data using cmsg(3).
+ // Returns true on success.
+ bool send(void* data, size_t len, int fd);
+
+private:
+ int mChannel;
+};
+
+#endif // NETD_CLIENT_INCLUDE_FWMARK_CLIENT_H
diff --git a/libnetd_client/NetdClient.cpp b/libnetd_client/NetdClient.cpp
new file mode 100644
index 0000000..8deea1e
--- /dev/null
+++ b/libnetd_client/NetdClient.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FwmarkClient.h"
+#include "netd_client/FwmarkCommands.h"
+
+#include <sys/socket.h>
+#include <unistd.h>
+
+namespace {
+
+int closeFdAndRestoreErrno(int fd) {
+ int error = errno;
+ close(fd);
+ errno = error;
+ return -1;
+}
+
+typedef int (*ConnectFunctionType)(int, const sockaddr*, socklen_t);
+typedef int (*AcceptFunctionType)(int, sockaddr*, socklen_t*);
+
+ConnectFunctionType libcConnect = 0;
+AcceptFunctionType libcAccept = 0;
+
+int netdClientConnect(int sockfd, const sockaddr* addr, socklen_t addrlen) {
+ if (FwmarkClient::shouldSetFwmark(sockfd, addr)) {
+ char data[] = {FWMARK_COMMAND_ON_CONNECT};
+ if (!FwmarkClient().send(data, sizeof(data), sockfd)) {
+ return -1;
+ }
+ }
+ return libcConnect(sockfd, addr, addrlen);
+}
+
+int netdClientAccept(int sockfd, sockaddr* addr, socklen_t* addrlen) {
+ int acceptedSocket = libcAccept(sockfd, addr, addrlen);
+ if (acceptedSocket == -1) {
+ return -1;
+ }
+ sockaddr socketAddress;
+ if (!addr) {
+ socklen_t socketAddressLen = sizeof(socketAddress);
+ if (getsockname(acceptedSocket, &socketAddress, &socketAddressLen) == -1) {
+ return closeFdAndRestoreErrno(acceptedSocket);
+ }
+ addr = &socketAddress;
+ }
+ if (FwmarkClient::shouldSetFwmark(acceptedSocket, addr)) {
+ char data[] = {FWMARK_COMMAND_ON_ACCEPT};
+ if (!FwmarkClient().send(data, sizeof(data), acceptedSocket)) {
+ return closeFdAndRestoreErrno(acceptedSocket);
+ }
+ }
+ return acceptedSocket;
+}
+
+} // namespace
+
+extern "C" void netdClientInitConnect(ConnectFunctionType* function) {
+ if (function && *function) {
+ libcConnect = *function;
+ *function = netdClientConnect;
+ }
+}
+
+extern "C" void netdClientInitAccept(AcceptFunctionType* function) {
+ if (function && *function) {
+ libcAccept = *function;
+ *function = netdClientAccept;
+ }
+}
diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc
index 3082216..2eb9318 100644
--- a/libziparchive/zip_archive_test.cc
+++ b/libziparchive/zip_archive_test.cc
@@ -209,7 +209,8 @@
sizeof(kATxtContents)));
// Assert that the total length of the file is sane
- ASSERT_EQ(data_size + sizeof(kATxtContents), lseek64(fd, 0, SEEK_END));
+ ASSERT_EQ(data_size + static_cast<ssize_t>(sizeof(kATxtContents)),
+ lseek64(fd, 0, SEEK_END));
close(fd);
}
@@ -247,4 +248,3 @@
return RUN_ALL_TESTS();
}
-
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index db4fddd..ed2c241 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -623,20 +623,21 @@
}
if (!devices) {
- devices = new log_device_t("main", false, 'm');
+ dev = devices = new log_device_t("main", false, 'm');
android::g_devCount = 1;
if (android_name_to_log_id("system") == LOG_ID_SYSTEM) {
- devices->next = new log_device_t("system", false, 's');
+ dev = dev->next = new log_device_t("system", false, 's');
android::g_devCount++;
}
if (android_name_to_log_id("crash") == LOG_ID_CRASH) {
- if (devices->next) {
- devices->next->next = new log_device_t("crash", false, 'c');
- } else {
- devices->next = new log_device_t("crash", false, 'c');
- }
+ dev = dev->next = new log_device_t("crash", false, 'c');
android::g_devCount++;
}
+ if (android_name_to_log_id("events") == LOG_ID_EVENTS) {
+ dev = dev->next = new log_device_t("events", true, 'e');
+ android::g_devCount++;
+ needBinary = true;
+ }
}
if (android::g_logRotateSizeKBytes != 0
diff --git a/logd/Android.mk b/logd/Android.mk
index 9f4c64f..188511f 100644
--- a/logd/Android.mk
+++ b/logd/Android.mk
@@ -17,7 +17,8 @@
LogStatistics.cpp \
LogWhiteBlackList.cpp \
libaudit.c \
- LogAudit.cpp
+ LogAudit.cpp \
+ event.logtags
LOCAL_SHARED_LIBRARIES := \
libsysutils \
@@ -25,7 +26,7 @@
libcutils \
libutils
-LOCAL_CFLAGS := -Werror
+LOCAL_CFLAGS := -Werror $(shell sed -n 's/^\([0-9]*\)[ \t]*auditd[ \t].*/-DAUDITD_LOG_TAG=\1/p' $(LOCAL_PATH)/event.logtags)
include $(BUILD_EXECUTABLE)
diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp
index add0f0e..0651a92 100644
--- a/logd/LogAudit.cpp
+++ b/logd/LogAudit.cpp
@@ -54,9 +54,6 @@
return true;
}
-#define AUDIT_LOG_ID LOG_ID_MAIN
-#define AUDIT_LOG_PRIO ANDROID_LOG_WARN
-
int LogAudit::logPrint(const char *fmt, ...) {
if (fmt == NULL) {
return -EINVAL;
@@ -115,43 +112,30 @@
strcpy(pidptr, cp);
}
- static const char comm_str[] = " comm=\"";
- char *comm = strstr(str, comm_str);
- if (comm) {
- cp = comm;
- comm += sizeof(comm_str) - 1;
- char *ecomm = strchr(comm, '"');
- if (ecomm) {
- *ecomm = '\0';
- }
- comm = strdup(comm);
- if (ecomm) {
- strcpy(cp, ecomm + 1);
- }
- } else if (pid == getpid()) {
- pid = tid;
- comm = strdup("auditd");
- } else if (!(comm = logbuf->pidToName(pid))) {
- comm = strdup("unknown");
- }
-
- size_t l = strlen(comm) + 1;
- size_t n = l + strlen(str) + 2;
+ size_t n = strlen(str);
+ n += sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint32_t);
char *newstr = reinterpret_cast<char *>(malloc(n));
if (!newstr) {
- free(comm);
free(str);
return -ENOMEM;
}
- *newstr = AUDIT_LOG_PRIO;
- strcpy(newstr + 1, comm);
- free(comm);
- strcpy(newstr + 1 + l, str);
+ char *msg = newstr;
+ *msg++ = AUDITD_LOG_TAG & 0xFF;
+ *msg++ = (AUDITD_LOG_TAG >> 8) & 0xFF;
+ *msg++ = (AUDITD_LOG_TAG >> 16) & 0xFF;
+ *msg++ = (AUDITD_LOG_TAG >> 24) & 0xFF;
+ *msg++ = EVENT_TYPE_STRING;
+ size_t l = n - sizeof(uint32_t) - sizeof(uint8_t) - sizeof(uint32_t);
+ *msg++ = l & 0xFF;
+ *msg++ = (l >> 8) & 0xFF;
+ *msg++ = (l >> 16) & 0xFF;
+ *msg++ = (l >> 24) & 0xFF;
+ memcpy(msg, str, l);
free(str);
- logbuf->log(AUDIT_LOG_ID, now, uid, pid, tid, newstr,
+ logbuf->log(LOG_ID_EVENTS, now, uid, pid, tid, newstr,
(n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
reader->notifyNewLog();
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index dc9d47e..ae167aa 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -18,6 +18,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/user.h>
#include <time.h>
#include <unistd.h>
@@ -32,6 +33,34 @@
// Default
#define LOG_BUFFER_SIZE (256 * 1024) // Tuned on a per-platform basis here?
#define log_buffer_size(id) mMaxSize[id]
+#define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
+#define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
+
+static bool valid_size(unsigned long value) {
+ if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
+ return false;
+ }
+
+ long pages = sysconf(_SC_PHYS_PAGES);
+ if (pages < 1) {
+ return true;
+ }
+
+ long pagesize = sysconf(_SC_PAGESIZE);
+ if (pagesize <= 1) {
+ pagesize = PAGE_SIZE;
+ }
+
+ // maximum memory impact a somewhat arbitrary ~3%
+ pages = (pages + 31) / 32;
+ unsigned long maximum = pages * pagesize;
+
+ if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
+ return true;
+ }
+
+ return value <= maximum;
+}
static unsigned long property_get_size(const char *key) {
char property[PROPERTY_VALUE_MAX];
@@ -56,6 +85,10 @@
value = 0;
}
+ if (!valid_size(value)) {
+ value = 0;
+ }
+
return value;
}
@@ -64,18 +97,38 @@
pthread_mutex_init(&mLogElementsLock, NULL);
dgram_qlen_statistics = false;
- static const char global_default[] = "persist.logd.size";
- unsigned long default_size = property_get_size(global_default);
+ static const char global_tuneable[] = "persist.logd.size"; // Settings App
+ static const char global_default[] = "ro.logd.size"; // BoardConfig.mk
+
+ unsigned long default_size = property_get_size(global_tuneable);
+ if (!default_size) {
+ default_size = property_get_size(global_default);
+ }
log_id_for_each(i) {
- setSize(i, LOG_BUFFER_SIZE);
- setSize(i, default_size);
-
char key[PROP_NAME_MAX];
- snprintf(key, sizeof(key), "%s.%s",
- global_default, android_log_id_to_name(i));
- setSize(i, property_get_size(key));
+ snprintf(key, sizeof(key), "%s.%s",
+ global_tuneable, android_log_id_to_name(i));
+ unsigned long property_size = property_get_size(key);
+
+ if (!property_size) {
+ snprintf(key, sizeof(key), "%s.%s",
+ global_default, android_log_id_to_name(i));
+ property_size = property_get_size(key);
+ }
+
+ if (!property_size) {
+ property_size = default_size;
+ }
+
+ if (!property_size) {
+ property_size = LOG_BUFFER_SIZE;
+ }
+
+ if (setSize(i, property_size)) {
+ setSize(i, LOG_BUFFER_MIN_SIZE);
+ }
}
}
@@ -339,7 +392,7 @@
// set the total space allocated to "id"
int LogBuffer::setSize(log_id_t id, unsigned long size) {
// Reasonable limits ...
- if ((size < (64 * 1024)) || ((256 * 1024 * 1024) < size)) {
+ if (!valid_size(size)) {
return -1;
}
pthread_mutex_lock(&mLogElementsLock);
diff --git a/logd/LogCommand.cpp b/logd/LogCommand.cpp
index 0873e63..e4c138e 100644
--- a/logd/LogCommand.cpp
+++ b/logd/LogCommand.cpp
@@ -64,7 +64,7 @@
}
gid_t gid = cli->getGid();
- if ((gid == AID_ROOT) || (gid == AID_LOG)) {
+ if ((gid == AID_ROOT) || (gid == AID_SYSTEM) || (gid == AID_LOG)) {
return true;
}
diff --git a/logd/event.logtags b/logd/event.logtags
new file mode 100644
index 0000000..a63f034
--- /dev/null
+++ b/logd/event.logtags
@@ -0,0 +1,36 @@
+# The entries in this file map a sparse set of log tag numbers to tag names.
+# This is installed on the device, in /system/etc, and parsed by logcat.
+#
+# Tag numbers are decimal integers, from 0 to 2^31. (Let's leave the
+# negative values alone for now.)
+#
+# Tag names are one or more ASCII letters and numbers or underscores, i.e.
+# "[A-Z][a-z][0-9]_". Do not include spaces or punctuation (the former
+# impacts log readability, the latter makes regex searches more annoying).
+#
+# Tag numbers and names are separated by whitespace. Blank lines and lines
+# starting with '#' are ignored.
+#
+# Optionally, after the tag names can be put a description for the value(s)
+# of the tag. Description are in the format
+# (<name>|data type[|data unit])
+# Multiple values are separated by commas.
+#
+# The data type is a number from the following values:
+# 1: int
+# 2: long
+# 3: string
+# 4: list
+#
+# The data unit is a number taken from the following list:
+# 1: Number of objects
+# 2: Number of bytes
+# 3: Number of milliseconds
+# 4: Number of allocations
+# 5: Id
+# 6: Percent
+# Default value for data of type int/long is 2 (bytes).
+#
+# TODO: generate ".java" and ".h" files with integer constants from this file.
+
+1003 auditd (avc|3)
diff --git a/rootdir/init.rc b/rootdir/init.rc
index e289a02..ed756e0 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -491,6 +491,7 @@
socket netd stream 0660 root system
socket dnsproxyd stream 0660 root inet
socket mdns stream 0660 root system
+ socket fwmarkd stream 0660 root inet
service debuggerd /system/bin/debuggerd
class main
diff --git a/rootdir/init.zygote32_64.rc b/rootdir/init.zygote32_64.rc
index 3d60a31..68c0668 100644
--- a/rootdir/init.zygote32_64.rc
+++ b/rootdir/init.zygote32_64.rc
@@ -1,4 +1,4 @@
-service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
+service zygote /system/bin/app_process32 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
diff --git a/toolbox/getprop.c b/toolbox/getprop.c
index 9dfdafe..dcc0ea0 100644
--- a/toolbox/getprop.c
+++ b/toolbox/getprop.c
@@ -3,7 +3,6 @@
#include <cutils/properties.h>
-#include <sys/system_properties.h>
#include "dynarray.h"
static void record_prop(const char* key, const char* name, void* opaque)
@@ -31,8 +30,6 @@
strlist_done(list);
}
-int __system_property_wait(prop_info *pi);
-
int getprop_main(int argc, char *argv[])
{
if (argc == 1) {
diff --git a/toolbox/ps.c b/toolbox/ps.c
index 6761555..57b4280 100644
--- a/toolbox/ps.c
+++ b/toolbox/ps.c
@@ -28,9 +28,12 @@
#define SHOW_POLICY 4
#define SHOW_CPU 8
#define SHOW_MACLABEL 16
+#define SHOW_ABI 32
static int display_flags = 0;
+static void print_exe_abi(int pid);
+
static int ps_line(int pid, int tid, char *namefilter)
{
char statline[1024];
@@ -170,7 +173,11 @@
else
printf(" %.2s ", get_sched_policy_name(p));
}
- printf(" %08x %08x %s %s", wchan, eip, state, cmdline[0] ? cmdline : name);
+ printf(" %08x %08x %s ", wchan, 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);
@@ -179,6 +186,39 @@
return 0;
}
+static void print_exe_abi(int pid)
+{
+ int fd, r;
+ char exeline[1024];
+
+ sprintf(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 *namefilter)
{
@@ -224,7 +264,9 @@
display_flags |= SHOW_PRIO;
} else if(!strcmp(argv[1],"-c")) {
display_flags |= SHOW_CPU;
- } else if(isdigit(argv[1][0])){
+ } else if(!strcmp(argv[1],"--abi")) {
+ display_flags |= SHOW_ABI;
+ } else if(isdigit(argv[1][0])){
pidfilter = atoi(argv[1]);
} else {
namefilter = argv[1];
@@ -236,10 +278,11 @@
if (display_flags & SHOW_MACLABEL) {
printf("LABEL USER PID PPID NAME\n");
} else {
- printf("USER PID PPID VSIZE RSS %s%s %s WCHAN PC NAME\n",
+ printf("USER PID PPID VSIZE RSS %s%s %s WCHAN PC %sNAME\n",
(display_flags&SHOW_CPU)?"CPU ":"",
(display_flags&SHOW_PRIO)?"PRIO NICE RTPRI SCHED ":"",
- (display_flags&SHOW_POLICY)?"PCY " : "");
+ (display_flags&SHOW_POLICY)?"PCY " : "",
+ (display_flags&SHOW_ABI)?"ABI " : "");
}
while((de = readdir(d)) != 0){
if(isdigit(de->d_name[0])){
diff --git a/toolbox/start.c b/toolbox/start.c
index 7f37108..0941e64 100644
--- a/toolbox/start.c
+++ b/toolbox/start.c
@@ -13,6 +13,7 @@
/* defaults to starting the common services stopped by stop.c */
property_set("ctl.start", "surfaceflinger");
property_set("ctl.start", "zygote");
+ property_set("ctl.start", "zygote_secondary");
}
return 0;
diff --git a/toolbox/stop.c b/toolbox/stop.c
index 2afedb7..ed9a293 100644
--- a/toolbox/stop.c
+++ b/toolbox/stop.c
@@ -9,6 +9,7 @@
property_set("ctl.stop", argv[1]);
} else{
/* defaults to stopping the common services */
+ property_set("ctl.stop", "zygote_secondary");
property_set("ctl.stop", "zygote");
property_set("ctl.stop", "surfaceflinger");
}