Merge "Revert "mkbootimg: add version and patch level"" into nyc-dev
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index e522119..5aa878b 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -1029,8 +1029,8 @@
// TODO: when we have libc++ for Windows, use a regular expression instead.
// wait-for-((any|local|usb)-)?(bootloader|device|recovery|sideload)
- char type[20];
- char state[20];
+ char type[20 + 1]; // sscanf's %20[...] doesn't include the NUL.
+ char state[20 + 1];
int length = 0;
if (sscanf(service, "wait-for-%20[a-z]-%20[a-z]%n", type, state, &length) < 2 ||
length != static_cast<int>(strlen(service))) {
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index 372bedf..f6c9df4 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -260,7 +260,8 @@
} else {
/* Host is connected. Register the transport, and start the
* exchange. */
- register_socket_transport(fd, "host", port, 1);
+ std::string serial = android::base::StringPrintf("host-%d", fd);
+ register_socket_transport(fd, serial.c_str(), port, 1);
if (!WriteFdExactly(fd, _start_req, strlen(_start_req))) {
adb_close(fd);
}
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index bcc8abd..1460803 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -20,6 +20,7 @@
#include <getopt.h>
#include <unistd.h>
+#include <cmath>
#include <cstddef>
#include <cstdio>
#include <ctime>
@@ -166,6 +167,15 @@
time_t current_time_utc = time(nullptr);
+ static const char* factory_reset_current_time = "factory_reset_current_time";
+ if (current_time_utc < 0) {
+ // UMA does not display negative values in buckets, so convert to positive.
+ LogBootEvent(factory_reset_current_time, std::abs(current_time_utc));
+ return;
+ } else {
+ LogBootEvent(factory_reset_current_time, current_time_utc);
+ }
+
// The factory_reset boot event does not exist after the device is reset, so
// use this signal to mark the time of the factory reset.
if (!boot_event_store.GetBootEvent("factory_reset", &record)) {
@@ -179,6 +189,7 @@
// Calculate and record the difference in time between now and the
// factory_reset time.
time_t factory_reset_utc = record.second;
+ LogBootEvent("factory_reset_record_value", factory_reset_utc);
time_t time_since_factory_reset = difftime(current_time_utc,
factory_reset_utc);
boot_event_store.AddBootEventWithValue("time_since_factory_reset",
diff --git a/debuggerd/backtrace.cpp b/debuggerd/backtrace.cpp
index b6916e5..32843d8 100644
--- a/debuggerd/backtrace.cpp
+++ b/debuggerd/backtrace.cpp
@@ -91,7 +91,8 @@
if (backtrace->Unwind(0)) {
dump_backtrace_to_log(backtrace.get(), log, " ");
} else {
- ALOGE("Unwind failed: tid = %d", tid);
+ ALOGE("Unwind failed: tid = %d: %s", tid,
+ backtrace->GetErrorString(backtrace->GetError()).c_str());
}
}
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index 8efbacc..86d7c14 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -449,18 +449,11 @@
return true;
}
-static bool fork_signal_sender(int* in_fd, int* out_fd, pid_t* sender_pid, pid_t target_pid) {
- int input_pipe[2];
- int output_pipe[2];
- if (pipe(input_pipe) != 0) {
- ALOGE("debuggerd: failed to create input pipe for signal sender: %s", strerror(errno));
- return false;
- }
-
- if (pipe(output_pipe) != 0) {
- close(input_pipe[0]);
- close(input_pipe[1]);
- ALOGE("debuggerd: failed to create output pipe for signal sender: %s", strerror(errno));
+// Fork a process that listens for signals to send, or 0, to exit.
+static bool fork_signal_sender(int* out_fd, pid_t* sender_pid, pid_t target_pid) {
+ int sfd[2];
+ if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sfd) != 0) {
+ ALOGE("debuggerd: failed to create socketpair for signal sender: %s", strerror(errno));
return false;
}
@@ -469,40 +462,42 @@
ALOGE("debuggerd: failed to initialize signal sender: fork failed: %s", strerror(errno));
return false;
} else if (fork_pid == 0) {
- close(input_pipe[1]);
- close(output_pipe[0]);
- auto wait = [=]() {
- char buf[1];
- if (TEMP_FAILURE_RETRY(read(input_pipe[0], buf, 1)) != 1) {
- ALOGE("debuggerd: signal sender failed to read from pipe");
+ close(sfd[1]);
+
+ while (true) {
+ int signal;
+ int rc = TEMP_FAILURE_RETRY(read(sfd[0], &signal, sizeof(signal)));
+ if (rc < 0) {
+ ALOGE("debuggerd: signal sender failed to read from socket");
+ kill(target_pid, SIGKILL);
+ exit(1);
+ } else if (rc != sizeof(signal)) {
+ ALOGE("debuggerd: signal sender read unexpected number of bytes: %d", rc);
+ kill(target_pid, SIGKILL);
exit(1);
}
- };
- auto notify_done = [=]() {
- if (TEMP_FAILURE_RETRY(write(output_pipe[1], "", 1)) != 1) {
- ALOGE("debuggerd: signal sender failed to write to pipe");
+
+ // Report success after sending a signal, or before exiting.
+ int err = 0;
+ if (signal != 0) {
+ if (kill(target_pid, signal) != 0) {
+ err = errno;
+ }
+ }
+
+ if (TEMP_FAILURE_RETRY(write(sfd[0], &err, sizeof(err))) < 0) {
+ ALOGE("debuggerd: signal sender failed to write: %s", strerror(errno));
+ kill(target_pid, SIGKILL);
exit(1);
}
- };
- wait();
- if (kill(target_pid, SIGSTOP) != 0) {
- ALOGE("debuggerd: failed to stop target '%d': %s", target_pid, strerror(errno));
+ if (signal == 0) {
+ exit(0);
+ }
}
- notify_done();
-
- wait();
- if (kill(target_pid, SIGCONT) != 0) {
- ALOGE("debuggerd: failed to resume target '%d': %s", target_pid, strerror(errno));
- }
- notify_done();
-
- exit(0);
} else {
- close(input_pipe[0]);
- close(output_pipe[1]);
- *in_fd = input_pipe[1];
- *out_fd = output_pipe[0];
+ close(sfd[0]);
+ *out_fd = sfd[1];
*sender_pid = fork_pid;
return true;
}
@@ -588,9 +583,15 @@
// Don't attach to the sibling threads if we want to attach gdb.
// Supposedly, it makes the process less reliable.
bool attach_gdb = should_attach_gdb(&request);
- int signal_in_fd = -1;
- int signal_out_fd = -1;
+ int signal_fd = -1;
pid_t signal_pid = 0;
+
+ // Fork a process that stays root, and listens on a pipe to pause and resume the target.
+ if (!fork_signal_sender(&signal_fd, &signal_pid, request.pid)) {
+ ALOGE("debuggerd: failed to fork signal sender");
+ exit(1);
+ }
+
if (attach_gdb) {
// Open all of the input devices we need to listen for VOLUMEDOWN before dropping privileges.
if (init_getevent() != 0) {
@@ -598,19 +599,21 @@
attach_gdb = false;
}
- // Fork a process that stays root, and listens on a pipe to pause and resume the target.
- if (!fork_signal_sender(&signal_in_fd, &signal_out_fd, &signal_pid, request.pid)) {
- attach_gdb = false;
- }
}
- auto notify_signal_sender = [=]() {
- char buf[1];
- if (TEMP_FAILURE_RETRY(write(signal_in_fd, "", 1)) != 1) {
+ auto send_signal = [=](int signal) {
+ int error;
+ if (TEMP_FAILURE_RETRY(write(signal_fd, &signal, sizeof(signal))) < 0) {
ALOGE("debuggerd: failed to notify signal process: %s", strerror(errno));
- } else if (TEMP_FAILURE_RETRY(read(signal_out_fd, buf, 1)) != 1) {
+ return false;
+ } else if (TEMP_FAILURE_RETRY(read(signal_fd, &error, sizeof(error))) < 0) {
ALOGE("debuggerd: failed to read response from signal process: %s", strerror(errno));
+ return false;
+ } else if (error != 0) {
+ errno = error;
+ return false;
}
+ return true;
};
std::set<pid_t> siblings;
@@ -624,19 +627,25 @@
bool succeeded = false;
// Now that we've done everything that requires privileges, we can drop them.
- if (drop_privileges()) {
- succeeded = perform_dump(request, fd, tombstone_fd, backtrace_map.get(), siblings);
- if (succeeded) {
- if (request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) {
- if (!tombstone_path.empty()) {
- write(fd, tombstone_path.c_str(), tombstone_path.length());
- }
+ if (!drop_privileges()) {
+ ALOGE("debuggerd: failed to drop privileges, exiting");
+ _exit(1);
+ }
+
+ succeeded = perform_dump(request, fd, tombstone_fd, backtrace_map.get(), siblings);
+ if (succeeded) {
+ if (request.action == DEBUGGER_ACTION_DUMP_TOMBSTONE) {
+ if (!tombstone_path.empty()) {
+ write(fd, tombstone_path.c_str(), tombstone_path.length());
}
}
+ }
- if (attach_gdb) {
- // Tell the signal process to send SIGSTOP to the target.
- notify_signal_sender();
+ if (attach_gdb) {
+ // Tell the signal process to send SIGSTOP to the target.
+ if (!send_signal(SIGSTOP)) {
+ ALOGE("debuggerd: failed to stop process for gdb attach: %s", strerror(errno));
+ attach_gdb = false;
}
}
@@ -648,17 +657,32 @@
ptrace(PTRACE_DETACH, sibling, 0, 0);
}
+ // Send the signal back to the process if it crashed and we're not waiting for gdb.
+ if (!attach_gdb && request.action == DEBUGGER_ACTION_CRASH) {
+ // TODO: Send the same signal that triggered the dump, so that shell says "Segmentation fault"
+ // instead of "Killed"?
+ if (!send_signal(SIGKILL)) {
+ ALOGE("debuggerd: failed to kill process %d: %s", request.pid, strerror(errno));
+ }
+ }
+
// Wait for gdb, if requested.
if (attach_gdb && succeeded) {
wait_for_user_action(request);
// Tell the signal process to send SIGCONT to the target.
- notify_signal_sender();
+ if (!send_signal(SIGCONT)) {
+ ALOGE("debuggerd: failed to resume process %d: %s", request.pid, strerror(errno));
+ }
uninit_getevent();
- waitpid(signal_pid, nullptr, 0);
}
+ if (!send_signal(0)) {
+ ALOGE("debuggerd: failed to notify signal sender to finish");
+ kill(signal_pid, SIGKILL);
+ }
+ waitpid(signal_pid, nullptr, 0);
exit(!succeeded);
}
diff --git a/include/backtrace/Backtrace.h b/include/backtrace/Backtrace.h
index f440bd2..c896ab8 100644
--- a/include/backtrace/Backtrace.h
+++ b/include/backtrace/Backtrace.h
@@ -34,6 +34,24 @@
typedef uint32_t word_t;
#endif
+enum BacktraceUnwindError : uint32_t {
+ BACKTRACE_UNWIND_NO_ERROR,
+ // Something failed while trying to perform the setup to begin the unwind.
+ BACKTRACE_UNWIND_ERROR_SETUP_FAILED,
+ // There is no map information to use with the unwind.
+ BACKTRACE_UNWIND_ERROR_MAP_MISSING,
+ // An error occurred that indicates a programming error.
+ BACKTRACE_UNWIND_ERROR_INTERNAL,
+ // The thread to unwind has disappeared before the unwind can begin.
+ BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST,
+ // The thread to unwind has not responded to a signal in a timely manner.
+ BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT,
+ // Attempt to do an unsupported operation.
+ BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION,
+ // Attempt to do an offline unwind without a context.
+ BACKTRACE_UNWIND_ERROR_NO_CONTEXT,
+};
+
struct backtrace_frame_data_t {
size_t num; // The current fame number.
uintptr_t pc; // The absolute pc.
@@ -127,6 +145,10 @@
BacktraceMap* GetMap() { return map_; }
+ BacktraceUnwindError GetError() { return error_; }
+
+ std::string GetErrorString(BacktraceUnwindError error);
+
protected:
Backtrace(pid_t pid, pid_t tid, BacktraceMap* map);
@@ -145,6 +167,8 @@
bool map_shared_;
std::vector<backtrace_frame_data_t> frames_;
+
+ BacktraceUnwindError error_;
};
#endif // _BACKTRACE_BACKTRACE_H
diff --git a/include/utils/Thread.h b/include/utils/Thread.h
index 1532b7e..3792db7 100644
--- a/include/utils/Thread.h
+++ b/include/utils/Thread.h
@@ -45,7 +45,7 @@
virtual ~Thread();
// Start the thread in threadLoop() which needs to be implemented.
- virtual status_t run( const char* name = 0,
+ virtual status_t run( const char* name,
int32_t priority = PRIORITY_DEFAULT,
size_t stack = 0);
diff --git a/include/ziparchive/zip_archive.h b/include/ziparchive/zip_archive.h
index 3591a6b..7dc60ae 100644
--- a/include/ziparchive/zip_archive.h
+++ b/include/ziparchive/zip_archive.h
@@ -152,6 +152,9 @@
* if this file entry contains a data descriptor footer. To verify crc32s
* and length, a call to VerifyCrcAndLengths must be made after entry data
* has been processed.
+ *
+ * On non-Windows platforms this method does not modify internal state and
+ * can be called concurrently.
*/
int32_t FindEntry(const ZipArchiveHandle handle, const ZipString& entryName,
ZipEntry* data);
diff --git a/libbacktrace/Backtrace.cpp b/libbacktrace/Backtrace.cpp
index baa3d0f..995abc0 100644
--- a/libbacktrace/Backtrace.cpp
+++ b/libbacktrace/Backtrace.cpp
@@ -148,3 +148,24 @@
return new UnwindPtrace(pid, tid, map);
}
}
+
+std::string Backtrace::GetErrorString(BacktraceUnwindError error) {
+ switch (error) {
+ case BACKTRACE_UNWIND_NO_ERROR:
+ return "No error";
+ case BACKTRACE_UNWIND_ERROR_SETUP_FAILED:
+ return "Setup failed";
+ case BACKTRACE_UNWIND_ERROR_MAP_MISSING:
+ return "No map found";
+ case BACKTRACE_UNWIND_ERROR_INTERNAL:
+ return "Internal libbacktrace error, please submit a bugreport";
+ case BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST:
+ return "Thread doesn't exist";
+ case BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT:
+ return "Thread has not repsonded to signal in time";
+ case BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION:
+ return "Attempt to use an unsupported feature";
+ case BACKTRACE_UNWIND_ERROR_NO_CONTEXT:
+ return "Attempt to do an offline unwind without a context";
+ }
+}
diff --git a/libbacktrace/BacktraceCurrent.cpp b/libbacktrace/BacktraceCurrent.cpp
index 8e22366..5173e2c 100644
--- a/libbacktrace/BacktraceCurrent.cpp
+++ b/libbacktrace/BacktraceCurrent.cpp
@@ -24,6 +24,8 @@
#include <ucontext.h>
#include <unistd.h>
+#include <stdlib.h>
+
#include <string>
#include <backtrace/Backtrace.h>
@@ -65,9 +67,11 @@
bool BacktraceCurrent::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) {
if (GetMap() == nullptr) {
// Without a map object, we can't do anything.
+ error_ = BACKTRACE_UNWIND_ERROR_MAP_MISSING;
return false;
}
+ error_ = BACKTRACE_UNWIND_NO_ERROR;
if (ucontext) {
return UnwindFromContext(num_ignore_frames, ucontext);
}
@@ -138,11 +142,19 @@
BACK_LOGE("sigaction failed: %s", strerror(errno));
ThreadEntry::Remove(entry);
pthread_mutex_unlock(&g_sigaction_mutex);
+ error_ = BACKTRACE_UNWIND_ERROR_INTERNAL;
return false;
}
if (tgkill(Pid(), Tid(), THREAD_SIGNAL) != 0) {
- BACK_LOGE("tgkill %d failed: %s", Tid(), strerror(errno));
+ // Do not emit an error message, this might be expected. Set the
+ // error and let the caller decide.
+ if (errno == ESRCH) {
+ error_ = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST;
+ } else {
+ error_ = BACKTRACE_UNWIND_ERROR_INTERNAL;
+ }
+
sigaction(THREAD_SIGNAL, &oldact, nullptr);
ThreadEntry::Remove(entry);
pthread_mutex_unlock(&g_sigaction_mutex);
@@ -183,7 +195,13 @@
BACK_LOGW("Timed out waiting for signal handler to indicate it finished.");
}
} else {
- BACK_LOGE("Timed out waiting for signal handler to get ucontext data.");
+ // Check to see if the thread has disappeared.
+ if (tgkill(Pid(), Tid(), 0) == -1 && errno == ESRCH) {
+ error_ = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST;
+ } else {
+ error_ = BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT;
+ BACK_LOGE("Timed out waiting for signal handler to get ucontext data.");
+ }
}
ThreadEntry::Remove(entry);
diff --git a/libbacktrace/BacktraceOffline.cpp b/libbacktrace/BacktraceOffline.cpp
index e84ae74..ac14046 100644
--- a/libbacktrace/BacktraceOffline.cpp
+++ b/libbacktrace/BacktraceOffline.cpp
@@ -129,9 +129,11 @@
bool BacktraceOffline::Unwind(size_t num_ignore_frames, ucontext_t* context) {
if (context == nullptr) {
BACK_LOGW("The context is needed for offline backtracing.");
+ error_ = BACKTRACE_UNWIND_ERROR_NO_CONTEXT;
return false;
}
context_ = context;
+ error_ = BACKTRACE_UNWIND_NO_ERROR;
unw_addr_space_t addr_space = unw_create_addr_space(&accessors, 0);
unw_cursor_t cursor;
@@ -139,6 +141,7 @@
if (ret != 0) {
BACK_LOGW("unw_init_remote failed %d", ret);
unw_destroy_addr_space(addr_space);
+ error_ = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
return false;
}
size_t num_frames = 0;
diff --git a/libbacktrace/UnwindCurrent.cpp b/libbacktrace/UnwindCurrent.cpp
index 67e583f..666c481 100644
--- a/libbacktrace/UnwindCurrent.cpp
+++ b/libbacktrace/UnwindCurrent.cpp
@@ -70,6 +70,7 @@
int ret = unw_getcontext(&context_);
if (ret < 0) {
BACK_LOGW("unw_getcontext failed %d", ret);
+ error_ = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
return false;
}
} else {
@@ -81,6 +82,7 @@
int ret = unw_init_local(cursor.get(), &context_);
if (ret < 0) {
BACK_LOGW("unw_init_local failed %d", ret);
+ error_ = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
return false;
}
diff --git a/libbacktrace/UnwindPtrace.cpp b/libbacktrace/UnwindPtrace.cpp
index 07c2430..306d2ac 100644
--- a/libbacktrace/UnwindPtrace.cpp
+++ b/libbacktrace/UnwindPtrace.cpp
@@ -50,17 +50,22 @@
bool UnwindPtrace::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) {
if (GetMap() == nullptr) {
// Without a map object, we can't do anything.
+ error_ = BACKTRACE_UNWIND_ERROR_MAP_MISSING;
return false;
}
+ error_ = BACKTRACE_UNWIND_NO_ERROR;
+
if (ucontext) {
BACK_LOGW("Unwinding from a specified context not supported yet.");
+ error_ = BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION;
return false;
}
addr_space_ = unw_create_addr_space(&_UPT_accessors, 0);
if (!addr_space_) {
BACK_LOGW("unw_create_addr_space failed.");
+ error_ = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
return false;
}
@@ -70,6 +75,7 @@
upt_info_ = reinterpret_cast<struct UPT_info*>(_UPT_create(Tid()));
if (!upt_info_) {
BACK_LOGW("Failed to create upt info.");
+ error_ = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
return false;
}
@@ -77,6 +83,7 @@
int ret = unw_init_remote(&cursor, addr_space_, upt_info_);
if (ret < 0) {
BACK_LOGW("unw_init_remote failed %d", ret);
+ error_ = BACKTRACE_UNWIND_ERROR_SETUP_FAILED;
return false;
}
diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp
index 7d829fe..f6b2591 100644
--- a/libbacktrace/backtrace_test.cpp
+++ b/libbacktrace/backtrace_test.cpp
@@ -162,6 +162,7 @@
Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
ASSERT_TRUE(backtrace.get() != nullptr);
ASSERT_TRUE(backtrace->Unwind(0));
+ ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, backtrace->GetError());
VerifyLevelDump(backtrace.get());
}
@@ -183,6 +184,7 @@
Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
ASSERT_TRUE(backtrace.get() != nullptr);
ASSERT_TRUE(backtrace->Unwind(0));
+ ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, backtrace->GetError());
VerifyMaxDump(backtrace.get());
}
@@ -200,6 +202,7 @@
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), tid));
ASSERT_TRUE(backtrace.get() != nullptr);
ASSERT_TRUE(backtrace->Unwind(0));
+ ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, backtrace->GetError());
VerifyFunc(backtrace.get());
}
@@ -220,6 +223,7 @@
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), getpid()));
ASSERT_TRUE(backtrace.get() != nullptr);
ASSERT_TRUE(backtrace->Unwind(0));
+ ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, backtrace->GetError());
ASSERT_TRUE(backtrace->NumFrames() != 0);
for (const auto& frame : *backtrace ) {
@@ -267,16 +271,19 @@
Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
ASSERT_TRUE(all.get() != nullptr);
ASSERT_TRUE(all->Unwind(0));
+ ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, all->GetError());
std::unique_ptr<Backtrace> ign1(
Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
ASSERT_TRUE(ign1.get() != nullptr);
ASSERT_TRUE(ign1->Unwind(1));
+ ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, ign1->GetError());
std::unique_ptr<Backtrace> ign2(
Backtrace::Create(BACKTRACE_CURRENT_PROCESS, BACKTRACE_CURRENT_THREAD));
ASSERT_TRUE(ign2.get() != nullptr);
ASSERT_TRUE(ign2->Unwind(2));
+ ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, ign2->GetError());
VerifyIgnoreFrames(all.get(), ign1.get(), ign2.get(), "VerifyLevelIgnoreFrames");
}
@@ -314,6 +321,7 @@
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid, map.get()));
ASSERT_TRUE(backtrace.get() != nullptr);
ASSERT_TRUE(backtrace->Unwind(0));
+ ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, backtrace->GetError());
if (ReadyFunc(backtrace.get())) {
VerifyFunc(backtrace.get());
verified = true;
@@ -372,10 +380,12 @@
std::unique_ptr<Backtrace> ign1(Backtrace::Create(bt_all->Pid(), BACKTRACE_CURRENT_THREAD));
ASSERT_TRUE(ign1.get() != nullptr);
ASSERT_TRUE(ign1->Unwind(1));
+ ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, ign1->GetError());
std::unique_ptr<Backtrace> ign2(Backtrace::Create(bt_all->Pid(), BACKTRACE_CURRENT_THREAD));
ASSERT_TRUE(ign2.get() != nullptr);
ASSERT_TRUE(ign2->Unwind(2));
+ ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, ign2->GetError());
VerifyIgnoreFrames(bt_all, ign1.get(), ign2.get(), nullptr);
}
@@ -463,6 +473,7 @@
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), gettid()));
ASSERT_TRUE(backtrace.get() != nullptr);
ASSERT_TRUE(backtrace->Unwind(0));
+ ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, backtrace->GetError());
VerifyLevelDump(backtrace.get());
}
@@ -475,6 +486,7 @@
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), gettid()));
ASSERT_TRUE(backtrace.get() != nullptr);
ASSERT_TRUE(backtrace->Unwind(0));
+ ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, backtrace->GetError());
VerifyMaxDump(backtrace.get());
}
@@ -516,6 +528,7 @@
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid));
ASSERT_TRUE(backtrace.get() != nullptr);
ASSERT_TRUE(backtrace->Unwind(0));
+ ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, backtrace->GetError());
VerifyLevelDump(backtrace.get());
@@ -555,14 +568,17 @@
std::unique_ptr<Backtrace> all(Backtrace::Create(getpid(), thread_data.tid));
ASSERT_TRUE(all.get() != nullptr);
ASSERT_TRUE(all->Unwind(0));
+ ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, all->GetError());
std::unique_ptr<Backtrace> ign1(Backtrace::Create(getpid(), thread_data.tid));
ASSERT_TRUE(ign1.get() != nullptr);
ASSERT_TRUE(ign1->Unwind(1));
+ ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, ign1->GetError());
std::unique_ptr<Backtrace> ign2(Backtrace::Create(getpid(), thread_data.tid));
ASSERT_TRUE(ign2.get() != nullptr);
ASSERT_TRUE(ign2->Unwind(2));
+ ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, ign2->GetError());
VerifyIgnoreFrames(all.get(), ign1.get(), ign2.get(), nullptr);
@@ -593,6 +609,7 @@
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), thread_data.tid));
ASSERT_TRUE(backtrace.get() != nullptr);
ASSERT_TRUE(backtrace->Unwind(0));
+ ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, backtrace->GetError());
VerifyMaxDump(backtrace.get());
@@ -719,18 +736,21 @@
Backtrace* back1 = Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD, map1);
ASSERT_TRUE(back1 != nullptr);
EXPECT_TRUE(back1->Unwind(0));
+ ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, back1->GetError());
delete back1;
delete map1;
Backtrace* back2 = Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD, map2);
ASSERT_TRUE(back2 != nullptr);
EXPECT_TRUE(back2->Unwind(0));
+ ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, back2->GetError());
delete back2;
delete map2;
Backtrace* back3 = Backtrace::Create(getpid(), BACKTRACE_CURRENT_THREAD, map3);
ASSERT_TRUE(back3 != nullptr);
EXPECT_TRUE(back3->Unwind(0));
+ ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, back3->GetError());
delete back3;
delete map3;
}
@@ -1309,6 +1329,7 @@
BACKTRACE_CURRENT_THREAD));
ASSERT_TRUE(backtrace.get() != nullptr);
ASSERT_TRUE(backtrace->Unwind(0));
+ ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, backtrace->GetError());
size_t frame_num;
ASSERT_TRUE(FindFuncFrameInBacktrace(backtrace.get(), test_func, &frame_num));
@@ -1365,6 +1386,7 @@
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, BACKTRACE_CURRENT_THREAD));
ASSERT_TRUE(backtrace.get() != nullptr);
ASSERT_TRUE(backtrace->Unwind(0));
+ ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, backtrace->GetError());
size_t frame_num;
if (FindFuncFrameInBacktrace(backtrace.get(),
@@ -1388,6 +1410,14 @@
ASSERT_TRUE(done) << "Test function never found in unwind.";
}
+TEST(libbacktrace, unwind_thread_doesnt_exist) {
+ std::unique_ptr<Backtrace> backtrace(
+ Backtrace::Create(BACKTRACE_CURRENT_PROCESS, 99999999));
+ ASSERT_TRUE(backtrace.get() != nullptr);
+ ASSERT_FALSE(backtrace->Unwind(0));
+ ASSERT_EQ(BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST, backtrace->GetError());
+}
+
#if defined(ENABLE_PSS_TESTS)
#include "GetPss.h"
@@ -1399,6 +1429,7 @@
Backtrace* backtrace = Backtrace::Create(pid, tid);
ASSERT_TRUE(backtrace != nullptr);
ASSERT_TRUE(backtrace->Unwind(0));
+ ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, backtrace->GetError());
delete backtrace;
}
size_t stable_pss = GetPssBytes();
@@ -1409,6 +1440,7 @@
Backtrace* backtrace = Backtrace::Create(pid, tid);
ASSERT_TRUE(backtrace != nullptr);
ASSERT_TRUE(backtrace->Unwind(0));
+ ASSERT_EQ(BACKTRACE_UNWIND_NO_ERROR, backtrace->GetError());
delete backtrace;
}
size_t new_pss = GetPssBytes();
diff --git a/liblog/Android.mk b/liblog/Android.mk
index dd5b518..6d53a4a 100644
--- a/liblog/Android.mk
+++ b/liblog/Android.mk
@@ -39,7 +39,7 @@
LOCAL_SRC_FILES_darwin := event_tag_map.c
LOCAL_SRC_FILES_linux := event_tag_map.c
LOCAL_SRC_FILES_windows := uio.c
-LOCAL_CFLAGS := -DFAKE_LOG_DEVICE=1 -Werror $(liblog_cflags)
+LOCAL_CFLAGS := -DFAKE_LOG_DEVICE=1 -Werror -fvisibility=hidden $(liblog_cflags)
LOCAL_MULTILIB := both
LOCAL_MODULE_HOST_OS := darwin linux windows
include $(BUILD_HOST_STATIC_LIBRARY)
@@ -59,7 +59,7 @@
include $(CLEAR_VARS)
LOCAL_MODULE := liblog
LOCAL_SRC_FILES := $(liblog_target_sources)
-LOCAL_CFLAGS := -Werror $(liblog_cflags)
+LOCAL_CFLAGS := -Werror -fvisibility=hidden $(liblog_cflags)
# AddressSanitizer runtime library depends on liblog.
LOCAL_SANITIZE := never
include $(BUILD_STATIC_LIBRARY)
@@ -67,7 +67,7 @@
include $(CLEAR_VARS)
LOCAL_MODULE := liblog
LOCAL_WHOLE_STATIC_LIBRARIES := liblog
-LOCAL_CFLAGS := -Werror $(liblog_cflags)
+LOCAL_CFLAGS := -Werror -fvisibility=hidden $(liblog_cflags)
# TODO: This is to work around b/24465209. Remove after root cause is fixed
LOCAL_LDFLAGS_arm := -Wl,--hash-style=both
diff --git a/liblog/event_tag_map.c b/liblog/event_tag_map.c
index bea99aa..870c69a 100644
--- a/liblog/event_tag_map.c
+++ b/liblog/event_tag_map.c
@@ -24,6 +24,8 @@
#include <log/event_tag_map.h>
#include <log/log.h>
+#include "log_cdefs.h"
+
#define OUT_TAG "EventTagMap"
/*
@@ -61,7 +63,7 @@
* We create a private mapping because we want to terminate the log tag
* strings with '\0'.
*/
-EventTagMap* android_openEventTagMap(const char* fileName)
+LIBLOG_ABI_PUBLIC EventTagMap* android_openEventTagMap(const char* fileName)
{
EventTagMap* newTagMap;
off_t end;
@@ -109,7 +111,7 @@
/*
* Close the map.
*/
-void android_closeEventTagMap(EventTagMap* map)
+LIBLOG_ABI_PUBLIC void android_closeEventTagMap(EventTagMap* map)
{
if (map == NULL)
return;
@@ -123,7 +125,8 @@
*
* The entries are sorted by tag number, so we can do a binary search.
*/
-const char* android_lookupEventTag(const EventTagMap* map, int tag)
+LIBLOG_ABI_PUBLIC const char* android_lookupEventTag(const EventTagMap* map,
+ int tag)
{
int hi, lo, mid;
diff --git a/liblog/fake_log_device.c b/liblog/fake_log_device.c
index 2fe5f6d..c73e03e 100644
--- a/liblog/fake_log_device.c
+++ b/liblog/fake_log_device.c
@@ -19,23 +19,19 @@
* passed on to the underlying (fake) log device. When not in the
* simulator, messages are printed to stderr.
*/
-#include "fake_log_device.h"
-
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
+#if !defined(_WIN32)
+#include <pthread.h>
+#endif
#include <stdlib.h>
#include <string.h>
#include <log/logd.h>
-#if !defined(_WIN32)
-#include <pthread.h>
-#endif
-
-#ifndef __unused
-#define __unused __attribute__((__unused__))
-#endif
+#include "fake_log_device.h"
+#include "log_cdefs.h"
#define kMaxTagLen 16 /* from the long-dead utils/Log.cpp */
@@ -69,7 +65,7 @@
int fakeFd;
/* a printable name for this fake device */
- char *debugName;
+ char debugName[sizeof("/dev/log/security")];
/* nonzero if this is a binary log */
int isBinary;
@@ -123,8 +119,8 @@
* File descriptor management.
*/
#define FAKE_FD_BASE 10000
-#define MAX_OPEN_LOGS 16
-static LogState *openLogTable[MAX_OPEN_LOGS];
+#define MAX_OPEN_LOGS 8
+static LogState openLogTable[MAX_OPEN_LOGS];
/*
* Allocate an fd and associate a new LogState with it.
@@ -134,11 +130,10 @@
{
size_t i;
- for (i = 0; i < sizeof(openLogTable); i++) {
- if (openLogTable[i] == NULL) {
- openLogTable[i] = calloc(1, sizeof(LogState));
- openLogTable[i]->fakeFd = FAKE_FD_BASE + i;
- return openLogTable[i];
+ for (i = 0; i < (sizeof(openLogTable) / sizeof(openLogTable[0])); i++) {
+ if (openLogTable[i].fakeFd == 0) {
+ openLogTable[i].fakeFd = FAKE_FD_BASE + i;
+ return &openLogTable[i];
}
}
return NULL;
@@ -150,7 +145,7 @@
static LogState *fdToLogState(int fd)
{
if (fd >= FAKE_FD_BASE && fd < FAKE_FD_BASE + MAX_OPEN_LOGS) {
- return openLogTable[fd - FAKE_FD_BASE];
+ return &openLogTable[fd - FAKE_FD_BASE];
}
return NULL;
}
@@ -166,9 +161,7 @@
ls = fdToLogState(fd);
if (ls != NULL) {
- openLogTable[fd - FAKE_FD_BASE] = NULL;
- free(ls->debugName);
- free(ls);
+ memset(&openLogTable[fd - FAKE_FD_BASE], 0, sizeof(openLogTable[0]));
}
unlock();
@@ -191,10 +184,12 @@
{
static const int kDevLogLen = sizeof("/dev/log/") - 1;
- logState->debugName = strdup(pathName);
+ strncpy(logState->debugName, pathName, sizeof(logState->debugName));
+ logState->debugName[sizeof(logState->debugName) - 1] = '\0';
/* identify binary logs */
- if (strcmp(pathName + kDevLogLen, "events") == 0) {
+ if (!strcmp(pathName + kDevLogLen, "events") ||
+ !strcmp(pathName + kDevLogLen, "security")) {
logState->isBinary = 1;
}
@@ -218,8 +213,7 @@
i = 0;
while (*tags != '\0' && !isspace(*tags) && *tags != ':' &&
- i < kMaxTagLen)
- {
+ i < kMaxTagLen) {
tagName[i++] = *tags++;
}
if (i == kMaxTagLen) {
@@ -320,9 +314,9 @@
};
int idx;
- idx = (int) priority - (int) ANDROID_LOG_VERBOSE;
+ idx = (int)priority - (int)ANDROID_LOG_VERBOSE;
if (idx < 0 ||
- idx >= (int) (sizeof(priorityStrings) / sizeof(priorityStrings[0])))
+ idx >= (int)(sizeof(priorityStrings) / sizeof(priorityStrings[0])))
return "?unknown?";
return priorityStrings[idx];
}
@@ -454,13 +448,15 @@
while (p < end) {
if (*p++ == '\n') numLines++;
}
- if (p > msg && *(p-1) != '\n') numLines++;
+ if (p > msg && *(p-1) != '\n') {
+ numLines++;
+ }
/*
* Create an array of iovecs large enough to write all of
* the lines with a prefix and a suffix.
*/
- const size_t INLINE_VECS = 6;
+ const size_t INLINE_VECS = 64;
const size_t MAX_LINES = ((size_t)~0)/(3*sizeof(struct iovec*));
struct iovec stackVec[INLINE_VECS];
struct iovec* vec = stackVec;
@@ -494,7 +490,9 @@
v++;
}
const char* start = p;
- while (p < end && *p != '\n') p++;
+ while (p < end && *p != '\n') {
+ p++;
+ }
if ((p-start) > 0) {
v->iov_base = (void*)start;
v->iov_len = p-start;
@@ -510,7 +508,7 @@
}
numLines -= 1;
}
-
+
/*
* Write the entire message to the log file with a single writev() call.
* We need to use this rather than a collection of printf()s on a FILE*
@@ -529,10 +527,10 @@
int cc = writev(fileno(stderr), vec, v-vec);
if (cc == totalLen) break;
-
+
if (cc < 0) {
if(errno == EINTR) continue;
-
+
/* can't really log the failure; for now, throw out a stderr */
fprintf(stderr, "+++ LOG: write failed (errno=%d)\n", errno);
break;
@@ -681,7 +679,7 @@
}
}
-int fakeLogOpen(const char *pathName, int flags)
+LIBLOG_HIDDEN int fakeLogOpen(const char *pathName, int flags)
{
if (redirectOpen == NULL) {
setRedirects();
@@ -689,19 +687,33 @@
return redirectOpen(pathName, flags);
}
-int fakeLogClose(int fd)
+/*
+ * The logger API has no means or need to 'stop' or 'close' using the logs,
+ * and as such, there is no way for that 'stop' or 'close' to translate into
+ * a close operation to the fake log handler. fakeLogClose is provided for
+ * completeness only.
+ *
+ * We have no intention of adding a log close operation as it would complicate
+ * every user of the logging API with no gain since the only valid place to
+ * call is in the exit handler. Logging can continue in the exit handler to
+ * help debug HOST tools ...
+ */
+LIBLOG_HIDDEN int fakeLogClose(int fd)
{
/* Assume that open() was called first. */
return redirectClose(fd);
}
-ssize_t fakeLogWritev(int fd, const struct iovec* vector, int count)
+LIBLOG_HIDDEN ssize_t fakeLogWritev(int fd,
+ const struct iovec* vector, int count)
{
/* Assume that open() was called first. */
return redirectWritev(fd, vector, count);
}
-int __android_log_is_loggable(int prio, const char *tag __unused, int def)
+LIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio,
+ const char *tag __unused,
+ int def)
{
int logLevel = def;
return logLevel >= 0 && prio >= logLevel;
diff --git a/liblog/fake_log_device.h b/liblog/fake_log_device.h
index 9d168cd..672b446 100644
--- a/liblog/fake_log_device.h
+++ b/liblog/fake_log_device.h
@@ -19,10 +19,13 @@
#include <sys/types.h>
+#include "log_cdefs.h"
+
struct iovec;
-int fakeLogOpen(const char *pathName, int flags);
-int fakeLogClose(int fd);
-ssize_t fakeLogWritev(int fd, const struct iovec* vector, int count);
+LIBLOG_HIDDEN int fakeLogOpen(const char *pathName, int flags);
+LIBLOG_HIDDEN int fakeLogClose(int fd);
+LIBLOG_HIDDEN ssize_t fakeLogWritev(int fd,
+ const struct iovec* vector, int count);
#endif // _LIBLOG_FAKE_LOG_DEVICE_H
diff --git a/liblog/log_cdefs.h b/liblog/log_cdefs.h
new file mode 100644
index 0000000..3a52625
--- /dev/null
+++ b/liblog/log_cdefs.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBLOG_CDEFS_H__
+#define _LIBLOG_CDEFS_H__
+
+#include <sys/cdefs.h>
+
+/* Declare this library function hidden and internal */
+#if defined(_WIN32)
+#define LIBLOG_HIDDEN
+#else
+#define LIBLOG_HIDDEN __attribute__((visibility("hidden")))
+#endif
+
+/* Declare this library function visible and external */
+#if defined(_WIN32)
+#define LIBLOG_ABI_PUBLIC
+#else
+#define LIBLOG_ABI_PUBLIC __attribute__((visibility("default")))
+#endif
+
+/* Declare this library function visible but private */
+#define LIBLOG_ABI_PRIVATE LIBLOG_ABI_PUBLIC
+
+/*
+ * Declare this library function as reimplementation.
+ * Prevent circular dependencies, but allow _real_ library to hijack
+ */
+#if defined(_WIN32)
+#define LIBLOG_WEAK static /* Accept that it is totally private */
+#else
+#define LIBLOG_WEAK __attribute__((weak,visibility("default")))
+#endif
+
+/* Unused argument. For C code only, remove symbol name for C++ */
+#ifndef __unused
+#define __unused __attribute__((__unused__))
+#endif
+
+#endif /* _LIBLOG_CDEFS_H__ */
diff --git a/liblog/log_event_list.c b/liblog/log_event_list.c
index 2213f21..a77c56e 100644
--- a/liblog/log_event_list.c
+++ b/liblog/log_event_list.c
@@ -25,6 +25,8 @@
#include <log/log.h>
#include <log/logger.h>
+#include "log_cdefs.h"
+
#define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(int32_t))
typedef struct {
@@ -43,7 +45,7 @@
uint8_t storage[LOGGER_ENTRY_MAX_PAYLOAD];
} android_log_context_internal;
-android_log_context create_android_logger(uint32_t tag) {
+LIBLOG_ABI_PUBLIC android_log_context create_android_logger(uint32_t tag) {
size_t needed, i;
android_log_context_internal *context;
@@ -65,7 +67,9 @@
return (android_log_context)context;
}
-android_log_context create_android_log_parser(const char *msg, size_t len) {
+LIBLOG_ABI_PUBLIC android_log_context create_android_log_parser(
+ const char *msg,
+ size_t len) {
android_log_context_internal *context;
size_t i;
@@ -81,7 +85,7 @@
return (android_log_context)context;
}
-int android_log_destroy(android_log_context *ctx) {
+LIBLOG_ABI_PUBLIC int android_log_destroy(android_log_context *ctx) {
android_log_context_internal *context;
context = (android_log_context_internal *)*ctx;
@@ -94,7 +98,7 @@
return 0;
}
-int android_log_write_list_begin(android_log_context ctx) {
+LIBLOG_ABI_PUBLIC int android_log_write_list_begin(android_log_context ctx) {
size_t needed;
android_log_context_internal *context;
@@ -137,7 +141,8 @@
buf[3] = (val >> 24) & 0xFF;
}
-int android_log_write_int32(android_log_context ctx, int32_t value) {
+LIBLOG_ABI_PUBLIC int android_log_write_int32(android_log_context ctx,
+ int32_t value) {
size_t needed;
android_log_context_internal *context;
@@ -172,7 +177,8 @@
buf[7] = (val >> 56) & 0xFF;
}
-int android_log_write_int64(android_log_context ctx, int64_t value) {
+LIBLOG_ABI_PUBLIC int android_log_write_int64(android_log_context ctx,
+ int64_t value) {
size_t needed;
android_log_context_internal *context;
@@ -195,8 +201,9 @@
return 0;
}
-int android_log_write_string8_len(android_log_context ctx,
- const char *value, size_t maxlen) {
+LIBLOG_ABI_PUBLIC int android_log_write_string8_len(android_log_context ctx,
+ const char *value,
+ size_t maxlen) {
size_t needed;
ssize_t len;
android_log_context_internal *context;
@@ -231,11 +238,13 @@
return len;
}
-int android_log_write_string8(android_log_context ctx, const char *value) {
+LIBLOG_ABI_PUBLIC int android_log_write_string8(android_log_context ctx,
+ const char *value) {
return android_log_write_string8_len(ctx, value, MAX_EVENT_PAYLOAD);
}
-int android_log_write_float32(android_log_context ctx, float value) {
+LIBLOG_ABI_PUBLIC int android_log_write_float32(android_log_context ctx,
+ float value) {
size_t needed;
uint32_t ivalue;
android_log_context_internal *context;
@@ -260,7 +269,7 @@
return 0;
}
-int android_log_write_list_end(android_log_context ctx) {
+LIBLOG_ABI_PUBLIC int android_log_write_list_end(android_log_context ctx) {
android_log_context_internal *context;
context = (android_log_context_internal *)ctx;
@@ -290,7 +299,8 @@
/*
* Logs the list of elements to the event log.
*/
-int android_log_write_list(android_log_context ctx, log_id_t id) {
+LIBLOG_ABI_PUBLIC int android_log_write_list(android_log_context ctx,
+ log_id_t id) {
android_log_context_internal *context;
const char *msg;
ssize_t len;
@@ -518,10 +528,12 @@
}
}
-android_log_list_element android_log_read_next(android_log_context ctx) {
+LIBLOG_ABI_PUBLIC android_log_list_element android_log_read_next(
+ android_log_context ctx) {
return android_log_read_next_internal(ctx, 0);
}
-android_log_list_element android_log_peek_next(android_log_context ctx) {
+LIBLOG_ABI_PUBLIC android_log_list_element android_log_peek_next(
+ android_log_context ctx) {
return android_log_read_next_internal(ctx, 1);
}
diff --git a/liblog/log_event_write.c b/liblog/log_event_write.c
index ad42edd..3535b94 100644
--- a/liblog/log_event_write.c
+++ b/liblog/log_event_write.c
@@ -18,10 +18,15 @@
#include <log/log.h>
+#include "log_cdefs.h"
+
#define MAX_SUBTAG_LEN 32
-int __android_log_error_write(int tag, const char *subTag, int32_t uid,
- const char *data, uint32_t dataLen)
+LIBLOG_ABI_PUBLIC int __android_log_error_write(
+ int tag,
+ const char *subTag,
+ int32_t uid,
+ const char *data, uint32_t dataLen)
{
int ret = -EINVAL;
diff --git a/liblog/log_is_loggable.c b/liblog/log_is_loggable.c
index 2f8f886..47fde20 100644
--- a/liblog/log_is_loggable.c
+++ b/liblog/log_is_loggable.c
@@ -23,6 +23,8 @@
#include <android/log.h>
+#include "log_cdefs.h"
+
static pthread_mutex_t lock_loggable = PTHREAD_MUTEX_INITIALIZER;
static int lock()
@@ -250,7 +252,8 @@
return default_prio;
}
-int __android_log_is_loggable(int prio, const char *tag, int default_prio)
+LIBLOG_ABI_PUBLIC int __android_log_is_loggable(int prio, const char *tag,
+ int default_prio)
{
int logLevel = __android_log_level(tag, default_prio);
return logLevel >= 0 && prio >= logLevel;
@@ -315,7 +318,7 @@
* Timestamp state generally remains constant, but can change at any time
* to handle developer requirements.
*/
-clockid_t android_log_clockid()
+LIBLOG_ABI_PUBLIC clockid_t android_log_clockid()
{
static struct cache2 clockid = {
PTHREAD_MUTEX_INITIALIZER,
@@ -343,7 +346,7 @@
return (c != BOOLEAN_FALSE) && c && (self->cache_persist.c == BOOLEAN_TRUE);
}
-int __android_log_security()
+LIBLOG_ABI_PUBLIC int __android_log_security()
{
static struct cache2 security = {
PTHREAD_MUTEX_INITIALIZER,
diff --git a/liblog/log_read.c b/liblog/log_read.c
index fc63d2c..4b83944 100644
--- a/liblog/log_read.c
+++ b/liblog/log_read.c
@@ -24,7 +24,6 @@
#define NOMINMAX /* for windows to suppress definition of min in stdlib.h */
#include <stdlib.h>
#include <string.h>
-#include <sys/cdefs.h>
#include <unistd.h>
#include <cutils/list.h>
@@ -34,23 +33,16 @@
#include <private/android_filesystem_config.h>
#include <private/android_logger.h>
+#include "log_cdefs.h"
+
/* branchless on many architectures. */
#define min(x,y) ((y) ^ (((x) ^ (y)) & -((x) < (y))))
-#if defined(_WIN32)
-#define WEAK static
-#else
-#define WEAK __attribute__((weak))
-#endif
-#ifndef __unused
-#define __unused __attribute__((unused))
-#endif
-
/* Private copy of ../libcutils/socket_local_client.c prevent library loops */
#if defined(_WIN32)
-int WEAK socket_local_client(const char *name, int namespaceId, int type)
+LIBLOG_WEAK int socket_local_client(const char *name, int namespaceId, int type)
{
errno = ENOSYS;
return -ENOSYS;
@@ -71,8 +63,9 @@
#define LISTEN_BACKLOG 4
/* Documented in header file. */
-int WEAK socket_make_sockaddr_un(const char *name, int namespaceId,
- struct sockaddr_un *p_addr, socklen_t *alen)
+LIBLOG_WEAK int socket_make_sockaddr_un(const char *name, int namespaceId,
+ struct sockaddr_un *p_addr,
+ socklen_t *alen)
{
memset (p_addr, 0, sizeof (*p_addr));
size_t namelen;
@@ -151,8 +144,8 @@
*
* Used by AndroidSocketImpl
*/
-int WEAK socket_local_client_connect(int fd, const char *name, int namespaceId,
- int type __unused)
+LIBLOG_WEAK int socket_local_client_connect(int fd, const char *name,
+ int namespaceId, int type __unused)
{
struct sockaddr_un addr;
socklen_t alen;
@@ -178,7 +171,7 @@
* connect to peer named "name"
* returns fd or -1 on error
*/
-int WEAK socket_local_client(const char *name, int namespaceId, int type)
+LIBLOG_WEAK int socket_local_client(const char *name, int namespaceId, int type)
{
int s;
@@ -212,7 +205,7 @@
[LOG_ID_KERNEL] = "kernel",
};
-const char *android_log_id_to_name(log_id_t log_id)
+LIBLOG_ABI_PUBLIC const char *android_log_id_to_name(log_id_t log_id)
{
if (log_id >= LOG_ID_MAX) {
log_id = LOG_ID_MAIN;
@@ -220,7 +213,7 @@
return LOG_NAME[log_id];
}
-log_id_t android_name_to_log_id(const char *logName)
+LIBLOG_ABI_PUBLIC log_id_t android_name_to_log_id(const char *logName)
{
const char *b;
int ret;
@@ -275,7 +268,7 @@
/* android_logger_alloc unimplemented, no use case */
/* method for getting the associated sublog id */
-log_id_t android_logger_get_id(struct logger *logger)
+LIBLOG_ABI_PUBLIC log_id_t android_logger_get_id(struct logger *logger)
{
return logger->id;
}
@@ -409,7 +402,7 @@
return last_uid = uid;
}
-int android_logger_clear(struct logger *logger)
+LIBLOG_ABI_PUBLIC int android_logger_clear(struct logger *logger)
{
char buf[512];
@@ -425,7 +418,7 @@
}
/* returns the total size of the log's ring buffer */
-long android_logger_get_log_size(struct logger *logger)
+LIBLOG_ABI_PUBLIC long android_logger_get_log_size(struct logger *logger)
{
char buf[512];
@@ -441,7 +434,8 @@
return atol(buf);
}
-int android_logger_set_log_size(struct logger *logger, unsigned long size)
+LIBLOG_ABI_PUBLIC int android_logger_set_log_size(struct logger *logger,
+ unsigned long size)
{
char buf[512];
@@ -455,7 +449,8 @@
* returns the readable size of the log's ring buffer (that is, amount of the
* log consumed)
*/
-long android_logger_get_log_readable_size(struct logger *logger)
+LIBLOG_ABI_PUBLIC long android_logger_get_log_readable_size(
+ struct logger *logger)
{
char buf[512];
@@ -474,16 +469,18 @@
/*
* returns the logger version
*/
-int android_logger_get_log_version(struct logger *logger __unused)
+LIBLOG_ABI_PUBLIC int android_logger_get_log_version(
+ struct logger *logger __unused)
{
- return 3;
+ return 4;
}
/*
* returns statistics
*/
-ssize_t android_logger_get_statistics(struct logger_list *logger_list,
- char *buf, size_t len)
+LIBLOG_ABI_PUBLIC ssize_t android_logger_get_statistics(
+ struct logger_list *logger_list,
+ char *buf, size_t len)
{
struct logger *logger;
char *cp = buf;
@@ -509,14 +506,16 @@
return send_log_msg(NULL, NULL, buf, len);
}
-ssize_t android_logger_get_prune_list(struct logger_list *logger_list __unused,
- char *buf, size_t len)
+LIBLOG_ABI_PUBLIC ssize_t android_logger_get_prune_list(
+ struct logger_list *logger_list __unused,
+ char *buf, size_t len)
{
return send_log_msg(NULL, "getPruneList", buf, len);
}
-int android_logger_set_prune_list(struct logger_list *logger_list __unused,
- char *buf, size_t len)
+LIBLOG_ABI_PUBLIC int android_logger_set_prune_list(
+ struct logger_list *logger_list __unused,
+ char *buf, size_t len)
{
const char cmd[] = "setPruneList ";
const size_t cmdlen = sizeof(cmd) - 1;
@@ -531,9 +530,10 @@
return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
}
-struct logger_list *android_logger_list_alloc(int mode,
- unsigned int tail,
- pid_t pid)
+LIBLOG_ABI_PUBLIC struct logger_list *android_logger_list_alloc(
+ int mode,
+ unsigned int tail,
+ pid_t pid)
{
struct logger_list *logger_list;
@@ -553,9 +553,10 @@
return logger_list;
}
-struct logger_list *android_logger_list_alloc_time(int mode,
- log_time start,
- pid_t pid)
+LIBLOG_ABI_PUBLIC struct logger_list *android_logger_list_alloc_time(
+ int mode,
+ log_time start,
+ pid_t pid)
{
struct logger_list *logger_list;
@@ -578,8 +579,9 @@
/* android_logger_list_unregister unimplemented, no use case */
/* Open the named log and add it to the logger list */
-struct logger *android_logger_open(struct logger_list *logger_list,
- log_id_t id)
+LIBLOG_ABI_PUBLIC struct logger *android_logger_open(
+ struct logger_list *logger_list,
+ log_id_t id)
{
struct logger *logger;
@@ -610,10 +612,11 @@
}
/* Open the single named log and make it part of a new logger list */
-struct logger_list *android_logger_list_open(log_id_t id,
- int mode,
- unsigned int tail,
- pid_t pid)
+LIBLOG_ABI_PUBLIC struct logger_list *android_logger_list_open(
+ log_id_t id,
+ int mode,
+ unsigned int tail,
+ pid_t pid)
{
struct logger_list *logger_list = android_logger_list_alloc(mode, tail, pid);
if (!logger_list) {
@@ -751,8 +754,9 @@
}
/* Read from the selected logs */
-int android_logger_list_read(struct logger_list *logger_list,
- struct log_msg *log_msg)
+LIBLOG_ABI_PUBLIC int android_logger_list_read(
+ struct logger_list *logger_list,
+ struct log_msg *log_msg)
{
int ret, e;
struct logger *logger;
@@ -892,7 +896,8 @@
}
/* Close all the logs */
-void android_logger_list_free(struct logger_list *logger_list)
+LIBLOG_ABI_PUBLIC void android_logger_list_free(
+ struct logger_list *logger_list)
{
if (logger_list == NULL) {
return;
diff --git a/liblog/log_time.cpp b/liblog/log_time.cpp
index 9d5ea0e..b6af222 100644
--- a/liblog/log_time.cpp
+++ b/liblog/log_time.cpp
@@ -18,16 +18,17 @@
#include <limits.h>
#include <stdio.h>
#include <string.h>
-#include <sys/cdefs.h>
#include <log/log_read.h>
-const char log_time::default_format[] = "%m-%d %H:%M:%S.%q";
-const timespec log_time::EPOCH = { 0, 0 };
+#include "log_cdefs.h"
+
+LIBLOG_ABI_PRIVATE const char log_time::default_format[] = "%m-%d %H:%M:%S.%q";
+LIBLOG_ABI_PRIVATE const timespec log_time::EPOCH = { 0, 0 };
// Add %#q for fractional seconds to standard strptime function
-char *log_time::strptime(const char *s, const char *format) {
+LIBLOG_ABI_PRIVATE char *log_time::strptime(const char *s, const char *format) {
time_t now;
#ifdef __linux__
*this = log_time(CLOCK_REALTIME);
@@ -133,7 +134,7 @@
return ret;
}
-log_time log_time::operator-= (const timespec &T) {
+LIBLOG_ABI_PRIVATE log_time log_time::operator-= (const timespec &T) {
// No concept of negative time, clamp to EPOCH
if (*this <= T) {
return *this = EPOCH;
@@ -150,7 +151,7 @@
return *this;
}
-log_time log_time::operator+= (const timespec &T) {
+LIBLOG_ABI_PRIVATE log_time log_time::operator+= (const timespec &T) {
this->tv_nsec += (unsigned long int)T.tv_nsec;
if (this->tv_nsec >= NS_PER_SEC) {
this->tv_nsec -= NS_PER_SEC;
@@ -161,7 +162,7 @@
return *this;
}
-log_time log_time::operator-= (const log_time &T) {
+LIBLOG_ABI_PRIVATE log_time log_time::operator-= (const log_time &T) {
// No concept of negative time, clamp to EPOCH
if (*this <= T) {
return *this = EPOCH;
@@ -178,7 +179,7 @@
return *this;
}
-log_time log_time::operator+= (const log_time &T) {
+LIBLOG_ABI_PRIVATE log_time log_time::operator+= (const log_time &T) {
this->tv_nsec += T.tv_nsec;
if (this->tv_nsec >= NS_PER_SEC) {
this->tv_nsec -= NS_PER_SEC;
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index 4946073..85a4aab 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -46,6 +46,8 @@
#include <private/android_filesystem_config.h>
#include <private/android_logger.h>
+#include "log_cdefs.h"
+
#define LOG_BUF_SIZE 1024
#if FAKE_LOG_DEVICE
@@ -56,10 +58,6 @@
static int __write_to_log_init(log_id_t, struct iovec *vec, size_t nr);
static int (*write_to_log)(log_id_t, struct iovec *vec, size_t nr) = __write_to_log_init;
-#ifndef __unused
-#define __unused __attribute__((__unused__))
-#endif
-
#if !defined(_WIN32)
static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -106,7 +104,7 @@
kLogUninitialized, kLogNotAvailable, kLogAvailable
} g_log_status = kLogUninitialized;
-int __android_log_dev_available(void)
+LIBLOG_ABI_PUBLIC int __android_log_dev_available()
{
if (g_log_status == kLogUninitialized) {
if (access("/dev/socket/logdw", W_OK) == 0)
@@ -125,7 +123,7 @@
#if FAKE_LOG_DEVICE
for (i = 0; i < LOG_ID_MAX; i++) {
- char buf[sizeof("/dev/log_system")];
+ char buf[sizeof("/dev/log_security")];
snprintf(buf, sizeof(buf), "/dev/log_%s", android_log_id_to_name(i));
log_fds[i] = fakeLogOpen(buf, O_WRONLY);
}
@@ -485,7 +483,7 @@
[LOG_ID_KERNEL] = "kernel",
};
-const char *android_log_id_to_name(log_id_t log_id)
+LIBLOG_ABI_PUBLIC const char *android_log_id_to_name(log_id_t log_id)
{
if (log_id >= LOG_ID_MAX) {
log_id = LOG_ID_MAIN;
@@ -520,12 +518,14 @@
return write_to_log(log_id, vec, nr);
}
-int __android_log_write(int prio, const char *tag, const char *msg)
+LIBLOG_ABI_PUBLIC int __android_log_write(int prio, const char *tag,
+ const char *msg)
{
return __android_log_buf_write(LOG_ID_MAIN, prio, tag, msg);
}
-int __android_log_buf_write(int bufID, int prio, const char *tag, const char *msg)
+LIBLOG_ABI_PUBLIC int __android_log_buf_write(int bufID, int prio,
+ const char *tag, const char *msg)
{
struct iovec vec[3];
char tmp_tag[32];
@@ -566,7 +566,8 @@
return write_to_log(bufID, vec, 3);
}
-int __android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap)
+LIBLOG_ABI_PUBLIC int __android_log_vprint(int prio, const char *tag,
+ const char *fmt, va_list ap)
{
char buf[LOG_BUF_SIZE];
@@ -575,7 +576,8 @@
return __android_log_write(prio, tag, buf);
}
-int __android_log_print(int prio, const char *tag, const char *fmt, ...)
+LIBLOG_ABI_PUBLIC int __android_log_print(int prio, const char *tag,
+ const char *fmt, ...)
{
va_list ap;
char buf[LOG_BUF_SIZE];
@@ -587,7 +589,9 @@
return __android_log_write(prio, tag, buf);
}
-int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...)
+LIBLOG_ABI_PUBLIC int __android_log_buf_print(int bufID, int prio,
+ const char *tag,
+ const char *fmt, ...)
{
va_list ap;
char buf[LOG_BUF_SIZE];
@@ -599,8 +603,10 @@
return __android_log_buf_write(bufID, prio, tag, buf);
}
-void __android_log_assert(const char *cond, const char *tag,
- const char *fmt, ...)
+LIBLOG_ABI_PUBLIC void __android_log_assert(
+ const char *cond,
+ const char *tag,
+ const char *fmt, ...)
{
char buf[LOG_BUF_SIZE];
@@ -625,7 +631,8 @@
/* NOTREACHED */
}
-int __android_log_bwrite(int32_t tag, const void *payload, size_t len)
+LIBLOG_ABI_PUBLIC int __android_log_bwrite(int32_t tag,
+ const void *payload, size_t len)
{
struct iovec vec[2];
@@ -637,7 +644,9 @@
return write_to_log(LOG_ID_EVENTS, vec, 2);
}
-int __android_log_security_bwrite(int32_t tag, const void *payload, size_t len)
+LIBLOG_ABI_PUBLIC int __android_log_security_bwrite(int32_t tag,
+ const void *payload,
+ size_t len)
{
struct iovec vec[2];
@@ -654,8 +663,8 @@
* for the general case where we're generating lists of stuff, but very
* handy if we just want to dump an integer into the log.
*/
-int __android_log_btwrite(int32_t tag, char type, const void *payload,
- size_t len)
+LIBLOG_ABI_PUBLIC int __android_log_btwrite(int32_t tag, char type,
+ const void *payload, size_t len)
{
struct iovec vec[3];
@@ -673,7 +682,7 @@
* Like __android_log_bwrite, but used for writing strings to the
* event log.
*/
-int __android_log_bswrite(int32_t tag, const char *payload)
+LIBLOG_ABI_PUBLIC int __android_log_bswrite(int32_t tag, const char *payload)
{
struct iovec vec[4];
char type = EVENT_TYPE_STRING;
@@ -695,7 +704,8 @@
* Like __android_log_security_bwrite, but used for writing strings to the
* security log.
*/
-int __android_log_security_bswrite(int32_t tag, const char *payload)
+LIBLOG_ABI_PUBLIC int __android_log_security_bswrite(int32_t tag,
+ const char *payload)
{
struct iovec vec[4];
char type = EVENT_TYPE_STRING;
diff --git a/liblog/logprint.c b/liblog/logprint.c
index 4ef62a1..19a3e27 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.c
@@ -34,12 +34,11 @@
#include <log/logprint.h>
#include <private/android_filesystem_config.h>
+#include "log_cdefs.h"
+
#define MS_PER_NSEC 1000000
#define US_PER_NSEC 1000
-/* open coded fragment, prevent circular dependencies */
-#define WEAK static
-
typedef struct FilterInfo_t {
char *mTag;
android_LogPriority mPri;
@@ -185,13 +184,15 @@
* returns 1 if this log line should be printed based on its priority
* and tag, and 0 if it should not
*/
-int android_log_shouldPrintLine (
- AndroidLogFormat *p_format, const char *tag, android_LogPriority pri)
+LIBLOG_ABI_PUBLIC int android_log_shouldPrintLine (
+ AndroidLogFormat *p_format,
+ const char *tag,
+ android_LogPriority pri)
{
return pri >= filterPriForTag(p_format, tag);
}
-AndroidLogFormat *android_log_format_new()
+LIBLOG_ABI_PUBLIC AndroidLogFormat *android_log_format_new()
{
AndroidLogFormat *p_ret;
@@ -213,7 +214,7 @@
static list_declare(convertHead);
-void android_log_format_free(AndroidLogFormat *p_format)
+LIBLOG_ABI_PUBLIC void android_log_format_free(AndroidLogFormat *p_format)
{
FilterInfo *p_info, *p_info_old;
@@ -236,7 +237,8 @@
}
}
-int android_log_setPrintFormat(AndroidLogFormat *p_format,
+LIBLOG_ABI_PUBLIC int android_log_setPrintFormat(
+ AndroidLogFormat *p_format,
AndroidLogPrintFormat format)
{
switch (format) {
@@ -277,7 +279,8 @@
/**
* Returns FORMAT_OFF on invalid string
*/
-AndroidLogPrintFormat android_log_formatFromString(const char * formatString)
+LIBLOG_ABI_PUBLIC AndroidLogPrintFormat android_log_formatFromString(
+ const char * formatString)
{
static AndroidLogPrintFormat format;
@@ -341,7 +344,8 @@
* Assumes single threaded execution
*/
-int android_log_addFilterRule(AndroidLogFormat *p_format,
+LIBLOG_ABI_PUBLIC int android_log_addFilterRule(
+ AndroidLogFormat *p_format,
const char *filterExpression)
{
size_t tagNameLength;
@@ -419,7 +423,8 @@
*
*/
-int android_log_addFilterString(AndroidLogFormat *p_format,
+LIBLOG_ABI_PUBLIC int android_log_addFilterString(
+ AndroidLogFormat *p_format,
const char *filterString)
{
char *filterStringCopy = strdup (filterString);
@@ -453,8 +458,9 @@
* Returns 0 on success and -1 on invalid wire format (entry will be
* in unspecified state)
*/
-int android_log_processLogBuffer(struct logger_entry *buf,
- AndroidLogEntry *entry)
+LIBLOG_ABI_PUBLIC int android_log_processLogBuffer(
+ struct logger_entry *buf,
+ AndroidLogEntry *entry)
{
entry->tv_sec = buf->sec;
entry->tv_nsec = buf->nsec;
@@ -734,9 +740,11 @@
* it however we choose, which means we can't really use a fixed-size buffer
* here.
*/
-int android_log_processBinaryLogBuffer(struct logger_entry *buf,
- AndroidLogEntry *entry, const EventTagMap* map, char* messageBuf,
- int messageBufLen)
+LIBLOG_ABI_PUBLIC int android_log_processBinaryLogBuffer(
+ struct logger_entry *buf,
+ AndroidLogEntry *entry,
+ const EventTagMap *map,
+ char *messageBuf, int messageBufLen)
{
size_t inCount;
unsigned int tagIndex;
@@ -852,7 +860,7 @@
* _also_ be part of libutils/Unicode.cpp if its usefullness needs to
* propagate globally.
*/
-WEAK ssize_t utf8_character_length(const char *src, size_t len)
+LIBLOG_WEAK ssize_t utf8_character_length(const char *src, size_t len)
{
const char *cur = src;
const char first_char = *cur++;
@@ -956,7 +964,7 @@
return p - begin;
}
-char *readSeconds(char *e, struct timespec *t)
+static char *readSeconds(char *e, struct timespec *t)
{
unsigned long multiplier;
char *p;
@@ -1243,12 +1251,12 @@
* Returns NULL on malloc error
*/
-char *android_log_formatLogLine (
- AndroidLogFormat *p_format,
- char *defaultBuffer,
- size_t defaultBufferSize,
- const AndroidLogEntry *entry,
- size_t *p_outLength)
+LIBLOG_ABI_PUBLIC char *android_log_formatLogLine (
+ AndroidLogFormat *p_format,
+ char *defaultBuffer,
+ size_t defaultBufferSize,
+ const AndroidLogEntry *entry,
+ size_t *p_outLength)
{
#if !defined(_WIN32)
struct tm tmBuf;
@@ -1526,10 +1534,10 @@
* Returns count bytes written
*/
-int android_log_printLogLine(
- AndroidLogFormat *p_format,
- int fd,
- const AndroidLogEntry *entry)
+LIBLOG_ABI_PUBLIC int android_log_printLogLine(
+ AndroidLogFormat *p_format,
+ int fd,
+ const AndroidLogEntry *entry)
{
int ret;
char defaultBuffer[512];
diff --git a/liblog/uio.c b/liblog/uio.c
index f77cc49..d0184dc 100644
--- a/liblog/uio.c
+++ b/liblog/uio.c
@@ -16,17 +16,20 @@
#if defined(_WIN32)
-#include <log/uio.h>
#include <unistd.h>
-int readv( int fd, struct iovec* vecs, int count )
+#include <log/uio.h>
+
+#include "log_cdefs.h"
+
+LIBLOG_ABI_PUBLIC int readv(int fd, struct iovec *vecs, int count)
{
int total = 0;
for ( ; count > 0; count--, vecs++ ) {
char* buf = vecs->iov_base;
int len = vecs->iov_len;
-
+
while (len > 0) {
int ret = read( fd, buf, len );
if (ret < 0) {
@@ -46,14 +49,14 @@
return total;
}
-int writev( int fd, const struct iovec* vecs, int count )
+LIBLOG_ABI_PUBLIC int writev(int fd, const struct iovec *vecs, int count)
{
int total = 0;
for ( ; count > 0; count--, vecs++ ) {
const char* buf = vecs->iov_base;
int len = vecs->iov_len;
-
+
while (len > 0) {
int ret = write( fd, buf, len );
if (ret < 0) {
@@ -69,7 +72,7 @@
len -= ret;
}
}
-Exit:
+Exit:
return total;
}
diff --git a/libutils/Threads.cpp b/libutils/Threads.cpp
index 6dda6b5..def739f 100644
--- a/libutils/Threads.cpp
+++ b/libutils/Threads.cpp
@@ -668,6 +668,8 @@
status_t Thread::run(const char* name, int32_t priority, size_t stack)
{
+ LOG_ALWAYS_FATAL_IF(name == nullptr, "thread name not provided to Thread::run");
+
Mutex::Autolock _l(mLock);
if (mRunning) {
diff --git a/libutils/tests/Looper_test.cpp b/libutils/tests/Looper_test.cpp
index 00077e6..17319e0 100644
--- a/libutils/tests/Looper_test.cpp
+++ b/libutils/tests/Looper_test.cpp
@@ -138,7 +138,7 @@
TEST_F(LooperTest, PollOnce_WhenNonZeroTimeoutAndAwokenWhileWaiting_PromptlyReturns) {
sp<DelayedWake> delayedWake = new DelayedWake(100, mLooper);
- delayedWake->run();
+ delayedWake->run("LooperTest");
StopWatch stopWatch("pollOnce");
int result = mLooper->pollOnce(1000);
@@ -251,7 +251,7 @@
sp<DelayedWriteSignal> delayedWriteSignal = new DelayedWriteSignal(100, & pipe);
handler.setCallback(mLooper, pipe.receiveFd, Looper::EVENT_INPUT);
- delayedWriteSignal->run();
+ delayedWriteSignal->run("LooperTest");
StopWatch stopWatch("pollOnce");
int result = mLooper->pollOnce(1000);
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index a2d6fcc..1f27500 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -495,14 +495,20 @@
}
// Attempts to read |len| bytes into |buf| at offset |off|.
-// Callers should not rely on the |fd| offset being incremented
-// as a side effect of this call.
+// On non-Windows platforms, callers are guaranteed that the |fd|
+// offset is unchanged and there is no side effect to this call.
+//
+// On Windows platforms this is not thread-safe.
static inline bool ReadAtOffset(int fd, uint8_t* buf, size_t len, off64_t off) {
+#if !defined(_WIN32)
+ return TEMP_FAILURE_RETRY(pread64(fd, buf, len, off));
+#else
if (lseek64(fd, off, SEEK_SET) != off) {
ALOGW("Zip: failed seek to offset %" PRId64, off);
return false;
}
return android::base::ReadFully(fd, buf, len);
+#endif
}
static int32_t FindEntry(const ZipArchive* archive, const int ent,