| OLD | NEW |
| 1 // Copyright (c) 2011 Google Inc. | 1 // Copyright (c) 2011 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 #include "common/linux/ignore_ret.h" | 47 #include "common/linux/ignore_ret.h" |
| 48 #include "common/linux/safe_readlink.h" | 48 #include "common/linux/safe_readlink.h" |
| 49 #include "common/scoped_ptr.h" | 49 #include "common/scoped_ptr.h" |
| 50 #include "common/tests/auto_tempdir.h" | 50 #include "common/tests/auto_tempdir.h" |
| 51 #include "common/tests/file_utils.h" | 51 #include "common/tests/file_utils.h" |
| 52 #include "common/using_std_string.h" | 52 #include "common/using_std_string.h" |
| 53 #include "google_breakpad/processor/minidump.h" | 53 #include "google_breakpad/processor/minidump.h" |
| 54 | 54 |
| 55 using namespace google_breakpad; | 55 using namespace google_breakpad; |
| 56 | 56 |
| 57 // Length of a formatted GUID string = | |
| 58 // sizeof(MDGUID) * 2 + 4 (for dashes) + 1 (null terminator) | |
| 59 const int kGUIDStringSize = 37; | |
| 60 | |
| 61 namespace { | 57 namespace { |
| 62 | 58 |
| 63 typedef testing::Test MinidumpWriterTest; | 59 typedef testing::Test MinidumpWriterTest; |
| 64 | 60 |
| 65 const char kMDWriterUnitTestFileName[] = "/minidump-writer-unittest"; | 61 const char kMDWriterUnitTestFileName[] = "/minidump-writer-unittest"; |
| 66 | 62 |
| 67 TEST(MinidumpWriterTest, SetupWithPath) { | 63 TEST(MinidumpWriterTest, SetupWithPath) { |
| 68 int fds[2]; | 64 int fds[2]; |
| 69 ASSERT_NE(-1, pipe(fds)); | 65 ASSERT_NE(-1, pipe(fds)); |
| 70 | 66 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 130 ASSERT_NE(-1, pipe(fds)); | 126 ASSERT_NE(-1, pipe(fds)); |
| 131 | 127 |
| 132 // These are defined here so the parent can use them to check the | 128 // These are defined here so the parent can use them to check the |
| 133 // data from the minidump afterwards. | 129 // data from the minidump afterwards. |
| 134 const uint32_t memory_size = sysconf(_SC_PAGESIZE); | 130 const uint32_t memory_size = sysconf(_SC_PAGESIZE); |
| 135 const char* kMemoryName = "a fake module"; | 131 const char* kMemoryName = "a fake module"; |
| 136 const uint8_t kModuleGUID[sizeof(MDGUID)] = { | 132 const uint8_t kModuleGUID[sizeof(MDGUID)] = { |
| 137 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, | 133 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, |
| 138 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF | 134 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF |
| 139 }; | 135 }; |
| 140 char module_identifier_buffer[kGUIDStringSize]; | 136 const string module_identifier = "33221100554477668899AABBCCDDEEFF0"; |
| 141 FileID::ConvertIdentifierToString(kModuleGUID, | |
| 142 module_identifier_buffer, | |
| 143 sizeof(module_identifier_buffer)); | |
| 144 string module_identifier(module_identifier_buffer); | |
| 145 // Strip out dashes | |
| 146 size_t pos; | |
| 147 while ((pos = module_identifier.find('-')) != string::npos) { | |
| 148 module_identifier.erase(pos, 1); | |
| 149 } | |
| 150 // And append a zero, because module IDs include an "age" field | |
| 151 // which is always zero on Linux. | |
| 152 module_identifier += "0"; | |
| 153 | 137 |
| 154 // Get some memory. | 138 // Get some memory. |
| 155 char* memory = | 139 char* memory = |
| 156 reinterpret_cast<char*>(mmap(NULL, | 140 reinterpret_cast<char*>(mmap(NULL, |
| 157 memory_size, | 141 memory_size, |
| 158 PROT_READ | PROT_WRITE, | 142 PROT_READ | PROT_WRITE, |
| 159 MAP_PRIVATE | MAP_ANON, | 143 MAP_PRIVATE | MAP_ANON, |
| 160 -1, | 144 -1, |
| 161 0)); | 145 0)); |
| 162 const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory); | 146 const uintptr_t kMemoryAddress = reinterpret_cast<uintptr_t>(memory); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_PROC_STATUS, &len)); | 207 EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_PROC_STATUS, &len)); |
| 224 EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_CMD_LINE, &len)); | 208 EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_CMD_LINE, &len)); |
| 225 EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_ENVIRON, &len)); | 209 EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_ENVIRON, &len)); |
| 226 EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_AUXV, &len)); | 210 EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_AUXV, &len)); |
| 227 EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_MAPS, &len)); | 211 EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_MAPS, &len)); |
| 228 EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_DSO_DEBUG, &len)); | 212 EXPECT_TRUE(minidump.SeekToStreamType(MD_LINUX_DSO_DEBUG, &len)); |
| 229 | 213 |
| 230 close(fds[1]); | 214 close(fds[1]); |
| 231 } | 215 } |
| 232 | 216 |
| 217 // Test that a binary with a longer-than-usual build id note |
| 218 // makes its way all the way through to the minidump unscathed. |
| 219 // The linux_client_unittest is linked with an explicit --build-id |
| 220 // in Makefile.am. |
| 221 TEST(MinidumpWriterTest, BuildIDLong) { |
| 222 int fds[2]; |
| 223 ASSERT_NE(-1, pipe(fds)); |
| 224 |
| 225 const pid_t child = fork(); |
| 226 if (child == 0) { |
| 227 close(fds[1]); |
| 228 char b; |
| 229 IGNORE_RET(HANDLE_EINTR(read(fds[0], &b, sizeof(b)))); |
| 230 close(fds[0]); |
| 231 syscall(__NR_exit); |
| 232 } |
| 233 close(fds[0]); |
| 234 |
| 235 ExceptionHandler::CrashContext context; |
| 236 memset(&context, 0, sizeof(context)); |
| 237 ASSERT_EQ(0, getcontext(&context.context)); |
| 238 context.tid = child; |
| 239 |
| 240 AutoTempDir temp_dir; |
| 241 const string dump_path = temp_dir.path() + kMDWriterUnitTestFileName; |
| 242 |
| 243 EXPECT_TRUE(WriteMinidump(dump_path.c_str(), |
| 244 child, &context, sizeof(context))); |
| 245 close(fds[1]); |
| 246 |
| 247 // Read the minidump. Load the module list, and ensure that |
| 248 // the main module has the correct debug id and code id. |
| 249 Minidump minidump(dump_path); |
| 250 ASSERT_TRUE(minidump.Read()); |
| 251 |
| 252 MinidumpModuleList* module_list = minidump.GetModuleList(); |
| 253 ASSERT_TRUE(module_list); |
| 254 const MinidumpModule* module = module_list->GetMainModule(); |
| 255 ASSERT_TRUE(module); |
| 256 const string module_identifier = "030201000504070608090A0B0C0D0E0F0"; |
| 257 // This is passed explicitly to the linker in Makefile.am |
| 258 const string build_id = |
| 259 "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"; |
| 260 EXPECT_EQ(module_identifier, module->debug_identifier()); |
| 261 EXPECT_EQ(build_id, module->code_identifier()); |
| 262 } |
| 263 |
| 233 // Test that mapping info can be specified, and that it overrides | 264 // Test that mapping info can be specified, and that it overrides |
| 234 // existing mappings that are wholly contained within the specified | 265 // existing mappings that are wholly contained within the specified |
| 235 // range. | 266 // range. |
| 236 TEST(MinidumpWriterTest, MappingInfoContained) { | 267 TEST(MinidumpWriterTest, MappingInfoContained) { |
| 237 int fds[2]; | 268 int fds[2]; |
| 238 ASSERT_NE(-1, pipe(fds)); | 269 ASSERT_NE(-1, pipe(fds)); |
| 239 | 270 |
| 240 // These are defined here so the parent can use them to check the | 271 // These are defined here so the parent can use them to check the |
| 241 // data from the minidump afterwards. | 272 // data from the minidump afterwards. |
| 242 const int32_t memory_size = sysconf(_SC_PAGESIZE); | 273 const int32_t memory_size = sysconf(_SC_PAGESIZE); |
| 243 const char* kMemoryName = "a fake module"; | 274 const char* kMemoryName = "a fake module"; |
| 244 const uint8_t kModuleGUID[sizeof(MDGUID)] = { | 275 const uint8_t kModuleGUID[sizeof(MDGUID)] = { |
| 245 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, | 276 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, |
| 246 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF | 277 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF |
| 247 }; | 278 }; |
| 248 char module_identifier_buffer[kGUIDStringSize]; | 279 const string module_identifier = "33221100554477668899AABBCCDDEEFF0"; |
| 249 FileID::ConvertIdentifierToString(kModuleGUID, | |
| 250 module_identifier_buffer, | |
| 251 sizeof(module_identifier_buffer)); | |
| 252 string module_identifier(module_identifier_buffer); | |
| 253 // Strip out dashes | |
| 254 size_t pos; | |
| 255 while ((pos = module_identifier.find('-')) != string::npos) { | |
| 256 module_identifier.erase(pos, 1); | |
| 257 } | |
| 258 // And append a zero, because module IDs include an "age" field | |
| 259 // which is always zero on Linux. | |
| 260 module_identifier += "0"; | |
| 261 | 280 |
| 262 // mmap a file | 281 // mmap a file |
| 263 AutoTempDir temp_dir; | 282 AutoTempDir temp_dir; |
| 264 string tempfile = temp_dir.path() + "/minidump-writer-unittest-temp"; | 283 string tempfile = temp_dir.path() + "/minidump-writer-unittest-temp"; |
| 265 int fd = open(tempfile.c_str(), O_RDWR | O_CREAT, 0); | 284 int fd = open(tempfile.c_str(), O_RDWR | O_CREAT, 0); |
| 266 ASSERT_NE(-1, fd); | 285 ASSERT_NE(-1, fd); |
| 267 unlink(tempfile.c_str()); | 286 unlink(tempfile.c_str()); |
| 268 // fill with zeros | 287 // fill with zeros |
| 269 google_breakpad::scoped_array<char> buffer(new char[memory_size]); | 288 google_breakpad::scoped_array<char> buffer(new char[memory_size]); |
| 270 memset(buffer.get(), 0, memory_size); | 289 memset(buffer.get(), 0, memory_size); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 403 Minidump minidump(templ); | 422 Minidump minidump(templ); |
| 404 ASSERT_TRUE(minidump.Read()); | 423 ASSERT_TRUE(minidump.Read()); |
| 405 | 424 |
| 406 // Check that the main module filename is correct. | 425 // Check that the main module filename is correct. |
| 407 MinidumpModuleList* module_list = minidump.GetModuleList(); | 426 MinidumpModuleList* module_list = minidump.GetModuleList(); |
| 408 ASSERT_TRUE(module_list); | 427 ASSERT_TRUE(module_list); |
| 409 const MinidumpModule* module = module_list->GetMainModule(); | 428 const MinidumpModule* module = module_list->GetMainModule(); |
| 410 EXPECT_STREQ(binpath.c_str(), module->code_file().c_str()); | 429 EXPECT_STREQ(binpath.c_str(), module->code_file().c_str()); |
| 411 // Check that the file ID is correct. | 430 // Check that the file ID is correct. |
| 412 FileID fileid(helper_path.c_str()); | 431 FileID fileid(helper_path.c_str()); |
| 413 uint8_t identifier[sizeof(MDGUID)]; | 432 PageAllocator allocator; |
| 433 wasteful_vector<uint8_t> identifier(&allocator, kDefaultBuildIdSize); |
| 414 EXPECT_TRUE(fileid.ElfFileIdentifier(identifier)); | 434 EXPECT_TRUE(fileid.ElfFileIdentifier(identifier)); |
| 415 char identifier_string[kGUIDStringSize]; | 435 string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier); |
| 416 FileID::ConvertIdentifierToString(identifier, | |
| 417 identifier_string, | |
| 418 kGUIDStringSize); | |
| 419 string module_identifier(identifier_string); | 436 string module_identifier(identifier_string); |
| 420 // Strip out dashes | 437 // Strip out dashes |
| 421 size_t pos; | 438 size_t pos; |
| 422 while ((pos = module_identifier.find('-')) != string::npos) { | 439 while ((pos = module_identifier.find('-')) != string::npos) { |
| 423 module_identifier.erase(pos, 1); | 440 module_identifier.erase(pos, 1); |
| 424 } | 441 } |
| 425 // And append a zero, because module IDs include an "age" field | 442 // And append a zero, because module IDs include an "age" field |
| 426 // which is always zero on Linux. | 443 // which is always zero on Linux. |
| 427 module_identifier += "0"; | 444 module_identifier += "0"; |
| 428 EXPECT_EQ(module_identifier, module->debug_identifier()); | 445 EXPECT_EQ(module_identifier, module->debug_identifier()); |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 kLimitBaseThreadCount) * kMinPerExtraThreadStackReduction; | 764 kLimitBaseThreadCount) * kMinPerExtraThreadStackReduction; |
| 748 EXPECT_LT(total_limit_stack_size, | 765 EXPECT_LT(total_limit_stack_size, |
| 749 total_normal_stack_size - min_expected_reduction); | 766 total_normal_stack_size - min_expected_reduction); |
| 750 } | 767 } |
| 751 | 768 |
| 752 // Kill the helper program. | 769 // Kill the helper program. |
| 753 kill(child_pid, SIGKILL); | 770 kill(child_pid, SIGKILL); |
| 754 } | 771 } |
| 755 | 772 |
| 756 } // namespace | 773 } // namespace |
| OLD | NEW |