Merge "Add libkeyutils."
diff --git a/adb/Android.mk b/adb/Android.mk
index dc87bb0..4d7d487 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -15,11 +15,11 @@
-Wno-unused-parameter \
-Wno-missing-field-initializers \
-Wvla \
- -DADB_VERSION="\"$(tool_version)\""
+ -DADB_VERSION="\"$(tool_version)\"" \
ADB_COMMON_posix_CFLAGS := \
-Wexit-time-destructors \
- -Wthread-safety
+ -Wthread-safety \
ADB_COMMON_linux_CFLAGS := \
$(ADB_COMMON_posix_CFLAGS) \
@@ -232,7 +232,7 @@
libcutils \
libdiagnose_usb \
libmdnssd \
- libgmock_host
+ libgmock_host \
LOCAL_STATIC_LIBRARIES_linux := libusb
LOCAL_STATIC_LIBRARIES_darwin := libusb
@@ -300,7 +300,7 @@
libcrypto \
libdiagnose_usb \
liblog \
- libmdnssd
+ libmdnssd \
# Don't use libcutils on Windows.
LOCAL_STATIC_LIBRARIES_darwin := libcutils
diff --git a/adb/adb.cpp b/adb/adb.cpp
index c1e0d98..23f6580 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -1054,15 +1054,12 @@
if (strcmp(service, "kill") == 0) {
fprintf(stderr, "adb server killed by remote request\n");
fflush(stdout);
+
+ // Send a reply even though we don't read it anymore, so that old versions
+ // of adb that do read it don't spew error messages.
SendOkay(reply_fd);
- // On Windows, if the process exits with open sockets that
- // shutdown(SD_SEND) has not been called on, TCP RST segments will be
- // sent to the peers which will cause their next recv() to error-out
- // with WSAECONNRESET. In the case of this code, that means the client
- // may not read the OKAY sent above.
- adb_shutdown(reply_fd);
-
+ // Rely on process exit to close the socket for us.
android::base::quick_exit(0);
}
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index 4f3ff25..f5d0f02 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -123,7 +123,7 @@
return false;
}
-int _adb_connect(const std::string& service, std::string* error) {
+static int _adb_connect(const std::string& service, std::string* error) {
D("_adb_connect: %s", service.c_str());
if (service.empty() || service.size() > MAX_PAYLOAD_V1) {
*error = android::base::StringPrintf("bad service name length (%zd)",
@@ -158,6 +158,25 @@
return fd;
}
+bool adb_kill_server() {
+ D("adb_kill_server");
+ std::string reason;
+ int fd = socket_spec_connect(__adb_server_socket_spec, &reason);
+ if (fd < 0) {
+ fprintf(stderr, "cannot connect to daemon at %s: %s\n", __adb_server_socket_spec,
+ reason.c_str());
+ return true;
+ }
+
+ if (!SendProtocolString(fd, "host:kill")) {
+ fprintf(stderr, "error: write failure during connection: %s\n", strerror(errno));
+ return false;
+ }
+
+ ReadOrderlyShutdown(fd);
+ return true;
+}
+
int adb_connect(const std::string& service, std::string* error) {
// first query the adb server's version
int fd = _adb_connect("host:version", error);
@@ -214,18 +233,7 @@
if (version != ADB_SERVER_VERSION) {
fprintf(stderr, "adb server version (%d) doesn't match this client (%d); killing...\n",
version, ADB_SERVER_VERSION);
- fd = _adb_connect("host:kill", error);
- if (fd >= 0) {
- ReadOrderlyShutdown(fd);
- adb_close(fd);
- } else {
- // If we couldn't connect to the server or had some other error,
- // report it, but still try to start the server.
- fprintf(stderr, "error: %s\n", error->c_str());
- }
-
- /* XXX can we better detect its death? */
- std::this_thread::sleep_for(2s);
+ adb_kill_server();
goto start_server;
}
}
diff --git a/adb/adb_client.h b/adb/adb_client.h
index d07c1e9..fabec00 100644
--- a/adb/adb_client.h
+++ b/adb/adb_client.h
@@ -26,7 +26,9 @@
// Connect to adb, connect to the named service, and return a valid fd for
// interacting with that service upon success or a negative number on failure.
int adb_connect(const std::string& service, std::string* _Nonnull error);
-int _adb_connect(const std::string& service, std::string* _Nonnull error);
+
+// Kill the currently running adb server, if it exists.
+bool adb_kill_server();
// Connect to adb, connect to the named service, returns true if the connection
// succeeded AND the service returned OKAY. Outputs any returned error otherwise.
diff --git a/adb/adb_listeners.cpp b/adb/adb_listeners.cpp
index 18b1492..30cb29b 100644
--- a/adb/adb_listeners.cpp
+++ b/adb/adb_listeners.cpp
@@ -19,8 +19,12 @@
#include <stdio.h>
#include <stdlib.h>
+#include <algorithm>
+#include <list>
+
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
+#include <android-base/thread_annotations.h>
#include <cutils/sockets.h>
#include "socket_spec.h"
@@ -64,8 +68,9 @@
// listener_list retains ownership of all created alistener objects. Removing an alistener from
// this list will cause it to be deleted.
+static auto& listener_list_mutex = *new std::mutex();
typedef std::list<std::unique_ptr<alistener>> ListenerList;
-static ListenerList& listener_list = *new ListenerList();
+static ListenerList& listener_list GUARDED_BY(listener_list_mutex) = *new ListenerList();
static void ss_listener_event_func(int _fd, unsigned ev, void *_l) {
if (ev & FDE_READ) {
@@ -108,7 +113,8 @@
}
// Called as a transport disconnect function. |arg| is the raw alistener*.
-static void listener_disconnect(void* arg, atransport*) {
+static void listener_disconnect(void* arg, atransport*) EXCLUDES(listener_list_mutex) {
+ std::lock_guard<std::mutex> lock(listener_list_mutex);
for (auto iter = listener_list.begin(); iter != listener_list.end(); ++iter) {
if (iter->get() == arg) {
(*iter)->transport = nullptr;
@@ -119,7 +125,8 @@
}
// Write the list of current listeners (network redirections) into a string.
-std::string format_listeners() {
+std::string format_listeners() EXCLUDES(listener_list_mutex) {
+ std::lock_guard<std::mutex> lock(listener_list_mutex);
std::string result;
for (auto& l : listener_list) {
// Ignore special listeners like those for *smartsocket*
@@ -135,7 +142,9 @@
return result;
}
-InstallStatus remove_listener(const char* local_name, atransport* transport) {
+InstallStatus remove_listener(const char* local_name, atransport* transport)
+ EXCLUDES(listener_list_mutex) {
+ std::lock_guard<std::mutex> lock(listener_list_mutex);
for (auto iter = listener_list.begin(); iter != listener_list.end(); ++iter) {
if (local_name == (*iter)->local_name) {
listener_list.erase(iter);
@@ -145,7 +154,8 @@
return INSTALL_STATUS_LISTENER_NOT_FOUND;
}
-void remove_all_listeners() {
+void remove_all_listeners() EXCLUDES(listener_list_mutex) {
+ std::lock_guard<std::mutex> lock(listener_list_mutex);
auto iter = listener_list.begin();
while (iter != listener_list.end()) {
// Never remove smart sockets.
@@ -157,9 +167,18 @@
}
}
+void close_smartsockets() EXCLUDES(listener_list_mutex) {
+ std::lock_guard<std::mutex> lock(listener_list_mutex);
+ auto pred = [](const std::unique_ptr<alistener>& listener) {
+ return listener->local_name == "*smartsocket*";
+ };
+ listener_list.erase(std::remove_if(listener_list.begin(), listener_list.end(), pred));
+}
+
InstallStatus install_listener(const std::string& local_name, const char* connect_to,
atransport* transport, int no_rebind, int* resolved_tcp_port,
- std::string* error) {
+ std::string* error) EXCLUDES(listener_list_mutex) {
+ std::lock_guard<std::mutex> lock(listener_list_mutex);
for (auto& l : listener_list) {
if (local_name == l->local_name) {
// Can't repurpose a smartsocket.
@@ -212,7 +231,7 @@
if (transport) {
listener->disconnect.opaque = listener.get();
- listener->disconnect.func = listener_disconnect;
+ listener->disconnect.func = listener_disconnect;
transport->AddDisconnect(&listener->disconnect);
}
diff --git a/adb/adb_listeners.h b/adb/adb_listeners.h
index 8eba00a..70a2ee1 100644
--- a/adb/adb_listeners.h
+++ b/adb/adb_listeners.h
@@ -41,4 +41,6 @@
InstallStatus remove_listener(const char* local_name, atransport* transport);
void remove_all_listeners(void);
+void close_smartsockets();
+
#endif /* __ADB_LISTENERS_H */
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index fe5099c..bd9ad01 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -92,6 +92,16 @@
}
#endif
+void adb_server_cleanup() {
+ // Upon exit, we want to clean up in the following order:
+ // 1. close_smartsockets, so that we don't get any new clients
+ // 2. kick_all_transports, to avoid writing only part of a packet to a transport.
+ // 3. usb_cleanup, to tear down the USB stack.
+ close_smartsockets();
+ kick_all_transports();
+ usb_cleanup();
+}
+
int adb_server_main(int is_daemon, const std::string& socket_spec, int ack_reply_fd) {
#if defined(_WIN32)
// adb start-server starts us up with stdout and stderr hooked up to
@@ -111,12 +121,13 @@
SetConsoleCtrlHandler(ctrlc_handler, TRUE);
#else
signal(SIGINT, [](int) {
- android::base::quick_exit(0);
+ fdevent_run_on_main_thread([]() { android::base::quick_exit(0); });
});
#endif
- init_transport_registration();
+ android::base::at_quick_exit(adb_server_cleanup);
+ init_transport_registration();
init_mdns_transport_discovery();
usb_init();
diff --git a/adb/client/usb_dispatch.cpp b/adb/client/usb_dispatch.cpp
index 710a3ce..ce57731 100644
--- a/adb/client/usb_dispatch.cpp
+++ b/adb/client/usb_dispatch.cpp
@@ -27,6 +27,14 @@
}
}
+void usb_cleanup() {
+ if (should_use_libusb()) {
+ libusb::usb_cleanup();
+ } else {
+ native::usb_cleanup();
+ }
+}
+
int usb_write(usb_handle* h, const void* data, int len) {
return should_use_libusb()
? libusb::usb_write(reinterpret_cast<libusb::usb_handle*>(h), data, len)
diff --git a/adb/client/usb_libusb.cpp b/adb/client/usb_libusb.cpp
index 15d4b7a..18a8ff2 100644
--- a/adb/client/usb_libusb.cpp
+++ b/adb/client/usb_libusb.cpp
@@ -152,7 +152,9 @@
static auto& usb_handles_mutex = *new std::mutex();
static std::thread* device_poll_thread = nullptr;
-static std::atomic<bool> terminate_device_poll_thread(false);
+static bool terminate_device_poll_thread = false;
+static auto& device_poll_mutex = *new std::mutex();
+static auto& device_poll_cv = *new std::condition_variable();
static std::string get_device_address(libusb_device* device) {
return StringPrintf("usb:%d:%d", libusb_get_bus_number(device),
@@ -376,7 +378,7 @@
static void poll_for_devices() {
libusb_device** list;
adb_thread_setname("device poll");
- while (!terminate_device_poll_thread) {
+ while (true) {
const ssize_t device_count = libusb_get_device_list(nullptr, &list);
LOG(VERBOSE) << "found " << device_count << " attached devices";
@@ -389,7 +391,10 @@
adb_notify_device_scan_complete();
- std::this_thread::sleep_for(500ms);
+ std::unique_lock<std::mutex> lock(device_poll_mutex);
+ if (device_poll_cv.wait_for(lock, 500ms, []() { return terminate_device_poll_thread; })) {
+ return;
+ }
}
}
@@ -410,11 +415,21 @@
// Spawn a thread to do device enumeration.
// TODO: Use libusb_hotplug_* instead?
+ std::unique_lock<std::mutex> lock(device_poll_mutex);
device_poll_thread = new std::thread(poll_for_devices);
- android::base::at_quick_exit([]() {
+}
+
+void usb_cleanup() {
+ {
+ std::unique_lock<std::mutex> lock(device_poll_mutex);
terminate_device_poll_thread = true;
- device_poll_thread->join();
- });
+
+ if (!device_poll_thread) {
+ return;
+ }
+ }
+ device_poll_cv.notify_all();
+ device_poll_thread->join();
}
// Dispatch a libusb transfer, unlock |device_lock|, and then wait for the result.
diff --git a/adb/client/usb_linux.cpp b/adb/client/usb_linux.cpp
index f9ba7cb..a7df0ed 100644
--- a/adb/client/usb_linux.cpp
+++ b/adb/client/usb_linux.cpp
@@ -598,4 +598,7 @@
std::thread(device_poll_thread).detach();
}
+
+void usb_cleanup() {}
+
} // namespace native
diff --git a/adb/client/usb_osx.cpp b/adb/client/usb_osx.cpp
index e366754..4e1480f 100644
--- a/adb/client/usb_osx.cpp
+++ b/adb/client/usb_osx.cpp
@@ -430,7 +430,7 @@
VLOG(USB) << "RunLoopThread done";
}
-static void usb_cleanup() NO_THREAD_SAFETY_ANALYSIS {
+void usb_cleanup() NO_THREAD_SAFETY_ANALYSIS {
VLOG(USB) << "usb_cleanup";
// Wait until usb operations in RunLoopThread finish, and prevent further operations.
operate_device_lock.lock();
@@ -440,8 +440,6 @@
void usb_init() {
static bool initialized = false;
if (!initialized) {
- atexit(usb_cleanup);
-
usb_inited_flag = false;
std::thread(RunLoopThread).detach();
diff --git a/adb/client/usb_windows.cpp b/adb/client/usb_windows.cpp
index ec55b0e..1620e6e 100644
--- a/adb/client/usb_windows.cpp
+++ b/adb/client/usb_windows.cpp
@@ -265,6 +265,8 @@
std::thread(_power_notification_thread).detach();
}
+void usb_cleanup() {}
+
usb_handle* do_usb_open(const wchar_t* interface_name) {
unsigned long name_len = 0;
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index a9b1540..f49c69d 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -1546,25 +1546,7 @@
return 0;
}
else if (!strcmp(argv[0], "kill-server")) {
- std::string error;
- int fd = _adb_connect("host:kill", &error);
- if (fd == -2) {
- // Failed to make network connection to server. Don't output the
- // network error since that is expected.
- fprintf(stderr,"* server not running *\n");
- // Successful exit code because the server is already "killed".
- return 0;
- } else if (fd == -1) {
- // Some other error.
- fprintf(stderr, "error: %s\n", error.c_str());
- return 1;
- } else {
- // Successfully connected, kill command sent, okay status came back.
- // Server should exit() in a moment, if not already.
- ReadOrderlyShutdown(fd);
- adb_close(fd);
- return 0;
- }
+ return adb_kill_server() ? 0 : 1;
}
else if (!strcmp(argv[0], "sideload")) {
if (argc != 2) return syntax_error("sideload requires an argument");
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 20de642..13cfaa1 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -568,15 +568,14 @@
transport_registration_func, 0);
fdevent_set(&transport_registration_fde, FDE_READ);
-#if ADB_HOST
- android::base::at_quick_exit([]() {
- // To avoid only writing part of a packet to a transport after exit, kick all transports.
- std::lock_guard<std::mutex> lock(transport_lock);
- for (auto t : transport_list) {
- t->Kick();
- }
- });
-#endif
+}
+
+void kick_all_transports() {
+ // To avoid only writing part of a packet to a transport after exit, kick all transports.
+ std::lock_guard<std::mutex> lock(transport_lock);
+ for (auto t : transport_list) {
+ t->Kick();
+ }
}
/* the fdevent select pump is single threaded */
diff --git a/adb/transport.h b/adb/transport.h
index e129355..006aaf4 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -207,6 +207,7 @@
std::string list_transports(bool long_listing);
atransport* find_transport(const char* serial);
void kick_all_tcp_devices();
+void kick_all_transports();
void register_usb_transport(usb_handle* h, const char* serial,
const char* devpath, unsigned writeable);
diff --git a/adb/usb.h b/adb/usb.h
index e867ec8..f428ede 100644
--- a/adb/usb.h
+++ b/adb/usb.h
@@ -22,6 +22,7 @@
#define ADB_USB_INTERFACE(handle_ref_type) \
void usb_init(); \
+ void usb_cleanup(); \
int usb_write(handle_ref_type h, const void* data, int len); \
int usb_read(handle_ref_type h, void* data, int len); \
int usb_close(handle_ref_type h); \
diff --git a/debuggerd/libdebuggerd/arm/machine.cpp b/debuggerd/libdebuggerd/arm/machine.cpp
index 78c2306..ac833ae 100644
--- a/debuggerd/libdebuggerd/arm/machine.cpp
+++ b/debuggerd/libdebuggerd/arm/machine.cpp
@@ -48,6 +48,21 @@
}
}
+#define DUMP_GP_REGISTERS(log, reg_prefix) \
+ _LOG(log, logtype::REGISTERS, " r0 %08x r1 %08x r2 %08x r3 %08x\n", \
+ static_cast<uint32_t>(reg_prefix##r0), static_cast<uint32_t>(reg_prefix##r1), \
+ static_cast<uint32_t>(reg_prefix##r2), static_cast<uint32_t>(reg_prefix##r3)); \
+ _LOG(log, logtype::REGISTERS, " r4 %08x r5 %08x r6 %08x r7 %08x\n", \
+ static_cast<uint32_t>(reg_prefix##r4), static_cast<uint32_t>(reg_prefix##r5), \
+ static_cast<uint32_t>(reg_prefix##r6), static_cast<uint32_t>(reg_prefix##r7)); \
+ _LOG(log, logtype::REGISTERS, " r8 %08x r9 %08x sl %08x fp %08x\n", \
+ static_cast<uint32_t>(reg_prefix##r8), static_cast<uint32_t>(reg_prefix##r9), \
+ static_cast<uint32_t>(reg_prefix##r10), static_cast<uint32_t>(reg_prefix##fp)); \
+ _LOG(log, logtype::REGISTERS, " ip %08x sp %08x lr %08x pc %08x cpsr %08x\n", \
+ static_cast<uint32_t>(reg_prefix##ip), static_cast<uint32_t>(reg_prefix##sp), \
+ static_cast<uint32_t>(reg_prefix##lr), static_cast<uint32_t>(reg_prefix##pc), \
+ static_cast<uint32_t>(reg_prefix##cpsr))
+
void dump_registers(log_t* log, pid_t tid) {
pt_regs r;
if (ptrace(PTRACE_GETREGS, tid, 0, &r)) {
@@ -55,19 +70,7 @@
return;
}
- _LOG(log, logtype::REGISTERS, " r0 %08x r1 %08x r2 %08x r3 %08x\n",
- static_cast<uint32_t>(r.ARM_r0), static_cast<uint32_t>(r.ARM_r1),
- static_cast<uint32_t>(r.ARM_r2), static_cast<uint32_t>(r.ARM_r3));
- _LOG(log, logtype::REGISTERS, " r4 %08x r5 %08x r6 %08x r7 %08x\n",
- static_cast<uint32_t>(r.ARM_r4), static_cast<uint32_t>(r.ARM_r5),
- static_cast<uint32_t>(r.ARM_r6), static_cast<uint32_t>(r.ARM_r7));
- _LOG(log, logtype::REGISTERS, " r8 %08x r9 %08x sl %08x fp %08x\n",
- static_cast<uint32_t>(r.ARM_r8), static_cast<uint32_t>(r.ARM_r9),
- static_cast<uint32_t>(r.ARM_r10), static_cast<uint32_t>(r.ARM_fp));
- _LOG(log, logtype::REGISTERS, " ip %08x sp %08x lr %08x pc %08x cpsr %08x\n",
- static_cast<uint32_t>(r.ARM_ip), static_cast<uint32_t>(r.ARM_sp),
- static_cast<uint32_t>(r.ARM_lr), static_cast<uint32_t>(r.ARM_pc),
- static_cast<uint32_t>(r.ARM_cpsr));
+ DUMP_GP_REGISTERS(log, r.ARM_);
user_vfp vfp_regs;
if (ptrace(PTRACE_GETVFPREGS, tid, 0, &vfp_regs)) {
@@ -81,3 +84,7 @@
}
_LOG(log, logtype::FP_REGISTERS, " scr %08lx\n", vfp_regs.fpscr);
}
+
+void dump_registers(log_t* log, const ucontext_t* uc) {
+ DUMP_GP_REGISTERS(log, uc->uc_mcontext.arm_);
+}
diff --git a/debuggerd/libdebuggerd/arm64/machine.cpp b/debuggerd/libdebuggerd/arm64/machine.cpp
index e7bf79a..fa73c99a 100644
--- a/debuggerd/libdebuggerd/arm64/machine.cpp
+++ b/debuggerd/libdebuggerd/arm64/machine.cpp
@@ -52,6 +52,17 @@
}
}
+#define DUMP_GP_REGISTERS(log) \
+ for (int i = 0; i < 28; i += 4) { \
+ const char* fmt = " x%-2d %016llx x%-2d %016llx x%-2d %016llx x%-2d %016llx\n"; \
+ _LOG(log, logtype::REGISTERS, fmt, i, r.regs[i], i + 1, r.regs[i + 1], i + 2, r.regs[i + 2], \
+ i + 3, r.regs[i + 3]); \
+ } \
+ _LOG(log, logtype::REGISTERS, " x28 %016llx x29 %016llx x30 %016llx\n", r.regs[28], \
+ r.regs[29], r.regs[30]); \
+ _LOG(log, logtype::REGISTERS, " sp %016llx pc %016llx pstate %016llx\n", r.sp, r.pc, \
+ r.pstate)
+
void dump_registers(log_t* log, pid_t tid) {
struct user_pt_regs r;
struct iovec io;
@@ -63,20 +74,7 @@
return;
}
- for (int i = 0; i < 28; i += 4) {
- _LOG(log, logtype::REGISTERS,
- " x%-2d %016llx x%-2d %016llx x%-2d %016llx x%-2d %016llx\n",
- i, r.regs[i],
- i+1, r.regs[i+1],
- i+2, r.regs[i+2],
- i+3, r.regs[i+3]);
- }
-
- _LOG(log, logtype::REGISTERS, " x28 %016llx x29 %016llx x30 %016llx\n",
- r.regs[28], r.regs[29], r.regs[30]);
-
- _LOG(log, logtype::REGISTERS, " sp %016llx pc %016llx pstate %016llx\n",
- r.sp, r.pc, r.pstate);
+ DUMP_GP_REGISTERS(log);
struct user_fpsimd_state f;
io.iov_base = &f;
@@ -99,3 +97,8 @@
}
_LOG(log, logtype::FP_REGISTERS, " fpsr %08x fpcr %08x\n", f.fpsr, f.fpcr);
}
+
+void dump_registers(log_t* log, const ucontext_t* ucontext) {
+ const mcontext_t& r = ucontext->uc_mcontext;
+ DUMP_GP_REGISTERS(log);
+}
diff --git a/debuggerd/libdebuggerd/include/machine.h b/debuggerd/libdebuggerd/include/machine.h
index e65b147..5e56682 100644
--- a/debuggerd/libdebuggerd/include/machine.h
+++ b/debuggerd/libdebuggerd/include/machine.h
@@ -25,5 +25,6 @@
void dump_memory_and_code(log_t* log, Backtrace* backtrace);
void dump_registers(log_t* log, pid_t tid);
+void dump_registers(log_t* log, const ucontext_t* uc);
#endif // _DEBUGGERD_MACHINE_H
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index 0c38449..edc7be5 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -470,6 +470,11 @@
}
}
+// Weak noop implementation, real implementations are in <arch>/machine.cpp.
+__attribute__((weak)) void dump_registers(log_t* log, const ucontext_t*) {
+ _LOG(log, logtype::REGISTERS, " register dumping unimplemented on this architecture");
+}
+
static void dump_thread(log_t* log, pid_t pid, pid_t tid, const std::string& process_name,
const std::string& thread_name, BacktraceMap* map,
uintptr_t abort_msg_address, bool primary_thread) {
@@ -749,11 +754,15 @@
read_with_default("/proc/self/comm", thread_name, sizeof(thread_name), "<unknown>");
read_with_default("/proc/self/cmdline", process_name, sizeof(process_name), "<unknown>");
+ _LOG(&log, logtype::HEADER, "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");
+ dump_header_info(&log);
dump_thread_info(&log, pid, tid, thread_name, process_name);
dump_signal_info(&log, siginfo);
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid));
dump_abort_message(backtrace.get(), &log, abort_msg_address);
+ dump_registers(&log, ucontext);
+
// TODO: Dump registers from the ucontext.
if (backtrace->Unwind(0, ucontext)) {
dump_backtrace_and_stack(backtrace.get(), &log);
diff --git a/init/Android.mk b/init/Android.mk
index 78a4882..617a809 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -61,6 +61,8 @@
endif
include $(CLEAR_VARS)
+# b/38002385, work around clang-tidy segmentation fault.
+LOCAL_TIDY_CHECKS := -misc-forwarding-reference-overload
LOCAL_CPPFLAGS := $(init_cflags)
LOCAL_SRC_FILES:= \
action.cpp \
@@ -82,6 +84,8 @@
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
+# b/38002385, work around clang-tidy segmentation fault.
+LOCAL_TIDY_CHECKS := -misc-forwarding-reference-overload
LOCAL_CPPFLAGS := $(init_cflags)
LOCAL_SRC_FILES:= \
bootchart.cpp \
@@ -140,6 +144,8 @@
# Unit tests.
# =========================================================
include $(CLEAR_VARS)
+# b/38002385, work around clang-tidy segmentation fault.
+LOCAL_TIDY_CHECKS := -misc-forwarding-reference-overload
LOCAL_MODULE := init_tests
LOCAL_COMPATIBILITY_SUITE := device-tests
LOCAL_SRC_FILES := \
diff --git a/libvndksupport/Android.bp b/libvndksupport/Android.bp
new file mode 100644
index 0000000..ab9e26f
--- /dev/null
+++ b/libvndksupport/Android.bp
@@ -0,0 +1,15 @@
+subdirs = ["tests"]
+
+cc_library_shared {
+ name: "libvndksupport",
+ srcs: ["linker.c"],
+ local_include_dirs: ["include/vndksupport"],
+ export_include_dirs: ["include"],
+ shared_libs: ["liblog"],
+}
+
+llndk_library {
+ name: "libvndksupport",
+ symbol_file: "libvndksupport.map.txt",
+ export_include_dirs: ["include"],
+}
diff --git a/libvndksupport/include/vndksupport/linker.h b/libvndksupport/include/vndksupport/linker.h
new file mode 100644
index 0000000..f509564
--- /dev/null
+++ b/libvndksupport/include/vndksupport/linker.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 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 VNDKSUPPORT_LINKER_H_
+#define VNDKSUPPORT_LINKER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void* android_load_sphal_library(const char* name, int flag);
+
+int android_unload_sphal_library(void* handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // VNDKSUPPORT_LINKER_H_
diff --git a/libvndksupport/libvndksupport.map.txt b/libvndksupport/libvndksupport.map.txt
new file mode 100644
index 0000000..16e38da
--- /dev/null
+++ b/libvndksupport/libvndksupport.map.txt
@@ -0,0 +1,7 @@
+LIBVNDKSUPPORT {
+ global:
+ android_load_sphal_library; # vndk
+ android_unload_sphal_library; # vndk
+ local:
+ *;
+};
diff --git a/libvndksupport/linker.c b/libvndksupport/linker.c
new file mode 100644
index 0000000..d82307b
--- /dev/null
+++ b/libvndksupport/linker.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2017 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 "linker.h"
+
+#include <android/dlext.h>
+#include <dlfcn.h>
+
+#define LOG_TAG "vndksupport"
+#include <log/log.h>
+
+extern struct android_namespace_t* android_get_exported_namespace(const char*);
+
+void* android_load_sphal_library(const char* name, int flag) {
+ struct android_namespace_t* sphal_namespace = android_get_exported_namespace("sphal");
+ if (sphal_namespace != NULL) {
+ const android_dlextinfo dlextinfo = {
+ .flags = ANDROID_DLEXT_USE_NAMESPACE, .library_namespace = sphal_namespace,
+ };
+ void* handle = android_dlopen_ext(name, flag, &dlextinfo);
+ if (handle) {
+ return handle;
+ } else {
+ ALOGW(
+ "Could not load %s from sphal namespace: %s. "
+ "Falling back to loading it from the current namespace,",
+ name, dlerror());
+ }
+ } else {
+ ALOGI(
+ "sphal namespace is not configured for this process. "
+ "Loading %s from the current namespace instead.",
+ name);
+ }
+ return dlopen(name, flag);
+}
+
+int android_unload_sphal_library(void* handle) {
+ return dlclose(handle);
+}
diff --git a/libvndksupport/tests/Android.bp b/libvndksupport/tests/Android.bp
new file mode 100644
index 0000000..3587cf8
--- /dev/null
+++ b/libvndksupport/tests/Android.bp
@@ -0,0 +1,26 @@
+// Copyright (C) 2017 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.
+
+cc_test {
+ name: "libvndksupport-tests",
+ srcs: [
+ "linker_test.cpp",
+ ],
+
+ host_supported: false,
+ shared_libs: [
+ "libvndksupport",
+ "libbase",
+ ]
+}
diff --git a/libvndksupport/tests/linker_test.cpp b/libvndksupport/tests/linker_test.cpp
new file mode 100644
index 0000000..7ce27d4
--- /dev/null
+++ b/libvndksupport/tests/linker_test.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 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 <gtest/gtest.h>
+
+#include <android-base/strings.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <vndksupport/linker.h>
+#include <string>
+
+// Since the test executable will be in /data and ld.config.txt does not
+// configure sphal namespace for executables in /data, the call to
+// android_load_sphal_library will always fallback to the plain dlopen from the
+// default namespace.
+
+// Let's use libEGL_<chipset>.so as a SP-HAL in test
+static std::string find_sphal_lib() {
+ const char* path =
+#if defined(__LP64__)
+ "/vendor/lib64/egl";
+#else
+ "/vendor/lib/egl";
+#endif
+ std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path), closedir);
+
+ dirent* dp;
+ while ((dp = readdir(dir.get())) != nullptr) {
+ std::string name = dp->d_name;
+ if (android::base::StartsWith(name, "libEGL_")) {
+ return std::string(path) + "/" + name;
+ }
+ }
+ return "";
+}
+
+TEST(linker, load_existing_lib) {
+ std::string name = find_sphal_lib();
+ ASSERT_NE("", name);
+ void* handle = android_load_sphal_library(name.c_str(), RTLD_NOW | RTLD_LOCAL);
+ ASSERT_NE(nullptr, handle);
+ android_unload_sphal_library(handle);
+}
+
+TEST(linker, load_nonexisting_lib) {
+ void* handle = android_load_sphal_library("libNeverUseThisName.so", RTLD_NOW | RTLD_LOCAL);
+ ASSERT_EQ(nullptr, handle);
+}
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 5f9f799..a4545af 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -60,7 +60,7 @@
namespace.sphal.links = default,vndk,rs
# WARNING: only NDK libs can be listed here.
-namespace.sphal.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libGLESv1_CM.so:libGLESv2.so
+namespace.sphal.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libGLESv1_CM.so:libGLESv2.so:libvndksupport.so
# WARNING: only VNDK-SP libs can be listed here. DO NOT EDIT this line.
namespace.sphal.link.vndk.shared_libs = android.hardware.renderscript@1.0.so:android.hardware.graphics.allocator@2.0.so:android.hardware.graphics.mapper@2.0.so:android.hardware.graphics.common@1.0.so:libhwbinder.so:libbase.so:libcutils.so:libhardware.so:libhidlbase.so:libhidltransport.so:libutils.so:libc++.so
@@ -81,7 +81,7 @@
namespace.rs.permitted.paths = /vendor/${LIB}:/data
namespace.rs.links = default,vndk
-namespace.rs.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libGLESv1_CM.so:libGLESv2.so:libmediandk.so:libui.so
+namespace.rs.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libGLESv1_CM.so:libGLESv2.so:libmediandk.so:libui.so:libvndksupport.so
namespace.rs.link.vndk.shared_libs = android.hardware.renderscript@1.0.so:android.hardware.graphics.allocator@2.0.so:android.hardware.graphics.mapper@2.0.so:android.hardware.graphics.common@1.0.so:libhwbinder.so:libbase.so:libcutils.so:libhardware.so:libhidlbase.so:libhidltransport.so:libutils.so:libc++.so
###############################################################################
@@ -100,7 +100,7 @@
# to the default namespace. This is possible since their ABI is stable across
# Android releases.
namespace.vndk.links = default
-namespace.vndk.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so
+namespace.vndk.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libvndksupport.so
[vendor]