OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2013 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2013 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 #include <assert.h> | 7 #include <assert.h> |
8 #include <pthread.h> | 8 #include <pthread.h> |
9 #include <stdint.h> | 9 #include <stdint.h> |
10 #include <stdio.h> | 10 #include <stdio.h> |
11 #include <stdlib.h> | 11 #include <stdlib.h> |
12 #include <string.h> | 12 #include <string.h> |
13 #include <sys/mman.h> | 13 #include <sys/mman.h> |
14 #include <unistd.h> | 14 #include <unistd.h> |
15 | 15 |
16 #include <algorithm> | 16 #include <algorithm> |
17 | 17 |
18 #include "breakpad/src/google_breakpad/common/minidump_format.h" | 18 #include "breakpad/src/google_breakpad/common/minidump_format.h" |
19 #include "native_client/src/include/elf_constants.h" | 19 #include "native_client/src/include/elf_constants.h" |
20 #include "native_client/src/include/nacl/nacl_exception.h" | 20 #include "native_client/src/include/nacl/nacl_exception.h" |
21 #include "native_client/src/include/nacl/nacl_minidump.h" | 21 #include "native_client/src/include/nacl/nacl_minidump.h" |
22 #include "native_client/src/untrusted/irt/irt.h" | 22 #include "native_client/src/untrusted/irt/irt.h" |
| 23 #include "native_client/src/untrusted/minidump_generator/build_id.c" |
23 | 24 |
24 | 25 |
25 extern char __executable_start[]; // Start of code segment | 26 extern char __executable_start[]; // Start of code segment |
26 extern char __etext[]; // End of code segment | 27 extern char __etext[]; // End of code segment |
27 | 28 |
28 // @IGNORE_LINES_FOR_CODE_HYGIENE[1] | 29 // @IGNORE_LINES_FOR_CODE_HYGIENE[1] |
29 #if defined(__GLIBC__) | 30 #if defined(__GLIBC__) |
30 // Variable defined by ld.so, used as a workaround for | 31 // Variable defined by ld.so, used as a workaround for |
31 // https://code.google.com/p/nativeclient/issues/detail?id=3431. | 32 // https://code.google.com/p/nativeclient/issues/detail?id=3431. |
32 extern void *__libc_stack_end; | 33 extern void *__libc_stack_end; |
33 #endif | 34 #endif |
34 | 35 |
35 class MinidumpFileWriter; | 36 class MinidumpFileWriter; |
36 | 37 |
37 // Restrict how much of the stack we dump to reduce upload size and to | 38 // Restrict how much of the stack we dump to reduce upload size and to |
38 // avoid dynamic allocation. | 39 // avoid dynamic allocation. |
39 static const size_t kLimitStackDumpSize = 512 * 1024; | 40 static const size_t kLimitStackDumpSize = 512 * 1024; |
40 | 41 |
41 static const size_t kLimitNonStackSize = 64 * 1024; | 42 static const size_t kLimitNonStackSize = 64 * 1024; |
42 | 43 |
43 // The crash reporter is expected to be used in a situation where the | 44 // The crash reporter is expected to be used in a situation where the |
44 // current process is damaged or out of memory, so it avoids dynamic | 45 // current process is damaged or out of memory, so it avoids dynamic |
45 // memory allocation and allocates a fixed-size buffer of the | 46 // memory allocation and allocates a fixed-size buffer of the |
46 // following size at startup. | 47 // following size at startup. |
47 static const size_t kMinidumpBufferSize = | 48 static const size_t kMinidumpBufferSize = |
48 kLimitStackDumpSize + kLimitNonStackSize; | 49 kLimitStackDumpSize + kLimitNonStackSize; |
49 | 50 |
50 static const char *g_module_name = "main.nexe"; | 51 static const char *g_module_name = "main.nexe"; |
51 static MDGUID g_module_build_id; | 52 static MDGUID g_module_build_id; |
| 53 static int g_module_build_id_set; |
52 static nacl_minidump_callback_t g_callback_func; | 54 static nacl_minidump_callback_t g_callback_func; |
53 static MinidumpFileWriter *g_minidump_writer; | 55 static MinidumpFileWriter *g_minidump_writer; |
54 static int g_handling_exception = 0; | 56 static int g_handling_exception = 0; |
55 | 57 |
56 | 58 |
57 class MinidumpFileWriter { | 59 class MinidumpFileWriter { |
58 char *buf_; | 60 char *buf_; |
59 uint32_t buf_size_; | 61 uint32_t buf_size_; |
60 uint32_t offset_; | 62 uint32_t offset_; |
61 | 63 |
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
423 &irt_exception_handling, | 425 &irt_exception_handling, |
424 sizeof(irt_exception_handling)) | 426 sizeof(irt_exception_handling)) |
425 != sizeof(irt_exception_handling)) { | 427 != sizeof(irt_exception_handling)) { |
426 fprintf(stderr, "minidump: Exception handling IRT interface not present\n"); | 428 fprintf(stderr, "minidump: Exception handling IRT interface not present\n"); |
427 return; | 429 return; |
428 } | 430 } |
429 if (irt_exception_handling.exception_handler(CrashHandler, NULL) != 0) { | 431 if (irt_exception_handling.exception_handler(CrashHandler, NULL) != 0) { |
430 fprintf(stderr, "minidump: Failed to register an exception handler\n"); | 432 fprintf(stderr, "minidump: Failed to register an exception handler\n"); |
431 return; | 433 return; |
432 } | 434 } |
| 435 |
| 436 if (!g_module_build_id_set) { |
| 437 // Try to use the nexe's built-in build ID. |
| 438 const char *data_ptr; |
| 439 size_t size; |
| 440 if (nacl_get_build_id(&data_ptr, &size)) { |
| 441 // Truncate the ID if necessary. The minidump format uses a 16 |
| 442 // byte ID, whereas ELF build IDs are typically 20-byte SHA1 |
| 443 // hashes. |
| 444 memcpy(&g_module_build_id, data_ptr, |
| 445 std::min(size, sizeof(g_module_build_id))); |
| 446 g_module_build_id_set = 1; |
| 447 } |
| 448 } |
| 449 |
433 g_minidump_writer = new MinidumpFileWriter(); | 450 g_minidump_writer = new MinidumpFileWriter(); |
434 } | 451 } |
435 | 452 |
436 void nacl_minidump_set_callback(nacl_minidump_callback_t callback) { | 453 void nacl_minidump_set_callback(nacl_minidump_callback_t callback) { |
437 g_callback_func = callback; | 454 g_callback_func = callback; |
438 } | 455 } |
439 | 456 |
440 void nacl_minidump_set_module_name(const char *module_name) { | 457 void nacl_minidump_set_module_name(const char *module_name) { |
441 g_module_name = module_name; | 458 g_module_name = module_name; |
442 } | 459 } |
443 | 460 |
444 void nacl_minidump_set_module_build_id( | 461 void nacl_minidump_set_module_build_id( |
445 const uint8_t data[NACL_MINIDUMP_BUILD_ID_SIZE]) { | 462 const uint8_t data[NACL_MINIDUMP_BUILD_ID_SIZE]) { |
446 assert(sizeof(g_module_build_id) == NACL_MINIDUMP_BUILD_ID_SIZE); | 463 assert(sizeof(g_module_build_id) == NACL_MINIDUMP_BUILD_ID_SIZE); |
447 memcpy(&g_module_build_id, data, NACL_MINIDUMP_BUILD_ID_SIZE); | 464 memcpy(&g_module_build_id, data, NACL_MINIDUMP_BUILD_ID_SIZE); |
| 465 g_module_build_id_set = 1; |
448 } | 466 } |
OLD | NEW |