ARM support, with some build system changes to support x86-64, arm, and i386 in an autoconf style build in Linux.  The O2 build for the unit tests is still broken but I'm checking this in to unblock people

A=nealsid
R=ajwong, hannahtang, ted.mielczarek



git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@541 4c0a9323-5329-0410-9bdc-e9ce6186880e
diff --git a/src/client/linux/minidump_writer/linux_dumper_unittest.cc b/src/client/linux/minidump_writer/linux_dumper_unittest.cc
index e060e53..6f1043c 100644
--- a/src/client/linux/minidump_writer/linux_dumper_unittest.cc
+++ b/src/client/linux/minidump_writer/linux_dumper_unittest.cc
@@ -29,10 +29,13 @@
 
 #include <limits.h>
 #include <unistd.h>
+#include <signal.h>
+#include <sys/types.h>
 
+#include "breakpad_googletest_includes.h"
 #include "client/linux/minidump_writer/linux_dumper.h"
 #include "common/linux/file_id.h"
-#include "breakpad_googletest_includes.h"
+#include "common/linux/memory.h"
 
 using namespace google_breakpad;
 
@@ -67,7 +70,7 @@
   LinuxDumper dumper(getpid());
   ASSERT_TRUE(dumper.Init());
 
-  ASSERT_GE(dumper.threads().size(), 1);
+  ASSERT_GE(dumper.threads().size(), (size_t)1);
   bool found = false;
   for (size_t i = 0; i < dumper.threads().size(); ++i) {
     if (dumper.threads()[i] == getpid()) {
@@ -77,6 +80,55 @@
   }
 }
 
+TEST(LinuxDumperTest, VerifyStackReadWithMultipleThreads) {
+  static const int kNumberOfThreadsInHelperProgram = 5;
+  char kNumberOfThreadsArgument[2];
+  sprintf(kNumberOfThreadsArgument, "%d", kNumberOfThreadsInHelperProgram);
+
+  pid_t child_pid = fork();
+  if (child_pid == 0) {
+    // Set the number of threads
+    execl("src/client/linux/linux_dumper_unittest_helper",
+          "linux_dumper_unittest_helper",
+          kNumberOfThreadsArgument,
+          NULL);
+    // Kill if we get here.
+    printf("Errno from exec: %d", errno);
+    FAIL() << "Exec 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());
+  EXPECT_EQ((size_t)kNumberOfThreadsInHelperProgram, dumper.threads().size());
+  EXPECT_TRUE(dumper.ThreadsSuspend());
+
+  ThreadInfo one_thread;
+  for(size_t i = 0; i < dumper.threads().size(); ++i) {
+    EXPECT_TRUE(dumper.ThreadInfoGet(dumper.threads()[i], &one_thread));
+    // We know the threads are in a function which has allocated exactly
+    // one word off the stack to store its thread id.
+#if defined(__ARM_EABI__)
+    void* process_tid_location = (void *)(one_thread.regs.uregs[11] - 8);
+#elif defined(__i386)
+    void* process_tid_location = (void *)(one_thread.regs.ebp - 4);
+#elif defined(__x86_64)
+    void* process_tid_location = (void *)(one_thread.regs.rbp - 4);
+#else
+#error Platform not supported!
+#endif
+    pid_t one_thread_id;
+    dumper.CopyFromProcess(&one_thread_id,
+                           dumper.threads()[i],
+                           process_tid_location,
+                           4);
+    EXPECT_EQ(dumper.threads()[i], one_thread_id);
+  }
+  kill(child_pid, SIGKILL);
+}
+
 TEST(LinuxDumperTest, BuildProcPath) {
   const pid_t pid = getpid();
   LinuxDumper dumper(pid);
@@ -106,28 +158,29 @@
 #endif
 }
 
+#if !defined(__ARM_EABI__)
 TEST(LinuxDumperTest, MappingsIncludeLinuxGate) {
   LinuxDumper dumper(getpid());
   ASSERT_TRUE(dumper.Init());
 
   void* linux_gate_loc = dumper.FindBeginningOfLinuxGateSharedLibrary(getpid());
-  if (linux_gate_loc) {
-    bool found_linux_gate = false;
+  ASSERT_TRUE(linux_gate_loc);
+  bool found_linux_gate = false;
 
-    const wasteful_vector<MappingInfo*> mappings = dumper.mappings();
-    const MappingInfo* mapping;
-    for (unsigned i = 0; i < mappings.size(); ++i) {
-      mapping = mappings[i];
-      if (!strcmp(mapping->name, kLinuxGateLibraryName)) {
-        found_linux_gate = true;
-        break;
-      }
+  const wasteful_vector<MappingInfo*> mappings = dumper.mappings();
+  const MappingInfo* mapping;
+  for (unsigned i = 0; i < mappings.size(); ++i) {
+    mapping = mappings[i];
+    if (!strcmp(mapping->name, kLinuxGateLibraryName)) {
+      found_linux_gate = true;
+      break;
     }
-    EXPECT_TRUE(found_linux_gate);
-    EXPECT_EQ(linux_gate_loc, reinterpret_cast<void*>(mapping->start_addr));
-    EXPECT_EQ(0, memcmp(linux_gate_loc, ELFMAG, SELFMAG));
   }
+  EXPECT_TRUE(found_linux_gate);
+  EXPECT_EQ(linux_gate_loc, reinterpret_cast<void*>(mapping->start_addr));
+  EXPECT_EQ(0, memcmp(linux_gate_loc, ELFMAG, SELFMAG));
 }
+#endif
 
 TEST(LinuxDumperTest, FileIDsMatch) {
   // Calculate the File ID of our binary using both