aboutsummaryrefslogtreecommitdiff
path: root/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/linux/core2md/core2md.cc4
-rw-r--r--src/tools/linux/core_handler/core_handler.cc4
-rw-r--r--src/tools/linux/dump_syms/dump_syms.cc6
-rw-r--r--src/tools/linux/md2core/minidump-2-core.cc76
-rw-r--r--src/tools/linux/md2core/minidump_memory_range_unittest.cc4
-rw-r--r--src/tools/linux/pid2md/pid2md.cc4
-rw-r--r--src/tools/linux/symupload/minidump_upload.cc4
-rw-r--r--src/tools/linux/symupload/sym_upload.cc4
-rw-r--r--src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj4
-rw-r--r--src/tools/mac/dump_syms/dump_syms_tool.cc88
-rw-r--r--src/tools/mac/dump_syms/macho_dump.cc202
-rw-r--r--src/tools/mac/symupload/symupload.xcodeproj/project.pbxproj4
-rw-r--r--src/tools/mac/upload_system_symbols/upload_system_symbols.go25
-rwxr-xr-xsrc/tools/mac/upload_system_symbols/upload_system_symbols.sh114
-rwxr-xr-xsrc/tools/python/deps-to-manifest.py7
-rw-r--r--src/tools/python/filter_syms.py9
-rw-r--r--src/tools/python/tests/filter_syms_unittest.py11
-rw-r--r--src/tools/solaris/dump_syms/dump_syms.cc4
-rw-r--r--src/tools/solaris/dump_syms/testdata/dump_syms_regtest.cc4
-rw-r--r--src/tools/windows/converter/ms_symbol_server_converter.cc4
-rw-r--r--src/tools/windows/converter_exe/converter.cc4
-rw-r--r--src/tools/windows/converter_exe/escaping.cc4
-rw-r--r--src/tools/windows/converter_exe/http_download.cc4
-rw-r--r--src/tools/windows/converter_exe/tokenizer.cc4
-rw-r--r--src/tools/windows/converter_exe/winhttp_client.cc4
-rw-r--r--src/tools/windows/converter_exe/wininet_client.cc4
-rw-r--r--src/tools/windows/dump_syms/dump_syms.cc4
-rw-r--r--src/tools/windows/dump_syms/dump_syms_unittest.cc4
-rw-r--r--src/tools/windows/dump_syms/testdata/dump_syms_regtest.cc5
-rw-r--r--src/tools/windows/symupload/symupload.cc4
30 files changed, 349 insertions, 274 deletions
diff --git a/src/tools/linux/core2md/core2md.cc b/src/tools/linux/core2md/core2md.cc
index 3f34294f..ec4a012a 100644
--- a/src/tools/linux/core2md/core2md.cc
+++ b/src/tools/linux/core2md/core2md.cc
@@ -28,6 +28,10 @@
// core2md.cc: A utility to convert an ELF core file to a minidump file.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <stdio.h>
#include "client/linux/minidump_writer/minidump_writer.h"
diff --git a/src/tools/linux/core_handler/core_handler.cc b/src/tools/linux/core_handler/core_handler.cc
index 224073d3..8a1d9766 100644
--- a/src/tools/linux/core_handler/core_handler.cc
+++ b/src/tools/linux/core_handler/core_handler.cc
@@ -28,6 +28,10 @@
// core_handler.cc: A tool to handle coredumps on Linux
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/src/tools/linux/dump_syms/dump_syms.cc b/src/tools/linux/dump_syms/dump_syms.cc
index 8998b3b3..2fce23c2 100644
--- a/src/tools/linux/dump_syms/dump_syms.cc
+++ b/src/tools/linux/dump_syms/dump_syms.cc
@@ -26,6 +26,10 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <paths.h>
#include <stdio.h>
#include <unistd.h>
@@ -56,7 +60,7 @@ int usage(const char* self) {
fprintf(stderr, " -n <name> Use specified name for name of the object\n");
fprintf(stderr, " -o <os> Use specified name for the "
"operating system\n");
- fprintf(stderr, " -m Enable writing the optional 'm' field on FUNC"
+ fprintf(stderr, " -m Enable writing the optional 'm' field on FUNC "
"and PUBLIC, denoting multiple symbols for "
"the address.\n");
return 1;
diff --git a/src/tools/linux/md2core/minidump-2-core.cc b/src/tools/linux/md2core/minidump-2-core.cc
index a4ddbe8e..3e310bc7 100644
--- a/src/tools/linux/md2core/minidump-2-core.cc
+++ b/src/tools/linux/md2core/minidump-2-core.cc
@@ -30,6 +30,10 @@
// Large parts lifted from the userspace core dumper:
// http://code.google.com/p/google-coredumper/
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <elf.h>
#include <errno.h>
#include <limits.h>
@@ -278,7 +282,7 @@ typedef struct prpsinfo { /* Information about process */
// We parse the minidump file and keep the parsed information in this structure
struct CrashedProcess {
CrashedProcess()
- : crashing_tid(-1),
+ : exception{-1},
auxv(NULL),
auxv_length(0) {
memset(&prps, 0, sizeof(prps));
@@ -302,7 +306,6 @@ struct CrashedProcess {
};
std::map<uint64_t, Mapping> mappings;
- pid_t crashing_tid;
int fatal_signal;
struct Thread {
@@ -326,6 +329,7 @@ struct CrashedProcess {
size_t stack_length;
};
std::vector<Thread> threads;
+ Thread exception;
const uint8_t* auxv;
size_t auxv_length;
@@ -579,25 +583,21 @@ ParseThreadRegisters(CrashedProcess::Thread* thread,
thread->mcontext.__gregs[30] = rawregs->t5;
thread->mcontext.__gregs[31] = rawregs->t6;
-# if __riscv_flen == 32
- for (int i = 0; i < MD_FLOATINGSAVEAREA_RISCV_FPR_COUNT; ++i) {
- thread->mcontext.__fpregs.__f.__f[i] = rawregs->float_save.regs[i];
+ // Breakpad only supports RISCV32 with 32 bit floating point.
+ // Breakpad only supports RISCV64 with 64 bit floating point.
+#if __riscv_xlen == 32
+ for (int i = 0; i < MD_CONTEXT_RISCV_FPR_COUNT; ++i) {
+ thread->mcontext.__fpregs.__f.__f[i] = rawregs->fpregs[i];
}
- thread->mcontext.__fpregs.__f.__fcsr = rawregs->float_save.fpcsr;
-# elif __riscv_flen == 64
- for (int i = 0; i < MD_FLOATINGSAVEAREA_RISCV_FPR_COUNT; ++i) {
- thread->mcontext.__fpregs.__d.__f[i] = rawregs->float_save.regs[i];
+ thread->mcontext.__fpregs.__f.__fcsr = rawregs->fcsr;
+#elif __riscv_xlen == 64
+ for (int i = 0; i < MD_CONTEXT_RISCV_FPR_COUNT; ++i) {
+ thread->mcontext.__fpregs.__d.__f[i] = rawregs->fpregs[i];
}
- thread->mcontext.__fpregs.__d.__fcsr = rawregs->float_save.fpcsr;
-# elif __riscv_flen == 128
- for (int i = 0; i < MD_FLOATINGSAVEAREA_RISCV_FPR_COUNT; ++i) {
- thread->mcontext.__fpregs.__q.__f[2*i] = rawregs->float_save.regs[i].high;
- thread->mcontext.__fpregs.__q.__f[2*i+1] = rawregs->float_save.regs[i].low;
- }
- thread->mcontext.__fpregs.__q.__fcsr = rawregs->float_save.fpcsr;
-# else
-# error "Unexpected __riscv_flen"
-# endif
+ thread->mcontext.__fpregs.__d.__fcsr = rawregs->fcsr;
+#else
+#error "Unexpected __riscv_xlen"
+#endif
}
#else
#error "This code has not been ported to your platform yet"
@@ -995,10 +995,25 @@ ParseDSODebugInfo(const Options& options, CrashedProcess* crashinfo,
static void
ParseExceptionStream(const Options& options, CrashedProcess* crashinfo,
- const MinidumpMemoryRange& range) {
+ const MinidumpMemoryRange& range,
+ const MinidumpMemoryRange& full_file) {
const MDRawExceptionStream* exp = range.GetData<MDRawExceptionStream>(0);
- crashinfo->crashing_tid = exp->thread_id;
+ if (!exp) {
+ return;
+ }
+ if (options.verbose) {
+ fprintf(stderr,
+ "MD_EXCEPTION_STREAM:\n"
+ "Found exception thread %" PRIu32 " \n"
+ "\n\n",
+ exp->thread_id);
+ }
crashinfo->fatal_signal = (int) exp->exception_record.exception_code;
+ crashinfo->exception = {};
+ crashinfo->exception.tid = exp->thread_id;
+ // crashinfo->threads[].tid == crashinfo->exception.tid provides the stack.
+ ParseThreadRegisters(&crashinfo->exception,
+ full_file.Subrange(exp->thread_context));
}
static bool
@@ -1361,7 +1376,7 @@ main(int argc, const char* argv[]) {
break;
case MD_EXCEPTION_STREAM:
ParseExceptionStream(options, &crashinfo,
- dump.Subrange(dirent->location));
+ dump.Subrange(dirent->location), dump);
break;
case MD_MODULE_LIST_STREAM:
ParseModuleStream(options, &crashinfo, dump.Subrange(dirent->location),
@@ -1477,16 +1492,21 @@ main(int argc, const char* argv[]) {
return 1;
}
- for (unsigned i = 0; i < crashinfo.threads.size(); ++i) {
- if (crashinfo.threads[i].tid == crashinfo.crashing_tid) {
- WriteThread(options, crashinfo.threads[i], crashinfo.fatal_signal);
+ 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
+ // the thread's own context. For the crashed thread the thread's own
+ // context is the state inside the exception handler. Using it would not
+ // result in the expected stack trace from the time of the crash.
+ // The stack memory has already been provided by current_thread.
+ WriteThread(options, crashinfo.exception, crashinfo.fatal_signal);
break;
}
}
- for (unsigned i = 0; i < crashinfo.threads.size(); ++i) {
- if (crashinfo.threads[i].tid != crashinfo.crashing_tid)
- WriteThread(options, crashinfo.threads[i], 0);
+ for (const auto& current_thread : crashinfo.threads) {
+ if (current_thread.tid != crashinfo.exception.tid)
+ WriteThread(options, current_thread, 0);
}
if (note_align) {
diff --git a/src/tools/linux/md2core/minidump_memory_range_unittest.cc b/src/tools/linux/md2core/minidump_memory_range_unittest.cc
index 9012101d..c939dd64 100644
--- a/src/tools/linux/md2core/minidump_memory_range_unittest.cc
+++ b/src/tools/linux/md2core/minidump_memory_range_unittest.cc
@@ -29,6 +29,10 @@
// minidump_memory_range_unittest.cc:
// Unit tests for google_breakpad::MinidumpMemoryRange.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "breakpad_googletest_includes.h"
#include "tools/linux/md2core/minidump_memory_range.h"
diff --git a/src/tools/linux/pid2md/pid2md.cc b/src/tools/linux/pid2md/pid2md.cc
index ca1cb637..add12a73 100644
--- a/src/tools/linux/pid2md/pid2md.cc
+++ b/src/tools/linux/pid2md/pid2md.cc
@@ -28,6 +28,10 @@
// pid2md.cc: An utility to generate a minidump from a running process
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
diff --git a/src/tools/linux/symupload/minidump_upload.cc b/src/tools/linux/symupload/minidump_upload.cc
index 6adead03..9f2c9674 100644
--- a/src/tools/linux/symupload/minidump_upload.cc
+++ b/src/tools/linux/symupload/minidump_upload.cc
@@ -33,6 +33,10 @@
// ver: the product version
// symbol_file: the breakpad format symbol file
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
diff --git a/src/tools/linux/symupload/sym_upload.cc b/src/tools/linux/symupload/sym_upload.cc
index 8f5e8a50..a76c55f7 100644
--- a/src/tools/linux/symupload/sym_upload.cc
+++ b/src/tools/linux/symupload/sym_upload.cc
@@ -38,6 +38,10 @@
// cpu: the CPU that the module was built for
// symbol_file: the contents of the breakpad-format symbol file
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj b/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj
index 5b644e24..c98b6ac5 100644
--- a/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj
+++ b/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj
@@ -1251,7 +1251,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 8B3102D411F0D60300FCF3E4 /* BreakpadDebug.xcconfig */;
buildSettings = {
- CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
HEADER_SEARCH_PATHS = (
../../..,
../../../common/mac/include/,
@@ -1264,7 +1264,7 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 8B3102D511F0D60300FCF3E4 /* BreakpadRelease.xcconfig */;
buildSettings = {
- CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
HEADER_SEARCH_PATHS = (
../../..,
../../../common/mac/include/,
diff --git a/src/tools/mac/dump_syms/dump_syms_tool.cc b/src/tools/mac/dump_syms/dump_syms_tool.cc
index 2e05cbf3..9fb8d13f 100644
--- a/src/tools/mac/dump_syms/dump_syms_tool.cc
+++ b/src/tools/mac/dump_syms/dump_syms_tool.cc
@@ -31,6 +31,10 @@
// dump_syms_tool.cc: Command line tool that uses the DumpSymbols class.
// TODO(waylonis): accept stdin
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <mach-o/arch.h>
#include <unistd.h>
@@ -59,16 +63,20 @@ struct Options {
cfi(true),
handle_inter_cu_refs(true),
handle_inlines(false),
- enable_multiple(false) {}
+ enable_multiple(false),
+ module_name(),
+ prefer_extern_name(false) {}
string srcPath;
string dsymPath;
- const NXArchInfo *arch;
+ std::optional<ArchInfo> arch;
bool header_only;
bool cfi;
bool handle_inter_cu_refs;
bool handle_inlines;
bool enable_multiple;
+ string module_name;
+ bool prefer_extern_name;
};
static bool StackFrameEntryComparator(const Module::StackFrameEntry* a,
@@ -117,11 +125,12 @@ static void CopyCFIDataBetweenModules(Module* to_module,
}
static bool SetArchitecture(DumpSymbols& dump_symbols,
- const NXArchInfo* arch,
+ const ArchInfo& arch,
const std::string& filename) {
- if (!dump_symbols.SetArchitecture(arch->cputype, arch->cpusubtype)) {
+ if (!dump_symbols.SetArchitecture(arch)) {
fprintf(stderr, "%s: no architecture '%s' is present in file.\n",
- filename.c_str(), arch->name);
+ filename.c_str(),
+ GetNameFromCPUType(arch.cputype, arch.cpusubtype));
size_t available_size;
const SuperFatArch* available =
dump_symbols.AvailableArchitectures(&available_size);
@@ -131,14 +140,8 @@ static bool SetArchitecture(DumpSymbols& dump_symbols,
fprintf(stderr, "architectures present in the file are:\n");
for (size_t i = 0; i < available_size; i++) {
const SuperFatArch* arch = &available[i];
- const NXArchInfo* arch_info =
- google_breakpad::BreakpadGetArchInfoFromCpuType(arch->cputype,
- arch->cpusubtype);
- if (arch_info)
- fprintf(stderr, "%s (%s)\n", arch_info->name, arch_info->description);
- else
- fprintf(stderr, "unrecognized cpu type 0x%x, subtype 0x%x\n",
- arch->cputype, arch->cpusubtype);
+ fprintf(stderr, "%s\n",
+ GetNameFromCPUType(arch->cputype, arch->cpusubtype));
}
return false;
}
@@ -150,7 +153,8 @@ static bool Start(const Options& options) {
(options.handle_inlines ? INLINES : NO_DATA) |
(options.cfi ? CFI : NO_DATA) | SYMBOLS_AND_FILES;
DumpSymbols dump_symbols(symbol_data, options.handle_inter_cu_refs,
- options.enable_multiple);
+ options.enable_multiple, options.module_name,
+ options.prefer_extern_name);
// For x86_64 binaries, the CFI data is in the __TEXT,__eh_frame of the
// Mach-O file, which is not copied into the dSYM. Whereas in i386, the CFI
@@ -169,7 +173,7 @@ static bool Start(const Options& options) {
return false;
if (options.arch &&
- !SetArchitecture(dump_symbols, options.arch, primary_file)) {
+ !SetArchitecture(dump_symbols, *options.arch, primary_file)) {
return false;
}
@@ -189,7 +193,7 @@ static bool Start(const Options& options) {
return false;
if (options.arch &&
- !SetArchitecture(dump_symbols, options.arch, options.srcPath)) {
+ !SetArchitecture(dump_symbols, *options.arch, options.srcPath)) {
return false;
}
Module* cfi_module = NULL;
@@ -197,13 +201,38 @@ static bool Start(const Options& options) {
return false;
scoped_ptr<Module> scoped_cfi_module(cfi_module);
+ bool name_matches;
+ if (!options.module_name.empty()) {
+ // Ignore the basename of the dSYM and binary and use the passed-in module
+ // name.
+ name_matches = true;
+ } else {
+ name_matches = cfi_module->name() == module->name();
+ }
+
// Ensure that the modules are for the same debug code file.
- if (cfi_module->name() != module->name() ||
- cfi_module->os() != module->os() ||
+ if (!name_matches || cfi_module->os() != module->os() ||
cfi_module->architecture() != module->architecture() ||
cfi_module->identifier() != module->identifier()) {
fprintf(stderr, "Cannot generate a symbol file from split sources that do"
" not match.\n");
+ if (!name_matches) {
+ fprintf(stderr, "Name mismatch: binary=[%s], dSYM=[%s]\n",
+ cfi_module->name().c_str(), module->name().c_str());
+ }
+ if (cfi_module->os() != module->os()) {
+ fprintf(stderr, "OS mismatch: binary=[%s], dSYM=[%s]\n",
+ cfi_module->os().c_str(), module->os().c_str());
+ }
+ if (cfi_module->architecture() != module->architecture()) {
+ fprintf(stderr, "Architecture mismatch: binary=[%s], dSYM=[%s]\n",
+ cfi_module->architecture().c_str(),
+ module->architecture().c_str());
+ }
+ if (cfi_module->identifier() != module->identifier()) {
+ fprintf(stderr, "Identifier mismatch: binary=[%s], dSYM=[%s]\n",
+ cfi_module->identifier().c_str(), module->identifier().c_str());
+ }
return false;
}
@@ -216,8 +245,10 @@ static bool Start(const Options& options) {
//=============================================================================
static void Usage(int argc, const char *argv[]) {
fprintf(stderr, "Output a Breakpad symbol file from a Mach-o file.\n");
- fprintf(stderr, "Usage: %s [-a ARCHITECTURE] [-c] [-g dSYM path] "
- "<Mach-o file>\n", argv[0]);
+ fprintf(stderr,
+ "Usage: %s [-a ARCHITECTURE] [-c] [-g dSYM path] "
+ "[-n MODULE] [-x] <Mach-o file>\n",
+ argv[0]);
fprintf(stderr, "\t-i: Output module header information only.\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");
@@ -229,6 +260,12 @@ static void Usage(int argc, const char *argv[]) {
fprintf(stderr,
"\t-m: Enable writing the optional 'm' field on FUNC "
"and PUBLIC, denoting multiple symbols for the address.\n");
+ fprintf(stderr,
+ "\t-n: Use MODULE as the name of the module rather than \n"
+ "the basename of the Mach-O file/dSYM.\n");
+ fprintf(stderr,
+ "\t-x: Prefer the PUBLIC (extern) name over the FUNC if\n"
+ "they do not match.\n");
fprintf(stderr, "\t-h: Usage\n");
fprintf(stderr, "\t-?: Usage\n");
}
@@ -238,14 +275,13 @@ 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?h")) != -1) {
+ while ((ch = getopt(argc, (char* const*)argv, "ia:g:crdm?hn:x")) != -1) {
switch (ch) {
case 'i':
options->header_only = true;
break;
case 'a': {
- const NXArchInfo *arch_info =
- google_breakpad::BreakpadGetArchInfoFromName(optarg);
+ std::optional<ArchInfo> arch_info = GetArchInfoFromName(optarg);
if (!arch_info) {
fprintf(stderr, "%s: Invalid architecture: %s\n", argv[0], optarg);
Usage(argc, argv);
@@ -269,6 +305,12 @@ static void SetupOptions(int argc, const char *argv[], Options *options) {
case 'm':
options->enable_multiple = true;
break;
+ case 'n':
+ options->module_name = optarg;
+ break;
+ case 'x':
+ options->prefer_extern_name = true;
+ break;
case '?':
case 'h':
Usage(argc, argv);
diff --git a/src/tools/mac/dump_syms/macho_dump.cc b/src/tools/mac/dump_syms/macho_dump.cc
deleted file mode 100644
index b724cc74..00000000
--- a/src/tools/mac/dump_syms/macho_dump.cc
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright 2010 Google LLC
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google LLC nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// macho_dump.cc: Dump the contents of a Mach-O file. This is mostly
-// a test program for the Mach_O::FatReader and Mach_O::Reader classes.
-
-#include <errno.h>
-#include <fcntl.h>
-#include <mach-o/arch.h>
-#include <sys/mman.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include "common/byte_cursor.h"
-#include "common/mac/arch_utilities.h"
-#include "common/mac/macho_reader.h"
-#include "common/path_helper.h"
-
-using google_breakpad::ByteBuffer;
-using std::ostringstream;
-using std::string;
-using std::vector;
-
-namespace {
-namespace mach_o = google_breakpad::mach_o;
-
-string program_name;
-
-int check_syscall(int result, const char* operation, const char* filename) {
- if (result < 0) {
- fprintf(stderr, "%s: %s '%s': %s\n",
- program_name.c_str(), operation,
- filename, strerror(errno));
- exit(1);
- }
- return result;
-}
-
-class DumpSection: public mach_o::Reader::SectionHandler {
- public:
- DumpSection() : index_(0) { }
- bool HandleSection(const mach_o::Section& section) {
- printf(" section %d '%s' in segment '%s'\n"
- " address: 0x%llx\n"
- " alignment: 1 << %d B\n"
- " flags: %d\n"
- " size: %ld\n",
- index_++, section.section_name.c_str(), section.segment_name.c_str(),
- section.address, section.align,
- mach_o::SectionFlags(section.flags),
- section.contents.Size());
- return true;
- }
-
- private:
- int index_;
-};
-
-class DumpCommand: public mach_o::Reader::LoadCommandHandler {
- public:
- DumpCommand(mach_o::Reader* reader) : reader_(reader), index_(0) { }
- bool UnknownCommand(mach_o::LoadCommandType type,
- const ByteBuffer& contents) {
- printf(" load command %d: %d", index_++, type);
- return true;
- }
- bool SegmentCommand(const mach_o::Segment& segment) {
- printf(" load command %d: %s-bit segment '%s'\n"
- " address: 0x%llx\n"
- " memory size: 0x%llx\n"
- " maximum protection: 0x%x\n"
- " initial protection: 0x%x\n"
- " flags: %d\n"
- " section_list size: %ld B\n",
- index_++, (segment.bits_64 ? "64" : "32"), segment.name.c_str(),
- segment.vmaddr, segment.vmsize, segment.maxprot,
- segment.initprot, mach_o::SegmentFlags(segment.flags),
- segment.section_list.Size());
-
- DumpSection dump_section;
- return reader_->WalkSegmentSections(segment, &dump_section);
- }
- private:
- mach_o::Reader* reader_;
- int index_;
-};
-
-void DumpFile(const char* filename) {
- int fd = check_syscall(open(filename, O_RDONLY), "opening", filename);
- struct stat attributes;
- check_syscall(fstat(fd, &attributes),
- "getting file attributes for", filename);
- void* mapping = mmap(NULL, attributes.st_size, PROT_READ,
- MAP_PRIVATE, fd, 0);
- close(fd);
- check_syscall(mapping == (void*)-1 ? -1 : 0,
- "mapping contents of", filename);
-
- mach_o::FatReader::Reporter fat_reporter(filename);
- mach_o::FatReader fat_reader(&fat_reporter);
- if (!fat_reader.Read(reinterpret_cast<uint8_t*>(mapping),
- attributes.st_size)) {
- exit(1);
- }
- printf("filename: %s\n", filename);
- size_t object_files_size;
- const SuperFatArch* super_fat_object_files =
- fat_reader.object_files(&object_files_size);
- struct fat_arch* object_files;
- if (!super_fat_object_files->ConvertToFatArch(object_files)) {
- exit(1);
- }
- printf(" object file count: %ld\n", object_files_size);
- for (size_t i = 0; i < object_files_size; i++) {
- const struct fat_arch& file = object_files[i];
- const NXArchInfo* fat_arch_info =
- google_breakpad::BreakpadGetArchInfoFromCpuType(
- file.cputype, file.cpusubtype);
- printf("\n object file %ld:\n"
- " fat header:\n:"
- " CPU type: %s (%s)\n"
- " size: %d B\n"
- " alignment: 1<<%d B\n",
- i, fat_arch_info->name, fat_arch_info->description,
- file.size, file.align);
-
- ostringstream name;
- name << filename;
- if (object_files_size > 1)
- name << ", object file #" << i;
- ByteBuffer file_contents(reinterpret_cast<uint8_t*>(mapping)
- + file.offset, file.size);
- mach_o::Reader::Reporter reporter(name.str());
- mach_o::Reader reader(&reporter);
- if (!reader.Read(file_contents, file.cputype, file.cpusubtype)) {
- exit(1);
- }
-
- const NXArchInfo* macho_arch_info =
- NXGetArchInfoFromCpuType(reader.cpu_type(),
- reader.cpu_subtype());
- printf(" Mach-O header:\n"
- " word size: %s\n"
- " CPU type: %s (%s)\n"
- " File type: %d\n"
- " flags: %x\n",
- (reader.bits_64() ? "64 bits" : "32 bits"),
- macho_arch_info->name, macho_arch_info->description,
- reader.file_type(), reader.flags());
-
- DumpCommand dump_command(&reader);
- reader.WalkLoadCommands(&dump_command);
- }
- munmap(mapping, attributes.st_size);
-}
-
-} // namespace
-
-int main(int argc, char** argv) {
- program_name = google_breakpad::BaseName(argv[0]);
- if (argc == 1) {
- fprintf(stderr, "Usage: %s FILE ...\n"
- "Dump the contents of the Mach-O or fat binary files "
- "'FILE ...'.\n", program_name.c_str());
- }
- for (int i = 1; i < argc; i++) {
- DumpFile(argv[i]);
- }
-}
diff --git a/src/tools/mac/symupload/symupload.xcodeproj/project.pbxproj b/src/tools/mac/symupload/symupload.xcodeproj/project.pbxproj
index 903c66f1..b1dd6a11 100644
--- a/src/tools/mac/symupload/symupload.xcodeproj/project.pbxproj
+++ b/src/tools/mac/symupload/symupload.xcodeproj/project.pbxproj
@@ -371,7 +371,7 @@
1DEB927508733DD40010E9CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
GCC_PREPROCESSOR_DEFINITIONS = HAVE_MACH_O_NLIST_H;
HEADER_SEARCH_PATHS = (
../../..,
@@ -385,7 +385,7 @@
1DEB927608733DD40010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
NDEBUG,
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 ba067276..f34c288a 100644
--- a/src/tools/mac/upload_system_symbols/upload_system_symbols.go
+++ b/src/tools/mac/upload_system_symbols/upload_system_symbols.go
@@ -163,6 +163,29 @@ func main() {
}
}
+// 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
+// the last path component; for example /System/Library/Frameworks/AppKit
+// becomes SLFAppKit.
+// Assumes ASCII.
+func manglePath(path string) string {
+ components := strings.Split(path, "/")
+ n := len(components)
+ builder := strings.Builder{}
+ for i, component := range components {
+ if len(component) == 0 {
+ continue
+ }
+ if i < n-1 {
+ builder.WriteString(component[:1])
+ } else {
+ builder.WriteString(component)
+ }
+ }
+ return builder.String()
+}
+
type WorkerPool struct {
wg sync.WaitGroup
}
@@ -296,7 +319,7 @@ func (dq *DumpQueue) worker() {
dumpSyms := path.Join(*breakpadTools, "dump_syms")
for req := range dq.queue {
- filebase := path.Join(dq.dumpPath, strings.Replace(req.path, "/", "_", -1))
+ filebase := path.Join(dq.dumpPath, manglePath(req.path))
symfile := fmt.Sprintf("%s_%s.sym", filebase, req.arch)
f, err := os.Create(symfile)
if err != nil {
diff --git a/src/tools/mac/upload_system_symbols/upload_system_symbols.sh b/src/tools/mac/upload_system_symbols/upload_system_symbols.sh
new file mode 100755
index 00000000..43fd98ed
--- /dev/null
+++ b/src/tools/mac/upload_system_symbols/upload_system_symbols.sh
@@ -0,0 +1,114 @@
+#!/bin/bash
+
+# Copyright 2023 Google LLC
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google LLC nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Finds the dyld_shared_cache on a system, extracts it, and dumps the symbols
+# in Breakpad format to the directory passed as the first argument
+# The script must be in the same directory as `dump_syms`,
+# `upload_system_symbols` and `dsc_extractor` binaries.
+# Exits with 0 if all supported architectures for this OS version were found and
+# dumped, and nonzero otherwise.
+
+set -ex
+
+if [[ $# -ne 1 ]]; then
+ echo "usage: $0 <destination_directory>" >& 2
+ exit 1
+fi
+
+destination_dir="$1"
+
+dir="$(dirname "$0")"
+dir="$(cd "${dir}"; pwd)"
+major_version=$(sw_vers -productVersion | cut -d . -f 1)
+if [[ "${major_version}" -lt 13 ]]; then
+ dsc_directory="/System/Library/dyld"
+else
+ dsc_directory="/System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld"
+fi
+
+working_dir=$(mktemp -d)
+mkdir "${destination_dir}"
+trap 'rm -rf "${working_dir}" "${destination_dir}"' EXIT
+
+architectures=(x86_64h)
+missing_architectures=()
+# macOS >= 13 on arm64 still has a x86_64 cache for Rosetta.
+if [[ "${major_version}" -lt 13 ]] || [[ $(uname -p) == "arm" ]]; then
+ architectures+=( x86_64 )
+fi
+if [[ "${major_version}" -ge 11 ]]; then
+ architectures+=( arm64e )
+fi
+
+for arch in "${architectures[@]}"; do
+ cache="${dsc_directory}/dyld_shared_cache_${arch}"
+ if [[ ! -f "${cache}" ]]; then
+ missing_architectures+=("${arch}")
+ continue
+ fi
+ "${dir}/dsc_extractor" \
+ "${cache}" \
+ "${working_dir}/${arch}"
+ "${dir}/upload_system_symbols" \
+ --breakpad-tools="${dir}" \
+ --system-root="${working_dir}/${arch}" \
+ --dump-to="${destination_dir}"
+done
+if [[ "${#missing_architectures[@]}" -eq "${#architectures[@]}" ]]; then
+ echo "Couldn't locate dyld_shared_cache for any architectures" >& 2
+ echo "in ${dsc_directory}. Exiting." >& 2
+ exit 1
+fi
+
+rm -rf "${working_dir}"
+# We have results now, so let's keep `destination_dir`.
+trap '' EXIT
+
+"${dir}/upload_system_symbols" \
+ --breakpad-tools="${dir}" \
+ --system-root=/ \
+ --dump-to="${destination_dir}"
+
+set +x
+echo
+echo "Dumped!"
+echo "To upload, run:"
+echo
+echo "'${dir}/upload_system_symbols'" \\
+echo " --breakpad-tools='${dir}'" \\
+echo " --api-key=<YOUR API KEY>" \\
+echo " --upload-from='${destination_dir}'"
+
+if [[ "${#missing_architectures[@]}" -gt 0 ]]; then
+ echo "dyld_shared_cache not found for architecture(s):" >& 2
+ echo " " "${missing_architectures[@]}" >& 2
+ echo "You'll need to get symbols for them elsewhere." >& 2
+ exit 1
+fi
diff --git a/src/tools/python/deps-to-manifest.py b/src/tools/python/deps-to-manifest.py
index 2fcaf771..b614f94f 100755
--- a/src/tools/python/deps-to-manifest.py
+++ b/src/tools/python/deps-to-manifest.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# Copyright 2016 Google LLC
#
# Redistribution and use in source and binary forms, with or without
@@ -29,8 +29,6 @@
"""Convert gclient's DEPS file to repo's manifest xml file."""
-from __future__ import print_function
-
import argparse
import os
import sys
@@ -76,7 +74,8 @@ def ConvertDepsToManifest(deps, manifest):
"""Convert the |deps| file to the |manifest|."""
# Load the DEPS file data.
ctx = {}
- execfile(deps, ctx)
+ with open(deps, 'rb') as file:
+ exec(compile(file.read(), deps, 'exec'), ctx)
new_contents = ''
diff --git a/src/tools/python/filter_syms.py b/src/tools/python/filter_syms.py
index caf3693a..8537769e 100644
--- a/src/tools/python/filter_syms.py
+++ b/src/tools/python/filter_syms.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright 2012 Google LLC
#
# Redistribution and use in source and binary forms, with or without
@@ -38,7 +38,6 @@ DWARF files and normalize and de-duplicate the FILE records found within,
updating any references to the FILE records in the other record types.
"""
-import macpath
import ntpath
import optparse
import os
@@ -132,8 +131,8 @@ class SymbolFileParser(object):
Returns:
The actual path to use when writing the FILE record.
"""
- return path[len(filter(path.startswith,
- self.ignored_prefixes + [''])[0]):]
+ return path[len(next(filter(path.startswith,
+ self.ignored_prefixes + ['']))):]
def _ParseFileRecord(self, file_record):
"""Parses and corrects a FILE record."""
@@ -193,7 +192,7 @@ def main():
symbol_parser = SymbolFileParser(sys.stdin, sys.stdout, options.prefixes,
path_handler)
symbol_parser.Process()
- except BreakpadParseError, e:
+ except BreakpadParseError as e:
print >> sys.stderr, 'Got an error while processing symbol file'
print >> sys.stderr, str(e)
return 1
diff --git a/src/tools/python/tests/filter_syms_unittest.py b/src/tools/python/tests/filter_syms_unittest.py
index 1081fc73..f6364b8b 100644
--- a/src/tools/python/tests/filter_syms_unittest.py
+++ b/src/tools/python/tests/filter_syms_unittest.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Copyright 2012 Google LLC
#
# Redistribution and use in source and binary forms, with or without
@@ -29,10 +29,9 @@
"""Unit tests for filter_syms.py"""
-import cStringIO
+import io
import ntpath
import os
-import StringIO
import sys
import unittest
@@ -44,8 +43,8 @@ import filter_syms
class FilterSysmsTest(unittest.TestCase):
def assertParsed(self, input_data, ignored_prefixes, expected):
- input_io = cStringIO.StringIO(input_data)
- output_io = cStringIO.StringIO()
+ input_io = io.StringIO(input_data)
+ output_io = io.StringIO()
parser = filter_syms.SymbolFileParser(input_io, output_io,
ignored_prefixes, ntpath)
parser.Process()
@@ -134,4 +133,4 @@ FUNC 1000 c 0 Function1_1
self.assertParsed(INPUT, IGNORED_PREFIXES, EXPECTED_OUTPUT)
if __name__ == '__main__':
- unittest.main() \ No newline at end of file
+ unittest.main()
diff --git a/src/tools/solaris/dump_syms/dump_syms.cc b/src/tools/solaris/dump_syms/dump_syms.cc
index fc331c21..ead16001 100644
--- a/src/tools/solaris/dump_syms/dump_syms.cc
+++ b/src/tools/solaris/dump_syms/dump_syms.cc
@@ -28,6 +28,10 @@
// Author: Alfred Peng
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <string>
#include <cstdio>
diff --git a/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.cc b/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.cc
index b4d191bd..fb6c883b 100644
--- a/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.cc
+++ b/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.cc
@@ -28,6 +28,10 @@
// ./dump_syms dump_syms_regtest.pdb > dump_syms_regtest.sym
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
namespace google_breakpad {
class C {
diff --git a/src/tools/windows/converter/ms_symbol_server_converter.cc b/src/tools/windows/converter/ms_symbol_server_converter.cc
index bfe46925..f7d9d943 100644
--- a/src/tools/windows/converter/ms_symbol_server_converter.cc
+++ b/src/tools/windows/converter/ms_symbol_server_converter.cc
@@ -33,6 +33,10 @@
//
// Author: Mark Mentovai
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <windows.h>
#include <dbghelp.h>
#include <pathcch.h>
diff --git a/src/tools/windows/converter_exe/converter.cc b/src/tools/windows/converter_exe/converter.cc
index 75ec55b0..92c41774 100644
--- a/src/tools/windows/converter_exe/converter.cc
+++ b/src/tools/windows/converter_exe/converter.cc
@@ -31,6 +31,10 @@
#pragma comment(lib, "diaguids.lib")
#pragma comment(lib, "imagehlp.lib")
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <cassert>
#include <cstdio>
#include <ctime>
diff --git a/src/tools/windows/converter_exe/escaping.cc b/src/tools/windows/converter_exe/escaping.cc
index de074298..e399c0f4 100644
--- a/src/tools/windows/converter_exe/escaping.cc
+++ b/src/tools/windows/converter_exe/escaping.cc
@@ -26,6 +26,10 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "tools/windows/converter_exe/escaping.h"
#include <assert.h>
diff --git a/src/tools/windows/converter_exe/http_download.cc b/src/tools/windows/converter_exe/http_download.cc
index 75f674e0..de824198 100644
--- a/src/tools/windows/converter_exe/http_download.cc
+++ b/src/tools/windows/converter_exe/http_download.cc
@@ -26,6 +26,10 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <assert.h>
#include <stdio.h>
#include <Windows.h>
diff --git a/src/tools/windows/converter_exe/tokenizer.cc b/src/tools/windows/converter_exe/tokenizer.cc
index 6d627536..08480d7b 100644
--- a/src/tools/windows/converter_exe/tokenizer.cc
+++ b/src/tools/windows/converter_exe/tokenizer.cc
@@ -26,6 +26,10 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <assert.h>
#include "tools/windows/converter_exe/tokenizer.h"
diff --git a/src/tools/windows/converter_exe/winhttp_client.cc b/src/tools/windows/converter_exe/winhttp_client.cc
index f8c1492d..425a9daa 100644
--- a/src/tools/windows/converter_exe/winhttp_client.cc
+++ b/src/tools/windows/converter_exe/winhttp_client.cc
@@ -26,6 +26,10 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "tools/windows/converter_exe/winhttp_client.h"
#include <assert.h>
diff --git a/src/tools/windows/converter_exe/wininet_client.cc b/src/tools/windows/converter_exe/wininet_client.cc
index 90cf114c..571ab86c 100644
--- a/src/tools/windows/converter_exe/wininet_client.cc
+++ b/src/tools/windows/converter_exe/wininet_client.cc
@@ -26,6 +26,10 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "tools/windows/converter_exe/wininet_client.h"
#include <assert.h>
diff --git a/src/tools/windows/dump_syms/dump_syms.cc b/src/tools/windows/dump_syms/dump_syms.cc
index 26c226a2..1979d430 100644
--- a/src/tools/windows/dump_syms/dump_syms.cc
+++ b/src/tools/windows/dump_syms/dump_syms.cc
@@ -29,6 +29,10 @@
// Windows utility to dump the line number data from a pdb file to
// a text-based format that we can use from the minidump processor.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <stdio.h>
#include <wchar.h>
diff --git a/src/tools/windows/dump_syms/dump_syms_unittest.cc b/src/tools/windows/dump_syms/dump_syms_unittest.cc
index 97dc5c9b..73c48a2f 100644
--- a/src/tools/windows/dump_syms/dump_syms_unittest.cc
+++ b/src/tools/windows/dump_syms/dump_syms_unittest.cc
@@ -26,6 +26,10 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <Windows.h>
#include <shellapi.h>
diff --git a/src/tools/windows/dump_syms/testdata/dump_syms_regtest.cc b/src/tools/windows/dump_syms/testdata/dump_syms_regtest.cc
index 442676ba..90d00af2 100644
--- a/src/tools/windows/dump_syms/testdata/dump_syms_regtest.cc
+++ b/src/tools/windows/dump_syms/testdata/dump_syms_regtest.cc
@@ -35,6 +35,11 @@
// cl /Zi dump_syms_regtest64.cc /link /PROFILE
// dump_syms dump_syms_regtest64.pdb > dump_syms_regtest64.sym
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
namespace google_breakpad {
class C {
diff --git a/src/tools/windows/symupload/symupload.cc b/src/tools/windows/symupload/symupload.cc
index 65123a28..46ace95a 100644
--- a/src/tools/windows/symupload/symupload.cc
+++ b/src/tools/windows/symupload/symupload.cc
@@ -42,6 +42,10 @@
// cpu: the CPU that the module was built for, typically "x86".
// symbol_file: the contents of the breakpad-format symbol file
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <windows.h>
#include <dbghelp.h>
#include <wininet.h>