aboutsummaryrefslogtreecommitdiff
path: root/src/client/linux/minidump_writer
diff options
context:
space:
mode:
authorted.mielczarek <ted.mielczarek@4c0a9323-5329-0410-9bdc-e9ce6186880e>2010-10-20 15:51:38 +0000
committerted.mielczarek <ted.mielczarek@4c0a9323-5329-0410-9bdc-e9ce6186880e>2010-10-20 15:51:38 +0000
commitcfc8628092e17069d8d6c7068d4f21d9baabe077 (patch)
tree43e9d016602ec4944511a3f02981a004a6225ef5 /src/client/linux/minidump_writer
parentDouble stack scanning length in stackwalker (diff)
downloadbreakpad-cfc8628092e17069d8d6c7068d4f21d9baabe077.tar.xz
Add support for building the Linux client code using the Android NDK
r=mwu at http://breakpad.appspot.com/212001/show git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@716 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/client/linux/minidump_writer')
-rw-r--r--src/client/linux/minidump_writer/line_reader_unittest.cc8
-rw-r--r--src/client/linux/minidump_writer/linux_dumper.cc13
-rw-r--r--src/client/linux/minidump_writer/linux_dumper.h24
-rw-r--r--src/client/linux/minidump_writer/linux_dumper_unittest.cc24
-rw-r--r--src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc4
-rw-r--r--src/client/linux/minidump_writer/minidump_writer.cc19
-rw-r--r--src/client/linux/minidump_writer/minidump_writer_unittest.cc8
7 files changed, 90 insertions, 10 deletions
diff --git a/src/client/linux/minidump_writer/line_reader_unittest.cc b/src/client/linux/minidump_writer/line_reader_unittest.cc
index 7c4c3ced..a2ea17f7 100644
--- a/src/client/linux/minidump_writer/line_reader_unittest.cc
+++ b/src/client/linux/minidump_writer/line_reader_unittest.cc
@@ -36,8 +36,14 @@
using namespace google_breakpad;
+#if !defined(__ANDROID__)
+#define TEMPDIR "/tmp"
+#else
+#define TEMPDIR "/data/local/tmp"
+#endif
+
static int TemporaryFile() {
- static const char templ[] = "/tmp/line-reader-unittest-XXXXXX";
+ static const char templ[] = TEMPDIR "/line-reader-unittest-XXXXXX";
char templ_copy[sizeof(templ)];
memcpy(templ_copy, templ, sizeof(templ));
const int fd = mkstemp(templ_copy);
diff --git a/src/client/linux/minidump_writer/linux_dumper.cc b/src/client/linux/minidump_writer/linux_dumper.cc
index b7ee1c4d..11b6a18b 100644
--- a/src/client/linux/minidump_writer/linux_dumper.cc
+++ b/src/client/linux/minidump_writer/linux_dumper.cc
@@ -45,7 +45,9 @@
#include <elf.h>
#include <errno.h>
#include <fcntl.h>
+#if !defined(__ANDROID__)
#include <link.h>
+#endif
#include <sys/types.h>
#include <sys/ptrace.h>
@@ -388,11 +390,16 @@ bool LinuxDumper::ThreadInfoGet(pid_t tid, ThreadInfo* info) {
if (info->ppid == -1 || info->tgid == -1)
return false;
- if (sys_ptrace(PTRACE_GETREGS, tid, NULL, &info->regs) == -1 ||
- sys_ptrace(PTRACE_GETFPREGS, tid, NULL, &info->fpregs) == -1) {
+ if (sys_ptrace(PTRACE_GETREGS, tid, NULL, &info->regs) == -1) {
return false;
}
+#if !defined(__ANDROID__)
+ if (sys_ptrace(PTRACE_GETFPREGS, tid, NULL, &info->fpregs) == -1) {
+ return false;
+ }
+#endif
+
#if defined(__i386)
if (sys_ptrace(PTRACE_GETFPXREGS, tid, NULL, &info->fpxregs) == -1)
return false;
@@ -417,7 +424,7 @@ bool LinuxDumper::ThreadInfoGet(pid_t tid, ThreadInfo* info) {
#elif defined(__x86_64)
memcpy(&stack_pointer, &info->regs.rsp, sizeof(info->regs.rsp));
#elif defined(__ARM_EABI__)
- memcpy(&stack_pointer, &info->regs.uregs[R13], sizeof(info->regs.uregs[R13]));
+ memcpy(&stack_pointer, &info->regs.ARM_sp, sizeof(info->regs.ARM_sp));
#else
#error "This code hasn't been ported to your platform yet."
#endif
diff --git a/src/client/linux/minidump_writer/linux_dumper.h b/src/client/linux/minidump_writer/linux_dumper.h
index b0c479a9..71d1188f 100644
--- a/src/client/linux/minidump_writer/linux_dumper.h
+++ b/src/client/linux/minidump_writer/linux_dumper.h
@@ -34,18 +34,38 @@
#include <linux/limits.h>
#include <stdint.h>
#include <sys/types.h>
+#if !defined(__ANDROID__)
#include <sys/user.h>
+#endif
#include "common/memory.h"
#include "google_breakpad/common/minidump_format.h"
namespace google_breakpad {
+#if defined(__i386) || defined(__x86_64)
typedef typeof(((struct user*) 0)->u_debugreg[0]) debugreg_t;
+#endif
// Typedef for our parsing of the auxv variables in /proc/pid/auxv.
#if defined(__i386) || defined(__ARM_EABI__)
+#if !defined(__ANDROID__)
typedef Elf32_auxv_t elf_aux_entry;
+#else
+// Android is missing this structure definition
+typedef struct
+{
+ uint32_t a_type; /* Entry type */
+ union
+ {
+ uint32_t a_val; /* Integer value */
+ } a_un;
+} elf_aux_entry;
+
+#if !defined(AT_SYSINFO_EHDR)
+#define AT_SYSINFO_EHDR 33
+#endif
+#endif // __ANDROID__
#elif defined(__x86_64__)
typedef Elf64_auxv_t elf_aux_entry;
#endif
@@ -76,8 +96,12 @@ struct ThreadInfo {
#elif defined(__ARM_EABI__)
// Mimicking how strace does this(see syscall.c, search for GETREGS)
+#if defined(__ANDROID__)
+ struct pt_regs regs;
+#else
struct user_regs regs;
struct user_fpregs fpregs;
+#endif // __ANDROID__
#endif
};
diff --git a/src/client/linux/minidump_writer/linux_dumper_unittest.cc b/src/client/linux/minidump_writer/linux_dumper_unittest.cc
index 8cfb6004..b81291b6 100644
--- a/src/client/linux/minidump_writer/linux_dumper_unittest.cc
+++ b/src/client/linux/minidump_writer/linux_dumper_unittest.cc
@@ -27,6 +27,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#include <string>
+
#include <limits.h>
#include <unistd.h>
#include <signal.h>
@@ -37,6 +39,7 @@
#include "common/linux/file_id.h"
#include "common/memory.h"
+using std::string;
using namespace google_breakpad;
// This provides a wrapper around system calls which may be
@@ -87,21 +90,36 @@ TEST(LinuxDumperTest, VerifyStackReadWithMultipleThreads) {
pid_t child_pid = fork();
if (child_pid == 0) {
+ // Locate helper binary next to the current binary.
+ char self_path[PATH_MAX];
+ if (readlink("/proc/self/exe", self_path, sizeof(self_path) - 1) == -1) {
+ FAIL() << "readlink failed: " << strerror(errno);
+ exit(1);
+ }
+ string helper_path(self_path);
+ size_t pos = helper_path.rfind('/');
+ if (pos == string::npos) {
+ FAIL() << "no trailing slash in path: " << helper_path;
+ exit(1);
+ }
+ helper_path.erase(pos + 1);
+ helper_path += "linux_dumper_unittest_helper";
+
// Set the number of threads
- execl("src/client/linux/linux_dumper_unittest_helper",
+ execl(helper_path.c_str(),
"linux_dumper_unittest_helper",
kNumberOfThreadsArgument,
NULL);
// Kill if we get here.
printf("Errno from exec: %d", errno);
- FAIL() << "Exec failed: " << strerror(errno);
+ FAIL() << "Exec of " << helper_path << " failed: " << strerror(errno);
exit(0);
}
// The sleep is flaky, but prevents us from reading
// the child process before all threads have been created.
sleep(1);
LinuxDumper dumper(child_pid);
- EXPECT_TRUE(dumper.Init());
+ ASSERT_TRUE(dumper.Init());
EXPECT_EQ((size_t)kNumberOfThreadsInHelperProgram, dumper.threads().size());
EXPECT_TRUE(dumper.ThreadsSuspend());
diff --git a/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc b/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
index e91e9767..6b7ad5a2 100644
--- a/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
+++ b/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc
@@ -37,6 +37,8 @@
#include <sys/syscall.h>
#include <unistd.h>
+#include "third_party/lss/linux_syscall_support.h"
+
#if defined(__ARM_EABI__)
#define TID_PTR_REGISTER "r3"
#elif defined(__i386)
@@ -48,7 +50,7 @@
#endif
void *thread_function(void *data) {
- volatile pid_t thread_id = syscall(SYS_gettid);
+ volatile pid_t thread_id = syscall(__NR_gettid);
register volatile pid_t *thread_id_ptr asm(TID_PTR_REGISTER) = &thread_id;
while (true)
asm volatile ("" : : "r" (thread_id_ptr));
diff --git a/src/client/linux/minidump_writer/minidump_writer.cc b/src/client/linux/minidump_writer/minidump_writer.cc
index d629ee81..9deed20b 100644
--- a/src/client/linux/minidump_writer/minidump_writer.cc
+++ b/src/client/linux/minidump_writer/minidump_writer.cc
@@ -50,11 +50,15 @@
#include <errno.h>
#include <fcntl.h>
+#if !defined(__ANDROID__)
#include <link.h>
+#endif
#include <stdio.h>
#include <unistd.h>
+#if !defined(__ANDROID__)
#include <sys/ucontext.h>
#include <sys/user.h>
+#endif
#include <sys/utsname.h>
#include "client/minidump_file_writer.h"
@@ -62,6 +66,10 @@
#include "google_breakpad/common/minidump_cpu_amd64.h"
#include "google_breakpad/common/minidump_cpu_x86.h"
+#if defined(__ANDROID__)
+#include "client/linux/android_link.h"
+#include "client/linux/android_ucontext.h"
+#endif
#include "client/linux/handler/exception_handler.h"
#include "client/linux/minidump_writer/line_reader.h"
#include "client/linux/minidump_writer/linux_dumper.h"
@@ -311,11 +319,13 @@ static void CPUFillFromThreadInfo(MDRawContextARM *out,
out->iregs[i] = info.regs.uregs[i];
// No CPSR register in ThreadInfo(it's not accessible via ptrace)
out->cpsr = 0;
+#if !defined(__ANDROID__)
out->float_save.fpscr = info.fpregs.fpsr |
(static_cast<u_int64_t>(info.fpregs.fpcr) << 32);
//TODO: sort this out, actually collect floating point registers
memset(&out->float_save.regs, 0, sizeof(out->float_save.regs));
memset(&out->float_save.extra, 0, sizeof(out->float_save.extra));
+#endif
}
static void CPUFillFromUContext(MDRawContextARM *out, const ucontext *uc,
@@ -389,7 +399,9 @@ class MinidumpWriter {
// it to a MD_LINUX_DSO_DEBUG stream.
struct r_debug* r_debug = NULL;
uint32_t dynamic_length = 0;
-
+#if !defined(__ANDROID__)
+ // The Android NDK is missing structure definitions for most of this.
+ // For now, it's simpler just to skip it.
for (int i = 0;;) {
ElfW(Dyn) dyn;
dynamic_length += sizeof(dyn);
@@ -400,6 +412,7 @@ class MinidumpWriter {
} else if (dyn.d_tag == DT_NULL)
break;
}
+#endif
// A minidump file contains a number of tagged streams. This is the number
// of stream which we write.
@@ -866,6 +879,9 @@ class MinidumpWriter {
bool WriteDSODebugStream(MDRawDirectory* dirent, struct r_debug* r_debug,
uint32_t dynamic_length) {
+#if defined(__ANDROID__)
+ return false;
+#else
// The caller provided us with a pointer to "struct r_debug". We can
// look up the "r_map" field to get a linked list of all loaded DSOs.
// Our list of DSOs potentially is different from the ones in the crashing
@@ -939,6 +955,7 @@ class MinidumpWriter {
delete[] dso_debug_data;
return true;
+#endif
}
private:
diff --git a/src/client/linux/minidump_writer/minidump_writer_unittest.cc b/src/client/linux/minidump_writer/minidump_writer_unittest.cc
index 0c02f587..e7a62145 100644
--- a/src/client/linux/minidump_writer/minidump_writer_unittest.cc
+++ b/src/client/linux/minidump_writer/minidump_writer_unittest.cc
@@ -37,6 +37,12 @@
using namespace google_breakpad;
+#if !defined(__ANDROID__)
+#define TEMPDIR "/tmp"
+#else
+#define TEMPDIR "/data/local/tmp"
+#endif
+
namespace {
typedef testing::Test MinidumpWriterTest;
}
@@ -58,7 +64,7 @@ TEST(MinidumpWriterTest, Setup) {
ExceptionHandler::CrashContext context;
memset(&context, 0, sizeof(context));
- char templ[] = "/tmp/minidump-writer-unittest-XXXXXX";
+ char templ[] = TEMPDIR "/minidump-writer-unittest-XXXXXX";
mktemp(templ);
ASSERT_TRUE(WriteMinidump(templ, child, &context, sizeof(context)));
struct stat st;