From 5fa0202f29377392a0856a8d02eac9af57e0f909 Mon Sep 17 00:00:00 2001 From: Tom Stuart & Jon Leighton Date: Mon, 18 Jun 2012 22:35:38 +0100 Subject: [PATCH] Add breakpad support for Mac This provides support for compiling the breakpad client into PhantomJS, and generifies that Linux packaging scripts so that they also apply to OS X and automate the symbol generation. Building the Breakpad tool programs seems to be less than straightforward on OS X, and documentation is poor. We have managed to produce tools/dump-syms-mac.pro which allows building the dump_syms program for dumping the debugging symbols. This needed a couple of modifications to breakpad in order to compile successfully. We have run out of time to work on making the minidump_stackwalk program build. However, this is solely a developer tool and so it can wait until after the 1.6 release before we complete this work. Testing is welcome! https://code.google.com/p/phantomjs/issues/detail?id=576 --- .gitignore | 1 + deploy/README.md | 8 +- deploy/build-and-package.sh | 37 ++- deploy/package-linux-dynamic.sh | 92 ------ deploy/package.sh | 104 ++++++ .../client/mac/handler/minidump_generator.h | 3 - src/breakpad/src/common/mac/stabs_reader.cc | 312 ++++++++++++++++++ src/main.cpp | 6 + src/phantomjs.pro | 29 +- tools/dump-symbols.sh | 19 +- tools/dump-syms-mac.pro | 23 ++ 11 files changed, 520 insertions(+), 114 deletions(-) delete mode 100755 deploy/package-linux-dynamic.sh create mode 100755 deploy/package.sh create mode 100644 src/breakpad/src/common/mac/stabs_reader.cc create mode 100644 tools/dump-syms-mac.pro diff --git a/.gitignore b/.gitignore index e1725423..b889a298 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ debian/*/ # ignore ctags /tags +tools/dump_syms.app/ diff --git a/deploy/README.md b/deploy/README.md index 71288289..60bc7b3f 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -51,4 +51,10 @@ again to ensure a clean state. (Or SSH in and do a git clean.) Packaging for OS X ------------------ -TODO +Run `deploy/build-and-package.sh`. That's it. + +However, if you have previously built the sources in release mode, you +should clean your tree to make sure all the debugging symbols gets +compiled: + + $ make clean && cd src/qt && make clean && cd ../.. diff --git a/deploy/build-and-package.sh b/deploy/build-and-package.sh index df0f0476..4978453c 100755 --- a/deploy/build-and-package.sh +++ b/deploy/build-and-package.sh @@ -2,23 +2,43 @@ cd `dirname $0`/.. +echo "Building Qt and PhantomJS in debug mode. If you have previously" \ + "built in release mode, you should run:" +echo +echo " $ make clean && cd src/qt && make clean && cd ../.." +echo + +# Build the project ./build.sh --qt-config "-debug -webkit-debug" || exit 1 -rm deploy/*.tar.bz2 -./deploy/package-linux-dynamic.sh || exit 1 +# Package the release tarball +rm deploy/*.tar.bz2 2>/dev/null +./deploy/package.sh || exit 1 -pushd src/breakpad -./configure && make || exit 1 -popd +# Build the dump_syms program for dumping breakpad debugging symbols +if [[ $OSTYPE = darwin* ]]; then + pushd tools + ../src/qt/bin/qmake dump-syms-mac.pro + popd +else + pushd src/breakpad + ./configure && make || exit 1 + popd +fi + +# Dump and package the breakpad debugging symbols... ./tools/dump-symbols.sh # The minidump_stackwalk program is architecture-specific, so copy the # binary for later use. This means that e.g. a developer on x86_64 can # analyse a crash dump produced by a i686 user. -cp src/breakpad/src/processor/minidump_stackwalk symbols/ +# +# We don't yet have a process for building minidump_stackwalk on OS X +if [[ $OSTYPE != darwin* ]]; then + cp src/breakpad/src/processor/minidump_stackwalk symbols/ -read -r -d '' README < symbols/README + echo "$README" > symbols/README +fi tar -cjf $(ls deploy/*.bz2 | sed 's/\.tar\.bz2/-symbols.tar.bz2/') symbols/ diff --git a/deploy/package-linux-dynamic.sh b/deploy/package-linux-dynamic.sh deleted file mode 100755 index 503f1701..00000000 --- a/deploy/package-linux-dynamic.sh +++ /dev/null @@ -1,92 +0,0 @@ -#!/bin/bash - -# -# usage: just run this script (after having run build.sh) -# and deploy the created tarball to your target machine. -# -# It creates a phantomjs-$version folder and copies the binary, -# example, license etc. together with all shared library dependencies -# to that folder. Furthermore brandelf is used to make the lib -# and binary compatible with older unix/linux machines that don't -# know the new Linux ELF ABI. -# - -cd $(dirname $0) - -if [[ ! -f ../bin/phantomjs ]]; then - echo "phantomjs was not built yet, please run build.sh first" - exit 1 -fi - -# get version -version=$(../bin/phantomjs --version | sed 's/ /-/' | sed 's/[()]//g') - -echo "creating quasi-static deployable phantomjs $version" - -if [[ ! -f brandelf ]]; then - echo - echo "brandelf executable not found in current dir" - echo -n "compiling it now..." - g++ brandelf.c -o brandelf || exit 1 - echo "done" -fi - -src=.. -dest="phantomjs-$version-linux-$(uname -m)-dynamic" - -rm -Rf $dest{.tar.bz2,} &> /dev/null -mkdir -p $dest/bin $dest/lib - -echo - -echo -n "copying files..." -cp $src/bin/phantomjs $dest/bin -cp -r $src/{ChangeLog,examples,LICENSE.BSD,README.md} $dest/ -echo "done" - -echo - -echo -n "copying shared libs..." -libld= -for l in $(ldd $dest/bin/phantomjs | egrep -o "/[^ ]+ "); do - if [[ "$l" != "" ]]; then - ll=$(basename $l) - cp $l $dest/lib/$ll - # ensure OS ABI compatibility - ./brandelf -t SVR4 $dest/lib/$ll - if [[ "$l" == *"ld-linux"* ]]; then - libld=$ll - fi - fi -done -echo "done" - -echo - -# strip to reduce file size -echo -n "stripping binary and libs..." -strip -s $dest/lib/* $dest/bin/* -echo "done" - -echo - -echo -n "writing run script..." -# write run scripts -mv $dest/bin/phantomjs $dest/bin/phantomjs.bin -run=$dest/bin/phantomjs -echo '#!/bin/sh' >> $run -echo 'path=$(dirname $(dirname $(readlink -f $0)))' >> $run -echo 'export LD_LIBRARY_PATH=$path/lib' >> $run -echo 'exec $path/lib/'$libld' $path/bin/phantomjs.bin $@' >> $run -chmod +x $run -echo "done" - -echo - -echo -n "creating tarball..." -tar -cjf $dest{.tar.bz2,} -echo "done" - -echo - -echo "you can now deploy $dest or $dest.tar.bz2" diff --git a/deploy/package.sh b/deploy/package.sh new file mode 100755 index 00000000..65576124 --- /dev/null +++ b/deploy/package.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +# +# usage: just run this script (after having run build.sh) +# and deploy the created tarball to your target machine. +# +# It creates a phantomjs-$version folder and copies the binary, +# example, license etc. together with all shared library dependencies +# to that folder. Furthermore brandelf is used to make the lib +# and binary compatible with older unix/linux machines that don't +# know the new Linux ELF ABI. +# + +cd $(dirname $0) + +if [[ ! -f ../bin/phantomjs ]]; then + echo "phantomjs was not built yet, please run build.sh first" + exit 1 +fi + +version=$(../bin/phantomjs --version | sed 's/ /-/' | sed 's/[()]//g') +src=.. + +echo "packaging phantomjs $version" + +if [[ $OSTYPE = darwin* ]]; then + dest="phantomjs-$version-macosx-static" +else + if [[ ! -f brandelf ]]; then + echo + echo "brandelf executable not found in current dir" + echo -n "compiling it now..." + g++ brandelf.c -o brandelf || exit 1 + echo "done" + fi + + dest="phantomjs-$version-linux-$(uname -m)-dynamic" +fi + +rm -Rf $dest{.tar.bz2,} &> /dev/null +mkdir -p $dest/bin + +if [[ $OSTYPE != darwin* ]]; then + mkdir -p $dest/lib +fi + +echo + +echo -n "copying files..." +cp $src/bin/phantomjs $dest/bin +cp -r $src/{ChangeLog,examples,LICENSE.BSD,README.md} $dest/ +echo "done" +echo + +if [[ $OSTYPE != darwin* ]]; then + echo -n "copying shared libs..." + libld= + for l in $(ldd $dest/bin/phantomjs | egrep -o "/[^ ]+ "); do + if [[ "$l" != "" ]]; then + ll=$(basename $l) + cp $l $dest/lib/$ll + # ensure OS ABI compatibility + ./brandelf -t SVR4 $dest/lib/$ll + if [[ "$l" == *"ld-linux"* ]]; then + libld=$ll + fi + fi + done + echo "done" + echo +fi + +# strip to reduce file size +echo -n "stripping binary and libs..." + +if [[ $OSTYPE = darwin* ]]; then + strip -x $dest/bin/* +else + strip -s $dest/lib/* $dest/bin/* +fi + +echo "done" +echo + +if [[ $OSTYPE != darwin* ]]; then + echo -n "writing run script..." + # write run scripts + mv $dest/bin/phantomjs $dest/bin/phantomjs.bin + run=$dest/bin/phantomjs + echo '#!/bin/sh' >> $run + echo 'path=$(dirname $(dirname $(readlink -f $0)))' >> $run + echo 'export LD_LIBRARY_PATH=$path/lib' >> $run + echo 'exec $path/lib/'$libld' $path/bin/phantomjs.bin $@' >> $run + chmod +x $run + echo "done" + echo +fi + +echo -n "creating tarball..." +tar -cjf $dest{.tar.bz2,} +echo "done" +echo + +echo "you can now deploy $dest or $dest.tar.bz2" diff --git a/src/breakpad/src/client/mac/handler/minidump_generator.h b/src/breakpad/src/client/mac/handler/minidump_generator.h index 80bb116c..90dbaf2f 100644 --- a/src/breakpad/src/client/mac/handler/minidump_generator.h +++ b/src/breakpad/src/client/mac/handler/minidump_generator.h @@ -45,9 +45,6 @@ #include "dynamic_images.h" #include "mach_vm_compat.h" -#if !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7) - #define HAS_PPC_SUPPORT -#endif #if defined(__arm__) #define HAS_ARM_SUPPORT #elif defined(__i386__) || defined(__x86_64__) diff --git a/src/breakpad/src/common/mac/stabs_reader.cc b/src/breakpad/src/common/mac/stabs_reader.cc new file mode 100644 index 00000000..30003a41 --- /dev/null +++ b/src/breakpad/src/common/mac/stabs_reader.cc @@ -0,0 +1,312 @@ +// 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. + +// Original author: Jim Blandy + +// This file implements the google_breakpad::StabsReader class. +// See stabs_reader.h. + +#include "common/stabs_reader.h" + +#include +#include +#define N_UNDF 0x0 /* undefined */ +#include + +using std::vector; + +namespace google_breakpad { + +StabsReader::EntryIterator::EntryIterator(const ByteBuffer *buffer, + bool big_endian, size_t value_size) + : value_size_(value_size), cursor_(buffer, big_endian) { + // Actually, we could handle weird sizes just fine, but they're + // probably mistakes --- expressed in bits, say. + assert(value_size == 4 || value_size == 8); + entry_.index = 0; + Fetch(); +} + +void StabsReader::EntryIterator::Fetch() { + cursor_ + .Read(4, false, &entry_.name_offset) + .Read(1, false, &entry_.type) + .Read(1, false, &entry_.other) + .Read(2, false, &entry_.descriptor) + .Read(value_size_, false, &entry_.value); + entry_.at_end = !cursor_; +} + +StabsReader::StabsReader(const uint8_t *stab, size_t stab_size, + const uint8_t *stabstr, size_t stabstr_size, + bool big_endian, size_t value_size, bool unitized, + StabsHandler *handler) + : entries_(stab, stab_size), + strings_(stabstr, stabstr_size), + iterator_(&entries_, big_endian, value_size), + unitized_(unitized), + handler_(handler), + string_offset_(0), + next_cu_string_offset_(0), + current_source_file_(NULL) { } + +const char *StabsReader::SymbolString() { + ptrdiff_t offset = string_offset_ + iterator_->name_offset; + if (offset < 0 || (size_t) offset >= strings_.Size()) { + handler_->Warning("symbol %d: name offset outside the string section\n", + iterator_->index); + // Return our null string, to keep our promise about all names being + // taken from the string section. + offset = 0; + } + return reinterpret_cast(strings_.start + offset); +} + +bool StabsReader::Process() { + while (!iterator_->at_end) { + if (iterator_->type == N_SO) { + if (! ProcessCompilationUnit()) + return false; + } else if (iterator_->type == N_UNDF && unitized_) { + // In unitized STABS (including Linux STABS, and pretty much anything + // else that puts STABS data in sections), at the head of each + // compilation unit's entries there is an N_UNDF stab giving the + // number of symbols in the compilation unit, and the number of bytes + // that compilation unit's strings take up in the .stabstr section. + // Each CU's strings are separate; the n_strx values are offsets + // within the current CU's portion of the .stabstr section. + // + // As an optimization, the GNU linker combines all the + // compilation units into one, with a single N_UNDF at the + // beginning. However, other linkers, like Gold, do not perform + // this optimization. + string_offset_ = next_cu_string_offset_; + next_cu_string_offset_ = iterator_->value; + ++iterator_; + } +#if defined(HAVE_MACH_O_NLIST_H) + // Export symbols in Mach-O binaries look like this. + // This is necessary in order to be able to dump symbols + // from OS X system libraries. + else if ((iterator_->type & N_STAB) == 0 && + (iterator_->type & N_TYPE) == N_SECT) { + ProcessExtern(); + } +#endif + else { + ++iterator_; + } + } + return true; +} + +bool StabsReader::ProcessCompilationUnit() { + assert(!iterator_->at_end && iterator_->type == N_SO); + + // There may be an N_SO entry whose name ends with a slash, + // indicating the directory in which the compilation occurred. + // The build directory defaults to NULL. + const char *build_directory = NULL; + { + const char *name = SymbolString(); + if (name[0] && name[strlen(name) - 1] == '/') { + build_directory = name; + ++iterator_; + } + } + + // We expect to see an N_SO entry with a filename next, indicating + // the start of the compilation unit. + { + if (iterator_->at_end || iterator_->type != N_SO) + return true; + const char *name = SymbolString(); + if (name[0] == '\0') { + // This seems to be a stray end-of-compilation-unit marker; + // consume it, but don't report the end, since we didn't see a + // beginning. + ++iterator_; + return true; + } + current_source_file_ = name; + } + + if (! handler_->StartCompilationUnit(current_source_file_, + iterator_->value, + build_directory)) + return false; + + ++iterator_; + + // The STABS documentation says that some compilers may emit + // additional N_SO entries with names immediately following the + // first, and that they should be ignored. However, the original + // Breakpad STABS reader doesn't ignore them, so we won't either. + + // Process the body of the compilation unit, up to the next N_SO. + while (!iterator_->at_end && iterator_->type != N_SO) { + if (iterator_->type == N_FUN) { + if (! ProcessFunction()) + return false; + } else if (iterator_->type == N_SLINE) { + // Mac OS X STABS place SLINE records before functions. + Line line; + // The value of an N_SLINE entry that appears outside a function is + // the absolute address of the line. + line.address = iterator_->value; + line.filename = current_source_file_; + // The n_desc of a N_SLINE entry is the line number. It's a + // signed 16-bit field; line numbers from 32768 to 65535 are + // stored as n-65536. + line.number = (uint16_t) iterator_->descriptor; + queued_lines_.push_back(line); + ++iterator_; + } else if (iterator_->type == N_SOL) { + current_source_file_ = SymbolString(); + ++iterator_; + } else { + // Ignore anything else. + ++iterator_; + } + } + + // An N_SO with an empty name indicates the end of the compilation + // unit. Default to zero. + uint64_t ending_address = 0; + if (!iterator_->at_end) { + assert(iterator_->type == N_SO); + const char *name = SymbolString(); + if (name[0] == '\0') { + ending_address = iterator_->value; + ++iterator_; + } + } + + if (! handler_->EndCompilationUnit(ending_address)) + return false; + + queued_lines_.clear(); + + return true; +} + +bool StabsReader::ProcessFunction() { + assert(!iterator_->at_end && iterator_->type == N_FUN); + + uint64_t function_address = iterator_->value; + // The STABS string for an N_FUN entry is the name of the function, + // followed by a colon, followed by type information for the + // function. We want to pass the name alone to StartFunction. + const char *stab_string = SymbolString(); + const char *name_end = strchr(stab_string, ':'); + if (! name_end) + name_end = stab_string + strlen(stab_string); + std::string name(stab_string, name_end - stab_string); + if (! handler_->StartFunction(name, function_address)) + return false; + ++iterator_; + + // If there were any SLINE records given before the function, report them now. + for (vector::const_iterator it = queued_lines_.begin(); + it != queued_lines_.end(); it++) { + if (!handler_->Line(it->address, it->filename, it->number)) + return false; + } + queued_lines_.clear(); + + while (!iterator_->at_end) { + if (iterator_->type == N_SO || iterator_->type == N_FUN) + break; + else if (iterator_->type == N_SLINE) { + // The value of an N_SLINE entry is the offset of the line from + // the function's start address. + uint64_t line_address = function_address + iterator_->value; + // The n_desc of a N_SLINE entry is the line number. It's a + // signed 16-bit field; line numbers from 32768 to 65535 are + // stored as n-65536. + uint16_t line_number = iterator_->descriptor; + if (! handler_->Line(line_address, current_source_file_, line_number)) + return false; + ++iterator_; + } else if (iterator_->type == N_SOL) { + current_source_file_ = SymbolString(); + ++iterator_; + } else + // Ignore anything else. + ++iterator_; + } + + // We've reached the end of the function. See if we can figure out its + // ending address. + uint64_t ending_address = 0; + if (!iterator_->at_end) { + assert(iterator_->type == N_SO || iterator_->type == N_FUN); + if (iterator_->type == N_FUN) { + const char *symbol_name = SymbolString(); + if (symbol_name[0] == '\0') { + // An N_FUN entry with no name is a terminator for this function; + // its value is the function's size. + ending_address = function_address + iterator_->value; + ++iterator_; + } else { + // An N_FUN entry with a name is the next function, and we can take + // its value as our ending address. Don't advance the iterator, as + // we'll use this symbol to start the next function as well. + ending_address = iterator_->value; + } + } else { + // An N_SO entry could be an end-of-compilation-unit marker, or the + // start of the next compilation unit, but in either case, its value + // is our ending address. We don't advance the iterator; + // ProcessCompilationUnit will decide what to do with this symbol. + ending_address = iterator_->value; + } + } + + if (! handler_->EndFunction(ending_address)) + return false; + + return true; +} + +bool StabsReader::ProcessExtern() { +#if defined(HAVE_MACH_O_NLIST_H) + assert(!iterator_->at_end && + (iterator_->type & N_STAB) == 0 && + (iterator_->type & N_TYPE) == N_SECT); +#endif + + // TODO(mark): only do symbols in the text section? + if (!handler_->Extern(SymbolString(), iterator_->value)) + return false; + + ++iterator_; + return true; +} + +} // namespace google_breakpad diff --git a/src/main.cpp b/src/main.cpp index 4f32be67..789019ad 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -35,6 +35,9 @@ #ifdef Q_OS_LINUX #include "client/linux/handler/exception_handler.h" #endif +#ifdef Q_OS_MAC +#include "client/mac/handler/exception_handler.h" +#endif #include @@ -47,6 +50,9 @@ int main(int argc, char** argv, const char** envp) #ifdef Q_OS_LINUX google_breakpad::ExceptionHandler eh("/tmp", NULL, Utils::exceptionHandler, NULL, true); #endif +#ifdef Q_OS_MAC + google_breakpad::ExceptionHandler eh("/tmp", NULL, Utils::exceptionHandler, NULL, true, NULL); +#endif QApplication app(argc, argv); Phantom phantom; diff --git a/src/phantomjs.pro b/src/phantomjs.pro index d439882b..1b9c471b 100644 --- a/src/phantomjs.pro +++ b/src/phantomjs.pro @@ -55,25 +55,44 @@ include(gif/gif.pri) include(mongoose/mongoose.pri) include(linenoise/linenoise.pri) -linux* { +linux*|mac { INCLUDEPATH += breakpad/src + SOURCES += breakpad/src/client/minidump_file_writer.cc \ + breakpad/src/common/convert_UTF.c \ + breakpad/src/common/md5.cc \ + breakpad/src/common/string_conversion.cc +} + +linux* { SOURCES += breakpad/src/client/linux/crash_generation/crash_generation_client.cc \ breakpad/src/client/linux/handler/exception_handler.cc \ breakpad/src/client/linux/log/log.cc \ breakpad/src/client/linux/minidump_writer/linux_dumper.cc \ breakpad/src/client/linux/minidump_writer/linux_ptrace_dumper.cc \ breakpad/src/client/linux/minidump_writer/minidump_writer.cc \ - breakpad/src/client/minidump_file_writer.cc \ - breakpad/src/common/convert_UTF.c \ - breakpad/src/common/md5.cc \ - breakpad/src/common/string_conversion.cc \ breakpad/src/common/linux/file_id.cc \ breakpad/src/common/linux/guid_creator.cc \ breakpad/src/common/linux/memory_mapped_file.cc \ breakpad/src/common/linux/safe_readlink.cc } +mac { + SOURCES += breakpad/src/client/mac/crash_generation/crash_generation_client.cc \ + breakpad/src/client/mac/handler/exception_handler.cc \ + breakpad/src/client/mac/handler/minidump_generator.cc \ + breakpad/src/client/mac/handler/dynamic_images.cc \ + breakpad/src/client/mac/handler/breakpad_nlist_64.cc \ + breakpad/src/common/mac/bootstrap_compat.cc \ + breakpad/src/common/mac/file_id.cc \ + breakpad/src/common/mac/macho_id.cc \ + breakpad/src/common/mac/macho_utilities.cc \ + breakpad/src/common/mac/macho_walker.cc \ + breakpad/src/common/mac/string_utilities.cc + + OBJECTIVE_SOURCES += breakpad/src/common/mac/MachIPC.mm +} + win32: RC_FILE = phantomjs_win.rc os2: RC_FILE = phantomjs_os2.rc diff --git a/tools/dump-symbols.sh b/tools/dump-symbols.sh index 3348f674..6fc28252 100755 --- a/tools/dump-symbols.sh +++ b/tools/dump-symbols.sh @@ -16,14 +16,23 @@ rm -r symbols/* files="" files+="bin/phantomjs " -files+="src/qt/lib/libQtCore.so.4.8.0 " -files+="src/qt/lib/libQtWebKit.so.4.9.0 " -files+="src/qt/lib/libQtGui.so.4.8.0 " -files+="src/qt/lib/libQtNetwork.so.4.8.0" + +if [[ $OSTYPE = darwin* ]]; then + # To compile this program, run ../src/qt/bin/qmake dump-syms-mac.pro && make from tools/ + dump_syms="tools/dump_syms.app/Contents/MacOS/dump_syms" +else + files+="src/qt/lib/libQtCore.so.4.8.0 " + files+="src/qt/lib/libQtWebKit.so.4.9.0 " + files+="src/qt/lib/libQtGui.so.4.8.0 " + files+="src/qt/lib/libQtNetwork.so.4.8.0" + + # To compile this program, run ./configure && make from src/breakpad/ + dump_syms="src/breakpad/src/tools/linux/dump_syms/dump_syms" +fi for file in $files; do name=`basename $file` - src/breakpad/src/tools/linux/dump_syms/dump_syms $file > $name.sym + $dump_syms $file > $name.sym dir=symbols/$name/`head -n1 $name.sym | cut -d ' ' -f 4` mkdir -p $dir mv $name.sym $dir diff --git a/tools/dump-syms-mac.pro b/tools/dump-syms-mac.pro new file mode 100644 index 00000000..7f4ed5e0 --- /dev/null +++ b/tools/dump-syms-mac.pro @@ -0,0 +1,23 @@ +INCLUDEPATH += ../src/breakpad/src + +OBJECTIVE_SOURCES += ../src/breakpad/src/tools/mac/dump_syms/dump_syms_tool.mm \ + ../src/breakpad/src/common/mac/dump_syms.mm + +SOURCES += ../src/breakpad/src/common/module.cc \ + ../src/breakpad/src/common/dwarf/dwarf2diehandler.cc \ + ../src/breakpad/src/common/dwarf/bytereader.cc \ + ../src/breakpad/src/common/stabs_to_module.cc \ + ../src/breakpad/src/common/mac/stabs_reader.cc \ + ../src/breakpad/src/common/dwarf_cu_to_module.cc \ + ../src/breakpad/src/common/dwarf_cfi_to_module.cc \ + ../src/breakpad/src/common/dwarf_line_to_module.cc \ + ../src/breakpad/src/common/language.cc \ + ../src/breakpad/src/common/md5.cc \ + ../src/breakpad/src/common/mac/macho_reader.cc \ + ../src/breakpad/src/common/mac/file_id.cc \ + ../src/breakpad/src/common/mac/macho_id.cc \ + ../src/breakpad/src/common/mac/macho_utilities.cc \ + ../src/breakpad/src/common/mac/macho_walker.cc \ + ../src/breakpad/src/common/dwarf/dwarf2reader.cc + +TARGET = dump_syms