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 |