aboutsummaryrefslogtreecommitdiff
path: root/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/linux/core2md/core2md.cc9
-rw-r--r--src/tools/linux/core_handler/core_handler.cc147
-rw-r--r--src/tools/linux/dump_syms/dump_syms.cc30
-rw-r--r--src/tools/linux/md2core/minidump-2-core.cc120
-rw-r--r--src/tools/linux/md2core/minidump_memory_range.h5
-rw-r--r--src/tools/linux/md2core/minidump_memory_range_unittest.cc5
-rw-r--r--src/tools/linux/pid2md/pid2md.cc58
-rw-r--r--src/tools/linux/symupload/minidump_upload.cc14
-rw-r--r--src/tools/linux/symupload/sym_upload.cc25
-rw-r--r--src/tools/linux/tools_linux.gypi83
-rw-r--r--src/tools/mac/crash_report/crash_report.mm408
-rw-r--r--src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj618
-rw-r--r--src/tools/mac/crash_report/on_demand_symbol_supplier.h111
-rw-r--r--src/tools/mac/crash_report/on_demand_symbol_supplier.mm314
-rw-r--r--src/tools/mac/dump_syms/dump_syms_tool.cc104
-rw-r--r--src/tools/mac/dump_syms/macho_dump.cc37
-rw-r--r--src/tools/mac/symupload/minidump_upload.m135
-rw-r--r--src/tools/mac/symupload/symupload.m204
-rw-r--r--src/tools/mac/symupload/symupload.mm474
-rw-r--r--src/tools/mac/symupload/symupload.xcodeproj/project.pbxproj230
-rw-r--r--src/tools/mac/tools_mac.gypi116
-rw-r--r--src/tools/mac/upload_system_symbols/arch_constants.h5
-rw-r--r--src/tools/mac/upload_system_symbols/arch_reader.go5
-rw-r--r--src/tools/mac/upload_system_symbols/go.mod3
-rw-r--r--src/tools/mac/upload_system_symbols/upload_system_symbols.go45
-rwxr-xr-xsrc/tools/python/deps-to-manifest.py9
-rw-r--r--src/tools/python/filter_syms.py5
-rw-r--r--src/tools/python/tests/filter_syms_unittest.py5
-rw-r--r--src/tools/solaris/dump_syms/Makefile5
-rw-r--r--src/tools/solaris/dump_syms/dump_syms.cc9
-rw-r--r--src/tools/solaris/dump_syms/run_regtest.sh5
-rw-r--r--src/tools/solaris/dump_syms/testdata/dump_syms_regtest.cc11
-rw-r--r--src/tools/tools.gyp38
-rw-r--r--src/tools/windows/converter/ms_symbol_server_converter.cc130
-rw-r--r--src/tools/windows/converter/ms_symbol_server_converter.gyp46
-rw-r--r--src/tools/windows/converter/ms_symbol_server_converter.h59
-rw-r--r--src/tools/windows/converter_exe/converter.cc1711
-rw-r--r--src/tools/windows/converter_exe/converter.gyp57
-rw-r--r--src/tools/windows/converter_exe/escaping.cc1514
-rw-r--r--src/tools/windows/converter_exe/escaping.h198
-rw-r--r--src/tools/windows/converter_exe/http_client.h192
-rw-r--r--src/tools/windows/converter_exe/http_download.cc652
-rw-r--r--src/tools/windows/converter_exe/http_download.h124
-rw-r--r--src/tools/windows/converter_exe/tokenizer.cc122
-rw-r--r--src/tools/windows/converter_exe/tokenizer.h102
-rw-r--r--src/tools/windows/converter_exe/winhttp_client.cc614
-rw-r--r--src/tools/windows/converter_exe/winhttp_client.h80
-rw-r--r--src/tools/windows/converter_exe/wininet_client.cc556
-rw-r--r--src/tools/windows/converter_exe/wininet_client.h80
-rw-r--r--src/tools/windows/dump_syms/dump_syms.cc63
-rw-r--r--src/tools/windows/dump_syms/dump_syms.gyp64
-rw-r--r--src/tools/windows/dump_syms/dump_syms_unittest.cc488
-rwxr-xr-xsrc/tools/windows/dump_syms/run_regtest.sh5
-rw-r--r--src/tools/windows/dump_syms/testdata/dump_syms_regtest.cc11
-rw-r--r--src/tools/windows/symupload/symupload.cc152
-rw-r--r--src/tools/windows/symupload/symupload.gyp50
-rw-r--r--src/tools/windows/tools_windows.gyp46
57 files changed, 4664 insertions, 5844 deletions
diff --git a/src/tools/linux/core2md/core2md.cc b/src/tools/linux/core2md/core2md.cc
index c3a9da39..3f34294f 100644
--- a/src/tools/linux/core2md/core2md.cc
+++ b/src/tools/linux/core2md/core2md.cc
@@ -1,5 +1,4 @@
-// Copyright (c) 2012, Google Inc.
-// All rights reserved.
+// Copyright 2012 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -11,7 +10,7 @@
// 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 Inc. nor the names of its
+// * 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.
//
@@ -33,13 +32,15 @@
#include "client/linux/minidump_writer/minidump_writer.h"
#include "client/linux/minidump_writer/linux_core_dumper.h"
+#include "common/path_helper.h"
using google_breakpad::AppMemoryList;
using google_breakpad::MappingList;
using google_breakpad::LinuxCoreDumper;
static int ShowUsage(const char* argv0) {
- fprintf(stderr, "Usage: %s <core file> <procfs dir> <output>\n", argv0);
+ fprintf(stderr, "Usage: %s <core file> <procfs dir> <output>\n",
+ google_breakpad::BaseName(argv0).c_str());
return 1;
}
diff --git a/src/tools/linux/core_handler/core_handler.cc b/src/tools/linux/core_handler/core_handler.cc
new file mode 100644
index 00000000..224073d3
--- /dev/null
+++ b/src/tools/linux/core_handler/core_handler.cc
@@ -0,0 +1,147 @@
+// Copyright 2020 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.
+
+// core_handler.cc: A tool to handle coredumps on Linux
+
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <sstream>
+
+#include "client/linux/minidump_writer/linux_core_dumper.h"
+#include "client/linux/minidump_writer/minidump_writer.h"
+#include "common/path_helper.h"
+#include "common/scoped_ptr.h"
+
+namespace {
+
+using google_breakpad::AppMemoryList;
+using google_breakpad::LinuxCoreDumper;
+using google_breakpad::MappingList;
+using google_breakpad::scoped_array;
+
+// Size of the core dump to read in order to access all the threads
+// descriptions.
+//
+// The first section is the note0 section which contains the thread states. On
+// x86-64 a typical thread description take about 1432B. Reading 1 MB allows
+// several hundreds of threads.
+const int core_read_size = 1024 * 1024;
+
+void ShowUsage(const char* argv0) {
+ fprintf(stderr, "Usage: %s <process id> <minidump file>\n\n",
+ google_breakpad::BaseName(argv0).c_str());
+ fprintf(stderr,
+ "A tool which serves as a core dump handler and produces "
+ "minidump files.\n");
+ fprintf(stderr, "Please refer to the online documentation:\n");
+ fprintf(stderr,
+ "https://chromium.googlesource.com/breakpad/breakpad/+/HEAD"
+ "/docs/linux_core_handler.md\n");
+}
+
+bool WriteMinidumpFromCore(const char* filename,
+ const char* core_path,
+ const char* procfs_override) {
+ MappingList mappings;
+ AppMemoryList memory_list;
+ LinuxCoreDumper dumper(0, core_path, procfs_override);
+ return google_breakpad::WriteMinidump(filename, mappings, memory_list,
+ &dumper);
+}
+
+bool HandleCrash(pid_t pid, const char* procfs_dir, const char* md_filename) {
+ int r = 0;
+ scoped_array<char> buf(new char[core_read_size]);
+ while (r != core_read_size) {
+ int ret = read(STDIN_FILENO, &buf[r], core_read_size - r);
+ if (ret == 0) {
+ break;
+ } else if (ret == -1) {
+ return false;
+ }
+ r += ret;
+ }
+
+ int fd = memfd_create("core_file", MFD_CLOEXEC);
+ if (fd == -1) {
+ return false;
+ }
+
+ int w = write(fd, &buf[0], r);
+ if (w != r) {
+ close(fd);
+ return false;
+ }
+
+ std::stringstream core_file_ss;
+ core_file_ss << "/proc/self/fd/" << fd;
+ std::string core_file(core_file_ss.str());
+
+ if (!WriteMinidumpFromCore(md_filename, core_file.c_str(), procfs_dir)) {
+ close(fd);
+ return false;
+ }
+ close(fd);
+
+ return true;
+}
+
+} // namespace
+
+int main(int argc, char* argv[]) {
+ int ret = EXIT_FAILURE;
+
+ if (argc != 3) {
+ ShowUsage(argv[0]);
+ return ret;
+ }
+
+ const char* pid_str = argv[1];
+ const char* md_filename = argv[2];
+ pid_t pid = atoi(pid_str);
+
+ std::stringstream proc_dir_ss;
+ proc_dir_ss << "/proc/" << pid_str;
+ std::string proc_dir(proc_dir_ss.str());
+
+ openlog("core_handler", 0, 0);
+ if (HandleCrash(pid, proc_dir.c_str(), md_filename)) {
+ syslog(LOG_NOTICE, "Minidump generated at %s\n", md_filename);
+ ret = EXIT_SUCCESS;
+ } else {
+ syslog(LOG_ERR, "Cannot generate minidump %s\n", md_filename);
+ }
+ closelog();
+
+ return ret;
+}
diff --git a/src/tools/linux/dump_syms/dump_syms.cc b/src/tools/linux/dump_syms/dump_syms.cc
index ebdf2314..8998b3b3 100644
--- a/src/tools/linux/dump_syms/dump_syms.cc
+++ b/src/tools/linux/dump_syms/dump_syms.cc
@@ -1,5 +1,4 @@
-// Copyright (c) 2011, Google Inc.
-// All rights reserved.
+// Copyright 2011 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -11,7 +10,7 @@
// 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 Inc. nor the names of its
+// * 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.
//
@@ -37,32 +36,41 @@
#include <vector>
#include "common/linux/dump_symbols.h"
+#include "common/path_helper.h"
using google_breakpad::WriteSymbolFile;
using google_breakpad::WriteSymbolFileHeader;
int usage(const char* self) {
- fprintf(stderr, "Usage: %s [OPTION] <binary-with-debugging-info> "
- "[directories-for-debug-file]\n\n", self);
+ fprintf(stderr,
+ "Usage: %s [OPTION] <binary-with-debugging-info> "
+ "[directories-for-debug-file]\n\n",
+ google_breakpad::BaseName(self).c_str());
fprintf(stderr, "Options:\n");
fprintf(stderr, " -i: Output module header information only.\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, " -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"
+ "and PUBLIC, denoting multiple symbols for "
+ "the address.\n");
return 1;
}
-int main(int argc, char **argv) {
+int main(int argc, char** argv) {
if (argc < 2)
return usage(argv[0]);
bool header_only = false;
bool cfi = true;
+ bool handle_inlines = false;
bool handle_inter_cu_refs = true;
bool log_to_stderr = false;
+ bool enable_multiple_field = false;
std::string obj_name;
const char* obj_os = "Linux";
int arg_index = 1;
@@ -72,6 +80,8 @@ int main(int argc, char **argv) {
header_only = true;
} else if (strcmp("-c", argv[arg_index]) == 0) {
cfi = false;
+ } else if (strcmp("-d", argv[arg_index]) == 0) {
+ handle_inlines = true;
} else if (strcmp("-r", argv[arg_index]) == 0) {
handle_inter_cu_refs = false;
} else if (strcmp("-v", argv[arg_index]) == 0) {
@@ -90,6 +100,8 @@ int main(int argc, char **argv) {
}
obj_os = argv[arg_index + 1];
++arg_index;
+ } else if (strcmp("-m", argv[arg_index]) == 0) {
+ enable_multiple_field = true;
} else {
printf("2.4 %s\n", argv[arg_index]);
return usage(argv[0]);
@@ -124,8 +136,10 @@ int main(int argc, char **argv) {
return 1;
}
} else {
- SymbolData symbol_data = cfi ? ALL_SYMBOL_DATA : NO_CFI;
- google_breakpad::DumpOptions options(symbol_data, handle_inter_cu_refs);
+ 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,
std::cout)) {
fprintf(saved_stderr, "Failed to write symbol file.\n");
diff --git a/src/tools/linux/md2core/minidump-2-core.cc b/src/tools/linux/md2core/minidump-2-core.cc
index a60be323..a4ddbe8e 100644
--- a/src/tools/linux/md2core/minidump-2-core.cc
+++ b/src/tools/linux/md2core/minidump-2-core.cc
@@ -1,5 +1,4 @@
-// Copyright (c) 2009, Google Inc.
-// All rights reserved.
+// Copyright 2009 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -11,7 +10,7 @@
// 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 Inc. nor the names of its
+// * 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.
//
@@ -77,6 +76,8 @@
#define ELF_ARCH EM_MIPS
#elif defined(__aarch64__)
#define ELF_ARCH EM_AARCH64
+#elif defined(__riscv)
+ #define ELF_ARCH EM_RISCV
#endif
#if defined(__arm__)
@@ -84,7 +85,7 @@
// containing core registers, while they use 'user_regs_struct' on other
// architectures. This file-local typedef simplifies the source code.
typedef user_regs user_regs_struct;
-#elif defined (__mips__)
+#elif defined (__mips__) || defined(__riscv)
// This file-local typedef simplifies the source code.
typedef gregset_t user_regs_struct;
#endif
@@ -149,16 +150,14 @@ SetupOptions(int argc, const char* argv[], Options* options) {
options->use_filename = false;
options->inc_guid = false;
- while ((ch = getopt(argc, (char * const *)argv, "fhio:S:v")) != -1) {
+ while ((ch = getopt(argc, (char * const*)argv, "fhio:S:v")) != -1) {
switch (ch) {
case 'h':
Usage(argc, argv);
exit(0);
- break;
case '?':
Usage(argc, argv);
exit(1);
- break;
case 'f':
options->use_filename = true;
@@ -224,7 +223,7 @@ writea(int fd, const void* idata, size_t length) {
*/
static inline int sex() {
int probe = 1;
- return !*(char *)&probe;
+ return !*(char*)&probe;
}
typedef struct elf_timeval { /* Time value with microsecond resolution */
@@ -261,7 +260,7 @@ typedef struct prpsinfo { /* Information about process */
unsigned char pr_zomb; /* Zombie */
signed char pr_nice; /* Nice val */
unsigned long pr_flag; /* Flags */
-#if defined(__x86_64__) || defined(__mips__)
+#if defined(__x86_64__) || defined(__mips__) || defined(__riscv)
uint32_t pr_uid; /* User ID */
uint32_t pr_gid; /* Group ID */
#else
@@ -308,7 +307,7 @@ struct CrashedProcess {
struct Thread {
pid_t tid;
-#if defined(__mips__)
+#if defined(__mips__) || defined(__riscv)
mcontext_t mcontext;
#else
user_regs_struct regs;
@@ -535,6 +534,71 @@ ParseThreadRegisters(CrashedProcess::Thread* thread,
thread->mcontext.fpc_eir = rawregs->float_save.fir;
#endif
}
+#elif defined(__riscv)
+static void
+ParseThreadRegisters(CrashedProcess::Thread* thread,
+ const MinidumpMemoryRange& range) {
+# if __riscv_xlen == 32
+ const MDRawContextRISCV* rawregs = range.GetData<MDRawContextRISCV>(0);
+# elif __riscv_xlen == 64
+ const MDRawContextRISCV64* rawregs = range.GetData<MDRawContextRISCV64>(0);
+# else
+# error "Unexpected __riscv_xlen"
+# endif
+
+ thread->mcontext.__gregs[0] = rawregs->pc;
+ thread->mcontext.__gregs[1] = rawregs->ra;
+ thread->mcontext.__gregs[2] = rawregs->sp;
+ thread->mcontext.__gregs[3] = rawregs->gp;
+ thread->mcontext.__gregs[4] = rawregs->tp;
+ thread->mcontext.__gregs[5] = rawregs->t0;
+ thread->mcontext.__gregs[6] = rawregs->t1;
+ thread->mcontext.__gregs[7] = rawregs->t2;
+ thread->mcontext.__gregs[8] = rawregs->s0;
+ thread->mcontext.__gregs[9] = rawregs->s1;
+ thread->mcontext.__gregs[10] = rawregs->a0;
+ thread->mcontext.__gregs[11] = rawregs->a1;
+ thread->mcontext.__gregs[12] = rawregs->a2;
+ thread->mcontext.__gregs[13] = rawregs->a3;
+ thread->mcontext.__gregs[14] = rawregs->a4;
+ thread->mcontext.__gregs[15] = rawregs->a5;
+ thread->mcontext.__gregs[16] = rawregs->a6;
+ thread->mcontext.__gregs[17] = rawregs->a7;
+ thread->mcontext.__gregs[18] = rawregs->s2;
+ thread->mcontext.__gregs[19] = rawregs->s3;
+ thread->mcontext.__gregs[20] = rawregs->s4;
+ thread->mcontext.__gregs[21] = rawregs->s5;
+ thread->mcontext.__gregs[22] = rawregs->s6;
+ thread->mcontext.__gregs[23] = rawregs->s7;
+ thread->mcontext.__gregs[24] = rawregs->s8;
+ thread->mcontext.__gregs[25] = rawregs->s9;
+ thread->mcontext.__gregs[26] = rawregs->s10;
+ thread->mcontext.__gregs[27] = rawregs->s11;
+ thread->mcontext.__gregs[28] = rawregs->t3;
+ thread->mcontext.__gregs[29] = rawregs->t4;
+ 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];
+ }
+ 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.__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
+}
#else
#error "This code has not been ported to your platform yet"
#endif
@@ -602,7 +666,8 @@ ParseSystemInfo(const Options& options, CrashedProcess* crashinfo,
exit(1);
}
#elif defined(__aarch64__)
- if (sysinfo->processor_architecture != MD_CPU_ARCHITECTURE_ARM64_OLD) {
+ if (sysinfo->processor_architecture != MD_CPU_ARCHITECTURE_ARM64_OLD &&
+ sysinfo->processor_architecture != MD_CPU_ARCHITECTURE_ARM64) {
fprintf(stderr,
"This version of minidump-2-core only supports ARM (64bit).\n");
exit(1);
@@ -623,11 +688,26 @@ ParseSystemInfo(const Options& options, CrashedProcess* crashinfo,
# else
# error "This mips ABI is currently not supported (n32)"
# endif
+#elif defined(__riscv)
+# if __riscv_xlen == 32
+ if (sysinfo->processor_architecture != MD_CPU_ARCHITECTURE_RISCV) {
+ fprintf(stderr,
+ "This version of minidump-2-core only supports RISCV.\n");
+ exit(1);
+ }
+# elif __riscv_xlen == 64
+ if (sysinfo->processor_architecture != MD_CPU_ARCHITECTURE_RISCV64) {
+ fprintf(stderr,
+ "This version of minidump-2-core only supports RISCV64.\n");
+ exit(1);
+ }
+# else
+# error "Unexpected __riscv_xlen"
+# endif
#else
#error "This code has not been ported to your platform yet"
#endif
- if (!strstr(full_file.GetAsciiMDString(sysinfo->csd_version_rva).c_str(),
- "Linux") &&
+ if (sysinfo->platform_id != MD_OS_LINUX &&
sysinfo->platform_id != MD_OS_NACL) {
fprintf(stderr, "This minidump was not generated by Linux or NaCl.\n");
exit(1);
@@ -651,6 +731,10 @@ ParseSystemInfo(const Options& options, CrashedProcess* crashinfo,
? "MIPS"
: sysinfo->processor_architecture == MD_CPU_ARCHITECTURE_MIPS64
? "MIPS64"
+ : sysinfo->processor_architecture == MD_CPU_ARCHITECTURE_RISCV
+ ? "RISCV"
+ : sysinfo->processor_architecture == MD_CPU_ARCHITECTURE_RISCV64
+ ? "RISCV64"
: "???",
sysinfo->number_of_processors,
sysinfo->processor_level,
@@ -660,10 +744,10 @@ ParseSystemInfo(const Options& options, CrashedProcess* crashinfo,
sysinfo->processor_architecture == MD_CPU_ARCHITECTURE_AMD64) {
fputs("Vendor id: ", stderr);
const char *nul =
- (const char *)memchr(sysinfo->cpu.x86_cpu_info.vendor_id, 0,
+ (const char*)memchr(sysinfo->cpu.x86_cpu_info.vendor_id, 0,
sizeof(sysinfo->cpu.x86_cpu_info.vendor_id));
fwrite(sysinfo->cpu.x86_cpu_info.vendor_id,
- nul ? nul - (const char *)&sysinfo->cpu.x86_cpu_info.vendor_id[0]
+ nul ? nul - (const char*)&sysinfo->cpu.x86_cpu_info.vendor_id[0]
: sizeof(sysinfo->cpu.x86_cpu_info.vendor_id), 1, stderr);
fputs("\n", stderr);
}
@@ -759,7 +843,7 @@ ParseEnvironment(const Options& options, CrashedProcess* crashinfo,
memcpy(env, range.data(), range.length());
int nul_count = 0;
for (char *ptr = env;;) {
- ptr = (char *)memchr(ptr, '\000', range.length() - (ptr - env));
+ ptr = (char*)memchr(ptr, '\000', range.length() - (ptr - env));
if (!ptr) {
break;
}
@@ -928,6 +1012,8 @@ WriteThread(const Options& options, const CrashedProcess::Thread& thread,
pr.pr_pid = thread.tid;
#if defined(__mips__)
memcpy(&pr.pr_reg, &thread.mcontext.gregs, sizeof(user_regs_struct));
+#elif defined(__riscv)
+ memcpy(&pr.pr_reg, &thread.mcontext.__gregs, sizeof(user_regs_struct));
#else
memcpy(&pr.pr_reg, &thread.regs, sizeof(user_regs_struct));
#endif
@@ -1076,7 +1162,7 @@ AugmentMappings(const Options& options, CrashedProcess* crashinfo,
for (unsigned i = 0; i < crashinfo->threads.size(); ++i) {
const CrashedProcess::Thread& thread = crashinfo->threads[i];
AddDataToMapping(crashinfo,
- string((char *)thread.stack, thread.stack_length),
+ string((char*)thread.stack, thread.stack_length),
thread.stack_addr);
}
diff --git a/src/tools/linux/md2core/minidump_memory_range.h b/src/tools/linux/md2core/minidump_memory_range.h
index a793e2cf..6cf07470 100644
--- a/src/tools/linux/md2core/minidump_memory_range.h
+++ b/src/tools/linux/md2core/minidump_memory_range.h
@@ -1,5 +1,4 @@
-// Copyright (c) 2011, Google Inc.
-// All rights reserved.
+// Copyright 2011 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -11,7 +10,7 @@
// 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 Inc. nor the names of its
+// * 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.
//
diff --git a/src/tools/linux/md2core/minidump_memory_range_unittest.cc b/src/tools/linux/md2core/minidump_memory_range_unittest.cc
index fe4ded83..9012101d 100644
--- a/src/tools/linux/md2core/minidump_memory_range_unittest.cc
+++ b/src/tools/linux/md2core/minidump_memory_range_unittest.cc
@@ -1,5 +1,4 @@
-// Copyright (c) 2011, Google Inc.
-// All rights reserved.
+// Copyright 2011 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -11,7 +10,7 @@
// 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 Inc. nor the names of its
+// * 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.
//
diff --git a/src/tools/linux/pid2md/pid2md.cc b/src/tools/linux/pid2md/pid2md.cc
new file mode 100644
index 00000000..ca1cb637
--- /dev/null
+++ b/src/tools/linux/pid2md/pid2md.cc
@@ -0,0 +1,58 @@
+// Copyright 2020 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.
+
+// pid2md.cc: An utility to generate a minidump from a running process
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "client/linux/minidump_writer/minidump_writer.h"
+#include "common/path_helper.h"
+
+int main(int argc, char* argv[]) {
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s <process id> <minidump file>\n\n",
+ google_breakpad::BaseName(argv[0]).c_str());
+ fprintf(stderr,
+ "A tool to generate a minidump from a running process. The process "
+ "resumes its\nactivity once the operation is completed. Permission "
+ "to trace the process is\nrequired.\n");
+ return EXIT_FAILURE;
+ }
+
+ pid_t process_id = atoi(argv[1]);
+ const char* minidump_file = argv[2];
+
+ if (!google_breakpad::WriteMinidump(minidump_file, process_id, process_id)) {
+ fprintf(stderr, "Unable to generate minidump.\n");
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/tools/linux/symupload/minidump_upload.cc b/src/tools/linux/symupload/minidump_upload.cc
index 19f17450..6adead03 100644
--- a/src/tools/linux/symupload/minidump_upload.cc
+++ b/src/tools/linux/symupload/minidump_upload.cc
@@ -1,5 +1,4 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
+// Copyright 2006 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -11,7 +10,7 @@
// 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 Inc. nor the names of its
+// * 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.
//
@@ -41,6 +40,7 @@
#include <string>
#include "common/linux/http_upload.h"
+#include "common/path_helper.h"
#include "common/using_std_string.h"
using google_breakpad::HTTPUpload;
@@ -91,8 +91,10 @@ static void Start(Options *options) {
static void
Usage(int argc, const char *argv[]) {
fprintf(stderr, "Submit minidump information.\n");
- fprintf(stderr, "Usage: %s [options...] -p <product> -v <version> <minidump> "
- "<upload-URL>\n", argv[0]);
+ fprintf(stderr,
+ "Usage: %s [options...] -p <product> -v <version> <minidump> "
+ "<upload-URL>\n",
+ google_breakpad::BaseName(argv[0]).c_str());
fprintf(stderr, "Options:\n");
fprintf(stderr, "<minidump> should be a minidump.\n");
fprintf(stderr, "<upload-URL> is the destination for the upload\n");
@@ -111,7 +113,7 @@ SetupOptions(int argc, const char *argv[], Options *options) {
extern int optind;
int ch;
- while ((ch = getopt(argc, (char * const *)argv, "p:u:v:x:h?")) != -1) {
+ while ((ch = getopt(argc, (char * const*)argv, "p:u:v:x:h?")) != -1) {
switch (ch) {
case 'p':
options->product = optarg;
diff --git a/src/tools/linux/symupload/sym_upload.cc b/src/tools/linux/symupload/sym_upload.cc
index f155eb95..8f5e8a50 100644
--- a/src/tools/linux/symupload/sym_upload.cc
+++ b/src/tools/linux/symupload/sym_upload.cc
@@ -1,5 +1,4 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
+// Copyright 2006 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -11,7 +10,7 @@
// 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 Inc. nor the names of its
+// * 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.
//
@@ -47,6 +46,7 @@
#include <locale>
#include "common/linux/symbol_upload.h"
+#include "common/path_helper.h"
using google_breakpad::sym_upload::UploadProtocol;
using google_breakpad::sym_upload::Options;
@@ -66,10 +66,11 @@ static void
Usage(int argc, const char *argv[]) {
fprintf(stderr, "Submit symbol information.\n");
fprintf(stderr, "Usage: %s [options...] <symbol-file> <upload-URL>\n",
- argv[0]);
+ google_breakpad::BaseName(argv[0]).c_str());
fprintf(stderr, "Options:\n");
- fprintf(stderr, "<symbol-file> should be created by using the dump_syms"
- "tool.\n");
+ fprintf(stderr,
+ "<symbol-file> should be created by using the dump_syms "
+ "tool.\n");
fprintf(stderr, "<upload-URL> is the destination for the upload\n");
fprintf(stderr, "-p:\t <protocol> One of ['sym-upload-v1',"
" 'sym-upload-v2'], defaults to 'sym-upload-v1'.\n");
@@ -111,17 +112,20 @@ Usage(int argc, const char *argv[]) {
//=============================================================================
static void
SetupOptions(int argc, const char *argv[], Options *options) {
- extern int optind;
+ extern int optind, optopt;
int ch;
constexpr char flag_pattern[] = "u:v:x:p:k:t:c:i:hf?";
- while ((ch = getopt(argc, (char * const *)argv, flag_pattern)) != -1) {
+ while ((ch = getopt(argc, (char * const*)argv, flag_pattern)) != -1) {
switch (ch) {
case 'h':
case '?':
Usage(argc, argv);
- exit(0);
- break;
+ // ch might be '?' because getopt found an error while parsing args (as
+ // opposed to finding "-?" as an arg), in which case optopt is set to
+ // the bad arg value, so return an error code if optopt is set,
+ // otherwise exit cleanly.
+ exit(optopt == 0 ? 0 : 1);
case 'u':
options->proxy_user_pwd = optarg;
break;
@@ -166,7 +170,6 @@ SetupOptions(int argc, const char *argv[], Options *options) {
fprintf(stderr, "Invalid option '%c'\n", ch);
Usage(argc, argv);
exit(1);
- break;
}
}
diff --git a/src/tools/linux/tools_linux.gypi b/src/tools/linux/tools_linux.gypi
deleted file mode 100644
index 020e4c1c..00000000
--- a/src/tools/linux/tools_linux.gypi
+++ /dev/null
@@ -1,83 +0,0 @@
-# Copyright 2014 Google Inc. All rights reserved.
-#
-# 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 Inc. 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.
-
-{
- 'target_defaults': {
- 'include_dirs': [
- '../..',
- ],
- },
- 'targets': [
- {
- 'target_name': 'dump_syms',
- 'type': 'executable',
- 'sources': [
- 'dump_syms/dump_syms.cc',
- ],
- 'dependencies': [
- '../common/common.gyp:common',
- ],
- },
- {
- 'target_name': 'md2core',
- 'type': 'executable',
- 'sources': [
- 'md2core/minidump-2-core.cc',
- 'md2core/minidump_memory_range.h',
- ],
- 'dependencies': [
- '../common/common.gyp:common',
- ],
- },
- {
- 'target_name': 'minidump_upload',
- 'type': 'executable',
- 'sources': [
- 'symupload/minidump_upload.cc',
- ],
- 'dependencies': [
- '../common/common.gyp:common',
- ],
- },
- {
- 'target_name': 'symupload',
- 'type': 'executable',
- 'sources': [
- 'symupload/sym_upload.cc',
- ],
- 'link_settings': {
- 'libraries': [
- '-ldl',
- ],
- },
- 'dependencies': [
- '../common/common.gyp:common',
- ],
- },
- ],
-}
diff --git a/src/tools/mac/crash_report/crash_report.mm b/src/tools/mac/crash_report/crash_report.mm
deleted file mode 100644
index f68200c7..00000000
--- a/src/tools/mac/crash_report/crash_report.mm
+++ /dev/null
@@ -1,408 +0,0 @@
-// Copyright (c) 2010 Google Inc.
-// All rights reserved.
-//
-// 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 Inc. 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.
-
-// crash_report.mm: Convert the contents of a minidump into a format that
-// looks more like Apple's CrashReporter format
-
-#include <unistd.h>
-
-#include <mach/machine.h>
-#include <mach-o/arch.h>
-
-#include <string>
-
-#include <Foundation/Foundation.h>
-
-#include "common/scoped_ptr.h"
-#include "google_breakpad/processor/basic_source_line_resolver.h"
-#include "google_breakpad/processor/call_stack.h"
-#include "google_breakpad/processor/code_module.h"
-#include "google_breakpad/processor/minidump.h"
-#include "google_breakpad/processor/minidump_processor.h"
-#include "google_breakpad/processor/process_state.h"
-#include "google_breakpad/processor/stack_frame_cpu.h"
-#include "google_breakpad/processor/system_info.h"
-#include "processor/pathname_stripper.h"
-#include "processor/simple_symbol_supplier.h"
-
-#include "on_demand_symbol_supplier.h"
-
-using std::string;
-
-using google_breakpad::BasicSourceLineResolver;
-using google_breakpad::CallStack;
-using google_breakpad::CodeModule;
-using google_breakpad::CodeModules;
-using google_breakpad::Minidump;
-using google_breakpad::MinidumpProcessor;
-using google_breakpad::OnDemandSymbolSupplier;
-using google_breakpad::PathnameStripper;
-using google_breakpad::ProcessState;
-using google_breakpad::scoped_ptr;
-using google_breakpad::StackFrame;
-using google_breakpad::StackFramePPC;
-using google_breakpad::StackFrameX86;
-using google_breakpad::SystemInfo;
-
-typedef struct {
- NSString *minidumpPath;
- NSString *searchDir;
- NSString *symbolSearchDir;
- BOOL printThreadMemory;
-} Options;
-
-//=============================================================================
-static int PrintRegister(const char *name, u_int32_t value, int sequence) {
- if (sequence % 4 == 0) {
- printf("\n");
- }
- printf("%6s = 0x%08x ", name, value);
- return ++sequence;
-}
-
-//=============================================================================
-static void PrintStack(const CallStack *stack, const string &cpu) {
- size_t frame_count = stack->frames()->size();
- char buffer[1024];
- for (size_t frame_index = 0; frame_index < frame_count; ++frame_index) {
- const StackFrame *frame = stack->frames()->at(frame_index);
- const CodeModule *module = frame->module;
- printf("%2zu ", frame_index);
-
- if (module) {
- // Module name (20 chars max)
- strcpy(buffer, PathnameStripper::File(module->code_file()).c_str());
- int maxStr = 20;
- buffer[maxStr] = 0;
- printf("%-*s", maxStr, buffer);
-
- strcpy(buffer, module->version().c_str());
- buffer[maxStr] = 0;
-
- printf("%-*s",maxStr, buffer);
-
- u_int64_t instruction = frame->instruction;
-
- // PPC only: Adjust the instruction to match that of Crash reporter. The
- // instruction listed is actually the return address. See the detailed
- // comments in stackwalker_ppc.cc for more information.
- if (cpu == "ppc" && frame_index)
- instruction += 4;
-
- printf(" 0x%08llx ", instruction);
-
- // Function name
- if (!frame->function_name.empty()) {
- printf("%s", frame->function_name.c_str());
- if (!frame->source_file_name.empty()) {
- string source_file = PathnameStripper::File(frame->source_file_name);
- printf(" + 0x%llx (%s:%d)",
- instruction - frame->source_line_base,
- source_file.c_str(), frame->source_line);
- } else {
- printf(" + 0x%llx", instruction - frame->function_base);
- }
- }
- }
- printf("\n");
- }
-}
-
-//=============================================================================
-static void PrintRegisters(const CallStack *stack, const string &cpu) {
- int sequence = 0;
- const StackFrame *frame = stack->frames()->at(0);
- if (cpu == "x86") {
- const StackFrameX86 *frame_x86 =
- reinterpret_cast<const StackFrameX86*>(frame);
-
- if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EIP)
- sequence = PrintRegister("eip", frame_x86->context.eip, sequence);
- if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESP)
- sequence = PrintRegister("esp", frame_x86->context.esp, sequence);
- if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EBP)
- sequence = PrintRegister("ebp", frame_x86->context.ebp, sequence);
- if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EBX)
- sequence = PrintRegister("ebx", frame_x86->context.ebx, sequence);
- if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESI)
- sequence = PrintRegister("esi", frame_x86->context.esi, sequence);
- if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EDI)
- sequence = PrintRegister("edi", frame_x86->context.edi, sequence);
- if (frame_x86->context_validity == StackFrameX86::CONTEXT_VALID_ALL) {
- sequence = PrintRegister("eax", frame_x86->context.eax, sequence);
- sequence = PrintRegister("ecx", frame_x86->context.ecx, sequence);
- sequence = PrintRegister("edx", frame_x86->context.edx, sequence);
- sequence = PrintRegister("efl", frame_x86->context.eflags, sequence);
- }
- } else if (cpu == "ppc") {
- const StackFramePPC *frame_ppc =
- reinterpret_cast<const StackFramePPC*>(frame);
-
- if ((frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_ALL) ==
- StackFramePPC::CONTEXT_VALID_ALL) {
- sequence = PrintRegister("srr0", frame_ppc->context.srr0, sequence);
- sequence = PrintRegister("srr1", frame_ppc->context.srr1, sequence);
- sequence = PrintRegister("cr", frame_ppc->context.cr, sequence);
- sequence = PrintRegister("xer", frame_ppc->context.xer, sequence);
- sequence = PrintRegister("lr", frame_ppc->context.lr, sequence);
- sequence = PrintRegister("ctr", frame_ppc->context.ctr, sequence);
- sequence = PrintRegister("mq", frame_ppc->context.mq, sequence);
- sequence = PrintRegister("vrsave", frame_ppc->context.vrsave, sequence);
-
- sequence = 0;
- char buffer[5];
- for (int i = 0; i < MD_CONTEXT_PPC_GPR_COUNT; ++i) {
- sprintf(buffer, "r%d", i);
- sequence = PrintRegister(buffer, frame_ppc->context.gpr[i], sequence);
- }
- } else {
- if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_SRR0)
- sequence = PrintRegister("srr0", frame_ppc->context.srr0, sequence);
- if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_GPR1)
- sequence = PrintRegister("r1", frame_ppc->context.gpr[1], sequence);
- }
- }
-
- printf("\n");
-}
-
-static void PrintModules(const CodeModules *modules) {
- if (!modules)
- return;
-
- printf("\n");
- printf("Loaded modules:\n");
-
- u_int64_t main_address = 0;
- const CodeModule *main_module = modules->GetMainModule();
- if (main_module) {
- main_address = main_module->base_address();
- }
-
- unsigned int module_count = modules->module_count();
- for (unsigned int module_sequence = 0;
- module_sequence < module_count;
- ++module_sequence) {
- const CodeModule *module = modules->GetModuleAtSequence(module_sequence);
- assert(module);
- u_int64_t base_address = module->base_address();
- printf("0x%08llx - 0x%08llx %s %s%s %s\n",
- base_address, base_address + module->size() - 1,
- PathnameStripper::File(module->code_file()).c_str(),
- module->version().empty() ? "???" : module->version().c_str(),
- main_module != NULL && base_address == main_address ?
- " (main)" : "",
- module->code_file().c_str());
- }
-}
-
-static void ProcessSingleReport(Options *options, NSString *file_path) {
- string minidump_file([file_path fileSystemRepresentation]);
- BasicSourceLineResolver resolver;
- string search_dir = options->searchDir ?
- [options->searchDir fileSystemRepresentation] : "";
- string symbol_search_dir = options->symbolSearchDir ?
- [options->symbolSearchDir fileSystemRepresentation] : "";
- scoped_ptr<OnDemandSymbolSupplier> symbol_supplier(
- new OnDemandSymbolSupplier(search_dir, symbol_search_dir));
- scoped_ptr<MinidumpProcessor>
- minidump_processor(new MinidumpProcessor(symbol_supplier.get(), &resolver));
- ProcessState process_state;
- scoped_ptr<Minidump> dump(new google_breakpad::Minidump(minidump_file));
-
- if (!dump->Read()) {
- fprintf(stderr, "Minidump %s could not be read\n", dump->path().c_str());
- return;
- }
- if (minidump_processor->Process(dump.get(), &process_state) !=
- google_breakpad::PROCESS_OK) {
- fprintf(stderr, "MinidumpProcessor::Process failed\n");
- return;
- }
-
- const SystemInfo *system_info = process_state.system_info();
- string cpu = system_info->cpu;
-
- // Convert the time to a string
- u_int32_t time_date_stamp = process_state.time_date_stamp();
- struct tm timestruct;
- gmtime_r(reinterpret_cast<time_t*>(&time_date_stamp), &timestruct);
- char timestr[20];
- strftime(timestr, 20, "%Y-%m-%d %H:%M:%S", &timestruct);
- printf("Date: %s GMT\n", timestr);
-
- printf("Operating system: %s (%s)\n", system_info->os.c_str(),
- system_info->os_version.c_str());
- printf("Architecture: %s\n", cpu.c_str());
-
- if (process_state.crashed()) {
- printf("Crash reason: %s\n", process_state.crash_reason().c_str());
- printf("Crash address: 0x%llx\n", process_state.crash_address());
- } else {
- printf("No crash\n");
- }
-
- int requesting_thread = process_state.requesting_thread();
- if (requesting_thread != -1) {
- printf("\n");
- printf("Thread %d (%s)\n",
- requesting_thread,
- process_state.crashed() ? "crashed" :
- "requested dump, did not crash");
- PrintStack(process_state.threads()->at(requesting_thread), cpu);
- }
-
- // Print all of the threads in the dump.
- int thread_count = static_cast<int>(process_state.threads()->size());
- const std::vector<google_breakpad::MemoryRegion*>
- *thread_memory_regions = process_state.thread_memory_regions();
-
- for (int thread_index = 0; thread_index < thread_count; ++thread_index) {
- if (thread_index != requesting_thread) {
- // Don't print the crash thread again, it was already printed.
- printf("\n");
- printf("Thread %d\n", thread_index);
- PrintStack(process_state.threads()->at(thread_index), cpu);
- google_breakpad::MemoryRegion *thread_stack_bytes =
- thread_memory_regions->at(thread_index);
- if (options->printThreadMemory) {
- thread_stack_bytes->Print();
- }
- }
- }
-
- // Print the crashed registers
- if (requesting_thread != -1) {
- printf("\nThread %d:", requesting_thread);
- PrintRegisters(process_state.threads()->at(requesting_thread), cpu);
- }
-
- // Print information about modules
- PrintModules(process_state.modules());
-}
-
-//=============================================================================
-static void Start(Options *options) {
- NSFileManager *manager = [NSFileManager defaultManager];
- NSString *minidump_path = options->minidumpPath;
- BOOL is_dir = NO;
- BOOL file_exists = [manager fileExistsAtPath:minidump_path
- isDirectory:&is_dir];
- if (file_exists && is_dir) {
- NSDirectoryEnumerator *enumerator =
- [manager enumeratorAtPath:minidump_path];
- NSString *current_file = nil;
- while ((current_file = [enumerator nextObject])) {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- if ([[current_file pathExtension] isEqualTo:@"dmp"]) {
- printf("Attempting to process report: %s\n",
- [current_file cStringUsingEncoding:NSASCIIStringEncoding]);
- NSString *full_path =
- [minidump_path stringByAppendingPathComponent:current_file];
- ProcessSingleReport(options, full_path);
- }
- [pool release];
- }
- } else if (file_exists) {
- ProcessSingleReport(options, minidump_path);
- }
-}
-
-//=============================================================================
-static void Usage(int argc, const char *argv[]) {
- fprintf(stderr, "Convert a minidump to a crash report. Breakpad symbol "
- "files will be used (or created if missing) in /tmp.\n"
- "If a symbol-file-search-dir is specified, any symbol "
- "files in it will be used instead of being loaded from "
- "modules on disk.\n"
- "If modules cannot be found at the paths stored in the "
- "minidump file, they will be searched for at "
- "<module-search-dir>/<path-in-minidump-file>.\n");
- fprintf(stderr, "Usage: %s [-s module-search-dir] [-S symbol-file-search-dir] "
- "minidump-file\n", argv[0]);
- fprintf(stderr, "\t-s: Specify a search directory to use for missing modules\n"
- "\t-S: Specify a search directory to use for symbol files\n"
- "\t-t: Print thread stack memory in hex\n"
- "\t-h: Usage\n"
- "\t-?: Usage\n");
-}
-
-//=============================================================================
-static void SetupOptions(int argc, const char *argv[], Options *options) {
- extern int optind;
- char ch;
-
- while ((ch = getopt(argc, (char * const *)argv, "S:s:ht?")) != -1) {
- switch (ch) {
- case 's':
- options->searchDir = [[NSFileManager defaultManager]
- stringWithFileSystemRepresentation:optarg
- length:strlen(optarg)];
- break;
-
- case 'S':
- options->symbolSearchDir = [[NSFileManager defaultManager]
- stringWithFileSystemRepresentation:optarg
- length:strlen(optarg)];
- break;
-
- case 't':
- options->printThreadMemory = YES;
- break;
- case 'h':
- case '?':
- Usage(argc, argv);
- exit(1);
- break;
- }
- }
-
- if ((argc - optind) != 1) {
- fprintf(stderr, "%s: Missing minidump file\n", argv[0]);
- Usage(argc, argv);
- exit(1);
- }
-
- options->minidumpPath = [[NSFileManager defaultManager]
- stringWithFileSystemRepresentation:argv[optind]
- length:strlen(argv[optind])];
-}
-
-//=============================================================================
-int main (int argc, const char * argv[]) {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- Options options;
-
- bzero(&options, sizeof(Options));
- SetupOptions(argc, argv, &options);
- Start(&options);
- [pool release];
-
- return 0;
-}
diff --git a/src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj b/src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj
deleted file mode 100644
index 33204f7e..00000000
--- a/src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj
+++ /dev/null
@@ -1,618 +0,0 @@
-// !$*UTF8*$!
-{
- archiveVersion = 1;
- classes = {
- };
- objectVersion = 45;
- objects = {
-
-/* Begin PBXBuildFile section */
- 162F64FE161C5ECB00CD68D5 /* arch_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 162F64FC161C5ECB00CD68D5 /* arch_utilities.cc */; };
- 4214B800211109A600B769FA /* convert_old_arm64_context.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4214B7FE211109A600B769FA /* convert_old_arm64_context.cc */; };
- 4247E6402110D5A500482558 /* path_helper.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4247E63F2110D5A500482558 /* path_helper.cc */; };
- 4D2C721B126F9ACC00B43EAF /* source_line_resolver_base.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C721A126F9ACC00B43EAF /* source_line_resolver_base.cc */; };
- 4D2C721F126F9ADE00B43EAF /* exploitability.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C721E126F9ADE00B43EAF /* exploitability.cc */; };
- 4D2C7223126F9AF900B43EAF /* exploitability_win.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C7222126F9AF900B43EAF /* exploitability_win.cc */; };
- 4D2C7227126F9B0F00B43EAF /* disassembler_x86.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C7226126F9B0F00B43EAF /* disassembler_x86.cc */; };
- 4D2C722B126F9B5A00B43EAF /* x86_disasm.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C722A126F9B5A00B43EAF /* x86_disasm.c */; };
- 4D2C722D126F9B6E00B43EAF /* x86_misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C722C126F9B6E00B43EAF /* x86_misc.c */; };
- 4D2C722F126F9B8300B43EAF /* x86_operand_list.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C722E126F9B8300B43EAF /* x86_operand_list.c */; };
- 4D2C7233126F9BB000B43EAF /* ia32_invariant.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C7232126F9BB000B43EAF /* ia32_invariant.c */; settings = {COMPILER_FLAGS = "-Wno-error"; }; };
- 4D2C7235126F9BC200B43EAF /* ia32_settings.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C7234126F9BC200B43EAF /* ia32_settings.c */; };
- 4D2C7246126F9C0B00B43EAF /* ia32_insn.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C7245126F9C0B00B43EAF /* ia32_insn.c */; };
- 4D2C724A126F9C2300B43EAF /* ia32_opcode_tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C7249126F9C2300B43EAF /* ia32_opcode_tables.c */; settings = {COMPILER_FLAGS = "-Wno-error"; }; };
- 4D2C724C126F9C3800B43EAF /* ia32_implicit.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C724B126F9C3800B43EAF /* ia32_implicit.c */; settings = {COMPILER_FLAGS = "-Wno-error"; }; };
- 4D2C724E126F9C4D00B43EAF /* ia32_reg.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C724D126F9C4D00B43EAF /* ia32_reg.c */; settings = {COMPILER_FLAGS = "-Wno-error"; }; };
- 4D2C725B126F9C8000B43EAF /* ia32_operand.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C725A126F9C8000B43EAF /* ia32_operand.c */; };
- 4D2C725D126F9C9200B43EAF /* x86_insn.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C725C126F9C9200B43EAF /* x86_insn.c */; };
- 4D2C7264126F9CBB00B43EAF /* ia32_modrm.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C7261126F9CBB00B43EAF /* ia32_modrm.c */; };
- 4D2C726D126F9CDC00B43EAF /* x86_imm.c in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C7263126F9CBB00B43EAF /* x86_imm.c */; };
- 4D72CA5713DFBA84006CABE3 /* md5.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D72CA5613DFBA84006CABE3 /* md5.cc */; };
- 557800400BE1F28500EC23E0 /* macho_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5578003E0BE1F28500EC23E0 /* macho_utilities.cc */; };
- 8B31FF2A11F0C62700FCF3E4 /* dwarf_cfi_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B31FF2411F0C62700FCF3E4 /* dwarf_cfi_to_module.cc */; };
- 8B31FF2B11F0C62700FCF3E4 /* dwarf_cu_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B31FF2611F0C62700FCF3E4 /* dwarf_cu_to_module.cc */; };
- 8B31FF2C11F0C62700FCF3E4 /* dwarf_line_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B31FF2811F0C62700FCF3E4 /* dwarf_line_to_module.cc */; };
- 8B31FF4111F0C64400FCF3E4 /* stabs_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B31FF3D11F0C64400FCF3E4 /* stabs_reader.cc */; };
- 8B31FF4211F0C64400FCF3E4 /* stabs_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B31FF3F11F0C64400FCF3E4 /* stabs_to_module.cc */; };
- 8B31FF7411F0C6E000FCF3E4 /* macho_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B31FF7211F0C6E000FCF3E4 /* macho_reader.cc */; };
- 8B31FF8811F0C6FB00FCF3E4 /* language.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B31FF8411F0C6FB00FCF3E4 /* language.cc */; };
- 8B31FF8911F0C6FB00FCF3E4 /* module.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B31FF8611F0C6FB00FCF3E4 /* module.cc */; };
- 8B31FFC511F0C8AB00FCF3E4 /* dwarf2diehandler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B31FFC311F0C8AB00FCF3E4 /* dwarf2diehandler.cc */; };
- 8B40BDC00C0638E4009535AF /* logging.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8B40BDBF0C0638E4009535AF /* logging.cc */; };
- 8DD76F9A0486AA7600D96B5E /* crash_report.mm in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* crash_report.mm */; settings = {ATTRIBUTES = (); }; };
- 8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; };
- 9B35FEEA0B26761C008DE8C7 /* basic_code_modules.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9B35FEE70B26761C008DE8C7 /* basic_code_modules.cc */; };
- 9B3904990B2E52FD0059FABE /* basic_source_line_resolver.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9B3904980B2E52FD0059FABE /* basic_source_line_resolver.cc */; };
- 9BDF172C0B1B8B2400F8391B /* call_stack.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF172A0B1B8B2400F8391B /* call_stack.cc */; };
- 9BDF172D0B1B8B2400F8391B /* minidump_processor.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF172B0B1B8B2400F8391B /* minidump_processor.cc */; };
- 9BDF17410B1B8B9A00F8391B /* minidump.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF173F0B1B8B9A00F8391B /* minidump.cc */; };
- 9BDF17540B1B8BF900F8391B /* stackwalker_ppc.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF17510B1B8BF900F8391B /* stackwalker_ppc.cc */; };
- 9BDF17550B1B8BF900F8391B /* stackwalker_x86.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF17520B1B8BF900F8391B /* stackwalker_x86.cc */; };
- 9BDF17560B1B8BF900F8391B /* stackwalker.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF17530B1B8BF900F8391B /* stackwalker.cc */; };
- 9BDF175D0B1B8C1B00F8391B /* process_state.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF175B0B1B8C1B00F8391B /* process_state.cc */; };
- 9BDF176E0B1B8CB100F8391B /* on_demand_symbol_supplier.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF176C0B1B8CB100F8391B /* on_demand_symbol_supplier.mm */; };
- 9BDF1A280B1BD58200F8391B /* pathname_stripper.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF1A270B1BD58200F8391B /* pathname_stripper.cc */; };
- 9BDF21A70B1E825400F8391B /* dump_syms.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BDF192E0B1BC15D00F8391B /* dump_syms.cc */; };
- 9BE650B20B52FE3000611104 /* file_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BE650AC0B52FE3000611104 /* file_id.cc */; };
- 9BE650B40B52FE3000611104 /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BE650AE0B52FE3000611104 /* macho_id.cc */; };
- 9BE650B60B52FE3000611104 /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9BE650B00B52FE3000611104 /* macho_walker.cc */; };
- D2A5DD4D1188651100081F03 /* cfi_frame_info.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2A5DD4C1188651100081F03 /* cfi_frame_info.cc */; };
- D2A5DD631188658B00081F03 /* tokenize.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2A5DD621188658B00081F03 /* tokenize.cc */; };
- F407DC48185773C10064622B /* exploitability_linux.cc in Sources */ = {isa = PBXBuildFile; fileRef = F407DC40185773C10064622B /* exploitability_linux.cc */; };
- F407DC49185773C10064622B /* stack_frame_symbolizer.cc in Sources */ = {isa = PBXBuildFile; fileRef = F407DC41185773C10064622B /* stack_frame_symbolizer.cc */; };
- F407DC4A185773C10064622B /* stackwalker_arm64.cc in Sources */ = {isa = PBXBuildFile; fileRef = F407DC42185773C10064622B /* stackwalker_arm64.cc */; };
- F407DC4B185773C10064622B /* stackwalker_mips.cc in Sources */ = {isa = PBXBuildFile; fileRef = F407DC44185773C10064622B /* stackwalker_mips.cc */; };
- F407DC4C185773C10064622B /* stackwalker_ppc64.cc in Sources */ = {isa = PBXBuildFile; fileRef = F407DC46185773C10064622B /* stackwalker_ppc64.cc */; };
- F44DDD8719C85CD50047280E /* dump_context.cc in Sources */ = {isa = PBXBuildFile; fileRef = F44DDD8419C85CD50047280E /* dump_context.cc */; };
- F44DDD8819C85CD50047280E /* dump_object.cc in Sources */ = {isa = PBXBuildFile; fileRef = F44DDD8519C85CD50047280E /* dump_object.cc */; };
- F44DDD8919C85CD50047280E /* microdump_processor.cc in Sources */ = {isa = PBXBuildFile; fileRef = F44DDD8619C85CD50047280E /* microdump_processor.cc */; };
- F47180561D745DEF0032F208 /* elf_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F47180541D745DEF0032F208 /* elf_reader.cc */; };
- F47180581D7467630032F208 /* proc_maps_linux.cc in Sources */ = {isa = PBXBuildFile; fileRef = F47180571D7467630032F208 /* proc_maps_linux.cc */; };
- F471805A1D7468A40032F208 /* symbolic_constants_win.cc in Sources */ = {isa = PBXBuildFile; fileRef = F47180591D7468A40032F208 /* symbolic_constants_win.cc */; };
- F4D43B2F1A38490700C290B2 /* microdump.cc in Sources */ = {isa = PBXBuildFile; fileRef = F4D43B2E1A38490700C290B2 /* microdump.cc */; };
- F9C7ECE50E8ABCA600E953AD /* bytereader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9C7ECE20E8ABCA600E953AD /* bytereader.cc */; };
- F9C7ECE60E8ABCA600E953AD /* dwarf2reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9C7ECE30E8ABCA600E953AD /* dwarf2reader.cc */; };
- F9C7ECE70E8ABCA600E953AD /* functioninfo.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9C7ECE40E8ABCA600E953AD /* functioninfo.cc */; };
- F9F0706710FBC02D0037B88B /* stackwalker_arm.cc in Sources */ = {isa = PBXBuildFile; fileRef = F9F0706510FBC02D0037B88B /* stackwalker_arm.cc */; };
- FD6625CD0CF4D45C004AC844 /* stackwalker_amd64.cc in Sources */ = {isa = PBXBuildFile; fileRef = FD6625C40CF4D438004AC844 /* stackwalker_amd64.cc */; };
- FD8EDEAE0CADDAD400A5EDF1 /* stackwalker_sparc.cc in Sources */ = {isa = PBXBuildFile; fileRef = FD8EDEAC0CADDAD400A5EDF1 /* stackwalker_sparc.cc */; };
-/* End PBXBuildFile section */
-
-/* Begin PBXFileReference section */
- 08FB7796FE84155DC02AAC07 /* crash_report.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = crash_report.mm; sourceTree = "<group>"; };
- 08FB779EFE84155DC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
- 162F64FC161C5ECB00CD68D5 /* arch_utilities.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = arch_utilities.cc; path = ../../../common/mac/arch_utilities.cc; sourceTree = "<group>"; };
- 162F64FD161C5ECB00CD68D5 /* arch_utilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = arch_utilities.h; path = ../../../common/mac/arch_utilities.h; sourceTree = "<group>"; };
- 4214B7FE211109A600B769FA /* convert_old_arm64_context.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = convert_old_arm64_context.cc; path = ../../../processor/convert_old_arm64_context.cc; sourceTree = "<group>"; };
- 4214B7FF211109A600B769FA /* convert_old_arm64_context.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = convert_old_arm64_context.h; path = ../../../processor/convert_old_arm64_context.h; sourceTree = "<group>"; };
- 4247E63E2110D5A500482558 /* path_helper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = path_helper.h; path = ../../../common/path_helper.h; sourceTree = "<group>"; };
- 4247E63F2110D5A500482558 /* path_helper.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = path_helper.cc; path = ../../../common/path_helper.cc; sourceTree = "<group>"; };
- 4D2C721A126F9ACC00B43EAF /* source_line_resolver_base.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = source_line_resolver_base.cc; path = ../../../processor/source_line_resolver_base.cc; sourceTree = SOURCE_ROOT; };
- 4D2C721E126F9ADE00B43EAF /* exploitability.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = exploitability.cc; path = ../../../processor/exploitability.cc; sourceTree = SOURCE_ROOT; };
- 4D2C7222126F9AF900B43EAF /* exploitability_win.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = exploitability_win.cc; path = ../../../processor/exploitability_win.cc; sourceTree = SOURCE_ROOT; };
- 4D2C7226126F9B0F00B43EAF /* disassembler_x86.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = disassembler_x86.cc; path = ../../../processor/disassembler_x86.cc; sourceTree = SOURCE_ROOT; };
- 4D2C722A126F9B5A00B43EAF /* x86_disasm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = x86_disasm.c; path = ../../../third_party/libdisasm/x86_disasm.c; sourceTree = SOURCE_ROOT; };
- 4D2C722C126F9B6E00B43EAF /* x86_misc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = x86_misc.c; path = ../../../third_party/libdisasm/x86_misc.c; sourceTree = SOURCE_ROOT; };
- 4D2C722E126F9B8300B43EAF /* x86_operand_list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = x86_operand_list.c; path = ../../../third_party/libdisasm/x86_operand_list.c; sourceTree = SOURCE_ROOT; };
- 4D2C7232126F9BB000B43EAF /* ia32_invariant.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ia32_invariant.c; path = ../../../third_party/libdisasm/ia32_invariant.c; sourceTree = SOURCE_ROOT; };
- 4D2C7234126F9BC200B43EAF /* ia32_settings.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ia32_settings.c; path = ../../../third_party/libdisasm/ia32_settings.c; sourceTree = SOURCE_ROOT; };
- 4D2C7245126F9C0B00B43EAF /* ia32_insn.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ia32_insn.c; path = ../../../third_party/libdisasm/ia32_insn.c; sourceTree = SOURCE_ROOT; };
- 4D2C7249126F9C2300B43EAF /* ia32_opcode_tables.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ia32_opcode_tables.c; path = ../../../third_party/libdisasm/ia32_opcode_tables.c; sourceTree = SOURCE_ROOT; };
- 4D2C724B126F9C3800B43EAF /* ia32_implicit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ia32_implicit.c; path = ../../../third_party/libdisasm/ia32_implicit.c; sourceTree = SOURCE_ROOT; };
- 4D2C724D126F9C4D00B43EAF /* ia32_reg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ia32_reg.c; path = ../../../third_party/libdisasm/ia32_reg.c; sourceTree = SOURCE_ROOT; };
- 4D2C725A126F9C8000B43EAF /* ia32_operand.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ia32_operand.c; path = ../../../third_party/libdisasm/ia32_operand.c; sourceTree = SOURCE_ROOT; };
- 4D2C725C126F9C9200B43EAF /* x86_insn.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = x86_insn.c; path = ../../../third_party/libdisasm/x86_insn.c; sourceTree = SOURCE_ROOT; };
- 4D2C7261126F9CBB00B43EAF /* ia32_modrm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ia32_modrm.c; path = ../../../third_party/libdisasm/ia32_modrm.c; sourceTree = SOURCE_ROOT; };
- 4D2C7263126F9CBB00B43EAF /* x86_imm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = x86_imm.c; path = ../../../third_party/libdisasm/x86_imm.c; sourceTree = SOURCE_ROOT; };
- 4D72CA5613DFBA84006CABE3 /* md5.cc */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = md5.cc; path = ../../../common/md5.cc; sourceTree = SOURCE_ROOT; };
- 5578003E0BE1F28500EC23E0 /* macho_utilities.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_utilities.cc; path = ../../../common/mac/macho_utilities.cc; sourceTree = SOURCE_ROOT; };
- 5578003F0BE1F28500EC23E0 /* macho_utilities.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_utilities.h; path = ../../../common/mac/macho_utilities.h; sourceTree = SOURCE_ROOT; };
- 8B31025311F0D2D400FCF3E4 /* Breakpad.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Breakpad.xcconfig; path = ../../../common/mac/Breakpad.xcconfig; sourceTree = SOURCE_ROOT; };
- 8B3102DA11F0D65600FCF3E4 /* BreakpadDebug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadDebug.xcconfig; path = ../../../common/mac/BreakpadDebug.xcconfig; sourceTree = SOURCE_ROOT; };
- 8B3102DB11F0D65600FCF3E4 /* BreakpadRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadRelease.xcconfig; path = ../../../common/mac/BreakpadRelease.xcconfig; sourceTree = SOURCE_ROOT; };
- 8B31FF2411F0C62700FCF3E4 /* dwarf_cfi_to_module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf_cfi_to_module.cc; path = ../../../common/dwarf_cfi_to_module.cc; sourceTree = SOURCE_ROOT; };
- 8B31FF2511F0C62700FCF3E4 /* dwarf_cfi_to_module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf_cfi_to_module.h; path = ../../../common/dwarf_cfi_to_module.h; sourceTree = SOURCE_ROOT; };
- 8B31FF2611F0C62700FCF3E4 /* dwarf_cu_to_module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf_cu_to_module.cc; path = ../../../common/dwarf_cu_to_module.cc; sourceTree = SOURCE_ROOT; };
- 8B31FF2711F0C62700FCF3E4 /* dwarf_cu_to_module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf_cu_to_module.h; path = ../../../common/dwarf_cu_to_module.h; sourceTree = SOURCE_ROOT; };
- 8B31FF2811F0C62700FCF3E4 /* dwarf_line_to_module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf_line_to_module.cc; path = ../../../common/dwarf_line_to_module.cc; sourceTree = SOURCE_ROOT; };
- 8B31FF2911F0C62700FCF3E4 /* dwarf_line_to_module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf_line_to_module.h; path = ../../../common/dwarf_line_to_module.h; sourceTree = SOURCE_ROOT; };
- 8B31FF3D11F0C64400FCF3E4 /* stabs_reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stabs_reader.cc; path = ../../../common/stabs_reader.cc; sourceTree = SOURCE_ROOT; };
- 8B31FF3E11F0C64400FCF3E4 /* stabs_reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stabs_reader.h; path = ../../../common/stabs_reader.h; sourceTree = SOURCE_ROOT; };
- 8B31FF3F11F0C64400FCF3E4 /* stabs_to_module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stabs_to_module.cc; path = ../../../common/stabs_to_module.cc; sourceTree = SOURCE_ROOT; };
- 8B31FF4011F0C64400FCF3E4 /* stabs_to_module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stabs_to_module.h; path = ../../../common/stabs_to_module.h; sourceTree = SOURCE_ROOT; };
- 8B31FF7211F0C6E000FCF3E4 /* macho_reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = macho_reader.cc; path = ../../../common/mac/macho_reader.cc; sourceTree = SOURCE_ROOT; };
- 8B31FF7311F0C6E000FCF3E4 /* macho_reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = macho_reader.h; path = ../../../common/mac/macho_reader.h; sourceTree = SOURCE_ROOT; };
- 8B31FF8411F0C6FB00FCF3E4 /* language.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = language.cc; path = ../../../common/language.cc; sourceTree = SOURCE_ROOT; };
- 8B31FF8511F0C6FB00FCF3E4 /* language.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = language.h; path = ../../../common/language.h; sourceTree = SOURCE_ROOT; };
- 8B31FF8611F0C6FB00FCF3E4 /* module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = module.cc; path = ../../../common/module.cc; sourceTree = SOURCE_ROOT; };
- 8B31FF8711F0C6FB00FCF3E4 /* module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = module.h; path = ../../../common/module.h; sourceTree = SOURCE_ROOT; };
- 8B31FFC311F0C8AB00FCF3E4 /* dwarf2diehandler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2diehandler.cc; path = ../../../common/dwarf/dwarf2diehandler.cc; sourceTree = SOURCE_ROOT; };
- 8B31FFC411F0C8AB00FCF3E4 /* dwarf2diehandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2diehandler.h; path = ../../../common/dwarf/dwarf2diehandler.h; sourceTree = SOURCE_ROOT; };
- 8B40BDBF0C0638E4009535AF /* logging.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = logging.cc; path = ../../../processor/logging.cc; sourceTree = SOURCE_ROOT; };
- 8DD76FA10486AA7600D96B5E /* crash_report */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = crash_report; sourceTree = BUILT_PRODUCTS_DIR; };
- 9B35FEE20B2675F9008DE8C7 /* code_module.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = code_module.h; path = ../../../google_breakpad/processor/code_module.h; sourceTree = SOURCE_ROOT; };
- 9B35FEE30B2675F9008DE8C7 /* code_modules.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = code_modules.h; path = ../../../google_breakpad/processor/code_modules.h; sourceTree = SOURCE_ROOT; };
- 9B35FEE60B26761C008DE8C7 /* basic_code_module.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = basic_code_module.h; path = ../../../processor/basic_code_module.h; sourceTree = SOURCE_ROOT; };
- 9B35FEE70B26761C008DE8C7 /* basic_code_modules.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = basic_code_modules.cc; path = ../../../processor/basic_code_modules.cc; sourceTree = SOURCE_ROOT; };
- 9B35FEE80B26761C008DE8C7 /* basic_code_modules.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = basic_code_modules.h; path = ../../../processor/basic_code_modules.h; sourceTree = SOURCE_ROOT; };
- 9B3904940B2E52D90059FABE /* basic_source_line_resolver.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = basic_source_line_resolver.h; sourceTree = "<group>"; };
- 9B3904950B2E52D90059FABE /* source_line_resolver_interface.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = source_line_resolver_interface.h; sourceTree = "<group>"; };
- 9B3904980B2E52FD0059FABE /* basic_source_line_resolver.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = basic_source_line_resolver.cc; path = ../../../processor/basic_source_line_resolver.cc; sourceTree = SOURCE_ROOT; };
- 9B44619D0B66C66B00BBB817 /* system_info.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = system_info.h; sourceTree = "<group>"; };
- 9BDF16F90B1B8ACD00F8391B /* breakpad_types.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = breakpad_types.h; sourceTree = "<group>"; };
- 9BDF16FA0B1B8ACD00F8391B /* minidump_format.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = minidump_format.h; sourceTree = "<group>"; };
- 9BDF16FC0B1B8ACD00F8391B /* call_stack.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = call_stack.h; sourceTree = "<group>"; };
- 9BDF16FD0B1B8ACD00F8391B /* memory_region.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = memory_region.h; sourceTree = "<group>"; };
- 9BDF16FE0B1B8ACD00F8391B /* minidump.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = minidump.h; sourceTree = "<group>"; };
- 9BDF16FF0B1B8ACD00F8391B /* minidump_processor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = minidump_processor.h; sourceTree = "<group>"; };
- 9BDF17000B1B8ACD00F8391B /* process_state.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = process_state.h; sourceTree = "<group>"; };
- 9BDF17010B1B8ACD00F8391B /* stack_frame.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = stack_frame.h; sourceTree = "<group>"; };
- 9BDF17020B1B8ACD00F8391B /* stack_frame_cpu.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = stack_frame_cpu.h; sourceTree = "<group>"; };
- 9BDF17030B1B8ACD00F8391B /* stackwalker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = stackwalker.h; sourceTree = "<group>"; };
- 9BDF17040B1B8ACD00F8391B /* symbol_supplier.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = symbol_supplier.h; sourceTree = "<group>"; };
- 9BDF172A0B1B8B2400F8391B /* call_stack.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = call_stack.cc; path = ../../../processor/call_stack.cc; sourceTree = SOURCE_ROOT; };
- 9BDF172B0B1B8B2400F8391B /* minidump_processor.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = minidump_processor.cc; path = ../../../processor/minidump_processor.cc; sourceTree = SOURCE_ROOT; };
- 9BDF173F0B1B8B9A00F8391B /* minidump.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = minidump.cc; path = ../../../processor/minidump.cc; sourceTree = SOURCE_ROOT; };
- 9BDF17510B1B8BF900F8391B /* stackwalker_ppc.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = stackwalker_ppc.cc; path = ../../../processor/stackwalker_ppc.cc; sourceTree = SOURCE_ROOT; };
- 9BDF17520B1B8BF900F8391B /* stackwalker_x86.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = stackwalker_x86.cc; path = ../../../processor/stackwalker_x86.cc; sourceTree = SOURCE_ROOT; };
- 9BDF17530B1B8BF900F8391B /* stackwalker.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = stackwalker.cc; path = ../../../processor/stackwalker.cc; sourceTree = SOURCE_ROOT; };
- 9BDF175B0B1B8C1B00F8391B /* process_state.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = process_state.cc; path = ../../../processor/process_state.cc; sourceTree = SOURCE_ROOT; };
- 9BDF176B0B1B8CB100F8391B /* on_demand_symbol_supplier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = on_demand_symbol_supplier.h; sourceTree = "<group>"; };
- 9BDF176C0B1B8CB100F8391B /* on_demand_symbol_supplier.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = on_demand_symbol_supplier.mm; sourceTree = "<group>"; };
- 9BDF192D0B1BC15D00F8391B /* dump_syms.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = dump_syms.h; path = ../../../common/mac/dump_syms.h; sourceTree = SOURCE_ROOT; };
- 9BDF192E0B1BC15D00F8391B /* dump_syms.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = dump_syms.cc; path = ../../../common/mac/dump_syms.cc; sourceTree = SOURCE_ROOT; };
- 9BDF1A270B1BD58200F8391B /* pathname_stripper.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = pathname_stripper.cc; path = ../../../processor/pathname_stripper.cc; sourceTree = SOURCE_ROOT; };
- 9BDF1A7A0B1BE30100F8391B /* range_map-inl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = "range_map-inl.h"; path = "../../../processor/range_map-inl.h"; sourceTree = SOURCE_ROOT; };
- 9BDF1A7B0B1BE30100F8391B /* range_map.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = range_map.h; path = ../../../processor/range_map.h; sourceTree = SOURCE_ROOT; };
- 9BDF1AFA0B1BEB6300F8391B /* address_map-inl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = "address_map-inl.h"; path = "../../../processor/address_map-inl.h"; sourceTree = SOURCE_ROOT; };
- 9BDF1AFB0B1BEB6300F8391B /* address_map.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = address_map.h; path = ../../../processor/address_map.h; sourceTree = SOURCE_ROOT; };
- 9BE650AC0B52FE3000611104 /* file_id.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = file_id.cc; path = ../../../common/mac/file_id.cc; sourceTree = SOURCE_ROOT; };
- 9BE650AD0B52FE3000611104 /* file_id.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = file_id.h; path = ../../../common/mac/file_id.h; sourceTree = SOURCE_ROOT; };
- 9BE650AE0B52FE3000611104 /* macho_id.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_id.cc; path = ../../../common/mac/macho_id.cc; sourceTree = SOURCE_ROOT; };
- 9BE650AF0B52FE3000611104 /* macho_id.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_id.h; path = ../../../common/mac/macho_id.h; sourceTree = SOURCE_ROOT; };
- 9BE650B00B52FE3000611104 /* macho_walker.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_walker.cc; path = ../../../common/mac/macho_walker.cc; sourceTree = SOURCE_ROOT; };
- 9BE650B10B52FE3000611104 /* macho_walker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_walker.h; path = ../../../common/mac/macho_walker.h; sourceTree = SOURCE_ROOT; };
- D2A5DD4C1188651100081F03 /* cfi_frame_info.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = cfi_frame_info.cc; path = ../../../processor/cfi_frame_info.cc; sourceTree = SOURCE_ROOT; };
- D2A5DD621188658B00081F03 /* tokenize.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tokenize.cc; path = ../../../processor/tokenize.cc; sourceTree = SOURCE_ROOT; };
- F407DC40185773C10064622B /* exploitability_linux.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = exploitability_linux.cc; path = ../../../processor/exploitability_linux.cc; sourceTree = "<group>"; };
- F407DC41185773C10064622B /* stack_frame_symbolizer.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stack_frame_symbolizer.cc; path = ../../../processor/stack_frame_symbolizer.cc; sourceTree = "<group>"; };
- F407DC42185773C10064622B /* stackwalker_arm64.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stackwalker_arm64.cc; path = ../../../processor/stackwalker_arm64.cc; sourceTree = "<group>"; };
- F407DC43185773C10064622B /* stackwalker_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stackwalker_arm64.h; path = ../../../processor/stackwalker_arm64.h; sourceTree = "<group>"; };
- F407DC44185773C10064622B /* stackwalker_mips.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stackwalker_mips.cc; path = ../../../processor/stackwalker_mips.cc; sourceTree = "<group>"; };
- F407DC45185773C10064622B /* stackwalker_mips.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stackwalker_mips.h; path = ../../../processor/stackwalker_mips.h; sourceTree = "<group>"; };
- F407DC46185773C10064622B /* stackwalker_ppc64.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stackwalker_ppc64.cc; path = ../../../processor/stackwalker_ppc64.cc; sourceTree = "<group>"; };
- F407DC47185773C10064622B /* stackwalker_ppc64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stackwalker_ppc64.h; path = ../../../processor/stackwalker_ppc64.h; sourceTree = "<group>"; };
- F44DDD8419C85CD50047280E /* dump_context.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dump_context.cc; path = ../../../processor/dump_context.cc; sourceTree = "<group>"; };
- F44DDD8519C85CD50047280E /* dump_object.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dump_object.cc; path = ../../../processor/dump_object.cc; sourceTree = "<group>"; };
- F44DDD8619C85CD50047280E /* microdump_processor.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = microdump_processor.cc; path = ../../../processor/microdump_processor.cc; sourceTree = "<group>"; };
- F44DDD8A19C85CFB0047280E /* dump_context.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = dump_context.h; path = ../../../google_breakpad/processor/dump_context.h; sourceTree = "<group>"; };
- F44DDD8B19C85CFB0047280E /* dump_object.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = dump_object.h; path = ../../../google_breakpad/processor/dump_object.h; sourceTree = "<group>"; };
- F44DDD8C19C85CFC0047280E /* microdump_processor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = microdump_processor.h; path = ../../../google_breakpad/processor/microdump_processor.h; sourceTree = "<group>"; };
- F44DDD8D19C85CFC0047280E /* process_result.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = process_result.h; path = ../../../google_breakpad/processor/process_result.h; sourceTree = "<group>"; };
- F47180541D745DEF0032F208 /* elf_reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = elf_reader.cc; path = ../../../common/dwarf/elf_reader.cc; sourceTree = "<group>"; };
- F47180551D745DEF0032F208 /* elf_reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = elf_reader.h; path = ../../../common/dwarf/elf_reader.h; sourceTree = "<group>"; };
- F47180571D7467630032F208 /* proc_maps_linux.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = proc_maps_linux.cc; path = ../../../processor/proc_maps_linux.cc; sourceTree = "<group>"; };
- F47180591D7468A40032F208 /* symbolic_constants_win.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = symbolic_constants_win.cc; path = ../../../processor/symbolic_constants_win.cc; sourceTree = "<group>"; };
- F4D43B2E1A38490700C290B2 /* microdump.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = microdump.cc; path = ../../../processor/microdump.cc; sourceTree = "<group>"; };
- F4D43B301A38492000C290B2 /* microdump.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = microdump.h; path = ../../../google_breakpad/processor/microdump.h; sourceTree = "<group>"; };
- F9C7ECE20E8ABCA600E953AD /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/dwarf/bytereader.cc; sourceTree = SOURCE_ROOT; };
- F9C7ECE30E8ABCA600E953AD /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; };
- F9C7ECE40E8ABCA600E953AD /* functioninfo.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = functioninfo.cc; path = ../../../common/dwarf/functioninfo.cc; sourceTree = SOURCE_ROOT; };
- F9F0706510FBC02D0037B88B /* stackwalker_arm.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stackwalker_arm.cc; path = ../../../processor/stackwalker_arm.cc; sourceTree = SOURCE_ROOT; };
- F9F0706610FBC02D0037B88B /* stackwalker_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stackwalker_arm.h; path = ../../../processor/stackwalker_arm.h; sourceTree = SOURCE_ROOT; };
- FD6625C40CF4D438004AC844 /* stackwalker_amd64.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stackwalker_amd64.cc; path = ../../../processor/stackwalker_amd64.cc; sourceTree = SOURCE_ROOT; };
- FD6625C50CF4D438004AC844 /* stackwalker_amd64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stackwalker_amd64.h; path = ../../../processor/stackwalker_amd64.h; sourceTree = SOURCE_ROOT; };
- FD8EDEAC0CADDAD400A5EDF1 /* stackwalker_sparc.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = stackwalker_sparc.cc; path = ../../../processor/stackwalker_sparc.cc; sourceTree = SOURCE_ROOT; };
- FD8EDEAD0CADDAD400A5EDF1 /* stackwalker_sparc.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = stackwalker_sparc.h; path = ../../../processor/stackwalker_sparc.h; sourceTree = SOURCE_ROOT; };
-/* End PBXFileReference section */
-
-/* Begin PBXFrameworksBuildPhase section */
- 8DD76F9B0486AA7600D96B5E /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXFrameworksBuildPhase section */
-
-/* Begin PBXGroup section */
- 08FB7794FE84155DC02AAC07 /* crash_report */ = {
- isa = PBXGroup;
- children = (
- 4214B7FE211109A600B769FA /* convert_old_arm64_context.cc */,
- 4214B7FF211109A600B769FA /* convert_old_arm64_context.h */,
- 4247E63F2110D5A500482558 /* path_helper.cc */,
- 4247E63E2110D5A500482558 /* path_helper.h */,
- 8B31025311F0D2D400FCF3E4 /* Breakpad.xcconfig */,
- 8B3102DA11F0D65600FCF3E4 /* BreakpadDebug.xcconfig */,
- 8B3102DB11F0D65600FCF3E4 /* BreakpadRelease.xcconfig */,
- F9C7ECE10E8ABC7F00E953AD /* DWARF */,
- 162F64FC161C5ECB00CD68D5 /* arch_utilities.cc */,
- 162F64FD161C5ECB00CD68D5 /* arch_utilities.h */,
- 5578003E0BE1F28500EC23E0 /* macho_utilities.cc */,
- 5578003F0BE1F28500EC23E0 /* macho_utilities.h */,
- 8B31FF7211F0C6E000FCF3E4 /* macho_reader.cc */,
- 8B31FF7311F0C6E000FCF3E4 /* macho_reader.h */,
- 9BDF192D0B1BC15D00F8391B /* dump_syms.h */,
- 9BDF192E0B1BC15D00F8391B /* dump_syms.cc */,
- 08FB7796FE84155DC02AAC07 /* crash_report.mm */,
- F44DDD8D19C85CFC0047280E /* process_result.h */,
- 9BDF176B0B1B8CB100F8391B /* on_demand_symbol_supplier.h */,
- F44DDD8419C85CD50047280E /* dump_context.cc */,
- F44DDD8A19C85CFB0047280E /* dump_context.h */,
- F44DDD8519C85CD50047280E /* dump_object.cc */,
- F44DDD8B19C85CFB0047280E /* dump_object.h */,
- F4D43B2E1A38490700C290B2 /* microdump.cc */,
- F4D43B301A38492000C290B2 /* microdump.h */,
- F44DDD8619C85CD50047280E /* microdump_processor.cc */,
- F44DDD8C19C85CFC0047280E /* microdump_processor.h */,
- 9BDF176C0B1B8CB100F8391B /* on_demand_symbol_supplier.mm */,
- 8B31FF2411F0C62700FCF3E4 /* dwarf_cfi_to_module.cc */,
- 8B31FF2511F0C62700FCF3E4 /* dwarf_cfi_to_module.h */,
- 8B31FF2611F0C62700FCF3E4 /* dwarf_cu_to_module.cc */,
- 8B31FF2711F0C62700FCF3E4 /* dwarf_cu_to_module.h */,
- 8B31FF2811F0C62700FCF3E4 /* dwarf_line_to_module.cc */,
- 8B31FF2911F0C62700FCF3E4 /* dwarf_line_to_module.h */,
- 8B31FF3D11F0C64400FCF3E4 /* stabs_reader.cc */,
- 8B31FF3E11F0C64400FCF3E4 /* stabs_reader.h */,
- 8B31FF3F11F0C64400FCF3E4 /* stabs_to_module.cc */,
- 8B31FF4011F0C64400FCF3E4 /* stabs_to_module.h */,
- 8B31FF8411F0C6FB00FCF3E4 /* language.cc */,
- 8B31FF8511F0C6FB00FCF3E4 /* language.h */,
- 4D72CA5613DFBA84006CABE3 /* md5.cc */,
- 8B31FF8611F0C6FB00FCF3E4 /* module.cc */,
- 8B31FF8711F0C6FB00FCF3E4 /* module.h */,
- 08FB7795FE84155DC02AAC07 /* breakpad */,
- 4D2C726E126F9CE200B43EAF /* libdisasm */,
- 08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */,
- 1AB674ADFE9D54B511CA2CBB /* Products */,
- );
- name = crash_report;
- sourceTree = "<group>";
- };
- 08FB7795FE84155DC02AAC07 /* breakpad */ = {
- isa = PBXGroup;
- children = (
- 9BE650AB0B52FE1A00611104 /* common */,
- 9BDF17280B1B8B0200F8391B /* processor */,
- 9BDF16F70B1B8ACD00F8391B /* google_breakpad */,
- );
- name = breakpad;
- sourceTree = "<group>";
- };
- 08FB779DFE84155DC02AAC07 /* External Frameworks and Libraries */ = {
- isa = PBXGroup;
- children = (
- 08FB779EFE84155DC02AAC07 /* Foundation.framework */,
- );
- name = "External Frameworks and Libraries";
- sourceTree = "<group>";
- };
- 1AB674ADFE9D54B511CA2CBB /* Products */ = {
- isa = PBXGroup;
- children = (
- 8DD76FA10486AA7600D96B5E /* crash_report */,
- );
- name = Products;
- sourceTree = "<group>";
- };
- 4D2C726E126F9CE200B43EAF /* libdisasm */ = {
- isa = PBXGroup;
- children = (
- 4D2C7226126F9B0F00B43EAF /* disassembler_x86.cc */,
- 4D2C724B126F9C3800B43EAF /* ia32_implicit.c */,
- 4D2C7245126F9C0B00B43EAF /* ia32_insn.c */,
- 4D2C7232126F9BB000B43EAF /* ia32_invariant.c */,
- 4D2C7261126F9CBB00B43EAF /* ia32_modrm.c */,
- 4D2C7249126F9C2300B43EAF /* ia32_opcode_tables.c */,
- 4D2C725A126F9C8000B43EAF /* ia32_operand.c */,
- 4D2C724D126F9C4D00B43EAF /* ia32_reg.c */,
- 4D2C7234126F9BC200B43EAF /* ia32_settings.c */,
- 4D2C722A126F9B5A00B43EAF /* x86_disasm.c */,
- 4D2C7263126F9CBB00B43EAF /* x86_imm.c */,
- 4D2C725C126F9C9200B43EAF /* x86_insn.c */,
- 4D2C722C126F9B6E00B43EAF /* x86_misc.c */,
- 4D2C722E126F9B8300B43EAF /* x86_operand_list.c */,
- );
- name = libdisasm;
- sourceTree = "<group>";
- };
- 9BDF16F70B1B8ACD00F8391B /* google_breakpad */ = {
- isa = PBXGroup;
- children = (
- 9BDF16F80B1B8ACD00F8391B /* common */,
- 9BDF16FB0B1B8ACD00F8391B /* processor */,
- );
- name = google_breakpad;
- path = ../../../google_breakpad;
- sourceTree = SOURCE_ROOT;
- };
- 9BDF16F80B1B8ACD00F8391B /* common */ = {
- isa = PBXGroup;
- children = (
- 9BDF16F90B1B8ACD00F8391B /* breakpad_types.h */,
- 9BDF16FA0B1B8ACD00F8391B /* minidump_format.h */,
- );
- path = common;
- sourceTree = "<group>";
- };
- 9BDF16FB0B1B8ACD00F8391B /* processor */ = {
- isa = PBXGroup;
- children = (
- 9B3904940B2E52D90059FABE /* basic_source_line_resolver.h */,
- 9BDF16FC0B1B8ACD00F8391B /* call_stack.h */,
- 9B35FEE20B2675F9008DE8C7 /* code_module.h */,
- 9B35FEE30B2675F9008DE8C7 /* code_modules.h */,
- 9BDF16FD0B1B8ACD00F8391B /* memory_region.h */,
- 9BDF16FE0B1B8ACD00F8391B /* minidump.h */,
- 9BDF16FF0B1B8ACD00F8391B /* minidump_processor.h */,
- 9BDF17000B1B8ACD00F8391B /* process_state.h */,
- 9B3904950B2E52D90059FABE /* source_line_resolver_interface.h */,
- 9BDF17010B1B8ACD00F8391B /* stack_frame.h */,
- 9BDF17020B1B8ACD00F8391B /* stack_frame_cpu.h */,
- 9BDF17030B1B8ACD00F8391B /* stackwalker.h */,
- 9BDF17040B1B8ACD00F8391B /* symbol_supplier.h */,
- 9B44619D0B66C66B00BBB817 /* system_info.h */,
- );
- path = processor;
- sourceTree = "<group>";
- };
- 9BDF17280B1B8B0200F8391B /* processor */ = {
- isa = PBXGroup;
- children = (
- 4D2C7222126F9AF900B43EAF /* exploitability_win.cc */,
- F407DC40185773C10064622B /* exploitability_linux.cc */,
- F407DC41185773C10064622B /* stack_frame_symbolizer.cc */,
- F407DC42185773C10064622B /* stackwalker_arm64.cc */,
- F407DC43185773C10064622B /* stackwalker_arm64.h */,
- F407DC44185773C10064622B /* stackwalker_mips.cc */,
- F407DC45185773C10064622B /* stackwalker_mips.h */,
- F407DC46185773C10064622B /* stackwalker_ppc64.cc */,
- F407DC47185773C10064622B /* stackwalker_ppc64.h */,
- 4D2C721E126F9ADE00B43EAF /* exploitability.cc */,
- 4D2C721A126F9ACC00B43EAF /* source_line_resolver_base.cc */,
- D2A5DD621188658B00081F03 /* tokenize.cc */,
- D2A5DD4C1188651100081F03 /* cfi_frame_info.cc */,
- F9F0706510FBC02D0037B88B /* stackwalker_arm.cc */,
- F9F0706610FBC02D0037B88B /* stackwalker_arm.h */,
- 9B3904980B2E52FD0059FABE /* basic_source_line_resolver.cc */,
- 9BDF1AFA0B1BEB6300F8391B /* address_map-inl.h */,
- 9BDF1AFB0B1BEB6300F8391B /* address_map.h */,
- 9B35FEE60B26761C008DE8C7 /* basic_code_module.h */,
- 9B35FEE70B26761C008DE8C7 /* basic_code_modules.cc */,
- 9B35FEE80B26761C008DE8C7 /* basic_code_modules.h */,
- 9BDF172A0B1B8B2400F8391B /* call_stack.cc */,
- 8B40BDBF0C0638E4009535AF /* logging.cc */,
- 9BDF173F0B1B8B9A00F8391B /* minidump.cc */,
- 9BDF172B0B1B8B2400F8391B /* minidump_processor.cc */,
- 9BDF1A270B1BD58200F8391B /* pathname_stripper.cc */,
- F47180571D7467630032F208 /* proc_maps_linux.cc */,
- 9BDF175B0B1B8C1B00F8391B /* process_state.cc */,
- 9BDF1A7A0B1BE30100F8391B /* range_map-inl.h */,
- 9BDF1A7B0B1BE30100F8391B /* range_map.h */,
- 9BDF17530B1B8BF900F8391B /* stackwalker.cc */,
- 9BDF17510B1B8BF900F8391B /* stackwalker_ppc.cc */,
- 9BDF17520B1B8BF900F8391B /* stackwalker_x86.cc */,
- FD8EDEAC0CADDAD400A5EDF1 /* stackwalker_sparc.cc */,
- FD8EDEAD0CADDAD400A5EDF1 /* stackwalker_sparc.h */,
- FD6625C40CF4D438004AC844 /* stackwalker_amd64.cc */,
- FD6625C50CF4D438004AC844 /* stackwalker_amd64.h */,
- F47180591D7468A40032F208 /* symbolic_constants_win.cc */,
- );
- name = processor;
- sourceTree = "<group>";
- };
- 9BE650AB0B52FE1A00611104 /* common */ = {
- isa = PBXGroup;
- children = (
- 9BE650AC0B52FE3000611104 /* file_id.cc */,
- 9BE650AD0B52FE3000611104 /* file_id.h */,
- 9BE650AE0B52FE3000611104 /* macho_id.cc */,
- 9BE650AF0B52FE3000611104 /* macho_id.h */,
- 9BE650B00B52FE3000611104 /* macho_walker.cc */,
- 9BE650B10B52FE3000611104 /* macho_walker.h */,
- );
- name = common;
- sourceTree = "<group>";
- };
- F9C7ECE10E8ABC7F00E953AD /* DWARF */ = {
- isa = PBXGroup;
- children = (
- F9C7ECE20E8ABCA600E953AD /* bytereader.cc */,
- F9C7ECE30E8ABCA600E953AD /* dwarf2reader.cc */,
- 8B31FFC311F0C8AB00FCF3E4 /* dwarf2diehandler.cc */,
- 8B31FFC411F0C8AB00FCF3E4 /* dwarf2diehandler.h */,
- F47180541D745DEF0032F208 /* elf_reader.cc */,
- F47180551D745DEF0032F208 /* elf_reader.h */,
- F9C7ECE40E8ABCA600E953AD /* functioninfo.cc */,
- );
- name = DWARF;
- sourceTree = "<group>";
- };
-/* End PBXGroup section */
-
-/* Begin PBXNativeTarget section */
- 8DD76F960486AA7600D96B5E /* crash_report */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 1DEB927408733DD40010E9CD /* Build configuration list for PBXNativeTarget "crash_report" */;
- buildPhases = (
- 8DD76F990486AA7600D96B5E /* Sources */,
- 8DD76F9B0486AA7600D96B5E /* Frameworks */,
- );
- buildRules = (
- );
- dependencies = (
- );
- name = crash_report;
- productInstallPath = "$(HOME)/bin";
- productName = crash_report;
- productReference = 8DD76FA10486AA7600D96B5E /* crash_report */;
- productType = "com.apple.product-type.tool";
- };
-/* End PBXNativeTarget section */
-
-/* Begin PBXProject section */
- 08FB7793FE84155DC02AAC07 /* Project object */ = {
- isa = PBXProject;
- attributes = {
- };
- buildConfigurationList = 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "crash_report" */;
- compatibilityVersion = "Xcode 3.1";
- developmentRegion = en;
- hasScannedForEncodings = 1;
- knownRegions = (
- English,
- Japanese,
- French,
- German,
- );
- mainGroup = 08FB7794FE84155DC02AAC07 /* crash_report */;
- projectDirPath = "";
- projectRoot = "";
- targets = (
- 8DD76F960486AA7600D96B5E /* crash_report */,
- );
- };
-/* End PBXProject section */
-
-/* Begin PBXSourcesBuildPhase section */
- 8DD76F990486AA7600D96B5E /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 162F64FE161C5ECB00CD68D5 /* arch_utilities.cc in Sources */,
- 8DD76F9A0486AA7600D96B5E /* crash_report.mm in Sources */,
- F47180581D7467630032F208 /* proc_maps_linux.cc in Sources */,
- 9BDF172C0B1B8B2400F8391B /* call_stack.cc in Sources */,
- 9BDF172D0B1B8B2400F8391B /* minidump_processor.cc in Sources */,
- 9BDF17410B1B8B9A00F8391B /* minidump.cc in Sources */,
- F44DDD8719C85CD50047280E /* dump_context.cc in Sources */,
- 9BDF17540B1B8BF900F8391B /* stackwalker_ppc.cc in Sources */,
- 9BDF17550B1B8BF900F8391B /* stackwalker_x86.cc in Sources */,
- 9BDF17560B1B8BF900F8391B /* stackwalker.cc in Sources */,
- 9BDF175D0B1B8C1B00F8391B /* process_state.cc in Sources */,
- F47180561D745DEF0032F208 /* elf_reader.cc in Sources */,
- 9BDF176E0B1B8CB100F8391B /* on_demand_symbol_supplier.mm in Sources */,
- 9BDF1A280B1BD58200F8391B /* pathname_stripper.cc in Sources */,
- 9BDF21A70B1E825400F8391B /* dump_syms.cc in Sources */,
- 9B35FEEA0B26761C008DE8C7 /* basic_code_modules.cc in Sources */,
- 9B3904990B2E52FD0059FABE /* basic_source_line_resolver.cc in Sources */,
- 9BE650B20B52FE3000611104 /* file_id.cc in Sources */,
- 9BE650B40B52FE3000611104 /* macho_id.cc in Sources */,
- 9BE650B60B52FE3000611104 /* macho_walker.cc in Sources */,
- 557800400BE1F28500EC23E0 /* macho_utilities.cc in Sources */,
- 8B40BDC00C0638E4009535AF /* logging.cc in Sources */,
- FD8EDEAE0CADDAD400A5EDF1 /* stackwalker_sparc.cc in Sources */,
- FD6625CD0CF4D45C004AC844 /* stackwalker_amd64.cc in Sources */,
- F9C7ECE50E8ABCA600E953AD /* bytereader.cc in Sources */,
- F9C7ECE60E8ABCA600E953AD /* dwarf2reader.cc in Sources */,
- F9C7ECE70E8ABCA600E953AD /* functioninfo.cc in Sources */,
- F9F0706710FBC02D0037B88B /* stackwalker_arm.cc in Sources */,
- D2A5DD4D1188651100081F03 /* cfi_frame_info.cc in Sources */,
- D2A5DD631188658B00081F03 /* tokenize.cc in Sources */,
- 8B31FF2A11F0C62700FCF3E4 /* dwarf_cfi_to_module.cc in Sources */,
- F4D43B2F1A38490700C290B2 /* microdump.cc in Sources */,
- 8B31FF2B11F0C62700FCF3E4 /* dwarf_cu_to_module.cc in Sources */,
- F44DDD8819C85CD50047280E /* dump_object.cc in Sources */,
- 8B31FF2C11F0C62700FCF3E4 /* dwarf_line_to_module.cc in Sources */,
- 8B31FF4111F0C64400FCF3E4 /* stabs_reader.cc in Sources */,
- 8B31FF4211F0C64400FCF3E4 /* stabs_to_module.cc in Sources */,
- 8B31FF7411F0C6E000FCF3E4 /* macho_reader.cc in Sources */,
- 8B31FF8811F0C6FB00FCF3E4 /* language.cc in Sources */,
- 8B31FF8911F0C6FB00FCF3E4 /* module.cc in Sources */,
- 8B31FFC511F0C8AB00FCF3E4 /* dwarf2diehandler.cc in Sources */,
- F407DC49185773C10064622B /* stack_frame_symbolizer.cc in Sources */,
- F471805A1D7468A40032F208 /* symbolic_constants_win.cc in Sources */,
- 4D2C721B126F9ACC00B43EAF /* source_line_resolver_base.cc in Sources */,
- 4D2C721F126F9ADE00B43EAF /* exploitability.cc in Sources */,
- 4D2C7223126F9AF900B43EAF /* exploitability_win.cc in Sources */,
- 4D2C7227126F9B0F00B43EAF /* disassembler_x86.cc in Sources */,
- F407DC48185773C10064622B /* exploitability_linux.cc in Sources */,
- 4214B800211109A600B769FA /* convert_old_arm64_context.cc in Sources */,
- 4D2C722B126F9B5A00B43EAF /* x86_disasm.c in Sources */,
- 4D2C722D126F9B6E00B43EAF /* x86_misc.c in Sources */,
- 4D2C722F126F9B8300B43EAF /* x86_operand_list.c in Sources */,
- F407DC4A185773C10064622B /* stackwalker_arm64.cc in Sources */,
- 4D2C7233126F9BB000B43EAF /* ia32_invariant.c in Sources */,
- 4D2C7235126F9BC200B43EAF /* ia32_settings.c in Sources */,
- 4D2C7246126F9C0B00B43EAF /* ia32_insn.c in Sources */,
- 4D2C724A126F9C2300B43EAF /* ia32_opcode_tables.c in Sources */,
- 4D2C724C126F9C3800B43EAF /* ia32_implicit.c in Sources */,
- 4247E6402110D5A500482558 /* path_helper.cc in Sources */,
- F44DDD8919C85CD50047280E /* microdump_processor.cc in Sources */,
- 4D2C724E126F9C4D00B43EAF /* ia32_reg.c in Sources */,
- 4D2C725B126F9C8000B43EAF /* ia32_operand.c in Sources */,
- F407DC4C185773C10064622B /* stackwalker_ppc64.cc in Sources */,
- 4D2C725D126F9C9200B43EAF /* x86_insn.c in Sources */,
- 4D2C7264126F9CBB00B43EAF /* ia32_modrm.c in Sources */,
- F407DC4B185773C10064622B /* stackwalker_mips.cc in Sources */,
- 4D2C726D126F9CDC00B43EAF /* x86_imm.c in Sources */,
- 4D72CA5713DFBA84006CABE3 /* md5.cc in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXSourcesBuildPhase section */
-
-/* Begin XCBuildConfiguration section */
- 1DEB927508733DD40010E9CD /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
- HEADER_SEARCH_PATHS = ../../../../src;
- PRODUCT_NAME = crash_report;
- };
- name = Debug;
- };
- 1DEB927608733DD40010E9CD /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
- HEADER_SEARCH_PATHS = ../../../../src;
- PRODUCT_NAME = crash_report;
- };
- name = Release;
- };
- 1DEB927908733DD40010E9CD /* Debug */ = {
- isa = XCBuildConfiguration;
- baseConfigurationReference = 8B3102DA11F0D65600FCF3E4 /* BreakpadDebug.xcconfig */;
- buildSettings = {
- GCC_PREPROCESSOR_DEFINITIONS = HAVE_MACH_O_NLIST_H;
- GCC_TREAT_WARNINGS_AS_ERRORS = NO;
- };
- name = Debug;
- };
- 1DEB927A08733DD40010E9CD /* Release */ = {
- isa = XCBuildConfiguration;
- baseConfigurationReference = 8B3102DB11F0D65600FCF3E4 /* BreakpadRelease.xcconfig */;
- buildSettings = {
- GCC_PREPROCESSOR_DEFINITIONS = HAVE_MACH_O_NLIST_H;
- };
- name = Release;
- };
-/* End XCBuildConfiguration section */
-
-/* Begin XCConfigurationList section */
- 1DEB927408733DD40010E9CD /* Build configuration list for PBXNativeTarget "crash_report" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 1DEB927508733DD40010E9CD /* Debug */,
- 1DEB927608733DD40010E9CD /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "crash_report" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 1DEB927908733DD40010E9CD /* Debug */,
- 1DEB927A08733DD40010E9CD /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
-/* End XCConfigurationList section */
- };
- rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
-}
diff --git a/src/tools/mac/crash_report/on_demand_symbol_supplier.h b/src/tools/mac/crash_report/on_demand_symbol_supplier.h
deleted file mode 100644
index 3fbe108e..00000000
--- a/src/tools/mac/crash_report/on_demand_symbol_supplier.h
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// 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 Inc. 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.
-
-// on_demand_symbol_supplier.h: Provides a Symbol Supplier that will create
-// a breakpad symbol file on demand.
-
-#ifndef TOOLS_MAC_CRASH_REPORT_ON_DEMAND_SYMBOL_SUPPLIER_H__
-#define TOOLS_MAC_CRASH_REPORT_ON_DEMAND_SYMBOL_SUPPLIER_H__
-
-#include <map>
-#include <string>
-#include "google_breakpad/processor/symbol_supplier.h"
-
-namespace google_breakpad {
-
-using std::map;
-using std::string;
-class MinidumpModule;
-
-class OnDemandSymbolSupplier : public SymbolSupplier {
- public:
- // |search_dir| is the directory to search for alternative symbols with
- // the same name as the module in the minidump
- OnDemandSymbolSupplier(const string &search_dir,
- const string &symbol_search_dir);
- virtual ~OnDemandSymbolSupplier() {}
-
- // Returns the path to the symbol file for the given module.
- virtual SymbolResult GetSymbolFile(const CodeModule *module,
- const SystemInfo *system_info,
- string *symbol_file);
-
- // Returns the path to the symbol file for the given module.
- virtual SymbolResult GetSymbolFile(const CodeModule *module,
- const SystemInfo *system_info,
- string *symbol_file,
- string *symbol_data);
- // Allocates data buffer on heap, and takes the ownership of
- // the data buffer.
- virtual SymbolResult GetCStringSymbolData(const CodeModule *module,
- const SystemInfo *system_info,
- string *symbol_file,
- char **symbol_data,
- size_t *symbol_data_size);
-
- // Delete the data buffer allocated for module in GetCStringSymbolData().
- virtual void FreeSymbolData(const CodeModule *module);
-
- protected:
- // Search directory
- string search_dir_;
- string symbol_search_dir_;
-
- // When we create a symbol file for a module, save the name of the module
- // and the path to that module's symbol file.
- map<string, string> module_file_map_;
-
- // Map of allocated data buffers, keyed by module->code_file().
- map<string, char *> memory_buffers_;
-
- // Return the name for |module| This will be the value used as the key
- // to the |module_file_map_|.
- string GetNameForModule(const CodeModule *module);
-
- // Find the module on local system. If the module resides in a different
- // location than the full path in the minidump, this will be the location
- // used.
- string GetLocalModulePath(const CodeModule *module);
-
- // Return the full path for |module|.
- string GetModulePath(const CodeModule *module);
-
- // Return the path to the symbol file for |module|. If an empty string is
- // returned, then |module| doesn't have a symbol file.
- string GetModuleSymbolFile(const CodeModule *module);
-
- // Generate the breakpad symbol file for |module|. Return true if successful.
- // File is generated in /tmp.
- bool GenerateSymbolFile(const CodeModule *module,
- const SystemInfo *system_info);
-};
-
-} // namespace google_breakpad
-
-#endif // TOOLS_MAC_CRASH_REPORT_ON_DEMAND_SYMBOL_SUPPLIER_H__
diff --git a/src/tools/mac/crash_report/on_demand_symbol_supplier.mm b/src/tools/mac/crash_report/on_demand_symbol_supplier.mm
deleted file mode 100644
index 1955d266..00000000
--- a/src/tools/mac/crash_report/on_demand_symbol_supplier.mm
+++ /dev/null
@@ -1,314 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// 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 Inc. 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.
-
-#import <Foundation/Foundation.h>
-#include <sys/stat.h>
-#include <map>
-#include <string>
-#include <iostream>
-#include <fstream>
-#include <utility>
-
-#include "google_breakpad/processor/basic_source_line_resolver.h"
-#include "google_breakpad/processor/minidump.h"
-#include "google_breakpad/processor/system_info.h"
-#include "processor/pathname_stripper.h"
-
-#include "on_demand_symbol_supplier.h"
-#include "common/mac/dump_syms.h"
-
-using std::map;
-using std::string;
-
-using google_breakpad::OnDemandSymbolSupplier;
-using google_breakpad::PathnameStripper;
-using google_breakpad::SymbolSupplier;
-using google_breakpad::SystemInfo;
-
-OnDemandSymbolSupplier::OnDemandSymbolSupplier(const string &search_dir,
- const string &symbol_search_dir)
- : search_dir_(search_dir) {
- NSFileManager *mgr = [NSFileManager defaultManager];
- size_t length = symbol_search_dir.length();
- if (length) {
- // Load all sym files in symbol_search_dir into our module_file_map
- // A symbol file always starts with a line like this:
- // MODULE mac x86 BBF0A8F9BEADDD2048E6464001CA193F0 GoogleDesktopDaemon
- // or
- // MODULE mac ppc BBF0A8F9BEADDD2048E6464001CA193F0 GoogleDesktopDaemon
- const char *symbolSearchStr = symbol_search_dir.c_str();
- NSString *symbolSearchPath =
- [mgr stringWithFileSystemRepresentation:symbolSearchStr
- length:strlen(symbolSearchStr)];
- NSDirectoryEnumerator *dirEnum = [mgr enumeratorAtPath:symbolSearchPath];
- NSString *fileName;
- NSCharacterSet *hexSet =
- [NSCharacterSet characterSetWithCharactersInString:@"0123456789ABCDEF"];
- NSCharacterSet *newlineSet =
- [NSCharacterSet characterSetWithCharactersInString:@"\r\n"];
- while ((fileName = [dirEnum nextObject])) {
- // Check to see what type of file we have
- NSDictionary *attrib = [dirEnum fileAttributes];
- NSString *fileType = [attrib objectForKey:NSFileType];
- if ([fileType isEqualToString:NSFileTypeDirectory]) {
- // Skip subdirectories
- [dirEnum skipDescendents];
- } else {
- NSString *filePath = [symbolSearchPath stringByAppendingPathComponent:fileName];
- NSString *dataStr = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:NULL];
- if (dataStr) {
- // Check file to see if it is of appropriate type, and grab module
- // name.
- NSScanner *scanner = [NSScanner scannerWithString:dataStr];
- BOOL goodScan = [scanner scanString:@"MODULE mac " intoString:nil];
- if (goodScan) {
- goodScan = ([scanner scanString:@"x86 " intoString:nil] ||
- [scanner scanString:@"x86_64 " intoString:nil] ||
- [scanner scanString:@"ppc " intoString:nil]);
- if (goodScan) {
- NSString *moduleID;
- goodScan = [scanner scanCharactersFromSet:hexSet
- intoString:&moduleID];
- if (goodScan) {
- // Module IDs are always 33 chars long
- goodScan = [moduleID length] == 33;
- if (goodScan) {
- NSString *moduleName;
- goodScan = [scanner scanUpToCharactersFromSet:newlineSet
- intoString:&moduleName];
- if (goodScan) {
- goodScan = [moduleName length] > 0;
- if (goodScan) {
- const char *moduleNameStr = [moduleName UTF8String];
- const char *filePathStr = [filePath fileSystemRepresentation];
- // Map our file
- module_file_map_[moduleNameStr] = filePathStr;
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
-}
-
-SymbolSupplier::SymbolResult
-OnDemandSymbolSupplier::GetSymbolFile(const CodeModule *module,
- const SystemInfo *system_info,
- string *symbol_file) {
- string path(GetModuleSymbolFile(module));
-
- if (path.empty()) {
- if (!GenerateSymbolFile(module, system_info))
- return NOT_FOUND;
-
- path = GetModuleSymbolFile(module);
- }
-
- if (path.empty())
- return NOT_FOUND;
-
- *symbol_file = path;
- return FOUND;
-}
-
-SymbolSupplier::SymbolResult
-OnDemandSymbolSupplier::GetSymbolFile(const CodeModule *module,
- const SystemInfo *system_info,
- string *symbol_file,
- string *symbol_data) {
- SymbolSupplier::SymbolResult s = GetSymbolFile(module,
- system_info,
- symbol_file);
-
-
- if (s == FOUND) {
- std::ifstream in(symbol_file->c_str());
- getline(in, *symbol_data, std::string::traits_type::to_char_type(
- std::string::traits_type::eof()));
- in.close();
- }
-
- return s;
-}
-
-SymbolSupplier::SymbolResult
-OnDemandSymbolSupplier::GetCStringSymbolData(const CodeModule *module,
- const SystemInfo *system_info,
- string *symbol_file,
- char **symbol_data,
- size_t *symbol_data_size) {
- std::string symbol_data_string;
- SymbolSupplier::SymbolResult result = GetSymbolFile(module,
- system_info,
- symbol_file,
- &symbol_data_string);
- if (result == FOUND) {
- *symbol_data_size = symbol_data_string.size() + 1;
- *symbol_data = new char[*symbol_data_size];
- if (*symbol_data == NULL) {
- // Should return INTERRUPT on memory allocation failure.
- return INTERRUPT;
- }
- memcpy(*symbol_data, symbol_data_string.c_str(), symbol_data_string.size());
- (*symbol_data)[symbol_data_string.size()] = '\0';
- memory_buffers_.insert(make_pair(module->code_file(), *symbol_data));
- }
- return result;
-}
-
-void OnDemandSymbolSupplier::FreeSymbolData(const CodeModule *module) {
- map<string, char *>::iterator it = memory_buffers_.find(module->code_file());
- if (it != memory_buffers_.end()) {
- delete [] it->second;
- memory_buffers_.erase(it);
- }
-}
-
-string OnDemandSymbolSupplier::GetLocalModulePath(const CodeModule *module) {
- NSFileManager *mgr = [NSFileManager defaultManager];
- const char *moduleStr = module->code_file().c_str();
- NSString *modulePath =
- [mgr stringWithFileSystemRepresentation:moduleStr length:strlen(moduleStr)];
- const char *searchStr = search_dir_.c_str();
- NSString *searchDir =
- [mgr stringWithFileSystemRepresentation:searchStr length:strlen(searchStr)];
-
- if ([mgr fileExistsAtPath:modulePath])
- return module->code_file();
-
- // If the module is not found, try to start appending the components to the
- // search string and stop if a file (not dir) is found or all components
- // have been appended
- NSArray *pathComponents = [modulePath componentsSeparatedByString:@"/"];
- size_t count = [pathComponents count];
- NSMutableString *path = [NSMutableString string];
-
- for (size_t i = 0; i < count; ++i) {
- [path setString:searchDir];
-
- for (size_t j = 0; j < i + 1; ++j) {
- size_t idx = count - 1 - i + j;
- [path appendFormat:@"/%@", [pathComponents objectAtIndex:idx]];
- }
-
- BOOL isDir;
- if ([mgr fileExistsAtPath:path isDirectory:&isDir] && (!isDir)) {
- return [path fileSystemRepresentation];
- }
- }
-
- return "";
-}
-
-string OnDemandSymbolSupplier::GetModulePath(const CodeModule *module) {
- return module->code_file();
-}
-
-string OnDemandSymbolSupplier::GetNameForModule(const CodeModule *module) {
- return PathnameStripper::File(module->code_file());
-}
-
-string OnDemandSymbolSupplier::GetModuleSymbolFile(const CodeModule *module) {
- string name(GetNameForModule(module));
- map<string, string>::iterator result = module_file_map_.find(name);
-
- return (result == module_file_map_.end()) ? "" : (*result).second;
-}
-
-static float GetFileModificationTime(const char *path) {
- float result = 0;
- struct stat file_stat;
- if (stat(path, &file_stat) == 0)
- result = (float)file_stat.st_mtimespec.tv_sec +
- (float)file_stat.st_mtimespec.tv_nsec / 1.0e9f;
-
- return result;
-}
-
-bool OnDemandSymbolSupplier::GenerateSymbolFile(const CodeModule *module,
- const SystemInfo *system_info) {
- bool result = true;
- string name = GetNameForModule(module);
- string module_path = GetLocalModulePath(module);
- NSString *symbol_path = [NSString stringWithFormat:@"/tmp/%s.%s.sym",
- name.c_str(), system_info->cpu.c_str()];
-
- if (module_path.empty())
- return false;
-
- // Check if there's already a symbol file cached. Ensure that the file is
- // newer than the module. Otherwise, generate a new one.
- BOOL generate_file = YES;
- if ([[NSFileManager defaultManager] fileExistsAtPath:symbol_path]) {
- // Check if the module file is newer than the saved symbols
- float cache_time =
- GetFileModificationTime([symbol_path fileSystemRepresentation]);
- float module_time =
- GetFileModificationTime(module_path.c_str());
-
- if (cache_time > module_time)
- generate_file = NO;
- }
-
- if (generate_file) {
- DumpSymbols dump(ALL_SYMBOL_DATA, false);
- if (dump.Read(module_path)) {
- // What Breakpad calls "x86" should be given to the system as "i386".
- std::string architecture;
- if (system_info->cpu.compare("x86") == 0) {
- architecture = "i386";
- } else {
- architecture = system_info->cpu;
- }
-
- if (dump.SetArchitecture(architecture)) {
- std::fstream file([symbol_path fileSystemRepresentation],
- std::ios_base::out | std::ios_base::trunc);
- dump.WriteSymbolFile(file);
- } else {
- printf("Architecture %s not available for %s\n",
- system_info->cpu.c_str(), name.c_str());
- result = false;
- }
- } else {
- printf("Unable to open %s\n", module_path.c_str());
- result = false;
- }
- }
-
- // Add the mapping
- if (result)
- module_file_map_[name] = [symbol_path fileSystemRepresentation];
-
- return result;
-}
diff --git a/src/tools/mac/dump_syms/dump_syms_tool.cc b/src/tools/mac/dump_syms/dump_syms_tool.cc
index 6f68457b..2e05cbf3 100644
--- a/src/tools/mac/dump_syms/dump_syms_tool.cc
+++ b/src/tools/mac/dump_syms/dump_syms_tool.cc
@@ -1,7 +1,6 @@
// -*- mode: c++ -*-
-// Copyright (c) 2011, Google Inc.
-// All rights reserved.
+// Copyright 2011 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -13,7 +12,7 @@
// 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 Inc. nor the names of its
+// * 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.
//
@@ -37,6 +36,8 @@
#include <algorithm>
#include <iostream>
+#include <memory>
+#include <utility>
#include <vector>
#include "common/mac/dump_syms.h"
@@ -51,8 +52,14 @@ using std::vector;
struct Options {
Options()
- : srcPath(), dsymPath(), arch(), header_only(false),
- cfi(true), handle_inter_cu_refs(true) {}
+ : srcPath(),
+ dsymPath(),
+ arch(),
+ header_only(false),
+ cfi(true),
+ handle_inter_cu_refs(true),
+ handle_inlines(false),
+ enable_multiple(false) {}
string srcPath;
string dsymPath;
@@ -60,6 +67,8 @@ struct Options {
bool header_only;
bool cfi;
bool handle_inter_cu_refs;
+ bool handle_inlines;
+ bool enable_multiple;
};
static bool StackFrameEntryComparator(const Module::StackFrameEntry* a,
@@ -101,14 +110,47 @@ static void CopyCFIDataBetweenModules(Module* to_module,
// If the entry does not overlap, then it is safe to copy to |to_module|.
if (to_it == to_data.end() || (from_entry->address < (*to_it)->address &&
from_entry_end < (*to_it)->address)) {
- to_module->AddStackFrameEntry(new Module::StackFrameEntry(*from_entry));
+ to_module->AddStackFrameEntry(
+ std::make_unique<Module::StackFrameEntry>(*from_entry));
}
}
}
-static bool Start(const Options &options) {
- SymbolData symbol_data = options.cfi ? ALL_SYMBOL_DATA : NO_CFI;
- DumpSymbols dump_symbols(symbol_data, options.handle_inter_cu_refs);
+static bool SetArchitecture(DumpSymbols& dump_symbols,
+ const NXArchInfo* arch,
+ const std::string& filename) {
+ if (!dump_symbols.SetArchitecture(arch->cputype, arch->cpusubtype)) {
+ fprintf(stderr, "%s: no architecture '%s' is present in file.\n",
+ filename.c_str(), arch->name);
+ size_t available_size;
+ const SuperFatArch* available =
+ dump_symbols.AvailableArchitectures(&available_size);
+ if (available_size == 1)
+ fprintf(stderr, "the file's architecture is: ");
+ else
+ 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);
+ }
+ return false;
+ }
+ return true;
+}
+
+static bool Start(const Options& options) {
+ SymbolData symbol_data =
+ (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);
// 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
@@ -126,31 +168,9 @@ static bool Start(const Options &options) {
if (!dump_symbols.Read(primary_file))
return false;
- if (options.arch) {
- if (!dump_symbols.SetArchitecture(options.arch->cputype,
- options.arch->cpusubtype)) {
- fprintf(stderr, "%s: no architecture '%s' is present in file.\n",
- primary_file.c_str(), options.arch->name);
- size_t available_size;
- const SuperFatArch *available =
- dump_symbols.AvailableArchitectures(&available_size);
- if (available_size == 1)
- fprintf(stderr, "the file's architecture is: ");
- else
- 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);
- }
- return false;
- }
+ if (options.arch &&
+ !SetArchitecture(dump_symbols, options.arch, primary_file)) {
+ return false;
}
if (options.header_only)
@@ -168,6 +188,10 @@ static bool Start(const Options &options) {
if (!dump_symbols.Read(options.srcPath))
return false;
+ if (options.arch &&
+ !SetArchitecture(dump_symbols, options.arch, options.srcPath)) {
+ return false;
+ }
Module* cfi_module = NULL;
if (!dump_symbols.ReadSymbolData(&cfi_module))
return false;
@@ -201,6 +225,10 @@ static void Usage(int argc, const char *argv[]) {
"Mach-o file\n");
fprintf(stderr, "\t-c: Do not generate CFI section\n");
fprintf(stderr, "\t-r: Do not handle inter-compilation unit references\n");
+ fprintf(stderr, "\t-d: Generate INLINE and INLINE_ORIGIN records\n");
+ fprintf(stderr,
+ "\t-m: Enable writing the optional 'm' field on FUNC "
+ "and PUBLIC, denoting multiple symbols for the address.\n");
fprintf(stderr, "\t-h: Usage\n");
fprintf(stderr, "\t-?: Usage\n");
}
@@ -210,7 +238,7 @@ 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:chr?")) != -1) {
+ while ((ch = getopt(argc, (char* const*)argv, "ia:g:crdm?h")) != -1) {
switch (ch) {
case 'i':
options->header_only = true;
@@ -235,6 +263,12 @@ static void SetupOptions(int argc, const char *argv[], Options *options) {
case 'r':
options->handle_inter_cu_refs = false;
break;
+ case 'd':
+ options->handle_inlines = true;
+ break;
+ case 'm':
+ options->enable_multiple = 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
index 6e784ca7..b724cc74 100644
--- a/src/tools/mac/dump_syms/macho_dump.cc
+++ b/src/tools/mac/dump_syms/macho_dump.cc
@@ -1,5 +1,4 @@
-// Copyright (c) 2010, Google Inc.
-// All rights reserved.
+// Copyright 2010 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -11,7 +10,7 @@
// 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 Inc. nor the names of its
+// * 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.
//
@@ -60,7 +59,7 @@ namespace mach_o = google_breakpad::mach_o;
string program_name;
-int check_syscall(int result, const char *operation, const char *filename) {
+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,
@@ -73,7 +72,7 @@ int check_syscall(int result, const char *operation, const char *filename) {
class DumpSection: public mach_o::Reader::SectionHandler {
public:
DumpSection() : index_(0) { }
- bool HandleSection(const mach_o::Section &section) {
+ bool HandleSection(const mach_o::Section& section) {
printf(" section %d '%s' in segment '%s'\n"
" address: 0x%llx\n"
" alignment: 1 << %d B\n"
@@ -92,13 +91,13 @@ class DumpSection: public mach_o::Reader::SectionHandler {
class DumpCommand: public mach_o::Reader::LoadCommandHandler {
public:
- DumpCommand(mach_o::Reader *reader) : reader_(reader), index_(0) { }
+ DumpCommand(mach_o::Reader* reader) : reader_(reader), index_(0) { }
bool UnknownCommand(mach_o::LoadCommandType type,
- const ByteBuffer &contents) {
+ const ByteBuffer& contents) {
printf(" load command %d: %d", index_++, type);
return true;
}
- bool SegmentCommand(const mach_o::Segment &segment) {
+ 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"
@@ -115,24 +114,24 @@ class DumpCommand: public mach_o::Reader::LoadCommandHandler {
return reader_->WalkSegmentSections(segment, &dump_section);
}
private:
- mach_o::Reader *reader_;
+ mach_o::Reader* reader_;
int index_;
};
-void DumpFile(const char *filename) {
+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,
+ void* mapping = mmap(NULL, attributes.st_size, PROT_READ,
MAP_PRIVATE, fd, 0);
close(fd);
- check_syscall(mapping == (void *)-1 ? -1 : 0,
+ 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),
+ if (!fat_reader.Read(reinterpret_cast<uint8_t*>(mapping),
attributes.st_size)) {
exit(1);
}
@@ -140,14 +139,14 @@ void DumpFile(const char *filename) {
size_t object_files_size;
const SuperFatArch* super_fat_object_files =
fat_reader.object_files(&object_files_size);
- struct fat_arch *object_files;
+ 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 =
+ 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"
@@ -162,7 +161,7 @@ void DumpFile(const char *filename) {
name << filename;
if (object_files_size > 1)
name << ", object file #" << i;
- ByteBuffer file_contents(reinterpret_cast<uint8_t *>(mapping)
+ ByteBuffer file_contents(reinterpret_cast<uint8_t*>(mapping)
+ file.offset, file.size);
mach_o::Reader::Reporter reporter(name.str());
mach_o::Reader reader(&reporter);
@@ -170,7 +169,7 @@ void DumpFile(const char *filename) {
exit(1);
}
- const NXArchInfo *macho_arch_info =
+ const NXArchInfo* macho_arch_info =
NXGetArchInfoFromCpuType(reader.cpu_type(),
reader.cpu_subtype());
printf(" Mach-O header:\n"
@@ -190,7 +189,7 @@ void DumpFile(const char *filename) {
} // namespace
-int main(int argc, char **argv) {
+int main(int argc, char** argv) {
program_name = google_breakpad::BaseName(argv[0]);
if (argc == 1) {
fprintf(stderr, "Usage: %s FILE ...\n"
diff --git a/src/tools/mac/symupload/minidump_upload.m b/src/tools/mac/symupload/minidump_upload.m
deleted file mode 100644
index 741ad765..00000000
--- a/src/tools/mac/symupload/minidump_upload.m
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// 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 Inc. 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.
-
-// minidump_upload.m: Upload a minidump to a HTTP server. The upload is sent as
-// a multipart/form-data POST request with the following parameters:
-// prod: the product name
-// ver: the product version
-// symbol_file: the breakpad format symbol file
-
-#import <unistd.h>
-
-#import <Foundation/Foundation.h>
-
-#import "common/mac/HTTPMultipartUpload.h"
-
-typedef struct {
- NSString *minidumpPath;
- NSString *uploadURLStr;
- NSString *product;
- NSString *version;
- BOOL success;
-} Options;
-
-//=============================================================================
-static void Start(Options *options) {
- NSURL *url = [NSURL URLWithString:options->uploadURLStr];
- HTTPMultipartUpload *ul = [[HTTPMultipartUpload alloc] initWithURL:url];
- NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
-
- // Add parameters
- [parameters setObject:options->product forKey:@"prod"];
- [parameters setObject:options->version forKey:@"ver"];
- [ul setParameters:parameters];
-
- // Add file
- [ul addFileAtPath:options->minidumpPath name:@"upload_file_minidump"];
-
- // Send it
- NSError *error = nil;
- NSData *data = [ul send:&error];
- NSString *result = [[NSString alloc] initWithData:data
- encoding:NSUTF8StringEncoding];
-
- NSLog(@"Send: %@", error ? [error description] : @"No Error");
- NSLog(@"Response: %ld", (long)[[ul response] statusCode]);
- NSLog(@"Result: %lu bytes\n%@", (unsigned long)[data length], result);
-
- [result release];
- [ul release];
- options->success = !error;
-}
-
-//=============================================================================
-static void
-Usage(int argc, const char *argv[]) {
- fprintf(stderr, "Submit minidump information.\n");
- fprintf(stderr, "Usage: %s -p <product> -v <version> <minidump> "
- "<upload-URL>\n", argv[0]);
- fprintf(stderr, "<minidump> should be a minidump.\n");
- fprintf(stderr, "<upload-URL> is the destination for the upload\n");
-
- fprintf(stderr, "\t-h: Usage\n");
- fprintf(stderr, "\t-?: Usage\n");
-}
-
-//=============================================================================
-static void
-SetupOptions(int argc, const char *argv[], Options *options) {
- extern int optind;
- char ch;
-
- while ((ch = getopt(argc, (char * const *)argv, "p:v:h?")) != -1) {
- switch (ch) {
- case 'p':
- options->product = [NSString stringWithUTF8String:optarg];
- break;
- case 'v':
- options->version = [NSString stringWithUTF8String:optarg];
- break;
-
- default:
- Usage(argc, argv);
- exit(0);
- break;
- }
- }
-
- if ((argc - optind) != 2) {
- fprintf(stderr, "%s: Missing symbols file and/or upload-URL\n", argv[0]);
- Usage(argc, argv);
- exit(1);
- }
-
- options->minidumpPath = [NSString stringWithUTF8String:argv[optind]];
- options->uploadURLStr = [NSString stringWithUTF8String:argv[optind + 1]];
-}
-
-//=============================================================================
-int main (int argc, const char * argv[]) {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- Options options;
-
- bzero(&options, sizeof(Options));
- SetupOptions(argc, argv, &options);
- Start(&options);
-
- [pool release];
- return options.success ? 0 : 1;
-}
diff --git a/src/tools/mac/symupload/symupload.m b/src/tools/mac/symupload/symupload.m
deleted file mode 100644
index a7cce7b0..00000000
--- a/src/tools/mac/symupload/symupload.m
+++ /dev/null
@@ -1,204 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// 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 Inc. 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.
-
-// symupload.m: Upload a symbol file to a HTTP server. The upload is sent as
-// a multipart/form-data POST request with the following parameters:
-// code_file: the basename of the module, e.g. "app"
-// debug_file: the basename of the debugging file, e.g. "app"
-// debug_identifier: the debug file's identifier, usually consisting of
-// the guid and age embedded in the pdb, e.g.
-// "11111111BBBB3333DDDD555555555555F"
-// os: the operating system that the module was built for
-// cpu: the CPU that the module was built for (x86 or ppc)
-// symbol_file: the contents of the breakpad-format symbol file
-
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <Foundation/Foundation.h>
-#include "HTTPMultipartUpload.h"
-
-typedef struct {
- NSString *symbolsPath;
- NSString *uploadURLStr;
- BOOL success;
-} Options;
-
-//=============================================================================
-static NSArray *ModuleDataForSymbolFile(NSString *file) {
- NSFileHandle *fh = [NSFileHandle fileHandleForReadingAtPath:file];
- NSData *data = [fh readDataOfLength:1024];
- NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
- NSScanner *scanner = [NSScanner scannerWithString:str];
- NSString *line;
- NSMutableArray *parts = nil;
- const int MODULE_ID_INDEX = 3;
-
- if ([scanner scanUpToString:@"\n" intoString:&line]) {
- parts = [[NSMutableArray alloc] init];
- NSScanner *moduleInfoScanner = [NSScanner scannerWithString:line];
- NSString *moduleInfo;
- // Get everything BEFORE the module name. None of these properties
- // can have spaces.
- for (int i = 0; i <= MODULE_ID_INDEX; i++) {
- [moduleInfoScanner scanUpToString:@" " intoString:&moduleInfo];
- [parts addObject:moduleInfo];
- }
-
- // Now get the module name. This can have a space so we scan to
- // the end of the line.
- [moduleInfoScanner scanUpToString:@"\n" intoString:&moduleInfo];
- [parts addObject:moduleInfo];
- }
-
- [str release];
-
- return parts;
-}
-
-//=============================================================================
-static void Start(Options *options) {
- NSURL *url = [NSURL URLWithString:options->uploadURLStr];
- HTTPMultipartUpload *ul = [[HTTPMultipartUpload alloc] initWithURL:url];
- NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
- NSArray *moduleParts = ModuleDataForSymbolFile(options->symbolsPath);
- NSMutableString *compactedID =
- [NSMutableString stringWithString:[moduleParts objectAtIndex:3]];
- [compactedID replaceOccurrencesOfString:@"-" withString:@"" options:0
- range:NSMakeRange(0, [compactedID length])];
-
- // Add parameters
- [parameters setObject:compactedID forKey:@"debug_identifier"];
-
- // MODULE <os> <cpu> <uuid> <module-name>
- // 0 1 2 3 4
- [parameters setObject:[moduleParts objectAtIndex:1] forKey:@"os"];
- [parameters setObject:[moduleParts objectAtIndex:2] forKey:@"cpu"];
- [parameters setObject:[moduleParts objectAtIndex:4] forKey:@"debug_file"];
- [parameters setObject:[moduleParts objectAtIndex:4] forKey:@"code_file"];
- [ul setParameters:parameters];
-
- NSArray *keys = [parameters allKeys];
- int count = [keys count];
- for (int i = 0; i < count; ++i) {
- NSString *key = [keys objectAtIndex:i];
- NSString *value = [parameters objectForKey:key];
- fprintf(stdout, "'%s' = '%s'\n", [key UTF8String],
- [value UTF8String]);
- }
-
- // Add file
- [ul addFileAtPath:options->symbolsPath name:@"symbol_file"];
-
- // Send it
- NSError *error = nil;
- NSData *data = [ul send:&error];
- NSString *result = [[NSString alloc] initWithData:data
- encoding:NSUTF8StringEncoding];
- int status = [[ul response] statusCode];
-
- fprintf(stdout, "Send: %s\n", error ? [[error description] UTF8String] :
- "No Error");
- fprintf(stdout, "Response: %d\n", status);
- fprintf(stdout, "Result: %lu bytes\n%s\n",
- (unsigned long)[data length], [result UTF8String]);
-
- [result release];
- [ul release];
- options->success = !error && status==200;
-}
-
-//=============================================================================
-static void
-Usage(int argc, const char *argv[]) {
- fprintf(stderr, "Submit symbol information.\n");
- fprintf(stderr, "Usage: %s <symbols> <upload-URL>\n", argv[0]);
- fprintf(stderr, "<symbols> should be created by using the dump_syms tool.\n");
- fprintf(stderr, "<upload-URL> is the destination for the upload\n");
- fprintf(stderr, "\t-h: Usage\n");
- fprintf(stderr, "\t-?: Usage\n");
-}
-
-//=============================================================================
-static void
-SetupOptions(int argc, const char *argv[], Options *options) {
- extern int optind;
- char ch;
-
- while ((ch = getopt(argc, (char * const *)argv, "h?")) != -1) {
- switch (ch) {
- default:
- Usage(argc, argv);
- exit(0);
- break;
- }
- }
-
- if ((argc - optind) != 2) {
- fprintf(stderr, "%s: Missing symbols file and/or upload-URL\n", argv[0]);
- Usage(argc, argv);
- exit(1);
- }
-
- int fd = open(argv[optind], O_RDONLY);
- if (fd < 0) {
- fprintf(stderr, "%s: %s: %s\n", argv[0], argv[optind], strerror(errno));
- exit(1);
- }
-
- struct stat statbuf;
- if (fstat(fd, &statbuf) < 0) {
- fprintf(stderr, "%s: %s: %s\n", argv[0], argv[optind], strerror(errno));
- close(fd);
- exit(1);
- }
- close(fd);
-
- if (!S_ISREG(statbuf.st_mode)) {
- fprintf(stderr, "%s: %s: not a regular file\n", argv[0], argv[optind]);
- exit(1);
- }
-
- options->symbolsPath = [NSString stringWithUTF8String:argv[optind]];
- options->uploadURLStr = [NSString stringWithUTF8String:argv[optind + 1]];
-}
-
-//=============================================================================
-int main (int argc, const char * argv[]) {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- Options options;
-
- bzero(&options, sizeof(Options));
- SetupOptions(argc, argv, &options);
- Start(&options);
-
- [pool release];
- return options.success ? 0 : 1;
-}
diff --git a/src/tools/mac/symupload/symupload.mm b/src/tools/mac/symupload/symupload.mm
new file mode 100644
index 00000000..521b811f
--- /dev/null
+++ b/src/tools/mac/symupload/symupload.mm
@@ -0,0 +1,474 @@
+// Copyright 2006 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.
+
+// symupload.mm: Upload a symbol file to a HTTP server. The upload is sent as
+// a multipart/form-data POST request with the following parameters:
+// code_file: the basename of the module, e.g. "app"
+// debug_file: the basename of the debugging file, e.g. "app"
+// debug_identifier: the debug file's identifier, usually consisting of
+// the guid and age embedded in the pdb, e.g.
+// "11111111BBBB3333DDDD555555555555F"
+// os: the operating system that the module was built for
+// cpu: the CPU that the module was built for (x86 or ppc)
+// symbol_file: the contents of the breakpad-format symbol file
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <Foundation/Foundation.h>
+
+#include "HTTPMultipartUpload.h"
+#include "HTTPPutRequest.h"
+#include "SymbolCollectorClient.h"
+#include "common/mac/dump_syms.h"
+
+using google_breakpad::DumpSymbols;
+
+NSString* const kBreakpadSymbolType = @"BREAKPAD";
+NSString* const kMachOSymbolType = @"MACHO";
+NSString* const kDSYMSymbolType = @"DSYM";
+
+typedef enum { kSymUploadProtocolV1, kSymUploadProtocolV2 } SymUploadProtocol;
+
+typedef enum {
+ kResultSuccess = 0,
+ kResultFailure = 1,
+ kResultAlreadyExists = 2
+} Result;
+
+typedef struct {
+ NSString* symbolsPath;
+ NSString* uploadURLStr;
+ SymUploadProtocol symUploadProtocol;
+ NSString* apiKey;
+ BOOL force;
+ Result result;
+ NSString* type;
+ NSString* codeFile;
+ NSString* debugID;
+ NSString* productName;
+} Options;
+
+//=============================================================================
+static NSArray* ModuleDataForSymbolFile(NSString* file) {
+ NSFileHandle* fh = [NSFileHandle fileHandleForReadingAtPath:file];
+ NSData* data = [fh readDataOfLength:1024];
+ NSString* str = [[NSString alloc] initWithData:data
+ encoding:NSUTF8StringEncoding];
+ NSScanner* scanner = [NSScanner scannerWithString:str];
+ NSString* line;
+ NSMutableArray* parts = nil;
+ const int MODULE_ID_INDEX = 3;
+
+ if ([scanner scanUpToString:@"\n" intoString:&line]) {
+ parts = [[NSMutableArray alloc] init];
+ NSScanner* moduleInfoScanner = [NSScanner scannerWithString:line];
+ NSString* moduleInfo;
+ // Get everything BEFORE the module name. None of these properties
+ // can have spaces.
+ for (int i = 0; i <= MODULE_ID_INDEX; i++) {
+ [moduleInfoScanner scanUpToString:@" " intoString:&moduleInfo];
+ [parts addObject:moduleInfo];
+ }
+
+ // Now get the module name. This can have a space so we scan to
+ // the end of the line.
+ [moduleInfoScanner scanUpToString:@"\n" intoString:&moduleInfo];
+ [parts addObject:moduleInfo];
+ }
+
+ [str release];
+
+ return parts;
+}
+
+//=============================================================================
+static void StartSymUploadProtocolV1(Options* options,
+ NSString* OS,
+ NSString* CPU,
+ NSString* debugID,
+ NSString* debugFile) {
+ NSURL* url = [NSURL URLWithString:options->uploadURLStr];
+ HTTPMultipartUpload* ul = [[HTTPMultipartUpload alloc] initWithURL:url];
+ NSMutableDictionary* parameters = [NSMutableDictionary dictionary];
+
+ // Add parameters
+ [parameters setObject:debugID forKey:@"debug_identifier"];
+ [parameters setObject:OS forKey:@"os"];
+ [parameters setObject:CPU forKey:@"cpu"];
+ [parameters setObject:debugFile forKey:@"debug_file"];
+ [parameters setObject:debugFile forKey:@"code_file"];
+ [ul setParameters:parameters];
+
+ NSArray* keys = [parameters allKeys];
+ int count = [keys count];
+ for (int i = 0; i < count; ++i) {
+ NSString* key = [keys objectAtIndex:i];
+ NSString* value = [parameters objectForKey:key];
+ fprintf(stdout, "'%s' = '%s'\n", [key UTF8String], [value UTF8String]);
+ }
+
+ // Add file
+ [ul addFileAtPath:options->symbolsPath name:@"symbol_file"];
+
+ // Send it
+ NSError* error = nil;
+ NSData* data = [ul send:&error];
+ NSString* result = [[NSString alloc] initWithData:data
+ encoding:NSUTF8StringEncoding];
+ int status = [[ul response] statusCode];
+
+ fprintf(stdout, "Send: %s\n",
+ error ? [[error description] UTF8String] : "No Error");
+ fprintf(stdout, "Response: %d\n", status);
+ fprintf(stdout, "Result: %lu bytes\n%s\n", (unsigned long)[data length],
+ [result UTF8String]);
+
+ [result release];
+ [ul release];
+ options->result = (!error && status == 200) ? kResultSuccess : kResultFailure;
+}
+
+//=============================================================================
+static void StartSymUploadProtocolV2(Options* options,
+ NSString* debugID,
+ NSString* debugFile) {
+ options->result = kResultFailure;
+
+ // Only check status of BREAKPAD symbols, because the v2 protocol doesn't
+ // (yet) have a way to check status of other symbol types.
+ if (!options->force && [options->type isEqualToString:kBreakpadSymbolType]) {
+ SymbolStatus symbolStatus =
+ [SymbolCollectorClient checkSymbolStatusOnServer:options->uploadURLStr
+ withAPIKey:options->apiKey
+ withDebugFile:debugFile
+ withDebugID:debugID];
+ if (symbolStatus == SymbolStatusFound) {
+ fprintf(stdout, "Symbol file already exists, upload aborted."
+ " Use \"-f\" to overwrite.\n");
+ options->result = kResultAlreadyExists;
+ return;
+ } else if (symbolStatus == SymbolStatusUnknown) {
+ fprintf(stdout, "Failed to get check for existing symbol.\n");
+ return;
+ }
+ }
+
+ UploadURLResponse* URLResponse =
+ [SymbolCollectorClient createUploadURLOnServer:options->uploadURLStr
+ withAPIKey:options->apiKey];
+ if (URLResponse == nil) {
+ return;
+ }
+
+ NSURL* uploadURL = [NSURL URLWithString:[URLResponse uploadURL]];
+ HTTPPutRequest* putRequest = [[HTTPPutRequest alloc] initWithURL:uploadURL];
+ [putRequest setFile:options->symbolsPath];
+
+ NSError* error = nil;
+ NSData* data = [putRequest send:&error];
+ NSString* result = [[NSString alloc] initWithData:data
+ encoding:NSUTF8StringEncoding];
+ int responseCode = [[putRequest response] statusCode];
+ [putRequest release];
+
+ if (error || responseCode != 200) {
+ fprintf(stdout, "Failed to upload symbol file.\n");
+ fprintf(stdout, "Response code: %d\n", responseCode);
+ fprintf(stdout, "Response:\n");
+ fprintf(stdout, "%s\n", [result UTF8String]);
+ return;
+ }
+
+ CompleteUploadResult completeUploadResult =
+ [SymbolCollectorClient completeUploadOnServer:options->uploadURLStr
+ withAPIKey:options->apiKey
+ withUploadKey:[URLResponse uploadKey]
+ withDebugFile:debugFile
+ withDebugID:debugID
+ withType:options->type
+ withProductName:options->productName];
+ [URLResponse release];
+ if (completeUploadResult == CompleteUploadResultError) {
+ fprintf(stdout, "Failed to complete upload.\n");
+ return;
+ } else if (completeUploadResult == CompleteUploadResultDuplicateData) {
+ fprintf(stdout, "Uploaded file checksum matched existing file checksum,"
+ " no change necessary.\n");
+ } else {
+ fprintf(stdout, "Successfully sent the symbol file.\n");
+ }
+ options->result = kResultSuccess;
+}
+
+//=============================================================================
+static void Start(Options* options) {
+ // If non-BREAKPAD upload special-case.
+ if (![options->type isEqualToString:kBreakpadSymbolType]) {
+ StartSymUploadProtocolV2(options, options->debugID, options->codeFile);
+ return;
+ }
+
+ NSArray* moduleParts = ModuleDataForSymbolFile(options->symbolsPath);
+ // MODULE <os> <cpu> <uuid> <module-name>
+ // 0 1 2 3 4
+ NSString* OS = [moduleParts objectAtIndex:1];
+ NSString* CPU = [moduleParts objectAtIndex:2];
+ NSMutableString* debugID =
+ [NSMutableString stringWithString:[moduleParts objectAtIndex:3]];
+ [debugID replaceOccurrencesOfString:@"-"
+ withString:@""
+ options:0
+ range:NSMakeRange(0, [debugID length])];
+ NSString* debugFile = [moduleParts objectAtIndex:4];
+
+ if (options->symUploadProtocol == kSymUploadProtocolV1) {
+ StartSymUploadProtocolV1(options, OS, CPU, debugID, debugFile);
+ } else if (options->symUploadProtocol == kSymUploadProtocolV2) {
+ StartSymUploadProtocolV2(options, debugID, debugFile);
+ }
+}
+
+//=============================================================================
+static void Usage(int argc, const char* argv[]) {
+ fprintf(stderr, "Submit symbol information.\n");
+ fprintf(stderr, "Usage: %s [options] <symbol-file> <upload-URL>\n", argv[0]);
+ fprintf(stderr, "<symbol-file> should be created by using the dump_syms "
+ "tool.\n");
+ fprintf(stderr, "<upload-URL> is the destination for the upload.\n");
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, "\t-p <protocol>: protocol to use for upload, accepts "
+ "[\"sym-upload-v1\", \"sym-upload-v2\"]. Default is "
+ "\"sym-upload-v1\".\n");
+ fprintf(stderr, "\t-k <api-key>: secret for authentication with upload "
+ "server. [Only in sym-upload-v2 protocol mode]\n");
+ fprintf(stderr, "\t-f: Overwrite symbol file on server if already present. "
+ "[Only in sym-upload-v2 protocol mode]\n");
+ fprintf(
+ stderr,
+ "\t-t: <symbol-type> Explicitly set symbol upload type ("
+ "default is 'breakpad').\n"
+ "\t One of ['breakpad', 'elf', 'pe', 'macho', 'debug_only', 'dwp', "
+ "'dsym', 'pdb'].\n"
+ "\t Note: When this flag is set to anything other than 'breakpad', then "
+ "the '-c' and '-i' flags must also be set.\n");
+ fprintf(stderr, "\t-c: <code-file> Explicitly set 'code_file' for symbol "
+ "upload (basename of executable).\n");
+ fprintf(stderr, "\t-i: <debug-id> Explicitly set 'debug_id' for symbol "
+ "upload (typically build ID of executable). The debug-id for "
+ "symbol-types 'dsym' and 'macho' will be determined "
+ "automatically. \n");
+ fprintf(stderr, "\t-n: <product-name> Optionally set 'product_name' for "
+ "symbol upload\n");
+ fprintf(stderr, "\t-h: Usage\n");
+ fprintf(stderr, "\t-?: Usage\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Exit codes:\n");
+ fprintf(stderr, "\t%d: Success\n", kResultSuccess);
+ fprintf(stderr, "\t%d: Failure\n", kResultFailure);
+ fprintf(stderr,
+ "\t%d: Symbol file already exists on server (and -f was not "
+ "specified).\n",
+ kResultAlreadyExists);
+ fprintf(stderr,
+ "\t [This exit code will only be returned by the sym-upload-v2 "
+ "protocol.\n");
+ fprintf(stderr,
+ "\t The sym-upload-v1 protocol can return either Success or "
+ "Failure\n");
+ fprintf(stderr, "\t in this case, and the action taken by the server is "
+ "unspecified.]\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Examples:\n");
+ fprintf(stderr, " With 'sym-upload-v1':\n");
+ fprintf(stderr, " %s path/to/symbol_file http://myuploadserver\n",
+ argv[0]);
+ fprintf(stderr, " With 'sym-upload-v2':\n");
+ fprintf(stderr, " [Defaulting to symbol type 'BREAKPAD']\n");
+ fprintf(stderr,
+ " %s -p sym-upload-v2 -k mysecret123! "
+ "path/to/symbol_file http://myuploadserver\n",
+ argv[0]);
+ fprintf(stderr, " [Explicitly set symbol type to 'macho']\n");
+ fprintf(stderr,
+ " %s -p sym-upload-v2 -k mysecret123! -t macho "
+ "-c app -i 11111111BBBB3333DDDD555555555555F "
+ "path/to/symbol_file http://myuploadserver\n",
+ argv[0]);
+}
+
+//=============================================================================
+static void SetupOptions(int argc, const char* argv[], Options* options) {
+ // Set default options values.
+ options->symUploadProtocol = kSymUploadProtocolV1;
+ options->apiKey = nil;
+ options->type = kBreakpadSymbolType;
+ options->codeFile = nil;
+ options->debugID = nil;
+ options->force = NO;
+ options->productName = nil;
+
+ extern int optind;
+ int ch;
+
+ while ((ch = getopt(argc, (char* const*)argv, "p:k:t:c:i:n:hf?")) != -1) {
+ switch (ch) {
+ case 'p':
+ if (strcmp(optarg, "sym-upload-v2") == 0) {
+ options->symUploadProtocol = kSymUploadProtocolV2;
+ break;
+ } else if (strcmp(optarg, "sym-upload-v1") == 0) {
+ // This is already the default but leave in case that changes.
+ options->symUploadProtocol = kSymUploadProtocolV1;
+ break;
+ }
+ Usage(argc, argv);
+ exit(0);
+ break;
+ case 'k':
+ options->apiKey = [NSString stringWithCString:optarg
+ encoding:NSASCIIStringEncoding];
+ break;
+ case 't': {
+ // This is really an enum, so treat as upper-case for consistency with
+ // enum naming convention on server-side.
+ options->type = [[NSString stringWithCString:optarg
+ encoding:NSASCIIStringEncoding]
+ uppercaseString];
+ break;
+ }
+ case 'c':
+ options->codeFile = [NSString stringWithCString:optarg
+ encoding:NSASCIIStringEncoding];
+ break;
+ case 'i':
+ options->debugID = [NSString stringWithCString:optarg
+ encoding:NSASCIIStringEncoding];
+ break;
+ case 'n':
+ options->productName =
+ [NSString stringWithCString:optarg
+ encoding:NSASCIIStringEncoding];
+ break;
+ case 'f':
+ options->force = YES;
+ break;
+ default:
+ Usage(argc, argv);
+ exit(0);
+ break;
+ }
+ }
+
+ if ((argc - optind) != 2) {
+ fprintf(stderr, "%s: Missing symbols file and/or upload-URL\n", argv[0]);
+ Usage(argc, argv);
+ exit(1);
+ }
+
+ int fd = open(argv[optind], O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "%s: %s: %s\n", argv[0], argv[optind], strerror(errno));
+ exit(1);
+ }
+
+ struct stat statbuf;
+ if (fstat(fd, &statbuf) < 0) {
+ fprintf(stderr, "%s: %s: %s\n", argv[0], argv[optind], strerror(errno));
+ close(fd);
+ exit(1);
+ }
+ close(fd);
+
+ if (!S_ISREG(statbuf.st_mode)) {
+ fprintf(stderr, "%s: %s: not a regular file\n", argv[0], argv[optind]);
+ exit(1);
+ }
+
+ bool isBreakpadUpload = [options->type isEqualToString:kBreakpadSymbolType];
+ bool hasCodeFile = options->codeFile != nil;
+ bool hasDebugID = options->debugID != nil;
+ if (isBreakpadUpload && (hasCodeFile || hasDebugID)) {
+ fprintf(stderr, "\n");
+ fprintf(stderr,
+ "%s: -c and -i should only be specified for non-breakpad "
+ "symbol upload types.\n",
+ argv[0]);
+ fprintf(stderr, "\n");
+ Usage(argc, argv);
+ exit(1);
+ }
+
+ if (!isBreakpadUpload && hasCodeFile && !hasDebugID &&
+ ([options->type isEqualToString:kMachOSymbolType] ||
+ [options->type isEqualToString:kDSYMSymbolType])) {
+ DumpSymbols dump_symbols(SYMBOLS_AND_FILES | INLINES, false);
+ if (dump_symbols.Read(argv[optind])) {
+ std::string identifier = dump_symbols.Identifier();
+ if (identifier.empty()) {
+ fprintf(stderr, "\n");
+ fprintf(stderr,
+ "%s: Unable to determine debug-id. Please specify with '-i'.\n",
+ argv[0]);
+ fprintf(stderr, "\n");
+ Usage(argc, argv);
+ exit(1);
+ }
+ options->debugID = [NSString stringWithUTF8String:identifier.c_str()];
+ hasDebugID = true;
+ }
+ }
+
+ if (!isBreakpadUpload && (!hasCodeFile || !hasDebugID)) {
+ fprintf(stderr, "\n");
+ fprintf(stderr,
+ "%s: -c and -i must be specified for non-breakpad "
+ "symbol upload types.\n",
+ argv[0]);
+ fprintf(stderr, "\n");
+ Usage(argc, argv);
+ exit(1);
+ }
+
+ options->symbolsPath = [NSString stringWithUTF8String:argv[optind]];
+ options->uploadURLStr = [NSString stringWithUTF8String:argv[optind + 1]];
+}
+
+//=============================================================================
+int main(int argc, const char* argv[]) {
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ Options options;
+
+ bzero(&options, sizeof(Options));
+ SetupOptions(argc, argv, &options);
+ Start(&options);
+
+ [pool release];
+ return options.result;
+}
diff --git a/src/tools/mac/symupload/symupload.xcodeproj/project.pbxproj b/src/tools/mac/symupload/symupload.xcodeproj/project.pbxproj
index a6a78dc5..903c66f1 100644
--- a/src/tools/mac/symupload/symupload.xcodeproj/project.pbxproj
+++ b/src/tools/mac/symupload/symupload.xcodeproj/project.pbxproj
@@ -7,9 +7,38 @@
objects = {
/* Begin PBXBuildFile section */
+ 5B6060BD222716FC0015F0A0 /* HTTPRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B6060BC222716FC0015F0A0 /* HTTPRequest.m */; };
+ 5B6060C02227201B0015F0A0 /* HTTPPutRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B6060BF2227201B0015F0A0 /* HTTPPutRequest.m */; };
+ 5B6060C7222735E50015F0A0 /* HTTPGetRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B6060C6222735E50015F0A0 /* HTTPGetRequest.m */; };
+ 5B6060CA2227374E0015F0A0 /* HTTPSimplePostRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B6060C92227374E0015F0A0 /* HTTPSimplePostRequest.m */; };
+ 5B6060D022273BDA0015F0A0 /* SymbolCollectorClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B6060CF22273BDA0015F0A0 /* SymbolCollectorClient.m */; };
+ 5B97447524D0AA5F000C71F5 /* encoding_util.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B97447424D0AA5F000C71F5 /* encoding_util.m */; };
8B31022C11F0CEBD00FCF3E4 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; };
- 8DD76F9A0486AA7600D96B5E /* symupload.m in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* symupload.m */; settings = {ATTRIBUTES = (); }; };
+ 8DD76F9A0486AA7600D96B5E /* symupload.mm in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* symupload.mm */; settings = {ATTRIBUTES = (); }; };
8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 08FB779EFE84155DC02AAC07 /* Foundation.framework */; };
+ 930DA19225ED543A008558E3 /* dump_syms.cc in Sources */ = {isa = PBXBuildFile; fileRef = 930DA19025ED543A008558E3 /* dump_syms.cc */; };
+ 930DA22C25ED55A9008558E3 /* module.cc in Sources */ = {isa = PBXBuildFile; fileRef = 930DA21F25ED55A8008558E3 /* module.cc */; };
+ 930DA22D25ED55A9008558E3 /* dwarf_cfi_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = 930DA22325ED55A8008558E3 /* dwarf_cfi_to_module.cc */; };
+ 930DA22E25ED55A9008558E3 /* stabs_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = 930DA22525ED55A8008558E3 /* stabs_to_module.cc */; };
+ 930DA22F25ED55A9008558E3 /* language.cc in Sources */ = {isa = PBXBuildFile; fileRef = 930DA22625ED55A9008558E3 /* language.cc */; };
+ 930DA23125ED55A9008558E3 /* dwarf_line_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = 930DA22A25ED55A9008558E3 /* dwarf_line_to_module.cc */; };
+ 930DA23225ED55A9008558E3 /* dwarf_cu_to_module.cc in Sources */ = {isa = PBXBuildFile; fileRef = 930DA22B25ED55A9008558E3 /* dwarf_cu_to_module.cc */; };
+ 930DA23725ED55B6008558E3 /* stabs_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = 930DA23625ED55B6008558E3 /* stabs_reader.cc */; };
+ 930DA24225ED55BF008558E3 /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = 930DA23A25ED55BF008558E3 /* macho_id.cc */; };
+ 930DA24325ED55BF008558E3 /* macho_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 930DA23C25ED55BF008558E3 /* macho_utilities.cc */; };
+ 930DA24425ED55BF008558E3 /* macho_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = 930DA23F25ED55BF008558E3 /* macho_reader.cc */; };
+ 930DA24525ED55BF008558E3 /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = 930DA24125ED55BF008558E3 /* macho_walker.cc */; };
+ 930DA25C25ED56DB008558E3 /* dwarf_range_list_handler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 930DA24D25ED56DB008558E3 /* dwarf_range_list_handler.cc */; };
+ 930DA25D25ED56DB008558E3 /* cfi_assembler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 930DA24E25ED56DB008558E3 /* cfi_assembler.cc */; };
+ 930DA25E25ED56DB008558E3 /* elf_reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = 930DA25225ED56DB008558E3 /* elf_reader.cc */; };
+ 930DA25F25ED56DB008558E3 /* dwarf2diehandler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 930DA25325ED56DB008558E3 /* dwarf2diehandler.cc */; };
+ 930DA26025ED56DB008558E3 /* dwarf2reader.cc in Sources */ = {isa = PBXBuildFile; fileRef = 930DA25625ED56DB008558E3 /* dwarf2reader.cc */; };
+ 930DA26125ED56DB008558E3 /* bytereader.cc in Sources */ = {isa = PBXBuildFile; fileRef = 930DA25925ED56DB008558E3 /* bytereader.cc */; };
+ 930DA26925ED56FF008558E3 /* test_assembler.cc in Sources */ = {isa = PBXBuildFile; fileRef = 930DA26825ED56FF008558E3 /* test_assembler.cc */; };
+ 930DA26E25ED571F008558E3 /* arch_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 930DA26D25ED571F008558E3 /* arch_utilities.cc */; };
+ 930DA27825ED572D008558E3 /* path_helper.cc in Sources */ = {isa = PBXBuildFile; fileRef = 930DA27125ED572C008558E3 /* path_helper.cc */; };
+ 930DA27925ED572D008558E3 /* file_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = 930DA27525ED572C008558E3 /* file_id.cc */; };
+ 930DA27A25ED572D008558E3 /* md5.cc in Sources */ = {isa = PBXBuildFile; fileRef = 930DA27725ED572D008558E3 /* md5.cc */; };
9BC1D49E0B37427A00F2A2B4 /* minidump_upload.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BD836000B0544BA0055103E /* minidump_upload.m */; };
9BD8336A0B03E4080055103E /* HTTPMultipartUpload.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9BD833680B03E4080055103E /* HTTPMultipartUpload.h */; };
9BD8336B0B03E4080055103E /* HTTPMultipartUpload.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BD833690B03E4080055103E /* HTTPMultipartUpload.m */; };
@@ -30,16 +59,78 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
- 08FB7796FE84155DC02AAC07 /* symupload.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = symupload.m; sourceTree = "<group>"; };
+ 08FB7796FE84155DC02AAC07 /* symupload.mm */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.objcpp; path = symupload.mm; sourceTree = "<group>"; tabWidth = 2; };
08FB779EFE84155DC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 5B6060BB222716FC0015F0A0 /* HTTPRequest.h */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = HTTPRequest.h; path = ../../../common/mac/HTTPRequest.h; sourceTree = "<group>"; tabWidth = 2; };
+ 5B6060BC222716FC0015F0A0 /* HTTPRequest.m */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; name = HTTPRequest.m; path = ../../../common/mac/HTTPRequest.m; sourceTree = "<group>"; tabWidth = 2; };
+ 5B6060BE2227201B0015F0A0 /* HTTPPutRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HTTPPutRequest.h; path = ../../../common/mac/HTTPPutRequest.h; sourceTree = "<group>"; };
+ 5B6060BF2227201B0015F0A0 /* HTTPPutRequest.m */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; name = HTTPPutRequest.m; path = ../../../common/mac/HTTPPutRequest.m; sourceTree = "<group>"; tabWidth = 2; };
+ 5B6060C22227303A0015F0A0 /* encoding_util.h */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = encoding_util.h; path = ../../../common/mac/encoding_util.h; sourceTree = "<group>"; tabWidth = 2; };
+ 5B6060C5222735E50015F0A0 /* HTTPGetRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HTTPGetRequest.h; path = ../../../common/mac/HTTPGetRequest.h; sourceTree = "<group>"; };
+ 5B6060C6222735E50015F0A0 /* HTTPGetRequest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = HTTPGetRequest.m; path = ../../../common/mac/HTTPGetRequest.m; sourceTree = "<group>"; };
+ 5B6060C82227374E0015F0A0 /* HTTPSimplePostRequest.h */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = HTTPSimplePostRequest.h; path = ../../../common/mac/HTTPSimplePostRequest.h; sourceTree = "<group>"; tabWidth = 2; };
+ 5B6060C92227374E0015F0A0 /* HTTPSimplePostRequest.m */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; name = HTTPSimplePostRequest.m; path = ../../../common/mac/HTTPSimplePostRequest.m; sourceTree = "<group>"; tabWidth = 2; };
+ 5B6060CE22273BDA0015F0A0 /* SymbolCollectorClient.h */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = SymbolCollectorClient.h; path = ../../../common/mac/SymbolCollectorClient.h; sourceTree = "<group>"; tabWidth = 2; };
+ 5B6060CF22273BDA0015F0A0 /* SymbolCollectorClient.m */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; name = SymbolCollectorClient.m; path = ../../../common/mac/SymbolCollectorClient.m; sourceTree = "<group>"; tabWidth = 2; };
+ 5B97447424D0AA5F000C71F5 /* encoding_util.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = encoding_util.m; path = ../../../common/mac/encoding_util.m; sourceTree = "<group>"; };
8B31022B11F0CE6900FCF3E4 /* Breakpad.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Breakpad.xcconfig; path = ../../../common/mac/Breakpad.xcconfig; sourceTree = SOURCE_ROOT; };
8B3102B611F0D5CE00FCF3E4 /* BreakpadDebug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadDebug.xcconfig; path = ../../../common/mac/BreakpadDebug.xcconfig; sourceTree = SOURCE_ROOT; };
8B3102B711F0D5CE00FCF3E4 /* BreakpadRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BreakpadRelease.xcconfig; path = ../../../common/mac/BreakpadRelease.xcconfig; sourceTree = SOURCE_ROOT; };
8DD76FA10486AA7600D96B5E /* symupload */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = symupload; sourceTree = BUILT_PRODUCTS_DIR; };
- 9BD833680B03E4080055103E /* HTTPMultipartUpload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTTPMultipartUpload.h; path = ../../../common/mac/HTTPMultipartUpload.h; sourceTree = "<group>"; };
- 9BD833690B03E4080055103E /* HTTPMultipartUpload.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HTTPMultipartUpload.m; path = ../../../common/mac/HTTPMultipartUpload.m; sourceTree = "<group>"; };
+ 930DA19025ED543A008558E3 /* dump_syms.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dump_syms.cc; path = ../../../common/mac/dump_syms.cc; sourceTree = "<group>"; };
+ 930DA19125ED543A008558E3 /* dump_syms.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dump_syms.h; path = ../../../common/mac/dump_syms.h; sourceTree = "<group>"; };
+ 930DA21F25ED55A8008558E3 /* module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = module.cc; path = ../../../common/module.cc; sourceTree = "<group>"; };
+ 930DA22025ED55A8008558E3 /* module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = module.h; path = ../../../common/module.h; sourceTree = "<group>"; };
+ 930DA22125ED55A8008558E3 /* dwarf_cfi_to_module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf_cfi_to_module.h; path = ../../../common/dwarf_cfi_to_module.h; sourceTree = "<group>"; };
+ 930DA22225ED55A8008558E3 /* dwarf_cu_to_module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf_cu_to_module.h; path = ../../../common/dwarf_cu_to_module.h; sourceTree = "<group>"; };
+ 930DA22325ED55A8008558E3 /* dwarf_cfi_to_module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf_cfi_to_module.cc; path = ../../../common/dwarf_cfi_to_module.cc; sourceTree = "<group>"; };
+ 930DA22425ED55A8008558E3 /* language.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = language.h; path = ../../../common/language.h; sourceTree = "<group>"; };
+ 930DA22525ED55A8008558E3 /* stabs_to_module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stabs_to_module.cc; path = ../../../common/stabs_to_module.cc; sourceTree = "<group>"; };
+ 930DA22625ED55A9008558E3 /* language.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = language.cc; path = ../../../common/language.cc; sourceTree = "<group>"; };
+ 930DA22725ED55A9008558E3 /* dwarf_line_to_module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf_line_to_module.h; path = ../../../common/dwarf_line_to_module.h; sourceTree = "<group>"; };
+ 930DA22825ED55A9008558E3 /* stabs_to_module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stabs_to_module.h; path = ../../../common/stabs_to_module.h; sourceTree = "<group>"; };
+ 930DA22A25ED55A9008558E3 /* dwarf_line_to_module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf_line_to_module.cc; path = ../../../common/dwarf_line_to_module.cc; sourceTree = "<group>"; };
+ 930DA22B25ED55A9008558E3 /* dwarf_cu_to_module.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf_cu_to_module.cc; path = ../../../common/dwarf_cu_to_module.cc; sourceTree = "<group>"; };
+ 930DA23525ED55B6008558E3 /* stabs_reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stabs_reader.h; path = ../../../common/stabs_reader.h; sourceTree = "<group>"; };
+ 930DA23625ED55B6008558E3 /* stabs_reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = stabs_reader.cc; path = ../../../common/stabs_reader.cc; sourceTree = "<group>"; };
+ 930DA23A25ED55BF008558E3 /* macho_id.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = macho_id.cc; path = ../../../common/mac/macho_id.cc; sourceTree = "<group>"; };
+ 930DA23B25ED55BF008558E3 /* macho_id.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = macho_id.h; path = ../../../common/mac/macho_id.h; sourceTree = "<group>"; };
+ 930DA23C25ED55BF008558E3 /* macho_utilities.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = macho_utilities.cc; path = ../../../common/mac/macho_utilities.cc; sourceTree = "<group>"; };
+ 930DA23D25ED55BF008558E3 /* macho_walker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = macho_walker.h; path = ../../../common/mac/macho_walker.h; sourceTree = "<group>"; };
+ 930DA23E25ED55BF008558E3 /* macho_reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = macho_reader.h; path = ../../../common/mac/macho_reader.h; sourceTree = "<group>"; };
+ 930DA23F25ED55BF008558E3 /* macho_reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = macho_reader.cc; path = ../../../common/mac/macho_reader.cc; sourceTree = "<group>"; };
+ 930DA24025ED55BF008558E3 /* macho_utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = macho_utilities.h; path = ../../../common/mac/macho_utilities.h; sourceTree = "<group>"; };
+ 930DA24125ED55BF008558E3 /* macho_walker.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = macho_walker.cc; path = ../../../common/mac/macho_walker.cc; sourceTree = "<group>"; };
+ 930DA24C25ED56DB008558E3 /* line_state_machine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = line_state_machine.h; path = ../../../common/dwarf/line_state_machine.h; sourceTree = "<group>"; };
+ 930DA24D25ED56DB008558E3 /* dwarf_range_list_handler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf_range_list_handler.cc; path = ../../../common/dwarf_range_list_handler.cc; sourceTree = "<group>"; };
+ 930DA24E25ED56DB008558E3 /* cfi_assembler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = cfi_assembler.cc; path = ../../../common/dwarf/cfi_assembler.cc; sourceTree = "<group>"; };
+ 930DA24F25ED56DB008558E3 /* dwarf2enums.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2enums.h; path = ../../../common/dwarf/dwarf2enums.h; sourceTree = "<group>"; };
+ 930DA25025ED56DB008558E3 /* bytereader-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "bytereader-inl.h"; path = "../../../common/dwarf/bytereader-inl.h"; sourceTree = "<group>"; };
+ 930DA25125ED56DB008558E3 /* dwarf_range_list_handler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf_range_list_handler.h; path = ../../../common/dwarf_range_list_handler.h; sourceTree = "<group>"; };
+ 930DA25225ED56DB008558E3 /* elf_reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = elf_reader.cc; path = ../../../common/dwarf/elf_reader.cc; sourceTree = "<group>"; };
+ 930DA25325ED56DB008558E3 /* dwarf2diehandler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2diehandler.cc; path = ../../../common/dwarf/dwarf2diehandler.cc; sourceTree = "<group>"; };
+ 930DA25425ED56DB008558E3 /* elf_reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = elf_reader.h; path = ../../../common/dwarf/elf_reader.h; sourceTree = "<group>"; };
+ 930DA25525ED56DB008558E3 /* bytereader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bytereader.h; path = ../../../common/dwarf/bytereader.h; sourceTree = "<group>"; };
+ 930DA25625ED56DB008558E3 /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/dwarf/dwarf2reader.cc; sourceTree = "<group>"; };
+ 930DA25725ED56DB008558E3 /* dwarf2reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2reader.h; path = ../../../common/dwarf/dwarf2reader.h; sourceTree = "<group>"; };
+ 930DA25825ED56DB008558E3 /* dwarf2diehandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2diehandler.h; path = ../../../common/dwarf/dwarf2diehandler.h; sourceTree = "<group>"; };
+ 930DA25925ED56DB008558E3 /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/dwarf/bytereader.cc; sourceTree = "<group>"; };
+ 930DA25A25ED56DB008558E3 /* cfi_assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cfi_assembler.h; path = ../../../common/dwarf/cfi_assembler.h; sourceTree = "<group>"; };
+ 930DA26725ED56FF008558E3 /* test_assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = test_assembler.h; path = ../../../common/test_assembler.h; sourceTree = "<group>"; };
+ 930DA26825ED56FF008558E3 /* test_assembler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = test_assembler.cc; path = ../../../common/test_assembler.cc; sourceTree = "<group>"; };
+ 930DA26C25ED571F008558E3 /* arch_utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = arch_utilities.h; path = ../../../common/mac/arch_utilities.h; sourceTree = "<group>"; };
+ 930DA26D25ED571F008558E3 /* arch_utilities.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = arch_utilities.cc; path = ../../../common/mac/arch_utilities.cc; sourceTree = "<group>"; };
+ 930DA27125ED572C008558E3 /* path_helper.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = path_helper.cc; path = ../../../common/path_helper.cc; sourceTree = "<group>"; };
+ 930DA27225ED572C008558E3 /* byteswap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = byteswap.h; path = ../../../common/mac/byteswap.h; sourceTree = "<group>"; };
+ 930DA27325ED572C008558E3 /* path_helper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = path_helper.h; path = ../../../common/path_helper.h; sourceTree = "<group>"; };
+ 930DA27425ED572C008558E3 /* byte_cursor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = byte_cursor.h; path = ../../../common/byte_cursor.h; sourceTree = "<group>"; };
+ 930DA27525ED572C008558E3 /* file_id.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = file_id.cc; path = ../../../common/mac/file_id.cc; sourceTree = "<group>"; };
+ 930DA27625ED572C008558E3 /* file_id.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = file_id.h; path = ../../../common/mac/file_id.h; sourceTree = "<group>"; };
+ 930DA27725ED572D008558E3 /* md5.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = md5.cc; path = ../../../common/md5.cc; sourceTree = "<group>"; };
+ 9BD833680B03E4080055103E /* HTTPMultipartUpload.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = HTTPMultipartUpload.h; path = ../../../common/mac/HTTPMultipartUpload.h; sourceTree = "<group>"; tabWidth = 2; };
+ 9BD833690B03E4080055103E /* HTTPMultipartUpload.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; name = HTTPMultipartUpload.m; path = ../../../common/mac/HTTPMultipartUpload.m; sourceTree = "<group>"; tabWidth = 2; };
9BD835FB0B0544950055103E /* minidump_upload */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = minidump_upload; sourceTree = BUILT_PRODUCTS_DIR; };
- 9BD836000B0544BA0055103E /* minidump_upload.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = minidump_upload.m; sourceTree = "<group>"; };
+ 9BD836000B0544BA0055103E /* minidump_upload.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = minidump_upload.m; path = ../../../common/mac/minidump_upload.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -65,10 +156,23 @@
08FB7794FE84155DC02AAC07 /* symupload */ = {
isa = PBXGroup;
children = (
+ 930DA21E25ED5586008558E3 /* dump_syms */,
+ 5B6060CE22273BDA0015F0A0 /* SymbolCollectorClient.h */,
+ 5B6060CF22273BDA0015F0A0 /* SymbolCollectorClient.m */,
+ 5B6060C82227374E0015F0A0 /* HTTPSimplePostRequest.h */,
+ 5B6060C92227374E0015F0A0 /* HTTPSimplePostRequest.m */,
+ 5B6060C5222735E50015F0A0 /* HTTPGetRequest.h */,
+ 5B6060C6222735E50015F0A0 /* HTTPGetRequest.m */,
+ 5B6060C22227303A0015F0A0 /* encoding_util.h */,
+ 5B97447424D0AA5F000C71F5 /* encoding_util.m */,
+ 5B6060BE2227201B0015F0A0 /* HTTPPutRequest.h */,
+ 5B6060BF2227201B0015F0A0 /* HTTPPutRequest.m */,
+ 5B6060BB222716FC0015F0A0 /* HTTPRequest.h */,
+ 5B6060BC222716FC0015F0A0 /* HTTPRequest.m */,
8B31022B11F0CE6900FCF3E4 /* Breakpad.xcconfig */,
8B3102B611F0D5CE00FCF3E4 /* BreakpadDebug.xcconfig */,
8B3102B711F0D5CE00FCF3E4 /* BreakpadRelease.xcconfig */,
- 08FB7796FE84155DC02AAC07 /* symupload.m */,
+ 08FB7796FE84155DC02AAC07 /* symupload.mm */,
9BD836000B0544BA0055103E /* minidump_upload.m */,
9BD833680B03E4080055103E /* HTTPMultipartUpload.h */,
9BD833690B03E4080055103E /* HTTPMultipartUpload.m */,
@@ -95,6 +199,63 @@
name = Products;
sourceTree = "<group>";
};
+ 930DA21E25ED5586008558E3 /* dump_syms */ = {
+ isa = PBXGroup;
+ children = (
+ 930DA23A25ED55BF008558E3 /* macho_id.cc */,
+ 930DA23B25ED55BF008558E3 /* macho_id.h */,
+ 930DA23F25ED55BF008558E3 /* macho_reader.cc */,
+ 930DA23E25ED55BF008558E3 /* macho_reader.h */,
+ 930DA23C25ED55BF008558E3 /* macho_utilities.cc */,
+ 930DA24025ED55BF008558E3 /* macho_utilities.h */,
+ 930DA24125ED55BF008558E3 /* macho_walker.cc */,
+ 930DA23D25ED55BF008558E3 /* macho_walker.h */,
+ 930DA19025ED543A008558E3 /* dump_syms.cc */,
+ 930DA19125ED543A008558E3 /* dump_syms.h */,
+ 930DA23625ED55B6008558E3 /* stabs_reader.cc */,
+ 930DA23525ED55B6008558E3 /* stabs_reader.h */,
+ 930DA22325ED55A8008558E3 /* dwarf_cfi_to_module.cc */,
+ 930DA22125ED55A8008558E3 /* dwarf_cfi_to_module.h */,
+ 930DA22B25ED55A9008558E3 /* dwarf_cu_to_module.cc */,
+ 930DA22225ED55A8008558E3 /* dwarf_cu_to_module.h */,
+ 930DA22A25ED55A9008558E3 /* dwarf_line_to_module.cc */,
+ 930DA22725ED55A9008558E3 /* dwarf_line_to_module.h */,
+ 930DA22625ED55A9008558E3 /* language.cc */,
+ 930DA22425ED55A8008558E3 /* language.h */,
+ 930DA21F25ED55A8008558E3 /* module.cc */,
+ 930DA22025ED55A8008558E3 /* module.h */,
+ 930DA22525ED55A8008558E3 /* stabs_to_module.cc */,
+ 930DA22825ED55A9008558E3 /* stabs_to_module.h */,
+ 930DA25025ED56DB008558E3 /* bytereader-inl.h */,
+ 930DA25925ED56DB008558E3 /* bytereader.cc */,
+ 930DA25525ED56DB008558E3 /* bytereader.h */,
+ 930DA24E25ED56DB008558E3 /* cfi_assembler.cc */,
+ 930DA25A25ED56DB008558E3 /* cfi_assembler.h */,
+ 930DA24D25ED56DB008558E3 /* dwarf_range_list_handler.cc */,
+ 930DA25125ED56DB008558E3 /* dwarf_range_list_handler.h */,
+ 930DA25325ED56DB008558E3 /* dwarf2diehandler.cc */,
+ 930DA25825ED56DB008558E3 /* dwarf2diehandler.h */,
+ 930DA24F25ED56DB008558E3 /* dwarf2enums.h */,
+ 930DA25625ED56DB008558E3 /* dwarf2reader.cc */,
+ 930DA25725ED56DB008558E3 /* dwarf2reader.h */,
+ 930DA25225ED56DB008558E3 /* elf_reader.cc */,
+ 930DA25425ED56DB008558E3 /* elf_reader.h */,
+ 930DA24C25ED56DB008558E3 /* line_state_machine.h */,
+ 930DA26825ED56FF008558E3 /* test_assembler.cc */,
+ 930DA26725ED56FF008558E3 /* test_assembler.h */,
+ 930DA26D25ED571F008558E3 /* arch_utilities.cc */,
+ 930DA26C25ED571F008558E3 /* arch_utilities.h */,
+ 930DA27425ED572C008558E3 /* byte_cursor.h */,
+ 930DA27225ED572C008558E3 /* byteswap.h */,
+ 930DA27525ED572C008558E3 /* file_id.cc */,
+ 930DA27625ED572C008558E3 /* file_id.h */,
+ 930DA27725ED572D008558E3 /* md5.cc */,
+ 930DA27125ED572C008558E3 /* path_helper.cc */,
+ 930DA27325ED572C008558E3 /* path_helper.h */,
+ );
+ name = dump_syms;
+ sourceTree = "<group>";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -137,9 +298,15 @@
/* Begin PBXProject section */
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
+ attributes = {
+ };
buildConfigurationList = 1DEB927808733DD40010E9CD /* Build configuration list for PBXProject "symupload" */;
compatibilityVersion = "Xcode 3.1";
+ developmentRegion = en;
hasScannedForEncodings = 1;
+ knownRegions = (
+ en,
+ );
mainGroup = 08FB7794FE84155DC02AAC07 /* symupload */;
projectDirPath = "";
projectRoot = "";
@@ -155,8 +322,37 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- 8DD76F9A0486AA7600D96B5E /* symupload.m in Sources */,
+ 8DD76F9A0486AA7600D96B5E /* symupload.mm in Sources */,
+ 930DA19225ED543A008558E3 /* dump_syms.cc in Sources */,
+ 930DA24525ED55BF008558E3 /* macho_walker.cc in Sources */,
+ 930DA22E25ED55A9008558E3 /* stabs_to_module.cc in Sources */,
+ 5B6060CA2227374E0015F0A0 /* HTTPSimplePostRequest.m in Sources */,
+ 930DA25F25ED56DB008558E3 /* dwarf2diehandler.cc in Sources */,
+ 930DA27825ED572D008558E3 /* path_helper.cc in Sources */,
+ 930DA27A25ED572D008558E3 /* md5.cc in Sources */,
+ 930DA22D25ED55A9008558E3 /* dwarf_cfi_to_module.cc in Sources */,
+ 930DA24425ED55BF008558E3 /* macho_reader.cc in Sources */,
+ 930DA24325ED55BF008558E3 /* macho_utilities.cc in Sources */,
+ 5B6060D022273BDA0015F0A0 /* SymbolCollectorClient.m in Sources */,
+ 5B6060C7222735E50015F0A0 /* HTTPGetRequest.m in Sources */,
+ 930DA27925ED572D008558E3 /* file_id.cc in Sources */,
+ 930DA26925ED56FF008558E3 /* test_assembler.cc in Sources */,
+ 930DA22F25ED55A9008558E3 /* language.cc in Sources */,
+ 930DA25E25ED56DB008558E3 /* elf_reader.cc in Sources */,
+ 930DA26E25ED571F008558E3 /* arch_utilities.cc in Sources */,
+ 930DA24225ED55BF008558E3 /* macho_id.cc in Sources */,
+ 5B6060C02227201B0015F0A0 /* HTTPPutRequest.m in Sources */,
+ 930DA25C25ED56DB008558E3 /* dwarf_range_list_handler.cc in Sources */,
+ 5B6060BD222716FC0015F0A0 /* HTTPRequest.m in Sources */,
+ 930DA25D25ED56DB008558E3 /* cfi_assembler.cc in Sources */,
+ 930DA23225ED55A9008558E3 /* dwarf_cu_to_module.cc in Sources */,
+ 930DA23125ED55A9008558E3 /* dwarf_line_to_module.cc in Sources */,
+ 930DA26125ED56DB008558E3 /* bytereader.cc in Sources */,
+ 930DA22C25ED55A9008558E3 /* module.cc in Sources */,
+ 5B97447524D0AA5F000C71F5 /* encoding_util.m in Sources */,
+ 930DA23725ED55B6008558E3 /* stabs_reader.cc in Sources */,
9BD8336B0B03E4080055103E /* HTTPMultipartUpload.m in Sources */,
+ 930DA26025ED56DB008558E3 /* dwarf2reader.cc in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -175,7 +371,13 @@
1DEB927508733DD40010E9CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
- HEADER_SEARCH_PATHS = ../../..;
+ CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+ GCC_PREPROCESSOR_DEFINITIONS = HAVE_MACH_O_NLIST_H;
+ HEADER_SEARCH_PATHS = (
+ ../../..,
+ ../../../common/mac/include,
+ ../../../third_party/musl/include/,
+ );
PRODUCT_NAME = symupload;
};
name = Debug;
@@ -183,7 +385,17 @@
1DEB927608733DD40010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
- HEADER_SEARCH_PATHS = ../../..;
+ CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ NDEBUG,
+ HAVE_MACH_O_NLIST_H,
+ );
+ HEADER_SEARCH_PATHS = (
+ ../../..,
+ ../../../common/mac/include,
+ ../../../third_party/musl/include/,
+ );
PRODUCT_NAME = symupload;
};
name = Release;
diff --git a/src/tools/mac/tools_mac.gypi b/src/tools/mac/tools_mac.gypi
deleted file mode 100644
index 7457573b..00000000
--- a/src/tools/mac/tools_mac.gypi
+++ /dev/null
@@ -1,116 +0,0 @@
-# Copyright 2014 Google Inc. All rights reserved.
-#
-# 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 Inc. 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.
-
-{
- 'target_defaults': {
- 'include_dirs': [
- '../..',
- ],
- },
- 'targets': [
- {
- 'target_name': 'crash_report',
- 'type': 'executable',
- 'sources': [
- 'crash_report/crash_report.mm',
- 'crash_report/on_demand_symbol_supplier.h',
- 'crash_report/on_demand_symbol_supplier.mm',
- ],
- 'link_settings': {
- 'libraries': [
- '$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
- ],
- },
- 'dependencies': [
- '../common/common.gyp:common',
- '../processor/processor.gyp:processor',
- ],
- },
- {
- 'target_name': 'dump_syms',
- 'type': 'executable',
- 'sources': [
- 'dump_syms/dump_syms_tool.cc',
- ],
- 'link_settings': {
- 'libraries': [
- '$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
- ],
- },
- 'dependencies': [
- '../common/common.gyp:common',
- ],
- },
- {
- 'target_name': 'macho_dump',
- 'type': 'executable',
- 'sources': [
- 'dump_syms/macho_dump.cc',
- ],
- 'dependencies': [
- '../common/common.gyp:common',
- ],
- },
- {
- 'target_name': 'minidump_upload',
- 'type': 'executable',
- 'sources': [
- 'symupload/minidump_upload.m',
- ],
- 'include_dirs': [
- '../../common/mac',
- ],
- 'link_settings': {
- 'libraries': [
- '$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
- ],
- },
- 'dependencies': [
- '../common/common.gyp:common',
- ],
- },
- {
- 'target_name': 'symupload',
- 'type': 'executable',
- 'sources': [
- 'symupload/symupload.m',
- ],
- 'include_dirs': [
- '../../common/mac',
- ],
- 'link_settings': {
- 'libraries': [
- '$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
- ],
- },
- 'dependencies': [
- '../common/common.gyp:common',
- ],
- },
- ],
-}
diff --git a/src/tools/mac/upload_system_symbols/arch_constants.h b/src/tools/mac/upload_system_symbols/arch_constants.h
index e12e53e2..b6dbc89a 100644
--- a/src/tools/mac/upload_system_symbols/arch_constants.h
+++ b/src/tools/mac/upload_system_symbols/arch_constants.h
@@ -1,5 +1,4 @@
-/* Copyright 2014, Google Inc.
-All rights reserved.
+/* Copyright 2014 Google LLC
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
@@ -11,7 +10,7 @@ notice, this list of conditions and the following disclaimer.
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 Inc. nor the names of its
+ * 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.
diff --git a/src/tools/mac/upload_system_symbols/arch_reader.go b/src/tools/mac/upload_system_symbols/arch_reader.go
index ed98fa60..03a76421 100644
--- a/src/tools/mac/upload_system_symbols/arch_reader.go
+++ b/src/tools/mac/upload_system_symbols/arch_reader.go
@@ -1,5 +1,4 @@
-/* Copyright 2014, Google Inc.
-All rights reserved.
+/* Copyright 2014 Google LLC
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
@@ -11,7 +10,7 @@ notice, this list of conditions and the following disclaimer.
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 Inc. nor the names of its
+ * 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.
diff --git a/src/tools/mac/upload_system_symbols/go.mod b/src/tools/mac/upload_system_symbols/go.mod
new file mode 100644
index 00000000..ff21bba9
--- /dev/null
+++ b/src/tools/mac/upload_system_symbols/go.mod
@@ -0,0 +1,3 @@
+module upload_system_symbols
+
+go 1.17
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 05a7764a..ba067276 100644
--- a/src/tools/mac/upload_system_symbols/upload_system_symbols.go
+++ b/src/tools/mac/upload_system_symbols/upload_system_symbols.go
@@ -1,5 +1,4 @@
-/* Copyright 2014, Google Inc.
-All rights reserved.
+/* Copyright 2014 Google LLC
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
@@ -11,7 +10,7 @@ notice, this list of conditions and the following disclaimer.
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 Inc. nor the names of its
+ * 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.
@@ -64,12 +63,12 @@ var (
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.")
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.")
)
var (
// pathsToScan are the subpaths in the systemRoot that should be scanned for shared libraries.
pathsToScan = []string{
- "/System/Library/Components",
"/System/Library/Frameworks",
"/System/Library/PrivateFrameworks",
"/usr/lib",
@@ -79,13 +78,26 @@ var (
optionalPathsToScan = []string{
// Gone in 10.15.
"/Library/QuickTime",
+ // Not present in dumped dyld_shared_caches
+ "/System/Library/Components",
}
- // uploadServers are the list of servers to which symbols should be uploaded.
- uploadServers = []string{
+ // uploadServersV1 are the list of servers to which symbols should be
+ // uploaded when using the V1 protocol.
+ uploadServersV1 = []string{
"https://clients2.google.com/cr/symbol",
"https://clients2.google.com/cr/staging_symbol",
}
+ // uploadServersV2 are the list of servers to which symbols should be
+ // uploaded when using the V2 protocol.
+ uploadServersV2 = []string{
+ "https://staging-crashsymbolcollector-pa.googleapis.com",
+ "https://prod-crashsymbolcollector-pa.googleapis.com",
+ }
+
+ // uploadServers are the list of servers that should be used, accounting
+ // for whether v1 or v2 protocol is used.
+ uploadServers = uploadServersV1
// blacklistRegexps match paths that should be excluded from dumping.
blacklistRegexps = []*regexp.Regexp{
@@ -102,6 +114,11 @@ func main() {
flag.Parse()
log.SetFlags(0)
+ // If `apiKey` is set, we're using the v2 protocol.
+ if len(*apiKey) > 0 {
+ uploadServers = uploadServersV2
+ }
+
var uq *UploadQueue
if *uploadOnlyPath != "" {
@@ -195,17 +212,29 @@ func (uq *UploadQueue) Done() {
close(uq.queue)
}
-func (uq *UploadQueue) worker() {
+func (uq *UploadQueue) runSymUpload(symfile, server string) *exec.Cmd {
symUpload := path.Join(*breakpadTools, "symupload")
+ args := []string{symfile, server}
+ if len(*apiKey) > 0 {
+ args = append([]string{"-p", "sym-upload-v2", "-k", *apiKey}, args...)
+ }
+ return exec.Command(symUpload, args...)
+}
+func (uq *UploadQueue) worker() {
for symfile := range uq.queue {
for _, server := range uploadServers {
for i := 0; i < 3; i++ { // Give each upload 3 attempts to succeed.
- cmd := exec.Command(symUpload, symfile, server)
+ cmd := uq.runSymUpload(symfile, server)
if output, err := cmd.Output(); err == nil {
// Success. No retry needed.
fmt.Printf("Uploaded %s to %s\n", symfile, server)
break
+ } else if exitError, ok := err.(*exec.ExitError); ok && exitError.ExitCode() == 2 && *apiKey != "" {
+ // Exit code 2 in protocol v2 means the file already exists on the server.
+ // No point retrying.
+ fmt.Printf("File %s already exists on %s\n", symfile, server)
+ break
} else {
log.Printf("Error running symupload(%s, %s), attempt %d: %v: %s\n", symfile, server, i, err, output)
time.Sleep(1 * time.Second)
diff --git a/src/tools/python/deps-to-manifest.py b/src/tools/python/deps-to-manifest.py
index b4562854..2fcaf771 100755
--- a/src/tools/python/deps-to-manifest.py
+++ b/src/tools/python/deps-to-manifest.py
@@ -1,6 +1,5 @@
#!/usr/bin/python
-# Copyright 2016 Google Inc.
-# All rights reserved.
+# Copyright 2016 Google LLC
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
@@ -12,7 +11,7 @@
# 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 Inc. nor the names of its
+# * 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.
#
@@ -49,7 +48,7 @@ MANIFEST_HEAD = """<?xml version='1.0' encoding='UTF-8'?>
<!-- AUTOGENERATED BY %(prog)s; DO NOT EDIT -->
<manifest>
- <default revision='refs/heads/master'
+ <default revision='refs/heads/main'
remote='chromium'
sync-c='true'
sync-j='8' />
@@ -100,7 +99,7 @@ def ConvertDepsToManifest(deps, manifest):
data = {
'path': 'src',
'name': 'breakpad/breakpad',
- 'revision': 'refs/heads/master',
+ 'revision': 'refs/heads/main',
'remote': 'chromium',
}
new_contents += MANIFEST_PROJECT % data
diff --git a/src/tools/python/filter_syms.py b/src/tools/python/filter_syms.py
index abddf789..caf3693a 100644
--- a/src/tools/python/filter_syms.py
+++ b/src/tools/python/filter_syms.py
@@ -1,6 +1,5 @@
#!/usr/bin/env python
-# Copyright (c) 2012 Google Inc.
-# All rights reserved.
+# Copyright 2012 Google LLC
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
@@ -12,7 +11,7 @@
# 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 Inc. nor the names of its
+# * 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.
#
diff --git a/src/tools/python/tests/filter_syms_unittest.py b/src/tools/python/tests/filter_syms_unittest.py
index b111f349..1081fc73 100644
--- a/src/tools/python/tests/filter_syms_unittest.py
+++ b/src/tools/python/tests/filter_syms_unittest.py
@@ -1,6 +1,5 @@
#!/usr/bin/env python
-# Copyright (c) 2012 Google Inc.
-# All rights reserved.
+# Copyright 2012 Google LLC
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
@@ -12,7 +11,7 @@
# 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 Inc. nor the names of its
+# * 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.
#
diff --git a/src/tools/solaris/dump_syms/Makefile b/src/tools/solaris/dump_syms/Makefile
index ff77105c..c5f48240 100644
--- a/src/tools/solaris/dump_syms/Makefile
+++ b/src/tools/solaris/dump_syms/Makefile
@@ -1,5 +1,4 @@
-# Copyright (c) 2007, Google Inc.
-# All rights reserved.
+# Copyright 2007 Google LLC
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
@@ -11,7 +10,7 @@
# 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 Inc. nor the names of its
+# * 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.
#
diff --git a/src/tools/solaris/dump_syms/dump_syms.cc b/src/tools/solaris/dump_syms/dump_syms.cc
index 54cea57e..fc331c21 100644
--- a/src/tools/solaris/dump_syms/dump_syms.cc
+++ b/src/tools/solaris/dump_syms/dump_syms.cc
@@ -1,5 +1,4 @@
-// Copyright (c) 2007, Google Inc.
-// All rights reserved.
+// Copyright 2007 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -11,7 +10,7 @@
// 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 Inc. nor the names of its
+// * 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.
//
@@ -36,13 +35,13 @@
using namespace google_breakpad;
-int main(int argc, char **argv) {
+int main(int argc, char** argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <binary-with-stab-symbol>\n", argv[0]);
return 1;
}
- const char *binary = argv[1];
+ const char* binary = argv[1];
DumpSymbols dumper;
if (!dumper.WriteSymbolFile(binary, fileno(stdout))) {
diff --git a/src/tools/solaris/dump_syms/run_regtest.sh b/src/tools/solaris/dump_syms/run_regtest.sh
index ffb34330..27710d9a 100644
--- a/src/tools/solaris/dump_syms/run_regtest.sh
+++ b/src/tools/solaris/dump_syms/run_regtest.sh
@@ -1,7 +1,6 @@
#!/bin/sh
-# Copyright (c) 2007, Google Inc.
-# All rights reserved.
+# Copyright 2007 Google LLC
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
@@ -13,7 +12,7 @@
# 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 Inc. nor the names of its
+# * 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.
#
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 e617a23b..b4d191bd 100644
--- a/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.cc
+++ b/src/tools/solaris/dump_syms/testdata/dump_syms_regtest.cc
@@ -1,5 +1,4 @@
-// Copyright (c) 2007, Google Inc.
-// All rights reserved.
+// Copyright 2007 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -11,7 +10,7 @@
// 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 Inc. nor the names of its
+// * 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.
//
@@ -41,7 +40,7 @@ class C {
void f() { member_ = g(); }
virtual int g() { return 2; }
- static char* h(const C &that) { return 0; }
+ static char* h(const C& that) { return 0; }
private:
int member_;
@@ -53,12 +52,12 @@ static int i() {
} // namespace google_breakpad
-int main(int argc, char **argv) {
+int main(int argc, char** argv) {
google_breakpad::C object;
object.set_member(google_breakpad::i());
object.f();
int value = object.g();
- char *nothing = object.h(object);
+ char* nothing = object.h(object);
return 0;
}
diff --git a/src/tools/tools.gyp b/src/tools/tools.gyp
deleted file mode 100644
index e6a4210f..00000000
--- a/src/tools/tools.gyp
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright 2014 Google Inc. All rights reserved.
-#
-# 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 Inc. 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.
-
-{
- 'conditions': [
- ['OS=="mac"', {
- 'includes': ['mac/tools_mac.gypi'],
- }],
- ['OS=="linux"', {
- 'includes': ['linux/tools_linux.gypi'],
- }],
- ],
-}
diff --git a/src/tools/windows/converter/ms_symbol_server_converter.cc b/src/tools/windows/converter/ms_symbol_server_converter.cc
index 2b40faee..bfe46925 100644
--- a/src/tools/windows/converter/ms_symbol_server_converter.cc
+++ b/src/tools/windows/converter/ms_symbol_server_converter.cc
@@ -1,5 +1,4 @@
-// Copyright (c) 2007, Google Inc.
-// All rights reserved.
+// Copyright 2007 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -11,7 +10,7 @@
// 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 Inc. nor the names of its
+// * 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.
//
@@ -92,7 +91,7 @@ namespace google_breakpad {
#endif // _MSC_VER >= 1400
bool GUIDOrSignatureIdentifier::InitializeFromString(
- const string &identifier) {
+ const string& identifier) {
type_ = TYPE_NONE;
size_t length = identifier.length();
@@ -128,11 +127,15 @@ bool GUIDOrSignatureIdentifier::InitializeFromString(
#undef SSCANF
MSSymbolServerConverter::MSSymbolServerConverter(
- const string &local_cache, const vector<string> &symbol_servers)
+ const string& local_cache,
+ const vector<string>& symbol_servers,
+ bool trace_symsrv)
: symbol_path_(),
fail_dns_(false),
fail_timeout_(false),
- fail_not_found_(false) {
+ fail_http_https_redir_(false),
+ fail_not_found_(false),
+ trace_symsrv_(trace_symsrv) {
// Setting local_cache can be done without verifying that it exists because
// SymSrv will create it if it is missing - any creation failures will occur
// at that time, so there's nothing to check here, making it safe to
@@ -184,7 +187,7 @@ class AutoSymSrv {
}
}
- bool Initialize(HANDLE process, char *path, bool invade_process) {
+ bool Initialize(HANDLE process, char* path, bool invade_process) {
process_ = process;
// TODO(nbilling): Figure out why dbghelp.dll is being loaded from
@@ -240,7 +243,7 @@ class AutoSymSrv {
// are supported by calling Delete().
class AutoDeleter {
public:
- explicit AutoDeleter(const string &path) : path_(path) {}
+ explicit AutoDeleter(const string& path) : path_(path) {}
~AutoDeleter() {
int error;
@@ -270,10 +273,10 @@ class AutoDeleter {
};
MSSymbolServerConverter::LocateResult
-MSSymbolServerConverter::LocateFile(const string &debug_or_code_file,
- const string &debug_or_code_id,
- const string &version,
- string *file_name) {
+MSSymbolServerConverter::LocateFile(const string& debug_or_code_file,
+ const string& debug_or_code_id,
+ const string& version,
+ string* file_name) {
assert(file_name);
file_name->clear();
@@ -290,7 +293,7 @@ MSSymbolServerConverter::LocateFile(const string &debug_or_code_file,
HANDLE process = GetCurrentProcess(); // CloseHandle is not needed.
AutoSymSrv symsrv;
if (!symsrv.Initialize(process,
- const_cast<char *>(symbol_path_.c_str()),
+ const_cast<char*>(symbol_path_.c_str()),
false)) {
fprintf(stderr, "LocateFile: SymInitialize: error %lu for %s %s %s\n",
GetLastError(),
@@ -326,8 +329,8 @@ MSSymbolServerConverter::LocateFile(const string &debug_or_code_file,
char path[MAX_PATH];
if (!SymFindFileInPath(
process, NULL,
- const_cast<char *>(debug_or_code_file.c_str()),
- const_cast<void *>(identifier.guid_or_signature_pointer()),
+ const_cast<char*>(debug_or_code_file.c_str()),
+ const_cast<void*>(identifier.guid_or_signature_pointer()),
identifier.age(), 0,
identifier.type() == GUIDOrSignatureIdentifier::TYPE_GUID ?
SSRVOPT_GUIDPTR : SSRVOPT_DWORDPTR,
@@ -342,6 +345,10 @@ MSSymbolServerConverter::LocateFile(const string &debug_or_code_file,
return LOCATE_RETRY;
}
+ if (fail_http_https_redir_) {
+ return LOCATE_HTTP_HTTPS_REDIR;
+ }
+
// This is an authoritiative file-not-found message.
if (fail_not_found_) {
fprintf(stderr,
@@ -393,15 +400,15 @@ MSSymbolServerConverter::LocateFile(const string &debug_or_code_file,
MSSymbolServerConverter::LocateResult
-MSSymbolServerConverter::LocatePEFile(const MissingSymbolInfo &missing,
- string *pe_file) {
+MSSymbolServerConverter::LocatePEFile(const MissingSymbolInfo& missing,
+ string* pe_file) {
return LocateFile(missing.code_file, missing.code_identifier,
missing.version, pe_file);
}
MSSymbolServerConverter::LocateResult
-MSSymbolServerConverter::LocateSymbolFile(const MissingSymbolInfo &missing,
- string *symbol_file) {
+MSSymbolServerConverter::LocateSymbolFile(const MissingSymbolInfo& missing,
+ string* symbol_file) {
return LocateFile(missing.debug_file, missing.debug_identifier,
missing.version, symbol_file);
}
@@ -412,51 +419,58 @@ BOOL CALLBACK MSSymbolServerConverter::SymCallback(HANDLE process,
ULONG action,
ULONG64 data,
ULONG64 context) {
- MSSymbolServerConverter *self =
- reinterpret_cast<MSSymbolServerConverter *>(context);
+ MSSymbolServerConverter* self =
+ reinterpret_cast<MSSymbolServerConverter*>(context);
switch (action) {
case CBA_EVENT: {
- IMAGEHLP_CBA_EVENT *cba_event =
- reinterpret_cast<IMAGEHLP_CBA_EVENT *>(data);
+ IMAGEHLP_CBA_EVENT* cba_event =
+ reinterpret_cast<IMAGEHLP_CBA_EVENT*>(data);
// Put the string into a string object to be able to use string::find
// for substring matching. This is important because the not-found
// message does not use the entire string but is appended to the URL
// that SymSrv attempted to retrieve.
string desc(cba_event->desc);
+ if (self->trace_symsrv_) {
+ fprintf(stderr, "LocateFile: SymCallback: action desc '%s'\n",
+ desc.c_str());
+ }
// desc_action maps strings (in desc) to boolean pointers that are to
// be set to true if the string matches.
struct desc_action {
- const char *desc; // The substring to match.
- bool *action; // On match, this pointer will be set to true.
+ const char* desc; // The substring to match.
+ bool* action; // On match, this pointer will be set to true.
};
static const desc_action desc_actions[] = {
- // When a DNS error occurs, it could be indiciative of network
- // problems.
- { "SYMSRV: The server name or address could not be resolved\n",
- &self->fail_dns_ },
-
- // This message is produced if no connection is opened.
- { "SYMSRV: A connection with the server could not be established\n",
- &self->fail_timeout_ },
-
- // This message is produced if a connection is established but the
- // server fails to respond to the HTTP request.
- { "SYMSRV: The operation timed out\n",
- &self->fail_timeout_ },
-
- // This message is produced when the requested file is not found,
- // even if one or more of the above messages are also produced.
- // It's trapped to distinguish between not-found and unknown-failure
- // conditions. Note that this message will not be produced if a
- // connection is established and the server begins to respond to the
- // HTTP request but does not finish transmitting the file.
- { " not found\n",
- &self->fail_not_found_ }
- };
+ // When a DNS error occurs, it could be indiciative of network
+ // problems.
+ {"SYMSRV: The server name or address could not be resolved\n",
+ &self->fail_dns_},
+
+ // This message is produced if no connection is opened.
+ {"SYMSRV: A connection with the server could not be established\n",
+ &self->fail_timeout_},
+
+ // This message is produced if a connection is established but the
+ // server fails to respond to the HTTP request.
+ {"SYMSRV: The operation timed out\n", &self->fail_timeout_},
+
+ // This message is produced if the server is redirecting us from http
+ // to https. When this happens SymSrv will fail and we need to use
+ // the https URL in our call-- we've made a mistake.
+ {"ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR\n",
+ &self->fail_http_https_redir_},
+
+ // This message is produced when the requested file is not found,
+ // even if one or more of the above messages are also produced.
+ // It's trapped to distinguish between not-found and unknown-failure
+ // conditions. Note that this message will not be produced if a
+ // connection is established and the server begins to respond to the
+ // HTTP request but does not finish transmitting the file.
+ {" not found\n", &self->fail_not_found_}};
for (int desc_action_index = 0;
desc_action_index <
@@ -478,7 +492,7 @@ BOOL CALLBACK MSSymbolServerConverter::SymCallback(HANDLE process,
// static
BOOL CALLBACK MSSymbolServerConverter::SymFindFileInPathCallback(
- const char *filename, void *context) {
+ const char* filename, void* context) {
// FALSE ends the search, indicating that the located symbol file is
// satisfactory.
return FALSE;
@@ -486,12 +500,12 @@ BOOL CALLBACK MSSymbolServerConverter::SymFindFileInPathCallback(
MSSymbolServerConverter::LocateResult
MSSymbolServerConverter::LocateAndConvertSymbolFile(
- const MissingSymbolInfo &missing,
+ const MissingSymbolInfo& missing,
bool keep_symbol_file,
bool keep_pe_file,
- string *converted_symbol_file,
- string *symbol_file,
- string *out_pe_file) {
+ string* converted_symbol_file,
+ string* symbol_file,
+ string* out_pe_file) {
assert(converted_symbol_file);
converted_symbol_file->clear();
if (symbol_file) {
@@ -580,7 +594,7 @@ MSSymbolServerConverter::LocateAndConvertSymbolFile(
*converted_symbol_file = pdb_file.substr(0, pdb_file.length() - 4) + ".sym";
- FILE *converted_output = NULL;
+ FILE* converted_output = NULL;
#if _MSC_VER >= 1400 // MSVC 2005/8
errno_t err;
if ((err = fopen_s(&converted_output, converted_symbol_file->c_str(), "w"))
@@ -634,10 +648,10 @@ MSSymbolServerConverter::LocateAndConvertSymbolFile(
MSSymbolServerConverter::LocateResult
MSSymbolServerConverter::LocateAndConvertPEFile(
- const MissingSymbolInfo &missing,
+ const MissingSymbolInfo& missing,
bool keep_pe_file,
- string *converted_symbol_file,
- string *out_pe_file) {
+ string* converted_symbol_file,
+ string* out_pe_file) {
assert(converted_symbol_file);
converted_symbol_file->clear();
@@ -676,7 +690,7 @@ MSSymbolServerConverter::LocateAndConvertPEFile(
*converted_symbol_file = pe_file.substr(0, pe_file.length() - 4) + ".sym";
- FILE *converted_output = NULL;
+ FILE* converted_output = NULL;
#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/ms_symbol_server_converter.gyp b/src/tools/windows/converter/ms_symbol_server_converter.gyp
deleted file mode 100644
index 57ec7906..00000000
--- a/src/tools/windows/converter/ms_symbol_server_converter.gyp
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright 2013 Google Inc. All rights reserved.
-#
-# 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 Inc. 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.
-
-{
- 'includes': [
- '../../../build/common.gypi',
- ],
- 'targets': [
- {
- 'target_name': 'ms_symbol_server_converter',
- 'type': 'static_library',
- 'msvs_guid': '1463C4CD-23FC-4DE9-BFDE-283338200157',
- 'sources': [
- 'ms_symbol_server_converter.cc',
- ],
- 'dependencies': [
- '../../../common/windows/common_windows.gyp:common_windows_lib',
- ],
- },
- ],
-}
diff --git a/src/tools/windows/converter/ms_symbol_server_converter.h b/src/tools/windows/converter/ms_symbol_server_converter.h
index 401f7c34..ffdea7c0 100644
--- a/src/tools/windows/converter/ms_symbol_server_converter.h
+++ b/src/tools/windows/converter/ms_symbol_server_converter.h
@@ -1,5 +1,4 @@
-// Copyright (c) 2007, Google Inc.
-// All rights reserved.
+// Copyright 2007 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -11,7 +10,7 @@
// 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 Inc. nor the names of its
+// * 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.
//
@@ -101,13 +100,13 @@ class GUIDOrSignatureIdentifier {
// component fields: either a GUID and age, or signature and age. If
// successful, sets the relevant fields in the object, including the type
// field, and returns true. On error, returns false.
- bool InitializeFromString(const string &identifier);
+ bool InitializeFromString(const string& identifier);
GUIDOrSignatureType type() const { return type_; }
GUID guid() const { return guid_; }
DWORD signature() const { return signature_; }
int age() const { return age_; }
- const void *guid_or_signature_pointer() const { return &guid_; }
+ const void* guid_or_signature_pointer() const { return &guid_; }
private:
GUIDOrSignatureType type_;
@@ -127,9 +126,10 @@ class MSSymbolServerConverter {
public:
enum LocateResult {
LOCATE_FAILURE = 0,
- LOCATE_NOT_FOUND, // Authoritative: the file is not present.
- LOCATE_RETRY, // Transient (network?) error, try again later.
- LOCATE_SUCCESS
+ LOCATE_NOT_FOUND, // Authoritative: the file is not present.
+ LOCATE_RETRY, // Transient (network?) error, try again later.
+ LOCATE_SUCCESS,
+ LOCATE_HTTP_HTTPS_REDIR
};
// Create a new object. local_cache is the location (pathname) of a local
@@ -141,23 +141,26 @@ class MSSymbolServerConverter {
// store to try. The vector must contain at least one string. None of the
// strings passed to this constructor may contain asterisk ('*') or semicolon
// (';') characters, as the symbol engine uses these characters as separators.
- MSSymbolServerConverter(const string &local_cache,
- const vector<string> &symbol_servers);
+ // If |trace_symsrv| is set then callbacks from SymSrv will be logged to
+ // stderr.
+ MSSymbolServerConverter(const string& local_cache,
+ const vector<string>& symbol_servers,
+ bool trace_symsrv);
// Locates the PE file (DLL or EXE) specified by the identifying information
// in |missing|, by checking the symbol stores identified when the object
// was created. When returning LOCATE_SUCCESS, pe_file is set to
// the pathname of the decompressed PE file as it is stored in the
// local cache.
- LocateResult LocatePEFile(const MissingSymbolInfo &missing, string *pe_file);
+ LocateResult LocatePEFile(const MissingSymbolInfo& missing, string* pe_file);
// Locates the symbol file specified by the identifying information in
// |missing|, by checking the symbol stores identified when the object
// was created. When returning LOCATE_SUCCESS, symbol_file is set to
// the pathname of the decompressed symbol file as it is stored in the
// local cache.
- LocateResult LocateSymbolFile(const MissingSymbolInfo &missing,
- string *symbol_file);
+ LocateResult LocateSymbolFile(const MissingSymbolInfo& missing,
+ string* symbol_file);
// Calls LocateSymbolFile and converts the returned symbol file to the
// dumped-symbol format, storing it adjacent to the symbol file. The
@@ -170,12 +173,12 @@ class MSSymbolServerConverter {
// is desired, set |keep_symbol_file| and |keep_pe_file| to false to indicate
// that the original symbol file (pdb) and executable file (exe, dll) should
// be deleted after conversion.
- LocateResult LocateAndConvertSymbolFile(const MissingSymbolInfo &missing,
+ LocateResult LocateAndConvertSymbolFile(const MissingSymbolInfo& missing,
bool keep_symbol_file,
bool keep_pe_file,
- string *converted_symbol_file,
- string *symbol_file,
- string *pe_file);
+ string* converted_symbol_file,
+ string* symbol_file,
+ string* pe_file);
// Calls LocatePEFile and converts the returned PE file to the
// dumped-symbol format, storing it adjacent to the PE file. The
@@ -188,10 +191,10 @@ class MSSymbolServerConverter {
// to false to indicate that the executable file (exe, dll) should be deleted
// after conversion.
// NOTE: Currrently only supports x64 PEs.
- LocateResult LocateAndConvertPEFile(const MissingSymbolInfo &missing,
- bool keep_pe_file,
- string *converted_symbol_file,
- string *pe_file);
+ LocateResult LocateAndConvertPEFile(const MissingSymbolInfo& missing,
+ bool keep_pe_file,
+ string* converted_symbol_file,
+ string* pe_file);
private:
// Locates the PDB or PE file (DLL or EXE) specified by the identifying
@@ -199,9 +202,9 @@ class MSSymbolServerConverter {
// the symbol stores identified when the object was created. When
// returning LOCATE_SUCCESS, file_name is set to the pathname of the
// decompressed PDB or PE file file as it is stored in the local cache.
- LocateResult LocateFile(const string &debug_or_code_file,
- const string &debug_or_code_id,
- const string &version, string *file_name);
+ LocateResult LocateFile(const string& debug_or_code_file,
+ const string& debug_or_code_id,
+ const string& version, string* file_name);
// Called by various SymSrv functions to report status as progress is made
// and to allow the callback to influence processing. Messages sent to this
@@ -215,8 +218,8 @@ class MSSymbolServerConverter {
// SymFindFileInPath actually seems to accept NULL for a callback function
// and behave properly for our needs in that case, but the documentation
// doesn't mention it, so this little callback is provided.
- static BOOL CALLBACK SymFindFileInPathCallback(const char *filename,
- void *context);
+ static BOOL CALLBACK SymFindFileInPathCallback(const char* filename,
+ void* context);
// The search path used by SymSrv, built based on the arguments to the
// constructor.
@@ -226,8 +229,12 @@ class MSSymbolServerConverter {
// SymFindFileInPath fails for an expected reason.
bool fail_dns_; // DNS failures (fail_not_found_ will also be set).
bool fail_timeout_; // Timeouts (fail_not_found_ will also be set).
+ bool fail_http_https_redir_; // Bad URL-- we should be using HTTPS.
bool fail_not_found_; // The file could not be found. If this is the only
// fail_* member set, then it is authoritative.
+
+ // If set then callbacks from SymSrv will be logged to stderr.
+ bool trace_symsrv_;
};
} // namespace google_breakpad
diff --git a/src/tools/windows/converter_exe/converter.cc b/src/tools/windows/converter_exe/converter.cc
index 5b70903a..75ec55b0 100644
--- a/src/tools/windows/converter_exe/converter.cc
+++ b/src/tools/windows/converter_exe/converter.cc
@@ -1,807 +1,904 @@
-// Copyright 2019 Google Inc. All rights reserved.
-//
-// 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 Inc. 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.
-
-#pragma comment(lib, "winhttp.lib")
-#pragma comment(lib, "wininet.lib")
-#pragma comment(lib, "diaguids.lib")
-#pragma comment(lib, "imagehlp.lib")
-
-#include <cassert>
-#include <cstdio>
-#include <ctime>
-#include <map>
-#include <regex>
-#include <string>
-#include <vector>
-
-#include "tools/windows/converter_exe/escaping.h"
-#include "tools/windows/converter_exe/http_download.h"
-#include "tools/windows/converter_exe/tokenizer.h"
-#include "common/windows/http_upload.h"
-#include "common/windows/string_utils-inl.h"
-#include "tools/windows/converter/ms_symbol_server_converter.h"
-
-using strings::WebSafeBase64Unescape;
-using strings::WebSafeBase64Escape;
-
-namespace {
-
-using std::map;
-using std::string;
-using std::vector;
-using std::wstring;
-using crash::HTTPDownload;
-using crash::Tokenizer;
-using google_breakpad::HTTPUpload;
-using google_breakpad::MissingSymbolInfo;
-using google_breakpad::MSSymbolServerConverter;
-using google_breakpad::WindowsStringUtils;
-
-const char *kMissingStringDelimiters = "|";
-const char *kLocalCachePath = "c:\\symbols";
-const char *kNoExeMSSSServer = "http://msdl.microsoft.com/download/symbols/";
-
-// Windows stdio doesn't do line buffering. Use this function to flush after
-// writing to stdout and stderr so that a log will be available if the
-// converter crashes.
-static int FprintfFlush(FILE *file, const char *format, ...) {
- va_list arguments;
- va_start(arguments, format);
- int retval = vfprintf(file, format, arguments);
- va_end(arguments);
- fflush(file);
- return retval;
-}
-
-static string CurrentDateAndTime() {
- const string kUnknownDateAndTime = R"(????-??-?? ??:??:??)";
-
- time_t current_time;
- time(&current_time);
-
- // localtime_s is safer but is only available in MSVC8. Use localtime
- // in earlier environments.
- struct tm *time_pointer;
-#if _MSC_VER >= 1400 // MSVC 2005/8
- struct tm time_struct;
- time_pointer = &time_struct;
- if (localtime_s(time_pointer, &current_time) != 0) {
- return kUnknownDateAndTime;
- }
-#else // _MSC_VER >= 1400
- time_pointer = localtime(&current_time);
- if (!time_pointer) {
- return kUnknownDateAndTime;
- }
-#endif // _MSC_VER >= 1400
-
- char buffer[256];
- if (!strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", time_pointer)) {
- return kUnknownDateAndTime;
- }
-
- return string(buffer);
-}
-
-// ParseMissingString turns |missing_string| into a MissingSymbolInfo
-// structure. It returns true on success, and false if no such conversion
-// is possible.
-static bool ParseMissingString(const string &missing_string,
- MissingSymbolInfo *missing_info) {
- assert(missing_info);
-
- vector<string> tokens;
- Tokenizer::Tokenize(kMissingStringDelimiters, missing_string, &tokens);
- if (tokens.size() != 5) {
- return false;
- }
-
- missing_info->debug_file = tokens[0];
- missing_info->debug_identifier = tokens[1];
- missing_info->version = tokens[2];
- missing_info->code_file = tokens[3];
- missing_info->code_identifier = tokens[4];
-
- return true;
-}
-
-// StringMapToWStringMap takes each element in a map that associates
-// (narrow) strings to strings and converts the keys and values to wstrings.
-// Returns true on success and false on failure, printing an error message.
-static bool StringMapToWStringMap(const map<string, string> &smap,
- map<wstring, wstring> *wsmap) {
- assert(wsmap);
- wsmap->clear();
-
- for (map<string, string>::const_iterator iterator = smap.begin();
- iterator != smap.end();
- ++iterator) {
- wstring key;
- if (!WindowsStringUtils::safe_mbstowcs(iterator->first, &key)) {
- FprintfFlush(stderr,
- "StringMapToWStringMap: safe_mbstowcs failed for key %s\n",
- iterator->first.c_str());
- return false;
- }
-
- wstring value;
- if (!WindowsStringUtils::safe_mbstowcs(iterator->second, &value)) {
- FprintfFlush(stderr, "StringMapToWStringMap: safe_mbstowcs failed "
- "for value %s\n",
- iterator->second.c_str());
- return false;
- }
-
- wsmap->insert(make_pair(key, value));
- }
-
- return true;
-}
-
-// MissingSymbolInfoToParameters turns a MissingSymbolInfo structure into a
-// map of parameters suitable for passing to HTTPDownload or HTTPUpload.
-// Returns true on success and false on failure, printing an error message.
-static bool MissingSymbolInfoToParameters(const MissingSymbolInfo &missing_info,
- map<wstring, wstring> *wparameters) {
- assert(wparameters);
-
- map<string, string> parameters;
- string encoded_param;
- // Indicate the params are encoded.
- parameters["encoded"] = "true"; // The string value here does not matter.
-
- WebSafeBase64Escape(missing_info.code_file, &encoded_param);
- parameters["code_file"] = encoded_param;
-
- WebSafeBase64Escape(missing_info.code_identifier, &encoded_param);
- parameters["code_identifier"] = encoded_param;
-
- WebSafeBase64Escape(missing_info.debug_file, &encoded_param);
- parameters["debug_file"] = encoded_param;
-
- WebSafeBase64Escape(missing_info.debug_identifier, &encoded_param);
- parameters["debug_identifier"] = encoded_param;
-
- if (!missing_info.version.empty()) {
- // The version is optional.
- WebSafeBase64Escape(missing_info.version, &encoded_param);
- parameters["version"] = encoded_param;
- }
-
- WebSafeBase64Escape("WinSymConv", &encoded_param);
- parameters["product"] = encoded_param;
-
- if (!StringMapToWStringMap(parameters, wparameters)) {
- // StringMapToWStringMap will have printed an error.
- return false;
- }
-
- return true;
-}
-
-// UploadSymbolFile sends |converted_file| as identified by |missing_info|
-// to the symbol server rooted at |upload_symbol_url|. Returns true on
-// success and false on failure, printing an error message.
-static bool UploadSymbolFile(const wstring &upload_symbol_url,
- const MissingSymbolInfo &missing_info,
- const string &converted_file) {
- map<wstring, wstring> parameters;
- if (!MissingSymbolInfoToParameters(missing_info, &parameters)) {
- // MissingSymbolInfoToParameters or a callee will have printed an error.
- return false;
- }
-
- wstring converted_file_w;
-
- if (!WindowsStringUtils::safe_mbstowcs(converted_file, &converted_file_w)) {
- FprintfFlush(stderr, "UploadSymbolFile: safe_mbstowcs failed for %s\n",
- converted_file.c_str());
- return false;
- }
- map<wstring, wstring> files;
- files[L"symbol_file"] = converted_file_w;
-
- FprintfFlush(stderr, "Uploading %s\n", converted_file.c_str());
- if (!HTTPUpload::SendMultipartPostRequest(
- upload_symbol_url, parameters,
- files, NULL, NULL, NULL)) {
- FprintfFlush(stderr, "UploadSymbolFile: HTTPUpload::SendRequest failed "
- "for %s %s %s\n",
- missing_info.debug_file.c_str(),
- missing_info.debug_identifier.c_str(),
- missing_info.version.c_str());
- return false;
- }
-
- return true;
-}
-
-// SendFetchFailedPing informs the symbol server based at
-// |fetch_symbol_failure_url| that the symbol file identified by
-// |missing_info| could authoritatively not be located. Returns
-// true on success and false on failure.
-static bool SendFetchFailedPing(const wstring &fetch_symbol_failure_url,
- const MissingSymbolInfo &missing_info) {
- map<wstring, wstring> parameters;
- if (!MissingSymbolInfoToParameters(missing_info, &parameters)) {
- // MissingSymbolInfoToParameters or a callee will have printed an error.
- return false;
- }
-
- string content;
- if (!HTTPDownload::Download(fetch_symbol_failure_url,
- &parameters,
- &content,
- NULL)) {
- FprintfFlush(stderr, "SendFetchFailedPing: HTTPDownload::Download failed "
- "for %s %s %s\n",
- missing_info.debug_file.c_str(),
- missing_info.debug_identifier.c_str(),
- missing_info.version.c_str());
- return false;
- }
-
- return true;
-}
-
-// Returns true if it's safe to make an external request for the symbol
-// file described in missing_info. It's considered safe to make an
-// external request unless the symbol file's debug_file string matches
-// the given blacklist regular expression.
-// The debug_file name is used from the MissingSymbolInfo struct,
-// matched against the blacklist_regex.
-static bool SafeToMakeExternalRequest(const MissingSymbolInfo &missing_info,
- std::regex blacklist_regex) {
- string file_name = missing_info.debug_file;
- // Use regex_search because we want to match substrings.
- if (std::regex_search(file_name, blacklist_regex)) {
- FprintfFlush(stderr, "Not safe to make external request for file %s\n",
- file_name.c_str());
- return false;
- }
-
- return true;
-}
-
-// Converter options derived from command line parameters.
-struct ConverterOptions {
- ConverterOptions()
- : report_fetch_failures(true) {
- }
-
- ~ConverterOptions() {
- }
-
- // Names of MS Symbol Supplier Servers that are internal to Google, and may
- // have symbols for any request.
- vector<string> full_internal_msss_servers;
-
- // Names of MS Symbol Supplier Servers that are internal to Google, and
- // shouldn't be checked for symbols for any .exe files.
- vector<string> full_external_msss_servers;
-
- // Names of MS Symbol Supplier Servers that are external to Google, and may
- // have symbols for any request.
- vector<string> no_exe_internal_msss_servers;
-
- // Names of MS Symbol Supplier Servers that are external to Google, and
- // shouldn't be checked for symbols for any .exe files.
- vector<string> no_exe_external_msss_servers;
-
- // Temporary local storage for symbols.
- string local_cache_path;
-
- // URL for uploading symbols.
- wstring upload_symbols_url;
-
- // URL to fetch list of missing symbols.
- wstring missing_symbols_url;
-
- // URL to report symbol fetch failure.
- wstring fetch_symbol_failure_url;
-
- // Are symbol fetch failures reported.
- bool report_fetch_failures;
-
- // File containing the list of missing symbols. Fetch failures are not
- // reported if such file is provided.
- string missing_symbols_file;
-
- // Regex used to blacklist files to prevent external symbol requests.
- // Owned and cleaned up by this struct.
- std::regex blacklist_regex;
-
- private:
- // DISABLE_COPY_AND_ASSIGN
- ConverterOptions(const ConverterOptions&);
- ConverterOptions& operator=(const ConverterOptions&);
-};
-
-// ConverMissingSymbolFile takes a single MissingSymbolInfo structure and
-// attempts to locate it from the symbol servers provided in the
-// |options.*_msss_servers| arguments. "Full" servers are those that will be
-// queried for all symbol files; "No-EXE" servers will only be queried for
-// modules whose missing symbol data indicates are not main program executables.
-// Results will be sent to the |options.upload_symbols_url| on success or
-// |options.fetch_symbol_failure_url| on failure, and the local cache will be
-// stored at |options.local_cache_path|. Because nothing can be done even in
-// the event of a failure, this function returns no value, although it
-// may result in error messages being printed.
-static void ConvertMissingSymbolFile(const MissingSymbolInfo &missing_info,
- const ConverterOptions &options) {
- string time_string = CurrentDateAndTime();
- FprintfFlush(stdout, "converter: %s: attempting %s %s %s\n",
- time_string.c_str(),
- missing_info.debug_file.c_str(),
- missing_info.debug_identifier.c_str(),
- missing_info.version.c_str());
-
- // The first lookup is always to internal symbol servers.
- // Always ask the symbol servers identified as "full."
- vector<string> msss_servers = options.full_internal_msss_servers;
-
- // If the file is not an .exe file, also ask an additional set of symbol
- // servers, such as Microsoft's public symbol server.
- bool is_exe = false;
-
- if (missing_info.code_file.length() >= 4) {
- string code_extension =
- missing_info.code_file.substr(missing_info.code_file.size() - 4);
-
- // Firefox is a special case: .dll-only servers should be consulted for
- // its symbols. This enables us to get its symbols from Mozilla's
- // symbol server when crashes occur in Google extension code hosted by a
- // Firefox process.
- if (_stricmp(code_extension.c_str(), ".exe") == 0 &&
- _stricmp(missing_info.code_file.c_str(), "firefox.exe") != 0) {
- is_exe = true;
- }
- }
-
- if (!is_exe) {
- msss_servers.insert(msss_servers.end(),
- options.no_exe_internal_msss_servers.begin(),
- options.no_exe_internal_msss_servers.end());
- }
-
- // If there are any suitable internal symbol servers, make a request.
- MSSymbolServerConverter::LocateResult located =
- MSSymbolServerConverter::LOCATE_FAILURE;
- string converted_file;
- if (msss_servers.size() > 0) {
- // Attempt to fetch the symbol file and convert it.
- FprintfFlush(stderr, "Making internal request for %s (%s)\n",
- missing_info.debug_file.c_str(),
- missing_info.debug_identifier.c_str());
- MSSymbolServerConverter converter(options.local_cache_path, msss_servers);
- located = converter.LocateAndConvertSymbolFile(missing_info,
- false, // keep_symbol_file
- false, // keep_pe_file
- &converted_file,
- NULL, // symbol_file
- NULL); // pe_file
- switch (located) {
- case MSSymbolServerConverter::LOCATE_SUCCESS:
- FprintfFlush(stderr, "LocateResult = LOCATE_SUCCESS\n");
- // Upload it. Don't bother checking the return value. If this
- // succeeds, it should disappear from the missing symbol list.
- // If it fails, something will print an error message indicating
- // the cause of the failure, and the item will remain on the
- // missing symbol list.
- UploadSymbolFile(options.upload_symbols_url, missing_info,
- converted_file);
- remove(converted_file.c_str());
-
- // Note: this does leave some directories behind that could be
- // cleaned up. The directories inside options.local_cache_path for
- // debug_file/debug_identifier can be removed at this point.
- break;
-
- case MSSymbolServerConverter::LOCATE_NOT_FOUND:
- FprintfFlush(stderr, "LocateResult = LOCATE_NOT_FOUND\n");
- // The symbol file definitively did not exist. Fall through,
- // so we can attempt an external query if it's safe to do so.
- break;
-
- case MSSymbolServerConverter::LOCATE_RETRY:
- FprintfFlush(stderr, "LocateResult = LOCATE_RETRY\n");
- // Fall through in case we should make an external request.
- // If not, or if an external request fails in the same way,
- // we'll leave the entry in the symbol file list and
- // try again on a future pass. Print a message so that there's
- // a record.
- break;
-
- case MSSymbolServerConverter::LOCATE_FAILURE:
- FprintfFlush(stderr, "LocateResult = LOCATE_FAILURE\n");
- // LocateAndConvertSymbolFile printed an error message.
- break;
-
- default:
- FprintfFlush(
- stderr,
- "FATAL: Unexpected return value '%d' from "
- "LocateAndConvertSymbolFile()\n",
- located);
- assert(0);
- break;
- }
- } else {
- // No suitable internal symbol servers. This is fine because the converter
- // is mainly used for downloading and converting of external symbols.
- }
-
- // Make a request to an external server if the internal request didn't
- // succeed, and it's safe to do so.
- if (located != MSSymbolServerConverter::LOCATE_SUCCESS &&
- SafeToMakeExternalRequest(missing_info, options.blacklist_regex)) {
- msss_servers = options.full_external_msss_servers;
- if (!is_exe) {
- msss_servers.insert(msss_servers.end(),
- options.no_exe_external_msss_servers.begin(),
- options.no_exe_external_msss_servers.end());
- }
- if (msss_servers.size() > 0) {
- FprintfFlush(stderr, "Making external request for %s (%s)\n",
- missing_info.debug_file.c_str(),
- missing_info.debug_identifier.c_str());
- MSSymbolServerConverter external_converter(options.local_cache_path,
- msss_servers);
- located = external_converter.LocateAndConvertSymbolFile(
- missing_info,
- false, // keep_symbol_file
- false, // keep_pe_file
- &converted_file,
- NULL, // symbol_file
- NULL); // pe_file
- } else {
- FprintfFlush(stderr, "ERROR: No suitable external symbol servers.\n");
- }
- }
-
- // Final handling for this symbol file is based on the result from the
- // external request (if performed above), or on the result from the
- // previous internal lookup.
- switch (located) {
- case MSSymbolServerConverter::LOCATE_SUCCESS:
- FprintfFlush(stderr, "LocateResult = LOCATE_SUCCESS\n");
- // Upload it. Don't bother checking the return value. If this
- // succeeds, it should disappear from the missing symbol list.
- // If it fails, something will print an error message indicating
- // the cause of the failure, and the item will remain on the
- // missing symbol list.
- UploadSymbolFile(options.upload_symbols_url, missing_info,
- converted_file);
- remove(converted_file.c_str());
-
- // Note: this does leave some directories behind that could be
- // cleaned up. The directories inside options.local_cache_path for
- // debug_file/debug_identifier can be removed at this point.
- break;
-
- case MSSymbolServerConverter::LOCATE_NOT_FOUND:
- // The symbol file definitively didn't exist. Inform the server.
- // If this fails, something will print an error message indicating
- // the cause of the failure, but there's really nothing more to
- // do. If this succeeds, the entry should be removed from the
- // missing symbols list.
- if (!options.report_fetch_failures) {
- FprintfFlush(stderr, "SendFetchFailedPing skipped\n");
- } else if (SendFetchFailedPing(options.fetch_symbol_failure_url,
- missing_info)) {
- FprintfFlush(stderr, "SendFetchFailedPing succeeded\n");
- } else {
- FprintfFlush(stderr, "SendFetchFailedPing failed\n");
- }
- break;
-
- case MSSymbolServerConverter::LOCATE_RETRY:
- FprintfFlush(stderr, "LocateResult = LOCATE_RETRY\n");
- // Nothing to do but leave the entry in the symbol file list and
- // try again on a future pass. Print a message so that there's
- // a record.
- FprintfFlush(stderr, "ConvertMissingSymbolFile: deferring retry "
- "for %s %s %s\n",
- missing_info.debug_file.c_str(),
- missing_info.debug_identifier.c_str(),
- missing_info.version.c_str());
- break;
-
- case MSSymbolServerConverter::LOCATE_FAILURE:
- FprintfFlush(stderr, "LocateResult = LOCATE_FAILURE\n");
- // LocateAndConvertSymbolFile printed an error message.
-
- // This is due to a bad debug file name, so fetch failed.
- if (!options.report_fetch_failures) {
- FprintfFlush(stderr, "SendFetchFailedPing skipped\n");
- } else if (SendFetchFailedPing(options.fetch_symbol_failure_url,
- missing_info)) {
- FprintfFlush(stderr, "SendFetchFailedPing succeeded\n");
- } else {
- FprintfFlush(stderr, "SendFetchFailedPing failed\n");
- }
- break;
-
- default:
- FprintfFlush(
- stderr,
- "FATAL: Unexpected return value '%d' from "
- "LocateAndConvertSymbolFile()\n",
- located);
- assert(0);
- break;
- }
-}
-
-
-// Reads the contents of file |file_name| and populates |contents|.
-// Returns true on success.
-static bool ReadFile(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) {
- contents->append(buffer);
- }
- fclose(fp);
- return true;
-}
-
-// ConvertMissingSymbolsList obtains a missing symbol list from
-// |options.missing_symbols_url| or |options.missing_symbols_file| and calls
-// ConvertMissingSymbolFile for each missing symbol file in the list.
-static bool ConvertMissingSymbolsList(const ConverterOptions &options) {
- // Set param to indicate requesting for encoded response.
- map<wstring, wstring> parameters;
- parameters[L"product"] = L"WinSymConv";
- parameters[L"encoded"] = L"true";
- // Get the missing symbol list.
- string missing_symbol_list;
- if (!options.missing_symbols_file.empty()) {
- if (!ReadFile(options.missing_symbols_file, &missing_symbol_list)) {
- return false;
- }
- } else if (!HTTPDownload::Download(options.missing_symbols_url, &parameters,
- &missing_symbol_list, NULL)) {
- return false;
- }
-
- // Tokenize the content into a vector.
- vector<string> missing_symbol_lines;
- Tokenizer::Tokenize("\n", missing_symbol_list, &missing_symbol_lines);
-
- FprintfFlush(stderr, "Found %d missing symbol files in list.\n",
- missing_symbol_lines.size() - 1); // last line is empty.
- int convert_attempts = 0;
- for (vector<string>::const_iterator iterator = missing_symbol_lines.begin();
- iterator != missing_symbol_lines.end();
- ++iterator) {
- // Decode symbol line.
- const string &encoded_line = *iterator;
- // Skip lines that are blank.
- if (encoded_line.empty()) {
- continue;
- }
-
- string line;
- if (!WebSafeBase64Unescape(encoded_line, &line)) {
- // If decoding fails, assume the line is not encoded.
- // This is helpful when the program connects to a debug server without
- // encoding.
- line = encoded_line;
- }
-
- FprintfFlush(stderr, "\nLine: %s\n", line.c_str());
-
- // Turn each element into a MissingSymbolInfo structure.
- MissingSymbolInfo missing_info;
- if (!ParseMissingString(line, &missing_info)) {
- FprintfFlush(stderr, "ConvertMissingSymbols: ParseMissingString failed "
- "for %s from %ws\n",
- line.c_str(), options.missing_symbols_url.c_str());
- continue;
- }
-
- ++convert_attempts;
- ConvertMissingSymbolFile(missing_info, options);
- }
-
- // Say something reassuring, since ConvertMissingSymbolFile was never called
- // and therefore never reported any progress.
- if (convert_attempts == 0) {
- string current_time = CurrentDateAndTime();
- FprintfFlush(stdout, "converter: %s: nothing to convert\n",
- current_time.c_str());
- }
-
- return true;
-}
-
-// usage prints the usage message. It returns 1 as a convenience, to be used
-// as a return value from main.
-static int usage(const char *program_name) {
- FprintfFlush(stderr,
- "usage: %s [options]\n"
- " -f <full_msss_server> MS servers to ask for all symbols\n"
- " -n <no_exe_msss_server> same, but prevent asking for EXEs\n"
- " -l <local_cache_path> Temporary local storage for symbols\n"
- " -s <upload_url> URL for uploading symbols\n"
- " -m <missing_symbols_url> URL to fetch list of missing symbols\n"
- " -mf <missing_symbols_file> File containing the list of missing\n"
- " symbols. Fetch failures are not\n"
- " reported if such file is provided.\n"
- " -t <fetch_failure_url> URL to report symbol fetch failure\n"
- " -b <regex> Regex used to blacklist files to\n"
- " prevent external symbol requests\n"
- " Note that any server specified by -f or -n that starts with \\filer\n"
- " will be treated as internal, and all others as external.\n",
- program_name);
-
- return 1;
-}
-
-// "Internal" servers consist only of those whose names start with
-// the literal string "\\filer\".
-static bool IsInternalServer(const string &server_name) {
- if (server_name.find("\\\\filer\\") == 0) {
- return true;
- }
- return false;
-}
-
-// Adds a server with the given name to the list of internal or external
-// servers, as appropriate.
-static void AddServer(const string &server_name,
- vector<string> *internal_servers,
- vector<string> *external_servers) {
- if (IsInternalServer(server_name)) {
- internal_servers->push_back(server_name);
- } else {
- external_servers->push_back(server_name);
- }
-}
-
-} // namespace
-
-int main(int argc, char **argv) {
- string time_string = CurrentDateAndTime();
- FprintfFlush(stdout, "converter: %s: starting\n", time_string.c_str());
-
- ConverterOptions options;
- options.report_fetch_failures = true;
-
- // All arguments are paired.
- if (argc % 2 != 1) {
- return usage(argv[0]);
- }
-
- string blacklist_regex_str;
- bool have_any_msss_servers = false;
- for (int argi = 1; argi < argc; argi += 2) {
- string option = argv[argi];
- string value = argv[argi + 1];
-
- if (option == "-f") {
- AddServer(value, &options.full_internal_msss_servers,
- &options.full_external_msss_servers);
- have_any_msss_servers = true;
- } else if (option == "-n") {
- AddServer(value, &options.no_exe_internal_msss_servers,
- &options.no_exe_external_msss_servers);
- have_any_msss_servers = true;
- } else if (option == "-l") {
- if (!options.local_cache_path.empty()) {
- return usage(argv[0]);
- }
- options.local_cache_path = value;
- } else if (option == "-s") {
- if (!WindowsStringUtils::safe_mbstowcs(value,
- &options.upload_symbols_url)) {
- FprintfFlush(stderr, "main: safe_mbstowcs failed for %s\n",
- value.c_str());
- return 1;
- }
- } else if (option == "-m") {
- if (!WindowsStringUtils::safe_mbstowcs(value,
- &options.missing_symbols_url)) {
- FprintfFlush(stderr, "main: safe_mbstowcs failed for %s\n",
- value.c_str());
- return 1;
- }
- } else if (option == "-mf") {
- options.missing_symbols_file = value;
- printf("Getting the list of missing symbols from a file. Fetch failures"
- " will not be reported.\n");
- options.report_fetch_failures = false;
- } else if (option == "-t") {
- if (!WindowsStringUtils::safe_mbstowcs(
- value,
- &options.fetch_symbol_failure_url)) {
- FprintfFlush(stderr, "main: safe_mbstowcs failed for %s\n",
- value.c_str());
- return 1;
- }
- } else if (option == "-b") {
- blacklist_regex_str = value;
- } else {
- return usage(argv[0]);
- }
- }
-
- if (blacklist_regex_str.empty()) {
- FprintfFlush(stderr, "No blacklist specified.\n");
- return usage(argv[0]);
- }
-
- // Compile the blacklist regular expression for later use.
- options.blacklist_regex = std::regex(blacklist_regex_str.c_str(),
- std::regex_constants::icase);
-
- // Set the defaults. If the user specified any MSSS servers, don't use
- // any default.
- if (!have_any_msss_servers) {
- AddServer(kNoExeMSSSServer, &options.no_exe_internal_msss_servers,
- &options.no_exe_external_msss_servers);
- }
-
- if (options.local_cache_path.empty()) {
- options.local_cache_path = kLocalCachePath;
- }
-
- if (options.upload_symbols_url.empty()) {
- FprintfFlush(stderr, "No upload symbols URL specified.\n");
- return usage(argv[0]);
- }
- if (options.missing_symbols_url.empty() &&
- options.missing_symbols_file.empty()) {
- FprintfFlush(stderr, "No missing symbols URL or file specified.\n");
- return usage(argv[0]);
- }
- if (options.fetch_symbol_failure_url.empty()) {
- FprintfFlush(stderr, "No fetch symbol failure URL specified.\n");
- return usage(argv[0]);
- }
-
- FprintfFlush(stdout,
- "# of Symbol Servers (int/ext): %d/%d full, %d/%d no_exe\n",
- options.full_internal_msss_servers.size(),
- options.full_external_msss_servers.size(),
- options.no_exe_internal_msss_servers.size(),
- options.no_exe_external_msss_servers.size());
-
- if (!ConvertMissingSymbolsList(options)) {
- return 1;
- }
-
- time_string = CurrentDateAndTime();
- FprintfFlush(stdout, "converter: %s: finished\n", time_string.c_str());
- return 0;
-}
+// Copyright 2019 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.
+
+#pragma comment(lib, "winhttp.lib")
+#pragma comment(lib, "wininet.lib")
+#pragma comment(lib, "diaguids.lib")
+#pragma comment(lib, "imagehlp.lib")
+
+#include <cassert>
+#include <cstdio>
+#include <ctime>
+#include <map>
+#include <regex>
+#include <string>
+#include <vector>
+
+#include "common/windows/http_upload.h"
+#include "common/windows/string_utils-inl.h"
+#include "common/windows/sym_upload_v2_protocol.h"
+#include "tools/windows/converter/ms_symbol_server_converter.h"
+#include "tools/windows/converter_exe/escaping.h"
+#include "tools/windows/converter_exe/http_download.h"
+#include "tools/windows/converter_exe/tokenizer.h"
+
+using strings::WebSafeBase64Unescape;
+using strings::WebSafeBase64Escape;
+
+namespace {
+
+using std::map;
+using std::string;
+using std::vector;
+using std::wstring;
+using crash::HTTPDownload;
+using crash::Tokenizer;
+using google_breakpad::HTTPUpload;
+using google_breakpad::MissingSymbolInfo;
+using google_breakpad::MSSymbolServerConverter;
+using google_breakpad::WindowsStringUtils;
+
+const char* kMissingStringDelimiters = "|";
+const char* kLocalCachePath = "c:\\symbols";
+const char* kNoExeMSSSServer = "http://msdl.microsoft.com/download/symbols/";
+const wchar_t* kSymbolUploadTypeBreakpad = L"BREAKPAD";
+const wchar_t* kSymbolUploadTypePE = L"PE";
+const wchar_t* kSymbolUploadTypePDB = L"PDB";
+const wchar_t* kConverterProductName = L"WinSymConv";
+
+// Windows stdio doesn't do line buffering. Use this function to flush after
+// writing to stdout and stderr so that a log will be available if the
+// converter crashes.
+static int FprintfFlush(FILE* file, const char* format, ...) {
+ va_list arguments;
+ va_start(arguments, format);
+ int retval = vfprintf(file, format, arguments);
+ va_end(arguments);
+ fflush(file);
+ return retval;
+}
+
+static string CurrentDateAndTime() {
+ const string kUnknownDateAndTime = R"(????-??-?? ??:??:??)";
+
+ time_t current_time;
+ time(&current_time);
+
+ // localtime_s is safer but is only available in MSVC8. Use localtime
+ // in earlier environments.
+ struct tm* time_pointer;
+#if _MSC_VER >= 1400 // MSVC 2005/8
+ struct tm time_struct;
+ time_pointer =& time_struct;
+ if (localtime_s(time_pointer,& current_time) != 0) {
+ return kUnknownDateAndTime;
+ }
+#else // _MSC_VER >= 1400
+ time_pointer = localtime(&current_time);
+ if (!time_pointer) {
+ return kUnknownDateAndTime;
+ }
+#endif // _MSC_VER >= 1400
+
+ char buffer[256];
+ if (!strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", time_pointer)) {
+ return kUnknownDateAndTime;
+ }
+
+ return string(buffer);
+}
+
+// ParseMissingString turns |missing_string| into a MissingSymbolInfo
+// structure. It returns true on success, and false if no such conversion
+// is possible.
+static bool ParseMissingString(const string& missing_string,
+ MissingSymbolInfo* missing_info) {
+ assert(missing_info);
+
+ vector<string> tokens;
+ Tokenizer::Tokenize(kMissingStringDelimiters, missing_string,& tokens);
+ if (tokens.size() != 5) {
+ return false;
+ }
+
+ missing_info->debug_file = tokens[0];
+ missing_info->debug_identifier = tokens[1];
+ missing_info->version = tokens[2];
+ missing_info->code_file = tokens[3];
+ missing_info->code_identifier = tokens[4];
+
+ return true;
+}
+
+// StringMapToWStringMap takes each element in a map that associates
+// (narrow) strings to strings and converts the keys and values to wstrings.
+// Returns true on success and false on failure, printing an error message.
+static bool StringMapToWStringMap(const map<string, string>& smap,
+ map<wstring, wstring>* wsmap) {
+ assert(wsmap);
+ wsmap->clear();
+
+ for (map<string, string>::const_iterator iterator = smap.begin();
+ iterator != smap.end();
+ ++iterator) {
+ wstring key;
+ if (!WindowsStringUtils::safe_mbstowcs(iterator->first,& key)) {
+ FprintfFlush(stderr,
+ "StringMapToWStringMap: safe_mbstowcs failed for key %s\n",
+ iterator->first.c_str());
+ return false;
+ }
+
+ wstring value;
+ if (!WindowsStringUtils::safe_mbstowcs(iterator->second,& value)) {
+ FprintfFlush(stderr, "StringMapToWStringMap: safe_mbstowcs failed "
+ "for value %s\n",
+ iterator->second.c_str());
+ return false;
+ }
+
+ wsmap->insert(make_pair(key, value));
+ }
+
+ return true;
+}
+
+// MissingSymbolInfoToParameters turns a MissingSymbolInfo structure into a
+// map of parameters suitable for passing to HTTPDownload or HTTPUpload.
+// Returns true on success and false on failure, printing an error message.
+static bool MissingSymbolInfoToParameters(const MissingSymbolInfo& missing_info,
+ map<wstring, wstring>* wparameters) {
+ assert(wparameters);
+
+ map<string, string> parameters;
+ string encoded_param;
+ // Indicate the params are encoded.
+ parameters["encoded"] = "true"; // The string value here does not matter.
+
+ WebSafeBase64Escape(missing_info.code_file,& encoded_param);
+ parameters["code_file"] = encoded_param;
+
+ WebSafeBase64Escape(missing_info.code_identifier,& encoded_param);
+ parameters["code_identifier"] = encoded_param;
+
+ WebSafeBase64Escape(missing_info.debug_file,& encoded_param);
+ parameters["debug_file"] = encoded_param;
+
+ WebSafeBase64Escape(missing_info.debug_identifier,& encoded_param);
+ parameters["debug_identifier"] = encoded_param;
+
+ if (!missing_info.version.empty()) {
+ // The version is optional.
+ WebSafeBase64Escape(missing_info.version,& encoded_param);
+ parameters["version"] = encoded_param;
+ }
+
+ WebSafeBase64Escape("WinSymConv",& encoded_param);
+ parameters["product"] = encoded_param;
+
+ if (!StringMapToWStringMap(parameters, wparameters)) {
+ // StringMapToWStringMap will have printed an error.
+ return false;
+ }
+
+ return true;
+}
+
+// UploadSymbolFile sends |converted_file| as identified by |debug_file| and
+// |debug_identifier|, to the symbol server rooted at |upload_symbol_url|.
+// Returns true on success and false on failure, printing an error message.
+static bool UploadSymbolFile(const wstring& upload_symbol_url,
+ const wstring& api_key,
+ const string& debug_file,
+ const string& debug_identifier,
+ const string& symbol_file,
+ const wstring& symbol_type) {
+ wstring debug_file_w;
+ if (!WindowsStringUtils::safe_mbstowcs(debug_file, &debug_file_w)) {
+ FprintfFlush(stderr, "UploadSymbolFile: safe_mbstowcs failed for %s\n",
+ symbol_file.c_str());
+ return false;
+ }
+
+ wstring debug_id_w;
+ if (!WindowsStringUtils::safe_mbstowcs(debug_identifier, &debug_id_w)) {
+ FprintfFlush(stderr, "UploadSymbolFile: safe_mbstowcs failed for %s\n",
+ symbol_file.c_str());
+ return false;
+ }
+
+ wstring symbol_file_w;
+ if (!WindowsStringUtils::safe_mbstowcs(symbol_file, &symbol_file_w)) {
+ FprintfFlush(stderr, "UploadSymbolFile: safe_mbstowcs failed for %s\n",
+ symbol_file.c_str());
+ return false;
+ }
+
+ int timeout_ms = 60 * 1000;
+ FprintfFlush(stderr, "Uploading %s\n", symbol_file.c_str());
+ if (!google_breakpad::SymUploadV2ProtocolSend(
+ upload_symbol_url.c_str(), api_key.c_str(), &timeout_ms, debug_file_w,
+ debug_id_w, symbol_file_w, symbol_type, kConverterProductName,
+ /*force=*/true)) {
+ FprintfFlush(stderr,
+ "UploadSymbolFile: HTTPUpload::SendRequest failed "
+ "for %s %s\n",
+ debug_file.c_str(), debug_identifier.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+// SendFetchFailedPing informs the symbol server based at
+// |fetch_symbol_failure_url| that the symbol file identified by
+// |missing_info| could authoritatively not be located. Returns
+// true on success and false on failure.
+static bool SendFetchFailedPing(const wstring& fetch_symbol_failure_url,
+ const MissingSymbolInfo& missing_info) {
+ map<wstring, wstring> parameters;
+ if (!MissingSymbolInfoToParameters(missing_info,& parameters)) {
+ // MissingSymbolInfoToParameters or a callee will have printed an error.
+ return false;
+ }
+
+ string content;
+ if (!HTTPDownload::Download(fetch_symbol_failure_url,
+ & parameters,
+ & content,
+ NULL)) {
+ FprintfFlush(stderr, "SendFetchFailedPing: HTTPDownload::Download failed "
+ "for %s %s %s\n",
+ missing_info.debug_file.c_str(),
+ missing_info.debug_identifier.c_str(),
+ missing_info.version.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+// Returns true if it's safe to make an external request for the symbol
+// file described in missing_info. It's considered safe to make an
+// external request unless the symbol file's debug_file string matches
+// the given blacklist regular expression.
+// The debug_file name is used from the MissingSymbolInfo struct,
+// matched against the blacklist_regex.
+static bool SafeToMakeExternalRequest(const MissingSymbolInfo& missing_info,
+ std::regex blacklist_regex) {
+ string file_name = missing_info.debug_file;
+ // Use regex_search because we want to match substrings.
+ if (std::regex_search(file_name, blacklist_regex)) {
+ FprintfFlush(stderr, "Not safe to make external request for file %s\n",
+ file_name.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+// Converter options derived from command line parameters.
+struct ConverterOptions {
+ ConverterOptions()
+ : report_fetch_failures(true), trace_symsrv(false), keep_files(false) {}
+
+ ~ConverterOptions() {
+ }
+
+ // Names of MS Symbol Supplier Servers that are internal to Google, and may
+ // have symbols for any request.
+ vector<string> full_internal_msss_servers;
+
+ // Names of MS Symbol Supplier Servers that are internal to Google, and
+ // shouldn't be checked for symbols for any .exe files.
+ vector<string> full_external_msss_servers;
+
+ // Names of MS Symbol Supplier Servers that are external to Google, and may
+ // have symbols for any request.
+ vector<string> no_exe_internal_msss_servers;
+
+ // Names of MS Symbol Supplier Servers that are external to Google, and
+ // shouldn't be checked for symbols for any .exe files.
+ vector<string> no_exe_external_msss_servers;
+
+ // Temporary local storage for symbols.
+ string local_cache_path;
+
+ // URL for uploading symbols.
+ wstring upload_symbols_url;
+
+ // API key to use when uploading symbols.
+ wstring api_key;
+
+ // URL to fetch list of missing symbols.
+ wstring missing_symbols_url;
+
+ // URL to report symbol fetch failure.
+ wstring fetch_symbol_failure_url;
+
+ // Are symbol fetch failures reported.
+ bool report_fetch_failures;
+
+ // File containing the list of missing symbols. Fetch failures are not
+ // reported if such file is provided.
+ string missing_symbols_file;
+
+ // Regex used to blacklist files to prevent external symbol requests.
+ // Owned and cleaned up by this struct.
+ std::regex blacklist_regex;
+
+ // If set then SymSrv callbacks are logged to stderr.
+ bool trace_symsrv;
+
+ // If set then Breakpad/PE/PDB files won't be deleted after processing.
+ bool keep_files;
+
+ private:
+ // DISABLE_COPY_AND_ASSIGN
+ ConverterOptions(const ConverterOptions&);
+ ConverterOptions& operator=(const ConverterOptions&);
+};
+
+// ConverMissingSymbolFile takes a single MissingSymbolInfo structure and
+// attempts to locate it from the symbol servers provided in the
+// |options.*_msss_servers| arguments. "Full" servers are those that will be
+// queried for all symbol files; "No-EXE" servers will only be queried for
+// modules whose missing symbol data indicates are not main program executables.
+// Results will be sent to the |options.upload_symbols_url| on success or
+// |options.fetch_symbol_failure_url| on failure, and the local cache will be
+// stored at |options.local_cache_path|. Because nothing can be done even in
+// the event of a failure, this function returns no value, although it
+// may result in error messages being printed.
+static void ConvertMissingSymbolFile(const MissingSymbolInfo& missing_info,
+ const ConverterOptions& options) {
+ string time_string = CurrentDateAndTime();
+ FprintfFlush(stdout, "converter: %s: attempting %s %s %s\n",
+ time_string.c_str(),
+ missing_info.debug_file.c_str(),
+ missing_info.debug_identifier.c_str(),
+ missing_info.version.c_str());
+
+ // The first lookup is always to internal symbol servers.
+ // Always ask the symbol servers identified as "full."
+ vector<string> msss_servers = options.full_internal_msss_servers;
+
+ // If the file is not an .exe file, also ask an additional set of symbol
+ // servers, such as Microsoft's public symbol server.
+ bool is_exe = false;
+
+ if (missing_info.code_file.length() >= 4) {
+ string code_extension =
+ missing_info.code_file.substr(missing_info.code_file.size() - 4);
+
+ // Firefox is a special case: .dll-only servers should be consulted for
+ // its symbols. This enables us to get its symbols from Mozilla's
+ // symbol server when crashes occur in Google extension code hosted by a
+ // Firefox process.
+ if (_stricmp(code_extension.c_str(), ".exe") == 0 &&
+ _stricmp(missing_info.code_file.c_str(), "firefox.exe") != 0) {
+ is_exe = true;
+ }
+ }
+
+ if (!is_exe) {
+ msss_servers.insert(msss_servers.end(),
+ options.no_exe_internal_msss_servers.begin(),
+ options.no_exe_internal_msss_servers.end());
+ }
+
+ // If there are any suitable internal symbol servers, make a request.
+ MSSymbolServerConverter::LocateResult located =
+ MSSymbolServerConverter::LOCATE_FAILURE;
+ string converted_file;
+ string symbol_file;
+ string pe_file;
+ if (msss_servers.size() > 0) {
+ // Attempt to fetch the symbol file and convert it.
+ FprintfFlush(stderr, "Making internal request for %s (%s)\n",
+ missing_info.debug_file.c_str(),
+ missing_info.debug_identifier.c_str());
+ MSSymbolServerConverter converter(options.local_cache_path, msss_servers,
+ options.trace_symsrv);
+ located = converter.LocateAndConvertSymbolFile(
+ missing_info,
+ /*keep_symbol_file=*/true,
+ /*keep_pe_file=*/true, &converted_file, &symbol_file, &pe_file);
+ switch (located) {
+ case MSSymbolServerConverter::LOCATE_SUCCESS:
+ FprintfFlush(stderr, "LocateResult = LOCATE_SUCCESS\n");
+ // Upload it. Don't bother checking the return value. If this
+ // succeeds, it should disappear from the missing symbol list.
+ // If it fails, something will print an error message indicating
+ // the cause of the failure, and the item will remain on the
+ // missing symbol list.
+ UploadSymbolFile(options.upload_symbols_url, options.api_key,
+ missing_info.debug_file, missing_info.debug_identifier,
+ converted_file, kSymbolUploadTypeBreakpad);
+ if (!options.keep_files)
+ remove(converted_file.c_str());
+
+ // Upload PDB/PE if we have them
+ if (!symbol_file.empty()) {
+ UploadSymbolFile(options.upload_symbols_url, options.api_key,
+ missing_info.debug_file,
+ missing_info.debug_identifier, symbol_file,
+ kSymbolUploadTypePDB);
+ if (!options.keep_files)
+ remove(symbol_file.c_str());
+ }
+ if (!pe_file.empty()) {
+ UploadSymbolFile(options.upload_symbols_url, options.api_key,
+ missing_info.code_file,
+ missing_info.debug_identifier, pe_file,
+ kSymbolUploadTypePE);
+ if (!options.keep_files)
+ remove(pe_file.c_str());
+ }
+
+ // Note: this does leave some directories behind that could be
+ // cleaned up. The directories inside options.local_cache_path for
+ // debug_file/debug_identifier can be removed at this point.
+ break;
+
+ case MSSymbolServerConverter::LOCATE_NOT_FOUND:
+ FprintfFlush(stderr, "LocateResult = LOCATE_NOT_FOUND\n");
+ // The symbol file definitively did not exist. Fall through,
+ // so we can attempt an external query if it's safe to do so.
+ break;
+
+ case MSSymbolServerConverter::LOCATE_RETRY:
+ FprintfFlush(stderr, "LocateResult = LOCATE_RETRY\n");
+ // Fall through in case we should make an external request.
+ // If not, or if an external request fails in the same way,
+ // we'll leave the entry in the symbol file list and
+ // try again on a future pass. Print a message so that there's
+ // a record.
+ break;
+
+ case MSSymbolServerConverter::LOCATE_HTTP_HTTPS_REDIR:
+ FprintfFlush(
+ stderr,
+ "LocateResult = LOCATE_HTTP_HTTPS_REDIR\n"
+ "One of the specified URLs is using HTTP, which causes a redirect "
+ "from the server to HTTPS, which causes the SymSrv lookup to "
+ "fail.\n"
+ "This URL must be replaced with the correct HTTPS URL.\n");
+ break;
+
+ case MSSymbolServerConverter::LOCATE_FAILURE:
+ FprintfFlush(stderr, "LocateResult = LOCATE_FAILURE\n");
+ // LocateAndConvertSymbolFile printed an error message.
+ break;
+
+ default:
+ FprintfFlush(
+ stderr,
+ "FATAL: Unexpected return value '%d' from "
+ "LocateAndConvertSymbolFile()\n",
+ located);
+ assert(0);
+ break;
+ }
+ } else {
+ // No suitable internal symbol servers. This is fine because the converter
+ // is mainly used for downloading and converting of external symbols.
+ }
+
+ // Make a request to an external server if the internal request didn't
+ // succeed, and it's safe to do so.
+ if (located != MSSymbolServerConverter::LOCATE_SUCCESS &&
+ SafeToMakeExternalRequest(missing_info, options.blacklist_regex)) {
+ msss_servers = options.full_external_msss_servers;
+ if (!is_exe) {
+ msss_servers.insert(msss_servers.end(),
+ options.no_exe_external_msss_servers.begin(),
+ options.no_exe_external_msss_servers.end());
+ }
+ if (msss_servers.size() > 0) {
+ FprintfFlush(stderr, "Making external request for %s (%s)\n",
+ missing_info.debug_file.c_str(),
+ missing_info.debug_identifier.c_str());
+ MSSymbolServerConverter external_converter(
+ options.local_cache_path, msss_servers, options.trace_symsrv);
+ located = external_converter.LocateAndConvertSymbolFile(
+ missing_info,
+ /*keep_symbol_file=*/true,
+ /*keep_pe_file=*/true, &converted_file, &symbol_file, &pe_file);
+ } else {
+ FprintfFlush(stderr, "ERROR: No suitable external symbol servers.\n");
+ }
+ }
+
+ // Final handling for this symbol file is based on the result from the
+ // external request (if performed above), or on the result from the
+ // previous internal lookup.
+ switch (located) {
+ case MSSymbolServerConverter::LOCATE_SUCCESS:
+ FprintfFlush(stderr, "LocateResult = LOCATE_SUCCESS\n");
+ // Upload it. Don't bother checking the return value. If this
+ // succeeds, it should disappear from the missing symbol list.
+ // If it fails, something will print an error message indicating
+ // the cause of the failure, and the item will remain on the
+ // missing symbol list.
+ UploadSymbolFile(options.upload_symbols_url, options.api_key,
+ missing_info.debug_file, missing_info.debug_identifier,
+ converted_file, kSymbolUploadTypeBreakpad);
+ if (!options.keep_files)
+ remove(converted_file.c_str());
+
+ // Upload PDB/PE if we have them
+ if (!symbol_file.empty()) {
+ UploadSymbolFile(options.upload_symbols_url, options.api_key,
+ missing_info.debug_file, missing_info.debug_identifier,
+ symbol_file, kSymbolUploadTypePDB);
+ if (!options.keep_files)
+ remove(symbol_file.c_str());
+ }
+ if (!pe_file.empty()) {
+ UploadSymbolFile(options.upload_symbols_url, options.api_key,
+ missing_info.code_file, missing_info.debug_identifier,
+ pe_file, kSymbolUploadTypePE);
+ if (!options.keep_files)
+ remove(pe_file.c_str());
+ }
+
+ // Note: this does leave some directories behind that could be
+ // cleaned up. The directories inside options.local_cache_path for
+ // debug_file/debug_identifier can be removed at this point.
+ break;
+
+ case MSSymbolServerConverter::LOCATE_NOT_FOUND:
+ // The symbol file definitively didn't exist. Inform the server.
+ // If this fails, something will print an error message indicating
+ // the cause of the failure, but there's really nothing more to
+ // do. If this succeeds, the entry should be removed from the
+ // missing symbols list.
+ if (!options.report_fetch_failures) {
+ FprintfFlush(stderr, "SendFetchFailedPing skipped\n");
+ } else if (SendFetchFailedPing(options.fetch_symbol_failure_url,
+ missing_info)) {
+ FprintfFlush(stderr, "SendFetchFailedPing succeeded\n");
+ } else {
+ FprintfFlush(stderr, "SendFetchFailedPing failed\n");
+ }
+ break;
+
+ case MSSymbolServerConverter::LOCATE_RETRY:
+ FprintfFlush(stderr, "LocateResult = LOCATE_RETRY\n");
+ // Nothing to do but leave the entry in the symbol file list and
+ // try again on a future pass. Print a message so that there's
+ // a record.
+ FprintfFlush(stderr, "ConvertMissingSymbolFile: deferring retry "
+ "for %s %s %s\n",
+ missing_info.debug_file.c_str(),
+ missing_info.debug_identifier.c_str(),
+ missing_info.version.c_str());
+ break;
+
+ case MSSymbolServerConverter::LOCATE_HTTP_HTTPS_REDIR:
+ FprintfFlush(
+ stderr,
+ "LocateResult = LOCATE_HTTP_HTTPS_REDIR\n"
+ "One of the specified URLs is using HTTP, which causes a redirect "
+ "from the server to HTTPS, which causes the SymSrv lookup to fail.\n"
+ "This URL must be replaced with the correct HTTPS URL.\n");
+ break;
+
+ case MSSymbolServerConverter::LOCATE_FAILURE:
+ FprintfFlush(stderr, "LocateResult = LOCATE_FAILURE\n");
+ // LocateAndConvertSymbolFile printed an error message.
+
+ // This is due to a bad debug file name, so fetch failed.
+ if (!options.report_fetch_failures) {
+ FprintfFlush(stderr, "SendFetchFailedPing skipped\n");
+ } else if (SendFetchFailedPing(options.fetch_symbol_failure_url,
+ missing_info)) {
+ FprintfFlush(stderr, "SendFetchFailedPing succeeded\n");
+ } else {
+ FprintfFlush(stderr, "SendFetchFailedPing failed\n");
+ }
+ break;
+
+ default:
+ FprintfFlush(
+ stderr,
+ "FATAL: Unexpected return value '%d' from "
+ "LocateAndConvertSymbolFile()\n",
+ located);
+ assert(0);
+ break;
+ }
+}
+
+
+// Reads the contents of file |file_name| and populates |contents|.
+// Returns true on success.
+static bool ReadFile(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) {
+ contents->append(buffer);
+ }
+ fclose(fp);
+ return true;
+}
+
+// ConvertMissingSymbolsList obtains a missing symbol list from
+// |options.missing_symbols_url| or |options.missing_symbols_file| and calls
+// ConvertMissingSymbolFile for each missing symbol file in the list.
+static bool ConvertMissingSymbolsList(const ConverterOptions& options) {
+ // Set param to indicate requesting for encoded response.
+ map<wstring, wstring> parameters;
+ parameters[L"product"] = kConverterProductName;
+ parameters[L"encoded"] = L"true";
+ // Get the missing symbol list.
+ string missing_symbol_list;
+ if (!options.missing_symbols_file.empty()) {
+ if (!ReadFile(options.missing_symbols_file,& missing_symbol_list)) {
+ return false;
+ }
+ } else if (!HTTPDownload::Download(options.missing_symbols_url,& parameters,
+ & missing_symbol_list, NULL)) {
+ return false;
+ }
+
+ // Tokenize the content into a vector.
+ vector<string> missing_symbol_lines;
+ Tokenizer::Tokenize("\n", missing_symbol_list,& missing_symbol_lines);
+
+ FprintfFlush(stderr, "Found %d missing symbol files in list.\n",
+ missing_symbol_lines.size() - 1); // last line is empty.
+ int convert_attempts = 0;
+ for (vector<string>::const_iterator iterator = missing_symbol_lines.begin();
+ iterator != missing_symbol_lines.end();
+ ++iterator) {
+ // Decode symbol line.
+ const string& encoded_line = *iterator;
+ // Skip lines that are blank.
+ if (encoded_line.empty()) {
+ continue;
+ }
+
+ string line;
+ if (!WebSafeBase64Unescape(encoded_line,& line)) {
+ // If decoding fails, assume the line is not encoded.
+ // This is helpful when the program connects to a debug server without
+ // encoding.
+ line = encoded_line;
+ }
+
+ FprintfFlush(stderr, "\nLine: %s\n", line.c_str());
+
+ // Turn each element into a MissingSymbolInfo structure.
+ MissingSymbolInfo missing_info;
+ if (!ParseMissingString(line,& missing_info)) {
+ FprintfFlush(stderr, "ConvertMissingSymbols: ParseMissingString failed "
+ "for %s from %ws\n",
+ line.c_str(), options.missing_symbols_url.c_str());
+ continue;
+ }
+
+ ++convert_attempts;
+ ConvertMissingSymbolFile(missing_info, options);
+ }
+
+ // Say something reassuring, since ConvertMissingSymbolFile was never called
+ // and therefore never reported any progress.
+ if (convert_attempts == 0) {
+ string current_time = CurrentDateAndTime();
+ FprintfFlush(stdout, "converter: %s: nothing to convert\n",
+ current_time.c_str());
+ }
+
+ return true;
+}
+
+// usage prints the usage message. It returns 1 as a convenience, to be used
+// as a return value from main.
+static int usage(const char* program_name) {
+ FprintfFlush(
+ stderr,
+ "usage: %s [options]\n"
+ " -f <full_msss_server> MS servers to ask for all symbols\n"
+ " -n <no_exe_msss_server> same, but prevent asking for EXEs\n"
+ " -l <local_cache_path> Temporary local storage for symbols\n"
+ " -s <upload_url> URL for uploading symbols\n"
+ " -k <api_key> API key to use when uploading symbols\n"
+ " -m <missing_symbols_url> URL to fetch list of missing symbols\n"
+ " -mf <missing_symbols_file> File containing the list of missing\n"
+ " symbols. Fetch failures are not\n"
+ " reported if such file is provided.\n"
+ " -t <fetch_failure_url> URL to report symbol fetch failure\n"
+ " -b <regex> Regex used to blacklist files to\n"
+ " prevent external symbol requests\n"
+ " -tss If set then SymSrv callbacks will be\n"
+ " traced to stderr.\n"
+ " -keep-files If set then don't delete Breakpad/PE/\n"
+ " PDB files after conversion.\n"
+ " Note that any server specified by -f or -n that starts with \\filer\n"
+ " will be treated as internal, and all others as external.\n",
+ program_name);
+
+ return 1;
+}
+
+// "Internal" servers consist only of those whose names start with
+// the literal string "\\filer\".
+static bool IsInternalServer(const string& server_name) {
+ if (server_name.find("\\\\filer\\") == 0) {
+ return true;
+ }
+ return false;
+}
+
+// Adds a server with the given name to the list of internal or external
+// servers, as appropriate.
+static void AddServer(const string& server_name,
+ vector<string>* internal_servers,
+ vector<string>* external_servers) {
+ if (IsInternalServer(server_name)) {
+ internal_servers->push_back(server_name);
+ } else {
+ external_servers->push_back(server_name);
+ }
+}
+
+} // namespace
+
+int main(int argc, char** argv) {
+ string time_string = CurrentDateAndTime();
+ FprintfFlush(stdout, "converter: %s: starting\n", time_string.c_str());
+
+ ConverterOptions options;
+ options.report_fetch_failures = true;
+
+ string blacklist_regex_str;
+ bool have_any_msss_servers = false;
+ for (int argi = 1; argi < argc; argi++) {
+ string option = argv[argi];
+ if (option == "-tss") {
+ printf("Tracing SymSrv callbacks to stderr.\n");
+ options.trace_symsrv = true;
+ continue;
+ } else if (option == "-keep-files") {
+ printf("Keeping Breakpad/PE/PDB files after conversion.\n");
+ options.keep_files = true;
+ continue;
+ }
+
+ string value = argv[++argi];
+ if (option == "-f") {
+ AddServer(value,& options.full_internal_msss_servers,
+ & options.full_external_msss_servers);
+ have_any_msss_servers = true;
+ } else if (option == "-n") {
+ AddServer(value,& options.no_exe_internal_msss_servers,
+ & options.no_exe_external_msss_servers);
+ have_any_msss_servers = true;
+ } else if (option == "-l") {
+ if (!options.local_cache_path.empty()) {
+ return usage(argv[0]);
+ }
+ options.local_cache_path = value;
+ } else if (option == "-s") {
+ if (!WindowsStringUtils::safe_mbstowcs(value,
+ & options.upload_symbols_url)) {
+ FprintfFlush(stderr, "main: safe_mbstowcs failed for %s\n",
+ value.c_str());
+ return 1;
+ }
+ } else if (option == "-k") {
+ if (!WindowsStringUtils::safe_mbstowcs(value, &options.api_key)) {
+ FprintfFlush(stderr, "main: safe_mbstowcs failed for %s\n",
+ value.c_str());
+ return 1;
+ }
+ } else if (option == "-m") {
+ if (!WindowsStringUtils::safe_mbstowcs(value,
+ & options.missing_symbols_url)) {
+ FprintfFlush(stderr, "main: safe_mbstowcs failed for %s\n",
+ value.c_str());
+ return 1;
+ }
+ } else if (option == "-mf") {
+ options.missing_symbols_file = value;
+ printf("Getting the list of missing symbols from a file. Fetch failures"
+ " will not be reported.\n");
+ options.report_fetch_failures = false;
+ } else if (option == "-t") {
+ if (!WindowsStringUtils::safe_mbstowcs(
+ value,
+ & options.fetch_symbol_failure_url)) {
+ FprintfFlush(stderr, "main: safe_mbstowcs failed for %s\n",
+ value.c_str());
+ return 1;
+ }
+ } else if (option == "-b") {
+ blacklist_regex_str = value;
+ } else {
+ return usage(argv[0]);
+ }
+ }
+
+ if (blacklist_regex_str.empty()) {
+ FprintfFlush(stderr, "No blacklist specified.\n");
+ return usage(argv[0]);
+ }
+
+ // Compile the blacklist regular expression for later use.
+ options.blacklist_regex = std::regex(blacklist_regex_str.c_str(),
+ std::regex_constants::icase);
+
+ // Set the defaults. If the user specified any MSSS servers, don't use
+ // any default.
+ if (!have_any_msss_servers) {
+ AddServer(kNoExeMSSSServer,& options.no_exe_internal_msss_servers,
+ & options.no_exe_external_msss_servers);
+ }
+
+ if (options.local_cache_path.empty()) {
+ options.local_cache_path = kLocalCachePath;
+ }
+
+ if (options.upload_symbols_url.empty()) {
+ FprintfFlush(stderr, "No upload symbols URL specified.\n");
+ return usage(argv[0]);
+ }
+ if (options.api_key.empty()) {
+ FprintfFlush(stderr, "No API key specified.\n");
+ return usage(argv[0]);
+ }
+ if (options.missing_symbols_url.empty() &&
+ options.missing_symbols_file.empty()) {
+ FprintfFlush(stderr, "No missing symbols URL or file specified.\n");
+ return usage(argv[0]);
+ }
+ if (options.fetch_symbol_failure_url.empty()) {
+ FprintfFlush(stderr, "No fetch symbol failure URL specified.\n");
+ return usage(argv[0]);
+ }
+
+ FprintfFlush(stdout,
+ "# of Symbol Servers (int/ext): %d/%d full, %d/%d no_exe\n",
+ options.full_internal_msss_servers.size(),
+ options.full_external_msss_servers.size(),
+ options.no_exe_internal_msss_servers.size(),
+ options.no_exe_external_msss_servers.size());
+
+ if (!ConvertMissingSymbolsList(options)) {
+ return 1;
+ }
+
+ time_string = CurrentDateAndTime();
+ FprintfFlush(stdout, "converter: %s: finished\n", time_string.c_str());
+ return 0;
+}
diff --git a/src/tools/windows/converter_exe/converter.gyp b/src/tools/windows/converter_exe/converter.gyp
deleted file mode 100644
index fe443d1b..00000000
--- a/src/tools/windows/converter_exe/converter.gyp
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright 2013 Google Inc. All rights reserved.
-#
-# 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 Inc. 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.
-
-{
- 'includes': [
- '../../../build/common.gypi',
- ],
- 'targets': [
- {
- 'target_name': 'converter_exe',
- 'type': 'executable',
- 'sources': [
- 'converter.cc',
- 'escaping.cc',
- 'escaping.h',
- 'http_client.h',
- 'http_download.cc',
- 'http_download.h',
- 'tokenizer.cc',
- 'tokenizer.h',
- 'winhttp_client.cc',
- 'winhttp_client.h',
- 'wininet_client.cc',
- 'wininet_client.h',
- ],
- 'dependencies': [
- '../../../common/windows/common_windows.gyp:common_windows_lib',
- '../converter/ms_symbol_server_converter.gyp:ms_symbol_server_converter',
- ],
- },
- ],
-}
diff --git a/src/tools/windows/converter_exe/escaping.cc b/src/tools/windows/converter_exe/escaping.cc
index 74a7203a..de074298 100644
--- a/src/tools/windows/converter_exe/escaping.cc
+++ b/src/tools/windows/converter_exe/escaping.cc
@@ -1,757 +1,757 @@
-// Copyright 2019 Google Inc. All rights reserved.
-//
-// 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 Inc. 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.
-
-#include "tools/windows/converter_exe/escaping.h"
-
-#include <assert.h>
-
-#define kApb kAsciiPropertyBits
-
-const unsigned char kAsciiPropertyBits[256] = {
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x00
- 0x40, 0x68, 0x48, 0x48, 0x48, 0x48, 0x40, 0x40,
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x10
- 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
- 0x28, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, // 0x20
- 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
- 0x84, 0x84, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
- 0x10, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x05, // 0x40
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x50
- 0x05, 0x05, 0x05, 0x10, 0x10, 0x10, 0x10, 0x10,
- 0x10, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x05, // 0x60
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x70
- 0x05, 0x05, 0x05, 0x10, 0x10, 0x10, 0x10, 0x40,
-};
-
-// Use !! to suppress the warning C4800 of forcing 'int' to 'bool'.
-static inline bool ascii_isspace(unsigned char c) { return !!(kApb[c] & 0x08); }
-
-///////////////////////////////////
-// scoped_array
-///////////////////////////////////
-// scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate
-// with new [] and the destructor deletes objects with delete [].
-//
-// As with scoped_ptr<C>, a scoped_array<C> either points to an object
-// or is NULL. A scoped_array<C> owns the object that it points to.
-// scoped_array<T> is thread-compatible, and once you index into it,
-// the returned objects have only the threadsafety guarantees of T.
-//
-// Size: sizeof(scoped_array<C>) == sizeof(C*)
-template <class C>
-class scoped_array {
- public:
-
- // The element type
- typedef C element_type;
-
- // 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) { }
-
- // Destructor. If there is a C object, delete it.
- // We don't need to test ptr_ == NULL because C++ does that for us.
- ~scoped_array() {
- enum { type_must_be_complete = sizeof(C) };
- delete[] 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) {
- if (p != array_) {
- enum { type_must_be_complete = sizeof(C) };
- delete[] array_;
- array_ = p;
- }
- }
-
- // Get one element of the current object.
- // 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);
- return array_[i];
- }
-
- // Get a pointer to the zeroth element of the current object.
- // If there is no current object, return NULL.
- C* get() const {
- return array_;
- }
-
- // Comparison operators.
- // These return whether a scoped_array and a raw pointer refer to
- // the same array, not just to two different but equal arrays.
- bool operator==(const C* p) const { return array_ == p; }
- bool operator!=(const C* p) const { return array_ != p; }
-
- // Swap two scoped arrays.
- void swap(scoped_array& p2) {
- C* tmp = array_;
- array_ = p2.array_;
- p2.array_ = tmp;
- }
-
- // Release an array.
- // 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 = array_;
- array_ = NULL;
- return retVal;
- }
-
- private:
- C* array_;
-
- // Forbid comparison of different scoped_array types.
- template <class C2> bool operator==(scoped_array<C2> const& p2) const;
- template <class C2> bool operator!=(scoped_array<C2> const& p2) const;
-
- // Disallow evil constructors
- scoped_array(const scoped_array&);
- void operator=(const scoped_array&);
-};
-
-
-///////////////////////////////////
-// Escape methods
-///////////////////////////////////
-
-namespace strings {
-
-// Return a mutable char* pointing to a string's internal buffer,
-// which may not be null-terminated. Writing through this pointer will
-// modify the string.
-//
-// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the
-// next call to a string method that invalidates iterators.
-//
-// As of 2006-04, there is no standard-blessed way of getting a
-// mutable reference to a string's internal buffer. However, issue 530
-// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530)
-// proposes this as the method. According to Matt Austern, this should
-// already work on all current implementations.
-inline char* string_as_array(string* str) {
- // DO NOT USE const_cast<char*>(str->data())! See the unittest for why.
- return str->empty() ? NULL : &*str->begin();
-}
-
-int CalculateBase64EscapedLen(int input_len, bool do_padding) {
- // these formulae were copied from comments that used to go with the base64
- // encoding functions
- int intermediate_result = 8 * input_len + 5;
- assert(intermediate_result > 0); // make sure we didn't overflow
- int len = intermediate_result / 6;
- if (do_padding) len = ((len + 3) / 4) * 4;
- return len;
-}
-
-// Base64Escape does padding, so this calculation includes padding.
-int CalculateBase64EscapedLen(int input_len) {
- return CalculateBase64EscapedLen(input_len, true);
-}
-
-// ----------------------------------------------------------------------
-// int Base64Unescape() - base64 decoder
-// int Base64Escape() - base64 encoder
-// int WebSafeBase64Unescape() - Google's variation of base64 decoder
-// int WebSafeBase64Escape() - Google's variation of base64 encoder
-//
-// Check out
-// http://www.cis.ohio-state.edu/htbin/rfc/rfc2045.html for formal
-// description, but what we care about is that...
-// Take the encoded stuff in groups of 4 characters and turn each
-// character into a code 0 to 63 thus:
-// A-Z map to 0 to 25
-// a-z map to 26 to 51
-// 0-9 map to 52 to 61
-// +(- for WebSafe) maps to 62
-// /(_ for WebSafe) maps to 63
-// There will be four numbers, all less than 64 which can be represented
-// by a 6 digit binary number (aaaaaa, bbbbbb, cccccc, dddddd respectively).
-// Arrange the 6 digit binary numbers into three bytes as such:
-// aaaaaabb bbbbcccc ccdddddd
-// Equals signs (one or two) are used at the end of the encoded block to
-// indicate that the text was not an integer multiple of three bytes long.
-// ----------------------------------------------------------------------
-
-int Base64UnescapeInternal(const char *src, int szsrc,
- char *dest, int szdest,
- const signed char* unbase64) {
- static const char kPad64 = '=';
-
- int decode = 0;
- int destidx = 0;
- int state = 0;
- unsigned int ch = 0;
- unsigned int temp = 0;
-
- // The GET_INPUT macro gets the next input character, skipping
- // over any whitespace, and stopping when we reach the end of the
- // string or when we read any non-data character. The arguments are
- // an arbitrary identifier (used as a label for goto) and the number
- // of data bytes that must remain in the input to avoid aborting the
- // loop.
-#define GET_INPUT(label, remain) \
- label: \
- --szsrc; \
- ch = *src++; \
- decode = unbase64[ch]; \
- if (decode < 0) { \
- if (ascii_isspace((char)ch) && szsrc >= remain) \
- goto label; \
- state = 4 - remain; \
- break; \
- }
-
- // if dest is null, we're just checking to see if it's legal input
- // rather than producing output. (I suspect this could just be done
- // with a regexp...). We duplicate the loop so this test can be
- // outside it instead of in every iteration.
-
- if (dest) {
- // This loop consumes 4 input bytes and produces 3 output bytes
- // per iteration. We can't know at the start that there is enough
- // data left in the string for a full iteration, so the loop may
- // break out in the middle; if so 'state' will be set to the
- // number of input bytes read.
-
- while (szsrc >= 4) {
- // We'll start by optimistically assuming that the next four
- // bytes of the string (src[0..3]) are four good data bytes
- // (that is, no nulls, whitespace, padding chars, or illegal
- // chars). We need to test src[0..2] for nulls individually
- // before constructing temp to preserve the property that we
- // never read past a null in the string (no matter how long
- // szsrc claims the string is).
-
- if (!src[0] || !src[1] || !src[2] ||
- (temp = ((unbase64[static_cast<int>(src[0])] << 18) |
- (unbase64[static_cast<int>(src[1])] << 12) |
- (unbase64[static_cast<int>(src[2])] << 6) |
- (unbase64[static_cast<int>(src[3])]))) & 0x80000000) {
- // Iff any of those four characters was bad (null, illegal,
- // whitespace, padding), then temp's high bit will be set
- // (because unbase64[] is -1 for all bad characters).
- //
- // We'll back up and resort to the slower decoder, which knows
- // how to handle those cases.
-
- GET_INPUT(first, 4);
- temp = decode;
- GET_INPUT(second, 3);
- temp = (temp << 6) | decode;
- GET_INPUT(third, 2);
- temp = (temp << 6) | decode;
- GET_INPUT(fourth, 1);
- temp = (temp << 6) | decode;
- } else {
- // We really did have four good data bytes, so advance four
- // characters in the string.
-
- szsrc -= 4;
- src += 4;
- decode = -1;
- ch = '\0';
- }
-
- // temp has 24 bits of input, so write that out as three bytes.
-
- if (destidx+3 > szdest) return -1;
- dest[destidx+2] = (char)temp;
- temp >>= 8;
- dest[destidx+1] = (char)temp;
- temp >>= 8;
- dest[destidx] = (char)temp;
- destidx += 3;
- }
- } else {
- while (szsrc >= 4) {
- if (!src[0] || !src[1] || !src[2] ||
- (temp = ((unbase64[static_cast<int>(src[0])] << 18) |
- (unbase64[static_cast<int>(src[1])] << 12) |
- (unbase64[static_cast<int>(src[2])] << 6) |
- (unbase64[static_cast<int>(src[3])]))) & 0x80000000) {
- GET_INPUT(first_no_dest, 4);
- GET_INPUT(second_no_dest, 3);
- GET_INPUT(third_no_dest, 2);
- GET_INPUT(fourth_no_dest, 1);
- } else {
- szsrc -= 4;
- src += 4;
- decode = -1;
- ch = '\0';
- }
- destidx += 3;
- }
- }
-
-#undef GET_INPUT
-
- // if the loop terminated because we read a bad character, return
- // now.
- if (decode < 0 && ch != '\0' && ch != kPad64 && !ascii_isspace((char)ch))
- return -1;
-
- if (ch == kPad64) {
- // if we stopped by hitting an '=', un-read that character -- we'll
- // look at it again when we count to check for the proper number of
- // equals signs at the end.
- ++szsrc;
- --src;
- } else {
- // This loop consumes 1 input byte per iteration. It's used to
- // clean up the 0-3 input bytes remaining when the first, faster
- // loop finishes. 'temp' contains the data from 'state' input
- // characters read by the first loop.
- while (szsrc > 0) {
- --szsrc;
- ch = *src++;
- decode = unbase64[ch];
- if (decode < 0) {
- if (ascii_isspace((char)ch)) {
- continue;
- } else if (ch == '\0') {
- break;
- } else if (ch == kPad64) {
- // back up one character; we'll read it again when we check
- // for the correct number of equals signs at the end.
- ++szsrc;
- --src;
- break;
- } else {
- return -1;
- }
- }
-
- // Each input character gives us six bits of output.
- temp = (temp << 6) | decode;
- ++state;
- if (state == 4) {
- // If we've accumulated 24 bits of output, write that out as
- // three bytes.
- if (dest) {
- if (destidx+3 > szdest) return -1;
- dest[destidx+2] = (char)temp;
- temp >>= 8;
- dest[destidx+1] = (char)temp;
- temp >>= 8;
- dest[destidx] = (char)temp;
- }
- destidx += 3;
- state = 0;
- temp = 0;
- }
- }
- }
-
- // Process the leftover data contained in 'temp' at the end of the input.
- int expected_equals = 0;
- switch (state) {
- case 0:
- // Nothing left over; output is a multiple of 3 bytes.
- break;
-
- case 1:
- // Bad input; we have 6 bits left over.
- return -1;
-
- case 2:
- // Produce one more output byte from the 12 input bits we have left.
- if (dest) {
- if (destidx+1 > szdest) return -1;
- temp >>= 4;
- dest[destidx] = (char)temp;
- }
- ++destidx;
- expected_equals = 2;
- break;
-
- case 3:
- // Produce two more output bytes from the 18 input bits we have left.
- if (dest) {
- if (destidx+2 > szdest) return -1;
- temp >>= 2;
- dest[destidx+1] = (char)temp;
- temp >>= 8;
- dest[destidx] = (char)temp;
- }
- destidx += 2;
- expected_equals = 1;
- break;
-
- default:
- // state should have no other values at this point.
- fprintf(stdout, "This can't happen; base64 decoder state = %d", state);
- }
-
- // The remainder of the string should be all whitespace, mixed with
- // exactly 0 equals signs, or exactly 'expected_equals' equals
- // signs. (Always accepting 0 equals signs is a google extension
- // not covered in the RFC.)
-
- int equals = 0;
- while (szsrc > 0 && *src) {
- if (*src == kPad64)
- ++equals;
- else if (!ascii_isspace(*src))
- return -1;
- --szsrc;
- ++src;
- }
-
- return (equals == 0 || equals == expected_equals) ? destidx : -1;
-}
-
-int Base64Unescape(const char *src, int szsrc, char *dest, int szdest) {
- static const signed char UnBase64[] = {
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 62/*+*/, -1, -1, -1, 63/*/ */,
- 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
- 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1,
- -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/,
- 7/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
- 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
- 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, -1,
- -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
- 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
- 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
- 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1
- };
- // The above array was generated by the following code
- // #include <sys/time.h>
- // #include <stdlib.h>
- // #include <string.h>
- // main()
- // {
- // static const char Base64[] =
- // "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- // char *pos;
- // int idx, i, j;
- // printf(" ");
- // for (i = 0; i < 255; i += 8) {
- // for (j = i; j < i + 8; j++) {
- // pos = strchr(Base64, j);
- // if ((pos == NULL) || (j == 0))
- // idx = -1;
- // else
- // idx = pos - Base64;
- // if (idx == -1)
- // printf(" %2d, ", idx);
- // else
- // printf(" %2d/*%c*/,", idx, j);
- // }
- // printf("\n ");
- // }
- // }
-
- return Base64UnescapeInternal(src, szsrc, dest, szdest, UnBase64);
-}
-
-bool Base64Unescape(const char *src, int slen, string* dest) {
- // Determine the size of the output string. Base64 encodes every 3 bytes into
- // 4 characters. any leftover chars are added directly for good measure.
- // This is documented in the base64 RFC: http://www.ietf.org/rfc/rfc3548.txt
- const int dest_len = 3 * (slen / 4) + (slen % 4);
-
- dest->resize(dest_len);
-
- // We are getting the destination buffer by getting the beginning of the
- // string and converting it into a char *.
- const int len = Base64Unescape(src, slen,
- string_as_array(dest), dest->size());
- if (len < 0) {
- return false;
- }
-
- // could be shorter if there was padding
- assert(len <= dest_len);
- dest->resize(len);
-
- return true;
-}
-
-// Base64Escape
-//
-// NOTE: We have to use an unsigned type for src because code built
-// in the the /google tree treats characters as signed unless
-// otherwised specified.
-//
-// TODO(who?): Move this function to use the char* type for "src"
-int Base64EscapeInternal(const unsigned char *src, int szsrc,
- char *dest, int szdest, const char *base64,
- bool do_padding) {
- static const char kPad64 = '=';
-
- if (szsrc <= 0) return 0;
-
- char *cur_dest = dest;
- const unsigned char *cur_src = src;
-
- // Three bytes of data encodes to four characters of cyphertext.
- // So we can pump through three-byte chunks atomically.
- while (szsrc > 2) { /* keep going until we have less than 24 bits */
- if ((szdest -= 4) < 0) return 0;
- cur_dest[0] = base64[cur_src[0] >> 2];
- cur_dest[1] = base64[((cur_src[0] & 0x03) << 4) + (cur_src[1] >> 4)];
- cur_dest[2] = base64[((cur_src[1] & 0x0f) << 2) + (cur_src[2] >> 6)];
- cur_dest[3] = base64[cur_src[2] & 0x3f];
-
- cur_dest += 4;
- cur_src += 3;
- szsrc -= 3;
- }
-
- /* now deal with the tail (<=2 bytes) */
- switch (szsrc) {
- case 0:
- // Nothing left; nothing more to do.
- break;
- case 1:
- // One byte left: this encodes to two characters, and (optionally)
- // two pad characters to round out the four-character cypherblock.
- if ((szdest -= 2) < 0) return 0;
- cur_dest[0] = base64[cur_src[0] >> 2];
- cur_dest[1] = base64[(cur_src[0] & 0x03) << 4];
- cur_dest += 2;
- if (do_padding) {
- if ((szdest -= 2) < 0) return 0;
- cur_dest[0] = kPad64;
- cur_dest[1] = kPad64;
- cur_dest += 2;
- }
- break;
- case 2:
- // Two bytes left: this encodes to three characters, and (optionally)
- // one pad character to round out the four-character cypherblock.
- if ((szdest -= 3) < 0) return 0;
- cur_dest[0] = base64[cur_src[0] >> 2];
- cur_dest[1] = base64[((cur_src[0] & 0x03) << 4) + (cur_src[1] >> 4)];
- cur_dest[2] = base64[(cur_src[1] & 0x0f) << 2];
- cur_dest += 3;
- if (do_padding) {
- if ((szdest -= 1) < 0) return 0;
- cur_dest[0] = kPad64;
- cur_dest += 1;
- }
- break;
- default:
- // Should not be reached: blocks of 3 bytes are handled
- // in the while loop before this switch statement.
- fprintf(stderr, "Logic problem? szsrc = %d", szsrc);
- assert(false);
- break;
- }
- return (cur_dest - dest);
-}
-
-static const char kBase64Chars[] =
-"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-static const char kWebSafeBase64Chars[] =
-"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
-
-int Base64Escape(const unsigned char *src, int szsrc, char *dest, int szdest) {
- return Base64EscapeInternal(src, szsrc, dest, szdest, kBase64Chars, true);
-}
-
-void Base64Escape(const unsigned char *src, int szsrc,
- string* dest, bool do_padding) {
- const int max_escaped_size =
- CalculateBase64EscapedLen(szsrc, do_padding);
- dest->clear();
- dest->resize(max_escaped_size + 1, '\0');
- const int escaped_len = Base64EscapeInternal(src, szsrc,
- &*dest->begin(), dest->size(),
- kBase64Chars,
- do_padding);
- assert(max_escaped_size <= escaped_len);
- dest->resize(escaped_len);
-}
-
-void Base64Escape(const string& src, string* dest) {
- Base64Escape(reinterpret_cast<const unsigned char*>(src.c_str()),
- src.size(), dest, true);
-}
-
-////////////////////////////////////////////////////
-// WebSafe methods
-////////////////////////////////////////////////////
-
-int WebSafeBase64Unescape(const char *src, int szsrc, char *dest, int szdest) {
- static const signed char UnBase64[] = {
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 62/*-*/, -1, -1,
- 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
- 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1,
- -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/,
- 7/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
- 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
- 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, 63/*_*/,
- -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
- 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
- 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
- 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1
- };
- // The above array was generated by the following code
- // #include <sys/time.h>
- // #include <stdlib.h>
- // #include <string.h>
- // main()
- // {
- // static const char Base64[] =
- // "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
- // char *pos;
- // int idx, i, j;
- // printf(" ");
- // for (i = 0; i < 255; i += 8) {
- // for (j = i; j < i + 8; j++) {
- // pos = strchr(Base64, j);
- // if ((pos == NULL) || (j == 0))
- // idx = -1;
- // else
- // idx = pos - Base64;
- // if (idx == -1)
- // printf(" %2d, ", idx);
- // else
- // printf(" %2d/*%c*/,", idx, j);
- // }
- // printf("\n ");
- // }
- // }
-
- return Base64UnescapeInternal(src, szsrc, dest, szdest, UnBase64);
-}
-
-bool WebSafeBase64Unescape(const char *src, int slen, string* dest) {
- int dest_len = 3 * (slen / 4) + (slen % 4);
- dest->clear();
- dest->resize(dest_len);
- int len = WebSafeBase64Unescape(src, slen, &*dest->begin(), dest->size());
- if (len < 0) {
- dest->clear();
- return false;
- }
- // could be shorter if there was padding
- assert(len <= dest_len);
- dest->resize(len);
- return true;
-}
-
-bool WebSafeBase64Unescape(const string& src, string* dest) {
- return WebSafeBase64Unescape(src.data(), src.size(), dest);
-}
-
-int WebSafeBase64Escape(const unsigned char *src, int szsrc, char *dest,
- int szdest, bool do_padding) {
- return Base64EscapeInternal(src, szsrc, dest, szdest,
- kWebSafeBase64Chars, do_padding);
-}
-
-void WebSafeBase64Escape(const unsigned char *src, int szsrc,
- string *dest, bool do_padding) {
- const int max_escaped_size =
- CalculateBase64EscapedLen(szsrc, do_padding);
- dest->clear();
- dest->resize(max_escaped_size + 1, '\0');
- const int escaped_len = Base64EscapeInternal(src, szsrc,
- &*dest->begin(), dest->size(),
- kWebSafeBase64Chars,
- do_padding);
- assert(max_escaped_size <= escaped_len);
- dest->resize(escaped_len);
-}
-
-void WebSafeBase64EscapeInternal(const string& src,
- string* dest,
- bool do_padding) {
- int encoded_len = CalculateBase64EscapedLen(src.size());
- scoped_array<char> buf(new char[encoded_len]);
- int len = WebSafeBase64Escape(reinterpret_cast<const unsigned char*>(src.c_str()),
- src.size(), buf.get(),
- encoded_len, do_padding);
- dest->assign(buf.get(), len);
-}
-
-void WebSafeBase64Escape(const string& src, string* dest) {
- WebSafeBase64EscapeInternal(src, dest, false);
-}
-
-void WebSafeBase64EscapeWithPadding(const string& src, string* dest) {
- WebSafeBase64EscapeInternal(src, dest, true);
-}
-
-} // namespace strings
+// Copyright 2019 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.
+
+#include "tools/windows/converter_exe/escaping.h"
+
+#include <assert.h>
+
+#define kApb kAsciiPropertyBits
+
+const unsigned char kAsciiPropertyBits[256] = {
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x00
+ 0x40, 0x68, 0x48, 0x48, 0x48, 0x48, 0x40, 0x40,
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x10
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x28, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, // 0x20
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x84, 0x84, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x05, // 0x40
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x50
+ 0x05, 0x05, 0x05, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x05, // 0x60
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, // 0x70
+ 0x05, 0x05, 0x05, 0x10, 0x10, 0x10, 0x10, 0x40,
+};
+
+// Use !! to suppress the warning C4800 of forcing 'int' to 'bool'.
+static inline bool ascii_isspace(unsigned char c) { return !!(kApb[c] & 0x08); }
+
+///////////////////////////////////
+// scoped_array
+///////////////////////////////////
+// scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate
+// with new [] and the destructor deletes objects with delete [].
+//
+// As with scoped_ptr<C>, a scoped_array<C> either points to an object
+// or is NULL. A scoped_array<C> owns the object that it points to.
+// scoped_array<T> is thread-compatible, and once you index into it,
+// the returned objects have only the threadsafety guarantees of T.
+//
+// Size: sizeof(scoped_array<C>) == sizeof(C*)
+template <class C>
+class scoped_array {
+ public:
+
+ // The element type
+ typedef C element_type;
+
+ // 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) { }
+
+ // Destructor. If there is a C object, delete it.
+ // We don't need to test ptr_ == NULL because C++ does that for us.
+ ~scoped_array() {
+ enum { type_must_be_complete = sizeof(C) };
+ delete[] 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) {
+ if (p != array_) {
+ enum { type_must_be_complete = sizeof(C) };
+ delete[] array_;
+ array_ = p;
+ }
+ }
+
+ // Get one element of the current object.
+ // 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);
+ return array_[i];
+ }
+
+ // Get a pointer to the zeroth element of the current object.
+ // If there is no current object, return NULL.
+ C* get() const {
+ return array_;
+ }
+
+ // Comparison operators.
+ // These return whether a scoped_array and a raw pointer refer to
+ // the same array, not just to two different but equal arrays.
+ bool operator==(const C* p) const { return array_ == p; }
+ bool operator!=(const C* p) const { return array_ != p; }
+
+ // Swap two scoped arrays.
+ void swap(scoped_array& p2) {
+ C* tmp = array_;
+ array_ = p2.array_;
+ p2.array_ = tmp;
+ }
+
+ // Release an array.
+ // 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 = array_;
+ array_ = NULL;
+ return retVal;
+ }
+
+ private:
+ C* array_;
+
+ // Forbid comparison of different scoped_array types.
+ template <class C2> bool operator==(scoped_array<C2> const& p2) const;
+ template <class C2> bool operator!=(scoped_array<C2> const& p2) const;
+
+ // Disallow evil constructors
+ scoped_array(const scoped_array&);
+ void operator=(const scoped_array&);
+};
+
+
+///////////////////////////////////
+// Escape methods
+///////////////////////////////////
+
+namespace strings {
+
+// Return a mutable char* pointing to a string's internal buffer,
+// which may not be null-terminated. Writing through this pointer will
+// modify the string.
+//
+// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the
+// next call to a string method that invalidates iterators.
+//
+// As of 2006-04, there is no standard-blessed way of getting a
+// mutable reference to a string's internal buffer. However, issue 530
+// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-active.html#530)
+// proposes this as the method. According to Matt Austern, this should
+// already work on all current implementations.
+inline char* string_as_array(string* str) {
+ // DO NOT USE const_cast<char*>(str->data())! See the unittest for why.
+ return str->empty() ? NULL : &*str->begin();
+}
+
+int CalculateBase64EscapedLen(int input_len, bool do_padding) {
+ // these formulae were copied from comments that used to go with the base64
+ // encoding functions
+ int intermediate_result = 8 * input_len + 5;
+ assert(intermediate_result > 0); // make sure we didn't overflow
+ int len = intermediate_result / 6;
+ if (do_padding) len = ((len + 3) / 4) * 4;
+ return len;
+}
+
+// Base64Escape does padding, so this calculation includes padding.
+int CalculateBase64EscapedLen(int input_len) {
+ return CalculateBase64EscapedLen(input_len, true);
+}
+
+// ----------------------------------------------------------------------
+// int Base64Unescape() - base64 decoder
+// int Base64Escape() - base64 encoder
+// int WebSafeBase64Unescape() - Google's variation of base64 decoder
+// int WebSafeBase64Escape() - Google's variation of base64 encoder
+//
+// Check out
+// http://www.cis.ohio-state.edu/htbin/rfc/rfc2045.html for formal
+// description, but what we care about is that...
+// Take the encoded stuff in groups of 4 characters and turn each
+// character into a code 0 to 63 thus:
+// A-Z map to 0 to 25
+// a-z map to 26 to 51
+// 0-9 map to 52 to 61
+// +(- for WebSafe) maps to 62
+// /(_ for WebSafe) maps to 63
+// There will be four numbers, all less than 64 which can be represented
+// by a 6 digit binary number (aaaaaa, bbbbbb, cccccc, dddddd respectively).
+// Arrange the 6 digit binary numbers into three bytes as such:
+// aaaaaabb bbbbcccc ccdddddd
+// Equals signs (one or two) are used at the end of the encoded block to
+// indicate that the text was not an integer multiple of three bytes long.
+// ----------------------------------------------------------------------
+
+int Base64UnescapeInternal(const char *src, int szsrc,
+ char *dest, int szdest,
+ const signed char* unbase64) {
+ static const char kPad64 = '=';
+
+ int decode = 0;
+ int destidx = 0;
+ int state = 0;
+ unsigned int ch = 0;
+ unsigned int temp = 0;
+
+ // The GET_INPUT macro gets the next input character, skipping
+ // over any whitespace, and stopping when we reach the end of the
+ // string or when we read any non-data character. The arguments are
+ // an arbitrary identifier (used as a label for goto) and the number
+ // of data bytes that must remain in the input to avoid aborting the
+ // loop.
+#define GET_INPUT(label, remain) \
+ label: \
+ --szsrc; \
+ ch = *src++; \
+ decode = unbase64[ch]; \
+ if (decode < 0) { \
+ if (ascii_isspace((char)ch) && szsrc >= remain) \
+ goto label; \
+ state = 4 - remain; \
+ break; \
+ }
+
+ // if dest is null, we're just checking to see if it's legal input
+ // rather than producing output. (I suspect this could just be done
+ // with a regexp...). We duplicate the loop so this test can be
+ // outside it instead of in every iteration.
+
+ if (dest) {
+ // This loop consumes 4 input bytes and produces 3 output bytes
+ // per iteration. We can't know at the start that there is enough
+ // data left in the string for a full iteration, so the loop may
+ // break out in the middle; if so 'state' will be set to the
+ // number of input bytes read.
+
+ while (szsrc >= 4) {
+ // We'll start by optimistically assuming that the next four
+ // bytes of the string (src[0..3]) are four good data bytes
+ // (that is, no nulls, whitespace, padding chars, or illegal
+ // chars). We need to test src[0..2] for nulls individually
+ // before constructing temp to preserve the property that we
+ // never read past a null in the string (no matter how long
+ // szsrc claims the string is).
+
+ if (!src[0] || !src[1] || !src[2] ||
+ (temp = ((unbase64[static_cast<int>(src[0])] << 18) |
+ (unbase64[static_cast<int>(src[1])] << 12) |
+ (unbase64[static_cast<int>(src[2])] << 6) |
+ (unbase64[static_cast<int>(src[3])]))) & 0x80000000) {
+ // Iff any of those four characters was bad (null, illegal,
+ // whitespace, padding), then temp's high bit will be set
+ // (because unbase64[] is -1 for all bad characters).
+ //
+ // We'll back up and resort to the slower decoder, which knows
+ // how to handle those cases.
+
+ GET_INPUT(first, 4);
+ temp = decode;
+ GET_INPUT(second, 3);
+ temp = (temp << 6) | decode;
+ GET_INPUT(third, 2);
+ temp = (temp << 6) | decode;
+ GET_INPUT(fourth, 1);
+ temp = (temp << 6) | decode;
+ } else {
+ // We really did have four good data bytes, so advance four
+ // characters in the string.
+
+ szsrc -= 4;
+ src += 4;
+ decode = -1;
+ ch = '\0';
+ }
+
+ // temp has 24 bits of input, so write that out as three bytes.
+
+ if (destidx+3 > szdest) return -1;
+ dest[destidx+2] = (char)temp;
+ temp >>= 8;
+ dest[destidx+1] = (char)temp;
+ temp >>= 8;
+ dest[destidx] = (char)temp;
+ destidx += 3;
+ }
+ } else {
+ while (szsrc >= 4) {
+ if (!src[0] || !src[1] || !src[2] ||
+ (temp = ((unbase64[static_cast<int>(src[0])] << 18) |
+ (unbase64[static_cast<int>(src[1])] << 12) |
+ (unbase64[static_cast<int>(src[2])] << 6) |
+ (unbase64[static_cast<int>(src[3])]))) & 0x80000000) {
+ GET_INPUT(first_no_dest, 4);
+ GET_INPUT(second_no_dest, 3);
+ GET_INPUT(third_no_dest, 2);
+ GET_INPUT(fourth_no_dest, 1);
+ } else {
+ szsrc -= 4;
+ src += 4;
+ decode = -1;
+ ch = '\0';
+ }
+ destidx += 3;
+ }
+ }
+
+#undef GET_INPUT
+
+ // if the loop terminated because we read a bad character, return
+ // now.
+ if (decode < 0 && ch != '\0' && ch != kPad64 && !ascii_isspace((char)ch))
+ return -1;
+
+ if (ch == kPad64) {
+ // if we stopped by hitting an '=', un-read that character -- we'll
+ // look at it again when we count to check for the proper number of
+ // equals signs at the end.
+ ++szsrc;
+ --src;
+ } else {
+ // This loop consumes 1 input byte per iteration. It's used to
+ // clean up the 0-3 input bytes remaining when the first, faster
+ // loop finishes. 'temp' contains the data from 'state' input
+ // characters read by the first loop.
+ while (szsrc > 0) {
+ --szsrc;
+ ch = *src++;
+ decode = unbase64[ch];
+ if (decode < 0) {
+ if (ascii_isspace((char)ch)) {
+ continue;
+ } else if (ch == '\0') {
+ break;
+ } else if (ch == kPad64) {
+ // back up one character; we'll read it again when we check
+ // for the correct number of equals signs at the end.
+ ++szsrc;
+ --src;
+ break;
+ } else {
+ return -1;
+ }
+ }
+
+ // Each input character gives us six bits of output.
+ temp = (temp << 6) | decode;
+ ++state;
+ if (state == 4) {
+ // If we've accumulated 24 bits of output, write that out as
+ // three bytes.
+ if (dest) {
+ if (destidx+3 > szdest) return -1;
+ dest[destidx+2] = (char)temp;
+ temp >>= 8;
+ dest[destidx+1] = (char)temp;
+ temp >>= 8;
+ dest[destidx] = (char)temp;
+ }
+ destidx += 3;
+ state = 0;
+ temp = 0;
+ }
+ }
+ }
+
+ // Process the leftover data contained in 'temp' at the end of the input.
+ int expected_equals = 0;
+ switch (state) {
+ case 0:
+ // Nothing left over; output is a multiple of 3 bytes.
+ break;
+
+ case 1:
+ // Bad input; we have 6 bits left over.
+ return -1;
+
+ case 2:
+ // Produce one more output byte from the 12 input bits we have left.
+ if (dest) {
+ if (destidx+1 > szdest) return -1;
+ temp >>= 4;
+ dest[destidx] = (char)temp;
+ }
+ ++destidx;
+ expected_equals = 2;
+ break;
+
+ case 3:
+ // Produce two more output bytes from the 18 input bits we have left.
+ if (dest) {
+ if (destidx+2 > szdest) return -1;
+ temp >>= 2;
+ dest[destidx+1] = (char)temp;
+ temp >>= 8;
+ dest[destidx] = (char)temp;
+ }
+ destidx += 2;
+ expected_equals = 1;
+ break;
+
+ default:
+ // state should have no other values at this point.
+ fprintf(stdout, "This can't happen; base64 decoder state = %d", state);
+ }
+
+ // The remainder of the string should be all whitespace, mixed with
+ // exactly 0 equals signs, or exactly 'expected_equals' equals
+ // signs. (Always accepting 0 equals signs is a google extension
+ // not covered in the RFC.)
+
+ int equals = 0;
+ while (szsrc > 0 && *src) {
+ if (*src == kPad64)
+ ++equals;
+ else if (!ascii_isspace(*src))
+ return -1;
+ --szsrc;
+ ++src;
+ }
+
+ return (equals == 0 || equals == expected_equals) ? destidx : -1;
+}
+
+int Base64Unescape(const char *src, int szsrc, char *dest, int szdest) {
+ static const signed char UnBase64[] = {
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 62/*+*/, -1, -1, -1, 63/*/ */,
+ 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
+ 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1,
+ -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/,
+ 7/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
+ 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
+ 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, -1,
+ -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
+ 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
+ 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
+ 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1
+ };
+ // The above array was generated by the following code
+ // #include <sys/time.h>
+ // #include <stdlib.h>
+ // #include <string.h>
+ // main()
+ // {
+ // static const char Base64[] =
+ // "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ // char *pos;
+ // int idx, i, j;
+ // printf(" ");
+ // for (i = 0; i < 255; i += 8) {
+ // for (j = i; j < i + 8; j++) {
+ // pos = strchr(Base64, j);
+ // if ((pos == NULL) || (j == 0))
+ // idx = -1;
+ // else
+ // idx = pos - Base64;
+ // if (idx == -1)
+ // printf(" %2d, ", idx);
+ // else
+ // printf(" %2d/*%c*/,", idx, j);
+ // }
+ // printf("\n ");
+ // }
+ // }
+
+ return Base64UnescapeInternal(src, szsrc, dest, szdest, UnBase64);
+}
+
+bool Base64Unescape(const char *src, int slen, string* dest) {
+ // Determine the size of the output string. Base64 encodes every 3 bytes into
+ // 4 characters. any leftover chars are added directly for good measure.
+ // This is documented in the base64 RFC: http://www.ietf.org/rfc/rfc3548.txt
+ const int dest_len = 3 * (slen / 4) + (slen % 4);
+
+ dest->resize(dest_len);
+
+ // We are getting the destination buffer by getting the beginning of the
+ // string and converting it into a char *.
+ const int len = Base64Unescape(src, slen,
+ string_as_array(dest), dest->size());
+ if (len < 0) {
+ return false;
+ }
+
+ // could be shorter if there was padding
+ assert(len <= dest_len);
+ dest->resize(len);
+
+ return true;
+}
+
+// Base64Escape
+//
+// NOTE: We have to use an unsigned type for src because code built
+// in the the /google tree treats characters as signed unless
+// otherwised specified.
+//
+// TODO(who?): Move this function to use the char* type for "src"
+int Base64EscapeInternal(const unsigned char *src, int szsrc,
+ char *dest, int szdest, const char *base64,
+ bool do_padding) {
+ static const char kPad64 = '=';
+
+ if (szsrc <= 0) return 0;
+
+ char *cur_dest = dest;
+ const unsigned char *cur_src = src;
+
+ // Three bytes of data encodes to four characters of cyphertext.
+ // So we can pump through three-byte chunks atomically.
+ while (szsrc > 2) { /* keep going until we have less than 24 bits */
+ if ((szdest -= 4) < 0) return 0;
+ cur_dest[0] = base64[cur_src[0] >> 2];
+ cur_dest[1] = base64[((cur_src[0] & 0x03) << 4) + (cur_src[1] >> 4)];
+ cur_dest[2] = base64[((cur_src[1] & 0x0f) << 2) + (cur_src[2] >> 6)];
+ cur_dest[3] = base64[cur_src[2] & 0x3f];
+
+ cur_dest += 4;
+ cur_src += 3;
+ szsrc -= 3;
+ }
+
+ /* now deal with the tail (<=2 bytes) */
+ switch (szsrc) {
+ case 0:
+ // Nothing left; nothing more to do.
+ break;
+ case 1:
+ // One byte left: this encodes to two characters, and (optionally)
+ // two pad characters to round out the four-character cypherblock.
+ if ((szdest -= 2) < 0) return 0;
+ cur_dest[0] = base64[cur_src[0] >> 2];
+ cur_dest[1] = base64[(cur_src[0] & 0x03) << 4];
+ cur_dest += 2;
+ if (do_padding) {
+ if ((szdest -= 2) < 0) return 0;
+ cur_dest[0] = kPad64;
+ cur_dest[1] = kPad64;
+ cur_dest += 2;
+ }
+ break;
+ case 2:
+ // Two bytes left: this encodes to three characters, and (optionally)
+ // one pad character to round out the four-character cypherblock.
+ if ((szdest -= 3) < 0) return 0;
+ cur_dest[0] = base64[cur_src[0] >> 2];
+ cur_dest[1] = base64[((cur_src[0] & 0x03) << 4) + (cur_src[1] >> 4)];
+ cur_dest[2] = base64[(cur_src[1] & 0x0f) << 2];
+ cur_dest += 3;
+ if (do_padding) {
+ if ((szdest -= 1) < 0) return 0;
+ cur_dest[0] = kPad64;
+ cur_dest += 1;
+ }
+ break;
+ default:
+ // Should not be reached: blocks of 3 bytes are handled
+ // in the while loop before this switch statement.
+ fprintf(stderr, "Logic problem? szsrc = %d", szsrc);
+ assert(false);
+ break;
+ }
+ return (cur_dest - dest);
+}
+
+static const char kBase64Chars[] =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static const char kWebSafeBase64Chars[] =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+
+int Base64Escape(const unsigned char *src, int szsrc, char *dest, int szdest) {
+ return Base64EscapeInternal(src, szsrc, dest, szdest, kBase64Chars, true);
+}
+
+void Base64Escape(const unsigned char *src, int szsrc,
+ string* dest, bool do_padding) {
+ const int max_escaped_size =
+ CalculateBase64EscapedLen(szsrc, do_padding);
+ dest->clear();
+ dest->resize(max_escaped_size + 1, '\0');
+ const int escaped_len = Base64EscapeInternal(src, szsrc,
+ &*dest->begin(), dest->size(),
+ kBase64Chars,
+ do_padding);
+ assert(max_escaped_size <= escaped_len);
+ dest->resize(escaped_len);
+}
+
+void Base64Escape(const string& src, string* dest) {
+ Base64Escape(reinterpret_cast<const unsigned char*>(src.c_str()),
+ src.size(), dest, true);
+}
+
+////////////////////////////////////////////////////
+// WebSafe methods
+////////////////////////////////////////////////////
+
+int WebSafeBase64Unescape(const char *src, int szsrc, char *dest, int szdest) {
+ static const signed char UnBase64[] = {
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 62/*-*/, -1, -1,
+ 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/,
+ 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1,
+ -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/,
+ 7/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/,
+ 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/,
+ 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, 63/*_*/,
+ -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/,
+ 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/,
+ 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/,
+ 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1
+ };
+ // The above array was generated by the following code
+ // #include <sys/time.h>
+ // #include <stdlib.h>
+ // #include <string.h>
+ // main()
+ // {
+ // static const char Base64[] =
+ // "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+ // char *pos;
+ // int idx, i, j;
+ // printf(" ");
+ // for (i = 0; i < 255; i += 8) {
+ // for (j = i; j < i + 8; j++) {
+ // pos = strchr(Base64, j);
+ // if ((pos == NULL) || (j == 0))
+ // idx = -1;
+ // else
+ // idx = pos - Base64;
+ // if (idx == -1)
+ // printf(" %2d, ", idx);
+ // else
+ // printf(" %2d/*%c*/,", idx, j);
+ // }
+ // printf("\n ");
+ // }
+ // }
+
+ return Base64UnescapeInternal(src, szsrc, dest, szdest, UnBase64);
+}
+
+bool WebSafeBase64Unescape(const char *src, int slen, string* dest) {
+ int dest_len = 3 * (slen / 4) + (slen % 4);
+ dest->clear();
+ dest->resize(dest_len);
+ int len = WebSafeBase64Unescape(src, slen, &*dest->begin(), dest->size());
+ if (len < 0) {
+ dest->clear();
+ return false;
+ }
+ // could be shorter if there was padding
+ assert(len <= dest_len);
+ dest->resize(len);
+ return true;
+}
+
+bool WebSafeBase64Unescape(const string& src, string* dest) {
+ return WebSafeBase64Unescape(src.data(), src.size(), dest);
+}
+
+int WebSafeBase64Escape(const unsigned char *src, int szsrc, char *dest,
+ int szdest, bool do_padding) {
+ return Base64EscapeInternal(src, szsrc, dest, szdest,
+ kWebSafeBase64Chars, do_padding);
+}
+
+void WebSafeBase64Escape(const unsigned char *src, int szsrc,
+ string *dest, bool do_padding) {
+ const int max_escaped_size =
+ CalculateBase64EscapedLen(szsrc, do_padding);
+ dest->clear();
+ dest->resize(max_escaped_size + 1, '\0');
+ const int escaped_len = Base64EscapeInternal(src, szsrc,
+ &*dest->begin(), dest->size(),
+ kWebSafeBase64Chars,
+ do_padding);
+ assert(max_escaped_size <= escaped_len);
+ dest->resize(escaped_len);
+}
+
+void WebSafeBase64EscapeInternal(const string& src,
+ string* dest,
+ bool do_padding) {
+ int encoded_len = CalculateBase64EscapedLen(src.size());
+ scoped_array<char> buf(new char[encoded_len]);
+ int len = WebSafeBase64Escape(reinterpret_cast<const unsigned char*>(src.c_str()),
+ src.size(), buf.get(),
+ encoded_len, do_padding);
+ dest->assign(buf.get(), len);
+}
+
+void WebSafeBase64Escape(const string& src, string* dest) {
+ WebSafeBase64EscapeInternal(src, dest, false);
+}
+
+void WebSafeBase64EscapeWithPadding(const string& src, string* dest) {
+ WebSafeBase64EscapeInternal(src, dest, true);
+}
+
+} // namespace strings
diff --git a/src/tools/windows/converter_exe/escaping.h b/src/tools/windows/converter_exe/escaping.h
index c8aa90b7..bc36bf57 100644
--- a/src/tools/windows/converter_exe/escaping.h
+++ b/src/tools/windows/converter_exe/escaping.h
@@ -1,99 +1,99 @@
-// Copyright 2019 Google Inc. All rights reserved.
-//
-// 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 Inc. 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.
-//
-// Base64 escaping methods to encode/decode strings.
-
-#ifndef TOOLS_WINDOWS_CONVERTER_EXE_ESCAPING_H_
-#define TOOLS_WINDOWS_CONVERTER_EXE_ESCAPING_H_
-
-#include <string>
-
-namespace strings {
-
-using std::string;
-
-// ----------------------------------------------------------------------
-// Base64Escape()
-// WebSafeBase64Escape()
-// Encode "src" to "dest" using base64 encoding.
-// src is not null terminated, instead specify len.
-// 'dest' should have at least CalculateBase64EscapedLen() length.
-// RETURNS the length of dest.
-// The WebSafe variation use '-' instead of '+' and '_' instead of '/'
-// so that we can place the out in the URL or cookies without having
-// to escape them. It also has an extra parameter "do_padding",
-// which when set to false will prevent padding with "=".
-// ----------------------------------------------------------------------
-void Base64Escape(const string& src, string* dest);
-int Base64Escape(const unsigned char* src, int slen, char* dest, int szdest);
-// Encode src into dest with padding.
-void Base64Escape(const unsigned char* src, int szsrc,
- string* dest, bool do_padding);
-
-int WebSafeBase64Escape(const unsigned char* src, int slen, char* dest,
- int szdest, bool do_padding);
-// Encode src into dest web-safely without padding.
-void WebSafeBase64Escape(const string& src, string* dest);
-// Encode src into dest web-safely with padding.
-void WebSafeBase64EscapeWithPadding(const string& src, string* dest);
-void WebSafeBase64Escape(const unsigned char* src, int szsrc,
- string* dest, bool do_padding);
-
-// ----------------------------------------------------------------------
-// Base64Unescape()
-// WebSafeBase64Unescape()
-// Copies "src" to "dest", where src is in base64 and is written to its
-// ASCII equivalents. src is not null terminated, instead specify len.
-// I recommend that slen<szdest, but we honor szdest anyway.
-// RETURNS the length of dest, or -1 if src contains invalid chars.
-// The WebSafe variation use '-' instead of '+' and '_' instead of '/'.
-// The variations that store into a string clear the string first, and
-// return false (with dest empty) if src contains invalid chars; for
-// these versions src and dest must be different strings.
-// ----------------------------------------------------------------------
-int Base64Unescape(const char* src, int slen, char* dest, int szdest);
-bool Base64Unescape(const char* src, int slen, string* dest);
-inline bool Base64Unescape(const string& src, string* dest) {
- return Base64Unescape(src.data(), src.size(), dest);
-}
-
-
-int WebSafeBase64Unescape(const char* src, int slen, char* dest, int szdest);
-bool WebSafeBase64Unescape(const char* src, int slen, string* dest);
-bool WebSafeBase64Unescape(const string& src, string* dest);
-
-// Return the length to use for the output buffer given to the base64 escape
-// routines. Make sure to use the same value for do_padding in both.
-// This function may return incorrect results if given input_len values that
-// are extremely high, which should happen rarely.
-int CalculateBase64EscapedLen(int input_len, bool do_padding);
-// Use this version when calling Base64Escape without a do_padding arg.
-int CalculateBase64EscapedLen(int input_len);
-} // namespace strings
-
-#endif // TOOLS_WINDOWS_CONVERTER_EXE_ESCAPING_H_
+// Copyright 2019 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.
+//
+// Base64 escaping methods to encode/decode strings.
+
+#ifndef TOOLS_WINDOWS_CONVERTER_EXE_ESCAPING_H_
+#define TOOLS_WINDOWS_CONVERTER_EXE_ESCAPING_H_
+
+#include <string>
+
+namespace strings {
+
+using std::string;
+
+// ----------------------------------------------------------------------
+// Base64Escape()
+// WebSafeBase64Escape()
+// Encode "src" to "dest" using base64 encoding.
+// src is not null terminated, instead specify len.
+// 'dest' should have at least CalculateBase64EscapedLen() length.
+// RETURNS the length of dest.
+// The WebSafe variation use '-' instead of '+' and '_' instead of '/'
+// so that we can place the out in the URL or cookies without having
+// to escape them. It also has an extra parameter "do_padding",
+// which when set to false will prevent padding with "=".
+// ----------------------------------------------------------------------
+void Base64Escape(const string& src, string* dest);
+int Base64Escape(const unsigned char* src, int slen, char* dest, int szdest);
+// Encode src into dest with padding.
+void Base64Escape(const unsigned char* src, int szsrc,
+ string* dest, bool do_padding);
+
+int WebSafeBase64Escape(const unsigned char* src, int slen, char* dest,
+ int szdest, bool do_padding);
+// Encode src into dest web-safely without padding.
+void WebSafeBase64Escape(const string& src, string* dest);
+// Encode src into dest web-safely with padding.
+void WebSafeBase64EscapeWithPadding(const string& src, string* dest);
+void WebSafeBase64Escape(const unsigned char* src, int szsrc,
+ string* dest, bool do_padding);
+
+// ----------------------------------------------------------------------
+// Base64Unescape()
+// WebSafeBase64Unescape()
+// Copies "src" to "dest", where src is in base64 and is written to its
+// ASCII equivalents. src is not null terminated, instead specify len.
+// I recommend that slen<szdest, but we honor szdest anyway.
+// RETURNS the length of dest, or -1 if src contains invalid chars.
+// The WebSafe variation use '-' instead of '+' and '_' instead of '/'.
+// The variations that store into a string clear the string first, and
+// return false (with dest empty) if src contains invalid chars; for
+// these versions src and dest must be different strings.
+// ----------------------------------------------------------------------
+int Base64Unescape(const char* src, int slen, char* dest, int szdest);
+bool Base64Unescape(const char* src, int slen, string* dest);
+inline bool Base64Unescape(const string& src, string* dest) {
+ return Base64Unescape(src.data(), src.size(), dest);
+}
+
+
+int WebSafeBase64Unescape(const char* src, int slen, char* dest, int szdest);
+bool WebSafeBase64Unescape(const char* src, int slen, string* dest);
+bool WebSafeBase64Unescape(const string& src, string* dest);
+
+// Return the length to use for the output buffer given to the base64 escape
+// routines. Make sure to use the same value for do_padding in both.
+// This function may return incorrect results if given input_len values that
+// are extremely high, which should happen rarely.
+int CalculateBase64EscapedLen(int input_len, bool do_padding);
+// Use this version when calling Base64Escape without a do_padding arg.
+int CalculateBase64EscapedLen(int input_len);
+} // namespace strings
+
+#endif // TOOLS_WINDOWS_CONVERTER_EXE_ESCAPING_H_
diff --git a/src/tools/windows/converter_exe/http_client.h b/src/tools/windows/converter_exe/http_client.h
index 3e7aa8a7..38ebf2e4 100644
--- a/src/tools/windows/converter_exe/http_client.h
+++ b/src/tools/windows/converter_exe/http_client.h
@@ -1,96 +1,96 @@
-// Copyright 2019 Google Inc. All rights reserved.
-//
-// 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 Inc. 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.
-
-#ifndef TOOLS_CRASH_CONVERTER_WINDOWS_HTTP_CLIENT_H_
-#define TOOLS_CRASH_CONVERTER_WINDOWS_HTTP_CLIENT_H_
-
-#include <tchar.h>
-#include <windows.h>
-#include <vector>
-
-typedef void* HttpHandle;
-
-namespace crash {
-
-// HttpClient provides an abstract layer for HTTP APIs. The actual
-// implementation can be based on either WinHttp or WinInet.
-class HttpClient {
- public:
- enum AccessType {
- ACCESS_TYPE_PRECONFIG,
- ACCESS_TYPE_DIRECT,
- ACCESS_TYPE_PROXY,
- };
-
- virtual ~HttpClient() {}
-
- virtual bool CrackUrl(const TCHAR* url,
- DWORD flags,
- TCHAR* scheme,
- size_t scheme_buffer_length,
- TCHAR* host,
- size_t host_buffer_length,
- TCHAR* uri,
- size_t uri_buffer_length,
- int* port) const = 0;
- virtual bool Open(const TCHAR* user_agent,
- DWORD access_type,
- const TCHAR* proxy_name,
- const TCHAR* proxy_bypass,
- HttpHandle* session_handle) const = 0;
- virtual bool Connect(HttpHandle session_handle,
- const TCHAR* server,
- int port,
- HttpHandle* connection_handle) const = 0;
- virtual bool OpenRequest(HttpHandle connection_handle,
- const TCHAR* verb,
- const TCHAR* uri,
- const TCHAR* version,
- const TCHAR* referrer,
- bool is_secure,
- HttpHandle* request_handle) const = 0;
- virtual bool SendRequest(HttpHandle request_handle,
- const TCHAR* headers,
- DWORD headers_length) const = 0;
- virtual bool ReceiveResponse(HttpHandle request_handle) const = 0;
- virtual bool GetHttpStatusCode(HttpHandle request_handle,
- int* status_code) const = 0;
- virtual bool GetContentLength(HttpHandle request_handle,
- DWORD* content_length) const = 0;
- virtual bool ReadData(HttpHandle request_handle,
- void* buffer,
- DWORD buffer_length,
- DWORD* bytes_read) const = 0;
- virtual bool Close(HttpHandle handle) const = 0;
-
- static const DWORD kUnknownContentLength = (DWORD)-1;
-};
-
-} // namespace crash
-
-#endif // TOOLS_CRASH_CONVERTER_WINDOWS_HTTP_CLIENT_H_
+// Copyright 2019 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.
+
+#ifndef TOOLS_CRASH_CONVERTER_WINDOWS_HTTP_CLIENT_H_
+#define TOOLS_CRASH_CONVERTER_WINDOWS_HTTP_CLIENT_H_
+
+#include <tchar.h>
+#include <windows.h>
+#include <vector>
+
+typedef void* HttpHandle;
+
+namespace crash {
+
+// HttpClient provides an abstract layer for HTTP APIs. The actual
+// implementation can be based on either WinHttp or WinInet.
+class HttpClient {
+ public:
+ enum AccessType {
+ ACCESS_TYPE_PRECONFIG,
+ ACCESS_TYPE_DIRECT,
+ ACCESS_TYPE_PROXY,
+ };
+
+ virtual ~HttpClient() {}
+
+ virtual bool CrackUrl(const TCHAR* url,
+ DWORD flags,
+ TCHAR* scheme,
+ size_t scheme_buffer_length,
+ TCHAR* host,
+ size_t host_buffer_length,
+ TCHAR* uri,
+ size_t uri_buffer_length,
+ int* port) const = 0;
+ virtual bool Open(const TCHAR* user_agent,
+ DWORD access_type,
+ const TCHAR* proxy_name,
+ const TCHAR* proxy_bypass,
+ HttpHandle* session_handle) const = 0;
+ virtual bool Connect(HttpHandle session_handle,
+ const TCHAR* server,
+ int port,
+ HttpHandle* connection_handle) const = 0;
+ virtual bool OpenRequest(HttpHandle connection_handle,
+ const TCHAR* verb,
+ const TCHAR* uri,
+ const TCHAR* version,
+ const TCHAR* referrer,
+ bool is_secure,
+ HttpHandle* request_handle) const = 0;
+ virtual bool SendRequest(HttpHandle request_handle,
+ const TCHAR* headers,
+ DWORD headers_length) const = 0;
+ virtual bool ReceiveResponse(HttpHandle request_handle) const = 0;
+ virtual bool GetHttpStatusCode(HttpHandle request_handle,
+ int* status_code) const = 0;
+ virtual bool GetContentLength(HttpHandle request_handle,
+ DWORD* content_length) const = 0;
+ virtual bool ReadData(HttpHandle request_handle,
+ void* buffer,
+ DWORD buffer_length,
+ DWORD* bytes_read) const = 0;
+ virtual bool Close(HttpHandle handle) const = 0;
+
+ static const DWORD kUnknownContentLength = (DWORD)-1;
+};
+
+} // namespace crash
+
+#endif // TOOLS_CRASH_CONVERTER_WINDOWS_HTTP_CLIENT_H_
diff --git a/src/tools/windows/converter_exe/http_download.cc b/src/tools/windows/converter_exe/http_download.cc
index 5afc1ccc..75f674e0 100644
--- a/src/tools/windows/converter_exe/http_download.cc
+++ b/src/tools/windows/converter_exe/http_download.cc
@@ -1,326 +1,326 @@
-// Copyright 2019 Google Inc. All rights reserved.
-//
-// 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 Inc. 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.
-
-#include <assert.h>
-#include <stdio.h>
-#include <Windows.h>
-#include <WinInet.h>
-
-#include <vector>
-
-#include "tools/windows/converter_exe/http_download.h"
-#include "tools/windows/converter_exe/winhttp_client.h"
-#include "tools/windows/converter_exe/wininet_client.h"
-
-namespace crash {
-static const std::vector<char>::size_type kVectorChunkSize = 4096; // 4 KB
-
-using std::vector;
-
-// Class that atuo closes the contained HttpHandle when the object
-// goes out of scope.
-class AutoHttpHandle {
- public:
- AutoHttpHandle() : handle_(NULL) {}
- explicit AutoHttpHandle(HttpHandle handle) : handle_(handle) {}
- ~AutoHttpHandle() {
- if (handle_) {
- InternetCloseHandle(handle_);
- }
- }
-
- HttpHandle get() { return handle_; }
- HttpHandle* get_handle_addr () { return &handle_; }
-
- private:
- HttpHandle handle_;
-};
-
-// Template class for auto releasing the contained pointer when
-// the object goes out of scope.
-template<typename T>
-class AutoPtr {
- public:
- explicit AutoPtr(T* ptr) : ptr_(ptr) {}
- ~AutoPtr() {
- if (ptr_) {
- delete ptr_;
- }
- }
-
- T* get() { return ptr_; }
- T* operator -> () { return ptr_; }
-
- private:
- T* ptr_;
-};
-
-// CheckParameters ensures that the parameters in |parameters| are safe for
-// use in an HTTP URL. Returns true if they are, false if unsafe characters
-// are present.
-static bool CheckParameters(const map<wstring, wstring> *parameters) {
- for (map<wstring, wstring>::const_iterator iterator = parameters->begin();
- iterator != parameters->end();
- ++iterator) {
- const wstring &key = iterator->first;
- if (key.empty()) {
- // Disallow empty parameter names.
- return false;
- }
- for (unsigned int i = 0; i < key.size(); ++i) {
- wchar_t c = key[i];
- if (c < 32 || c == '"' || c == '?' || c == '&' || c > 127) {
- return false;
- }
- }
-
- const wstring &value = iterator->second;
- for (unsigned int i = 0; i < value.size(); ++i) {
- wchar_t c = value[i];
- if (c < 32 || c == '"' || c == '?' || c == '&' || c > 127) {
- return false;
- }
- }
- }
-
- return true;
-}
-
-HttpClient* HTTPDownload::CreateHttpClient(const wchar_t* url) {
- const TCHAR* kHttpApiPolicyEnvironmentVariable = TEXT("USE_WINHTTP");
- TCHAR buffer[2] = {0};
- HttpClient* http_client = NULL;
-
- if (::GetEnvironmentVariable(kHttpApiPolicyEnvironmentVariable,
- buffer,
- sizeof(buffer)/sizeof(buffer[0])) > 0) {
- fprintf(stdout,
- "Environment variable [%ws] is set, use WinHttp\n",
- kHttpApiPolicyEnvironmentVariable);
- http_client = CreateWinHttpClient(url);
- if (http_client == NULL) {
- fprintf(stderr, "WinHttpClient not created, Is the protocol HTTPS? "
- "Fall back to WinInet API.\n");
- }
- } else {
- fprintf(stderr,
- "Environment variable [%ws] is NOT set, use WinInet API\n",
- kHttpApiPolicyEnvironmentVariable);
- }
-
- if (http_client == NULL) {
- return CreateWinInetClient(url);
- }
-
- return http_client;
-}
-
-// static
-bool HTTPDownload::Download(const wstring &url,
- const map<wstring, wstring> *parameters,
- string *content, int *status_code) {
- assert(content);
- AutoPtr<HttpClient> http_client(CreateHttpClient(url.c_str()));
-
- if (!http_client.get()) {
- fprintf(stderr, "Failed to create any http client.\n");
- return false;
- }
-
- if (status_code) {
- *status_code = 0;
- }
-
- wchar_t scheme[16] = {0};
- wchar_t host[256] = {0};
- wchar_t path[256] = {0};
- int port = 0;
- if (!http_client->CrackUrl(url.c_str(),
- 0,
- scheme,
- sizeof(scheme)/sizeof(scheme[0]),
- host,
- sizeof(host)/sizeof(host[0]),
- path,
- sizeof(path)/sizeof(path[0]),
- &port)) {
- fprintf(stderr,
- "HTTPDownload::Download: InternetCrackUrl: error %lu for %ws\n",
- GetLastError(), url.c_str());
- return false;
- }
-
- bool secure = false;
- if (_wcsicmp(scheme, L"https") == 0) {
- secure = true;
- } else if (wcscmp(scheme, L"http") != 0) {
- fprintf(stderr,
- "HTTPDownload::Download: scheme must be http or https for %ws\n",
- url.c_str());
- return false;
- }
-
- AutoHttpHandle internet;
- if (!http_client->Open(NULL, // user agent
- HttpClient::ACCESS_TYPE_PRECONFIG,
- NULL, // proxy name
- NULL, // proxy bypass
- internet.get_handle_addr())) {
- fprintf(stderr,
- "HTTPDownload::Download: Open: error %lu for %ws\n",
- GetLastError(), url.c_str());
- return false;
- }
-
- AutoHttpHandle connection;
- if (!http_client->Connect(internet.get(),
- host,
- port,
- connection.get_handle_addr())) {
- fprintf(stderr,
- "HTTPDownload::Download: InternetConnect: error %lu for %ws\n",
- GetLastError(), url.c_str());
- return false;
- }
-
- wstring request_string = path;
- if (parameters) {
- // TODO(mmentovai): escape bad characters in parameters instead of
- // forbidding them.
- if (!CheckParameters(parameters)) {
- fprintf(stderr,
- "HTTPDownload::Download: invalid characters in parameters\n");
- return false;
- }
-
- bool added_parameter = false;
- for (map<wstring, wstring>::const_iterator iterator = parameters->begin();
- iterator != parameters->end();
- ++iterator) {
- request_string.append(added_parameter ? L"&" : L"?");
- request_string.append(iterator->first);
- request_string.append(L"=");
- request_string.append(iterator->second);
- added_parameter = true;
- }
- }
-
- AutoHttpHandle request;
- if (!http_client->OpenRequest(connection.get(),
- L"GET",
- request_string.c_str(),
- NULL, // version
- NULL, // referer
- secure,
- request.get_handle_addr())) {
- fprintf(stderr,
- "HttpClient::OpenRequest: error %lu for %ws, request: %ws\n",
- GetLastError(), url.c_str(), request_string.c_str());
- return false;
- }
-
- if (!http_client->SendRequest(request.get(), NULL, 0)) {
- fprintf(stderr,
- "HttpClient::SendRequest: error %lu for %ws\n",
- GetLastError(), url.c_str());
- return false;
- }
-
- if (!http_client->ReceiveResponse(request.get())) {
- fprintf(stderr,
- "HttpClient::ReceiveResponse: error %lu for %ws\n",
- GetLastError(), url.c_str());
- return false;
- }
-
- int http_status = 0;
- if (!http_client->GetHttpStatusCode(request.get(), &http_status)) {
- fprintf(stderr,
- "HttpClient::GetHttpStatusCode: error %lu for %ws\n",
- GetLastError(), url.c_str());
- return false;
- }
- if (http_status != 200) {
- fprintf(stderr,
- "HTTPDownload::Download: HTTP status code %d for %ws\n",
- http_status, url.c_str());
- return false;
- }
-
- DWORD content_length = 0;
- vector<char>::size_type buffer_size = 0;
- http_client->GetContentLength(request.get(), &content_length);
- if (content_length == HttpClient::kUnknownContentLength) {
- buffer_size = kVectorChunkSize;
- } else {
- buffer_size = content_length;
- }
-
- if (content_length != 0) {
- vector<char> response_buffer = vector<char>(buffer_size+1);
- DWORD size_read;
- DWORD total_read = 0;
- bool read_result;
- do {
- if (content_length == HttpClient::kUnknownContentLength
- && buffer_size == total_read) {
- // The content length wasn't specified in the response header, so we
- // have to keep growing the buffer until we're done reading.
- buffer_size += kVectorChunkSize;
- response_buffer.resize(buffer_size);
- }
- read_result = !!http_client->ReadData(
- request.get(),
- &response_buffer[total_read],
- static_cast<DWORD>(buffer_size) - total_read,
- &size_read);
- total_read += size_read;
- } while (read_result && (size_read != 0));
-
- if (!read_result) {
- fprintf(stderr,
- "HttpClient::ReadData: error %lu for %ws\n",
- GetLastError(),
- url.c_str());
- return false;
- } else if (size_read != 0) {
- fprintf(stderr,
- "HttpClient::ReadData: error %lu/%lu for %ws\n",
- total_read,
- content_length,
- url.c_str());
- return false;
- }
- content->assign(&response_buffer[0], total_read);
- } else {
- content->clear();
- }
- return true;
-}
-
-} // namespace crash
+// Copyright 2019 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.
+
+#include <assert.h>
+#include <stdio.h>
+#include <Windows.h>
+#include <WinInet.h>
+
+#include <vector>
+
+#include "tools/windows/converter_exe/http_download.h"
+#include "tools/windows/converter_exe/winhttp_client.h"
+#include "tools/windows/converter_exe/wininet_client.h"
+
+namespace crash {
+static const std::vector<char>::size_type kVectorChunkSize = 4096; // 4 KB
+
+using std::vector;
+
+// Class that atuo closes the contained HttpHandle when the object
+// goes out of scope.
+class AutoHttpHandle {
+ public:
+ AutoHttpHandle() : handle_(NULL) {}
+ explicit AutoHttpHandle(HttpHandle handle) : handle_(handle) {}
+ ~AutoHttpHandle() {
+ if (handle_) {
+ InternetCloseHandle(handle_);
+ }
+ }
+
+ HttpHandle get() { return handle_; }
+ HttpHandle* get_handle_addr () { return &handle_; }
+
+ private:
+ HttpHandle handle_;
+};
+
+// Template class for auto releasing the contained pointer when
+// the object goes out of scope.
+template<typename T>
+class AutoPtr {
+ public:
+ explicit AutoPtr(T* ptr) : ptr_(ptr) {}
+ ~AutoPtr() {
+ if (ptr_) {
+ delete ptr_;
+ }
+ }
+
+ T* get() { return ptr_; }
+ T* operator -> () { return ptr_; }
+
+ private:
+ T* ptr_;
+};
+
+// CheckParameters ensures that the parameters in |parameters| are safe for
+// use in an HTTP URL. Returns true if they are, false if unsafe characters
+// are present.
+static bool CheckParameters(const map<wstring, wstring>* parameters) {
+ for (map<wstring, wstring>::const_iterator iterator = parameters->begin();
+ iterator != parameters->end();
+ ++iterator) {
+ const wstring& key = iterator->first;
+ if (key.empty()) {
+ // Disallow empty parameter names.
+ return false;
+ }
+ for (unsigned int i = 0; i < key.size(); ++i) {
+ wchar_t c = key[i];
+ if (c < 32 || c == '"' || c == '?' || c == '&' || c > 127) {
+ return false;
+ }
+ }
+
+ const wstring& value = iterator->second;
+ for (unsigned int i = 0; i < value.size(); ++i) {
+ wchar_t c = value[i];
+ if (c < 32 || c == '"' || c == '?' || c == '&' || c > 127) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+HttpClient* HTTPDownload::CreateHttpClient(const wchar_t* url) {
+ const TCHAR* kHttpApiPolicyEnvironmentVariable = TEXT("USE_WINHTTP");
+ TCHAR buffer[2] = {0};
+ HttpClient* http_client = NULL;
+
+ if (::GetEnvironmentVariable(kHttpApiPolicyEnvironmentVariable,
+ buffer,
+ sizeof(buffer)/sizeof(buffer[0])) > 0) {
+ fprintf(stdout,
+ "Environment variable [%ws] is set, use WinHttp\n",
+ kHttpApiPolicyEnvironmentVariable);
+ http_client = CreateWinHttpClient(url);
+ if (http_client == NULL) {
+ fprintf(stderr, "WinHttpClient not created, Is the protocol HTTPS? "
+ "Fall back to WinInet API.\n");
+ }
+ } else {
+ fprintf(stderr,
+ "Environment variable [%ws] is NOT set, use WinInet API\n",
+ kHttpApiPolicyEnvironmentVariable);
+ }
+
+ if (http_client == NULL) {
+ return CreateWinInetClient(url);
+ }
+
+ return http_client;
+}
+
+// static
+bool HTTPDownload::Download(const wstring& url,
+ const map<wstring, wstring>* parameters,
+ string *content, int *status_code) {
+ assert(content);
+ AutoPtr<HttpClient> http_client(CreateHttpClient(url.c_str()));
+
+ if (!http_client.get()) {
+ fprintf(stderr, "Failed to create any http client.\n");
+ return false;
+ }
+
+ if (status_code) {
+ *status_code = 0;
+ }
+
+ wchar_t scheme[16] = {0};
+ wchar_t host[256] = {0};
+ wchar_t path[256] = {0};
+ int port = 0;
+ if (!http_client->CrackUrl(url.c_str(),
+ 0,
+ scheme,
+ sizeof(scheme)/sizeof(scheme[0]),
+ host,
+ sizeof(host)/sizeof(host[0]),
+ path,
+ sizeof(path)/sizeof(path[0]),
+ &port)) {
+ fprintf(stderr,
+ "HTTPDownload::Download: InternetCrackUrl: error %lu for %ws\n",
+ GetLastError(), url.c_str());
+ return false;
+ }
+
+ bool secure = false;
+ if (_wcsicmp(scheme, L"https") == 0) {
+ secure = true;
+ } else if (wcscmp(scheme, L"http") != 0) {
+ fprintf(stderr,
+ "HTTPDownload::Download: scheme must be http or https for %ws\n",
+ url.c_str());
+ return false;
+ }
+
+ AutoHttpHandle internet;
+ if (!http_client->Open(NULL, // user agent
+ HttpClient::ACCESS_TYPE_PRECONFIG,
+ NULL, // proxy name
+ NULL, // proxy bypass
+ internet.get_handle_addr())) {
+ fprintf(stderr,
+ "HTTPDownload::Download: Open: error %lu for %ws\n",
+ GetLastError(), url.c_str());
+ return false;
+ }
+
+ AutoHttpHandle connection;
+ if (!http_client->Connect(internet.get(),
+ host,
+ port,
+ connection.get_handle_addr())) {
+ fprintf(stderr,
+ "HTTPDownload::Download: InternetConnect: error %lu for %ws\n",
+ GetLastError(), url.c_str());
+ return false;
+ }
+
+ wstring request_string = path;
+ if (parameters) {
+ // TODO(mmentovai): escape bad characters in parameters instead of
+ // forbidding them.
+ if (!CheckParameters(parameters)) {
+ fprintf(stderr,
+ "HTTPDownload::Download: invalid characters in parameters\n");
+ return false;
+ }
+
+ bool added_parameter = false;
+ for (map<wstring, wstring>::const_iterator iterator = parameters->begin();
+ iterator != parameters->end();
+ ++iterator) {
+ request_string.append(added_parameter ? L"&" : L"?");
+ request_string.append(iterator->first);
+ request_string.append(L"=");
+ request_string.append(iterator->second);
+ added_parameter = true;
+ }
+ }
+
+ AutoHttpHandle request;
+ if (!http_client->OpenRequest(connection.get(),
+ L"GET",
+ request_string.c_str(),
+ NULL, // version
+ NULL, // referer
+ secure,
+ request.get_handle_addr())) {
+ fprintf(stderr,
+ "HttpClient::OpenRequest: error %lu for %ws, request: %ws\n",
+ GetLastError(), url.c_str(), request_string.c_str());
+ return false;
+ }
+
+ if (!http_client->SendRequest(request.get(), NULL, 0)) {
+ fprintf(stderr,
+ "HttpClient::SendRequest: error %lu for %ws\n",
+ GetLastError(), url.c_str());
+ return false;
+ }
+
+ if (!http_client->ReceiveResponse(request.get())) {
+ fprintf(stderr,
+ "HttpClient::ReceiveResponse: error %lu for %ws\n",
+ GetLastError(), url.c_str());
+ return false;
+ }
+
+ int http_status = 0;
+ if (!http_client->GetHttpStatusCode(request.get(), &http_status)) {
+ fprintf(stderr,
+ "HttpClient::GetHttpStatusCode: error %lu for %ws\n",
+ GetLastError(), url.c_str());
+ return false;
+ }
+ if (http_status != 200) {
+ fprintf(stderr,
+ "HTTPDownload::Download: HTTP status code %d for %ws\n",
+ http_status, url.c_str());
+ return false;
+ }
+
+ DWORD content_length = 0;
+ vector<char>::size_type buffer_size = 0;
+ http_client->GetContentLength(request.get(), &content_length);
+ if (content_length == HttpClient::kUnknownContentLength) {
+ buffer_size = kVectorChunkSize;
+ } else {
+ buffer_size = content_length;
+ }
+
+ if (content_length != 0) {
+ vector<char> response_buffer = vector<char>(buffer_size+1);
+ DWORD size_read;
+ DWORD total_read = 0;
+ bool read_result;
+ do {
+ if (content_length == HttpClient::kUnknownContentLength
+ && buffer_size == total_read) {
+ // The content length wasn't specified in the response header, so we
+ // have to keep growing the buffer until we're done reading.
+ buffer_size += kVectorChunkSize;
+ response_buffer.resize(buffer_size);
+ }
+ read_result = !!http_client->ReadData(
+ request.get(),
+ &response_buffer[total_read],
+ static_cast<DWORD>(buffer_size) - total_read,
+ &size_read);
+ total_read += size_read;
+ } while (read_result && (size_read != 0));
+
+ if (!read_result) {
+ fprintf(stderr,
+ "HttpClient::ReadData: error %lu for %ws\n",
+ GetLastError(),
+ url.c_str());
+ return false;
+ } else if (size_read != 0) {
+ fprintf(stderr,
+ "HttpClient::ReadData: error %lu/%lu for %ws\n",
+ total_read,
+ content_length,
+ url.c_str());
+ return false;
+ }
+ content->assign(&response_buffer[0], total_read);
+ } else {
+ content->clear();
+ }
+ return true;
+}
+
+} // namespace crash
diff --git a/src/tools/windows/converter_exe/http_download.h b/src/tools/windows/converter_exe/http_download.h
index 2d705d5e..f58a3d0f 100644
--- a/src/tools/windows/converter_exe/http_download.h
+++ b/src/tools/windows/converter_exe/http_download.h
@@ -1,62 +1,62 @@
-// Copyright 2019 Google Inc. All rights reserved.
-//
-// 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 Inc. 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.
-
-#ifndef TOOLS_WINDOWS_CONVERTER_EXE_HTTP_DOWNLOAD_H_
-#define TOOLS_WINDOWS_CONVERTER_EXE_HTTP_DOWNLOAD_H_
-
-#include <map>
-#include <string>
-#include "tools/windows/converter_exe/winhttp_client.h"
-
-namespace crash {
-
-using std::map;
-using std::string;
-using std::wstring;
-
-class HTTPDownload {
- public:
- // Retrieves the resource located at |url|, a http or https URL, via WinInet.
- // The request is fetched with GET request; the optional |parameters| are
- // appended to the URL. Returns true on success, placing the content of the
- // retrieved resource in |content|. Returns false on failure. HTTP status
- // codes other than 200 cause Download to return false. If |status_code| is
- // supplied, it will be set to the value of the HTTP status code, if an HTTP
- // transaction occurs. If Download fails before a transaction can occur,
- // |status_code| will be set to 0. Any failures will result in messages
- // being printed to stderr.
- static bool Download(const wstring &url,
- const map<wstring, wstring> *parameters,
- string *content, int *status_code);
- private:
- static HttpClient* CreateHttpClient(const wchar_t*);
-};
-
-} // namespace crash
-
-#endif // TOOLS_WINDOWS_CONVERTER_EXE_HTTP_DOWNLOAD_H_
+// Copyright 2019 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.
+
+#ifndef TOOLS_WINDOWS_CONVERTER_EXE_HTTP_DOWNLOAD_H_
+#define TOOLS_WINDOWS_CONVERTER_EXE_HTTP_DOWNLOAD_H_
+
+#include <map>
+#include <string>
+#include "tools/windows/converter_exe/winhttp_client.h"
+
+namespace crash {
+
+using std::map;
+using std::string;
+using std::wstring;
+
+class HTTPDownload {
+ public:
+ // Retrieves the resource located at |url|, a http or https URL, via WinInet.
+ // The request is fetched with GET request; the optional |parameters| are
+ // appended to the URL. Returns true on success, placing the content of the
+ // retrieved resource in |content|. Returns false on failure. HTTP status
+ // codes other than 200 cause Download to return false. If |status_code| is
+ // supplied, it will be set to the value of the HTTP status code, if an HTTP
+ // transaction occurs. If Download fails before a transaction can occur,
+ // |status_code| will be set to 0. Any failures will result in messages
+ // being printed to stderr.
+ static bool Download(const wstring& url,
+ const map<wstring, wstring>* parameters,
+ string *content, int *status_code);
+ private:
+ static HttpClient* CreateHttpClient(const wchar_t*);
+};
+
+} // namespace crash
+
+#endif // TOOLS_WINDOWS_CONVERTER_EXE_HTTP_DOWNLOAD_H_
diff --git a/src/tools/windows/converter_exe/tokenizer.cc b/src/tools/windows/converter_exe/tokenizer.cc
index 992694cd..6d627536 100644
--- a/src/tools/windows/converter_exe/tokenizer.cc
+++ b/src/tools/windows/converter_exe/tokenizer.cc
@@ -1,61 +1,61 @@
-// Copyright 2019 Google Inc. All rights reserved.
-//
-// 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 Inc. 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.
-
-#include <assert.h>
-
-#include "tools/windows/converter_exe/tokenizer.h"
-
-namespace crash {
-
-// static
-void Tokenizer::Tokenize(const string &delimiters, const string &input,
- vector<string> *output) {
- assert(output);
- output->clear();
-
- string::size_type position = 0; // Where to begin looking for a delimiter
- string::size_type new_position; // Position of found delimiter
- string token;
-
- while ((new_position = input.find_first_of(delimiters, position)) !=
- string::npos) {
- token = input.substr(position, new_position - position);
- output->push_back(token);
-
- // Next time, begin looking right after this delimiter.
- position = new_position + 1;
- }
-
- // There are no more delimiters in the string. Take everything from the
- // final delimiter up to the end of the string as a token. This may be
- // an empty string.
- token = input.substr(position);
- output->push_back(token);
-}
-
-} // namespace crash
+// Copyright 2019 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.
+
+#include <assert.h>
+
+#include "tools/windows/converter_exe/tokenizer.h"
+
+namespace crash {
+
+// static
+void Tokenizer::Tokenize(const string& delimiters, const string& input,
+ vector<string>* output) {
+ assert(output);
+ output->clear();
+
+ string::size_type position = 0; // Where to begin looking for a delimiter
+ string::size_type new_position; // Position of found delimiter
+ string token;
+
+ while ((new_position = input.find_first_of(delimiters, position)) !=
+ string::npos) {
+ token = input.substr(position, new_position - position);
+ output->push_back(token);
+
+ // Next time, begin looking right after this delimiter.
+ position = new_position + 1;
+ }
+
+ // There are no more delimiters in the string. Take everything from the
+ // final delimiter up to the end of the string as a token. This may be
+ // an empty string.
+ token = input.substr(position);
+ output->push_back(token);
+}
+
+} // namespace crash
diff --git a/src/tools/windows/converter_exe/tokenizer.h b/src/tools/windows/converter_exe/tokenizer.h
index f4bbcfd0..d9829f60 100644
--- a/src/tools/windows/converter_exe/tokenizer.h
+++ b/src/tools/windows/converter_exe/tokenizer.h
@@ -1,51 +1,51 @@
-// Copyright 2019 Google Inc. All rights reserved.
-//
-// 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 Inc. 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.
-
-#ifndef TOOLS_WINDOWS_CONVERTER_EXE_TOKENIZER_H_
-#define TOOLS_WINDOWS_CONVERTER_EXE_TOKENIZER_H_
-
-#include <string>
-#include <vector>
-
-namespace crash {
-
-using std::string;
-using std::vector;
-
-class Tokenizer {
- public:
- // Splits |input| into a series of tokens delimited in the input string by
- // any of the characters in |delimiters|. The tokens are passed back in the
- // |output| vector.
- static void Tokenize(const string &delimiters, const string &input,
- vector<string> *output);
-};
-
-} // namespace crash
-
-#endif // TOOLS_WINDOWS_CONVERTER_EXE_TOKENIZER_H_
+// Copyright 2019 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.
+
+#ifndef TOOLS_WINDOWS_CONVERTER_EXE_TOKENIZER_H_
+#define TOOLS_WINDOWS_CONVERTER_EXE_TOKENIZER_H_
+
+#include <string>
+#include <vector>
+
+namespace crash {
+
+using std::string;
+using std::vector;
+
+class Tokenizer {
+ public:
+ // Splits |input| into a series of tokens delimited in the input string by
+ // any of the characters in |delimiters|. The tokens are passed back in the
+ // |output| vector.
+ static void Tokenize(const string& delimiters, const string& input,
+ vector<string>* output);
+};
+
+} // namespace crash
+
+#endif // 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 8a8ade3b..f8c1492d 100644
--- a/src/tools/windows/converter_exe/winhttp_client.cc
+++ b/src/tools/windows/converter_exe/winhttp_client.cc
@@ -1,307 +1,307 @@
-// Copyright 2019 Google Inc. All rights reserved.
-//
-// 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 Inc. 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.
-
-#include "tools/windows/converter_exe/winhttp_client.h"
-
-#include <assert.h>
-#include <stdlib.h>
-#include <windows.h>
-#include <winhttp.h>
-#include <vector>
-
-namespace crash {
-
-namespace internal {
-
-// This class implements HttpClient based on WinInet APIs.
-class WinHttpClient : public HttpClient {
- public:
- virtual ~WinHttpClient() {}
- virtual bool CrackUrl(const TCHAR* url,
- DWORD flags,
- TCHAR* scheme,
- size_t scheme_buffer_length,
- TCHAR* host,
- size_t host_buffer_length,
- TCHAR* uri,
- size_t uri_buffer_length,
- int* port) const;
- virtual bool Open(const TCHAR* user_agent,
- DWORD access_type,
- const TCHAR* proxy_name,
- const TCHAR* proxy_bypass,
- HttpHandle* session_handle) const;
- virtual bool Connect(HttpHandle session_handle,
- const TCHAR* server,
- int port,
- HttpHandle* connection_handle) const;
- virtual bool OpenRequest(HttpHandle connection_handle,
- const TCHAR* verb,
- const TCHAR* uri,
- const TCHAR* version,
- const TCHAR* referrer,
- bool is_secure,
- HttpHandle* request_handle) const;
- virtual bool SendRequest(HttpHandle request_handle,
- const TCHAR* headers,
- DWORD headers_length) const;
- virtual bool ReceiveResponse(HttpHandle request_handle) const;
- virtual bool GetHttpStatusCode(HttpHandle request_handle,
- int* status_code) const;
- virtual bool GetContentLength(HttpHandle request_handle,
- DWORD* content_length) const;
- virtual bool ReadData(HttpHandle request_handle,
- void* buffer,
- DWORD buffer_length,
- DWORD* bytes_read) const;
- virtual bool Close(HttpHandle handle) const;
-
- private:
- static DWORD MapAccessType(DWORD access_type);
- static HINTERNET ToHINTERNET(HttpHandle handle);
- static HttpHandle FromHINTERNET(HINTERNET handle);
-};
-
-bool WinHttpClient::CrackUrl(const TCHAR* url,
- DWORD flags,
- TCHAR* scheme,
- size_t scheme_buffer_length,
- TCHAR* host,
- size_t host_buffer_length,
- TCHAR* uri,
- size_t uri_buffer_length,
- int* port) const {
- assert(url);
- assert(scheme);
- assert(host);
- assert(uri);
- assert(port);
-
- URL_COMPONENTS url_comp = {0};
- url_comp.dwStructSize = sizeof(url_comp);
- url_comp.lpszScheme = scheme;
- url_comp.dwSchemeLength = static_cast<DWORD>(scheme_buffer_length);
- url_comp.lpszHostName = host;
- url_comp.dwHostNameLength = static_cast<DWORD>(host_buffer_length);
- url_comp.lpszUrlPath = uri;
- url_comp.dwUrlPathLength = static_cast<DWORD>(uri_buffer_length);
-
- bool result = !!::WinHttpCrackUrl(url, 0, flags, &url_comp);
- if (result) {
- *port = static_cast<int>(url_comp.nPort);
- }
- return result;
-}
-
-bool WinHttpClient::Open(const TCHAR* user_agent,
- DWORD access_type,
- const TCHAR* proxy_name,
- const TCHAR* proxy_bypass,
- HttpHandle* session_handle) const {
- *session_handle = FromHINTERNET(::WinHttpOpen(user_agent,
- MapAccessType(access_type),
- proxy_name,
- proxy_bypass,
- 0));
-
- return !!(*session_handle);
-}
-
-bool WinHttpClient::Connect(HttpHandle session_handle,
- const TCHAR* server,
- int port,
- HttpHandle* connection_handle) const {
- assert(server);
-
- // Uses NULL user name and password to connect.
- *connection_handle = FromHINTERNET(::WinHttpConnect(
- ToHINTERNET(session_handle),
- server,
- static_cast<INTERNET_PORT>(port),
- NULL));
- return !!(*connection_handle);
-}
-
-bool WinHttpClient::OpenRequest(HttpHandle connection_handle,
- const TCHAR* verb,
- const TCHAR* uri,
- const TCHAR* version,
- const TCHAR* referrer,
- bool is_secure,
- HttpHandle* request_handle) const {
- assert(connection_handle);
- assert(verb);
- assert(uri);
- assert(request_handle);
-
- *request_handle = FromHINTERNET(::WinHttpOpenRequest(
- ToHINTERNET(connection_handle),
- verb,
- uri,
- version,
- referrer,
- WINHTTP_DEFAULT_ACCEPT_TYPES,
- is_secure ? WINHTTP_FLAG_SECURE : 0));
- return !!(*request_handle);
-}
-
-bool WinHttpClient::SendRequest(HttpHandle request_handle,
- const TCHAR* headers,
- DWORD headers_length) const {
- assert(request_handle);
-
- return !!::WinHttpSendRequest(ToHINTERNET(request_handle),
- headers,
- headers_length,
- NULL,
- 0,
- WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH,
- NULL);
-}
-
-bool WinHttpClient::ReceiveResponse(HttpHandle request_handle) const {
- assert(request_handle);
-
- return !!::WinHttpReceiveResponse(ToHINTERNET(request_handle), NULL);
-}
-
-bool WinHttpClient::GetHttpStatusCode(HttpHandle request_handle,
- int* status_code) const {
- TCHAR http_status_string[4] = {0};
- DWORD http_status_string_size = sizeof(http_status_string);
- if (!::WinHttpQueryHeaders(ToHINTERNET(request_handle),
- WINHTTP_QUERY_STATUS_CODE,
- WINHTTP_HEADER_NAME_BY_INDEX,
- static_cast<void *>(&http_status_string),
- &http_status_string_size, 0)) {
- return false;
- }
-
- *status_code = static_cast<DWORD>(_tcstol(http_status_string, NULL, 10));
- return true;
-}
-
-bool WinHttpClient::GetContentLength(HttpHandle request_handle,
- DWORD* content_length) const {
- assert(request_handle);
- assert(content_length);
-
- TCHAR content_length_string[11] = {0};
- DWORD content_length_string_size = sizeof(content_length_string);
- if (!::WinHttpQueryHeaders(ToHINTERNET(request_handle),
- WINHTTP_QUERY_CONTENT_LENGTH,
- WINHTTP_HEADER_NAME_BY_INDEX,
- static_cast<void *>(&content_length_string),
- &content_length_string_size, 0)) {
- *content_length = kUnknownContentLength;
- } else {
- *content_length =
- static_cast<DWORD>(wcstol(content_length_string, NULL, 10));
- }
- return true;
-}
-
-bool WinHttpClient::ReadData(HttpHandle request_handle,
- void* buffer,
- DWORD buffer_length,
- DWORD* bytes_read) const {
- assert(request_handle);
- assert(buffer);
- assert(bytes_read);
-
- DWORD bytes_read_local = 0;
- if (!::WinHttpReadData(ToHINTERNET(request_handle),
- buffer,
- buffer_length,
- &bytes_read_local)) {
- return false;
- }
- *bytes_read = bytes_read_local;
- return true;
-}
-
-bool WinHttpClient::Close(HttpHandle handle) const {
- assert(handle);
- return !!::WinHttpCloseHandle(ToHINTERNET(handle));
-}
-
-DWORD WinHttpClient::MapAccessType(DWORD access_type) {
- switch (static_cast<AccessType>(access_type)) {
- case ACCESS_TYPE_PRECONFIG:
- default:
- return WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
- case ACCESS_TYPE_DIRECT:
- return WINHTTP_ACCESS_TYPE_NO_PROXY;
- case ACCESS_TYPE_PROXY:
- return WINHTTP_ACCESS_TYPE_NAMED_PROXY;
- }
-}
-
-
-HINTERNET WinHttpClient::ToHINTERNET(HttpHandle handle) {
- return static_cast<HINTERNET>(handle);
-}
-
-HttpHandle WinHttpClient::FromHINTERNET(HINTERNET handle) {
- return static_cast<HttpHandle>(handle);
-}
-
-} // namespace internal
-
-HttpClient* CreateWinHttpClient(const TCHAR* url) {
- assert(url);
-
- internal::WinHttpClient winhttp;
- wchar_t scheme[16] = {0};
- wchar_t host[256] = {0};
- wchar_t path[256] = {0};
- int port = 0;
-
- if (!winhttp.CrackUrl(url,
- 0,
- scheme,
- sizeof(scheme)/sizeof(scheme[0]),
- host,
- sizeof(host)/sizeof(host[0]),
- path,
- sizeof(path)/sizeof(path[0]),
- &port)) {
- return NULL;
- }
-
- 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 new internal::WinHttpClient();
-}
-
-} // namespace crash
+// Copyright 2019 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.
+
+#include "tools/windows/converter_exe/winhttp_client.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <windows.h>
+#include <winhttp.h>
+#include <vector>
+
+namespace crash {
+
+namespace internal {
+
+// This class implements HttpClient based on WinInet APIs.
+class WinHttpClient : public HttpClient {
+ public:
+ virtual ~WinHttpClient() {}
+ virtual bool CrackUrl(const TCHAR* url,
+ DWORD flags,
+ TCHAR* scheme,
+ size_t scheme_buffer_length,
+ TCHAR* host,
+ size_t host_buffer_length,
+ TCHAR* uri,
+ size_t uri_buffer_length,
+ int* port) const;
+ virtual bool Open(const TCHAR* user_agent,
+ DWORD access_type,
+ const TCHAR* proxy_name,
+ const TCHAR* proxy_bypass,
+ HttpHandle* session_handle) const;
+ virtual bool Connect(HttpHandle session_handle,
+ const TCHAR* server,
+ int port,
+ HttpHandle* connection_handle) const;
+ virtual bool OpenRequest(HttpHandle connection_handle,
+ const TCHAR* verb,
+ const TCHAR* uri,
+ const TCHAR* version,
+ const TCHAR* referrer,
+ bool is_secure,
+ HttpHandle* request_handle) const;
+ virtual bool SendRequest(HttpHandle request_handle,
+ const TCHAR* headers,
+ DWORD headers_length) const;
+ virtual bool ReceiveResponse(HttpHandle request_handle) const;
+ virtual bool GetHttpStatusCode(HttpHandle request_handle,
+ int* status_code) const;
+ virtual bool GetContentLength(HttpHandle request_handle,
+ DWORD* content_length) const;
+ virtual bool ReadData(HttpHandle request_handle,
+ void* buffer,
+ DWORD buffer_length,
+ DWORD* bytes_read) const;
+ virtual bool Close(HttpHandle handle) const;
+
+ private:
+ static DWORD MapAccessType(DWORD access_type);
+ static HINTERNET ToHINTERNET(HttpHandle handle);
+ static HttpHandle FromHINTERNET(HINTERNET handle);
+};
+
+bool WinHttpClient::CrackUrl(const TCHAR* url,
+ DWORD flags,
+ TCHAR* scheme,
+ size_t scheme_buffer_length,
+ TCHAR* host,
+ size_t host_buffer_length,
+ TCHAR* uri,
+ size_t uri_buffer_length,
+ int* port) const {
+ assert(url);
+ assert(scheme);
+ assert(host);
+ assert(uri);
+ assert(port);
+
+ URL_COMPONENTS url_comp = {0};
+ url_comp.dwStructSize = sizeof(url_comp);
+ url_comp.lpszScheme = scheme;
+ url_comp.dwSchemeLength = static_cast<DWORD>(scheme_buffer_length);
+ url_comp.lpszHostName = host;
+ url_comp.dwHostNameLength = static_cast<DWORD>(host_buffer_length);
+ url_comp.lpszUrlPath = uri;
+ url_comp.dwUrlPathLength = static_cast<DWORD>(uri_buffer_length);
+
+ bool result = !!::WinHttpCrackUrl(url, 0, flags, &url_comp);
+ if (result) {
+ *port = static_cast<int>(url_comp.nPort);
+ }
+ return result;
+}
+
+bool WinHttpClient::Open(const TCHAR* user_agent,
+ DWORD access_type,
+ const TCHAR* proxy_name,
+ const TCHAR* proxy_bypass,
+ HttpHandle* session_handle) const {
+ *session_handle = FromHINTERNET(::WinHttpOpen(user_agent,
+ MapAccessType(access_type),
+ proxy_name,
+ proxy_bypass,
+ 0));
+
+ return !!(*session_handle);
+}
+
+bool WinHttpClient::Connect(HttpHandle session_handle,
+ const TCHAR* server,
+ int port,
+ HttpHandle* connection_handle) const {
+ assert(server);
+
+ // Uses NULL user name and password to connect.
+ *connection_handle = FromHINTERNET(::WinHttpConnect(
+ ToHINTERNET(session_handle),
+ server,
+ static_cast<INTERNET_PORT>(port),
+ NULL));
+ return !!(*connection_handle);
+}
+
+bool WinHttpClient::OpenRequest(HttpHandle connection_handle,
+ const TCHAR* verb,
+ const TCHAR* uri,
+ const TCHAR* version,
+ const TCHAR* referrer,
+ bool is_secure,
+ HttpHandle* request_handle) const {
+ assert(connection_handle);
+ assert(verb);
+ assert(uri);
+ assert(request_handle);
+
+ *request_handle = FromHINTERNET(::WinHttpOpenRequest(
+ ToHINTERNET(connection_handle),
+ verb,
+ uri,
+ version,
+ referrer,
+ WINHTTP_DEFAULT_ACCEPT_TYPES,
+ is_secure ? WINHTTP_FLAG_SECURE : 0));
+ return !!(*request_handle);
+}
+
+bool WinHttpClient::SendRequest(HttpHandle request_handle,
+ const TCHAR* headers,
+ DWORD headers_length) const {
+ assert(request_handle);
+
+ return !!::WinHttpSendRequest(ToHINTERNET(request_handle),
+ headers,
+ headers_length,
+ NULL,
+ 0,
+ WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH,
+ NULL);
+}
+
+bool WinHttpClient::ReceiveResponse(HttpHandle request_handle) const {
+ assert(request_handle);
+
+ return !!::WinHttpReceiveResponse(ToHINTERNET(request_handle), NULL);
+}
+
+bool WinHttpClient::GetHttpStatusCode(HttpHandle request_handle,
+ int* status_code) const {
+ TCHAR http_status_string[4] = {0};
+ DWORD http_status_string_size = sizeof(http_status_string);
+ if (!::WinHttpQueryHeaders(ToHINTERNET(request_handle),
+ WINHTTP_QUERY_STATUS_CODE,
+ WINHTTP_HEADER_NAME_BY_INDEX,
+ static_cast<void*>(&http_status_string),
+ &http_status_string_size, 0)) {
+ return false;
+ }
+
+ *status_code = static_cast<DWORD>(_tcstol(http_status_string, NULL, 10));
+ return true;
+}
+
+bool WinHttpClient::GetContentLength(HttpHandle request_handle,
+ DWORD* content_length) const {
+ assert(request_handle);
+ assert(content_length);
+
+ TCHAR content_length_string[11] = {0};
+ DWORD content_length_string_size = sizeof(content_length_string);
+ if (!::WinHttpQueryHeaders(ToHINTERNET(request_handle),
+ WINHTTP_QUERY_CONTENT_LENGTH,
+ WINHTTP_HEADER_NAME_BY_INDEX,
+ static_cast<void*>(&content_length_string),
+ &content_length_string_size, 0)) {
+ *content_length = kUnknownContentLength;
+ } else {
+ *content_length =
+ static_cast<DWORD>(wcstol(content_length_string, NULL, 10));
+ }
+ return true;
+}
+
+bool WinHttpClient::ReadData(HttpHandle request_handle,
+ void* buffer,
+ DWORD buffer_length,
+ DWORD* bytes_read) const {
+ assert(request_handle);
+ assert(buffer);
+ assert(bytes_read);
+
+ DWORD bytes_read_local = 0;
+ if (!::WinHttpReadData(ToHINTERNET(request_handle),
+ buffer,
+ buffer_length,
+ &bytes_read_local)) {
+ return false;
+ }
+ *bytes_read = bytes_read_local;
+ return true;
+}
+
+bool WinHttpClient::Close(HttpHandle handle) const {
+ assert(handle);
+ return !!::WinHttpCloseHandle(ToHINTERNET(handle));
+}
+
+DWORD WinHttpClient::MapAccessType(DWORD access_type) {
+ switch (static_cast<AccessType>(access_type)) {
+ case ACCESS_TYPE_PRECONFIG:
+ default:
+ return WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
+ case ACCESS_TYPE_DIRECT:
+ return WINHTTP_ACCESS_TYPE_NO_PROXY;
+ case ACCESS_TYPE_PROXY:
+ return WINHTTP_ACCESS_TYPE_NAMED_PROXY;
+ }
+}
+
+
+HINTERNET WinHttpClient::ToHINTERNET(HttpHandle handle) {
+ return static_cast<HINTERNET>(handle);
+}
+
+HttpHandle WinHttpClient::FromHINTERNET(HINTERNET handle) {
+ return static_cast<HttpHandle>(handle);
+}
+
+} // namespace internal
+
+HttpClient* CreateWinHttpClient(const TCHAR* url) {
+ assert(url);
+
+ internal::WinHttpClient winhttp;
+ wchar_t scheme[16] = {0};
+ wchar_t host[256] = {0};
+ wchar_t path[256] = {0};
+ int port = 0;
+
+ if (!winhttp.CrackUrl(url,
+ 0,
+ scheme,
+ sizeof(scheme)/sizeof(scheme[0]),
+ host,
+ sizeof(host)/sizeof(host[0]),
+ path,
+ sizeof(path)/sizeof(path[0]),
+ &port)) {
+ return NULL;
+ }
+
+ 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 new internal::WinHttpClient();
+}
+
+} // namespace crash
diff --git a/src/tools/windows/converter_exe/winhttp_client.h b/src/tools/windows/converter_exe/winhttp_client.h
index 819d610f..4ccac7e0 100644
--- a/src/tools/windows/converter_exe/winhttp_client.h
+++ b/src/tools/windows/converter_exe/winhttp_client.h
@@ -1,40 +1,40 @@
-// Copyright 2019 Google Inc. All rights reserved.
-//
-// 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 Inc. 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.
-
-#ifndef TOOLS_WINDOWS_CONVERTER_EXE_WINHTTP_CLIENT_H_
-#define TOOLS_WINDOWS_CONVERTER_EXE_WINHTTP_CLIENT_H_
-
-#include "tools/windows/converter_exe/http_client.h"
-
-namespace crash {
-
-HttpClient* CreateWinHttpClient(const TCHAR* url);
-
-} // namespace crash
-
-#endif // TOOLS_WINDOWS_CONVERTER_EXE_WINHTTP_CLIENT_H_
+// Copyright 2019 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.
+
+#ifndef TOOLS_WINDOWS_CONVERTER_EXE_WINHTTP_CLIENT_H_
+#define TOOLS_WINDOWS_CONVERTER_EXE_WINHTTP_CLIENT_H_
+
+#include "tools/windows/converter_exe/http_client.h"
+
+namespace crash {
+
+HttpClient* CreateWinHttpClient(const TCHAR* url);
+
+} // namespace crash
+
+#endif // TOOLS_WINDOWS_CONVERTER_EXE_WINHTTP_CLIENT_H_
diff --git a/src/tools/windows/converter_exe/wininet_client.cc b/src/tools/windows/converter_exe/wininet_client.cc
index 3e542db2..90cf114c 100644
--- a/src/tools/windows/converter_exe/wininet_client.cc
+++ b/src/tools/windows/converter_exe/wininet_client.cc
@@ -1,278 +1,278 @@
-// Copyright 2019 Google Inc. All rights reserved.
-//
-// 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 Inc. 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.
-
-#include "tools/windows/converter_exe/wininet_client.h"
-
-#include <assert.h>
-#include <stdlib.h>
-#include <windows.h>
-#include <wininet.h>
-
-namespace crash {
-
-namespace internal {
-
-// This class implements HttpClient based on WinInet APIs.
-class WinInetClient : public HttpClient {
- public:
- virtual ~WinInetClient() {}
- virtual bool CrackUrl(const TCHAR* url,
- DWORD flags,
- TCHAR* scheme,
- size_t scheme_buffer_length,
- TCHAR* host,
- size_t host_buffer_length,
- TCHAR* uri,
- size_t uri_buffer_length,
- int* port) const;
- virtual bool Open(const TCHAR* user_agent,
- DWORD access_type,
- const TCHAR* proxy_name,
- const TCHAR* proxy_bypass,
- HttpHandle* session_handle) const;
- virtual bool Connect(HttpHandle session_handle,
- const TCHAR* server,
- int port,
- HttpHandle* connection_handle) const;
- virtual bool OpenRequest(HttpHandle connection_handle,
- const TCHAR* verb,
- const TCHAR* uri,
- const TCHAR* version,
- const TCHAR* referrer,
- bool is_secure,
- HttpHandle* request_handle) const;
- virtual bool SendRequest(HttpHandle request_handle,
- const TCHAR* headers,
- DWORD headers_length) const;
- virtual bool ReceiveResponse(HttpHandle request_handle) const;
- virtual bool GetHttpStatusCode(HttpHandle request_handle,
- int* status_code) const;
- virtual bool GetContentLength(HttpHandle request_handle,
- DWORD* content_length) const;
- virtual bool ReadData(HttpHandle request_handle,
- void* buffer,
- DWORD buffer_length,
- DWORD* bytes_read) const;
- virtual bool Close(HttpHandle handle) const;
-
- private:
- static DWORD MapAccessType(DWORD access_type);
- static HINTERNET ToHINTERNET(HttpHandle handle);
- static HttpHandle FromHINTERNET(HINTERNET handle);
-};
-
-bool WinInetClient::CrackUrl(const TCHAR* url,
- DWORD flags,
- TCHAR* scheme,
- size_t scheme_buffer_length,
- TCHAR* host,
- size_t host_buffer_length,
- TCHAR* uri,
- size_t uri_buffer_length,
- int* port) const {
- assert(url);
- assert(scheme);
- assert(host);
- assert(uri);
- assert(port);
-
- URL_COMPONENTS url_comp = {0};
- url_comp.dwStructSize = sizeof(url_comp);
- url_comp.lpszScheme = scheme;
- url_comp.dwSchemeLength = static_cast<DWORD>(scheme_buffer_length);
- url_comp.lpszHostName = host;
- url_comp.dwHostNameLength = static_cast<DWORD>(host_buffer_length);
- url_comp.lpszUrlPath = uri;
- url_comp.dwUrlPathLength = static_cast<DWORD>(uri_buffer_length);
-
- bool result = !!::InternetCrackUrl(url, 0, flags, &url_comp);
- if (result) {
- *port = static_cast<int>(url_comp.nPort);
- }
- return result;
-}
-
-bool WinInetClient::Open(const TCHAR* user_agent,
- DWORD access_type,
- const TCHAR* proxy_name,
- const TCHAR* proxy_bypass,
- HttpHandle* session_handle) const {
- *session_handle = FromHINTERNET(::InternetOpen(user_agent,
- MapAccessType(access_type),
- proxy_name,
- proxy_bypass,
- 0));
- return !!(*session_handle);
-}
-
-bool WinInetClient::Connect(HttpHandle session_handle,
- const TCHAR* server,
- int port,
- HttpHandle* connection_handle) const {
- assert(server);
-
- // Uses NULL user name and password to connect. Always uses http service.
- *connection_handle = FromHINTERNET(::InternetConnect(
- ToHINTERNET(session_handle),
- server,
- static_cast<INTERNET_PORT>(port),
- NULL,
- NULL,
- INTERNET_SERVICE_HTTP,
- 0,
- 0));
- return !!(*connection_handle);
-}
-
-bool WinInetClient::OpenRequest(HttpHandle connection_handle,
- const TCHAR* verb,
- const TCHAR* uri,
- const TCHAR* version,
- const TCHAR* referrer,
- bool is_secure,
- HttpHandle* request_handle) const {
- assert(connection_handle);
- assert(verb);
- assert(uri);
-
- *request_handle = FromHINTERNET(::HttpOpenRequest(
- ToHINTERNET(connection_handle),
- verb,
- uri,
- version,
- referrer,
- NULL,
- is_secure ? INTERNET_FLAG_SECURE : 0,
- NULL));
- return !!(*request_handle);
-}
-
-bool WinInetClient::SendRequest(HttpHandle request_handle,
- const TCHAR* headers,
- DWORD headers_length) const {
- assert(request_handle);
-
- return !!::HttpSendRequest(ToHINTERNET(request_handle),
- headers,
- headers_length,
- NULL,
- 0);
-}
-
-bool WinInetClient::ReceiveResponse(HttpHandle) const {
- return true;
-}
-
-bool WinInetClient::GetHttpStatusCode(HttpHandle request_handle,
- int* status_code) const {
- assert(request_handle);
-
- TCHAR http_status_string[4] = {0};
- DWORD http_status_string_size = sizeof(http_status_string);
- if (!::HttpQueryInfo(ToHINTERNET(request_handle),
- HTTP_QUERY_STATUS_CODE,
- static_cast<void *>(&http_status_string),
- &http_status_string_size,
- 0)) {
- return false;
- }
-
- *status_code = _tcstol(http_status_string, NULL, 10);
- return true;
-}
-
-bool WinInetClient::GetContentLength(HttpHandle request_handle,
- DWORD* content_length) const {
- assert(request_handle);
- assert(content_length);
-
- TCHAR content_length_string[11];
- DWORD content_length_string_size = sizeof(content_length_string);
- if (!::HttpQueryInfo(ToHINTERNET(request_handle),
- HTTP_QUERY_CONTENT_LENGTH,
- static_cast<void *>(&content_length_string),
- &content_length_string_size,
- 0)) {
- *content_length = kUnknownContentLength;
- } else {
- *content_length = wcstol(content_length_string, NULL, 10);
- }
- return true;
-}
-
-bool WinInetClient::ReadData(HttpHandle request_handle,
- void* buffer,
- DWORD buffer_length,
- DWORD* bytes_read) const {
- assert(request_handle);
- assert(buffer);
- assert(bytes_read);
-
- DWORD bytes_read_local = 0;
- if (!::InternetReadFile(ToHINTERNET(request_handle),
- buffer,
- buffer_length,
- &bytes_read_local)) {
- return false;
- }
- *bytes_read = bytes_read_local;
- return true;
-}
-
-bool WinInetClient::Close(HttpHandle handle) const {
- assert(handle);
- return !!::InternetCloseHandle(ToHINTERNET(handle));
-}
-
-DWORD WinInetClient::MapAccessType(DWORD access_type) {
- switch (static_cast<AccessType>(access_type)) {
- case ACCESS_TYPE_PRECONFIG:
- default:
- return INTERNET_OPEN_TYPE_PRECONFIG;
- case ACCESS_TYPE_DIRECT:
- return INTERNET_OPEN_TYPE_DIRECT;
- case ACCESS_TYPE_PROXY:
- return INTERNET_OPEN_TYPE_PROXY;
- }
-}
-
-HINTERNET WinInetClient::ToHINTERNET(HttpHandle handle) {
- return static_cast<HINTERNET>(handle);
-}
-
-HttpHandle WinInetClient::FromHINTERNET(HINTERNET handle) {
- return static_cast<HttpHandle>(handle);
-}
-
-} // namespace internal
-
-HttpClient* CreateWinInetClient(const TCHAR*) {
- return new internal::WinInetClient();
-}
-
-} // namespace crash
+// Copyright 2019 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.
+
+#include "tools/windows/converter_exe/wininet_client.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <windows.h>
+#include <wininet.h>
+
+namespace crash {
+
+namespace internal {
+
+// This class implements HttpClient based on WinInet APIs.
+class WinInetClient : public HttpClient {
+ public:
+ virtual ~WinInetClient() {}
+ virtual bool CrackUrl(const TCHAR* url,
+ DWORD flags,
+ TCHAR* scheme,
+ size_t scheme_buffer_length,
+ TCHAR* host,
+ size_t host_buffer_length,
+ TCHAR* uri,
+ size_t uri_buffer_length,
+ int* port) const;
+ virtual bool Open(const TCHAR* user_agent,
+ DWORD access_type,
+ const TCHAR* proxy_name,
+ const TCHAR* proxy_bypass,
+ HttpHandle* session_handle) const;
+ virtual bool Connect(HttpHandle session_handle,
+ const TCHAR* server,
+ int port,
+ HttpHandle* connection_handle) const;
+ virtual bool OpenRequest(HttpHandle connection_handle,
+ const TCHAR* verb,
+ const TCHAR* uri,
+ const TCHAR* version,
+ const TCHAR* referrer,
+ bool is_secure,
+ HttpHandle* request_handle) const;
+ virtual bool SendRequest(HttpHandle request_handle,
+ const TCHAR* headers,
+ DWORD headers_length) const;
+ virtual bool ReceiveResponse(HttpHandle request_handle) const;
+ virtual bool GetHttpStatusCode(HttpHandle request_handle,
+ int* status_code) const;
+ virtual bool GetContentLength(HttpHandle request_handle,
+ DWORD* content_length) const;
+ virtual bool ReadData(HttpHandle request_handle,
+ void* buffer,
+ DWORD buffer_length,
+ DWORD* bytes_read) const;
+ virtual bool Close(HttpHandle handle) const;
+
+ private:
+ static DWORD MapAccessType(DWORD access_type);
+ static HINTERNET ToHINTERNET(HttpHandle handle);
+ static HttpHandle FromHINTERNET(HINTERNET handle);
+};
+
+bool WinInetClient::CrackUrl(const TCHAR* url,
+ DWORD flags,
+ TCHAR* scheme,
+ size_t scheme_buffer_length,
+ TCHAR* host,
+ size_t host_buffer_length,
+ TCHAR* uri,
+ size_t uri_buffer_length,
+ int* port) const {
+ assert(url);
+ assert(scheme);
+ assert(host);
+ assert(uri);
+ assert(port);
+
+ URL_COMPONENTS url_comp = {0};
+ url_comp.dwStructSize = sizeof(url_comp);
+ url_comp.lpszScheme = scheme;
+ url_comp.dwSchemeLength = static_cast<DWORD>(scheme_buffer_length);
+ url_comp.lpszHostName = host;
+ url_comp.dwHostNameLength = static_cast<DWORD>(host_buffer_length);
+ url_comp.lpszUrlPath = uri;
+ url_comp.dwUrlPathLength = static_cast<DWORD>(uri_buffer_length);
+
+ bool result = !!::InternetCrackUrl(url, 0, flags, &url_comp);
+ if (result) {
+ *port = static_cast<int>(url_comp.nPort);
+ }
+ return result;
+}
+
+bool WinInetClient::Open(const TCHAR* user_agent,
+ DWORD access_type,
+ const TCHAR* proxy_name,
+ const TCHAR* proxy_bypass,
+ HttpHandle* session_handle) const {
+ *session_handle = FromHINTERNET(::InternetOpen(user_agent,
+ MapAccessType(access_type),
+ proxy_name,
+ proxy_bypass,
+ 0));
+ return !!(*session_handle);
+}
+
+bool WinInetClient::Connect(HttpHandle session_handle,
+ const TCHAR* server,
+ int port,
+ HttpHandle* connection_handle) const {
+ assert(server);
+
+ // Uses NULL user name and password to connect. Always uses http service.
+ *connection_handle = FromHINTERNET(::InternetConnect(
+ ToHINTERNET(session_handle),
+ server,
+ static_cast<INTERNET_PORT>(port),
+ NULL,
+ NULL,
+ INTERNET_SERVICE_HTTP,
+ 0,
+ 0));
+ return !!(*connection_handle);
+}
+
+bool WinInetClient::OpenRequest(HttpHandle connection_handle,
+ const TCHAR* verb,
+ const TCHAR* uri,
+ const TCHAR* version,
+ const TCHAR* referrer,
+ bool is_secure,
+ HttpHandle* request_handle) const {
+ assert(connection_handle);
+ assert(verb);
+ assert(uri);
+
+ *request_handle = FromHINTERNET(::HttpOpenRequest(
+ ToHINTERNET(connection_handle),
+ verb,
+ uri,
+ version,
+ referrer,
+ NULL,
+ is_secure ? INTERNET_FLAG_SECURE : 0,
+ NULL));
+ return !!(*request_handle);
+}
+
+bool WinInetClient::SendRequest(HttpHandle request_handle,
+ const TCHAR* headers,
+ DWORD headers_length) const {
+ assert(request_handle);
+
+ return !!::HttpSendRequest(ToHINTERNET(request_handle),
+ headers,
+ headers_length,
+ NULL,
+ 0);
+}
+
+bool WinInetClient::ReceiveResponse(HttpHandle) const {
+ return true;
+}
+
+bool WinInetClient::GetHttpStatusCode(HttpHandle request_handle,
+ int* status_code) const {
+ assert(request_handle);
+
+ TCHAR http_status_string[4] = {0};
+ DWORD http_status_string_size = sizeof(http_status_string);
+ if (!::HttpQueryInfo(ToHINTERNET(request_handle),
+ HTTP_QUERY_STATUS_CODE,
+ static_cast<void*>(&http_status_string),
+ &http_status_string_size,
+ 0)) {
+ return false;
+ }
+
+ *status_code = _tcstol(http_status_string, NULL, 10);
+ return true;
+}
+
+bool WinInetClient::GetContentLength(HttpHandle request_handle,
+ DWORD* content_length) const {
+ assert(request_handle);
+ assert(content_length);
+
+ TCHAR content_length_string[11];
+ DWORD content_length_string_size = sizeof(content_length_string);
+ if (!::HttpQueryInfo(ToHINTERNET(request_handle),
+ HTTP_QUERY_CONTENT_LENGTH,
+ static_cast<void*>(&content_length_string),
+ &content_length_string_size,
+ 0)) {
+ *content_length = kUnknownContentLength;
+ } else {
+ *content_length = wcstol(content_length_string, NULL, 10);
+ }
+ return true;
+}
+
+bool WinInetClient::ReadData(HttpHandle request_handle,
+ void* buffer,
+ DWORD buffer_length,
+ DWORD* bytes_read) const {
+ assert(request_handle);
+ assert(buffer);
+ assert(bytes_read);
+
+ DWORD bytes_read_local = 0;
+ if (!::InternetReadFile(ToHINTERNET(request_handle),
+ buffer,
+ buffer_length,
+ &bytes_read_local)) {
+ return false;
+ }
+ *bytes_read = bytes_read_local;
+ return true;
+}
+
+bool WinInetClient::Close(HttpHandle handle) const {
+ assert(handle);
+ return !!::InternetCloseHandle(ToHINTERNET(handle));
+}
+
+DWORD WinInetClient::MapAccessType(DWORD access_type) {
+ switch (static_cast<AccessType>(access_type)) {
+ case ACCESS_TYPE_PRECONFIG:
+ default:
+ return INTERNET_OPEN_TYPE_PRECONFIG;
+ case ACCESS_TYPE_DIRECT:
+ return INTERNET_OPEN_TYPE_DIRECT;
+ case ACCESS_TYPE_PROXY:
+ return INTERNET_OPEN_TYPE_PROXY;
+ }
+}
+
+HINTERNET WinInetClient::ToHINTERNET(HttpHandle handle) {
+ return static_cast<HINTERNET>(handle);
+}
+
+HttpHandle WinInetClient::FromHINTERNET(HINTERNET handle) {
+ return static_cast<HttpHandle>(handle);
+}
+
+} // namespace internal
+
+HttpClient* CreateWinInetClient(const TCHAR*) {
+ return new internal::WinInetClient();
+}
+
+} // namespace crash
diff --git a/src/tools/windows/converter_exe/wininet_client.h b/src/tools/windows/converter_exe/wininet_client.h
index bd04b605..8b4c61b5 100644
--- a/src/tools/windows/converter_exe/wininet_client.h
+++ b/src/tools/windows/converter_exe/wininet_client.h
@@ -1,40 +1,40 @@
-// Copyright 2019 Google Inc. All rights reserved.
-//
-// 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 Inc. 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.
-
-#ifndef TOOLS_WINDOWS_CONVERTER_EXE_WININET_CLIENT_H_
-#define TOOLS_WINDOWS_CONVERTER_EXE_WININET_CLIENT_H_
-
-#include "tools/windows/converter_exe/http_client.h"
-
-namespace crash {
-
-HttpClient* CreateWinInetClient(const TCHAR* url);
-
-} // namespace crash
-
-#endif // TOOLS_WINDOWS_CONVERTER_EXE_WININET_CLIENT_H_
+// Copyright 2019 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.
+
+#ifndef TOOLS_WINDOWS_CONVERTER_EXE_WININET_CLIENT_H_
+#define TOOLS_WINDOWS_CONVERTER_EXE_WININET_CLIENT_H_
+
+#include "tools/windows/converter_exe/http_client.h"
+
+namespace crash {
+
+HttpClient* CreateWinInetClient(const TCHAR* url);
+
+} // namespace crash
+
+#endif // TOOLS_WINDOWS_CONVERTER_EXE_WININET_CLIENT_H_
diff --git a/src/tools/windows/dump_syms/dump_syms.cc b/src/tools/windows/dump_syms/dump_syms.cc
index 5b7d1777..26c226a2 100644
--- a/src/tools/windows/dump_syms/dump_syms.cc
+++ b/src/tools/windows/dump_syms/dump_syms.cc
@@ -1,5 +1,4 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
+// Copyright 2006 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -11,7 +10,7 @@
// 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 Inc. nor the names of its
+// * 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.
//
@@ -33,35 +32,61 @@
#include <stdio.h>
#include <wchar.h>
+#include <memory>
#include <string>
#include "common/windows/pdb_source_line_writer.h"
#include "common/windows/pe_source_line_writer.h"
-using std::wstring;
using google_breakpad::PDBSourceLineWriter;
using google_breakpad::PESourceLineWriter;
using std::unique_ptr;
+using std::wstring;
+
+int usage(const wchar_t* self) {
+ fprintf(stderr, "Usage: %ws [--pe] [--i] <file.[pdb|exe|dll]>\n", self);
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr,
+ "--pe:\tRead debugging information from PE file and do "
+ "not attempt to locate matching PDB file.\n"
+ "\tThis is only supported for PE32+ (64 bit) PE files.\n");
+ fprintf(stderr,
+ "--i:\tOutput INLINE/INLINE_ORIGIN record\n"
+ "\tThis cannot be used with [--pe].\n");
+ return 1;
+}
-int wmain(int argc, wchar_t **argv) {
- bool success;
- if (argc == 2) {
- PDBSourceLineWriter pdb_writer;
- if (!pdb_writer.Open(wstring(argv[1]), PDBSourceLineWriter::ANY_FILE)) {
+int wmain(int argc, wchar_t** argv) {
+ bool success = false;
+ bool pe = false;
+ bool handle_inline = false;
+ int arg_index = 1;
+ while (arg_index < argc && wcslen(argv[arg_index]) > 0 &&
+ wcsncmp(L"--", argv[arg_index], 2) == 0) {
+ if (wcscmp(L"--pe", argv[arg_index]) == 0) {
+ pe = true;
+ } else if (wcscmp(L"--i", argv[arg_index]) == 0) {
+ handle_inline = true;
+ }
+ ++arg_index;
+ }
+
+ if ((pe && handle_inline) || arg_index == argc) {
+ usage(argv[0]);
+ return 1;
+ }
+
+ wchar_t* file_path = argv[arg_index];
+ if (pe) {
+ PESourceLineWriter pe_writer(file_path);
+ success = pe_writer.WriteSymbols(stdout);
+ } else {
+ PDBSourceLineWriter pdb_writer(handle_inline);
+ if (!pdb_writer.Open(wstring(file_path), PDBSourceLineWriter::ANY_FILE)) {
fprintf(stderr, "Open failed.\n");
return 1;
}
success = pdb_writer.WriteSymbols(stdout);
- } else if (argc == 3 && wcscmp(argv[1], L"--pe") == 0) {
- PESourceLineWriter pe_writer(argv[2]);
- success = pe_writer.WriteSymbols(stdout);
- } else {
- fprintf(stderr, "Usage: %ws [--pe] <file.[pdb|exe|dll]>\n", argv[0]);
- fprintf(stderr, "Options:\n");
- fprintf(stderr, "--pe:\tRead debugging information from PE file and do "
- "not attempt to locate matching PDB file.\n"
- "\tThis is only supported for PE32+ (64 bit) PE files.\n");
- return 1;
}
if (!success) {
diff --git a/src/tools/windows/dump_syms/dump_syms.gyp b/src/tools/windows/dump_syms/dump_syms.gyp
deleted file mode 100644
index b815574b..00000000
--- a/src/tools/windows/dump_syms/dump_syms.gyp
+++ /dev/null
@@ -1,64 +0,0 @@
-# Copyright 2013 Google Inc. All rights reserved.
-#
-# 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 Inc. 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.
-
-{
- 'includes': [
- '../../../build/common.gypi',
- ],
- 'targets': [
- {
- 'target_name': 'dump_syms',
- 'type': 'executable',
- 'sources': [
- 'dump_syms.cc',
- ],
- 'dependencies': [
- '../../../common/windows/common_windows.gyp:common_windows_lib',
- ],
- },
- {
- 'target_name': 'dump_syms_unittest',
- 'type': 'executable',
- 'sources': [
- 'dump_syms_unittest.cc',
- ],
- 'dependencies': [
- '<(DEPTH)/client/windows/unittests/testing.gyp:gmock',
- '<(DEPTH)/client/windows/unittests/testing.gyp:gtest',
- 'dump_syms',
- ],
- 'msvs_settings': {
- 'VCLinkerTool': {
- 'AdditionalDependencies': [
- 'shell32.lib',
- ],
- },
- },
- },
- ],
-}
diff --git a/src/tools/windows/dump_syms/dump_syms_unittest.cc b/src/tools/windows/dump_syms/dump_syms_unittest.cc
index 766e5c09..97dc5c9b 100644
--- a/src/tools/windows/dump_syms/dump_syms_unittest.cc
+++ b/src/tools/windows/dump_syms/dump_syms_unittest.cc
@@ -1,244 +1,244 @@
-// Copyright 2003 Google Inc. All rights reserved.
-//
-// 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 Inc. 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.
-
-#include <Windows.h>
-#include <shellapi.h>
-
-#include <string>
-#include <utility>
-
-#include "breakpad_googletest_includes.h"
-
-namespace tools {
-namespace windows {
-namespace dump_syms {
-
-namespace {
-
-// Root names of PDB and dumped symbol files to be regression tested. These are
-// specified in complexity of the resulting dumped symbol files.
-const wchar_t* kRootNames[] = {
- // A PDB file with no OMAP data.
- L"dump_syms_regtest",
- // A PDB file with OMAP data for an image that has been function-level
- // reordered.
- L"omap_reorder_funcs",
- // A PDB file with OMAP data for an image that had new content injected, all
- // of it with source data.
- L"omap_stretched_filled",
- // A PDB file with OMAP data for an image that had new content injected, but
- // without source data.
- L"omap_stretched",
- // A PDB file with OMAP data for an image that has been basic block reordered.
- L"omap_reorder_bbs",
- // A 64bit PDB file with no OMAP data.
- L"dump_syms_regtest64",
-};
-
-const wchar_t* kPEOnlyRootNames[] = {
- L"pe_only_symbol_test",
-};
-
-void TrimLastComponent(const std::wstring& path,
- std::wstring* trimmed,
- std::wstring* component) {
- size_t len = path.size();
- while (len > 0 && path[len - 1] != '\\')
- --len;
-
- if (component != NULL)
- component->assign(path.c_str() + len, path.c_str() + path.size());
-
- while (len > 0 && path[len - 1] == '\\')
- --len;
-
- if (trimmed != NULL)
- trimmed->assign(path.c_str(), len);
-}
-
-// Get the directory of the current executable.
-bool GetSelfDirectory(std::wstring* self_dir) {
- std::wstring command_line = GetCommandLineW();
-
- int num_args = 0;
- wchar_t** args = NULL;
- args = ::CommandLineToArgvW(command_line.c_str(), &num_args);
- if (args == NULL)
- return false;
-
- *self_dir = args[0];
- TrimLastComponent(*self_dir, self_dir, NULL);
-
- return true;
-}
-
-void RunCommand(const std::wstring& command_line,
- std::string* stdout_string) {
- // Create a PIPE for the child process stdout.
- HANDLE child_stdout_read = 0;
- HANDLE child_stdout_write = 0;
- SECURITY_ATTRIBUTES sec_attr_stdout = {};
- sec_attr_stdout.nLength = sizeof(sec_attr_stdout);
- sec_attr_stdout.bInheritHandle = TRUE;
- ASSERT_TRUE(::CreatePipe(&child_stdout_read, &child_stdout_write,
- &sec_attr_stdout, 0));
- ASSERT_TRUE(::SetHandleInformation(child_stdout_read, HANDLE_FLAG_INHERIT,
- 0));
-
- // Create a PIPE for the child process stdin.
- HANDLE child_stdin_read = 0;
- HANDLE child_stdin_write = 0;
- SECURITY_ATTRIBUTES sec_attr_stdin = {};
- sec_attr_stdin.nLength = sizeof(sec_attr_stdin);
- sec_attr_stdin.bInheritHandle = TRUE;
- ASSERT_TRUE(::CreatePipe(&child_stdin_read, &child_stdin_write,
- &sec_attr_stdin, 0));
- ASSERT_TRUE(::SetHandleInformation(child_stdin_write, HANDLE_FLAG_INHERIT,
- 0));
-
- // Startup the child.
- STARTUPINFO startup_info = {};
- PROCESS_INFORMATION process_info = {};
- startup_info.cb = sizeof(STARTUPINFO);
- startup_info.hStdError = NULL;
- 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,
- &startup_info, &process_info));
-
- // Collect the output.
- ASSERT_TRUE(::CloseHandle(child_stdout_write));
- char buffer[4096] = {};
- DWORD bytes_read = 0;
- while (::ReadFile(child_stdout_read, buffer, sizeof(buffer), &bytes_read,
- NULL) && bytes_read > 0) {
- stdout_string->append(buffer, bytes_read);
- }
-
- // Wait for the process to finish.
- ::WaitForSingleObject(process_info.hProcess, INFINITE);
-
- // Shut down all of our handles.
- ASSERT_TRUE(::CloseHandle(process_info.hThread));
- ASSERT_TRUE(::CloseHandle(process_info.hProcess));
- ASSERT_TRUE(::CloseHandle(child_stdin_write));
- ASSERT_TRUE(::CloseHandle(child_stdin_read));
- ASSERT_TRUE(::CloseHandle(child_stdout_read));
-}
-
-void GetFileContents(const std::wstring& path, std::string* content) {
- FILE* f = ::_wfopen(path.c_str(), L"rb");
- ASSERT_TRUE(f != NULL);
-
- char buffer[4096] = {};
- while (true) {
- size_t bytes_read = ::fread(buffer, 1, sizeof(buffer), f);
- if (bytes_read == 0)
- break;
- content->append(buffer, bytes_read);
- }
-}
-
-class DumpSymsRegressionTest : public testing::TestWithParam<const wchar_t *> {
- public:
- virtual void SetUp() {
- std::wstring self_dir;
- ASSERT_TRUE(GetSelfDirectory(&self_dir));
- dump_syms_exe = self_dir + L"\\dump_syms.exe";
-
- TrimLastComponent(self_dir, &testdata_dir, NULL);
- testdata_dir += L"\\testdata";
- }
-
- std::wstring dump_syms_exe;
- std::wstring testdata_dir;
-};
-
-class DumpSymsPEOnlyRegressionTest : public testing::TestWithParam<const wchar_t *> {
-public:
- virtual void SetUp() {
- std::wstring self_dir;
- ASSERT_TRUE(GetSelfDirectory(&self_dir));
- dump_syms_exe = self_dir + L"\\dump_syms.exe";
-
- TrimLastComponent(self_dir, &testdata_dir, NULL);
- testdata_dir += L"\\testdata";
- }
-
- std::wstring dump_syms_exe;
- std::wstring testdata_dir;
-};
-
-} //namespace
-
-TEST_P(DumpSymsRegressionTest, EnsureDumpedSymbolsMatch) {
- const wchar_t* root_name = GetParam();
- std::wstring root_path = testdata_dir + L"\\" + root_name;
-
- std::wstring sym_path = root_path + L".sym";
- std::string expected_symbols;
- ASSERT_NO_FATAL_FAILURE(GetFileContents(sym_path, &expected_symbols));
-
- std::wstring pdb_path = root_path + L".pdb";
- std::wstring command_line = L"\"" + dump_syms_exe + L"\" \"" +
- pdb_path + L"\"";
- std::string symbols;
- ASSERT_NO_FATAL_FAILURE(RunCommand(command_line, &symbols));
-
- EXPECT_EQ(expected_symbols, symbols);
-}
-
-INSTANTIATE_TEST_CASE_P(DumpSyms, DumpSymsRegressionTest,
- testing::ValuesIn(kRootNames));
-
-TEST_P(DumpSymsPEOnlyRegressionTest, EnsurePEOnlyDumpedSymbolsMatch) {
- const wchar_t* root_name = GetParam();
- std::wstring root_path = testdata_dir + L"\\" + root_name;
-
- std::wstring sym_path = root_path + L".sym";
- std::string expected_symbols;
- ASSERT_NO_FATAL_FAILURE(GetFileContents(sym_path, &expected_symbols));
-
- std::wstring dll_path = root_path + L".dll";
- std::wstring command_line = L"\"" + dump_syms_exe + L"\" --pe \"" +
- dll_path + L"\"";
- std::string symbols;
- ASSERT_NO_FATAL_FAILURE(RunCommand(command_line, &symbols));
-
- EXPECT_EQ(expected_symbols, symbols);
-}
-
-INSTANTIATE_TEST_CASE_P(PEOnlyDumpSyms, DumpSymsPEOnlyRegressionTest,
- testing::ValuesIn(kPEOnlyRootNames));
-
-
-} // namespace dump_syms
-} // namespace windows
-} // namespace tools
+// Copyright 2003 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.
+
+#include <Windows.h>
+#include <shellapi.h>
+
+#include <string>
+#include <utility>
+
+#include "breakpad_googletest_includes.h"
+
+namespace tools {
+namespace windows {
+namespace dump_syms {
+
+namespace {
+
+// Root names of PDB and dumped symbol files to be regression tested. These are
+// specified in complexity of the resulting dumped symbol files.
+const wchar_t* kRootNames[] = {
+ // A PDB file with no OMAP data.
+ L"dump_syms_regtest",
+ // A PDB file with OMAP data for an image that has been function-level
+ // reordered.
+ L"omap_reorder_funcs",
+ // A PDB file with OMAP data for an image that had new content injected, all
+ // of it with source data.
+ L"omap_stretched_filled",
+ // A PDB file with OMAP data for an image that had new content injected, but
+ // without source data.
+ L"omap_stretched",
+ // A PDB file with OMAP data for an image that has been basic block reordered.
+ L"omap_reorder_bbs",
+ // A 64bit PDB file with no OMAP data.
+ L"dump_syms_regtest64",
+};
+
+const wchar_t* kPEOnlyRootNames[] = {
+ L"pe_only_symbol_test",
+};
+
+void TrimLastComponent(const std::wstring& path,
+ std::wstring* trimmed,
+ std::wstring* component) {
+ size_t len = path.size();
+ while (len > 0 && path[len - 1] != '\\')
+ --len;
+
+ if (component != NULL)
+ component->assign(path.c_str() + len, path.c_str() + path.size());
+
+ while (len > 0 && path[len - 1] == '\\')
+ --len;
+
+ if (trimmed != NULL)
+ trimmed->assign(path.c_str(), len);
+}
+
+// Get the directory of the current executable.
+bool GetSelfDirectory(std::wstring* self_dir) {
+ std::wstring command_line = GetCommandLineW();
+
+ int num_args = 0;
+ wchar_t** args = NULL;
+ args = ::CommandLineToArgvW(command_line.c_str(), &num_args);
+ if (args == NULL)
+ return false;
+
+ *self_dir = args[0];
+ TrimLastComponent(*self_dir, self_dir, NULL);
+
+ return true;
+}
+
+void RunCommand(const std::wstring& command_line,
+ std::string* stdout_string) {
+ // Create a PIPE for the child process stdout.
+ HANDLE child_stdout_read = 0;
+ HANDLE child_stdout_write = 0;
+ SECURITY_ATTRIBUTES sec_attr_stdout = {};
+ sec_attr_stdout.nLength = sizeof(sec_attr_stdout);
+ sec_attr_stdout.bInheritHandle = TRUE;
+ ASSERT_TRUE(::CreatePipe(&child_stdout_read, &child_stdout_write,
+ &sec_attr_stdout, 0));
+ ASSERT_TRUE(::SetHandleInformation(child_stdout_read, HANDLE_FLAG_INHERIT,
+ 0));
+
+ // Create a PIPE for the child process stdin.
+ HANDLE child_stdin_read = 0;
+ HANDLE child_stdin_write = 0;
+ SECURITY_ATTRIBUTES sec_attr_stdin = {};
+ sec_attr_stdin.nLength = sizeof(sec_attr_stdin);
+ sec_attr_stdin.bInheritHandle = TRUE;
+ ASSERT_TRUE(::CreatePipe(&child_stdin_read, &child_stdin_write,
+ &sec_attr_stdin, 0));
+ ASSERT_TRUE(::SetHandleInformation(child_stdin_write, HANDLE_FLAG_INHERIT,
+ 0));
+
+ // Startup the child.
+ STARTUPINFO startup_info = {};
+ PROCESS_INFORMATION process_info = {};
+ startup_info.cb = sizeof(STARTUPINFO);
+ startup_info.hStdError = NULL;
+ 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,
+ &startup_info, &process_info));
+
+ // Collect the output.
+ ASSERT_TRUE(::CloseHandle(child_stdout_write));
+ char buffer[4096] = {};
+ DWORD bytes_read = 0;
+ while (::ReadFile(child_stdout_read, buffer, sizeof(buffer), &bytes_read,
+ NULL) && bytes_read > 0) {
+ stdout_string->append(buffer, bytes_read);
+ }
+
+ // Wait for the process to finish.
+ ::WaitForSingleObject(process_info.hProcess, INFINITE);
+
+ // Shut down all of our handles.
+ ASSERT_TRUE(::CloseHandle(process_info.hThread));
+ ASSERT_TRUE(::CloseHandle(process_info.hProcess));
+ ASSERT_TRUE(::CloseHandle(child_stdin_write));
+ ASSERT_TRUE(::CloseHandle(child_stdin_read));
+ ASSERT_TRUE(::CloseHandle(child_stdout_read));
+}
+
+void GetFileContents(const std::wstring& path, std::string* content) {
+ FILE* f = ::_wfopen(path.c_str(), L"rb");
+ ASSERT_TRUE(f != NULL);
+
+ char buffer[4096] = {};
+ while (true) {
+ size_t bytes_read = ::fread(buffer, 1, sizeof(buffer), f);
+ if (bytes_read == 0)
+ break;
+ content->append(buffer, bytes_read);
+ }
+}
+
+class DumpSymsRegressionTest : public testing::TestWithParam<const wchar_t*> {
+ public:
+ virtual void SetUp() {
+ std::wstring self_dir;
+ ASSERT_TRUE(GetSelfDirectory(&self_dir));
+ dump_syms_exe = self_dir + L"\\dump_syms.exe";
+
+ TrimLastComponent(self_dir, &testdata_dir, NULL);
+ testdata_dir += L"\\testdata";
+ }
+
+ std::wstring dump_syms_exe;
+ std::wstring testdata_dir;
+};
+
+class DumpSymsPEOnlyRegressionTest : public testing::TestWithParam<const wchar_t*> {
+public:
+ virtual void SetUp() {
+ std::wstring self_dir;
+ ASSERT_TRUE(GetSelfDirectory(&self_dir));
+ dump_syms_exe = self_dir + L"\\dump_syms.exe";
+
+ TrimLastComponent(self_dir, &testdata_dir, NULL);
+ testdata_dir += L"\\testdata";
+ }
+
+ std::wstring dump_syms_exe;
+ std::wstring testdata_dir;
+};
+
+} //namespace
+
+TEST_P(DumpSymsRegressionTest, EnsureDumpedSymbolsMatch) {
+ const wchar_t* root_name = GetParam();
+ std::wstring root_path = testdata_dir + L"\\" + root_name;
+
+ std::wstring sym_path = root_path + L".sym";
+ std::string expected_symbols;
+ ASSERT_NO_FATAL_FAILURE(GetFileContents(sym_path, &expected_symbols));
+
+ std::wstring pdb_path = root_path + L".pdb";
+ std::wstring command_line = L"\"" + dump_syms_exe + L"\" \"" +
+ pdb_path + L"\"";
+ std::string symbols;
+ ASSERT_NO_FATAL_FAILURE(RunCommand(command_line, &symbols));
+
+ EXPECT_EQ(expected_symbols, symbols);
+}
+
+INSTANTIATE_TEST_SUITE_P(DumpSyms, DumpSymsRegressionTest,
+ testing::ValuesIn(kRootNames));
+
+TEST_P(DumpSymsPEOnlyRegressionTest, EnsurePEOnlyDumpedSymbolsMatch) {
+ const wchar_t* root_name = GetParam();
+ std::wstring root_path = testdata_dir + L"\\" + root_name;
+
+ std::wstring sym_path = root_path + L".sym";
+ std::string expected_symbols;
+ ASSERT_NO_FATAL_FAILURE(GetFileContents(sym_path, &expected_symbols));
+
+ std::wstring dll_path = root_path + L".dll";
+ std::wstring command_line = L"\"" + dump_syms_exe + L"\" --pe \"" +
+ dll_path + L"\"";
+ std::string symbols;
+ ASSERT_NO_FATAL_FAILURE(RunCommand(command_line, &symbols));
+
+ EXPECT_EQ(expected_symbols, symbols);
+}
+
+INSTANTIATE_TEST_SUITE_P(PEOnlyDumpSyms, DumpSymsPEOnlyRegressionTest,
+ testing::ValuesIn(kPEOnlyRootNames));
+
+
+} // namespace dump_syms
+} // namespace windows
+} // namespace tools
diff --git a/src/tools/windows/dump_syms/run_regtest.sh b/src/tools/windows/dump_syms/run_regtest.sh
index 1f20f64f..2401edd1 100755
--- a/src/tools/windows/dump_syms/run_regtest.sh
+++ b/src/tools/windows/dump_syms/run_regtest.sh
@@ -1,7 +1,6 @@
#!/bin/sh
-# Copyright (c) 2006, Google Inc.
-# All rights reserved.
+# Copyright 2006 Google LLC
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
@@ -13,7 +12,7 @@
# 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 Inc. nor the names of its
+# * 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.
#
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 e8efbeb8..442676ba 100644
--- a/src/tools/windows/dump_syms/testdata/dump_syms_regtest.cc
+++ b/src/tools/windows/dump_syms/testdata/dump_syms_regtest.cc
@@ -1,5 +1,4 @@
-// Copyright (c) 2007, Google Inc.
-// All rights reserved.
+// Copyright 2007 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -11,7 +10,7 @@
// 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 Inc. nor the names of its
+// * 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.
//
@@ -48,7 +47,7 @@ class C {
void f() { member_ = g(); }
virtual int g() { return 2; }
- static char* h(const C &that) { return 0; }
+ static char* h(const C& that) { return 0; }
private:
int member_;
@@ -60,12 +59,12 @@ static int i() {
} // namespace google_breakpad
-int main(int argc, char **argv) {
+int main(int argc, char** argv) {
google_breakpad::C object;
object.set_member(google_breakpad::i());
object.f();
int value = object.g();
- char *nothing = object.h(object);
+ char* nothing = object.h(object);
return 0;
}
diff --git a/src/tools/windows/symupload/symupload.cc b/src/tools/windows/symupload/symupload.cc
index 7e302932..65123a28 100644
--- a/src/tools/windows/symupload/symupload.cc
+++ b/src/tools/windows/symupload/symupload.cc
@@ -1,5 +1,4 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
+// Copyright 2006 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -11,7 +10,7 @@
// 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 Inc. nor the names of its
+// * 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.
//
@@ -56,24 +55,23 @@
#include "common/windows/http_upload.h"
#include "common/windows/pdb_source_line_writer.h"
+#include "common/windows/sym_upload_v2_protocol.h"
#include "common/windows/symbol_collector_client.h"
-using std::string;
-using std::wstring;
-using std::vector;
-using std::map;
using google_breakpad::HTTPUpload;
-using google_breakpad::SymbolCollectorClient;
-using google_breakpad::SymbolStatus;
-using google_breakpad::UploadUrlResponse;
-using google_breakpad::CompleteUploadResult;
using google_breakpad::PDBModuleInfo;
using google_breakpad::PDBSourceLineWriter;
using google_breakpad::WindowsStringUtils;
+using std::map;
+using std::string;
+using std::vector;
+using std::wstring;
+
+const wchar_t* kSymbolUploadTypeBreakpad = L"BREAKPAD";
// Extracts the file version information for the given filename,
// as a string, for example, "1.2.3.4". Returns true on success.
-static bool GetFileVersionString(const wchar_t *filename, wstring *version) {
+static bool GetFileVersionString(const wchar_t* filename, wstring* version) {
DWORD handle;
DWORD version_size = GetFileVersionInfoSize(filename, &handle);
if (version_size < sizeof(VS_FIXEDFILEINFO)) {
@@ -85,7 +83,7 @@ static bool GetFileVersionString(const wchar_t *filename, wstring *version) {
return false;
}
- void *file_info_buffer = NULL;
+ void* file_info_buffer = NULL;
unsigned int file_info_length;
if (!VerQueryValue(&version_info[0], L"\\",
&file_info_buffer, &file_info_length)) {
@@ -95,7 +93,7 @@ static bool GetFileVersionString(const wchar_t *filename, wstring *version) {
// The maximum value of each version component is 65535 (0xffff),
// so the max length is 24, including the terminating null.
wchar_t ver_string[24];
- VS_FIXEDFILEINFO *file_info =
+ VS_FIXEDFILEINFO* file_info =
reinterpret_cast<VS_FIXEDFILEINFO*>(file_info_buffer);
swprintf(ver_string, sizeof(ver_string) / sizeof(ver_string[0]),
L"%d.%d.%d.%d",
@@ -114,10 +112,11 @@ static bool GetFileVersionString(const wchar_t *filename, wstring *version) {
// Creates a new temporary file and writes the symbol data from the given
// exe/dll file to it. Returns the path to the temp file in temp_file_path
// and information about the pdb in pdb_info.
-static bool DumpSymbolsToTempFile(const wchar_t *file,
- wstring *temp_file_path,
- PDBModuleInfo *pdb_info) {
- google_breakpad::PDBSourceLineWriter writer;
+static bool DumpSymbolsToTempFile(const wchar_t* file,
+ wstring* temp_file_path,
+ PDBModuleInfo* pdb_info,
+ bool handle_inline) {
+ google_breakpad::PDBSourceLineWriter writer(handle_inline);
// Use EXE_FILE to get information out of the exe/dll in addition to the
// pdb. The name and version number of the exe/dll are of value, and
// there's no way to locate an exe/dll given a pdb.
@@ -135,7 +134,7 @@ static bool DumpSymbolsToTempFile(const wchar_t *file,
return false;
}
- FILE *temp_file = NULL;
+ FILE* temp_file = NULL;
#if _MSC_VER >= 1400 // MSVC 2005/8
if (_wfopen_s(&temp_file, temp_filename, L"w") != 0)
#else // _MSC_VER >= 1400
@@ -159,97 +158,12 @@ static bool DumpSymbolsToTempFile(const wchar_t *file,
return writer.GetModuleInfo(pdb_info);
}
-static bool DoSymUploadV2(
- const wchar_t* api_url,
- const wchar_t* api_key,
- const wstring& debug_file,
- const wstring& debug_id,
- const wstring& symbol_file,
- bool force) {
- wstring url(api_url);
- wstring key(api_key);
-
- if (!force) {
- SymbolStatus symbolStatus = SymbolCollectorClient::CheckSymbolStatus(
- url,
- key,
- debug_file,
- debug_id);
- if (symbolStatus == SymbolStatus::Found) {
- wprintf(L"Symbol file already exists, upload aborted."
- L" Use \"-f\" to overwrite.\n");
- return true;
- }
- else if (symbolStatus == SymbolStatus::Unknown) {
- wprintf(L"Failed to get check for existing symbol.\n");
- return false;
- }
- }
-
- UploadUrlResponse uploadUrlResponse;
- if (!SymbolCollectorClient::CreateUploadUrl(
- url,
- key,
- &uploadUrlResponse)) {
- wprintf(L"Failed to create upload URL.\n");
- return false;
- }
-
- wstring signed_url = uploadUrlResponse.upload_url;
- wstring upload_key = uploadUrlResponse.upload_key;
- wstring response;
- int response_code;
- bool success = HTTPUpload::SendPutRequest(
- signed_url,
- symbol_file,
- /* timeout = */ NULL,
- &response,
- &response_code);
- if (!success) {
- wprintf(L"Failed to send symbol file.\n");
- wprintf(L"Response code: %ld\n", response_code);
- wprintf(L"Response:\n");
- wprintf(L"%s\n", response.c_str());
- return false;
- }
- else if (response_code == 0) {
- wprintf(L"Failed to send symbol file: No response code\n");
- return false;
- }
- else if (response_code != 200) {
- wprintf(L"Failed to send symbol file: Response code %ld\n", response_code);
- wprintf(L"Response:\n");
- wprintf(L"%s\n", response.c_str());
- return false;
- }
-
- CompleteUploadResult completeUploadResult =
- SymbolCollectorClient::CompleteUpload(
- url,
- key,
- upload_key,
- debug_file,
- debug_id);
- if (completeUploadResult == CompleteUploadResult::Error) {
- wprintf(L"Failed to complete upload.\n");
- return false;
- }
- else if (completeUploadResult == CompleteUploadResult::DuplicateData) {
- wprintf(L"Uploaded file checksum matched existing file checksum,"
- L" no change necessary.\n");
- }
- else {
- wprintf(L"Successfully sent the symbol file.\n");
- }
-
- return true;
-}
-
__declspec(noreturn) void printUsageAndExit() {
wprintf(L"Usage:\n\n"
- L" symupload [--timeout NN] [--product product_name] ^\n"
+ L" symupload [--i] [--timeout NN] [--product product_name] ^\n"
L" <file.exe|file.dll> <symbol upload URL> ^\n"
L" [...<symbol upload URLs>]\n\n");
+ wprintf(L" - i: Extract inline information from pdb.\n");
wprintf(L" - Timeout is in milliseconds, or can be 0 to be unlimited.\n");
wprintf(L" - product_name is an HTTP-friendly product name. It must only\n"
L" contain an ascii subset: alphanumeric and punctuation.\n"
@@ -270,9 +184,10 @@ __declspec(noreturn) void printUsageAndExit() {
exit(0);
}
-int wmain(int argc, wchar_t *argv[]) {
- const wchar_t *module;
- const wchar_t *product = nullptr;
+int wmain(int argc, wchar_t* argv[]) {
+ const wchar_t* module;
+ const wchar_t* product = nullptr;
+ bool handle_inline = false;
int timeout = -1;
int currentarg = 1;
bool use_sym_upload_v2 = false;
@@ -280,6 +195,11 @@ int wmain(int argc, wchar_t *argv[]) {
const wchar_t* api_url = nullptr;
const wchar_t* api_key = nullptr;
while (argc > currentarg + 1) {
+ if (!wcscmp(L"--i", argv[currentarg])) {
+ handle_inline = true;
+ ++currentarg;
+ continue;
+ }
if (!wcscmp(L"--timeout", argv[currentarg])) {
timeout = _wtoi(argv[currentarg + 1]);
currentarg += 2;
@@ -310,7 +230,7 @@ int wmain(int argc, wchar_t *argv[]) {
wstring symbol_file;
PDBModuleInfo pdb_info;
- if (!DumpSymbolsToTempFile(module, &symbol_file, &pdb_info)) {
+ if (!DumpSymbolsToTempFile(module, &symbol_file, &pdb_info, handle_inline)) {
fwprintf(stderr, L"Could not get symbol data from %s\n", module);
return 1;
}
@@ -329,14 +249,12 @@ int wmain(int argc, wchar_t *argv[]) {
if (argc >= currentarg + 2) {
api_url = argv[currentarg++];
api_key = argv[currentarg++];
+ wstring product_name = product ? wstring(product) : L"";
- success = DoSymUploadV2(
- api_url,
- api_key,
- pdb_info.debug_file,
- pdb_info.debug_identifier,
- symbol_file,
- force);
+ success = google_breakpad::SymUploadV2ProtocolSend(
+ api_url, api_key, timeout == -1 ? nullptr : &timeout,
+ pdb_info.debug_file, pdb_info.debug_identifier, symbol_file,
+ kSymbolUploadTypeBreakpad, product_name, force);
} else {
printUsageAndExit();
}
diff --git a/src/tools/windows/symupload/symupload.gyp b/src/tools/windows/symupload/symupload.gyp
deleted file mode 100644
index 4567a4bd..00000000
--- a/src/tools/windows/symupload/symupload.gyp
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright 2013 Google Inc. All rights reserved.
-#
-# 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 Inc. 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.
-
-{
- 'includes': [
- '../../../build/common.gypi',
- ],
- 'targets': [
- {
- 'target_name': 'symupload',
- 'type': 'executable',
- 'sources': [
- 'symupload.cc',
- ],
- 'dependencies': [
- '../../../common/windows/common_windows.gyp:common_windows_lib',
- ],
- 'msvs_settings': {
- 'VCLinkerTool': {
- 'LargeAddressAware': '2',
- },
- },
- },
- ],
-}
diff --git a/src/tools/windows/tools_windows.gyp b/src/tools/windows/tools_windows.gyp
deleted file mode 100644
index 17b88b4a..00000000
--- a/src/tools/windows/tools_windows.gyp
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright 2017 Google Inc. All rights reserved.
-#
-# 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 Inc. 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.
-
-
-{
- 'includes': [
- '../../build/common.gypi',
- ],
- 'targets': [
- {
- 'target_name': 'build_all',
- 'type': 'none',
- 'dependencies': [
- './converter/ms_symbol_server_converter.gyp:*',
- './converter_exe/converter.gyp:*',
- './dump_syms/dump_syms.gyp:*',
- './symupload/symupload.gyp:*',
- ],
- },
- ],
-}