OLD | NEW |
1 // Copyright (c) 2009, Google Inc. | 1 // Copyright (c) 2009, Google Inc. |
2 // All rights reserved. | 2 // All rights reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 #include "common/using_std_string.h" | 59 #include "common/using_std_string.h" |
60 | 60 |
61 #ifndef PR_SET_PTRACER | 61 #ifndef PR_SET_PTRACER |
62 #define PR_SET_PTRACER 0x59616d61 | 62 #define PR_SET_PTRACER 0x59616d61 |
63 #endif | 63 #endif |
64 | 64 |
65 using namespace google_breakpad; | 65 using namespace google_breakpad; |
66 | 66 |
67 namespace { | 67 namespace { |
68 | 68 |
| 69 typedef wasteful_vector<uint8_t> id_vector; |
69 typedef testing::Test LinuxPtraceDumperTest; | 70 typedef testing::Test LinuxPtraceDumperTest; |
70 | 71 |
71 /* Fixture for running tests in a child process. */ | 72 /* Fixture for running tests in a child process. */ |
72 class LinuxPtraceDumperChildTest : public testing::Test { | 73 class LinuxPtraceDumperChildTest : public testing::Test { |
73 protected: | 74 protected: |
74 virtual void SetUp() { | 75 virtual void SetUp() { |
75 child_pid_ = fork(); | 76 child_pid_ = fork(); |
76 #ifndef __ANDROID__ | 77 #ifndef __ANDROID__ |
77 prctl(PR_SET_PTRACER, child_pid_); | 78 prctl(PR_SET_PTRACER, child_pid_); |
78 #endif | 79 #endif |
(...skipping 19 matching lines...) Expand all Loading... |
98 } else if (WEXITSTATUS(status) == kNonFatalFailure) { | 99 } else if (WEXITSTATUS(status) == kNonFatalFailure) { |
99 GTEST_NONFATAL_FAILURE_("Test failed in child process"); | 100 GTEST_NONFATAL_FAILURE_("Test failed in child process"); |
100 } | 101 } |
101 } | 102 } |
102 | 103 |
103 /* Gtest defines TestBody functions through its macros, but classes | 104 /* Gtest defines TestBody functions through its macros, but classes |
104 * derived from this one need to define RealTestBody instead. | 105 * derived from this one need to define RealTestBody instead. |
105 * This is achieved by defining a TestBody macro further below. | 106 * This is achieved by defining a TestBody macro further below. |
106 */ | 107 */ |
107 virtual void RealTestBody() = 0; | 108 virtual void RealTestBody() = 0; |
| 109 |
| 110 id_vector make_vector() { |
| 111 return id_vector(&allocator, kDefaultBuildIdSize); |
| 112 } |
| 113 |
108 private: | 114 private: |
109 static const int kFatalFailure = 1; | 115 static const int kFatalFailure = 1; |
110 static const int kNonFatalFailure = 2; | 116 static const int kNonFatalFailure = 2; |
111 | 117 |
112 pid_t child_pid_; | 118 pid_t child_pid_; |
| 119 PageAllocator allocator; |
113 }; | 120 }; |
114 | 121 |
115 } // namespace | 122 } // namespace |
116 | 123 |
117 /* Replace TestBody declarations within TEST*() with RealTestBody | 124 /* Replace TestBody declarations within TEST*() with RealTestBody |
118 * declarations */ | 125 * declarations */ |
119 #define TestBody RealTestBody | 126 #define TestBody RealTestBody |
120 | 127 |
121 TEST_F(LinuxPtraceDumperChildTest, Setup) { | 128 TEST_F(LinuxPtraceDumperChildTest, Setup) { |
122 LinuxPtraceDumper dumper(getppid()); | 129 LinuxPtraceDumper dumper(getppid()); |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 if (!strcmp(mappings[i]->name, kLinuxGateLibraryName)) { | 310 if (!strcmp(mappings[i]->name, kLinuxGateLibraryName)) { |
304 found_linux_gate = true; | 311 found_linux_gate = true; |
305 index = i; | 312 index = i; |
306 break; | 313 break; |
307 } | 314 } |
308 } | 315 } |
309 ASSERT_TRUE(found_linux_gate); | 316 ASSERT_TRUE(found_linux_gate); |
310 | 317 |
311 // Need to suspend the child so ptrace actually works. | 318 // Need to suspend the child so ptrace actually works. |
312 ASSERT_TRUE(dumper.ThreadsSuspend()); | 319 ASSERT_TRUE(dumper.ThreadsSuspend()); |
313 uint8_t identifier[sizeof(MDGUID)]; | 320 id_vector identifier(make_vector()); |
314 ASSERT_TRUE(dumper.ElfFileIdentifierForMapping(*mappings[index], | 321 ASSERT_TRUE(dumper.ElfFileIdentifierForMapping(*mappings[index], |
315 true, | 322 true, |
316 index, | 323 index, |
317 identifier)); | 324 identifier)); |
318 uint8_t empty_identifier[sizeof(MDGUID)]; | 325 |
319 memset(empty_identifier, 0, sizeof(empty_identifier)); | 326 id_vector empty_identifier(make_vector()); |
320 EXPECT_NE(0, memcmp(empty_identifier, identifier, sizeof(identifier))); | 327 empty_identifier.resize(kDefaultBuildIdSize, 0); |
| 328 EXPECT_NE(empty_identifier, identifier); |
321 EXPECT_TRUE(dumper.ThreadsResume()); | 329 EXPECT_TRUE(dumper.ThreadsResume()); |
322 } | 330 } |
323 #endif | 331 #endif |
324 | 332 |
325 TEST_F(LinuxPtraceDumperChildTest, FileIDsMatch) { | 333 TEST_F(LinuxPtraceDumperChildTest, FileIDsMatch) { |
326 // Calculate the File ID of our binary using both | 334 // Calculate the File ID of our binary using both |
327 // FileID::ElfFileIdentifier and LinuxDumper::ElfFileIdentifierForMapping | 335 // FileID::ElfFileIdentifier and LinuxDumper::ElfFileIdentifierForMapping |
328 // and ensure that we get the same result from both. | 336 // and ensure that we get the same result from both. |
329 char exe_name[PATH_MAX]; | 337 char exe_name[PATH_MAX]; |
330 ASSERT_TRUE(SafeReadLink("/proc/self/exe", exe_name)); | 338 ASSERT_TRUE(SafeReadLink("/proc/self/exe", exe_name)); |
331 | 339 |
332 LinuxPtraceDumper dumper(getppid()); | 340 LinuxPtraceDumper dumper(getppid()); |
333 ASSERT_TRUE(dumper.Init()); | 341 ASSERT_TRUE(dumper.Init()); |
334 const wasteful_vector<MappingInfo*> mappings = dumper.mappings(); | 342 const wasteful_vector<MappingInfo*> mappings = dumper.mappings(); |
335 bool found_exe = false; | 343 bool found_exe = false; |
336 unsigned i; | 344 unsigned i; |
337 for (i = 0; i < mappings.size(); ++i) { | 345 for (i = 0; i < mappings.size(); ++i) { |
338 const MappingInfo* mapping = mappings[i]; | 346 const MappingInfo* mapping = mappings[i]; |
339 if (!strcmp(mapping->name, exe_name)) { | 347 if (!strcmp(mapping->name, exe_name)) { |
340 found_exe = true; | 348 found_exe = true; |
341 break; | 349 break; |
342 } | 350 } |
343 } | 351 } |
344 ASSERT_TRUE(found_exe); | 352 ASSERT_TRUE(found_exe); |
345 | 353 |
346 uint8_t identifier1[sizeof(MDGUID)]; | 354 id_vector identifier1(make_vector()); |
347 uint8_t identifier2[sizeof(MDGUID)]; | 355 id_vector identifier2(make_vector()); |
348 EXPECT_TRUE(dumper.ElfFileIdentifierForMapping(*mappings[i], true, i, | 356 EXPECT_TRUE(dumper.ElfFileIdentifierForMapping(*mappings[i], true, i, |
349 identifier1)); | 357 identifier1)); |
350 FileID fileid(exe_name); | 358 FileID fileid(exe_name); |
351 EXPECT_TRUE(fileid.ElfFileIdentifier(identifier2)); | 359 EXPECT_TRUE(fileid.ElfFileIdentifier(identifier2)); |
352 char identifier_string1[37]; | 360 |
353 char identifier_string2[37]; | 361 string identifier_string1 = |
354 FileID::ConvertIdentifierToString(identifier1, identifier_string1, | 362 FileID::ConvertIdentifierToUUIDString(identifier1); |
355 37); | 363 string identifier_string2 = |
356 FileID::ConvertIdentifierToString(identifier2, identifier_string2, | 364 FileID::ConvertIdentifierToUUIDString(identifier2); |
357 37); | 365 EXPECT_EQ(identifier_string1, identifier_string2); |
358 EXPECT_STREQ(identifier_string1, identifier_string2); | |
359 } | 366 } |
360 | 367 |
361 /* Get back to normal behavior of TEST*() macros wrt TestBody. */ | 368 /* Get back to normal behavior of TEST*() macros wrt TestBody. */ |
362 #undef TestBody | 369 #undef TestBody |
363 | 370 |
364 TEST(LinuxPtraceDumperTest, VerifyStackReadWithMultipleThreads) { | 371 TEST(LinuxPtraceDumperTest, VerifyStackReadWithMultipleThreads) { |
365 static const int kNumberOfThreadsInHelperProgram = 5; | 372 static const int kNumberOfThreadsInHelperProgram = 5; |
366 char kNumberOfThreadsArgument[2]; | 373 char kNumberOfThreadsArgument[2]; |
367 sprintf(kNumberOfThreadsArgument, "%d", kNumberOfThreadsInHelperProgram); | 374 sprintf(kNumberOfThreadsArgument, "%d", kNumberOfThreadsInHelperProgram); |
368 | 375 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 } | 461 } |
455 EXPECT_TRUE(dumper.ThreadsResume()); | 462 EXPECT_TRUE(dumper.ThreadsResume()); |
456 kill(child_pid, SIGKILL); | 463 kill(child_pid, SIGKILL); |
457 | 464 |
458 // Reap child | 465 // Reap child |
459 int status; | 466 int status; |
460 ASSERT_NE(-1, HANDLE_EINTR(waitpid(child_pid, &status, 0))); | 467 ASSERT_NE(-1, HANDLE_EINTR(waitpid(child_pid, &status, 0))); |
461 ASSERT_TRUE(WIFSIGNALED(status)); | 468 ASSERT_TRUE(WIFSIGNALED(status)); |
462 ASSERT_EQ(SIGKILL, WTERMSIG(status)); | 469 ASSERT_EQ(SIGKILL, WTERMSIG(status)); |
463 } | 470 } |
OLD | NEW |