Chromium Code Reviews| 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 |