diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..1f5493729 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +src/processor/testdata/*.out text eol=lf diff --git a/DEPS b/DEPS index 3fcd524dc..f00f5d246 100644 --- a/DEPS +++ b/DEPS @@ -36,7 +36,7 @@ deps = { # Testing libraries and utilities. "src/src/testing": "https://github.com/google/googletest.git" + - "@release-1.11.0", + "@v1.16.0", # Protobuf. "src/src/third_party/protobuf/protobuf": @@ -46,7 +46,7 @@ deps = { # Linux syscall support. "src/src/third_party/lss": "https://chromium.googlesource.com/linux-syscall-support/" + - "@9719c1e1e676814c456b55f5f070eabad6709d31", + "@ed31caa60f20a4f6569883b2d752ef7522de51e0", } hooks = [ diff --git a/Makefile.in b/Makefile.in index 0c47bf87d..7637800c0 100644 --- a/Makefile.in +++ b/Makefile.in @@ -2691,11 +2691,13 @@ src_tools_linux_dump_syms_dump_syms_SOURCES = \ src/tools/linux/dump_syms/dump_syms.cc src_tools_linux_dump_syms_dump_syms_CXXFLAGS = \ - $(RUSTC_DEMANGLE_CFLAGS) + $(RUSTC_DEMANGLE_CFLAGS) \ + $(ZSTD_CFLAGS) src_tools_linux_dump_syms_dump_syms_LDADD = \ $(RUSTC_DEMANGLE_LIBS) \ - -lz -lzstd + $(ZSTD_CFLAGS) \ + -lz src_tools_linux_md2core_minidump_2_core_SOURCES = \ src/common/linux/memory_mapped_file.cc \ @@ -2822,13 +2824,15 @@ src_common_dumper_unittest_SOURCES = \ src_common_dumper_unittest_CPPFLAGS = \ $(AM_CPPFLAGS) $(TEST_CFLAGS) \ $(RUSTC_DEMANGLE_CFLAGS) \ - $(PTHREAD_CFLAGS) + $(PTHREAD_CFLAGS) \ + $(ZSTD_CFLAGS) src_common_dumper_unittest_LDADD = \ $(TEST_LIBS) \ $(RUSTC_DEMANGLE_LIBS) \ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) \ - -lz -lzstd + $(ZSTD_LIBS) \ + -lz src_common_mac_macho_reader_unittest_SOURCES = \ src/common/dwarf_cfi_to_module.cc \ diff --git a/OWNERS b/OWNERS index 2fde281f9..ca36bef10 100644 --- a/OWNERS +++ b/OWNERS @@ -11,3 +11,6 @@ rsesek@chromium.org ted@mielczarek.org thestig@chromium.org vapier@chromium.org + +# Allow autoroller to update our DEPS file automatically. +per-file DEPS=* diff --git a/android/sample_app/jni/test_breakpad.cpp b/android/sample_app/jni/test_breakpad.cpp index 481cbe762..64ed4a2c8 100644 --- a/android/sample_app/jni/test_breakpad.cpp +++ b/android/sample_app/jni/test_breakpad.cpp @@ -41,7 +41,7 @@ bool DumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, } void Crash() { - volatile int* a = reinterpret_cast(NULL); + volatile int* a = static_cast(nullptr); *a = 1; } @@ -49,8 +49,8 @@ void Crash() { int main(int argc, char* argv[]) { google_breakpad::MinidumpDescriptor descriptor("."); - google_breakpad::ExceptionHandler eh(descriptor, NULL, DumpCallback, - NULL, true, -1); + google_breakpad::ExceptionHandler eh(descriptor, nullptr, DumpCallback, + nullptr, true, -1); Crash(); return 0; } diff --git a/configure b/configure index 3442e7969..37f3ac3ef 100755 --- a/configure +++ b/configure @@ -675,7 +675,7 @@ ANDROID_HOST_TRUE LINUX_HOST_FALSE LINUX_HOST_TRUE WARN_CXXFLAGS -HAVE_CXX17 +HAVE_CXX20 HAVE_MEMFD_CREATE_FALSE HAVE_MEMFD_CREATE_TRUE HAVE_GETCONTEXT_FALSE @@ -7594,7 +7594,7 @@ fi - ax_cxx_compile_alternatives="17 1z" ax_cxx_compile_cxx17_required=true + ax_cxx_compile_alternatives="20" ax_cxx_compile_cxx20_required=true ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -7602,9 +7602,9 @@ ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ex ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ac_success=no - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++17 features by default" >&5 -printf %s "checking whether $CXX supports C++17 features by default... " >&6; } -if test ${ax_cv_cxx_compile_cxx17+y} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++20 features by default" >&5 +printf %s "checking whether $CXX supports C++20 features by default... " >&6; } +if test ${ax_cv_cxx_compile_cxx20+y} then : printf %s "(cached) " >&6 else $as_nop @@ -8400,27 +8400,53 @@ namespace cxx17 + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 202002L && !defined _MSC_VER + +#error "This is not a C++20 compiler" + +#else + +#include + +namespace cxx20 +{ + +// As C++20 supports feature test macros in the standard, there is no +// immediate need to actually test for feature availability on the +// Autoconf side. + +} // namespace cxx20 + +#endif // __cplusplus < 202002L && !defined _MSC_VER + + + _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : - ax_cv_cxx_compile_cxx17=yes + ax_cv_cxx_compile_cxx20=yes else $as_nop - ax_cv_cxx_compile_cxx17=no + ax_cv_cxx_compile_cxx20=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx17" >&5 -printf "%s\n" "$ax_cv_cxx_compile_cxx17" >&6; } - if test x$ax_cv_cxx_compile_cxx17 = xyes; then +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx20" >&5 +printf "%s\n" "$ax_cv_cxx_compile_cxx20" >&6; } + if test x$ax_cv_cxx_compile_cxx20 = xyes; then ac_success=yes fi if test x$ac_success = xno; then for alternative in ${ax_cxx_compile_alternatives}; do switch="-std=gnu++${alternative}" - cachevar=`printf "%s\n" "ax_cv_cxx_compile_cxx17_$switch" | $as_tr_sh` - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++17 features with $switch" >&5 -printf %s "checking whether $CXX supports C++17 features with $switch... " >&6; } + cachevar=`printf "%s\n" "ax_cv_cxx_compile_cxx20_$switch" | $as_tr_sh` + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++20 features with $switch" >&5 +printf %s "checking whether $CXX supports C++20 features with $switch... " >&6; } if eval test \${$cachevar+y} then : printf %s "(cached) " >&6 @@ -9219,6 +9245,32 @@ namespace cxx17 + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 202002L && !defined _MSC_VER + +#error "This is not a C++20 compiler" + +#else + +#include + +namespace cxx20 +{ + +// As C++20 supports feature test macros in the standard, there is no +// immediate need to actually test for feature availability on the +// Autoconf side. + +} // namespace cxx20 + +#endif // __cplusplus < 202002L && !defined _MSC_VER + + + _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : @@ -9246,9 +9298,9 @@ printf "%s\n" "$ac_res" >&6; } if test x$ac_success = xno; then for alternative in ${ax_cxx_compile_alternatives}; do for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do - cachevar=`printf "%s\n" "ax_cv_cxx_compile_cxx17_$switch" | $as_tr_sh` - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++17 features with $switch" >&5 -printf %s "checking whether $CXX supports C++17 features with $switch... " >&6; } + cachevar=`printf "%s\n" "ax_cv_cxx_compile_cxx20_$switch" | $as_tr_sh` + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++20 features with $switch" >&5 +printf %s "checking whether $CXX supports C++20 features with $switch... " >&6; } if eval test \${$cachevar+y} then : printf %s "(cached) " >&6 @@ -10047,6 +10099,32 @@ namespace cxx17 + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 202002L && !defined _MSC_VER + +#error "This is not a C++20 compiler" + +#else + +#include + +namespace cxx20 +{ + +// As C++20 supports feature test macros in the standard, there is no +// immediate need to actually test for feature availability on the +// Autoconf side. + +} // namespace cxx20 + +#endif // __cplusplus < 202002L && !defined _MSC_VER + + + _ACEOF if ac_fn_cxx_try_compile "$LINENO" then : @@ -10080,19 +10158,19 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu - if test x$ax_cxx_compile_cxx17_required = xtrue; then + if test x$ax_cxx_compile_cxx20_required = xtrue; then if test x$ac_success = xno; then - as_fn_error $? "*** A compiler with support for C++17 language features is required." "$LINENO" 5 + as_fn_error $? "*** A compiler with support for C++20 language features is required." "$LINENO" 5 fi fi if test x$ac_success = xno; then - HAVE_CXX17=0 - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: No compiler with C++17 support was found" >&5 -printf "%s\n" "$as_me: No compiler with C++17 support was found" >&6;} + HAVE_CXX20=0 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: No compiler with C++20 support was found" >&5 +printf "%s\n" "$as_me: No compiler with C++20 support was found" >&6;} else - HAVE_CXX17=1 + HAVE_CXX20=1 -printf "%s\n" "#define HAVE_CXX17 1" >>confdefs.h +printf "%s\n" "#define HAVE_CXX20 1" >>confdefs.h fi diff --git a/configure.ac b/configure.ac index bfee372a3..0258c116e 100644 --- a/configure.ac +++ b/configure.ac @@ -66,7 +66,7 @@ AC_CHECK_FUNCS([arc4random getcontext getrandom memfd_create]) AM_CONDITIONAL([HAVE_GETCONTEXT], [test "x$ac_cv_func_getcontext" = xyes]) AM_CONDITIONAL([HAVE_MEMFD_CREATE], [test "x$ac_cv_func_memfd_create" = xyes]) -AX_CXX_COMPILE_STDCXX(17, , mandatory) +AX_CXX_COMPILE_STDCXX(20, , mandatory) dnl Test supported warning flags. WARN_CXXFLAGS= diff --git a/default.xml b/default.xml index 916b41fe7..72ff675b4 100644 --- a/default.xml +++ b/default.xml @@ -7,14 +7,14 @@ sync-c='true' sync-j='8' /> - - + + - - + + diff --git a/src/client/ios/exception_handler_no_mach.cc b/src/client/ios/exception_handler_no_mach.cc index 675e3424d..58bec65ef 100644 --- a/src/client/ios/exception_handler_no_mach.cc +++ b/src/client/ios/exception_handler_no_mach.cc @@ -30,9 +30,12 @@ #include // Must come first #endif +#include #include #include +#include + #include "client/mac/handler/minidump_generator.h" #include "client/ios/exception_handler_no_mach.h" @@ -65,7 +68,7 @@ const int kExceptionSignals[] = { }; const int kNumHandledSignals = sizeof(kExceptionSignals) / sizeof(kExceptionSignals[0]); -struct scoped_ptr old_handlers[kNumHandledSignals]; +struct std::unique_ptr old_handlers[kNumHandledSignals]; static union { #if USE_PROTECTED_ALLOCATIONS diff --git a/src/client/ios/exception_handler_no_mach.h b/src/client/ios/exception_handler_no_mach.h index 57247e617..4d47b70b6 100644 --- a/src/client/ios/exception_handler_no_mach.h +++ b/src/client/ios/exception_handler_no_mach.h @@ -35,7 +35,6 @@ #include #include "client/mac/handler/ucontext_compat.h" -#include "common/scoped_ptr.h" namespace google_breakpad { diff --git a/src/client/linux/crash_generation/crash_generation_client.cc b/src/client/linux/crash_generation/crash_generation_client.cc index 020c61466..23daec819 100644 --- a/src/client/linux/crash_generation/crash_generation_client.cc +++ b/src/client/linux/crash_generation/crash_generation_client.cc @@ -101,7 +101,7 @@ class CrashGenerationClientImpl : public CrashGenerationClient { // static CrashGenerationClient* CrashGenerationClient::TryCreate(int server_fd) { if (server_fd < 0) - return NULL; + return nullptr; return new CrashGenerationClientImpl(server_fd); } diff --git a/src/client/linux/crash_generation/crash_generation_server.cc b/src/client/linux/crash_generation/crash_generation_server.cc index e3270c9d4..f5f371a00 100644 --- a/src/client/linux/crash_generation/crash_generation_server.cc +++ b/src/client/linux/crash_generation/crash_generation_server.cc @@ -105,7 +105,7 @@ CrashGenerationServer::Start() control_pipe_in_ = control_pipe[0]; control_pipe_out_ = control_pipe[1]; - if (pthread_create(&thread_, NULL, + if (pthread_create(&thread_, nullptr, ThreadMain, reinterpret_cast(this))) return false; @@ -330,7 +330,7 @@ void* CrashGenerationServer::ThreadMain(void* arg) { reinterpret_cast(arg)->Run(); - return NULL; + return nullptr; } } // namespace google_breakpad diff --git a/src/client/linux/handler/exception_handler.cc b/src/client/linux/handler/exception_handler.cc index 9e23c1194..c65d03932 100644 --- a/src/client/linux/handler/exception_handler.cc +++ b/src/client/linux/handler/exception_handler.cc @@ -145,12 +145,12 @@ void InstallAlternateStackLocked() { // Only set an alternative stack if there isn't already one, or if the current // one is too small. - if (sys_sigaltstack(NULL, &old_stack) == -1 || !old_stack.ss_sp || + if (sys_sigaltstack(nullptr, &old_stack) == -1 || !old_stack.ss_sp || old_stack.ss_size < kSigStackSize) { new_stack.ss_sp = calloc(1, kSigStackSize); new_stack.ss_size = kSigStackSize; - if (sys_sigaltstack(&new_stack, NULL) == -1) { + if (sys_sigaltstack(&new_stack, nullptr) == -1) { free(new_stack.ss_sp); return; } @@ -164,19 +164,19 @@ void RestoreAlternateStackLocked() { return; stack_t current_stack; - if (sys_sigaltstack(NULL, ¤t_stack) == -1) + if (sys_sigaltstack(nullptr, ¤t_stack) == -1) return; // Only restore the old_stack if the current alternative stack is the one // installed by the call to InstallAlternateStackLocked. if (current_stack.ss_sp == new_stack.ss_sp) { if (old_stack.ss_sp) { - if (sys_sigaltstack(&old_stack, NULL) == -1) + if (sys_sigaltstack(&old_stack, nullptr) == -1) return; } else { stack_t disable_stack; disable_stack.ss_flags = SS_DISABLE; - if (sys_sigaltstack(&disable_stack, NULL) == -1) + if (sys_sigaltstack(&disable_stack, nullptr) == -1) return; } } @@ -197,7 +197,7 @@ void InstallDefaultHandler(int sig) { sys_sigemptyset(&sa.sa_mask); sa.sa_handler_ = SIG_DFL; sa.sa_flags = SA_RESTART; - sys_rt_sigaction(sig, &sa, NULL, sizeof(kernel_sigset_t)); + sys_rt_sigaction(sig, &sa, nullptr, sizeof(kernel_sigset_t)); #else signal(sig, SIG_DFL); #endif @@ -206,7 +206,7 @@ void InstallDefaultHandler(int sig) { // The global exception handler stack. This is needed because there may exist // multiple ExceptionHandler instances in a process. Each will have itself // registered in this stack. -std::vector* g_handler_stack_ = NULL; +std::vector* g_handler_stack_ = nullptr; pthread_mutex_t g_handler_stack_mutex_ = PTHREAD_MUTEX_INITIALIZER; // sizeof(CrashContext) can be too big w.r.t the size of alternatate stack @@ -229,7 +229,7 @@ ExceptionHandler::ExceptionHandler(const MinidumpDescriptor& descriptor, callback_(callback), callback_context_(callback_context), minidump_descriptor_(descriptor), - crash_handler_(NULL) { + crash_handler_(nullptr) { if (server_fd >= 0) crash_generation_client_.reset(CrashGenerationClient::TryCreate(server_fd)); @@ -266,7 +266,7 @@ ExceptionHandler::~ExceptionHandler() { g_handler_stack_->erase(handler); if (g_handler_stack_->empty()) { delete g_handler_stack_; - g_handler_stack_ = NULL; + g_handler_stack_ = nullptr; RestoreAlternateStackLocked(); RestoreHandlersLocked(); } @@ -281,7 +281,7 @@ bool ExceptionHandler::InstallHandlersLocked() { // Fail if unable to store all the old handlers. for (int i = 0; i < kNumHandledSignals; ++i) { - if (sigaction(kExceptionSignals[i], NULL, &old_handlers[i]) == -1) + if (sigaction(kExceptionSignals[i], nullptr, &old_handlers[i]) == -1) return false; } @@ -297,7 +297,7 @@ bool ExceptionHandler::InstallHandlersLocked() { sa.sa_flags = SA_ONSTACK | SA_SIGINFO; for (int i = 0; i < kNumHandledSignals; ++i) { - if (sigaction(kExceptionSignals[i], &sa, NULL) == -1) { + if (sigaction(kExceptionSignals[i], &sa, nullptr) == -1) { // At this point it is impractical to back out changes, and so failure to // install a signal is intentionally ignored. } @@ -314,7 +314,7 @@ void ExceptionHandler::RestoreHandlersLocked() { return; for (int i = 0; i < kNumHandledSignals; ++i) { - if (sigaction(kExceptionSignals[i], &old_handlers[i], NULL) == -1) { + if (sigaction(kExceptionSignals[i], &old_handlers[i], nullptr) == -1) { InstallDefaultHandler(kExceptionSignals[i]); } } @@ -355,7 +355,7 @@ void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) { // This forces the signal to be thrown again, but this time the kernel // will call the function with the right arguments. struct sigaction cur_handler; - if (sigaction(sig, NULL, &cur_handler) == 0 && + if (sigaction(sig, nullptr, &cur_handler) == 0 && cur_handler.sa_sigaction == SignalHandler && (cur_handler.sa_flags & SA_SIGINFO) == 0) { // Reset signal handler with the right flags. @@ -365,7 +365,7 @@ void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) { cur_handler.sa_sigaction = SignalHandler; cur_handler.sa_flags = SA_ONSTACK | SA_SIGINFO; - if (sigaction(sig, &cur_handler, NULL) == -1) { + if (sigaction(sig, &cur_handler, nullptr) == -1) { // When resetting the handler fails, try to reset the // default one to avoid an infinite loop here. InstallDefaultHandler(sig); @@ -447,7 +447,8 @@ bool ExceptionHandler::HandleSignal(int /*sig*/, siginfo_t* info, void* uc) { // Allow ourselves to be dumped if the signal is trusted. bool signal_trusted = info->si_code > 0; bool signal_pid_trusted = info->si_code == SI_USER || - info->si_code == SI_TKILL; + info->si_code == SI_TKILL || + info->si_code == SI_QUEUE; if (signal_trusted || (signal_pid_trusted && info->si_pid == getpid())) { sys_prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); } @@ -472,7 +473,7 @@ bool ExceptionHandler::HandleSignal(int /*sig*/, siginfo_t* info, void* uc) { } #endif g_crash_context_.tid = syscall(__NR_gettid); - if (crash_handler_ != NULL) { + if (crash_handler_ != nullptr) { if (crash_handler_(&g_crash_context_, sizeof(g_crash_context_), callback_context_)) { return true; @@ -536,8 +537,8 @@ bool ExceptionHandler::GenerateDump(CrashContext* context) { } const pid_t child = sys_clone( - ThreadEntry, stack, CLONE_FS | CLONE_UNTRACED, &thread_arg, NULL, NULL, - NULL); + ThreadEntry, stack, CLONE_FS | CLONE_UNTRACED, &thread_arg, nullptr, + nullptr, nullptr); if (child == -1) { sys_close(fdes[0]); sys_close(fdes[1]); @@ -645,7 +646,8 @@ bool ExceptionHandler::WriteMinidump(const string& dump_path, MinidumpCallback callback, void* callback_context) { MinidumpDescriptor descriptor(dump_path); - ExceptionHandler eh(descriptor, NULL, callback, callback_context, false, -1); + ExceptionHandler eh(descriptor, nullptr, callback, callback_context, false, + -1); return eh.WriteMinidump(); } diff --git a/src/client/linux/handler/exception_handler.h b/src/client/linux/handler/exception_handler.h index f8bc1ead7..adeee7069 100644 --- a/src/client/linux/handler/exception_handler.h +++ b/src/client/linux/handler/exception_handler.h @@ -34,12 +34,12 @@ #include #include +#include #include #include "client/linux/crash_generation/crash_generation_client.h" #include "client/linux/handler/minidump_descriptor.h" #include "client/linux/minidump_writer/minidump_writer.h" -#include "common/scoped_ptr.h" #include "common/using_std_string.h" #include "google_breakpad/common/minidump_format.h" @@ -207,7 +207,7 @@ class ExceptionHandler { // Returns whether out-of-process dump generation is used or not. bool IsOutOfProcess() const { - return crash_generation_client_.get() != NULL; + return crash_generation_client_.get() != nullptr; } // Add information about a memory mapping. This can be used if @@ -252,7 +252,7 @@ class ExceptionHandler { const MinidumpCallback callback_; void* const callback_context_; - scoped_ptr crash_generation_client_; + std::unique_ptr crash_generation_client_; MinidumpDescriptor minidump_descriptor_; diff --git a/src/client/linux/handler/exception_handler_unittest.cc b/src/client/linux/handler/exception_handler_unittest.cc index b2d8d4681..876cb2df8 100644 --- a/src/client/linux/handler/exception_handler_unittest.cc +++ b/src/client/linux/handler/exception_handler_unittest.cc @@ -43,6 +43,7 @@ #include #endif +#include #include #include "breakpad_googletest_includes.h" @@ -51,6 +52,7 @@ #include "common/linux/eintr_wrapper.h" #include "common/linux/ignore_ret.h" #include "common/linux/linux_libc_support.h" +#include "common/scoped_ptr.h" #include "common/tests/auto_tempdir.h" #include "common/using_std_string.h" #include "third_party/lss/linux_syscall_support.h" @@ -122,7 +124,7 @@ class ExceptionHandlerTest : public ::testing::Test { } void TearDown() { - sigaction(SIGCHLD, &old_action, NULL); + sigaction(SIGCHLD, &old_action, nullptr); } struct sigaction old_action; @@ -163,7 +165,7 @@ void ReadMinidumpPathFromPipe(int fd, string* path) { TEST(ExceptionHandlerTest, SimpleWithPath) { AutoTempDir temp_dir; ExceptionHandler handler( - MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1); + MinidumpDescriptor(temp_dir.path()), nullptr, nullptr, nullptr, true, -1); EXPECT_EQ(temp_dir.path(), handler.minidump_descriptor().directory()); string temp_subdir = temp_dir.path() + "/subdir"; handler.set_minidump_descriptor(MinidumpDescriptor(temp_subdir)); @@ -174,7 +176,8 @@ TEST(ExceptionHandlerTest, SimpleWithFD) { AutoTempDir temp_dir; string path; const int fd = CreateTMPFile(temp_dir.path(), &path); - ExceptionHandler handler(MinidumpDescriptor(fd), NULL, NULL, NULL, true, -1); + ExceptionHandler handler( + MinidumpDescriptor(fd), nullptr, nullptr, nullptr, true, -1); close(fd); } @@ -224,15 +227,16 @@ void ChildCrash(bool use_fd) { const pid_t child = fork(); if (child == 0) { { - google_breakpad::scoped_ptr handler; + std::unique_ptr handler; if (use_fd) { handler.reset(new ExceptionHandler(MinidumpDescriptor(minidump_fd), - NULL, NULL, NULL, true, -1)); + nullptr, nullptr, nullptr, true, + -1)); } else { close(fds[0]); // Close the reading end. void* fd_param = reinterpret_cast(fds[1]); handler.reset(new ExceptionHandler(MinidumpDescriptor(temp_dir.path()), - NULL, DoneCallback, fd_param, + nullptr, DoneCallback, fd_param, true, -1)); } // Crash with the exception handler in scope. @@ -264,14 +268,14 @@ TEST(ExceptionHandlerTest, ChildCrashWithFD) { #if !defined(__ANDROID_API__) || __ANDROID_API__ >= __ANDROID_API_N__ static void* SleepFunction(void* unused) { while (true) usleep(1000000); - return NULL; + return nullptr; } static void* CrashFunction(void* b_ptr) { pthread_barrier_t* b = reinterpret_cast(b_ptr); pthread_barrier_wait(b); DoNullPointerDereference(); - return NULL; + return nullptr; } // Tests that concurrent crashes do not enter a loop by alternately triggering @@ -280,9 +284,9 @@ TEST(ExceptionHandlerTest, ParallelChildCrashesDontHang) { AutoTempDir temp_dir; const pid_t child = fork(); if (child == 0) { - google_breakpad::scoped_ptr handler( - new ExceptionHandler(MinidumpDescriptor(temp_dir.path()), NULL, NULL, - NULL, true, -1)); + std::unique_ptr handler( + new ExceptionHandler(MinidumpDescriptor(temp_dir.path()), nullptr, + nullptr, nullptr, true, -1)); // We start a number of threads to make sure handling the signal takes // enough time for the second thread to enter the signal handler. @@ -290,8 +294,8 @@ TEST(ExceptionHandlerTest, ParallelChildCrashesDontHang) { google_breakpad::scoped_array sleep_threads( new pthread_t[num_sleep_threads]); for (int i = 0; i < num_sleep_threads; ++i) { - ASSERT_EQ(0, pthread_create(&sleep_threads[i], NULL, SleepFunction, - NULL)); + ASSERT_EQ(0, pthread_create(&sleep_threads[i], nullptr, SleepFunction, + nullptr)); } int num_crash_threads = 2; @@ -299,13 +303,14 @@ TEST(ExceptionHandlerTest, ParallelChildCrashesDontHang) { new pthread_t[num_crash_threads]); // Barrier to synchronize crashing both threads at the same time. pthread_barrier_t b; - ASSERT_EQ(0, pthread_barrier_init(&b, NULL, num_crash_threads + 1)); + ASSERT_EQ(0, pthread_barrier_init(&b, nullptr, num_crash_threads + 1)); for (int i = 0; i < num_crash_threads; ++i) { - ASSERT_EQ(0, pthread_create(&crash_threads[i], NULL, CrashFunction, &b)); + ASSERT_EQ(0, + pthread_create(&crash_threads[i], nullptr, CrashFunction, &b)); } pthread_barrier_wait(&b); for (int i = 0; i < num_crash_threads; ++i) { - ASSERT_EQ(0, pthread_join(crash_threads[i], NULL)); + ASSERT_EQ(0, pthread_join(crash_threads[i], nullptr)); } } @@ -373,14 +378,14 @@ static bool InstallRaiseSIGKILL() { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = RaiseSIGKILL; - return sigaction(SIGSEGV, &sa, NULL) != -1; + return sigaction(SIGSEGV, &sa, nullptr) != -1; } static void CrashWithCallbacks(ExceptionHandler::FilterCallback filter, ExceptionHandler::MinidumpCallback done, - string path) { + const string& path) { ExceptionHandler handler( - MinidumpDescriptor(path), filter, done, NULL, true, -1); + MinidumpDescriptor(path), filter, done, nullptr, true, -1); // Crash with the exception handler in scope. DoNullPointerDereference(); } @@ -391,7 +396,7 @@ TEST(ExceptionHandlerTest, RedeliveryOnFilterCallbackFalse) { const pid_t child = fork(); if (child == 0) { ASSERT_TRUE(InstallRaiseSIGKILL()); - CrashWithCallbacks(FilterCallbackReturnFalse, NULL, temp_dir.path()); + CrashWithCallbacks(FilterCallbackReturnFalse, nullptr, temp_dir.path()); } ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL)); @@ -403,7 +408,7 @@ TEST(ExceptionHandlerTest, RedeliveryOnDoneCallbackFalse) { const pid_t child = fork(); if (child == 0) { ASSERT_TRUE(InstallRaiseSIGKILL()); - CrashWithCallbacks(NULL, DoneCallbackReturnFalse, temp_dir.path()); + CrashWithCallbacks(nullptr, DoneCallbackReturnFalse, temp_dir.path()); } ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL)); @@ -415,7 +420,7 @@ TEST(ExceptionHandlerTest, NoRedeliveryOnDoneCallbackTrue) { const pid_t child = fork(); if (child == 0) { ASSERT_TRUE(InstallRaiseSIGKILL()); - CrashWithCallbacks(NULL, DoneCallbackReturnTrue, temp_dir.path()); + CrashWithCallbacks(nullptr, DoneCallbackReturnTrue, temp_dir.path()); } ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV)); @@ -427,7 +432,7 @@ TEST(ExceptionHandlerTest, NoRedeliveryOnFilterCallbackTrue) { const pid_t child = fork(); if (child == 0) { ASSERT_TRUE(InstallRaiseSIGKILL()); - CrashWithCallbacks(FilterCallbackReturnTrue, NULL, temp_dir.path()); + CrashWithCallbacks(FilterCallbackReturnTrue, nullptr, temp_dir.path()); } ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV)); @@ -442,7 +447,7 @@ TEST(ExceptionHandlerTest, RedeliveryToDefaultHandler) { // are undesirable in this child. signal(SIGSEGV, SIG_DFL); - CrashWithCallbacks(FilterCallbackReturnFalse, NULL, temp_dir.path()); + CrashWithCallbacks(FilterCallbackReturnFalse, nullptr, temp_dir.path()); } // As RaiseSIGKILL wasn't installed, the redelivery should just kill the child @@ -464,8 +469,8 @@ TEST(ExceptionHandlerTest, RedeliveryOnBadSignalHandlerFlag) { // Create a new exception handler, this installs a new SIGSEGV // handler, after saving the old one. ExceptionHandler handler( - MinidumpDescriptor(temp_dir.path()), NULL, - DoneCallbackReturnFalse, NULL, true, -1); + MinidumpDescriptor(temp_dir.path()), nullptr, + DoneCallbackReturnFalse, nullptr, true, -1); // Install the default SIGSEGV handler, saving the current one. // Then re-install the current one with 'signal', this loses the @@ -489,12 +494,12 @@ TEST(ExceptionHandlerTest, StackedHandlersDeliveredToTop) { const pid_t child = fork(); if (child == 0) { ExceptionHandler bottom(MinidumpDescriptor(temp_dir.path()), - NULL, - NULL, - NULL, + nullptr, + nullptr, + nullptr, true, -1); - CrashWithCallbacks(NULL, DoneCallbackRaiseSIGKILL, temp_dir.path()); + CrashWithCallbacks(nullptr, DoneCallbackRaiseSIGKILL, temp_dir.path()); } ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL)); } @@ -505,12 +510,12 @@ TEST(ExceptionHandlerTest, StackedHandlersNotDeliveredToBottom) { const pid_t child = fork(); if (child == 0) { ExceptionHandler bottom(MinidumpDescriptor(temp_dir.path()), - NULL, + nullptr, DoneCallbackRaiseSIGKILL, - NULL, + nullptr, true, -1); - CrashWithCallbacks(NULL, NULL, temp_dir.path()); + CrashWithCallbacks(nullptr, nullptr, temp_dir.path()); } ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGSEGV)); } @@ -521,12 +526,12 @@ TEST(ExceptionHandlerTest, StackedHandlersFilteredToBottom) { const pid_t child = fork(); if (child == 0) { ExceptionHandler bottom(MinidumpDescriptor(temp_dir.path()), - NULL, + nullptr, DoneCallbackRaiseSIGKILL, - NULL, + nullptr, true, -1); - CrashWithCallbacks(FilterCallbackReturnFalse, NULL, temp_dir.path()); + CrashWithCallbacks(FilterCallbackReturnFalse, nullptr, temp_dir.path()); } ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL)); } @@ -537,12 +542,12 @@ TEST(ExceptionHandlerTest, StackedHandlersUnhandledToBottom) { const pid_t child = fork(); if (child == 0) { ExceptionHandler bottom(MinidumpDescriptor(temp_dir.path()), - NULL, + nullptr, DoneCallbackRaiseSIGKILL, - NULL, + nullptr, true, -1); - CrashWithCallbacks(NULL, DoneCallbackReturnFalse, temp_dir.path()); + CrashWithCallbacks(nullptr, DoneCallbackReturnFalse, temp_dir.path()); } ASSERT_NO_FATAL_FAILURE(WaitForProcessToTerminate(child, SIGKILL)); } @@ -560,7 +565,8 @@ TEST(ExceptionHandlerTest, FirstChanceHandlerRuns) { const pid_t child = fork(); if (child == 0) { ExceptionHandler handler( - MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1); + MinidumpDescriptor(temp_dir.path()), nullptr, nullptr, nullptr, true, + -1); google_breakpad::SetFirstChanceExceptionHandler(SimpleFirstChanceHandler); DoNullPointerDereference(); } @@ -597,12 +603,12 @@ TEST(ExceptionHandlerTest, InstructionPointerMemory) { const pid_t child = fork(); if (child == 0) { close(fds[0]); - ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL, + ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), nullptr, DoneCallback, reinterpret_cast(fds[1]), true, -1); // Get some executable memory. char* memory = - reinterpret_cast(mmap(NULL, + reinterpret_cast(mmap(nullptr, kMemorySize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, @@ -689,12 +695,12 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryMinBound) { const pid_t child = fork(); if (child == 0) { close(fds[0]); - ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL, + ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), nullptr, DoneCallback, reinterpret_cast(fds[1]), true, -1); // Get some executable memory. char* memory = - reinterpret_cast(mmap(NULL, + reinterpret_cast(mmap(nullptr, kMemorySize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, @@ -780,12 +786,12 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryMaxBound) { const pid_t child = fork(); if (child == 0) { close(fds[0]); - ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL, + ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), nullptr, DoneCallback, reinterpret_cast(fds[1]), true, -1); // Get some executable memory. char* memory = - reinterpret_cast(mmap(NULL, + reinterpret_cast(mmap(nullptr, kMemorySize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, @@ -865,7 +871,7 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryNullPointer) { const pid_t child = fork(); if (child == 0) { close(fds[0]); - ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL, + ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), nullptr, DoneCallback, reinterpret_cast(fds[1]), true, -1); // Try calling a NULL pointer. @@ -873,7 +879,7 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryNullPointer) { // Volatile markings are needed to keep Clang from generating invalid // opcodes. See http://crbug.com/498354 for details. volatile void_function memory_function = - reinterpret_cast(NULL); + static_cast(nullptr); memory_function(); // not reached exit(1); @@ -941,7 +947,7 @@ TEST(ExceptionHandlerTest, ModuleInfo) { // Get some memory. char* memory = - reinterpret_cast(mmap(NULL, + reinterpret_cast(mmap(nullptr, kMemorySize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, @@ -952,7 +958,7 @@ TEST(ExceptionHandlerTest, ModuleInfo) { AutoTempDir temp_dir; ExceptionHandler handler( - MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1); + MinidumpDescriptor(temp_dir.path()), nullptr, nullptr, nullptr, true, -1); // Add info about the anonymous memory mapping. handler.AddMappingInfo(kMemoryName, @@ -1046,7 +1052,7 @@ TEST(ExceptionHandlerTest, ExternalDumper) { const pid_t child = fork(); if (child == 0) { close(fds[0]); - ExceptionHandler handler(MinidumpDescriptor("/tmp1"), NULL, NULL, + ExceptionHandler handler(MinidumpDescriptor("/tmp1"), nullptr, nullptr, reinterpret_cast(fds[1]), true, -1); handler.set_crash_handler(CrashHandler); DoNullPointerDereference(); @@ -1112,8 +1118,8 @@ TEST(ExceptionHandlerTest, ExternalDumper) { TEST(ExceptionHandlerTest, WriteMinidumpExceptionStream) { AutoTempDir temp_dir; - ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL, NULL, - NULL, false, -1); + ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), nullptr, + nullptr, nullptr, false, -1); ASSERT_TRUE(handler.WriteMinidump()); string minidump_path = handler.minidump_descriptor().path(); @@ -1133,7 +1139,8 @@ TEST(ExceptionHandlerTest, GenerateMultipleDumpsWithFD) { AutoTempDir temp_dir; string path; const int fd = CreateTMPFile(temp_dir.path(), &path); - ExceptionHandler handler(MinidumpDescriptor(fd), NULL, NULL, NULL, false, -1); + ExceptionHandler handler( + MinidumpDescriptor(fd), nullptr, nullptr, nullptr, false, -1); ASSERT_TRUE(handler.WriteMinidump()); // Check by the size of the data written to the FD that a minidump was // generated. @@ -1148,8 +1155,8 @@ TEST(ExceptionHandlerTest, GenerateMultipleDumpsWithFD) { TEST(ExceptionHandlerTest, GenerateMultipleDumpsWithPath) { AutoTempDir temp_dir; - ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), NULL, NULL, - NULL, false, -1); + ExceptionHandler handler(MinidumpDescriptor(temp_dir.path()), nullptr, + nullptr, nullptr, false, -1); ASSERT_TRUE(handler.WriteMinidump()); const MinidumpDescriptor& minidump_1 = handler.minidump_descriptor(); @@ -1193,7 +1200,7 @@ TEST(ExceptionHandlerTest, AdditionalMemory) { AutoTempDir temp_dir; ExceptionHandler handler( - MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1); + MinidumpDescriptor(temp_dir.path()), nullptr, nullptr, nullptr, true, -1); // Add the memory region to the list of memory to be included. handler.RegisterAppMemory(memory, kMemorySize); @@ -1232,7 +1239,7 @@ TEST(ExceptionHandlerTest, AdditionalMemoryRemove) { AutoTempDir temp_dir; ExceptionHandler handler( - MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1); + MinidumpDescriptor(temp_dir.path()), nullptr, nullptr, nullptr, true, -1); // Add the memory region to the list of memory to be included. handler.RegisterAppMemory(memory, kMemorySize); diff --git a/src/client/linux/handler/microdump_extra_info.h b/src/client/linux/handler/microdump_extra_info.h index 1da69d090..6418c1304 100644 --- a/src/client/linux/handler/microdump_extra_info.h +++ b/src/client/linux/handler/microdump_extra_info.h @@ -40,10 +40,10 @@ struct MicrodumpExtraInfo { const char* process_type; MicrodumpExtraInfo() - : build_fingerprint(NULL), - product_info(NULL), - gpu_fingerprint(NULL), - process_type(NULL) {} + : build_fingerprint(nullptr), + product_info(nullptr), + gpu_fingerprint(nullptr), + process_type(nullptr) {} }; } diff --git a/src/client/linux/handler/minidump_descriptor.cc b/src/client/linux/handler/minidump_descriptor.cc index db2f9b180..7b4c721f0 100644 --- a/src/client/linux/handler/minidump_descriptor.cc +++ b/src/client/linux/handler/minidump_descriptor.cc @@ -30,6 +30,7 @@ #include // Must come first #endif +#include #include #include "client/linux/handler/minidump_descriptor.h" @@ -46,7 +47,7 @@ MinidumpDescriptor::MinidumpDescriptor(const MinidumpDescriptor& descriptor) : mode_(descriptor.mode_), fd_(descriptor.fd_), directory_(descriptor.directory_), - c_path_(NULL), + c_path_(nullptr), size_limit_(descriptor.size_limit_), address_within_principal_mapping_( descriptor.address_within_principal_mapping_), @@ -70,7 +71,7 @@ MinidumpDescriptor& MinidumpDescriptor::operator=( path_.clear(); if (c_path_) { // This descriptor already had a path set, so generate a new one. - c_path_ = NULL; + c_path_ = nullptr; UpdatePath(); } size_limit_ = descriptor.size_limit_; diff --git a/src/client/linux/handler/minidump_descriptor.h b/src/client/linux/handler/minidump_descriptor.h index d822c9d92..72d119d9e 100644 --- a/src/client/linux/handler/minidump_descriptor.h +++ b/src/client/linux/handler/minidump_descriptor.h @@ -30,9 +30,9 @@ #define CLIENT_LINUX_HANDLER_MINIDUMP_DESCRIPTOR_H_ #include +#include #include -#include #include #include "client/linux/handler/microdump_extra_info.h" @@ -61,7 +61,7 @@ class MinidumpDescriptor { : mode_(kWriteMinidumpToFile), fd_(-1), directory_(directory), - c_path_(NULL), + c_path_(nullptr), size_limit_(-1), address_within_principal_mapping_(0), skip_dump_if_principal_mapping_not_referenced_(false), @@ -72,7 +72,7 @@ class MinidumpDescriptor { explicit MinidumpDescriptor(int fd) : mode_(kWriteMinidumpToFd), fd_(fd), - c_path_(NULL), + c_path_(nullptr), size_limit_(-1), address_within_principal_mapping_(0), skip_dump_if_principal_mapping_not_referenced_(false), diff --git a/src/client/linux/microdump_writer/microdump_writer.cc b/src/client/linux/microdump_writer/microdump_writer.cc index 93dae35e5..903a29d6e 100644 --- a/src/client/linux/microdump_writer/microdump_writer.cc +++ b/src/client/linux/microdump_writer/microdump_writer.cc @@ -35,6 +35,8 @@ #include "client/linux/microdump_writer/microdump_writer.h" +#include + #include #include @@ -140,9 +142,9 @@ class MicrodumpWriter { bool sanitize_stack, const MicrodumpExtraInfo& microdump_extra_info, LinuxDumper* dumper) - : ucontext_(context ? &context->context : NULL), + : ucontext_(context ? &context->context : nullptr), #if GOOGLE_BREAKPAD_CRASH_CONTEXT_HAS_FLOAT_STATE - float_state_(context ? &context->float_state : NULL), + float_state_(context ? &context->float_state : nullptr), #endif dumper_(dumper), mapping_list_(mappings), @@ -151,8 +153,8 @@ class MicrodumpWriter { address_within_principal_mapping_(address_within_principal_mapping), sanitize_stack_(sanitize_stack), microdump_extra_info_(microdump_extra_info), - log_line_(NULL), - stack_copy_(NULL), + log_line_(nullptr), + stack_copy_(nullptr), stack_len_(0), stack_lower_bound_(0), stack_pointer_(0) { @@ -603,7 +605,7 @@ class MicrodumpWriter { continue; } - DumpModule(mapping, true, i, NULL); + DumpModule(mapping, true, i, nullptr); } // Next write all the mappings provided by the caller for (MappingList::const_iterator iter = mapping_list_.begin(); @@ -654,7 +656,7 @@ bool WriteMicrodump(pid_t crashing_process, bool sanitize_stack, const MicrodumpExtraInfo& microdump_extra_info) { LinuxPtraceDumper dumper(crashing_process); - const ExceptionHandler::CrashContext* context = NULL; + const ExceptionHandler::CrashContext* context = nullptr; if (blob) { if (blob_size != sizeof(ExceptionHandler::CrashContext)) return false; diff --git a/src/client/linux/microdump_writer/microdump_writer_unittest.cc b/src/client/linux/microdump_writer/microdump_writer_unittest.cc index b1d570eb4..93172824c 100644 --- a/src/client/linux/microdump_writer/microdump_writer_unittest.cc +++ b/src/client/linux/microdump_writer/microdump_writer_unittest.cc @@ -46,7 +46,6 @@ #include "common/linux/breakpad_getcontext.h" #include "common/linux/eintr_wrapper.h" #include "common/linux/ignore_ret.h" -#include "common/scoped_ptr.h" #include "common/tests/auto_tempdir.h" #include "common/using_std_string.h" @@ -169,7 +168,8 @@ void ExtractMicrodumpStackContents(const string& microdump_content, result->reserve(result->size() + data.size() / 2); for (size_t i = 0; i < data.size(); i += 2) { std::string byte = data.substr(i, 2); - result->push_back(static_cast(strtoul(byte.c_str(), NULL, 16))); + result->push_back( + static_cast(strtoul(byte.c_str(), nullptr, 16))); } } } @@ -400,7 +400,7 @@ TEST(MicrodumpWriterTest, NoProductInfo) { MappingList no_mappings; const MicrodumpExtraInfo kMicrodumpExtraInfoNoProductInfo( - MakeMicrodumpExtraInfo(kBuildFingerprint, NULL, kGPUFingerprint)); + MakeMicrodumpExtraInfo(kBuildFingerprint, nullptr, kGPUFingerprint)); CrashAndGetMicrodump(no_mappings, kMicrodumpExtraInfoNoProductInfo, &buf); ASSERT_TRUE(ContainsMicrodump(buf)); @@ -415,7 +415,7 @@ TEST(MicrodumpWriterTest, NoGPUInfo) { MappingList no_mappings; const MicrodumpExtraInfo kMicrodumpExtraInfoNoGPUInfo( - MakeMicrodumpExtraInfo(kBuildFingerprint, kProductInfo, NULL)); + MakeMicrodumpExtraInfo(kBuildFingerprint, kProductInfo, nullptr)); CrashAndGetMicrodump(no_mappings, kMicrodumpExtraInfoNoGPUInfo, &buf); ASSERT_TRUE(ContainsMicrodump(buf)); diff --git a/src/client/linux/minidump_writer/cpu_set.h b/src/client/linux/minidump_writer/cpu_set.h index 70c1c7582..9023d3a5b 100644 --- a/src/client/linux/minidump_writer/cpu_set.h +++ b/src/client/linux/minidump_writer/cpu_set.h @@ -79,7 +79,7 @@ class CpuSet { size_t item_len = static_cast(p_end - p); const char* item_next = static_cast(my_memchr(p, ',', item_len)); - if (item_next != NULL) { + if (item_next != nullptr) { p = item_next + 1; item_len = static_cast(item_next - item); } else { diff --git a/src/client/linux/minidump_writer/directory_reader_unittest.cc b/src/client/linux/minidump_writer/directory_reader_unittest.cc index 708d586ed..975ace9e7 100644 --- a/src/client/linux/minidump_writer/directory_reader_unittest.cc +++ b/src/client/linux/minidump_writer/directory_reader_unittest.cc @@ -51,7 +51,7 @@ TEST(DirectoryReaderTest, CompareResults) { std::set dent_set; DIR* const dir = opendir("/proc/self"); - ASSERT_TRUE(dir != NULL); + ASSERT_TRUE(dir != nullptr); struct dirent* dent; while ((dent = readdir(dir))) diff --git a/src/client/linux/minidump_writer/linux_core_dumper_unittest.cc b/src/client/linux/minidump_writer/linux_core_dumper_unittest.cc index 72790422e..9ea064da9 100644 --- a/src/client/linux/minidump_writer/linux_core_dumper_unittest.cc +++ b/src/client/linux/minidump_writer/linux_core_dumper_unittest.cc @@ -64,9 +64,9 @@ TEST(LinuxCoreDumperTest, BuildProcPath) { EXPECT_TRUE(dumper.BuildProcPath(maps_path, pid, "maps")); EXPECT_STREQ(maps_path_expected, maps_path); - EXPECT_FALSE(dumper.BuildProcPath(NULL, pid, "maps")); + EXPECT_FALSE(dumper.BuildProcPath(nullptr, pid, "maps")); EXPECT_FALSE(dumper.BuildProcPath(maps_path, pid, "")); - EXPECT_FALSE(dumper.BuildProcPath(maps_path, pid, NULL)); + EXPECT_FALSE(dumper.BuildProcPath(maps_path, pid, nullptr)); char long_node[NAME_MAX]; size_t long_node_len = NAME_MAX - strlen(procfs_path) - 1; diff --git a/src/client/linux/minidump_writer/linux_dumper.cc b/src/client/linux/minidump_writer/linux_dumper.cc index 5c4c389c3..25cf19018 100644 --- a/src/client/linux/minidump_writer/linux_dumper.cc +++ b/src/client/linux/minidump_writer/linux_dumper.cc @@ -47,12 +47,17 @@ #include #include +#if defined(__CHROMEOS__) +#include +#endif // defined(__CHROMEOS__) + #include "client/linux/minidump_writer/line_reader.h" #include "common/linux/elfutils.h" #include "common/linux/file_id.h" #include "common/linux/linux_libc_support.h" #include "common/linux/memory_mapped_file.h" #include "common/linux/safe_readlink.h" +#include "common/memory_allocator.h" #include "google_breakpad/common/minidump_exception_linux.h" #include "third_party/lss/linux_syscall_support.h" @@ -329,7 +334,7 @@ LinuxDumper::ElfFileIdentifierForMapping(const MappingInfo& mapping, // Special-case linux-gate because it's not a real file. if (my_strcmp(mapping.name, kLinuxGateLibraryName) == 0) { - void* linux_gate = NULL; + void* linux_gate = nullptr; if (pid_ == sys_getpid()) { linux_gate = reinterpret_cast(mapping.start_addr); } else { @@ -488,7 +493,7 @@ void LinuxDumper::GetMappingEffectiveNameAndPath(const MappingInfo& mapping, // file_path := /path/to/libname.so // file_name := libname.so const char* basename = my_strrchr(file_path, '/'); - basename = basename == NULL ? file_path : (basename + 1); + basename = basename == nullptr ? file_path : (basename + 1); my_strlcpy(file_name, basename, file_name_size); return; } @@ -579,10 +584,10 @@ bool LinuxDumper::EnumerateMappings() { bool exec = (*(i2 + 3) == 'x'); const char* i3 = my_read_hex_ptr(&offset, i2 + 6 /* skip ' rwxp ' */); if (*i3 == ' ') { - const char* name = NULL; + const char* name = nullptr; // Only copy name if the name is a valid path name, or if // it's the VDSO image. - if (((name = my_strchr(line, '/')) == NULL) && + if (((name = my_strchr(line, '/')) == nullptr) && linux_gate_loc && reinterpret_cast(start_addr) == linux_gate_loc) { name = kLinuxGateLibraryName; @@ -615,7 +620,7 @@ bool LinuxDumper::EnumerateMappings() { module->size = end_addr - start_addr; module->offset = offset; module->exec = exec; - if (name != NULL) { + if (name != nullptr) { const unsigned l = my_strlen(name); if (l < sizeof(module->name)) my_memcpy(module->name, name, l); @@ -840,8 +845,7 @@ void LinuxDumper::SanitizeStackCopy(uint8_t* stack_copy, size_t stack_len, } // Zero memory that is below the current stack pointer. - const uintptr_t offset = - (sp_offset + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1); + const uintptr_t offset = PageAllocator::AlignUp(sp_offset, sizeof(uintptr_t)); if (offset) { my_memset(stack_copy, 0, offset); } @@ -891,8 +895,7 @@ bool LinuxDumper::StackHasPointerToMapping(const uint8_t* stack_copy, // aligned word in the target process. const uintptr_t low_addr = mapping.system_mapping_info.start_addr; const uintptr_t high_addr = mapping.system_mapping_info.end_addr; - const uintptr_t offset = - (sp_offset + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1); + const uintptr_t offset = PageAllocator::AlignUp(sp_offset, sizeof(uintptr_t)); for (const uint8_t* sp = stack_copy + offset; sp <= stack_copy + stack_len - sizeof(uintptr_t); @@ -915,7 +918,7 @@ const MappingInfo* LinuxDumper::FindMapping(const void* address) const { return mappings_[i]; } - return NULL; + return nullptr; } // Find the mapping which the given memory address falls in. Uses the @@ -928,7 +931,7 @@ const MappingInfo* LinuxDumper::FindMappingNoBias(uintptr_t address) const { return mappings_[i]; } } - return NULL; + return nullptr; } bool LinuxDumper::HandleDeletedFileInMapping(char* path) const { diff --git a/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc b/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc index 5a135fda0..fddfd3ca9 100644 --- a/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc +++ b/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc @@ -41,6 +41,7 @@ #include #include +#include "common/macros.h" #include "common/scoped_ptr.h" #include "third_party/lss/linux_syscall_support.h" @@ -68,12 +69,12 @@ void* thread_function(void* data) { uint8_t byte = 1; if (write(pipefd, &byte, sizeof(byte)) != sizeof(byte)) { perror("ERROR: parent notification failed"); - return NULL; + return nullptr; } register volatile pid_t* thread_id_ptr asm(TID_PTR_REGISTER) = thread_id; while (true) asm volatile ("" : : "r" (thread_id_ptr)); - return NULL; + unreachable(); } int main(int argc, char* argv[]) { diff --git a/src/client/linux/minidump_writer/linux_ptrace_dumper.cc b/src/client/linux/minidump_writer/linux_ptrace_dumper.cc index 2adc39e12..6d8b4cf92 100644 --- a/src/client/linux/minidump_writer/linux_ptrace_dumper.cc +++ b/src/client/linux/minidump_writer/linux_ptrace_dumper.cc @@ -59,22 +59,55 @@ #include "client/linux/minidump_writer/directory_reader.h" #include "client/linux/minidump_writer/line_reader.h" +#include "common/linux/eintr_wrapper.h" #include "common/linux/linux_libc_support.h" #include "third_party/lss/linux_syscall_support.h" +#if defined(__arm__) +/* + * https://elixir.bootlin.com/linux/v6.8-rc2/source/arch/arm/include/asm/user.h#L81 + * User specific VFP registers. If only VFPv2 is present, registers 16 to 31 + * are ignored by the ptrace system call and the signal handler. + */ +typedef struct { + unsigned long long fpregs[32]; + unsigned long fpscr; +// Kernel just appends fpscr to the copy of fpregs, so we need to force +// compiler to build the same layout. +} __attribute__((packed, aligned(4))) user_vfp_t; +#endif // defined(__arm__) + // Suspends a thread by attaching to it. static bool SuspendThread(pid_t pid) { // This may fail if the thread has just died or debugged. errno = 0; - if (sys_ptrace(PTRACE_ATTACH, pid, NULL, NULL) != 0 && + if (sys_ptrace(PTRACE_ATTACH, pid, nullptr, nullptr) != 0 && errno != 0) { return false; } - while (sys_waitpid(pid, NULL, __WALL) < 0) { - if (errno != EINTR) { - sys_ptrace(PTRACE_DETACH, pid, NULL, NULL); + while (true) { + int status; + int r = HANDLE_EINTR(sys_waitpid(pid, &status, __WALL)); + if (r < 0) { + sys_ptrace(PTRACE_DETACH, pid, nullptr, nullptr); return false; } + + if (!WIFSTOPPED(status)) + return false; + + // Any signal will stop the thread, make sure it is SIGSTOP. Otherwise, this + // signal will be delivered after PTRACE_DETACH, and the thread will enter + // the "T (stopped)" state. + if (WSTOPSIG(status) == SIGSTOP) + break; + + // Signals other than SIGSTOP that are received need to be reinjected, + // or they will otherwise get lost. + r = sys_ptrace(PTRACE_CONT, pid, nullptr, + reinterpret_cast(WSTOPSIG(status))); + if (r < 0) + return false; } #if defined(__i386) || defined(__x86_64) // On x86, the stack pointer is NULL or -1, when executing trusted code in @@ -85,14 +118,14 @@ static bool SuspendThread(pid_t pid) { // We thus test the stack pointer and exclude any threads that are part of // the seccomp sandbox's trusted code. user_regs_struct regs; - if (sys_ptrace(PTRACE_GETREGS, pid, NULL, ®s) == -1 || + if (sys_ptrace(PTRACE_GETREGS, pid, nullptr, ®s) == -1 || #if defined(__i386) !regs.esp #elif defined(__x86_64) !regs.rsp #endif ) { - sys_ptrace(PTRACE_DETACH, pid, NULL, NULL); + sys_ptrace(PTRACE_DETACH, pid, nullptr, nullptr); return false; } #endif @@ -101,7 +134,7 @@ static bool SuspendThread(pid_t pid) { // Resumes a thread by detaching from it. static bool ResumeThread(pid_t pid) { - return sys_ptrace(PTRACE_DETACH, pid, NULL, NULL) >= 0; + return sys_ptrace(PTRACE_DETACH, pid, nullptr, nullptr) >= 0; } namespace google_breakpad { @@ -152,6 +185,24 @@ bool LinuxPtraceDumper::CopyFromProcess(void* dest, pid_t child, return true; } +// This read VFP registers via either PTRACE_GETREGSET or PTRACE_GETREGS +#if defined(__arm__) +static bool ReadVFPRegistersArm32(pid_t tid, struct iovec* io) { +#ifdef PTRACE_GETREGSET + if (sys_ptrace(PTRACE_GETREGSET, tid, reinterpret_cast(NT_ARM_VFP), + io) == 0 && io->iov_len == sizeof(user_vfp_t)) { + return true; + } +#endif // PTRACE_GETREGSET +#ifdef PTRACE_GETVFPREGS + if (sys_ptrace(PTRACE_GETVFPREGS, tid, nullptr, io->iov_base) == 0) { + return true; + } +#endif // PTRACE_GETVFPREGS + return false; +} +#endif // defined(__arm__) + bool LinuxPtraceDumper::ReadRegisterSet(ThreadInfo* info, pid_t tid) { #ifdef PTRACE_GETREGSET @@ -163,7 +214,24 @@ bool LinuxPtraceDumper::ReadRegisterSet(ThreadInfo* info, pid_t tid) info->GetFloatingPointRegisters(&io.iov_base, &io.iov_len); if (sys_ptrace(PTRACE_GETREGSET, tid, (void*)NT_FPREGSET, (void*)&io) == -1) { - return false; + // We are going to check if we can read VFP registers on ARM32. + // Currently breakpad does not support VFP registers to be a part of minidump, + // so this is only to confirm that we can actually read FP registers. + // That is needed to prevent a false-positive minidumps failures with ARM32 + // binaries running on top of ARM64 Linux kernels. +#if defined(__arm__) + switch (errno) { + case EIO: + case EINVAL: + user_vfp_t vfp; + struct iovec io; + io.iov_base = &vfp; + io.iov_len = sizeof(vfp); + return ReadVFPRegistersArm32(tid, &io); + default: + return false; + } +#endif // defined(__arm__) } return true; #else @@ -174,8 +242,8 @@ bool LinuxPtraceDumper::ReadRegisterSet(ThreadInfo* info, pid_t tid) bool LinuxPtraceDumper::ReadRegisters(ThreadInfo* info, pid_t tid) { #ifdef PTRACE_GETREGS void* gp_addr; - info->GetGeneralPurposeRegisters(&gp_addr, NULL); - if (sys_ptrace(PTRACE_GETREGS, tid, NULL, gp_addr) == -1) { + info->GetGeneralPurposeRegisters(&gp_addr, nullptr); + if (sys_ptrace(PTRACE_GETREGS, tid, nullptr, gp_addr) == -1) { return false; } @@ -192,9 +260,26 @@ bool LinuxPtraceDumper::ReadRegisters(ThreadInfo* info, pid_t tid) { // aren't written to the cpu context anyway, so just don't get them here. // See http://crbug.com/508324 void* fp_addr; - info->GetFloatingPointRegisters(&fp_addr, NULL); - if (sys_ptrace(PTRACE_GETFPREGS, tid, NULL, fp_addr) == -1) { - return false; + info->GetFloatingPointRegisters(&fp_addr, nullptr); + if (sys_ptrace(PTRACE_GETFPREGS, tid, nullptr, fp_addr) == -1) { + // We are going to check if we can read VFP registers on ARM32. + // Currently breakpad does not support VFP registers to be a part of minidump, + // so this is only to confirm that we can actually read FP registers. + // That is needed to prevent a false-positive minidumps failures with ARM32 + // binaries running on top of ARM64 Linux kernels. +#if defined(__arm__) + switch (errno) { + case EIO: + case EINVAL: + user_vfp_t vfp; + struct iovec io; + io.iov_base = &vfp; + io.iov_len = sizeof(vfp); + return ReadVFPRegistersArm32(tid, &io); + default: + return false; + } +#endif // defined(__arm__) } #endif // !(defined(__ANDROID__) && defined(__ARM_EABI__)) #endif // !defined(__SOFTFP__) @@ -214,7 +299,7 @@ bool LinuxPtraceDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) { pid_t tid = threads_[index]; - assert(info != NULL); + assert(info != nullptr); char status_path[NAME_MAX]; if (!BuildProcPath(status_path, tid, "status")) return false; @@ -257,7 +342,7 @@ bool LinuxPtraceDumper::GetThreadInfoByIndex(size_t index, ThreadInfo* info) { int eax, ebx, ecx, edx; __cpuid(1, eax, ebx, ecx, edx); if (edx & bit_FXSAVE) { - if (sys_ptrace(PTRACE_GETFPXREGS, tid, NULL, &info->fpxregs) == -1) { + if (sys_ptrace(PTRACE_GETFPXREGS, tid, nullptr, &info->fpxregs) == -1) { return false; } } else { diff --git a/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc b/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc index 16a9daf1d..9dafa06c4 100644 --- a/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc +++ b/src/client/linux/minidump_writer/linux_ptrace_dumper_unittest.cc @@ -96,7 +96,7 @@ pid_t SetupChildProcess(int number_of_threads) { "linux_dumper_unittest_helper", pipe_fd_string, kNumberOfThreadsArgument, - NULL); + nullptr); // Kill if we get here. printf("Errno from exec: %d", errno); std::string err_str = "Exec of " + helper_path + " failed"; @@ -197,7 +197,7 @@ TEST_F(LinuxPtraceDumperChildTest, FindMappings) { ASSERT_TRUE(dumper.FindMapping(reinterpret_cast(getpid))); ASSERT_TRUE(dumper.FindMapping(reinterpret_cast(printf))); - ASSERT_FALSE(dumper.FindMapping(NULL)); + ASSERT_FALSE(dumper.FindMapping(nullptr)); } TEST_F(LinuxPtraceDumperChildTest, ThreadList) { @@ -220,7 +220,7 @@ TEST_F(LinuxPtraceDumperChildTest, ThreadList) { class StackHelper { public: StackHelper() - : fd_(-1), mapping_(NULL), size_(0) {} + : fd_(-1), mapping_(nullptr), size_(0) {} ~StackHelper() { if (size_) munmap(mapping_, size_); @@ -266,7 +266,7 @@ void LinuxPtraceDumperMappingsTest::SetUp() { ASSERT_NE(-1, fd) << "Failed to open file: " << helper_path_ << ", Error: " << strerror(errno); char* mapping = - reinterpret_cast(mmap(NULL, + reinterpret_cast(mmap(nullptr, kMappingSize, PROT_READ, MAP_SHARED, @@ -323,10 +323,10 @@ TEST_F(LinuxPtraceDumperChildTest, BuildProcPath) { EXPECT_TRUE(dumper.BuildProcPath(maps_path, pid, "maps")); EXPECT_STREQ(maps_path_expected, maps_path); - EXPECT_FALSE(dumper.BuildProcPath(NULL, pid, "maps")); + EXPECT_FALSE(dumper.BuildProcPath(nullptr, pid, "maps")); EXPECT_FALSE(dumper.BuildProcPath(maps_path, 0, "maps")); EXPECT_FALSE(dumper.BuildProcPath(maps_path, pid, "")); - EXPECT_FALSE(dumper.BuildProcPath(maps_path, pid, NULL)); + EXPECT_FALSE(dumper.BuildProcPath(maps_path, pid, nullptr)); char long_node[NAME_MAX]; size_t long_node_len = NAME_MAX - strlen("/proc/123") - 1; diff --git a/src/client/linux/minidump_writer/minidump_writer.cc b/src/client/linux/minidump_writer/minidump_writer.cc index a95dd2548..06113954f 100644 --- a/src/client/linux/minidump_writer/minidump_writer.cc +++ b/src/client/linux/minidump_writer/minidump_writer.cc @@ -50,6 +50,7 @@ #include "client/linux/minidump_writer/minidump_writer.h" #include "client/minidump_file_writer-inl.h" +#include #include #include #include @@ -143,9 +144,9 @@ class MinidumpWriter { LinuxDumper* dumper) : fd_(minidump_fd), path_(minidump_path), - ucontext_(context ? &context->context : NULL), + ucontext_(context ? &context->context : nullptr), #if GOOGLE_BREAKPAD_CRASH_CONTEXT_HAS_FLOAT_STATE - float_state_(context ? &context->float_state : NULL), + float_state_(context ? &context->float_state : nullptr), #endif dumper_(dumper), minidump_size_limit_(-1), @@ -245,7 +246,7 @@ class MinidumpWriter { header.get()->signature = MD_HEADER_SIGNATURE; header.get()->version = MD_HEADER_VERSION; - header.get()->time_date_stamp = time(NULL); + header.get()->time_date_stamp = time(nullptr); header.get()->stream_count = kNumWriters; header.get()->stream_directory_rva = dir.position(); } @@ -325,7 +326,7 @@ class MinidumpWriter { bool FillThreadStack(MDRawThread* thread, uintptr_t stack_pointer, uintptr_t pc, int max_stack_len, uint8_t** stack_copy) { - *stack_copy = NULL; + *stack_copy = nullptr; const void* stack; size_t stack_len; @@ -610,7 +611,7 @@ class MinidumpWriter { continue; MDRawModule mod; - if (!FillRawModule(mapping, true, i, &mod, NULL)) + if (!FillRawModule(mapping, true, i, &mod, nullptr)) return false; list.CopyIndexAfterObject(j++, &mod, MD_MODULE_SIZE); } @@ -829,7 +830,7 @@ class MinidumpWriter { // The dynamic linker makes information available that helps gdb find all // DSOs loaded into the program. If this information is indeed available, // dump it to a MD_LINUX_DSO_DEBUG stream. - struct r_debug* r_debug = NULL; + struct r_debug* r_debug = nullptr; uint32_t dynamic_length = 0; for (int i = 0; ; ++i) { @@ -1330,7 +1331,7 @@ class MinidumpWriter { size_t len; uint8_t data[kBufSize]; }* buffers = reinterpret_cast(Alloc(sizeof(Buffers))); - buffers->next = NULL; + buffers->next = nullptr; buffers->len = 0; size_t total = 0; @@ -1348,7 +1349,7 @@ class MinidumpWriter { if (bufptr->len == kBufSize) { bufptr->next = reinterpret_cast(Alloc(sizeof(Buffers))); bufptr = bufptr->next; - bufptr->next = NULL; + bufptr->next = nullptr; bufptr->len = 0; } } @@ -1367,7 +1368,7 @@ class MinidumpWriter { // zero bytes being read after the final buffer was just allocated. if (buffers->len == 0) { // This can only occur with final buffer. - assert(buffers->next == NULL); + assert(buffers->next == nullptr); continue; } memory.Copy(pos, &buffers->data, buffers->len); @@ -1396,7 +1397,7 @@ class MinidumpWriter { uts.release, uts.version, uts.machine, - NULL + nullptr }; bool first_item = true; for (const char** cur_info = info_table; *cur_info; cur_info++) { @@ -1477,7 +1478,7 @@ bool WriteMinidumpImpl(const char* minidump_path, uintptr_t principal_mapping_address, bool sanitize_stacks) { LinuxPtraceDumper dumper(crashing_process); - const ExceptionHandler::CrashContext* context = NULL; + const ExceptionHandler::CrashContext* context = nullptr; if (blob) { if (blob_size != sizeof(ExceptionHandler::CrashContext)) return false; @@ -1517,7 +1518,7 @@ bool WriteMinidump(int minidump_fd, pid_t crashing_process, bool skip_stacks_if_mapping_unreferenced, uintptr_t principal_mapping_address, bool sanitize_stacks) { - return WriteMinidumpImpl(NULL, minidump_fd, -1, + return WriteMinidumpImpl(nullptr, minidump_fd, -1, crashing_process, blob, blob_size, MappingList(), AppMemoryList(), skip_stacks_if_mapping_unreferenced, @@ -1533,7 +1534,7 @@ bool WriteMinidump(const char* minidump_path, pid_t process, dumper.set_crash_thread(process_blamed_thread); MappingList mapping_list; AppMemoryList app_memory_list; - MinidumpWriter writer(minidump_path, -1, NULL, mapping_list, + MinidumpWriter writer(minidump_path, -1, nullptr, mapping_list, app_memory_list, false, 0, false, &dumper); if (!writer.Init()) return false; @@ -1562,7 +1563,7 @@ bool WriteMinidump(int minidump_fd, pid_t crashing_process, bool skip_stacks_if_mapping_unreferenced, uintptr_t principal_mapping_address, bool sanitize_stacks) { - return WriteMinidumpImpl(NULL, minidump_fd, -1, crashing_process, + return WriteMinidumpImpl(nullptr, minidump_fd, -1, crashing_process, blob, blob_size, mappings, appmem, skip_stacks_if_mapping_unreferenced, @@ -1594,7 +1595,7 @@ bool WriteMinidump(int minidump_fd, off_t minidump_size_limit, bool skip_stacks_if_mapping_unreferenced, uintptr_t principal_mapping_address, bool sanitize_stacks) { - return WriteMinidumpImpl(NULL, minidump_fd, minidump_size_limit, + return WriteMinidumpImpl(nullptr, minidump_fd, minidump_size_limit, crashing_process, blob, blob_size, mappings, appmem, skip_stacks_if_mapping_unreferenced, @@ -1606,7 +1607,7 @@ bool WriteMinidump(const char* filename, const MappingList& mappings, const AppMemoryList& appmem, LinuxDumper* dumper) { - MinidumpWriter writer(filename, -1, NULL, mappings, appmem, + MinidumpWriter writer(filename, -1, nullptr, mappings, appmem, false, 0, false, dumper); if (!writer.Init()) return false; diff --git a/src/client/linux/minidump_writer/minidump_writer_unittest.cc b/src/client/linux/minidump_writer/minidump_writer_unittest.cc index effedc5e1..3b1b3b4b6 100644 --- a/src/client/linux/minidump_writer/minidump_writer_unittest.cc +++ b/src/client/linux/minidump_writer/minidump_writer_unittest.cc @@ -145,7 +145,7 @@ TEST(MinidumpWriterTest, MappingInfo) { // Get some memory. char* memory = - reinterpret_cast(mmap(NULL, + reinterpret_cast(mmap(nullptr, memory_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, @@ -450,7 +450,7 @@ TEST(MinidumpWriterTest, MappingInfoContained) { lseek(fd, 0, SEEK_SET); char* memory = - reinterpret_cast(mmap(NULL, + reinterpret_cast(mmap(nullptr, memory_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, @@ -545,7 +545,7 @@ TEST(MinidumpWriterTest, DeletedBinary) { binpath.c_str(), pipe_fd_string, kNumberOfThreadsArgument.c_str(), - NULL); + nullptr); } close(fds[1]); // Wait for the child process to signal that it's ready. @@ -748,9 +748,9 @@ TEST(MinidumpWriterTest, InvalidStackPointer) { bool found_empty_stack = false; for (int i = 0; i < dump_thread_list->thread_count(); i++) { MinidumpThread* thread = dump_thread_list->GetThreadAtIndex(i); - ASSERT_TRUE(thread->thread() != NULL); + ASSERT_TRUE(thread->thread() != nullptr); // When the stack size is zero bytes, GetMemory() returns NULL. - if (thread->GetMemory() == NULL) { + if (thread->GetMemory() == nullptr) { found_empty_stack = true; break; } @@ -792,7 +792,7 @@ TEST(MinidumpWriterTest, MinidumpSizeLimit) { helper_path.c_str(), pipe_fd_string, number_of_threads_arg, - NULL); + nullptr); } close(fds[1]); @@ -829,7 +829,7 @@ TEST(MinidumpWriterTest, MinidumpSizeLimit) { string normal_dump = temp_dir.path() + "/minidump-writer-unittest.dmp"; ASSERT_TRUE(WriteMinidump(normal_dump.c_str(), -1, - child_pid, NULL, 0, + child_pid, nullptr, 0, MappingList(), AppMemoryList())); struct stat st; ASSERT_EQ(0, stat(normal_dump.c_str(), &st)); @@ -842,10 +842,10 @@ TEST(MinidumpWriterTest, MinidumpSizeLimit) { ASSERT_TRUE(dump_thread_list); for (unsigned int i = 0; i < dump_thread_list->thread_count(); i++) { MinidumpThread* thread = dump_thread_list->GetThreadAtIndex(i); - ASSERT_TRUE(thread->thread() != NULL); + ASSERT_TRUE(thread->thread() != nullptr); // When the stack size is zero bytes, GetMemory() returns NULL. MinidumpMemoryRegion* memory = thread->GetMemory(); - ASSERT_TRUE(memory != NULL); + ASSERT_TRUE(memory != nullptr); total_normal_stack_size += memory->GetSize(); } } @@ -860,7 +860,7 @@ TEST(MinidumpWriterTest, MinidumpSizeLimit) { string same_dump = temp_dir.path() + "/minidump-writer-unittest-same.dmp"; ASSERT_TRUE(WriteMinidump(same_dump.c_str(), minidump_size_limit, - child_pid, NULL, 0, + child_pid, nullptr, 0, MappingList(), AppMemoryList())); struct stat st; ASSERT_EQ(0, stat(same_dump.c_str(), &st)); @@ -893,7 +893,7 @@ TEST(MinidumpWriterTest, MinidumpSizeLimit) { string limit_dump = temp_dir.path() + "/minidump-writer-unittest-limit.dmp"; ASSERT_TRUE(WriteMinidump(limit_dump.c_str(), minidump_size_limit, - child_pid, NULL, 0, + child_pid, nullptr, 0, MappingList(), AppMemoryList())); struct stat st; ASSERT_EQ(0, stat(limit_dump.c_str(), &st)); @@ -910,10 +910,10 @@ TEST(MinidumpWriterTest, MinidumpSizeLimit) { int total_limit_stack_size = 0; for (unsigned int i = 0; i < dump_thread_list->thread_count(); i++) { MinidumpThread* thread = dump_thread_list->GetThreadAtIndex(i); - ASSERT_TRUE(thread->thread() != NULL); + ASSERT_TRUE(thread->thread() != nullptr); // When the stack size is zero bytes, GetMemory() returns NULL. MinidumpMemoryRegion* memory = thread->GetMemory(); - ASSERT_TRUE(memory != NULL); + ASSERT_TRUE(memory != nullptr); total_limit_stack_size += memory->GetSize(); } diff --git a/src/client/linux/minidump_writer/pe_structs.h b/src/client/linux/minidump_writer/pe_structs.h index 122cc2956..017ac0619 100644 --- a/src/client/linux/minidump_writer/pe_structs.h +++ b/src/client/linux/minidump_writer/pe_structs.h @@ -29,7 +29,7 @@ #ifndef CLIENT_LINUX_MINIDUMP_WRITER_PE_STRUCTS_H_ #define CLIENT_LINUX_MINIDUMP_WRITER_PE_STRUCTS_H_ -#include +#include namespace google_breakpad { @@ -222,4 +222,4 @@ typedef struct _RSDS_DEBUG_FORMAT { } // namespace google_breakpad -#endif // CLIENT_LINUX_MINIDUMP_WRITER_PE_STRUCTS_H_ \ No newline at end of file +#endif // CLIENT_LINUX_MINIDUMP_WRITER_PE_STRUCTS_H_ diff --git a/src/client/linux/minidump_writer/proc_cpuinfo_reader.h b/src/client/linux/minidump_writer/proc_cpuinfo_reader.h index 5ae16dfbc..5ba1bafa6 100644 --- a/src/client/linux/minidump_writer/proc_cpuinfo_reader.h +++ b/src/client/linux/minidump_writer/proc_cpuinfo_reader.h @@ -74,7 +74,7 @@ class ProcCpuInfoReader { // - can contain spaces. // - some fields have an empty char* sep = static_cast(my_memchr(line, ':', line_len)); - if (sep == NULL) + if (sep == nullptr) continue; // Record the value. Skip leading space after the column to get diff --git a/src/client/linux/sender/google_crash_report_sender.cc b/src/client/linux/sender/google_crash_report_sender.cc index f6e481939..2fa6a2b41 100644 --- a/src/client/linux/sender/google_crash_report_sender.cc +++ b/src/client/linux/sender/google_crash_report_sender.cc @@ -104,5 +104,5 @@ int main(int argc, char* argv[]) { FLAGS_crash_server, FLAGS_proxy_host, FLAGS_proxy_userpasswd); - g.Upload(NULL, NULL, NULL); + g.Upload(nullptr, nullptr, nullptr); } diff --git a/src/client/mac/crash_generation/Inspector.mm b/src/client/mac/crash_generation/Inspector.mm index 8d4e3e98b..4c0a78062 100644 --- a/src/client/mac/crash_generation/Inspector.mm +++ b/src/client/mac/crash_generation/Inspector.mm @@ -28,26 +28,23 @@ // // Utility that can inspect another process and write a crash dump -#include -#include +#import "client/mac/crash_generation/Inspector.h" + +#import #include #include #include -#include -#import "client/mac/crash_generation/Inspector.h" +#include +#include +#import "GTMDefines.h" #import "client/mac/Framework/Breakpad.h" #import "client/mac/handler/minidump_generator.h" - #import "common/mac/MachIPC.h" #include "common/mac/bootstrap_compat.h" #include "common/mac/launch_reporter.h" -#import "GTMDefines.h" - -#import - namespace google_breakpad { //============================================================================= @@ -358,4 +355,3 @@ } } // namespace google_breakpad - diff --git a/src/client/mac/crash_generation/crash_generation_server.cc b/src/client/mac/crash_generation/crash_generation_server.cc index 8d742f361..f099dd4c5 100644 --- a/src/client/mac/crash_generation/crash_generation_server.cc +++ b/src/client/mac/crash_generation/crash_generation_server.cc @@ -69,7 +69,7 @@ CrashGenerationServer::~CrashGenerationServer() { } bool CrashGenerationServer::Start() { - int thread_create_result = pthread_create(&server_thread_, NULL, + int thread_create_result = pthread_create(&server_thread_, nullptr, &WaitForMessages, this); started_ = thread_create_result == 0; return started_; @@ -85,7 +85,7 @@ bool CrashGenerationServer::Stop() { const mach_msg_timeout_t kSendTimeoutMs = 2 * 1000; kern_return_t result = sender.SendMessage(quit_message, kSendTimeoutMs); if (result == KERN_SUCCESS) { - int thread_join_result = pthread_join(server_thread_, NULL); + int thread_join_result = pthread_join(server_thread_, nullptr); started_ = thread_join_result != 0; } @@ -97,7 +97,7 @@ void* CrashGenerationServer::WaitForMessages(void* server) { CrashGenerationServer* self = reinterpret_cast(server); while (self->WaitForOneMessage()) {} - return NULL; + return nullptr; } bool CrashGenerationServer::WaitForOneMessage() { @@ -123,7 +123,7 @@ bool CrashGenerationServer::WaitForOneMessage() { ScopedTaskSuspend suspend(remote_task); MinidumpGenerator generator(remote_task, handler_thread); - dump_path = generator.UniqueNameInDirectory(dump_dir_, NULL); + dump_path = generator.UniqueNameInDirectory(dump_dir_, nullptr); if (info.exception_type && info.exception_code) { generator.SetExceptionInformation(info.exception_type, diff --git a/src/client/mac/handler/breakpad_nlist_64.cc b/src/client/mac/handler/breakpad_nlist_64.cc index d59c7b080..fcf09baef 100644 --- a/src/client/mac/handler/breakpad_nlist_64.cc +++ b/src/client/mac/handler/breakpad_nlist_64.cc @@ -221,7 +221,7 @@ int __breakpad_fdnlist(int fd, nlist_type* list, const char** symbolNames, /* Read in the fat archs */ struct fat_arch* fat_archs = (struct fat_arch*)malloc(fh.nfat_arch * sizeof(struct fat_arch)); - if (fat_archs == NULL) { + if (fat_archs == nullptr) { return -1; } if (read(fd, (char*)fat_archs, @@ -248,7 +248,7 @@ int __breakpad_fdnlist(int fd, nlist_type* list, const char** symbolNames, CFSwapInt32BigToHost(fat_archs[i].align); } - struct fat_arch* fap = NULL; + struct fat_arch* fap = nullptr; for (unsigned i = 0; i < fh.nfat_arch; i++) { if (fat_archs[i].cputype == cpu_type) { fap = &fat_archs[i]; @@ -286,7 +286,7 @@ int __breakpad_fdnlist(int fd, nlist_type* list, const char** symbolNames, struct load_command* load_commands = (struct load_command*)malloc(mh.sizeofcmds); - if (load_commands == NULL) { + if (load_commands == nullptr) { return -1; } if (read(fd, (char*)load_commands, mh.sizeofcmds) != @@ -294,7 +294,7 @@ int __breakpad_fdnlist(int fd, nlist_type* list, const char** symbolNames, free(load_commands); return -1; } - struct symtab_command* stp = NULL; + struct symtab_command* stp = nullptr; struct load_command* lcp = load_commands; // iterate through all load commands, looking for // LC_SYMTAB load command @@ -315,7 +315,7 @@ int __breakpad_fdnlist(int fd, nlist_type* list, const char** symbolNames, } lcp = (struct load_command*)((char*)lcp + lcp->cmdsize); } - if (stp == NULL) { + if (stp == nullptr) { free(load_commands); return -1; } diff --git a/src/client/mac/handler/dynamic_images.cc b/src/client/mac/handler/dynamic_images.cc index 3db7467bf..3bee00b47 100644 --- a/src/client/mac/handler/dynamic_images.cc +++ b/src/client/mac/handler/dynamic_images.cc @@ -51,6 +51,7 @@ extern "C" { // needed to compile on Leopard #include #include "breakpad_nlist_64.h" +#include "common/memory_allocator.h" #if !TARGET_OS_IPHONE #include @@ -192,7 +193,7 @@ kern_return_t ReadTaskMemory(task_port_t target_task, mach_vm_address_t page_address = address & (-systemPageSize); mach_vm_address_t last_page_address = - (address + length + (systemPageSize - 1)) & (-systemPageSize); + PageAllocator::AlignUp(address + length, systemPageSize); mach_vm_size_t page_size = last_page_address - page_address; uint8_t* local_start; @@ -532,7 +533,7 @@ DynamicImage* DynamicImages::GetExecutableImage() { return GetImage(executable_index); } - return NULL; + return nullptr; } //============================================================================== diff --git a/src/client/mac/handler/dynamic_images.h b/src/client/mac/handler/dynamic_images.h index b5af75848..68a506956 100644 --- a/src/client/mac/handler/dynamic_images.h +++ b/src/client/mac/handler/dynamic_images.h @@ -110,7 +110,7 @@ class DynamicImage { DynamicImage(uint8_t* header, // data is copied size_t header_size, // includes load commands uint64_t load_address, - string file_path, + const string& file_path, uintptr_t image_mod_date, mach_port_t task, cpu_type_t cpu_type) @@ -254,7 +254,7 @@ class DynamicImages { if (i < (int)image_list_.size()) { return image_list_[i]; } - return NULL; + return nullptr; } // Returns the image corresponding to the main executable. diff --git a/src/client/mac/handler/exception_handler.cc b/src/client/mac/handler/exception_handler.cc index 63a42d9ed..5fe626e9d 100644 --- a/src/client/mac/handler/exception_handler.cc +++ b/src/client/mac/handler/exception_handler.cc @@ -30,6 +30,7 @@ #include // Must come first #endif +#include #include #include #include @@ -37,11 +38,13 @@ #include #include +#include #include "client/mac/handler/exception_handler.h" #include "client/mac/handler/minidump_generator.h" #include "common/mac/macho_utilities.h" #include "common/mac/scoped_task_suspend-inl.h" +#include "common/macros.h" #include "google_breakpad/common/minidump_exception_mac.h" #ifndef __EXCEPTIONS @@ -233,10 +236,10 @@ ExceptionHandler::ExceptionHandler(const string& dump_path, filter_(filter), callback_(callback), callback_context_(callback_context), - directCallback_(NULL), - handler_thread_(NULL), + directCallback_(nullptr), + handler_thread_(nullptr), handler_port_(MACH_PORT_NULL), - previous_(NULL), + previous_(nullptr), installed_exception_handler_(false), is_in_teardown_(false), last_minidump_write_result_(false), @@ -257,13 +260,13 @@ ExceptionHandler::ExceptionHandler(DirectCallback callback, void* callback_context, bool install_handler) : dump_path_(), - filter_(NULL), - callback_(NULL), + filter_(nullptr), + callback_(nullptr), callback_context_(callback_context), directCallback_(callback), - handler_thread_(NULL), + handler_thread_(nullptr), handler_port_(MACH_PORT_NULL), - previous_(NULL), + previous_(nullptr), installed_exception_handler_(false), is_in_teardown_(false), last_minidump_write_result_(false), @@ -311,8 +314,8 @@ bool ExceptionHandler::WriteMinidump(const string& dump_path, bool write_exception_stream, MinidumpCallback callback, void* callback_context) { - ExceptionHandler handler(dump_path, NULL, callback, callback_context, false, - NULL); + ExceptionHandler handler(dump_path, nullptr, callback, callback_context, + false, nullptr); return handler.WriteMinidump(write_exception_stream); } @@ -537,7 +540,7 @@ void* ExceptionHandler::WaitForMessage(void* exception_handler_class) { // Don't touch self, since this message could have been sent // from its destructor. if (receive.header.msgh_id == kShutdownMessage) - return NULL; + return nullptr; self->SuspendThreads(); @@ -566,7 +569,7 @@ void* ExceptionHandler::WaitForMessage(void* exception_handler_class) { // Write out the dump and save the result for later retrieval self->last_minidump_write_result_ = self->WriteMinidumpWithException(exception_type, exception_code, - 0, NULL, thread, + 0, nullptr, thread, false, false); #if USE_PROTECTED_ALLOCATIONS @@ -601,7 +604,7 @@ void* ExceptionHandler::WaitForMessage(void* exception_handler_class) { // Generate the minidump with the exception data. self->WriteMinidumpWithException(receive.exception, receive.code[0], - subcode, NULL, receive.thread.name, + subcode, nullptr, receive.thread.name, true, false); #if USE_PROTECTED_ALLOCATIONS @@ -634,7 +637,7 @@ void* ExceptionHandler::WaitForMessage(void* exception_handler_class) { } } - return NULL; + unreachable(); } // static @@ -659,7 +662,7 @@ void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) { bool ExceptionHandler::InstallHandler() { // If a handler is already installed, something is really wrong. - if (gProtectedData.handler != NULL) { + if (gProtectedData.handler != nullptr) { return false; } if (!IsOutOfProcess()) { @@ -670,7 +673,7 @@ bool ExceptionHandler::InstallHandler() { sa.sa_sigaction = ExceptionHandler::SignalHandler; sa.sa_flags = SA_SIGINFO; - scoped_ptr old(new struct sigaction); + std::unique_ptr old(new struct sigaction); if (sigaction(SIGABRT, &sa, old.get()) == -1) { return false; } @@ -720,13 +723,13 @@ bool ExceptionHandler::UninstallHandler(bool in_exception) { kern_return_t result = KERN_SUCCESS; if (old_handler_.get()) { - sigaction(SIGABRT, old_handler_.get(), NULL); + sigaction(SIGABRT, old_handler_.get(), nullptr); #if USE_PROTECTED_ALLOCATIONS mprotect(gProtectedData.protected_buffer, PAGE_SIZE, PROT_READ | PROT_WRITE); #endif old_handler_.reset(); - gProtectedData.handler = NULL; + gProtectedData.handler = nullptr; } if (installed_exception_handler_) { @@ -751,7 +754,7 @@ bool ExceptionHandler::UninstallHandler(bool in_exception) { #endif } - previous_ = NULL; + previous_ = nullptr; installed_exception_handler_ = false; } @@ -759,7 +762,7 @@ bool ExceptionHandler::UninstallHandler(bool in_exception) { } bool ExceptionHandler::Setup(bool install_handler) { - if (pthread_mutex_init(&minidump_write_mutex_, NULL)) + if (pthread_mutex_init(&minidump_write_mutex_, nullptr)) return false; // Create a receive right @@ -807,7 +810,7 @@ bool ExceptionHandler::Teardown() { return false; } - handler_thread_ = NULL; + handler_thread_ = nullptr; handler_port_ = MACH_PORT_NULL; pthread_mutex_destroy(&minidump_write_mutex_); diff --git a/src/client/mac/handler/exception_handler.h b/src/client/mac/handler/exception_handler.h index e39042dc9..f4d286a7f 100644 --- a/src/client/mac/handler/exception_handler.h +++ b/src/client/mac/handler/exception_handler.h @@ -38,10 +38,10 @@ #include #include +#include #include #include "client/mac/handler/ucontext_compat.h" -#include "common/scoped_ptr.h" #if !TARGET_OS_IPHONE #include "client/mac/crash_generation/crash_generation_client.h" @@ -175,7 +175,7 @@ class ExceptionHandler { #if TARGET_OS_IPHONE return false; #else - return crash_generation_client_.get() != NULL; + return crash_generation_client_.get() != nullptr; #endif } @@ -283,11 +283,11 @@ class ExceptionHandler { // Old signal handler for SIGABRT. Used to be able to restore it when // uninstalling. - scoped_ptr old_handler_; + std::unique_ptr old_handler_; #if !TARGET_OS_IPHONE // Client for out-of-process dump generation. - scoped_ptr crash_generation_client_; + std::unique_ptr crash_generation_client_; #endif }; diff --git a/src/client/mac/handler/minidump_generator.cc b/src/client/mac/handler/minidump_generator.cc index 7737778e5..f55e2ca42 100644 --- a/src/client/mac/handler/minidump_generator.cc +++ b/src/client/mac/handler/minidump_generator.cc @@ -30,20 +30,20 @@ #include // Must come first #endif -#include -#include +#include "client/mac/handler/minidump_generator.h" +#include +#include +#include +#include #include #include #include -#include -#include -#include +#include #include +#include -#include - -#include "client/mac/handler/minidump_generator.h" +#include #if defined(HAS_ARM_SUPPORT) || defined(HAS_ARM64_SUPPORT) #include @@ -83,8 +83,8 @@ MinidumpGenerator::MinidumpGenerator() crashing_task_(mach_task_self()), handler_thread_(mach_thread_self()), cpu_type_(DynamicImages::GetNativeCPUType()), - task_context_(NULL), - dynamic_images_(NULL), + task_context_(nullptr), + dynamic_images_(nullptr), memory_blocks_(&allocator_) { GatherSystemInformation(); } @@ -101,14 +101,14 @@ MinidumpGenerator::MinidumpGenerator(mach_port_t crashing_task, crashing_task_(crashing_task), handler_thread_(handler_thread), cpu_type_(DynamicImages::GetNativeCPUType()), - task_context_(NULL), - dynamic_images_(NULL), + task_context_(nullptr), + dynamic_images_(nullptr), memory_blocks_(&allocator_) { if (crashing_task != mach_task_self()) { dynamic_images_ = new DynamicImages(crashing_task_); cpu_type_ = dynamic_images_->GetCPUType(); } else { - dynamic_images_ = NULL; + dynamic_images_ = nullptr; cpu_type_ = DynamicImages::GetNativeCPUType(); } @@ -134,11 +134,11 @@ void MinidumpGenerator::GatherSystemInformation() { CFStringRef vers_path = CFSTR("/System/Library/CoreServices/SystemVersion.plist"); CFURLRef sys_vers = - CFURLCreateWithFileSystemPath(NULL, + CFURLCreateWithFileSystemPath(nullptr, vers_path, kCFURLPOSIXPathStyle, false); - CFReadStreamRef read_stream = CFReadStreamCreateWithFile(NULL, sys_vers); + CFReadStreamRef read_stream = CFReadStreamCreateWithFile(nullptr, sys_vers); CFRelease(sys_vers); if (!read_stream) { return; @@ -147,7 +147,7 @@ void MinidumpGenerator::GatherSystemInformation() { CFRelease(read_stream); return; } - CFMutableDataRef data = NULL; + CFMutableDataRef data = nullptr; while (true) { // Actual data file tests: Mac at 480 bytes and iOS at 413 bytes. const CFIndex kMaxBufferLength = 1024; @@ -157,13 +157,13 @@ void MinidumpGenerator::GatherSystemInformation() { if (num_bytes_read < 0) { if (data) { CFRelease(data); - data = NULL; + data = nullptr; } break; } else if (num_bytes_read == 0) { break; } else if (!data) { - data = CFDataCreateMutable(NULL, 0); + data = CFDataCreateMutable(nullptr, 0); } CFDataAppendBytes(data, data_bytes, num_bytes_read); } @@ -174,7 +174,7 @@ void MinidumpGenerator::GatherSystemInformation() { } CFDictionaryRef list = static_cast(CFPropertyListCreateWithData( - NULL, data, kCFPropertyListImmutable, NULL, NULL)); + nullptr, data, kCFPropertyListImmutable, nullptr, nullptr)); CFRelease(data); if (!list) { return; @@ -254,8 +254,8 @@ bool MinidumpGenerator::GetThreadContext(mach_port_t thread_id, breakpad_ucontex string MinidumpGenerator::UniqueNameInDirectory(const string& dir, string* unique_name) { - CFUUIDRef uuid = CFUUIDCreate(NULL); - CFStringRef uuid_cfstr = CFUUIDCreateString(NULL, uuid); + CFUUIDRef uuid = CFUUIDCreate(nullptr); + CFStringRef uuid_cfstr = CFUUIDCreateString(nullptr, uuid); CFRelease(uuid); string file_name(ConvertToString(uuid_cfstr)); CFRelease(uuid_cfstr); @@ -1133,9 +1133,8 @@ bool MinidumpGenerator::WriteMemoryListStream( ip_memory_d.start_of_memory_range = std::max(uintptr_t(addr), uintptr_t(ip - (kIPMemorySize / 2))); - uintptr_t end_of_range = - std::min(uintptr_t(ip + (kIPMemorySize / 2)), - uintptr_t(addr + size)); + uintptr_t end_of_range = std::min(uintptr_t(ip + (kIPMemorySize / 2)), + uintptr_t(addr + size)); uintptr_t range_diff = end_of_range - static_cast(ip_memory_d.start_of_memory_range); ip_memory_d.memory.data_size = static_cast(range_diff); @@ -1247,7 +1246,7 @@ bool MinidumpGenerator::WriteSystemInfoStream( // CPU Information uint32_t number_of_processors; size_t len = sizeof(number_of_processors); - sysctlbyname("hw.ncpu", &number_of_processors, &len, NULL, 0); + sysctlbyname("hw.ncpu", &number_of_processors, &len, nullptr, 0); MDRawSystemInfo* info_ptr = info.get(); switch (cpu_type_) { @@ -1624,7 +1623,7 @@ bool MinidumpGenerator::WriteMiscInfoStream(MDRawDirectory* misc_info_stream) { uint mibsize = static_cast(sizeof(mib) / sizeof(mib[0])); struct kinfo_proc proc; size_t size = sizeof(proc); - if (sysctl(mib, mibsize, &proc, &size, NULL, 0) == 0) { + if (sysctl(mib, mibsize, &proc, &size, nullptr, 0) == 0) { info_ptr->process_create_time = static_cast(proc.kp_proc.p_starttime.tv_sec); } @@ -1633,11 +1632,11 @@ bool MinidumpGenerator::WriteMiscInfoStream(MDRawDirectory* misc_info_stream) { uint64_t speed; const uint64_t kOneMillion = 1000 * 1000; size = sizeof(speed); - sysctlbyname("hw.cpufrequency_max", &speed, &size, NULL, 0); + sysctlbyname("hw.cpufrequency_max", &speed, &size, nullptr, 0); info_ptr->processor_max_mhz = static_cast(speed / kOneMillion); info_ptr->processor_mhz_limit = static_cast(speed / kOneMillion); size = sizeof(speed); - sysctlbyname("hw.cpufrequency", &speed, &size, NULL, 0); + sysctlbyname("hw.cpufrequency", &speed, &size, nullptr, 0); info_ptr->processor_current_mhz = static_cast(speed / kOneMillion); return true; diff --git a/src/client/mac/handler/minidump_generator.h b/src/client/mac/handler/minidump_generator.h index 8c0cc6270..d74b28f1e 100644 --- a/src/client/mac/handler/minidump_generator.h +++ b/src/client/mac/handler/minidump_generator.h @@ -44,6 +44,7 @@ #include "dynamic_images.h" #include "mach_vm_compat.h" +#include "AvailabilityMacros.h" #if !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7) #define HAS_PPC_SUPPORT diff --git a/src/client/mac/handler/protected_memory_allocator.cc b/src/client/mac/handler/protected_memory_allocator.cc index 8205a214d..8e70b05ed 100644 --- a/src/client/mac/handler/protected_memory_allocator.cc +++ b/src/client/mac/handler/protected_memory_allocator.cc @@ -69,7 +69,7 @@ char *ProtectedMemoryAllocator::Allocate(vm_size_t bytes) { return p; } - return NULL; // ran out of memory in our allocation block + return nullptr; // ran out of memory in our allocation block } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/client/mac/handler/testcases/breakpad_nlist_test.cc b/src/client/mac/handler/testcases/breakpad_nlist_test.cc index 3779e357a..aeec44fb5 100644 --- a/src/client/mac/handler/testcases/breakpad_nlist_test.cc +++ b/src/client/mac/handler/testcases/breakpad_nlist_test.cc @@ -73,7 +73,7 @@ void BreakpadNlistTest::CompareToNM() { symbolNames[0] = (const char*)symbolName; symbolNames[1] = "\0"; breakpad_nlist_64("/usr/lib/dyld", &list, symbolNames); - uint64_t nmAddr = strtol(oneNMAddr, NULL, 16); + uint64_t nmAddr = strtol(oneNMAddr, nullptr, 16); if (!IsSymbolMoreThanOnceInDyld(symbolName)) { CPTAssert(nmAddr == symbolList[0].n_value); } diff --git a/src/client/mac/tests/crash_generation_server_test.cc b/src/client/mac/tests/crash_generation_server_test.cc index 743b268e0..4dd18f900 100644 --- a/src/client/mac/tests/crash_generation_server_test.cc +++ b/src/client/mac/tests/crash_generation_server_test.cc @@ -102,12 +102,12 @@ int CrashGenerationServerTest::i = 0; // Test that starting and stopping a server works TEST_F(CrashGenerationServerTest, testStartStopServer) { CrashGenerationServer server(mach_port_name, - NULL, // filter callback - NULL, // filter context - NULL, // dump callback - NULL, // dump context - NULL, // exit callback - NULL, // exit context + nullptr, // filter callback + nullptr, // filter context + nullptr, // dump callback + nullptr, // dump context + nullptr, // exit callback + nullptr, // exit context false, // generate dumps ""); // dump path ASSERT_TRUE(server.Start()); @@ -118,12 +118,12 @@ TEST_F(CrashGenerationServerTest, testStartStopServer) { // Test without actually dumping TEST_F(CrashGenerationServerTest, testRequestDumpNoDump) { CrashGenerationServer server(mach_port_name, - NULL, // filter callback - NULL, // filter context - NULL, // dump callback - NULL, // dump context - NULL, // exit callback - NULL, // exit context + nullptr, // filter callback + nullptr, // filter context + nullptr, // dump callback + nullptr, // dump context + nullptr, // exit callback + nullptr, // exit context false, // don't generate dumps temp_dir.path()); // dump path ASSERT_TRUE(server.Start()); @@ -144,7 +144,7 @@ TEST_F(CrashGenerationServerTest, testRequestDumpNoDump) { // check that no minidump was written string pattern = temp_dir.path() + "/*"; glob_t dirContents; - ret = glob(pattern.c_str(), GLOB_NOSORT, NULL, &dirContents); + ret = glob(pattern.c_str(), GLOB_NOSORT, nullptr, &dirContents); EXPECT_EQ(GLOB_NOMATCH, ret); if (ret != GLOB_NOMATCH) globfree(&dirContents); @@ -170,12 +170,12 @@ void* RequestDump(void* context) { // Test that actually writing a minidump works TEST_F(CrashGenerationServerTest, testRequestDump) { CrashGenerationServer server(mach_port_name, - NULL, // filter callback - NULL, // filter context + nullptr, // filter callback + nullptr, // filter context dumpCallback, // dump callback this, // dump context - NULL, // exit callback - NULL, // exit context + nullptr, // exit callback + nullptr, // exit context true, // generate dumps temp_dir.path()); // dump path ASSERT_TRUE(server.Start()); @@ -187,7 +187,8 @@ TEST_F(CrashGenerationServerTest, testRequestDump) { // because MinidumpGenerator assumes the handler thread is not // the only thread pthread_t thread; - if (pthread_create(&thread, NULL, RequestDump, (void*)mach_port_name) != 0) + if (pthread_create(&thread, nullptr, RequestDump, (void*)mach_port_name) + != 0) exit(1); void* result; pthread_join(thread, &result); @@ -220,12 +221,12 @@ static void Crasher() { // the parent. TEST_F(CrashGenerationServerTest, testChildProcessCrash) { CrashGenerationServer server(mach_port_name, - NULL, // filter callback - NULL, // filter context + nullptr, // filter callback + nullptr, // filter context dumpCallback, // dump callback this, // dump context - NULL, // exit callback - NULL, // exit context + nullptr, // exit callback + nullptr, // exit context true, // generate dumps temp_dir.path()); // dump path ASSERT_TRUE(server.Start()); @@ -234,7 +235,7 @@ TEST_F(CrashGenerationServerTest, testChildProcessCrash) { ASSERT_NE(-1, pid); if (pid == 0) { // Instantiate an OOP exception handler. - ExceptionHandler eh("", NULL, NULL, NULL, true, mach_port_name); + ExceptionHandler eh("", nullptr, nullptr, nullptr, true, mach_port_name); Crasher(); // not reached exit(0); @@ -283,12 +284,12 @@ TEST_F(CrashGenerationServerTest, testChildProcessCrash) { // produces a valid minidump. TEST_F(CrashGenerationServerTest, testChildProcessCrashCrossArchitecture) { CrashGenerationServer server(mach_port_name, - NULL, // filter callback - NULL, // filter context + nullptr, // filter callback + nullptr, // filter context dumpCallback, // dump callback this, // dump context - NULL, // exit callback - NULL, // exit context + nullptr, // exit callback + nullptr, // exit context true, // generate dumps temp_dir.path()); // dump path ASSERT_TRUE(server.Start()); @@ -299,7 +300,7 @@ TEST_F(CrashGenerationServerTest, testChildProcessCrashCrossArchitecture) { helper_path.c_str(), "crash", mach_port_name, - NULL + nullptr }; pid_t pid = spawn_child_process(argv); ASSERT_NE(-1, pid); @@ -372,8 +373,8 @@ TEST_F(CrashGenerationServerTest, testFilter) { this, // filter context dumpCallback, // dump callback this, // dump context - NULL, // exit callback - NULL, // exit context + nullptr, // exit callback + nullptr, // exit context true, // generate dumps temp_dir.path()); // dump path ASSERT_TRUE(server.Start()); @@ -382,7 +383,7 @@ TEST_F(CrashGenerationServerTest, testFilter) { ASSERT_NE(-1, pid); if (pid == 0) { // Instantiate an OOP exception handler. - ExceptionHandler eh("", NULL, NULL, NULL, true, mach_port_name); + ExceptionHandler eh("", nullptr, nullptr, nullptr, true, mach_port_name); Crasher(); // not reached exit(0); diff --git a/src/client/mac/tests/exception_handler_test.cc b/src/client/mac/tests/exception_handler_test.cc index 91b931b94..fb42c8bb2 100644 --- a/src/client/mac/tests/exception_handler_test.cc +++ b/src/client/mac/tests/exception_handler_test.cc @@ -113,7 +113,8 @@ void ExceptionHandlerTest::InProcessCrash(bool aborting) { if (pid == 0) { // In the child process. close(fds[0]); - ExceptionHandler eh(tempDir.path(), NULL, MDCallback, &fds[1], true, NULL); + ExceptionHandler eh(tempDir.path(), nullptr, MDCallback, &fds[1], true, + nullptr); // crash SoonToCrash(aborting ? &AbortCrasher : &Crasher); // not reached @@ -195,8 +196,8 @@ static bool DumpNameMDCallback(const char* dump_dir, const char* file_name, } TEST_F(ExceptionHandlerTest, WriteMinidump) { - ExceptionHandler eh(tempDir.path(), NULL, DumpNameMDCallback, this, true, - NULL); + ExceptionHandler eh(tempDir.path(), nullptr, DumpNameMDCallback, this, true, + nullptr); ASSERT_TRUE(eh.WriteMinidump()); // Ensure that minidump file exists and is > 0 bytes. @@ -214,8 +215,8 @@ TEST_F(ExceptionHandlerTest, WriteMinidump) { } TEST_F(ExceptionHandlerTest, WriteMinidumpWithException) { - ExceptionHandler eh(tempDir.path(), NULL, DumpNameMDCallback, this, true, - NULL); + ExceptionHandler eh(tempDir.path(), nullptr, DumpNameMDCallback, this, true, + nullptr); ASSERT_TRUE(eh.WriteMinidump(true)); // Ensure that minidump file exists and is > 0 bytes. @@ -323,10 +324,11 @@ TEST_F(ExceptionHandlerTest, InstructionPointerMemory) { pid_t pid = fork(); if (pid == 0) { close(fds[0]); - ExceptionHandler eh(tempDir.path(), NULL, MDCallback, &fds[1], true, NULL); + ExceptionHandler eh(tempDir.path(), nullptr, MDCallback, &fds[1], true, + nullptr); // Get some executable memory. char* memory = - reinterpret_cast(mmap(NULL, + reinterpret_cast(mmap(nullptr, kMemorySize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, @@ -422,10 +424,11 @@ TEST_F(ExceptionHandlerTest, InstructionPointerMemoryMinBound) { pid_t pid = fork(); if (pid == 0) { close(fds[0]); - ExceptionHandler eh(tempDir.path(), NULL, MDCallback, &fds[1], true, NULL); + ExceptionHandler eh(tempDir.path(), nullptr, MDCallback, &fds[1], true, + nullptr); // Get some executable memory. char* memory = - reinterpret_cast(mmap(NULL, + reinterpret_cast(mmap(nullptr, kMemorySize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, @@ -521,10 +524,11 @@ TEST_F(ExceptionHandlerTest, InstructionPointerMemoryMaxBound) { pid_t pid = fork(); if (pid == 0) { close(fds[0]); - ExceptionHandler eh(tempDir.path(), NULL, MDCallback, &fds[1], true, NULL); + ExceptionHandler eh(tempDir.path(), nullptr, MDCallback, &fds[1], true, + nullptr); // Get some executable memory. char* memory = - reinterpret_cast(mmap(NULL, + reinterpret_cast(mmap(nullptr, kMemorySize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, @@ -611,13 +615,14 @@ TEST_F(ExceptionHandlerTest, InstructionPointerMemoryNullPointer) { pid_t pid = fork(); if (pid == 0) { close(fds[0]); - ExceptionHandler eh(tempDir.path(), NULL, MDCallback, &fds[1], true, NULL); + ExceptionHandler eh(tempDir.path(), nullptr, MDCallback, &fds[1], true, + nullptr); // Try calling a NULL pointer. typedef void (*void_function)(void); // Volatile markings are needed to keep Clang from generating invalid // opcodes. See http://crbug.com/498354 for details. volatile void_function memory_function = - reinterpret_cast(NULL); + static_cast(nullptr); memory_function(); // not reached exit(1); @@ -657,7 +662,7 @@ TEST_F(ExceptionHandlerTest, InstructionPointerMemoryNullPointer) { static void* Junk(void*) { sleep(1000000); - return NULL; + return nullptr; } // Test that the memory list gets written correctly when multiple @@ -670,11 +675,12 @@ TEST_F(ExceptionHandlerTest, MemoryListMultipleThreads) { pid_t pid = fork(); if (pid == 0) { close(fds[0]); - ExceptionHandler eh(tempDir.path(), NULL, MDCallback, &fds[1], true, NULL); + ExceptionHandler eh(tempDir.path(), nullptr, MDCallback, &fds[1], true, + nullptr); // Run an extra thread so >2 memory regions will be written. pthread_t junk_thread; - if (pthread_create(&junk_thread, NULL, Junk, NULL) == 0) + if (pthread_create(&junk_thread, nullptr, Junk, nullptr) == 0) pthread_detach(junk_thread); // Just crash. diff --git a/src/client/mac/tests/minidump_generator_test.cc b/src/client/mac/tests/minidump_generator_test.cc index 2606e14f5..4ab6abfba 100644 --- a/src/client/mac/tests/minidump_generator_test.cc +++ b/src/client/mac/tests/minidump_generator_test.cc @@ -87,19 +87,19 @@ static void* Junk(void* data) { while (!*wait) { usleep(10000); } - return NULL; + return nullptr; } TEST_F(MinidumpGeneratorTest, InProcess) { MinidumpGenerator generator; string dump_filename = - MinidumpGenerator::UniqueNameInDirectory(tempDir.path(), NULL); + MinidumpGenerator::UniqueNameInDirectory(tempDir.path(), nullptr); // Run an extra thread since MinidumpGenerator assumes there // are 2 or more threads. pthread_t junk_thread; bool quit = false; - ASSERT_EQ(0, pthread_create(&junk_thread, NULL, Junk, &quit)); + ASSERT_EQ(0, pthread_create(&junk_thread, nullptr, Junk, &quit)); ASSERT_TRUE(generator.Write(dump_filename.c_str())); // Ensure that minidump file exists and is > 0 bytes. @@ -109,7 +109,7 @@ TEST_F(MinidumpGeneratorTest, InProcess) { // join the background thread quit = true; - pthread_join(junk_thread, NULL); + pthread_join(junk_thread, nullptr); // Read the minidump, sanity check some data. Minidump minidump(dump_filename.c_str()); @@ -184,7 +184,7 @@ TEST_F(MinidumpGeneratorTest, OutOfProcess) { // Write a minidump of the child process. MinidumpGenerator generator(child_task, MACH_PORT_NULL); string dump_filename = - MinidumpGenerator::UniqueNameInDirectory(tempDir.path(), NULL); + MinidumpGenerator::UniqueNameInDirectory(tempDir.path(), nullptr); ASSERT_TRUE(generator.Write(dump_filename.c_str())); // Ensure that minidump file exists and is > 0 bytes. @@ -248,7 +248,7 @@ TEST_F(MinidumpGeneratorTest, CrossArchitectureDump) { const char* argv[] = { helper_path.c_str(), machPortName, - NULL + nullptr }; pid_t pid = spawn_child_process(argv); ASSERT_NE(-1, pid); @@ -263,7 +263,7 @@ TEST_F(MinidumpGeneratorTest, CrossArchitectureDump) { // Write a minidump of the child process. MinidumpGenerator generator(child_task, MACH_PORT_NULL); string dump_filename = - MinidumpGenerator::UniqueNameInDirectory(tempDir.path(), NULL); + MinidumpGenerator::UniqueNameInDirectory(tempDir.path(), nullptr); ASSERT_TRUE(generator.Write(dump_filename.c_str())); // Ensure that minidump file exists and is > 0 bytes. diff --git a/src/client/mac/tests/minidump_generator_test_helper.cc b/src/client/mac/tests/minidump_generator_test_helper.cc index 8177eeab7..34f22c74d 100644 --- a/src/client/mac/tests/minidump_generator_test_helper.cc +++ b/src/client/mac/tests/minidump_generator_test_helper.cc @@ -67,7 +67,8 @@ int main(int argc, char** argv) { } } else if (argc == 3 && strcmp(argv[1], "crash") == 0) { // Instantiate an OOP exception handler - google_breakpad::ExceptionHandler eh("", NULL, NULL, NULL, true, argv[2]); + google_breakpad::ExceptionHandler eh("", nullptr, nullptr, nullptr, true, + argv[2]); // and crash. int *a = (int*)0x42; *a = 1; diff --git a/src/client/mac/tests/spawn_child_process.h b/src/client/mac/tests/spawn_child_process.h index cc8045116..983816fc3 100644 --- a/src/client/mac/tests/spawn_child_process.h +++ b/src/client/mac/tests/spawn_child_process.h @@ -129,9 +129,9 @@ pid_t spawn_child_process(const char** argv) { argv_v.push_back(strdup(*argv)); argv++; } - argv_v.push_back(NULL); + argv_v.push_back(nullptr); pid_t new_pid = 0; - int result = posix_spawnp(&new_pid, argv_v[0], NULL, &spawnattr, + int result = posix_spawnp(&new_pid, argv_v[0], nullptr, &spawnattr, &argv_v[0], *_NSGetEnviron()); posix_spawnattr_destroy(&spawnattr); diff --git a/src/client/minidump_file_writer.cc b/src/client/minidump_file_writer.cc index c00af36c8..d82fd8158 100644 --- a/src/client/minidump_file_writer.cc +++ b/src/client/minidump_file_writer.cc @@ -34,6 +34,7 @@ #include // Must come first #endif +#include #include #include #include @@ -42,6 +43,7 @@ #include "client/minidump_file_writer-inl.h" #include "common/linux/linux_libc_support.h" +#include "common/memory_allocator.h" #include "common/string_conversion.h" #if defined(__linux__) && __linux__ #include "third_party/lss/linux_syscall_support.h" @@ -287,7 +289,7 @@ MDRVA MinidumpFileWriter::Allocate(size_t size) { return current_position; } #endif - size_t aligned_size = (size + 7) & ~7; // 64-bit alignment + size_t aligned_size = PageAllocator::AlignUp(size, 8); // 64-bit alignment if (position_ + aligned_size > size_) { size_t growth = aligned_size; diff --git a/src/client/solaris/handler/exception_handler.cc b/src/client/solaris/handler/exception_handler.cc index 0e5f44976..69d2d09e7 100644 --- a/src/client/solaris/handler/exception_handler.cc +++ b/src/client/solaris/handler/exception_handler.cc @@ -32,16 +32,16 @@ #include // Must come first #endif +#include "client/solaris/handler/exception_handler.h" + +#include #include +#include #include #include +#include #include -#include -#include -#include - -#include "client/solaris/handler/exception_handler.h" #include "common/solaris/guid_creator.h" #include "common/solaris/message_output.h" #include "google_breakpad/common/minidump_format.h" @@ -57,7 +57,7 @@ static const int kSigTable[] = { SIGBUS }; -std::vector* ExceptionHandler::handler_stack_ = NULL; +std::vector* ExceptionHandler::handler_stack_ = nullptr; int ExceptionHandler::handler_stack_index_ = 0; pthread_mutex_t ExceptionHandler::handler_stack_mutex_ = PTHREAD_MUTEX_INITIALIZER; @@ -81,7 +81,7 @@ ExceptionHandler::ExceptionHandler(const string& dump_path, if (install_handler) { pthread_mutex_lock(&handler_stack_mutex_); - if (handler_stack_ == NULL) + if (handler_stack_ == nullptr) handler_stack_ = new std::vector; handler_stack_->push_back(this); pthread_mutex_unlock(&handler_stack_mutex_); @@ -109,22 +109,22 @@ ExceptionHandler::~ExceptionHandler() { // When destroying the last ExceptionHandler that installed a handler, // clean up the handler stack. delete handler_stack_; - handler_stack_ = NULL; + handler_stack_ = nullptr; } pthread_mutex_unlock(&handler_stack_mutex_); } bool ExceptionHandler::WriteMinidump() { - return InternalWriteMinidump(0, 0, NULL); + return InternalWriteMinidump(0, 0, nullptr); } // static bool ExceptionHandler::WriteMinidump(const string& dump_path, MinidumpCallback callback, void* callback_context) { - ExceptionHandler handler(dump_path, NULL, callback, + ExceptionHandler handler(dump_path, nullptr, callback, callback_context, false); - return handler.InternalWriteMinidump(0, 0, NULL); + return handler.InternalWriteMinidump(0, 0, nullptr); } void ExceptionHandler::SetupHandler() { @@ -132,12 +132,12 @@ void ExceptionHandler::SetupHandler() { // of the crashing lwp. struct sigaltstack sig_stack; sig_stack.ss_sp = malloc(MINSIGSTKSZ); - if (sig_stack.ss_sp == NULL) + if (sig_stack.ss_sp == nullptr) return; sig_stack.ss_size = MINSIGSTKSZ; sig_stack.ss_flags = 0; - if (sigaltstack(&sig_stack, NULL) < 0) + if (sigaltstack(&sig_stack, nullptr) < 0) return; for (size_t i = 0; i < sizeof(kSigTable) / sizeof(kSigTable[0]); ++i) SetupHandler(kSigTable[i]); @@ -191,7 +191,7 @@ void ExceptionHandler::HandleException(int signo) { // Restore original handler. current_handler->TeardownHandler(signo); - ucontext_t* sig_ctx = NULL; + ucontext_t* sig_ctx = nullptr; if (current_handler->InternalWriteMinidump(signo, current_ebp, &sig_ctx)) { // if (current_handler->InternalWriteMinidump(signo, &sig_ctx)) { // Fully handled this exception, safe to exit. @@ -202,7 +202,7 @@ void ExceptionHandler::HandleException(int signo) { typedef void (*SignalHandler)(int signo); SignalHandler old_handler = reinterpret_cast(current_handler->old_handlers_[signo]); - if (old_handler != NULL) + if (old_handler != nullptr) old_handler(signo); } diff --git a/src/client/solaris/handler/exception_handler_test.cc b/src/client/solaris/handler/exception_handler_test.cc index 3d656820d..3d2f17930 100644 --- a/src/client/solaris/handler/exception_handler_test.cc +++ b/src/client/solaris/handler/exception_handler_test.cc @@ -32,15 +32,15 @@ #include // Must come first #endif +#include "client/solaris/handler/exception_handler.h" + +#include #include +#include +#include +#include #include -#include -#include -#include -#include - -#include "client/solaris/handler/exception_handler.h" #include "client/solaris/handler/solaris_lwp.h" using namespace google_breakpad; @@ -69,18 +69,18 @@ static void* thread_crash(void*) { sleep(3); a = foo(a); printf("%x\n", a); - return NULL; + return nullptr; } static void* thread_main(void*) { while (!should_exit) sleep(1); - return NULL; + return nullptr; } static void CreateCrashThread() { pthread_t h; - pthread_create(&h, NULL, thread_crash, NULL); + pthread_create(&h, nullptr, thread_crash, nullptr); pthread_detach(h); } @@ -88,7 +88,7 @@ static void CreateCrashThread() { static void CreateThread(int num) { pthread_t h; for (int i = 0; i < num; ++i) { - pthread_create(&h, NULL, thread_main, NULL); + pthread_create(&h, nullptr, thread_main, nullptr); pthread_detach(h); } } @@ -109,7 +109,7 @@ static bool MinidumpCallback(const char* dump_path, int main(int argc, char* argv[]) { int handler_index = 1; - ExceptionHandler handler_ignore(".", NULL, MinidumpCallback, + ExceptionHandler handler_ignore(".", nullptr, MinidumpCallback, (void*)handler_index, true); CreateCrashThread(); CreateThread(10); diff --git a/src/client/solaris/handler/minidump_generator.cc b/src/client/solaris/handler/minidump_generator.cc index 5d24d0ae8..9982d0bb1 100644 --- a/src/client/solaris/handler/minidump_generator.cc +++ b/src/client/solaris/handler/minidump_generator.cc @@ -32,18 +32,19 @@ #include // Must come first #endif +#include "client/solaris/handler/minidump_generator.h" + +#include #include +#include #include #include #include #include #include +#include #include -#include -#include - -#include "client/solaris/handler/minidump_generator.h" #include "client/minidump_file_writer-inl.h" #include "common/solaris/file_id.h" @@ -90,7 +91,7 @@ struct FindCrashLwpContext { int crashing_lwpid; FindCrashLwpContext() : - lwp_lister(NULL), + lwp_lister(nullptr), crashing_stack_bottom(0UL), crashing_lwpid(-1) { } @@ -156,7 +157,7 @@ bool WriteLwpStack(const SolarisLwp* lwp_lister, #if TARGET_CPU_SPARC bool WriteContext(MDRawContextSPARC* context, ucontext_t* sig_ctx) { - assert(sig_ctx != NULL); + assert(sig_ctx != nullptr); int* regs = sig_ctx->uc_mcontext.gregs; context->context_flags = MD_CONTEXT_SPARC_FULL; @@ -236,7 +237,7 @@ bool WriteCrashedLwpStream(MinidumpFileWriter* minidump_writer, const WriterArgument* writer_args, const lwpstatus_t* lsp, MDRawThread* lwp) { - assert(writer_args->sig_ctx != NULL); + assert(writer_args->sig_ctx != nullptr); lwp->thread_id = lsp->pr_lwpid; @@ -337,7 +338,7 @@ bool WriteCPUInformation(MDRawSystemInfo* sys_info) { build = strchr(uts.version, '_'); ++build; sys_info->build_number = atoi(build); - + return true; } @@ -356,10 +357,10 @@ bool WriteOSInformation(MinidumpFileWriter* minidump_writer, uts.version, uts.machine, "OpenSolaris", - NULL + nullptr }; for (const char** cur_os_info = os_info_table; - *cur_os_info != NULL; + *cur_os_info != nullptr; ++cur_os_info) { if (cur_os_info != os_info_table && space_left > 1) { strcat(os_version, " "); @@ -402,7 +403,7 @@ bool LwpInformationCallback(lwpstatus_t* lsp, void* context) { memset(&lwp, 0, sizeof(MDRawThread)); if (lsp->pr_lwpid != callback_context->writer_args->crashed_lwpid || - callback_context->writer_args->sig_ctx == NULL) { + callback_context->writer_args->sig_ctx == nullptr) { success = WriteLwpStream(callback_context->minidump_writer, callback_context->writer_args->lwp_lister, lsp, &lwp); @@ -519,7 +520,7 @@ bool ModuleInfoCallback(const ModuleInfo& module_info, void* context) { return false; buf[count] = '\0'; - if ((realname = strrchr(buf, '/')) == NULL) + if ((realname = strrchr(buf, '/')) == nullptr) return false; realname++; @@ -581,7 +582,7 @@ bool WriteExceptionStream(MinidumpFileWriter* minidump_writer, const WriterArgument* writer_args, MDRawDirectory* dir) { // This happenes when this is not a crash, but a requested dump. - if (writer_args->sig_ctx == NULL) + if (writer_args->sig_ctx == nullptr) return false; TypedMDRVA exception(minidump_writer); @@ -595,9 +596,9 @@ bool WriteExceptionStream(MinidumpFileWriter* minidump_writer, exception.get()->exception_record.exception_flags = 0; #if TARGET_CPU_SPARC - if (writer_args->sig_ctx != NULL) { - exception.get()->exception_record.exception_address = - writer_args->sig_ctx->uc_mcontext.gregs[REG_PC]; + if (writer_args->sig_ctx != nullptr) { + exception.get()->exception_record.exception_address = + writer_args->sig_ctx->uc_mcontext.gregs[REG_PC]; } else { return true; } @@ -610,7 +611,7 @@ bool WriteExceptionStream(MinidumpFileWriter* minidump_writer, memset(context.get(), 0, sizeof(MDRawContextSPARC)); return WriteContext(context.get(), writer_args->sig_ctx); #elif TARGET_CPU_X86 - if (writer_args->sig_ctx != NULL) { + if (writer_args->sig_ctx != nullptr) { exception.get()->exception_record.exception_address = writer_args->sig_ctx->uc_mcontext.gregs[EIP]; } else { @@ -625,7 +626,7 @@ bool WriteExceptionStream(MinidumpFileWriter* minidump_writer, memset(context.get(), 0, sizeof(MDRawContextX86)); return WriteContext(context.get(), (int*)&writer_args->sig_ctx->uc_mcontext.gregs, - NULL); + nullptr); #endif } @@ -693,21 +694,21 @@ void* Write(void* argument) { WriterArgument* writer_args = static_cast(argument); if (!writer_args->lwp_lister->ControlAllLwps(true)) - return NULL; + return nullptr; AutoLwpResumer lwpResumer(writer_args->lwp_lister); if (writer_args->sighandler_ebp != 0 && writer_args->lwp_lister->FindSigContext(writer_args->sighandler_ebp, &writer_args->sig_ctx)) { - writer_args->crashed_stack_bottom = - writer_args->lwp_lister->GetLwpStackBottom( + writer_args->crashed_stack_bottom = + writer_args->lwp_lister->GetLwpStackBottom( #if TARGET_CPU_SPARC - writer_args->sig_ctx->uc_mcontext.gregs[REG_O6] + writer_args->sig_ctx->uc_mcontext.gregs[REG_O6] #elif TARGET_CPU_X86 - writer_args->sig_ctx->uc_mcontext.gregs[UESP] + writer_args->sig_ctx->uc_mcontext.gregs[UESP] #endif - ); + ); int crashed_lwpid = FindCrashingLwp(writer_args->crashed_stack_bottom, writer_args->requester_pid, @@ -728,7 +729,7 @@ void* Write(void* argument) { return 0; header.get()->signature = MD_HEADER_SIGNATURE; header.get()->version = MD_HEADER_VERSION; - header.get()->time_date_stamp = time(NULL); + header.get()->time_date_stamp = time(nullptr); header.get()->stream_count = writer_count; header.get()->stream_directory_rva = dir.position(); @@ -761,9 +762,9 @@ bool MinidumpGenerator::WriteMinidumpToFile(const char* file_pathname, // The exception handler thread. pthread_t handler_thread; - assert(file_pathname != NULL); + assert(file_pathname != nullptr); - if (file_pathname == NULL) + if (file_pathname == nullptr) return false; MinidumpFileWriter minidump_writer; @@ -777,10 +778,10 @@ bool MinidumpGenerator::WriteMinidumpToFile(const char* file_pathname, argument.crashed_lwpid = pthread_self(); argument.signo = signo; argument.sighandler_ebp = sighandler_ebp; - argument.sig_ctx = NULL; + argument.sig_ctx = nullptr; - pthread_create(&handler_thread, NULL, Write, (void*)&argument); - pthread_join(handler_thread, NULL); + pthread_create(&handler_thread, nullptr, Write, (void*)&argument); + pthread_join(handler_thread, nullptr); return true; } diff --git a/src/client/solaris/handler/minidump_test.cc b/src/client/solaris/handler/minidump_test.cc index a8f690632..7a20eb827 100644 --- a/src/client/solaris/handler/minidump_test.cc +++ b/src/client/solaris/handler/minidump_test.cc @@ -51,10 +51,10 @@ static void* Reporter(void*) { snprintf(buffer, sizeof(buffer), "./minidump_test.out"); fprintf(stdout, "Writing %s\n", buffer); - md.WriteMinidumpToFile(buffer, 0, 0, NULL); + md.WriteMinidumpToFile(buffer, 0, 0, nullptr); doneWritingReport = true; - return NULL; + return nullptr; } static void SleepyFunction() { @@ -66,7 +66,7 @@ static void SleepyFunction() { int main(int argc, char * const argv[]) { pthread_t reporter_thread; - if (pthread_create(&reporter_thread, NULL, Reporter, NULL) == 0) { + if (pthread_create(&reporter_thread, nullptr, Reporter, nullptr) == 0) { pthread_detach(reporter_thread); } else { perror("pthread_create"); diff --git a/src/client/solaris/handler/solaris_lwp.cc b/src/client/solaris/handler/solaris_lwp.cc index 02f1c37e8..77c6bcd54 100644 --- a/src/client/solaris/handler/solaris_lwp.cc +++ b/src/client/solaris/handler/solaris_lwp.cc @@ -32,11 +32,16 @@ #include // Must come first #endif +#include "client/solaris/handler/solaris_lwp.h" + +#include #include #include #include #include #include +#include +#include #include #include #include @@ -44,12 +49,8 @@ #include #include -#include -#include -#include #include -#include "client/solaris/handler/solaris_lwp.h" #include "common/solaris/message_output.h" using namespace google_breakpad; @@ -73,9 +74,9 @@ struct AddressValidatingContext { // Convert from string to int. static bool LocalAtoi(char* s, int* r) { - assert(s != NULL); - assert(r != NULL); - char* endptr = NULL; + assert(s != nullptr); + assert(r != nullptr); + char* endptr = nullptr; int ret = strtol(s, &endptr, 10); if (endptr == s) return false; @@ -106,11 +107,11 @@ static int IterateLwpAll(int pid, int count = 0; snprintf(lwp_path, sizeof (lwp_path), "/proc/%d/lwp", (int)pid); - if ((dir = opendir(lwp_path)) == NULL) + if ((dir = opendir(lwp_path)) == nullptr) return -1; - struct dirent* entry = NULL; - while ((entry = readdir(dir)) != NULL) { + struct dirent* entry = nullptr; + while ((entry = readdir(dir)) != nullptr) { if ((strcmp(entry->d_name, ".") != 0) && (strcmp(entry->d_name, "..") != 0)) { int lwpid = 0; @@ -134,11 +135,11 @@ static int IterateLwpAll(int pid, void* GetNextFrame(void** last_ebp) { void* sp = *last_ebp; if ((unsigned long)sp == (unsigned long)last_ebp) - return NULL; + return nullptr; if ((unsigned long)sp & (sizeof(void*) - 1)) - return NULL; + return nullptr; if ((unsigned long)sp - (unsigned long)last_ebp > 100000) - return NULL; + return nullptr; return sp; } #elif defined(__sparc) @@ -241,7 +242,7 @@ int SolarisLwp::ControlAllLwps(bool suspend) { } int SolarisLwp::GetLwpCount() const { - return IterateLwpAll(pid_, NULL); + return IterateLwpAll(pid_, nullptr); } int SolarisLwp::Lwp_iter_all(int pid, @@ -261,9 +262,9 @@ int SolarisLwp::Lwp_iter_all(int pid, * The /proc/pid/lstatus file has the array of lwpstatus_t's and the * /proc/pid/lpsinfo file has the array of lwpsinfo_t's. */ - if (read_lfile(pid, "lstatus", Lhp) == NULL) + if (read_lfile(pid, "lstatus", Lhp) == nullptr) return -1; - if (read_lfile(pid, "lpsinfo", Lphp) == NULL) { + if (read_lfile(pid, "lpsinfo", Lphp) == nullptr) { return -1; } @@ -275,7 +276,7 @@ int SolarisLwp::Lwp_iter_all(int pid, sp = Lsp; Lsp = (lwpstatus_t*)((uintptr_t)Lsp + Lhp->pr_entsize); } else { - sp = NULL; + sp = nullptr; } if (callback_param && !(callback_param->call_back)(sp, callback_param->context)) @@ -297,7 +298,7 @@ uintptr_t SolarisLwp::GetLwpStackBottom(uintptr_t current_esp) const { } int SolarisLwp::GetModuleCount() const { - return ListModules(NULL); + return ListModules(nullptr); } int SolarisLwp::ListModules( @@ -320,7 +321,7 @@ int SolarisLwp::ListModules( return -1; /* - * Determine number of mappings, this value must be + * Determine number of mappings, this value must be * larger than the actual module count */ size = status.st_size; @@ -337,7 +338,7 @@ int SolarisLwp::ListModules( prmap_t* _maps; int _num; int module_count = 0; - + /* * Scan each mapping - note it is assummed that the mappings are * presented in order. We fill holes between mappings. On intel diff --git a/src/client/solaris/handler/solaris_lwp.h b/src/client/solaris/handler/solaris_lwp.h index f27d6b747..f2fe7c197 100644 --- a/src/client/solaris/handler/solaris_lwp.h +++ b/src/client/solaris/handler/solaris_lwp.h @@ -89,7 +89,7 @@ struct CallbackParam { // Callback context; void* context; - CallbackParam() : call_back(NULL), context(NULL) { + CallbackParam() : call_back(nullptr), context(nullptr) { } CallbackParam(CallbackFunc func, void* func_context) : diff --git a/src/client/windows/common/ipc_protocol.h b/src/client/windows/common/ipc_protocol.h index 7e0c24e3c..31667b567 100644 --- a/src/client/windows/common/ipc_protocol.h +++ b/src/client/windows/common/ipc_protocol.h @@ -46,8 +46,8 @@ struct CustomInfoEntry { CustomInfoEntry() { // Putting name and value in initializer list makes VC++ show warning 4351. - set_name(NULL); - set_value(NULL); + set_name(nullptr); + set_value(nullptr); } CustomInfoEntry(const wchar_t* name_arg, const wchar_t* value_arg) { @@ -105,12 +105,12 @@ struct ProtocolMessage { id(0), dump_type(MiniDumpNormal), thread_id(0), - exception_pointers(NULL), - assert_info(NULL), + exception_pointers(nullptr), + assert_info(nullptr), custom_client_info(), - dump_request_handle(NULL), - dump_generated_handle(NULL), - server_alive_handle(NULL) { + dump_request_handle(nullptr), + dump_generated_handle(nullptr), + server_alive_handle(nullptr) { } // Creates an instance with the given parameters. diff --git a/src/client/windows/crash_generation/client_info.cc b/src/client/windows/crash_generation/client_info.cc index 61ee21262..75eca7947 100644 --- a/src/client/windows/crash_generation/client_info.cc +++ b/src/client/windows/crash_generation/client_info.cc @@ -52,12 +52,12 @@ ClientInfo::ClientInfo(CrashGenerationServer* crash_server, assert_info_(assert_info), custom_client_info_(custom_client_info), thread_id_(thread_id), - process_handle_(NULL), - dump_requested_handle_(NULL), - dump_generated_handle_(NULL), - dump_request_wait_handle_(NULL), - process_exit_wait_handle_(NULL), - crash_id_(NULL) { + process_handle_(nullptr), + dump_requested_handle_(nullptr), + dump_generated_handle_(nullptr), + dump_request_wait_handle_(nullptr), + process_exit_wait_handle_(nullptr), + crash_id_(0) { GetSystemTimeAsFileTime(&start_time_); } @@ -75,26 +75,26 @@ bool ClientInfo::Initialize() { } crash_id_ = start_time_.dwLowDateTime; - dump_requested_handle_ = CreateEvent(NULL, // Security attributes. - TRUE, // Manual reset. - FALSE, // Initial state. - NULL); // Name. + dump_requested_handle_ = CreateEvent(nullptr, // Security attributes. + TRUE, // Manual reset. + FALSE, // Initial state. + nullptr); // Name. if (!dump_requested_handle_) { return false; } - dump_generated_handle_ = CreateEvent(NULL, // Security attributes. - TRUE, // Manual reset. - FALSE, // Initial state. - NULL); // Name. - return dump_generated_handle_ != NULL; + dump_generated_handle_ = CreateEvent(nullptr, // Security attributes. + TRUE, // Manual reset. + FALSE, // Initial state. + nullptr); // Name. + return dump_generated_handle_ != nullptr; } void ClientInfo::UnregisterDumpRequestWaitAndBlockUntilNoPending() { if (dump_request_wait_handle_) { // Wait for callbacks that might already be running to finish. UnregisterWaitEx(dump_request_wait_handle_, INVALID_HANDLE_VALUE); - dump_request_wait_handle_ = NULL; + dump_request_wait_handle_ = nullptr; } } @@ -106,7 +106,7 @@ void ClientInfo::UnregisterProcessExitWait(bool block_until_no_pending) { } else { UnregisterWait(process_exit_wait_handle_); } - process_exit_wait_handle_ = NULL; + process_exit_wait_handle_ = nullptr; } } diff --git a/src/client/windows/crash_generation/crash_generation_client.cc b/src/client/windows/crash_generation/crash_generation_client.cc index 67529ff68..c7cb0d979 100644 --- a/src/client/windows/crash_generation/crash_generation_client.cc +++ b/src/client/windows/crash_generation/crash_generation_client.cc @@ -31,8 +31,11 @@ #endif #include "client/windows/crash_generation/crash_generation_client.h" -#include + +#include + #include + #include "client/windows/common/ipc_protocol.h" namespace google_breakpad { @@ -81,7 +84,7 @@ static bool TransactNamedPipeDebugHelper(HANDLE pipe, in_buffer, in_size, bytes_count, - NULL)) { + nullptr)) { return false; } @@ -89,7 +92,7 @@ static bool TransactNamedPipeDebugHelper(HANDLE pipe, // and read. // Sleep(5000); - return ReadFile(pipe, out_buffer, out_size, bytes_count, NULL) != FALSE; + return ReadFile(pipe, out_buffer, out_size, bytes_count, nullptr) != FALSE; } **/ @@ -98,15 +101,15 @@ CrashGenerationClient::CrashGenerationClient( MINIDUMP_TYPE dump_type, const CustomClientInfo* custom_info) : pipe_name_(pipe_name), - pipe_handle_(NULL), + pipe_handle_(nullptr), custom_info_(), dump_type_(dump_type), - crash_event_(NULL), - crash_generated_(NULL), - server_alive_(NULL), + crash_event_(nullptr), + crash_generated_(nullptr), + server_alive_(nullptr), server_process_id_(0), thread_id_(0), - exception_pointers_(NULL) { + exception_pointers_(nullptr) { memset(&assert_info_, 0, sizeof(assert_info_)); if (custom_info) { custom_info_ = *custom_info; @@ -121,12 +124,12 @@ CrashGenerationClient::CrashGenerationClient( pipe_handle_(pipe_handle), custom_info_(), dump_type_(dump_type), - crash_event_(NULL), - crash_generated_(NULL), - server_alive_(NULL), + crash_event_(nullptr), + crash_generated_(nullptr), + server_alive_(nullptr), server_process_id_(0), thread_id_(0), - exception_pointers_(NULL) { + exception_pointers_(nullptr) { memset(&assert_info_, 0, sizeof(assert_info_)); if (custom_info) { custom_info_ = *custom_info; @@ -201,12 +204,12 @@ bool CrashGenerationClient::RequestUpload(DWORD crash_id) { return false; } - CustomClientInfo custom_info = {NULL, 0}; + CustomClientInfo custom_info = {nullptr, 0}; ProtocolMessage msg(MESSAGE_TAG_UPLOAD_REQUEST, crash_id, - static_cast(NULL), NULL, NULL, NULL, - custom_info, NULL, NULL, NULL); + MiniDumpNormal, nullptr, nullptr, + nullptr, custom_info, nullptr, nullptr, nullptr); DWORD bytes_count = 0; - bool success = WriteFile(pipe, &msg, sizeof(msg), &bytes_count, NULL) != 0; + bool success = WriteFile(pipe, &msg, sizeof(msg), &bytes_count, nullptr) != 0; CloseHandle(pipe); return success; @@ -217,13 +220,13 @@ HANDLE CrashGenerationClient::ConnectToServer() { kPipeDesiredAccess, kPipeFlagsAndAttributes); if (!pipe) { - return NULL; + return nullptr; } DWORD mode = kPipeMode; - if (!SetNamedPipeHandleState(pipe, &mode, NULL, NULL)) { + if (!SetNamedPipeHandleState(pipe, &mode, nullptr, nullptr)) { CloseHandle(pipe); - pipe = NULL; + pipe = nullptr; } return pipe; @@ -240,9 +243,9 @@ bool CrashGenerationClient::RegisterClient(HANDLE pipe) { &exception_pointers_, &assert_info_, custom_info_, - NULL, - NULL, - NULL); + nullptr, + nullptr, + nullptr); ProtocolMessage reply; DWORD bytes_count = 0; // The call to TransactNamedPipe below can be changed to a call @@ -254,7 +257,7 @@ bool CrashGenerationClient::RegisterClient(HANDLE pipe) { &reply, sizeof(ProtocolMessage), &bytes_count, - NULL)) { + nullptr)) { return false; } @@ -265,7 +268,7 @@ bool CrashGenerationClient::RegisterClient(HANDLE pipe) { ProtocolMessage ack_msg; ack_msg.tag = MESSAGE_TAG_REGISTRATION_ACK; - if (!WriteFile(pipe, &ack_msg, sizeof(ack_msg), &bytes_count, NULL)) { + if (!WriteFile(pipe, &ack_msg, sizeof(ack_msg), &bytes_count, nullptr)) { return false; } crash_event_ = reply.dump_request_handle; @@ -282,7 +285,7 @@ HANDLE CrashGenerationClient::ConnectToPipe(const wchar_t* pipe_name, DWORD flags_attrs) { if (pipe_handle_) { HANDLE t = pipe_handle_; - pipe_handle_ = NULL; + pipe_handle_ = nullptr; return t; } @@ -290,10 +293,10 @@ HANDLE CrashGenerationClient::ConnectToPipe(const wchar_t* pipe_name, HANDLE pipe = CreateFile(pipe_name, pipe_access, 0, - NULL, + nullptr, OPEN_EXISTING, flags_attrs, - NULL); + nullptr); if (pipe != INVALID_HANDLE_VALUE) { return pipe; } @@ -310,20 +313,20 @@ HANDLE CrashGenerationClient::ConnectToPipe(const wchar_t* pipe_name, } } - return NULL; + return nullptr; } bool CrashGenerationClient::ValidateResponse( const ProtocolMessage& msg) const { return (msg.tag == MESSAGE_TAG_REGISTRATION_RESPONSE) && (msg.id != 0) && - (msg.dump_request_handle != NULL) && - (msg.dump_generated_handle != NULL) && - (msg.server_alive_handle != NULL); + (msg.dump_request_handle != nullptr) && + (msg.dump_generated_handle != nullptr) && + (msg.server_alive_handle != nullptr); } bool CrashGenerationClient::IsRegistered() const { - return crash_event_ != NULL; + return crash_event_ != nullptr; } bool CrashGenerationClient::RequestDump(EXCEPTION_POINTERS* ex_info, @@ -345,11 +348,11 @@ bool CrashGenerationClient::RequestDump(EXCEPTION_POINTERS* ex_info, } bool CrashGenerationClient::RequestDump(EXCEPTION_POINTERS* ex_info) { - return RequestDump(ex_info, NULL); + return RequestDump(ex_info, nullptr); } bool CrashGenerationClient::RequestDump(MDRawAssertionInfo* assert_info) { - return RequestDump(NULL, assert_info); + return RequestDump(nullptr, assert_info); } bool CrashGenerationClient::SignalCrashEventAndWait() { @@ -384,8 +387,8 @@ HANDLE CrashGenerationClient::DuplicatePipeToClientProcess(const wchar_t* pipe_n HANDLE hProcess) { for (int i = 0; i < kPipeConnectMaxAttempts; ++i) { HANDLE local_pipe = CreateFile(pipe_name, kPipeDesiredAccess, - 0, NULL, OPEN_EXISTING, - kPipeFlagsAndAttributes, NULL); + 0, nullptr, OPEN_EXISTING, + kPipeFlagsAndAttributes, nullptr); if (local_pipe != INVALID_HANDLE_VALUE) { HANDLE remotePipe = INVALID_HANDLE_VALUE; if (DuplicateHandle(GetCurrentProcess(), local_pipe, diff --git a/src/client/windows/crash_generation/crash_generation_client.h b/src/client/windows/crash_generation/crash_generation_client.h index f912bf5f9..6afd044e6 100644 --- a/src/client/windows/crash_generation/crash_generation_client.h +++ b/src/client/windows/crash_generation/crash_generation_client.h @@ -34,7 +34,6 @@ #include #include #include "client/windows/common/ipc_protocol.h" -#include "common/scoped_ptr.h" namespace google_breakpad { diff --git a/src/client/windows/crash_generation/crash_generation_server.cc b/src/client/windows/crash_generation/crash_generation_server.cc index 61b0cbc0b..35596b435 100644 --- a/src/client/windows/crash_generation/crash_generation_server.cc +++ b/src/client/windows/crash_generation/crash_generation_server.cc @@ -31,12 +31,15 @@ #endif #include "client/windows/crash_generation/crash_generation_server.h" + #include -#include + +#include + #include -#include "client/windows/common/auto_critical_section.h" -#include "common/scoped_ptr.h" +#include +#include "client/windows/common/auto_critical_section.h" #include "client/windows/crash_generation/client_info.h" namespace google_breakpad { @@ -83,9 +86,9 @@ static bool IsClientRequestValid(const ProtocolMessage& msg) { return msg.tag == MESSAGE_TAG_UPLOAD_REQUEST || (msg.tag == MESSAGE_TAG_REGISTRATION_REQUEST && msg.id != 0 && - msg.thread_id != NULL && - msg.exception_pointers != NULL && - msg.assert_info != NULL); + msg.thread_id != nullptr && + msg.exception_pointers != nullptr && + msg.assert_info != nullptr); } #ifndef NDEBUG @@ -112,9 +115,9 @@ CrashGenerationServer::CrashGenerationServer( const std::wstring* dump_path) : pipe_name_(pipe_name), pipe_sec_attrs_(pipe_sec_attrs), - pipe_(NULL), - pipe_wait_handle_(NULL), - server_alive_handle_(NULL), + pipe_(nullptr), + pipe_wait_handle_(nullptr), + server_alive_handle_(nullptr), connect_callback_(connect_callback), connect_context_(connect_context), dump_callback_(dump_callback), @@ -129,7 +132,7 @@ CrashGenerationServer::CrashGenerationServer( server_state_(IPC_SERVER_STATE_UNINITIALIZED), shutting_down_(false), overlapped_(), - client_info_(NULL) { + client_info_(nullptr) { InitializeCriticalSection(&sync_); } @@ -218,16 +221,16 @@ bool CrashGenerationServer::Start() { server_state_ = IPC_SERVER_STATE_INITIAL; - server_alive_handle_ = CreateMutex(NULL, TRUE, NULL); + server_alive_handle_ = CreateMutex(nullptr, TRUE, nullptr); if (!server_alive_handle_) { return false; } // Event to signal the client connection and pipe reads and writes. - overlapped_.hEvent = CreateEvent(NULL, // Security descriptor. - TRUE, // Manual reset. - FALSE, // Initially nonsignaled. - NULL); // Name. + overlapped_.hEvent = CreateEvent(nullptr, // Security descriptor. + TRUE, // Manual reset. + FALSE, // Initially nonsignaled. + nullptr); // Name. if (!overlapped_.hEvent) { return false; } @@ -281,17 +284,17 @@ void CrashGenerationServer::HandleErrorState() { if (pipe_wait_handle_) { UnregisterWait(pipe_wait_handle_); - pipe_wait_handle_ = NULL; + pipe_wait_handle_ = nullptr; } if (pipe_) { CloseHandle(pipe_); - pipe_ = NULL; + pipe_ = nullptr; } if (overlapped_.hEvent) { CloseHandle(overlapped_.hEvent); - overlapped_.hEvent = NULL; + overlapped_.hEvent = nullptr; } } @@ -364,7 +367,7 @@ void CrashGenerationServer::HandleConnectedState() { assert(server_state_ == IPC_SERVER_STATE_CONNECTED); DWORD bytes_count = 0; - memset(&msg_, 0, sizeof(msg_)); + memset(static_cast(&msg_), 0, sizeof(msg_)); bool success = ReadFile(pipe_, &msg_, sizeof(msg_), @@ -426,7 +429,7 @@ void CrashGenerationServer::HandleReadDoneState() { return; } - scoped_ptr client_info( + std::unique_ptr client_info( new ClientInfo(this, msg_.id, msg_.dump_type, @@ -560,13 +563,13 @@ void CrashGenerationServer::HandleDisconnectingState() { assert(server_state_ == IPC_SERVER_STATE_DISCONNECTING); // Done serving the client. - client_info_ = NULL; + client_info_ = nullptr; - overlapped_.Internal = NULL; - overlapped_.InternalHigh = NULL; + overlapped_.Internal = 0; + overlapped_.InternalHigh = 0; overlapped_.Offset = 0; overlapped_.OffsetHigh = 0; - overlapped_.Pointer = NULL; + overlapped_.Pointer = nullptr; if (!ResetEvent(overlapped_.hEvent)) { EnterErrorState(); @@ -618,34 +621,34 @@ bool CrashGenerationServer::PrepareReply(const ClientInfo& client_info, if (reply->dump_request_handle) { DuplicateHandle(client_info.process_handle(), // hSourceProcessHandle reply->dump_request_handle, // hSourceHandle - NULL, // hTargetProcessHandle + nullptr, // hTargetProcessHandle 0, // lpTargetHandle 0, // dwDesiredAccess FALSE, // bInheritHandle DUPLICATE_CLOSE_SOURCE); // dwOptions - reply->dump_request_handle = NULL; + reply->dump_request_handle = nullptr; } if (reply->dump_generated_handle) { DuplicateHandle(client_info.process_handle(), // hSourceProcessHandle reply->dump_generated_handle, // hSourceHandle - NULL, // hTargetProcessHandle + nullptr, // hTargetProcessHandle 0, // lpTargetHandle 0, // dwDesiredAccess FALSE, // bInheritHandle DUPLICATE_CLOSE_SOURCE); // dwOptions - reply->dump_generated_handle = NULL; + reply->dump_generated_handle = nullptr; } if (reply->server_alive_handle) { DuplicateHandle(client_info.process_handle(), // hSourceProcessHandle reply->server_alive_handle, // hSourceHandle - NULL, // hTargetProcessHandle + nullptr, // hTargetProcessHandle 0, // lpTargetHandle 0, // dwDesiredAccess FALSE, // bInheritHandle DUPLICATE_CLOSE_SOURCE); // dwOptions - reply->server_alive_handle = NULL; + reply->server_alive_handle = nullptr; } return false; @@ -773,7 +776,7 @@ void CrashGenerationServer::HandleConnectionRequest() { } bool CrashGenerationServer::AddClient(ClientInfo* client_info) { - HANDLE request_wait_handle = NULL; + HANDLE request_wait_handle = nullptr; if (!RegisterWaitForSingleObject(&request_wait_handle, client_info->dump_requested_handle(), OnDumpRequest, @@ -786,7 +789,7 @@ bool CrashGenerationServer::AddClient(ClientInfo* client_info) { client_info->set_dump_request_wait_handle(request_wait_handle); // OnClientEnd will be called when the client process terminates. - HANDLE process_wait_handle = NULL; + HANDLE process_wait_handle = nullptr; if (!RegisterWaitForSingleObject(&process_wait_handle, client_info->process_handle(), OnClientEnd, @@ -892,7 +895,7 @@ void CrashGenerationServer::HandleDumpRequest(const ClientInfo& client_info) { } if (dump_callback_ && execute_callback) { - std::wstring* ptr_dump_path = (dump_path == L"") ? NULL : &dump_path; + std::wstring* ptr_dump_path = (dump_path == L"") ? nullptr : &dump_path; dump_callback_(dump_context_, &client_info, ptr_dump_path); } @@ -906,7 +909,7 @@ bool CrashGenerationServer::GenerateDump(const ClientInfo& client, // We have to get the address of EXCEPTION_INFORMATION from // the client process address space. - EXCEPTION_POINTERS* client_ex_info = NULL; + EXCEPTION_POINTERS* client_ex_info = nullptr; if (!client.GetClientExceptionInfo(&client_ex_info)) { return false; } diff --git a/src/client/windows/crash_generation/crash_generation_server.h b/src/client/windows/crash_generation/crash_generation_server.h index 74275a748..b7004d6a9 100644 --- a/src/client/windows/crash_generation/crash_generation_server.h +++ b/src/client/windows/crash_generation/crash_generation_server.h @@ -33,7 +33,6 @@ #include #include "client/windows/common/ipc_protocol.h" #include "client/windows/crash_generation/minidump_generator.h" -#include "common/scoped_ptr.h" namespace google_breakpad { class ClientInfo; diff --git a/src/client/windows/crash_generation/minidump_generator.cc b/src/client/windows/crash_generation/minidump_generator.cc index a0454cf94..3811d4acb 100644 --- a/src/client/windows/crash_generation/minidump_generator.cc +++ b/src/client/windows/crash_generation/minidump_generator.cc @@ -104,9 +104,9 @@ class HandleTraceData { }; HandleTraceData::HandleTraceData() - : verifier_module_(NULL), - enumerate_resource_(NULL), - handle_(NULL) { + : verifier_module_(nullptr), + enumerate_resource_(nullptr), + handle_(0) { } HandleTraceData::~HandleTraceData() { @@ -211,7 +211,7 @@ bool HandleTraceData::ReadExceptionCode( exception_pointers, &pointers, sizeof(pointers), - NULL)) { + nullptr)) { return false; } @@ -219,7 +219,7 @@ bool HandleTraceData::ReadExceptionCode( pointers.ExceptionRecord, exception_code, sizeof(*exception_code), - NULL)) { + nullptr)) { return false; } @@ -261,10 +261,10 @@ MinidumpGenerator::MinidumpGenerator( MDRawAssertionInfo* assert_info, const MINIDUMP_TYPE dump_type, const bool is_client_pointers) - : dbghelp_module_(NULL), - write_dump_(NULL), - rpcrt4_module_(NULL), - create_uuid_(NULL), + : dbghelp_module_(nullptr), + write_dump_(nullptr), + rpcrt4_module_(nullptr), + create_uuid_(nullptr), process_handle_(process_handle), process_id_(process_id), thread_id_(thread_id), @@ -279,8 +279,8 @@ MinidumpGenerator::MinidumpGenerator( full_dump_file_(INVALID_HANDLE_VALUE), dump_file_is_internal_(false), full_dump_file_is_internal_(false), - additional_streams_(NULL), - callback_info_(NULL) { + additional_streams_(nullptr), + callback_info_(nullptr) { uuid_ = {0}; InitializeCriticalSection(&module_load_sync_); InitializeCriticalSection(&get_proc_address_sync_); @@ -319,7 +319,7 @@ bool MinidumpGenerator::WriteMinidump() { return false; } - MINIDUMP_EXCEPTION_INFORMATION* dump_exception_pointers = NULL; + MINIDUMP_EXCEPTION_INFORMATION* dump_exception_pointers = nullptr; MINIDUMP_EXCEPTION_INFORMATION dump_exception_info; // Setup the exception information object only if it's a dump @@ -437,7 +437,7 @@ bool MinidumpGenerator::WriteMinidump() { | MiniDumpWithHandleData), dump_exception_pointers, &user_streams, - NULL) != FALSE; + nullptr) != FALSE; } // Add handle operations trace stream to the minidump if it was collected. @@ -474,10 +474,10 @@ bool MinidumpGenerator::GenerateDumpFile(wstring* dump_path) { dump_file_ = CreateFile(dump_file_path.c_str(), GENERIC_WRITE, 0, - NULL, + nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, - NULL); + nullptr); if (dump_file_ == INVALID_HANDLE_VALUE) { return false; } @@ -509,10 +509,10 @@ bool MinidumpGenerator::GenerateFullDumpFile(wstring* full_dump_path) { full_dump_file_ = CreateFile(full_dump_file_path.c_str(), GENERIC_WRITE, 0, - NULL, + nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, - NULL); + nullptr); if (full_dump_file_ == INVALID_HANDLE_VALUE) { return false; } diff --git a/src/client/windows/handler/exception_handler.cc b/src/client/windows/handler/exception_handler.cc index 64b297999..12c48067a 100644 --- a/src/client/windows/handler/exception_handler.cc +++ b/src/client/windows/handler/exception_handler.cc @@ -30,17 +30,18 @@ #include // Must come first #endif +#include "client/windows/handler/exception_handler.h" + +#include #include +#include #include -#include -#include - -#include "common/windows/string_utils-inl.h" +#include #include "client/windows/common/ipc_protocol.h" -#include "client/windows/handler/exception_handler.h" #include "common/windows/guid_string.h" +#include "common/windows/string_utils-inl.h" namespace google_breakpad { @@ -55,7 +56,7 @@ typedef struct { #define DBG_PRINTEXCEPTION_WIDE_C ((DWORD)0x4001000A) #endif -vector* ExceptionHandler::handler_stack_ = NULL; +vector* ExceptionHandler::handler_stack_ = nullptr; LONG ExceptionHandler::handler_stack_index_ = 0; CRITICAL_SECTION ExceptionHandler::handler_stack_critical_section_; volatile LONG ExceptionHandler::instance_count_ = 0; @@ -75,8 +76,8 @@ ExceptionHandler::ExceptionHandler(const wstring& dump_path, handler_types, dump_type, pipe_name, - NULL, // pipe_handle - NULL, // crash_generation_client + nullptr, // pipe_handle + nullptr, // crash_generation_client custom_info); } @@ -94,9 +95,9 @@ ExceptionHandler::ExceptionHandler(const wstring& dump_path, callback_context, handler_types, dump_type, - NULL, // pipe_name + nullptr, // pipe_name pipe_handle, - NULL, // crash_generation_client + nullptr, // crash_generation_client custom_info); } @@ -115,10 +116,10 @@ ExceptionHandler::ExceptionHandler( callback_context, handler_types, MiniDumpNormal, // dump_type - not used - NULL, // pipe_name - not used - NULL, // pipe_handle + nullptr, // pipe_name - not used + nullptr, // pipe_handle crash_generation_client, - NULL); // custom_info - not used + nullptr); // custom_info - not used } ExceptionHandler::ExceptionHandler(const wstring& dump_path, @@ -132,10 +133,10 @@ ExceptionHandler::ExceptionHandler(const wstring& dump_path, callback_context, handler_types, MiniDumpNormal, - NULL, // pipe_name - NULL, // pipe_handle - NULL, // crash_generation_client - NULL); // custom_info + nullptr, // pipe_name + nullptr, // pipe_handle + nullptr, // crash_generation_client + nullptr); // custom_info } void ExceptionHandler::Initialize( @@ -153,34 +154,34 @@ void ExceptionHandler::Initialize( filter_ = filter; callback_ = callback; callback_context_ = callback_context; - dump_path_c_ = NULL; - next_minidump_id_c_ = NULL; - next_minidump_path_c_ = NULL; - dbghelp_module_ = NULL; - minidump_write_dump_ = NULL; + dump_path_c_ = nullptr; + next_minidump_id_c_ = nullptr; + next_minidump_path_c_ = nullptr; + dbghelp_module_ = nullptr; + minidump_write_dump_ = nullptr; dump_type_ = dump_type; - rpcrt4_module_ = NULL; - uuid_create_ = NULL; + rpcrt4_module_ = nullptr; + uuid_create_ = nullptr; handler_types_ = handler_types; - previous_filter_ = NULL; + previous_filter_ = nullptr; #if _MSC_VER >= 1400 // MSVC 2005/8 - previous_iph_ = NULL; + previous_iph_ = nullptr; #endif // _MSC_VER >= 1400 - previous_pch_ = NULL; - handler_thread_ = NULL; + previous_pch_ = nullptr; + handler_thread_ = nullptr; is_shutdown_ = false; - handler_start_semaphore_ = NULL; - handler_finish_semaphore_ = NULL; + handler_start_semaphore_ = nullptr; + handler_finish_semaphore_ = nullptr; requesting_thread_id_ = 0; - exception_info_ = NULL; - assertion_ = NULL; + exception_info_ = nullptr; + assertion_ = nullptr; handler_return_value_ = false; handle_debug_exceptions_ = false; consume_invalid_handle_exceptions_ = false; // Attempt to use out-of-process if user has specified a pipe or a // crash generation client. - scoped_ptr client; + std::unique_ptr client; if (crash_generation_client) { client.reset(crash_generation_client); } else if (pipe_name) { @@ -191,7 +192,7 @@ void ExceptionHandler::Initialize( new CrashGenerationClient(pipe_handle, dump_type_, custom_info)); } - if (client.get() != NULL) { + if (client.get() != nullptr) { // If successful in registering with the monitoring process, // there is no need to setup in-process crash generation. if (client->Register()) { @@ -210,23 +211,24 @@ void ExceptionHandler::Initialize( // and it allows an easy way to get a snapshot of the requesting thread's // context outside of an exception. InitializeCriticalSection(&handler_critical_section_); - handler_start_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL); - assert(handler_start_semaphore_ != NULL); + handler_start_semaphore_ = CreateSemaphore(nullptr, 0, 1, nullptr); + assert(handler_start_semaphore_ != nullptr); - handler_finish_semaphore_ = CreateSemaphore(NULL, 0, 1, NULL); - assert(handler_finish_semaphore_ != NULL); + handler_finish_semaphore_ = CreateSemaphore(nullptr, 0, 1, nullptr); + assert(handler_finish_semaphore_ != nullptr); // Don't attempt to create the thread if we could not create the semaphores. - if (handler_finish_semaphore_ != NULL && handler_start_semaphore_ != NULL) { + if (handler_finish_semaphore_ != nullptr && + handler_start_semaphore_ != nullptr) { DWORD thread_id; const int kExceptionHandlerThreadInitialStackSize = 64 * 1024; - handler_thread_ = CreateThread(NULL, // lpThreadAttributes + handler_thread_ = CreateThread(nullptr, // lpThreadAttributes kExceptionHandlerThreadInitialStackSize, ExceptionHandlerThreadMain, this, // lpParameter 0, // dwCreationFlags &thread_id); - assert(handler_thread_ != NULL); + assert(handler_thread_ != nullptr); } dbghelp_module_ = LoadLibrary(L"dbghelp.dll"); @@ -251,7 +253,7 @@ void ExceptionHandler::Initialize( // Reserve one element for the instruction memory AppMemory instruction_memory; - instruction_memory.ptr = NULL; + instruction_memory.ptr = reinterpret_cast(nullptr); instruction_memory.length = 0; app_memory_info_.push_back(instruction_memory); @@ -338,7 +340,7 @@ ExceptionHandler::~ExceptionHandler() { // When destroying the last ExceptionHandler that installed a handler, // clean up the handler stack. delete handler_stack_; - handler_stack_ = NULL; + handler_stack_ = nullptr; } LeaveCriticalSection(&handler_stack_critical_section_); @@ -355,7 +357,7 @@ ExceptionHandler::~ExceptionHandler() { // deadlock if the exception handler is destroyed while executing code // inside DllMain. is_shutdown_ = true; - ReleaseSemaphore(handler_start_semaphore_, 1, NULL); + ReleaseSemaphore(handler_start_semaphore_, 1, nullptr); const int kWaitForHandlerThreadMs = 60000; WaitForSingleObject(handler_thread_, kWaitForHandlerThreadMs); #else @@ -363,7 +365,7 @@ ExceptionHandler::~ExceptionHandler() { #endif // BREAKPAD_NO_TERMINATE_THREAD CloseHandle(handler_thread_); - handler_thread_ = NULL; + handler_thread_ = nullptr; DeleteCriticalSection(&handler_critical_section_); CloseHandle(handler_start_semaphore_); CloseHandle(handler_finish_semaphore_); @@ -388,8 +390,8 @@ bool ExceptionHandler::RequestUpload(DWORD crash_id) { DWORD ExceptionHandler::ExceptionHandlerThreadMain(void* lpParameter) { ExceptionHandler* self = reinterpret_cast(lpParameter); assert(self); - assert(self->handler_start_semaphore_ != NULL); - assert(self->handler_finish_semaphore_ != NULL); + assert(self->handler_start_semaphore_ != nullptr); + assert(self->handler_finish_semaphore_ != nullptr); for (;;) { if (WaitForSingleObject(self->handler_start_semaphore_, INFINITE) == @@ -406,7 +408,7 @@ DWORD ExceptionHandler::ExceptionHandlerThreadMain(void* lpParameter) { } // Allow the requesting thread to proceed. - ReleaseSemaphore(self->handler_finish_semaphore_, 1, NULL); + ReleaseSemaphore(self->handler_finish_semaphore_, 1, nullptr); } } @@ -507,9 +509,9 @@ LONG ExceptionHandler::HandleException(EXCEPTION_POINTERS* exinfo) { success = current_handler->WriteMinidumpWithException( GetCurrentThreadId(), exinfo, - NULL); + nullptr); } else { - success = current_handler->WriteMinidumpOnHandlerThread(exinfo, NULL); + success = current_handler->WriteMinidumpOnHandlerThread(exinfo, nullptr); } } @@ -707,14 +709,14 @@ bool ExceptionHandler::WriteMinidumpOnHandlerThread( // There isn't much we can do if the handler thread // was not successfully created. - if (handler_thread_ == NULL) { + if (handler_thread_ == nullptr) { LeaveCriticalSection(&handler_critical_section_); return false; } // The handler thread should only be created when the semaphores are valid. - assert(handler_start_semaphore_ != NULL); - assert(handler_finish_semaphore_ != NULL); + assert(handler_start_semaphore_ != nullptr); + assert(handler_finish_semaphore_ != nullptr); // Set up data to be passed in to the handler thread. requesting_thread_id_ = GetCurrentThreadId(); @@ -722,7 +724,7 @@ bool ExceptionHandler::WriteMinidumpOnHandlerThread( assertion_ = assertion; // This causes the handler thread to call WriteMinidumpWithException. - ReleaseSemaphore(handler_start_semaphore_, 1, NULL); + ReleaseSemaphore(handler_start_semaphore_, 1, nullptr); // Wait until WriteMinidumpWithException is done and collect its return value. WaitForSingleObject(handler_finish_semaphore_, INFINITE); @@ -730,8 +732,8 @@ bool ExceptionHandler::WriteMinidumpOnHandlerThread( // Clean up. requesting_thread_id_ = 0; - exception_info_ = NULL; - assertion_ = NULL; + exception_info_ = nullptr; + assertion_ = nullptr; LeaveCriticalSection(&handler_critical_section_); @@ -759,10 +761,10 @@ bool ExceptionHandler::WriteMinidumpForException(EXCEPTION_POINTERS* exinfo) { if (IsOutOfProcess()) { return WriteMinidumpWithException(GetCurrentThreadId(), exinfo, - NULL); + nullptr); } - bool success = WriteMinidumpOnHandlerThread(exinfo, NULL); + bool success = WriteMinidumpOnHandlerThread(exinfo, nullptr); UpdateNextID(); return success; } @@ -772,8 +774,8 @@ bool ExceptionHandler::WriteMinidump(const wstring& dump_path, MinidumpCallback callback, void* callback_context, MINIDUMP_TYPE dump_type) { - ExceptionHandler handler(dump_path, NULL, callback, callback_context, - HANDLER_NONE, dump_type, (HANDLE)NULL, NULL); + ExceptionHandler handler(dump_path, nullptr, callback, callback_context, + HANDLER_NONE, dump_type, (HANDLE)nullptr, nullptr); return handler.WriteMinidump(); } @@ -786,7 +788,7 @@ bool ExceptionHandler::WriteMinidumpForChild(HANDLE child, MINIDUMP_TYPE dump_type) { EXCEPTION_RECORD ex; CONTEXT ctx; - EXCEPTION_POINTERS exinfo = { NULL, NULL }; + EXCEPTION_POINTERS exinfo = { nullptr, nullptr }; // As documented on MSDN, on failure SuspendThread returns (DWORD) -1 const DWORD kFailedToSuspendThread = static_cast(-1); DWORD last_suspend_count = kFailedToSuspendThread; @@ -797,7 +799,7 @@ bool ExceptionHandler::WriteMinidumpForChild(HANDLE child, child_blamed_thread); // This thread may have died already, so not opening the handle is a // non-fatal error. - if (child_thread_handle != NULL) { + if (child_thread_handle != nullptr) { last_suspend_count = SuspendThread(child_thread_handle); if (last_suspend_count != kFailedToSuspendThread) { ctx.ContextFlags = CONTEXT_ALL; @@ -815,12 +817,12 @@ bool ExceptionHandler::WriteMinidumpForChild(HANDLE child, } } - ExceptionHandler handler(dump_path, NULL, callback, callback_context, - HANDLER_NONE, dump_type, (HANDLE)NULL, NULL); + ExceptionHandler handler(dump_path, nullptr, callback, callback_context, + HANDLER_NONE, dump_type, (HANDLE)nullptr, nullptr); bool success = handler.WriteMinidumpWithExceptionForProcess( child_blamed_thread, - exinfo.ExceptionRecord ? &exinfo : NULL, - NULL, child, false); + exinfo.ExceptionRecord ? &exinfo : nullptr, + nullptr, child, false); if (last_suspend_count != kFailedToSuspendThread) { ResumeThread(child_thread_handle); @@ -830,7 +832,7 @@ bool ExceptionHandler::WriteMinidumpForChild(HANDLE child, if (callback) { success = callback(handler.dump_path_c_, handler.next_minidump_id_c_, - callback_context, NULL, NULL, success); + callback_context, nullptr, nullptr, success); } return success; @@ -923,10 +925,10 @@ bool ExceptionHandler::WriteMinidumpWithExceptionForProcess( HANDLE dump_file = CreateFile(next_minidump_path_c_, GENERIC_WRITE, 0, // no sharing - NULL, + nullptr, CREATE_NEW, // fail if exists FILE_ATTRIBUTE_NORMAL, - NULL); + nullptr); if (dump_file != INVALID_HANDLE_VALUE) { MINIDUMP_EXCEPTION_INFORMATION except_info; except_info.ThreadId = requesting_thread_id; @@ -1029,7 +1031,7 @@ bool ExceptionHandler::WriteMinidumpWithExceptionForProcess( GetProcessId(process), dump_file, dump_type_, - exinfo ? &except_info : NULL, + exinfo ? &except_info : nullptr, &user_streams, &callback) == TRUE); diff --git a/src/client/windows/handler/exception_handler.h b/src/client/windows/handler/exception_handler.h index 963572bf3..37ee68aaa 100644 --- a/src/client/windows/handler/exception_handler.h +++ b/src/client/windows/handler/exception_handler.h @@ -65,12 +65,12 @@ #pragma warning(disable:4530) #include +#include #include #include #include "client/windows/common/ipc_protocol.h" #include "client/windows/crash_generation/crash_generation_client.h" -#include "common/scoped_ptr.h" #include "google_breakpad/common/minidump_format.h" namespace google_breakpad { @@ -274,7 +274,9 @@ class ExceptionHandler { } // Returns whether out-of-process dump generation is used or not. - bool IsOutOfProcess() const { return crash_generation_client_.get() != NULL; } + bool IsOutOfProcess() const { + return crash_generation_client_.get() != nullptr; + } // Calling RegisterAppMemory(p, len) causes len bytes starting // at address p to be copied to the minidump when a crash happens. @@ -385,7 +387,7 @@ class ExceptionHandler { MinidumpCallback callback_; void* callback_context_; - scoped_ptr crash_generation_client_; + std::unique_ptr crash_generation_client_; // The directory in which a minidump will be written, set by the dump_path // argument to the constructor, or set_dump_path. diff --git a/src/client/windows/sender/crash_report_sender.cc b/src/client/windows/sender/crash_report_sender.cc index 6ce0026ce..1433bd722 100644 --- a/src/client/windows/sender/crash_report_sender.cc +++ b/src/client/windows/sender/crash_report_sender.cc @@ -72,7 +72,7 @@ ReportResult CrashReportSender::SendCrashReport( int http_response = 0; bool result = HTTPUpload::SendMultipartPostRequest( - url, parameters, files, NULL, report_code, + url, parameters, files, nullptr, report_code, &http_response); if (result) { @@ -135,7 +135,7 @@ int CrashReportSender::OpenCheckpointFile(const wchar_t* mode, FILE** fd) { return _wfopen_s(fd, checkpoint_file_.c_str(), mode); #else *fd = _wfopen(checkpoint_file_.c_str(), mode); - if (*fd == NULL) { + if (*fd == nullptr) { return errno; } return 0; diff --git a/src/client/windows/tests/crash_generation_app/crash_generation_app.cc b/src/client/windows/tests/crash_generation_app/crash_generation_app.cc index 9ae4679e3..7bc22286e 100644 --- a/src/client/windows/tests/crash_generation_app/crash_generation_app.cc +++ b/src/client/windows/tests/crash_generation_app/crash_generation_app.cc @@ -62,7 +62,7 @@ const DWORD kEditBoxStyles = WS_CHILD | const size_t kMaximumLineLength = 256; // CS to access edit control in a thread safe way. -static CRITICAL_SECTION* cs_edit = NULL; +static CRITICAL_SECTION* cs_edit = nullptr; // Edit control. static HWND client_status_edit_box; @@ -82,8 +82,8 @@ static CustomInfoEntry kCustomInfoEntries[] = { CustomInfoEntry(L"ver", L"1.0"), }; -static ExceptionHandler* handler = NULL; -static CrashGenerationServer* crash_server = NULL; +static ExceptionHandler* handler = nullptr; +static CrashGenerationServer* crash_server = nullptr; // Registers the window class. // @@ -102,7 +102,7 @@ ATOM MyRegisterClass(HINSTANCE instance) { wcex.hInstance = instance; wcex.hIcon = LoadIcon(instance, MAKEINTRESOURCE(IDI_CRASHGENERATIONAPP)); - wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCE(IDC_CRASHGENERATIONAPP); wcex.lpszClassName = window_class; @@ -124,10 +124,10 @@ BOOL InitInstance(HINSTANCE instance, int command_show) { 0, CW_USEDEFAULT, 0, - NULL, - NULL, + nullptr, + nullptr, instance, - NULL); + nullptr); if (!wnd) { return FALSE; @@ -288,33 +288,33 @@ void CrashServerStart() { std::wstring dump_path = L"C:\\Dumps\\"; if (_wmkdir(dump_path.c_str()) && (errno != EEXIST)) { - MessageBoxW(NULL, L"Unable to create dump directory", L"Dumper", MB_OK); + MessageBoxW(nullptr, L"Unable to create dump directory", L"Dumper", MB_OK); return; } crash_server = new CrashGenerationServer(kPipeName, - NULL, + nullptr, ShowClientConnected, - NULL, + nullptr, ShowClientCrashed, - NULL, + nullptr, ShowClientExited, - NULL, - NULL, - NULL, + nullptr, + nullptr, + nullptr, true, &dump_path); if (!crash_server->Start()) { - MessageBoxW(NULL, L"Unable to start server", L"Dumper", MB_OK); + MessageBoxW(nullptr, L"Unable to start server", L"Dumper", MB_OK); delete crash_server; - crash_server = NULL; + crash_server = nullptr; } } void CrashServerStop() { delete crash_server; - crash_server = NULL; + crash_server = nullptr; } void DerefZeroCrash() { @@ -323,7 +323,7 @@ void DerefZeroCrash() { } void InvalidParamCrash() { - printf(NULL); + printf(nullptr); } void PureCallCrash() { @@ -332,7 +332,7 @@ void PureCallCrash() { void RequestDump() { if (!handler->WriteMinidump()) { - MessageBoxW(NULL, L"Dump request failed", L"Dumper", MB_OK); + MessageBoxW(nullptr, L"Dump request failed", L"Dumper", MB_OK); } kCustomInfoEntries[1].set_value(L"1.1"); } @@ -407,16 +407,16 @@ LRESULT CALLBACK WndProc(HWND wnd, break; case WM_CREATE: client_status_edit_box = CreateWindow(TEXT("EDIT"), - NULL, + nullptr, kEditBoxStyles, 0, 0, 0, 0, wnd, - NULL, + nullptr, instance, - NULL); + nullptr); break; case WM_SIZE: // Make the edit control the size of the window's client area. @@ -487,9 +487,9 @@ int APIENTRY _tWinMain(HINSTANCE instance, // failures and instead let the code handle it. _CrtSetReportMode(_CRT_ASSERT, 0); handler = new ExceptionHandler(L"C:\\dumps\\", - NULL, + nullptr, google_breakpad::ShowDumpResults, - NULL, + nullptr, ExceptionHandler::HANDLER_ALL, MiniDumpNormal, kPipeName, @@ -514,7 +514,7 @@ int APIENTRY _tWinMain(HINSTANCE instance, // Main message loop. MSG msg; - while (GetMessage(&msg, NULL, 0, 0)) { + while (GetMessage(&msg, nullptr, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, accel_table, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); diff --git a/src/client/windows/unittests/crash_generation_server_test.cc b/src/client/windows/unittests/crash_generation_server_test.cc index adb03f400..cc117040b 100644 --- a/src/client/windows/unittests/crash_generation_server_test.cc +++ b/src/client/windows/unittests/crash_generation_server_test.cc @@ -61,15 +61,15 @@ class CrashGenerationServerTest : public ::testing::Test { public: CrashGenerationServerTest() : crash_generation_server_(kPipeName, - NULL, + nullptr, CallOnClientConnected, &mock_callbacks_, CallOnClientDumpRequested, &mock_callbacks_, CallOnClientExited, &mock_callbacks_, CallOnClientUploadRequested, &mock_callbacks_, false, - NULL), + nullptr), thread_id_(0), - exception_pointers_(NULL) { + exception_pointers_(nullptr) { memset(&assert_info_, 0, sizeof(assert_info_)); } @@ -106,10 +106,10 @@ class CrashGenerationServerTest : public ::testing::Test { HANDLE pipe = CreateFile(kPipeName, kPipeDesiredAccess, 0, - NULL, + nullptr, OPEN_EXISTING, kPipeFlagsAndAttributes, - NULL); + nullptr); if (pipe == INVALID_HANDLE_VALUE) { ASSERT_EQ(ERROR_PIPE_BUSY, GetLastError()); @@ -120,16 +120,16 @@ class CrashGenerationServerTest : public ::testing::Test { pipe = CreateFile(kPipeName, kPipeDesiredAccess, 0, - NULL, + nullptr, OPEN_EXISTING, kPipeFlagsAndAttributes, - NULL); + nullptr); } ASSERT_NE(pipe, INVALID_HANDLE_VALUE); DWORD mode = kPipeMode; - ASSERT_TRUE(SetNamedPipeHandleState(pipe, &mode, NULL, NULL)); + ASSERT_TRUE(SetNamedPipeHandleState(pipe, &mode, nullptr, nullptr)); DoFaultyClient(fault_type, pipe); @@ -177,9 +177,9 @@ class CrashGenerationServerTest : public ::testing::Test { &exception_pointers_, &assert_info_, custom_info, - NULL, - NULL, - NULL); + nullptr, + nullptr, + nullptr); DWORD bytes_count = 0; @@ -188,7 +188,7 @@ class CrashGenerationServerTest : public ::testing::Test { fault_type == TRUNCATE_REGISTRATION ? sizeof(msg) / 2 : sizeof(msg), &bytes_count, - NULL)); + nullptr)); if (fault_type == CLOSE_AFTER_REGISTRATION) { return; @@ -202,7 +202,7 @@ class CrashGenerationServerTest : public ::testing::Test { sizeof(google_breakpad::ProtocolMessage) / 2 : sizeof(google_breakpad::ProtocolMessage), &bytes_count, - NULL)) { + nullptr)) { switch (fault_type) { case TRUNCATE_REGISTRATION: case RESPONSE_BUFFER_TOO_SMALL: @@ -226,7 +226,7 @@ class CrashGenerationServerTest : public ::testing::Test { SEND_INVALID_ACK ? sizeof(ack_msg) : sizeof(ack_msg) / 2, &bytes_count, - NULL)); + nullptr)); return; } diff --git a/src/client/windows/unittests/dump_analysis.cc b/src/client/windows/unittests/dump_analysis.cc index c403d8556..5dd3dc338 100644 --- a/src/client/windows/unittests/dump_analysis.cc +++ b/src/client/windows/unittests/dump_analysis.cc @@ -38,52 +38,52 @@ #include "client/windows/unittests/dump_analysis.h" // NOLINT DumpAnalysis::~DumpAnalysis() { - if (dump_file_view_ != NULL) { + if (dump_file_view_ != nullptr) { EXPECT_TRUE(::UnmapViewOfFile(dump_file_view_)); ::CloseHandle(dump_file_mapping_); - dump_file_mapping_ = NULL; + dump_file_mapping_ = nullptr; } - if (dump_file_handle_ != NULL) { + if (dump_file_handle_ != nullptr) { ::CloseHandle(dump_file_handle_); - dump_file_handle_ = NULL; + dump_file_handle_ = nullptr; } } void DumpAnalysis::EnsureDumpMapped() { - if (dump_file_view_ == NULL) { + if (dump_file_view_ == nullptr) { dump_file_handle_ = ::CreateFile(dump_file_.c_str(), GENERIC_READ, 0, - NULL, + nullptr, OPEN_EXISTING, 0, - NULL); - ASSERT_TRUE(dump_file_handle_ != NULL); - ASSERT_TRUE(dump_file_mapping_ == NULL); + nullptr); + ASSERT_TRUE(dump_file_handle_ != nullptr); + ASSERT_TRUE(dump_file_mapping_ == nullptr); dump_file_mapping_ = ::CreateFileMapping(dump_file_handle_, - NULL, + nullptr, PAGE_READONLY, 0, 0, - NULL); - ASSERT_TRUE(dump_file_mapping_ != NULL); + nullptr); + ASSERT_TRUE(dump_file_mapping_ != nullptr); dump_file_view_ = ::MapViewOfFile(dump_file_mapping_, FILE_MAP_READ, 0, 0, 0); - ASSERT_TRUE(dump_file_view_ != NULL); + ASSERT_TRUE(dump_file_view_ != nullptr); } } bool DumpAnalysis::HasTebs() const { - MINIDUMP_THREAD_LIST* thread_list = NULL; + MINIDUMP_THREAD_LIST* thread_list = nullptr; size_t thread_list_size = GetStream(ThreadListStream, &thread_list); - if (thread_list_size > 0 && thread_list != NULL) { + if (thread_list_size > 0 && thread_list != nullptr) { for (ULONG i = 0; i < thread_list->NumberOfThreads; ++i) { if (!HasMemory(thread_list->Threads[i].Teb)) return false; @@ -97,12 +97,12 @@ bool DumpAnalysis::HasTebs() const { } bool DumpAnalysis::HasPeb() const { - MINIDUMP_THREAD_LIST* thread_list = NULL; + MINIDUMP_THREAD_LIST* thread_list = nullptr; size_t thread_list_size = GetStream(ThreadListStream, &thread_list); - if (thread_list_size > 0 && thread_list != NULL && + if (thread_list_size > 0 && thread_list != nullptr && thread_list->NumberOfThreads > 0) { - FakeTEB* teb = NULL; + FakeTEB* teb = nullptr; if (!HasMemory(thread_list->Threads[0].Teb, &teb)) return false; @@ -113,13 +113,13 @@ bool DumpAnalysis::HasPeb() const { } bool DumpAnalysis::HasStream(ULONG stream_number) const { - void* stream = NULL; + void* stream = nullptr; size_t stream_size = GetStreamImpl(stream_number, &stream); - return stream_size > 0 && stream != NULL; + return stream_size > 0 && stream != nullptr; } size_t DumpAnalysis::GetStreamImpl(ULONG stream_number, void** stream) const { - MINIDUMP_DIRECTORY* directory = NULL; + MINIDUMP_DIRECTORY* directory = nullptr; ULONG memory_list_size = 0; BOOL ret = ::MiniDumpReadDumpStream(dump_file_view_, stream_number, @@ -133,9 +133,9 @@ size_t DumpAnalysis::GetStreamImpl(ULONG stream_number, void** stream) const { bool DumpAnalysis::HasMemoryImpl(const void* addr_in, size_t structuresize, void** structure) const { uintptr_t address = reinterpret_cast(addr_in); - MINIDUMP_MEMORY_LIST* memory_list = NULL; + MINIDUMP_MEMORY_LIST* memory_list = nullptr; size_t memory_list_size = GetStream(MemoryListStream, &memory_list); - if (memory_list_size > 0 && memory_list != NULL) { + if (memory_list_size > 0 && memory_list != nullptr) { for (ULONG i = 0; i < memory_list->NumberOfMemoryRanges; ++i) { MINIDUMP_MEMORY_DESCRIPTOR& descr = memory_list->MemoryRanges[i]; const uintptr_t range_start = @@ -146,7 +146,7 @@ bool DumpAnalysis::HasMemoryImpl(const void* addr_in, size_t structuresize, address + structuresize < range_end) { // The start address falls in the range, and the end address is // in bounds, return a pointer to the structure if requested. - if (structure != NULL) + if (structure != nullptr) *structure = RVA_TO_ADDR(dump_file_view_, descr.Memory.Rva); return true; @@ -157,9 +157,9 @@ bool DumpAnalysis::HasMemoryImpl(const void* addr_in, size_t structuresize, // We didn't find the range in a MINIDUMP_MEMORY_LIST, so maybe this // is a full dump using MINIDUMP_MEMORY64_LIST with all the memory at the // end of the dump file. - MINIDUMP_MEMORY64_LIST* memory64_list = NULL; + MINIDUMP_MEMORY64_LIST* memory64_list = nullptr; memory_list_size = GetStream(Memory64ListStream, &memory64_list); - if (memory_list_size > 0 && memory64_list != NULL) { + if (memory_list_size > 0 && memory64_list != nullptr) { // Keep track of where the current descriptor maps to. RVA64 curr_rva = memory64_list->BaseRva; for (ULONG i = 0; i < memory64_list->NumberOfMemoryRanges; ++i) { @@ -172,7 +172,7 @@ bool DumpAnalysis::HasMemoryImpl(const void* addr_in, size_t structuresize, address + structuresize < range_end) { // The start address falls in the range, and the end address is // in bounds, return a pointer to the structure if requested. - if (structure != NULL) + if (structure != nullptr) *structure = RVA_TO_ADDR(dump_file_view_, curr_rva); return true; diff --git a/src/client/windows/unittests/dump_analysis.h b/src/client/windows/unittests/dump_analysis.h index f8acc268d..87116b902 100644 --- a/src/client/windows/unittests/dump_analysis.h +++ b/src/client/windows/unittests/dump_analysis.h @@ -40,8 +40,10 @@ struct FakeTEB { class DumpAnalysis { public: explicit DumpAnalysis(const std::wstring& file_path) - : dump_file_(file_path), dump_file_view_(NULL), dump_file_mapping_(NULL), - dump_file_handle_(NULL) { + : dump_file_(file_path), + dump_file_view_(nullptr), + dump_file_mapping_(nullptr), + dump_file_handle_(nullptr) { EnsureDumpMapped(); } ~DumpAnalysis(); @@ -59,15 +61,15 @@ class DumpAnalysis { bool HasTebs() const; bool HasPeb() const; bool HasMemory(ULONG64 address) const { - return HasMemory(address, NULL); + return HasMemory(address, nullptr); } bool HasMemory(const void* address) const { - return HasMemory(address, NULL); + return HasMemory(address, nullptr); } template - bool HasMemory(ULONG64 address, StructureType** structure = NULL) const { + bool HasMemory(ULONG64 address, StructureType** structure = nullptr) const { // We can't cope with 64 bit addresses for now. if (address > 0xFFFFFFFFUL) return false; @@ -76,7 +78,8 @@ class DumpAnalysis { } template - bool HasMemory(const void* addr_in, StructureType** structure = NULL) const { + bool HasMemory(const void* addr_in, + StructureType** structure = nullptr) const { return HasMemoryImpl(addr_in, sizeof(StructureType), reinterpret_cast(structure)); } diff --git a/src/client/windows/unittests/exception_handler_death_test.cc b/src/client/windows/unittests/exception_handler_death_test.cc index 50d3fda9d..5d456a7df 100644 --- a/src/client/windows/unittests/exception_handler_death_test.cc +++ b/src/client/windows/unittests/exception_handler_death_test.cc @@ -30,12 +30,14 @@ #include // Must come first #endif +#include #include #include #include #include #include +#include #include #include "breakpad_googletest_includes.h" @@ -92,7 +94,7 @@ void ExceptionHandlerDeathTest::SetUp() { assert(false); } StringCchPrintfW(temp_path_, MAX_PATH, L"%s%s", temp_path, test_name_wide); - CreateDirectory(temp_path_, NULL); + CreateDirectory(temp_path_, nullptr); } BOOL DoesPathExist(const TCHAR* path_name) { @@ -127,18 +129,18 @@ TEST_F(ExceptionHandlerDeathTest, InProcTest) { // the semantics of the exception handler being inherited/not // inherited across CreateProcess(). ASSERT_TRUE(DoesPathExist(temp_path_)); - scoped_ptr exc( + std::unique_ptr exc( new google_breakpad::ExceptionHandler( temp_path_, - NULL, + nullptr, &MinidumpWrittenCallback, - NULL, + nullptr, google_breakpad::ExceptionHandler::HANDLER_ALL)); // Disable GTest SEH handler testing::DisableExceptionHandlerInScope disable_exception_handler; - int* i = NULL; + int* i = nullptr; ASSERT_DEATH((*i)++, kSuccessIndicator); } @@ -152,32 +154,32 @@ void clientDumpCallback(void* dump_context, void ExceptionHandlerDeathTest::DoCrashAccessViolation( const OutOfProcGuarantee out_of_proc_guarantee) { - scoped_ptr exc; + std::unique_ptr exc; if (out_of_proc_guarantee == OUT_OF_PROC_GUARANTEED) { google_breakpad::CrashGenerationClient* client = new google_breakpad::CrashGenerationClient(kPipeName, MiniDumpNormal, - NULL); // custom_info + nullptr); // custom_info ASSERT_TRUE(client->Register()); exc.reset(new google_breakpad::ExceptionHandler( temp_path_, - NULL, // filter - NULL, // callback - NULL, // callback_context + nullptr, // filter + nullptr, // callback + nullptr, // callback_context google_breakpad::ExceptionHandler::HANDLER_ALL, client)); } else { ASSERT_TRUE(out_of_proc_guarantee == OUT_OF_PROC_BEST_EFFORT); exc.reset(new google_breakpad::ExceptionHandler( temp_path_, - NULL, // filter - NULL, // callback - NULL, // callback_context + nullptr, // filter + nullptr, // callback + nullptr, // callback_context google_breakpad::ExceptionHandler::HANDLER_ALL, MiniDumpNormal, kPipeName, - NULL)); // custom_info + nullptr)); // custom_info } // Disable GTest SEH handler @@ -187,7 +189,7 @@ void ExceptionHandlerDeathTest::DoCrashAccessViolation( // if it's not true we'll still get an error rather than the crash // being expected. ASSERT_TRUE(exc->IsOutOfProcess()); - int* i = NULL; + int* i = nullptr; printf("%d\n", (*i)++); } @@ -203,8 +205,8 @@ TEST_F(ExceptionHandlerDeathTest, OutOfProcTest) { ASSERT_TRUE(DoesPathExist(temp_path_)); std::wstring dump_path(temp_path_); google_breakpad::CrashGenerationServer server( - kPipeName, NULL, NULL, NULL, &clientDumpCallback, NULL, NULL, NULL, NULL, - NULL, true, &dump_path); + kPipeName, nullptr, nullptr, nullptr, &clientDumpCallback, nullptr, + nullptr, nullptr, nullptr, nullptr, true, &dump_path); // This HAS to be EXPECT_, because when this test case is executed in the // child process, the server registration will fail due to the named pipe @@ -226,8 +228,8 @@ TEST_F(ExceptionHandlerDeathTest, OutOfProcGuaranteedTest) { ASSERT_TRUE(DoesPathExist(temp_path_)); std::wstring dump_path(temp_path_); google_breakpad::CrashGenerationServer server( - kPipeName, NULL, NULL, NULL, &clientDumpCallback, NULL, NULL, NULL, NULL, - NULL, true, &dump_path); + kPipeName, nullptr, nullptr, nullptr, &clientDumpCallback, nullptr, + nullptr, nullptr, nullptr, nullptr, true, &dump_path); // This HAS to be EXPECT_, because when this test case is executed in the // child process, the server registration will fail due to the named pipe @@ -242,7 +244,7 @@ TEST_F(ExceptionHandlerDeathTest, InvalidParameterTest) { using google_breakpad::ExceptionHandler; ASSERT_TRUE(DoesPathExist(temp_path_)); - ExceptionHandler handler(temp_path_, NULL, NULL, NULL, + ExceptionHandler handler(temp_path_, nullptr, nullptr, nullptr, ExceptionHandler::HANDLER_INVALID_PARAMETER); // Disable the message box for assertions @@ -250,7 +252,7 @@ TEST_F(ExceptionHandlerDeathTest, InvalidParameterTest) { // Call with a bad argument. The invalid parameter will be swallowed // and a dump will be generated, the process will exit(0). - ASSERT_EXIT(printf(NULL), ::testing::ExitedWithCode(0), ""); + ASSERT_EXIT(printf(nullptr), ::testing::ExitedWithCode(0), ""); } @@ -276,7 +278,7 @@ TEST_F(ExceptionHandlerDeathTest, PureVirtualCallTest) { using google_breakpad::ExceptionHandler; ASSERT_TRUE(DoesPathExist(temp_path_)); - ExceptionHandler handler(temp_path_, NULL, NULL, NULL, + ExceptionHandler handler(temp_path_, nullptr, nullptr, nullptr, ExceptionHandler::HANDLER_PURECALL); // Disable the message box for assertions @@ -314,12 +316,12 @@ wstring find_minidump_in_directory(const wstring& directory) { TEST_F(ExceptionHandlerDeathTest, InstructionPointerMemory) { ASSERT_TRUE(DoesPathExist(temp_path_)); - scoped_ptr exc( + std::unique_ptr exc( new google_breakpad::ExceptionHandler( temp_path_, - NULL, - NULL, - NULL, + nullptr, + nullptr, + nullptr, google_breakpad::ExceptionHandler::HANDLER_ALL)); // Disable GTest SEH handler @@ -330,7 +332,7 @@ TEST_F(ExceptionHandlerDeathTest, InstructionPointerMemory) { const int kOffset = kMemorySize / 2; // This crashes with SIGILL on x86/x86-64/arm. const unsigned char instructions[] = { 0xff, 0xff, 0xff, 0xff }; - char* memory = reinterpret_cast(VirtualAlloc(NULL, + char* memory = reinterpret_cast(VirtualAlloc(nullptr, kMemorySize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)); @@ -406,12 +408,12 @@ TEST_F(ExceptionHandlerDeathTest, InstructionPointerMemory) { TEST_F(ExceptionHandlerDeathTest, InstructionPointerMemoryMinBound) { ASSERT_TRUE(DoesPathExist(temp_path_)); - scoped_ptr exc( + std::unique_ptr exc( new google_breakpad::ExceptionHandler( temp_path_, - NULL, - NULL, - NULL, + nullptr, + nullptr, + nullptr, google_breakpad::ExceptionHandler::HANDLER_ALL)); // Disable GTest SEH handler @@ -427,7 +429,7 @@ TEST_F(ExceptionHandlerDeathTest, InstructionPointerMemoryMinBound) { const unsigned char instructions[] = { 0xff, 0xff, 0xff, 0xff }; // Get some executable memory. Specifically, reserve two pages, // but only commit the second. - char* all_memory = reinterpret_cast(VirtualAlloc(NULL, + char* all_memory = reinterpret_cast(VirtualAlloc(nullptr, kPageSize * 2, MEM_RESERVE, PAGE_NOACCESS)); @@ -499,12 +501,12 @@ TEST_F(ExceptionHandlerDeathTest, InstructionPointerMemoryMinBound) { TEST_F(ExceptionHandlerDeathTest, InstructionPointerMemoryMaxBound) { ASSERT_TRUE(DoesPathExist(temp_path_)); - scoped_ptr exc( + std::unique_ptr exc( new google_breakpad::ExceptionHandler( temp_path_, - NULL, - NULL, - NULL, + nullptr, + nullptr, + nullptr, google_breakpad::ExceptionHandler::HANDLER_ALL)); // Disable GTest SEH handler @@ -519,7 +521,7 @@ TEST_F(ExceptionHandlerDeathTest, InstructionPointerMemoryMaxBound) { const int kOffset = kPageSize - sizeof(instructions); // Get some executable memory. Specifically, reserve two pages, // but only commit the first. - char* memory = reinterpret_cast(VirtualAlloc(NULL, + char* memory = reinterpret_cast(VirtualAlloc(nullptr, kPageSize * 2, MEM_RESERVE, PAGE_NOACCESS)); diff --git a/src/client/windows/unittests/exception_handler_nesting_test.cc b/src/client/windows/unittests/exception_handler_nesting_test.cc index 7fa6ac226..5b6420b3e 100644 --- a/src/client/windows/unittests/exception_handler_nesting_test.cc +++ b/src/client/windows/unittests/exception_handler_nesting_test.cc @@ -136,7 +136,7 @@ void DoCrash(const char* message) { fprintf(stderr, "%s", message); fflush(stderr); } - int* i = NULL; + int* i = nullptr; (*i)++; ASSERT_TRUE(false); @@ -156,23 +156,23 @@ void InstallExceptionHandlerAndCrash(bool install_filter, (filter_return_value ? &CrashHandlerFilter : &CrashHandlerFilter) : - NULL, + nullptr, install_callback ? (callback_return_value ? &MinidumpWrittenCallback : &MinidumpWrittenCallback) : - NULL, - NULL, // callback_context + nullptr, + nullptr, // callback_context google_breakpad::ExceptionHandler::HANDLER_EXCEPTION); // Disable GTest SEH handler testing::DisableExceptionHandlerInScope disable_exception_handler; - DoCrash(NULL); + DoCrash(nullptr); } TEST(AssertDeathSanity, Simple) { - ASSERT_DEATH(DoCrash(NULL), ""); + ASSERT_DEATH(DoCrash(nullptr), ""); } TEST(AssertDeathSanity, Regex) { @@ -264,7 +264,7 @@ TEST(ExceptionHandlerNesting, Skip_From_Inner_Filter) { temp_path, &CrashHandlerFilter, &MinidumpWrittenCallback, - NULL, // callback_context + nullptr, // callback_context google_breakpad::ExceptionHandler::HANDLER_EXCEPTION); ASSERT_DEATH( @@ -288,7 +288,7 @@ TEST(ExceptionHandlerNesting, Skip_From_Inner_Callback) { temp_path, &CrashHandlerFilter, &MinidumpWrittenCallback, - NULL, // callback_context + nullptr, // callback_context google_breakpad::ExceptionHandler::HANDLER_EXCEPTION); ASSERT_DEATH( @@ -313,7 +313,7 @@ TEST(ExceptionHandlerNesting, Handled_By_Inner_Handler) { temp_path, &CrashHandlerFilter, &MinidumpWrittenCallback, - NULL, // callback_context + nullptr, // callback_context google_breakpad::ExceptionHandler::HANDLER_EXCEPTION); ASSERT_DEATH( diff --git a/src/client/windows/unittests/exception_handler_test.cc b/src/client/windows/unittests/exception_handler_test.cc index f658726ba..9ebc93fdc 100644 --- a/src/client/windows/unittests/exception_handler_test.cc +++ b/src/client/windows/unittests/exception_handler_test.cc @@ -32,6 +32,7 @@ #include "client/windows/unittests/exception_handler_test.h" +#include #include #include #include @@ -130,7 +131,7 @@ void ExceptionHandlerTest::SetUp() { assert(false); } StringCchPrintfW(temp_path_, MAX_PATH, L"%s%s", temp_path, test_name_wide); - CreateDirectory(temp_path_, NULL); + CreateDirectory(temp_path_, nullptr); } void ExceptionHandlerTest::TearDown() { @@ -179,9 +180,9 @@ bool ExceptionHandlerTest::DumpCallback(const wchar_t* dump_path, void ExceptionHandlerTest::DoCrashInvalidParameter() { google_breakpad::ExceptionHandler* exc = new google_breakpad::ExceptionHandler( - temp_path_, NULL, NULL, NULL, + temp_path_, nullptr, nullptr, nullptr, google_breakpad::ExceptionHandler::HANDLER_INVALID_PARAMETER, - kFullDumpType, kPipeName, NULL); + kFullDumpType, kPipeName, nullptr); // Disable the message box for assertions _CrtSetReportMode(_CRT_ASSERT, 0); @@ -190,7 +191,7 @@ void ExceptionHandlerTest::DoCrashInvalidParameter() { // if it's not true we'll still get an error rather than the crash // being expected. ASSERT_TRUE(exc->IsOutOfProcess()); - printf(NULL); + printf(nullptr); } @@ -211,9 +212,9 @@ struct PureVirtualCall : public PureVirtualCallBase { void ExceptionHandlerTest::DoCrashPureVirtualCall() { google_breakpad::ExceptionHandler* exc = new google_breakpad::ExceptionHandler( - temp_path_, NULL, NULL, NULL, + temp_path_, nullptr, nullptr, nullptr, google_breakpad::ExceptionHandler::HANDLER_PURECALL, - kFullDumpType, kPipeName, NULL); + kFullDumpType, kPipeName, nullptr); // Disable the message box for assertions _CrtSetReportMode(_CRT_ASSERT, 0); @@ -238,8 +239,8 @@ TEST_F(ExceptionHandlerTest, InvalidParameterMiniDumpTest) { ASSERT_TRUE(DoesPathExist(temp_path_)); wstring dump_path(temp_path_); google_breakpad::CrashGenerationServer server( - kPipeName, NULL, NULL, NULL, ClientDumpCallback, NULL, NULL, NULL, NULL, - NULL, true, &dump_path); + kPipeName, nullptr, nullptr, nullptr, ClientDumpCallback, nullptr, + nullptr, nullptr, nullptr, nullptr, true, &dump_path); ASSERT_TRUE(dump_file.empty() && full_dump_file.empty()); @@ -310,8 +311,8 @@ TEST_F(ExceptionHandlerTest, PureVirtualCallMiniDumpTest) { ASSERT_TRUE(DoesPathExist(temp_path_)); wstring dump_path(temp_path_); google_breakpad::CrashGenerationServer server( - kPipeName, NULL, NULL, NULL, ClientDumpCallback, NULL, NULL, NULL, NULL, - NULL, true, &dump_path); + kPipeName, nullptr, nullptr, nullptr, ClientDumpCallback, nullptr, + nullptr, nullptr, nullptr, nullptr, true, &dump_path); ASSERT_TRUE(dump_file.empty() && full_dump_file.empty()); @@ -377,9 +378,9 @@ TEST_F(ExceptionHandlerTest, PureVirtualCallMiniDumpTest) { // some expected structures. TEST_F(ExceptionHandlerTest, WriteMinidumpTest) { ExceptionHandler handler(temp_path_, - NULL, + nullptr, DumpCallback, - NULL, + nullptr, ExceptionHandler::HANDLER_ALL); // Disable GTest SEH handler @@ -415,9 +416,9 @@ TEST_F(ExceptionHandlerTest, AdditionalMemory) { } ExceptionHandler handler(temp_path_, - NULL, + nullptr, DumpCallback, - NULL, + nullptr, ExceptionHandler::HANDLER_ALL); // Disable GTest SEH handler @@ -469,9 +470,9 @@ TEST_F(ExceptionHandlerTest, AdditionalMemoryRemove) { } ExceptionHandler handler(temp_path_, - NULL, + nullptr, DumpCallback, - NULL, + nullptr, ExceptionHandler::HANDLER_ALL); // Disable GTest SEH handler diff --git a/src/client/windows/unittests/minidump_test.cc b/src/client/windows/unittests/minidump_test.cc index 741447df4..1fe52f5cc 100644 --- a/src/client/windows/unittests/minidump_test.cc +++ b/src/client/windows/unittests/minidump_test.cc @@ -68,12 +68,12 @@ class MinidumpTest: public testing::Test { virtual void SetUp() { // Make sure URLMon isn't loaded into our process. - ASSERT_EQ(NULL, ::GetModuleHandle(L"urlmon.dll")); + ASSERT_EQ(nullptr, ::GetModuleHandle(L"urlmon.dll")); // Then load and unload it to ensure we have something to // stock the unloaded module list with. HMODULE urlmon = ::LoadLibrary(L"urlmon.dll"); - ASSERT_TRUE(urlmon != NULL); + ASSERT_TRUE(urlmon != nullptr); ASSERT_TRUE(::FreeLibrary(urlmon)); } @@ -95,7 +95,7 @@ class MinidumpTest: public testing::Test { EXCEPTION_RECORD ex_record = { STATUS_ACCESS_VIOLATION, // ExceptionCode 0, // ExceptionFlags - NULL, // ExceptionRecord; + nullptr, // ExceptionRecord; reinterpret_cast(static_cast(0xCAFEBABE)), // ExceptionAddress; 2, // NumberParameters; { EXCEPTION_WRITE_FAULT, reinterpret_cast(this) } @@ -112,7 +112,7 @@ class MinidumpTest: public testing::Test { ::GetCurrentThreadId(), ::GetCurrentThreadId(), &ex_ptrs, - NULL, + nullptr, static_cast(flags), TRUE); generator.GenerateDumpFile(&dump_file_); @@ -135,7 +135,7 @@ bool HasFileInfo(const std::wstring& file_path) { const wchar_t* path = file_path.c_str(); DWORD length = ::GetFileVersionInfoSize(path, &dummy); if (length == 0) - return NULL; + return nullptr; void* data = calloc(length, 1); if (!data) @@ -146,7 +146,7 @@ bool HasFileInfo(const std::wstring& file_path) { return false; } - void* translate = NULL; + void* translate = nullptr; UINT page_count; BOOL query_result = VerQueryValue( data, @@ -167,14 +167,14 @@ TEST_F(MinidumpTest, Version) { ImagehlpApiVersion(); HMODULE dbg_help = ::GetModuleHandle(L"dbghelp.dll"); - ASSERT_TRUE(dbg_help != NULL); + ASSERT_TRUE(dbg_help != nullptr); wchar_t dbg_help_file[1024] = {}; ASSERT_TRUE(::GetModuleFileName(dbg_help, dbg_help_file, sizeof(dbg_help_file) / sizeof(*dbg_help_file))); - ASSERT_TRUE(HasFileInfo(std::wstring(dbg_help_file)) != NULL); + ASSERT_TRUE(HasFileInfo(std::wstring(dbg_help_file)) != nullptr); // LOG(INFO) << "DbgHelp.dll version: " << file_info->file_version(); } diff --git a/src/common/android/testing/mkdtemp.h b/src/common/android/testing/mkdtemp.h index f05cf653d..2664e8012 100644 --- a/src/common/android/testing/mkdtemp.h +++ b/src/common/android/testing/mkdtemp.h @@ -53,9 +53,9 @@ namespace { char* breakpad_mkdtemp(char* path) { - if (path == NULL) { + if (path == nullptr) { errno = EINVAL; - return NULL; + return nullptr; } // 'path' must be terminated with six 'X' @@ -66,23 +66,23 @@ char* breakpad_mkdtemp(char* path) { if (static_cast(path_end - path) < kSuffixLen || memcmp(path_end - kSuffixLen, kSuffix, kSuffixLen) != 0) { errno = EINVAL; - return NULL; + return nullptr; } // If 'path' contains a directory separator, check that it exists to // avoid looping later. char* sep = strrchr(path, '/'); - if (sep != NULL) { + if (sep != nullptr) { struct stat st; int ret; *sep = '\0'; // temporarily zero-terminate the dirname. ret = stat(path, &st); *sep = '/'; // restore full path. if (ret < 0) - return NULL; + return nullptr; if (!S_ISDIR(st.st_mode)) { errno = ENOTDIR; - return NULL; + return nullptr; } } @@ -97,11 +97,11 @@ char* breakpad_mkdtemp(char* path) { return path; // Success if (errno != EEXIST) - return NULL; + return nullptr; } assert(errno == EEXIST); - return NULL; + return nullptr; } } // namespace diff --git a/src/common/android/testing/pthread_fixes.h b/src/common/android/testing/pthread_fixes.h index 04bf63691..f9caee938 100644 --- a/src/common/android/testing/pthread_fixes.h +++ b/src/common/android/testing/pthread_fixes.h @@ -53,8 +53,8 @@ int pthread_barrier_init(pthread_barrier_t* barrier, const void* /* barrier_attr */, unsigned count) { barrier->count = count; - pthread_mutex_init(&barrier->mutex, NULL); - pthread_cond_init(&barrier->cond, NULL); + pthread_mutex_init(&barrier->mutex, nullptr); + pthread_cond_init(&barrier->cond, nullptr); return 0; } diff --git a/src/common/basictypes.h b/src/common/basictypes.h index 79c9b7756..26b997d08 100644 --- a/src/common/basictypes.h +++ b/src/common/basictypes.h @@ -36,7 +36,7 @@ namespace google_breakpad { // that has been marked with __attribute__((warn_unused_result)), wrap it with // this. Example: // -// scoped_ptr my_var = ...; +// std::unique_ptr my_var = ...; // if (TakeOwnership(my_var.get()) == SUCCESS) // ignore_result(my_var.release()); // diff --git a/src/common/byte_cursor.h b/src/common/byte_cursor.h index fd0e45ffd..8033e9db1 100644 --- a/src/common/byte_cursor.h +++ b/src/common/byte_cursor.h @@ -218,7 +218,7 @@ class ByteCursor { *pointer = here_; here_ += size; } else { - *pointer = NULL; + *pointer = nullptr; } return *this; } diff --git a/src/common/byte_cursor_unittest.cc b/src/common/byte_cursor_unittest.cc index 41180ca2e..69b31d3f8 100644 --- a/src/common/byte_cursor_unittest.cc +++ b/src/common/byte_cursor_unittest.cc @@ -733,7 +733,7 @@ TEST(Strings, PointTo) { EXPECT_EQ(data + 0, received1); EXPECT_EQ(data + 3, received2); EXPECT_EQ(data + 6, received3); - EXPECT_EQ(NULL, received4); + EXPECT_EQ(nullptr, received4); } TEST(Strings, CString) { diff --git a/src/common/convert_UTF.cc b/src/common/convert_UTF.cc index 6e95b2f9b..60a0d7aa9 100644 --- a/src/common/convert_UTF.cc +++ b/src/common/convert_UTF.cc @@ -297,15 +297,15 @@ ConversionResult ConvertUTF16toUTF8 (const UTF16** sourceStart, const UTF16* sou case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - BP_FALLTHROUGH; + [[fallthrough]]; case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - BP_FALLTHROUGH; + [[fallthrough]]; case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - BP_FALLTHROUGH; + [[fallthrough]]; case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); } @@ -338,10 +338,10 @@ Boolean isLegalUTF8(const UTF8 *source, int length) { /* Everything else falls through when "true"... */ case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; - BP_FALLTHROUGH; + [[fallthrough]]; case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; - BP_FALLTHROUGH; + [[fallthrough]]; case 2: if ((a = (*--srcptr)) > 0xBF) return false; @@ -353,7 +353,7 @@ Boolean isLegalUTF8(const UTF8 *source, int length) { case 0xF4: if (a > 0x8F) return false; break; default: if (a < 0x80) return false; } - BP_FALLTHROUGH; + [[fallthrough]]; case 1: if (*source >= 0x80 && *source < 0xC2) return false; } if (*source > 0xF4) return false; @@ -399,12 +399,12 @@ ConversionResult ConvertUTF8toUTF16 (const UTF8** sourceStart, const UTF8* sourc */ switch (extraBytesToRead) { /* remember, illegal UTF-8 */ - case 5: ch += *source++; ch <<= 6; BP_FALLTHROUGH; + case 5: ch += *source++; ch <<= 6; [[fallthrough]]; /* remember, illegal UTF-8 */ - case 4: ch += *source++; ch <<= 6; BP_FALLTHROUGH; - case 3: ch += *source++; ch <<= 6; BP_FALLTHROUGH; - case 2: ch += *source++; ch <<= 6; BP_FALLTHROUGH; - case 1: ch += *source++; ch <<= 6; BP_FALLTHROUGH; + case 4: ch += *source++; ch <<= 6; [[fallthrough]]; + case 3: ch += *source++; ch <<= 6; [[fallthrough]]; + case 2: ch += *source++; ch <<= 6; [[fallthrough]]; + case 1: ch += *source++; ch <<= 6; [[fallthrough]]; case 0: ch += *source++; } ch -= offsetsFromUTF8[extraBytesToRead]; @@ -493,15 +493,15 @@ ConversionResult ConvertUTF32toUTF8 (const UTF32** sourceStart, const UTF32* sou case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - BP_FALLTHROUGH; + [[fallthrough]]; case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - BP_FALLTHROUGH; + [[fallthrough]]; case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - BP_FALLTHROUGH; + [[fallthrough]]; case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]); } @@ -534,11 +534,11 @@ ConversionResult ConvertUTF8toUTF32 (const UTF8** sourceStart, const UTF8* sourc * The cases all fall through. See "Note A" below. */ switch (extraBytesToRead) { - case 5: ch += *source++; ch <<= 6; BP_FALLTHROUGH; - case 4: ch += *source++; ch <<= 6; BP_FALLTHROUGH; - case 3: ch += *source++; ch <<= 6; BP_FALLTHROUGH; - case 2: ch += *source++; ch <<= 6; BP_FALLTHROUGH; - case 1: ch += *source++; ch <<= 6; BP_FALLTHROUGH; + case 5: ch += *source++; ch <<= 6; [[fallthrough]]; + case 4: ch += *source++; ch <<= 6; [[fallthrough]]; + case 3: ch += *source++; ch <<= 6; [[fallthrough]]; + case 2: ch += *source++; ch <<= 6; [[fallthrough]]; + case 1: ch += *source++; ch <<= 6; [[fallthrough]]; case 0: ch += *source++; } ch -= offsetsFromUTF8[extraBytesToRead]; diff --git a/src/common/dwarf/bytereader.cc b/src/common/dwarf/bytereader.cc index faa7d680a..eea6850d6 100644 --- a/src/common/dwarf/bytereader.cc +++ b/src/common/dwarf/bytereader.cc @@ -36,11 +36,12 @@ #include "common/dwarf/bytereader-inl.h" #include "common/dwarf/bytereader.h" +#include "common/memory_allocator.h" namespace google_breakpad { ByteReader::ByteReader(enum Endianness endian) - :offset_reader_(NULL), address_reader_(NULL), endian_(endian), + :offset_reader_(nullptr), address_reader_(nullptr), endian_(endian), address_size_(0), offset_size_(0), have_section_base_(), have_text_base_(), have_data_base_(), have_function_base_() { } @@ -132,7 +133,7 @@ uint64_t ByteReader::ReadEncodedPointer(const uint8_t* buffer, // Now find the offset from that aligned address to buffer. uint64_t offset = skew + (buffer - buffer_base_); // Round up to the next boundary. - uint64_t aligned = (offset + AddressSize() - 1) & -AddressSize(); + uint64_t aligned = PageAllocator::AlignUp(offset, AddressSize()); // Convert back to a pointer. const uint8_t* aligned_buffer = buffer_base_ + (aligned - skew); // Finally, store the length and actually fetch the pointer. diff --git a/src/common/dwarf/cfi_assembler.cc b/src/common/dwarf/cfi_assembler.cc index b3e064f06..773fd250f 100644 --- a/src/common/dwarf/cfi_assembler.cc +++ b/src/common/dwarf/cfi_assembler.cc @@ -119,7 +119,7 @@ CFISection& CFISection::FinishEntry() { Align(address_size_, DW_CFA_nop); entry_length_->length = Here() - entry_length_->start; delete entry_length_; - entry_length_ = NULL; + entry_length_ = nullptr; in_fde_ = false; return *this; } diff --git a/src/common/dwarf/cfi_assembler.h b/src/common/dwarf/cfi_assembler.h index a33d5d847..c707632d4 100644 --- a/src/common/dwarf/cfi_assembler.h +++ b/src/common/dwarf/cfi_assembler.h @@ -96,7 +96,7 @@ class CFISection: public Section { bool eh_frame = false) : Section(endianness), address_size_(address_size), eh_frame_(eh_frame), pointer_encoding_(DW_EH_PE_absptr), - encoded_pointer_bases_(), entry_length_(NULL), in_fde_(false) { + encoded_pointer_bases_(), entry_length_(nullptr), in_fde_(false) { // The 'start', 'Here', and 'Mark' members of a CFISection all refer // to section offsets. start() = 0; diff --git a/src/common/dwarf/dwarf2diehandler.cc b/src/common/dwarf/dwarf2diehandler.cc index 8aea0f2ff..1c95ad20c 100644 --- a/src/common/dwarf/dwarf2diehandler.cc +++ b/src/common/dwarf/dwarf2diehandler.cc @@ -64,7 +64,7 @@ bool DIEDispatcher::StartCompilationUnit(uint64_t offset, uint8_t address_size, bool DIEDispatcher::StartDIE(uint64_t offset, enum DwarfTag tag) { // The stack entry for the parent of this DIE, if there is one. - HandlerStack* parent = die_handlers_.empty() ? NULL : &die_handlers_.top(); + HandlerStack* parent = die_handlers_.empty() ? nullptr : &die_handlers_.top(); // Does this call indicate that we're done receiving the parent's // attributes' values? If so, call its EndAttributes member function. @@ -76,7 +76,7 @@ bool DIEDispatcher::StartDIE(uint64_t offset, enum DwarfTag tag) { parent->handler_->Finish(); if (parent->handler_ != root_handler_) delete parent->handler_; - parent->handler_ = NULL; + parent->handler_ = nullptr; return false; } } @@ -90,7 +90,7 @@ bool DIEDispatcher::StartDIE(uint64_t offset, enum DwarfTag tag) { else // No parent handler means we're not interested in any of our // children. - handler = NULL; + handler = nullptr; } else { // This is the root DIE. For a non-root DIE, the parent's handler // decides whether to visit it, but the root DIE has no parent @@ -99,7 +99,7 @@ bool DIEDispatcher::StartDIE(uint64_t offset, enum DwarfTag tag) { if (root_handler_->StartRootDIE(offset, tag)) handler = root_handler_; else - handler = NULL; + handler = nullptr; } // Push a handler stack entry for this new handler. As an @@ -114,7 +114,7 @@ bool DIEDispatcher::StartDIE(uint64_t offset, enum DwarfTag tag) { die_handlers_.push(entry); } - return handler != NULL; + return handler != nullptr; } void DIEDispatcher::EndDIE(uint64_t offset) { diff --git a/src/common/dwarf/dwarf2diehandler.h b/src/common/dwarf/dwarf2diehandler.h index 02c22853e..14be55acc 100644 --- a/src/common/dwarf/dwarf2diehandler.h +++ b/src/common/dwarf/dwarf2diehandler.h @@ -245,7 +245,7 @@ class DIEHandler { // // The default definition skips all children. virtual DIEHandler* FindChildHandler(uint64_t offset, enum DwarfTag tag) { - return NULL; + return nullptr; } // When we are done processing a DIE, we call this member function. diff --git a/src/common/dwarf/dwarf2diehandler_unittest.cc b/src/common/dwarf/dwarf2diehandler_unittest.cc index afcbf6254..a52f2ab72 100644 --- a/src/common/dwarf/dwarf2diehandler_unittest.cc +++ b/src/common/dwarf/dwarf2diehandler_unittest.cc @@ -343,7 +343,7 @@ TEST(Dwarf2DIEHandler, FindAndSkipChildren) { EXPECT_CALL(mock_root_handler, FindChildHandler(0x97412be24875de9dLL, (DwarfTag) 0x505a068b)) - .WillOnce(Return((DIEHandler*) NULL)); + .WillOnce(Return((DIEHandler*) nullptr)); // Third child DIE. EXPECT_CALL(mock_root_handler, diff --git a/src/common/dwarf/dwarf2reader.cc b/src/common/dwarf/dwarf2reader.cc index 8a8bf6f86..4977dcda7 100644 --- a/src/common/dwarf/dwarf2reader.cc +++ b/src/common/dwarf/dwarf2reader.cc @@ -37,9 +37,11 @@ #include "common/dwarf/dwarf2reader.h" +#include #include #include #include +#include #include #include @@ -67,6 +69,11 @@ const SectionMap::const_iterator GetSectionByName(const SectionMap& std::string macho_name("__"); macho_name += name + 1; iter = sections.find(macho_name); + + // .debug_str_offsets is alternatively named .debug_str_offs, so try both + if (iter == sections.end() && std::string(name) == ".debug_str_offsets") { + return GetSectionByName(sections, ".debug_str_offs"); + } return iter; } @@ -75,10 +82,10 @@ CompilationUnit::CompilationUnit(const string& path, ByteReader* reader, Dwarf2Handler* handler) : path_(path), offset_from_section_start_(offset), reader_(reader), sections_(sections), handler_(handler), abbrevs_(), - string_buffer_(NULL), string_buffer_length_(0), - line_string_buffer_(NULL), line_string_buffer_length_(0), - str_offsets_buffer_(NULL), str_offsets_buffer_length_(0), - addr_buffer_(NULL), addr_buffer_length_(0), + string_buffer_(nullptr), string_buffer_length_(0), + line_string_buffer_(nullptr), line_string_buffer_length_(0), + str_offsets_buffer_(nullptr), str_offsets_buffer_length_(0), + addr_buffer_(nullptr), addr_buffer_length_(0), is_split_dwarf_(false), is_type_unit_(false), dwo_id_(0), dwo_name_(), skeleton_dwo_id_(0), addr_base_(0), str_offsets_base_(0), have_checked_for_dwp_(false), @@ -173,7 +180,7 @@ void CompilationUnit::ReadAbbrevs() { value); abbrev.attributes.push_back(abbrev_attr); } - abbrevs_->push_back(abbrev); + abbrevs_->push_back(std::move(abbrev)); } // Account of cases where entries are out of order. @@ -285,8 +292,8 @@ const uint8_t* CompilationUnit::SkipAttribute(const uint8_t* start, case DW_FORM_sec_offset: return start + reader_->OffsetSize(); } - fprintf(stderr,"Unhandled form type"); - return NULL; + fprintf(stderr,"Unhandled form type 0x%x\n", form); + return nullptr; } // Read the abbreviation offset from a compilation unit header. @@ -369,7 +376,7 @@ void CompilationUnit::ReadHeader() { break; case DW_UT_type: case DW_UT_split_type: - is_type_unit_ = true; + is_type_unit_ = true; headerptr += ReadTypeSignature(headerptr); headerptr += ReadTypeOffset(headerptr); break; @@ -463,13 +470,18 @@ uint64_t CompilationUnit::Start() { } // Now that we have our abbreviations, start processing DIE's. - ProcessDIEs(); + if (!ProcessDIEs()) { + // If ProcessDIEs fails return 0, ourlength must be non-zero + // as it is equal to header_.length + (12 or 4) + return 0; + } // If this is a skeleton compilation unit generated with split DWARF, // and the client needs the full debug info, we need to find the full // compilation unit in a .dwo or .dwp file. should_process_split_dwarf_ = - !is_split_dwarf_ && dwo_name_ != NULL && handler_->NeedSplitDebugInfo(); + !is_split_dwarf_ && dwo_name_ != nullptr && + handler_->NeedSplitDebugInfo(); return ourlength; } @@ -512,7 +524,7 @@ const uint8_t* CompilationUnit::ProcessOffsetBaseAttribute( &len)); start += len; return ProcessOffsetBaseAttribute(dieoffset, start, attr, form, - implicit_const); + implicit_const); case DW_FORM_flag_present: return start; @@ -568,10 +580,10 @@ const uint8_t* CompilationUnit::ProcessOffsetBaseAttribute( // offset size. assert(header_.version >= 2); if (header_.version == 2) { - reader_->ReadAddress(start); + reader_->ReadAddress(start); return start + reader_->AddressSize(); } else if (header_.version >= 3) { - reader_->ReadOffset(start); + reader_->ReadOffset(start); return start + reader_->OffsetSize(); } break; @@ -647,8 +659,8 @@ const uint8_t* CompilationUnit::ProcessOffsetBaseAttribute( reader_->ReadUnsignedLEB128(start, &len); return start + len; } - fprintf(stderr, "Unhandled form type\n"); - return NULL; + fprintf(stderr,"Unhandled form type 0x%x\n", form); + return nullptr; } // If one really wanted, you could merge SkipAttribute and @@ -789,7 +801,7 @@ const uint8_t* CompilationUnit::ProcessAttribute( return start + datalen + len; } case DW_FORM_strp: { - assert(string_buffer_ != NULL); + assert(string_buffer_ != nullptr); const uint64_t offset = reader_->ReadOffset(start); assert(string_buffer_ + offset < string_buffer_ + string_buffer_length_); @@ -799,7 +811,7 @@ const uint8_t* CompilationUnit::ProcessAttribute( return start + reader_->OffsetSize(); } case DW_FORM_line_strp: { - assert(line_string_buffer_ != NULL); + assert(line_string_buffer_ != nullptr); const uint64_t offset = reader_->ReadOffset(start); assert(line_string_buffer_ + offset < @@ -880,7 +892,7 @@ const uint8_t* CompilationUnit::ProcessAttribute( return start + len; } fprintf(stderr, "Unhandled form type\n"); - return NULL; + return nullptr; } const uint8_t* CompilationUnit::ProcessDIE(uint64_t dieoffset, @@ -896,11 +908,11 @@ const uint8_t* CompilationUnit::ProcessDIE(uint64_t dieoffset, uint64_t dieoffset_copy = dieoffset; const uint8_t* start_copy = start; for (AttributeList::const_iterator i = abbrev.attributes.begin(); - i != abbrev.attributes.end(); - i++) { + i != abbrev.attributes.end(); + i++) { start_copy = ProcessOffsetBaseAttribute(dieoffset_copy, start_copy, - i->attr_, i->form_, - i->value_); + i->attr_, i->form_, + i->value_); } } @@ -916,13 +928,13 @@ const uint8_t* CompilationUnit::ProcessDIE(uint64_t dieoffset, if (abbrev.tag == DW_TAG_compile_unit && is_split_dwarf_ && dwo_id_ != skeleton_dwo_id_) { - return NULL; + return nullptr; } return start; } -void CompilationUnit::ProcessDIEs() { +bool CompilationUnit::ProcessDIEs() { const uint8_t* dieptr = after_header_; size_t len; @@ -953,13 +965,21 @@ void CompilationUnit::ProcessDIEs() { if (abbrev_num == 0) { if (die_stack.size() == 0) // If it is padding, then we are done with the compilation unit's DIEs. - return; + return true; const uint64_t offset = die_stack.top(); die_stack.pop(); handler_->EndDIE(offset); continue; } + // Abbrev > abbrev_.size() indicates a corruption in the dwarf file. + if (abbrev_num > abbrevs_->size()) { + fprintf(stderr, "An invalid abbrev was referenced %" PRIu64 " / %zu. " + "Stopped procesing following DIEs in this CU.", abbrev_num, + abbrevs_->size()); + return false; + } + const Abbrev& abbrev = abbrevs_->at(static_cast(abbrev_num)); const enum DwarfTag tag = abbrev.tag; if (!handler_->StartDIE(absolute_offset, tag)) { @@ -989,6 +1009,7 @@ void CompilationUnit::ProcessDIEs() { handler_->EndDIE(absolute_offset); } } + return true; } // Check for a valid ELF file and return the Address size. @@ -1081,7 +1102,7 @@ void CompilationUnit::ReadDebugSectionsFromDwo(ElfReader* elf_reader, size_t section_size; const char* section_data = elf_reader->GetSectionByName(dwo_name, §ion_size); - if (section_data != NULL) + if (section_data != nullptr) sections->insert(std::make_pair( base_name, std::make_pair( reinterpret_cast(section_data), @@ -1091,17 +1112,17 @@ void CompilationUnit::ReadDebugSectionsFromDwo(ElfReader* elf_reader, DwpReader::DwpReader(const ByteReader& byte_reader, ElfReader* elf_reader) : elf_reader_(elf_reader), byte_reader_(byte_reader), - cu_index_(NULL), cu_index_size_(0), string_buffer_(NULL), + cu_index_(nullptr), cu_index_size_(0), string_buffer_(nullptr), string_buffer_size_(0), version_(0), ncolumns_(0), nunits_(0), - nslots_(0), phash_(NULL), pindex_(NULL), shndx_pool_(NULL), - offset_table_(NULL), size_table_(NULL), abbrev_data_(NULL), - abbrev_size_(0), info_data_(NULL), info_size_(0), - str_offsets_data_(NULL), str_offsets_size_(0) {} + nslots_(0), phash_(nullptr), pindex_(nullptr), shndx_pool_(nullptr), + offset_table_(nullptr), size_table_(nullptr), abbrev_data_(nullptr), + abbrev_size_(0), info_data_(nullptr), info_size_(0), + str_offsets_data_(nullptr), str_offsets_size_(0) {} void DwpReader::Initialize() { cu_index_ = elf_reader_->GetSectionByName(".debug_cu_index", &cu_index_size_); - if (cu_index_ == NULL) { + if (cu_index_ == nullptr) { return; } // The .debug_str.dwo section is shared by all CUs in the file. @@ -1317,7 +1338,7 @@ LineInfo::LineInfo(const uint8_t* buffer, uint64_t buffer_length, string_buffer_length_ = string_buffer_length; line_string_buffer_length_ = line_string_buffer_length; #endif - header_.std_opcode_lengths = NULL; + header_.std_opcode_lengths = nullptr; } uint64_t LineInfo::Start() { @@ -1811,7 +1832,7 @@ void LineInfo::ReadLines() { size_t oplength; bool add_row = ProcessOneOpcode(reader_, handler_, header_, lineptr, &lsm, &oplength, (uintptr)-1, - NULL); + nullptr); if (add_row) { if (have_pending_line) handler_->AddLine(pending_address, lsm.address - pending_address, @@ -2000,7 +2021,7 @@ class CallFrameInfo::UndefinedRule: public CallFrameInfo::Rule { // dynamic_cast is allowed by the Google C++ Style Guide, if the use has // been carefully considered; cheap RTTI-like workarounds are forbidden. const UndefinedRule* our_rhs = dynamic_cast(&rhs); - return (our_rhs != NULL); + return (our_rhs != nullptr); } Rule* Copy() const { return new UndefinedRule(*this); } }; @@ -2017,7 +2038,7 @@ class CallFrameInfo::SameValueRule: public CallFrameInfo::Rule { // dynamic_cast is allowed by the Google C++ Style Guide, if the use has // been carefully considered; cheap RTTI-like workarounds are forbidden. const SameValueRule* our_rhs = dynamic_cast(&rhs); - return (our_rhs != NULL); + return (our_rhs != nullptr); } Rule* Copy() const { return new SameValueRule(*this); } }; @@ -2141,8 +2162,8 @@ class CallFrameInfo::ValExpressionRule: public CallFrameInfo::Rule { // A map from register numbers to rules. class CallFrameInfo::RuleMap { public: - RuleMap() : cfa_rule_(NULL) { } - RuleMap(const RuleMap& rhs) : cfa_rule_(NULL) { *this = rhs; } + RuleMap() : cfa_rule_(nullptr) { } + RuleMap(const RuleMap& rhs) : cfa_rule_(nullptr) { *this = rhs; } ~RuleMap() { Clear(); } RuleMap& operator=(const RuleMap& rhs); @@ -2202,7 +2223,7 @@ CallFrameInfo::Rule* CallFrameInfo::RuleMap::RegisterRule(int reg) const { if (it != registers_.end()) return it->second->Copy(); else - return NULL; + return nullptr; } void CallFrameInfo::RuleMap::SetRegisterRule(int reg, Rule* rule) { @@ -2283,7 +2304,7 @@ bool CallFrameInfo::RuleMap::HandleTransitionTo( // Remove all register rules and clear cfa_rule_. void CallFrameInfo::RuleMap::Clear() { delete cfa_rule_; - cfa_rule_ = NULL; + cfa_rule_ = nullptr; for (RuleByNumber::iterator it = registers_.begin(); it != registers_.end(); it++) delete it->second; @@ -2299,7 +2320,7 @@ class CallFrameInfo::State { State(ByteReader* reader, Handler* handler, Reporter* reporter, uint64_t address) : reader_(reader), handler_(handler), reporter_(reporter), - address_(address), entry_(NULL), cursor_(NULL) { } + address_(address), entry_(nullptr), cursor_(nullptr) { } // Interpret instructions from CIE, save the resulting rule set for // DW_CFA_restore instructions, and return true. On error, report @@ -2873,7 +2894,7 @@ bool CallFrameInfo::ReadEntryPrologue(const uint8_t* cursor, Entry* entry) { entry->offset = cursor - buffer_; entry->start = cursor; entry->kind = kUnknown; - entry->end = NULL; + entry->end = nullptr; // Read the initial length. This sets reader_'s offset size. size_t length_size; @@ -2939,7 +2960,7 @@ bool CallFrameInfo::ReadEntryPrologue(const uint8_t* cursor, Entry* entry) { // The fields specific to this kind of entry start here. entry->fields = cursor; - entry->cie = NULL; + entry->cie = nullptr; return true; } diff --git a/src/common/dwarf/dwarf2reader.h b/src/common/dwarf/dwarf2reader.h index b6bd2f31a..bd2e4d2e9 100644 --- a/src/common/dwarf/dwarf2reader.h +++ b/src/common/dwarf/dwarf2reader.h @@ -570,10 +570,10 @@ class CompilationUnit { // Special version of ProcessAttribute, for finding str_offsets_base and // DW_AT_addr_base in DW_TAG_compile_unit, for DWARF v5. const uint8_t* ProcessOffsetBaseAttribute(uint64_t dieoffset, - const uint8_t* start, - enum DwarfAttribute attr, - enum DwarfForm form, - uint64_t implicit_const); + const uint8_t* start, + enum DwarfAttribute attr, + enum DwarfForm form, + uint64_t implicit_const); // Called when we have an attribute with unsigned data to give to // our handler. The attribute is for the DIE at OFFSET from the @@ -664,7 +664,7 @@ class CompilationUnit { } // Processes all DIEs for this compilation unit - void ProcessDIEs(); + bool ProcessDIEs(); // Skips the die with attributes specified in ABBREV starting at // START, and return the new place to position the stream to. @@ -909,11 +909,11 @@ class DwpReader { // // For example, here is a complete (uncompressed) table describing the // function above: -// +// // insn cfa r0 r1 ... ra // ======================================= // func+0: sp cfa[0] -// func+1: sp+16 cfa[0] +// func+1: sp+16 cfa[0] // func+2: sp+16 cfa[-4] cfa[0] // func+11: sp+20 cfa[-4] cfa[0] // func+21: sp+20 cfa[0] @@ -947,7 +947,7 @@ class DwpReader { // save them, caller-saves registers are probably dead in the caller // anyway, so compilers usually don't generate CFA for caller-saves // registers.) -// +// // - Exactly where the CFA points is a matter of convention that // depends on the architecture and ABI in use. In the example, the // CFA is the value the stack pointer had upon entry to the @@ -968,7 +968,7 @@ class DwpReader { // reduces the size of the data by mentioning only the addresses and // columns at which changes take place. So for the above, DWARF CFI // data would only actually mention the following: -// +// // insn cfa r0 r1 ... ra // ======================================= // func+0: sp cfa[0] @@ -976,7 +976,7 @@ class DwpReader { // func+2: cfa[-4] // func+11: sp+20 // func+21: r0 -// func+22: sp +// func+22: sp // // In fact, this is the way the parser reports CFI to the consumer: as // a series of statements of the form, "At address X, column Y changed @@ -1094,7 +1094,7 @@ class CallFrameInfo { // handling are described here, rather poorly: // http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html // http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html - // + // // The mechanics of C++ exception handling, personality routines, // and language-specific data areas are described here, rather nicely: // http://www.codesourcery.com/public/cxx-abi/abi-eh.html @@ -1127,7 +1127,7 @@ class CallFrameInfo { // The start of this entry in the buffer. const uint8_t* start; - + // Which kind of entry this is. // // We want to be able to use this for error reporting even while we're @@ -1161,13 +1161,13 @@ class CallFrameInfo { struct CIE: public Entry { uint8_t version; // CFI data version number string augmentation; // vendor format extension markers - uint64_t code_alignment_factor; // scale for code address adjustments + uint64_t code_alignment_factor; // scale for code address adjustments int data_alignment_factor; // scale for stack pointer adjustments unsigned return_address_register; // which register holds the return addr // True if this CIE includes Linux C++ ABI 'z' augmentation data. bool has_z_augmentation; - + // Parsed 'z' augmentation data. These are meaningful only if // has_z_augmentation is true. bool has_z_lsda; // The 'z' augmentation included 'L'. @@ -1221,7 +1221,7 @@ class CallFrameInfo { class ValExpressionRule; class RuleMap; class State; - + // Parse the initial length and id of a CFI entry, either a CIE, an FDE, // or a .eh_frame end-of-data mark. CURSOR points to the beginning of the // data to parse. On success, populate ENTRY as appropriate, and return @@ -1308,7 +1308,7 @@ class CallFrameInfo::Handler { // Immediately after a call to Entry, the handler should assume that // the rule for each callee-saves register is "unchanged" --- that // is, that the register still has the value it had in the caller. - // + // // If a *Rule function returns true, we continue processing this entry's // instructions. If a *Rule function returns false, we stop evaluating // instructions, and skip to the next entry. Either way, we call End @@ -1497,13 +1497,13 @@ class CallFrameInfo::Reporter { // The instruction at INSN_OFFSET in the entry at OFFSET, of kind // KIND, establishes a rule that cites the CFA, but we have not // established a CFA rule yet. - virtual void NoCFARule(uint64_t offset, CallFrameInfo::EntryKind kind, + virtual void NoCFARule(uint64_t offset, CallFrameInfo::EntryKind kind, uint64_t insn_offset); // The instruction at INSN_OFFSET in the entry at OFFSET, of kind // KIND, is a DW_CFA_restore_state instruction, but the stack of // saved states is empty. - virtual void EmptyStateStack(uint64_t offset, CallFrameInfo::EntryKind kind, + virtual void EmptyStateStack(uint64_t offset, CallFrameInfo::EntryKind kind, uint64_t insn_offset); // The DW_CFA_remember_state instruction at INSN_OFFSET in the entry @@ -1511,7 +1511,7 @@ class CallFrameInfo::Reporter { // rule, whereas the current state does have a CFA rule. This is // bogus input, which the CallFrameInfo::Handler interface doesn't // (and shouldn't) have any way to report. - virtual void ClearingCFARule(uint64_t offset, CallFrameInfo::EntryKind kind, + virtual void ClearingCFARule(uint64_t offset, CallFrameInfo::EntryKind kind, uint64_t insn_offset); protected: diff --git a/src/common/dwarf/dwarf2reader_cfi_unittest.cc b/src/common/dwarf/dwarf2reader_cfi_unittest.cc index 67b662a35..ce92f1698 100644 --- a/src/common/dwarf/dwarf2reader_cfi_unittest.cc +++ b/src/common/dwarf/dwarf2reader_cfi_unittest.cc @@ -34,6 +34,7 @@ #include // Must come first #endif +#include #include #include diff --git a/src/common/dwarf/dwarf2reader_die_unittest.cc b/src/common/dwarf/dwarf2reader_die_unittest.cc index 2b365396d..2eb663370 100644 --- a/src/common/dwarf/dwarf2reader_die_unittest.cc +++ b/src/common/dwarf/dwarf2reader_die_unittest.cc @@ -34,6 +34,7 @@ #include // Must come first #endif +#include #include #include diff --git a/src/common/dwarf/elf_reader.cc b/src/common/dwarf/elf_reader.cc index 31deb9db4..7669895b9 100644 --- a/src/common/dwarf/elf_reader.cc +++ b/src/common/dwarf/elf_reader.cc @@ -195,8 +195,8 @@ class ElfSectionReader { public: ElfSectionReader(const char* cname, const string& path, int fd, const typename ElfArch::Shdr& section_header) - : contents_aligned_(NULL), - contents_(NULL), + : contents_aligned_(nullptr), + contents_(nullptr), header_(section_header) { // Back up to the beginning of the page we're interested in. const size_t additional = header_.sh_offset % getpagesize(); @@ -218,7 +218,7 @@ class ElfSectionReader { return; } - contents_aligned_ = mmap(NULL, size_aligned_, PROT_READ, MAP_SHARED, + contents_aligned_ = mmap(nullptr, size_aligned_, PROT_READ, MAP_SHARED, fd, offset_aligned); // Set where the offset really should begin. contents_ = reinterpret_cast(contents_aligned_) + @@ -232,7 +232,7 @@ class ElfSectionReader { } ~ElfSectionReader() { - if (contents_aligned_ != NULL) + if (contents_aligned_ != nullptr) munmap(contents_aligned_, size_aligned_); else delete[] contents_; @@ -274,14 +274,14 @@ class SymbolIterator { SymbolIterator(ElfReaderImpl* reader, typename ElfArch::Word section_type) : symbol_section_(reader->GetSectionByType(section_type)), - string_section_(NULL), + string_section_(nullptr), num_symbols_in_section_(0), symbol_within_section_(0) { // If this section type doesn't exist, leave // num_symbols_in_section_ as zero, so this iterator is already // done(). - if (symbol_section_ != NULL) { + if (symbol_section_ != nullptr) { num_symbols_in_section_ = symbol_section_->header().sh_size / symbol_section_->header().sh_entsize; @@ -313,7 +313,7 @@ class SymbolIterator { const char* GetSymbolName() const { int name_offset = GetSymbol()->st_name; if (name_offset == 0) - return NULL; + return nullptr; return string_section_->GetOffset(name_offset); } @@ -351,9 +351,9 @@ class ElfReaderImpl { explicit ElfReaderImpl(const string& path, int fd) : path_(path), fd_(fd), - section_headers_(NULL), - program_headers_(NULL), - opd_section_(NULL), + section_headers_(nullptr), + program_headers_(nullptr), + opd_section_(nullptr), base_for_text_(0), plts_supported_(false), plt_code_size_(0), @@ -409,17 +409,17 @@ class ElfReaderImpl { static bool IsArchElfFile(int fd, string* error) { unsigned char header[EI_NIDENT]; if (pread(fd, header, sizeof(header), 0) != sizeof(header)) { - if (error != NULL) *error = "Could not read header"; + if (error != nullptr) *error = "Could not read header"; return false; } if (memcmp(header, ELFMAG, SELFMAG) != 0) { - if (error != NULL) *error = "Missing ELF magic"; + if (error != nullptr) *error = "Missing ELF magic"; return false; } if (header[EI_CLASS] != ElfArch::kElfClass) { - if (error != NULL) *error = "Different word size"; + if (error != nullptr) *error = "Different word size"; return false; } @@ -429,7 +429,7 @@ class ElfReaderImpl { else if (header[EI_DATA] == ELFDATA2MSB) endian = __BIG_ENDIAN; if (endian != __BYTE_ORDER) { - if (error != NULL) *error = "Different byte order"; + if (error != nullptr) *error = "Different byte order"; return false; } @@ -476,7 +476,7 @@ class ElfReaderImpl { for (SymbolIterator it(this, section_type); !it.done(); it.Next()) { const char* name = it.GetSymbolName(); - if (name == NULL) + if (name == nullptr) continue; const typename ElfArch::Sym* sym = it.GetSymbol(); if (CanUseSymbol(name, sym)) { @@ -720,7 +720,7 @@ class ElfReaderImpl { return GetSection(k); } } - return NULL; + return nullptr; } // Return the name of section "shndx". Returns NULL if the section @@ -733,11 +733,11 @@ class ElfReaderImpl { // "size". Returns NULL if the section is not found. const char* GetSectionContentsByIndex(int shndx, size_t* size) { const ElfSectionReader* section = GetSection(shndx); - if (section != NULL) { + if (section != nullptr) { *size = section->section_size(); return section->contents(); } - return NULL; + return nullptr; } // Return a pointer to the first section of the given name by @@ -751,17 +751,17 @@ class ElfReaderImpl { // table, so reverse the direction of iteration. int shndx = is_dwp_ ? GetNumSections() - k - 1 : k; const char* name = GetSectionName(section_headers_[shndx].sh_name); - if (name != NULL && ElfReader::SectionNamesMatch(section_name, name)) { + if (name != nullptr && ElfReader::SectionNamesMatch(section_name, name)) { const ElfSectionReader* section = GetSection(shndx); - if (section == NULL) { - return NULL; + if (section == nullptr) { + return nullptr; } else { *size = section->section_size(); return section->contents(); } } } - return NULL; + return nullptr; } // This is like GetSectionContentsByName() but it returns a lot of extra @@ -774,10 +774,10 @@ class ElfReaderImpl { // table, so reverse the direction of iteration. int shndx = is_dwp_ ? GetNumSections() - k - 1 : k; const char* name = GetSectionName(section_headers_[shndx].sh_name); - if (name != NULL && ElfReader::SectionNamesMatch(section_name, name)) { + if (name != nullptr && ElfReader::SectionNamesMatch(section_name, name)) { const ElfSectionReader* section = GetSection(shndx); - if (section == NULL) { - return NULL; + if (section == nullptr) { + return nullptr; } else { info->type = section->header().sh_type; info->flags = section->header().sh_flags; @@ -792,7 +792,7 @@ class ElfReaderImpl { } } } - return NULL; + return nullptr; } // p_vaddr of the first PT_LOAD segment (if any), or 0 if no PT_LOAD @@ -881,10 +881,10 @@ class ElfReaderImpl { const char* GetSectionName(typename ElfArch::Word sh_name) { const ElfSectionReader* shstrtab = GetSection(GetStringTableIndex()); - if (shstrtab != NULL) { + if (shstrtab != nullptr) { return shstrtab->GetOffset(sh_name); } - return NULL; + return nullptr; } // Return an ElfSectionReader for the given section. The reader will @@ -898,7 +898,7 @@ class ElfReaderImpl { else name = GetSectionNameByIndex(num); ElfSectionReader*& reader = sections_[num]; - if (reader == NULL) + if (reader == nullptr) reader = new ElfSectionReader(name, path_, fd_, section_headers_[num]); return reader->contents() ? reader : nullptr; @@ -953,14 +953,14 @@ class ElfReaderImpl { program_headers_ = new typename ElfArch::Phdr[GetNumProgramHeaders()]; // Presize the sections array for efficiency. - sections_.resize(GetNumSections(), NULL); + sections_.resize(GetNumSections(), nullptr); return true; } // Given the "value" of a function descriptor return the address of the // function (i.e. the dereferenced value). Otherwise return "value". uint64_t AdjustPPC64FunctionDescriptorSymbolValue(uint64_t value) { - if (opd_section_ != NULL && + if (opd_section_ != nullptr && opd_info_.addr <= value && value < opd_info_.addr + opd_info_.size) { uint64_t offset = value - opd_info_.addr; @@ -1051,7 +1051,7 @@ class ElfReaderImpl { }; ElfReader::ElfReader(const string& path) - : path_(path), fd_(-1), impl32_(NULL), impl64_(NULL) { + : path_(path), fd_(-1), impl32_(nullptr), impl64_(nullptr) { // linux 2.6.XX kernel can show deleted files like this: // /var/run/nscd/dbYLJYaE (deleted) // and the kernel-supplied vdso and vsyscall mappings like this: @@ -1070,9 +1070,9 @@ ElfReader::ElfReader(const string& path) ElfReader::~ElfReader() { if (fd_ != -1) close(fd_); - if (impl32_ != NULL) + if (impl32_ != nullptr) delete impl32_; - if (impl64_ != NULL) + if (impl64_ != nullptr) delete impl64_; } @@ -1090,7 +1090,7 @@ template static bool IsElfFile(const int fd, const string& path) { if (fd < 0) return false; - if (!ElfReaderImpl::IsArchElfFile(fd, NULL)) { + if (!ElfReaderImpl::IsArchElfFile(fd, nullptr)) { // No error message here. IsElfFile gets called many times. return false; } @@ -1173,13 +1173,14 @@ uint64_t ElfReader::VaddrOfFirstLoadSegment() { } const char* ElfReader::GetSectionName(int shndx) { - if (shndx < 0 || static_cast(shndx) >= GetNumSections()) return NULL; + if (shndx < 0 || static_cast(shndx) >= GetNumSections()) + return nullptr; if (IsElf32File()) { return GetImpl32()->GetSectionNameByIndex(shndx); } else if (IsElf64File()) { return GetImpl64()->GetSectionNameByIndex(shndx); } else { - return NULL; + return nullptr; } } @@ -1199,7 +1200,7 @@ const char* ElfReader::GetSectionByIndex(int shndx, size_t* size) { } else if (IsElf64File()) { return GetImpl64()->GetSectionContentsByIndex(shndx, size); } else { - return NULL; + return nullptr; } } @@ -1210,7 +1211,7 @@ const char* ElfReader::GetSectionByName(const string& section_name, } else if (IsElf64File()) { return GetImpl64()->GetSectionContentsByName(section_name, size); } else { - return NULL; + return nullptr; } } @@ -1221,7 +1222,7 @@ const char* ElfReader::GetSectionInfoByName(const string& section_name, } else if (IsElf64File()) { return GetImpl64()->GetSectionInfoByName(section_name, info); } else { - return NULL; + return nullptr; } } @@ -1249,14 +1250,14 @@ bool ElfReader::IsDynamicSharedObject() { } ElfReaderImpl* ElfReader::GetImpl32() { - if (impl32_ == NULL) { + if (impl32_ == nullptr) { impl32_ = new ElfReaderImpl(path_, fd_); } return impl32_; } ElfReaderImpl* ElfReader::GetImpl64() { - if (impl64_ == NULL) { + if (impl64_ == nullptr) { impl64_ = new ElfReaderImpl(path_, fd_); } return impl64_; @@ -1268,11 +1269,11 @@ ElfReaderImpl* ElfReader::GetImpl64() { template static bool IsNonStrippedELFBinaryImpl(const string& path, const int fd, bool debug_only) { - if (!ElfReaderImpl::IsArchElfFile(fd, NULL)) return false; + if (!ElfReaderImpl::IsArchElfFile(fd, nullptr)) return false; ElfReaderImpl elf_reader(path, fd); return debug_only ? elf_reader.HasDebugSections() - : (elf_reader.GetSectionByType(SHT_SYMTAB) != NULL); + : (elf_reader.GetSectionByType(SHT_SYMTAB) != nullptr); } // Helper for the IsNon[Debug]StrippedELFBinary functions. diff --git a/src/common/dwarf/functioninfo.cc b/src/common/dwarf/functioninfo.cc index 5b0ce81a4..39c24c8cb 100644 --- a/src/common/dwarf/functioninfo.cc +++ b/src/common/dwarf/functioninfo.cc @@ -38,12 +38,12 @@ #include #include +#include #include #include #include "common/dwarf/functioninfo.h" #include "common/dwarf/bytereader.h" -#include "common/scoped_ptr.h" #include "common/using_std_string.h" namespace google_breakpad { @@ -164,7 +164,7 @@ void CUFunctionInfoHandler::ProcessAttributeUnsigned(uint64_t offset, GetSectionByName(sections_, ".debug_line"); assert(iter != sections_.end()); - scoped_ptr lireader(new LineInfo(iter->second.first + data, + std::unique_ptr lireader(new LineInfo(iter->second.first + data, iter->second.second - data, reader_, linehandler_)); lireader->Start(); diff --git a/src/common/dwarf/functioninfo.h b/src/common/dwarf/functioninfo.h index 1387c5ba4..4139564cf 100644 --- a/src/common/dwarf/functioninfo.h +++ b/src/common/dwarf/functioninfo.h @@ -124,7 +124,7 @@ class CUFunctionInfoHandler: public Dwarf2Handler { offset_to_funcinfo_(offset_to_funcinfo), address_to_funcinfo_(address_to_funcinfo), linehandler_(linehandler), sections_(sections), - reader_(reader), current_function_info_(NULL) { } + reader_(reader), current_function_info_(nullptr) { } virtual ~CUFunctionInfoHandler() { } diff --git a/src/common/dwarf_cfi_to_module.cc b/src/common/dwarf_cfi_to_module.cc index 4c594175e..c6325bd78 100644 --- a/src/common/dwarf_cfi_to_module.cc +++ b/src/common/dwarf_cfi_to_module.cc @@ -37,6 +37,8 @@ #include // Must come first #endif +#include + #include #include #include diff --git a/src/common/dwarf_cu_to_module.cc b/src/common/dwarf_cu_to_module.cc index 94a0d428e..c58181d71 100644 --- a/src/common/dwarf_cu_to_module.cc +++ b/src/common/dwarf_cu_to_module.cc @@ -302,9 +302,9 @@ class DwarfCUToModule::GenericDIEHandler: public DIEHandler { parent_context_(parent_context), offset_(offset), declaration_(false), - specification_(NULL), + specification_(nullptr), no_specification(false), - abstract_origin_(NULL), + abstract_origin_(nullptr), forward_ref_die_offset_(0), specification_offset_(0) { } // Derived classes' ProcessAttributeUnsigned can defer to this to @@ -562,6 +562,29 @@ static bool IsEmptyRange(const vector& ranges) { return size == 0; } +// A handler for DW_TAG_lexical_block DIEs. +class DwarfCUToModule::LexicalBlockHandler : public GenericDIEHandler { + public: + LexicalBlockHandler(CUContext* cu_context, + uint64_t offset, + int inline_nest_level, + vector>& inlines) + : GenericDIEHandler(cu_context, nullptr, offset), + inline_nest_level_(inline_nest_level), + inlines_(inlines) {} + + DIEHandler* FindChildHandler(uint64_t offset, enum DwarfTag tag); + bool EndAttributes() { return true; } + void Finish(); + + private: + int inline_nest_level_; + // A vector of inlines in the same nest level. It's owned by its parent + // function/inline. At Finish(), add this inline into the vector. + vector>& inlines_; + // A vector of child inlines. + vector> child_inlines_; +}; // A handler for DW_TAG_inlined_subroutine DIEs. class DwarfCUToModule::InlineHandler : public GenericDIEHandler { @@ -645,8 +668,11 @@ DIEHandler* DwarfCUToModule::InlineHandler::FindChildHandler( case DW_TAG_inlined_subroutine: return new InlineHandler(cu_context_, nullptr, offset, inline_nest_level_ + 1, child_inlines_); + case DW_TAG_lexical_block: + return new LexicalBlockHandler(cu_context_, offset, + inline_nest_level_ + 1, child_inlines_); default: - return NULL; + return nullptr; } } @@ -715,6 +741,29 @@ void DwarfCUToModule::InlineHandler::Finish() { inlines_.push_back(std::move(in)); } +DIEHandler* DwarfCUToModule::LexicalBlockHandler::FindChildHandler( + uint64_t offset, + enum DwarfTag tag) { + switch (tag) { + case DW_TAG_inlined_subroutine: + return new InlineHandler(cu_context_, nullptr, offset, inline_nest_level_, + child_inlines_); + case DW_TAG_lexical_block: + return new LexicalBlockHandler(cu_context_, offset, inline_nest_level_, + child_inlines_); + default: + return nullptr; + } +} + +void DwarfCUToModule::LexicalBlockHandler::Finish() { + // Insert child inlines inside the lexical block into the inline vector from + // parent as if the block does not exit. + inlines_.insert(inlines_.end(), + std::make_move_iterator(child_inlines_.begin()), + std::make_move_iterator(child_inlines_.end())); +} + // A handler for DIEs that contain functions and contribute a // component to their names: namespaces, classes, etc. class DwarfCUToModule::NamedScopeHandler: public GenericDIEHandler { @@ -831,8 +880,11 @@ DIEHandler* DwarfCUToModule::FuncHandler::FindChildHandler( case DW_TAG_union_type: return new NamedScopeHandler(cu_context_, &child_context_, offset, handle_inline_); + case DW_TAG_lexical_block: + if (handle_inline_) + return new LexicalBlockHandler(cu_context_, offset, 0, child_inlines_); default: - return NULL; + return nullptr; } } @@ -908,7 +960,7 @@ void DwarfCUToModule::FuncHandler::Finish() { StringView name = name_.empty() ? name_omitted : name_; // Create a Module::Function based on the data we've gathered, and // add it to the functions_ list. - scoped_ptr func(new Module::Function(name, low_pc_)); + std::unique_ptr func(new Module::Function(name, low_pc_)); func->ranges = ranges; func->parameter_size = 0; // If the name was unqualified, prefer the Extern name if there's a mismatch @@ -949,7 +1001,7 @@ void DwarfCUToModule::FuncHandler::Finish() { } bool DwarfCUToModule::NamedScopeHandler::EndAttributes() { - child_context_.name = ComputeQualifiedName(NULL); + child_context_.name = ComputeQualifiedName(nullptr); if (child_context_.name.empty() && no_specification) { cu_context_->reporter->UnknownSpecification(offset_, specification_offset_); } @@ -970,7 +1022,7 @@ DIEHandler* DwarfCUToModule::NamedScopeHandler::FindChildHandler( return new NamedScopeHandler(cu_context_, &child_context_, offset, handle_inline_); default: - return NULL; + return nullptr; } } @@ -1180,7 +1232,7 @@ DIEHandler* DwarfCUToModule::FindChildHandler( return new NamedScopeHandler(cu_context_.get(), child_context_.get(), offset, handle_inline); default: - return NULL; + return nullptr; } } @@ -1342,12 +1394,12 @@ void DwarfCUToModule::AssignLinesToFunctions() { // The last line that we used any piece of. We use this only for // generating warnings. - const Module::Line* last_line_used = NULL; + const Module::Line* last_line_used = nullptr; // The last function and line we warned about --- so we can avoid // doing so more than once. - const Module::Function* last_function_cited = NULL; - const Module::Line* last_line_cited = NULL; + const Module::Function* last_function_cited = nullptr; + const Module::Line* last_line_cited = nullptr; // Prepare a sorted list of ranges with range-to-function mapping vector sorted_ranges; @@ -1373,12 +1425,12 @@ void DwarfCUToModule::AssignLinesToFunctions() { line = &*line_it; current = std::min(range->address, line->address); } else if (line_it != lines_.end()) { - range = NULL; + range = nullptr; line = &*line_it; current = line->address; } else if (range_it != sorted_ranges.end()) { range = &*range_it; - line = NULL; + line = nullptr; current = range->address; } else { return; @@ -1509,12 +1561,12 @@ void DwarfCUToModule::AssignLinesToFunctions() { && next_transition >= range_it->address && !within(*range_it, next_transition)) range_it++; - range = (range_it != sorted_ranges.end()) ? &(*range_it) : NULL; + range = (range_it != sorted_ranges.end()) ? &(*range_it) : nullptr; while (line_it != lines_.end() && next_transition >= line_it->address && !within(*line_it, next_transition)) line_it++; - line = (line_it != lines_.end()) ? &*line_it : NULL; + line = (line_it != lines_.end()) ? &*line_it : nullptr; // We must make progress. assert(next_transition > current); diff --git a/src/common/dwarf_cu_to_module.h b/src/common/dwarf_cu_to_module.h index 1ff0ebc7f..90adde1ca 100644 --- a/src/common/dwarf_cu_to_module.h +++ b/src/common/dwarf_cu_to_module.h @@ -40,6 +40,7 @@ #include +#include #include #include @@ -47,7 +48,6 @@ #include "common/module.h" #include "common/dwarf/dwarf2diehandler.h" #include "common/dwarf/dwarf2reader.h" -#include "common/scoped_ptr.h" #include "common/using_std_string.h" namespace google_breakpad { @@ -118,7 +118,7 @@ class DwarfCUToModule: public RootDIEHandler { const bool handle_inter_cu_refs_; // Inter-compilation unit data used internally by the handlers. - scoped_ptr file_private_; + std::unique_ptr file_private_; std::vector uncompressed_sections_; }; @@ -254,6 +254,63 @@ class DwarfCUToModule: public RootDIEHandler { void UncoveredHeading(); }; + class NullWarningReporter : public WarningReporter { + public: + NullWarningReporter(const string& filename, uint64_t cu_offset) + : WarningReporter(filename, cu_offset) {} + + // Set the name of the compilation unit we're processing to NAME. + void SetCUName(const string& name) {} + + // Accessor and setter for uncovered_warnings_enabled_. + // UncoveredFunction and UncoveredLine only report a problem if that is + // true. By default, these warnings are disabled, because those + // conditions occur occasionally in healthy code. + void set_uncovered_warnings_enabled(bool value) {} + + // A DW_AT_specification in the DIE at OFFSET refers to a DIE we + // haven't processed yet, or that wasn't marked as a declaration, + // at TARGET. + void UnknownSpecification(uint64_t offset, uint64_t target) {} + + // A DW_AT_abstract_origin in the DIE at OFFSET refers to a DIE we + // haven't processed yet, or that wasn't marked as inline, at TARGET. + void UnknownAbstractOrigin(uint64_t offset, uint64_t target) {} + + // We were unable to find the DWARF section named SECTION_NAME. + void MissingSection(const string& section_name) {} + + // The CU's DW_AT_stmt_list offset OFFSET is bogus. + void BadLineInfoOffset(uint64_t offset) {} + + // FUNCTION includes code covered by no line number data. + void UncoveredFunction(const Module::Function& function) {} + + // Line number NUMBER in LINE_FILE, of length LENGTH, includes code + // covered by no function. + void UncoveredLine(const Module::Line& line) {} + + // The DW_TAG_subprogram DIE at OFFSET has no name specified directly + // in the DIE, nor via a DW_AT_specification or DW_AT_abstract_origin + // link. + void UnnamedFunction(uint64_t offset) {} + + // __cxa_demangle() failed to demangle INPUT. + void DemangleError(const string& input) {} + + // The DW_FORM_ref_addr at OFFSET to TARGET was not handled because + // FilePrivate did not retain the inter-CU specification data. + void UnhandledInterCUReference(uint64_t offset, uint64_t target) {} + + // The DW_AT_ranges at offset is malformed (truncated or outside of the + // .debug_ranges section's bound). + void MalformedRangeList(uint64_t offset) {} + + // A DW_AT_ranges attribute was encountered but the no .debug_ranges + // section was found. + void MissingRanges() {} + }; + // Create a DWARF debugging info handler for a compilation unit // within FILE_CONTEXT. This uses information received from the // CompilationUnit DWARF parser to populate @@ -300,6 +357,7 @@ class DwarfCUToModule: public RootDIEHandler { struct Specification; class GenericDIEHandler; class FuncHandler; + class LexicalBlockHandler; class InlineHandler; class NamedScopeHandler; @@ -333,10 +391,10 @@ class DwarfCUToModule: public RootDIEHandler { LineToModuleHandler* line_reader_; // This compilation unit's context. - scoped_ptr cu_context_; + std::unique_ptr cu_context_; // A context for our children. - scoped_ptr child_context_; + std::unique_ptr child_context_; // True if this compilation unit has source line information. bool has_source_line_info_; diff --git a/src/common/dwarf_cu_to_module_unittest.cc b/src/common/dwarf_cu_to_module_unittest.cc index 134b2c243..d073c87a0 100644 --- a/src/common/dwarf_cu_to_module_unittest.cc +++ b/src/common/dwarf_cu_to_module_unittest.cc @@ -209,7 +209,8 @@ class CUFixtureBase { // not Finish. If NAME is non-zero, use it as the DW_AT_name // attribute. DIEHandler* StartSpecifiedDIE(DIEHandler* parent, DwarfTag tag, - uint64_t specification, const char* name = NULL); + uint64_t specification, + const char* name = nullptr); // Define a function as a child of PARENT with the given name, address, and // size. If high_pc_form is DW_FORM_addr then the DW_AT_high_pc attribute @@ -410,7 +411,7 @@ DIEHandler* CUFixtureBase::StartNamedDIE(DIEHandler* parent, google_breakpad::DIEHandler* handler = parent->FindChildHandler(0x8f4c783c0467c989ULL, tag); if (!handler) - return NULL; + return nullptr; handler->ProcessAttributeString(google_breakpad::DW_AT_name, google_breakpad::DW_FORM_strp, name); @@ -418,7 +419,7 @@ DIEHandler* CUFixtureBase::StartNamedDIE(DIEHandler* parent, if (!handler->EndAttributes()) { handler->Finish(); delete handler; - return NULL; + return nullptr; } return handler; @@ -431,7 +432,7 @@ DIEHandler* CUFixtureBase::StartSpecifiedDIE(DIEHandler* parent, google_breakpad::DIEHandler* handler = parent->FindChildHandler(0x8f4c783c0467c989ULL, tag); if (!handler) - return NULL; + return nullptr; if (name) handler->ProcessAttributeString(google_breakpad::DW_AT_name, google_breakpad::DW_FORM_strp, @@ -442,7 +443,7 @@ DIEHandler* CUFixtureBase::StartSpecifiedDIE(DIEHandler* parent, if (!handler->EndAttributes()) { handler->Finish(); delete handler; - return NULL; + return nullptr; } return handler; @@ -456,7 +457,7 @@ void CUFixtureBase::DefineFunction(google_breakpad::DIEHandler* parent, google_breakpad::DIEHandler* func = parent->FindChildHandler(0xe34797c7e68590a8LL, google_breakpad::DW_TAG_subprogram); - ASSERT_TRUE(func != NULL); + ASSERT_TRUE(func != nullptr); func->ProcessAttributeString(google_breakpad::DW_AT_name, google_breakpad::DW_FORM_strp, name); @@ -488,7 +489,7 @@ void CUFixtureBase::DeclarationDIE(DIEHandler* parent, uint64_t offset, const string& name, const string& mangled_name) { google_breakpad::DIEHandler* die = parent->FindChildHandler(offset, tag); - ASSERT_TRUE(die != NULL); + ASSERT_TRUE(die != nullptr); if (!name.empty()) die->ProcessAttributeString(google_breakpad::DW_AT_name, google_breakpad::DW_FORM_strp, @@ -514,7 +515,7 @@ void CUFixtureBase::DefinitionDIE(DIEHandler* parent, Module::Address size) { google_breakpad::DIEHandler* die = parent->FindChildHandler(0x6ccfea031a9e6cc9ULL, tag); - ASSERT_TRUE(die != NULL); + ASSERT_TRUE(die != nullptr); die->ProcessAttributeReference(google_breakpad::DW_AT_specification, google_breakpad::DW_FORM_ref4, specification); @@ -543,7 +544,7 @@ void CUFixtureBase::AbstractInstanceDIE(DIEHandler* parent, DwarfForm form) { google_breakpad::DIEHandler* die = parent->FindChildHandler(offset, google_breakpad::DW_TAG_subprogram); - ASSERT_TRUE(die != NULL); + ASSERT_TRUE(die != nullptr); if (specification != 0ULL) die->ProcessAttributeReference(google_breakpad::DW_AT_specification, google_breakpad::DW_FORM_ref4, @@ -571,7 +572,7 @@ void CUFixtureBase::DefineInlineInstanceDIE(DIEHandler* parent, google_breakpad::DIEHandler* func = parent->FindChildHandler(0x11c70f94c6e87ccdLL, google_breakpad::DW_TAG_subprogram); - ASSERT_TRUE(func != NULL); + ASSERT_TRUE(func != nullptr); if (!name.empty()) { func->ProcessAttributeString(google_breakpad::DW_AT_name, google_breakpad::DW_FORM_strp, @@ -681,7 +682,7 @@ TEST_F(SimpleCU, OneFunc) { StartCU(); DefineFunction(&root_handler_, "function1", - 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, NULL); + 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, nullptr); root_handler_.Finish(); TestFunctionCount(1); @@ -697,7 +698,7 @@ TEST_F(SimpleCU, OneFuncHighPcIsLength) { StartCU(); DefineFunction6(&root_handler_, "function1", - 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, NULL, + 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, nullptr, google_breakpad::DW_FORM_udata); root_handler_.Finish(); @@ -731,7 +732,7 @@ TEST_F(SimpleCU, IrrelevantNamedScopeChildren) { StartCU(); DIEHandler* class_A_handler = StartNamedDIE(&root_handler_, google_breakpad::DW_TAG_class_type, "class_A"); - EXPECT_TRUE(class_A_handler != NULL); + EXPECT_TRUE(class_A_handler != nullptr); EXPECT_FALSE(class_A_handler ->FindChildHandler(0x02e55999b865e4e9ULL, google_breakpad::DW_TAG_lexical_block)); @@ -816,7 +817,7 @@ TEST_F(SimpleCU, UnnamedFunction) { StartCU(); DefineFunction(&root_handler_, "", - 0x72b80e41a0ac1d40ULL, 0x537174f231ee181cULL, NULL); + 0x72b80e41a0ac1d40ULL, 0x537174f231ee181cULL, nullptr); root_handler_.Finish(); TestFunctionCount(1); @@ -893,10 +894,10 @@ TEST_P(FuncLinePairing, Pairing) { StartCU(); DefineFunction(&root_handler_, "function1", s.functions[0].start, - s.functions[0].end - s.functions[0].start, NULL); + s.functions[0].end - s.functions[0].start, nullptr); DefineFunction(&root_handler_, "function2", s.functions[1].start, - s.functions[1].end - s.functions[1].start, NULL); + s.functions[1].end - s.functions[1].start, nullptr); root_handler_.Finish(); TestFunctionCount(2); @@ -940,7 +941,7 @@ TEST_F(FuncLinePairing, FuncsNoLines) { StartCU(); DefineFunction(&root_handler_, "function1", 0x127da12ffcf5c51fULL, 0x1000U, - NULL); + nullptr); root_handler_.Finish(); TestFunctionCount(1); @@ -952,8 +953,8 @@ TEST_F(FuncLinePairing, GapThenFunction) { PushLine(10, 2, "line-file-1", 263008005); StartCU(); - DefineFunction(&root_handler_, "function1", 10, 2, NULL); - DefineFunction(&root_handler_, "function2", 20, 2, NULL); + DefineFunction(&root_handler_, "function1", 10, 2, nullptr); + DefineFunction(&root_handler_, "function2", 20, 2, nullptr); root_handler_.Finish(); TestFunctionCount(2); @@ -978,10 +979,10 @@ TEST_F(FuncLinePairing, GCCAlignmentStretch) { PushLine(20, 10, "line-file", 61661044); StartCU(); - DefineFunction(&root_handler_, "function1", 10, 5, NULL); + DefineFunction(&root_handler_, "function1", 10, 5, nullptr); // five-byte gap between functions, covered by line 63351048. // This should not elicit a warning. - DefineFunction(&root_handler_, "function2", 20, 10, NULL); + DefineFunction(&root_handler_, "function2", 20, 10, nullptr); root_handler_.Finish(); TestFunctionCount(2); @@ -1002,8 +1003,10 @@ TEST_F(FuncLinePairing, LineAtEndOfAddressSpace) { EXPECT_CALL(reporter_, UncoveredLine(_)).WillOnce(Return()); StartCU(); - DefineFunction(&root_handler_, "function1", 0xfffffffffffffff0ULL, 6, NULL); - DefineFunction(&root_handler_, "function2", 0xfffffffffffffffaULL, 5, NULL); + DefineFunction(&root_handler_, "function1", 0xfffffffffffffff0ULL, 6, + nullptr); + DefineFunction(&root_handler_, "function2", 0xfffffffffffffffaULL, 5, + nullptr); root_handler_.Finish(); TestFunctionCount(2); @@ -1023,7 +1026,7 @@ TEST_F(FuncLinePairing, WarnOnceFunc) { EXPECT_CALL(reporter_, UncoveredFunction(_)).WillOnce(Return()); StartCU(); - DefineFunction(&root_handler_, "function", 10, 11, NULL); + DefineFunction(&root_handler_, "function", 10, 11, nullptr); root_handler_.Finish(); TestFunctionCount(1); @@ -1040,8 +1043,8 @@ TEST_F(FuncLinePairing, WarnOnceLine) { EXPECT_CALL(reporter_, UncoveredLine(_)).WillOnce(Return()); StartCU(); - DefineFunction(&root_handler_, "function1", 11, 1, NULL); - DefineFunction(&root_handler_, "function2", 13, 1, NULL); + DefineFunction(&root_handler_, "function1", 11, 1, nullptr); + DefineFunction(&root_handler_, "function2", 13, 1, nullptr); root_handler_.Finish(); TestFunctionCount(2); @@ -1072,9 +1075,9 @@ TEST_P(CXXQualifiedNames, TwoFunctions) { StartCU(); DIEHandler* enclosure_handler = StartNamedDIE(&root_handler_, tag, "Enclosure"); - EXPECT_TRUE(enclosure_handler != NULL); - DefineFunction(enclosure_handler, "func_B", 10, 1, NULL); - DefineFunction(enclosure_handler, "func_C", 20, 1, NULL); + EXPECT_TRUE(enclosure_handler != nullptr); + DefineFunction(enclosure_handler, "func_B", 10, 1, nullptr); + DefineFunction(enclosure_handler, "func_C", 20, 1, nullptr); enclosure_handler->Finish(); delete enclosure_handler; root_handler_.Finish(); @@ -1094,11 +1097,11 @@ TEST_P(CXXQualifiedNames, FuncInEnclosureInNamespace) { DIEHandler* namespace_handler = StartNamedDIE(&root_handler_, google_breakpad::DW_TAG_namespace, "Namespace"); - EXPECT_TRUE(namespace_handler != NULL); + EXPECT_TRUE(namespace_handler != nullptr); DIEHandler* enclosure_handler = StartNamedDIE(namespace_handler, tag, "Enclosure"); - EXPECT_TRUE(enclosure_handler != NULL); - DefineFunction(enclosure_handler, "function", 10, 1, NULL); + EXPECT_TRUE(enclosure_handler != nullptr); + DefineFunction(enclosure_handler, "function", 10, 1, nullptr); enclosure_handler->Finish(); delete enclosure_handler; namespace_handler->Finish(); @@ -1117,15 +1120,15 @@ TEST_F(CXXQualifiedNames, FunctionInClassInStructInNamespace) { DIEHandler* namespace_handler = StartNamedDIE(&root_handler_, google_breakpad::DW_TAG_namespace, "namespace_A"); - EXPECT_TRUE(namespace_handler != NULL); + EXPECT_TRUE(namespace_handler != nullptr); DIEHandler* struct_handler = StartNamedDIE(namespace_handler, google_breakpad::DW_TAG_structure_type, "struct_B"); - EXPECT_TRUE(struct_handler != NULL); + EXPECT_TRUE(struct_handler != nullptr); DIEHandler* class_handler = StartNamedDIE(struct_handler, google_breakpad::DW_TAG_class_type, "class_C"); - DefineFunction(class_handler, "function_D", 10, 1, NULL); + DefineFunction(class_handler, "function_D", 10, 1, nullptr); class_handler->Finish(); delete class_handler; struct_handler->Finish(); @@ -1151,7 +1154,7 @@ const LanguageAndQualifiedName LanguageAndQualifiedNameCases[] = { { google_breakpad::DW_LANG_C_plus_plus, "class_A::function_B" }, { google_breakpad::DW_LANG_Java, "class_A.function_B" }, { google_breakpad::DW_LANG_Cobol74, "class_A::function_B" }, - { google_breakpad::DW_LANG_Mips_Assembler, NULL } + { google_breakpad::DW_LANG_Mips_Assembler, nullptr } }; class QualifiedForLanguage @@ -1171,7 +1174,7 @@ TEST_P(QualifiedForLanguage, MemberFunction) { DIEHandler* class_handler = StartNamedDIE(&root_handler_, google_breakpad::DW_TAG_class_type, "class_A"); - DefineFunction(class_handler, "function_B", 10, 1, NULL); + DefineFunction(class_handler, "function_B", 10, 1, nullptr); class_handler->Finish(); delete class_handler; root_handler_.Finish(); @@ -1195,7 +1198,7 @@ TEST_P(QualifiedForLanguage, MemberFunctionSignedLanguage) { DIEHandler* class_handler = StartNamedDIE(&root_handler_, google_breakpad::DW_TAG_class_type, "class_A"); - DefineFunction(class_handler, "function_B", 10, 1, NULL); + DefineFunction(class_handler, "function_B", 10, 1, nullptr); class_handler->Finish(); delete class_handler; root_handler_.Finish(); @@ -1321,7 +1324,7 @@ TEST_F(Specifications, FunctionDeclarationParent) { DIEHandler* class_handler = StartNamedDIE(&root_handler_, google_breakpad::DW_TAG_class_type, "class_A"); - ASSERT_TRUE(class_handler != NULL); + ASSERT_TRUE(class_handler != nullptr); DeclarationDIE(class_handler, 0x0e0e877c8404544aULL, google_breakpad::DW_TAG_subprogram, "declaration-name", ""); class_handler->Finish(); @@ -1349,7 +1352,7 @@ TEST_F(Specifications, NamedScopeDeclarationParent) { DIEHandler* space_handler = StartNamedDIE(&root_handler_, google_breakpad::DW_TAG_namespace, "space_A"); - ASSERT_TRUE(space_handler != NULL); + ASSERT_TRUE(space_handler != nullptr); DeclarationDIE(space_handler, 0x419bb1d12f9a73a2ULL, google_breakpad::DW_TAG_class_type, "class-declaration-name", ""); @@ -1361,9 +1364,9 @@ TEST_F(Specifications, NamedScopeDeclarationParent) { DIEHandler* class_handler = StartSpecifiedDIE(&root_handler_, google_breakpad::DW_TAG_class_type, 0x419bb1d12f9a73a2ULL, "class-definition-name"); - ASSERT_TRUE(class_handler != NULL); + ASSERT_TRUE(class_handler != nullptr); DefineFunction(class_handler, "function", - 0x5d13433d0df13d00ULL, 0x48ebebe5ade2cab4ULL, NULL); + 0x5d13433d0df13d00ULL, 0x48ebebe5ade2cab4ULL, nullptr); class_handler->Finish(); delete class_handler; } @@ -1402,7 +1405,7 @@ TEST_F(Specifications, InlineFunctionInNamespace) { DIEHandler* space_handler = StartNamedDIE(&root_handler_, google_breakpad::DW_TAG_namespace, "Namespace"); - ASSERT_TRUE(space_handler != NULL); + ASSERT_TRUE(space_handler != nullptr); AbstractInstanceDIE(space_handler, 0x1e8dac5d507ed7abULL, google_breakpad::DW_INL_inlined, 0LL, "func-name"); DefineInlineInstanceDIE(space_handler, "", 0x1e8dac5d507ed7abULL, diff --git a/src/common/language.cc b/src/common/language.cc index 61693a8cd..a1d17adec 100644 --- a/src/common/language.cc +++ b/src/common/language.cc @@ -92,7 +92,7 @@ class CPPLanguage: public Language { int status; char* demangled_c = - abi::__cxa_demangle(mangled.c_str(), NULL, NULL, &status); + abi::__cxa_demangle(mangled.c_str(), nullptr, nullptr, &status); DemangleResult result; if (status == 0) { diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc index b693fc9e1..f0680a959 100644 --- a/src/common/linux/dump_symbols.cc +++ b/src/common/linux/dump_symbols.cc @@ -55,6 +55,7 @@ #include #endif +#include #include #include #include @@ -103,7 +104,6 @@ using google_breakpad::PageAllocator; #ifndef NO_STABS_SUPPORT using google_breakpad::StabsToModule; #endif -using google_breakpad::scoped_ptr; using google_breakpad::wasteful_vector; // Define AARCH64 ELF architecture if host machine does not include this define. @@ -150,7 +150,7 @@ class MmapWrapper { public: MmapWrapper() : is_set_(false) {} ~MmapWrapper() { - if (is_set_ && base_ != NULL) { + if (is_set_ && base_ != nullptr) { assert(size_ > 0); munmap(base_, size_); } @@ -163,7 +163,7 @@ class MmapWrapper { void release() { assert(is_set_); is_set_ = false; - base_ = NULL; + base_ = nullptr; size_ = 0; } @@ -315,31 +315,17 @@ uint32_t GetCompressionHeader( std::pair UncompressZlibSectionContents( const uint8_t* compressed_buffer, uint64_t compressed_size, uint64_t uncompressed_size) { - z_stream stream; - memset(&stream, 0, sizeof stream); - - stream.avail_in = compressed_size; - stream.avail_out = uncompressed_size; - stream.next_in = const_cast(compressed_buffer); - google_breakpad::scoped_array uncompressed_buffer( new uint8_t[uncompressed_size]); - int status = inflateInit(&stream); - while (stream.avail_in != 0 && status == Z_OK) { - stream.next_out = - uncompressed_buffer.get() + uncompressed_size - stream.avail_out; + uLongf size = static_cast(uncompressed_size); - if ((status = inflate(&stream, Z_FINISH)) != Z_STREAM_END) { - break; - } - - status = inflateReset(&stream); - } + int status = uncompress( + uncompressed_buffer.get(), &size, compressed_buffer, compressed_size); - return inflateEnd(&stream) != Z_OK || status != Z_OK || stream.avail_out != 0 - ? std::make_pair(nullptr, 0) - : std::make_pair(uncompressed_buffer.release(), uncompressed_size); + return status != Z_OK + ? std::make_pair(nullptr, 0) + : std::make_pair(uncompressed_buffer.release(), uncompressed_size); } #ifdef HAVE_LIBZSTD @@ -512,7 +498,11 @@ bool LoadDwarf(const string& dwarf_filename, &byte_reader, &die_dispatcher); // Process the entire compilation unit; get the offset of the next. - offset += reader.Start(); + uint64_t result = reader.Start(); + if (result == 0) { + return false; + } + offset += result; // Start to process split dwarf file. if (reader.ShouldProcessSplitDwarf()) { StartProcessSplitDwarf(&reader, module, endianness, handle_inter_cu_refs, @@ -654,7 +644,7 @@ bool LoadELF(const string& obj_file, MmapWrapper* map_wrapper, obj_file.c_str(), strerror(errno)); return false; } - void* obj_base = mmap(NULL, st.st_size, + void* obj_base = mmap(nullptr, st.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, obj_fd, 0); if (obj_base == MAP_FAILED) { fprintf(stderr, "Failed to mmap ELF file '%s': %s\n", @@ -836,7 +826,7 @@ class LoadSymbolsInfo { string debuglink_file() const { return debuglink_file_; } - void set_debuglink_file(string file) { + void set_debuglink_file(const string& file) { debuglink_file_ = file; } @@ -892,6 +882,7 @@ bool LoadSymbols(const string& obj_file, const char* names_end = names + section_names->sh_size; bool found_debug_info_section = false; bool found_usable_info = false; + bool usable_info_parsed = false; if ((options.symbol_data & SYMBOLS_AND_FILES) || (options.symbol_data & INLINES)) { @@ -907,8 +898,10 @@ bool LoadSymbols(const string& obj_file, found_debug_info_section = true; found_usable_info = true; info->LoadedSection(".stab"); - if (!LoadStabs(elf_header, stab_section, stabstr_section, - big_endian, module)) { + bool result = LoadStabs(elf_header, stab_section, stabstr_section, + big_endian, module); + usable_info_parsed = usable_info_parsed || result; + if (!result) { fprintf(stderr, "%s: \".stab\" section found, but failed to load" " STABS debugging information\n", obj_file.c_str()); } @@ -995,9 +988,11 @@ bool LoadSymbols(const string& obj_file, found_debug_info_section = true; found_usable_info = true; info->LoadedSection(".debug_info"); - if (!LoadDwarf(obj_file, elf_header, big_endian, + bool result = LoadDwarf(obj_file, elf_header, big_endian, options.handle_inter_cu_refs, - options.symbol_data & INLINES, module)) { + options.symbol_data & INLINES, module); + usable_info_parsed = usable_info_parsed || result; + if (!result){ fprintf(stderr, "%s: \".debug_info\" section found, but failed to load " "DWARF debugging information\n", obj_file.c_str()); } @@ -1102,7 +1097,7 @@ bool LoadSymbols(const string& obj_file, return false; } - return true; + return usable_info_parsed; } // Return the breakpad symbol file identifier for the architecture of @@ -1123,7 +1118,8 @@ const char* ElfArchitecture(const typename ElfClass::Ehdr* elf_header) { case EM_SPARCV9: return "sparcv9"; case EM_X86_64: return "x86_64"; case EM_RISCV: return "riscv"; - default: return NULL; + case EM_NDS32: return "nds32"; + default: return nullptr; } } @@ -1162,7 +1158,8 @@ template bool InitModuleForElfClass(const typename ElfClass::Ehdr* elf_header, const string& obj_filename, const string& obj_os, - scoped_ptr& module, + const string& module_id, + std::unique_ptr& module, bool enable_multiple_field) { PageAllocator allocator; wasteful_vector identifier(&allocator, kDefaultBuildIdSize); @@ -1185,10 +1182,14 @@ bool InitModuleForElfClass(const typename ElfClass::Ehdr* elf_header, ? name_buf : google_breakpad::BaseName(obj_filename); - // Add an extra "0" at the end. PDB files on Windows have an 'age' - // number appended to the end of the file identifier; this isn't - // really used or necessary on other platforms, but be consistent. - string id = FileID::ConvertIdentifierToUUIDString(identifier) + "0"; + // Use the provided module_id + string id = module_id.empty() + // Add an extra "0" at the end. PDB files on Windows have an 'age' + // number appended to the end of the file identifier; this isn't + // really used or necessary on other platforms, but be consistent. + ? FileID::ConvertIdentifierToUUIDString(identifier) + "0" + : module_id; + // This is just the raw Build ID in hex. string code_id = FileID::ConvertIdentifierToString(identifier); @@ -1202,16 +1203,17 @@ template bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header, const string& obj_filename, const string& obj_os, + const string& module_id, const std::vector& debug_dirs, const DumpOptions& options, Module** out_module) { typedef typename ElfClass::Ehdr Ehdr; - *out_module = NULL; + *out_module = nullptr; - scoped_ptr module; - if (!InitModuleForElfClass(elf_header, obj_filename, obj_os, module, - options.enable_multiple_field)) { + std::unique_ptr module; + if (!InitModuleForElfClass(elf_header, obj_filename, obj_os, module_id, + module, options.enable_multiple_field)) { return false; } @@ -1231,7 +1233,7 @@ bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header, // Load debuglink ELF file. fprintf(stderr, "Found debugging info in %s\n", debuglink_file.c_str()); MmapWrapper debug_map_wrapper; - Ehdr* debug_elf_header = NULL; + Ehdr* debug_elf_header = nullptr; if (!LoadELF(debuglink_file, &debug_map_wrapper, reinterpret_cast(&debug_elf_header)) || !SanitizeDebugFile(debug_elf_header, debuglink_file, @@ -1260,6 +1262,7 @@ namespace google_breakpad { bool ReadSymbolDataInternal(const uint8_t* obj_file, const string& obj_filename, const string& obj_os, + const string& module_id, const std::vector& debug_dirs, const DumpOptions& options, Module** module) { @@ -1272,12 +1275,12 @@ bool ReadSymbolDataInternal(const uint8_t* obj_file, if (elfclass == ELFCLASS32) { return ReadSymbolDataElfClass( reinterpret_cast(obj_file), obj_filename, obj_os, - debug_dirs, options, module); + module_id, debug_dirs, options, module); } if (elfclass == ELFCLASS64) { return ReadSymbolDataElfClass( reinterpret_cast(obj_file), obj_filename, obj_os, - debug_dirs, options, module); + module_id, debug_dirs, options, module); } return false; @@ -1286,15 +1289,16 @@ bool ReadSymbolDataInternal(const uint8_t* obj_file, bool WriteSymbolFile(const string& load_path, const string& obj_file, const string& obj_os, + const string& module_id, const std::vector& debug_dirs, const DumpOptions& options, std::ostream& sym_stream) { Module* module; - if (!ReadSymbolData(load_path, obj_file, obj_os, debug_dirs, options, + if (!ReadSymbolData(load_path, obj_file, obj_os, module_id, debug_dirs, options, &module)) return false; - bool result = module->Write(sym_stream, options.symbol_data); + bool result = module->Write(sym_stream, options.symbol_data, options.preserve_load_address); delete module; return result; } @@ -1305,9 +1309,10 @@ bool WriteSymbolFile(const string& load_path, bool WriteSymbolFileHeader(const string& load_path, const string& obj_file, const string& obj_os, + const string& module_id, std::ostream& sym_stream) { MmapWrapper map_wrapper; - void* elf_header = NULL; + void* elf_header = nullptr; if (!LoadELF(load_path, &map_wrapper, &elf_header)) { fprintf(stderr, "Could not load ELF file: %s\n", obj_file.c_str()); return false; @@ -1319,18 +1324,18 @@ bool WriteSymbolFileHeader(const string& load_path, } int elfclass = ElfClass(elf_header); - scoped_ptr module; + std::unique_ptr module; if (elfclass == ELFCLASS32) { if (!InitModuleForElfClass( reinterpret_cast(elf_header), obj_file, obj_os, - module, /*enable_multiple_field=*/false)) { + module_id, module, /*enable_multiple_field=*/false)) { fprintf(stderr, "Failed to load ELF module: %s\n", obj_file.c_str()); return false; } } else if (elfclass == ELFCLASS64) { if (!InitModuleForElfClass( reinterpret_cast(elf_header), obj_file, obj_os, - module, /*enable_multiple_field=*/false)) { + module_id, module, /*enable_multiple_field=*/false)) { fprintf(stderr, "Failed to load ELF module: %s\n", obj_file.c_str()); return false; } @@ -1345,16 +1350,17 @@ bool WriteSymbolFileHeader(const string& load_path, bool ReadSymbolData(const string& load_path, const string& obj_file, const string& obj_os, + const string& module_id, const std::vector& debug_dirs, const DumpOptions& options, Module** module) { MmapWrapper map_wrapper; - void* elf_header = NULL; + void* elf_header = nullptr; if (!LoadELF(load_path, &map_wrapper, &elf_header)) return false; return ReadSymbolDataInternal(reinterpret_cast(elf_header), - obj_file, obj_os, debug_dirs, options, module); + obj_file, obj_os, module_id, debug_dirs, options, module); } } // namespace google_breakpad diff --git a/src/common/linux/dump_symbols.h b/src/common/linux/dump_symbols.h index f1802ecc3..25ede3e0f 100644 --- a/src/common/linux/dump_symbols.h +++ b/src/common/linux/dump_symbols.h @@ -48,14 +48,17 @@ class Module; struct DumpOptions { DumpOptions(SymbolData symbol_data, bool handle_inter_cu_refs, - bool enable_multiple_field) + bool enable_multiple_field, + bool preserve_load_address) : symbol_data(symbol_data), handle_inter_cu_refs(handle_inter_cu_refs), - enable_multiple_field(enable_multiple_field) {} + enable_multiple_field(enable_multiple_field), + preserve_load_address(preserve_load_address) {} SymbolData symbol_data; bool handle_inter_cu_refs; bool enable_multiple_field; + bool preserve_load_address; }; // Find all the debugging information in OBJ_FILE, an ELF executable @@ -67,6 +70,7 @@ struct DumpOptions { bool WriteSymbolFile(const string& load_path, const string& obj_file, const string& obj_os, + const string& module_id, const std::vector& debug_dirs, const DumpOptions& options, std::ostream& sym_stream); @@ -78,6 +82,7 @@ bool WriteSymbolFile(const string& load_path, bool WriteSymbolFileHeader(const string& load_path, const string& obj_file, const string& obj_os, + const string& module_id, std::ostream& sym_stream); // As above, but simply return the debugging information in MODULE @@ -86,6 +91,7 @@ bool WriteSymbolFileHeader(const string& load_path, bool ReadSymbolData(const string& load_path, const string& obj_file, const string& obj_os, + const string& module_id, const std::vector& debug_dirs, const DumpOptions& options, Module** module); diff --git a/src/common/linux/dump_symbols_unittest.cc b/src/common/linux/dump_symbols_unittest.cc index 55dcdeed8..f20ac0dfc 100644 --- a/src/common/linux/dump_symbols_unittest.cc +++ b/src/common/linux/dump_symbols_unittest.cc @@ -55,6 +55,7 @@ namespace google_breakpad { bool ReadSymbolDataInternal(const uint8_t* obj_file, const string& obj_filename, const string& obj_os, + const string& module_id, const std::vector& debug_dir, const DumpOptions& options, Module** module); @@ -95,10 +96,11 @@ TYPED_TEST(DumpSymbols, Invalid) { Elf32_Ehdr header; memset(&header, 0, sizeof(header)); Module* module; - DumpOptions options(ALL_SYMBOL_DATA, true, false); + DumpOptions options(ALL_SYMBOL_DATA, true, false, false); EXPECT_FALSE(ReadSymbolDataInternal(reinterpret_cast(&header), "foo", "Linux", + "", vector(), options, &module)); @@ -132,10 +134,11 @@ TYPED_TEST(DumpSymbols, SimplePublic) { this->GetElfContents(elf); Module* module; - DumpOptions options(ALL_SYMBOL_DATA, true, false); + DumpOptions options(ALL_SYMBOL_DATA, true, false, false); EXPECT_TRUE(ReadSymbolDataInternal(this->elfdata, "foo", "Linux", + "", vector(), options, &module)); @@ -151,6 +154,54 @@ TYPED_TEST(DumpSymbols, SimplePublic) { delete module; } +TYPED_TEST(DumpSymbols, ModuleIdOverride) { + ELF elf(TypeParam::kMachine, TypeParam::kClass, kLittleEndian); + // Zero out text section for simplicity. + Section text(kLittleEndian); + text.Append(4096, 0); + elf.AddSection(".text", text, SHT_PROGBITS); + + // Add a public symbol. + StringTable table(kLittleEndian); + SymbolTable syms(kLittleEndian, TypeParam::kAddrSize, table); + syms.AddSymbol("superfunc", + (typename TypeParam::Addr)0x1000, + (typename TypeParam::Addr)0x10, + // ELF32_ST_INFO works for 32-or 64-bit. + ELF32_ST_INFO(STB_GLOBAL, STT_FUNC), + SHN_UNDEF + 1); + int index = elf.AddSection(".dynstr", table, SHT_STRTAB); + elf.AddSection(".dynsym", syms, + SHT_DYNSYM, // type + SHF_ALLOC, // flags + 0, // addr + index, // link + sizeof(typename TypeParam::Sym)); // entsize + + elf.Finish(); + this->GetElfContents(elf); + + Module* module; + DumpOptions options(ALL_SYMBOL_DATA, true, false, false); + EXPECT_TRUE(ReadSymbolDataInternal(this->elfdata, + "foo", + "Linux", + "some_module_id", + vector(), + options, + &module)); + + stringstream s; + module->Write(s, ALL_SYMBOL_DATA); + const string expected = + string("MODULE Linux ") + TypeParam::kMachineName + + " some_module_id foo\n" + "INFO CODE_ID 00000000000000000000000000000000\n" + "PUBLIC 1000 0 superfunc\n"; + EXPECT_EQ(expected, s.str()); + delete module; +} + TYPED_TEST(DumpSymbols, SimpleBuildID) { ELF elf(TypeParam::kMachine, TypeParam::kClass, kLittleEndian); // Zero out text section for simplicity. @@ -189,10 +240,11 @@ TYPED_TEST(DumpSymbols, SimpleBuildID) { this->GetElfContents(elf); Module* module; - DumpOptions options(ALL_SYMBOL_DATA, true, false); + DumpOptions options(ALL_SYMBOL_DATA, true, false, false); EXPECT_TRUE(ReadSymbolDataInternal(this->elfdata, "foo", "Linux", + "", vector(), options, &module)); diff --git a/src/common/linux/elf_core_dump.cc b/src/common/linux/elf_core_dump.cc index 67257fd27..89cfed5bd 100644 --- a/src/common/linux/elf_core_dump.cc +++ b/src/common/linux/elf_core_dump.cc @@ -39,6 +39,8 @@ #include #include +#include "common/memory_allocator.h" + namespace google_breakpad { // Implementation of ElfCoreDump::Note. @@ -48,7 +50,7 @@ ElfCoreDump::Note::Note() {} ElfCoreDump::Note::Note(const MemoryRange& content) : content_(content) {} bool ElfCoreDump::Note::IsValid() const { - return GetHeader() != NULL; + return GetHeader() != nullptr; } const ElfCoreDump::Nhdr* ElfCoreDump::Note::GetHeader() const { @@ -92,8 +94,7 @@ ElfCoreDump::Note ElfCoreDump::Note::GetNextNote() const { // static size_t ElfCoreDump::Note::AlignedSize(size_t size) { - size_t mask = sizeof(Word) - 1; - return (size + mask) & ~mask; + return PageAllocator::AlignUp(size, sizeof(Word)); } @@ -144,7 +145,7 @@ const ElfCoreDump::Phdr* ElfCoreDump::GetProgramHeader(unsigned index) const { return reinterpret_cast(content_.GetArrayElement( header->e_phoff, header->e_phentsize, index)); } - return NULL; + return nullptr; } const ElfCoreDump::Phdr* ElfCoreDump::GetFirstProgramHeaderOfType( @@ -155,7 +156,7 @@ const ElfCoreDump::Phdr* ElfCoreDump::GetFirstProgramHeaderOfType( return program; } } - return NULL; + return nullptr; } unsigned ElfCoreDump::GetProgramHeaderCount() const { diff --git a/src/common/linux/elf_core_dump_unittest.cc b/src/common/linux/elf_core_dump_unittest.cc index 25cab99f8..633b60dbd 100644 --- a/src/common/linux/elf_core_dump_unittest.cc +++ b/src/common/linux/elf_core_dump_unittest.cc @@ -55,10 +55,10 @@ using std::set; TEST(ElfCoreDumpTest, DefaultConstructor) { ElfCoreDump core; EXPECT_FALSE(core.IsValid()); - EXPECT_EQ(NULL, core.GetHeader()); + EXPECT_EQ(nullptr, core.GetHeader()); EXPECT_EQ(0U, core.GetProgramHeaderCount()); - EXPECT_EQ(NULL, core.GetProgramHeader(0)); - EXPECT_EQ(NULL, core.GetFirstProgramHeaderOfType(PT_LOAD)); + EXPECT_EQ(nullptr, core.GetProgramHeader(0)); + EXPECT_EQ(nullptr, core.GetFirstProgramHeaderOfType(PT_LOAD)); EXPECT_FALSE(core.GetFirstNote().IsValid()); } @@ -76,10 +76,10 @@ TEST(ElfCoreDumpTest, TestElfHeader) { ASSERT_TRUE(mapped_core_file.Map(core_file, 0)); core.SetContent(mapped_core_file.content()); EXPECT_FALSE(core.IsValid()); - EXPECT_EQ(NULL, core.GetHeader()); + EXPECT_EQ(nullptr, core.GetHeader()); EXPECT_EQ(0U, core.GetProgramHeaderCount()); - EXPECT_EQ(NULL, core.GetProgramHeader(0)); - EXPECT_EQ(NULL, core.GetFirstProgramHeaderOfType(PT_LOAD)); + EXPECT_EQ(nullptr, core.GetProgramHeader(0)); + EXPECT_EQ(nullptr, core.GetFirstProgramHeaderOfType(PT_LOAD)); EXPECT_FALSE(core.GetFirstNote().IsValid()); ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header))); @@ -146,7 +146,7 @@ TEST(ElfCoreDumpTest, ValidCoreFile) { const unsigned kCrashThread = 1; const int kCrashSignal = SIGABRT; ASSERT_TRUE(crash_generator.CreateChildCrash(kNumOfThreads, kCrashThread, - kCrashSignal, NULL)); + kCrashSignal, nullptr)); pid_t expected_crash_thread_id = crash_generator.GetThreadId(kCrashThread); set expected_thread_ids; for (unsigned i = 0; i < kNumOfThreads; ++i) { @@ -210,13 +210,13 @@ TEST(ElfCoreDumpTest, ValidCoreFile) { switch (note.GetType()) { case NT_PRPSINFO: { - EXPECT_TRUE(description.data() != NULL); + EXPECT_TRUE(description.data() != nullptr); EXPECT_EQ(sizeof(elf_prpsinfo), description.length()); ++num_nt_prpsinfo; break; } case NT_PRSTATUS: { - EXPECT_TRUE(description.data() != NULL); + EXPECT_TRUE(description.data() != nullptr); EXPECT_EQ(sizeof(elf_prstatus), description.length()); const elf_prstatus* status = description.GetData(0); actual_thread_ids.insert(status->pr_pid); @@ -231,7 +231,7 @@ TEST(ElfCoreDumpTest, ValidCoreFile) { } #if defined(__i386__) || defined(__x86_64__) case NT_FPREGSET: { - EXPECT_TRUE(description.data() != NULL); + EXPECT_TRUE(description.data() != nullptr); EXPECT_EQ(sizeof(user_fpregs_struct), description.length()); ++num_nt_fpregset; break; @@ -239,7 +239,7 @@ TEST(ElfCoreDumpTest, ValidCoreFile) { #endif #if defined(__i386__) case NT_PRXFPREG: { - EXPECT_TRUE(description.data() != NULL); + EXPECT_TRUE(description.data() != nullptr); EXPECT_EQ(sizeof(user_fpxregs_struct), description.length()); ++num_nt_prxfpreg; break; diff --git a/src/common/linux/elf_symbols_to_module.cc b/src/common/linux/elf_symbols_to_module.cc index 70d50f891..2e5c4eeb5 100644 --- a/src/common/linux/elf_symbols_to_module.cc +++ b/src/common/linux/elf_symbols_to_module.cc @@ -36,6 +36,7 @@ #include "common/linux/elf_symbols_to_module.h" +#include #include #include #include @@ -168,7 +169,7 @@ bool ELFSymbolsToModule(const uint8_t* symtab_section, #if !defined(__ANDROID__) // Android NDK doesn't provide abi::__cxa_demangle. int status = 0; char* demangled = - abi::__cxa_demangle(ext->name.c_str(), NULL, NULL, &status); + abi::__cxa_demangle(ext->name.c_str(), nullptr, nullptr, &status); if (demangled) { if (status == 0) ext->name = demangled; diff --git a/src/common/linux/elfutils-inl.h b/src/common/linux/elfutils-inl.h index 5fcc9c445..571371310 100644 --- a/src/common/linux/elfutils-inl.h +++ b/src/common/linux/elfutils-inl.h @@ -49,13 +49,13 @@ const typename ElfClass::Shdr* FindElfSectionByName( const char* section_names, const char* names_end, int nsection) { - assert(name != NULL); - assert(sections != NULL); + assert(name != nullptr); + assert(sections != nullptr); assert(nsection > 0); int name_len = my_strlen(name); if (name_len == 0) - return NULL; + return nullptr; for (int i = 0; i < nsection; ++i) { const char* section_name = section_names + sections[i].sh_name; @@ -65,7 +65,7 @@ const typename ElfClass::Shdr* FindElfSectionByName( return sections + i; } } - return NULL; + return nullptr; } } // namespace google_breakpad diff --git a/src/common/linux/elfutils.cc b/src/common/linux/elfutils.cc index 95b5db829..770aeb1dc 100644 --- a/src/common/linux/elfutils.cc +++ b/src/common/linux/elfutils.cc @@ -61,7 +61,7 @@ void FindElfClassSection(const char* elf_base, assert(elf_header->e_ident[EI_CLASS] == ElfClass::kClass); if (elf_header->e_shoff == 0) { - *section_start = NULL; + *section_start = nullptr; *section_size = 0; return; } @@ -78,7 +78,7 @@ void FindElfClassSection(const char* elf_base, sections, names, names_end, elf_header->e_shnum); - if (section != NULL && section->sh_size > 0) { + if (section != nullptr && section->sh_size > 0) { *section_start = elf_base + section->sh_offset; *section_size = section->sh_size; } @@ -135,7 +135,7 @@ bool FindElfSection(const void* elf_mapped_base, assert(section_start); assert(section_size); - *section_start = NULL; + *section_start = nullptr; *section_size = 0; if (!IsValidElf(elf_mapped_base)) @@ -148,11 +148,11 @@ bool FindElfSection(const void* elf_mapped_base, if (cls == ELFCLASS32) { FindElfClassSection(elf_base, section_name, section_type, section_start, section_size); - return *section_start != NULL; + return *section_start != nullptr; } else if (cls == ELFCLASS64) { FindElfClassSection(elf_base, section_name, section_type, section_start, section_size); - return *section_start != NULL; + return *section_start != nullptr; } return false; diff --git a/src/common/linux/file_id.cc b/src/common/linux/file_id.cc index d8fcbd8d6..1dfd5e956 100644 --- a/src/common/linux/file_id.cc +++ b/src/common/linux/file_id.cc @@ -48,6 +48,7 @@ #include "common/linux/elfutils.h" #include "common/linux/linux_libc_support.h" #include "common/linux/memory_mapped_file.h" +#include "common/memory_allocator.h" #include "common/using_std_string.h" #include "third_party/lss/linux_syscall_support.h" @@ -60,7 +61,10 @@ const size_t kMDGUIDSize = sizeof(MDGUID); FileID::FileID(const char* path) : path_(path) {} // ELF note name and desc are 32-bits word padded. -#define NOTE_PADDING(a) ((a + 3) & ~3) +template +inline T NotePadding(T size) { + return PageAllocator::AlignUp(size, 4); +} // These functions are also used inside the crashed process, so be safe // and use the syscall/libc wrappers instead of direct syscalls or libc. @@ -77,9 +81,9 @@ static bool ElfClassBuildIDNoteIdentifier(const void* section, size_t length, if (note_header->n_type == NT_GNU_BUILD_ID) break; note_header = reinterpret_cast( - reinterpret_cast(note_header) + sizeof(Nhdr) + - NOTE_PADDING(note_header->n_namesz) + - NOTE_PADDING(note_header->n_descsz)); + reinterpret_cast(note_header) + sizeof(Nhdr) + + NotePadding(note_header->n_namesz) + + NotePadding(note_header->n_descsz)); } if (reinterpret_cast(note_header) >= section_end || note_header->n_descsz == 0) { @@ -87,7 +91,7 @@ static bool ElfClassBuildIDNoteIdentifier(const void* section, size_t length, } const uint8_t* build_id = reinterpret_cast(note_header) + - sizeof(Nhdr) + NOTE_PADDING(note_header->n_namesz); + sizeof(Nhdr) + NotePadding(note_header->n_namesz); identifier.insert(identifier.end(), build_id, build_id + note_header->n_descsz); @@ -99,6 +103,13 @@ static bool ElfClassBuildIDNoteIdentifier(const void* section, size_t length, // and copy it into |identifier|. static bool FindElfBuildIDNote(const void* elf_mapped_base, wasteful_vector& identifier) { + void* note_section; + size_t note_size; + if (FindElfSection(elf_mapped_base, ".note.gnu.build-id", SHT_NOTE, + (const void**)¬e_section, ¬e_size)) { + return ElfClassBuildIDNoteIdentifier(note_section, note_size, identifier); + } + PageAllocator allocator; // lld normally creates 2 PT_NOTEs, gold normally creates 1. auto_wasteful_vector segs(&allocator); @@ -110,13 +121,6 @@ static bool FindElfBuildIDNote(const void* elf_mapped_base, } } - void* note_section; - size_t note_size; - if (FindElfSection(elf_mapped_base, ".note.gnu.build-id", SHT_NOTE, - (const void**)¬e_section, ¬e_size)) { - return ElfClassBuildIDNoteIdentifier(note_section, note_size, identifier); - } - return false; } @@ -128,8 +132,10 @@ static bool HashElfTextSection(const void* elf_mapped_base, void* text_section; size_t text_size; - if (!FindElfSection(elf_mapped_base, ".text", SHT_PROGBITS, - (const void**)&text_section, &text_size) || + if ((!FindElfSection(elf_mapped_base, ".text", SHT_PROGBITS, + (const void**)&text_section, &text_size) && + !FindElfSection(elf_mapped_base, "text", SHT_PROGBITS, + (const void**)&text_section, &text_size)) || text_size == 0) { return false; } diff --git a/src/common/linux/file_id_unittest.cc b/src/common/linux/file_id_unittest.cc index 0ef453532..9de57c123 100644 --- a/src/common/linux/file_id_unittest.cc +++ b/src/common/linux/file_id_unittest.cc @@ -176,6 +176,31 @@ TYPED_TEST(FileIDTest, ElfClass) { EXPECT_EQ(expected_identifier_string, identifier_string); } +TYPED_TEST(FileIDTest, ZephyrTextSection) { + const char expected_identifier_string[] = + "80808080808000000000008080808080"; + const size_t kTextSectionSize = 128; + + ELF elf(EM_386, TypeParam::kClass, kLittleEndian); + Section text(kLittleEndian); + for (size_t i = 0; i < kTextSectionSize; ++i) { + text.D8(i * 3); + } + // Some binaries, namely Zephyr firmware binaries (https://www.zephyrproject.org/), + // refer to the `.text` section as `text`. They are logically identical however + // and should be handled the same. + elf.AddSection("text", text, SHT_PROGBITS); + elf.Finish(); + this->GetElfContents(elf); + + id_vector identifier(this->make_vector()); + EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata, + identifier)); + + string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier); + EXPECT_EQ(expected_identifier_string, identifier_string); +} + TYPED_TEST(FileIDTest, BuildID) { const uint8_t kExpectedIdentifierBytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, @@ -326,6 +351,45 @@ TYPED_TEST(FileIDTest, BuildIDMultiplePH) { EXPECT_EQ(expected_identifier_string, identifier_string); } +TYPED_TEST(FileIDTest, BuildIDMultiplePHPreferGNU) { + const uint8_t kExpectedIdentifierBytes[] = + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13}; + const string expected_identifier_string = + this->get_file_id(kExpectedIdentifierBytes); + + ELF elf(EM_386, TypeParam::kClass, kLittleEndian); + Section text(kLittleEndian); + text.Append(4096, 0); + elf.AddSection(".text", text, SHT_PROGBITS); + Notes notes1(kLittleEndian); + notes1.AddNote(0, "Linux", + reinterpret_cast("\0x42\0x02\0\0"), 4); + Notes notes2(kLittleEndian); + notes2.AddNote(NT_GNU_BUILD_ID, "GNU", + reinterpret_cast("\0x42\0x02\0\0"), 4); + Notes notes3(kLittleEndian); + notes3.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes, + sizeof(kExpectedIdentifierBytes)); + int note1_idx = elf.AddSection(".note1", notes1, SHT_NOTE); + int note2_idx = elf.AddSection(".note2", notes2, SHT_NOTE); + int note3_idx = elf.AddSection(".note.gnu.build-id", notes3, SHT_NOTE); + elf.AddSegment(note1_idx, note1_idx, PT_NOTE); + elf.AddSegment(note2_idx, note2_idx, PT_NOTE); + elf.AddSegment(note3_idx, note3_idx, PT_NOTE); + elf.Finish(); + this->GetElfContents(elf); + + id_vector identifier(this->make_vector()); + EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata, + identifier)); + EXPECT_EQ(sizeof(kExpectedIdentifierBytes), identifier.size()); + + string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier); + EXPECT_EQ(expected_identifier_string, identifier_string); +} + // Test to make sure two files with different text sections produce // different hashes when not using a build id. TYPED_TEST(FileIDTest, UniqueHashes) { diff --git a/src/common/linux/google_crashdump_uploader_test.cc b/src/common/linux/google_crashdump_uploader_test.cc index e81f21d64..4e0c30e39 100644 --- a/src/common/linux/google_crashdump_uploader_test.cc +++ b/src/common/linux/google_crashdump_uploader_test.cc @@ -67,7 +67,7 @@ TEST_F(GoogleCrashdumpUploaderTest, InitFailsCausesUploadFailure) { GoogleCrashdumpUploader uploader("foobar", "1.0", "AAA-BBB", "", "", "test@test.com", "none", "/tmp/foo.dmp", "http://foo.com", "", "", std::move(m)); - ASSERT_FALSE(uploader.Upload(NULL, NULL, NULL)); + ASSERT_FALSE(uploader.Upload(nullptr, nullptr, nullptr)); } TEST_F(GoogleCrashdumpUploaderTest, TestSendRequestHappensWithValidParameters) { @@ -86,7 +86,7 @@ TEST_F(GoogleCrashdumpUploaderTest, TestSendRequestHappensWithValidParameters) { GoogleCrashdumpUploader uploader("foobar", "1.0", "AAA-BBB", "", "", "test@test.com", "none", tempfn, "http://foo.com", "", "", std::move(m)); - ASSERT_TRUE(uploader.Upload(NULL, NULL, NULL)); + ASSERT_TRUE(uploader.Upload(nullptr, nullptr, nullptr)); } @@ -97,7 +97,7 @@ TEST_F(GoogleCrashdumpUploaderTest, InvalidPathname) { GoogleCrashdumpUploader uploader("foobar", "1.0", "AAA-BBB", "", "", "test@test.com", "none", "/tmp/foo.dmp", "http://foo.com", "", "", std::move(m)); - ASSERT_FALSE(uploader.Upload(NULL, NULL, NULL)); + ASSERT_FALSE(uploader.Upload(nullptr, nullptr, nullptr)); } TEST_F(GoogleCrashdumpUploaderTest, TestRequiredParametersMustBePresent) { @@ -113,7 +113,7 @@ TEST_F(GoogleCrashdumpUploaderTest, TestRequiredParametersMustBePresent) { "http://foo.com", "", ""); - ASSERT_FALSE(uploader.Upload(NULL, NULL, NULL)); + ASSERT_FALSE(uploader.Upload(nullptr, nullptr, nullptr)); // Test with empty product version. GoogleCrashdumpUploader uploader1("product", @@ -128,7 +128,7 @@ TEST_F(GoogleCrashdumpUploaderTest, TestRequiredParametersMustBePresent) { "", ""); - ASSERT_FALSE(uploader1.Upload(NULL, NULL, NULL)); + ASSERT_FALSE(uploader1.Upload(nullptr, nullptr, nullptr)); // Test with empty client GUID. GoogleCrashdumpUploader uploader2("product", @@ -142,6 +142,6 @@ TEST_F(GoogleCrashdumpUploaderTest, TestRequiredParametersMustBePresent) { "", "", ""); - ASSERT_FALSE(uploader2.Upload(NULL, NULL, NULL)); + ASSERT_FALSE(uploader2.Upload(nullptr, nullptr, nullptr)); } } diff --git a/src/common/linux/guid_creator.cc b/src/common/linux/guid_creator.cc index 8635f9dc0..f3e576a40 100644 --- a/src/common/linux/guid_creator.cc +++ b/src/common/linux/guid_creator.cc @@ -121,7 +121,7 @@ class GUIDGenerator { // time(NULL) is a very poor seed, so lacking anything better mix an // address into it. We drop the four rightmost bits as they're likely to // be 0 on almost all architectures. - srand(time(NULL) | ((uintptr_t)&once_control >> 4)); + srand(time(nullptr) | ((uintptr_t)&once_control >> 4)); } static pthread_once_t once_control; diff --git a/src/common/linux/http_upload.cc b/src/common/linux/http_upload.cc index 0a5bdb502..e39042651 100644 --- a/src/common/linux/http_upload.cc +++ b/src/common/linux/http_upload.cc @@ -66,7 +66,7 @@ bool HTTPUpload::SendRequest(const string& url, string* response_body, long* response_code, string* error_description) { - if (response_code != NULL) + if (response_code != nullptr) *response_code = 0; if (!CheckParameters(parameters)) @@ -74,19 +74,19 @@ bool HTTPUpload::SendRequest(const string& url, // We may have been linked statically; if curl_easy_init is in the // current binary, no need to search for a dynamic version. - void* curl_lib = dlopen(NULL, RTLD_NOW); + void* curl_lib = dlopen(nullptr, RTLD_NOW); if (!CheckCurlLib(curl_lib)) { fprintf(stderr, "Failed to open curl lib from binary, use libcurl.so instead\n"); dlerror(); // Clear dlerror before attempting to open libraries. dlclose(curl_lib); - curl_lib = NULL; + curl_lib = nullptr; } if (!curl_lib) { curl_lib = dlopen("libcurl.so", RTLD_NOW); } if (!curl_lib) { - if (error_description != NULL) + if (error_description != nullptr) *error_description = dlerror(); curl_lib = dlopen("libcurl.so.4", RTLD_NOW); } @@ -105,7 +105,7 @@ bool HTTPUpload::SendRequest(const string& url, CURL* (*curl_easy_init)(void); *(void**) (&curl_easy_init) = dlsym(curl_lib, "curl_easy_init"); CURL* curl = (*curl_easy_init)(); - if (error_description != NULL) + if (error_description != nullptr) *error_description = "No Error"; if (!curl) { @@ -131,8 +131,8 @@ bool HTTPUpload::SendRequest(const string& url, if (!ca_certificate_file.empty()) (*curl_easy_setopt)(curl, CURLOPT_CAINFO, ca_certificate_file.c_str()); - struct curl_httppost* formpost = NULL; - struct curl_httppost* lastptr = NULL; + struct curl_httppost* formpost = nullptr; + struct curl_httppost* lastptr = nullptr; // Add form data. CURLFORMcode (*curl_formadd)(struct curl_httppost**, struct curl_httppost**, ...); *(void**) (&curl_formadd) = dlsym(curl_lib, "curl_formadd"); @@ -154,14 +154,14 @@ bool HTTPUpload::SendRequest(const string& url, (*curl_easy_setopt)(curl, CURLOPT_HTTPPOST, formpost); // Disable 100-continue header. - struct curl_slist* headerlist = NULL; + struct curl_slist* headerlist = nullptr; char buf[] = "Expect:"; struct curl_slist* (*curl_slist_append)(struct curl_slist*, const char*); *(void**) (&curl_slist_append) = dlsym(curl_lib, "curl_slist_append"); headerlist = (*curl_slist_append)(headerlist, buf); (*curl_easy_setopt)(curl, CURLOPT_HTTPHEADER, headerlist); - if (response_body != NULL) { + if (response_body != nullptr) { (*curl_easy_setopt)(curl, CURLOPT_WRITEFUNCTION, WriteCallback); (*curl_easy_setopt)(curl, CURLOPT_WRITEDATA, reinterpret_cast(response_body)); @@ -173,7 +173,7 @@ bool HTTPUpload::SendRequest(const string& url, CURLcode (*curl_easy_perform)(CURL*); *(void**) (&curl_easy_perform) = dlsym(curl_lib, "curl_easy_perform"); err_code = (*curl_easy_perform)(curl); - if (response_code != NULL) { + if (response_code != nullptr) { CURLcode (*curl_easy_getinfo)(CURL*, CURLINFO, ...); *(void**) (&curl_easy_getinfo) = dlsym(curl_lib, "curl_easy_getinfo"); (*curl_easy_getinfo)(curl, CURLINFO_RESPONSE_CODE, response_code); @@ -186,18 +186,18 @@ bool HTTPUpload::SendRequest(const string& url, url.c_str(), (*curl_easy_strerror)(err_code)); #endif - if (error_description != NULL) + if (error_description != nullptr) *error_description = (*curl_easy_strerror)(err_code); void (*curl_easy_cleanup)(CURL*); *(void**) (&curl_easy_cleanup) = dlsym(curl_lib, "curl_easy_cleanup"); (*curl_easy_cleanup)(curl); - if (formpost != NULL) { + if (formpost != nullptr) { void (*curl_formfree)(struct curl_httppost*); *(void**) (&curl_formfree) = dlsym(curl_lib, "curl_formfree"); (*curl_formfree)(formpost); } - if (headerlist != NULL) { + if (headerlist != nullptr) { void (*curl_slist_free_all)(struct curl_slist*); *(void**) (&curl_slist_free_all) = dlsym(curl_lib, "curl_slist_free_all"); (*curl_slist_free_all)(headerlist); diff --git a/src/common/linux/linux_libc_support.cc b/src/common/linux/linux_libc_support.cc index abcbfde8a..deb1a74b6 100644 --- a/src/common/linux/linux_libc_support.cc +++ b/src/common/linux/linux_libc_support.cc @@ -132,7 +132,7 @@ const char* my_strchr(const char* haystack, char needle) { } const char* my_strrchr(const char* haystack, char needle) { - const char* ret = NULL; + const char* ret = nullptr; while (*haystack) { if (*haystack == needle) ret = haystack; @@ -148,7 +148,7 @@ void* my_memchr(const void* src, int needle, size_t src_len) { if (*p == needle) return (void*)p; } - return NULL; + return nullptr; } // Read a hex value diff --git a/src/common/linux/linux_libc_support_unittest.cc b/src/common/linux/linux_libc_support_unittest.cc index 30dd1430c..48d6f5e29 100644 --- a/src/common/linux/linux_libc_support_unittest.cc +++ b/src/common/linux/linux_libc_support_unittest.cc @@ -38,7 +38,7 @@ typedef testing::Test LinuxLibcSupportTest; } TEST(LinuxLibcSupportTest, strlen) { - static const char* test_data[] = { "", "a", "aa", "aaa", "aabc", NULL }; + static const char* test_data[] = { "", "a", "aa", "aaa", "aabc", nullptr }; for (unsigned i = 0; ; ++i) { if (!test_data[i]) break; @@ -56,7 +56,7 @@ TEST(LinuxLibcSupportTest, strcmp) { "ab", "aa", "abc", "ab", "abc", "abc", - NULL, + nullptr, }; for (unsigned i = 0; ; ++i) { @@ -130,9 +130,9 @@ TEST(LinuxLibcSupportTest, uitos) { } TEST(LinuxLibcSupportTest, strchr) { - ASSERT_EQ(NULL, my_strchr("abc", 'd')); - ASSERT_EQ(NULL, my_strchr("", 'd')); - ASSERT_EQ(NULL, my_strchr("efghi", 'd')); + ASSERT_EQ(nullptr, my_strchr("abc", 'd')); + ASSERT_EQ(nullptr, my_strchr("", 'd')); + ASSERT_EQ(nullptr, my_strchr("efghi", 'd')); ASSERT_TRUE(my_strchr("a", 'a')); ASSERT_TRUE(my_strchr("abc", 'a')); @@ -144,9 +144,9 @@ TEST(LinuxLibcSupportTest, strchr) { } TEST(LinuxLibcSupportTest, strrchr) { - ASSERT_EQ(NULL, my_strrchr("abc", 'd')); - ASSERT_EQ(NULL, my_strrchr("", 'd')); - ASSERT_EQ(NULL, my_strrchr("efghi", 'd')); + ASSERT_EQ(nullptr, my_strrchr("abc", 'd')); + ASSERT_EQ(nullptr, my_strrchr("", 'd')); + ASSERT_EQ(nullptr, my_strrchr("efghi", 'd')); ASSERT_TRUE(my_strrchr("a", 'a')); ASSERT_TRUE(my_strrchr("abc", 'a')); @@ -158,9 +158,9 @@ TEST(LinuxLibcSupportTest, strrchr) { } TEST(LinuxLibcSupportTest, memchr) { - ASSERT_EQ(NULL, my_memchr("abc", 'd', 3)); - ASSERT_EQ(NULL, my_memchr("abcd", 'd', 3)); - ASSERT_EQ(NULL, my_memchr("a", 'a', 0)); + ASSERT_EQ(nullptr, my_memchr("abc", 'd', 3)); + ASSERT_EQ(nullptr, my_memchr("abcd", 'd', 3)); + ASSERT_EQ(nullptr, my_memchr("a", 'a', 0)); static const char abc3[] = "abcabcabc"; ASSERT_EQ(abc3, my_memchr(abc3, 'a', 3)); diff --git a/src/common/linux/memory_mapped_file.cc b/src/common/linux/memory_mapped_file.cc index a7b96eb59..5e54aca5a 100644 --- a/src/common/linux/memory_mapped_file.cc +++ b/src/common/linux/memory_mapped_file.cc @@ -95,7 +95,8 @@ bool MemoryMappedFile::Map(const char* path, size_t offset) { } size_t content_len = file_len - offset; - void* data = sys_mmap(NULL, content_len, PROT_READ, MAP_PRIVATE, fd, offset); + void* data = sys_mmap(nullptr, content_len, PROT_READ, MAP_PRIVATE, fd, + offset); sys_close(fd); if (data == MAP_FAILED) { return false; @@ -108,7 +109,7 @@ bool MemoryMappedFile::Map(const char* path, size_t offset) { void MemoryMappedFile::Unmap() { if (content_.data()) { sys_munmap(const_cast(content_.data()), content_.length()); - content_.Set(NULL, 0); + content_.Set(nullptr, 0); } } diff --git a/src/common/linux/memory_mapped_file_unittest.cc b/src/common/linux/memory_mapped_file_unittest.cc index b7a61a70e..213dca6f8 100644 --- a/src/common/linux/memory_mapped_file_unittest.cc +++ b/src/common/linux/memory_mapped_file_unittest.cc @@ -55,7 +55,7 @@ class MemoryMappedFileTest : public testing::Test { protected: void ExpectNoMappedData(const MemoryMappedFile& mapped_file) { EXPECT_TRUE(mapped_file.content().IsEmpty()); - EXPECT_TRUE(mapped_file.data() == NULL); + EXPECT_TRUE(mapped_file.data() == nullptr); EXPECT_EQ(0U, mapped_file.size()); } }; @@ -87,7 +87,7 @@ TEST_F(MemoryMappedFileTest, MapNonexistentFile) { TEST_F(MemoryMappedFileTest, MapEmptyFile) { AutoTempDir temp_dir; string test_file = temp_dir.path() + "/empty_file"; - ASSERT_TRUE(WriteFile(test_file.c_str(), NULL, 0)); + ASSERT_TRUE(WriteFile(test_file.c_str(), nullptr, 0)); { MemoryMappedFile mapped_file(test_file.c_str(), 0); @@ -114,7 +114,7 @@ TEST_F(MemoryMappedFileTest, MapNonEmptyFile) { { MemoryMappedFile mapped_file(test_file.c_str(), 0); EXPECT_FALSE(mapped_file.content().IsEmpty()); - EXPECT_TRUE(mapped_file.data() != NULL); + EXPECT_TRUE(mapped_file.data() != nullptr); EXPECT_EQ(data_size, mapped_file.size()); EXPECT_EQ(0, memcmp(data, mapped_file.data(), data_size)); } @@ -122,7 +122,7 @@ TEST_F(MemoryMappedFileTest, MapNonEmptyFile) { MemoryMappedFile mapped_file; EXPECT_TRUE(mapped_file.Map(test_file.c_str(), 0)); EXPECT_FALSE(mapped_file.content().IsEmpty()); - EXPECT_TRUE(mapped_file.data() != NULL); + EXPECT_TRUE(mapped_file.data() != nullptr); EXPECT_EQ(data_size, mapped_file.size()); EXPECT_EQ(0, memcmp(data, mapped_file.data(), data_size)); } @@ -150,13 +150,13 @@ TEST_F(MemoryMappedFileTest, RemapAfterMap) { { MemoryMappedFile mapped_file(test_file1.c_str(), 0); EXPECT_FALSE(mapped_file.content().IsEmpty()); - EXPECT_TRUE(mapped_file.data() != NULL); + EXPECT_TRUE(mapped_file.data() != nullptr); EXPECT_EQ(data1_size, mapped_file.size()); EXPECT_EQ(0, memcmp(data1, mapped_file.data(), data1_size)); mapped_file.Map(test_file2.c_str(), 0); EXPECT_FALSE(mapped_file.content().IsEmpty()); - EXPECT_TRUE(mapped_file.data() != NULL); + EXPECT_TRUE(mapped_file.data() != nullptr); EXPECT_EQ(data2_size, mapped_file.size()); EXPECT_EQ(0, memcmp(data2, mapped_file.data(), data2_size)); } @@ -164,13 +164,13 @@ TEST_F(MemoryMappedFileTest, RemapAfterMap) { MemoryMappedFile mapped_file; EXPECT_TRUE(mapped_file.Map(test_file1.c_str(), 0)); EXPECT_FALSE(mapped_file.content().IsEmpty()); - EXPECT_TRUE(mapped_file.data() != NULL); + EXPECT_TRUE(mapped_file.data() != nullptr); EXPECT_EQ(data1_size, mapped_file.size()); EXPECT_EQ(0, memcmp(data1, mapped_file.data(), data1_size)); mapped_file.Map(test_file2.c_str(), 0); EXPECT_FALSE(mapped_file.content().IsEmpty()); - EXPECT_TRUE(mapped_file.data() != NULL); + EXPECT_TRUE(mapped_file.data() != nullptr); EXPECT_EQ(data2_size, mapped_file.size()); EXPECT_EQ(0, memcmp(data2, mapped_file.data(), data2_size)); } @@ -192,7 +192,7 @@ TEST_F(MemoryMappedFileTest, MapWithOffset) { { MemoryMappedFile mapped_file(test_file1.c_str(), page_size); EXPECT_FALSE(mapped_file.content().IsEmpty()); - EXPECT_TRUE(mapped_file.data() != NULL); + EXPECT_TRUE(mapped_file.data() != nullptr); EXPECT_EQ(data1_size - page_size, mapped_file.size()); EXPECT_EQ( 0, @@ -202,7 +202,7 @@ TEST_F(MemoryMappedFileTest, MapWithOffset) { MemoryMappedFile mapped_file; mapped_file.Map(test_file1.c_str(), page_size); EXPECT_FALSE(mapped_file.content().IsEmpty()); - EXPECT_TRUE(mapped_file.data() != NULL); + EXPECT_TRUE(mapped_file.data() != nullptr); EXPECT_EQ(data1_size - page_size, mapped_file.size()); EXPECT_EQ( 0, diff --git a/src/common/linux/synth_elf.cc b/src/common/linux/synth_elf.cc index 8e9170e7f..4de506666 100644 --- a/src/common/linux/synth_elf.cc +++ b/src/common/linux/synth_elf.cc @@ -10,6 +10,7 @@ #include #include "common/linux/elf_gnu_compat.h" +#include "common/memory_allocator.h" #include "common/using_std_string.h" namespace google_breakpad { @@ -159,7 +160,7 @@ void ELF::AddSegment(int start, int end, uint32_t type, uint32_t flags) { if (sections_[i].type_ != SHT_NOBITS) { assert(!prev_was_nobits); // non SHT_NOBITS sections are 4-byte aligned (see AddSection) - size = (size + 3) & ~3; + size = PageAllocator::AlignUp(size, 4); filesz += size; } else { prev_was_nobits = true; diff --git a/src/common/linux/tests/crash_generator.cc b/src/common/linux/tests/crash_generator.cc index 1cad9ae26..7a7dae51d 100644 --- a/src/common/linux/tests/crash_generator.cc +++ b/src/common/linux/tests/crash_generator.cc @@ -101,7 +101,7 @@ void* thread_function(void* data) { namespace google_breakpad { CrashGenerator::CrashGenerator() - : shared_memory_(NULL), + : shared_memory_(nullptr), shared_memory_size_(0) { } @@ -154,7 +154,7 @@ bool CrashGenerator::UnmapSharedMemory() { return true; if (munmap(shared_memory_, shared_memory_size_) == 0) { - shared_memory_ = NULL; + shared_memory_ = nullptr; shared_memory_size_ = 0; return true; } @@ -312,7 +312,7 @@ void CrashGenerator::CreateThreadsInChildProcess(unsigned num_threads) { } pthread_barrier_t thread_barrier; - if (pthread_barrier_init(&thread_barrier, NULL, num_threads) != 0) { + if (pthread_barrier_init(&thread_barrier, nullptr, num_threads) != 0) { fprintf(stderr, "CrashGenerator: Failed to initialize thread barrier\n"); exit(1); } diff --git a/src/common/long_string_dictionary.cc b/src/common/long_string_dictionary.cc index 19a649e7b..537972e50 100644 --- a/src/common/long_string_dictionary.cc +++ b/src/common/long_string_dictionary.cc @@ -164,7 +164,7 @@ const string LongStringDictionary::GetValueForKey(const char* key) const { const char* segment_value = SimpleStringDictionary::GetValueForKey(segment_key); - if (segment_value != NULL) { + if (segment_value != nullptr) { found_segment = true; return_value.append(segment_value); } else { diff --git a/src/common/long_string_dictionary_unittest.cc b/src/common/long_string_dictionary_unittest.cc index f10dc0d97..86bb26bab 100644 --- a/src/common/long_string_dictionary_unittest.cc +++ b/src/common/long_string_dictionary_unittest.cc @@ -63,7 +63,7 @@ TEST(LongStringDictionary, LongStringDictionary) { EXPECT_EQ("", dict.GetValueForKey("key3")); // Remove by setting value to NULL - dict.SetKeyValue("key2", NULL); + dict.SetKeyValue("key2", nullptr); // Now make sure it's not there anymore EXPECT_EQ("", dict.GetValueForKey("key2")); diff --git a/src/common/mac/MachIPC.h b/src/common/mac/MachIPC.h index 78b97ad96..38b339f5e 100644 --- a/src/common/mac/MachIPC.h +++ b/src/common/mac/MachIPC.h @@ -164,7 +164,7 @@ class MachMessage { // The receiver of the message can retrieve the raw data this way uint8_t* GetData() { - return GetDataLength() > 0 ? GetDataPacket()->data : NULL; + return GetDataLength() > 0 ? GetDataPacket()->data : nullptr; } uint32_t GetDataLength() { diff --git a/src/common/mac/MachIPC.mm b/src/common/mac/MachIPC.mm index 62e0f6b59..e2e7332bd 100644 --- a/src/common/mac/MachIPC.mm +++ b/src/common/mac/MachIPC.mm @@ -29,9 +29,10 @@ // MachIPC.mm // Wrapper for mach IPC calls -#import #import "MachIPC.h" +#import #include "common/mac/bootstrap_compat.h" +#include "common/memory_allocator.h" namespace google_breakpad { //============================================================================== @@ -77,7 +78,7 @@ size_t size = sizeof(mach_msg_header_t) + sizeof(mach_msg_body_t); // add space for MessageDataPacket - int32_t alignedDataLength = (GetDataLength() + 3) & ~0x3; + size_t alignedDataLength = PageAllocator::AlignUp(GetDataLength(), 4); size += 2*sizeof(int32_t) + alignedDataLength; // add space for descriptors diff --git a/src/common/mac/arch_utilities.cc b/src/common/mac/arch_utilities.cc index 742108205..cfa2e2d70 100644 --- a/src/common/mac/arch_utilities.cc +++ b/src/common/mac/arch_utilities.cc @@ -38,10 +38,21 @@ #include #include -#if defined(__APPLE__) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= 130000 || \ - __IPHONE_OS_VERSION_MAX_ALLOWED >= 160000 || \ - __TVOS_OS_VERSION_MAX_ALLOWED >= 160000) +#ifdef __APPLE__ +#include +#include + +#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && defined(__IPHONE_16_0) && \ + __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_16_0) || \ + (defined(MAC_OS_X_VERSION_MIN_REQUIRED) && defined(MAC_OS_VERSION_13_0) && \ + MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_13_0) || \ + (defined(__TV_OS_VERSION_MIN_REQUIRED) && defined(__TV_OS_VERSION_16_0) && \ + __TV_OS_VERSION_MIN_REQUIRED >= __TVOS_16_0) +#define HAS_MACHO_UTILS 1 #include +#else +#define HAS_MACHO_UTILS 0 +#endif #endif namespace { @@ -89,7 +100,7 @@ ArchInfo GetLocalArchInfo(void) { #elif defined(__powerpc__) arch = kArch_ppc; #else -#error "Unsupported CPU architecture" + #error "Unsupported CPU architecture" #endif return kKnownArchitectures[arch].info; } @@ -97,57 +108,43 @@ ArchInfo GetLocalArchInfo(void) { #ifdef __APPLE__ std::optional GetArchInfoFromName(const char* arch_name) { -#if (__MAC_OS_X_VERSION_MAX_ALLOWED >= 130000 || \ - __IPHONE_OS_VERSION_MAX_ALLOWED >= 160000 || \ - __TVOS_OS_VERSION_MAX_ALLOWED >= 160000) +#if HAS_MACHO_UTILS if (__builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, *)) { cpu_type_t type; cpu_subtype_t subtype; if (macho_cpu_type_for_arch_name(arch_name, &type, &subtype)) { return ArchInfo{type, subtype}; } - } else { + return std::nullopt; + } +#endif #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - const NXArchInfo* info = NXGetArchInfoFromName(arch_name); -#pragma clang diagnostic pop - if (info) { - return ArchInfo{info->cputype, info->cpusubtype}; - } - } -#else const NXArchInfo* info = NXGetArchInfoFromName(arch_name); +#pragma clang diagnostic pop if (info) { return ArchInfo{info->cputype, info->cpusubtype}; } -#endif return std::nullopt; } const char* GetNameFromCPUType(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype) { -#if (__MAC_OS_X_VERSION_MAX_ALLOWED >= 130000 || \ - __IPHONE_OS_VERSION_MAX_ALLOWED >= 160000 || \ - __TVOS_OS_VERSION_MAX_ALLOWED >= 160000) +#if HAS_MACHO_UTILS if (__builtin_available(macOS 13.0, iOS 16.0, tvOS 16.0, *)) { const char* name = macho_arch_name_for_cpu_type(cpu_type, cpu_subtype); if (name) { return name; } - } else { + return kUnknownArchName; + } +#endif #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - const NXArchInfo* info = NXGetArchInfoFromCpuType(cpu_type, cpu_subtype); -#pragma clang diagnostic pop - if (info) { - return info->name; - } - } -#else const NXArchInfo* info = NXGetArchInfoFromCpuType(cpu_type, cpu_subtype); +#pragma clang diagnostic pop if (info) { return info->name; } -#endif return kUnknownArchName; } diff --git a/src/common/mac/dump_syms.cc b/src/common/mac/dump_syms.cc index c06945e48..0e2c094f4 100644 --- a/src/common/mac/dump_syms.cc +++ b/src/common/mac/dump_syms.cc @@ -49,6 +49,7 @@ #include #include +#include #include #include #include @@ -88,7 +89,6 @@ using google_breakpad::mach_o::Segment; using google_breakpad::Module; using google_breakpad::StabsReader; using google_breakpad::StabsToModule; -using google_breakpad::scoped_ptr; using std::make_pair; using std::pair; using std::string; @@ -109,7 +109,7 @@ vector list_directory(const string& directory) { path += '/'; } - struct dirent* entry = NULL; + struct dirent* entry = nullptr; while ((entry = readdir(dir))) { if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { entries.push_back(path + entry->d_name); @@ -265,8 +265,12 @@ SuperFatArch* DumpSymbols::FindBestMatchForArchitecture( return nullptr; } +void DumpSymbols::SetReportWarnings(bool report_warnings) { + report_warnings_ = report_warnings; +} + string DumpSymbols::Identifier() { - scoped_ptr file_id; + std::unique_ptr file_id; if (from_disk_) { file_id.reset(new FileID(object_filename_.c_str())); @@ -274,7 +278,7 @@ string DumpSymbols::Identifier() { file_id.reset(new FileID(contents_.get(), size_)); } unsigned char identifier_bytes[16]; - scoped_ptr module; + std::unique_ptr module; if (!selected_object_file_) { if (!CreateEmptyModule(module)) return string(); @@ -350,8 +354,9 @@ class DumpSymbols::DumperLineToModule: vector* lines, std::map* files) { DwarfLineToModule handler(module, compilation_dir_, lines, files); - LineInfo parser(program, length, byte_reader_, nullptr, 0, - nullptr, 0, &handler); + LineInfo parser(program, length, byte_reader_, string_section, + string_section_length, line_string_section, + line_string_section_length, &handler); parser.Start(); } private: @@ -359,7 +364,7 @@ class DumpSymbols::DumperLineToModule: ByteReader* byte_reader_; // WEAK }; -bool DumpSymbols::CreateEmptyModule(scoped_ptr& module) { +bool DumpSymbols::CreateEmptyModule(std::unique_ptr& module) { // Select an object file, if SetArchitecture hasn't been called to set one // explicitly. if (!selected_object_file_) { @@ -390,7 +395,7 @@ bool DumpSymbols::CreateEmptyModule(scoped_ptr& module) { // In certain cases, it is possible that architecture info can't be reliably // determined, e.g. new architectures that breakpad is unware of. In that // case, avoid crashing and return false instead. - if (selected_arch_name == kUnknownArchName) { + if (strcmp(selected_arch_name, kUnknownArchName) == 0) { return false; } @@ -402,7 +407,7 @@ bool DumpSymbols::CreateEmptyModule(scoped_ptr& module) { selected_object_name_ = object_filename_; if (object_files_.size() > 1) { selected_object_name_ += ", architecture "; - selected_object_name_ + selected_arch_name; + selected_object_name_ += selected_arch_name; } // Compute a module name, to appear in the MODULE record. @@ -524,10 +529,17 @@ void DumpSymbols::ReadDwarf(google_breakpad::Module* module, for (uint64_t offset = 0; offset < debug_info_length;) { // Make a handler for the root DIE that populates MODULE with the // debug info. - DwarfCUToModule::WarningReporter reporter(selected_object_name_, - offset); + std::unique_ptr reporter; + if (report_warnings_) { + reporter = std::make_unique( + selected_object_name_, offset); + } else { + reporter = std::make_unique( + selected_object_name_, offset); + } DwarfCUToModule root_handler(&file_context, &line_to_module, - &ranges_handler, &reporter, handle_inline); + &ranges_handler, reporter.get(), + handle_inline); // Make a Dwarf2Handler that drives our DIEHandler. DIEDispatcher die_dispatcher(&root_handler); // Make a DWARF parser for the compilation unit at OFFSET. @@ -687,7 +699,7 @@ bool DumpSymbols::LoadCommandDumper::SymtabCommand(const ByteBuffer& entries, } bool DumpSymbols::ReadSymbolData(Module** out_module) { - scoped_ptr module; + std::unique_ptr module; if (!CreateEmptyModule(module)) return false; @@ -716,7 +728,7 @@ bool DumpSymbols::ReadSymbolData(Module** out_module) { // header only to |stream|. Return true on success; if an error occurs, report // it and return false. bool DumpSymbols::WriteSymbolFileHeader(std::ostream& stream) { - scoped_ptr module; + std::unique_ptr module; if (!CreateEmptyModule(module)) return false; diff --git a/src/common/mac/dump_syms.h b/src/common/mac/dump_syms.h index 5ccf49e3e..8afd0ac5a 100644 --- a/src/common/mac/dump_syms.h +++ b/src/common/mac/dump_syms.h @@ -38,6 +38,7 @@ #include #include +#include #include #include #include @@ -71,7 +72,8 @@ class DumpSymbols { selected_object_name_(), enable_multiple_(enable_multiple), module_name_(module_name), - prefer_extern_name_(prefer_extern_name) {} + prefer_extern_name_(prefer_extern_name), + report_warnings_(true) {} ~DumpSymbols() = default; // Prepare to read debugging information from |filename|. |filename| may be @@ -103,6 +105,9 @@ class DumpSymbols { // architecture matches that of this dumper program. bool SetArchitecture(const ArchInfo& info); + // Set whether or not to report DWARF warnings + void SetReportWarnings(bool report_warnings); + // Return a pointer to an array of SuperFatArch structures describing the // object files contained in this dumper's file. Set *|count| to the number // of elements in the array. The returned array is owned by this DumpSymbols @@ -114,7 +119,7 @@ class DumpSymbols { *count = object_files_.size(); if (object_files_.size() > 0) return &object_files_[0]; - return NULL; + return nullptr; } // Read the selected object file's debugging information, and write out the @@ -142,7 +147,7 @@ class DumpSymbols { cpu_type_t cpu_type, cpu_subtype_t cpu_subtype); // Creates an empty module object. - bool CreateEmptyModule(scoped_ptr& module); + bool CreateEmptyModule(std::unique_ptr& module); // Process the split dwarf file referenced by reader. void StartProcessSplitDwarf(google_breakpad::CompilationUnit* reader, @@ -224,6 +229,9 @@ class DumpSymbols { // (which are placed in the Extern), not in the DWARF symbols (which are // placed in the Function). bool prefer_extern_name_; + + // Whether or not to report warnings + bool report_warnings_; }; } // namespace google_breakpad diff --git a/src/common/mac/file_id.cc b/src/common/mac/file_id.cc index ee4a66bbe..f080a2114 100644 --- a/src/common/mac/file_id.cc +++ b/src/common/mac/file_id.cc @@ -42,8 +42,9 @@ #include #include +#include + #include "common/mac/macho_id.h" -#include "common/scoped_ptr.h" using MacFileUtilities::MachoID; @@ -61,7 +62,7 @@ FileID::FileID(void* memory, size_t size) bool FileID::MachoIdentifier(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype, unsigned char identifier[16]) { - scoped_ptr macho; + std::unique_ptr macho; if (memory_) { macho.reset(new MachoID(memory_, size_)); } else { diff --git a/src/common/mac/launch_reporter.cc b/src/common/mac/launch_reporter.cc index f6b8aed1c..3f86af873 100644 --- a/src/common/mac/launch_reporter.cc +++ b/src/common/mac/launch_reporter.cc @@ -38,7 +38,7 @@ namespace google_breakpad { void LaunchReporter(const char *reporter_executable_path, const char *config_file_path) { - const char* argv[] = { reporter_executable_path, config_file_path, NULL }; + const char* argv[] = { reporter_executable_path, config_file_path, nullptr }; // Launch the reporter pid_t pid = fork(); diff --git a/src/common/mac/macho_id.cc b/src/common/mac/macho_id.cc index bb0058ced..aba3b306e 100644 --- a/src/common/mac/macho_id.cc +++ b/src/common/mac/macho_id.cc @@ -53,7 +53,7 @@ using google_breakpad::MD5Update; using google_breakpad::MD5Final; MachoID::MachoID(const char* path) - : memory_(0), memory_size_(0), md5_context_(), update_function_(NULL) { + : memory_(0), memory_size_(0), md5_context_(), update_function_(nullptr) { snprintf(path_, sizeof(path_), "%s", path); } @@ -62,7 +62,7 @@ MachoID::MachoID(void* memory, size_t size) memory_(memory), memory_size_(size), md5_context_(), - update_function_(NULL) {} + update_function_(nullptr) {} MachoID::~MachoID() {} diff --git a/src/common/mac/macho_reader.cc b/src/common/mac/macho_reader.cc index 0324be143..0f2f7bc3f 100644 --- a/src/common/mac/macho_reader.cc +++ b/src/common/mac/macho_reader.cc @@ -368,7 +368,7 @@ bool Reader::WalkLoadCommands(Reader::LoadCommandHandler* handler) const { // out. To help us handle this special case properly, give such // segments' contents NULL starting and ending pointers. if (segment.fileoff == 0 && segment.filesize == 0) { - segment.contents.start = segment.contents.end = NULL; + segment.contents.start = segment.contents.end = nullptr; } else { segment.contents.start = buffer_.start + segment.fileoff; segment.contents.end = segment.contents.start + segment.filesize; @@ -507,16 +507,16 @@ bool Reader::WalkSegmentSections(const Segment& segment, if (section_type == S_ZEROFILL || section_type == S_THREAD_LOCAL_ZEROFILL || section_type == S_GB_ZEROFILL) { // Zero-fill sections have a size, but no contents. - section.contents.start = section.contents.end = NULL; - } else if (segment.contents.start == NULL && - segment.contents.end == NULL) { + section.contents.start = section.contents.end = nullptr; + } else if (segment.contents.start == nullptr && + segment.contents.end == nullptr) { // Mach-O files in .dSYM bundles have the contents of the loaded // segments removed, and their file offsets and file sizes zeroed // out. However, the sections within those segments still have // non-zero sizes. There's no reason to call MisplacedSectionData in // this case; the caller may just need the section's load // address. But do set the contents' limits to NULL, for safety. - section.contents.start = section.contents.end = NULL; + section.contents.start = section.contents.end = nullptr; } else { if (offset < size_t(segment.contents.start - buffer_.start) || offset > size_t(segment.contents.end - buffer_.start) || @@ -530,7 +530,7 @@ bool Reader::WalkSegmentSections(const Segment& segment, // segments partially removed. The removed sections will have zero as // their offset. MisplacedSectionData should not be called in this // case. - section.contents.start = section.contents.end = NULL; + section.contents.start = section.contents.end = nullptr; } } else { section.contents.start = buffer_.start + offset; diff --git a/src/common/mac/macho_reader.h b/src/common/mac/macho_reader.h index d3c61a06a..47134b03a 100644 --- a/src/common/mac/macho_reader.h +++ b/src/common/mac/macho_reader.h @@ -133,7 +133,7 @@ class FatReader { *count = object_files_.size(); if (object_files_.size() > 0) return &object_files_[0]; - return NULL; + return nullptr; } private: diff --git a/src/common/mac/macho_reader_unittest.cc b/src/common/mac/macho_reader_unittest.cc index 4b5ac6ca0..7b629d1a0 100644 --- a/src/common/mac/macho_reader_unittest.cc +++ b/src/common/mac/macho_reader_unittest.cc @@ -35,6 +35,8 @@ #include // Must come first #endif +#include + #include #include #include @@ -499,7 +501,7 @@ class WithConfiguration { WithConfiguration* saved_; }; -WithConfiguration* WithConfiguration::current_ = NULL; +WithConfiguration* WithConfiguration::current_ = nullptr; // A test_assembler::Section with a size that we can cite. The start(), // Here() and Mark() member functions of a SizedSection always represent @@ -1640,7 +1642,7 @@ TEST_F(LoadCommand, ZappedSegment) { Segment actual_segment; EXPECT_TRUE(reader.FindSegment("zapped", &actual_segment)); - ByteBuffer zapped_extent(NULL, 0); + ByteBuffer zapped_extent(nullptr, 0); EXPECT_CALL(section_handler, HandleSection(MatchSection(false, "twitching", "zapped", 0x696d83cc, 0, 0x93b3bd42, @@ -1706,7 +1708,7 @@ TEST_F(LoadCommand, MapSegmentSections) { MatchSection(true, "cara cara", "thorax", 0x04d462e2)); ASSERT_TRUE(section_map.find("sixteenprecisely") != section_map.end()); - ByteBuffer sixteenprecisely_contents(NULL, 0); + ByteBuffer sixteenprecisely_contents(nullptr, 0); EXPECT_THAT(section_map["sixteenprecisely"], MatchSection(true, "sixteenprecisely", "thorax", 0x04d462e2 + 7, 12, S_ZEROFILL, diff --git a/src/common/mac/macho_walker.cc b/src/common/mac/macho_walker.cc index 4b9f56c2a..c047da998 100644 --- a/src/common/mac/macho_walker.cc +++ b/src/common/mac/macho_walker.cc @@ -53,11 +53,11 @@ namespace MacFileUtilities { MachoWalker::MachoWalker(const char* path, LoadCommandCallback callback, void* context) : file_(-1), - memory_(NULL), + memory_(nullptr), memory_size_(0), callback_(callback), callback_context_(context), - current_header_(NULL), + current_header_(nullptr), current_header_size_(0), current_header_offset_(0) { file_ = open(path, O_RDONLY); @@ -70,7 +70,7 @@ MachoWalker::MachoWalker(void* memory, size_t size, memory_size_(size), callback_(callback), callback_context_(context), - current_header_(NULL), + current_header_(nullptr), current_header_size_(0), current_header_offset_(0) { } @@ -221,7 +221,7 @@ bool MachoWalker::WalkHeaderAtOffset(off_t offset) { current_header_offset_ = offset; offset += current_header_size_; bool result = WalkHeaderCore(offset, header.ncmds, swap); - current_header_ = NULL; + current_header_ = nullptr; current_header_size_ = 0; current_header_offset_ = 0; return result; @@ -241,7 +241,7 @@ bool MachoWalker::WalkHeader64AtOffset(off_t offset) { current_header_offset_ = offset; offset += current_header_size_; bool result = WalkHeaderCore(offset, header.ncmds, swap); - current_header_ = NULL; + current_header_ = nullptr; current_header_size_ = 0; current_header_offset_ = 0; return result; diff --git a/src/common/macros.h b/src/common/macros.h index 828d49d1a..741a1c3b8 100644 --- a/src/common/macros.h +++ b/src/common/macros.h @@ -29,16 +29,11 @@ #ifndef BREAKPAD_COMMON_MACROS_H_ #define BREAKPAD_COMMON_MACROS_H_ -// Ensure that this macro definition stays in a private header file: clang -// suggests the first macro expanding to [[clang::fallthrough]] in its -// diagnostics, so if BP_FALLTHROUGH is visible in code depending on breakpad, -// clang would suggest BP_FALLTHROUGH for code depending on breakpad, instead of -// the client code's own fallthrough macro. -// TODO(thakis): Once everyone uses C++17, use its [[fallthrough]] instead. -#if defined(__clang__) -#define BP_FALLTHROUGH [[clang::fallthrough]] -#else -#define BP_FALLTHROUGH +#include + +// TODO: Delete when we require C++23. +#ifndef unreachable +#define unreachable() __builtin_unreachable() #endif #endif // BREAKPAD_COMMON_MACROS_H_ diff --git a/src/common/memory_allocator.h b/src/common/memory_allocator.h index 1c99913ad..e6dc4e9f2 100644 --- a/src/common/memory_allocator.h +++ b/src/common/memory_allocator.h @@ -29,10 +29,11 @@ #ifndef GOOGLE_BREAKPAD_COMMON_MEMORY_ALLOCATOR_H_ #define GOOGLE_BREAKPAD_COMMON_MEMORY_ALLOCATOR_H_ +#include #include #include -#include #include +#include #include #include @@ -60,8 +61,8 @@ class PageAllocator { public: PageAllocator() : page_size_(getpagesize()), - last_(NULL), - current_page_(NULL), + last_(nullptr), + current_page_(nullptr), page_offset_(0), pages_allocated_(0) { } @@ -70,16 +71,24 @@ class PageAllocator { FreeAll(); } + // Rounds up `offset` to the closest properly aligned value. `alignment` must + // be positive and a power of two. + template + static T AlignUp(T offset, size_t alignment) { + assert(alignment > 0 && ((alignment - 1) & alignment) == 0); + return (offset + (alignment - 1)) & ~(alignment - 1); + } + void* Alloc(size_t bytes) { if (!bytes) - return NULL; + return nullptr; if (current_page_ && page_size_ - page_offset_ >= bytes) { uint8_t* const ret = current_page_ + page_offset_; page_offset_ += bytes; if (page_offset_ == page_size_) { page_offset_ = 0; - current_page_ = NULL; + current_page_ = nullptr; } return ret; @@ -89,12 +98,12 @@ class PageAllocator { (bytes + sizeof(PageHeader) + page_size_ - 1) / page_size_; uint8_t* const ret = GetNPages(pages); if (!ret) - return NULL; + return nullptr; page_offset_ = (page_size_ - (page_size_ * pages - (bytes + sizeof(PageHeader)))) % page_size_; - current_page_ = page_offset_ ? ret + page_size_ * (pages - 1) : NULL; + current_page_ = page_offset_ ? ret + page_size_ * (pages - 1) : nullptr; return ret + sizeof(PageHeader); } @@ -115,10 +124,10 @@ class PageAllocator { private: uint8_t* GetNPages(size_t num_pages) { - void* a = sys_mmap(NULL, page_size_ * num_pages, PROT_READ | PROT_WRITE, + void* a = sys_mmap(nullptr, page_size_ * num_pages, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (a == MAP_FAILED) - return NULL; + return nullptr; #if defined(MEMORY_SANITIZER) // We need to indicate to MSan that memory allocated through sys_mmap is @@ -167,7 +176,7 @@ struct PageStdAllocator { using size_type = typename AllocatorTraits::size_type; explicit PageStdAllocator(PageAllocator& allocator) : allocator_(allocator), - stackdata_(NULL), + stackdata_(nullptr), stackdata_size_(0) {} diff --git a/src/common/memory_allocator_unittest.cc b/src/common/memory_allocator_unittest.cc index 8ef68913b..07bce6f85 100644 --- a/src/common/memory_allocator_unittest.cc +++ b/src/common/memory_allocator_unittest.cc @@ -30,6 +30,10 @@ #include // Must come first #endif +#include + +#include + #include "breakpad_googletest_includes.h" #include "common/memory_allocator.h" @@ -37,7 +41,7 @@ using namespace google_breakpad; namespace { typedef testing::Test PageAllocatorTest; -} +} // namespace TEST(PageAllocatorTest, Setup) { PageAllocator allocator; @@ -50,7 +54,7 @@ TEST(PageAllocatorTest, SmallObjects) { EXPECT_EQ(0U, allocator.pages_allocated()); for (unsigned i = 1; i < 1024; ++i) { uint8_t* p = reinterpret_cast(allocator.Alloc(i)); - ASSERT_FALSE(p == NULL); + ASSERT_FALSE(p == nullptr); memset(p, 0, i); } } @@ -60,15 +64,44 @@ TEST(PageAllocatorTest, LargeObject) { EXPECT_EQ(0U, allocator.pages_allocated()); uint8_t* p = reinterpret_cast(allocator.Alloc(10000)); - ASSERT_FALSE(p == NULL); + ASSERT_FALSE(p == nullptr); EXPECT_EQ(3U, allocator.pages_allocated()); for (unsigned i = 1; i < 10; ++i) { uint8_t* p = reinterpret_cast(allocator.Alloc(i)); - ASSERT_FALSE(p == NULL); + ASSERT_FALSE(p == nullptr); memset(p, 0, i); } } +TEST(PageAllocatorTest, AlignUp) { + EXPECT_EQ(PageAllocator::AlignUp(0x11U, 1), 0x11U); + EXPECT_EQ(PageAllocator::AlignUp(0x11U, 2), 0x12U); + EXPECT_EQ(PageAllocator::AlignUp(0x13U, 2), 0x14U); + EXPECT_EQ(PageAllocator::AlignUp(0x11U, 4), 0x14U); + EXPECT_EQ(PageAllocator::AlignUp(0x15U, 4), 0x18U); + EXPECT_EQ(PageAllocator::AlignUp(0x11U, 8), 0x18U); + EXPECT_EQ(PageAllocator::AlignUp(0x19U, 8), 0x20U); + + // Ensure large 64 bit values are not truncated. + constexpr uint64_t kUnalignedU64 = 0x8000'0000'0000'0011; + constexpr uint64_t kAligned8U64 = 0x8000'0000'0000'0018; + static_assert(kUnalignedU64 > std::numeric_limits::max()); + static_assert(kAligned8U64 > std::numeric_limits::max()); + EXPECT_EQ(PageAllocator::AlignUp(kUnalignedU64, 8), kAligned8U64); +} + +namespace { +typedef testing::Test PageAllocatorDeathTest; +} // namespace + +TEST(PageAllocatorDeathTest, AlignUpBad0) { + EXPECT_DEBUG_DEATH({ PageAllocator::AlignUp(0x11U, 0); }, ""); +} + +TEST(PageAllocatorDeathTest, AlignUpBad9) { + EXPECT_DEBUG_DEATH({ PageAllocator::AlignUp(0x11U, 9); }, ""); +} + namespace { typedef testing::Test WastefulVectorTest; } diff --git a/src/common/memory_range.h b/src/common/memory_range.h index e2ab61d5a..3dda169e7 100644 --- a/src/common/memory_range.h +++ b/src/common/memory_range.h @@ -46,7 +46,7 @@ namespace google_breakpad { // in a crashed environment. class MemoryRange { public: - MemoryRange() : data_(NULL), length_(0) {} + MemoryRange() : data_(nullptr), length_(0) {} MemoryRange(const void* data, size_t length) { Set(data, length); @@ -60,7 +60,7 @@ class MemoryRange { // Resets to an empty range. void Reset() { - data_ = NULL; + data_ = nullptr; length_ = 0; } @@ -87,7 +87,7 @@ class MemoryRange { // |sub_offset| bytes of this memory range, or NULL if the subrange // is out of bounds. const void* GetData(size_t sub_offset, size_t sub_length) const { - return Covers(sub_offset, sub_length) ? (data_ + sub_offset) : NULL; + return Covers(sub_offset, sub_length) ? (data_ + sub_offset) : nullptr; } // Same as the two-argument version of GetData() but uses sizeof(DataType) diff --git a/src/common/memory_range_unittest.cc b/src/common/memory_range_unittest.cc index f081d6798..0e19daaed 100644 --- a/src/common/memory_range_unittest.cc +++ b/src/common/memory_range_unittest.cc @@ -84,11 +84,11 @@ const struct { { 0, 4, 9, kBufferPointer + 36 }, { kBufferSize - 1, 1, 0, kBufferPointer + kBufferSize - 1 }, // Invalid array elemenets - { 0, 1, kBufferSize, NULL }, - { 0, 4, 10, NULL }, - { kBufferSize - 1, 1, 1, NULL }, - { kBufferSize - 1, 2, 0, NULL }, - { kBufferSize, 1, 0, NULL }, + { 0, 1, kBufferSize, nullptr }, + { 0, 4, 10, nullptr }, + { kBufferSize - 1, 1, 1, nullptr }, + { kBufferSize - 1, 2, 0, nullptr }, + { kBufferSize, 1, 0, nullptr }, }; const size_t kNumElements = sizeof(kElements) / sizeof(kElements[0]); @@ -96,7 +96,7 @@ const size_t kNumElements = sizeof(kElements) / sizeof(kElements[0]); TEST(MemoryRangeTest, DefaultConstructor) { MemoryRange range; - EXPECT_EQ(NULL, range.data()); + EXPECT_EQ(nullptr, range.data()); EXPECT_EQ(0U, range.length()); } @@ -109,7 +109,7 @@ TEST(MemoryRangeTest, ConstructorWithDataAndLength) { TEST(MemoryRangeTest, Reset) { MemoryRange range; range.Reset(); - EXPECT_EQ(NULL, range.data()); + EXPECT_EQ(nullptr, range.data()); EXPECT_EQ(0U, range.length()); range.Set(kBuffer, kBufferSize); @@ -117,7 +117,7 @@ TEST(MemoryRangeTest, Reset) { EXPECT_EQ(kBufferSize, range.length()); range.Reset(); - EXPECT_EQ(NULL, range.data()); + EXPECT_EQ(nullptr, range.data()); EXPECT_EQ(0U, range.length()); } @@ -127,15 +127,15 @@ TEST(MemoryRangeTest, Set) { EXPECT_EQ(kBufferPointer, range.data()); EXPECT_EQ(kBufferSize, range.length()); - range.Set(NULL, 0); - EXPECT_EQ(NULL, range.data()); + range.Set(nullptr, 0); + EXPECT_EQ(nullptr, range.data()); EXPECT_EQ(0U, range.length()); } TEST(MemoryRangeTest, SubrangeOfEmptyMemoryRange) { MemoryRange range; MemoryRange subrange = range.Subrange(0, 10); - EXPECT_EQ(NULL, subrange.data()); + EXPECT_EQ(nullptr, subrange.data()); EXPECT_EQ(0U, subrange.length()); } @@ -157,8 +157,8 @@ TEST(MemoryRangeTest, SubrangeAndGetData) { EXPECT_EQ(sub_length, subrange.length()); } else { EXPECT_FALSE(range.Covers(sub_offset, sub_length)); - EXPECT_EQ(NULL, range.GetData(sub_offset, sub_length)); - EXPECT_EQ(NULL, subrange.data()); + EXPECT_EQ(nullptr, range.GetData(sub_offset, sub_length)); + EXPECT_EQ(nullptr, subrange.data()); EXPECT_EQ(0U, subrange.length()); } } diff --git a/src/common/module.cc b/src/common/module.cc index 0eb5aad82..c55bb6cf9 100644 --- a/src/common/module.cc +++ b/src/common/module.cc @@ -42,6 +42,7 @@ #include #include +#include #include #include #include @@ -272,7 +273,7 @@ Module::File* Module::FindFile(const char* name) { Module::File* Module::FindExistingFile(const string& name) { FileByNameMap::iterator it = files_.find(&name); - return (it == files_.end()) ? NULL : it->second; + return (it == files_.end()) ? nullptr : it->second; } void Module::GetFiles(vector* vec) { @@ -379,7 +380,7 @@ bool Module::AddressIsInModule(Address address) const { return false; } -bool Module::Write(std::ostream& stream, SymbolData symbol_data) { +bool Module::Write(std::ostream& stream, SymbolData symbol_data, bool preserve_load_address) { stream << "MODULE " << os_ << " " << architecture_ << " " << id_ << " " << name_ << "\n"; if (!stream.good()) @@ -389,6 +390,13 @@ bool Module::Write(std::ostream& stream, SymbolData symbol_data) { stream << "INFO CODE_ID " << code_id_ << "\n"; } + // load_address is subtracted from each line. If we use zero instead, we + // preserve the original addresses present in the ELF binary. + Address load_offset = load_address_; + if (preserve_load_address) { + load_offset = 0; + } + if (symbol_data & SYMBOLS_AND_FILES) { // Get all referenced inline origins. set inline_origins; @@ -405,13 +413,13 @@ bool Module::Write(std::ostream& stream, SymbolData symbol_data) { return ReportError(); } } + // Write out inline origins. for (InlineOrigin* origin : inline_origins) { stream << "INLINE_ORIGIN " << origin->id << " " << origin->name << "\n"; if (!stream.good()) return ReportError(); } - // Write out functions and their inlines and lines. for (FunctionSet::const_iterator func_it = functions_.begin(); func_it != functions_.end(); ++func_it) { @@ -420,7 +428,7 @@ bool Module::Write(std::ostream& stream, SymbolData symbol_data) { for (auto range_it = func->ranges.cbegin(); range_it != func->ranges.cend(); ++range_it) { stream << "FUNC " << (func->is_multiple ? "m " : "") << hex - << (range_it->address - load_address_) << " " << range_it->size + << (range_it->address - load_offset) << " " << range_it->size << " " << func->parameter_size << " " << func->name << dec << "\n"; @@ -433,7 +441,7 @@ bool Module::Write(std::ostream& stream, SymbolData symbol_data) { stream << in->inline_nest_level << " " << in->call_site_line << " " << in->getCallSiteFileID() << " " << in->origin->id << hex; for (const Range& r : in->ranges) - stream << " " << (r.address - load_address_) << " " << r.size; + stream << " " << (r.address - load_offset) << " " << r.size; stream << dec << "\n"; }; Module::Inline::InlineDFS(func->inlines, write_inline); @@ -444,7 +452,7 @@ bool Module::Write(std::ostream& stream, SymbolData symbol_data) { (line_it->address >= range_it->address) && (line_it->address < (range_it->address + range_it->size))) { stream << hex - << (line_it->address - load_address_) << " " + << (line_it->address - load_offset) << " " << line_it->size << " " << dec << line_it->number << " " @@ -463,7 +471,7 @@ bool Module::Write(std::ostream& stream, SymbolData symbol_data) { extern_it != externs_.end(); ++extern_it) { Extern* ext = extern_it->get(); stream << "PUBLIC " << (ext->is_multiple ? "m " : "") << hex - << (ext->address - load_address_) << " 0 " << ext->name << dec + << (ext->address - load_offset) << " 0 " << ext->name << dec << "\n"; } } @@ -474,7 +482,7 @@ bool Module::Write(std::ostream& stream, SymbolData symbol_data) { frame_it != stack_frame_entries_.end(); ++frame_it) { StackFrameEntry* entry = frame_it->get(); stream << "STACK CFI INIT " << hex - << (entry->address - load_address_) << " " + << (entry->address - load_offset) << " " << entry->size << " " << dec; if (!stream.good() || !WriteRuleMap(entry->initial_rules, stream)) @@ -486,7 +494,7 @@ bool Module::Write(std::ostream& stream, SymbolData symbol_data) { for (RuleChangeMap::const_iterator delta_it = entry->rule_changes.begin(); delta_it != entry->rule_changes.end(); ++delta_it) { stream << "STACK CFI " << hex - << (delta_it->first - load_address_) << " " << dec; + << (delta_it->first - load_offset) << " " << dec; if (!stream.good() || !WriteRuleMap(delta_it->second, stream)) return ReportError(); diff --git a/src/common/module.h b/src/common/module.h index 28e8e9c50..69eec36de 100644 --- a/src/common/module.h +++ b/src/common/module.h @@ -421,8 +421,9 @@ class Module { // If symbol_data is CFI then: // - all CFI records. // Addresses in the output are all relative to the load address - // established by SetLoadAddress. - bool Write(std::ostream& stream, SymbolData symbol_data); + // established by SetLoadAddress, unless preserve_load_address + // is equal to true, in which case each address will remain unchanged. + bool Write(std::ostream& stream, SymbolData symbol_data, bool preserve_load_address = false); // Place the name in the global set of strings. Return a StringView points to // a string inside the pool. diff --git a/src/common/module_unittest.cc b/src/common/module_unittest.cc index c51162e52..2a5579351 100644 --- a/src/common/module_unittest.cc +++ b/src/common/module_unittest.cc @@ -175,6 +175,49 @@ TEST(Module, WriteRelativeLoadAddress) { contents.c_str()); } +TEST(Module, WritePreserveLoadAddress) { + stringstream s; + Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); + // Set the load address to something. Doesn't matter what. + // The goal of this test is to demonstrate that the load + // address does not impact any of the generated addresses + // when the preserve_load_address option is equal to true. + m.SetLoadAddress(0x1337ULL); + + Module::File* file = m.FindFile("filename-a.cc"); + Module::Function* function = new Module::Function( + "do_stuff", 0x110ULL); + Module::Range range(0x110ULL, 0x210ULL); + function->ranges.push_back(range); + function->parameter_size = 0x50ULL; + Module::Line line1 = { 0x110ULL, 0x1ULL, + file, 20ULL }; + function->lines.push_back(line1); + m.AddFunction(function); + + // Some stack information. + auto entry = std::make_unique(); + entry->address = 0x200ULL; + entry->size = 0x55ULL; + entry->initial_rules[".cfa"] = "some call frame info"; + entry->rule_changes[0x201ULL][".s0"] = + "some rules change call frame info"; + m.AddStackFrameEntry(std::move(entry)); + + bool preserve_load_address = true; + m.Write(s, ALL_SYMBOL_DATA, preserve_load_address); + string contents = s.str(); + EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n" + "FILE 0 filename-a.cc\n" + "FUNC 110 210 50 do_stuff\n" + "110 1 20 0\n" + "STACK CFI INIT 200 55" + " .cfa: some call frame info\n" + "STACK CFI 201" + " .s0: some rules change call frame info\n", + contents.c_str()); +} + TEST(Module, WriteOmitUnusedFiles) { Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID); @@ -461,7 +504,7 @@ TEST(Module, ConstructUniqueFiles) { EXPECT_EQ(file1, file3); EXPECT_EQ(file2, file4); EXPECT_EQ(file1, m.FindExistingFile("foo")); - EXPECT_TRUE(m.FindExistingFile("baz") == NULL); + EXPECT_TRUE(m.FindExistingFile("baz") == nullptr); } TEST(Module, ConstructDuplicateFunctions) { diff --git a/src/common/scoped_ptr.h b/src/common/scoped_ptr.h index d11101782..cec94c29b 100644 --- a/src/common/scoped_ptr.h +++ b/src/common/scoped_ptr.h @@ -26,159 +26,28 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// Scopers help you manage ownership of a pointer, helping you easily manage the -// a pointer within a scope, and automatically destroying the pointer at the -// end of a scope. There are two main classes you will use, which correspond -// to the operators new/delete and new[]/delete[]. -// -// Example usage (scoped_ptr): -// { -// scoped_ptr foo(new Foo("wee")); -// } // foo goes out of scope, releasing the pointer with it. -// -// { -// scoped_ptr foo; // No pointer managed. -// foo.reset(new Foo("wee")); // Now a pointer is managed. -// foo.reset(new Foo("wee2")); // Foo("wee") was destroyed. -// foo.reset(new Foo("wee3")); // Foo("wee2") was destroyed. -// foo->Method(); // Foo::Method() called. -// foo.get()->Method(); // Foo::Method() called. -// SomeFunc(foo.release()); // SomeFunc takes ownership, foo no longer -// // manages a pointer. -// foo.reset(new Foo("wee4")); // foo manages a pointer again. -// foo.reset(); // Foo("wee4") destroyed, foo no longer -// // manages a pointer. -// } // foo wasn't managing a pointer, so nothing was destroyed. -// -// Example usage (scoped_array): -// { -// scoped_array foo(new Foo[100]); -// foo.get()->Method(); // Foo::Method on the 0th element. -// foo[10].Method(); // Foo::Method on the 10th element. -// } +// scoped_ptr is just a type alias for std::unique_ptr. Mass conversion TBD. #ifndef COMMON_SCOPED_PTR_H_ #define COMMON_SCOPED_PTR_H_ // This is an implementation designed to match the anticipated future TR2 -// implementation of the scoped_ptr class, and its closely-related brethren, -// scoped_array, scoped_ptr_malloc. +// implementation of the scoped_array class. #include #include #include -namespace google_breakpad { - -// A scoped_ptr is like a T*, except that the destructor of scoped_ptr -// automatically deletes the pointer it holds (if any). -// That is, scoped_ptr owns the T object that it points to. -// Like a T*, a scoped_ptr may hold either NULL or a pointer to a T object. -// Also like T*, scoped_ptr is thread-compatible, and once you -// dereference it, you get the threadsafety guarantees of T. -// -// The size of a scoped_ptr is small: -// sizeof(scoped_ptr) == sizeof(C*) -template -class scoped_ptr { - public: - - // The element type - typedef C element_type; - - // Constructor. Defaults to initializing with NULL. - // There is no way to create an uninitialized scoped_ptr. - // The input parameter must be allocated with new. - explicit scoped_ptr(C* p = NULL) : ptr_(p) { } - - // Destructor. If there is a C object, delete it. - // We don't need to test ptr_ == NULL because C++ does that for us. - ~scoped_ptr() { - enum { type_must_be_complete = sizeof(C) }; - delete ptr_; - } - - // Reset. Deletes the current owned object, if any. - // Then takes ownership of a new object, if given. - // this->reset(this->get()) works. - void reset(C* p = NULL) { - if (p != ptr_) { - enum { type_must_be_complete = sizeof(C) }; - delete ptr_; - ptr_ = p; - } - } +#include - // Accessors to get the owned object. - // operator* and operator-> will assert() if there is no current object. - C& operator*() const { - assert(ptr_ != NULL); - return *ptr_; - } - C* operator->() const { - assert(ptr_ != NULL); - return ptr_; - } - C* get() const { return ptr_; } +#include "common/scoped_ptr.h" - // Comparison operators. - // These return whether two scoped_ptr refer to the same object, not just to - // two different but equal objects. - bool operator==(C* p) const { return ptr_ == p; } - bool operator!=(C* p) const { return ptr_ != p; } - - // Swap two scoped pointers. - void swap(scoped_ptr& p2) { - C* tmp = ptr_; - ptr_ = p2.ptr_; - p2.ptr_ = tmp; - } - - // Release a pointer. - // The return value is the current pointer held by this object. - // If this object holds a NULL pointer, the return value is NULL. - // After this operation, this object will hold a NULL pointer, - // and will not own the object any more. - C* release() { - C* retVal = ptr_; - ptr_ = NULL; - return retVal; - } - - private: - C* ptr_; - - // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't - // make sense, and if C2 == C, it still doesn't make sense because you should - // never have the same object owned by two different scoped_ptrs. - template bool operator==(scoped_ptr const& p2) const; - template bool operator!=(scoped_ptr const& p2) const; - - // Disallow evil constructors - scoped_ptr(const scoped_ptr&); - void operator=(const scoped_ptr&); -}; - -// Free functions -template -void swap(scoped_ptr& p1, scoped_ptr& p2) { - p1.swap(p2); -} - -template -bool operator==(C* p1, const scoped_ptr& p2) { - return p1 == p2.get(); -} - -template -bool operator!=(C* p1, const scoped_ptr& p2) { - return p1 != p2.get(); -} +namespace google_breakpad { -// scoped_array is like scoped_ptr, except that the caller must allocate +// scoped_array is like std::unique_ptr, except that the caller must allocate // with new [] and the destructor deletes objects with delete []. // -// As with scoped_ptr, a scoped_array either points to an object +// As with std::unique_ptr, a scoped_array either points to an object // or is NULL. A scoped_array owns the object that it points to. // scoped_array is thread-compatible, and once you index into it, // the returned objects have only the threadsafety guarantees of T. @@ -194,7 +63,7 @@ class scoped_array { // Constructor. Defaults to intializing with NULL. // There is no way to create an uninitialized scoped_array. // The input parameter must be allocated with new []. - explicit scoped_array(C* p = NULL) : array_(p) { } + explicit scoped_array(C* p = nullptr) : array_(p) { } // Destructor. If there is a C object, delete it. // We don't need to test ptr_ == NULL because C++ does that for us. @@ -206,7 +75,7 @@ class scoped_array { // Reset. Deletes the current owned object, if any. // Then takes ownership of a new object, if given. // this->reset(this->get()) works. - void reset(C* p = NULL) { + void reset(C* p = nullptr) { if (p != array_) { enum { type_must_be_complete = sizeof(C) }; delete[] array_; @@ -218,7 +87,7 @@ class scoped_array { // Will assert() if there is no current object, or index i is negative. C& operator[](ptrdiff_t i) const { assert(i >= 0); - assert(array_ != NULL); + assert(array_ != nullptr); return array_[i]; } @@ -248,7 +117,7 @@ class scoped_array { // and will not own the object any more. C* release() { C* retVal = array_; - array_ = NULL; + array_ = nullptr; return retVal; } @@ -280,125 +149,6 @@ bool operator!=(C* p1, const scoped_array& p2) { return p1 != p2.get(); } -// This class wraps the c library function free() in a class that can be -// passed as a template argument to scoped_ptr_malloc below. -class ScopedPtrMallocFree { - public: - inline void operator()(void* x) const { - free(x); - } -}; - -// scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a -// second template argument, the functor used to free the object. - -template -class scoped_ptr_malloc { - public: - - // The element type - typedef C element_type; - - // Constructor. Defaults to initializing with NULL. - // There is no way to create an uninitialized scoped_ptr. - // The input parameter must be allocated with an allocator that matches the - // Free functor. For the default Free functor, this is malloc, calloc, or - // realloc. - explicit scoped_ptr_malloc(C* p = NULL): ptr_(p) {} - - // Destructor. If there is a C object, call the Free functor. - ~scoped_ptr_malloc() { - reset(); - } - - // Reset. Calls the Free functor on the current owned object, if any. - // Then takes ownership of a new object, if given. - // this->reset(this->get()) works. - void reset(C* p = NULL) { - if (ptr_ != p) { - FreeProc free_proc; - free_proc(ptr_); - ptr_ = p; - } - } - - // Get the current object. - // operator* and operator-> will cause an assert() failure if there is - // no current object. - C& operator*() const { - assert(ptr_ != NULL); - return *ptr_; - } - - C* operator->() const { - assert(ptr_ != NULL); - return ptr_; - } - - C* get() const { - return ptr_; - } - - // Comparison operators. - // These return whether a scoped_ptr_malloc and a plain pointer refer - // to the same object, not just to two different but equal objects. - // For compatibility with the boost-derived implementation, these - // take non-const arguments. - bool operator==(C* p) const { - return ptr_ == p; - } - - bool operator!=(C* p) const { - return ptr_ != p; - } - - // Swap two scoped pointers. - void swap(scoped_ptr_malloc & b) { - C* tmp = b.ptr_; - b.ptr_ = ptr_; - ptr_ = tmp; - } - - // Release a pointer. - // The return value is the current pointer held by this object. - // If this object holds a NULL pointer, the return value is NULL. - // After this operation, this object will hold a NULL pointer, - // and will not own the object any more. - C* release() { - C* tmp = ptr_; - ptr_ = NULL; - return tmp; - } - - private: - C* ptr_; - - // no reason to use these: each scoped_ptr_malloc should have its own object - template - bool operator==(scoped_ptr_malloc const& p) const; - template - bool operator!=(scoped_ptr_malloc const& p) const; - - // Disallow evil constructors - scoped_ptr_malloc(const scoped_ptr_malloc&); - void operator=(const scoped_ptr_malloc&); -}; - -template inline -void swap(scoped_ptr_malloc& a, scoped_ptr_malloc& b) { - a.swap(b); -} - -template inline -bool operator==(C* p, const scoped_ptr_malloc& b) { - return p == b.get(); -} - -template inline -bool operator!=(C* p, const scoped_ptr_malloc& b) { - return p != b.get(); -} - } // namespace google_breakpad #endif // COMMON_SCOPED_PTR_H_ diff --git a/src/common/simple_string_dictionary.h b/src/common/simple_string_dictionary.h index 166d56c8d..0e3158859 100644 --- a/src/common/simple_string_dictionary.h +++ b/src/common/simple_string_dictionary.h @@ -142,11 +142,11 @@ class NonAllocatingMap { const char* GetValueForKey(const char* key) const { assert(key); if (!key) - return NULL; + return nullptr; size_t index = GetEntryIndexForKey(key); if (index == num_entries) - return NULL; + return nullptr; return entries_[index].value; } diff --git a/src/common/simple_string_dictionary_unittest.cc b/src/common/simple_string_dictionary_unittest.cc index b4dd7fe90..caa21c5c4 100644 --- a/src/common/simple_string_dictionary_unittest.cc +++ b/src/common/simple_string_dictionary_unittest.cc @@ -86,7 +86,7 @@ TEST(NonAllocatingMapTest, SimpleStringDictionary) { EXPECT_FALSE(dict.GetValueForKey("key3")); // Remove by setting value to NULL - dict.SetKeyValue("key2", NULL); + dict.SetKeyValue("key2", nullptr); // Now make sure it's not there anymore EXPECT_FALSE(dict.GetValueForKey("key2")); @@ -326,13 +326,13 @@ TEST(NonAllocatingMapTest, ByIndex) { TEST(NonAllocatingMapTest, NullKey) { NonAllocatingMap<4, 6, 6> map; - ASSERT_DEATH(map.SetKeyValue(NULL, "hello"), ""); + ASSERT_DEATH(map.SetKeyValue(nullptr, "hello"), ""); map.SetKeyValue("hi", "there"); - ASSERT_DEATH(map.GetValueForKey(NULL), ""); + ASSERT_DEATH(map.GetValueForKey(nullptr), ""); EXPECT_STREQ("there", map.GetValueForKey("hi")); - ASSERT_DEATH(map.GetValueForKey(NULL), ""); + ASSERT_DEATH(map.GetValueForKey(nullptr), ""); map.RemoveKey("hi"); EXPECT_EQ(0u, map.GetCount()); } diff --git a/src/common/solaris/dump_symbols.cc b/src/common/solaris/dump_symbols.cc index 09e5b376b..07ca87e7a 100644 --- a/src/common/solaris/dump_symbols.cc +++ b/src/common/solaris/dump_symbols.cc @@ -32,6 +32,7 @@ #include // Must come first #endif +#include #include #include #include @@ -46,7 +47,6 @@ #include #include -#include "common/scoped_ptr.h" #include "common/solaris/dump_symbols.h" #include "common/solaris/file_id.h" #include "common/solaris/guid_creator.h" @@ -219,14 +219,14 @@ bool IsValidElf(const GElf_Ehdr* elf_header) { static bool FindSectionByName(Elf* elf, const char* name, int shstrndx, GElf_Shdr* shdr) { - assert(name != NULL); + assert(name != nullptr); if (strlen(name) == 0) return false; - Elf_Scn* scn = NULL; + Elf_Scn* scn = nullptr; - while ((scn = elf_nextscn(elf, scn)) != NULL) { + while ((scn = elf_nextscn(elf, scn)) != nullptr) { if (gelf_getshdr(scn, shdr) == (GElf_Shdr*)0) { fprintf(stderr, "failed to read section header: %s\n", elf_errmsg(0)); return false; @@ -399,7 +399,7 @@ bool LoadAllSymbols(const GElf_Shdr* stab_section, const GElf_Shdr* stabstr_section, GElf_Word base, struct SymbolInfo* symbols) { - if (stab_section == NULL || stabstr_section == NULL) + if (stab_section == nullptr || stabstr_section == nullptr) return false; char* stabstr = reinterpret_cast(stabstr_section->sh_offset + base); @@ -482,7 +482,7 @@ bool LoadSymbols(Elf* elf, GElf_Ehdr* elf_header, struct SymbolInfo* symbols, } bool WriteModuleInfo(int fd, GElf_Half arch, const std::string& obj_file) { - const char* arch_name = NULL; + const char* arch_name = nullptr; if (arch == EM_386) arch_name = "x86"; else if (arch == EM_X86_64) @@ -610,13 +610,13 @@ class MmapWrapper { base_(mapped_address), size_(mapped_size) { } ~MmapWrapper() { - if (base_ != NULL) { + if (base_ != nullptr) { assert(size_ > 0); munmap((char*)base_, size_); } } void release() { - base_ = NULL; + base_ = nullptr; size_ = 0; } @@ -651,16 +651,16 @@ bool DumpSymbols::WriteSymbolFile(const std::string& obj_file, int sym_fd) { struct stat st; if (fstat(obj_fd, &st) != 0 && st.st_size <= 0) return false; - void* obj_base = mmap(NULL, st.st_size, + void* obj_base = mmap(nullptr, st.st_size, PROT_READ, MAP_PRIVATE, obj_fd, 0); if (obj_base == MAP_FAILED) return false; MmapWrapper map_wrapper(obj_base, st.st_size); GElf_Ehdr elf_header; - Elf* elf = elf_begin(obj_fd, ELF_C_READ, NULL); + Elf* elf = elf_begin(obj_fd, ELF_C_READ, nullptr); AutoElfEnder elfEnder(elf); - if (gelf_getehdr(elf, &elf_header) == (GElf_Ehdr*)NULL) { + if (gelf_getehdr(elf, &elf_header) == (GElf_Ehdr*)nullptr) { fprintf(stderr, "failed to read elf header: %s\n", elf_errmsg(-1)); return false; } diff --git a/src/common/solaris/file_id.cc b/src/common/solaris/file_id.cc index 5a9982bb4..9efb2e86d 100644 --- a/src/common/solaris/file_id.cc +++ b/src/common/solaris/file_id.cc @@ -36,20 +36,19 @@ #include // Must come first #endif +#include "common/solaris/file_id.h" + +#include #include #include #include -#include -#include #include #include +#include +#include #include -#include -#include - #include "common/md5.h" -#include "common/solaris/file_id.h" #include "common/solaris/message_output.h" #include "google_breakpad/common/minidump_format.h" @@ -71,7 +70,7 @@ static bool FindElfTextSection(int fd, const void* elf_base, assert(text_start); assert(text_size); - *text_start = NULL; + *text_start = nullptr; *text_size = 0; if (elf_version(EV_CURRENT) == EV_NONE) { @@ -81,10 +80,10 @@ static bool FindElfTextSection(int fd, const void* elf_base, GElf_Ehdr elf_header; lseek(fd, 0L, 0); - Elf* elf = elf_begin(fd, ELF_C_READ, NULL); + Elf* elf = elf_begin(fd, ELF_C_READ, nullptr); AutoElfEnder elfEnder(elf); - if (gelf_getehdr(elf, &elf_header) == (GElf_Ehdr*)NULL) { + if (gelf_getehdr(elf, &elf_header) == (GElf_Ehdr*)nullptr) { print_message2(2, "failed to read elf header: %s\n", elf_errmsg(-1)); return false; } @@ -98,11 +97,11 @@ static bool FindElfTextSection(int fd, const void* elf_base, } static const char kTextSectionName[] = ".text"; - const GElf_Shdr* text_section = NULL; - Elf_Scn* scn = NULL; + const GElf_Shdr* text_section = nullptr; + Elf_Scn* scn = nullptr; GElf_Shdr shdr; - while ((scn = elf_nextscn(elf, scn)) != NULL) { + while ((scn = elf_nextscn(elf, scn)) != nullptr) { if (gelf_getshdr(scn, &shdr) == (GElf_Shdr*)0) { print_message2(2, "failed to read section header: %s\n", elf_errmsg(0)); return false; @@ -122,7 +121,7 @@ static bool FindElfTextSection(int fd, const void* elf_base, } } } - if (text_section != NULL && text_section->sh_size > 0) { + if (text_section != nullptr && text_section->sh_size > 0) { *text_start = (char*)elf_base + text_section->sh_offset; *text_size = text_section->sh_size; return true; @@ -155,12 +154,12 @@ bool FileID::ElfFileIdentifier(unsigned char identifier[16]) { if (fstat(fd, &st) != 0 || st.st_size <= 0) return false; - void* base = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + void* base = mmap(nullptr, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (base == MAP_FAILED) return false; bool success = false; - const void* text_section = NULL; + const void* text_section = nullptr; int text_size = 0; if (FindElfTextSection(fd, base, &text_section, &text_size)) { diff --git a/src/common/solaris/guid_creator.cc b/src/common/solaris/guid_creator.cc index 998d24991..e6f377e88 100644 --- a/src/common/solaris/guid_creator.cc +++ b/src/common/solaris/guid_creator.cc @@ -32,15 +32,14 @@ #include // Must come first #endif -#include -#include +#include "common/solaris/guid_creator.h" +#include #include #include +#include #include -#include "common/solaris/guid_creator.h" - // // GUIDGenerator // @@ -51,7 +50,7 @@ class GUIDGenerator { public: GUIDGenerator() { - srandom(time(NULL)); + srandom(time(nullptr)); } bool CreateGUID(GUID *guid) const { diff --git a/src/common/stabs_reader.cc b/src/common/stabs_reader.cc index e18780c9d..55f24813c 100644 --- a/src/common/stabs_reader.cc +++ b/src/common/stabs_reader.cc @@ -80,7 +80,7 @@ StabsReader::StabsReader(const uint8_t* stab, size_t stab_size, handler_(handler), string_offset_(0), next_cu_string_offset_(0), - current_source_file_(NULL) { } + current_source_file_(nullptr) { } const char* StabsReader::SymbolString() { ptrdiff_t offset = string_offset_ + iterator_->name_offset; @@ -138,7 +138,7 @@ bool StabsReader::ProcessCompilationUnit() { // There may be an N_SO entry whose name ends with a slash, // indicating the directory in which the compilation occurred. // The build directory defaults to NULL. - const char* build_directory = NULL; + const char* build_directory = nullptr; { const char* name = SymbolString(); if (name[0] && name[strlen(name) - 1] == '/') { diff --git a/src/common/stabs_reader_unittest.cc b/src/common/stabs_reader_unittest.cc index 294e8836a..fe7fb9e07 100644 --- a/src/common/stabs_reader_unittest.cc +++ b/src/common/stabs_reader_unittest.cc @@ -135,7 +135,7 @@ class StabsAssembler: public Section { string_assembler_(string_assembler), value_size_(0), entry_count_(0), - cu_header_(NULL) { } + cu_header_(nullptr) { } ~StabsAssembler() { assert(!cu_header_); } // Accessor and setter for value_size_. @@ -188,7 +188,7 @@ class StabsAssembler: public Section { cu_header_->final_entry_count = entry_count_; cu_header_->final_string_size = string_assembler_->EndCU(); delete cu_header_; - cu_header_ = NULL; + cu_header_ = nullptr; return *this; } @@ -320,7 +320,7 @@ TEST_F(Stabs, MockStabsInput) { EXPECT_CALL(mock_handler, EndCompilationUnit(0xd04b7448U)) .WillOnce(Return(true)); EXPECT_CALL(mock_handler, StartCompilationUnit(StrEq("file3.c"), - 0x11759f10U, NULL)) + 0x11759f10U, nullptr)) .WillOnce(Return(true)); EXPECT_CALL(mock_handler, EndCompilationUnit(0x11cfe4b5U)) .WillOnce(Return(true)); @@ -338,7 +338,7 @@ TEST_F(Stabs, AbruptCU) { InSequence s; EXPECT_CALL(mock_handler, - StartCompilationUnit(StrEq("file2-1.c"), 0xbf10d5e4, NULL)) + StartCompilationUnit(StrEq("file2-1.c"), 0xbf10d5e4, nullptr)) .WillOnce(Return(true)); EXPECT_CALL(mock_handler, EndCompilationUnit(0)) .WillOnce(Return(true)); @@ -358,7 +358,7 @@ TEST_F(Stabs, AbruptFunction) { InSequence s; EXPECT_CALL(mock_handler, - StartCompilationUnit(StrEq("file3-1.c"), 0xb83ddf10U, NULL)) + StartCompilationUnit(StrEq("file3-1.c"), 0xb83ddf10U, nullptr)) .WillOnce(Return(true)); EXPECT_CALL(mock_handler, StartFunction(StrEq("fun3_1"), 0xbbd4a145U)) .WillOnce(Return(true)); @@ -395,12 +395,12 @@ TEST_F(Stabs, NoCUEnd) { InSequence s; EXPECT_CALL(mock_handler, - StartCompilationUnit(StrEq("file5-1.c"), 0x2f7493c9U, NULL)) + StartCompilationUnit(StrEq("file5-1.c"), 0x2f7493c9U, nullptr)) .WillOnce(Return(true)); EXPECT_CALL(mock_handler, EndCompilationUnit(0)) .WillOnce(Return(true)); EXPECT_CALL(mock_handler, - StartCompilationUnit(StrEq("file5-2.c"), 0xf9f1d50fU, NULL)) + StartCompilationUnit(StrEq("file5-2.c"), 0xf9f1d50fU, nullptr)) .WillOnce(Return(true)); EXPECT_CALL(mock_handler, EndCompilationUnit(0)) .WillOnce(Return(true)); @@ -430,7 +430,7 @@ TEST_F(Stabs, Unitized) { { InSequence s; EXPECT_CALL(mock_handler, - StartCompilationUnit(StrEq("antimony"), 0x7e259f1aU, NULL)) + StartCompilationUnit(StrEq("antimony"), 0x7e259f1aU, nullptr)) .WillOnce(Return(true)); EXPECT_CALL(mock_handler, StartFunction(Eq("arsenic"), 0x7fbcccaeU)) .WillOnce(Return(true)); @@ -439,7 +439,7 @@ TEST_F(Stabs, Unitized) { EXPECT_CALL(mock_handler, EndCompilationUnit(0x80b0014cU)) .WillOnce(Return(true)); EXPECT_CALL(mock_handler, - StartCompilationUnit(StrEq("aluminum"), 0x86756839U, NULL)) + StartCompilationUnit(StrEq("aluminum"), 0x86756839U, nullptr)) .WillOnce(Return(true)); EXPECT_CALL(mock_handler, StartFunction(Eq("selenium"), 0xa8e120b0U)) .WillOnce(Return(true)); @@ -469,7 +469,7 @@ TEST_F(Stabs, NonUnitized) { InSequence s; EXPECT_CALL(mock_handler, StartCompilationUnit(StrEq("Tanzania"), - 0x11a97352, NULL)) + 0x11a97352, nullptr)) .WillOnce(Return(true)); EXPECT_CALL(mock_handler, EndCompilationUnit(0x21a97352)) .WillOnce(Return(true)); @@ -497,7 +497,7 @@ TEST_F(Stabs, FunctionEnd) { InSequence s; EXPECT_CALL(mock_handler, StartCompilationUnit(StrEq("compilation unit"), - 0x52a830d644cd6942ULL, NULL)) + 0x52a830d644cd6942ULL, nullptr)) .WillOnce(Return(true)); EXPECT_CALL(mock_handler, StartFunction(Eq("function 1"), 0xbb5ab70ecdd23bfeULL)) diff --git a/src/common/stabs_to_module.cc b/src/common/stabs_to_module.cc index f04c987ad..05982b941 100644 --- a/src/common/stabs_to_module.cc +++ b/src/common/stabs_to_module.cc @@ -52,8 +52,9 @@ namespace google_breakpad { // Older GCC may not support it. static string Demangle(const string& mangled) { int status = 0; - char *demangled = abi::__cxa_demangle(mangled.c_str(), NULL, NULL, &status); - if (status == 0 && demangled != NULL) { + char *demangled = abi::__cxa_demangle( + mangled.c_str(), nullptr, nullptr, &status); + if (status == 0 && demangled != nullptr) { string str(demangled); free(demangled); return str; @@ -85,8 +86,8 @@ bool StabsToModule::EndCompilationUnit(uint64_t address) { assert(in_compilation_unit_); in_compilation_unit_ = false; comp_unit_base_address_ = 0; - current_source_file_ = NULL; - current_source_file_name_ = NULL; + current_source_file_ = nullptr; + current_source_file_name_ = nullptr; if (address) boundaries_.push_back(static_cast(address)); return true; @@ -115,7 +116,7 @@ bool StabsToModule::EndFunction(uint64_t address) { functions_.push_back(current_function_); else delete current_function_; - current_function_ = NULL; + current_function_ = nullptr; if (address) boundaries_.push_back(static_cast(address)); return true; diff --git a/src/common/stabs_to_module.h b/src/common/stabs_to_module.h index 99c61b0c9..e384e66f4 100644 --- a/src/common/stabs_to_module.h +++ b/src/common/stabs_to_module.h @@ -66,9 +66,9 @@ class StabsToModule: public google_breakpad::StabsHandler { module_(module), in_compilation_unit_(false), comp_unit_base_address_(0), - current_function_(NULL), - current_source_file_(NULL), - current_source_file_name_(NULL) { } + current_function_(nullptr), + current_source_file_(nullptr), + current_source_file_name_(nullptr) { } ~StabsToModule(); // The standard StabsHandler virtual member functions. diff --git a/src/common/stabs_to_module_unittest.cc b/src/common/stabs_to_module_unittest.cc index c6d40281b..3befb51c2 100644 --- a/src/common/stabs_to_module_unittest.cc +++ b/src/common/stabs_to_module_unittest.cc @@ -59,7 +59,7 @@ TEST(StabsToModule, SimpleCU) { // Now check to see what has been added to the Module. Module::File *file = m.FindExistingFile("source-file-name"); - ASSERT_TRUE(file != NULL); + ASSERT_TRUE(file != nullptr); vector functions; m.GetFunctions(&functions, functions.end()); @@ -125,7 +125,7 @@ TEST(StabsToModule, DuplicateFunctionNames) { // Now check to see what has been added to the Module. Module::File *file = m.FindExistingFile("compilation-unit"); - ASSERT_TRUE(file != NULL); + ASSERT_TRUE(file != nullptr); vector functions; m.GetFunctions(&functions, functions.end()); @@ -158,9 +158,9 @@ TEST(InferSizes, LineSize) { // Now check to see what has been added to the Module. Module::File *file1 = m.FindExistingFile("source-file-name-1"); - ASSERT_TRUE(file1 != NULL); + ASSERT_TRUE(file1 != nullptr); Module::File *file2 = m.FindExistingFile("source-file-name-2"); - ASSERT_TRUE(file2 != NULL); + ASSERT_TRUE(file2 != nullptr); vector functions; m.GetFunctions(&functions, functions.end()); @@ -205,7 +205,7 @@ TEST(FunctionNames, Mangled) { // Now check to see what has been added to the Module. Module::File *file = m.FindExistingFile("compilation-unit"); - ASSERT_TRUE(file != NULL); + ASSERT_TRUE(file != nullptr); vector functions; m.GetFunctions(&functions, functions.end()); diff --git a/src/common/string_view.h b/src/common/string_view.h index a8e15922d..8b9b19e6e 100644 --- a/src/common/string_view.h +++ b/src/common/string_view.h @@ -29,9 +29,13 @@ #ifndef COMMON_STRING_VIEW_H__ #define COMMON_STRING_VIEW_H__ -#include -#include +#include +#include +#include + +#include #include + #include "common/using_std_string.h" namespace google_breakpad { diff --git a/src/common/test_assembler.cc b/src/common/test_assembler.cc index 6b1c1fd35..95c1619a3 100644 --- a/src/common/test_assembler.cc +++ b/src/common/test_assembler.cc @@ -42,6 +42,8 @@ #include +#include "common/memory_allocator.h" + namespace google_breakpad { namespace test_assembler { @@ -58,7 +60,7 @@ Label::~Label() { } Label& Label::operator=(uint64_t value) { - value_->Set(NULL, value); + value_->Set(nullptr, value); return *this; } @@ -108,7 +110,7 @@ bool Label::IsKnownConstant(uint64_t* value_p) const { Binding* base; uint64_t addend; value_->Get(&base, &addend); - if (base != NULL) return false; + if (base != nullptr) return false; if (value_p) *value_p = addend; return true; } @@ -130,7 +132,7 @@ bool Label::IsKnownOffsetFrom(const Label& label, uint64_t* offset_p) const Label::Binding::Binding() : base_(this), addend_(), reference_count_(1) { } Label::Binding::Binding(uint64_t addend) - : base_(NULL), addend_(addend), reference_count_(1) { } + : base_(nullptr), addend_(addend), reference_count_(1) { } Label::Binding::~Binding() { assert(reference_count_ == 0); @@ -145,7 +147,7 @@ void Label::Binding::Set(Binding* binding, uint64_t addend) { } else if (!base_) { // We are a known constant, but BINDING may not be, so turn the // tables and try to set BINDING's value instead. - binding->Set(NULL, addend_ - addend); + binding->Set(nullptr, addend_ - addend); } else { if (binding) { // Find binding's final value. Since the final value is always either @@ -327,7 +329,7 @@ Section& Section::ULEB128(uint64_t value) { Section& Section::Align(size_t alignment, uint8_t pad_byte) { // ALIGNMENT must be a power of two. assert(((alignment - 1) & alignment) == 0); - size_t new_size = (contents_.size() + alignment - 1) & ~(alignment - 1); + size_t new_size = PageAllocator::AlignUp(contents_.size(), alignment); contents_.append(new_size - contents_.size(), pad_byte); assert((contents_.size() & (alignment - 1)) == 0); return *this; diff --git a/src/common/test_assembler.h b/src/common/test_assembler.h index 809c7b21d..4d40b50dd 100644 --- a/src/common/test_assembler.h +++ b/src/common/test_assembler.h @@ -134,7 +134,7 @@ class Label { // Return true if this label's value is known. If VALUE_P is given, // set *VALUE_P to the known value if returning true. - bool IsKnownConstant(uint64_t* value_p = NULL) const; + bool IsKnownConstant(uint64_t* value_p = nullptr) const; // Return true if the offset from LABEL to this label is known. If // OFFSET_P is given, set *OFFSET_P to the offset when returning true. @@ -154,7 +154,8 @@ class Label { // l-m // -10 // m-l // 10 // m.Value() // error: m's value is not known - bool IsKnownOffsetFrom(const Label& label, uint64_t* offset_p = NULL) const; + bool IsKnownOffsetFrom(const Label& label, + uint64_t* offset_p = nullptr) const; private: // A label's value, or if that is not yet known, how the value is diff --git a/src/common/tests/auto_tempdir.h b/src/common/tests/auto_tempdir.h index 963c2dcf4..d7b583e1a 100644 --- a/src/common/tests/auto_tempdir.h +++ b/src/common/tests/auto_tempdir.h @@ -52,7 +52,7 @@ class AutoTempDir { public: AutoTempDir() { char temp_dir[] = TEMPDIR "/breakpad.XXXXXX"; - EXPECT_TRUE(mkdtemp(temp_dir) != NULL); + EXPECT_TRUE(mkdtemp(temp_dir) != nullptr); path_.assign(temp_dir); } @@ -72,7 +72,7 @@ class AutoTempDir { return; dirent* entry; - while ((entry = readdir(dir)) != NULL) { + while ((entry = readdir(dir)) != nullptr) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; string entry_path = path + "/" + entry->d_name; diff --git a/src/common/windows/dia_util.cc b/src/common/windows/dia_util.cc index a5d984d1a..631e389d5 100644 --- a/src/common/windows/dia_util.cc +++ b/src/common/windows/dia_util.cc @@ -81,7 +81,7 @@ bool FindTable(REFIID iid, IDiaSession* session, void** table) { ULONG fetched = 0; while (SUCCEEDED(enum_tables->Next(1, &temp_table, &fetched)) && fetched == 1) { - void* temp = NULL; + void* temp = nullptr; if (SUCCEEDED(temp_table->QueryInterface(iid, &temp))) { *table = temp; return true; diff --git a/src/common/windows/http_upload.cc b/src/common/windows/http_upload.cc index bd48a2339..76363398b 100644 --- a/src/common/windows/http_upload.cc +++ b/src/common/windows/http_upload.cc @@ -30,14 +30,24 @@ #include // Must come first #endif +#include +#include +#include +#include + #include +#include +#include +#include +#include + +#if defined(HAVE_ZLIB) +#include +#endif // Disable exception handler warnings. #pragma warning(disable:4530) -#include -#include - #include "common/windows/string_utils-inl.h" #include "common/windows/http_upload.h" @@ -46,9 +56,64 @@ namespace { using std::string; using std::wstring; using std::map; - using std::vector; - using std::ifstream; - using std::ios; + using std::unique_ptr; + +// Silence warning C4100, which may strike when building without zlib support. +#pragma warning(push) +#pragma warning(disable:4100) + + // Compresses the contents of `data` into `deflated` using the deflate + // algorithm, if supported. Returns true on success, or false if not supported + // or in case of any error. The contents of `deflated` are undefined in the + // latter case. + bool Deflate(const string& data, string& deflated) { +#if defined(HAVE_ZLIB) + z_stream stream{}; + + // Start with an output buffer sufficient for 75% compression to avoid + // reallocations. + deflated.resize(data.size() / 4); + stream.next_in = reinterpret_cast(const_cast(data.data())); + stream.avail_in = data.size(); + stream.next_out = reinterpret_cast(&deflated[0]); + stream.avail_out = deflated.size(); + stream.data_type = Z_TEXT; + + // Z_BEST_SPEED is chosen because, in practice, it offers excellent speed + // with comparable compression for the symbol data typically being uploaded. + // Z_BEST_COMPRESSION: 2151202094 bytes compressed 84.27% in 74.440s. + // Z_DEFAULT_COMPRESSION: 2151202094 bytes compressed 84.08% in 36.016s. + // Z_BEST_SPEED: 2151202094 bytes compressed 80.39% in 13.73s. + int result = deflateInit(&stream, Z_BEST_SPEED); + if (result != Z_OK) { + return false; + } + + while (true) { + result = deflate(&stream, /*flush=*/Z_FINISH); + if (result == Z_STREAM_END) { // All data processed. + deflated.resize(stream.total_out); + break; + } + if (result != Z_OK && result != Z_BUF_ERROR) { + fwprintf(stderr, L"Compression failed with zlib error %d\n", result); + break; // Error condition. + } + // Grow `deflated` by at least 1k to accept the rest of the data. + deflated.resize(deflated.size() + std::max(stream.avail_in, 1024U)); + stream.next_out = reinterpret_cast(&deflated[stream.total_out]); + stream.avail_out = deflated.size() - stream.total_out; + } + deflateEnd(&stream); + + return result == Z_STREAM_END; +#else + return false; +#endif // defined(HAVE_ZLIB) + } + +// Restore C4100 to its previous state. +#pragma warning(pop) const wchar_t kUserAgent[] = L"Breakpad/1.0 (Windows)"; @@ -74,7 +139,8 @@ namespace { } // compute the length of the buffer we'll need - int charcount = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, NULL, 0); + int charcount = MultiByteToWideChar( + CP_UTF8, 0, utf8.c_str(), -1, nullptr, 0); if (charcount == 0) { return wstring(); @@ -95,7 +161,7 @@ namespace { // compute the length of the buffer we'll need int charcount = WideCharToMultiByte(cp, 0, wide.c_str(), -1, - NULL, 0, NULL, NULL); + nullptr, 0, nullptr, nullptr); if (charcount == 0) { return string(); } @@ -103,45 +169,82 @@ namespace { // convert char *buf = new char[charcount]; WideCharToMultiByte(cp, 0, wide.c_str(), -1, buf, charcount, - NULL, NULL); + nullptr, nullptr); string result(buf); delete[] buf; return result; } - bool GetFileContents(const wstring& filename, vector* contents) { - bool rv = false; - // The "open" method on pre-MSVC8 ifstream implementations doesn't accept a - // wchar_t* filename, so use _wfopen directly in that case. For VC8 and - // later, _wfopen has been deprecated in favor of _wfopen_s, which does - // not exist in earlier versions, so let the ifstream open the file itself. - // GCC doesn't support wide file name and opening on FILE* requires ugly - // hacks, so fallback to multi byte file. -#ifdef _MSC_VER - ifstream file; - file.open(filename.c_str(), ios::binary); -#else // GCC - ifstream file(WideToMBCP(filename, CP_ACP).c_str(), ios::binary); -#endif // _MSC_VER >= 1400 - if (file.is_open()) { - file.seekg(0, ios::end); - std::streamoff length = file.tellg(); - // Check for loss of data when converting lenght from std::streamoff into - // std::vector::size_type - std::vector::size_type vector_size = - static_cast::size_type>(length); - if (static_cast(vector_size) == length) { - contents->resize(vector_size); - if (length != 0) { - file.seekg(0, ios::beg); - file.read(&((*contents)[0]), length); + // Returns a string representation of a given Windows error code, or null + // on failure. + using ScopedLocalString = unique_ptr; + ScopedLocalString FormatError(DWORD error) { + wchar_t* message_buffer = nullptr; + DWORD message_length = + ::FormatMessageW( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS, + /*lpSource=*/::GetModuleHandle(L"wininet.dll"), error, + /*dwLanguageId=*/0, reinterpret_cast(&message_buffer), + /*nSize=*/0, /*Arguments=*/nullptr); + return ScopedLocalString(message_length ? message_buffer : nullptr, + &LocalFree); + } + + // Emits a log message to stderr for the named operation and Windows error + // code. + void LogError(const char* operation, DWORD error) { + ScopedLocalString message = FormatError(error); + fwprintf(stderr, L"%S failed with error %u: %s\n", operation, error, + message ? message.get() : L""); + } + + // Invokes the Win32 CloseHandle function on `handle` if it is valid. + // Intended for use as a deleter for a std::unique_ptr. + void CloseWindowsHandle(void* handle) { + if (handle != INVALID_HANDLE_VALUE && handle != nullptr) { + ::CloseHandle(handle); + } + } + + // Appends the contents of the file at `filename` to `contents`. + bool AppendFileContents(const wstring& filename, string* contents) { + // Use Win32 APIs rather than the STL so that files larger than 2^31-1 bytes + // can be read. This also allows for use of a hint to the cache manager that + // the file will be read sequentially, which can improve performance. + using ScopedWindowsHandle = + unique_ptr; + ScopedWindowsHandle file( + ::CreateFileW(filename.c_str(), GENERIC_READ, + FILE_SHARE_DELETE | FILE_SHARE_READ, + /*lpSecurityAttributes=*/nullptr, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, + /*hTemplateFile=*/nullptr), &CloseWindowsHandle); + BY_HANDLE_FILE_INFORMATION info = {}; + if (file.get() != nullptr && file.get() != INVALID_HANDLE_VALUE && + ::GetFileInformationByHandle(file.get(), &info)) { + uint64_t file_size = info.nFileSizeHigh; + file_size <<= 32; + file_size |= info.nFileSizeLow; + string::size_type position = contents->size(); + contents->resize(position + file_size); + constexpr DWORD kChunkSize = 1024*1024; + while (file_size) { + const DWORD bytes_to_read = + (file_size >= kChunkSize + ? kChunkSize + : static_cast(file_size)); + DWORD bytes_read = 0; + if (!::ReadFile(file.get(), &((*contents)[position]), bytes_to_read, + &bytes_read, /*lpOverlapped=*/nullptr)) { + return false; } - rv = true; + position += bytes_read; + file_size -= bytes_read; } - file.close(); } - return rv; + return true; } bool CheckParameters(const map& parameters) { @@ -177,39 +280,48 @@ namespace { static_cast(&content_length), &content_length_size, 0)) { has_content_length_header = true; - claimed_size = wcstol(content_length, NULL, 10); + claimed_size = wcstol(content_length, nullptr, 10); response_body.reserve(claimed_size); + } else { + DWORD error = ::GetLastError(); + if (error != ERROR_HTTP_HEADER_NOT_FOUND) { + LogError("HttpQueryInfo", error); + } } - DWORD bytes_available; DWORD total_read = 0; - BOOL return_code; - - while (((return_code = InternetQueryDataAvailable(request, &bytes_available, - 0, 0)) != 0) && bytes_available > 0) { - vector response_buffer(bytes_available); + while (true) { + DWORD bytes_available; + if (!InternetQueryDataAvailable(request, &bytes_available, 0, 0)) { + LogError("InternetQueryDataAvailable", ::GetLastError()); + return false; + } + if (bytes_available == 0) { + break; + } + // Grow the output to hold the available bytes. + response_body.resize(total_read + bytes_available); DWORD size_read; - - return_code = InternetReadFile(request, - &response_buffer[0], - bytes_available, &size_read); - - if (return_code && size_read > 0) { - total_read += size_read; - response_body.append(&response_buffer[0], size_read); + if (!InternetReadFile(request, &response_body[total_read], + bytes_available, &size_read)) { + LogError("InternetReadFile", ::GetLastError()); + return false; } - else { + if (size_read == 0) { break; } + total_read += size_read; } + // The body may have been over-sized above; shrink to the actual bytes read. + response_body.resize(total_read); - bool succeeded = return_code && (!has_content_length_header || - (total_read == claimed_size)); - if (succeeded && response) { + if (has_content_length_header && (total_read != claimed_size)) { + return false; // The response doesn't match the Content-Length header. + } + if (response) { *response = UTF8ToWide(response_body); } - - return succeeded; + return true; } bool SendRequestInner( @@ -237,8 +349,7 @@ namespace { components.dwUrlPathLength = sizeof(path) / sizeof(path[0]); if (!InternetCrackUrl(url.c_str(), static_cast(url.size()), 0, &components)) { - DWORD err = GetLastError(); - wprintf(L"%d\n", err); + LogError("InternetCrackUrl", ::GetLastError()); return false; } bool secure = false; @@ -251,22 +362,24 @@ namespace { AutoInternetHandle internet(InternetOpen(kUserAgent, INTERNET_OPEN_TYPE_PRECONFIG, - NULL, // proxy name - NULL, // proxy bypass + nullptr, // proxy name + nullptr, // proxy bypass 0)); // flags if (!internet.get()) { + LogError("InternetOpen", ::GetLastError()); return false; } AutoInternetHandle connection(InternetConnect(internet.get(), host, components.nPort, - NULL, // user name - NULL, // password + nullptr, // user name + nullptr, // password INTERNET_SERVICE_HTTP, 0, // flags 0)); // context if (!connection.get()) { + LogError("InternetConnect", ::GetLastError()); return false; } @@ -275,20 +388,23 @@ namespace { AutoInternetHandle request(HttpOpenRequest(connection.get(), http_method.c_str(), path, - NULL, // version - NULL, // referer - NULL, // agent type + nullptr, // version + nullptr, // referer + nullptr, // agent type http_open_flags, 0)); // context if (!request.get()) { + LogError("HttpOpenRequest", ::GetLastError()); return false; } if (!content_type_header.empty()) { - HttpAddRequestHeaders(request.get(), - content_type_header.c_str(), - static_cast(-1), - HTTP_ADDREQ_FLAG_ADD); + if (!HttpAddRequestHeaders(request.get(), + content_type_header.c_str(), + static_cast(-1), + HTTP_ADDREQ_FLAG_ADD)) { + LogError("HttpAddRequestHeaders", ::GetLastError()); + } } if (timeout_ms) { @@ -296,20 +412,21 @@ namespace { INTERNET_OPTION_SEND_TIMEOUT, timeout_ms, sizeof(*timeout_ms))) { - fwprintf(stderr, L"Could not unset send timeout, continuing...\n"); + LogError("InternetSetOption-send timeout", ::GetLastError()); } if (!InternetSetOption(request.get(), INTERNET_OPTION_RECEIVE_TIMEOUT, timeout_ms, sizeof(*timeout_ms))) { - fwprintf(stderr, L"Could not unset receive timeout, continuing...\n"); + LogError("InternetSetOption-receive timeout", ::GetLastError()); } } - if (!HttpSendRequest(request.get(), NULL, 0, + if (!HttpSendRequest(request.get(), nullptr, 0, const_cast(request_body.data()), static_cast(request_body.size()))) { + LogError("HttpSendRequest", ::GetLastError()); return false; } @@ -319,10 +436,11 @@ namespace { if (!HttpQueryInfo(request.get(), HTTP_QUERY_STATUS_CODE, static_cast(&http_status), &http_status_size, 0)) { + LogError("HttpQueryInfo", ::GetLastError()); return false; } - int http_response = wcstol(http_status, NULL, 10); + int http_response = wcstol(http_status, nullptr, 10); if (response_code) { *response_code = http_response; } @@ -386,16 +504,7 @@ namespace { request_body->append("\r\n"); } - vector contents; - if (!GetFileContents(filename, &contents)) { - return false; - } - - if (!contents.empty()) { - request_body->append(&(contents[0]), contents.size()); - } - - return true; + return AppendFileContents(filename, request_body); } bool GenerateRequestBody(const map& parameters, @@ -448,10 +557,20 @@ namespace google_breakpad { return false; } + static const wchar_t kNoEncoding[] = L""; + static const wchar_t kDeflateEncoding[] = L"Content-Encoding: deflate\r\n"; + const wchar_t* encoding_header = &kNoEncoding[0]; + string compressed_body; + if (Deflate(request_body, compressed_body)) { + request_body.swap(compressed_body); + encoding_header = &kDeflateEncoding[0]; + } // else deflate unsupported or failed; send the raw data. + string().swap(compressed_body); // Free memory. + return SendRequestInner( url, L"PUT", - L"", + encoding_header, request_body, timeout_ms, response_body, diff --git a/src/common/windows/http_upload.h b/src/common/windows/http_upload.h index e117840e9..4a2e9bf2f 100644 --- a/src/common/windows/http_upload.h +++ b/src/common/windows/http_upload.h @@ -41,6 +41,7 @@ #include #include +#include namespace google_breakpad { @@ -51,7 +52,8 @@ using std::map; class HTTPUpload { public: // Sends a PUT request containing the data in |path| to the given - // URL. + // URL. The data is encoded via the deflate algorithm, if support for such + // is available at build-time. // Only HTTP(S) URLs are currently supported. Returns true on success. // If the request is successful and response_body is non-NULL, // the response body will be returned in response_body. diff --git a/src/common/windows/omap.cc b/src/common/windows/omap.cc index 1ffcec765..12d1a2f15 100644 --- a/src/common/windows/omap.cc +++ b/src/common/windows/omap.cc @@ -106,10 +106,10 @@ #include "common/windows/omap.h" +#include #include #include -#include #include #include "common/windows/dia_util.h" @@ -174,14 +174,14 @@ bool EndpointIndexLess(const EndpointIndex& ei1, const EndpointIndex& ei2) { bool FindAndLoadOmapTable(const wchar_t* name, IDiaSession* session, OmapTable* table) { - assert(name != NULL); - assert(session != NULL); - assert(table != NULL); + assert(name != nullptr); + assert(session != nullptr); + assert(table != nullptr); CComPtr stream; if (!FindDebugStream(name, session, &stream)) return false; - assert(stream.p != NULL); + assert(stream.p != nullptr); LONG count = 0; if (FAILED(stream->get_Count(&count))) { @@ -193,7 +193,7 @@ bool FindAndLoadOmapTable(const wchar_t* name, // Get the length of the stream in bytes. DWORD bytes_read = 0; ULONG count_read = 0; - if (FAILED(stream->Next(count, 0, &bytes_read, NULL, &count_read))) { + if (FAILED(stream->Next(count, 0, &bytes_read, nullptr, &count_read))) { fprintf(stderr, "IDiaEnumDebugStreamData::Next failed while reading " "length of stream \"%ws\"\n", name); return false; @@ -224,20 +224,20 @@ bool FindAndLoadOmapTable(const wchar_t* name, // This determines the original image length by looking through the segment // table. bool GetOriginalImageLength(IDiaSession* session, DWORD* image_length) { - assert(session != NULL); - assert(image_length != NULL); + assert(session != nullptr); + assert(image_length != nullptr); CComPtr enum_segments; if (!FindTable(session, &enum_segments)) return false; - assert(enum_segments.p != NULL); + assert(enum_segments.p != nullptr); DWORD temp_image_length = 0; CComPtr segment; ULONG fetched = 0; while (SUCCEEDED(enum_segments->Next(1, &segment, &fetched)) && fetched == 1) { - assert(segment.p != NULL); + assert(segment.p != nullptr); DWORD rva = 0; DWORD length = 0; @@ -266,7 +266,7 @@ bool GetOriginalImageLength(IDiaSession* session, DWORD* image_length) { // immediately preceding a gap. The mapped ranges must be sorted by // 'rva_original'. void FillInRemovedLengths(Mapping* mapping) { - assert(mapping != NULL); + assert(mapping != nullptr); // Find and fill gaps. We do this with two sweeps. We first sweep forward // looking for gaps. When we identify a gap we then sweep forward with a @@ -319,7 +319,7 @@ void FillInRemovedLengths(Mapping* mapping) { // Builds a unified view of the mapping between the original and transformed // image space by merging OMAPTO and OMAPFROM data. void BuildMapping(const OmapData& omap_data, Mapping* mapping) { - assert(mapping != NULL); + assert(mapping != nullptr); mapping->clear(); @@ -407,7 +407,7 @@ void BuildMapping(const OmapData& omap_data, Mapping* mapping) { } void BuildEndpointIndexMap(ImageMap* image_map) { - assert(image_map != NULL); + assert(image_map != nullptr); if (image_map->mapping.size() == 0) return; @@ -477,7 +477,7 @@ void BuildSubsequentRVAMap(const OmapData& omap_data, // Clips the given mapped range. void ClipMappedRangeOriginal(const AddressRange& clip_range, MappedRange* mapped_range) { - assert(mapped_range != NULL); + assert(mapped_range != nullptr); // The clipping range is entirely outside of the mapped range. if (clip_range.end() <= mapped_range->rva_original || @@ -547,15 +547,15 @@ int AddressRange::Compare(const AddressRange& rhs) const { bool GetOmapDataAndDisableTranslation(IDiaSession* session, OmapData* omap_data) { - assert(session != NULL); - assert(omap_data != NULL); + assert(session != nullptr); + assert(omap_data != nullptr); CComPtr address_map; if (FAILED(session->QueryInterface(&address_map))) { fprintf(stderr, "IDiaSession::QueryInterface(IDiaAddressMap) failed\n"); return false; } - assert(address_map.p != NULL); + assert(address_map.p != nullptr); BOOL omap_enabled = FALSE; if (FAILED(address_map->get_addressMapEnabled(&omap_enabled))) { @@ -597,7 +597,7 @@ bool GetOmapDataAndDisableTranslation(IDiaSession* session, } void BuildImageMap(const OmapData& omap_data, ImageMap* image_map) { - assert(image_map != NULL); + assert(image_map != nullptr); BuildMapping(omap_data, &image_map->mapping); BuildEndpointIndexMap(image_map); @@ -607,7 +607,7 @@ void BuildImageMap(const OmapData& omap_data, ImageMap* image_map) { void MapAddressRange(const ImageMap& image_map, const AddressRange& original_range, AddressRangeVector* mapped_ranges) { - assert(mapped_ranges != NULL); + assert(mapped_ranges != nullptr); const Mapping& map = image_map.mapping; diff --git a/src/common/windows/pdb_source_line_writer.cc b/src/common/windows/pdb_source_line_writer.cc index dd80a6d25..7ae978c7d 100644 --- a/src/common/windows/pdb_source_line_writer.cc +++ b/src/common/windows/pdb_source_line_writer.cc @@ -105,7 +105,7 @@ void MaybeRecordSymbol(DWORD rva, // Take the 'least' symbol by lexicographical order of the decorated name. We // use the decorated rather than undecorated name because computing the latter // is expensive. - BSTR current_name, new_name; + CComBSTR current_name, new_name; loc->second.symbol->get_name(¤t_name); symbol->get_name(&new_name); if (wcscmp(new_name, current_name) < 0) { @@ -401,7 +401,7 @@ void PDBSourceLineWriter::Lines::AddLine(const Line& line) { } PDBSourceLineWriter::PDBSourceLineWriter(bool handle_inline) - : output_(NULL), handle_inline_(handle_inline) {} + : output_(nullptr), handle_inline_(handle_inline) {} PDBSourceLineWriter::~PDBSourceLineWriter() { Close(); @@ -421,7 +421,7 @@ bool PDBSourceLineWriter::Open(const wstring& file, FileFormat format) { Close(); code_file_.clear(); - if (FAILED(CoInitialize(NULL))) { + if (FAILED(CoInitialize(nullptr))) { fprintf(stderr, "CoInitialize failed\n"); return false; } @@ -448,7 +448,7 @@ bool PDBSourceLineWriter::Open(const wstring& file, FileFormat format) { } break; case EXE_FILE: - for_exe_result = data_source->loadDataForExe(file_name, NULL, NULL); + for_exe_result = data_source->loadDataForExe(file_name, nullptr, nullptr); if (FAILED(for_exe_result)) { PrintOpenError(for_exe_result, "loadDataForExe", file_name); return false; @@ -458,7 +458,8 @@ bool PDBSourceLineWriter::Open(const wstring& file, FileFormat format) { case ANY_FILE: from_pdb_result = data_source->loadDataFromPdb(file_name); if (FAILED(from_pdb_result)) { - for_exe_result = data_source->loadDataForExe(file_name, NULL, NULL); + for_exe_result = data_source->loadDataForExe( + file_name, nullptr, nullptr); if (FAILED(for_exe_result)) { PrintOpenError(from_pdb_result, "loadDataFromPdb", file_name); PrintOpenError(for_exe_result, "loadDataForExe", file_name); @@ -479,6 +480,28 @@ bool PDBSourceLineWriter::Open(const wstring& file, FileFormat format) { return true; } +int PDBSourceLineWriter::GetCallsiteInlineOriginId( + CComPtr& callsite) { + wstring name; + { + CComBSTR name_bstr; + callsite->get_name(&name_bstr); + if (name.assign(name_bstr, name_bstr.Length()).empty()) { + name = L""; + } + } + + const int next_id = inline_origins_.size(); + auto iter_inserted = inline_origins_.emplace(std::move(name), next_id); + if (!iter_inserted.second) { + // `name` is already present. Return its previously-assigned unique id. + return iter_inserted.first->second; + } + // `name` was just inserted. Assign it the next id and return this value. + iter_inserted.first->second = next_id; + return next_id; +} + bool PDBSourceLineWriter::GetLine(IDiaLineNumber* dia_line, Line* line) const { if (FAILED(dia_line->get_relativeVirtualAddress(&line->rva))) { fprintf(stderr, "failed to get line rva\n"); @@ -609,7 +632,7 @@ bool PDBSourceLineWriter::PrintSourceFiles() { } CComPtr compilands; - if (FAILED(global->findChildren(SymTagCompiland, NULL, + if (FAILED(global->findChildren(SymTagCompiland, nullptr, nsNone, &compilands))) { fprintf(stderr, "findChildren failed\n"); return false; @@ -623,7 +646,7 @@ bool PDBSourceLineWriter::PrintSourceFiles() { ULONG count; while (SUCCEEDED(compilands->Next(1, &compiland, &count)) && count == 1) { CComPtr source_files; - if (FAILED(session_->findFile(compiland, NULL, nsNone, &source_files))) { + if (FAILED(session_->findFile(compiland, nullptr, nsNone, &source_files))) { return false; } CComPtr file; @@ -666,14 +689,14 @@ bool PDBSourceLineWriter::PrintFunctions() { return false; } - CComPtr symbols = NULL; + CComPtr symbols = nullptr; // Find all function symbols first. SymbolMap rva_symbol; - hr = global->findChildren(SymTagFunction, NULL, nsNone, &symbols); + hr = global->findChildren(SymTagFunction, nullptr, nsNone, &symbols); if (SUCCEEDED(hr)) { - CComPtr symbol = NULL; + CComPtr symbol = nullptr; while (SUCCEEDED(symbols->Next(1, &symbol, &count)) && count == 1) { if (SUCCEEDED(symbol->get_relativeVirtualAddress(&rva))) { @@ -692,10 +715,10 @@ bool PDBSourceLineWriter::PrintFunctions() { // Find all public symbols and record public symbols that are not also private // symbols. - hr = global->findChildren(SymTagPublicSymbol, NULL, nsNone, &symbols); + hr = global->findChildren(SymTagPublicSymbol, nullptr, nsNone, &symbols); if (SUCCEEDED(hr)) { - CComPtr symbol = NULL; + CComPtr symbol = nullptr; while (SUCCEEDED(symbols->Next(1, &symbol, &count)) && count == 1) { if (SUCCEEDED(symbol->get_relativeVirtualAddress(&rva))) { @@ -734,7 +757,7 @@ bool PDBSourceLineWriter::PrintFunctions() { // of those blocks and print out an extra FUNC line for blocks // that are not contained in their parent functions. CComPtr compilands; - if (FAILED(global->findChildren(SymTagCompiland, NULL, + if (FAILED(global->findChildren(SymTagCompiland, nullptr, nsNone, &compilands))) { fprintf(stderr, "findChildren failed on the global\n"); return false; @@ -743,7 +766,7 @@ bool PDBSourceLineWriter::PrintFunctions() { CComPtr compiland; while (SUCCEEDED(compilands->Next(1, &compiland, &count)) && count == 1) { CComPtr blocks; - if (FAILED(compiland->findChildren(SymTagBlock, NULL, + if (FAILED(compiland->findChildren(SymTagBlock, nullptr, nsNone, &blocks))) { fprintf(stderr, "findChildren failed on a compiland\n"); return false; @@ -783,17 +806,16 @@ bool PDBSourceLineWriter::PrintFunctions() { } void PDBSourceLineWriter::PrintInlineOrigins() const { - struct OriginCompare { - bool operator()(const InlineOrigin lhs, const InlineOrigin rhs) const { - return lhs.id < rhs.id; - } - }; - set origins; - // Sort by origin id. - for (auto const& origin : inline_origins_) - origins.insert(origin.second); - for (auto o : origins) { - fprintf(output_, "INLINE_ORIGIN %d %ls\n", o.id, o.name.c_str()); + // Inline origins' unique identifiers are assigned sequentially starting from + // zero. Make a reverse-mapping from ids to names, then print the names in + // order of id. + vector names_by_id(inline_origins_.size()); + for (const auto& origin : inline_origins_) { + names_by_id[origin.second] = &origin.first; + } + int id = 0; + for (const wstring* name : names_by_id) { + fprintf(output_, "INLINE_ORIGIN %d %ls\n", id++, name->c_str()); } } @@ -838,19 +860,7 @@ bool PDBSourceLineWriter::GetInlines(IDiaSymbol* block, } dia_line.Release(); } - BSTR name; - callsite->get_name(&name); - if (SysStringLen(name) == 0) { - name = SysAllocString(L""); - } - auto iter = inline_origins_.find(name); - if (iter == inline_origins_.end()) { - InlineOrigin origin; - origin.id = inline_origins_.size(); - origin.name = name; - inline_origins_[name] = origin; - } - new_inline->SetOriginId(inline_origins_[name].id); + new_inline->SetOriginId(GetCallsiteInlineOriginId(callsite)); new_inline->SetCallSiteLine(call_site_line); new_inline->SetCallSiteFileId(file_id); // Go to next level. @@ -1091,7 +1101,7 @@ bool PDBSourceLineWriter::PrintCodePublicSymbol(IDiaSymbol* symbol, if (rva == 0) break; - CComPtr next_sym = NULL; + CComPtr next_sym = nullptr; LONG displacement; if (FAILED(session_->findSymbolByRVAEx(rva, SymTagPublicSymbol, &next_sym, &displacement))) { @@ -1300,7 +1310,7 @@ int PDBSourceLineWriter::GetFunctionStackParamSize(IDiaSymbol* function) { // Gather the symbols corresponding to data. CComPtr data_children; - if (FAILED(function->findChildren(SymTagData, NULL, nsNone, + if (FAILED(function->findChildren(SymTagData, nullptr, nsNone, &data_children))) { return 0; } @@ -1426,7 +1436,7 @@ bool PDBSourceLineWriter::WriteSymbols(FILE* symbol_file) { ret = ret && PrintSourceFiles() && PrintFunctions() && PrintFrameData(); PrintInlineOrigins(); - output_ = NULL; + output_ = nullptr; return ret; } diff --git a/src/common/windows/pdb_source_line_writer.h b/src/common/windows/pdb_source_line_writer.h index 8c74e2ca3..c4d7c0613 100644 --- a/src/common/windows/pdb_source_line_writer.h +++ b/src/common/windows/pdb_source_line_writer.h @@ -103,15 +103,6 @@ class PDBSourceLineWriter { bool UsesGUID(bool *uses_guid); private: - // InlineOrigin represents INLINE_ORIGIN record in a symbol file. It's an - // inlined function. - struct InlineOrigin { - // The unique id for an InlineOrigin. - int id; - // The name of the inlined function. - wstring name; - }; - // Line represents LINE record in a symbol file. It represents a source code // line. struct Line { @@ -196,6 +187,10 @@ class PDBSourceLineWriter { map line_map_; }; + // Returns the unique id for the inline origin with the same name as the given + // callsite, creating a new id if needed. + int GetCallsiteInlineOriginId(CComPtr& callsite); + // Construct Line from IDiaLineNumber. The output Line is stored at line. // Return true on success. bool GetLine(IDiaLineNumber* dia_line, Line* line) const; @@ -337,8 +332,8 @@ class PDBSourceLineWriter { // This maps unique filenames to file IDs. unordered_map unique_files_; - // The INLINE_ORIGINS records. The key is the function name. - std::map inline_origins_; + // The INLINE_ORIGINS records; inline origin name -> unique id. + std::map inline_origins_; // This is used for calculating post-transform symbol addresses and lengths. ImageMap image_map_; diff --git a/src/common/windows/pe_util.cc b/src/common/windows/pe_util.cc index 2d4aebe79..4af88a4ba 100644 --- a/src/common/windows/pe_util.cc +++ b/src/common/windows/pe_util.cc @@ -140,7 +140,7 @@ bool ReadModuleInfo(const wstring & pe_file, PDBModuleInfo * info) { return false; } - AutoImage img(ImageLoad((PSTR)img_file.c_str(), NULL)); + AutoImage img(ImageLoad((PSTR)img_file.c_str(), nullptr)); if (!img) { fprintf(stderr, "Failed to load %s\n", img_file.c_str()); return false; @@ -214,7 +214,7 @@ bool ReadPEInfo(const wstring & pe_file, PEModuleInfo * info) { return false; } - AutoImage img(ImageLoad((PSTR)img_file.c_str(), NULL)); + AutoImage img(ImageLoad((PSTR)img_file.c_str(), nullptr)); if (!img) { fprintf(stderr, "Failed to open PE file: %S\n", pe_file.c_str()); return false; @@ -256,7 +256,7 @@ bool PrintPEFrameData(const wstring & pe_file, FILE * out_file) return false; } - AutoImage img(ImageLoad((PSTR)img_file.c_str(), NULL)); + AutoImage img(ImageLoad((PSTR)img_file.c_str(), nullptr)); if (!img) { fprintf(stderr, "Failed to load %s\n", img_file.c_str()); return false; @@ -366,7 +366,7 @@ bool PrintPEFrameData(const wstring & pe_file, FILE * out_file) &img->LastRvaSection)); } else { - unwind_info = NULL; + unwind_info = nullptr; } } while (unwind_info); fprintf(out_file, "STACK CFI INIT %lx %lx .cfa: $rsp .ra: .cfa %lu - ^\n", diff --git a/src/common/windows/string_utils.cc b/src/common/windows/string_utils.cc index 1e570b525..032131208 100644 --- a/src/common/windows/string_utils.cc +++ b/src/common/windows/string_utils.cc @@ -30,11 +30,13 @@ #include // Must come first #endif -#include -#include - #include "common/windows/string_utils-inl.h" +#include +#include + +#include + namespace google_breakpad { // static @@ -55,13 +57,14 @@ bool WindowsStringUtils::safe_mbstowcs(const string& mbs, wstring* wcs) { size_t wcs_length; #if _MSC_VER >= 1400 // MSVC 2005/8 - errno_t err; - if ((err = mbstowcs_s(&wcs_length, NULL, 0, mbs.c_str(), _TRUNCATE)) != 0) { + errno_t err = mbstowcs_s(&wcs_length, nullptr, 0, mbs.c_str(), _TRUNCATE); + if (err != 0) { return false; } assert(wcs_length > 0); #else // _MSC_VER >= 1400 - if ((wcs_length = mbstowcs(NULL, mbs.c_str(), mbs.length())) == (size_t)-1) { + wcs_length = mbstowcs(nullptr, mbs.c_str(), mbs.length()); + if (wcs_length == (size_t)-1) { return false; } @@ -73,7 +76,7 @@ bool WindowsStringUtils::safe_mbstowcs(const string& mbs, wstring* wcs) { // Now, convert. #if _MSC_VER >= 1400 // MSVC 2005/8 - if ((err = mbstowcs_s(NULL, &wcs_v[0], wcs_length, mbs.c_str(), + if ((err = mbstowcs_s(nullptr, &wcs_v[0], wcs_length, mbs.c_str(), _TRUNCATE)) != 0) { return false; } @@ -98,13 +101,14 @@ bool WindowsStringUtils::safe_wcstombs(const wstring& wcs, string* mbs) { size_t mbs_length; #if _MSC_VER >= 1400 // MSVC 2005/8 - errno_t err; - if ((err = wcstombs_s(&mbs_length, NULL, 0, wcs.c_str(), _TRUNCATE)) != 0) { + errno_t err = wcstombs_s(&mbs_length, nullptr, 0, wcs.c_str(), _TRUNCATE); + if (err != 0) { return false; } assert(mbs_length > 0); #else // _MSC_VER >= 1400 - if ((mbs_length = wcstombs(NULL, wcs.c_str(), wcs.length())) == (size_t)-1) { + mbs_length = wcstombs(nullptr, wcs.c_str(), wcs.length()); + if (mbs_length == (size_t)-1) { return false; } @@ -116,7 +120,7 @@ bool WindowsStringUtils::safe_wcstombs(const wstring& wcs, string* mbs) { // Now, convert. #if _MSC_VER >= 1400 // MSVC 2005/8 - if ((err = wcstombs_s(NULL, &mbs_v[0], mbs_length, wcs.c_str(), + if ((err = wcstombs_s(nullptr, &mbs_v[0], mbs_length, wcs.c_str(), _TRUNCATE)) != 0) { return false; } diff --git a/src/common/windows/sym_upload_v2_protocol.cc b/src/common/windows/sym_upload_v2_protocol.cc index 450f3626b..ee3b1919e 100644 --- a/src/common/windows/sym_upload_v2_protocol.cc +++ b/src/common/windows/sym_upload_v2_protocol.cc @@ -32,7 +32,7 @@ #include "common/windows/sym_upload_v2_protocol.h" -#include +#include #include "common/windows/http_upload.h" #include "common/windows/symbol_collector_client.h" diff --git a/src/common/windows/symbol_collector_client.cc b/src/common/windows/symbol_collector_client.cc index d91b702b0..9695100a0 100644 --- a/src/common/windows/symbol_collector_client.cc +++ b/src/common/windows/symbol_collector_client.cc @@ -106,7 +106,7 @@ namespace google_breakpad { if (!HTTPUpload::SendSimplePostRequest( url, body, - L"application/json", + L"Content-Type: application/json", timeout_ms, &response, &response_code)) { @@ -176,4 +176,4 @@ namespace google_breakpad { SymbolStatus::Missing; } -} // namespace google_breakpad \ No newline at end of file +} // namespace google_breakpad diff --git a/src/google_breakpad/processor/call_stack.h b/src/google_breakpad/processor/call_stack.h index 9bf062f83..a18f8f74b 100644 --- a/src/google_breakpad/processor/call_stack.h +++ b/src/google_breakpad/processor/call_stack.h @@ -44,7 +44,8 @@ #ifndef GOOGLE_BREAKPAD_PROCESSOR_CALL_STACK_H__ #define GOOGLE_BREAKPAD_PROCESSOR_CALL_STACK_H__ -#include +#include + #include namespace google_breakpad { diff --git a/src/google_breakpad/processor/code_modules.h b/src/google_breakpad/processor/code_modules.h index 7538328bd..b7f726760 100644 --- a/src/google_breakpad/processor/code_modules.h +++ b/src/google_breakpad/processor/code_modules.h @@ -34,8 +34,6 @@ #ifndef GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULES_H__ #define GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULES_H__ -#include - #include #include "google_breakpad/common/breakpad_types.h" diff --git a/src/google_breakpad/processor/microdump.h b/src/google_breakpad/processor/microdump.h index 7c2f3e662..2a2bdec6c 100644 --- a/src/google_breakpad/processor/microdump.h +++ b/src/google_breakpad/processor/microdump.h @@ -38,10 +38,10 @@ #ifndef GOOGLE_BREAKPAD_PROCESSOR_MICRODUMP_H__ #define GOOGLE_BREAKPAD_PROCESSOR_MICRODUMP_H__ +#include #include #include -#include "common/scoped_ptr.h" #include "common/using_std_string.h" #include "google_breakpad/processor/dump_context.h" #include "google_breakpad/processor/memory_region.h" @@ -121,10 +121,10 @@ class Microdump { string GetCrashReason() { return crash_reason_; } uint64_t GetCrashAddress() { return crash_address_; } private: - scoped_ptr context_; - scoped_ptr stack_region_; - scoped_ptr modules_; - scoped_ptr system_info_; + std::unique_ptr context_; + std::unique_ptr stack_region_; + std::unique_ptr modules_; + std::unique_ptr system_info_; string crash_reason_; uint64_t crash_address_; }; diff --git a/src/google_breakpad/processor/minidump_processor.h b/src/google_breakpad/processor/minidump_processor.h index 8475407e7..2a5b07499 100644 --- a/src/google_breakpad/processor/minidump_processor.h +++ b/src/google_breakpad/processor/minidump_processor.h @@ -138,6 +138,11 @@ class MinidumpProcessor { enable_objdump_for_exploitability_ = enabled; } + // Sets the maximum number of threads to process. + void set_max_thread_count(int max_thread_count) { + max_thread_count_ = max_thread_count; + } + private: StackFrameSymbolizer* frame_symbolizer_; // Indicate whether resolver_helper_ is owned by this instance. @@ -157,6 +162,10 @@ class MinidumpProcessor { // purposes of disassembly. This results in significantly more overhead than // the enable_objdump_ flag. bool enable_objdump_for_exploitability_; + + // The maximum number of threads to process. This can be exceeded if the + // requesting thread comes after the limit. Setting this to -1 means no limit. + int max_thread_count_; }; } // namespace google_breakpad diff --git a/src/google_breakpad/processor/process_state.h b/src/google_breakpad/processor/process_state.h index 3fe6a5c27..50f3d5889 100644 --- a/src/google_breakpad/processor/process_state.h +++ b/src/google_breakpad/processor/process_state.h @@ -91,7 +91,7 @@ enum ExploitabilityRating { class ProcessState { public: - ProcessState() : modules_(NULL), unloaded_modules_(NULL) { Clear(); } + ProcessState() : modules_(nullptr), unloaded_modules_(nullptr) { Clear(); } ~ProcessState(); // Resets the ProcessState to its default values @@ -105,6 +105,7 @@ class ProcessState { uint64_t crash_address() const { return crash_address_; } string assertion() const { return assertion_; } int requesting_thread() const { return requesting_thread_; } + int original_thread_count() const { return original_thread_count_; } const ExceptionRecord* exception_record() const { return &exception_record_; } const vector* threads() const { return &threads_; } const vector* thread_memory_regions() const { @@ -168,6 +169,11 @@ class ProcessState { // indicating that the dump thread is not available. int requesting_thread_; + // Original thread count. The Processor has limit on how many threads to + // process, so not all threads are processed. This tells you how many threads + // were originally in the minudump. + int original_thread_count_; + // Exception record details: code, flags, address, parameters. ExceptionRecord exception_record_; diff --git a/src/google_breakpad/processor/stack_frame.h b/src/google_breakpad/processor/stack_frame.h index eebe06e6a..5960f89b4 100644 --- a/src/google_breakpad/processor/stack_frame.h +++ b/src/google_breakpad/processor/stack_frame.h @@ -59,7 +59,7 @@ struct StackFrame { StackFrame() : instruction(), - module(NULL), + module(nullptr), function_name(), function_base(), source_file_name(), diff --git a/src/google_breakpad/processor/stack_frame_cpu.h b/src/google_breakpad/processor/stack_frame_cpu.h index 91f1d0cb1..086a6f5a4 100644 --- a/src/google_breakpad/processor/stack_frame_cpu.h +++ b/src/google_breakpad/processor/stack_frame_cpu.h @@ -72,8 +72,8 @@ struct StackFrameX86 : public StackFrame { StackFrameX86() : context(), context_validity(CONTEXT_VALID_NONE), - windows_frame_info(NULL), - cfi_frame_info(NULL) {} + windows_frame_info(nullptr), + cfi_frame_info(nullptr) {} ~StackFrameX86(); // Overriden to return the return address as saved on the stack. diff --git a/src/processor/address_map_unittest.cc b/src/processor/address_map_unittest.cc index 2d754b602..6ea811257 100644 --- a/src/processor/address_map_unittest.cc +++ b/src/processor/address_map_unittest.cc @@ -111,7 +111,7 @@ static bool DoAddressMapTest() { ASSERT_EQ(entry->id(), 1); ASSERT_EQ(address, 10); ASSERT_TRUE(test_map.Retrieve(11, &entry, &address)); - ASSERT_TRUE(test_map.Retrieve(11, &entry, NULL)); // NULL ok here + ASSERT_TRUE(test_map.Retrieve(11, &entry, nullptr)); // nullptr ok here // Add some more elements. ASSERT_TRUE(test_map.Store(5, diff --git a/src/processor/basic_code_modules.cc b/src/processor/basic_code_modules.cc index bdfc8f3de..23008c3fa 100644 --- a/src/processor/basic_code_modules.cc +++ b/src/processor/basic_code_modules.cc @@ -83,7 +83,8 @@ BasicCodeModules::BasicCodeModules(const CodeModules* that, linked_ptr module(that->GetModuleAtIndex(i)->Copy()); uint64_t delta = 0; if (map_.RetrieveRange(module->base_address() + module->size() - 1, - &module, NULL /* base */, &delta, NULL /* size */) && + &module, nullptr /* base */, &delta, + nullptr /* size */) && delta > 0) { BPLOG(INFO) << "The range for module " << module->code_file() << " was shrunk down by " << HexString(delta) << " bytes."; @@ -109,10 +110,10 @@ unsigned int BasicCodeModules::module_count() const { const CodeModule* BasicCodeModules::GetModuleForAddress( uint64_t address) const { linked_ptr module; - if (!map_.RetrieveRange(address, &module, NULL /* base */, NULL /* delta */, - NULL /* size */)) { + if (!map_.RetrieveRange(address, &module, nullptr /* base */, + nullptr /* delta */, nullptr /* size */)) { BPLOG(INFO) << "No module at " << HexString(address); - return NULL; + return nullptr; } return module.get(); @@ -125,10 +126,10 @@ const CodeModule* BasicCodeModules::GetMainModule() const { const CodeModule* BasicCodeModules::GetModuleAtSequence( unsigned int sequence) const { linked_ptr module; - if (!map_.RetrieveRangeAtIndex(sequence, &module, NULL /* base */, - NULL /* delta */, NULL /* size */)) { + if (!map_.RetrieveRangeAtIndex(sequence, &module, nullptr /* base */, + nullptr /* delta */, nullptr /* size */)) { BPLOG(ERROR) << "RetrieveRangeAtIndex failed for sequence " << sequence; - return NULL; + return nullptr; } return module.get(); diff --git a/src/processor/basic_code_modules.h b/src/processor/basic_code_modules.h index e9d58f6b0..2eaf49ecc 100644 --- a/src/processor/basic_code_modules.h +++ b/src/processor/basic_code_modules.h @@ -40,8 +40,6 @@ #ifndef PROCESSOR_BASIC_CODE_MODULES_H__ #define PROCESSOR_BASIC_CODE_MODULES_H__ -#include - #include #include "google_breakpad/processor/code_modules.h" diff --git a/src/processor/basic_source_line_resolver.cc b/src/processor/basic_source_line_resolver.cc index 220bd746c..20037b1a7 100644 --- a/src/processor/basic_source_line_resolver.cc +++ b/src/processor/basic_source_line_resolver.cc @@ -170,7 +170,7 @@ bool BasicSourceLineResolver::Module::LoadMapFromMemory( char* buffer; buffer = strtok_r(memory_buffer, "\r\n", &save_ptr); - while (buffer != NULL) { + while (buffer != nullptr) { ++line_number; if (strncmp(buffer, "FILE ", 5) == 0) { @@ -237,7 +237,7 @@ bool BasicSourceLineResolver::Module::LoadMapFromMemory( if (num_errors > kMaxErrorsBeforeBailing) { break; } - buffer = strtok_r(NULL, "\r\n", &save_ptr); + buffer = strtok_r(nullptr, "\r\n", &save_ptr); } is_corrupt_ = num_errors > 0; return true; @@ -318,7 +318,7 @@ void BasicSourceLineResolver::Module::LookupAddress( MemAddr function_size; MemAddr public_address; if (functions_.RetrieveNearestRange(address, &func, &function_base, - NULL /* delta */, &function_size) && + nullptr /* delta */, &function_size) && address >= function_base && address - function_base < function_size) { frame->function_name = func->name; frame->function_base = frame->module->base_address() + function_base; @@ -326,8 +326,8 @@ void BasicSourceLineResolver::Module::LookupAddress( linked_ptr line; MemAddr line_base; - if (func->lines.RetrieveRange(address, &line, &line_base, NULL /* delta */, - NULL /* size */)) { + if (func->lines.RetrieveRange(address, &line, &line_base, + nullptr /* delta */, nullptr /* size */)) { FileMap::const_iterator it = files_.find(line->source_file_id); if (it != files_.end()) { frame->source_file_name = files_.find(line->source_file_id)->second; @@ -352,7 +352,7 @@ void BasicSourceLineResolver::Module::LookupAddress( WindowsFrameInfo* BasicSourceLineResolver::Module::FindWindowsFrameInfo( const StackFrame* frame) const { MemAddr address = frame->instruction - frame->module->base_address(); - scoped_ptr result(new WindowsFrameInfo()); + std::unique_ptr result(new WindowsFrameInfo()); // We only know about WindowsFrameInfo::STACK_INFO_FRAME_DATA and // WindowsFrameInfo::STACK_INFO_FPO. Prefer them in this order. @@ -379,7 +379,7 @@ WindowsFrameInfo* BasicSourceLineResolver::Module::FindWindowsFrameInfo( linked_ptr function; MemAddr function_base, function_size; if (functions_.RetrieveNearestRange(address, &function, &function_base, - NULL /* delta */, &function_size) && + nullptr /* delta */, &function_size) && address >= function_base && address - function_base < function_size) { result->parameter_size = function->parameter_size; result->valid |= WindowsFrameInfo::VALID_PARAMETER_SIZE; @@ -395,7 +395,7 @@ WindowsFrameInfo* BasicSourceLineResolver::Module::FindWindowsFrameInfo( result->parameter_size = public_symbol->parameter_size; } - return NULL; + return nullptr; } CFIFrameInfo* BasicSourceLineResolver::Module::FindCFIFrameInfo( @@ -409,15 +409,15 @@ CFIFrameInfo* BasicSourceLineResolver::Module::FindCFIFrameInfo( // forward from the initial rule's starting address to frame's // instruction address, applying delta rules. if (!cfi_initial_rules_.RetrieveRange(address, &initial_rules, &initial_base, - NULL /* delta */, &initial_size)) { - return NULL; + nullptr /* delta */, &initial_size)) { + return nullptr; } // Create a frame info structure, and populate it with the rules from // the STACK CFI INIT record. - scoped_ptr rules(new CFIFrameInfo()); + std::unique_ptr rules(new CFIFrameInfo()); if (!ParseCFIRuleSet(initial_rules, rules.get())) - return NULL; + return nullptr; // Find the first delta rule that falls within the initial rule's range. map::const_iterator delta = @@ -488,7 +488,7 @@ BasicSourceLineResolver::Module::ParseFunction(char* function_line) { &size, &stack_param_size, &name)) { return new Function(name, address, size, stack_param_size, is_multiple); } - return NULL; + return nullptr; } BasicSourceLineResolver::Line* BasicSourceLineResolver::Module::ParseLine( @@ -502,7 +502,7 @@ BasicSourceLineResolver::Line* BasicSourceLineResolver::Module::ParseLine( &source_file)) { return new Line(address, size, source_file, line_number); } - return NULL; + return nullptr; } bool BasicSourceLineResolver::Module::ParsePublicSymbol(char* public_line) { @@ -553,7 +553,7 @@ bool BasicSourceLineResolver::Module::ParseStackInfo(char* stack_info_line) { type, rva, code_size)); - if (stack_frame_info == NULL) + if (stack_frame_info == nullptr) return false; // TODO(mmentovai): I wanted to use StoreRange's return value as this @@ -598,26 +598,26 @@ bool BasicSourceLineResolver::Module::ParseCFIFrameInfo( if (strcmp(init_or_address, "INIT") == 0) { // This record has the form "STACK INIT
". - char* address_field = strtok_r(NULL, " \r\n", &cursor); + char* address_field = strtok_r(nullptr, " \r\n", &cursor); if (!address_field) return false; - char* size_field = strtok_r(NULL, " \r\n", &cursor); + char* size_field = strtok_r(nullptr, " \r\n", &cursor); if (!size_field) return false; - char* initial_rules = strtok_r(NULL, "\r\n", &cursor); + char* initial_rules = strtok_r(nullptr, "\r\n", &cursor); if (!initial_rules) return false; - MemAddr address = strtoul(address_field, NULL, 16); - MemAddr size = strtoul(size_field, NULL, 16); + MemAddr address = strtoul(address_field, nullptr, 16); + MemAddr size = strtoul(size_field, nullptr, 16); cfi_initial_rules_.StoreRange(address, size, initial_rules); return true; } // This record has the form "STACK
". char* address_field = init_or_address; - char* delta_rules = strtok_r(NULL, "\r\n", &cursor); + char* delta_rules = strtok_r(nullptr, "\r\n", &cursor); if (!delta_rules) return false; - MemAddr address = strtoul(address_field, NULL, 16); + MemAddr address = strtoul(address_field, nullptr, 16); cfi_delta_rules_[address] = delta_rules; return true; } @@ -921,7 +921,8 @@ bool SymbolParseHelper::ParsePublicSymbol(char* public_line, bool* is_multiple, // static bool SymbolParseHelper::IsValidAfterNumber(char* after_number) { - if (after_number != NULL && strchr(kWhitespace, *after_number) != NULL) { + if (after_number != nullptr && + strchr(kWhitespace, *after_number) != nullptr) { return true; } return false; diff --git a/src/processor/basic_source_line_resolver_types.h b/src/processor/basic_source_line_resolver_types.h index 3c8b01c70..66fcbc6b8 100644 --- a/src/processor/basic_source_line_resolver_types.h +++ b/src/processor/basic_source_line_resolver_types.h @@ -39,7 +39,6 @@ #include #include -#include "common/scoped_ptr.h" #include "google_breakpad/processor/basic_source_line_resolver.h" #include "processor/source_line_resolver_base_types.h" diff --git a/src/processor/basic_source_line_resolver_unittest.cc b/src/processor/basic_source_line_resolver_unittest.cc index a73ded8b7..9cfd915ed 100644 --- a/src/processor/basic_source_line_resolver_unittest.cc +++ b/src/processor/basic_source_line_resolver_unittest.cc @@ -33,10 +33,10 @@ #include #include +#include #include #include "breakpad_googletest_includes.h" -#include "common/scoped_ptr.h" #include "common/using_std_string.h" #include "google_breakpad/processor/basic_source_line_resolver.h" #include "google_breakpad/processor/code_module.h" @@ -55,12 +55,11 @@ using google_breakpad::CodeModule; using google_breakpad::MemoryRegion; using google_breakpad::StackFrame; using google_breakpad::WindowsFrameInfo; -using google_breakpad::scoped_ptr; using google_breakpad::SymbolParseHelper; class TestCodeModule : public CodeModule { public: - TestCodeModule(string code_file) : code_file_(code_file) {} + TestCodeModule(const string& code_file) : code_file_(code_file) {} virtual ~TestCodeModule() {} virtual uint64_t base_address() const { return 0; } @@ -160,7 +159,7 @@ static bool VerifyEmpty(const StackFrame& frame) { static void ClearSourceLineInfo(StackFrame* frame) { frame->function_name.clear(); - frame->module = NULL; + frame->module = nullptr; frame->source_file_name.clear(); frame->source_line = 0; } @@ -187,10 +186,10 @@ TEST_F(TestBasicSourceLineResolver, TestLoadAndResolve) StackFrame frame; - scoped_ptr windows_frame_info; - scoped_ptr cfi_frame_info; + std::unique_ptr windows_frame_info; + std::unique_ptr cfi_frame_info; frame.instruction = 0x1000; - frame.module = NULL; + frame.module = nullptr; resolver.FillSourceLineInfo(&frame, nullptr); ASSERT_FALSE(frame.module); ASSERT_TRUE(frame.function_name.empty()); diff --git a/src/processor/cfi_frame_info.cc b/src/processor/cfi_frame_info.cc index 2094e0941..1aef1e36b 100644 --- a/src/processor/cfi_frame_info.cc +++ b/src/processor/cfi_frame_info.cc @@ -37,6 +37,7 @@ #include "processor/cfi_frame_info.h" +#include #include #include @@ -161,7 +162,7 @@ bool CFIRuleParser::Parse(const string& rule_set) { expression_ += ' '; expression_ += token; } - token = strtok_r(NULL, token_breaks, &cursor); + token = strtok_r(nullptr, token_breaks, &cursor); } } diff --git a/src/processor/cfi_frame_info_unittest.cc b/src/processor/cfi_frame_info_unittest.cc index 0cf4562d3..dcbd7721b 100644 --- a/src/processor/cfi_frame_info_unittest.cc +++ b/src/processor/cfi_frame_info_unittest.cc @@ -485,11 +485,11 @@ struct SimpleCFIWalkerFixture { SimpleCFIWalkerFixture::CFIWalker::RegisterSet SimpleCFIWalkerFixture::register_map[7] = { - { "r0", NULL, true, R0_VALID, &RawContext::r0 }, - { "r1", NULL, true, R1_VALID, &RawContext::r1 }, - { "r2", NULL, false, R2_VALID, &RawContext::r2 }, - { "r3", NULL, false, R3_VALID, &RawContext::r3 }, - { "r4", NULL, true, R4_VALID, &RawContext::r4 }, + { "r0", nullptr, true, R0_VALID, &RawContext::r0 }, + { "r1", nullptr, true, R1_VALID, &RawContext::r1 }, + { "r2", nullptr, false, R2_VALID, &RawContext::r2 }, + { "r3", nullptr, false, R3_VALID, &RawContext::r3 }, + { "r4", nullptr, true, R4_VALID, &RawContext::r4 }, { "sp", ".cfa", true, SP_VALID, &RawContext::sp }, { "pc", ".ra", true, PC_VALID, &RawContext::pc }, }; diff --git a/src/processor/contained_range_map-inl.h b/src/processor/contained_range_map-inl.h index e085dcb45..301c62128 100644 --- a/src/processor/contained_range_map-inl.h +++ b/src/processor/contained_range_map-inl.h @@ -126,7 +126,7 @@ bool ContainedRangeMap::StoreRange( // Optimization: if the iterators are equal, no child ranges would be // moved. Create the new child range with a NULL map to conserve space // in leaf nodes, of which there will be many. - AddressToRangeMap* child_map = NULL; + AddressToRangeMap* child_map = nullptr; if (iterator_base != iterator_high) { // The children of this range that are contained by the new range must @@ -203,7 +203,7 @@ void ContainedRangeMap::Clear() { delete child->second; delete map_; - map_ = NULL; + map_ = nullptr; } } diff --git a/src/processor/contained_range_map.h b/src/processor/contained_range_map.h index 24a3bb41e..3f5a4959a 100644 --- a/src/processor/contained_range_map.h +++ b/src/processor/contained_range_map.h @@ -76,7 +76,10 @@ class ContainedRangeMap { // and no entry, and as such is only suitable for the root node of a // ContainedRangeMap tree. explicit ContainedRangeMap(bool allow_equal_range = false) - : base_(), entry_(), map_(NULL), allow_equal_range_(allow_equal_range) {} + : base_(), + entry_(), + map_(nullptr), + allow_equal_range_(allow_equal_range) {} ~ContainedRangeMap(); diff --git a/src/processor/disassembler_objdump.cc b/src/processor/disassembler_objdump.cc index 9f9569a5e..3e0b6d196 100644 --- a/src/processor/disassembler_objdump.cc +++ b/src/processor/disassembler_objdump.cc @@ -73,7 +73,8 @@ bool IsOperandSize(const string& token) { return false; } -bool GetSegmentAddressX86(const DumpContext& context, string segment_name, +bool GetSegmentAddressX86(const DumpContext& context, + const string& segment_name, uint64_t& address) { if (segment_name == "ds") { address = context.GetContextX86()->ds; @@ -91,7 +92,8 @@ bool GetSegmentAddressX86(const DumpContext& context, string segment_name, return true; } -bool GetSegmentAddressAMD64(const DumpContext& context, string segment_name, +bool GetSegmentAddressAMD64(const DumpContext& context, + const string& segment_name, uint64_t& address) { if (segment_name == "ds") { address = 0; @@ -105,7 +107,8 @@ bool GetSegmentAddressAMD64(const DumpContext& context, string segment_name, return true; } -bool GetSegmentAddress(const DumpContext& context, string segment_name, +bool GetSegmentAddress(const DumpContext& context, + const string& segment_name, uint64_t& address) { if (context.GetContextCPU() == MD_CONTEXT_X86) { return GetSegmentAddressX86(context, segment_name, address); @@ -117,7 +120,8 @@ bool GetSegmentAddress(const DumpContext& context, string segment_name, } } -bool GetRegisterValueX86(const DumpContext& context, string register_name, +bool GetRegisterValueX86(const DumpContext& context, + const string& register_name, uint64_t& value) { if (register_name == "eax") { value = context.GetContextX86()->eax; @@ -145,7 +149,8 @@ bool GetRegisterValueX86(const DumpContext& context, string register_name, return true; } -bool GetRegisterValueAMD64(const DumpContext& context, string register_name, +bool GetRegisterValueAMD64(const DumpContext& context, + const string& register_name, uint64_t& value) { if (register_name == "rax") { value = context.GetContextAMD64()->rax; @@ -193,7 +198,8 @@ bool GetRegisterValueAMD64(const DumpContext& context, string register_name, // success. // Support for non-full-size registers not implemented, since we're only using // this to evaluate address expressions. -bool GetRegisterValue(const DumpContext& context, string register_name, +bool GetRegisterValue(const DumpContext& context, + const string& register_name, uint64_t& value) { if (context.GetContextCPU() == MD_CONTEXT_X86) { return GetRegisterValueX86(context, register_name, value); @@ -484,4 +490,4 @@ bool DisassemblerObjdump::CalculateDestAddress(const DumpContext& context, return CalculateAddress(context, dest_, address); } -} // namespace google_breakpad \ No newline at end of file +} // namespace google_breakpad diff --git a/src/processor/disassembler_x86.cc b/src/processor/disassembler_x86.cc index 741cec7fd..16d864ca6 100644 --- a/src/processor/disassembler_x86.cc +++ b/src/processor/disassembler_x86.cc @@ -56,26 +56,26 @@ DisassemblerX86::DisassemblerX86(const uint8_t* bytecode, pushed_bad_value_(false), end_of_block_(false), flags_(0) { - libdis::x86_init(libdis::opt_none, NULL, NULL); + x86_init(opt_none, nullptr, nullptr); } DisassemblerX86::~DisassemblerX86() { if (instr_valid_) - libdis::x86_oplist_free(¤t_instr_); + x86_oplist_free(¤t_instr_); - libdis::x86_cleanup(); + x86_cleanup(); } uint32_t DisassemblerX86::NextInstruction() { if (instr_valid_) - libdis::x86_oplist_free(¤t_instr_); + x86_oplist_free(¤t_instr_); if (current_byte_offset_ >= size_) { instr_valid_ = false; return 0; } uint32_t instr_size = 0; - instr_size = libdis::x86_disasm((unsigned char*)bytecode_, size_, + instr_size = x86_disasm((unsigned char*)bytecode_, size_, virtual_address_, current_byte_offset_, ¤t_instr_); if (instr_size == 0) { @@ -85,39 +85,39 @@ uint32_t DisassemblerX86::NextInstruction() { current_byte_offset_ += instr_size; current_inst_offset_++; - instr_valid_ = libdis::x86_insn_is_valid(¤t_instr_); + instr_valid_ = x86_insn_is_valid(¤t_instr_); if (!instr_valid_) return 0; - if (current_instr_.type == libdis::insn_return) + if (current_instr_.type == insn_return) end_of_block_ = true; - libdis::x86_op_t* src = libdis::x86_get_src_operand(¤t_instr_); - libdis::x86_op_t* dest = libdis::x86_get_dest_operand(¤t_instr_); + x86_op_t* src = x86_get_src_operand(¤t_instr_); + x86_op_t* dest = x86_get_dest_operand(¤t_instr_); if (register_valid_) { switch (current_instr_.group) { // Flag branches based off of bad registers and calls that occur // after pushing bad values. - case libdis::insn_controlflow: + case insn_controlflow: switch (current_instr_.type) { - case libdis::insn_jmp: - case libdis::insn_jcc: - case libdis::insn_call: - case libdis::insn_callcc: + case insn_jmp: + case insn_jcc: + case insn_call: + case insn_callcc: if (dest) { switch (dest->type) { - case libdis::op_expression: + case op_expression: if (dest->data.expression.base.id == bad_register_.id) flags_ |= DISX86_BAD_BRANCH_TARGET; break; - case libdis::op_register: + case op_register: if (dest->data.reg.id == bad_register_.id) flags_ |= DISX86_BAD_BRANCH_TARGET; break; default: if (pushed_bad_value_ && - (current_instr_.type == libdis::insn_call || - current_instr_.type == libdis::insn_callcc)) + (current_instr_.type == insn_call || + current_instr_.type == insn_callcc)) flags_ |= DISX86_BAD_ARGUMENT_PASSED; break; } @@ -129,24 +129,24 @@ uint32_t DisassemblerX86::NextInstruction() { break; // Flag block data operations that use bad registers for src or dest. - case libdis::insn_string: - if (dest && dest->type == libdis::op_expression && + case insn_string: + if (dest && dest->type == op_expression && dest->data.expression.base.id == bad_register_.id) flags_ |= DISX86_BAD_BLOCK_WRITE; - if (src && src->type == libdis::op_expression && + if (src && src->type == op_expression && src->data.expression.base.id == bad_register_.id) flags_ |= DISX86_BAD_BLOCK_READ; break; // Flag comparisons based on bad data. - case libdis::insn_comparison: - if ((dest && dest->type == libdis::op_expression && + case insn_comparison: + if ((dest && dest->type == op_expression && dest->data.expression.base.id == bad_register_.id) || - (src && src->type == libdis::op_expression && + (src && src->type == op_expression && src->data.expression.base.id == bad_register_.id) || - (dest && dest->type == libdis::op_register && + (dest && dest->type == op_register && dest->data.reg.id == bad_register_.id) || - (src && src->type == libdis::op_register && + (src && src->type == op_register && src->data.reg.id == bad_register_.id)) flags_ |= DISX86_BAD_COMPARISON; break; @@ -154,10 +154,10 @@ uint32_t DisassemblerX86::NextInstruction() { // Flag any other instruction which derefs a bad register for // src or dest. default: - if (dest && dest->type == libdis::op_expression && + if (dest && dest->type == op_expression && dest->data.expression.base.id == bad_register_.id) flags_ |= DISX86_BAD_WRITE; - if (src && src->type == libdis::op_expression && + if (src && src->type == op_expression && src->data.expression.base.id == bad_register_.id) flags_ |= DISX86_BAD_READ; break; @@ -166,14 +166,14 @@ uint32_t DisassemblerX86::NextInstruction() { // When a register is marked as tainted check if it is pushed. // TODO(cdn): may also want to check for MOVs into EBP offsets. - if (register_valid_ && dest && current_instr_.type == libdis::insn_push) { + if (register_valid_ && dest && current_instr_.type == insn_push) { switch (dest->type) { - case libdis::op_expression: + case op_expression: if (dest->data.expression.base.id == bad_register_.id || dest->data.expression.index.id == bad_register_.id) pushed_bad_value_ = true; break; - case libdis::op_register: + case op_register: if (dest->data.reg.id == bad_register_.id) pushed_bad_value_ = true; break; @@ -187,31 +187,31 @@ uint32_t DisassemblerX86::NextInstruction() { // there is a hit. if (register_valid_) { switch (current_instr_.type) { - case libdis::insn_xor: - if (src && src->type == libdis::op_register && - dest && dest->type == libdis::op_register && + case insn_xor: + if (src && src->type == op_register && + dest && dest->type == op_register && src->data.reg.id == bad_register_.id && src->data.reg.id == dest->data.reg.id) register_valid_ = false; break; - case libdis::insn_pop: - case libdis::insn_mov: - case libdis::insn_movcc: - if (dest && dest->type == libdis::op_register && + case insn_pop: + case insn_mov: + case insn_movcc: + if (dest && dest->type == op_register && dest->data.reg.id == bad_register_.id) register_valid_ = false; break; - case libdis::insn_popregs: + case insn_popregs: register_valid_ = false; break; - case libdis::insn_xchg: - case libdis::insn_xchgcc: - if (dest && dest->type == libdis::op_register && - src && src->type == libdis::op_register) { + case insn_xchg: + case insn_xchgcc: + if (dest && dest->type == op_register && + src && src->type == op_register) { if (dest->data.reg.id == bad_register_.id) - memcpy(&bad_register_, &src->data.reg, sizeof(libdis::x86_reg_t)); + memcpy(&bad_register_, &src->data.reg, sizeof(x86_reg_t)); else if (src->data.reg.id == bad_register_.id) - memcpy(&bad_register_, &dest->data.reg, sizeof(libdis::x86_reg_t)); + memcpy(&bad_register_, &dest->data.reg, sizeof(x86_reg_t)); } break; default: @@ -226,12 +226,12 @@ bool DisassemblerX86::setBadRead() { if (!instr_valid_) return false; - libdis::x86_op_t* operand = libdis::x86_get_src_operand(¤t_instr_); - if (!operand || operand->type != libdis::op_expression) + x86_op_t* operand = x86_get_src_operand(¤t_instr_); + if (!operand || operand->type != op_expression) return false; memcpy(&bad_register_, &operand->data.expression.base, - sizeof(libdis::x86_reg_t)); + sizeof(x86_reg_t)); register_valid_ = true; return true; } @@ -240,12 +240,12 @@ bool DisassemblerX86::setBadWrite() { if (!instr_valid_) return false; - libdis::x86_op_t* operand = libdis::x86_get_dest_operand(¤t_instr_); - if (!operand || operand->type != libdis::op_expression) + x86_op_t* operand = x86_get_dest_operand(¤t_instr_); + if (!operand || operand->type != op_expression) return false; memcpy(&bad_register_, &operand->data.expression.base, - sizeof(libdis::x86_reg_t)); + sizeof(x86_reg_t)); register_valid_ = true; return true; } diff --git a/src/processor/disassembler_x86.h b/src/processor/disassembler_x86.h index 493f7f2e7..4f3b6bf57 100644 --- a/src/processor/disassembler_x86.h +++ b/src/processor/disassembler_x86.h @@ -36,14 +36,10 @@ #ifndef GOOGLE_BREAKPAD_PROCESSOR_DISASSEMBLER_X86_H_ #define GOOGLE_BREAKPAD_PROCESSOR_DISASSEMBLER_X86_H_ -#include #include #include "google_breakpad/common/breakpad_types.h" - -namespace libdis { #include "third_party/libdisasm/libdis.h" -} namespace google_breakpad { @@ -78,12 +74,12 @@ class DisassemblerX86 { // Returns the current instruction as defined in libdis.h, // or NULL if the current instruction is not valid. - const libdis::x86_insn_t* currentInstruction() { - return instr_valid_ ? ¤t_instr_ : NULL; + const x86_insn_t* currentInstruction() { + return instr_valid_ ? ¤t_instr_ : nullptr; } // Returns the type of the current instruction as defined in libdis.h. - libdis::x86_insn_group currentInstructionGroup() { + x86_insn_group currentInstructionGroup() { return current_instr_.group; } @@ -109,12 +105,12 @@ class DisassemblerX86 { uint32_t current_inst_offset_; bool instr_valid_; - libdis::x86_insn_t current_instr_; + x86_insn_t current_instr_; // TODO(cdn): Maybe also track an expression's index register. // ex: mov eax, [ebx + ecx]; ebx is base, ecx is index. bool register_valid_; - libdis::x86_reg_t bad_register_; + x86_reg_t bad_register_; bool pushed_bad_value_; bool end_of_block_; diff --git a/src/processor/disassembler_x86_unittest.cc b/src/processor/disassembler_x86_unittest.cc index 18525b825..9bb57af88 100644 --- a/src/processor/disassembler_x86_unittest.cc +++ b/src/processor/disassembler_x86_unittest.cc @@ -88,13 +88,13 @@ TEST(DisassemblerX86Test, SimpleReturnInstruction) { EXPECT_TRUE(dis.currentInstructionValid()); EXPECT_EQ(0U, dis.flags()); EXPECT_TRUE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_controlflow, dis.currentInstructionGroup()); - const libdis::x86_insn_t* instruction = dis.currentInstruction(); - EXPECT_EQ(libdis::insn_controlflow, instruction->group); - EXPECT_EQ(libdis::insn_return, instruction->type); + EXPECT_EQ(insn_controlflow, dis.currentInstructionGroup()); + const x86_insn_t* instruction = dis.currentInstruction(); + EXPECT_EQ(insn_controlflow, instruction->group); + EXPECT_EQ(insn_return, instruction->type); EXPECT_EQ(0U, dis.NextInstruction()); EXPECT_FALSE(dis.currentInstructionValid()); - EXPECT_EQ(NULL, dis.currentInstruction()); + EXPECT_EQ(nullptr, dis.currentInstruction()); } TEST(DisassemblerX86Test, SimpleInvalidInstruction) { @@ -109,18 +109,18 @@ TEST(DisassemblerX86Test, BadReadLeadsToBranch) { EXPECT_TRUE(dis.currentInstructionValid()); EXPECT_EQ(0U, dis.flags()); EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup()); + EXPECT_EQ(insn_move, dis.currentInstructionGroup()); EXPECT_TRUE(dis.setBadRead()); EXPECT_EQ(2U, dis.NextInstruction()); EXPECT_TRUE(dis.currentInstructionValid()); EXPECT_EQ(0U, dis.flags()); EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_logic, dis.currentInstructionGroup()); + EXPECT_EQ(insn_logic, dis.currentInstructionGroup()); EXPECT_EQ(2U, dis.NextInstruction()); EXPECT_TRUE(dis.currentInstructionValid()); EXPECT_EQ(google_breakpad::DISX86_BAD_BRANCH_TARGET, dis.flags()); EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_controlflow, dis.currentInstructionGroup()); + EXPECT_EQ(insn_controlflow, dis.currentInstructionGroup()); } TEST(DisassemblerX86Test, BadWriteLeadsToPushedArg) { @@ -130,13 +130,13 @@ TEST(DisassemblerX86Test, BadWriteLeadsToPushedArg) { EXPECT_TRUE(dis.currentInstructionValid()); EXPECT_EQ(0U, dis.flags()); EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup()); + EXPECT_EQ(insn_move, dis.currentInstructionGroup()); EXPECT_TRUE(dis.setBadWrite()); EXPECT_EQ(3U, dis.NextInstruction()); EXPECT_TRUE(dis.currentInstructionValid()); EXPECT_EQ(0U, dis.flags()); EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_arithmetic, dis.currentInstructionGroup()); + EXPECT_EQ(insn_arithmetic, dis.currentInstructionGroup()); EXPECT_EQ(1U, dis.NextInstruction()); EXPECT_TRUE(dis.currentInstructionValid()); EXPECT_EQ(0U, dis.flags()); @@ -144,7 +144,7 @@ TEST(DisassemblerX86Test, BadWriteLeadsToPushedArg) { EXPECT_EQ(5U, dis.NextInstruction()); EXPECT_TRUE(dis.currentInstructionValid()); EXPECT_EQ(google_breakpad::DISX86_BAD_ARGUMENT_PASSED, dis.flags()); - EXPECT_EQ(libdis::insn_controlflow, dis.currentInstructionGroup()); + EXPECT_EQ(insn_controlflow, dis.currentInstructionGroup()); EXPECT_FALSE(dis.endOfBlock()); } @@ -155,18 +155,18 @@ TEST(DisassemblerX86Test, BadReadLeadsToBlockWrite) { EXPECT_TRUE(dis.currentInstructionValid()); EXPECT_EQ(0U, dis.flags()); EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup()); + EXPECT_EQ(insn_move, dis.currentInstructionGroup()); EXPECT_TRUE(dis.setBadRead()); EXPECT_EQ(2U, dis.NextInstruction()); EXPECT_TRUE(dis.currentInstructionValid()); EXPECT_EQ(0U, dis.flags()); EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup()); + EXPECT_EQ(insn_move, dis.currentInstructionGroup()); EXPECT_EQ(2U, dis.NextInstruction()); EXPECT_TRUE(dis.currentInstructionValid()); EXPECT_EQ(google_breakpad::DISX86_BAD_BLOCK_WRITE, dis.flags()); EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_string, dis.currentInstructionGroup()); + EXPECT_EQ(insn_string, dis.currentInstructionGroup()); } TEST(DisassemblerX86Test, BadReadClobberThenWrite) { @@ -175,18 +175,18 @@ TEST(DisassemblerX86Test, BadReadClobberThenWrite) { EXPECT_TRUE(dis.currentInstructionValid()); EXPECT_EQ(0U, dis.flags()); EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_arithmetic, dis.currentInstructionGroup()); + EXPECT_EQ(insn_arithmetic, dis.currentInstructionGroup()); EXPECT_TRUE(dis.setBadRead()); EXPECT_EQ(2U, dis.NextInstruction()); EXPECT_TRUE(dis.currentInstructionValid()); EXPECT_EQ(0U, dis.flags()); EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup()); + EXPECT_EQ(insn_move, dis.currentInstructionGroup()); EXPECT_EQ(2U, dis.NextInstruction()); EXPECT_TRUE(dis.currentInstructionValid()); EXPECT_EQ(0U, dis.flags()); EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup()); + EXPECT_EQ(insn_move, dis.currentInstructionGroup()); } TEST(DisassemblerX86Test, BadReadXCHGThenWrite) { @@ -195,23 +195,23 @@ TEST(DisassemblerX86Test, BadReadXCHGThenWrite) { EXPECT_TRUE(dis.currentInstructionValid()); EXPECT_EQ(0U, dis.flags()); EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_arithmetic, dis.currentInstructionGroup()); + EXPECT_EQ(insn_arithmetic, dis.currentInstructionGroup()); EXPECT_TRUE(dis.setBadRead()); EXPECT_EQ(1U, dis.NextInstruction()); EXPECT_TRUE(dis.currentInstructionValid()); EXPECT_EQ(0U, dis.flags()); EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup()); + EXPECT_EQ(insn_move, dis.currentInstructionGroup()); EXPECT_EQ(2U, dis.NextInstruction()); EXPECT_TRUE(dis.currentInstructionValid()); EXPECT_EQ(0U, dis.flags()); EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup()); + EXPECT_EQ(insn_move, dis.currentInstructionGroup()); EXPECT_EQ(2U, dis.NextInstruction()); EXPECT_TRUE(dis.currentInstructionValid()); EXPECT_EQ(google_breakpad::DISX86_BAD_WRITE, dis.flags()); EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup()); + EXPECT_EQ(insn_move, dis.currentInstructionGroup()); } TEST(DisassemblerX86Test, BadReadThenCMP) { @@ -220,17 +220,17 @@ TEST(DisassemblerX86Test, BadReadThenCMP) { EXPECT_TRUE(dis.currentInstructionValid()); EXPECT_EQ(0U, dis.flags()); EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_arithmetic, dis.currentInstructionGroup()); + EXPECT_EQ(insn_arithmetic, dis.currentInstructionGroup()); EXPECT_TRUE(dis.setBadRead()); EXPECT_EQ(3U, dis.NextInstruction()); EXPECT_TRUE(dis.currentInstructionValid()); EXPECT_EQ(google_breakpad::DISX86_BAD_COMPARISON, dis.flags()); EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_comparison, dis.currentInstructionGroup()); + EXPECT_EQ(insn_comparison, dis.currentInstructionGroup()); EXPECT_EQ(2U, dis.NextInstruction()); EXPECT_TRUE(dis.currentInstructionValid()); EXPECT_EQ(google_breakpad::DISX86_BAD_COMPARISON, dis.flags()); EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_controlflow, dis.currentInstructionGroup()); + EXPECT_EQ(insn_controlflow, dis.currentInstructionGroup()); } } diff --git a/src/processor/dump_context.cc b/src/processor/dump_context.cc index ab97930f9..372fee5ee 100644 --- a/src/processor/dump_context.cc +++ b/src/processor/dump_context.cc @@ -73,7 +73,7 @@ uint32_t DumpContext::GetContextFlags() const { const MDRawContextX86* DumpContext::GetContextX86() const { if (GetContextCPU() != MD_CONTEXT_X86) { BPLOG(ERROR) << "DumpContext cannot get x86 context"; - return NULL; + return nullptr; } return context_.x86; @@ -82,7 +82,7 @@ const MDRawContextX86* DumpContext::GetContextX86() const { const MDRawContextPPC* DumpContext::GetContextPPC() const { if (GetContextCPU() != MD_CONTEXT_PPC) { BPLOG(ERROR) << "DumpContext cannot get ppc context"; - return NULL; + return nullptr; } return context_.ppc; @@ -91,7 +91,7 @@ const MDRawContextPPC* DumpContext::GetContextPPC() const { const MDRawContextPPC64* DumpContext::GetContextPPC64() const { if (GetContextCPU() != MD_CONTEXT_PPC64) { BPLOG(ERROR) << "DumpContext cannot get ppc64 context"; - return NULL; + return nullptr; } return context_.ppc64; @@ -100,7 +100,7 @@ const MDRawContextPPC64* DumpContext::GetContextPPC64() const { const MDRawContextAMD64* DumpContext::GetContextAMD64() const { if (GetContextCPU() != MD_CONTEXT_AMD64) { BPLOG(ERROR) << "DumpContext cannot get amd64 context"; - return NULL; + return nullptr; } return context_.amd64; @@ -109,7 +109,7 @@ const MDRawContextAMD64* DumpContext::GetContextAMD64() const { const MDRawContextSPARC* DumpContext::GetContextSPARC() const { if (GetContextCPU() != MD_CONTEXT_SPARC) { BPLOG(ERROR) << "DumpContext cannot get sparc context"; - return NULL; + return nullptr; } return context_.ctx_sparc; @@ -118,7 +118,7 @@ const MDRawContextSPARC* DumpContext::GetContextSPARC() const { const MDRawContextARM* DumpContext::GetContextARM() const { if (GetContextCPU() != MD_CONTEXT_ARM) { BPLOG(ERROR) << "DumpContext cannot get arm context"; - return NULL; + return nullptr; } return context_.arm; @@ -127,7 +127,7 @@ const MDRawContextARM* DumpContext::GetContextARM() const { const MDRawContextARM64* DumpContext::GetContextARM64() const { if (GetContextCPU() != MD_CONTEXT_ARM64) { BPLOG(ERROR) << "DumpContext cannot get arm64 context"; - return NULL; + return nullptr; } return context_.arm64; @@ -137,7 +137,7 @@ const MDRawContextMIPS* DumpContext::GetContextMIPS() const { if ((GetContextCPU() != MD_CONTEXT_MIPS) && (GetContextCPU() != MD_CONTEXT_MIPS64)) { BPLOG(ERROR) << "DumpContext cannot get MIPS context"; - return NULL; + return nullptr; } return context_.ctx_mips; @@ -146,7 +146,7 @@ const MDRawContextMIPS* DumpContext::GetContextMIPS() const { const MDRawContextRISCV* DumpContext::GetContextRISCV() const { if (GetContextCPU() != MD_CONTEXT_RISCV) { BPLOG(ERROR) << "DumpContext cannot get RISCV context"; - return NULL; + return nullptr; } return context_.riscv; @@ -155,7 +155,7 @@ const MDRawContextRISCV* DumpContext::GetContextRISCV() const { const MDRawContextRISCV64* DumpContext::GetContextRISCV64() const { if (GetContextCPU() != MD_CONTEXT_RISCV64) { BPLOG(ERROR) << "DumpContext cannot get RISCV64 context"; - return NULL; + return nullptr; } return context_.riscv64; @@ -356,7 +356,7 @@ void DumpContext::FreeContext() { } context_flags_ = 0; - context_.base = NULL; + context_.base = nullptr; } void DumpContext::Print() { diff --git a/src/processor/exploitability.cc b/src/processor/exploitability.cc index 89064c9b1..5e1639c1e 100644 --- a/src/processor/exploitability.cc +++ b/src/processor/exploitability.cc @@ -37,9 +37,8 @@ #include // Must come first #endif -#include +#include -#include "common/scoped_ptr.h" #include "google_breakpad/processor/exploitability.h" #include "google_breakpad/processor/minidump.h" #include "google_breakpad/processor/process_state.h" @@ -68,15 +67,15 @@ Exploitability *Exploitability::ExploitabilityForPlatform( Minidump *dump, ProcessState *process_state, bool enable_objdump) { - Exploitability *platform_exploitability = NULL; + Exploitability *platform_exploitability = nullptr; MinidumpSystemInfo *minidump_system_info = dump->GetSystemInfo(); if (!minidump_system_info) - return NULL; + return nullptr; const MDRawSystemInfo *raw_system_info = minidump_system_info->system_info(); if (!raw_system_info) - return NULL; + return nullptr; switch (raw_system_info->platform_id) { case MD_OS_WIN32_NT: @@ -98,7 +97,7 @@ Exploitability *Exploitability::ExploitabilityForPlatform( case MD_OS_PS3: case MD_OS_FUCHSIA: default: { - platform_exploitability = NULL; + platform_exploitability = nullptr; break; } } diff --git a/src/processor/exploitability_linux.cc b/src/processor/exploitability_linux.cc index 76e78f45b..c8a5ca59c 100644 --- a/src/processor/exploitability_linux.cc +++ b/src/processor/exploitability_linux.cc @@ -104,12 +104,12 @@ ExploitabilityRating ExploitabilityLinux::CheckPlatformExploitability() { // Getting exception data. (It should exist for all minidumps.) MinidumpException* exception = dump_->GetException(); - if (exception == NULL) { + if (exception == nullptr) { BPLOG(INFO) << "No exception record."; return EXPLOITABILITY_ERR_PROCESSING; } const MDRawExceptionStream* raw_exception_stream = exception->exception(); - if (raw_exception_stream == NULL) { + if (raw_exception_stream == nullptr) { BPLOG(INFO) << "No raw exception stream."; return EXPLOITABILITY_ERR_PROCESSING; } @@ -125,7 +125,7 @@ ExploitabilityRating ExploitabilityLinux::CheckPlatformExploitability() { uint64_t stack_ptr = 0; const MinidumpContext* context = exception->GetContext(); - if (context == NULL) { + if (context == nullptr) { BPLOG(INFO) << "No exception context."; return EXPLOITABILITY_ERR_PROCESSING; } @@ -170,7 +170,7 @@ bool ExploitabilityLinux::EndedOnIllegalWrite(uint64_t instruction_ptr) { MinidumpMemoryList* memory_list = dump_->GetMemoryList(); MinidumpMemoryRegion* memory_region = memory_list ? - memory_list->GetMemoryRegionForAddress(instruction_ptr) : NULL; + memory_list->GetMemoryRegionForAddress(instruction_ptr) : nullptr; if (!memory_region) { BPLOG(INFO) << "No memory region around instruction pointer."; return false; @@ -273,7 +273,7 @@ bool ExploitabilityLinux::InstructionPointerInCode(uint64_t instruction_ptr) { MinidumpLinuxMapsList* linux_maps_list = dump_->GetLinuxMapsList(); const MinidumpLinuxMaps* linux_maps = linux_maps_list ? - linux_maps_list->GetLinuxMapsForAddress(instruction_ptr) : NULL; + linux_maps_list->GetLinuxMapsForAddress(instruction_ptr) : nullptr; return linux_maps ? linux_maps->IsExecutable() : false; } diff --git a/src/processor/exploitability_unittest.cc b/src/processor/exploitability_unittest.cc index 09e4690d5..aa7514ae2 100644 --- a/src/processor/exploitability_unittest.cc +++ b/src/processor/exploitability_unittest.cc @@ -51,7 +51,7 @@ namespace google_breakpad { class ExploitabilityLinuxTestMinidumpContext : public MinidumpContext { public: explicit ExploitabilityLinuxTestMinidumpContext( - const MDRawContextAMD64& context) : MinidumpContext(NULL) { + const MDRawContextAMD64& context) : MinidumpContext(nullptr) { valid_ = true; SetContextAMD64(new MDRawContextAMD64(context)); SetContextFlags(MD_CONTEXT_AMD64); diff --git a/src/processor/exploitability_win.cc b/src/processor/exploitability_win.cc index b94e87255..fb0a1c76c 100644 --- a/src/processor/exploitability_win.cc +++ b/src/processor/exploitability_win.cc @@ -41,7 +41,6 @@ #include "processor/exploitability_win.h" -#include "common/scoped_ptr.h" #include "google_breakpad/common/minidump_exception_win32.h" #include "google_breakpad/processor/minidump.h" #include "processor/disassembler_x86.h" @@ -227,10 +226,10 @@ ExploitabilityRating ExploitabilityWin::CheckPlatformExploitability() { // Check if the faulting instruction falls into one of // several interesting groups. switch (disassembler.currentInstructionGroup()) { - case libdis::insn_controlflow: + case insn_controlflow: exploitability_weight += kLargeBump; break; - case libdis::insn_string: + case insn_string: exploitability_weight += kHugeBump; break; default: diff --git a/src/processor/fast_source_line_resolver.cc b/src/processor/fast_source_line_resolver.cc index 79803f2ca..99fca9c76 100644 --- a/src/processor/fast_source_line_resolver.cc +++ b/src/processor/fast_source_line_resolver.cc @@ -41,15 +41,17 @@ #endif #include "google_breakpad/processor/fast_source_line_resolver.h" -#include "processor/fast_source_line_resolver_types.h" -#include +#include +#include + #include +#include #include #include -#include "common/scoped_ptr.h" #include "common/using_std_string.h" +#include "processor/fast_source_line_resolver_types.h" #include "processor/logging.h" #include "processor/module_factory.h" #include "processor/simple_serializer-inl.h" @@ -77,9 +79,9 @@ void FastSourceLineResolver::Module::LookupAddress( // extent of the PUBLIC symbol we find, below. This does mean we // need to check that address indeed falls within the function we // find; do the range comparison in an overflow-friendly way. - scoped_ptr func(new Function); + std::unique_ptr func(new Function); const Function* func_ptr = 0; - scoped_ptr public_symbol(new PublicSymbol); + std::unique_ptr public_symbol(new PublicSymbol); const PublicSymbol* public_symbol_ptr = 0; MemAddr function_base; MemAddr function_size; @@ -93,10 +95,10 @@ void FastSourceLineResolver::Module::LookupAddress( frame->function_base = frame->module->base_address() + function_base; frame->is_multiple = func->is_multiple; - scoped_ptr line(new Line); + std::unique_ptr line(new Line); const Line* line_ptr = 0; MemAddr line_base; - if (func->lines.RetrieveRange(address, line_ptr, &line_base, NULL)) { + if (func->lines.RetrieveRange(address, line_ptr, &line_base, nullptr)) { line->CopyFrom(line_ptr); FileMap::iterator it = files_.find(line->source_file_id); if (it != files_.end()) { @@ -131,13 +133,13 @@ void FastSourceLineResolver::Module::ConstructInlineFrames( } for (const char* inline_ptr : inline_ptrs) { - scoped_ptr in(new Inline); + std::unique_ptr in(new Inline); in->CopyFrom(inline_ptr); unique_ptr new_frame = unique_ptr(new StackFrame(*frame)); auto origin_iter = inline_origins_.find(in->origin_id); if (origin_iter != inline_origins_.end()) { - scoped_ptr origin(new InlineOrigin); + std::unique_ptr origin(new InlineOrigin); origin->CopyFrom(origin_iter.GetValuePtr()); new_frame->function_name = origin->name; } else { @@ -154,7 +156,7 @@ void FastSourceLineResolver::Module::ConstructInlineFrames( } } - // Use the starting adress of the inlined range as inlined function base. + // Use the starting address of the inlined range as inlined function base. new_frame->function_base = new_frame->module->base_address(); for (const auto& range : in->inline_ranges) { if (address >= range.first && address < range.first + range.second) { @@ -228,21 +230,21 @@ bool FastSourceLineResolver::Module::LoadMapFromMemory( const char* mem_buffer = memory_buffer; mem_buffer = SimpleSerializer::Read(mem_buffer, &is_corrupt_); - const uint32_t* map_sizes = reinterpret_cast(mem_buffer); + const uint64_t* map_sizes = reinterpret_cast(mem_buffer); - unsigned int header_size = kNumberMaps_ * sizeof(unsigned int); + unsigned int header_size = kNumberMaps_ * sizeof(uint64_t); // offsets[]: an array of offset addresses (with respect to mem_buffer), // for each "Static***Map" component of Module. // "Static***Map": static version of std::map or map wrapper, i.e., StaticMap, // StaticAddressMap, StaticContainedRangeMap, and StaticRangeMap. - unsigned int offsets[kNumberMaps_]; + uint64_t offsets[kNumberMaps_]; offsets[0] = header_size; for (int i = 1; i < kNumberMaps_; ++i) { offsets[i] = offsets[i - 1] + map_sizes[i - 1]; } - unsigned int expected_size = sizeof(bool) + offsets[kNumberMaps_ - 1] + - map_sizes[kNumberMaps_ - 1] + 1; + size_t expected_size = sizeof(bool) + offsets[kNumberMaps_ - 1] + + map_sizes[kNumberMaps_ - 1] + 1; if (expected_size != memory_buffer_size && // Allow for having an extra null terminator. expected_size != memory_buffer_size - 1) { @@ -277,7 +279,7 @@ bool FastSourceLineResolver::Module::LoadMapFromMemory( WindowsFrameInfo* FastSourceLineResolver::Module::FindWindowsFrameInfo( const StackFrame* frame) const { MemAddr address = frame->instruction - frame->module->base_address(); - scoped_ptr result(new WindowsFrameInfo()); + std::unique_ptr result(new WindowsFrameInfo()); // We only know about WindowsFrameInfo::STACK_INFO_FRAME_DATA and // WindowsFrameInfo::STACK_INFO_FPO. Prefer them in this order. @@ -301,7 +303,7 @@ WindowsFrameInfo* FastSourceLineResolver::Module::FindWindowsFrameInfo( // below. However, this does mean we need to check that ADDRESS // falls within the retrieved function's range; do the range // comparison in an overflow-friendly way. - scoped_ptr function(new Function); + std::unique_ptr function(new Function); const Function* function_ptr = 0; MemAddr function_base, function_size; if (functions_.RetrieveNearestRange(address, function_ptr, @@ -315,7 +317,7 @@ WindowsFrameInfo* FastSourceLineResolver::Module::FindWindowsFrameInfo( // PUBLIC symbols might have a parameter size. Use the function we // found above to limit the range the public symbol covers. - scoped_ptr public_symbol(new PublicSymbol); + std::unique_ptr public_symbol(new PublicSymbol); const PublicSymbol* public_symbol_ptr = 0; MemAddr public_address; if (public_symbols_.Retrieve(address, public_symbol_ptr, &public_address) && @@ -324,14 +326,14 @@ WindowsFrameInfo* FastSourceLineResolver::Module::FindWindowsFrameInfo( result->parameter_size = public_symbol->parameter_size; } - return NULL; + return nullptr; } CFIFrameInfo* FastSourceLineResolver::Module::FindCFIFrameInfo( const StackFrame* frame) const { MemAddr address = frame->instruction - frame->module->base_address(); MemAddr initial_base, initial_size; - const char* initial_rules = NULL; + const char* initial_rules = nullptr; // Find the initial rule whose range covers this address. That // provides an initial set of register recovery rules. Then, walk @@ -339,14 +341,14 @@ CFIFrameInfo* FastSourceLineResolver::Module::FindCFIFrameInfo( // instruction address, applying delta rules. if (!cfi_initial_rules_.RetrieveRange(address, initial_rules, &initial_base, &initial_size)) { - return NULL; + return nullptr; } // Create a frame info structure, and populate it with the rules from // the STACK CFI INIT record. - scoped_ptr rules(new CFIFrameInfo()); + std::unique_ptr rules(new CFIFrameInfo()); if (!ParseCFIRuleSet(initial_rules, rules.get())) - return NULL; + return nullptr; // Find the first delta rule that falls within the initial rule's range. StaticMap::iterator delta = diff --git a/src/processor/fast_source_line_resolver_types.h b/src/processor/fast_source_line_resolver_types.h index 75b9004f6..ae58d7525 100644 --- a/src/processor/fast_source_line_resolver_types.h +++ b/src/processor/fast_source_line_resolver_types.h @@ -36,7 +36,8 @@ #ifndef PROCESSOR_FAST_SOURCE_LINE_RESOLVER_TYPES_H__ #define PROCESSOR_FAST_SOURCE_LINE_RESOLVER_TYPES_H__ -#include +#include + #include #include @@ -107,7 +108,7 @@ struct FastSourceLineResolver::Inline : public SourceLineResolverBase::Inline { // De-serialize the memory data of a Inline. void CopyFrom(const char* raw) { - DESERIALIZE(raw, has_call_site_file_id); + raw = SimpleSerializer::Read(raw, &has_call_site_file_id); DESERIALIZE(raw, inline_nest_level); DESERIALIZE(raw, call_site_line); DESERIALIZE(raw, call_site_file_id); diff --git a/src/processor/fast_source_line_resolver_unittest.cc b/src/processor/fast_source_line_resolver_unittest.cc index 08340c15a..4baee92f1 100644 --- a/src/processor/fast_source_line_resolver_unittest.cc +++ b/src/processor/fast_source_line_resolver_unittest.cc @@ -43,6 +43,7 @@ #include #include +#include #include #include @@ -67,11 +68,10 @@ using google_breakpad::CodeModule; using google_breakpad::MemoryRegion; using google_breakpad::StackFrame; using google_breakpad::WindowsFrameInfo; -using google_breakpad::scoped_ptr; class TestCodeModule : public CodeModule { public: - explicit TestCodeModule(string code_file) : code_file_(code_file) {} + explicit TestCodeModule(const string& code_file) : code_file_(code_file) {} virtual ~TestCodeModule() {} virtual uint64_t base_address() const { return 0; } @@ -170,7 +170,7 @@ static bool VerifyEmpty(const StackFrame& frame) { static void ClearSourceLineInfo(StackFrame* frame) { frame->function_name.clear(); - frame->module = NULL; + frame->module = nullptr; frame->source_file_name.clear(); frame->source_line = 0; } @@ -215,10 +215,10 @@ TEST_F(TestFastSourceLineResolver, TestLoadAndResolve) { ASSERT_TRUE(fast_resolver.HasModule(&module2)); StackFrame frame; - scoped_ptr windows_frame_info; - scoped_ptr cfi_frame_info; + std::unique_ptr windows_frame_info; + std::unique_ptr cfi_frame_info; frame.instruction = 0x1000; - frame.module = NULL; + frame.module = nullptr; fast_resolver.FillSourceLineInfo(&frame, nullptr); ASSERT_FALSE(frame.module); ASSERT_TRUE(frame.function_name.empty()); diff --git a/src/processor/linked_ptr.h b/src/processor/linked_ptr.h index 5de49ee90..c67e36b25 100644 --- a/src/processor/linked_ptr.h +++ b/src/processor/linked_ptr.h @@ -97,7 +97,7 @@ class linked_ptr { // Take over ownership of a raw pointer. This should happen as soon as // possible after the object is created. - explicit linked_ptr(T* ptr = NULL) { capture(ptr); } + explicit linked_ptr(T* ptr = nullptr) { capture(ptr); } ~linked_ptr() { depart(); } // Copy an existing linked_ptr<>, adding ourselves to the list of references. @@ -120,7 +120,7 @@ class linked_ptr { } // Smart pointer members. - void reset(T* ptr = NULL) { depart(); capture(ptr); } + void reset(T* ptr = nullptr) { depart(); capture(ptr); } T* get() const { return value_; } T* operator->() const { return value_; } T& operator*() const { return *value_; } @@ -129,7 +129,7 @@ class linked_ptr { T* release() { link_.depart(); T* v = value_; - value_ = NULL; + value_ = nullptr; return v; } diff --git a/src/processor/logging.h b/src/processor/logging.h index 8c040837f..519c852f5 100644 --- a/src/processor/logging.h +++ b/src/processor/logging.h @@ -57,7 +57,9 @@ #define PROCESSOR_LOGGING_H__ #include +#include #include +#include #include "common/using_std_string.h" #include "google_breakpad/common/breakpad_types.h" @@ -119,9 +121,12 @@ class LogMessageVoidify { }; // Returns number formatted as a hexadecimal string, such as "0x7b". -string HexString(uint32_t number); -string HexString(uint64_t number); -string HexString(int number); +template +string HexString(T number) { + std::stringstream stream; + stream << "0x" << std::hex << number; + return stream.str(); +} // Returns the error code as set in the global errno variable, and sets // error_string, a required argument, to a string describing that error diff --git a/src/processor/map_serializers-inl.h b/src/processor/map_serializers-inl.h index 577b95f7b..e86ffe382 100644 --- a/src/processor/map_serializers-inl.h +++ b/src/processor/map_serializers-inl.h @@ -54,7 +54,7 @@ template size_t StdMapSerializer::SizeOf( const std::map& m) const { size_t size = 0; - size_t header_size = (1 + m.size()) * sizeof(uint32_t); + size_t header_size = (1 + m.size()) * sizeof(uint64_t); size += header_size; typename std::map::const_iterator iter; @@ -70,25 +70,25 @@ char* StdMapSerializer::Write(const std::map& m, char* dest) const { if (!dest) { BPLOG(ERROR) << "StdMapSerializer failed: write to NULL address."; - return NULL; + return nullptr; } char* start_address = dest; // Write header: // Number of nodes. - dest = SimpleSerializer::Write(m.size(), dest); + dest = SimpleSerializer::Write(m.size(), dest); // Nodes offsets. - uint32_t* offsets = reinterpret_cast(dest); - dest += sizeof(uint32_t) * m.size(); + uint64_t* offsets = reinterpret_cast(dest); + dest += sizeof(uint64_t) * m.size(); char* key_address = dest; dest += sizeof(Key) * m.size(); // Traverse map. typename std::map::const_iterator iter; - int index = 0; + int64_t index = 0; for (iter = m.begin(); iter != m.end(); ++iter, ++index) { - offsets[index] = static_cast(dest - start_address); + offsets[index] = static_cast(dest - start_address); key_address = key_serializer_.Write(iter->first, key_address); dest = value_serializer_.Write(iter->second, dest); } @@ -97,15 +97,15 @@ char* StdMapSerializer::Write(const std::map& m, template char* StdMapSerializer::Serialize( - const std::map& m, unsigned int* size) const { + const std::map& m, uint64_t* size) const { // Compute size of memory to be allocated. - unsigned int size_to_alloc = SizeOf(m); + uint64_t size_to_alloc = SizeOf(m); // Allocate memory. char* serialized_data = new char[size_to_alloc]; if (!serialized_data) { BPLOG(INFO) << "StdMapSerializer memory allocation failed."; if (size) *size = 0; - return NULL; + return nullptr; } // Write serialized data into memory. Write(m, serialized_data); @@ -118,7 +118,7 @@ template size_t RangeMapSerializer::SizeOf( const RangeMap& m) const { size_t size = 0; - size_t header_size = (1 + m.map_.size()) * sizeof(uint32_t); + size_t header_size = (1 + m.map_.size()) * sizeof(uint64_t); size += header_size; typename std::map::const_iterator iter; @@ -138,25 +138,25 @@ char* RangeMapSerializer::Write( const RangeMap& m, char* dest) const { if (!dest) { BPLOG(ERROR) << "RangeMapSerializer failed: write to NULL address."; - return NULL; + return nullptr; } char* start_address = dest; // Write header: // Number of nodes. - dest = SimpleSerializer::Write(m.map_.size(), dest); + dest = SimpleSerializer::Write(m.map_.size(), dest); // Nodes offsets. - uint32_t* offsets = reinterpret_cast(dest); - dest += sizeof(uint32_t) * m.map_.size(); + uint64_t* offsets = reinterpret_cast(dest); + dest += sizeof(uint64_t) * m.map_.size(); char* key_address = dest; dest += sizeof(Address) * m.map_.size(); // Traverse map. typename std::map::const_iterator iter; - int index = 0; + int64_t index = 0; for (iter = m.map_.begin(); iter != m.map_.end(); ++iter, ++index) { - offsets[index] = static_cast(dest - start_address); + offsets[index] = static_cast(dest - start_address); key_address = address_serializer_.Write(iter->first, key_address); dest = address_serializer_.Write(iter->second.base(), dest); dest = entry_serializer_.Write(iter->second.entry(), dest); @@ -166,15 +166,15 @@ char* RangeMapSerializer::Write( template char* RangeMapSerializer::Serialize( - const RangeMap& m, unsigned int* size) const { + const RangeMap& m, uint64_t* size) const { // Compute size of memory to be allocated. - unsigned int size_to_alloc = SizeOf(m); + uint64_t size_to_alloc = SizeOf(m); // Allocate memory. char* serialized_data = new char[size_to_alloc]; if (!serialized_data) { BPLOG(INFO) << "RangeMapSerializer memory allocation failed."; if (size) *size = 0; - return NULL; + return nullptr; } // Write serialized data into memory. @@ -191,12 +191,12 @@ size_t ContainedRangeMapSerializer::SizeOf( size_t size = 0; size_t header_size = addr_serializer_.SizeOf(m->base_) + entry_serializer_.SizeOf(m->entry_) - + sizeof(uint32_t); + + sizeof(uint64_t); size += header_size; // In case m.map_ == NULL, we treat it as an empty map: - size += sizeof(uint32_t); + size += sizeof(uint64_t); if (m->map_) { - size += m->map_->size() * sizeof(uint32_t); + size += m->map_->size() * sizeof(uint64_t); typename Map::const_iterator iter; for (iter = m->map_->begin(); iter != m->map_->end(); ++iter) { size += addr_serializer_.SizeOf(iter->first); @@ -212,30 +212,30 @@ char* ContainedRangeMapSerializer::Write( const ContainedRangeMap* m, char* dest) const { if (!dest) { BPLOG(ERROR) << "StdMapSerializer failed: write to NULL address."; - return NULL; + return nullptr; } dest = addr_serializer_.Write(m->base_, dest); - dest = SimpleSerializer::Write(entry_serializer_.SizeOf(m->entry_), + dest = SimpleSerializer::Write(entry_serializer_.SizeOf(m->entry_), dest); dest = entry_serializer_.Write(m->entry_, dest); // Write map<: char* map_address = dest; - if (m->map_ == NULL) { - dest = SimpleSerializer::Write(0, dest); + if (m->map_ == nullptr) { + dest = SimpleSerializer::Write(0, dest); } else { - dest = SimpleSerializer::Write(m->map_->size(), dest); - uint32_t* offsets = reinterpret_cast(dest); - dest += sizeof(uint32_t) * m->map_->size(); + dest = SimpleSerializer::Write(m->map_->size(), dest); + uint64_t* offsets = reinterpret_cast(dest); + dest += sizeof(uint64_t) * m->map_->size(); char* key_address = dest; dest += sizeof(AddrType) * m->map_->size(); // Traverse map. typename Map::const_iterator iter; - int index = 0; + int64_t index = 0; for (iter = m->map_->begin(); iter != m->map_->end(); ++iter, ++index) { - offsets[index] = static_cast(dest - map_address); + offsets[index] = static_cast(dest - map_address); key_address = addr_serializer_.Write(iter->first, key_address); // Recursively write. dest = Write(iter->second, dest); @@ -246,14 +246,14 @@ char* ContainedRangeMapSerializer::Write( template char* ContainedRangeMapSerializer::Serialize( - const ContainedRangeMap* m, unsigned int* size) const { - unsigned int size_to_alloc = SizeOf(m); + const ContainedRangeMap* m, uint64_t* size) const { + uint64_t size_to_alloc = SizeOf(m); // Allocating memory. char* serialized_data = new char[size_to_alloc]; if (!serialized_data) { BPLOG(INFO) << "ContainedRangeMapSerializer memory allocation failed."; if (size) *size = 0; - return NULL; + return nullptr; } Write(m, serialized_data); if (size) *size = size_to_alloc; diff --git a/src/processor/map_serializers.h b/src/processor/map_serializers.h index 54153f8a2..933ff6fde 100644 --- a/src/processor/map_serializers.h +++ b/src/processor/map_serializers.h @@ -65,7 +65,7 @@ class StdMapSerializer { // Returns a pointer to the serialized data. If size != NULL, *size is set // to the size of serialized data, i.e., SizeOf(m). // Caller has the ownership of memory allocated as "new char[]". - char* Serialize(const std::map& m, unsigned int* size) const; + char* Serialize(const std::map& m, uint64_t* size) const; private: SimpleSerializer key_serializer_; @@ -93,7 +93,7 @@ class AddressMapSerializer { // Returns a pointer to the serialized data. If size != NULL, *size is set // to the size of serialized data, i.e., SizeOf(m). // Caller has the ownership of memory allocated as "new char[]". - char* Serialize(const AddressMap& m, unsigned int* size) const { + char* Serialize(const AddressMap& m, uint64_t* size) const { return std_map_serializer_.Serialize(m.map_, size); } @@ -120,7 +120,7 @@ class RangeMapSerializer { // Returns a pointer to the serialized data. If size != NULL, *size is set // to the size of serialized data, i.e., SizeOf(m). // Caller has the ownership of memory allocated as "new char[]". - char* Serialize(const RangeMap& m, unsigned int* size) const; + char* Serialize(const RangeMap& m, uint64_t* size) const; private: // Convenient type name for Range. @@ -151,7 +151,7 @@ class ContainedRangeMapSerializer { // to the size of serialized data, i.e., SizeOf(m). // Caller has the ownership of memory allocated as "new char[]". char* Serialize(const ContainedRangeMap* m, - unsigned int* size) const; + uint64_t* size) const; private: // Convenient type name for the underlying map type. diff --git a/src/processor/map_serializers_unittest.cc b/src/processor/map_serializers_unittest.cc index cd31ddc83..2a421ef73 100644 --- a/src/processor/map_serializers_unittest.cc +++ b/src/processor/map_serializers_unittest.cc @@ -35,7 +35,11 @@ #include // Must come first #endif -#include +#include "map_serializers-inl.h" + +#include +#include + #include #include #include @@ -43,20 +47,18 @@ #include #include "breakpad_googletest_includes.h" -#include "map_serializers-inl.h" - #include "processor/address_map-inl.h" #include "processor/range_map-inl.h" #include "processor/contained_range_map-inl.h" -typedef int32_t AddrType; -typedef int32_t EntryType; +typedef int64_t AddrType; +typedef int64_t EntryType; class TestStdMapSerializer : public ::testing::Test { protected: void SetUp() { serialized_size_ = 0; - serialized_data_ = NULL; + serialized_data_ = nullptr; } void TearDown() { @@ -65,13 +67,13 @@ class TestStdMapSerializer : public ::testing::Test { std::map std_map_; google_breakpad::StdMapSerializer serializer_; - uint32_t serialized_size_; + uint64_t serialized_size_; char* serialized_data_; }; TEST_F(TestStdMapSerializer, EmptyMapTestCase) { - const int32_t correct_data[] = { 0 }; - uint32_t correct_size = sizeof(correct_data); + const int64_t correct_data[] = { 0 }; + uint64_t correct_size = sizeof(correct_data); // std_map_ is empty. serialized_data_ = serializer_.Serialize(std_map_, &serialized_size_); @@ -81,17 +83,17 @@ TEST_F(TestStdMapSerializer, EmptyMapTestCase) { } TEST_F(TestStdMapSerializer, MapWithTwoElementsTestCase) { - const int32_t correct_data[] = { + const int64_t correct_data[] = { // # of nodes 2, // Offsets - 20, 24, + 40, 48, // Keys 1, 3, // Values 2, 6 }; - uint32_t correct_size = sizeof(correct_data); + uint64_t correct_size = sizeof(correct_data); std_map_.insert(std::make_pair(1, 2)); std_map_.insert(std::make_pair(3, 6)); @@ -103,17 +105,17 @@ TEST_F(TestStdMapSerializer, MapWithTwoElementsTestCase) { } TEST_F(TestStdMapSerializer, MapWithFiveElementsTestCase) { - const int32_t correct_data[] = { + const int64_t correct_data[] = { // # of nodes 5, // Offsets - 44, 48, 52, 56, 60, + 88, 96, 104, 112, 120, // Keys 1, 2, 3, 4, 5, // Values 11, 12, 13, 14, 15 }; - uint32_t correct_size = sizeof(correct_data); + uint64_t correct_size = sizeof(correct_data); for (int i = 1; i < 6; ++i) std_map_.insert(std::make_pair(i, 10 + i)); @@ -137,13 +139,13 @@ class TestAddressMapSerializer : public ::testing::Test { google_breakpad::AddressMap address_map_; google_breakpad::AddressMapSerializer serializer_; - uint32_t serialized_size_; + uint64_t serialized_size_; char* serialized_data_; }; TEST_F(TestAddressMapSerializer, EmptyMapTestCase) { - const int32_t correct_data[] = { 0 }; - uint32_t correct_size = sizeof(correct_data); + const int64_t correct_data[] = { 0 }; + uint64_t correct_size = sizeof(correct_data); // std_map_ is empty. serialized_data_ = serializer_.Serialize(address_map_, &serialized_size_); @@ -153,17 +155,17 @@ TEST_F(TestAddressMapSerializer, EmptyMapTestCase) { } TEST_F(TestAddressMapSerializer, MapWithTwoElementsTestCase) { - const int32_t correct_data[] = { + const int64_t correct_data[] = { // # of nodes 2, // Offsets - 20, 24, + 40, 48, // Keys 1, 3, // Values 2, 6 }; - uint32_t correct_size = sizeof(correct_data); + uint64_t correct_size = sizeof(correct_data); address_map_.Store(1, 2); address_map_.Store(3, 6); @@ -175,17 +177,17 @@ TEST_F(TestAddressMapSerializer, MapWithTwoElementsTestCase) { } TEST_F(TestAddressMapSerializer, MapWithFourElementsTestCase) { - const int32_t correct_data[] = { + const int64_t correct_data[] = { // # of nodes 4, // Offsets - 36, 40, 44, 48, + 72, 80, 88, 96, // Keys -6, -4, 8, 123, // Values 2, 3, 5, 8 }; - uint32_t correct_size = sizeof(correct_data); + uint64_t correct_size = sizeof(correct_data); address_map_.Store(-6, 2); address_map_.Store(-4, 3); @@ -212,13 +214,13 @@ class TestRangeMapSerializer : public ::testing::Test { google_breakpad::RangeMap range_map_; google_breakpad::RangeMapSerializer serializer_; - uint32_t serialized_size_; + uint64_t serialized_size_; char* serialized_data_; }; TEST_F(TestRangeMapSerializer, EmptyMapTestCase) { - const int32_t correct_data[] = { 0 }; - uint32_t correct_size = sizeof(correct_data); + const int64_t correct_data[] = { 0 }; + uint64_t correct_size = sizeof(correct_data); // range_map_ is empty. serialized_data_ = serializer_.Serialize(range_map_, &serialized_size_); @@ -228,17 +230,17 @@ TEST_F(TestRangeMapSerializer, EmptyMapTestCase) { } TEST_F(TestRangeMapSerializer, MapWithOneRangeTestCase) { - const int32_t correct_data[] = { + const int64_t correct_data[] = { // # of nodes 1, // Offsets - 12, + 24, // Keys: high address 10, // Values: (low address, entry) pairs 1, 6 }; - uint32_t correct_size = sizeof(correct_data); + uint64_t correct_size = sizeof(correct_data); range_map_.StoreRange(1, 10, 6); @@ -249,17 +251,17 @@ TEST_F(TestRangeMapSerializer, MapWithOneRangeTestCase) { } TEST_F(TestRangeMapSerializer, MapWithThreeRangesTestCase) { - const int32_t correct_data[] = { + const int64_t correct_data[] = { // # of nodes 3, // Offsets - 28, 36, 44, + 56, 72, 88, // Keys: high address - 5, 9, 20, + 5, 9, 20, // Values: (low address, entry) pairs - 2, 1, 6, 2, 10, 3 + 2, 1, 6, 2, 10, 3 }; - uint32_t correct_size = sizeof(correct_data); + uint64_t correct_size = sizeof(correct_data); ASSERT_TRUE(range_map_.StoreRange(2, 4, 1)); ASSERT_TRUE(range_map_.StoreRange(6, 4, 2)); @@ -285,18 +287,18 @@ class TestContainedRangeMapSerializer : public ::testing::Test { google_breakpad::ContainedRangeMap crm_map_; google_breakpad::ContainedRangeMapSerializer serializer_; - uint32_t serialized_size_; + uint64_t serialized_size_; char* serialized_data_; }; TEST_F(TestContainedRangeMapSerializer, EmptyMapTestCase) { - const int32_t correct_data[] = { + const int64_t correct_data[] = { 0, // base address of root - 4, // size of entry + 8, // size of entry 0, // entry stored at root 0 // empty map stored at root }; - uint32_t correct_size = sizeof(correct_data); + uint64_t correct_size = sizeof(correct_data); // crm_map_ is empty. serialized_data_ = serializer_.Serialize(&crm_map_, &serialized_size_); @@ -306,21 +308,21 @@ TEST_F(TestContainedRangeMapSerializer, EmptyMapTestCase) { } TEST_F(TestContainedRangeMapSerializer, MapWithOneRangeTestCase) { - const int32_t correct_data[] = { + const int64_t correct_data[] = { 0, // base address of root - 4, // size of entry + 8, // size of entry 0, // entry stored at root // Map stored at root node: 1, // # of nodes - 12, // offset + 24, // offset 9, // key // value: a child ContainedRangeMap 3, // base address of child CRM - 4, // size of entry + 8, // size of entry -1, // entry stored in child CRM 0 // empty sub-map stored in child CRM }; - uint32_t correct_size = sizeof(correct_data); + uint64_t correct_size = sizeof(correct_data); crm_map_.StoreRange(3, 7, -1); @@ -342,27 +344,27 @@ TEST_F(TestContainedRangeMapSerializer, MapWithTwoLevelsTestCase) { // / \ | // 3~4 6~7 16-20 level 2: grandchild1, grandchild2, grandchild3 - const int32_t correct_data[] = { + const int64_t correct_data[] = { // root: base, entry_size, entry - 0, 4, 0, + 0, 8, 0, // root's map: # of nodes, offset1, offset2, key1, key2 - 2, 20, 84, 8, 20, + 2, 40, 168, 8, 20, // child1: base, entry_size, entry: - 2, 4, -1, + 2, 8, -1, // child1's map: # of nodes, offset1, offset2, key1, key2 - 2, 20, 36, 4, 7, + 2, 40, 72, 4, 7, // grandchild1: base, entry_size, entry, empty_map - 3, 4, -1, 0, + 3, 8, -1, 0, // grandchild2: base, entry_size, entry, empty_map - 6, 4, -1, 0, + 6, 8, -1, 0, // child2: base, entry_size, entry: - 10, 4, -1, + 10, 8, -1, // child2's map: # of nodes, offset1, key1 - 1, 12, 20, + 1, 24, 20, // grandchild3: base, entry_size, entry, empty_map - 16, 4, -1, 0 + 16, 8, -1, 0 }; - uint32_t correct_size = sizeof(correct_data); + uint64_t correct_size = sizeof(correct_data); // Store child1. ASSERT_TRUE(crm_map_.StoreRange(2, 7, -1)); diff --git a/src/processor/microdump.cc b/src/processor/microdump.cc index 94d2c200a..ec2314570 100644 --- a/src/processor/microdump.cc +++ b/src/processor/microdump.cc @@ -36,6 +36,7 @@ #include "google_breakpad/processor/microdump.h" +#include #include #include diff --git a/src/processor/microdump_processor.cc b/src/processor/microdump_processor.cc index 3c25d5cf0..a38f199e2 100644 --- a/src/processor/microdump_processor.cc +++ b/src/processor/microdump_processor.cc @@ -38,6 +38,7 @@ #include +#include #include #include "common/using_std_string.h" @@ -64,16 +65,16 @@ ProcessResult MicrodumpProcessor::Process(Microdump *microdump, process_state->Clear(); process_state->modules_ = microdump->GetModules()->Copy(); - scoped_ptr stackwalker( + std::unique_ptr stackwalker( Stackwalker::StackwalkerForCPU( &process_state->system_info_, microdump->GetContext(), microdump->GetMemory(), process_state->modules_, - /* unloaded_modules= */ NULL, + /* unloaded_modules= */ nullptr, frame_symbolizer_)); - scoped_ptr stack(new CallStack()); + std::unique_ptr stack(new CallStack()); if (stackwalker.get()) { if (!stackwalker->Walk(stack.get(), &process_state->modules_without_symbols_, diff --git a/src/processor/microdump_processor_unittest.cc b/src/processor/microdump_processor_unittest.cc index 47f5e35ec..5379def8d 100644 --- a/src/processor/microdump_processor_unittest.cc +++ b/src/processor/microdump_processor_unittest.cc @@ -32,6 +32,8 @@ #include // Must come first #endif +#include + #include #include #include diff --git a/src/processor/microdump_stackwalk.cc b/src/processor/microdump_stackwalk.cc index 222310f76..585c40c93 100644 --- a/src/processor/microdump_stackwalk.cc +++ b/src/processor/microdump_stackwalk.cc @@ -38,11 +38,11 @@ #include #include +#include #include #include #include "common/path_helper.h" -#include "common/scoped_ptr.h" #include "common/using_std_string.h" #include "google_breakpad/processor/basic_source_line_resolver.h" #include "google_breakpad/processor/microdump.h" @@ -69,7 +69,6 @@ using google_breakpad::Microdump; using google_breakpad::MicrodumpProcessor; using google_breakpad::ProcessResult; using google_breakpad::ProcessState; -using google_breakpad::scoped_ptr; using google_breakpad::SimpleSymbolSupplier; using google_breakpad::StackFrameSymbolizer; @@ -96,7 +95,7 @@ int PrintMicrodumpProcess(const Options& options) { file_stream.read(&bytes[0], bytes.size()); string microdump_content(&bytes[0], bytes.size()); - scoped_ptr symbol_supplier; + std::unique_ptr symbol_supplier; if (!options.symbol_paths.empty()) { symbol_supplier.reset(new SimpleSymbolSupplier(options.symbol_paths)); } diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc index 83f72b97b..43db2a20e 100644 --- a/src/processor/minidump.cc +++ b/src/processor/minidump.cc @@ -32,6 +32,11 @@ // // Author: Mark Mentovai +// For PRI* macros, before anything else might #include it. +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif /* __STDC_FORMAT_MACROS */ + #ifdef HAVE_CONFIG_H #include // Must come first #endif @@ -42,6 +47,7 @@ #include #include #include +#include #include #include @@ -54,10 +60,9 @@ #include #include #include +#include #include -#include "processor/range_map-inl.h" - #include "common/macros.h" #include "common/scoped_ptr.h" #include "common/stdio_wrapper.h" @@ -66,6 +71,7 @@ #include "processor/basic_code_modules.h" #include "processor/convert_old_arm64_context.h" #include "processor/logging.h" +#include "processor/range_map-inl.h" namespace google_breakpad { @@ -253,7 +259,7 @@ inline void Swap(uint16_t* data, size_t size_in_bytes) { // CPU's endianness into consideration. It doesn't seems worth the trouble // of making it a dependency when we don't care about anything but UTF-16. string* UTF16ToUTF8(const vector& in, bool swap) { - scoped_ptr out(new string()); + std::unique_ptr out(new string()); // Set the string's initial capacity to the number of UTF-16 characters, // because the UTF-8 representation will always be at least this long. @@ -273,14 +279,14 @@ string* UTF16ToUTF8(const vector& in, bool swap) { if (in_word >= 0xdc00 && in_word <= 0xdcff) { BPLOG(ERROR) << "UTF16ToUTF8 found low surrogate " << HexString(in_word) << " without high"; - return NULL; + return nullptr; } else if (in_word >= 0xd800 && in_word <= 0xdbff) { // High surrogate. unichar = (in_word - 0xd7c0) << 10; if (++iterator == in.end()) { BPLOG(ERROR) << "UTF16ToUTF8 found high surrogate " << HexString(in_word) << " at end of string"; - return NULL; + return nullptr; } uint32_t high_word = in_word; in_word = *iterator; @@ -288,7 +294,7 @@ string* UTF16ToUTF8(const vector& in, bool swap) { BPLOG(ERROR) << "UTF16ToUTF8 found high surrogate " << HexString(high_word) << " without low " << HexString(in_word); - return NULL; + return nullptr; } unichar |= in_word & 0x03ff; } else { @@ -316,7 +322,7 @@ string* UTF16ToUTF8(const vector& in, bool swap) { } else { BPLOG(ERROR) << "UTF16ToUTF8 cannot represent high value " << HexString(unichar) << " in UTF-8"; - return NULL; + return nullptr; } } @@ -357,7 +363,7 @@ void ConvertUTF16BufferToUTF8String(const uint16_t* utf16_data, size_t byte_length = word_length * sizeof(utf16_data[0]); vector utf16_vector(word_length); memcpy(&utf16_vector[0], &utf16_data[0], byte_length); - scoped_ptr temp(UTF16ToUTF8(utf16_vector, swap)); + std::unique_ptr temp(UTF16ToUTF8(utf16_vector, swap)); if (temp.get()) { utf8_result->assign(*temp); } @@ -501,7 +507,7 @@ bool MinidumpContext::Read(uint32_t expected_size) { expected_size >= sizeof(MDRawContextAMD64))) { BPLOG(INFO) << "MinidumpContext: looks like AMD64 context"; - scoped_ptr context_amd64(new MDRawContextAMD64()); + std::unique_ptr context_amd64(new MDRawContextAMD64()); if (!minidump_->ReadBytes(context_amd64.get(), sizeof(MDRawContextAMD64))) { BPLOG(ERROR) << "MinidumpContext could not read amd64 context"; @@ -623,7 +629,7 @@ bool MinidumpContext::Read(uint32_t expected_size) { Swap(&context_flags); uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK; - scoped_ptr context_ppc64(new MDRawContextPPC64()); + std::unique_ptr context_ppc64(new MDRawContextPPC64()); if (cpu_type == 0) { if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) { @@ -719,7 +725,7 @@ bool MinidumpContext::Read(uint32_t expected_size) { if (minidump_->swap()) Swap(&context_flags); - scoped_ptr context_arm64(new MDRawContextARM64_Old()); + std::unique_ptr context_arm64(new MDRawContextARM64_Old()); uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK; if (cpu_type == 0) { @@ -778,7 +784,7 @@ bool MinidumpContext::Read(uint32_t expected_size) { } } - scoped_ptr new_context(new MDRawContextARM64()); + std::unique_ptr new_context(new MDRawContextARM64()); ConvertOldARM64Context(*context_arm64.get(), new_context.get()); SetContextFlags(new_context->context_flags); SetContextARM64(new_context.release()); @@ -817,12 +823,22 @@ bool MinidumpContext::Read(uint32_t expected_size) { switch (cpu_type) { case MD_CONTEXT_X86: { if (expected_size != sizeof(MDRawContextX86)) { - BPLOG(ERROR) << "MinidumpContext x86 size mismatch, " << - expected_size << " != " << sizeof(MDRawContextX86); - return false; + // Context may include xsave registers and so be larger than + // sizeof(MDRawContextX86). For now we skip this extended data. + if (context_flags & MD_CONTEXT_X86_XSTATE) { + int64_t bytes_left = expected_size - sizeof(MDRawContextX86); + if (bytes_left > kMaxXSaveAreaSize) { + BPLOG(ERROR) << "MinidumpContext oversized xstate area"; + return false; + } + } else { + BPLOG(ERROR) << "MinidumpContext x86 size mismatch, " + << expected_size << " != " << sizeof(MDRawContextX86); + return false; + } } - scoped_ptr context_x86(new MDRawContextX86()); + std::unique_ptr context_x86(new MDRawContextX86()); // Set the context_flags member, which has already been read, and // read the rest of the structure beginning with the first member @@ -885,6 +901,16 @@ bool MinidumpContext::Read(uint32_t expected_size) { SetContextX86(context_x86.release()); + // Skip extended xstate data if present in X86 context. + if (context_flags & MD_CONTEXT_X86_XSTATE) { + if (!minidump_->SeekSet( + (minidump_->Tell() - sizeof(MDRawContextX86)) + + expected_size)) { + BPLOG(ERROR) << "MinidumpContext cannot seek to past xstate data"; + return false; + } + } + break; } @@ -895,7 +921,7 @@ bool MinidumpContext::Read(uint32_t expected_size) { return false; } - scoped_ptr context_ppc(new MDRawContextPPC()); + std::unique_ptr context_ppc(new MDRawContextPPC()); // Set the context_flags member, which has already been read, and // read the rest of the structure beginning with the first member @@ -971,7 +997,7 @@ bool MinidumpContext::Read(uint32_t expected_size) { return false; } - scoped_ptr context_sparc(new MDRawContextSPARC()); + std::unique_ptr context_sparc(new MDRawContextSPARC()); // Set the context_flags member, which has already been read, and // read the rest of the structure beginning with the first member @@ -1027,7 +1053,7 @@ bool MinidumpContext::Read(uint32_t expected_size) { return false; } - scoped_ptr context_arm(new MDRawContextARM()); + std::unique_ptr context_arm(new MDRawContextARM()); // Set the context_flags member, which has already been read, and // read the rest of the structure beginning with the first member @@ -1082,7 +1108,7 @@ bool MinidumpContext::Read(uint32_t expected_size) { return false; } - scoped_ptr context_arm64(new MDRawContextARM64()); + std::unique_ptr context_arm64(new MDRawContextARM64()); // Set the context_flags member, which has already been read, and // read the rest of the structure beginning with the first member @@ -1137,7 +1163,7 @@ bool MinidumpContext::Read(uint32_t expected_size) { return false; } - scoped_ptr context_mips(new MDRawContextMIPS()); + std::unique_ptr context_mips(new MDRawContextMIPS()); // Set the context_flags member, which has already been read, and // read the rest of the structure beginning with the first member @@ -1202,7 +1228,7 @@ bool MinidumpContext::Read(uint32_t expected_size) { return false; } - scoped_ptr context_riscv(new MDRawContextRISCV()); + std::unique_ptr context_riscv(new MDRawContextRISCV()); // Set the context_flags member, which has already been read, and // read the rest of the structure beginning with the first member @@ -1279,7 +1305,7 @@ bool MinidumpContext::Read(uint32_t expected_size) { return false; } - scoped_ptr context_riscv64( + std::unique_ptr context_riscv64( new MDRawContextRISCV64()); // Set the context_flags member, which has already been read, and @@ -1471,8 +1497,8 @@ uint32_t MinidumpMemoryRegion::max_bytes_ = 64 * 1024 * 1024; // 64MB MinidumpMemoryRegion::MinidumpMemoryRegion(Minidump* minidump) : MinidumpObject(minidump), - descriptor_(NULL), - memory_(NULL) { + descriptor_(nullptr), + memory_(nullptr) { hexdump_width_ = minidump_ ? minidump_->HexdumpMode() : 0; hexdump_ = hexdump_width_ != 0; } @@ -1495,33 +1521,33 @@ void MinidumpMemoryRegion::SetDescriptor(MDMemoryDescriptor* descriptor) { const uint8_t* MinidumpMemoryRegion::GetMemory() const { if (!valid_) { BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetMemory"; - return NULL; + return nullptr; } if (!memory_) { if (descriptor_->memory.data_size == 0) { BPLOG(ERROR) << "MinidumpMemoryRegion is empty"; - return NULL; + return nullptr; } if (!minidump_->SeekSet(descriptor_->memory.rva)) { BPLOG(ERROR) << "MinidumpMemoryRegion could not seek to memory region"; - return NULL; + return nullptr; } if (descriptor_->memory.data_size > max_bytes_) { BPLOG(ERROR) << "MinidumpMemoryRegion size " << descriptor_->memory.data_size << " exceeds maximum " << max_bytes_; - return NULL; + return nullptr; } - scoped_ptr< vector > memory( + std::unique_ptr< vector > memory( new vector(descriptor_->memory.data_size)); if (!minidump_->ReadBytes(&(*memory)[0], descriptor_->memory.data_size)) { BPLOG(ERROR) << "MinidumpMemoryRegion could not read memory region"; - return NULL; + return nullptr; } memory_ = memory.release(); @@ -1553,7 +1579,7 @@ uint32_t MinidumpMemoryRegion::GetSize() const { void MinidumpMemoryRegion::FreeMemory() { delete memory_; - memory_ = NULL; + memory_ = nullptr; } @@ -1712,8 +1738,8 @@ void MinidumpMemoryRegion::SetPrintMode(bool hexdump, MinidumpThread::MinidumpThread(Minidump* minidump) : MinidumpObject(minidump), thread_(), - memory_(NULL), - context_(NULL) { + memory_(nullptr), + context_(nullptr) { } @@ -1726,9 +1752,9 @@ MinidumpThread::~MinidumpThread() { bool MinidumpThread::Read() { // Invalidate cached data. delete memory_; - memory_ = NULL; + memory_ = nullptr; delete context_; - context_ = NULL; + context_ = nullptr; valid_ = false; @@ -1778,7 +1804,7 @@ uint64_t MinidumpThread::GetStartOfStackMemoryRange() const { MinidumpMemoryRegion* MinidumpThread::GetMemory() { if (!valid_) { BPLOG(ERROR) << "Invalid MinidumpThread for GetMemory"; - return NULL; + return nullptr; } return memory_; @@ -1788,20 +1814,20 @@ MinidumpMemoryRegion* MinidumpThread::GetMemory() { MinidumpContext* MinidumpThread::GetContext() { if (!valid_) { BPLOG(ERROR) << "Invalid MinidumpThread for GetContext"; - return NULL; + return nullptr; } if (!context_) { if (!minidump_->SeekSet(thread_.thread_context.rva)) { BPLOG(ERROR) << "MinidumpThread cannot seek to context"; - return NULL; + return nullptr; } - scoped_ptr context(new MinidumpContext(minidump_)); + std::unique_ptr context(new MinidumpContext(minidump_)); if (!context->Read(thread_.thread_context.data_size)) { BPLOG(ERROR) << "MinidumpThread cannot read context"; - return NULL; + return nullptr; } context_ = context.release(); @@ -1880,7 +1906,7 @@ uint32_t MinidumpThreadList::max_threads_ = 4096; MinidumpThreadList::MinidumpThreadList(Minidump* minidump) : MinidumpStream(minidump), id_to_thread_map_(), - threads_(NULL), + threads_(nullptr), thread_count_(0) { } @@ -1894,7 +1920,7 @@ bool MinidumpThreadList::Read(uint32_t expected_size) { // Invalidate cached data. id_to_thread_map_.clear(); delete threads_; - threads_ = NULL; + threads_ = nullptr; thread_count_ = 0; valid_ = false; @@ -1946,7 +1972,7 @@ bool MinidumpThreadList::Read(uint32_t expected_size) { } if (thread_count != 0) { - scoped_ptr threads( + std::unique_ptr threads( new MinidumpThreads(thread_count, MinidumpThread(minidump_))); for (unsigned int thread_index = 0; @@ -1992,13 +2018,13 @@ MinidumpThread* MinidumpThreadList::GetThreadAtIndex(unsigned int index) const { if (!valid_) { BPLOG(ERROR) << "Invalid MinidumpThreadList for GetThreadAtIndex"; - return NULL; + return nullptr; } if (index >= thread_count_) { BPLOG(ERROR) << "MinidumpThreadList index out of range: " << index << "/" << thread_count_; - return NULL; + return nullptr; } return &(*threads_)[index]; @@ -2039,7 +2065,7 @@ MinidumpThreadName::MinidumpThreadName(Minidump* minidump) : MinidumpObject(minidump), thread_name_valid_(false), thread_name_(), - name_(NULL) {} + name_(nullptr) {} MinidumpThreadName::~MinidumpThreadName() { delete name_; @@ -2048,7 +2074,7 @@ MinidumpThreadName::~MinidumpThreadName() { bool MinidumpThreadName::Read() { // Invalidate cached data. delete name_; - name_ = NULL; + name_ = nullptr; valid_ = false; @@ -2135,7 +2161,7 @@ void MinidumpThreadName::Print() { // MinidumpThreadNameList::MinidumpThreadNameList(Minidump* minidump) - : MinidumpStream(minidump), thread_names_(NULL), thread_name_count_(0) {} + : MinidumpStream(minidump), thread_names_(nullptr), thread_name_count_(0) {} MinidumpThreadNameList::~MinidumpThreadNameList() { delete thread_names_; @@ -2144,7 +2170,7 @@ MinidumpThreadNameList::~MinidumpThreadNameList() { bool MinidumpThreadNameList::Read(uint32_t expected_size) { // Invalidate cached data. delete thread_names_; - thread_names_ = NULL; + thread_names_ = nullptr; thread_name_count_ = 0; valid_ = false; @@ -2186,7 +2212,7 @@ bool MinidumpThreadNameList::Read(uint32_t expected_size) { } if (thread_name_count != 0) { - scoped_ptr thread_names(new MinidumpThreadNames( + std::unique_ptr thread_names(new MinidumpThreadNames( thread_name_count, MinidumpThreadName(minidump_))); for (unsigned int thread_name_index = 0; @@ -2225,13 +2251,13 @@ MinidumpThreadName* MinidumpThreadNameList::GetThreadNameAtIndex( unsigned int index) const { if (!valid_) { BPLOG(ERROR) << "Invalid MinidumpThreadNameList for GetThreadNameAtIndex"; - return NULL; + return nullptr; } if (index >= thread_name_count_) { BPLOG(ERROR) << "MinidumpThreadNameList index out of range: " << index << "/" << thread_name_count_; - return NULL; + return nullptr; } return &(*thread_names_)[index]; @@ -2269,10 +2295,10 @@ MinidumpModule::MinidumpModule(Minidump* minidump) module_valid_(false), has_debug_info_(false), module_(), - name_(NULL), - cv_record_(NULL), + name_(nullptr), + cv_record_(nullptr), cv_record_signature_(MD_CVINFOUNKNOWN_SIGNATURE), - misc_record_(NULL) { + misc_record_(nullptr) { } @@ -2286,12 +2312,12 @@ MinidumpModule::~MinidumpModule() { bool MinidumpModule::Read() { // Invalidate cached data. delete name_; - name_ = NULL; + name_ = nullptr; delete cv_record_; - cv_record_ = NULL; + cv_record_ = nullptr; cv_record_signature_ = MD_CVINFOUNKNOWN_SIGNATURE; delete misc_record_; - misc_record_ = NULL; + misc_record_ = nullptr; module_valid_ = false; has_debug_info_ = false; @@ -2360,13 +2386,13 @@ bool MinidumpModule::ReadAuxiliaryData() { // CodeView and miscellaneous debug records are only required if the // module indicates that they exist. - if (module_.cv_record.data_size && !GetCVRecord(NULL)) { + if (module_.cv_record.data_size && !GetCVRecord(nullptr)) { BPLOG(ERROR) << "MinidumpModule has no CodeView record, " "but one was expected"; return false; } - if (module_.misc_record.data_size && !GetMiscRecord(NULL)) { + if (module_.misc_record.data_size && !GetMiscRecord(nullptr)) { BPLOG(ERROR) << "MinidumpModule has no miscellaneous debug record, " "but one was expected"; return false; @@ -2443,7 +2469,7 @@ string MinidumpModule::code_identifier() const { break; } // Otherwise fall through to the case below. - BP_FALLTHROUGH; + [[fallthrough]]; } case MD_OS_MAC_OS_X: @@ -2543,9 +2569,9 @@ string MinidumpModule::debug_file() const { // GetMiscRecord already byte-swapped the data[] field if it contains // UTF-16, so pass false as the swap argument. - scoped_ptr new_file(UTF16ToUTF8(string_utf16, false)); + std::unique_ptr new_file(UTF16ToUTF8(string_utf16, false)); if (new_file.get() != nullptr) { - file = *new_file; + file = string(*new_file); } } } @@ -2700,26 +2726,26 @@ void MinidumpModule::SetShrinkDownDelta(uint64_t shrink_down_delta) { const uint8_t* MinidumpModule::GetCVRecord(uint32_t* size) { if (!module_valid_) { BPLOG(ERROR) << "Invalid MinidumpModule for GetCVRecord"; - return NULL; + return nullptr; } if (!cv_record_) { // This just guards against 0-sized CodeView records; more specific checks // are used when the signature is checked against various structure types. if (module_.cv_record.data_size == 0) { - return NULL; + return nullptr; } if (!minidump_->SeekSet(module_.cv_record.rva)) { BPLOG(ERROR) << "MinidumpModule could not seek to CodeView record"; - return NULL; + return nullptr; } if (module_.cv_record.data_size > max_cv_bytes_) { BPLOG(ERROR) << "MinidumpModule CodeView record size " << module_.cv_record.data_size << " exceeds maximum " << max_cv_bytes_; - return NULL; + return nullptr; } // Allocating something that will be accessed as MDCVInfoPDB70 or @@ -2729,12 +2755,12 @@ const uint8_t* MinidumpModule::GetCVRecord(uint32_t* size) { // variable-sized due to their pdb_file_name fields; these structures // are not MDCVInfoPDB70_minsize or MDCVInfoPDB20_minsize and treating // them as such would result in incomplete structures or overruns. - scoped_ptr< vector > cv_record( + std::unique_ptr< vector > cv_record( new vector(module_.cv_record.data_size)); if (!minidump_->ReadBytes(&(*cv_record)[0], module_.cv_record.data_size)) { BPLOG(ERROR) << "MinidumpModule could not read CodeView record"; - return NULL; + return nullptr; } uint32_t signature = MD_CVINFOUNKNOWN_SIGNATURE; @@ -2753,7 +2779,7 @@ const uint8_t* MinidumpModule::GetCVRecord(uint32_t* size) { BPLOG(ERROR) << "MinidumpModule CodeView7 record size mismatch, " << MDCVInfoPDB70_minsize << " > " << module_.cv_record.data_size; - return NULL; + return nullptr; } if (minidump_->swap()) { @@ -2771,7 +2797,7 @@ const uint8_t* MinidumpModule::GetCVRecord(uint32_t* size) { if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') { BPLOG(ERROR) << "MinidumpModule CodeView7 record string is not " "0-terminated"; - return NULL; + return nullptr; } } else if (signature == MD_CVINFOPDB20_SIGNATURE) { // Now that the structure type is known, recheck the size, @@ -2780,7 +2806,7 @@ const uint8_t* MinidumpModule::GetCVRecord(uint32_t* size) { BPLOG(ERROR) << "MinidumpModule CodeView2 record size mismatch, " << MDCVInfoPDB20_minsize << " > " << module_.cv_record.data_size; - return NULL; + return nullptr; } if (minidump_->swap()) { MDCVInfoPDB20* cv_record_20 = @@ -2798,7 +2824,7 @@ const uint8_t* MinidumpModule::GetCVRecord(uint32_t* size) { if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') { BPLOG(ERROR) << "MindumpModule CodeView2 record string is not " "0-terminated"; - return NULL; + return nullptr; } } else if (signature == MD_CVINFOELF_SIGNATURE) { // Now that the structure type is known, recheck the size. @@ -2806,7 +2832,7 @@ const uint8_t* MinidumpModule::GetCVRecord(uint32_t* size) { BPLOG(ERROR) << "MinidumpModule CodeViewELF record size mismatch, " << MDCVInfoELF_minsize << " > " << module_.cv_record.data_size; - return NULL; + return nullptr; } if (minidump_->swap()) { MDCVInfoELF* cv_record_elf = @@ -2837,32 +2863,32 @@ const uint8_t* MinidumpModule::GetCVRecord(uint32_t* size) { const MDImageDebugMisc* MinidumpModule::GetMiscRecord(uint32_t* size) { if (!module_valid_) { BPLOG(ERROR) << "Invalid MinidumpModule for GetMiscRecord"; - return NULL; + return nullptr; } if (!misc_record_) { if (module_.misc_record.data_size == 0) { - return NULL; + return nullptr; } if (MDImageDebugMisc_minsize > module_.misc_record.data_size) { BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record " "size mismatch, " << MDImageDebugMisc_minsize << " > " << module_.misc_record.data_size; - return NULL; + return nullptr; } if (!minidump_->SeekSet(module_.misc_record.rva)) { BPLOG(ERROR) << "MinidumpModule could not seek to miscellaneous " "debugging record"; - return NULL; + return nullptr; } if (module_.misc_record.data_size > max_misc_bytes_) { BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record size " << module_.misc_record.data_size << " exceeds maximum " << max_misc_bytes_; - return NULL; + return nullptr; } // Allocating something that will be accessed as MDImageDebugMisc but @@ -2871,7 +2897,7 @@ const MDImageDebugMisc* MinidumpModule::GetMiscRecord(uint32_t* size) { // because the MDImageDebugMisc is variable-sized due to its data field; // this structure is not MDImageDebugMisc_minsize and treating it as such // would result in an incomplete structure or an overrun. - scoped_ptr< vector > misc_record_mem( + std::unique_ptr< vector > misc_record_mem( new vector(module_.misc_record.data_size)); MDImageDebugMisc* misc_record = reinterpret_cast(&(*misc_record_mem)[0]); @@ -2879,7 +2905,7 @@ const MDImageDebugMisc* MinidumpModule::GetMiscRecord(uint32_t* size) { if (!minidump_->ReadBytes(misc_record, module_.misc_record.data_size)) { BPLOG(ERROR) << "MinidumpModule could not read miscellaneous debugging " "record"; - return NULL; + return nullptr; } if (minidump_->swap()) { @@ -2902,7 +2928,7 @@ const MDImageDebugMisc* MinidumpModule::GetMiscRecord(uint32_t* size) { BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record data " "size mismatch, " << module_.misc_record.data_size << " != " << misc_record->length; - return NULL; + return nullptr; } // Store the vector type because that's how storage was allocated, but @@ -3030,7 +3056,7 @@ void MinidumpModule::Print() { printf(" (cv_record) = (null)\n"); } - const MDImageDebugMisc* misc_record = GetMiscRecord(NULL); + const MDImageDebugMisc* misc_record = GetMiscRecord(nullptr); if (misc_record) { printf(" (misc_record).data_type = 0x%x\n", misc_record->data_type); @@ -3074,7 +3100,7 @@ uint32_t MinidumpModuleList::max_modules_ = 2048; MinidumpModuleList::MinidumpModuleList(Minidump* minidump) : MinidumpStream(minidump), range_map_(new RangeMap()), - modules_(NULL), + modules_(nullptr), module_count_(0) { MDOSPlatform platform; if (minidump_->GetPlatform(&platform) && @@ -3094,7 +3120,7 @@ bool MinidumpModuleList::Read(uint32_t expected_size) { // Invalidate cached data. range_map_->Clear(); delete modules_; - modules_ = NULL; + modules_ = nullptr; module_count_ = 0; valid_ = false; @@ -3145,7 +3171,7 @@ bool MinidumpModuleList::Read(uint32_t expected_size) { } if (module_count != 0) { - scoped_ptr modules( + std::unique_ptr modules( new MinidumpModules(module_count, MinidumpModule(minidump_))); for (uint32_t module_index = 0; module_index < module_count; @@ -3274,15 +3300,15 @@ const MinidumpModule* MinidumpModuleList::GetModuleForAddress( uint64_t address) const { if (!valid_) { BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleForAddress"; - return NULL; + return nullptr; } unsigned int module_index; - if (!range_map_->RetrieveRange(address, &module_index, NULL /* base */, - NULL /* delta */, NULL /* size */)) { + if (!range_map_->RetrieveRange(address, &module_index, nullptr /* base */, + nullptr /* delta */, nullptr /* size */)) { BPLOG(INFO) << "MinidumpModuleList has no module at " << HexString(address); - return NULL; + return nullptr; } return GetModuleAtIndex(module_index); @@ -3292,7 +3318,7 @@ const MinidumpModule* MinidumpModuleList::GetModuleForAddress( const MinidumpModule* MinidumpModuleList::GetMainModule() const { if (!valid_) { BPLOG(ERROR) << "Invalid MinidumpModuleList for GetMainModule"; - return NULL; + return nullptr; } // The main code module is the first one present in a minidump file's @@ -3305,21 +3331,21 @@ const MinidumpModule* MinidumpModuleList::GetModuleAtSequence( unsigned int sequence) const { if (!valid_) { BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleAtSequence"; - return NULL; + return nullptr; } if (sequence >= module_count_) { BPLOG(ERROR) << "MinidumpModuleList sequence out of range: " << sequence << "/" << module_count_; - return NULL; + return nullptr; } unsigned int module_index; if (!range_map_->RetrieveRangeAtIndex(sequence, &module_index, - NULL /* base */, NULL /* delta */, - NULL /* size */)) { + nullptr /* base */, nullptr /* delta */, + nullptr /* size */)) { BPLOG(ERROR) << "MinidumpModuleList has no module at sequence " << sequence; - return NULL; + return nullptr; } return GetModuleAtIndex(module_index); @@ -3330,13 +3356,13 @@ const MinidumpModule* MinidumpModuleList::GetModuleAtIndex( unsigned int index) const { if (!valid_) { BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleAtIndex"; - return NULL; + return nullptr; } if (index >= module_count_) { BPLOG(ERROR) << "MinidumpModuleList index out of range: " << index << "/" << module_count_; - return NULL; + return nullptr; } return &(*modules_)[index]; @@ -3383,8 +3409,8 @@ uint32_t MinidumpMemoryList::max_regions_ = 4096; MinidumpMemoryList::MinidumpMemoryList(Minidump* minidump) : MinidumpStream(minidump), range_map_(new RangeMap()), - descriptors_(NULL), - regions_(NULL), + descriptors_(nullptr), + regions_(nullptr), region_count_(0) { } @@ -3399,9 +3425,9 @@ MinidumpMemoryList::~MinidumpMemoryList() { bool MinidumpMemoryList::Read(uint32_t expected_size) { // Invalidate cached data. delete descriptors_; - descriptors_ = NULL; + descriptors_ = nullptr; delete regions_; - regions_ = NULL; + regions_ = nullptr; range_map_->Clear(); region_count_ = 0; @@ -3454,7 +3480,7 @@ bool MinidumpMemoryList::Read(uint32_t expected_size) { } if (region_count != 0) { - scoped_ptr descriptors( + std::unique_ptr descriptors( new MemoryDescriptors(region_count)); // Read the entire array in one fell swoop, instead of reading one entry @@ -3465,7 +3491,7 @@ bool MinidumpMemoryList::Read(uint32_t expected_size) { return false; } - scoped_ptr regions( + std::unique_ptr regions( new MemoryRegions(region_count, MinidumpMemoryRegion(minidump_))); for (unsigned int region_index = 0; @@ -3515,13 +3541,13 @@ MinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionAtIndex( unsigned int index) { if (!valid_) { BPLOG(ERROR) << "Invalid MinidumpMemoryList for GetMemoryRegionAtIndex"; - return NULL; + return nullptr; } if (index >= region_count_) { BPLOG(ERROR) << "MinidumpMemoryList index out of range: " << index << "/" << region_count_; - return NULL; + return nullptr; } return &(*regions_)[index]; @@ -3532,15 +3558,15 @@ MinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionForAddress( uint64_t address) { if (!valid_) { BPLOG(ERROR) << "Invalid MinidumpMemoryList for GetMemoryRegionForAddress"; - return NULL; + return nullptr; } unsigned int region_index; - if (!range_map_->RetrieveRange(address, ®ion_index, NULL /* base */, - NULL /* delta */, NULL /* size */)) { + if (!range_map_->RetrieveRange(address, ®ion_index, nullptr /* base */, + nullptr /* delta */, nullptr /* size */)) { BPLOG(INFO) << "MinidumpMemoryList has no memory region at " << HexString(address); - return NULL; + return nullptr; } return GetMemoryRegionAtIndex(region_index); @@ -3587,7 +3613,7 @@ void MinidumpMemoryList::Print() { MinidumpException::MinidumpException(Minidump* minidump) : MinidumpStream(minidump), exception_(), - context_(NULL) { + context_(nullptr) { } @@ -3599,7 +3625,7 @@ MinidumpException::~MinidumpException() { bool MinidumpException::Read(uint32_t expected_size) { // Invalidate cached data. delete context_; - context_ = NULL; + context_ = nullptr; valid_ = false; @@ -3657,22 +3683,22 @@ bool MinidumpException::GetThreadID(uint32_t* thread_id) const { MinidumpContext* MinidumpException::GetContext() { if (!valid_) { BPLOG(ERROR) << "Invalid MinidumpException for GetContext"; - return NULL; + return nullptr; } if (!context_) { if (!minidump_->SeekSet(exception_.thread_context.rva)) { BPLOG(ERROR) << "MinidumpException cannot seek to context"; - return NULL; + return nullptr; } - scoped_ptr context(new MinidumpContext(minidump_)); + std::unique_ptr context(new MinidumpContext(minidump_)); // Don't log as an error if we can still fall back on the thread's context // (which must be possible if we got this far.) if (!context->Read(exception_.thread_context.data_size)) { BPLOG(INFO) << "MinidumpException cannot read context"; - return NULL; + return nullptr; } context_ = context.release(); @@ -3803,8 +3829,8 @@ void MinidumpAssertion::Print() { MinidumpSystemInfo::MinidumpSystemInfo(Minidump* minidump) : MinidumpStream(minidump), system_info_(), - csd_version_(NULL), - cpu_vendor_(NULL) { + csd_version_(nullptr), + cpu_vendor_(nullptr) { } @@ -3817,9 +3843,9 @@ MinidumpSystemInfo::~MinidumpSystemInfo() { bool MinidumpSystemInfo::Read(uint32_t expected_size) { // Invalidate cached data. delete csd_version_; - csd_version_ = NULL; + csd_version_ = nullptr; delete cpu_vendor_; - cpu_vendor_ = NULL; + cpu_vendor_ = nullptr; valid_ = false; @@ -3982,7 +4008,7 @@ string MinidumpSystemInfo::GetCPU() { const string* MinidumpSystemInfo::GetCSDVersion() { if (!valid_) { BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCSDVersion"; - return NULL; + return nullptr; } if (!csd_version_) @@ -3998,7 +4024,7 @@ const string* MinidumpSystemInfo::GetCSDVersion() { const string* MinidumpSystemInfo::GetCPUVendor() { if (!valid_) { BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCPUVendor"; - return NULL; + return nullptr; } // CPU vendor information can only be determined from x86 minidumps. @@ -4107,7 +4133,7 @@ MinidumpUnloadedModule::MinidumpUnloadedModule(Minidump* minidump) : MinidumpObject(minidump), module_valid_(false), unloaded_module_(), - name_(NULL) { + name_(nullptr) { } @@ -4289,7 +4315,7 @@ uint32_t MinidumpUnloadedModuleList::max_modules_ = 2048; MinidumpUnloadedModuleList::MinidumpUnloadedModuleList(Minidump* minidump) : MinidumpStream(minidump), range_map_(new RangeMap()), - unloaded_modules_(NULL), + unloaded_modules_(nullptr), module_count_(0) { range_map_->SetMergeStrategy(MergeRangeStrategy::kTruncateLower); } @@ -4303,7 +4329,7 @@ MinidumpUnloadedModuleList::~MinidumpUnloadedModuleList() { bool MinidumpUnloadedModuleList::Read(uint32_t expected_size) { range_map_->Clear(); delete unloaded_modules_; - unloaded_modules_ = NULL; + unloaded_modules_ = nullptr; module_count_ = 0; valid_ = false; @@ -4358,7 +4384,7 @@ bool MinidumpUnloadedModuleList::Read(uint32_t expected_size) { } if (number_of_entries != 0) { - scoped_ptr modules( + std::unique_ptr modules( new MinidumpUnloadedModules(number_of_entries, MinidumpUnloadedModule(minidump_))); @@ -4406,15 +4432,15 @@ const MinidumpUnloadedModule* MinidumpUnloadedModuleList::GetModuleForAddress( if (!valid_) { BPLOG(ERROR) << "Invalid MinidumpUnloadedModuleList for GetModuleForAddress"; - return NULL; + return nullptr; } unsigned int module_index; - if (!range_map_->RetrieveRange(address, &module_index, NULL /* base */, - NULL /* delta */, NULL /* size */)) { + if (!range_map_->RetrieveRange(address, &module_index, nullptr /* base */, + nullptr /* delta */, nullptr /* size */)) { BPLOG(INFO) << "MinidumpUnloadedModuleList has no module at " << HexString(address); - return NULL; + return nullptr; } return GetModuleAtIndex(module_index); @@ -4422,7 +4448,7 @@ const MinidumpUnloadedModule* MinidumpUnloadedModuleList::GetModuleForAddress( const MinidumpUnloadedModule* MinidumpUnloadedModuleList::GetMainModule() const { - return NULL; + return nullptr; } const MinidumpUnloadedModule* @@ -4430,22 +4456,22 @@ MinidumpUnloadedModuleList::GetModuleAtSequence(unsigned int sequence) const { if (!valid_) { BPLOG(ERROR) << "Invalid MinidumpUnloadedModuleList for GetModuleAtSequence"; - return NULL; + return nullptr; } if (sequence >= module_count_) { BPLOG(ERROR) << "MinidumpUnloadedModuleList sequence out of range: " << sequence << "/" << module_count_; - return NULL; + return nullptr; } unsigned int module_index; if (!range_map_->RetrieveRangeAtIndex(sequence, &module_index, - NULL /* base */, NULL /* delta */, - NULL /* size */)) { + nullptr /* base */, nullptr /* delta */, + nullptr /* size */)) { BPLOG(ERROR) << "MinidumpUnloadedModuleList has no module at sequence " << sequence; - return NULL; + return nullptr; } return GetModuleAtIndex(module_index); @@ -4456,13 +4482,13 @@ MinidumpUnloadedModuleList::GetModuleAtIndex( unsigned int index) const { if (!valid_) { BPLOG(ERROR) << "Invalid MinidumpUnloadedModuleList for GetModuleAtIndex"; - return NULL; + return nullptr; } if (index >= module_count_) { BPLOG(ERROR) << "MinidumpUnloadedModuleList index out of range: " << index << "/" << module_count_; - return NULL; + return nullptr; } return &(*unloaded_modules_)[index]; @@ -4944,7 +4970,7 @@ void MinidumpMemoryInfo::Print() { MinidumpMemoryInfoList::MinidumpMemoryInfoList(Minidump* minidump) : MinidumpStream(minidump), range_map_(new RangeMap()), - infos_(NULL), + infos_(nullptr), info_count_(0) { } @@ -4958,7 +4984,7 @@ MinidumpMemoryInfoList::~MinidumpMemoryInfoList() { bool MinidumpMemoryInfoList::Read(uint32_t expected_size) { // Invalidate cached data. delete infos_; - infos_ = NULL; + infos_ = nullptr; range_map_->Clear(); info_count_ = 0; @@ -5027,7 +5053,7 @@ bool MinidumpMemoryInfoList::Read(uint32_t expected_size) { } if (header.number_of_entries != 0) { - scoped_ptr infos( + std::unique_ptr infos( new MinidumpMemoryInfos(header_number_of_entries, MinidumpMemoryInfo(minidump_))); @@ -5070,13 +5096,13 @@ const MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoAtIndex( unsigned int index) const { if (!valid_) { BPLOG(ERROR) << "Invalid MinidumpMemoryInfoList for GetMemoryInfoAtIndex"; - return NULL; + return nullptr; } if (index >= info_count_) { BPLOG(ERROR) << "MinidumpMemoryInfoList index out of range: " << index << "/" << info_count_; - return NULL; + return nullptr; } return &(*infos_)[index]; @@ -5088,15 +5114,15 @@ const MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoForAddress( if (!valid_) { BPLOG(ERROR) << "Invalid MinidumpMemoryInfoList for" " GetMemoryInfoForAddress"; - return NULL; + return nullptr; } unsigned int info_index; - if (!range_map_->RetrieveRange(address, &info_index, NULL /* base */, - NULL /* delta */, NULL /* size */)) { + if (!range_map_->RetrieveRange(address, &info_index, nullptr /* base */, + nullptr /* delta */, nullptr /* size */)) { BPLOG(INFO) << "MinidumpMemoryInfoList has no memory info at " << HexString(address); - return NULL; + return nullptr; } return GetMemoryInfoAtIndex(info_index); @@ -5144,7 +5170,7 @@ void MinidumpLinuxMaps::Print() const { MinidumpLinuxMapsList::MinidumpLinuxMapsList(Minidump* minidump) : MinidumpStream(minidump), - maps_(NULL), + maps_(nullptr), maps_count_(0) { } @@ -5159,9 +5185,9 @@ MinidumpLinuxMapsList::~MinidumpLinuxMapsList() { const MinidumpLinuxMaps* MinidumpLinuxMapsList::GetLinuxMapsForAddress( uint64_t address) const { - if (!valid_ || (maps_ == NULL)) { + if (!valid_ || (maps_ == nullptr)) { BPLOG(ERROR) << "Invalid MinidumpLinuxMapsList for GetLinuxMapsForAddress"; - return NULL; + return nullptr; } // Search every memory mapping. @@ -5176,23 +5202,23 @@ const MinidumpLinuxMaps* MinidumpLinuxMapsList::GetLinuxMapsForAddress( // No mapping encloses the memory address. BPLOG(ERROR) << "MinidumpLinuxMapsList has no mapping at " << HexString(address); - return NULL; + return nullptr; } const MinidumpLinuxMaps* MinidumpLinuxMapsList::GetLinuxMapsAtIndex( unsigned int index) const { - if (!valid_ || (maps_ == NULL)) { + if (!valid_ || (maps_ == nullptr)) { BPLOG(ERROR) << "Invalid MinidumpLinuxMapsList for GetLinuxMapsAtIndex"; - return NULL; + return nullptr; } // Index out of bounds. - if (index >= maps_count_ || (maps_ == NULL)) { + if (index >= maps_count_ || (maps_ == nullptr)) { BPLOG(ERROR) << "MinidumpLinuxMapsList index of out range: " << index << "/" << maps_count_; - return NULL; + return nullptr; } return (*maps_)[index]; } @@ -5205,7 +5231,7 @@ bool MinidumpLinuxMapsList::Read(uint32_t expected_size) { } delete maps_; } - maps_ = NULL; + maps_ = nullptr; maps_count_ = 0; valid_ = false; @@ -5239,11 +5265,11 @@ bool MinidumpLinuxMapsList::Read(uint32_t expected_size) { return false; } - scoped_ptr maps(new MinidumpLinuxMappings()); + std::unique_ptr maps(new MinidumpLinuxMappings()); // Push mapping data into wrapper classes. for (size_t i = 0; i < all_regions.size(); i++) { - scoped_ptr ele(new MinidumpLinuxMaps(minidump_)); + std::unique_ptr ele(new MinidumpLinuxMaps(minidump_)); ele->region_ = all_regions[i]; ele->valid_ = true; maps->push_back(ele.release()); @@ -5257,7 +5283,7 @@ bool MinidumpLinuxMapsList::Read(uint32_t expected_size) { } void MinidumpLinuxMapsList::Print() const { - if (!valid_ || (maps_ == NULL)) { + if (!valid_ || (maps_ == nullptr)) { BPLOG(ERROR) << "MinidumpLinuxMapsList cannot print valid data"; return; } @@ -5443,9 +5469,12 @@ bool MinidumpCrashpadInfo::Read(uint32_t expected_size) { module_crashpad_info_links_.push_back( module_crashpad_info_links[index].minidump_module_list_index); module_crashpad_info_.push_back(module_crashpad_info); - module_crashpad_info_list_annotations_.push_back(list_annotations); - module_crashpad_info_simple_annotations_.push_back(simple_annotations); - module_crashpad_info_annotation_objects_.push_back(annotation_objects); + module_crashpad_info_list_annotations_.push_back(std::move( + list_annotations)); + module_crashpad_info_simple_annotations_.push_back(std::move( + simple_annotations)); + module_crashpad_info_annotation_objects_.push_back(std::move( + annotation_objects)); } } @@ -5529,10 +5558,10 @@ unsigned int Minidump::max_string_length_ = 1024; Minidump::Minidump(const string& path, bool hexdump, unsigned int hexdump_width) : header_(), - directory_(NULL), + directory_(nullptr), stream_map_(new MinidumpStreamMap()), path_(path), - stream_(NULL), + stream_(nullptr), swap_(false), is_big_endian_(false), valid_(false), @@ -5542,7 +5571,7 @@ Minidump::Minidump(const string& path, bool hexdump, unsigned int hexdump_width) Minidump::Minidump(istream& stream) : header_(), - directory_(NULL), + directory_(nullptr), stream_map_(new MinidumpStreamMap()), path_(), stream_(&stream), @@ -5566,7 +5595,7 @@ Minidump::~Minidump() { bool Minidump::Open() { - if (stream_ != NULL) { + if (stream_ != nullptr) { BPLOG(INFO) << "Minidump reopening minidump " << path_; // The file is already open. Seek to the beginning, which is the position @@ -5600,9 +5629,9 @@ bool Minidump::GetContextCPUFlagsFromSystemInfo(uint32_t* context_cpu_flags) { } const MDRawSystemInfo* system_info = - GetSystemInfo() ? GetSystemInfo()->system_info() : NULL; + GetSystemInfo() ? GetSystemInfo()->system_info() : nullptr; - if (system_info != NULL) { + if (system_info != nullptr) { switch (system_info->processor_architecture) { case MD_CPU_ARCHITECTURE_X86: *context_cpu_flags = MD_CONTEXT_X86; @@ -5675,7 +5704,7 @@ bool Minidump::GetContextCPUFlagsFromSystemInfo(uint32_t* context_cpu_flags) { bool Minidump::Read() { // Invalidate cached data. delete directory_; - directory_ = NULL; + directory_ = nullptr; stream_map_->clear(); valid_ = false; @@ -5753,7 +5782,7 @@ bool Minidump::Read() { } if (header_.stream_count != 0) { - scoped_ptr directory( + std::unique_ptr directory( new MinidumpDirectoryEntries(header_.stream_count)); // Read the entire array in one fell swoop, instead of reading one entry @@ -5794,7 +5823,7 @@ bool Minidump::Read() { stream_type << ", but can only deal with one"; return false; } - BP_FALLTHROUGH; + [[fallthrough]]; } default: { @@ -5891,7 +5920,7 @@ bool Minidump::GetPlatform(MDOSPlatform* platform) { return false; } const MDRawSystemInfo* system_info = - GetSystemInfo() ? GetSystemInfo()->system_info() : NULL; + GetSystemInfo() ? GetSystemInfo()->system_info() : nullptr; // Restore position and return if (!SeekSet(saved_position)) { @@ -6041,13 +6070,13 @@ const MDRawDirectory* Minidump::GetDirectoryEntryAtIndex(unsigned int index) const { if (!valid_) { BPLOG(ERROR) << "Invalid Minidump for GetDirectoryEntryAtIndex"; - return NULL; + return nullptr; } if (index >= header_.stream_count) { BPLOG(ERROR) << "Minidump stream directory index out of range: " << index << "/" << header_.stream_count; - return NULL; + return nullptr; } return &(*directory_)[index]; @@ -6122,18 +6151,18 @@ off_t Minidump::Tell() { string* Minidump::ReadString(off_t offset) { if (!valid_) { BPLOG(ERROR) << "Invalid Minidump for ReadString"; - return NULL; + return nullptr; } if (!SeekSet(offset)) { BPLOG(ERROR) << "ReadString could not seek to string at offset " << offset; - return NULL; + return nullptr; } uint32_t bytes; if (!ReadBytes(&bytes, sizeof(bytes))) { BPLOG(ERROR) << "ReadString could not read string size at offset " << offset; - return NULL; + return nullptr; } if (swap_) Swap(&bytes); @@ -6141,7 +6170,7 @@ string* Minidump::ReadString(off_t offset) { if (bytes % 2 != 0) { BPLOG(ERROR) << "ReadString found odd-sized " << bytes << "-byte string at offset " << offset; - return NULL; + return nullptr; } unsigned int utf16_words = bytes / 2; @@ -6149,7 +6178,7 @@ string* Minidump::ReadString(off_t offset) { BPLOG(ERROR) << "ReadString string length " << utf16_words << " exceeds maximum " << max_string_length_ << " at offset " << offset; - return NULL; + return nullptr; } vector string_utf16(utf16_words); @@ -6158,7 +6187,7 @@ string* Minidump::ReadString(off_t offset) { if (!ReadBytes(&string_utf16[0], bytes)) { BPLOG(ERROR) << "ReadString could not read " << bytes << "-byte string at offset " << offset; - return NULL; + return nullptr; } } @@ -6247,7 +6276,7 @@ bool Minidump::ReadStringList( return false; } - string_list->push_back(entry); + string_list->push_back(std::move(entry)); } return true; @@ -6377,9 +6406,9 @@ bool Minidump::ReadCrashpadAnnotationsList( return false; } - MinidumpCrashpadInfo::AnnotationObject object = {annotation.type, name, - value_data}; - annotations_list->push_back(object); + MinidumpCrashpadInfo::AnnotationObject object{annotation.type, name, + value_data}; + annotations_list->push_back(std::move(object)); } return true; @@ -6435,18 +6464,18 @@ T* Minidump::GetStream(T** stream) { BPLOG_IF(ERROR, !stream) << "Minidump::GetStream type " << stream_type << " requires |stream|"; assert(stream); - *stream = NULL; + *stream = nullptr; if (!valid_) { BPLOG(ERROR) << "Invalid Minidump for GetStream type " << stream_type; - return NULL; + return nullptr; } MinidumpStreamMap::iterator iterator = stream_map_->find(stream_type); if (iterator == stream_map_->end()) { // This stream type didn't exist in the directory. BPLOG(INFO) << "GetStream: type " << stream_type << " not present"; - return NULL; + return nullptr; } // Get a pointer so that the stored stream field can be altered. @@ -6462,14 +6491,14 @@ T* Minidump::GetStream(T** stream) { uint32_t stream_length; if (!SeekToStreamType(stream_type, &stream_length)) { BPLOG(ERROR) << "GetStream could not seek to stream type " << stream_type; - return NULL; + return nullptr; } - scoped_ptr new_stream(new T(this)); + std::unique_ptr new_stream(new T(this)); if (!new_stream->Read(stream_length)) { BPLOG(ERROR) << "GetStream could not read stream type " << stream_type; - return NULL; + return nullptr; } *stream = new_stream.release(); diff --git a/src/processor/minidump_dump.cc b/src/processor/minidump_dump.cc index d3c33ad4f..914d6b765 100644 --- a/src/processor/minidump_dump.cc +++ b/src/processor/minidump_dump.cc @@ -40,7 +40,6 @@ #include #include "common/path_helper.h" -#include "common/scoped_ptr.h" #include "google_breakpad/processor/minidump.h" #include "processor/logging.h" @@ -98,7 +97,7 @@ static void DumpRawStream(Minidump *minidump, printf("%.*s", int_remaining, &contents[current_offset]); char *next_null = reinterpret_cast( memchr(&contents[current_offset], 0, remaining)); - if (next_null == NULL) + if (next_null == nullptr) break; printf("\\0\n"); size_t null_offset = next_null - &contents[0]; diff --git a/src/processor/minidump_processor.cc b/src/processor/minidump_processor.cc index 5d2dea6d8..463b09793 100644 --- a/src/processor/minidump_processor.cc +++ b/src/processor/minidump_processor.cc @@ -33,14 +33,16 @@ #include "google_breakpad/processor/minidump_processor.h" #include +#include +#include #include #include #include +#include #include #include -#include "common/scoped_ptr.h" #include "common/stdio_wrapper.h" #include "common/using_std_string.h" #include "google_breakpad/processor/call_stack.h" @@ -64,7 +66,8 @@ MinidumpProcessor::MinidumpProcessor(SymbolSupplier* supplier, own_frame_symbolizer_(true), enable_exploitability_(false), enable_objdump_(false), - enable_objdump_for_exploitability_(false) { + enable_objdump_for_exploitability_(false), + max_thread_count_(-1) { } MinidumpProcessor::MinidumpProcessor(SymbolSupplier* supplier, @@ -74,7 +77,8 @@ MinidumpProcessor::MinidumpProcessor(SymbolSupplier* supplier, own_frame_symbolizer_(true), enable_exploitability_(enable_exploitability), enable_objdump_(false), - enable_objdump_for_exploitability_(false) { + enable_objdump_for_exploitability_(false), + max_thread_count_(-1) { } MinidumpProcessor::MinidumpProcessor(StackFrameSymbolizer* frame_symbolizer, @@ -83,7 +87,8 @@ MinidumpProcessor::MinidumpProcessor(StackFrameSymbolizer* frame_symbolizer, own_frame_symbolizer_(false), enable_exploitability_(enable_exploitability), enable_objdump_(false), - enable_objdump_for_exploitability_(false) { + enable_objdump_for_exploitability_(false), + max_thread_count_(-1) { assert(frame_symbolizer_); } @@ -195,42 +200,45 @@ ProcessResult MinidumpProcessor::Process( } BPLOG(INFO) << "Minidump " << dump->path() << " has " << - (has_cpu_info ? "" : "no ") << "CPU info, " << - (has_os_info ? "" : "no ") << "OS info, " << - (breakpad_info != NULL ? "" : "no ") << "Breakpad info, " << - (exception != NULL ? "" : "no ") << "exception, " << - (module_list != NULL ? "" : "no ") << "module list, " << - (threads != NULL ? "" : "no ") << "thread list, " << - (has_dump_thread ? "" : "no ") << "dump thread, " << - (has_requesting_thread ? "" : "no ") << "requesting thread, and " << - (has_process_create_time ? "" : "no ") << "process create time"; + (has_cpu_info ? "" : "no ") << "CPU info, " << + (has_os_info ? "" : "no ") << "OS info, " << + (breakpad_info != nullptr ? "" : "no ") << "Breakpad info, " << + (exception != nullptr ? "" : "no ") << "exception, " << + (module_list != nullptr ? "" : "no ") << "module list, " << + (threads != nullptr ? "" : "no ") << "thread list, " << + (has_dump_thread ? "" : "no ") << "dump thread, " << + (has_requesting_thread ? "" : "no ") << "requesting thread, and " << + (has_process_create_time ? "" : "no ") << "process create time"; bool interrupted = false; bool found_requesting_thread = false; unsigned int thread_count = threads->thread_count(); + process_state->original_thread_count_ = thread_count; // Reset frame_symbolizer_ at the beginning of stackwalk for each minidump. frame_symbolizer_->Reset(); - MinidumpThreadNameList* thread_names = dump->GetThreadNameList(); std::map thread_id_to_name; if (thread_names) { const unsigned int thread_name_count = thread_names->thread_name_count(); for (unsigned int thread_name_index = 0; - thread_name_index < thread_name_count; - ++thread_name_index) { - MinidumpThreadName* thread_name = thread_names->GetThreadNameAtIndex(thread_name_index); + thread_name_index < thread_name_count; ++thread_name_index) { + MinidumpThreadName* thread_name = + thread_names->GetThreadNameAtIndex(thread_name_index); if (!thread_name) { - BPLOG(ERROR) << "Could not get thread name for thread at index " << thread_name_index; + BPLOG(ERROR) << "Could not get thread name for thread at index " + << thread_name_index; return PROCESS_ERROR_GETTING_THREAD_NAME; } uint32_t thread_id; if (!thread_name->GetThreadID(&thread_id)) { - BPLOG(ERROR) << "Could not get thread ID for thread at index " << thread_name_index; + BPLOG(ERROR) << "Could not get thread ID for thread at index " + << thread_name_index; return PROCESS_ERROR_GETTING_THREAD_NAME; } - thread_id_to_name.insert(std::make_pair(thread_id, thread_name->GetThreadName())); + thread_id_to_name.insert( + std::make_pair(thread_id, thread_name->GetThreadName())); } } @@ -270,6 +278,7 @@ ProcessResult MinidumpProcessor::Process( // dump of itself (when both its context and its stack are in flux), // processing that stack wouldn't provide much useful data. if (has_dump_thread && thread_id == dump_thread_id) { + process_state->original_thread_count_--; continue; } @@ -290,6 +299,13 @@ ProcessResult MinidumpProcessor::Process( // be the index of the current thread when it's pushed into the // vector. process_state->requesting_thread_ = process_state->threads_.size(); + if (max_thread_count_ >= 0) { + thread_count = + std::min(thread_count, + std::max(static_cast( + process_state->requesting_thread_ + 1), + static_cast(max_thread_count_))); + } found_requesting_thread = true; @@ -328,7 +344,7 @@ ProcessResult MinidumpProcessor::Process( // returns. process_state->modules_ is owned by the ProcessState object // (just like the StackFrame objects), and is much more suitable for this // task. - scoped_ptr stackwalker( + std::unique_ptr stackwalker( Stackwalker::StackwalkerForCPU(process_state->system_info(), context, thread_memory, @@ -336,7 +352,7 @@ ProcessResult MinidumpProcessor::Process( process_state->unloaded_modules_, frame_symbolizer_)); - scoped_ptr stack(new CallStack()); + std::unique_ptr stack(new CallStack()); if (stackwalker.get()) { if (!stackwalker->Walk(stack.get(), &process_state->modules_without_symbols_, @@ -354,7 +370,7 @@ ProcessResult MinidumpProcessor::Process( stack->set_tid(thread_id); process_state->threads_.push_back(stack.release()); process_state->thread_memory_regions_.push_back(thread_memory); - process_state->thread_names_.push_back(thread_name); + process_state->thread_names_.push_back(std::move(thread_name)); } if (interrupted) { @@ -377,11 +393,11 @@ ProcessResult MinidumpProcessor::Process( // If an exploitability run was requested we perform the platform specific // rating. if (enable_exploitability_) { - scoped_ptr exploitability( + std::unique_ptr exploitability( Exploitability::ExploitabilityForPlatform( dump, process_state, enable_objdump_for_exploitability_)); // The engine will be null if the platform is not supported - if (exploitability != NULL) { + if (exploitability != nullptr) { process_state->exploitability_ = exploitability->CheckExploitability(); } else { process_state->exploitability_ = EXPLOITABILITY_ERR_NOENGINE; @@ -412,7 +428,7 @@ static const MDRawSystemInfo* GetSystemInfo(Minidump* dump, MinidumpSystemInfo** system_info) { MinidumpSystemInfo* minidump_system_info = dump->GetSystemInfo(); if (!minidump_system_info) - return NULL; + return nullptr; if (system_info) *system_info = minidump_system_info; @@ -445,7 +461,7 @@ static uint64_t GetAddressForArchitecture(const MDCPUArchitecture architecture, // cpu_info: address of target string, cpu info text will be appended to it. static void GetARMCpuInfo(const MDRawSystemInfo* raw_info, string* cpu_info) { - assert(raw_info != NULL && cpu_info != NULL); + assert(raw_info != nullptr && cpu_info != nullptr); // Write ARM architecture version. char cpu_string[32]; @@ -515,7 +531,7 @@ static void GetARMCpuInfo(const MDRawSystemInfo* raw_info, uint32_t cpuid = raw_info->cpu.arm_cpu_info.cpuid; if (cpuid != 0) { // Extract vendor name from CPUID - const char* vendor = NULL; + const char* vendor = nullptr; uint32_t vendor_id = (cpuid >> 24) & 0xff; for (size_t i = 0; i < sizeof(vendors)/sizeof(vendors[0]); ++i) { if (vendors[i].id == vendor_id) { @@ -533,7 +549,7 @@ static void GetARMCpuInfo(const MDRawSystemInfo* raw_info, // Extract part name from CPUID uint32_t part_id = (cpuid & 0xff00fff0); - const char* part = NULL; + const char* part = nullptr; for (size_t i = 0; i < sizeof(parts)/sizeof(parts[0]); ++i) { if (parts[i].id == part_id) { part = parts[i].name; @@ -541,7 +557,7 @@ static void GetARMCpuInfo(const MDRawSystemInfo* raw_info, } } cpu_info->append(" "); - if (part != NULL) { + if (part != nullptr) { cpu_info->append(part); } else { snprintf(cpu_string, sizeof(cpu_string), "part(0x%x)", part_id); @@ -794,13 +810,13 @@ static bool IsCanonicalAddress(uint64_t address) { static void CalculateFaultAddressFromInstruction(Minidump* dump, uint64_t* address) { MinidumpException* exception = dump->GetException(); - if (exception == NULL) { + if (exception == nullptr) { BPLOG(INFO) << "Failed to get exception."; return; } MinidumpContext* context = exception->GetContext(); - if (context == NULL) { + if (context == nullptr) { BPLOG(INFO) << "Failed to get exception context."; return; } @@ -815,7 +831,7 @@ static void CalculateFaultAddressFromInstruction(Minidump* dump, MinidumpMemoryList* memory_list = dump->GetMemoryList(); MinidumpMemoryRegion* memory_region = memory_list ? - memory_list->GetMemoryRegionForAddress(instruction_ptr) : NULL; + memory_list->GetMemoryRegionForAddress(instruction_ptr) : nullptr; if (!memory_region) { BPLOG(INFO) << "No memory region around instruction pointer."; return; @@ -823,8 +839,6 @@ static void CalculateFaultAddressFromInstruction(Minidump* dump, DisassemblerObjdump disassembler(context->GetContextCPU(), memory_region, instruction_ptr); - fprintf(stderr, "%s %s %s\n", disassembler.operation().c_str(), - disassembler.src().c_str(), disassembler.dest().c_str()); if (!disassembler.IsValid()) { BPLOG(INFO) << "Disassembling fault instruction failed."; return; @@ -882,7 +896,7 @@ string MinidumpProcessor::GetCrashReason(Minidump* dump, uint64_t* address, flags_string); string reason = reason_string; - const MDRawSystemInfo* raw_system_info = GetSystemInfo(dump, NULL); + const MDRawSystemInfo* raw_system_info = GetSystemInfo(dump, nullptr); if (!raw_system_info) return reason; @@ -1343,7 +1357,7 @@ string MinidumpProcessor::GetCrashReason(Minidump* dump, uint64_t* address, // an attempt to read data, 1 if it was an attempt to write data, // and 8 if this was a data execution violation. // exception_information[2] contains the underlying NTSTATUS code, - // which is the explanation for why this error occured. + // which is the explanation for why this error occurred. // This information is useful in addition to the code address, which // will be present in the crash thread's instruction field anyway. if (raw_exception->exception_record.number_parameters >= 1) { diff --git a/src/processor/minidump_processor_unittest.cc b/src/processor/minidump_processor_unittest.cc index de3cfdd59..c95cdd9df 100644 --- a/src/processor/minidump_processor_unittest.cc +++ b/src/processor/minidump_processor_unittest.cc @@ -42,7 +42,6 @@ #include #include "breakpad_googletest_includes.h" -#include "common/scoped_ptr.h" #include "common/using_std_string.h" #include "google_breakpad/processor/basic_source_line_resolver.h" #include "google_breakpad/processor/call_stack.h" @@ -80,12 +79,12 @@ class MockMinidump : public Minidump { class MockMinidumpUnloadedModule : public MinidumpUnloadedModule { public: - MockMinidumpUnloadedModule() : MinidumpUnloadedModule(NULL) {} + MockMinidumpUnloadedModule() : MinidumpUnloadedModule(nullptr) {} }; class MockMinidumpUnloadedModuleList : public MinidumpUnloadedModuleList { public: - MockMinidumpUnloadedModuleList() : MinidumpUnloadedModuleList(NULL) {} + MockMinidumpUnloadedModuleList() : MinidumpUnloadedModuleList(nullptr) {} ~MockMinidumpUnloadedModuleList() {} MOCK_CONST_METHOD0(Copy, CodeModules*()); @@ -95,7 +94,7 @@ class MockMinidumpUnloadedModuleList : public MinidumpUnloadedModuleList { class MockMinidumpThreadList : public MinidumpThreadList { public: - MockMinidumpThreadList() : MinidumpThreadList(NULL) {} + MockMinidumpThreadList() : MinidumpThreadList(nullptr) {} MOCK_CONST_METHOD0(thread_count, unsigned int()); MOCK_CONST_METHOD1(GetThreadAtIndex, MinidumpThread*(unsigned int)); @@ -103,14 +102,14 @@ class MockMinidumpThreadList : public MinidumpThreadList { class MockMinidumpMemoryList : public MinidumpMemoryList { public: - MockMinidumpMemoryList() : MinidumpMemoryList(NULL) {} + MockMinidumpMemoryList() : MinidumpMemoryList(nullptr) {} MOCK_METHOD1(GetMemoryRegionForAddress, MinidumpMemoryRegion*(uint64_t)); }; class MockMinidumpThread : public MinidumpThread { public: - MockMinidumpThread() : MinidumpThread(NULL) {} + MockMinidumpThread() : MinidumpThread(nullptr) {} MOCK_CONST_METHOD1(GetThreadID, bool(uint32_t*)); MOCK_METHOD0(GetContext, MinidumpContext*()); @@ -123,7 +122,7 @@ class MockMinidumpThread : public MinidumpThread { class MockMinidumpMemoryRegion : public MinidumpMemoryRegion { public: MockMinidumpMemoryRegion(uint64_t base, const string& contents) : - MinidumpMemoryRegion(NULL) { + MinidumpMemoryRegion(nullptr) { region_.Init(base, contents); } @@ -151,7 +150,7 @@ class MockMinidumpMemoryRegion : public MinidumpMemoryRegion { class TestMinidumpMiscInfo : public MinidumpMiscInfo { public: explicit TestMinidumpMiscInfo(const MDRawMiscInfo& misc_info) : - MinidumpMiscInfo(NULL) { + MinidumpMiscInfo(nullptr) { valid_ = true; misc_info_ = misc_info; } @@ -179,7 +178,6 @@ using google_breakpad::MockMinidumpThreadList; using google_breakpad::MockMinidumpUnloadedModule; using google_breakpad::MockMinidumpUnloadedModuleList; using google_breakpad::ProcessState; -using google_breakpad::scoped_ptr; using google_breakpad::SymbolSupplier; using google_breakpad::SystemInfo; using ::testing::_; @@ -297,7 +295,7 @@ SymbolSupplier::SymbolResult TestSymbolSupplier::GetCStringSymbolData( if (s == FOUND) { *symbol_data_size = symbol_data_string.size() + 1; *symbol_data = new char[*symbol_data_size]; - if (*symbol_data == NULL) { + if (*symbol_data == nullptr) { BPLOG(ERROR) << "Memory allocation failed for module: " << module->code_file() << " size: " << *symbol_data_size; return INTERRUPT; @@ -323,7 +321,7 @@ void TestSymbolSupplier::FreeSymbolData(const CodeModule* module) { class TestMinidumpSystemInfo : public MinidumpSystemInfo { public: explicit TestMinidumpSystemInfo(MDRawSystemInfo info) : - MinidumpSystemInfo(NULL) { + MinidumpSystemInfo(nullptr) { valid_ = true; system_info_ = info; csd_version_ = new string(""); @@ -335,7 +333,7 @@ class TestMinidumpSystemInfo : public MinidumpSystemInfo { class TestMinidumpContext : public MinidumpContext { public: explicit TestMinidumpContext(const MDRawContextX86& context) : - MinidumpContext(NULL) { + MinidumpContext(nullptr) { valid_ = true; SetContextX86(new MDRawContextX86(context)); SetContextFlags(MD_CONTEXT_X86); @@ -417,7 +415,7 @@ TEST_F(MinidumpProcessorTest, TestUnloadedModules) { EXPECT_CALL(*unloaded_module_list_copy, GetModuleForAddress(kExpectedEIP)). WillOnce(Return(&unloaded_module)); - MinidumpProcessor processor(reinterpret_cast(NULL), NULL); + MinidumpProcessor processor(static_cast(nullptr), nullptr); ProcessState state; EXPECT_EQ(processor.Process(&dump, &state), google_breakpad::PROCESS_OK); @@ -445,16 +443,16 @@ TEST_F(MinidumpProcessorTest, TestCorruptMinidumps) { MDRawHeader fakeHeader; fakeHeader.time_date_stamp = 0; EXPECT_CALL(dump, header()). - WillOnce(Return(reinterpret_cast(NULL))). + WillOnce(Return(static_cast(nullptr))). WillRepeatedly(Return(&fakeHeader)); EXPECT_EQ(processor.Process(&dump, &state), google_breakpad::PROCESS_ERROR_NO_MINIDUMP_HEADER); EXPECT_CALL(dump, GetThreadList()). - WillOnce(Return(reinterpret_cast(NULL))); + WillOnce(Return(static_cast(nullptr))); EXPECT_CALL(dump, GetSystemInfo()). - WillRepeatedly(Return(reinterpret_cast(NULL))); + WillRepeatedly(Return(static_cast(nullptr))); EXPECT_EQ(processor.Process(&dump, &state), google_breakpad::PROCESS_ERROR_NO_THREAD_LIST); @@ -618,13 +616,13 @@ TEST_F(MinidumpProcessorTest, TestThreadMissingMemory) { WillRepeatedly(DoAll(SetArgumentPointee<0>(1), Return(true))); EXPECT_CALL(no_memory_thread, GetMemory()). - WillRepeatedly(Return(reinterpret_cast(NULL))); + WillRepeatedly(Return(static_cast(nullptr))); const uint64_t kTestStartOfMemoryRange = 0x1234; EXPECT_CALL(no_memory_thread, GetStartOfStackMemoryRange()). WillRepeatedly(Return(kTestStartOfMemoryRange)); EXPECT_CALL(memory_list, GetMemoryRegionForAddress(kTestStartOfMemoryRange)). - WillRepeatedly(Return(reinterpret_cast(NULL))); + WillRepeatedly(Return(static_cast(nullptr))); MDRawContextX86 no_memory_thread_raw_context; memset(&no_memory_thread_raw_context, 0, @@ -641,7 +639,7 @@ TEST_F(MinidumpProcessorTest, TestThreadMissingMemory) { EXPECT_CALL(thread_list, GetThreadAtIndex(0)). WillOnce(Return(&no_memory_thread)); - MinidumpProcessor processor(reinterpret_cast(NULL), NULL); + MinidumpProcessor processor(static_cast(nullptr), nullptr); ProcessState state; EXPECT_EQ(processor.Process(&dump, &state), google_breakpad::PROCESS_OK); @@ -677,7 +675,7 @@ TEST_F(MinidumpProcessorTest, GetProcessCreateTime) { EXPECT_CALL(dump, GetThreadList()).WillOnce(Return(&thread_list)); EXPECT_CALL(thread_list, thread_count()).WillRepeatedly(Return(0)); - MinidumpProcessor processor(reinterpret_cast(NULL), NULL); + MinidumpProcessor processor(static_cast(nullptr), nullptr); ProcessState state; EXPECT_EQ(google_breakpad::PROCESS_OK, processor.Process(&dump, &state)); @@ -718,7 +716,7 @@ TEST_F(MinidumpProcessorTest, TestThreadMissingContext) { WillRepeatedly(DoAll(SetArgumentPointee<0>(1), Return(true))); EXPECT_CALL(no_context_thread, GetContext()). - WillRepeatedly(Return(reinterpret_cast(NULL))); + WillRepeatedly(Return(static_cast(nullptr))); // The memory contents don't really matter here, since it won't be used. MockMinidumpMemoryRegion no_context_thread_memory(0x1234, "xxx"); @@ -734,7 +732,7 @@ TEST_F(MinidumpProcessorTest, TestThreadMissingContext) { EXPECT_CALL(thread_list, GetThreadAtIndex(0)). WillOnce(Return(&no_context_thread)); - MinidumpProcessor processor(reinterpret_cast(NULL), NULL); + MinidumpProcessor processor(static_cast(nullptr), nullptr); ProcessState state; EXPECT_EQ(processor.Process(&dump, &state), google_breakpad::PROCESS_OK); @@ -764,6 +762,29 @@ TEST_F(MinidumpProcessorTest, Test32BitCrashingAddress) { ASSERT_EQ(state.crash_address(), 0x45U); } +TEST_F(MinidumpProcessorTest, TestXStateX86ContextMinidump) { + // This tests if we can passively process a minidump with cet registers in its + // context. Dump is captured from a toy executable and is readable by windbg. + MinidumpProcessor processor(nullptr, nullptr /*&supplier, &resolver*/); + + string minidump_file = GetTestDataPath() + + "tiny-exe-with-cet-xsave-x86.dmp"; + + ProcessState state; + ASSERT_EQ(processor.Process(minidump_file, &state), + google_breakpad::PROCESS_OK); + ASSERT_EQ(state.system_info()->os, "Windows NT"); + ASSERT_EQ(state.system_info()->os_version, "10.0.22631 "); + ASSERT_EQ(state.system_info()->cpu, "x86"); + ASSERT_EQ(state.system_info()->cpu_info, + "GenuineIntel family 6 model 151 stepping 2"); + ASSERT_FALSE(state.crashed()); + ASSERT_EQ(state.threads()->size(), size_t(3)); + + // TODO: verify cetumsr and cetussp once these are supported by + // breakpad. +} + TEST_F(MinidumpProcessorTest, TestXStateAmd64ContextMinidump) { // This tests if we can passively process a minidump with cet registers in its // context. Dump is captured from a toy executable and is readable by windbg. diff --git a/src/processor/minidump_stackwalk.cc b/src/processor/minidump_stackwalk.cc index 74b41acf7..7fab30f4b 100644 --- a/src/processor/minidump_stackwalk.cc +++ b/src/processor/minidump_stackwalk.cc @@ -40,11 +40,11 @@ #include #include +#include #include #include #include "common/path_helper.h" -#include "common/scoped_ptr.h" #include "common/using_std_string.h" #include "google_breakpad/processor/basic_source_line_resolver.h" #include "google_breakpad/processor/minidump.h" @@ -74,7 +74,6 @@ using google_breakpad::MinidumpThreadList; using google_breakpad::MinidumpProcessor; using google_breakpad::ProcessState; using google_breakpad::SimpleSymbolSupplier; -using google_breakpad::scoped_ptr; // Processes |options.minidump_file| using MinidumpProcessor. // |options.symbol_path|, if non-empty, is the base directory of a @@ -88,7 +87,7 @@ using google_breakpad::scoped_ptr; // call stacks for each thread contained in the minidump. All information // is printed to stdout. bool PrintMinidumpProcess(const Options& options) { - scoped_ptr symbol_supplier; + std::unique_ptr symbol_supplier; if (!options.symbol_paths.empty()) { // TODO(mmentovai): check existence of symbol_path if specified? symbol_supplier.reset(new SimpleSymbolSupplier(options.symbol_paths)); diff --git a/src/processor/minidump_unittest.cc b/src/processor/minidump_unittest.cc index 719adf78a..e91ff26a7 100644 --- a/src/processor/minidump_unittest.cc +++ b/src/processor/minidump_unittest.cc @@ -96,13 +96,13 @@ TEST_F(MinidumpTest, TestMinidumpFromFile) { ASSERT_EQ(minidump.path(), minidump_file_); ASSERT_TRUE(minidump.Read()); const MDRawHeader* header = minidump.header(); - ASSERT_NE(header, (MDRawHeader*)NULL); + ASSERT_NE(header, (MDRawHeader*)nullptr); ASSERT_EQ(header->signature, uint32_t(MD_HEADER_SIGNATURE)); MinidumpModuleList* md_module_list = minidump.GetModuleList(); - ASSERT_TRUE(md_module_list != NULL); + ASSERT_TRUE(md_module_list != nullptr); const MinidumpModule* md_module = md_module_list->GetModuleAtIndex(0); - ASSERT_TRUE(md_module != NULL); + ASSERT_TRUE(md_module != nullptr); ASSERT_EQ("c:\\test_app.exe", md_module->code_file()); ASSERT_EQ("c:\\test_app.pdb", md_module->debug_file()); ASSERT_EQ("45D35F6C2d000", md_module->code_identifier()); @@ -111,7 +111,7 @@ TEST_F(MinidumpTest, TestMinidumpFromFile) { TEST_F(MinidumpTest, TestMinidumpFromStream) { // read minidump contents into memory, construct a stringstream around them - ifstream file_stream(minidump_file_.c_str(), std::ios::in); + ifstream file_stream(minidump_file_.c_str(), std::ios::in | std::ios::binary); ASSERT_TRUE(file_stream.good()); vector bytes; file_stream.seekg(0, std::ios_base::end); @@ -130,7 +130,7 @@ TEST_F(MinidumpTest, TestMinidumpFromStream) { ASSERT_EQ(minidump.path(), ""); ASSERT_TRUE(minidump.Read()); const MDRawHeader* header = minidump.header(); - ASSERT_NE(header, (MDRawHeader*)NULL); + ASSERT_NE(header, (MDRawHeader*)nullptr); ASSERT_EQ(header->signature, uint32_t(MD_HEADER_SIGNATURE)); //TODO: add more checks here } @@ -145,7 +145,7 @@ TEST_F(MinidumpTest, TestMinidumpWithCrashpadAnnotations) { ASSERT_TRUE(minidump.Read()); MinidumpCrashpadInfo* crashpad_info = minidump.GetCrashpadInfo(); - ASSERT_TRUE(crashpad_info != NULL); + ASSERT_TRUE(crashpad_info != nullptr); const std::vector>* annotation_objects_list = @@ -208,7 +208,7 @@ TEST(Dump, OneStream) { ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); const MDRawDirectory* dir = minidump.GetDirectoryEntryAtIndex(0); - ASSERT_TRUE(dir != NULL); + ASSERT_TRUE(dir != nullptr); EXPECT_EQ(0xfbb7fa2bU, dir->stream_type); uint32_t stream_length; @@ -244,11 +244,11 @@ TEST(Dump, OneMemory) { ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); const MDRawDirectory* dir = minidump.GetDirectoryEntryAtIndex(0); - ASSERT_TRUE(dir != NULL); + ASSERT_TRUE(dir != nullptr); EXPECT_EQ((uint32_t) MD_MEMORY_LIST_STREAM, dir->stream_type); MinidumpMemoryList* memory_list = minidump.GetMemoryList(); - ASSERT_TRUE(memory_list != NULL); + ASSERT_TRUE(memory_list != nullptr); ASSERT_EQ(1U, memory_list->region_count()); MinidumpMemoryRegion* region1 = memory_list->GetMemoryRegionAtIndex(0); @@ -298,7 +298,7 @@ TEST(Dump, OneThread) { ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); MinidumpMemoryList* md_memory_list = minidump.GetMemoryList(); - ASSERT_TRUE(md_memory_list != NULL); + ASSERT_TRUE(md_memory_list != nullptr); ASSERT_EQ(1U, md_memory_list->region_count()); MinidumpMemoryRegion* md_region = md_memory_list->GetMemoryRegionAtIndex(0); @@ -308,23 +308,23 @@ TEST(Dump, OneThread) { ASSERT_TRUE(memcmp("stack for thread", region_bytes, 16) == 0); MinidumpThreadList* thread_list = minidump.GetThreadList(); - ASSERT_TRUE(thread_list != NULL); + ASSERT_TRUE(thread_list != nullptr); ASSERT_EQ(1U, thread_list->thread_count()); MinidumpThread* md_thread = thread_list->GetThreadAtIndex(0); - ASSERT_TRUE(md_thread != NULL); + ASSERT_TRUE(md_thread != nullptr); uint32_t thread_id; ASSERT_TRUE(md_thread->GetThreadID(&thread_id)); ASSERT_EQ(0xa898f11bU, thread_id); MinidumpMemoryRegion* md_stack = md_thread->GetMemory(); - ASSERT_TRUE(md_stack != NULL); + ASSERT_TRUE(md_stack != nullptr); ASSERT_EQ(0x2326a0faU, md_stack->GetBase()); ASSERT_EQ(16U, md_stack->GetSize()); const uint8_t* md_stack_bytes = md_stack->GetMemory(); ASSERT_TRUE(memcmp("stack for thread", md_stack_bytes, 16) == 0); MinidumpContext* md_context = md_thread->GetContext(); - ASSERT_TRUE(md_context != NULL); + ASSERT_TRUE(md_context != nullptr); ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU()); uint64_t eip; @@ -332,7 +332,7 @@ TEST(Dump, OneThread) { EXPECT_EQ(kExpectedEIP, eip); const MDRawContextX86* md_raw_context = md_context->GetContextX86(); - ASSERT_TRUE(md_raw_context != NULL); + ASSERT_TRUE(md_raw_context != nullptr); ASSERT_EQ((uint32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL), (md_raw_context->context_flags & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL))); @@ -378,21 +378,21 @@ TEST(Dump, ThreadMissingMemory) { // This should succeed even though the thread has no stack memory. MinidumpThreadList* thread_list = minidump.GetThreadList(); - ASSERT_TRUE(thread_list != NULL); + ASSERT_TRUE(thread_list != nullptr); ASSERT_EQ(1U, thread_list->thread_count()); MinidumpThread* md_thread = thread_list->GetThreadAtIndex(0); - ASSERT_TRUE(md_thread != NULL); + ASSERT_TRUE(md_thread != nullptr); uint32_t thread_id; ASSERT_TRUE(md_thread->GetThreadID(&thread_id)); ASSERT_EQ(0xa898f11bU, thread_id); MinidumpContext* md_context = md_thread->GetContext(); - ASSERT_NE(reinterpret_cast(NULL), md_context); + ASSERT_NE(static_cast(nullptr), md_context); MinidumpMemoryRegion* md_stack = md_thread->GetMemory(); - ASSERT_EQ(reinterpret_cast(NULL), md_stack); + ASSERT_EQ(static_cast(nullptr), md_stack); } TEST(Dump, ThreadMissingContext) { @@ -421,20 +421,20 @@ TEST(Dump, ThreadMissingContext) { // This should succeed even though the thread has no stack memory. MinidumpThreadList* thread_list = minidump.GetThreadList(); - ASSERT_TRUE(thread_list != NULL); + ASSERT_TRUE(thread_list != nullptr); ASSERT_EQ(1U, thread_list->thread_count()); MinidumpThread* md_thread = thread_list->GetThreadAtIndex(0); - ASSERT_TRUE(md_thread != NULL); + ASSERT_TRUE(md_thread != nullptr); uint32_t thread_id; ASSERT_TRUE(md_thread->GetThreadID(&thread_id)); ASSERT_EQ(0xa898f11bU, thread_id); MinidumpMemoryRegion* md_stack = md_thread->GetMemory(); - ASSERT_NE(reinterpret_cast(NULL), md_stack); + ASSERT_NE(static_cast(nullptr), md_stack); MinidumpContext* md_context = md_thread->GetContext(); - ASSERT_EQ(reinterpret_cast(NULL), md_context); + ASSERT_EQ(static_cast(nullptr), md_context); } TEST(Dump, OneUnloadedModule) { @@ -466,17 +466,17 @@ TEST(Dump, OneUnloadedModule) { ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); const MDRawDirectory* dir = minidump.GetDirectoryEntryAtIndex(1); - ASSERT_TRUE(dir != NULL); + ASSERT_TRUE(dir != nullptr); EXPECT_EQ((uint32_t) MD_UNLOADED_MODULE_LIST_STREAM, dir->stream_type); MinidumpUnloadedModuleList* md_unloaded_module_list = minidump.GetUnloadedModuleList(); - ASSERT_TRUE(md_unloaded_module_list != NULL); + ASSERT_TRUE(md_unloaded_module_list != nullptr); ASSERT_EQ(1U, md_unloaded_module_list->module_count()); const MinidumpUnloadedModule* md_unloaded_module = md_unloaded_module_list->GetModuleAtIndex(0); - ASSERT_TRUE(md_unloaded_module != NULL); + ASSERT_TRUE(md_unloaded_module != nullptr); ASSERT_EQ(0xa90206ca83eb2852ULL, md_unloaded_module->base_address()); ASSERT_EQ(0xada542bd, md_unloaded_module->size()); ASSERT_EQ("unloaded module", md_unloaded_module->code_file()); @@ -487,7 +487,7 @@ TEST(Dump, OneUnloadedModule) { const MDRawUnloadedModule* md_raw_unloaded_module = md_unloaded_module->module(); - ASSERT_TRUE(md_raw_unloaded_module != NULL); + ASSERT_TRUE(md_raw_unloaded_module != nullptr); ASSERT_EQ(0xb1054d2aU, md_raw_unloaded_module->time_date_stamp); ASSERT_EQ(0x34571371U, md_raw_unloaded_module->checksum); } @@ -547,15 +547,15 @@ TEST(Dump, OneModule) { ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); const MDRawDirectory* dir = minidump.GetDirectoryEntryAtIndex(1); - ASSERT_TRUE(dir != NULL); + ASSERT_TRUE(dir != nullptr); EXPECT_EQ((uint32_t) MD_MODULE_LIST_STREAM, dir->stream_type); MinidumpModuleList* md_module_list = minidump.GetModuleList(); - ASSERT_TRUE(md_module_list != NULL); + ASSERT_TRUE(md_module_list != nullptr); ASSERT_EQ(1U, md_module_list->module_count()); const MinidumpModule* md_module = md_module_list->GetModuleAtIndex(0); - ASSERT_TRUE(md_module != NULL); + ASSERT_TRUE(md_module != nullptr); ASSERT_EQ(0xa90206ca83eb2852ULL, md_module->base_address()); ASSERT_EQ(0xada542bd, md_module->size()); ASSERT_EQ("single module", md_module->code_file()); @@ -565,7 +565,7 @@ TEST(Dump, OneModule) { ASSERT_EQ("ABCD1234F00DBEEF01020304050607081", md_module->debug_identifier()); const MDRawModule* md_raw_module = md_module->module(); - ASSERT_TRUE(md_raw_module != NULL); + ASSERT_TRUE(md_raw_module != nullptr); ASSERT_EQ(0xb1054d2aU, md_raw_module->time_date_stamp); ASSERT_EQ(0x34571371U, md_raw_module->checksum); ASSERT_TRUE(memcmp(&md_raw_module->version_info, &fixed_file_info, @@ -629,11 +629,11 @@ TEST(Dump, OneModuleCVELF) { ASSERT_TRUE(minidump.Read()); MinidumpModuleList* md_module_list = minidump.GetModuleList(); - ASSERT_TRUE(md_module_list != NULL); + ASSERT_TRUE(md_module_list != nullptr); ASSERT_EQ(1U, md_module_list->module_count()); const MinidumpModule* md_module = md_module_list->GetModuleAtIndex(0); - ASSERT_TRUE(md_module != NULL); + ASSERT_TRUE(md_module != nullptr); ASSERT_EQ(0xa90206ca83eb2852ULL, md_module->base_address()); ASSERT_EQ(0xada542bd, md_module->size()); ASSERT_EQ("elf module", md_module->code_file()); @@ -647,7 +647,7 @@ TEST(Dump, OneModuleCVELF) { ASSERT_EQ("B4CDA95F53101BDF86FAB733B4DF37380", md_module->debug_identifier()); const MDRawModule* md_raw_module = md_module->module(); - ASSERT_TRUE(md_raw_module != NULL); + ASSERT_TRUE(md_raw_module != nullptr); ASSERT_EQ(0xb1054d2aU, md_raw_module->time_date_stamp); ASSERT_EQ(0x34571371U, md_raw_module->checksum); ASSERT_TRUE(memcmp(&md_raw_module->version_info, &fixed_file_info, @@ -711,11 +711,11 @@ TEST(Dump, CVELFShort) { ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); MinidumpModuleList* md_module_list = minidump.GetModuleList(); - ASSERT_TRUE(md_module_list != NULL); + ASSERT_TRUE(md_module_list != nullptr); ASSERT_EQ(1U, md_module_list->module_count()); const MinidumpModule* md_module = md_module_list->GetModuleAtIndex(0); - ASSERT_TRUE(md_module != NULL); + ASSERT_TRUE(md_module != nullptr); // just the build_id, directly ASSERT_EQ("5fa9cdb4", md_module->code_identifier()); // build_id expanded to GUID length and treated as such, with zero @@ -783,11 +783,11 @@ TEST(Dump, CVELFLong) { ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); MinidumpModuleList* md_module_list = minidump.GetModuleList(); - ASSERT_TRUE(md_module_list != NULL); + ASSERT_TRUE(md_module_list != nullptr); ASSERT_EQ(1U, md_module_list->module_count()); const MinidumpModule* md_module = md_module_list->GetModuleAtIndex(0); - ASSERT_TRUE(md_module != NULL); + ASSERT_TRUE(md_module != nullptr); // just the build_id, directly ASSERT_EQ( "5fa9cdb41053df1b86fab733b4df3738cea34a870102030405060708090a0b0c0d0e0f", @@ -814,11 +814,11 @@ TEST(Dump, OneSystemInfo) { ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); const MDRawDirectory* dir = minidump.GetDirectoryEntryAtIndex(0); - ASSERT_TRUE(dir != NULL); + ASSERT_TRUE(dir != nullptr); EXPECT_EQ((uint32_t) MD_SYSTEM_INFO_STREAM, dir->stream_type); MinidumpSystemInfo* md_system_info = minidump.GetSystemInfo(); - ASSERT_TRUE(md_system_info != NULL); + ASSERT_TRUE(md_system_info != nullptr); ASSERT_EQ("windows", md_system_info->GetOS()); ASSERT_EQ("x86", md_system_info->GetCPU()); ASSERT_EQ("Petulant Pierogi", *md_system_info->GetCSDVersion()); @@ -953,7 +953,7 @@ TEST(Dump, BigDump) { // Check the threads. MinidumpThreadList* thread_list = minidump.GetThreadList(); - ASSERT_TRUE(thread_list != NULL); + ASSERT_TRUE(thread_list != nullptr); ASSERT_EQ(5U, thread_list->thread_count()); uint32_t thread_id; ASSERT_TRUE(thread_list->GetThreadAtIndex(0)->GetThreadID(&thread_id)); @@ -998,7 +998,7 @@ TEST(Dump, BigDump) { // Check the modules. MinidumpModuleList* md_module_list = minidump.GetModuleList(); - ASSERT_TRUE(md_module_list != NULL); + ASSERT_TRUE(md_module_list != nullptr); ASSERT_EQ(3U, md_module_list->module_count()); EXPECT_EQ(0xeb77da57b5d4cbdaULL, md_module_list->GetModuleAtIndex(0)->base_address()); @@ -1010,7 +1010,7 @@ TEST(Dump, BigDump) { // Check unloaded modules MinidumpUnloadedModuleList* md_unloaded_module_list = minidump.GetUnloadedModuleList(); - ASSERT_TRUE(md_unloaded_module_list != NULL); + ASSERT_TRUE(md_unloaded_module_list != nullptr); ASSERT_EQ(3U, md_unloaded_module_list->module_count()); EXPECT_EQ(umodule1_base, md_unloaded_module_list->GetModuleAtIndex(0)->base_address()); @@ -1027,7 +1027,7 @@ TEST(Dump, BigDump) { umodule = md_unloaded_module_list->GetModuleAtSequence(0); EXPECT_EQ(umodule1_base, umodule->base_address()); - EXPECT_EQ(NULL, md_unloaded_module_list->GetMainModule()); + EXPECT_EQ(nullptr, md_unloaded_module_list->GetMainModule()); } @@ -1066,11 +1066,11 @@ TEST(Dump, OneMemoryInfo) { ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); const MDRawDirectory* dir = minidump.GetDirectoryEntryAtIndex(0); - ASSERT_TRUE(dir != NULL); + ASSERT_TRUE(dir != nullptr); EXPECT_EQ((uint32_t) MD_MEMORY_INFO_LIST_STREAM, dir->stream_type); MinidumpMemoryInfoList* info_list = minidump.GetMemoryInfoList(); - ASSERT_TRUE(info_list != NULL); + ASSERT_TRUE(info_list != nullptr); ASSERT_EQ(1U, info_list->info_count()); const MinidumpMemoryInfo* info1 = info_list->GetMemoryInfoAtIndex(0); @@ -1124,24 +1124,24 @@ TEST(Dump, OneExceptionX86) { ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); MinidumpException* md_exception = minidump.GetException(); - ASSERT_TRUE(md_exception != NULL); + ASSERT_TRUE(md_exception != nullptr); uint32_t thread_id; ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); ASSERT_EQ(0x1234abcdU, thread_id); const MDRawExceptionStream* raw_exception = md_exception->exception(); - ASSERT_TRUE(raw_exception != NULL); + ASSERT_TRUE(raw_exception != nullptr); EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); EXPECT_EQ(0x0919a9b9c9d9e9f9ULL, raw_exception->exception_record.exception_address); MinidumpContext* md_context = md_exception->GetContext(); - ASSERT_TRUE(md_context != NULL); + ASSERT_TRUE(md_context != nullptr); ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU()); const MDRawContextX86* md_raw_context = md_context->GetContextX86(); - ASSERT_TRUE(md_raw_context != NULL); + ASSERT_TRUE(md_raw_context != nullptr); ASSERT_EQ((uint32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL), (md_raw_context->context_flags & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL))); @@ -1198,24 +1198,24 @@ TEST(Dump, OneExceptionX86XState) { ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); MinidumpException* md_exception = minidump.GetException(); - ASSERT_TRUE(md_exception != NULL); + ASSERT_TRUE(md_exception != nullptr); uint32_t thread_id; ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); ASSERT_EQ(0x1234abcdU, thread_id); const MDRawExceptionStream* raw_exception = md_exception->exception(); - ASSERT_TRUE(raw_exception != NULL); + ASSERT_TRUE(raw_exception != nullptr); EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); EXPECT_EQ(0x0919a9b9c9d9e9f9ULL, raw_exception->exception_record.exception_address); MinidumpContext* md_context = md_exception->GetContext(); - ASSERT_TRUE(md_context != NULL); + ASSERT_TRUE(md_context != nullptr); ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU()); const MDRawContextX86* md_raw_context = md_context->GetContextX86(); - ASSERT_TRUE(md_raw_context != NULL); + ASSERT_TRUE(md_raw_context != nullptr); ASSERT_EQ((uint32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL), (md_raw_context->context_flags & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL))); @@ -1283,25 +1283,25 @@ TEST(Dump, OneExceptionX86NoCPUFlags) { ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); MinidumpException* md_exception = minidump.GetException(); - ASSERT_TRUE(md_exception != NULL); + ASSERT_TRUE(md_exception != nullptr); uint32_t thread_id; ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); ASSERT_EQ(0x1234abcdU, thread_id); const MDRawExceptionStream* raw_exception = md_exception->exception(); - ASSERT_TRUE(raw_exception != NULL); + ASSERT_TRUE(raw_exception != nullptr); EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); EXPECT_EQ(0x0919a9b9c9d9e9f9ULL, raw_exception->exception_record.exception_address); MinidumpContext* md_context = md_exception->GetContext(); - ASSERT_TRUE(md_context != NULL); + ASSERT_TRUE(md_context != nullptr); ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU()); const MDRawContextX86* md_raw_context = md_context->GetContextX86(); - ASSERT_TRUE(md_raw_context != NULL); + ASSERT_TRUE(md_raw_context != nullptr); // Even though the CPU flags were missing from the context_flags, the // GetContext call above is expected to load the missing CPU flags from the @@ -1365,14 +1365,14 @@ TEST(Dump, OneExceptionX86NoCPUFlagsNoSystemInfo) { ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); MinidumpException* md_exception = minidump.GetException(); - ASSERT_TRUE(md_exception != NULL); + ASSERT_TRUE(md_exception != nullptr); uint32_t thread_id; ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); ASSERT_EQ(0x1234abcdU, thread_id); const MDRawExceptionStream* raw_exception = md_exception->exception(); - ASSERT_TRUE(raw_exception != NULL); + ASSERT_TRUE(raw_exception != nullptr); EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); EXPECT_EQ(0x0919a9b9c9d9e9f9ULL, @@ -1382,7 +1382,7 @@ TEST(Dump, OneExceptionX86NoCPUFlagsNoSystemInfo) { // don't have CPU type information and at the same time the minidump lacks // system info stream so it is impossible to deduce the CPU type. MinidumpContext* md_context = md_exception->GetContext(); - ASSERT_EQ(NULL, md_context); + ASSERT_EQ(nullptr, md_context); } TEST(Dump, OneExceptionARM) { @@ -1428,24 +1428,24 @@ TEST(Dump, OneExceptionARM) { ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); MinidumpException* md_exception = minidump.GetException(); - ASSERT_TRUE(md_exception != NULL); + ASSERT_TRUE(md_exception != nullptr); uint32_t thread_id; ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); ASSERT_EQ(0x1234abcdU, thread_id); const MDRawExceptionStream* raw_exception = md_exception->exception(); - ASSERT_TRUE(raw_exception != NULL); + ASSERT_TRUE(raw_exception != nullptr); EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); EXPECT_EQ(0x0919a9b9c9d9e9f9ULL, raw_exception->exception_record.exception_address); MinidumpContext* md_context = md_exception->GetContext(); - ASSERT_TRUE(md_context != NULL); + ASSERT_TRUE(md_context != nullptr); ASSERT_EQ((uint32_t) MD_CONTEXT_ARM, md_context->GetContextCPU()); const MDRawContextARM* md_raw_context = md_context->GetContextARM(); - ASSERT_TRUE(md_raw_context != NULL); + ASSERT_TRUE(md_raw_context != nullptr); ASSERT_EQ((uint32_t) MD_CONTEXT_ARM_INTEGER, (md_raw_context->context_flags & MD_CONTEXT_ARM_INTEGER)); @@ -1512,24 +1512,24 @@ TEST(Dump, OneExceptionARMOldFlags) { ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); MinidumpException* md_exception = minidump.GetException(); - ASSERT_TRUE(md_exception != NULL); + ASSERT_TRUE(md_exception != nullptr); uint32_t thread_id; ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); ASSERT_EQ(0x1234abcdU, thread_id); const MDRawExceptionStream* raw_exception = md_exception->exception(); - ASSERT_TRUE(raw_exception != NULL); + ASSERT_TRUE(raw_exception != nullptr); EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); EXPECT_EQ(0x0919a9b9c9d9e9f9ULL, raw_exception->exception_record.exception_address); MinidumpContext* md_context = md_exception->GetContext(); - ASSERT_TRUE(md_context != NULL); + ASSERT_TRUE(md_context != nullptr); ASSERT_EQ((uint32_t) MD_CONTEXT_ARM, md_context->GetContextCPU()); const MDRawContextARM* md_raw_context = md_context->GetContextARM(); - ASSERT_TRUE(md_raw_context != NULL); + ASSERT_TRUE(md_raw_context != nullptr); ASSERT_EQ((uint32_t) MD_CONTEXT_ARM_INTEGER, (md_raw_context->context_flags & MD_CONTEXT_ARM_INTEGER)); @@ -1611,24 +1611,24 @@ TEST(Dump, OneExceptionMIPS) { ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); MinidumpException* md_exception = minidump.GetException(); - ASSERT_TRUE(md_exception != NULL); + ASSERT_TRUE(md_exception != nullptr); uint32_t thread_id; ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); ASSERT_EQ(0x1234abcdU, thread_id); const MDRawExceptionStream* raw_exception = md_exception->exception(); - ASSERT_TRUE(raw_exception != NULL); + ASSERT_TRUE(raw_exception != nullptr); EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); EXPECT_EQ(0x0919a9b9U, raw_exception->exception_record.exception_address); MinidumpContext* md_context = md_exception->GetContext(); - ASSERT_TRUE(md_context != NULL); + ASSERT_TRUE(md_context != nullptr); ASSERT_EQ((uint32_t) MD_CONTEXT_MIPS, md_context->GetContextCPU()); const MDRawContextMIPS* md_raw_context = md_context->GetContextMIPS(); - ASSERT_TRUE(md_raw_context != NULL); + ASSERT_TRUE(md_raw_context != nullptr); ASSERT_EQ((uint32_t) MD_CONTEXT_MIPS_INTEGER, (md_raw_context->context_flags & MD_CONTEXT_MIPS_INTEGER)); EXPECT_EQ(0x3ecba80dU, raw_context.iregs[0]); diff --git a/src/processor/module_comparer.cc b/src/processor/module_comparer.cc index a6413038a..ccc2e4724 100644 --- a/src/processor/module_comparer.cc +++ b/src/processor/module_comparer.cc @@ -38,6 +38,7 @@ #include "processor/module_comparer.h" #include +#include #include #include "common/scoped_ptr.h" @@ -56,8 +57,8 @@ namespace google_breakpad { bool ModuleComparer::Compare(const string& symbol_data) { - scoped_ptr basic_module(new BasicModule("test_module")); - scoped_ptr fast_module(new FastModule("test_module")); + std::unique_ptr basic_module(new BasicModule("test_module")); + std::unique_ptr fast_module(new FastModule("test_module")); // Load symbol data into basic_module scoped_array buffer(new char[symbol_data.size() + 1]); diff --git a/src/processor/module_serializer.cc b/src/processor/module_serializer.cc index 05519958f..ba374ce97 100644 --- a/src/processor/module_serializer.cc +++ b/src/processor/module_serializer.cc @@ -38,11 +38,23 @@ #include "processor/module_serializer.h" +#include +#include + #include +#include #include +#include "common/scoped_ptr.h" +#include "google_breakpad/processor/basic_source_line_resolver.h" +#include "google_breakpad/processor/code_module.h" +#include "google_breakpad/processor/fast_source_line_resolver.h" #include "processor/basic_code_module.h" +#include "processor/linked_ptr.h" #include "processor/logging.h" +#include "processor/map_serializers.h" +#include "processor/simple_serializer.h" +#include "processor/windows_frame_info.h" namespace google_breakpad { @@ -78,7 +90,7 @@ size_t ModuleSerializer::SizeOf(const BasicSourceLineResolver::Module& module) { inline_origin_serializer_.SizeOf(module.inline_origins_); // Header size. - total_size_alloc_ += kNumberMaps_ * sizeof(uint32_t); + total_size_alloc_ += kNumberMaps_ * sizeof(uint64_t); for (int i = 0; i < kNumberMaps_; ++i) { total_size_alloc_ += map_sizes_[i]; @@ -95,8 +107,8 @@ char* ModuleSerializer::Write(const BasicSourceLineResolver::Module& module, // Write the is_corrupt flag. dest = SimpleSerializer::Write(module.is_corrupt_, dest); // Write header. - memcpy(dest, map_sizes_, kNumberMaps_ * sizeof(uint32_t)); - dest += kNumberMaps_ * sizeof(uint32_t); + memcpy(dest, map_sizes_, kNumberMaps_ * sizeof(uint64_t)); + dest += kNumberMaps_ * sizeof(uint64_t); // Write each map. dest = files_serializer_.Write(module.files_, dest); dest = functions_serializer_.Write(module.functions_, dest); @@ -122,7 +134,7 @@ char* ModuleSerializer::Serialize(const BasicSourceLineResolver::Module& module, BPLOG(ERROR) << "ModuleSerializer: memory allocation failed, " << "size to alloc: " << size_to_alloc; if (size) *size = 0; - return NULL; + return nullptr; } // Write serialized data to allocated memory chunk. @@ -161,11 +173,11 @@ bool ModuleSerializer::SerializeModuleAndLoadIntoFastResolver( // Copy the data into string. // Must pass string to LoadModuleUsingMapBuffer(), instead of passing char* to - // LoadModuleUsingMemoryBuffer(), becaused of data ownership/lifetime issue. + // LoadModuleUsingMemoryBuffer(), because of data ownership/lifetime issue. string symbol_data_string(symbol_data.get(), size); symbol_data.reset(); - scoped_ptr code_module( + std::unique_ptr code_module( new BasicCodeModule(0, 0, iter->first, "", "", "", "")); return fast_resolver->LoadModuleUsingMapBuffer(code_module.get(), @@ -204,16 +216,16 @@ bool ModuleSerializer::ConvertOneModule( char* ModuleSerializer::SerializeSymbolFileData(const string& symbol_data, size_t* size) { - scoped_ptr module( + std::unique_ptr module( new BasicSourceLineResolver::Module("no name")); scoped_array buffer(new char[symbol_data.size() + 1]); memcpy(buffer.get(), symbol_data.c_str(), symbol_data.size()); buffer.get()[symbol_data.size()] = '\0'; if (!module->LoadMapFromMemory(buffer.get(), symbol_data.size() + 1)) { - return NULL; + return nullptr; } - buffer.reset(NULL); - return Serialize(*(module.get()), size); + buffer.reset(nullptr); + return Serialize(*module, size); } } // namespace google_breakpad diff --git a/src/processor/module_serializer.h b/src/processor/module_serializer.h index fd387cbbc..eefe2857d 100644 --- a/src/processor/module_serializer.h +++ b/src/processor/module_serializer.h @@ -36,6 +36,8 @@ #ifndef PROCESSOR_MODULE_SERIALIZER_H__ #define PROCESSOR_MODULE_SERIALIZER_H__ +#include + #include #include @@ -110,7 +112,7 @@ class ModuleSerializer { FastSourceLineResolver::Module::kNumberMaps_; // Memory sizes required to serialize map components in Module. - uint32_t map_sizes_[kNumberMaps_]; + uint64_t map_sizes_[kNumberMaps_]; // Serializers for each individual map component in Module class. StdMapSerializer files_serializer_; diff --git a/src/processor/postfix_evaluator-inl.h b/src/processor/postfix_evaluator-inl.h index abdf259ef..61e044e81 100644 --- a/src/processor/postfix_evaluator-inl.h +++ b/src/processor/postfix_evaluator-inl.h @@ -175,7 +175,7 @@ bool PostfixEvaluator::EvaluateToken( // The identifier must name a variable, not a constant. Variables // begin with '$'. string identifier; - if (PopValueOrIdentifier(NULL, &identifier) != POP_RESULT_IDENTIFIER) { + if (PopValueOrIdentifier(nullptr, &identifier) != POP_RESULT_IDENTIFIER) { BPLOG(ERROR) << "PopValueOrIdentifier returned a value, but an " "identifier is needed to assign " << HexString(value) << ": " << expression; @@ -254,7 +254,7 @@ bool PostfixEvaluator::EvaluateForValue(const string& expression, // Ensure that the stack is cleared before returning. AutoStackClearer clearer(&stack_); - if (!EvaluateInternal(expression, NULL)) + if (!EvaluateInternal(expression, nullptr)) return false; // A successful execution should leave exactly one value on the stack. diff --git a/src/processor/postfix_evaluator_unittest.cc b/src/processor/postfix_evaluator_unittest.cc index d3c524092..969ed0ca4 100644 --- a/src/processor/postfix_evaluator_unittest.cc +++ b/src/processor/postfix_evaluator_unittest.cc @@ -225,7 +225,7 @@ static bool RunTests() { FakeMemoryRegion fake_memory; PostfixEvaluator postfix_evaluator = - PostfixEvaluator(NULL, &fake_memory); + PostfixEvaluator(nullptr, &fake_memory); for (unsigned int evaluate_test_set_index = 0; evaluate_test_set_index < evaluate_test_set_count; diff --git a/src/processor/proc_maps_linux.cc b/src/processor/proc_maps_linux.cc index 6fcb909a1..2ab6da225 100644 --- a/src/processor/proc_maps_linux.cc +++ b/src/processor/proc_maps_linux.cc @@ -2,9 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// For PRI* macros, before anything else might #include it. #ifndef __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS -#endif +#endif /* __STDC_FORMAT_MACROS */ #ifdef HAVE_CONFIG_H #include // Must come first @@ -16,6 +17,8 @@ #include #include +#include + #include "common/using_std_string.h" #include "processor/logging.h" @@ -98,7 +101,7 @@ bool ParseProcMaps(const string& input, return false; // Pushing then assigning saves us a string copy. - regions.push_back(region); + regions.push_back(std::move(region)); regions.back().path.assign(line + path_index); regions.back().line.assign(line); } diff --git a/src/processor/process_state.cc b/src/processor/process_state.cc index c5c38b6cc..03121cb67 100644 --- a/src/processor/process_state.cc +++ b/src/processor/process_state.cc @@ -54,6 +54,7 @@ void ProcessState::Clear() { crash_address_ = 0; assertion_.clear(); requesting_thread_ = -1; + original_thread_count_ = 0; for (vector::const_iterator iterator = threads_.begin(); iterator != threads_.end(); ++iterator) { @@ -67,9 +68,9 @@ void ProcessState::Clear() { modules_without_symbols_.clear(); modules_with_corrupt_symbols_.clear(); delete modules_; - modules_ = NULL; + modules_ = nullptr; delete unloaded_modules_; - unloaded_modules_ = NULL; + unloaded_modules_ = nullptr; } } // namespace google_breakpad diff --git a/src/processor/range_map-inl.h b/src/processor/range_map-inl.h index 860314f52..e38fe50a7 100644 --- a/src/processor/range_map-inl.h +++ b/src/processor/range_map-inl.h @@ -57,7 +57,7 @@ template bool RangeMap::StoreRangeInternal( const AddressType& base, const AddressType& delta, const AddressType& size, const EntryType& entry) { - AddressType high; + AddressType high = AddressType(); bool high_ok = false; if (size > 0) { std::pair result = AddWithOverflowCheck(base, size - 1); @@ -250,7 +250,7 @@ bool RangeMap::RetrieveNearestRange( template bool RangeMap::RetrieveRangeAtIndex( - int index, EntryType* entry, AddressType* entry_base, + int64_t index, EntryType* entry, AddressType* entry_base, AddressType* entry_delta, AddressType* entry_size) const { BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveRangeAtIndex requires |entry|"; assert(entry); @@ -263,7 +263,7 @@ bool RangeMap::RetrieveRangeAtIndex( // Walk through the map. Although it's ordered, it's not a vector, so it // can't be addressed directly by index. MapConstIterator iterator = map_.begin(); - for (int this_index = 0; this_index < index; ++this_index) + for (int64_t this_index = 0; this_index < index; ++this_index) ++iterator; *entry = iterator->second.entry(); @@ -279,8 +279,8 @@ bool RangeMap::RetrieveRangeAtIndex( template -int RangeMap::GetCount() const { - return static_cast(map_.size()); +int64_t RangeMap::GetCount() const { + return static_cast(map_.size()); } diff --git a/src/processor/range_map.h b/src/processor/range_map.h index 578bd1442..05c659758 100644 --- a/src/processor/range_map.h +++ b/src/processor/range_map.h @@ -40,6 +40,7 @@ #define PROCESSOR_RANGE_MAP_H__ +#include #include @@ -109,12 +110,12 @@ class RangeMap { // entry was shrunk down (original start address was increased by delta). // // RetrieveRangeAtIndex is not optimized for speedy operation. - bool RetrieveRangeAtIndex(int index, EntryType* entry, + bool RetrieveRangeAtIndex(int64_t index, EntryType* entry, AddressType* entry_base, AddressType* entry_delta, AddressType* entry_size) const; // Returns the number of ranges stored in the RangeMap. - int GetCount() const; + int64_t GetCount() const; // Empties the range map, restoring it to the state it was when it was // initially created. diff --git a/src/processor/range_map_unittest.cc b/src/processor/range_map_unittest.cc index 8735bb095..a4634cc0e 100644 --- a/src/processor/range_map_unittest.cc +++ b/src/processor/range_map_unittest.cc @@ -30,17 +30,23 @@ // // Author: Mark Mentovai +// For PRI* macros, before anything else might #include it. +#ifndef __STDC_FORMAT_MACROS +#define __STDC_FORMAT_MACROS +#endif /* __STDC_FORMAT_MACROS */ #ifdef HAVE_CONFIG_H #include // Must come first #endif +#include #include #include +#include + #include "processor/range_map-inl.h" -#include "common/scoped_ptr.h" #include "processor/linked_ptr.h" #include "processor/logging.h" @@ -49,7 +55,6 @@ namespace { using google_breakpad::AddIgnoringOverflow; using google_breakpad::linked_ptr; using google_breakpad::RangeMap; -using google_breakpad::scoped_ptr; // A CountedObject holds an int. A global (not thread safe!) count of // allocated CountedObjects is maintained to help test memory management. @@ -274,14 +279,15 @@ static bool RetrieveTest(TestMap* range_map, const RangeTest* range_test) { // false if the test fails. static bool RetrieveIndexTest(TestMap* range_map, int set) { linked_ptr object; - CountedObject* last_object = NULL; + CountedObject* last_object = nullptr; AddressType last_base = 0; int object_count = range_map->GetCount(); for (int object_index = 0; object_index < object_count; ++object_index) { AddressType base; if (!range_map->RetrieveRangeAtIndex(object_index, &object, &base, - NULL /* delta */, NULL /* size */)) { + nullptr /* delta */, + nullptr /* size */)) { fprintf(stderr, "FAILED: RetrieveRangeAtIndex set %d index %d, " "expected success, observed failure\n", set, object_index); @@ -290,7 +296,7 @@ static bool RetrieveIndexTest(TestMap* range_map, int set) { if (!object.get()) { fprintf(stderr, "FAILED: RetrieveRangeAtIndex set %d index %d, " - "expected object, observed NULL\n", + "expected object, observed nullptr\n", set, object_index); return false; } @@ -321,8 +327,9 @@ static bool RetrieveIndexTest(TestMap* range_map, int set) { // Make sure that RetrieveRangeAtIndex doesn't allow lookups at indices that // are too high. - if (range_map->RetrieveRangeAtIndex(object_count, &object, NULL /* base */, - NULL /* delta */, NULL /* size */)) { + if (range_map->RetrieveRangeAtIndex(object_count, &object, nullptr /* base */, + nullptr /* delta */, + nullptr /* size */)) { fprintf(stderr, "FAILED: RetrieveRangeAtIndex set %d index %d (too large), " "expected failure, observed success\n", set, object_count); @@ -332,12 +339,12 @@ static bool RetrieveIndexTest(TestMap* range_map, int set) { return true; } -// Additional RetriveAtIndex test to expose the bug in RetrieveRangeAtIndex(). +// Additional RetrieveAtIndex test to expose the bug in RetrieveRangeAtIndex(). // Bug info: RetrieveRangeAtIndex() previously retrieves the high address of // entry, however, it is supposed to retrieve the base address of entry as // stated in the comment in range_map.h. -static bool RetriveAtIndexTest2() { - scoped_ptr range_map(new TestMap()); +static bool RetrieveAtIndexTest2() { + std::unique_ptr range_map(new TestMap()); // Store ranges with base address = 2 * object_id: const int range_size = 2; @@ -352,7 +359,8 @@ static bool RetriveAtIndexTest2() { for (int object_index = 0; object_index < object_count; ++object_index) { AddressType base; if (!range_map->RetrieveRangeAtIndex(object_index, &object, &base, - NULL /* delta */, NULL /* size */)) { + nullptr /* delta */, + nullptr /* size */)) { fprintf(stderr, "FAILED: RetrieveAtIndexTest2 index %d, " "expected success, observed failure\n", object_index); return false; @@ -360,7 +368,7 @@ static bool RetriveAtIndexTest2() { int expected_base = 2 * object->id(); if (base != expected_base) { - fprintf(stderr, "FAILED: RetriveAtIndexTest2 index %d, " + fprintf(stderr, "FAILED: RetrieveAtIndexTest2 index %d, " "expected base %d, observed base %d", object_index, expected_base, base); return false; @@ -463,7 +471,7 @@ static bool RunTests() { // Maintain the range map in a pointer so that deletion can be meaningfully // tested. - scoped_ptr range_map(new TestMap()); + std::unique_ptr range_map(new TestMap()); // Run all of the test sets in sequence. unsigned int range_test_set_count = sizeof(range_test_sets) / @@ -504,7 +512,7 @@ static bool RunTests() { // The RangeMap's own count of objects should also match. if (range_map->GetCount() != stored_count) { fprintf(stderr, "FAILED: stored object count doesn't match GetCount, " - "expected %d, observed %d\n", + "expected %d, observed %" PRId64 "\n", stored_count, range_map->GetCount()); return false; @@ -542,7 +550,7 @@ static bool RunTests() { } } - if (!RetriveAtIndexTest2()) { + if (!RetrieveAtIndexTest2()) { fprintf(stderr, "FAILED: did not pass RetrieveAtIndexTest2()\n"); return false; } diff --git a/src/processor/simple_serializer-inl.h b/src/processor/simple_serializer-inl.h index bc2c8def2..d3c89b368 100644 --- a/src/processor/simple_serializer-inl.h +++ b/src/processor/simple_serializer-inl.h @@ -39,7 +39,8 @@ #include "processor/simple_serializer.h" -#include +#include + #include #include "google_breakpad/processor/basic_source_line_resolver.h" @@ -192,7 +193,7 @@ class SimpleSerializer< linked_ptr > { typedef BasicSourceLineResolver::Line Line; public: static size_t SizeOf(const linked_ptr& lineptr) { - if (lineptr.get() == NULL) return 0; + if (lineptr.get() == nullptr) return 0; return SimpleSerializer::SizeOf(*(lineptr.get())); } static char* Write(const linked_ptr& lineptr, char* dest) { @@ -208,7 +209,7 @@ class SimpleSerializer> { public: static size_t SizeOf(const linked_ptr& origin_ptr) { - if (origin_ptr.get() == NULL) + if (origin_ptr.get() == nullptr) return 0; return SimpleSerializer::SizeOf(*(origin_ptr.get())); } @@ -237,7 +238,7 @@ class SimpleSerializer> { public: static size_t SizeOf(const linked_ptr& inline_ptr) { - if (inline_ptr.get() == NULL) + if (inline_ptr.get() == nullptr) return 0; return SimpleSerializer::SizeOf(*(inline_ptr.get())); } @@ -342,7 +343,7 @@ class SimpleSerializer< linked_ptr > { typedef BasicSourceLineResolver::PublicSymbol PublicSymbol; public: static size_t SizeOf(const linked_ptr& pubsymbol) { - if (pubsymbol.get() == NULL) return 0; + if (pubsymbol.get() == nullptr) return 0; return SimpleSerializer::SizeOf(*(pubsymbol.get())); } static char* Write(const linked_ptr& pubsymbol, char* dest) { @@ -356,7 +357,7 @@ template<> class SimpleSerializer< linked_ptr > { public: static size_t SizeOf(const linked_ptr& wfi) { - if (wfi.get() == NULL) return 0; + if (wfi.get() == nullptr) return 0; return SimpleSerializer::SizeOf(*(wfi.get())); } static char* Write(const linked_ptr& wfi, char* dest) { diff --git a/src/processor/simple_symbol_supplier.cc b/src/processor/simple_symbol_supplier.cc index 0de34c949..f134d10f0 100644 --- a/src/processor/simple_symbol_supplier.cc +++ b/src/processor/simple_symbol_supplier.cc @@ -114,7 +114,7 @@ SymbolSupplier::SymbolResult SimpleSymbolSupplier::GetCStringSymbolData( if (s == FOUND) { *symbol_data_size = symbol_data_string.size() + 1; *symbol_data = new char[*symbol_data_size]; - if (*symbol_data == NULL) { + if (*symbol_data == nullptr) { BPLOG(ERROR) << "Memory allocation for size " << *symbol_data_size << " failed"; return INTERRUPT; diff --git a/src/processor/source_line_resolver_base.cc b/src/processor/source_line_resolver_base.cc index da9ff7624..817ac8a01 100644 --- a/src/processor/source_line_resolver_base.cc +++ b/src/processor/source_line_resolver_base.cc @@ -70,11 +70,11 @@ SourceLineResolverBase::~SourceLineResolverBase() { } // Delete the map of modules. delete modules_; - modules_ = NULL; + modules_ = nullptr; // Delete the set of corrupt modules. delete corrupt_modules_; - corrupt_modules_ = NULL; + corrupt_modules_ = nullptr; MemoryMap::iterator iter = memory_buffers_->begin(); for (; iter != memory_buffers_->end(); ++iter) { @@ -82,16 +82,16 @@ SourceLineResolverBase::~SourceLineResolverBase() { } // Delete the map of memory buffers. delete memory_buffers_; - memory_buffers_ = NULL; + memory_buffers_ = nullptr; delete module_factory_; - module_factory_ = NULL; + module_factory_ = nullptr; } bool SourceLineResolverBase::ReadSymbolFile(const string& map_file, char** symbol_data, size_t* symbol_data_size) { - if (symbol_data == NULL || symbol_data_size == NULL) { + if (symbol_data == nullptr || symbol_data_size == nullptr) { BPLOG(ERROR) << "Could not Read file into Null memory pointer"; return false; } @@ -113,7 +113,7 @@ bool SourceLineResolverBase::ReadSymbolFile(const string& map_file, *symbol_data_size = file_size + 1; *symbol_data = new char[file_size + 1]; - if (*symbol_data == NULL) { + if (*symbol_data == nullptr) { BPLOG(ERROR) << "Could not allocate memory for " << map_file; return false; } @@ -127,7 +127,7 @@ bool SourceLineResolverBase::ReadSymbolFile(const string& map_file, BPLOG(ERROR) << "Could not open " << map_file << ", error " << error_code << ": " << error_string; delete [] (*symbol_data); - *symbol_data = NULL; + *symbol_data = nullptr; return false; } @@ -143,7 +143,7 @@ bool SourceLineResolverBase::ReadSymbolFile(const string& map_file, BPLOG(ERROR) << "Could not slurp " << map_file << ", error " << error_code << ": " << error_string; delete [] (*symbol_data); - *symbol_data = NULL; + *symbol_data = nullptr; return false; } @@ -153,7 +153,7 @@ bool SourceLineResolverBase::ReadSymbolFile(const string& map_file, bool SourceLineResolverBase::LoadModule(const CodeModule* module, const string& map_file) { - if (module == NULL) + if (module == nullptr) return false; // Make sure we don't already have a module with the given name. @@ -193,7 +193,7 @@ bool SourceLineResolverBase::LoadModuleUsingMapBuffer( BPLOG(INFO) << "SourceLineResolverBase::LoadModuleUsingMapBuffer(module = " << module->code_file() << ", map_buffer.size() = " << map_buffer.size() << ")"; - if (module == NULL) + if (module == nullptr) return false; // Make sure we don't already have a module with the given name. @@ -205,7 +205,7 @@ bool SourceLineResolverBase::LoadModuleUsingMapBuffer( size_t memory_buffer_size = map_buffer.size() + 1; char* memory_buffer = new char[memory_buffer_size]; - if (memory_buffer == NULL) { + if (memory_buffer == nullptr) { BPLOG(ERROR) << "Could not allocate memory for " << module->code_file(); return false; } @@ -253,7 +253,6 @@ bool SourceLineResolverBase::LoadModuleUsingMemoryBuffer( // Returning false from here would be an indication that the symbols for // this module are missing which would be wrong. Intentionally fall through // and add the module to both the modules_ and the corrupt_modules_ lists. - assert(basic_module->IsCorrupt()); } modules_->insert(make_pair(module->code_file(), basic_module)); @@ -322,7 +321,7 @@ WindowsFrameInfo* SourceLineResolverBase::FindWindowsFrameInfo( return it->second->FindWindowsFrameInfo(frame); } } - return NULL; + return nullptr; } CFIFrameInfo* SourceLineResolverBase::FindCFIFrameInfo( @@ -333,7 +332,7 @@ CFIFrameInfo* SourceLineResolverBase::FindCFIFrameInfo( return it->second->FindCFIFrameInfo(frame); } } - return NULL; + return nullptr; } bool SourceLineResolverBase::CompareString::operator()( diff --git a/src/processor/stack_frame_symbolizer.cc b/src/processor/stack_frame_symbolizer.cc index 3afd471b8..f54653c26 100644 --- a/src/processor/stack_frame_symbolizer.cc +++ b/src/processor/stack_frame_symbolizer.cc @@ -39,7 +39,6 @@ #include -#include "common/scoped_ptr.h" #include "google_breakpad/processor/code_module.h" #include "google_breakpad/processor/code_modules.h" #include "google_breakpad/processor/source_line_resolver_interface.h" @@ -64,7 +63,7 @@ StackFrameSymbolizer::SymbolizerResult StackFrameSymbolizer::FillSourceLineInfo( std::deque>* inlined_frames) { assert(frame); - const CodeModule* module = NULL; + const CodeModule* module = nullptr; if (modules) { module = modules->GetModuleForAddress(frame->instruction); } @@ -96,7 +95,7 @@ StackFrameSymbolizer::SymbolizerResult StackFrameSymbolizer::FillSourceLineInfo( // Start fetching symbol from supplier. string symbol_file; - char* symbol_data = NULL; + char* symbol_data = nullptr; size_t symbol_data_size; SymbolSupplier::SymbolResult symbol_result = supplier_->GetCStringSymbolData( module, system_info, &symbol_file, &symbol_data, &symbol_data_size); @@ -138,12 +137,12 @@ StackFrameSymbolizer::SymbolizerResult StackFrameSymbolizer::FillSourceLineInfo( WindowsFrameInfo* StackFrameSymbolizer::FindWindowsFrameInfo( const StackFrame* frame) { - return resolver_ ? resolver_->FindWindowsFrameInfo(frame) : NULL; + return resolver_ ? resolver_->FindWindowsFrameInfo(frame) : nullptr; } CFIFrameInfo* StackFrameSymbolizer::FindCFIFrameInfo( const StackFrame* frame) { - return resolver_ ? resolver_->FindCFIFrameInfo(frame) : NULL; + return resolver_ ? resolver_->FindCFIFrameInfo(frame) : nullptr; } } // namespace google_breakpad diff --git a/src/processor/stackwalk_common.cc b/src/processor/stackwalk_common.cc index 688b27823..809836151 100644 --- a/src/processor/stackwalk_common.cc +++ b/src/processor/stackwalk_common.cc @@ -1112,7 +1112,7 @@ static void PrintModulesMachineReadable(const CodeModules* modules) { kOutputSeparator, base_address, kOutputSeparator, base_address + module->size() - 1, kOutputSeparator, - main_module != NULL && base_address == main_address ? 1 : 0); + main_module != nullptr && base_address == main_address ? 1 : 0); } } diff --git a/src/processor/stackwalker.cc b/src/processor/stackwalker.cc index 1ff6cf7cb..e84845ec0 100644 --- a/src/processor/stackwalker.cc +++ b/src/processor/stackwalker.cc @@ -40,7 +40,8 @@ #include -#include "common/scoped_ptr.h" +#include + #include "google_breakpad/processor/call_stack.h" #include "google_breakpad/processor/code_module.h" #include "google_breakpad/processor/code_modules.h" @@ -82,7 +83,7 @@ Stackwalker::Stackwalker(const SystemInfo* system_info, : system_info_(system_info), memory_(memory), modules_(modules), - unloaded_modules_(NULL), + unloaded_modules_(nullptr), frame_symbolizer_(frame_symbolizer) { assert(frame_symbolizer_); } @@ -136,7 +137,7 @@ bool Stackwalker::Walk( uint32_t scanned_frames = 0; // Take ownership of the pointer returned by GetContextFrame. - scoped_ptr frame(GetContextFrame()); + std::unique_ptr frame(GetContextFrame()); while (frame.get()) { // frame already contains a good frame with properly set instruction and @@ -214,10 +215,10 @@ Stackwalker* Stackwalker::StackwalkerForCPU( StackFrameSymbolizer* frame_symbolizer) { if (!context) { BPLOG(ERROR) << "Can't choose a stackwalker implementation without context"; - return NULL; + return nullptr; } - Stackwalker* cpu_stackwalker = NULL; + Stackwalker* cpu_stackwalker = nullptr; uint32_t cpu = context->GetContextCPU(); switch (cpu) { diff --git a/src/processor/stackwalker_address_list.cc b/src/processor/stackwalker_address_list.cc index 7c346c665..a4951ebc1 100644 --- a/src/processor/stackwalker_address_list.cc +++ b/src/processor/stackwalker_address_list.cc @@ -54,40 +54,37 @@ StackwalkerAddressList::StackwalkerAddressList( size_t frame_count, const CodeModules* modules, StackFrameSymbolizer* frame_symbolizer) - : Stackwalker(NULL, NULL, modules, frame_symbolizer), + : Stackwalker(nullptr, nullptr, modules, frame_symbolizer), frames_(frames), - frame_count_(frame_count) { + frame_count_(frame_count), + next_frame_index_(0) { assert(frames); assert(frame_symbolizer); } StackFrame* StackwalkerAddressList::GetContextFrame() { if (frame_count_ == 0) - return NULL; + return nullptr; StackFrame* frame = new StackFrame(); frame->instruction = frames_[0]; frame->trust = StackFrame::FRAME_TRUST_PREWALKED; + + next_frame_index_ = 1; + return frame; } -StackFrame* StackwalkerAddressList::GetCallerFrame(const CallStack* stack, +StackFrame* StackwalkerAddressList::GetCallerFrame(const CallStack*, bool stack_scan_allowed) { - if (!stack) { - BPLOG(ERROR) << "Can't get caller frame without stack"; - return NULL; - } - - size_t frame_index = stack->frames()->size(); - // There are no more frames to fetch. - if (frame_index >= frame_count_) - return NULL; + if (next_frame_index_ >= frame_count_) + return nullptr; // All frames have the highest level of trust because they were // explicitly provided. StackFrame* frame = new StackFrame(); - frame->instruction = frames_[frame_index]; + frame->instruction = frames_[next_frame_index_++]; frame->trust = StackFrame::FRAME_TRUST_PREWALKED; return frame; } diff --git a/src/processor/stackwalker_address_list.h b/src/processor/stackwalker_address_list.h index d27f3fb2d..b024d2ca6 100644 --- a/src/processor/stackwalker_address_list.h +++ b/src/processor/stackwalker_address_list.h @@ -63,6 +63,7 @@ class StackwalkerAddressList : public Stackwalker { const uint64_t* frames_; size_t frame_count_; + size_t next_frame_index_; }; } // namespace google_breakpad diff --git a/src/processor/stackwalker_address_list_unittest.cc b/src/processor/stackwalker_address_list_unittest.cc index 1b5a4fc79..1da0b17b2 100644 --- a/src/processor/stackwalker_address_list_unittest.cc +++ b/src/processor/stackwalker_address_list_unittest.cc @@ -101,24 +101,38 @@ class StackwalkerAddressListTest : public testing::Test { void SetModuleSymbols(MockCodeModule* module, const string& info) { size_t buffer_size; char* buffer = supplier.CopySymbolDataAndOwnTheCopy(info, &buffer_size); - EXPECT_CALL(supplier, GetCStringSymbolData(module, NULL, _, _, _)) + EXPECT_CALL(supplier, GetCStringSymbolData(module, nullptr, _, _, _)) .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer), SetArgumentPointee<4>(buffer_size), Return(MockSymbolSupplier::FOUND))); } - void CheckCallStack(const CallStack& call_stack) { + void CheckCallStack(const CallStack& call_stack, bool allow_inline=false) { const std::vector* frames = call_stack.frames(); - ASSERT_EQ(arraysize(kDummyFrames), frames->size()); - for (size_t i = 0; i < arraysize(kDummyFrames); ++i) { - ASSERT_EQ(kDummyFrames[i], frames->at(i)->instruction); - ASSERT_EQ(StackFrame::FRAME_TRUST_PREWALKED, frames->at(i)->trust); + ASSERT_LE(arraysize(kDummyFrames), frames->size()); + + // Iterate through the produced stack frames, validating that all of the + // prewalked frames match the expected input frames. Inlined frames are only + // allowed if `allow_inline` is set to true. + + size_t j = 0; + for (size_t i = 0; i < frames->size(); ++i) { + if (j <= 2) { + ASSERT_EQ(static_cast(&module2), frames->at(i)->module); + } else { + ASSERT_EQ(static_cast(&module1), frames->at(i)->module); + } + + ASSERT_EQ(kDummyFrames[j], frames->at(i)->instruction); + if (frames->at(i)->trust == StackFrame::FRAME_TRUST_PREWALKED) { + // Only move on to the next "real" stack frame if this isn't an + // inlined stack frame. + ++j; + } else { + ASSERT_TRUE(allow_inline); + ASSERT_EQ(StackFrame::FRAME_TRUST_INLINE, frames->at(i)->trust); + } } - ASSERT_EQ(static_cast(&module2), frames->at(0)->module); - ASSERT_EQ(static_cast(&module2), frames->at(1)->module); - ASSERT_EQ(static_cast(&module2), frames->at(2)->module); - ASSERT_EQ(static_cast(&module1), frames->at(3)->module); - ASSERT_EQ(static_cast(&module1), frames->at(4)->module); } MockCodeModule module1; @@ -199,3 +213,80 @@ TEST_F(StackwalkerAddressListTest, ScanWithSymbols) { ASSERT_EQ("mod1func1", frames->at(4)->function_name); ASSERT_EQ(0x40001000u, frames->at(4)->function_base); } + +TEST_F(StackwalkerAddressListTest, ScanWithInlining) { + // File : FILE number(dex) name + // Function: FUNC address(hex) size(hex) parameter_size(hex) name + // Inline: : INLINE_ORIGIN number(dec) name + // : INLINE depth(dec) line(dec) filenum(dec) inlinenum(dec) + // address(hex) size(hex) + // Line : address(hex) size(hex) line(dec) filenum(dec) + SetModuleSymbols(&module2, + "FILE 1 module2.cc\n" + "INLINE_ORIGIN 0 mod2inlinefunc1\n" + "INLINE_ORIGIN 1 mod2inlinefunc2\n" + "INLINE_ORIGIN 2 mod2inlinefunc3\n" + "FUNC 3000 100 10 mod2func3\n" + "INLINE 0 1 1 1 3000 10\n" + "INLINE 1 1 1 2 3000 10\n" + "3000 10 1 1\n" + "FUNC 2000 200 10 mod2func2\n" + "INLINE 0 1 1 0 2000 10\n" + "FUNC 1000 300 10 mod2func1\n"); + SetModuleSymbols(&module1, + "FUNC 2000 200 10 mod1func2\n" + "FUNC 1000 300 10 mod1func1\n"); + + StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); + StackwalkerAddressList walker(kDummyFrames, arraysize(kDummyFrames), + &modules, &frame_symbolizer); + + CallStack call_stack; + vector modules_without_symbols; + vector modules_with_corrupt_symbols; + ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, + &modules_with_corrupt_symbols)); + + ASSERT_EQ(0u, modules_without_symbols.size()); + ASSERT_EQ(0u, modules_with_corrupt_symbols.size()); + + ASSERT_NO_FATAL_FAILURE(CheckCallStack(call_stack, /*allow_inline=*/true)); + + const std::vector* frames = call_stack.frames(); + + // We have full file/line information for the first function call, including + // inline functions + ASSERT_EQ("mod2inlinefunc3", frames->at(0)->function_name); + ASSERT_EQ(0x50003000u, frames->at(0)->function_base); + ASSERT_EQ("module2.cc", frames->at(0)->source_file_name); + ASSERT_EQ(1, frames->at(0)->source_line); + ASSERT_EQ(0x50003000u, frames->at(0)->source_line_base); + + ASSERT_EQ("mod2inlinefunc2", frames->at(1)->function_name); + ASSERT_EQ(0x50003000u, frames->at(1)->function_base); + ASSERT_EQ("module2.cc", frames->at(1)->source_file_name); + ASSERT_EQ(1, frames->at(1)->source_line); + ASSERT_EQ(0x50003000u, frames->at(1)->source_line_base); + + ASSERT_EQ("mod2func3", frames->at(2)->function_name); + ASSERT_EQ(0x50003000u, frames->at(2)->function_base); + ASSERT_EQ("module2.cc", frames->at(2)->source_file_name); + ASSERT_EQ(1, frames->at(2)->source_line); + ASSERT_EQ(0x50003000u, frames->at(2)->source_line_base); + + // Here we have inlining information, but no file/line information. + ASSERT_EQ("mod2inlinefunc1", frames->at(3)->function_name); + ASSERT_EQ(0x50002000u, frames->at(3)->function_base); + + ASSERT_EQ("mod2func2", frames->at(4)->function_name); + ASSERT_EQ(0x50002000u, frames->at(4)->function_base); + + ASSERT_EQ("mod2func1", frames->at(5)->function_name); + ASSERT_EQ(0x50001000u, frames->at(5)->function_base); + + ASSERT_EQ("mod1func2", frames->at(6)->function_name); + ASSERT_EQ(0x40002000u, frames->at(6)->function_base); + + ASSERT_EQ("mod1func1", frames->at(7)->function_name); + ASSERT_EQ(0x40001000u, frames->at(7)->function_base); +} diff --git a/src/processor/stackwalker_amd64.cc b/src/processor/stackwalker_amd64.cc index b934e73b4..5a397fce5 100644 --- a/src/processor/stackwalker_amd64.cc +++ b/src/processor/stackwalker_amd64.cc @@ -38,7 +38,8 @@ #include -#include "common/scoped_ptr.h" +#include + #include "google_breakpad/processor/call_stack.h" #include "google_breakpad/processor/memory_region.h" #include "google_breakpad/processor/source_line_resolver_interface.h" @@ -58,37 +59,37 @@ StackwalkerAMD64::cfi_register_map_[] = { // flags here really means that the walker should assume they're // unchanged if the CFI doesn't mention them --- clearly wrong for $rip // and $rsp. - { "$rax", NULL, false, + { "$rax", nullptr, false, StackFrameAMD64::CONTEXT_VALID_RAX, &MDRawContextAMD64::rax }, - { "$rdx", NULL, false, + { "$rdx", nullptr, false, StackFrameAMD64::CONTEXT_VALID_RDX, &MDRawContextAMD64::rdx }, - { "$rcx", NULL, false, + { "$rcx", nullptr, false, StackFrameAMD64::CONTEXT_VALID_RCX, &MDRawContextAMD64::rcx }, - { "$rbx", NULL, true, + { "$rbx", nullptr, true, StackFrameAMD64::CONTEXT_VALID_RBX, &MDRawContextAMD64::rbx }, - { "$rsi", NULL, false, + { "$rsi", nullptr, false, StackFrameAMD64::CONTEXT_VALID_RSI, &MDRawContextAMD64::rsi }, - { "$rdi", NULL, false, + { "$rdi", nullptr, false, StackFrameAMD64::CONTEXT_VALID_RDI, &MDRawContextAMD64::rdi }, - { "$rbp", NULL, true, + { "$rbp", nullptr, true, StackFrameAMD64::CONTEXT_VALID_RBP, &MDRawContextAMD64::rbp }, { "$rsp", ".cfa", false, StackFrameAMD64::CONTEXT_VALID_RSP, &MDRawContextAMD64::rsp }, - { "$r8", NULL, false, + { "$r8", nullptr, false, StackFrameAMD64::CONTEXT_VALID_R8, &MDRawContextAMD64::r8 }, - { "$r9", NULL, false, + { "$r9", nullptr, false, StackFrameAMD64::CONTEXT_VALID_R9, &MDRawContextAMD64::r9 }, - { "$r10", NULL, false, + { "$r10", nullptr, false, StackFrameAMD64::CONTEXT_VALID_R10, &MDRawContextAMD64::r10 }, - { "$r11", NULL, false, + { "$r11", nullptr, false, StackFrameAMD64::CONTEXT_VALID_R11, &MDRawContextAMD64::r11 }, - { "$r12", NULL, true, + { "$r12", nullptr, true, StackFrameAMD64::CONTEXT_VALID_R12, &MDRawContextAMD64::r12 }, - { "$r13", NULL, true, + { "$r13", nullptr, true, StackFrameAMD64::CONTEXT_VALID_R13, &MDRawContextAMD64::r13 }, - { "$r14", NULL, true, + { "$r14", nullptr, true, StackFrameAMD64::CONTEXT_VALID_R14, &MDRawContextAMD64::r14 }, - { "$r15", NULL, true, + { "$r15", nullptr, true, StackFrameAMD64::CONTEXT_VALID_R15, &MDRawContextAMD64::r15 }, { "$rip", ".ra", false, StackFrameAMD64::CONTEXT_VALID_RIP, &MDRawContextAMD64::rip }, @@ -113,7 +114,7 @@ uint64_t StackFrameAMD64::ReturnAddress() const { StackFrame* StackwalkerAMD64::GetContextFrame() { if (!context_) { BPLOG(ERROR) << "Can't get context frame without context"; - return NULL; + return nullptr; } StackFrameAMD64* frame = new StackFrameAMD64(); @@ -133,22 +134,21 @@ StackFrameAMD64* StackwalkerAMD64::GetCallerByCFIFrameInfo( CFIFrameInfo* cfi_frame_info) { StackFrameAMD64* last_frame = static_cast(frames.back()); - scoped_ptr frame(new StackFrameAMD64()); + std::unique_ptr frame(new StackFrameAMD64()); if (!cfi_walker_ .FindCallerRegisters(*memory_, *cfi_frame_info, last_frame->context, last_frame->context_validity, &frame->context, &frame->context_validity)) - return NULL; + return nullptr; // Make sure we recovered all the essentials. static const int essentials = (StackFrameAMD64::CONTEXT_VALID_RIP | StackFrameAMD64::CONTEXT_VALID_RSP); if ((frame->context_validity & essentials) != essentials) - return NULL; + return nullptr; if (!frame->context.rip || !frame->context.rsp) { - BPLOG(ERROR) << "invalid rip/rsp"; - return NULL; + return nullptr; } frame->trust = StackFrame::FRAME_TRUST_CFI; @@ -184,7 +184,7 @@ StackFrameAMD64* StackwalkerAMD64::GetCallerByFramePointerRecovery( // If rbp is not 8-byte aligned it can't be a frame pointer. if (last_rbp % 8 != 0) { - return NULL; + return nullptr; } uint64_t caller_rip, caller_rbp; @@ -195,18 +195,18 @@ StackFrameAMD64* StackwalkerAMD64::GetCallerByFramePointerRecovery( // If the recovered rip is not a canonical address it can't be // the return address, so rbp must not have been a frame pointer. if (is_non_canonical(caller_rip)) { - return NULL; + return nullptr; } // Check that rbp is within the right frame if (caller_rsp <= last_rbp || caller_rbp < caller_rsp) { - return NULL; + return nullptr; } // Sanity check that resulting rbp is still inside stack memory. uint64_t unused; if (!memory_->GetMemoryAtAddress(caller_rbp, &unused)) { - return NULL; + return nullptr; } StackFrameAMD64* frame = new StackFrameAMD64(); @@ -221,7 +221,7 @@ StackFrameAMD64* StackwalkerAMD64::GetCallerByFramePointerRecovery( return frame; } - return NULL; + return nullptr; } StackFrameAMD64* StackwalkerAMD64::GetCallerBySimulatingReturn( @@ -235,7 +235,7 @@ StackFrameAMD64* StackwalkerAMD64::GetCallerBySimulatingReturn( searchwords)) { // No plausible return address at the top of the stack. Unable to simulate // a return. - return NULL; + return nullptr; } // Create a new stack frame (ownership will be transferred to the caller) @@ -263,7 +263,7 @@ StackFrameAMD64* StackwalkerAMD64::GetCallerByStackScan( /*is_context_frame=*/last_frame->trust == StackFrame::FRAME_TRUST_CONTEXT)) { // No plausible return address was found. - return NULL; + return nullptr; } // Create a new stack frame (ownership will be transferred to the caller) @@ -308,15 +308,15 @@ StackFrame* StackwalkerAMD64::GetCallerFrame(const CallStack* stack, bool stack_scan_allowed) { if (!memory_ || !stack) { BPLOG(ERROR) << "Can't get caller frame without memory or stack"; - return NULL; + return nullptr; } const vector& frames = *stack->frames(); StackFrameAMD64* last_frame = static_cast(frames.back()); - scoped_ptr new_frame; + std::unique_ptr new_frame; // If we have CFI information, use it. - scoped_ptr cfi_frame_info( + std::unique_ptr cfi_frame_info( frame_symbolizer_->FindCFIFrameInfo(last_frame)); if (cfi_frame_info.get()) new_frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get())); @@ -347,7 +347,7 @@ StackFrame* StackwalkerAMD64::GetCallerFrame(const CallStack* stack, // If nothing worked, tell the caller. if (!new_frame.get()) - return NULL; + return nullptr; if (system_info_->os_short == "nacl") { // Apply constraints from Native Client's x86-64 sandbox. These @@ -364,7 +364,7 @@ StackFrame* StackwalkerAMD64::GetCallerFrame(const CallStack* stack, last_frame->context.rsp, /*first_unwind=*/last_frame->trust == StackFrame::FRAME_TRUST_CONTEXT)) { - return NULL; + return nullptr; } // new_frame->context.rip is the return address, which is the instruction diff --git a/src/processor/stackwalker_amd64_unittest.cc b/src/processor/stackwalker_amd64_unittest.cc index 88f6ef7f0..824e9a8f8 100644 --- a/src/processor/stackwalker_amd64_unittest.cc +++ b/src/processor/stackwalker_amd64_unittest.cc @@ -156,7 +156,7 @@ TEST_F(SanityCheck, NoResolver) { raw_context.rip = 0x00007400c0000200ULL; raw_context.rbp = 0x8000000080000000ULL; - StackFrameSymbolizer frame_symbolizer(NULL, NULL); + StackFrameSymbolizer frame_symbolizer(nullptr, nullptr); StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); // This should succeed even without a resolver or supplier. @@ -208,7 +208,7 @@ TEST_F(GetContextFrame, NoStackMemory) { raw_context.rbp = 0x8000000080000000ULL; StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerAMD64 walker(&system_info, &raw_context, NULL, &modules, + StackwalkerAMD64 walker(&system_info, &raw_context, nullptr, &modules, &frame_symbolizer); vector modules_without_symbols; vector modules_with_corrupt_symbols; diff --git a/src/processor/stackwalker_arm.cc b/src/processor/stackwalker_arm.cc index 5f6f3e8da..87c928144 100644 --- a/src/processor/stackwalker_arm.cc +++ b/src/processor/stackwalker_arm.cc @@ -36,9 +36,9 @@ #include // Must come first #endif +#include #include -#include "common/scoped_ptr.h" #include "google_breakpad/processor/call_stack.h" #include "google_breakpad/processor/memory_region.h" #include "google_breakpad/processor/source_line_resolver_interface.h" @@ -65,7 +65,7 @@ StackwalkerARM::StackwalkerARM(const SystemInfo* system_info, StackFrame* StackwalkerARM::GetContextFrame() { if (!context_) { BPLOG(ERROR) << "Can't get context frame without context"; - return NULL; + return nullptr; } StackFrameARM* frame = new StackFrameARM(); @@ -90,7 +90,7 @@ StackFrameARM* StackwalkerARM::GetCallerByCFIFrameInfo( "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "fps", "cpsr", - NULL + nullptr }; // Populate a dictionary with the valid register values in last_frame. @@ -103,10 +103,10 @@ StackFrameARM* StackwalkerARM::GetCallerByCFIFrameInfo( CFIFrameInfo::RegisterValueMap caller_registers; if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_, &caller_registers)) - return NULL; + return nullptr; // Construct a new stack frame given the values the CFI recovered. - scoped_ptr frame(new StackFrameARM()); + std::unique_ptr frame(new StackFrameARM()); for (int i = 0; register_names[i]; i++) { CFIFrameInfo::RegisterValueMap::iterator entry = caller_registers.find(register_names[i]); @@ -158,7 +158,7 @@ StackFrameARM* StackwalkerARM::GetCallerByCFIFrameInfo( static const int essentials = (StackFrameARM::CONTEXT_VALID_SP | StackFrameARM::CONTEXT_VALID_PC); if ((frame->context_validity & essentials) != essentials) - return NULL; + return nullptr; frame->trust = StackFrame::FRAME_TRUST_CFI; return frame.release(); @@ -174,7 +174,7 @@ StackFrameARM* StackwalkerARM::GetCallerByStackScan( /*is_context_frame=*/last_frame->trust == StackFrame::FRAME_TRUST_CONTEXT)) { // No plausible return address was found. - return NULL; + return nullptr; } // ScanForReturnAddress found a reasonable return address. Advance @@ -202,7 +202,7 @@ StackFrameARM* StackwalkerARM::GetCallerByFramePointer( if (!(last_frame->context_validity & StackFrameARM::RegisterValidFlag(fp_register_))) { - return NULL; + return nullptr; } uint32_t last_fp = last_frame->context.iregs[fp_register_]; @@ -211,14 +211,14 @@ StackFrameARM* StackwalkerARM::GetCallerByFramePointer( if (last_fp && !memory_->GetMemoryAtAddress(last_fp, &caller_fp)) { BPLOG(ERROR) << "Unable to read caller_fp from last_fp: 0x" << std::hex << last_fp; - return NULL; + return nullptr; } uint32_t caller_lr = 0; if (last_fp && !memory_->GetMemoryAtAddress(last_fp + 4, &caller_lr)) { BPLOG(ERROR) << "Unable to read caller_lr from last_fp + 4: 0x" << std::hex << (last_fp + 4); - return NULL; + return nullptr; } uint32_t caller_sp = last_fp ? last_fp + 8 : @@ -246,18 +246,18 @@ StackFrame* StackwalkerARM::GetCallerFrame(const CallStack* stack, bool stack_scan_allowed) { if (!memory_ || !stack) { BPLOG(ERROR) << "Can't get caller frame without memory or stack"; - return NULL; + return nullptr; } const vector& frames = *stack->frames(); StackFrameARM* last_frame = static_cast(frames.back()); - scoped_ptr frame; + std::unique_ptr frame; // See if there is DWARF call frame information covering this address. // TODO(jperaza): Ignore iOS CFI info until it is properly collected. // https://bugs.chromium.org/p/google-breakpad/issues/detail?id=764 if (!system_info_ || system_info_->os != "iOS") { - scoped_ptr cfi_frame_info( + std::unique_ptr cfi_frame_info( frame_symbolizer_->FindCFIFrameInfo(last_frame)); if (cfi_frame_info.get()) frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get())); @@ -274,7 +274,7 @@ StackFrame* StackwalkerARM::GetCallerFrame(const CallStack* stack, // If nothing worked, tell the caller. if (!frame.get()) - return NULL; + return nullptr; // Should we terminate the stack walk? (end-of-stack or broken invariant) if (TerminateWalk(frame->context.iregs[MD_CONTEXT_ARM_REG_PC], @@ -282,7 +282,7 @@ StackFrame* StackwalkerARM::GetCallerFrame(const CallStack* stack, last_frame->context.iregs[MD_CONTEXT_ARM_REG_SP], /*first_unwind=*/last_frame->trust == StackFrame::FRAME_TRUST_CONTEXT)) { - return NULL; + return nullptr; } // The new frame's context's PC is the return address, which is one diff --git a/src/processor/stackwalker_arm64.cc b/src/processor/stackwalker_arm64.cc index 0fa02e04f..a174fb5b2 100644 --- a/src/processor/stackwalker_arm64.cc +++ b/src/processor/stackwalker_arm64.cc @@ -36,16 +36,19 @@ #include // Must come first #endif +#include "processor/stackwalker_arm64.h" + +#include + +#include #include -#include "common/scoped_ptr.h" #include "google_breakpad/processor/call_stack.h" #include "google_breakpad/processor/memory_region.h" #include "google_breakpad/processor/source_line_resolver_interface.h" #include "google_breakpad/processor/stack_frame_cpu.h" #include "processor/cfi_frame_info.h" #include "processor/logging.h" -#include "processor/stackwalker_arm64.h" namespace google_breakpad { @@ -84,7 +87,7 @@ uint64_t StackwalkerARM64::PtrauthStrip(uint64_t ptr) { StackFrame* StackwalkerARM64::GetContextFrame() { if (!context_) { BPLOG(ERROR) << "Can't get context frame without context"; - return NULL; + return nullptr; } StackFrameARM64* frame = new StackFrameARM64(); @@ -111,7 +114,7 @@ StackFrameARM64* StackwalkerARM64::GetCallerByCFIFrameInfo( "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "sp", - "pc", NULL + "pc", nullptr }; // Populate a dictionary with the valid register values in last_frame. @@ -125,10 +128,10 @@ StackFrameARM64* StackwalkerARM64::GetCallerByCFIFrameInfo( CFIFrameInfo::RegisterValueMap caller_registers; if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_, &caller_registers)) { - return NULL; + return nullptr; } // Construct a new stack frame given the values the CFI recovered. - scoped_ptr frame(new StackFrameARM64()); + std::unique_ptr frame(new StackFrameARM64()); for (int i = 0; register_names[i]; i++) { CFIFrameInfo::RegisterValueMap::iterator entry = caller_registers.find(register_names[i]); @@ -171,7 +174,7 @@ StackFrameARM64* StackwalkerARM64::GetCallerByCFIFrameInfo( static const uint64_t essentials = (StackFrameARM64::CONTEXT_VALID_SP | StackFrameARM64::CONTEXT_VALID_PC); if ((frame->context_validity & essentials) != essentials) - return NULL; + return nullptr; frame->context.iregs[MD_CONTEXT_ARM64_REG_PC] = PtrauthStrip(frame->context.iregs[MD_CONTEXT_ARM64_REG_PC]); @@ -189,7 +192,7 @@ StackFrameARM64* StackwalkerARM64::GetCallerByStackScan( /*is_context_frame=*/last_frame->trust == StackFrame::FRAME_TRUST_CONTEXT)) { // No plausible return address was found. - return NULL; + return nullptr; } // ScanForReturnAddress found a reasonable return address. Advance @@ -224,14 +227,14 @@ StackFrameARM64* StackwalkerARM64::GetCallerByFramePointer( if (last_fp && !memory_->GetMemoryAtAddress(last_fp, &caller_fp)) { BPLOG(ERROR) << "Unable to read caller_fp from last_fp: 0x" << std::hex << last_fp; - return NULL; + return nullptr; } uint64_t caller_lr = 0; if (last_fp && !memory_->GetMemoryAtAddress(last_fp + 8, &caller_lr)) { BPLOG(ERROR) << "Unable to read caller_lr from last_fp + 8: 0x" << std::hex << (last_fp + 8); - return NULL; + return nullptr; } caller_lr = PtrauthStrip(caller_lr); @@ -269,11 +272,15 @@ void StackwalkerARM64::CorrectRegLRByFramePointer( // Searching for a real callee frame. Skipping inline frames since they // don't contain context (and cannot be downcasted to StackFrameARM64). - size_t last_frame_callee_id = frames.size() - 2; + int64_t last_frame_callee_id = frames.size() - 2; while (last_frame_callee_id >= 0 && frames[last_frame_callee_id]->trust == StackFrame::FRAME_TRUST_INLINE) { last_frame_callee_id--; } + // last_frame_callee_id should not become negative because at the top of the + // stack trace we always have a context frame (FRAME_TRUST_CONTEXT) so the + // above loop should end before last_frame_callee_id gets negative. But we are + // being extra defensive here and bail if it ever becomes negative. if (last_frame_callee_id < 0) return; StackFrameARM64* last_frame_callee = static_cast(frames[last_frame_callee_id]); @@ -284,8 +291,6 @@ void StackwalkerARM64::CorrectRegLRByFramePointer( uint64_t last_fp = 0; if (last_frame_callee_fp && !memory_->GetMemoryAtAddress(last_frame_callee_fp, &last_fp)) { - BPLOG(ERROR) << "Unable to read last_fp from last_last_fp: 0x" << std::hex - << last_frame_callee_fp; return; } // Give up if STACK CFI doesn't agree with frame pointer. @@ -308,15 +313,15 @@ StackFrame* StackwalkerARM64::GetCallerFrame(const CallStack* stack, bool stack_scan_allowed) { if (!memory_ || !stack) { BPLOG(ERROR) << "Can't get caller frame without memory or stack"; - return NULL; + return nullptr; } const vector& frames = *stack->frames(); StackFrameARM64* last_frame = static_cast(frames.back()); - scoped_ptr frame; + std::unique_ptr frame; // See if there is DWARF call frame information covering this address. - scoped_ptr cfi_frame_info( + std::unique_ptr cfi_frame_info( frame_symbolizer_->FindCFIFrameInfo(last_frame)); if (cfi_frame_info.get()) frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get())); @@ -331,7 +336,7 @@ StackFrame* StackwalkerARM64::GetCallerFrame(const CallStack* stack, // If nothing worked, tell the caller. if (!frame.get()) - return NULL; + return nullptr; // Should we terminate the stack walk? (end-of-stack or broken invariant) if (TerminateWalk(frame->context.iregs[MD_CONTEXT_ARM64_REG_PC], @@ -339,7 +344,7 @@ StackFrame* StackwalkerARM64::GetCallerFrame(const CallStack* stack, last_frame->context.iregs[MD_CONTEXT_ARM64_REG_SP], /*first_unwind=*/last_frame->trust == StackFrame::FRAME_TRUST_CONTEXT)) { - return NULL; + return nullptr; } // The new frame's context's PC is the return address, which is one diff --git a/src/processor/stackwalker_arm64.h b/src/processor/stackwalker_arm64.h index 193ab302a..933b557ff 100644 --- a/src/processor/stackwalker_arm64.h +++ b/src/processor/stackwalker_arm64.h @@ -41,6 +41,7 @@ #include "google_breakpad/common/breakpad_types.h" #include "google_breakpad/common/minidump_format.h" +#include "google_breakpad/processor/stack_frame_cpu.h" #include "google_breakpad/processor/stackwalker.h" namespace google_breakpad { diff --git a/src/processor/stackwalker_arm64_unittest.cc b/src/processor/stackwalker_arm64_unittest.cc index f302d7d56..24c3527db 100644 --- a/src/processor/stackwalker_arm64_unittest.cc +++ b/src/processor/stackwalker_arm64_unittest.cc @@ -150,7 +150,7 @@ class SanityCheck: public StackwalkerARM64Fixture, public Test { }; TEST_F(SanityCheck, NoResolver) { // Since the context's frame pointer is garbage, the stack walk will end after // the first frame. - StackFrameSymbolizer frame_symbolizer(NULL, NULL); + StackFrameSymbolizer frame_symbolizer(nullptr, nullptr); StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); // This should succeed even without a resolver or supplier. @@ -174,7 +174,7 @@ class GetContextFrame: public StackwalkerARM64Fixture, public Test { }; // without stack memory present. TEST_F(GetContextFrame, NoStackMemory) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerARM64 walker(&system_info, &raw_context, NULL, &modules, + StackwalkerARM64 walker(&system_info, &raw_context, nullptr, &modules, &frame_symbolizer); vector modules_without_symbols; vector modules_with_corrupt_symbols; diff --git a/src/processor/stackwalker_arm_unittest.cc b/src/processor/stackwalker_arm_unittest.cc index 6103e2029..eab51c379 100644 --- a/src/processor/stackwalker_arm_unittest.cc +++ b/src/processor/stackwalker_arm_unittest.cc @@ -152,7 +152,7 @@ TEST_F(SanityCheck, NoResolver) { // Since we have no call frame information, and all unwinding // requires call frame information, the stack walk will end after // the first frame. - StackFrameSymbolizer frame_symbolizer(NULL, NULL); + StackFrameSymbolizer frame_symbolizer(nullptr, nullptr); StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, &frame_symbolizer); // This should succeed even without a resolver or supplier. @@ -197,7 +197,7 @@ TEST_F(GetContextFrame, Simple) { // without stack memory present. TEST_F(GetContextFrame, NoStackMemory) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerARM walker(&system_info, &raw_context, -1, NULL, &modules, + StackwalkerARM walker(&system_info, &raw_context, -1, nullptr, &modules, &frame_symbolizer); vector modules_without_symbols; vector modules_with_corrupt_symbols; diff --git a/src/processor/stackwalker_mips.cc b/src/processor/stackwalker_mips.cc index 7195c1627..4a7c0e107 100644 --- a/src/processor/stackwalker_mips.cc +++ b/src/processor/stackwalker_mips.cc @@ -36,7 +36,8 @@ #include // Must come first #endif -#include "common/scoped_ptr.h" +#include + #include "google_breakpad/processor/call_stack.h" #include "google_breakpad/processor/code_modules.h" #include "google_breakpad/processor/memory_region.h" @@ -65,7 +66,7 @@ StackwalkerMIPS::StackwalkerMIPS(const SystemInfo* system_info, << HexString(memory_->GetBase()) << "+" << HexString(memory_->GetSize()); - memory_ = NULL; + memory_ = nullptr; } } else { if (0xffffffff - memory_->GetBase() < memory_->GetSize() - 1) { @@ -73,7 +74,7 @@ StackwalkerMIPS::StackwalkerMIPS(const SystemInfo* system_info, << HexString(memory_->GetBase()) << "+" << HexString(memory_->GetSize()); - memory_ = NULL; + memory_ = nullptr; } } } @@ -82,7 +83,7 @@ StackwalkerMIPS::StackwalkerMIPS(const SystemInfo* system_info, StackFrame* StackwalkerMIPS::GetContextFrame() { if (!context_) { BPLOG(ERROR) << "Can't get context frame without context."; - return NULL; + return nullptr; } StackFrameMIPS* frame = new StackFrameMIPS(); @@ -102,7 +103,7 @@ static const char* const kRegisterNames[] = { "$zero", "$at", "$v0", "$v1", "$a0", "$a1", "$a2", "$a3", "$to", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$s0", "$s1", "$s2", "$s3", "$s4", "$s5", "$s6", "$s7", "$t8", "$t9", "$k0", "$k1", "$gp", "$sp", - "$fp", "$ra", NULL + "$fp", "$ra", nullptr // TODO(gordanac): add float point save registers }; @@ -126,7 +127,7 @@ StackFrameMIPS* StackwalkerMIPS::GetCallerByCFIFrameInfo( if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_, &caller_registers)) { - return NULL; + return nullptr; } CFIFrameInfo::RegisterValueMap::const_iterator entry = @@ -143,7 +144,7 @@ StackFrameMIPS* StackwalkerMIPS::GetCallerByCFIFrameInfo( } caller_registers["$pc"] = pc; // Construct a new stack frame given the values the CFI recovered. - scoped_ptr frame(new StackFrameMIPS()); + std::unique_ptr frame(new StackFrameMIPS()); for (int i = 0; kRegisterNames[i]; ++i) { CFIFrameInfo::RegisterValueMap::const_iterator caller_entry = @@ -193,7 +194,7 @@ StackFrameMIPS* StackwalkerMIPS::GetCallerByCFIFrameInfo( if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_, &caller_registers)) { - return NULL; + return nullptr; } CFIFrameInfo::RegisterValueMap::const_iterator entry = @@ -210,7 +211,7 @@ StackFrameMIPS* StackwalkerMIPS::GetCallerByCFIFrameInfo( } caller_registers["$pc"] = pc; // Construct a new stack frame given the values the CFI recovered. - scoped_ptr frame(new StackFrameMIPS()); + std::unique_ptr frame(new StackFrameMIPS()); for (int i = 0; kRegisterNames[i]; ++i) { CFIFrameInfo::RegisterValueMap::const_iterator caller_entry = @@ -252,15 +253,15 @@ StackFrame* StackwalkerMIPS::GetCallerFrame(const CallStack* stack, bool stack_scan_allowed) { if (!memory_ || !stack) { BPLOG(ERROR) << "Can't get caller frame without memory or stack"; - return NULL; + return nullptr; } const vector& frames = *stack->frames(); StackFrameMIPS* last_frame = static_cast(frames.back()); - scoped_ptr new_frame; + std::unique_ptr new_frame; // See if there is DWARF call frame information covering this address. - scoped_ptr cfi_frame_info( + std::unique_ptr cfi_frame_info( frame_symbolizer_->FindCFIFrameInfo(last_frame)); if (cfi_frame_info.get()) new_frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get())); @@ -272,7 +273,7 @@ StackFrame* StackwalkerMIPS::GetCallerFrame(const CallStack* stack, // If nothing worked, tell the caller. if (!new_frame.get()) { - return NULL; + return nullptr; } // Should we terminate the stack walk? (end-of-stack or broken invariant) @@ -281,7 +282,7 @@ StackFrame* StackwalkerMIPS::GetCallerFrame(const CallStack* stack, last_frame->context.iregs[MD_CONTEXT_MIPS_REG_SP], /*first_unwind=*/last_frame->trust == StackFrame::FRAME_TRUST_CONTEXT)) { - return NULL; + return nullptr; } return new_frame.release(); @@ -326,13 +327,13 @@ StackFrameMIPS* StackwalkerMIPS::GetCallerByStackScan( // If we can't find an instruction pointer even with stack scanning, // give up. BPLOG(ERROR) << " ScanForReturnAddress failed "; - return NULL; + return nullptr; } // Get $fp stored in the stack frame. if (!memory_->GetMemoryAtAddress(caller_sp - sizeof(caller_pc), &caller_fp)) { BPLOG(INFO) << " GetMemoryAtAddress for fp failed " ; - return NULL; + return nullptr; } count = count - (caller_sp - last_sp) / sizeof(caller_pc); @@ -342,7 +343,7 @@ StackFrameMIPS* StackwalkerMIPS::GetCallerByStackScan( if (!count) { BPLOG(INFO) << " No frame found " ; - return NULL; + return nullptr; } // ScanForReturnAddress found a reasonable return address. Advance @@ -392,13 +393,13 @@ StackFrameMIPS* StackwalkerMIPS::GetCallerByStackScan( // If we can't find an instruction pointer even with stack scanning, // give up. BPLOG(ERROR) << " ScanForReturnAddress failed "; - return NULL; + return nullptr; } // Get $fp stored in the stack frame. if (!memory_->GetMemoryAtAddress(caller_sp - sizeof(caller_pc), &caller_fp)) { BPLOG(INFO) << " GetMemoryAtAddress for fp failed " ; - return NULL; + return nullptr; } count = count - (caller_sp - last_sp) / sizeof(caller_pc); @@ -408,7 +409,7 @@ StackFrameMIPS* StackwalkerMIPS::GetCallerByStackScan( if (!count) { BPLOG(INFO) << " No frame found " ; - return NULL; + return nullptr; } // ScanForReturnAddress found a reasonable return address. Advance diff --git a/src/processor/stackwalker_mips64_unittest.cc b/src/processor/stackwalker_mips64_unittest.cc index 55b7503fa..f8791e3c4 100644 --- a/src/processor/stackwalker_mips64_unittest.cc +++ b/src/processor/stackwalker_mips64_unittest.cc @@ -158,7 +158,7 @@ TEST_F(SanityCheck, NoResolver) { raw_context.epc = 0x00400020; raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000; - StackFrameSymbolizer frame_symbolizer(NULL, NULL); + StackFrameSymbolizer frame_symbolizer(nullptr, nullptr); StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); // This should succeed, even without a resolver or supplier. @@ -214,7 +214,7 @@ TEST_F(GetContextFrame, NoStackMemory) { raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000; StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerMIPS walker(&system_info, &raw_context, NULL, &modules, + StackwalkerMIPS walker(&system_info, &raw_context, nullptr, &modules, &frame_symbolizer); vector modules_without_symbols; vector modules_with_corrupt_symbols; diff --git a/src/processor/stackwalker_mips_unittest.cc b/src/processor/stackwalker_mips_unittest.cc index 305f4db8d..c92d1f0a7 100644 --- a/src/processor/stackwalker_mips_unittest.cc +++ b/src/processor/stackwalker_mips_unittest.cc @@ -156,7 +156,7 @@ TEST_F(SanityCheck, NoResolver) { raw_context.epc = 0x00400020; raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000; - StackFrameSymbolizer frame_symbolizer(NULL, NULL); + StackFrameSymbolizer frame_symbolizer(nullptr, nullptr); StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); // This should succeed, even without a resolver or supplier. @@ -210,7 +210,7 @@ TEST_F(GetContextFrame, NoStackMemory) { raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000; StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerMIPS walker(&system_info, &raw_context, NULL, &modules, + StackwalkerMIPS walker(&system_info, &raw_context, nullptr, &modules, &frame_symbolizer); vector modules_without_symbols; vector modules_with_corrupt_symbols; diff --git a/src/processor/stackwalker_ppc.cc b/src/processor/stackwalker_ppc.cc index 0083392b5..4afeec83d 100644 --- a/src/processor/stackwalker_ppc.cc +++ b/src/processor/stackwalker_ppc.cc @@ -37,7 +37,8 @@ #include // Must come first #endif -#include "common/scoped_ptr.h" +#include + #include "processor/stackwalker_ppc.h" #include "google_breakpad/processor/call_stack.h" #include "google_breakpad/processor/memory_region.h" @@ -61,7 +62,7 @@ StackwalkerPPC::StackwalkerPPC(const SystemInfo* system_info, BPLOG(ERROR) << "Memory out of range for stackwalking: " << HexString(memory_->GetBase()) << "+" << HexString(memory_->GetSize()); - memory_ = NULL; + memory_ = nullptr; } } @@ -69,7 +70,7 @@ StackwalkerPPC::StackwalkerPPC(const SystemInfo* system_info, StackFrame* StackwalkerPPC::GetContextFrame() { if (!context_) { BPLOG(ERROR) << "Can't get context frame without context"; - return NULL; + return nullptr; } StackFramePPC* frame = new StackFramePPC(); @@ -89,7 +90,7 @@ StackFrame* StackwalkerPPC::GetCallerFrame(const CallStack* stack, bool stack_scan_allowed) { if (!memory_ || !stack) { BPLOG(ERROR) << "Can't get caller frame without memory or stack"; - return NULL; + return nullptr; } // The instruction pointers for previous frames are saved on the stack. @@ -111,7 +112,7 @@ StackFrame* StackwalkerPPC::GetCallerFrame(const CallStack* stack, if (!memory_->GetMemoryAtAddress(last_frame->context.gpr[1], &stack_pointer) || stack_pointer <= last_frame->context.gpr[1]) { - return NULL; + return nullptr; } // Mac OS X/Darwin gives 1 as the return address from the bottom-most @@ -122,10 +123,10 @@ StackFrame* StackwalkerPPC::GetCallerFrame(const CallStack* stack, uint32_t instruction; if (!memory_->GetMemoryAtAddress(stack_pointer + 8, &instruction) || instruction <= 1) { - return NULL; + return nullptr; } - scoped_ptr frame(new StackFramePPC()); + std::unique_ptr frame(new StackFramePPC()); frame->context = last_frame->context; frame->context.srr0 = instruction; @@ -138,7 +139,7 @@ StackFrame* StackwalkerPPC::GetCallerFrame(const CallStack* stack, if (TerminateWalk(instruction, stack_pointer, last_frame->context.gpr[1], /*first_unwind=*/last_frame->trust == StackFrame::FRAME_TRUST_CONTEXT)) { - return NULL; + return nullptr; } // frame->context.srr0 is the return address, which is one instruction diff --git a/src/processor/stackwalker_ppc64.cc b/src/processor/stackwalker_ppc64.cc index c36d16be3..f0298f2bc 100644 --- a/src/processor/stackwalker_ppc64.cc +++ b/src/processor/stackwalker_ppc64.cc @@ -35,7 +35,8 @@ #include // Must come first #endif -#include "common/scoped_ptr.h" +#include + #include "processor/stackwalker_ppc64.h" #include "google_breakpad/processor/call_stack.h" #include "google_breakpad/processor/memory_region.h" @@ -60,7 +61,7 @@ StackwalkerPPC64::StackwalkerPPC64(const SystemInfo* system_info, StackFrame* StackwalkerPPC64::GetContextFrame() { if (!context_) { BPLOG(ERROR) << "Can't get context frame without context"; - return NULL; + return nullptr; } StackFramePPC64* frame = new StackFramePPC64(); @@ -80,7 +81,7 @@ StackFrame* StackwalkerPPC64::GetCallerFrame(const CallStack* stack, bool stack_scan_allowed) { if (!memory_ || !stack) { BPLOG(ERROR) << "Can't get caller frame without memory or stack"; - return NULL; + return nullptr; } // The instruction pointers for previous frames are saved on the stack. @@ -102,7 +103,7 @@ StackFrame* StackwalkerPPC64::GetCallerFrame(const CallStack* stack, if (!memory_->GetMemoryAtAddress(last_frame->context.gpr[1], &stack_pointer) || stack_pointer <= last_frame->context.gpr[1]) { - return NULL; + return nullptr; } // Mac OS X/Darwin gives 1 as the return address from the bottom-most @@ -113,10 +114,10 @@ StackFrame* StackwalkerPPC64::GetCallerFrame(const CallStack* stack, uint64_t instruction; if (!memory_->GetMemoryAtAddress(stack_pointer + 16, &instruction) || instruction <= 1) { - return NULL; + return nullptr; } - scoped_ptr frame(new StackFramePPC64()); + std::unique_ptr frame(new StackFramePPC64()); frame->context = last_frame->context; frame->context.srr0 = instruction; @@ -129,7 +130,7 @@ StackFrame* StackwalkerPPC64::GetCallerFrame(const CallStack* stack, if (TerminateWalk(instruction, stack_pointer, last_frame->context.gpr[1], /*is_context_frame=*/last_frame->trust == StackFrame::FRAME_TRUST_CONTEXT)) { - return NULL; + return nullptr; } // frame->context.srr0 is the return address, which is one instruction diff --git a/src/processor/stackwalker_riscv.cc b/src/processor/stackwalker_riscv.cc index c3681a617..d350fe54f 100644 --- a/src/processor/stackwalker_riscv.cc +++ b/src/processor/stackwalker_riscv.cc @@ -37,7 +37,8 @@ #include // Must come first #endif -#include "common/scoped_ptr.h" +#include + #include "google_breakpad/processor/call_stack.h" #include "google_breakpad/processor/code_modules.h" #include "google_breakpad/processor/memory_region.h" @@ -63,7 +64,7 @@ StackwalkerRISCV::StackwalkerRISCV(const SystemInfo* system_info, StackFrame* StackwalkerRISCV::GetContextFrame() { if (!context_) { BPLOG(ERROR) << "Can't get context frame without context"; - return NULL; + return nullptr; } StackFrameRISCV* frame = new StackFrameRISCV(); @@ -153,12 +154,12 @@ StackFrameRISCV* StackwalkerRISCV::GetCallerByCFIFrameInfo( CFIFrameInfo::RegisterValueMap caller_registers; if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_, &caller_registers)) { - return NULL; + return nullptr; } // Construct a new stack frame given the values the CFI recovered. CFIFrameInfo::RegisterValueMap::iterator entry; - scoped_ptr frame(new StackFrameRISCV()); + std::unique_ptr frame(new StackFrameRISCV()); entry = caller_registers.find("pc"); if (entry != caller_registers.end()) { frame->context_validity |= StackFrameRISCV::CONTEXT_VALID_PC; @@ -410,7 +411,7 @@ StackFrameRISCV* StackwalkerRISCV::GetCallerByCFIFrameInfo( static const uint64_t essentials = (StackFrameRISCV::CONTEXT_VALID_SP | StackFrameRISCV::CONTEXT_VALID_PC); if ((frame->context_validity & essentials) != essentials) - return NULL; + return nullptr; frame->trust = StackFrame::FRAME_TRUST_CFI; return frame.release(); @@ -426,7 +427,7 @@ StackFrameRISCV* StackwalkerRISCV::GetCallerByStackScan( if (!ScanForReturnAddress(last_sp, &caller_sp, &caller_pc, last_frame->trust == StackFrame::FRAME_TRUST_CONTEXT)) { // No plausible return address was found. - return NULL; + return nullptr; } // ScanForReturnAddress found a reasonable return address. Advance @@ -459,14 +460,14 @@ StackFrameRISCV* StackwalkerRISCV::GetCallerByStackScan( if (last_fp && !memory_->GetMemoryAtAddress(last_fp, &caller_fp)) { BPLOG(ERROR) << "Unable to read caller_fp from last_fp: 0x" << std::hex << last_fp; - return NULL; + return nullptr; } uint32_t caller_ra = 0; if (last_fp && !memory_->GetMemoryAtAddress(last_fp + 4, &caller_ra)) { BPLOG(ERROR) << "Unable to read caller_ra from last_fp + 4: 0x" << std::hex << (last_fp + 4); - return NULL; + return nullptr; } uint32_t caller_sp = last_fp ? last_fp + 8 : last_frame->context.s0; @@ -492,16 +493,16 @@ StackFrame* StackwalkerRISCV::GetCallerFrame(const CallStack* stack, bool stack_scan_allowed) { if (!memory_ || !stack) { BPLOG(ERROR) << "Can't get caller frame without memory or stack"; - return NULL; + return nullptr; } const vector& frames = *stack->frames(); StackFrameRISCV* last_frame = static_cast(frames.back()); - scoped_ptr frame; + std::unique_ptr frame; // Try to recover caller information from CFI. - scoped_ptr cfi_frame_info( + std::unique_ptr cfi_frame_info( frame_symbolizer_->FindCFIFrameInfo(last_frame)); if (cfi_frame_info.get()) frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get())); @@ -516,13 +517,13 @@ StackFrame* StackwalkerRISCV::GetCallerFrame(const CallStack* stack, // If nothing worked, tell the caller. if (!frame.get()) - return NULL; + return nullptr; // Should we terminate the stack walk? (end-of-stack or broken invariant) if (TerminateWalk(frame->context.pc, frame->context.sp, last_frame->context.sp, last_frame->trust == StackFrame::FRAME_TRUST_CONTEXT)) { - return NULL; + return nullptr; } // The new frame's context's PC is the return address, which is one diff --git a/src/processor/stackwalker_riscv64.cc b/src/processor/stackwalker_riscv64.cc index 0ed7b5e65..3da914db9 100644 --- a/src/processor/stackwalker_riscv64.cc +++ b/src/processor/stackwalker_riscv64.cc @@ -37,7 +37,8 @@ #include // Must come first #endif -#include "common/scoped_ptr.h" +#include + #include "google_breakpad/processor/call_stack.h" #include "google_breakpad/processor/code_modules.h" #include "google_breakpad/processor/memory_region.h" @@ -63,7 +64,7 @@ StackwalkerRISCV64::StackwalkerRISCV64(const SystemInfo* system_info, StackFrame* StackwalkerRISCV64::GetContextFrame() { if (!context_) { BPLOG(ERROR) << "Can't get context frame without context"; - return NULL; + return nullptr; } StackFrameRISCV64* frame = new StackFrameRISCV64(); @@ -153,12 +154,12 @@ StackFrameRISCV64* StackwalkerRISCV64::GetCallerByCFIFrameInfo( CFIFrameInfo::RegisterValueMap caller_registers; if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_, &caller_registers)) { - return NULL; + return nullptr; } // Construct a new stack frame given the values the CFI recovered. CFIFrameInfo::RegisterValueMap::iterator entry; - scoped_ptr frame(new StackFrameRISCV64()); + std::unique_ptr frame(new StackFrameRISCV64()); entry = caller_registers.find("pc"); if (entry != caller_registers.end()) { frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_PC; @@ -410,7 +411,7 @@ StackFrameRISCV64* StackwalkerRISCV64::GetCallerByCFIFrameInfo( static const uint64_t essentials = (StackFrameRISCV64::CONTEXT_VALID_SP | StackFrameRISCV64::CONTEXT_VALID_PC); if ((frame->context_validity & essentials) != essentials) - return NULL; + return nullptr; frame->trust = StackFrame::FRAME_TRUST_CFI; return frame.release(); @@ -426,7 +427,7 @@ StackFrameRISCV64* StackwalkerRISCV64::GetCallerByStackScan( if (!ScanForReturnAddress(last_sp, &caller_sp, &caller_pc, last_frame->trust == StackFrame::FRAME_TRUST_CONTEXT)) { // No plausible return address was found. - return NULL; + return nullptr; } // ScanForReturnAddress found a reasonable return address. Advance @@ -459,14 +460,14 @@ StackFrameRISCV64* StackwalkerRISCV64::GetCallerByFramePointer( if (last_fp && !memory_->GetMemoryAtAddress(last_fp, &caller_fp)) { BPLOG(ERROR) << "Unable to read caller_fp from last_fp: 0x" << std::hex << last_fp; - return NULL; + return nullptr; } uint64_t caller_ra = 0; if (last_fp && !memory_->GetMemoryAtAddress(last_fp + 8, &caller_ra)) { BPLOG(ERROR) << "Unable to read caller_ra from last_fp + 8: 0x" << std::hex << (last_fp + 8); - return NULL; + return nullptr; } uint64_t caller_sp = last_fp ? last_fp + 16 : last_frame->context.s0; @@ -492,16 +493,16 @@ StackFrame* StackwalkerRISCV64::GetCallerFrame(const CallStack* stack, bool stack_scan_allowed) { if (!memory_ || !stack) { BPLOG(ERROR) << "Can't get caller frame without memory or stack"; - return NULL; + return nullptr; } const vector& frames = *stack->frames(); StackFrameRISCV64* last_frame = static_cast(frames.back()); - scoped_ptr frame; + std::unique_ptr frame; // Try to recover caller information from CFI. - scoped_ptr cfi_frame_info( + std::unique_ptr cfi_frame_info( frame_symbolizer_->FindCFIFrameInfo(last_frame)); if (cfi_frame_info.get()) frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get())); @@ -516,13 +517,13 @@ StackFrame* StackwalkerRISCV64::GetCallerFrame(const CallStack* stack, // If nothing worked, tell the caller. if (!frame.get()) - return NULL; + return nullptr; // Should we terminate the stack walk? (end-of-stack or broken invariant) if (TerminateWalk(frame->context.pc, frame->context.sp, last_frame->context.sp, last_frame->trust == StackFrame::FRAME_TRUST_CONTEXT)) { - return NULL; + return nullptr; } // The new frame's context's PC is the return address, which is one diff --git a/src/processor/stackwalker_riscv64_unittest.cc b/src/processor/stackwalker_riscv64_unittest.cc index c8579b9b9..5f02c0d9f 100644 --- a/src/processor/stackwalker_riscv64_unittest.cc +++ b/src/processor/stackwalker_riscv64_unittest.cc @@ -151,7 +151,7 @@ class SanityCheck: public StackwalkerRISCV64Fixture, public Test { }; TEST_F(SanityCheck, NoResolver) { // Since the context's frame pointer is garbage, the stack walk will end after // the first frame. - StackFrameSymbolizer frame_symbolizer(NULL, NULL); + StackFrameSymbolizer frame_symbolizer(nullptr, nullptr); StackwalkerRISCV64 walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); // This should succeed even without a resolver or supplier. @@ -175,7 +175,7 @@ class GetContextFrame: public StackwalkerRISCV64Fixture, public Test { }; // without stack memory present. TEST_F(GetContextFrame, NoStackMemory) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerRISCV64 walker(&system_info, &raw_context, NULL, &modules, + StackwalkerRISCV64 walker(&system_info, &raw_context, nullptr, &modules, &frame_symbolizer); vector modules_without_symbols; vector modules_with_corrupt_symbols; diff --git a/src/processor/stackwalker_riscv_unittest.cc b/src/processor/stackwalker_riscv_unittest.cc index 37f0e233a..555b55d01 100644 --- a/src/processor/stackwalker_riscv_unittest.cc +++ b/src/processor/stackwalker_riscv_unittest.cc @@ -151,7 +151,7 @@ class SanityCheck: public StackwalkerRISCVFixture, public Test { }; TEST_F(SanityCheck, NoResolver) { // Since the context's frame pointer is garbage, the stack walk will end after // the first frame. - StackFrameSymbolizer frame_symbolizer(NULL, NULL); + StackFrameSymbolizer frame_symbolizer(nullptr, nullptr); StackwalkerRISCV walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); // This should succeed even without a resolver or supplier. @@ -175,7 +175,7 @@ class GetContextFrame: public StackwalkerRISCVFixture, public Test { }; // without stack memory present. TEST_F(GetContextFrame, NoStackMemory) { StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerRISCV walker(&system_info, &raw_context, NULL, &modules, + StackwalkerRISCV walker(&system_info, &raw_context, nullptr, &modules, &frame_symbolizer); vector modules_without_symbols; vector modules_with_corrupt_symbols; diff --git a/src/processor/stackwalker_selftest.cc b/src/processor/stackwalker_selftest.cc index 4f3483b41..977567cce 100644 --- a/src/processor/stackwalker_selftest.cc +++ b/src/processor/stackwalker_selftest.cc @@ -69,7 +69,6 @@ #include -#include "common/scoped_ptr.h" #include "google_breakpad/common/breakpad_types.h" #include "google_breakpad/common/minidump_format.h" #include "google_breakpad/processor/basic_source_line_resolver.h" @@ -83,7 +82,6 @@ using google_breakpad::BasicSourceLineResolver; using google_breakpad::CallStack; using google_breakpad::CodeModule; using google_breakpad::MemoryRegion; -using google_breakpad::scoped_ptr; using google_breakpad::StackFrame; using google_breakpad::StackFramePPC; using google_breakpad::StackFrameX86; @@ -327,23 +325,23 @@ static unsigned int CountCallerFrames() { context.ebp = GetEBP(); context.esp = GetESP(); - StackwalkerX86 stackwalker = StackwalkerX86(NULL, &context, &memory, NULL, - NULL, &resolver); + StackwalkerX86 stackwalker = StackwalkerX86(nullptr, &context, &memory, + nullptr, nullptr, &resolver); #elif defined(__ppc__) MDRawContextPPC context = MDRawContextPPC(); context.srr0 = GetPC(); context.gpr[1] = GetSP(); - StackwalkerPPC stackwalker = StackwalkerPPC(NULL, &context, &memory, NULL, - NULL, &resolver); + StackwalkerPPC stackwalker = StackwalkerPPC(nullptr, &context, &memory, + nullptr, nullptr, &resolver); #elif defined(__sparc__) MDRawContextSPARC context = MDRawContextSPARC(); context.pc = GetPC(); context.g_r[14] = GetSP(); context.g_r[30] = GetFP(); - StackwalkerSPARC stackwalker = StackwalkerSPARC(NULL, &context, &memory, - NULL, NULL, &resolver); + StackwalkerSPARC stackwalker = StackwalkerSPARC(nullptr, &context, &memory, + nullptr, nullptr, &resolver); #endif // __i386__ || __ppc__ || __sparc__ CallStack stack; diff --git a/src/processor/stackwalker_sparc.cc b/src/processor/stackwalker_sparc.cc index ed7f7dc3d..9fc78a2e6 100644 --- a/src/processor/stackwalker_sparc.cc +++ b/src/processor/stackwalker_sparc.cc @@ -59,7 +59,7 @@ StackwalkerSPARC::StackwalkerSPARC(const SystemInfo* system_info, StackFrame* StackwalkerSPARC::GetContextFrame() { if (!context_) { BPLOG(ERROR) << "Can't get context frame without context"; - return NULL; + return nullptr; } StackFrameSPARC* frame = new StackFrameSPARC(); @@ -79,7 +79,7 @@ StackFrame* StackwalkerSPARC::GetCallerFrame(const CallStack* stack, bool stack_scan_allowed) { if (!memory_ || !stack) { BPLOG(ERROR) << "Can't get caller frame without memory or stack"; - return NULL; + return nullptr; } StackFrameSPARC* last_frame = static_cast( @@ -99,26 +99,26 @@ StackFrame* StackwalkerSPARC::GetCallerFrame(const CallStack* stack, // end of the stack. uint64_t stack_pointer = last_frame->context.g_r[30]; if (stack_pointer <= last_frame->context.g_r[14]) { - return NULL; + return nullptr; } uint32_t instruction; if (!memory_->GetMemoryAtAddress(stack_pointer + 60, &instruction) || instruction <= 1) { - return NULL; + return nullptr; } uint32_t stack_base; if (!memory_->GetMemoryAtAddress(stack_pointer + 56, &stack_base) || stack_base <= 1) { - return NULL; + return nullptr; } // Should we terminate the stack walk? (end-of-stack or broken invariant) if (TerminateWalk(instruction, stack_pointer, last_frame->context.g_r[14], /*is_context_frame=*/last_frame->trust == StackFrame::FRAME_TRUST_CONTEXT)) { - return NULL; + return nullptr; } StackFrameSPARC* frame = new StackFrameSPARC(); diff --git a/src/processor/stackwalker_unittest_utils.h b/src/processor/stackwalker_unittest_utils.h index 3d651b2cb..ef09ebbd7 100644 --- a/src/processor/stackwalker_unittest_utils.h +++ b/src/processor/stackwalker_unittest_utils.h @@ -147,7 +147,7 @@ class MockCodeModules: public google_breakpad::CodeModules { address - module->base_address() < module->size()) return module; } - return NULL; + return nullptr; }; const CodeModule* GetMainModule() const { return modules_[0]; } diff --git a/src/processor/stackwalker_x86.cc b/src/processor/stackwalker_x86.cc index 9bda5f8c4..ae8706d1a 100644 --- a/src/processor/stackwalker_x86.cc +++ b/src/processor/stackwalker_x86.cc @@ -37,9 +37,10 @@ #endif #include + +#include #include -#include "common/scoped_ptr.h" #include "google_breakpad/processor/call_stack.h" #include "google_breakpad/processor/code_modules.h" #include "google_breakpad/processor/memory_region.h" @@ -71,19 +72,19 @@ StackwalkerX86::cfi_register_map_[] = { StackFrameX86::CONTEXT_VALID_EIP, &MDRawContextX86::eip }, { "$esp", ".cfa", false, StackFrameX86::CONTEXT_VALID_ESP, &MDRawContextX86::esp }, - { "$ebp", NULL, true, + { "$ebp", nullptr, true, StackFrameX86::CONTEXT_VALID_EBP, &MDRawContextX86::ebp }, - { "$eax", NULL, false, + { "$eax", nullptr, false, StackFrameX86::CONTEXT_VALID_EAX, &MDRawContextX86::eax }, - { "$ebx", NULL, true, + { "$ebx", nullptr, true, StackFrameX86::CONTEXT_VALID_EBX, &MDRawContextX86::ebx }, - { "$ecx", NULL, false, + { "$ecx", nullptr, false, StackFrameX86::CONTEXT_VALID_ECX, &MDRawContextX86::ecx }, - { "$edx", NULL, false, + { "$edx", nullptr, false, StackFrameX86::CONTEXT_VALID_EDX, &MDRawContextX86::edx }, - { "$esi", NULL, true, + { "$esi", nullptr, true, StackFrameX86::CONTEXT_VALID_ESI, &MDRawContextX86::esi }, - { "$edi", NULL, true, + { "$edi", nullptr, true, StackFrameX86::CONTEXT_VALID_EDI, &MDRawContextX86::edi }, }; @@ -102,17 +103,17 @@ StackwalkerX86::StackwalkerX86(const SystemInfo* system_info, BPLOG(ERROR) << "Memory out of range for stackwalking: " << HexString(memory_->GetBase()) << "+" << HexString(memory_->GetSize()); - memory_ = NULL; + memory_ = nullptr; } } StackFrameX86::~StackFrameX86() { if (windows_frame_info) delete windows_frame_info; - windows_frame_info = NULL; + windows_frame_info = nullptr; if (cfi_frame_info) delete cfi_frame_info; - cfi_frame_info = NULL; + cfi_frame_info = nullptr; } uint64_t StackFrameX86::ReturnAddress() const { @@ -123,7 +124,7 @@ uint64_t StackFrameX86::ReturnAddress() const { StackFrame* StackwalkerX86::GetContextFrame() { if (!context_) { BPLOG(ERROR) << "Can't get context frame without context"; - return NULL; + return nullptr; } StackFrameX86* frame = new StackFrameX86(); @@ -157,7 +158,7 @@ StackFrameX86* StackwalkerX86::GetCallerByWindowsFrameInfo( // last_frame_info is VALID_PARAMETER_SIZE-only, then we should // assume the traditional frame format or use some other strategy. if (last_frame_info->valid != WindowsFrameInfo::VALID_ALL) - return NULL; + return nullptr; // This stackwalker sets each frame's %esp to its value immediately prior // to the CALL into the callee. This means that %esp points to the last @@ -254,7 +255,7 @@ StackFrameX86* StackwalkerX86::GetCallerByWindowsFrameInfo( // for calculation of the value of .raSearchStart are available. if (ScanForReturnAddress(raSearchStart, &raSearchStart, &found, 3) && last_frame->trust == StackFrame::FRAME_TRUST_CONTEXT && - last_frame->windows_frame_info != NULL && + last_frame->windows_frame_info != nullptr && last_frame_info->type_ == WindowsFrameInfo::STACK_INFO_FPO && raSearchStartOld == raSearchStart && found == last_frame->context.eip) { @@ -403,7 +404,7 @@ StackFrameX86* StackwalkerX86::GetCallerByWindowsFrameInfo( StackFrame::FRAME_TRUST_CONTEXT)) { // if we can't find an instruction pointer even with stack scanning, // give up. - return NULL; + return nullptr; } // This seems like a reasonable return address. Since program string @@ -536,19 +537,19 @@ StackFrameX86* StackwalkerX86::GetCallerByCFIFrameInfo( StackFrameX86* last_frame = static_cast(frames.back()); last_frame->cfi_frame_info = cfi_frame_info; - scoped_ptr frame(new StackFrameX86()); + std::unique_ptr frame(new StackFrameX86()); if (!cfi_walker_ .FindCallerRegisters(*memory_, *cfi_frame_info, last_frame->context, last_frame->context_validity, &frame->context, &frame->context_validity)) - return NULL; + return nullptr; // Make sure we recovered all the essentials. static const int essentials = (StackFrameX86::CONTEXT_VALID_EIP | StackFrameX86::CONTEXT_VALID_ESP | StackFrameX86::CONTEXT_VALID_EBP); if ((frame->context_validity & essentials) != essentials) - return NULL; + return nullptr; frame->trust = StackFrame::FRAME_TRUST_CFI; @@ -607,7 +608,7 @@ StackFrameX86* StackwalkerX86::GetCallerByEBPAtBase( StackFrame::FRAME_TRUST_CONTEXT)) { // if we can't find an instruction pointer even with stack scanning, // give up. - return NULL; + return nullptr; } // ScanForReturnAddress found a reasonable return address. Advance %esp to @@ -650,7 +651,7 @@ StackFrame* StackwalkerX86::GetCallerFrame(const CallStack* stack, bool stack_scan_allowed) { if (!memory_ || !stack) { BPLOG(ERROR) << "Can't get caller frame without memory or stack"; - return NULL; + return nullptr; } const vector& frames = *stack->frames(); @@ -658,7 +659,7 @@ StackFrame* StackwalkerX86::GetCallerFrame(const CallStack* stack, // The last frame can never be inline. A sequence of inline frames always // finishes with a conventional frame. assert(last_frame->trust != StackFrame::FRAME_TRUST_INLINE); - scoped_ptr new_frame; + std::unique_ptr new_frame; // If the resolver has Windows stack walking information, use that. WindowsFrameInfo* windows_frame_info @@ -681,14 +682,14 @@ StackFrame* StackwalkerX86::GetCallerFrame(const CallStack* stack, // If nothing worked, tell the caller. if (!new_frame.get()) - return NULL; + return nullptr; // Should we terminate the stack walk? (end-of-stack or broken invariant) if (TerminateWalk(new_frame->context.eip, new_frame->context.esp, last_frame->context.esp, /*first_unwind=*/last_frame->trust == StackFrame::FRAME_TRUST_CONTEXT)) { - return NULL; + return nullptr; } // new_frame->context.eip is the return address, which is the instruction diff --git a/src/processor/stackwalker_x86_unittest.cc b/src/processor/stackwalker_x86_unittest.cc index b614b0e44..e5bb63e49 100644 --- a/src/processor/stackwalker_x86_unittest.cc +++ b/src/processor/stackwalker_x86_unittest.cc @@ -166,7 +166,7 @@ TEST_F(SanityCheck, NoResolver) { raw_context.eip = 0x40000200; raw_context.ebp = 0x80000000; - StackFrameSymbolizer frame_symbolizer(NULL, NULL); + StackFrameSymbolizer frame_symbolizer(nullptr, nullptr); StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, &frame_symbolizer); // This should succeed, even without a resolver or supplier. @@ -217,7 +217,7 @@ TEST_F(GetContextFrame, NoStackMemory) { raw_context.ebp = 0x80000000; StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerX86 walker(&system_info, &raw_context, NULL, &modules, + StackwalkerX86 walker(&system_info, &raw_context, nullptr, &modules, &frame_symbolizer); vector modules_without_symbols; vector modules_with_corrupt_symbols; @@ -278,7 +278,7 @@ TEST_F(GetCallerFrame, Traditional) { EXPECT_EQ(0x4000c7a5U, frame0->instruction); EXPECT_EQ(0x4000c7a5U, frame0->context.eip); EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp); - EXPECT_EQ(NULL, frame0->windows_frame_info); + EXPECT_EQ(nullptr, frame0->windows_frame_info); } { // To avoid reusing locals by mistake @@ -291,7 +291,7 @@ TEST_F(GetCallerFrame, Traditional) { EXPECT_EQ(0x40008679U, frame1->instruction + 1); EXPECT_EQ(0x40008679U, frame1->context.eip); EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); - EXPECT_EQ(NULL, frame1->windows_frame_info); + EXPECT_EQ(nullptr, frame1->windows_frame_info); } } @@ -343,7 +343,7 @@ TEST_F(GetCallerFrame, TraditionalScan) { EXPECT_EQ(0x4000f49dU, frame0->context.eip); EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); EXPECT_EQ(0xd43eed6eU, frame0->context.ebp); - EXPECT_EQ(NULL, frame0->windows_frame_info); + EXPECT_EQ(nullptr, frame0->windows_frame_info); } { // To avoid reusing locals by mistake @@ -357,7 +357,7 @@ TEST_F(GetCallerFrame, TraditionalScan) { EXPECT_EQ(0x4000129dU, frame1->context.eip); EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); - EXPECT_EQ(NULL, frame1->windows_frame_info); + EXPECT_EQ(nullptr, frame1->windows_frame_info); } } @@ -409,7 +409,7 @@ TEST_F(GetCallerFrame, TraditionalScanLongWay) { EXPECT_EQ(0x4000f49dU, frame0->context.eip); EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); EXPECT_EQ(0xd43eed6eU, frame0->context.ebp); - EXPECT_EQ(NULL, frame0->windows_frame_info); + EXPECT_EQ(nullptr, frame0->windows_frame_info); } { // To avoid reusing locals by mistake @@ -423,7 +423,7 @@ TEST_F(GetCallerFrame, TraditionalScanLongWay) { EXPECT_EQ(0x4000129dU, frame1->context.eip); EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); - EXPECT_EQ(NULL, frame1->windows_frame_info); + EXPECT_EQ(nullptr, frame1->windows_frame_info); } } @@ -475,7 +475,7 @@ TEST_F(GetCallerFrame, ScanningNotAllowed) { EXPECT_EQ(0x4000f49dU, frame0->context.eip); EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); EXPECT_EQ(0xd43eed6eU, frame0->context.ebp); - EXPECT_EQ(NULL, frame0->windows_frame_info); + EXPECT_EQ(nullptr, frame0->windows_frame_info); } } @@ -534,7 +534,7 @@ TEST_F(GetCallerFrame, WindowsFrameData) { EXPECT_EQ(0x4000aa85U, frame0->context.eip); EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); EXPECT_EQ(0xf052c1deU, frame0->context.ebp); - EXPECT_TRUE(frame0->windows_frame_info != NULL); + EXPECT_TRUE(frame0->windows_frame_info != nullptr); } { // To avoid reusing locals by mistake @@ -554,7 +554,7 @@ TEST_F(GetCallerFrame, WindowsFrameData) { EXPECT_EQ(0x9068a878U, frame1->context.ebx); EXPECT_EQ(0xa7120d1aU, frame1->context.esi); EXPECT_EQ(0x630891beU, frame1->context.edi); - EXPECT_EQ(NULL, frame1->windows_frame_info); + EXPECT_EQ(nullptr, frame1->windows_frame_info); } } @@ -615,7 +615,7 @@ TEST_F(GetCallerFrame, WindowsFrameDataAligned) { EXPECT_EQ(0x4000aa85U, frame0->context.eip); EXPECT_EQ(frame0_esp.Value(), frame0->context.esp); EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp); - EXPECT_TRUE(frame0->windows_frame_info != NULL); + EXPECT_TRUE(frame0->windows_frame_info != nullptr); } { // To avoid reusing locals by mistake @@ -629,7 +629,7 @@ TEST_F(GetCallerFrame, WindowsFrameDataAligned) { EXPECT_EQ(0x5000129dU, frame1->context.eip); EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); - EXPECT_EQ(NULL, frame1->windows_frame_info); + EXPECT_EQ(nullptr, frame1->windows_frame_info); } } @@ -708,7 +708,7 @@ TEST_F(GetCallerFrame, WindowsFrameDataParameterSize) { EXPECT_EQ(0x40001000U, frame0->function_base); // The FUNC record for module1::wheedle should have produced a // WindowsFrameInfo structure with only the parameter size valid. - ASSERT_TRUE(frame0->windows_frame_info != NULL); + ASSERT_TRUE(frame0->windows_frame_info != nullptr); EXPECT_EQ(WindowsFrameInfo::VALID_PARAMETER_SIZE, frame0->windows_frame_info->valid); EXPECT_EQ(WindowsFrameInfo::STACK_INFO_UNKNOWN, @@ -730,7 +730,7 @@ TEST_F(GetCallerFrame, WindowsFrameDataParameterSize) { EXPECT_EQ(&module2, frame1->module); EXPECT_EQ("module2::whine", frame1->function_name); EXPECT_EQ(0x5000aa85U, frame1->function_base); - ASSERT_TRUE(frame1->windows_frame_info != NULL); + ASSERT_TRUE(frame1->windows_frame_info != nullptr); EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid); EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, frame1->windows_frame_info->type_); @@ -752,8 +752,8 @@ TEST_F(GetCallerFrame, WindowsFrameDataParameterSize) { EXPECT_EQ(frame2_esp.Value(), frame2->context.esp); EXPECT_EQ(frame2_ebp.Value(), frame2->context.ebp); EXPECT_EQ(0x2558c7f3U, frame2->context.ebx); - EXPECT_EQ(NULL, frame2->module); - EXPECT_EQ(NULL, frame2->windows_frame_info); + EXPECT_EQ(nullptr, frame2->module); + EXPECT_EQ(nullptr, frame2->windows_frame_info); } } @@ -803,7 +803,7 @@ TEST_F(GetCallerFrame, WindowsFrameDataScan) { EXPECT_EQ(0x40000c9cU, frame0->context.eip); EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); EXPECT_EQ(0x2ae314cdU, frame0->context.ebp); - EXPECT_TRUE(frame0->windows_frame_info != NULL); + EXPECT_TRUE(frame0->windows_frame_info != nullptr); } { // To avoid reusing locals by mistake @@ -820,7 +820,7 @@ TEST_F(GetCallerFrame, WindowsFrameDataScan) { EXPECT_EQ(0x50007ce9U, frame1->instruction + 1); EXPECT_EQ(0x50007ce9U, frame1->context.eip); EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); - EXPECT_TRUE(frame1->windows_frame_info != NULL); + EXPECT_TRUE(frame1->windows_frame_info != nullptr); } } @@ -892,7 +892,7 @@ TEST_F(GetCallerFrame, WindowsFrameDataBadEIPScan) { EXPECT_EQ(0x40000700U, frame0->context.eip); EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp); - EXPECT_TRUE(frame0->windows_frame_info != NULL); + EXPECT_TRUE(frame0->windows_frame_info != nullptr); } { // To avoid reusing locals by mistake @@ -910,7 +910,7 @@ TEST_F(GetCallerFrame, WindowsFrameDataBadEIPScan) { EXPECT_EQ(0x5000d000U, frame1->context.eip); EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); - EXPECT_TRUE(frame1->windows_frame_info != NULL); + EXPECT_TRUE(frame1->windows_frame_info != nullptr); } } @@ -971,7 +971,7 @@ TEST_F(GetCallerFrame, WindowsFPOUnchangedEBP) { EXPECT_EQ(0x4000e8a8U, frame0->function_base); // The STACK WIN record for module1::discombobulated should have // produced a fully populated WindowsFrameInfo structure. - ASSERT_TRUE(frame0->windows_frame_info != NULL); + ASSERT_TRUE(frame0->windows_frame_info != nullptr); EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid); EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO, frame0->windows_frame_info->type_); @@ -992,7 +992,7 @@ TEST_F(GetCallerFrame, WindowsFPOUnchangedEBP) { EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); EXPECT_EQ(&module1, frame1->module); EXPECT_EQ("", frame1->function_name); - EXPECT_EQ(NULL, frame1->windows_frame_info); + EXPECT_EQ(nullptr, frame1->windows_frame_info); } } @@ -1054,7 +1054,7 @@ TEST_F(GetCallerFrame, WindowsFPOUsedEBP) { EXPECT_EQ(0x40009aa8U, frame0->function_base); // The STACK WIN record for module1::RaisedByTheAliens should have // produced a fully populated WindowsFrameInfo structure. - ASSERT_TRUE(frame0->windows_frame_info != NULL); + ASSERT_TRUE(frame0->windows_frame_info != nullptr); EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid); EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO, frame0->windows_frame_info->type_); @@ -1075,7 +1075,7 @@ TEST_F(GetCallerFrame, WindowsFPOUsedEBP) { EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); EXPECT_EQ(&module1, frame1->module); EXPECT_EQ("", frame1->function_name); - EXPECT_EQ(NULL, frame1->windows_frame_info); + EXPECT_EQ(nullptr, frame1->windows_frame_info); } } @@ -1332,7 +1332,7 @@ TEST_F(GetCallerFrame, WindowsFPOSystemCall) { EXPECT_EQ("ZwWaitForSingleObject", frame0->function_name); // The STACK WIN record for module3!ZwWaitForSingleObject should have // produced a fully populated WindowsFrameInfo structure. - ASSERT_TRUE(frame0->windows_frame_info != NULL); + ASSERT_TRUE(frame0->windows_frame_info != nullptr); EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid); EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO, frame0->windows_frame_info->type_); @@ -1356,7 +1356,7 @@ TEST_F(GetCallerFrame, WindowsFPOSystemCall) { EXPECT_EQ("WaitForSingleObjectEx", frame1->function_name); // The STACK WIN record for module4!WaitForSingleObjectEx should have // produced a fully populated WindowsFrameInfo structure. - ASSERT_TRUE(frame1->windows_frame_info != NULL); + ASSERT_TRUE(frame1->windows_frame_info != nullptr); EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid); EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, frame1->windows_frame_info->type_); @@ -1544,7 +1544,7 @@ TEST_F(GetCallerFrame, ReturnAddressIsNotInKnownModule) { EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp); EXPECT_EQ(&msvcrt_dll, frame0->module); EXPECT_EQ("wcsstr", frame0->function_name); - ASSERT_TRUE(frame0->windows_frame_info != NULL); + ASSERT_TRUE(frame0->windows_frame_info != nullptr); EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid); EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, frame0->windows_frame_info->type_); @@ -1569,7 +1569,7 @@ TEST_F(GetCallerFrame, ReturnAddressIsNotInKnownModule) { EXPECT_EQ(frame2_ebp.Value(), frame1->context.ebp); EXPECT_EQ(&kernel32_dll, frame1->module); EXPECT_EQ("FindNextFileW", frame1->function_name); - ASSERT_TRUE(frame1->windows_frame_info != NULL); + ASSERT_TRUE(frame1->windows_frame_info != nullptr); EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid); EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, frame1->windows_frame_info->type_); @@ -1593,7 +1593,7 @@ TEST_F(GetCallerFrame, ReturnAddressIsNotInKnownModule) { EXPECT_EQ(frame3_ebp.Value(), frame2->context.ebp); EXPECT_EQ(&chrome_dll, frame2->module); EXPECT_EQ("file_util::FileEnumerator::Next()", frame2->function_name); - ASSERT_TRUE(frame2->windows_frame_info != NULL); + ASSERT_TRUE(frame2->windows_frame_info != nullptr); EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame2->windows_frame_info->valid); EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, frame2->windows_frame_info->type_); @@ -1747,7 +1747,7 @@ TEST_F(GetCallerFrame, HandleAlignmentInProgramString) { EXPECT_EQ(frame0_esp.Value(), frame->context.esp); EXPECT_EQ(frame0_ebp.Value(), frame->context.ebp); EXPECT_EQ(&chrome_dll, frame->module); - ASSERT_TRUE(frame->windows_frame_info != NULL); + ASSERT_TRUE(frame->windows_frame_info != nullptr); EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame->windows_frame_info->valid); EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, frame->windows_frame_info->type_); @@ -1772,7 +1772,7 @@ TEST_F(GetCallerFrame, HandleAlignmentInProgramString) { EXPECT_EQ(frame1_esp.Value(), frame->context.esp); EXPECT_EQ(frame1_ebp.Value(), frame->context.ebp); EXPECT_EQ(&chrome_dll, frame->module); - ASSERT_TRUE(frame->windows_frame_info != NULL); + ASSERT_TRUE(frame->windows_frame_info != nullptr); EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame->windows_frame_info->valid); EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, frame->windows_frame_info->type_); @@ -1794,7 +1794,7 @@ TEST_F(GetCallerFrame, HandleAlignmentInProgramString) { EXPECT_EQ(frame2_esp.Value(), frame->context.esp); EXPECT_EQ(frame2_ebp.Value(), frame->context.ebp); EXPECT_EQ(&chrome_dll, frame->module); - ASSERT_TRUE(frame->windows_frame_info != NULL); + ASSERT_TRUE(frame->windows_frame_info != nullptr); EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame->windows_frame_info->valid); EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, frame->windows_frame_info->type_); @@ -1993,9 +1993,9 @@ void GetCallerFrame::IPAddressIsNotInKnownModuleTestImpl( EXPECT_EQ(raw_context.eip, frame0->context.eip); EXPECT_EQ(raw_context.ebp, frame0->context.ebp); EXPECT_EQ(raw_context.esp, frame0->context.esp); - EXPECT_EQ(NULL, frame0->module); // IP not in known module + EXPECT_EQ(nullptr, frame0->module); // IP not in known module EXPECT_EQ("", frame0->function_name); - ASSERT_EQ(NULL, frame0->windows_frame_info); + ASSERT_EQ(nullptr, frame0->windows_frame_info); } { // To avoid reusing locals by mistake @@ -2009,7 +2009,7 @@ void GetCallerFrame::IPAddressIsNotInKnownModuleTestImpl( EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); EXPECT_EQ(&remoting_core_dll, frame1->module); EXPECT_EQ("nsc_ECDSAVerifyStub", frame1->function_name); - ASSERT_TRUE(frame1->windows_frame_info != NULL); + ASSERT_TRUE(frame1->windows_frame_info != nullptr); EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid); EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, frame1->windows_frame_info->type_); @@ -2029,7 +2029,7 @@ void GetCallerFrame::IPAddressIsNotInKnownModuleTestImpl( EXPECT_EQ(frame2_esp.Value(), frame2->context.esp); EXPECT_EQ(&remoting_core_dll, frame2->module); EXPECT_EQ("NSC_Verify", frame2->function_name); - ASSERT_TRUE(frame2->windows_frame_info != NULL); + ASSERT_TRUE(frame2->windows_frame_info != nullptr); EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame2->windows_frame_info->valid); EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, frame2->windows_frame_info->type_); @@ -2049,7 +2049,7 @@ void GetCallerFrame::IPAddressIsNotInKnownModuleTestImpl( EXPECT_EQ(frame3_esp.Value(), frame3->context.esp); EXPECT_EQ(&remoting_core_dll, frame3->module); EXPECT_EQ("PK11_Verify", frame3->function_name); - ASSERT_TRUE(frame3->windows_frame_info != NULL); + ASSERT_TRUE(frame3->windows_frame_info != nullptr); EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame3->windows_frame_info->valid); EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, frame3->windows_frame_info->type_); @@ -2134,10 +2134,10 @@ struct CFIFixture: public StackwalkerX86Fixture { ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); EXPECT_EQ("enchiridion", frame0->function_name); EXPECT_EQ(0x40004000U, frame0->function_base); - ASSERT_TRUE(frame0->windows_frame_info != NULL); + ASSERT_TRUE(frame0->windows_frame_info != nullptr); ASSERT_EQ(WindowsFrameInfo::VALID_PARAMETER_SIZE, frame0->windows_frame_info->valid); - ASSERT_TRUE(frame0->cfi_frame_info != NULL); + ASSERT_TRUE(frame0->cfi_frame_info != nullptr); } { // To avoid reusing locals by mistake diff --git a/src/processor/static_address_map_unittest.cc b/src/processor/static_address_map_unittest.cc index aebab976c..7626a0546 100644 --- a/src/processor/static_address_map_unittest.cc +++ b/src/processor/static_address_map_unittest.cc @@ -34,9 +34,12 @@ #include // Must come first #endif -#include -#include -#include +#include "processor/static_address_map-inl.h" + +#include +#include +#include + #include #include #include @@ -44,7 +47,6 @@ #include "breakpad_googletest_includes.h" #include "common/using_std_string.h" #include "processor/address_map-inl.h" -#include "processor/static_address_map-inl.h" #include "processor/simple_serializer-inl.h" #include "map_serializers-inl.h" @@ -69,7 +71,7 @@ class TestStaticAddressMap : public ::testing::Test { testdata[2][i] = tempdata[i]; // Test data set3: - srand(time(NULL)); + srand(time(nullptr)); for (int i = 0; i < testsize[3]; ++i) testdata[3][i] = rand(); @@ -81,7 +83,7 @@ class TestStaticAddressMap : public ::testing::Test { sstream << "test " << testdata[testcase][data_item]; addr_map[testcase].Store(testdata[testcase][data_item], sstream.str()); } - map_data[testcase] = serializer.Serialize(addr_map[testcase], NULL); + map_data[testcase] = serializer.Serialize(addr_map[testcase], nullptr); test_map[testcase] = TestMap(map_data[testcase]); } } @@ -98,7 +100,7 @@ class TestStaticAddressMap : public ::testing::Test { int address_test; string entry; string entry_test; - const char* entry_cstring = NULL; + const char* entry_cstring = nullptr; bool found; bool found_test; @@ -124,7 +126,7 @@ class TestStaticAddressMap : public ::testing::Test { srand(time(0)); for (int data_item = 0; data_item < testsize[testcase]; ++data_item) { - // Retrive (aka, search) for target address and compare results from + // Retrieve (aka, search) for target address and compare results from // AddressMap and StaticAddressMap. // First, assign the search target to be one of original testdata that is diff --git a/src/processor/static_contained_range_map-inl.h b/src/processor/static_contained_range_map-inl.h index 60606ddc6..78a2fc15c 100644 --- a/src/processor/static_contained_range_map-inl.h +++ b/src/processor/static_contained_range_map-inl.h @@ -45,12 +45,12 @@ template StaticContainedRangeMap::StaticContainedRangeMap( const char *base) : base_(*(reinterpret_cast(base))), - entry_size_(*(reinterpret_cast(base + sizeof(base_)))), + entry_size_(*(reinterpret_cast(base + sizeof(base_)))), entry_ptr_(reinterpret_cast( base + sizeof(base_) + sizeof(entry_size_))), map_(base + sizeof(base_) + sizeof(entry_size_) + entry_size_) { if (entry_size_ == 0) - entry_ptr_ = NULL; + entry_ptr_ = nullptr; } diff --git a/src/processor/static_contained_range_map.h b/src/processor/static_contained_range_map.h index 86e54666d..eea03db72 100644 --- a/src/processor/static_contained_range_map.h +++ b/src/processor/static_contained_range_map.h @@ -86,7 +86,7 @@ class StaticContainedRangeMap { // actually contain an entry, so its entry_ field is meaningless. For // this reason, the entry_ field should only be accessed on child // ContainedRangeMap objects, and never on |this|. - uint32_t entry_size_; + uint64_t entry_size_; const EntryType *entry_ptr_; // The map containing child ranges, keyed by each child range's high diff --git a/src/processor/static_contained_range_map_unittest.cc b/src/processor/static_contained_range_map_unittest.cc index d0507a4b1..261529e60 100644 --- a/src/processor/static_contained_range_map_unittest.cc +++ b/src/processor/static_contained_range_map_unittest.cc @@ -35,10 +35,15 @@ #include // Must come first #endif +#include "processor/static_contained_range_map-inl.h" + +#include + +#include + #include "breakpad_googletest_includes.h" #include "common/scoped_ptr.h" #include "processor/contained_range_map-inl.h" -#include "processor/static_contained_range_map-inl.h" #include "processor/simple_serializer-inl.h" #include "processor/map_serializers-inl.h" #include "processor/logging.h" @@ -161,7 +166,7 @@ class TestStaticCRMMap : public ::testing::Test { protected: void SetUp(); - // A referrence map for testing StaticCRMMap. + // A reference map for testing StaticCRMMap. google_breakpad::ContainedRangeMap crm_map_; // Static version of crm_map using serialized data of crm_map. @@ -177,7 +182,7 @@ class TestStaticCRMMap : public ::testing::Test { void TestStaticCRMMap::SetUp() { // First, do the StoreRange tests. This validates the containment // rules. - // We confirm the referrence map correctly stores data during setup. + // We confirm the reference map correctly stores data during setup. ASSERT_TRUE (crm_map_.StoreRange(10, 10, 1)); ASSERT_FALSE(crm_map_.StoreRange(10, 10, 2)); // exactly equal to 1 ASSERT_FALSE(crm_map_.StoreRange(11, 10, 3)); // begins inside 1 and extends up @@ -228,7 +233,7 @@ void TestStaticCRMMap::SetUp() { ASSERT_FALSE(crm_map_.StoreRange(86, 2, 48)); // Serialize crm_map to generate serialized data. - unsigned int size; + uint64_t size; serialized_data_.reset(serializer_.Serialize(&crm_map_, &size)); BPLOG(INFO) << "Serialized data size: " << size << " Bytes."; @@ -239,12 +244,12 @@ void TestStaticCRMMap::SetUp() { TEST_F(TestStaticCRMMap, TestEmptyMap) { CRMMap empty_crm_map; - unsigned int size; + uint64_t size; scoped_array serialized_data; serialized_data.reset(serializer_.Serialize(&empty_crm_map, &size)); - scoped_ptr test_map(new TestMap(serialized_data.get())); + std::unique_ptr test_map(new TestMap(serialized_data.get())); - const unsigned int kCorrectSizeForEmptyMap = 16; + const unsigned int kCorrectSizeForEmptyMap = 24; ASSERT_EQ(kCorrectSizeForEmptyMap, size); const int *entry_test; @@ -259,12 +264,12 @@ TEST_F(TestStaticCRMMap, TestSingleElementMap) { int entry = 1; crm_map.StoreRange(10, 10, entry); - unsigned int size; + uint64_t size; scoped_array serialized_data; serialized_data.reset(serializer_.Serialize(&crm_map, &size)); - scoped_ptr test_map(new TestMap(serialized_data.get())); + std::unique_ptr test_map(new TestMap(serialized_data.get())); - const unsigned int kCorrectSizeForSingleElementMap = 40; + const unsigned int kCorrectSizeForSingleElementMap = 60; ASSERT_EQ(kCorrectSizeForSingleElementMap, size); const int *entry_test; @@ -283,10 +288,10 @@ TEST_F(TestStaticCRMMap, TestRetrieveRangeEntries) { crm_map.StoreRange(2, 6, 1); crm_map.StoreRange(2, 7, 2); - unsigned int size; + uint64_t size; scoped_array serialized_data; serialized_data.reset(serializer_.Serialize(&crm_map, &size)); - scoped_ptr test_map(new TestMap(serialized_data.get())); + std::unique_ptr test_map(new TestMap(serialized_data.get())); std::vector entry_tests; ASSERT_TRUE(test_map->RetrieveRanges(3, entry_tests)); diff --git a/src/processor/static_map-inl.h b/src/processor/static_map-inl.h index f9929efe9..2e827b9f7 100644 --- a/src/processor/static_map-inl.h +++ b/src/processor/static_map-inl.h @@ -47,23 +47,23 @@ StaticMap::StaticMap(const char* raw_data) : raw_data_(raw_data), compare_() { // First 4 Bytes store the number of nodes. - num_nodes_ = *(reinterpret_cast(raw_data_)); + num_nodes_ = *(reinterpret_cast(raw_data_)); - offsets_ = reinterpret_cast( + offsets_ = reinterpret_cast( raw_data_ + sizeof(num_nodes_)); keys_ = reinterpret_cast( - raw_data_ + (1 + num_nodes_) * sizeof(uint32_t)); + raw_data_ + (1 + num_nodes_) * sizeof(uint64_t)); } // find(), lower_bound() and upper_bound() implement binary search algorithm. template StaticMapIterator StaticMap::find(const Key& key) const { - int begin = 0; - int end = num_nodes_; - int middle; - int compare_result; + int64_t begin = 0; + int64_t end = num_nodes_; + int64_t middle; + int64_t compare_result; while (begin < end) { middle = begin + (end - begin) / 2; compare_result = compare_(key, GetKeyAtIndex(middle)); @@ -81,10 +81,10 @@ StaticMap::find(const Key& key) const { template StaticMapIterator StaticMap::lower_bound(const Key& key) const { - int begin = 0; - int end = num_nodes_; - int middle; - int comp_result; + int64_t begin = 0; + int64_t end = num_nodes_; + int64_t middle; + int64_t comp_result; while (begin < end) { middle = begin + (end - begin) / 2; comp_result = compare_(key, GetKeyAtIndex(middle)); @@ -102,10 +102,10 @@ StaticMap::lower_bound(const Key& key) const { template StaticMapIterator StaticMap::upper_bound(const Key& key) const { - int begin = 0; - int end = num_nodes_; - int middle; - int compare_result; + int64_t begin = 0; + int64_t end = num_nodes_; + int64_t middle; + int64_t compare_result; while (begin < end) { middle = begin + (end - begin) / 2; compare_result = compare_(key, GetKeyAtIndex(middle)); @@ -124,22 +124,22 @@ template bool StaticMap::ValidateInMemoryStructure() const { // check the number of nodes is non-negative: if (!raw_data_) return false; - int32_t num_nodes = *(reinterpret_cast(raw_data_)); + int64_t num_nodes = *(reinterpret_cast(raw_data_)); if (num_nodes < 0) { BPLOG(INFO) << "StaticMap check failed: negative number of nodes"; return false; } - int node_index = 0; + int64_t node_index = 0; if (num_nodes_) { - uint64_t first_offset = sizeof(int32_t) * (num_nodes_ + 1) + uint64_t first_offset = sizeof(int64_t) * (num_nodes_ + 1) + sizeof(Key) * num_nodes_; // Num_nodes_ is too large. if (first_offset > 0xffffffffUL) { BPLOG(INFO) << "StaticMap check failed: size exceeds limit"; return false; } - if (offsets_[node_index] != static_cast(first_offset)) { + if (offsets_[node_index] != static_cast(first_offset)) { BPLOG(INFO) << "StaticMap check failed: first node offset is incorrect"; return false; } @@ -162,7 +162,7 @@ bool StaticMap::ValidateInMemoryStructure() const { } template -const Key StaticMap::GetKeyAtIndex(int index) const { +const Key StaticMap::GetKeyAtIndex(int64_t index) const { if (index < 0 || index >= num_nodes_) { BPLOG(ERROR) << "Key index out of range error"; // Key type is required to be primitive type. Return 0 if index is invalid. diff --git a/src/processor/static_map.h b/src/processor/static_map.h index a8f495820..be2c7d55a 100644 --- a/src/processor/static_map.h +++ b/src/processor/static_map.h @@ -34,11 +34,11 @@ // // The chunk of memory should contain data with pre-defined pattern: // **************** header *************** -// uint32 (4 bytes): number of nodes -// uint32 (4 bytes): address offset of node1's mapped_value -// uint32 (4 bytes): address offset of node2's mapped_value +// int64 (8 bytes): number of nodes +// uint64 (8 bytes): address offset of node1's mapped_value +// uint64 (8 bytes): address offset of node2's mapped_value // ... -// uint32 (4 bytes): address offset of nodeN's mapped_value +// uint64 (8 bytes): address offset of nodeN's mapped_value // // ************* Key array ************ // (X bytes): node1's key @@ -54,9 +54,6 @@ // // REQUIREMENT: Key type MUST be primitive type or pointers so that: // X = sizeof(typename Key); -// -// Note: since address offset is stored as uint32, user should keep in mind that -// StaticMap only supports up to 4GB size of memory data. // Author: Siyang Xie (lambxsy@google.com) @@ -72,7 +69,7 @@ namespace google_breakpad { template class DefaultCompare { public: - int operator()(const Key& k1, const Key& k2) const { + int64_t operator()(const Key& k1, const Key& k2) const { if (k1 < k2) return -1; if (k1 == k2) return 0; return 1; @@ -93,13 +90,13 @@ class StaticMap { explicit StaticMap(const char* raw_data); inline bool empty() const { return num_nodes_ == 0; } - inline unsigned int size() const { return num_nodes_; } + inline uint64_t size() const { return num_nodes_; } // Return iterators. inline iterator begin() const { return IteratorAtIndex(0); } inline iterator last() const { return IteratorAtIndex(num_nodes_ - 1); } inline iterator end() const { return IteratorAtIndex(num_nodes_); } - inline iterator IteratorAtIndex(int index) const { + inline iterator IteratorAtIndex(int64_t index) const { return iterator(raw_data_, index); } @@ -120,18 +117,18 @@ class StaticMap { bool ValidateInMemoryStructure() const; private: - const Key GetKeyAtIndex(int i) const; + const Key GetKeyAtIndex(int64_t i) const; // Start address of a raw memory chunk with serialized data. const char* raw_data_; // Number of nodes in the static map. - int32_t num_nodes_; + int64_t num_nodes_; // Array of offset addresses for stored values. // For example: // address_of_i-th_node_value = raw_data_ + offsets_[i] - const uint32_t* offsets_; + const uint64_t* offsets_; // keys_[i] = key of i_th node const Key* keys_; diff --git a/src/processor/static_map_iterator-inl.h b/src/processor/static_map_iterator-inl.h index 01a1b7f7b..1e1d417ec 100644 --- a/src/processor/static_map_iterator-inl.h +++ b/src/processor/static_map_iterator-inl.h @@ -43,12 +43,12 @@ namespace google_breakpad { template StaticMapIterator::StaticMapIterator(const char* base, - const int& index): + int64_t index): index_(index), base_(base) { // See static_map.h for documentation on // bytes format of serialized StaticMap data. - num_nodes_ = *(reinterpret_cast(base_)); - offsets_ = reinterpret_cast(base_ + sizeof(num_nodes_)); + num_nodes_ = *(reinterpret_cast(base_)); + offsets_ = reinterpret_cast(base_ + sizeof(num_nodes_)); keys_ = reinterpret_cast( base_ + (1 + num_nodes_) * sizeof(num_nodes_)); } @@ -106,7 +106,7 @@ template const Key* StaticMapIterator::GetKeyPtr() const { if (!IsValid()) { BPLOG(ERROR) << "call GetKeyPtr() on invalid iterator"; - return NULL; + return nullptr; } return &(keys_[index_]); } @@ -115,7 +115,7 @@ template const char* StaticMapIterator::GetValueRawPtr() const { if (!IsValid()) { BPLOG(ERROR) << "call GetValuePtr() on invalid iterator"; - return NULL; + return nullptr; } return base_ + offsets_[index_]; } diff --git a/src/processor/static_map_iterator.h b/src/processor/static_map_iterator.h index 6c190e975..53d7c5d77 100644 --- a/src/processor/static_map_iterator.h +++ b/src/processor/static_map_iterator.h @@ -52,7 +52,7 @@ template class StaticMapIterator { public: // Constructors. - StaticMapIterator(): index_(-1), base_(NULL) { } + StaticMapIterator(): index_(-1), base_(nullptr) { } // Increment & Decrement operators: StaticMapIterator& operator++(); @@ -87,21 +87,21 @@ class StaticMapIterator { friend class StaticMap; // Only StaticMap can call this constructor. - explicit StaticMapIterator(const char* base, const int32_t& index); + explicit StaticMapIterator(const char* base, int64_t index); // Index of node that the iterator is pointing to. - int32_t index_; + int64_t index_; // Beginning address of the serialized map data. const char* base_; // Number of nodes in the map. Use it to identify end() iterator. - int32_t num_nodes_; + int64_t num_nodes_; // offsets_ is an array of offset addresses of mapped values. // For example: // address_of_i-th_node_value = base_ + offsets_[i] - const uint32_t* offsets_; + const uint64_t* offsets_; // keys_[i] = key of i_th node. const Key* keys_; diff --git a/src/processor/static_map_unittest.cc b/src/processor/static_map_unittest.cc index 67b201b63..7ad9bb85c 100644 --- a/src/processor/static_map_unittest.cc +++ b/src/processor/static_map_unittest.cc @@ -34,12 +34,14 @@ #include // Must come first #endif -#include +#include "processor/static_map-inl.h" + +#include +#include + #include #include "breakpad_googletest_includes.h" -#include "processor/static_map-inl.h" - typedef int ValueType; typedef int KeyType; @@ -50,10 +52,10 @@ template class SimpleMapSerializer { public: static char* Serialize(const std::map& stdmap, - unsigned int* size = NULL) { + unsigned int* size = nullptr) { unsigned int size_per_node = - sizeof(uint32_t) + sizeof(Key) + sizeof(Value); - unsigned int memsize = sizeof(int32_t) + size_per_node * stdmap.size(); + sizeof(uint64_t) + sizeof(Key) + sizeof(Value); + unsigned int memsize = sizeof(int64_t) + size_per_node * stdmap.size(); if (size) *size = memsize; // Allocate memory for serialized data: @@ -61,12 +63,12 @@ class SimpleMapSerializer { char* address = mem; // Writer the number of nodes: - new (address) uint32_t(static_cast(stdmap.size())); - address += sizeof(uint32_t); + new (address) uint64_t(static_cast(stdmap.size())); + address += sizeof(uint64_t); // Nodes' offset: - uint32_t* offsets = reinterpret_cast(address); - address += sizeof(uint32_t) * stdmap.size(); + uint64_t* offsets = reinterpret_cast(address); + address += sizeof(uint64_t) * stdmap.size(); // Keys: Key* keys = reinterpret_cast(address); @@ -98,16 +100,16 @@ class TestInvalidMap : public ::testing::Test { }; TEST_F(TestInvalidMap, TestNegativeNumberNodes) { - memset(data, 0xff, sizeof(uint32_t)); // Set the number of nodes = -1 + memset(data, 0xff, sizeof(uint64_t)); // Set the number of nodes = -1 test_map = TestMap(data); ASSERT_FALSE(test_map.ValidateInMemoryStructure()); } TEST_F(TestInvalidMap, TestWrongOffsets) { - uint32_t* header = reinterpret_cast(data); - const uint32_t kNumNodes = 2; - const uint32_t kHeaderOffset = - sizeof(uint32_t) + kNumNodes * (sizeof(uint32_t) + sizeof(KeyType)); + uint64_t* header = reinterpret_cast(data); + const uint64_t kNumNodes = 2; + const uint64_t kHeaderOffset = + sizeof(uint64_t) + kNumNodes * (sizeof(uint64_t) + sizeof(KeyType)); header[0] = kNumNodes; header[1] = kHeaderOffset + 3; // Wrong offset for first node @@ -121,16 +123,16 @@ TEST_F(TestInvalidMap, TestWrongOffsets) { } TEST_F(TestInvalidMap, TestUnSortedKeys) { - uint32_t* header = reinterpret_cast(data); - const uint32_t kNumNodes = 2; - const uint32_t kHeaderOffset = - sizeof(uint32_t) + kNumNodes * (sizeof(uint32_t) + sizeof(KeyType)); + uint64_t* header = reinterpret_cast(data); + const uint64_t kNumNodes = 2; + const uint64_t kHeaderOffset = + sizeof(uint64_t) + kNumNodes * (sizeof(uint64_t) + sizeof(KeyType)); header[0] = kNumNodes; header[1] = kHeaderOffset; header[2] = kHeaderOffset + sizeof(ValueType); KeyType* keys = reinterpret_cast( - data + (kNumNodes + 1) * sizeof(uint32_t)); + data + (kNumNodes + 1) * sizeof(uint64_t)); // Set keys in non-increasing order. keys[0] = 10; keys[1] = 7; @@ -174,10 +176,10 @@ class TestValidMap : public ::testing::Test { // Set correct size of memory allocation for each test case. unsigned int size_per_node = - sizeof(uint32_t) + sizeof(KeyType) + sizeof(ValueType); + sizeof(uint64_t) + sizeof(KeyType) + sizeof(ValueType); for (testcase = 0; testcase < kNumberTestCases; ++testcase) { correct_size[testcase] = - sizeof(uint32_t) + std_map[testcase].size() * size_per_node; + sizeof(uint64_t) + std_map[testcase].size() * size_per_node; } } diff --git a/src/processor/static_range_map-inl.h b/src/processor/static_range_map-inl.h index b0a327479..3ffeec975 100644 --- a/src/processor/static_range_map-inl.h +++ b/src/processor/static_range_map-inl.h @@ -102,7 +102,7 @@ bool StaticRangeMap::RetrieveNearestRange( template bool StaticRangeMap::RetrieveRangeAtIndex( - int index, const EntryType*& entry, + int64_t index, const EntryType*& entry, AddressType* entry_base, AddressType* entry_size) const { if (index >= GetCount()) { diff --git a/src/processor/static_range_map.h b/src/processor/static_range_map.h index 319085db2..c63d2fa94 100644 --- a/src/processor/static_range_map.h +++ b/src/processor/static_range_map.h @@ -73,12 +73,12 @@ class StaticRangeMap { // range. // // RetrieveRangeAtIndex is not optimized for speedy operation. - bool RetrieveRangeAtIndex(int index, const EntryType*& entry, + bool RetrieveRangeAtIndex(int64_t index, const EntryType*& entry, AddressType* entry_base, AddressType* entry_size) const; // Returns the number of ranges stored in the RangeMap. - inline int GetCount() const { return map_.size(); } + inline int64_t GetCount() const { return map_.size(); } private: friend class ModuleComparer; diff --git a/src/processor/static_range_map_unittest.cc b/src/processor/static_range_map_unittest.cc index d4ddec0c5..e7e65d1ca 100644 --- a/src/processor/static_range_map_unittest.cc +++ b/src/processor/static_range_map_unittest.cc @@ -34,6 +34,8 @@ #include // Must come first #endif +#include + #include "breakpad_googletest_includes.h" #include "common/scoped_ptr.h" #include "processor/range_map-inl.h" @@ -322,7 +324,7 @@ void TestStaticRangeMap::RetrieveIndexTest(const TestMap* range_map, int set) { ASSERT_TRUE(range_map->RetrieveRangeAtIndex(object_index, entry, &base, - NULL)) + nullptr)) << "FAILED: RetrieveRangeAtIndex set " << set << " index " << object_index; @@ -346,16 +348,16 @@ void TestStaticRangeMap::RetrieveIndexTest(const TestMap* range_map, int set) { // Make sure that RetrieveRangeAtIndex doesn't allow lookups at indices that // are too high. ASSERT_FALSE(range_map->RetrieveRangeAtIndex( - object_count, entry, NULL, NULL)) << "FAILED: RetrieveRangeAtIndex set " - << set << " index " << object_count - << " (too large)"; + object_count, entry, nullptr, nullptr)) << "FAILED: RetrieveRangeAtIndex " + << "set " << set << " index " + << object_count << " (too large)"; } // RunTests runs a series of test sets. void TestStaticRangeMap::RunTestCase(int test_case) { // Maintain the range map in a pointer so that deletion can be meaningfully // tested. - scoped_ptr rmap(new RMap()); + std::unique_ptr rmap(new RMap()); const RangeTest* range_tests = range_test_sets[test_case].range_tests; unsigned int range_test_count = range_test_sets[test_case].range_test_count; @@ -373,8 +375,8 @@ void TestStaticRangeMap::RunTestCase(int test_case) { ++stored_count; } - scoped_array memaddr(serializer_.Serialize(*rmap, NULL)); - scoped_ptr static_range_map(new TestMap(memaddr.get())); + scoped_array memaddr(serializer_.Serialize(*rmap, nullptr)); + std::unique_ptr static_range_map(new TestMap(memaddr.get())); // The RangeMap's own count of objects should also match. EXPECT_EQ(static_range_map->GetCount(), stored_count); diff --git a/src/processor/synth_minidump.cc b/src/processor/synth_minidump.cc index e51d1060a..3356ee7c0 100644 --- a/src/processor/synth_minidump.cc +++ b/src/processor/synth_minidump.cc @@ -36,6 +36,8 @@ #include "processor/synth_minidump.h" +#include + namespace google_breakpad { namespace SynthMinidump { diff --git a/src/processor/synth_minidump.h b/src/processor/synth_minidump.h index a52be03bf..b747f2328 100644 --- a/src/processor/synth_minidump.h +++ b/src/processor/synth_minidump.h @@ -259,8 +259,8 @@ class Module: public Section { uint32_t time_date_stamp = 1262805309, uint32_t checksum = 0, const MDVSFixedFileInfo& version_info = Module::stock_version_info, - const Section* cv_record = NULL, - const Section* misc_record = NULL); + const Section* cv_record = nullptr, + const Section* misc_record = nullptr); private: // A standard MDVSFixedFileInfo structure to use as a default for diff --git a/src/processor/synth_minidump_unittest.cc b/src/processor/synth_minidump_unittest.cc index 3b803afe3..e19fc51cd 100644 --- a/src/processor/synth_minidump_unittest.cc +++ b/src/processor/synth_minidump_unittest.cc @@ -35,6 +35,8 @@ #include // Must come first #endif +#include + #include #include @@ -147,7 +149,12 @@ TEST(Context, ARM) { == 0); } +#if GTEST_OS_WINDOWS && !GTEST_HAS_ABSL +// GTest on Windows does not support complex regular expressions. +TEST(ContextDeathTest, DISABLED_X86BadFlags) { +#else TEST(ContextDeathTest, X86BadFlags) { +#endif Dump dump(0, kLittleEndian); MDRawContextX86 raw; raw.context_flags = MD_CONTEXT_AMD64; @@ -155,7 +162,12 @@ TEST(ContextDeathTest, X86BadFlags) { "context\\.context_flags & (0x[0-9a-f]+|MD_CONTEXT_X86)"); } +#if GTEST_OS_WINDOWS && !GTEST_HAS_ABSL +// GTest on Windows does not support complex regular expressions. +TEST(ContextDeathTest, DISABLED_X86BadEndianness) { +#else TEST(ContextDeathTest, X86BadEndianness) { +#endif Dump dump(0, kBigEndian); MDRawContextX86 raw; raw.context_flags = MD_CONTEXT_X86; diff --git a/src/processor/testdata/linux_test_app.cc b/src/processor/testdata/linux_test_app.cc index b0bbb6698..fcf78247f 100644 --- a/src/processor/testdata/linux_test_app.cc +++ b/src/processor/testdata/linux_test_app.cc @@ -75,7 +75,7 @@ static void CrashFunction() { } // namespace int main(int argc, char** argv) { - google_breakpad::ExceptionHandler eh(".", NULL, callback, NULL, true); + google_breakpad::ExceptionHandler eh(".", nullptr, callback, nullptr, true); if (!eh.WriteMinidump()) { printf("Failed to generate on-demand minidump\n"); } diff --git a/src/processor/testdata/test_app.cc b/src/processor/testdata/test_app.cc index 83468fbbf..cd5eafd24 100644 --- a/src/processor/testdata/test_app.cc +++ b/src/processor/testdata/test_app.cc @@ -64,7 +64,7 @@ static void CrashFunction() { int main(int argc, char** argv) { google_breakpad::ExceptionHandler eh( - L".", NULL, callback, NULL, + L".", nullptr, callback, nullptr, google_breakpad::ExceptionHandler::HANDLER_ALL); CrashFunction(); printf("did not crash?\n"); diff --git a/src/processor/testdata/tiny-exe-with-cet-xsave-x86.dmp b/src/processor/testdata/tiny-exe-with-cet-xsave-x86.dmp new file mode 100644 index 000000000..f5a08ca86 Binary files /dev/null and b/src/processor/testdata/tiny-exe-with-cet-xsave-x86.dmp differ diff --git a/src/processor/tokenize.cc b/src/processor/tokenize.cc index a46c9644c..87271c8f4 100644 --- a/src/processor/tokenize.cc +++ b/src/processor/tokenize.cc @@ -32,6 +32,7 @@ #include +#include #include #include @@ -61,11 +62,11 @@ bool Tokenize(char* line, while (token && --remaining > 0) { tokens->push_back(token); if (remaining > 1) - token = strtok_r(NULL, separators, &save_ptr); + token = strtok_r(nullptr, separators, &save_ptr); } // If there's anything left, just add it as a single token. - if (remaining == 0 && (token = strtok_r(NULL, "\r\n", &save_ptr))) { + if (remaining == 0 && (token = strtok_r(nullptr, "\r\n", &save_ptr))) { tokens->push_back(token); } diff --git a/src/processor/windows_frame_info.h b/src/processor/windows_frame_info.h index 4014a1a99..88e1b8bbe 100644 --- a/src/processor/windows_frame_info.h +++ b/src/processor/windows_frame_info.h @@ -95,7 +95,7 @@ struct WindowsFrameInfo { uint32_t set_local_size, uint32_t set_max_stack_size, int set_allocates_base_pointer, - const string set_program_string) + const string& set_program_string) : type_(type), valid(VALID_ALL), prolog_size(set_prolog_size), @@ -111,7 +111,7 @@ struct WindowsFrameInfo { // a string. Returns NULL if parsing fails, or a new object // otherwise. type, rva and code_size are present in the STACK line, // but not the StackFrameInfo structure, so return them as outparams. - static WindowsFrameInfo *ParseFromString(const string string, + static WindowsFrameInfo *ParseFromString(const string& string, int& type, uint64_t& rva, uint64_t& code_size) { @@ -123,28 +123,28 @@ struct WindowsFrameInfo { StringToVector(string, buffer); std::vector tokens; if (!Tokenize(&buffer[0], " \r\n", 11, &tokens)) - return NULL; + return nullptr; - type = strtol(tokens[0], NULL, 16); + type = strtol(tokens[0], nullptr, 16); if (type < 0 || type > STACK_INFO_LAST - 1) - return NULL; - - rva = strtoull(tokens[1], NULL, 16); - code_size = strtoull(tokens[2], NULL, 16); - uint32_t prolog_size = strtoul(tokens[3], NULL, 16); - uint32_t epilog_size = strtoul(tokens[4], NULL, 16); - uint32_t parameter_size = strtoul(tokens[5], NULL, 16); - uint32_t saved_register_size = strtoul(tokens[6], NULL, 16); - uint32_t local_size = strtoul(tokens[7], NULL, 16); - uint32_t max_stack_size = strtoul(tokens[8], NULL, 16); - int has_program_string = strtoul(tokens[9], NULL, 16); + return nullptr; + + rva = strtoull(tokens[1], nullptr, 16); + code_size = strtoull(tokens[2], nullptr, 16); + uint32_t prolog_size = strtoul(tokens[3], nullptr, 16); + uint32_t epilog_size = strtoul(tokens[4], nullptr, 16); + uint32_t parameter_size = strtoul(tokens[5], nullptr, 16); + uint32_t saved_register_size = strtoul(tokens[6], nullptr, 16); + uint32_t local_size = strtoul(tokens[7], nullptr, 16); + uint32_t max_stack_size = strtoul(tokens[8], nullptr, 16); + int has_program_string = strtoul(tokens[9], nullptr, 16); const char *program_string = ""; int allocates_base_pointer = 0; if (has_program_string) { program_string = tokens[10]; } else { - allocates_base_pointer = strtoul(tokens[10], NULL, 16); + allocates_base_pointer = strtoul(tokens[10], nullptr, 16); } return new WindowsFrameInfo(static_cast(type), diff --git a/src/third_party/libdisasm/ia32_modrm.c b/src/third_party/libdisasm/ia32_modrm.c index b0fe2ed3d..c80c1b95e 100644 --- a/src/third_party/libdisasm/ia32_modrm.c +++ b/src/third_party/libdisasm/ia32_modrm.c @@ -2,6 +2,9 @@ #include "ia32_reg.h" #include "x86_imm.h" +#include +#include + /* NOTE: when decoding ModR/M and SIB, we have to add 1 to all register * values obtained from decoding the ModR/M or SIB byte, since they * are encoded with eAX = 0 and the tables in ia32_reg.c use eAX = 1. @@ -72,16 +75,18 @@ static unsigned int imm32_signsized( unsigned char *buf, size_t buf_len, return 0; } + int16_t local_short; switch (size) { case 1: *dest = *((signed char *) buf); break; case 2: - *dest = *((signed short *) buf); + memcpy(&local_short, buf, 2); + *dest = local_short; break; case 4: default: - *dest = *((signed int *) buf); + memcpy(dest, buf, 4); break; } diff --git a/src/third_party/libdisasm/x86_imm.c b/src/third_party/libdisasm/x86_imm.c index cd59bfc9a..11c8a7de9 100644 --- a/src/third_party/libdisasm/x86_imm.c +++ b/src/third_party/libdisasm/x86_imm.c @@ -2,36 +2,15 @@ #include "x86_imm.h" #include +#include unsigned int x86_imm_signsized( unsigned char * buf, size_t buf_len, void *dest, unsigned int size ) { - signed char *cp = (signed char *) dest; - signed short *sp = (signed short *) dest; - int32_t *lp = (int32_t *) dest; - qword_t *qp = (qword_t *) dest; - if ( size > buf_len ) { return 0; } - /* Copy 'size' bytes from *buf to *op - * return number of bytes copied */ - switch (size) { - case 1: /* BYTE */ - *cp = *((signed char *) buf); - break; - case 2: /* WORD */ - *sp = *((signed short *) buf); - break; - case 6: - case 8: /* QWORD */ - *qp = *((qword_t *) buf); - break; - case 4: /* DWORD */ - default: - *lp = *((int32_t *) buf); - break; - } + memcpy(dest, buf, size); return (size); } diff --git a/src/tools/linux/dump_syms/dump_syms.cc b/src/tools/linux/dump_syms/dump_syms.cc index 2fce23c2a..f5f89f410 100644 --- a/src/tools/linux/dump_syms/dump_syms.cc +++ b/src/tools/linux/dump_syms/dump_syms.cc @@ -32,9 +32,9 @@ #include #include +#include #include -#include #include #include #include @@ -52,11 +52,14 @@ int usage(const char* self) { google_breakpad::BaseName(self).c_str()); fprintf(stderr, "Options:\n"); fprintf(stderr, " -i: Output module header information only.\n"); + fprintf(stderr, " -a Preserve the load address - Do not normalize " + "the load address to zero.\n"); fprintf(stderr, " -c Do not generate CFI section\n"); fprintf(stderr, " -d Generate INLINE/INLINE_ORIGIN records\n"); fprintf(stderr, " -r Do not handle inter-compilation " "unit references\n"); fprintf(stderr, " -v Print all warnings to stderr\n"); + fprintf(stderr, " -b Use specified id for the module id\n"); fprintf(stderr, " -n Use specified name for name of the object\n"); fprintf(stderr, " -o Use specified name for the " "operating system\n"); @@ -69,6 +72,7 @@ int usage(const char* self) { int main(int argc, char** argv) { if (argc < 2) return usage(argv[0]); + bool preserve_load_address = false; bool header_only = false; bool cfi = true; bool handle_inlines = false; @@ -76,12 +80,15 @@ int main(int argc, char** argv) { bool log_to_stderr = false; bool enable_multiple_field = false; std::string obj_name; + std::string module_id; const char* obj_os = "Linux"; int arg_index = 1; while (arg_index < argc && strlen(argv[arg_index]) > 0 && argv[arg_index][0] == '-') { if (strcmp("-i", argv[arg_index]) == 0) { header_only = true; + } else if (strcmp("-a", argv[arg_index]) == 0) { + preserve_load_address = true; } else if (strcmp("-c", argv[arg_index]) == 0) { cfi = false; } else if (strcmp("-d", argv[arg_index]) == 0) { @@ -90,6 +97,13 @@ int main(int argc, char** argv) { handle_inter_cu_refs = false; } else if (strcmp("-v", argv[arg_index]) == 0) { log_to_stderr = true; + } else if (strcmp("-b", argv[arg_index]) == 0) { + if (arg_index + 1 >= argc) { + fprintf(stderr, "Missing argument to -b\n"); + return usage(argv[0]); + } + module_id = argv[arg_index + 1]; + ++arg_index; } else if (strcmp("-n", argv[arg_index]) == 0) { if (arg_index + 1 >= argc) { fprintf(stderr, "Missing argument to -n\n"); @@ -135,7 +149,7 @@ int main(int argc, char** argv) { obj_name = binary; if (header_only) { - if (!WriteSymbolFileHeader(binary, obj_name, obj_os, std::cout)) { + if (!WriteSymbolFileHeader(binary, obj_name, obj_os, module_id, std::cout)) { fprintf(saved_stderr, "Failed to process file.\n"); return 1; } @@ -143,8 +157,8 @@ int main(int argc, char** argv) { SymbolData symbol_data = (handle_inlines ? INLINES : NO_DATA) | (cfi ? CFI : NO_DATA) | SYMBOLS_AND_FILES; google_breakpad::DumpOptions options(symbol_data, handle_inter_cu_refs, - enable_multiple_field); - if (!WriteSymbolFile(binary, obj_name, obj_os, debug_dirs, options, + enable_multiple_field, preserve_load_address); + if (!WriteSymbolFile(binary, obj_name, obj_os, module_id, debug_dirs, options, std::cout)) { fprintf(saved_stderr, "Failed to write symbol file.\n"); return 1; diff --git a/src/tools/linux/md2core/minidump-2-core.cc b/src/tools/linux/md2core/minidump-2-core.cc index 3e310bc7d..d60de5fcf 100644 --- a/src/tools/linux/md2core/minidump-2-core.cc +++ b/src/tools/linux/md2core/minidump-2-core.cc @@ -49,6 +49,7 @@ #include #include "common/linux/memory_mapped_file.h" +#include "common/memory_allocator.h" #include "common/minidump_type_helper.h" #include "common/path_helper.h" #include "common/scoped_ptr.h" @@ -97,6 +98,7 @@ typedef gregset_t user_regs_struct; using google_breakpad::MDTypeHelper; using google_breakpad::MemoryMappedFile; using google_breakpad::MinidumpMemoryRange; +using google_breakpad::PageAllocator; typedef MDTypeHelper::MDRawDebug MDRawDebug; typedef MDTypeHelper::MDRawLinkMap MDRawLinkMap; @@ -147,7 +149,7 @@ static void SetupOptions(int argc, const char* argv[], Options* options) { extern int optind; int ch; - const char* output_file = NULL; + const char* output_file = nullptr; // Initialize the options struct as needed. options->verbose = false; @@ -187,7 +189,7 @@ SetupOptions(int argc, const char* argv[], Options* options) { exit(1); } - if (output_file == NULL || !strcmp(output_file, "-")) { + if (output_file == nullptr || !strcmp(output_file, "-")) { options->out_fd = STDOUT_FILENO; } else { options->out_fd = open(output_file, O_WRONLY|O_CREAT|O_TRUNC, 0664); @@ -283,7 +285,7 @@ typedef struct prpsinfo { /* Information about process */ struct CrashedProcess { CrashedProcess() : exception{-1}, - auxv(NULL), + auxv(nullptr), auxv_length(0) { memset(&prps, 0, sizeof(prps)); prps.pr_sname = 'R'; @@ -349,6 +351,34 @@ struct CrashedProcess { std::vector link_map; }; +/* NT_FILE note as defined by linux kernel in fs/binfmt_elf.c + * is structured as: + * long count -- how many files are mapped + * long page_size -- units for file_ofs + * array of [COUNT] elements of + * long start + * long end + * long file_ofs + * followed by COUNT filenames in ASCII: "FILE1" NUL "FILE2" NUL... + * we can re-use the file mappings info + */ +struct NtFileNote { + NtFileNote() + // XXX: we really should source page size from the minidump itself but + // I cannot find anywhere in the minidump generation code where this + // would be stashed. + : page_sz((unsigned long)getpagesize()), + filename_count(0), + filenames_length(0) { + } + + unsigned long page_sz; + unsigned long filename_count; + std::vector file_mappings; + std::vector filenames; + size_t filenames_length; +}; + #if defined(__i386__) static uint32_t U32(const uint8_t* data) { @@ -802,8 +832,8 @@ ParseMaps(const Options& options, CrashedProcess* crashinfo, eol ? eol - ptr : range.data() + range.length() - ptr); ptr = eol ? eol + 1 : range.data() + range.length(); unsigned long long start, stop, offset; - char* permissions = NULL; - char* filename = NULL; + char* permissions = nullptr; + char* filename = nullptr; sscanf(line.c_str(), "%llx-%llx %m[-rwxp] %llx %*[:0-9a-f] %*d %ms", &start, &stop, &permissions, &offset, &filename); if (filename && *filename == '/') { @@ -1162,8 +1192,7 @@ AddDataToMapping(CrashedProcess* crashinfo, const string& data, CrashedProcess::Mapping mapping; mapping.permissions = PF_R | PF_W; mapping.start_address = addr & ~4095; - mapping.end_address = - (addr + data.size() + 4095) & ~4095; + mapping.end_address = PageAllocator::AlignUp(addr + data.size(), 4096); mapping.data.assign(addr & 4095, 0).append(data); mapping.data.append(-mapping.data.size() & 4095, 0); crashinfo->mappings[mapping.start_address] = mapping; @@ -1262,9 +1291,9 @@ AugmentMappings(const Options& options, CrashedProcess* crashinfo, if (std::distance(iter, crashinfo->link_map.end()) == 1) { link_map.l_next = 0; } else { - link_map.l_next = (struct link_map*)(start_addr + data.size() + - sizeof(link_map) + - ((filename.size() + 8) & ~7)); + link_map.l_next = + (struct link_map*)(start_addr + data.size() + sizeof(link_map) + + PageAllocator::AlignUp(filename.size(), 8)); } data.append((char*)&link_map, sizeof(link_map)); data.append(filename); @@ -1298,6 +1327,8 @@ AugmentMappings(const Options& options, CrashedProcess* crashinfo, } AddDataToMapping(crashinfo, crashinfo->dynamic_data, (uintptr_t)crashinfo->debug.dynamic); + } else { + fprintf(stderr, "dynamic data empty\n"); } } @@ -1417,19 +1448,40 @@ main(int argc, const char* argv[]) { if (!writea(options.out_fd, &ehdr, sizeof(Ehdr))) return 1; + struct NtFileNote nt_file; + for (auto iter = crashinfo.mappings.begin(); + iter != crashinfo.mappings.end(); iter++) { + if (iter->second.filename.empty()) + continue; + nt_file.file_mappings.push_back(iter->second.start_address); + nt_file.file_mappings.push_back(iter->second.end_address); + nt_file.file_mappings.push_back(iter->second.offset); + nt_file.filenames.push_back(iter->second.filename); + nt_file.filenames_length += iter->second.filename.length() + 1; + nt_file.filename_count += 1; + } + // implementation of NT_FILE note seems to pad alignment by 4 bytes but + // keep the header size the true size of the note. so we keep nt_file_align + // as separate field. + size_t nt_file_data_sz = (2 * sizeof(unsigned long)) + + (nt_file.file_mappings.size() * sizeof(unsigned long)) + + nt_file.filenames_length; + size_t nt_file_align = nt_file_data_sz % 4 == 0 ? 0 : 4 - + (nt_file_data_sz % 4); size_t offset = sizeof(Ehdr) + ehdr.e_phnum * sizeof(Phdr); size_t filesz = sizeof(Nhdr) + 8 + sizeof(prpsinfo) + - // sizeof(Nhdr) + 8 + sizeof(user) + - sizeof(Nhdr) + 8 + crashinfo.auxv_length + - crashinfo.threads.size() * ( - (sizeof(Nhdr) + 8 + sizeof(prstatus)) + // sizeof(Nhdr) + 8 + sizeof(user) + + sizeof(Nhdr) + 8 + crashinfo.auxv_length + + sizeof(Nhdr) + 8 + nt_file_data_sz + nt_file_align + + crashinfo.threads.size() * ( + (sizeof(Nhdr) + 8 + sizeof(prstatus)) #if defined(__i386__) || defined(__x86_64__) - + sizeof(Nhdr) + 8 + sizeof(user_fpregs_struct) + + sizeof(Nhdr) + 8 + sizeof(user_fpregs_struct) #endif #if defined(__i386__) - + sizeof(Nhdr) + 8 + sizeof(user_fpxregs_struct) + + sizeof(Nhdr) + 8 + sizeof(user_fpxregs_struct) #endif - ); + ); Phdr phdr; memset(&phdr, 0, sizeof(Phdr)); @@ -1492,6 +1544,28 @@ main(int argc, const char* argv[]) { return 1; } + nhdr.n_descsz = nt_file_data_sz; + nhdr.n_type = NT_FILE; + if (!writea(options.out_fd, &nhdr, sizeof(nhdr)) || + !writea(options.out_fd, "CORE\0\0\0\0", 8) || + !writea(options.out_fd, + &nt_file.filename_count, sizeof(nt_file.filename_count)) || + !writea(options.out_fd, &nt_file.page_sz, sizeof(nt_file.page_sz))) { + return 1; + } + for (auto iter = nt_file.file_mappings.begin(); + iter != nt_file.file_mappings.end(); iter++) { + if (!writea(options.out_fd, &*iter, sizeof(*iter))) + return 1; + } + for (auto iter = nt_file.filenames.begin(); + iter != nt_file.filenames.end(); iter++) { + if (!writea(options.out_fd, iter->c_str(), iter->length() + 1)) + return 1; + } + if (!writea(options.out_fd, "\0\0\0\0", nt_file_align)) + return 1; + for (const auto& current_thread : crashinfo.threads) { if (current_thread.tid == crashinfo.exception.tid) { // Use the exception record's context for the crashed thread instead of diff --git a/src/tools/linux/md2core/minidump_memory_range_unittest.cc b/src/tools/linux/md2core/minidump_memory_range_unittest.cc index c939dd647..9c597df40 100644 --- a/src/tools/linux/md2core/minidump_memory_range_unittest.cc +++ b/src/tools/linux/md2core/minidump_memory_range_unittest.cc @@ -85,11 +85,11 @@ const struct { { 0, 4, 9, kBufferPointer + 36 }, { kBufferSize - 1, 1, 0, kBufferPointer + kBufferSize - 1 }, // Invalid array elemenets - { 0, 1, kBufferSize, NULL }, - { 0, 4, 10, NULL }, - { kBufferSize - 1, 1, 1, NULL }, - { kBufferSize - 1, 2, 0, NULL }, - { kBufferSize, 1, 0, NULL }, + { 0, 1, kBufferSize, nullptr }, + { 0, 4, 10, nullptr }, + { kBufferSize - 1, 1, 1, nullptr }, + { kBufferSize - 1, 2, 0, nullptr }, + { kBufferSize, 1, 0, nullptr }, }; const size_t kNumElements = sizeof(kElements) / sizeof(kElements[0]); @@ -97,7 +97,7 @@ const size_t kNumElements = sizeof(kElements) / sizeof(kElements[0]); TEST(MinidumpMemoryRangeTest, DefaultConstructor) { MinidumpMemoryRange range; - EXPECT_EQ(NULL, range.data()); + EXPECT_EQ(nullptr, range.data()); EXPECT_EQ(0U, range.length()); } @@ -110,7 +110,7 @@ TEST(MinidumpMemoryRangeTest, ConstructorWithDataAndLength) { TEST(MinidumpMemoryRangeTest, Reset) { MinidumpMemoryRange range; range.Reset(); - EXPECT_EQ(NULL, range.data()); + EXPECT_EQ(nullptr, range.data()); EXPECT_EQ(0U, range.length()); range.Set(kBuffer, kBufferSize); @@ -118,7 +118,7 @@ TEST(MinidumpMemoryRangeTest, Reset) { EXPECT_EQ(kBufferSize, range.length()); range.Reset(); - EXPECT_EQ(NULL, range.data()); + EXPECT_EQ(nullptr, range.data()); EXPECT_EQ(0U, range.length()); } @@ -128,15 +128,15 @@ TEST(MinidumpMemoryRangeTest, Set) { EXPECT_EQ(kBufferPointer, range.data()); EXPECT_EQ(kBufferSize, range.length()); - range.Set(NULL, 0); - EXPECT_EQ(NULL, range.data()); + range.Set(nullptr, 0); + EXPECT_EQ(nullptr, range.data()); EXPECT_EQ(0U, range.length()); } TEST(MinidumpMemoryRangeTest, SubrangeOfEmptyMemoryRange) { MinidumpMemoryRange range; MinidumpMemoryRange subrange = range.Subrange(0, 10); - EXPECT_EQ(NULL, subrange.data()); + EXPECT_EQ(nullptr, subrange.data()); EXPECT_EQ(0U, subrange.length()); } @@ -158,8 +158,8 @@ TEST(MinidumpMemoryRangeTest, SubrangeAndGetData) { EXPECT_EQ(sub_length, subrange.length()); } else { EXPECT_FALSE(range.Covers(sub_offset, sub_length)); - EXPECT_EQ(NULL, range.GetData(sub_offset, sub_length)); - EXPECT_EQ(NULL, subrange.data()); + EXPECT_EQ(nullptr, range.GetData(sub_offset, sub_length)); + EXPECT_EQ(nullptr, subrange.data()); EXPECT_EQ(0U, subrange.length()); } } @@ -186,8 +186,8 @@ TEST(MinidumpMemoryRangeTest, SubrangeWithMDLocationDescriptor) { EXPECT_EQ(sub_length, subrange.length()); } else { EXPECT_FALSE(range.Covers(sub_offset, sub_length)); - EXPECT_EQ(NULL, range.GetData(sub_offset, sub_length)); - EXPECT_EQ(NULL, subrange.data()); + EXPECT_EQ(nullptr, range.GetData(sub_offset, sub_length)); + EXPECT_EQ(nullptr, subrange.data()); EXPECT_EQ(0U, subrange.length()); } } diff --git a/src/tools/linux/symupload/minidump_upload.cc b/src/tools/linux/symupload/minidump_upload.cc index 9f2c96744..645da8c9e 100644 --- a/src/tools/linux/symupload/minidump_upload.cc +++ b/src/tools/linux/symupload/minidump_upload.cc @@ -78,7 +78,7 @@ static void Start(Options *options) { options->proxy_user_pwd, "", &response, - NULL, + nullptr, &error); if (success) { diff --git a/src/tools/mac/dump_syms/dump_syms_tool.cc b/src/tools/mac/dump_syms/dump_syms_tool.cc index 9fb8d13f2..3eb721630 100644 --- a/src/tools/mac/dump_syms/dump_syms_tool.cc +++ b/src/tools/mac/dump_syms/dump_syms_tool.cc @@ -47,36 +47,25 @@ #include "common/mac/dump_syms.h" #include "common/mac/arch_utilities.h" #include "common/mac/macho_utilities.h" -#include "common/scoped_ptr.h" using google_breakpad::DumpSymbols; using google_breakpad::Module; -using google_breakpad::scoped_ptr; using std::vector; struct Options { - Options() - : srcPath(), - dsymPath(), - arch(), - header_only(false), - cfi(true), - handle_inter_cu_refs(true), - handle_inlines(false), - enable_multiple(false), - module_name(), - prefer_extern_name(false) {} + Options() = default; string srcPath; string dsymPath; std::optional arch; - bool header_only; - bool cfi; - bool handle_inter_cu_refs; - bool handle_inlines; - bool enable_multiple; + bool header_only = false; + bool cfi = true; + bool handle_inter_cu_refs = true; + bool handle_inlines = false; + bool enable_multiple = false; string module_name; - bool prefer_extern_name; + bool prefer_extern_name = false; + bool report_warnings = false; }; static bool StackFrameEntryComparator(const Module::StackFrameEntry* a, @@ -169,6 +158,8 @@ static bool Start(const Options& options) { const string& primary_file = split_module ? options.dsymPath : options.srcPath; + dump_symbols.SetReportWarnings(options.report_warnings); + if (!dump_symbols.Read(primary_file)) return false; @@ -181,10 +172,10 @@ static bool Start(const Options& options) { return dump_symbols.WriteSymbolFileHeader(std::cout); // Read the primary file into a Breakpad Module. - Module* module = NULL; + Module* module = nullptr; if (!dump_symbols.ReadSymbolData(&module)) return false; - scoped_ptr scoped_module(module); + std::unique_ptr scoped_module(module); // If this is a split module, read the secondary Mach-O file, from which the // CFI data will be extracted. @@ -196,10 +187,10 @@ static bool Start(const Options& options) { !SetArchitecture(dump_symbols, *options.arch, options.srcPath)) { return false; } - Module* cfi_module = NULL; + Module* cfi_module = nullptr; if (!dump_symbols.ReadSymbolData(&cfi_module)) return false; - scoped_ptr scoped_cfi_module(cfi_module); + std::unique_ptr scoped_cfi_module(cfi_module); bool name_matches; if (!options.module_name.empty()) { @@ -250,6 +241,7 @@ static void Usage(int argc, const char *argv[]) { "[-n MODULE] [-x] \n", argv[0]); fprintf(stderr, "\t-i: Output module header information only.\n"); + fprintf(stderr, "\t-w: Output warning information.\n"); fprintf(stderr, "\t-a: Architecture type [default: native, or whatever is\n"); fprintf(stderr, "\t in the file, if it contains only one architecture]\n"); fprintf(stderr, "\t-g: Debug symbol file (dSYM) to dump in addition to the " @@ -275,11 +267,14 @@ static void SetupOptions(int argc, const char *argv[], Options *options) { extern int optind; signed char ch; - while ((ch = getopt(argc, (char* const*)argv, "ia:g:crdm?hn:x")) != -1) { + while ((ch = getopt(argc, (char* const*)argv, "iwa:g:crdm?hn:x")) != -1) { switch (ch) { case 'i': options->header_only = true; break; + case 'w': + options->report_warnings = true; + break; case 'a': { std::optional arch_info = GetArchInfoFromName(optarg); if (!arch_info) { diff --git a/src/tools/mac/upload_system_symbols/arch_constants.h b/src/tools/mac/upload_system_symbols/arch/arch_constants.h similarity index 100% rename from src/tools/mac/upload_system_symbols/arch_constants.h rename to src/tools/mac/upload_system_symbols/arch/arch_constants.h diff --git a/src/tools/mac/upload_system_symbols/arch_reader.go b/src/tools/mac/upload_system_symbols/arch/arch_reader.go similarity index 94% rename from src/tools/mac/upload_system_symbols/arch_reader.go rename to src/tools/mac/upload_system_symbols/arch/arch_reader.go index 03a764215..6553c8ba1 100644 --- a/src/tools/mac/upload_system_symbols/arch_reader.go +++ b/src/tools/mac/upload_system_symbols/arch/arch_reader.go @@ -27,7 +27,7 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package main +package arch import ( "debug/macho" @@ -38,10 +38,10 @@ import ( */ import "C" -// getArchStringFromHeader takes a MachO FileHeader and returns a string that +// GetArchStringFromHeader takes a MachO FileHeader and returns a string that // represents the CPU type and subtype. // This function is a Go version of src/common/mac/arch_utilities.cc:BreakpadGetArchInfoFromCpuType(). -func getArchStringFromHeader(header macho.FileHeader) string { +func GetArchStringFromHeader(header macho.FileHeader) string { // TODO(rsesek): As of 10.9.4, OS X doesn't list these in /usr/include/mach/machine.h. if header.Cpu == C.kCPU_TYPE_ARM64 && header.SubCpu == C.kCPU_SUBTYPE_ARM64_ALL { return "arm64" diff --git a/src/tools/mac/upload_system_symbols/archive/extract.go b/src/tools/mac/upload_system_symbols/archive/extract.go new file mode 100644 index 000000000..965e154e3 --- /dev/null +++ b/src/tools/mac/upload_system_symbols/archive/extract.go @@ -0,0 +1,517 @@ +package archive + +// #cgo LDFLAGS: -lParallelCompression +// #include +// #include +// #include +// +// typedef struct +// { +// int64_t unknown1; +// int64_t unknown2; +// char *input; +// char *output; +// char *patch; +// uint32_t not_cryptex_cache; +// uint32_t threads; +// uint32_t verbose; +// } RawImage; +// +// extern int32_t RawImagePatch(RawImage *) __attribute__((weak)); +import "C" + +import ( + "archive/zip" + "bytes" + "errors" + "fmt" + "io" + "log" + "os" + "os/exec" + "path" + "path/filepath" + "strconv" + "strings" + "unsafe" +) + +type ArchiveFormat int + +const ( + IPSW ArchiveFormat = iota + Installer +) + +// ExtractCaches extracts any dyld shared caches from `archive` to `destination`. +func ExtractCaches(format ArchiveFormat, archive string, destination string, verbose bool) error { + opts := ExtractorOptions{Verbose: true, Source: archive, Destination: destination} + var e *Extractor + switch format { + case IPSW: + e = NewIPSWExtractor(opts) + case Installer: + e = NewInstallAssistantExtractor(opts) + default: + return fmt.Errorf("unknown format %v", format) + } + return e.Extract() +} + +// NewIPSWExtractor returns an `Extractor` that can handle `.ipsw` files. +func NewIPSWExtractor(opts ExtractorOptions) *Extractor { + ie := &ipswExtractor{} + ie.Extractor = &Extractor{opts: opts, impl: ie} + return ie.Extractor +} + +// NewInstallAssistantExtractor returns an extractor that can handle Apple installers. +func NewInstallAssistantExtractor(opts ExtractorOptions) *Extractor { + ie := &installAssistantExtractor{} + ie.Extractor = &Extractor{opts: opts, impl: ie} + return ie.Extractor +} + +// ExtractorOptions are provided to an extractor to specify source file, destination, +// and whether verbose logging should be used. +type ExtractorOptions struct { + Verbose bool + Source string + Destination string +} + +// Extractor encapsulates the process of extracting dyld shared caches from an IPSW or installer. +type Extractor struct { + opts ExtractorOptions + impl extractorImpl + + scratchDir string + + // If non-empty, the path at which the DMG was mounted. This will + // be un-mounted at the end of Extract(). + dmgMountPaths []string +} + +// Extract extracts any dyld shared caches in `opts.Source` to `opts.Destination`. +func (e *Extractor) Extract() error { + scratchDir, err := os.MkdirTemp("", "extracted_system") + if err != nil { + return fmt.Errorf("couldn't create scratch directory to extract: %v", err) + } + defer os.RemoveAll(scratchDir) + e.scratchDir = scratchDir + + err = e.impl.doExtract() + + for _, path := range e.dmgMountPaths { + unmountErr := unmountDMG(path) + if unmountErr != nil { + err = errors.Join(err, unmountErr) + } + } + + return err +} + +// vlog logs if `opts.Verbose` is set and is a no-op otherwise. +func (e *Extractor) vlog(format string, args ...interface{}) { + if e.opts.Verbose { + fmt.Printf(format+"\n", args...) + } +} + +// mountDMG mounts the disk image at `dmgPath` to mountpoint and tracks it so that +// it can be unmounted by the end of `Extract` +func (e *Extractor) mountDMG(dmgPath string, mountpoint string) error { + cmd := exec.Command("hdiutil", "attach", dmgPath, "-mountpoint", mountpoint, "-quiet", "-nobrowse", "-readonly") + err := cmd.Run() + if err == nil { + e.dmgMountPaths = append(e.dmgMountPaths, mountpoint) + } + return err +} + +// extractorImpl is a private interface implemented by the backend +// extractors. +type extractorImpl interface { + doExtract() error +} + +// ipswExtractor extracts IPSWs +type ipswExtractor struct { + *Extractor +} + +// doExtract extracts dyld shared caches from an IPSW. +// It: +// Extracts the system disk image from the IPSW and mounts it. +// Copies any dyld shared caches from /System/Library/dyld on the mounted +// image to `opts.Destination`. +func (e *ipswExtractor) doExtract() error { + e.vlog("Extracting and mounting system disk:\n") + system, err := e.mountSystemDMG(e.opts.Source) + if err != nil { + return fmt.Errorf("couldn't mount system DMG: %v", err) + } + e.vlog("System mounted at %v\n", system) + e.vlog("Extracting shared caches:\n") + cachesPath := path.Join(system, "System/Library/dyld") + if !pathExists(cachesPath) { + return errors.New("couldn't find /System/Library/dyld") + } + + caches, err := filepath.Glob(path.Join(cachesPath, "dyld_shared_cache*")) + if err != nil { + // "The only possible returned error is ErrBadPattern" so treat + // this like a programmer error. + log.Fatalf("Failed to glob %v", path.Join(cachesPath, "dyld_shared_cache*")) + } + + for _, cache := range caches { + src, err := os.Open(cache) + if err != nil { + return err + } + defer src.Close() + filename := path.Base(cache) + dst, err := os.Create(path.Join(e.opts.Destination, filename)) + if err != nil { + return err + } + defer dst.Close() + e.vlog("Extracted %v\n", filename) + if _, err := io.Copy(dst, src); err != nil { + return err + } + } + + return nil +} + +// mountSystemDMG finds the name of the system image disk in the build manifest inside the +// IPSW at `ipswPath`, mounts it inside `e.scratchDir` and returns the mountpoint. +func (e *ipswExtractor) mountSystemDMG(ipswPath string) (string, error) { + r, err := zip.OpenReader(ipswPath) + if err != nil { + return "", fmt.Errorf("couldn't open ipsw at %s: %v", ipswPath, err) + } + defer r.Close() + dmgPath := "" + for _, f := range r.File { + if f.Name == "BuildManifest.plist" { + manifest, err := os.Create(path.Join(e.scratchDir, f.Name)) + if err != nil { + return "", err + } + if err := extractFileToPath(f, path.Join(e.scratchDir, f.Name)); err != nil { + return "", err + } + path, err := e.getSystemDMGPath(manifest.Name()) + if err != nil { + return "", err + } + dmgPath = path + } + } + if dmgPath == "" { + return "", errors.New("couldn't find build manifest") + } + for _, f := range r.File { + if filepath.Base(f.Name) == dmgPath { + dmgPath := path.Join(e.scratchDir, f.Name) + if err := extractFileToPath(f, dmgPath); err != nil { + return "", err + } + dmgMountpoint := path.Join(e.scratchDir, "Root") + e.vlog("Mounting %v at %v\n", dmgPath, dmgMountpoint) + if err := e.mountDMG(dmgPath, dmgMountpoint); err != nil { + return "", err + } + return dmgMountpoint, nil + } + } + return "", fmt.Errorf("%v not present in %v", dmgPath, ipswPath) +} + +// getSystemDMGPath finds the system disk image inside a IPSW from the build manifest +// at `manifest`. +func (e *ipswExtractor) getSystemDMGPath(manifest string) (string, error) { + print_cmd := "print :BuildIdentities:1:Manifest:Cryptex1,SystemOS:Info:Path" + result, err := exec.Command("/usr/libexec/PlistBuddy", "-c", print_cmd, manifest).Output() + if err != nil { + return "", err + } + return strings.TrimSpace(string(result)), nil +} + +// installAssistantExtractor extracts Apple installers. +type installAssistantExtractor struct { + *Extractor +} + +// doExtract extracts dyld shared caches from an Apple installer. +// It: +// 1. Expands the installer to disk +// 2. Finds and mounts SharedSupport.dmg +// 3. Determines based on system version whether this installer contains cryptexes or not. +// 4. If cryptexes are present, extracts them to disk images, mounts them, then copies any shared caches +// to `opts.Destination`. Otherwise, finds any payload zips containing shared caches, extracts them, and +// copies the caches to `opts.Destination` +func (e *installAssistantExtractor) doExtract() error { + expandedPath := path.Join(e.scratchDir, "installer") + e.vlog("Expanding installer to %v\n", expandedPath) + if err := e.expandInstaller(e.opts.Source, expandedPath); err != nil { + return fmt.Errorf("expand installer: %v", err) + } + + dmgPath := path.Join(expandedPath, "SharedSupport.dmg") + if !pathExists(dmgPath) { + return fmt.Errorf("couldn't find SharedSupport.dmg at %v", dmgPath) + } + dmgMountpoint := path.Join(e.scratchDir, "shared_support") + e.vlog("Mounting %v at %v\n", dmgPath, dmgMountpoint) + if err := e.mountDMG(dmgPath, dmgMountpoint); err != nil { + return fmt.Errorf("mount %v: %v", dmgPath, err) + } + + zipsPath := path.Join(dmgMountpoint, "com_apple_MobileAsset_MacSoftwareUpdate") + if !pathExists(zipsPath) { + return fmt.Errorf("couldn't find com_apple_MobileAsset_MacSoftwareUpdate on SharedSupport.dmg") + } + hasCryptexes, err := e.hasCryptexes(path.Join(zipsPath, "com_apple_MobileAsset_MacSoftwareUpdate.xml")) + if err != nil { + return fmt.Errorf("couldn't determine system version: %v", err) + } + zips, err := filepath.Glob(path.Join(zipsPath, "*.zip")) + if err != nil { + // "The only possible returned error is ErrBadPattern" so treat + // this like a programmer error. + log.Fatalf("Failed to glob %v", path.Join(zipsPath, "*.zip")) + } + return e.extractCachesFromZips(zips, e.opts.Destination, hasCryptexes) +} + +// expandInstaller expands the installer at `installerPath` to `destinaton`. +func (e *installAssistantExtractor) expandInstaller(installerPath string, destination string) error { + return exec.Command("pkgutil", "--expand-full", installerPath, destination).Run() +} + +// hasCryptexes returns true if the installer containing the plist at `plistPath` is for +// macOS version 13 or higher, and accordingly stores dyld shared caches inside cryptexes. +func (e *installAssistantExtractor) hasCryptexes(plistPath string) (bool, error) { + print_cmd := "print :Assets:0:OSVersion" + result, err := exec.Command("/usr/libexec/PlistBuddy", "-c", print_cmd, plistPath).Output() + if err != nil { + return false, fmt.Errorf("couldn't read OS version from %s: %v", plistPath, err) + } + majorVersion := strings.Split(string(result), ".")[0] + if v, err := strconv.Atoi(majorVersion); err != nil { + return false, fmt.Errorf("couldn't parse major version %s:%v", majorVersion, err) + } else { + return v >= 13, nil + } +} + +// extractCachesFromZips extracts zips that contain dyld shared caches, and extracts the dyld shared caches from them. +// The specifics depend on whether this installer uses cryptexes or payload files. +func (e *installAssistantExtractor) extractCachesFromZips(zips []string, destination string, hasCryptexes bool) error { + containerPath := path.Join(e.scratchDir, "container") + if !hasCryptexes { + if err := e.unarchiveZipsMatching(zips, containerPath, "AssetData/payloadv2/payload.0??"); err != nil { + return err + } + if err := e.extractCachesFromPayloads(containerPath, destination); err != nil { + return fmt.Errorf("couldn't extract caches from %v: %v", containerPath, err) + } + } else { + if err := e.unarchiveZipsMatching(zips, containerPath, "AssetData/payloadv2/image_patches/cryptex-system-*"); err != nil { + return err + } + if err := e.extractCachesFromCryptexes(containerPath, destination); err != nil { + return fmt.Errorf("couldn't extract caches from %v: %v", containerPath, err) + } + } + return nil +} + +// unarchiveZipsMatching unarchives all files matching `glob` from the zip files in `zips` to destination. +func (e *installAssistantExtractor) unarchiveZipsMatching(zips []string, destination string, glob string) error { + for _, zipFile := range zips { + archive, err := zip.OpenReader(zipFile) + if err != nil { + return fmt.Errorf("couldn't read %v: %v", zipFile, err) + } + defer archive.Close() + e.vlog("Unarchiving %v\n", zipFile) + if err := e.unarchiveFilesMatching(archive, destination, glob); err != nil { + return fmt.Errorf("couldn't unarchive files matching %v from %v", glob, zipFile) + } + } + return nil +} + +// unarchiveFilesMatching unarchives all files matching `glob` from `r` to destination. +func (e *installAssistantExtractor) unarchiveFilesMatching(r *zip.ReadCloser, destination string, glob string) error { + if err := os.MkdirAll(destination, 0755); err != nil { + return err + } + for _, file := range r.File { + if file.FileInfo().IsDir() { + continue + } + if ok, err := path.Match(glob, file.Name); !ok || err != nil { + continue + } + _, filename := path.Split(file.Name) + writePath := path.Join(destination, filename) + if err := extractFileToPath(file, writePath); err != nil { + return err + } + } + return nil +} + +// extractCachesFromPayloads unarchives any files containing dyld shared caches from `payloadsPath` +// then copies any shared caches to `destination`. +func (e *installAssistantExtractor) extractCachesFromPayloads(payloadsPath string, destination string) error { + scratchDir, err := os.MkdirTemp(e.scratchDir, "payload") + if err != nil { + return err + } + files, err := os.ReadDir(payloadsPath) + if err != nil { + return err + } + for _, f := range files { + payload := path.Join(payloadsPath, f.Name()) + if e.payloadHasSharedCache(payload) { + e.vlog("Extracting %v\n", payload) + if err := e.extractPayload(payload, scratchDir); err != nil { + return err + } + } + } + return e.copySharedCaches(scratchDir, destination) +} + +// payloadHasSharedCache returns true if the archive at `payloadPath` contains a dyld shared cache. +func (e *installAssistantExtractor) payloadHasSharedCache(payloadPath string) bool { + out, err := exec.Command("yaa", "list", "-i", payloadPath).Output() + return err == nil && bytes.Contains(out, []byte("/dyld_shared_cache")) +} + +// extractPayload extracts the apple archive at `payloadPath` to `destination`. +func (e *installAssistantExtractor) extractPayload(payloadPath string, destination string) error { + return exec.Command("yaa", "extract", "-i", payloadPath, "-d", destination).Run() +} + +// copySharedCaches copies the contents of `System/Library/dyld` in `from` to `to`. +func (e *installAssistantExtractor) copySharedCaches(from, to string) error { + dyldPath := path.Join(from, "System/Library/dyld") + if !pathExists(dyldPath) { + return fmt.Errorf("couldn't find System/Library/dyld in %s", dyldPath) + } + cacheFiles, err := os.ReadDir(dyldPath) + if err != nil { + return err + } + for _, cacheFile := range cacheFiles { + name := cacheFile.Name() + src := path.Join(dyldPath, name) + dst := path.Join(to, name) + e.vlog("Copying %v to %v\n", src, dst) + if err := copyFile(src, dst); err != nil { + return fmt.Errorf("couldn't copy %s to %s: %v", src, dst, err) + } + } + return nil +} + +// extractCachesFromCryptexes extracts disk images from any cryptexes at `cryptexesPath`, mounts them, +// and extracts any dyld shared caches to `destination`. +func (e *installAssistantExtractor) extractCachesFromCryptexes(cryptexesPath string, destination string) error { + scratchDir, err := os.MkdirTemp(e.scratchDir, "cryptex_dmg") + if err != nil { + return err + } + files, err := os.ReadDir(cryptexesPath) + if err != nil { + return err + } + for _, f := range files { + cryptexMountpoint := path.Join(scratchDir, "cryptex_"+f.Name()) + cryptex := path.Join(cryptexesPath, f.Name()) + dmgPath := path.Join(scratchDir, f.Name()+".dmg") + e.extractCryptexDMG(cryptex, dmgPath) + e.vlog("Mounting %s at %s\n", cryptex, dmgPath) + e.mountDMG(dmgPath, cryptexMountpoint) + if err := e.copySharedCaches(cryptexMountpoint, destination); err != nil { + return err + } + } + return nil +} + +// extractCryptexDMG extracts the cryptex at `cryptexPath` to `dmgPath` using libParallelCompression. +func (e *installAssistantExtractor) extractCryptexDMG(cryptexPath, dmgPath string) error { + inp := C.CString("") + defer C.free(unsafe.Pointer(inp)) + cryptex := C.CString(cryptexPath) + defer C.free(unsafe.Pointer(cryptex)) + result := C.CString(dmgPath) + defer C.free(unsafe.Pointer(result)) + + ri := C.RawImage{unknown1: 0, unknown2: 0, input: inp, output: result, patch: cryptex, not_cryptex_cache: 0, threads: 0, verbose: 1} + if exitCode := C.RawImagePatch(&ri); exitCode != 0 { + return fmt.Errorf("RawImagePatch failed with %d", exitCode) + } + return nil +} + +// pathExists returns true if `path` exists. +func pathExists(path string) bool { + _, err := os.Stat(path) + return !os.IsNotExist(err) +} + +// extractFileToPath extracts the contents of `f` to `path`. +func extractFileToPath(f *zip.File, path string) error { + w, err := os.Create(path) + if err != nil { + return err + } + defer w.Close() + reader, err := f.Open() + if err != nil { + return err + } + + if _, err := io.Copy(w, reader); err != nil { + return err + } + return nil +} + +// copyFile copies `src` to `dst`, which can be on different volumes. +func copyFile(src, dst string) error { + w, err := os.Create(dst) + if err != nil { + return err + } + defer w.Close() + + reader, err := os.Open(src) + if err != nil { + return err + } + defer reader.Close() + if _, err := io.Copy(w, reader); err != nil { + return err + } + return nil +} + +// unmountDMG unmounts the disk image at `mountpoint`. +func unmountDMG(mountpoint string) error { + return exec.Command("hdiutil", "detach", mountpoint).Run() +} diff --git a/src/tools/mac/upload_system_symbols/upload_system_symbols.go b/src/tools/mac/upload_system_symbols/upload_system_symbols.go index f34c288ae..921e83bf0 100644 --- a/src/tools/mac/upload_system_symbols/upload_system_symbols.go +++ b/src/tools/mac/upload_system_symbols/upload_system_symbols.go @@ -43,27 +43,34 @@ package main import ( "debug/macho" + "errors" "flag" "fmt" "io" - "io/ioutil" "log" "os" "os/exec" "path" + "path/filepath" "regexp" "strings" "sync" "time" + + "upload_system_symbols/arch" + "upload_system_symbols/archive" ) var ( breakpadTools = flag.String("breakpad-tools", "out/Release/", "Path to the Breakpad tools directory, containing dump_syms and symupload.") uploadOnlyPath = flag.String("upload-from", "", "Upload a directory of symbol files that has been dumped independently.") dumpOnlyPath = flag.String("dump-to", "", "Dump the symbols to the specified directory, but do not upload them.") - systemRoot = flag.String("system-root", "", "Path to the root of the Mac OS X system whose symbols will be dumped.") + systemRoot = flag.String("system-root", "", "Path to the root of the macOS system whose symbols will be dumped. Mutually exclusive with --installer and --ipsw.") dumpArchitecture = flag.String("arch", "", "The CPU architecture for which symbols should be dumped. If not specified, dumps all architectures.") apiKey = flag.String("api-key", "", "API key to use. If this is present, the `sym-upload-v2` protocol is used.\nSee https://chromium.googlesource.com/breakpad/breakpad/+/HEAD/docs/sym_upload_v2_protocol.md or\n`symupload`'s help for more information.") + installer = flag.String("installer", "", "Path to macOS installer. Mutually exclusive with --system-root and --ipsw.") + ipsw = flag.String("ipsw", "", "Path to macOS IPSW. Mutually exclusive with --system-root and --installer.") + separateArch = flag.Bool("separate-arch", false, "Whether to separate symbols into architecture-specific directories when dumping.") ) var ( @@ -108,6 +115,7 @@ var ( regexp.MustCompile(`\.a$`), regexp.MustCompile(`\.dat$`), } + maxFileCreateTries = 10 ) func main() { @@ -129,26 +137,13 @@ func main() { return } - if *systemRoot == "" { - log.Fatal("Need a -system-root to dump symbols for") - } - - if *dumpOnlyPath != "" { - // -dump-to specified, so make sure that the path is a directory. - if fi, err := os.Stat(*dumpOnlyPath); err != nil { - log.Fatalf("-dump-to location: %v", err) - } else if !fi.IsDir() { - log.Fatal("-dump-to location is not a directory") - } - } - dumpPath := *dumpOnlyPath if *dumpOnlyPath == "" { // If -dump-to was not specified, then run the upload pipeline and create // a temporary dump output directory. uq = StartUploadQueue() - if p, err := ioutil.TempDir("", "upload_system_symbols"); err != nil { + if p, err := os.MkdirTemp("", "upload_system_symbols"); err != nil { log.Fatalf("Failed to create temporary directory: %v", err) } else { dumpPath = p @@ -156,13 +151,61 @@ func main() { } } - dq := StartDumpQueue(*systemRoot, dumpPath, uq) + tempDir, err := os.MkdirTemp("", "systemRoots") + if err != nil { + log.Fatalf("Failed to create temporary directory: %v", err) + } + defer os.RemoveAll(tempDir) + roots := getSystemRoots(tempDir) + + if *dumpOnlyPath != "" { + // -dump-to specified, so make sure that the path is a directory. + if fi, err := os.Stat(*dumpOnlyPath); err != nil { + log.Fatalf("-dump-to location: %v", err) + } else if !fi.IsDir() { + log.Fatal("-dump-to location is not a directory") + } + } + + dq := StartDumpQueue(roots, dumpPath, *separateArch, uq) dq.Wait() if uq != nil { uq.Wait() } } +// getSystemRoots returns which system roots should be dumped from the parsed +// flags, extracting them if necessary. +func getSystemRoots(tempDir string) []string { + hasInstaller := len(*installer) > 0 + hasIPSW := len(*ipsw) > 0 + hasRoot := len(*systemRoot) > 0 + + if hasInstaller { + if hasIPSW || hasRoot { + log.Fatalf("--installer, --ipsw, and --system-root are mutually exclusive") + } + if rs, err := extractSystems(archive.Installer, *installer, tempDir); err != nil { + log.Fatalf("Couldn't extract installer at %s: %v", *installer, err) + } else { + return rs + } + } else if hasIPSW { + if hasRoot { + log.Fatalf("--installer, --ipsw, and --system-root are mutually exclusive") + } + if rs, err := extractSystems(archive.IPSW, *ipsw, tempDir); err != nil { + log.Fatalf("Couldn't extract IPSW at %s: %v", *ipsw, err) + } else { + return rs + } + } else if hasRoot { + return []string{*systemRoot} + } + log.Fatal("Need a --system-root, --installer, or --ipsw to dump symbols for") + return []string{} +} + // manglePath reduces an absolute filesystem path to a string suitable as the // base for a file name which encodes some of the original path. The result // concatenates the leading initial from each path component except the last to @@ -186,6 +229,34 @@ func manglePath(path string) string { return builder.String() } +// createSymbolFile creates a writable file in `base` with a name derived from +// `original_path`. It ensures that multiple threads can't simultaneously create +// the same file for two `original_paths` that map to the same mangled name. +// Returns the filename, the file, and an error if creating the file failed. +func createSymbolFile(base string, original_path string, arch string) (filename string, f *os.File, err error) { + mangled := manglePath(original_path) + counter := 0 + filebase := path.Join(base, mangled) + for { + var symfile string + if counter == 0 { + symfile = fmt.Sprintf("%s_%s.sym", filebase, arch) + } else { + symfile = fmt.Sprintf("%s_%s_%d.sym", filebase, arch, counter) + } + f, err := os.OpenFile(symfile, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644) + if err == nil { + return symfile, f, nil + } + if os.IsExist(err) && counter < maxFileCreateTries { + counter++ + continue + } + return "", nil, err + } + +} + type WorkerPool struct { wg sync.WaitGroup } @@ -269,9 +340,10 @@ func (uq *UploadQueue) worker() { type DumpQueue struct { *WorkerPool - dumpPath string - queue chan dumpRequest - uq *UploadQueue + dumpPath string + queue chan dumpRequest + separateArch bool + uq *UploadQueue } type dumpRequest struct { @@ -282,15 +354,16 @@ type dumpRequest struct { // StartDumpQueue creates a new worker pool to find all the Mach-O libraries in // root and dump their symbols to dumpPath. If an UploadQueue is passed, the // path to the symbol file will be enqueued there, too. -func StartDumpQueue(root, dumpPath string, uq *UploadQueue) *DumpQueue { +func StartDumpQueue(roots []string, dumpPath string, separateArch bool, uq *UploadQueue) *DumpQueue { dq := &DumpQueue{ - dumpPath: dumpPath, - queue: make(chan dumpRequest), - uq: uq, + dumpPath: dumpPath, + queue: make(chan dumpRequest), + separateArch: separateArch, + uq: uq, } dq.WorkerPool = StartWorkerPool(12, dq.worker) - findLibsInRoot(root, dq) + findLibsInRoots(roots, dq) return dq } @@ -319,9 +392,14 @@ func (dq *DumpQueue) worker() { dumpSyms := path.Join(*breakpadTools, "dump_syms") for req := range dq.queue { - filebase := path.Join(dq.dumpPath, manglePath(req.path)) - symfile := fmt.Sprintf("%s_%s.sym", filebase, req.arch) - f, err := os.Create(symfile) + dumpPath := dq.dumpPath + if dq.separateArch { + dumpPath = path.Join(dumpPath, req.arch) + if err := ensureDirectory(dumpPath); err != nil { + log.Fatalf("Error creating directory %s: %v", dumpPath, err) + } + } + symfile, f, err := createSymbolFile(dumpPath, req.path, req.arch) if err != nil { log.Fatalf("Error creating symbol file: %v", err) } @@ -369,21 +447,22 @@ type findQueue struct { dq *DumpQueue } -// findLibsInRoot looks in all the pathsToScan in the root and manages the +// findLibsInRoot looks in all the pathsToScan in all roots and manages the // interaction between findQueue and DumpQueue. -func findLibsInRoot(root string, dq *DumpQueue) { +func findLibsInRoots(roots []string, dq *DumpQueue) { fq := &findQueue{ queue: make(chan string, 10), dq: dq, } fq.WorkerPool = StartWorkerPool(12, fq.worker) + for _, root := range roots { + for _, p := range pathsToScan { + fq.findLibsInPath(path.Join(root, p), true) + } - for _, p := range pathsToScan { - fq.findLibsInPath(path.Join(root, p), true) - } - - for _, p := range optionalPathsToScan { - fq.findLibsInPath(path.Join(root, p), false) + for _, p := range optionalPathsToScan { + fq.findLibsInPath(path.Join(root, p), false) + } } close(fq.queue) @@ -468,11 +547,13 @@ func (fq *findQueue) worker() { } func (fq *findQueue) dumpMachOFile(fp string, image *macho.File) { - if image.Type != MachODylib && image.Type != MachOBundle && image.Type != MachODylinker { + if image.Type != arch.MachODylib && + image.Type != arch.MachOBundle && + image.Type != arch.MachODylinker { return } - arch := getArchStringFromHeader(image.FileHeader) + arch := arch.GetArchStringFromHeader(image.FileHeader) if arch == "" { // Don't know about this architecture type. return @@ -482,3 +563,54 @@ func (fq *findQueue) dumpMachOFile(fp string, image *macho.File) { fq.dq.DumpSymbols(fp, arch) } } + +// extractSystems extracts any dyld shared caches from `archivePath`, then extracts the caches +// into macOS system libraries, returning the locations on disk of any systems extracted. +func extractSystems(format archive.ArchiveFormat, archivePath string, extractPath string) ([]string, error) { + cachesPath := path.Join(extractPath, "caches") + if err := os.MkdirAll(cachesPath, 0755); err != nil { + return nil, err + } + if err := archive.ExtractCaches(format, archivePath, cachesPath, true); err != nil { + return nil, err + } + files, err := os.ReadDir(cachesPath) + if err != nil { + return nil, err + } + cachePrefix := "dyld_shared_cache_" + extractedDirPath := path.Join(extractPath, "extracted") + roots := make([]string, 0) + for _, file := range files { + fileName := file.Name() + if filepath.Ext(fileName) == "" && strings.HasPrefix(fileName, cachePrefix) { + arch := strings.TrimPrefix(fileName, cachePrefix) + extractedSystemPath := path.Join(extractedDirPath, arch) + // XXX: Maybe this shouldn't be fatal? + if err := extractDyldSharedCache(path.Join(cachesPath, fileName), extractedSystemPath); err != nil { + return nil, err + } + roots = append(roots, extractedSystemPath) + } + } + return roots, nil +} + +// extractDyldSharedCache extracts the dyld shared cache at `cachePath` to `destination`. +func extractDyldSharedCache(cachePath string, destination string) error { + dscExtractor := path.Join(*breakpadTools, "dsc_extractor") + cmd := exec.Command(dscExtractor, cachePath, destination) + if output, err := cmd.Output(); err != nil { + return fmt.Errorf("extracting shared cache at %s: %v. dsc_extractor said %v", cachePath, err, output) + } + return nil +} + +// ensureDirectory creates a directory at `path` if one does not already exist. +func ensureDirectory(path string) error { + if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) { + return os.MkdirAll(path, 0755) + } else { + return err + } +} diff --git a/src/tools/solaris/dump_syms/dump_syms.cc b/src/tools/solaris/dump_syms/dump_syms.cc index ead160011..8f5924ae2 100644 --- a/src/tools/solaris/dump_syms/dump_syms.cc +++ b/src/tools/solaris/dump_syms/dump_syms.cc @@ -32,11 +32,12 @@ #include // Must come first #endif -#include -#include - #include "common/solaris/dump_symbols.h" +#include + +#include + using namespace google_breakpad; int main(int argc, char** argv) { diff --git a/src/tools/windows/converter/ms_symbol_server_converter.cc b/src/tools/windows/converter/ms_symbol_server_converter.cc index f7d9d9431..42878f52d 100644 --- a/src/tools/windows/converter/ms_symbol_server_converter.cc +++ b/src/tools/windows/converter/ms_symbol_server_converter.cc @@ -37,14 +37,15 @@ #include // Must come first #endif +#include "tools/windows/converter/ms_symbol_server_converter.h" + #include + +#include #include #include +#include -#include -#include - -#include "tools/windows/converter/ms_symbol_server_converter.h" #include "common/windows/pdb_source_line_writer.h" #include "common/windows/pe_source_line_writer.h" #include "common/windows/string_utils-inl.h" @@ -332,7 +333,7 @@ MSSymbolServerConverter::LocateFile(const string& debug_or_code_file, // Do the lookup. char path[MAX_PATH]; if (!SymFindFileInPath( - process, NULL, + process, nullptr, const_cast(debug_or_code_file.c_str()), const_cast(identifier.guid_or_signature_pointer()), identifier.age(), 0, @@ -598,7 +599,7 @@ MSSymbolServerConverter::LocateAndConvertSymbolFile( *converted_symbol_file = pdb_file.substr(0, pdb_file.length() - 4) + ".sym"; - FILE* converted_output = NULL; + FILE* converted_output = nullptr; #if _MSC_VER >= 1400 // MSVC 2005/8 errno_t err; if ((err = fopen_s(&converted_output, converted_symbol_file->c_str(), "w")) @@ -694,7 +695,7 @@ MSSymbolServerConverter::LocateAndConvertPEFile( *converted_symbol_file = pe_file.substr(0, pe_file.length() - 4) + ".sym"; - FILE* converted_output = NULL; + FILE* converted_output = nullptr; #if _MSC_VER >= 1400 // MSVC 2005/8 errno_t err; if ((err = fopen_s(&converted_output, converted_symbol_file->c_str(), "w")) diff --git a/src/tools/windows/converter_exe/converter.cc b/src/tools/windows/converter_exe/converter.cc index 92c41774a..9e1df7f8b 100644 --- a/src/tools/windows/converter_exe/converter.cc +++ b/src/tools/windows/converter_exe/converter.cc @@ -35,9 +35,10 @@ #include // Must come first #endif -#include -#include -#include +#include +#include +#include + #include #include #include @@ -275,7 +276,7 @@ static bool SendFetchFailedPing(const wstring& fetch_symbol_failure_url, if (!HTTPDownload::Download(fetch_symbol_failure_url, & parameters, & content, - NULL)) { + nullptr)) { FprintfFlush(stderr, "SendFetchFailedPing: HTTPDownload::Download failed " "for %s %s %s\n", missing_info.debug_file.c_str(), @@ -642,14 +643,14 @@ static void ConvertMissingSymbolFile(const MissingSymbolInfo& missing_info, // Reads the contents of file |file_name| and populates |contents|. // Returns true on success. -static bool ReadFile(string file_name, string* contents) { +static bool ReadFile(const string& file_name, string* contents) { char buffer[1024 * 8]; FILE* fp = fopen(file_name.c_str(), "rt"); if (!fp) { return false; } contents->clear(); - while (fgets(buffer, sizeof(buffer), fp) != NULL) { + while (fgets(buffer, sizeof(buffer), fp) != nullptr) { contents->append(buffer); } fclose(fp); @@ -671,7 +672,7 @@ static bool ConvertMissingSymbolsList(const ConverterOptions& options) { return false; } } else if (!HTTPDownload::Download(options.missing_symbols_url,& parameters, - & missing_symbol_list, NULL)) { + & missing_symbol_list, nullptr)) { return false; } diff --git a/src/tools/windows/converter_exe/escaping.cc b/src/tools/windows/converter_exe/escaping.cc index e399c0f48..bb7b50363 100644 --- a/src/tools/windows/converter_exe/escaping.cc +++ b/src/tools/windows/converter_exe/escaping.cc @@ -34,6 +34,10 @@ #include +#include + +#include "common/scoped_ptr.h" + #define kApb kAsciiPropertyBits const unsigned char kAsciiPropertyBits[256] = { @@ -60,10 +64,10 @@ static inline bool ascii_isspace(unsigned char c) { return !!(kApb[c] & 0x08); } /////////////////////////////////// // scoped_array /////////////////////////////////// -// scoped_array is like scoped_ptr, except that the caller must allocate +// scoped_array is like std::unique_ptr, except that the caller must allocate // with new [] and the destructor deletes objects with delete []. // -// As with scoped_ptr, a scoped_array either points to an object +// As with std::unique_ptr, a scoped_array either points to an object // or is NULL. A scoped_array owns the object that it points to. // scoped_array is thread-compatible, and once you index into it, // the returned objects have only the threadsafety guarantees of T. @@ -79,7 +83,7 @@ class scoped_array { // Constructor. Defaults to intializing with NULL. // There is no way to create an uninitialized scoped_array. // The input parameter must be allocated with new []. - explicit scoped_array(C* p = NULL) : array_(p) { } + explicit scoped_array(C* p = nullptr) : array_(p) { } // Destructor. If there is a C object, delete it. // We don't need to test ptr_ == NULL because C++ does that for us. @@ -91,7 +95,7 @@ class scoped_array { // Reset. Deletes the current owned object, if any. // Then takes ownership of a new object, if given. // this->reset(this->get()) works. - void reset(C* p = NULL) { + void reset(C* p = nullptr) { if (p != array_) { enum { type_must_be_complete = sizeof(C) }; delete[] array_; @@ -103,7 +107,7 @@ class scoped_array { // Will assert() if there is no current object, or index i is negative. C& operator[](std::ptrdiff_t i) const { assert(i >= 0); - assert(array_ != NULL); + assert(array_ != nullptr); return array_[i]; } @@ -133,7 +137,7 @@ class scoped_array { // and will not own the object any more. C* release() { C* retVal = array_; - array_ = NULL; + array_ = nullptr; return retVal; } @@ -170,7 +174,7 @@ namespace strings { // already work on all current implementations. inline char* string_as_array(string* str) { // DO NOT USE const_cast(str->data())! See the unittest for why. - return str->empty() ? NULL : &*str->begin(); + return str->empty() ? nullptr : &*str->begin(); } int CalculateBase64EscapedLen(int input_len, bool do_padding) { @@ -489,7 +493,7 @@ int Base64Unescape(const char *src, int szsrc, char *dest, int szdest) { // for (i = 0; i < 255; i += 8) { // for (j = i; j < i + 8; j++) { // pos = strchr(Base64, j); - // if ((pos == NULL) || (j == 0)) + // if ((pos == nullptr) || (j == 0)) // idx = -1; // else // idx = pos - Base64; @@ -684,7 +688,7 @@ int WebSafeBase64Unescape(const char *src, int szsrc, char *dest, int szdest) { // for (i = 0; i < 255; i += 8) { // for (j = i; j < i + 8; j++) { // pos = strchr(Base64, j); - // if ((pos == NULL) || (j == 0)) + // if ((pos == nullptr) || (j == 0)) // idx = -1; // else // idx = pos - Base64; diff --git a/src/tools/windows/converter_exe/http_download.cc b/src/tools/windows/converter_exe/http_download.cc index de8241980..054ffbe6f 100644 --- a/src/tools/windows/converter_exe/http_download.cc +++ b/src/tools/windows/converter_exe/http_download.cc @@ -50,7 +50,7 @@ using std::vector; // goes out of scope. class AutoHttpHandle { public: - AutoHttpHandle() : handle_(NULL) {} + AutoHttpHandle() : handle_(nullptr) {} explicit AutoHttpHandle(HttpHandle handle) : handle_(handle) {} ~AutoHttpHandle() { if (handle_) { @@ -118,7 +118,7 @@ static bool CheckParameters(const map* parameters) { HttpClient* HTTPDownload::CreateHttpClient(const wchar_t* url) { const TCHAR* kHttpApiPolicyEnvironmentVariable = TEXT("USE_WINHTTP"); TCHAR buffer[2] = {0}; - HttpClient* http_client = NULL; + HttpClient* http_client = nullptr; if (::GetEnvironmentVariable(kHttpApiPolicyEnvironmentVariable, buffer, @@ -127,7 +127,7 @@ HttpClient* HTTPDownload::CreateHttpClient(const wchar_t* url) { "Environment variable [%ws] is set, use WinHttp\n", kHttpApiPolicyEnvironmentVariable); http_client = CreateWinHttpClient(url); - if (http_client == NULL) { + if (http_client == nullptr) { fprintf(stderr, "WinHttpClient not created, Is the protocol HTTPS? " "Fall back to WinInet API.\n"); } @@ -137,7 +137,7 @@ HttpClient* HTTPDownload::CreateHttpClient(const wchar_t* url) { kHttpApiPolicyEnvironmentVariable); } - if (http_client == NULL) { + if (http_client == nullptr) { return CreateWinInetClient(url); } @@ -190,10 +190,10 @@ bool HTTPDownload::Download(const wstring& url, } AutoHttpHandle internet; - if (!http_client->Open(NULL, // user agent + if (!http_client->Open(nullptr, // user agent HttpClient::ACCESS_TYPE_PRECONFIG, - NULL, // proxy name - NULL, // proxy bypass + nullptr, // proxy name + nullptr, // proxy bypass internet.get_handle_addr())) { fprintf(stderr, "HTTPDownload::Download: Open: error %lu for %ws\n", @@ -238,8 +238,8 @@ bool HTTPDownload::Download(const wstring& url, if (!http_client->OpenRequest(connection.get(), L"GET", request_string.c_str(), - NULL, // version - NULL, // referer + nullptr, // version + nullptr, // referer secure, request.get_handle_addr())) { fprintf(stderr, @@ -248,7 +248,7 @@ bool HTTPDownload::Download(const wstring& url, return false; } - if (!http_client->SendRequest(request.get(), NULL, 0)) { + if (!http_client->SendRequest(request.get(), nullptr, 0)) { fprintf(stderr, "HttpClient::SendRequest: error %lu for %ws\n", GetLastError(), url.c_str()); diff --git a/src/tools/windows/converter_exe/winhttp_client.cc b/src/tools/windows/converter_exe/winhttp_client.cc index 425a9daad..371b32c16 100644 --- a/src/tools/windows/converter_exe/winhttp_client.cc +++ b/src/tools/windows/converter_exe/winhttp_client.cc @@ -147,7 +147,7 @@ bool WinHttpClient::Connect(HttpHandle session_handle, ToHINTERNET(session_handle), server, static_cast(port), - NULL)); + 0)); return !!(*connection_handle); } @@ -182,16 +182,16 @@ bool WinHttpClient::SendRequest(HttpHandle request_handle, return !!::WinHttpSendRequest(ToHINTERNET(request_handle), headers, headers_length, - NULL, + nullptr, 0, WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH, - NULL); + 0); } bool WinHttpClient::ReceiveResponse(HttpHandle request_handle) const { assert(request_handle); - return !!::WinHttpReceiveResponse(ToHINTERNET(request_handle), NULL); + return !!::WinHttpReceiveResponse(ToHINTERNET(request_handle), nullptr); } bool WinHttpClient::GetHttpStatusCode(HttpHandle request_handle, @@ -206,7 +206,7 @@ bool WinHttpClient::GetHttpStatusCode(HttpHandle request_handle, return false; } - *status_code = static_cast(_tcstol(http_status_string, NULL, 10)); + *status_code = static_cast(_tcstol(http_status_string, nullptr, 10)); return true; } @@ -225,7 +225,7 @@ bool WinHttpClient::GetContentLength(HttpHandle request_handle, *content_length = kUnknownContentLength; } else { *content_length = - static_cast(wcstol(content_length_string, NULL, 10)); + static_cast(wcstol(content_length_string, nullptr, 10)); } return true; } @@ -295,14 +295,14 @@ HttpClient* CreateWinHttpClient(const TCHAR* url) { path, sizeof(path)/sizeof(path[0]), &port)) { - return NULL; + return nullptr; } if (_wcsicmp(scheme, L"https") == 0) { // Winhttp under WINE doesn't support wildcard certificates, so avoid // to use it if the scheme is https. The caller should fall back to // use wininet if NULL is returned. - return NULL; + return nullptr; } return new internal::WinHttpClient(); diff --git a/src/tools/windows/converter_exe/wininet_client.cc b/src/tools/windows/converter_exe/wininet_client.cc index 571ab86c6..43fb43c5b 100644 --- a/src/tools/windows/converter_exe/wininet_client.cc +++ b/src/tools/windows/converter_exe/wininet_client.cc @@ -145,8 +145,8 @@ bool WinInetClient::Connect(HttpHandle session_handle, ToHINTERNET(session_handle), server, static_cast(port), - NULL, - NULL, + nullptr, + nullptr, INTERNET_SERVICE_HTTP, 0, 0)); @@ -170,9 +170,9 @@ bool WinInetClient::OpenRequest(HttpHandle connection_handle, uri, version, referrer, - NULL, + nullptr, is_secure ? INTERNET_FLAG_SECURE : 0, - NULL)); + 0)); return !!(*request_handle); } @@ -184,7 +184,7 @@ bool WinInetClient::SendRequest(HttpHandle request_handle, return !!::HttpSendRequest(ToHINTERNET(request_handle), headers, headers_length, - NULL, + nullptr, 0); } @@ -206,7 +206,7 @@ bool WinInetClient::GetHttpStatusCode(HttpHandle request_handle, return false; } - *status_code = _tcstol(http_status_string, NULL, 10); + *status_code = _tcstol(http_status_string, nullptr, 10); return true; } @@ -224,7 +224,7 @@ bool WinInetClient::GetContentLength(HttpHandle request_handle, 0)) { *content_length = kUnknownContentLength; } else { - *content_length = wcstol(content_length_string, NULL, 10); + *content_length = wcstol(content_length_string, nullptr, 10); } return true; } diff --git a/src/tools/windows/converter_exe/winsymconv.cmd b/src/tools/windows/converter_exe/winsymconv.cmd index bea84b589..ca1847847 100644 --- a/src/tools/windows/converter_exe/winsymconv.cmd +++ b/src/tools/windows/converter_exe/winsymconv.cmd @@ -39,6 +39,7 @@ google_converter.exe ^ -n https://download.amd.com/dir/bin ^ -n https://driver-symbols.nvidia.com ^ -n https://software.intel.com/sites/downloads/symbols ^ + -n https://www.nvaccess.org/files/nvda/symbols ^ -l %SYMBOL_DIR% ^ -s https://clients2.google.com/cr/staging_symbol ^ -m https://clients2.google.com/cr/staging_symbol/missingsymbols ^ @@ -58,6 +59,7 @@ google_converter.exe ^ -n https://download.amd.com/dir/bin ^ -n https://driver-symbols.nvidia.com ^ -n https://software.intel.com/sites/downloads/symbols ^ + -n https://www.nvaccess.org/files/nvda/symbols ^ -l %SYMBOL_DIR% ^ -s https://clients2.google.com/cr/symbol ^ -m https://clients2.google.com/cr/symbol/missingsymbols ^ diff --git a/src/tools/windows/converter_exe/winsymconv_test.cmd b/src/tools/windows/converter_exe/winsymconv_test.cmd index c17770660..448244d84 100644 --- a/src/tools/windows/converter_exe/winsymconv_test.cmd +++ b/src/tools/windows/converter_exe/winsymconv_test.cmd @@ -37,6 +37,7 @@ google_converter.exe ^ -n https://download.amd.com/dir/bin ^ -n https://driver-symbols.nvidia.com ^ -n https://software.intel.com/sites/downloads/symbols ^ + -n https://www.nvaccess.org/files/nvda/symbols ^ -l %SYMBOL_DIR% ^ -s https://clients2.google.com/cr/staging_symbol ^ -mf %SCRIPT_LOCATION%missing_symbols_test.txt ^ @@ -56,6 +57,7 @@ google_converter.exe ^ -n https://download.amd.com/dir/bin ^ -n https://driver-symbols.nvidia.com ^ -n https://software.intel.com/sites/downloads/symbols ^ + -n https://www.nvaccess.org/files/nvda/symbols ^ -l %SYMBOL_DIR% ^ -s https://clients2.google.com/cr/symbol ^ -mf %SCRIPT_LOCATION%missing_symbols_test.txt ^ diff --git a/src/tools/windows/dump_syms/dump_syms_unittest.cc b/src/tools/windows/dump_syms/dump_syms_unittest.cc index 73c48a2f4..f50bd3b89 100644 --- a/src/tools/windows/dump_syms/dump_syms_unittest.cc +++ b/src/tools/windows/dump_syms/dump_syms_unittest.cc @@ -75,13 +75,13 @@ void TrimLastComponent(const std::wstring& path, while (len > 0 && path[len - 1] != '\\') --len; - if (component != NULL) + if (component != nullptr) component->assign(path.c_str() + len, path.c_str() + path.size()); while (len > 0 && path[len - 1] == '\\') --len; - if (trimmed != NULL) + if (trimmed != nullptr) trimmed->assign(path.c_str(), len); } @@ -90,13 +90,13 @@ bool GetSelfDirectory(std::wstring* self_dir) { std::wstring command_line = GetCommandLineW(); int num_args = 0; - wchar_t** args = NULL; + wchar_t** args = nullptr; args = ::CommandLineToArgvW(command_line.c_str(), &num_args); - if (args == NULL) + if (args == nullptr) return false; *self_dir = args[0]; - TrimLastComponent(*self_dir, self_dir, NULL); + TrimLastComponent(*self_dir, self_dir, nullptr); return true; } @@ -129,12 +129,12 @@ void RunCommand(const std::wstring& command_line, STARTUPINFO startup_info = {}; PROCESS_INFORMATION process_info = {}; startup_info.cb = sizeof(STARTUPINFO); - startup_info.hStdError = NULL; + startup_info.hStdError = nullptr; startup_info.hStdInput = child_stdin_read; startup_info.hStdOutput = child_stdout_write; startup_info.dwFlags = STARTF_USESTDHANDLES; - ASSERT_TRUE(::CreateProcessW(NULL, (LPWSTR)command_line.c_str(), NULL, NULL, - TRUE, 0, NULL, NULL, + ASSERT_TRUE(::CreateProcessW(nullptr, (LPWSTR)command_line.c_str(), nullptr, + nullptr, TRUE, 0, nullptr, nullptr, &startup_info, &process_info)); // Collect the output. @@ -142,7 +142,7 @@ void RunCommand(const std::wstring& command_line, char buffer[4096] = {}; DWORD bytes_read = 0; while (::ReadFile(child_stdout_read, buffer, sizeof(buffer), &bytes_read, - NULL) && bytes_read > 0) { + nullptr) && bytes_read > 0) { stdout_string->append(buffer, bytes_read); } @@ -159,7 +159,7 @@ void RunCommand(const std::wstring& command_line, void GetFileContents(const std::wstring& path, std::string* content) { FILE* f = ::_wfopen(path.c_str(), L"rb"); - ASSERT_TRUE(f != NULL); + ASSERT_TRUE(f != nullptr); char buffer[4096] = {}; while (true) { @@ -177,7 +177,7 @@ class DumpSymsRegressionTest : public testing::TestWithParam { ASSERT_TRUE(GetSelfDirectory(&self_dir)); dump_syms_exe = self_dir + L"\\dump_syms.exe"; - TrimLastComponent(self_dir, &testdata_dir, NULL); + TrimLastComponent(self_dir, &testdata_dir, nullptr); testdata_dir += L"\\testdata"; } @@ -192,7 +192,7 @@ class DumpSymsPEOnlyRegressionTest : public testing::TestWithParam + #include +#include #include -#include #include #include #include -#include "common/windows/string_utils-inl.h" - #include "common/windows/http_upload.h" #include "common/windows/pdb_source_line_writer.h" +#include "common/windows/string_utils-inl.h" #include "common/windows/sym_upload_v2_protocol.h" #include "common/windows/symbol_collector_client.h" @@ -87,7 +87,7 @@ static bool GetFileVersionString(const wchar_t* filename, wstring* version) { return false; } - void* file_info_buffer = NULL; + void* file_info_buffer = nullptr; unsigned int file_info_length; if (!VerQueryValue(&version_info[0], L"\\", &file_info_buffer, &file_info_length)) { @@ -138,7 +138,7 @@ static bool DumpSymbolsToTempFile(const wchar_t* file, return false; } - FILE* temp_file = NULL; + FILE* temp_file = nullptr; #if _MSC_VER >= 1400 // MSVC 2005/8 if (_wfopen_s(&temp_file, temp_filename, L"w") != 0) #else // _MSC_VER >= 1400 @@ -292,7 +292,7 @@ int wmain(int argc, wchar_t* argv[]) { while (currentarg < argc) { int response_code; if (!HTTPUpload::SendMultipartPostRequest(argv[currentarg], parameters, files, - timeout == -1 ? NULL : &timeout, + timeout == -1 ? nullptr : &timeout, nullptr, &response_code)) { success = false; fwprintf(stderr, @@ -305,12 +305,12 @@ int wmain(int argc, wchar_t* argv[]) { _wunlink(symbol_file.c_str()); - if (success) { - wprintf(L"Uploaded breakpad symbols for windows-%s/%s/%s (%s %s)\n", - pdb_info.cpu.c_str(), pdb_info.debug_file.c_str(), - pdb_info.debug_identifier.c_str(), code_file.c_str(), - file_version.c_str()); - } + fwprintf(success ? stdout : stderr, + L"%S breakpad symbols for windows-%s/%s/%s (%s %s)\n", + success ? "Uploaded" : "Failed to upload", + pdb_info.cpu.c_str(), pdb_info.debug_file.c_str(), + pdb_info.debug_identifier.c_str(), code_file.c_str(), + file_version.c_str()); return success ? 0 : 1; }