Index: src/client/linux/minidump_writer/linux_dumper_unittest.cc |
=================================================================== |
--- src/client/linux/minidump_writer/linux_dumper_unittest.cc (revision 400) |
+++ src/client/linux/minidump_writer/linux_dumper_unittest.cc (working copy) |
@@ -28,9 +28,12 @@ |
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
#include <unistd.h> |
+#include <signal.h> |
+#include <sys/types.h> |
+#include "breakpad_googletest_includes.h" |
+#include "common/linux/memory.h" |
#include "client/linux/minidump_writer/linux_dumper.h" |
-#include "breakpad_googletest_includes.h" |
using namespace google_breakpad; |
@@ -55,7 +58,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()) { |
@@ -65,6 +68,53 @@ |
} |
} |
+TEST(LinuxDumperTest, VerifyStackReadWithMultipleThreads) { |
+ static const int kNumberOfThreadsInHelperProgram = 5; |
+ char kNumberOfThreadsArgument[2]; |
+ sprintf(kNumberOfThreadsArgument, "%d", kNumberOfThreadsInHelperProgram); |
awong
2010/02/08 20:52:55
Can you use StrintPrintf instead (if you have it)?
|
+ pid_t child_pid = fork(); |
+ if (child_pid == 0) { |
+ // Set the number of threads |
+ execl("./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); |
+ } |
+ // 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.ebp - 8); |
Ted Mielczarek
2010/02/05 17:04:07
This should be one_thread.regs.rbp. Also, this tes
|
+#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); |
@@ -94,25 +144,26 @@ |
#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 |