| 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 |