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