# HG changeset patch # User Wolfgang Rosenauer # Date 1262780379 -3600 # Node ID 3a1561dda105b1741d47e5fa0aded91ab1d78c88 # Parent 6ee6583389c7f029fdee3adc374d0cf055d89b02 Patch mozilla-central breakpad code into 1.9.2 Wrap translation package preambles into %ifs for consistency diff -r 6ee6583389c7 -r 3a1561dda105 mozilla-breakpad-update.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mozilla-breakpad-update.patch Wed Jan 06 13:19:39 2010 +0100 @@ -0,0 +1,65765 @@ +diff --git a/profile/dirserviceprovider/src/nsProfileLock.cpp b/profile/dirserviceprovider/src/nsProfileLock.cpp +--- a/profile/dirserviceprovider/src/nsProfileLock.cpp ++++ b/profile/dirserviceprovider/src/nsProfileLock.cpp +@@ -154,17 +154,18 @@ void nsProfileLock::RemovePidLockFiles() + static struct sigaction SIGHUP_oldact; + static struct sigaction SIGINT_oldact; + static struct sigaction SIGQUIT_oldact; + static struct sigaction SIGILL_oldact; + static struct sigaction SIGABRT_oldact; + static struct sigaction SIGSEGV_oldact; + static struct sigaction SIGTERM_oldact; + +-void nsProfileLock::FatalSignalHandler(int signo) ++void nsProfileLock::FatalSignalHandler(int signo, siginfo_t *info, ++ void *context) + { + // Remove any locks still held. + RemovePidLockFiles(); + + // Chain to the old handler, which may exit. + struct sigaction *oldact = nsnull; + + switch (signo) { +@@ -206,16 +207,20 @@ void nsProfileLock::FatalSignalHandler(i + sigset_t unblock_sigs; + sigemptyset(&unblock_sigs); + sigaddset(&unblock_sigs, signo); + + sigprocmask(SIG_UNBLOCK, &unblock_sigs, NULL); + + raise(signo); + } ++ else if (oldact->sa_sigaction && ++ (oldact->sa_flags & SA_SIGINFO) == SA_SIGINFO) { ++ oldact->sa_sigaction(signo, info, context); ++ } + else if (oldact->sa_handler && oldact->sa_handler != SIG_IGN) + { + oldact->sa_handler(signo); + } + } + + // Backstop exit call, just in case. + _exit(signo); +@@ -382,18 +387,18 @@ nsresult nsProfileLock::LockWithSymlink( + // Clean up on normal termination. + atexit(RemovePidLockFiles); + + // Clean up on abnormal termination, using POSIX sigaction. + // Don't arm a handler if the signal is being ignored, e.g., + // because mozilla is run via nohup. + if (!sDisableSignalHandling) { + struct sigaction act, oldact; +- act.sa_handler = FatalSignalHandler; +- act.sa_flags = 0; ++ act.sa_sigaction = FatalSignalHandler; ++ act.sa_flags = SA_SIGINFO; + sigfillset(&act.sa_mask); + + #define CATCH_SIGNAL(signame) \ + PR_BEGIN_MACRO \ + if (sigaction(signame, NULL, &oldact) == 0 && \ + oldact.sa_handler != SIG_IGN) \ + { \ + sigaction(signame, &act, &signame##_oldact); \ +diff --git a/profile/dirserviceprovider/src/nsProfileLock.h b/profile/dirserviceprovider/src/nsProfileLock.h +--- a/profile/dirserviceprovider/src/nsProfileLock.h ++++ b/profile/dirserviceprovider/src/nsProfileLock.h +@@ -50,16 +50,17 @@ class nsIProfileUnlocker; + + #if defined (XP_OS2) + #define INCL_DOSERRORS + #define INCL_DOSFILEMGR + #include + #endif + + #if defined (XP_UNIX) ++#include + #include "prclist.h" + #endif + + class nsProfileLock + #if defined (XP_UNIX) + : public PRCList + #endif + { +@@ -87,17 +88,18 @@ private: + PRPackedBool mHaveLock; + + #if defined (XP_WIN) + HANDLE mLockFileHandle; + #elif defined (XP_OS2) + LHANDLE mLockFileHandle; + #elif defined (XP_UNIX) + static void RemovePidLockFiles(); +- static void FatalSignalHandler(int signo); ++ static void FatalSignalHandler(int signo, siginfo_t *info, ++ void *context); + static PRCList mPidLockList; + + nsresult LockWithFcntl(const nsACString& lockFilePath); + + /** + * @param aHaveFcntlLock if true, we've already acquired an fcntl lock so this + * lock is merely an "obsolete" lock to keep out old Firefoxes + */ +diff --git a/toolkit/crashreporter/Makefile.in b/toolkit/crashreporter/Makefile.in +--- a/toolkit/crashreporter/Makefile.in ++++ b/toolkit/crashreporter/Makefile.in +@@ -77,16 +77,17 @@ endif + ifeq ($(OS_ARCH),Linux) + # there's no define for this normally + DEFINES += -DXP_LINUX + DIRS += \ + google-breakpad/src/common \ + google-breakpad/src/common/linux \ + google-breakpad/src/client \ + google-breakpad/src/client/linux/handler \ ++ google-breakpad/src/client/linux/minidump_writer \ + google-breakpad/src/tools/linux/dump_syms \ + $(NULL) + endif + + ifeq ($(OS_ARCH),SunOS) + # there's no define for this normally + DEFINES += -DXP_SOLARIS + DIRS += \ +diff --git a/toolkit/crashreporter/client/Makefile.in b/toolkit/crashreporter/client/Makefile.in +--- a/toolkit/crashreporter/client/Makefile.in ++++ b/toolkit/crashreporter/client/Makefile.in +@@ -80,29 +80,27 @@ endif + ifeq ($(OS_ARCH),Linux) + CPPSRCS += crashreporter_linux.cpp + LIBS += \ + $(DEPTH)/toolkit/crashreporter/google-breakpad/src/common/linux/$(LIB_PREFIX)breakpad_linux_common_s.$(LIB_SUFFIX) \ + $(NULL) + LOCAL_INCLUDES += -I$(srcdir) + OS_CXXFLAGS += $(MOZ_GTK2_CFLAGS) $(MOZ_GTHREAD_CFLAGS) + OS_LIBS += $(MOZ_GTK2_LIBS) $(MOZ_GTHREAD_LIBS) +-CPPSRCS += http_upload.cc + FORCE_USE_PIC=1 + endif + + ifeq ($(OS_ARCH),SunOS) + CPPSRCS += crashreporter_linux.cpp + LIBS += \ + $(DEPTH)/toolkit/crashreporter/google-breakpad/src/common/solaris/$(LIB_PREFIX)breakpad_solaris_common_s.$(LIB_SUFFIX) \ + $(NULL) + LOCAL_INCLUDES += -I$(srcdir) + OS_CXXFLAGS += $(MOZ_GTK2_CFLAGS) $(MOZ_GTHREAD_CFLAGS) + OS_LIBS += $(MOZ_GTK2_LIBS) $(MOZ_GTHREAD_LIBS) +-CPPSRCS += http_upload.cc + FORCE_USE_PIC=1 + endif + + include $(topsrcdir)/config/rules.mk + + ifeq ($(OS_ARCH),Darwin) + libs:: + $(NSINSTALL) -D $(DIST)/bin/crashreporter.app +@@ -110,14 +108,11 @@ libs:: + sed -e "s/%APP_NAME%/$(MOZ_APP_DISPLAYNAME)/" $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | \ + iconv -f UTF-8 -t UTF-16 > $(DIST)/bin/crashreporter.app/Contents/Resources/English.lproj/InfoPlist.strings + $(NSINSTALL) -D $(DIST)/bin/crashreporter.app/Contents/MacOS + $(NSINSTALL) $(DIST)/bin/crashreporter $(DIST)/bin/crashreporter.app/Contents/MacOS + rm -f $(DIST)/bin/crashreporter + endif + + ifeq (,$(filter-out Linux SunOS,$(OS_ARCH))) +-export:: $(srcdir)/../google-breakpad/src/common/linux/http_upload.cc +- $(INSTALL) $^ . +- + libs:: $(topsrcdir)/toolkit/themes/winstripe/global/throbber/Throbber-small.gif + $(INSTALL) $^ $(DIST)/bin + endif +diff --git a/toolkit/crashreporter/google-breakpad/Makefile.am b/toolkit/crashreporter/google-breakpad/Makefile.am +--- a/toolkit/crashreporter/google-breakpad/Makefile.am ++++ b/toolkit/crashreporter/google-breakpad/Makefile.am +@@ -90,16 +90,18 @@ src_libbreakpad_la_SOURCES = \ + src/processor/range_map.h \ + src/processor/scoped_ptr.h \ + src/processor/simple_symbol_supplier.cc \ + src/processor/simple_symbol_supplier.h \ + src/processor/stack_frame_info.h \ + src/processor/stackwalker.cc \ + src/processor/stackwalker_amd64.cc \ + src/processor/stackwalker_amd64.h \ ++ src/processor/stackwalker_arm.cc \ ++ src/processor/stackwalker_arm.h \ + src/processor/stackwalker_ppc.cc \ + src/processor/stackwalker_ppc.h \ + src/processor/stackwalker_sparc.cc \ + src/processor/stackwalker_sparc.h \ + src/processor/stackwalker_x86.cc \ + src/processor/stackwalker_x86.h + + +@@ -110,16 +112,17 @@ bin_PROGRAMS = \ + + + ## Tests + check_PROGRAMS = \ + src/processor/address_map_unittest \ + src/processor/basic_source_line_resolver_unittest \ + src/processor/contained_range_map_unittest \ + src/processor/minidump_processor_unittest \ ++ src/processor/minidump_unittest \ + src/processor/pathname_stripper_unittest \ + src/processor/postfix_evaluator_unittest \ + src/processor/range_map_unittest + + if SELFTEST + check_PROGRAMS += \ + src/processor/stackwalker_selftest + endif SELFTEST +@@ -147,32 +150,55 @@ src_processor_basic_source_line_resolver + + src_processor_contained_range_map_unittest_SOURCES = \ + src/processor/contained_range_map_unittest.cc + src_processor_contained_range_map_unittest_LDADD = \ + src/processor/logging.lo \ + src/processor/pathname_stripper.lo + + src_processor_minidump_processor_unittest_SOURCES = \ +- src/processor/minidump_processor_unittest.cc ++ src/processor/minidump_processor_unittest.cc \ ++ src/testing/gtest/src/gtest-all.cc \ ++ src/testing/src/gmock-all.cc ++src_processor_minidump_processor_unittest_CPPFLAGS = \ ++ -I$(top_srcdir)/src/testing/include \ ++ -I$(top_srcdir)/src/testing/gtest/include \ ++ -I$(top_srcdir)/src/testing/gtest \ ++ -I$(top_srcdir)/src/testing + src_processor_minidump_processor_unittest_LDADD = \ + src/processor/basic_code_modules.lo \ + src/processor/basic_source_line_resolver.lo \ + src/processor/call_stack.lo \ + src/processor/logging.lo \ + src/processor/minidump_processor.lo \ + src/processor/minidump.lo \ + src/processor/pathname_stripper.lo \ + src/processor/process_state.lo \ + src/processor/stackwalker.lo \ + src/processor/stackwalker_amd64.lo \ ++ src/processor/stackwalker_arm.lo \ + src/processor/stackwalker_ppc.lo \ + src/processor/stackwalker_sparc.lo \ + src/processor/stackwalker_x86.lo + ++src_processor_minidump_unittest_SOURCES = \ ++ src/processor/minidump_unittest.cc \ ++ src/testing/gtest/src/gtest-all.cc \ ++ src/testing/src/gmock-all.cc ++src_processor_minidump_unittest_CPPFLAGS = \ ++ -I$(top_srcdir)/src/testing/include \ ++ -I$(top_srcdir)/src/testing/gtest/include \ ++ -I$(top_srcdir)/src/testing/gtest \ ++ -I$(top_srcdir)/src/testing ++src_processor_minidump_unittest_LDADD = \ ++ src/processor/basic_code_modules.lo \ ++ src/processor/logging.lo \ ++ src/processor/minidump.lo \ ++ src/processor/pathname_stripper.lo ++ + src_processor_pathname_stripper_unittest_SOURCES = \ + src/processor/pathname_stripper_unittest.cc + src_processor_pathname_stripper_unittest_LDADD = \ + src/processor/pathname_stripper.lo + + src_processor_postfix_evaluator_unittest_SOURCES = \ + src/processor/postfix_evaluator_unittest.cc + src_processor_postfix_evaluator_unittest_LDADD = \ +@@ -191,16 +217,17 @@ src_processor_stackwalker_selftest_LDADD + src/processor/basic_code_modules.lo \ + src/processor/basic_source_line_resolver.lo \ + src/processor/call_stack.lo \ + src/processor/logging.lo \ + src/processor/minidump.lo \ + src/processor/pathname_stripper.lo \ + src/processor/stackwalker.lo \ + src/processor/stackwalker_amd64.lo \ ++ src/processor/stackwalker_arm.lo \ + src/processor/stackwalker_ppc.lo \ + src/processor/stackwalker_sparc.lo \ + src/processor/stackwalker_x86.lo + + ## Non-installables + noinst_PROGRAMS = + noinst_SCRIPTS = $(check_SCRIPTS) + +@@ -221,16 +248,17 @@ src_processor_minidump_stackwalk_LDADD = + src/processor/logging.lo \ + src/processor/minidump.lo \ + src/processor/minidump_processor.lo \ + src/processor/pathname_stripper.lo \ + src/processor/process_state.lo \ + src/processor/simple_symbol_supplier.lo \ + src/processor/stackwalker.lo \ + src/processor/stackwalker_amd64.lo \ ++ src/processor/stackwalker_arm.lo \ + src/processor/stackwalker_ppc.lo \ + src/processor/stackwalker_sparc.lo \ + src/processor/stackwalker_x86.lo + + + ## Additional files to be included in a source distribution + ## + ## find src/client src/common src/processor/testdata src/tools \ +diff --git a/toolkit/crashreporter/google-breakpad/Makefile.in b/toolkit/crashreporter/google-breakpad/Makefile.in +--- a/toolkit/crashreporter/google-breakpad/Makefile.in ++++ b/toolkit/crashreporter/google-breakpad/Makefile.in +@@ -142,18 +142,19 @@ src_processor_contained_range_map_unitte + src/processor/logging.lo src/processor/pathname_stripper.lo + am_src_processor_minidump_dump_OBJECTS = \ + src/processor/minidump_dump.$(OBJEXT) + src_processor_minidump_dump_OBJECTS = \ + $(am_src_processor_minidump_dump_OBJECTS) + src_processor_minidump_dump_DEPENDENCIES = \ + src/processor/basic_code_modules.lo src/processor/logging.lo \ + src/processor/minidump.lo src/processor/pathname_stripper.lo +-am_src_processor_minidump_processor_unittest_OBJECTS = \ +- src/processor/minidump_processor_unittest.$(OBJEXT) ++am_src_processor_minidump_processor_unittest_OBJECTS = src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.$(OBJEXT) \ ++ src/testing/gtest/src/src_processor_minidump_processor_unittest-gtest-all.$(OBJEXT) \ ++ src/testing/src/src_processor_minidump_processor_unittest-gmock-all.$(OBJEXT) + src_processor_minidump_processor_unittest_OBJECTS = \ + $(am_src_processor_minidump_processor_unittest_OBJECTS) + src_processor_minidump_processor_unittest_DEPENDENCIES = \ + src/processor/basic_code_modules.lo \ + src/processor/basic_source_line_resolver.lo \ + src/processor/call_stack.lo src/processor/logging.lo \ + src/processor/minidump_processor.lo src/processor/minidump.lo \ + src/processor/pathname_stripper.lo \ +@@ -284,16 +285,17 @@ CPP = @CPP@ + CPPFLAGS = @CPPFLAGS@ + CXX = @CXX@ + CXXCPP = @CXXCPP@ + CXXDEPMODE = @CXXDEPMODE@ + CXXFLAGS = @CXXFLAGS@ + CYGPATH_W = @CYGPATH_W@ + DEFS = @DEFS@ + DEPDIR = @DEPDIR@ ++DSYMUTIL = @DSYMUTIL@ + ECHO = @ECHO@ + ECHO_C = @ECHO_C@ + ECHO_N = @ECHO_N@ + ECHO_T = @ECHO_T@ + EGREP = @EGREP@ + EXEEXT = @EXEEXT@ + F77 = @F77@ + FFLAGS = @FFLAGS@ +@@ -307,25 +309,27 @@ LDFLAGS = @LDFLAGS@ + LIBOBJS = @LIBOBJS@ + LIBS = @LIBS@ + LIBTOOL = @LIBTOOL@ + LIBTOOL_DEPS = @LIBTOOL_DEPS@ + LN_S = @LN_S@ + LTLIBOBJS = @LTLIBOBJS@ + MAKEINFO = @MAKEINFO@ + MKDIR_P = @MKDIR_P@ ++NMEDIT = @NMEDIT@ + OBJEXT = @OBJEXT@ + PACKAGE = @PACKAGE@ + PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ + PACKAGE_NAME = @PACKAGE_NAME@ + PACKAGE_STRING = @PACKAGE_STRING@ + PACKAGE_TARNAME = @PACKAGE_TARNAME@ + PACKAGE_VERSION = @PACKAGE_VERSION@ + PATH_SEPARATOR = @PATH_SEPARATOR@ + RANLIB = @RANLIB@ ++SED = @SED@ + SET_MAKE = @SET_MAKE@ + SHELL = @SHELL@ + STRIP = @STRIP@ + VERSION = @VERSION@ + abs_builddir = @abs_builddir@ + abs_srcdir = @abs_srcdir@ + abs_top_builddir = @abs_top_builddir@ + abs_top_srcdir = @abs_top_srcdir@ +@@ -466,17 +470,25 @@ src_processor_basic_source_line_resolver + src_processor_contained_range_map_unittest_SOURCES = \ + src/processor/contained_range_map_unittest.cc + + src_processor_contained_range_map_unittest_LDADD = \ + src/processor/logging.lo \ + src/processor/pathname_stripper.lo + + src_processor_minidump_processor_unittest_SOURCES = \ +- src/processor/minidump_processor_unittest.cc ++ src/processor/minidump_processor_unittest.cc \ ++ src/testing/gtest/src/gtest-all.cc \ ++ src/testing/src/gmock-all.cc ++ ++src_processor_minidump_processor_unittest_CPPFLAGS = \ ++ -I$(top_srcdir)/src/testing/include \ ++ -I$(top_srcdir)/src/testing/gtest/include \ ++ -I$(top_srcdir)/src/testing/gtest \ ++ -I$(top_srcdir)/src/testing + + src_processor_minidump_processor_unittest_LDADD = \ + src/processor/basic_code_modules.lo \ + src/processor/basic_source_line_resolver.lo \ + src/processor/call_stack.lo \ + src/processor/logging.lo \ + src/processor/minidump_processor.lo \ + src/processor/minidump.lo \ +@@ -866,19 +878,37 @@ src/processor/contained_range_map_unitte + src/processor/contained_range_map_unittest$(EXEEXT): $(src_processor_contained_range_map_unittest_OBJECTS) $(src_processor_contained_range_map_unittest_DEPENDENCIES) src/processor/$(am__dirstamp) + @rm -f src/processor/contained_range_map_unittest$(EXEEXT) + $(CXXLINK) $(src_processor_contained_range_map_unittest_OBJECTS) $(src_processor_contained_range_map_unittest_LDADD) $(LIBS) + src/processor/minidump_dump.$(OBJEXT): src/processor/$(am__dirstamp) \ + src/processor/$(DEPDIR)/$(am__dirstamp) + src/processor/minidump_dump$(EXEEXT): $(src_processor_minidump_dump_OBJECTS) $(src_processor_minidump_dump_DEPENDENCIES) src/processor/$(am__dirstamp) + @rm -f src/processor/minidump_dump$(EXEEXT) + $(CXXLINK) $(src_processor_minidump_dump_OBJECTS) $(src_processor_minidump_dump_LDADD) $(LIBS) +-src/processor/minidump_processor_unittest.$(OBJEXT): \ ++src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.$(OBJEXT): \ + src/processor/$(am__dirstamp) \ + src/processor/$(DEPDIR)/$(am__dirstamp) ++src/testing/gtest/src/$(am__dirstamp): ++ @$(MKDIR_P) src/testing/gtest/src ++ @: > src/testing/gtest/src/$(am__dirstamp) ++src/testing/gtest/src/$(DEPDIR)/$(am__dirstamp): ++ @$(MKDIR_P) src/testing/gtest/src/$(DEPDIR) ++ @: > src/testing/gtest/src/$(DEPDIR)/$(am__dirstamp) ++src/testing/gtest/src/src_processor_minidump_processor_unittest-gtest-all.$(OBJEXT): \ ++ src/testing/gtest/src/$(am__dirstamp) \ ++ src/testing/gtest/src/$(DEPDIR)/$(am__dirstamp) ++src/testing/src/$(am__dirstamp): ++ @$(MKDIR_P) src/testing/src ++ @: > src/testing/src/$(am__dirstamp) ++src/testing/src/$(DEPDIR)/$(am__dirstamp): ++ @$(MKDIR_P) src/testing/src/$(DEPDIR) ++ @: > src/testing/src/$(DEPDIR)/$(am__dirstamp) ++src/testing/src/src_processor_minidump_processor_unittest-gmock-all.$(OBJEXT): \ ++ src/testing/src/$(am__dirstamp) \ ++ src/testing/src/$(DEPDIR)/$(am__dirstamp) + src/processor/minidump_processor_unittest$(EXEEXT): $(src_processor_minidump_processor_unittest_OBJECTS) $(src_processor_minidump_processor_unittest_DEPENDENCIES) src/processor/$(am__dirstamp) + @rm -f src/processor/minidump_processor_unittest$(EXEEXT) + $(CXXLINK) $(src_processor_minidump_processor_unittest_OBJECTS) $(src_processor_minidump_processor_unittest_LDADD) $(LIBS) + src/processor/minidump_stackwalk.$(OBJEXT): \ + src/processor/$(am__dirstamp) \ + src/processor/$(DEPDIR)/$(am__dirstamp) + src/processor/minidump_stackwalk$(EXEEXT): $(src_processor_minidump_stackwalk_OBJECTS) $(src_processor_minidump_stackwalk_DEPENDENCIES) src/processor/$(am__dirstamp) + @rm -f src/processor/minidump_stackwalk$(EXEEXT) +@@ -921,66 +951,70 @@ mostlyclean-compile: + -rm -f src/processor/contained_range_map_unittest.$(OBJEXT) + -rm -f src/processor/logging.$(OBJEXT) + -rm -f src/processor/logging.lo + -rm -f src/processor/minidump.$(OBJEXT) + -rm -f src/processor/minidump.lo + -rm -f src/processor/minidump_dump.$(OBJEXT) + -rm -f src/processor/minidump_processor.$(OBJEXT) + -rm -f src/processor/minidump_processor.lo +- -rm -f src/processor/minidump_processor_unittest.$(OBJEXT) + -rm -f src/processor/minidump_stackwalk.$(OBJEXT) + -rm -f src/processor/pathname_stripper.$(OBJEXT) + -rm -f src/processor/pathname_stripper.lo + -rm -f src/processor/pathname_stripper_unittest.$(OBJEXT) + -rm -f src/processor/postfix_evaluator_unittest.$(OBJEXT) + -rm -f src/processor/process_state.$(OBJEXT) + -rm -f src/processor/process_state.lo + -rm -f src/processor/range_map_unittest.$(OBJEXT) + -rm -f src/processor/simple_symbol_supplier.$(OBJEXT) + -rm -f src/processor/simple_symbol_supplier.lo ++ -rm -f src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.$(OBJEXT) + -rm -f src/processor/stackwalker.$(OBJEXT) + -rm -f src/processor/stackwalker.lo + -rm -f src/processor/stackwalker_amd64.$(OBJEXT) + -rm -f src/processor/stackwalker_amd64.lo + -rm -f src/processor/stackwalker_ppc.$(OBJEXT) + -rm -f src/processor/stackwalker_ppc.lo + -rm -f src/processor/stackwalker_selftest.$(OBJEXT) + -rm -f src/processor/stackwalker_sparc.$(OBJEXT) + -rm -f src/processor/stackwalker_sparc.lo + -rm -f src/processor/stackwalker_x86.$(OBJEXT) + -rm -f src/processor/stackwalker_x86.lo ++ -rm -f src/testing/gtest/src/src_processor_minidump_processor_unittest-gtest-all.$(OBJEXT) ++ -rm -f src/testing/src/src_processor_minidump_processor_unittest-gmock-all.$(OBJEXT) + + distclean-compile: + -rm -f *.tab.c + + @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/address_map_unittest.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/basic_code_modules.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/basic_source_line_resolver.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/basic_source_line_resolver_unittest.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/call_stack.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/contained_range_map_unittest.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/logging.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_dump.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_processor.Plo@am__quote@ +-@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_processor_unittest.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/minidump_stackwalk.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/pathname_stripper.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/pathname_stripper_unittest.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/postfix_evaluator_unittest.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/process_state.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/range_map_unittest.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/simple_symbol_supplier.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/src_processor_minidump_processor_unittest-minidump_processor_unittest.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stackwalker.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stackwalker_amd64.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stackwalker_ppc.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stackwalker_selftest.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stackwalker_sparc.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@src/processor/$(DEPDIR)/stackwalker_x86.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@src/testing/gtest/src/$(DEPDIR)/src_processor_minidump_processor_unittest-gtest-all.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@src/testing/src/$(DEPDIR)/src_processor_minidump_processor_unittest-gmock-all.Po@am__quote@ + + .cc.o: + @am__fastdepCXX_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ + @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ + @am__fastdepCXX_TRUE@ mv -f $$depbase.Tpo $$depbase.Po + @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ + @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + @am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< +@@ -996,16 +1030,58 @@ distclean-compile: + .cc.lo: + @am__fastdepCXX_TRUE@ depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ + @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ + @am__fastdepCXX_TRUE@ mv -f $$depbase.Tpo $$depbase.Plo + @AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ + @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + @am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< + ++src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.o: src/processor/minidump_processor_unittest.cc ++@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_processor_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.o -MD -MP -MF src/processor/$(DEPDIR)/src_processor_minidump_processor_unittest-minidump_processor_unittest.Tpo -c -o src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.o `test -f 'src/processor/minidump_processor_unittest.cc' || echo '$(srcdir)/'`src/processor/minidump_processor_unittest.cc ++@am__fastdepCXX_TRUE@ mv -f src/processor/$(DEPDIR)/src_processor_minidump_processor_unittest-minidump_processor_unittest.Tpo src/processor/$(DEPDIR)/src_processor_minidump_processor_unittest-minidump_processor_unittest.Po ++@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/processor/minidump_processor_unittest.cc' object='src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.o' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_processor_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.o `test -f 'src/processor/minidump_processor_unittest.cc' || echo '$(srcdir)/'`src/processor/minidump_processor_unittest.cc ++ ++src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.obj: src/processor/minidump_processor_unittest.cc ++@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_processor_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.obj -MD -MP -MF src/processor/$(DEPDIR)/src_processor_minidump_processor_unittest-minidump_processor_unittest.Tpo -c -o src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.obj `if test -f 'src/processor/minidump_processor_unittest.cc'; then $(CYGPATH_W) 'src/processor/minidump_processor_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/minidump_processor_unittest.cc'; fi` ++@am__fastdepCXX_TRUE@ mv -f src/processor/$(DEPDIR)/src_processor_minidump_processor_unittest-minidump_processor_unittest.Tpo src/processor/$(DEPDIR)/src_processor_minidump_processor_unittest-minidump_processor_unittest.Po ++@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/processor/minidump_processor_unittest.cc' object='src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.obj' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_processor_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/processor/src_processor_minidump_processor_unittest-minidump_processor_unittest.obj `if test -f 'src/processor/minidump_processor_unittest.cc'; then $(CYGPATH_W) 'src/processor/minidump_processor_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/processor/minidump_processor_unittest.cc'; fi` ++ ++src/testing/gtest/src/src_processor_minidump_processor_unittest-gtest-all.o: src/testing/gtest/src/gtest-all.cc ++@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_processor_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_processor_minidump_processor_unittest-gtest-all.o -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_processor_minidump_processor_unittest-gtest-all.Tpo -c -o src/testing/gtest/src/src_processor_minidump_processor_unittest-gtest-all.o `test -f 'src/testing/gtest/src/gtest-all.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest-all.cc ++@am__fastdepCXX_TRUE@ mv -f src/testing/gtest/src/$(DEPDIR)/src_processor_minidump_processor_unittest-gtest-all.Tpo src/testing/gtest/src/$(DEPDIR)/src_processor_minidump_processor_unittest-gtest-all.Po ++@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/gtest/src/gtest-all.cc' object='src/testing/gtest/src/src_processor_minidump_processor_unittest-gtest-all.o' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_processor_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_processor_minidump_processor_unittest-gtest-all.o `test -f 'src/testing/gtest/src/gtest-all.cc' || echo '$(srcdir)/'`src/testing/gtest/src/gtest-all.cc ++ ++src/testing/gtest/src/src_processor_minidump_processor_unittest-gtest-all.obj: src/testing/gtest/src/gtest-all.cc ++@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_processor_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/gtest/src/src_processor_minidump_processor_unittest-gtest-all.obj -MD -MP -MF src/testing/gtest/src/$(DEPDIR)/src_processor_minidump_processor_unittest-gtest-all.Tpo -c -o src/testing/gtest/src/src_processor_minidump_processor_unittest-gtest-all.obj `if test -f 'src/testing/gtest/src/gtest-all.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest-all.cc'; fi` ++@am__fastdepCXX_TRUE@ mv -f src/testing/gtest/src/$(DEPDIR)/src_processor_minidump_processor_unittest-gtest-all.Tpo src/testing/gtest/src/$(DEPDIR)/src_processor_minidump_processor_unittest-gtest-all.Po ++@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/gtest/src/gtest-all.cc' object='src/testing/gtest/src/src_processor_minidump_processor_unittest-gtest-all.obj' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_processor_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/gtest/src/src_processor_minidump_processor_unittest-gtest-all.obj `if test -f 'src/testing/gtest/src/gtest-all.cc'; then $(CYGPATH_W) 'src/testing/gtest/src/gtest-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/gtest/src/gtest-all.cc'; fi` ++ ++src/testing/src/src_processor_minidump_processor_unittest-gmock-all.o: src/testing/src/gmock-all.cc ++@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_processor_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/src/src_processor_minidump_processor_unittest-gmock-all.o -MD -MP -MF src/testing/src/$(DEPDIR)/src_processor_minidump_processor_unittest-gmock-all.Tpo -c -o src/testing/src/src_processor_minidump_processor_unittest-gmock-all.o `test -f 'src/testing/src/gmock-all.cc' || echo '$(srcdir)/'`src/testing/src/gmock-all.cc ++@am__fastdepCXX_TRUE@ mv -f src/testing/src/$(DEPDIR)/src_processor_minidump_processor_unittest-gmock-all.Tpo src/testing/src/$(DEPDIR)/src_processor_minidump_processor_unittest-gmock-all.Po ++@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/src/gmock-all.cc' object='src/testing/src/src_processor_minidump_processor_unittest-gmock-all.o' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_processor_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/src/src_processor_minidump_processor_unittest-gmock-all.o `test -f 'src/testing/src/gmock-all.cc' || echo '$(srcdir)/'`src/testing/src/gmock-all.cc ++ ++src/testing/src/src_processor_minidump_processor_unittest-gmock-all.obj: src/testing/src/gmock-all.cc ++@am__fastdepCXX_TRUE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_processor_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT src/testing/src/src_processor_minidump_processor_unittest-gmock-all.obj -MD -MP -MF src/testing/src/$(DEPDIR)/src_processor_minidump_processor_unittest-gmock-all.Tpo -c -o src/testing/src/src_processor_minidump_processor_unittest-gmock-all.obj `if test -f 'src/testing/src/gmock-all.cc'; then $(CYGPATH_W) 'src/testing/src/gmock-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/src/gmock-all.cc'; fi` ++@am__fastdepCXX_TRUE@ mv -f src/testing/src/$(DEPDIR)/src_processor_minidump_processor_unittest-gmock-all.Tpo src/testing/src/$(DEPDIR)/src_processor_minidump_processor_unittest-gmock-all.Po ++@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/testing/src/gmock-all.cc' object='src/testing/src/src_processor_minidump_processor_unittest-gmock-all.obj' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(src_processor_minidump_processor_unittest_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o src/testing/src/src_processor_minidump_processor_unittest-gmock-all.obj `if test -f 'src/testing/src/gmock-all.cc'; then $(CYGPATH_W) 'src/testing/src/gmock-all.cc'; else $(CYGPATH_W) '$(srcdir)/src/testing/src/gmock-all.cc'; fi` ++ + mostlyclean-libtool: + -rm -f *.lo + + clean-libtool: + -rm -rf .libs _libs + -rm -rf src/.libs src/_libs + -rm -rf src/processor/.libs src/processor/_libs + +@@ -1304,29 +1380,33 @@ mostlyclean-generic: + + clean-generic: + + distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -rm -f src/$(am__dirstamp) + -rm -f src/processor/$(DEPDIR)/$(am__dirstamp) + -rm -f src/processor/$(am__dirstamp) ++ -rm -f src/testing/gtest/src/$(DEPDIR)/$(am__dirstamp) ++ -rm -f src/testing/gtest/src/$(am__dirstamp) ++ -rm -f src/testing/src/$(DEPDIR)/$(am__dirstamp) ++ -rm -f src/testing/src/$(am__dirstamp) + + maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + clean: clean-am + + clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ + clean-libLTLIBRARIES clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + + distclean: distclean-am + -rm -f $(am__CONFIG_DISTCLEAN_FILES) +- -rm -rf src/processor/$(DEPDIR) ++ -rm -rf src/processor/$(DEPDIR) src/testing/gtest/src/$(DEPDIR) src/testing/src/$(DEPDIR) + -rm -f Makefile + distclean-am: clean-am distclean-compile distclean-generic \ + distclean-hdr distclean-libtool distclean-tags + + dvi: dvi-am + + dvi-am: + +@@ -1352,17 +1432,17 @@ install-pdf: install-pdf-am + + install-ps: install-ps-am + + installcheck-am: + + maintainer-clean: maintainer-clean-am + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache +- -rm -rf src/processor/$(DEPDIR) ++ -rm -rf src/processor/$(DEPDIR) src/testing/gtest/src/$(DEPDIR) src/testing/src/$(DEPDIR) + -rm -f Makefile + maintainer-clean-am: distclean-am maintainer-clean-generic + + mostlyclean: mostlyclean-am + + mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +diff --git a/toolkit/crashreporter/google-breakpad/aclocal.m4 b/toolkit/crashreporter/google-breakpad/aclocal.m4 +--- a/toolkit/crashreporter/google-breakpad/aclocal.m4 ++++ b/toolkit/crashreporter/google-breakpad/aclocal.m4 +@@ -13,17 +13,17 @@ + + m4_if(m4_PACKAGE_VERSION, [2.61],, + [m4_fatal([this file was generated for autoconf 2.61. + You have another version of autoconf. If you want to use that, + you should regenerate the build system entirely.], [63])]) + + # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- + +-# serial 48 AC_PROG_LIBTOOL ++# serial 52 AC_PROG_LIBTOOL + + + # AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) + # ----------------------------------------------------------- + # If this macro is not defined by Autoconf, define it here. + m4_ifdef([AC_PROVIDE_IFELSE], + [], + [m4_define([AC_PROVIDE_IFELSE], +@@ -101,17 +101,16 @@ AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl + AC_REQUIRE([AC_PROG_NM])dnl + + AC_REQUIRE([AC_PROG_LN_S])dnl + AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl + # Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! + AC_REQUIRE([AC_OBJEXT])dnl + AC_REQUIRE([AC_EXEEXT])dnl + dnl +- + AC_LIBTOOL_SYS_MAX_CMD_LEN + AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE + AC_LIBTOOL_OBJDIR + + AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl + _LT_AC_PROG_ECHO_BACKSLASH + + case $host_os in +@@ -176,17 +175,17 @@ test -z "$MAGIC_CMD" && MAGIC_CMD=file + test -z "$NM" && NM=nm + test -z "$SED" && SED=sed + test -z "$OBJDUMP" && OBJDUMP=objdump + test -z "$RANLIB" && RANLIB=: + test -z "$STRIP" && STRIP=: + test -z "$ac_objext" && ac_objext=o + + # Determine commands to create old-style static archives. +-old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' ++old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' + old_postinstall_cmds='chmod 644 $oldlib' + old_postuninstall_cmds= + + if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; +@@ -203,16 +202,18 @@ _LT_CC_BASENAME([$compiler]) + case $deplibs_check_method in + file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + AC_PATH_MAGIC + fi + ;; + esac + ++_LT_REQUIRED_DARWIN_CHECKS ++ + AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) + AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], + enable_win32_dll=yes, enable_win32_dll=no) + + AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) + test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes +@@ -263,52 +264,133 @@ cc_basename=`$echo "X$cc_temp" | $Xsed - + ]) + + + # _LT_COMPILER_BOILERPLATE + # ------------------------ + # Check for compiler boilerplate output or warnings with + # the simple compiler test code. + AC_DEFUN([_LT_COMPILER_BOILERPLATE], +-[ac_outfile=conftest.$ac_objext +-printf "$lt_simple_compile_test_code" >conftest.$ac_ext ++[AC_REQUIRE([LT_AC_PROG_SED])dnl ++ac_outfile=conftest.$ac_objext ++echo "$lt_simple_compile_test_code" >conftest.$ac_ext + eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err + _lt_compiler_boilerplate=`cat conftest.err` + $rm conftest* + ])# _LT_COMPILER_BOILERPLATE + + + # _LT_LINKER_BOILERPLATE + # ---------------------- + # Check for linker boilerplate output or warnings with + # the simple link test code. + AC_DEFUN([_LT_LINKER_BOILERPLATE], +-[ac_outfile=conftest.$ac_objext +-printf "$lt_simple_link_test_code" >conftest.$ac_ext ++[AC_REQUIRE([LT_AC_PROG_SED])dnl ++ac_outfile=conftest.$ac_objext ++echo "$lt_simple_link_test_code" >conftest.$ac_ext + eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err + _lt_linker_boilerplate=`cat conftest.err` +-$rm conftest* ++$rm -r conftest* + ])# _LT_LINKER_BOILERPLATE + ++# _LT_REQUIRED_DARWIN_CHECKS ++# -------------------------- ++# Check for some things on darwin ++AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS],[ ++ case $host_os in ++ rhapsody* | darwin*) ++ AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) ++ AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) ++ ++ AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], ++ [lt_cv_apple_cc_single_mod=no ++ if test -z "${LT_MULTI_MODULE}"; then ++ # By default we will add the -single_module flag. You can override ++ # by either setting the environment variable LT_MULTI_MODULE ++ # non-empty at configure time, or by adding -multi_module to the ++ # link flags. ++ echo "int foo(void){return 1;}" > conftest.c ++ $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ ++ -dynamiclib ${wl}-single_module conftest.c ++ if test -f libconftest.dylib; then ++ lt_cv_apple_cc_single_mod=yes ++ rm -rf libconftest.dylib* ++ fi ++ rm conftest.c ++ fi]) ++ AC_CACHE_CHECK([for -exported_symbols_list linker flag], ++ [lt_cv_ld_exported_symbols_list], ++ [lt_cv_ld_exported_symbols_list=no ++ save_LDFLAGS=$LDFLAGS ++ echo "_main" > conftest.sym ++ LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" ++ AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], ++ [lt_cv_ld_exported_symbols_list=yes], ++ [lt_cv_ld_exported_symbols_list=no]) ++ LDFLAGS="$save_LDFLAGS" ++ ]) ++ case $host_os in ++ rhapsody* | darwin1.[[0123]]) ++ _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; ++ darwin1.*) ++ _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; ++ darwin*) ++ # if running on 10.5 or later, the deployment target defaults ++ # to the OS version, if on x86, and 10.4, the deployment ++ # target defaults to 10.4. Don't you love it? ++ case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in ++ 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) ++ _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; ++ 10.[[012]]*) ++ _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; ++ 10.*) ++ _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; ++ esac ++ ;; ++ esac ++ if test "$lt_cv_apple_cc_single_mod" = "yes"; then ++ _lt_dar_single_mod='$single_module' ++ fi ++ if test "$lt_cv_ld_exported_symbols_list" = "yes"; then ++ _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' ++ else ++ _lt_dar_export_syms="~$NMEDIT -s \$output_objdir/\${libname}-symbols.expsym \${lib}" ++ fi ++ if test "$DSYMUTIL" != ":"; then ++ _lt_dsymutil="~$DSYMUTIL \$lib || :" ++ else ++ _lt_dsymutil= ++ fi ++ ;; ++ esac ++]) + + # _LT_AC_SYS_LIBPATH_AIX + # ---------------------- + # Links a minimal program and checks the executable + # for the system default hardcoded library path. In most cases, + # this is /usr/lib:/lib, but when the MPI compilers are used + # the location of the communication and MPI libs are included too. + # If we don't find anything, use the default library path according + # to the aix ld manual. + AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX], +-[AC_LINK_IFELSE(AC_LANG_PROGRAM,[ +-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +-}'` ++[AC_REQUIRE([LT_AC_PROG_SED])dnl ++AC_LINK_IFELSE(AC_LANG_PROGRAM,[ ++lt_aix_libpath_sed=' ++ /Import File Strings/,/^$/ { ++ /^0/ { ++ s/^0 *\(.*\)$/\1/ ++ p ++ } ++ }' ++aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. +-if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +-}'`; fi],[]) ++if test -z "$aix_libpath"; then ++ aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` ++fi],[]) + if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + ])# _LT_AC_SYS_LIBPATH_AIX + + + # _LT_AC_SHELL_INIT(ARG) + # ---------------------- + AC_DEFUN([_LT_AC_SHELL_INIT], + [ifdef([AC_DIVERSION_NOTICE], +@@ -529,39 +611,46 @@ ia64-*-hpux*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +-x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) ++x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ ++s390*-*linux*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in ++ x86_64-*kfreebsd*-gnu) ++ LD="${LD-ld} -m elf_i386_fbsd" ++ ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in ++ x86_64-*kfreebsd*-gnu) ++ LD="${LD-ld} -m elf_x86_64_fbsd" ++ ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*) + LD="${LD-ld} -m elf64_s390" +@@ -592,17 +681,21 @@ x86_64-*linux*|ppc*-*linux*|powerpc*-*li + sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; +- *) LD="${LD-ld} -64" ;; ++ *) ++ if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then ++ LD="${LD-ld} -64" ++ fi ++ ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + + AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +@@ -623,17 +716,17 @@ need_locks="$enable_libtool_lock" + # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) + # ---------------------------------------------------------------- + # Check whether the given compiler option works + AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], + [AC_REQUIRE([LT_AC_PROG_SED]) + AC_CACHE_CHECK([$1], [$2], + [$2=no + ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) +- printf "$lt_simple_compile_test_code" > conftest.$ac_ext ++ echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ +@@ -664,37 +757,38 @@ fi + ])# AC_LIBTOOL_COMPILER_OPTION + + + # AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, + # [ACTION-SUCCESS], [ACTION-FAILURE]) + # ------------------------------------------------------------ + # Check whether the given compiler option works + AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], +-[AC_CACHE_CHECK([$1], [$2], ++[AC_REQUIRE([LT_AC_PROG_SED])dnl ++AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" +- printf "$lt_simple_link_test_code" > conftest.$ac_ext ++ echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi +- $rm conftest* ++ $rm -r conftest* + LDFLAGS="$save_LDFLAGS" + ]) + + if test x"[$]$2" = xyes; then + ifelse([$4], , :, [$4]) + else + ifelse([$5], , :, [$5]) + fi +@@ -782,34 +876,37 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [d + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) +- # If test is not a shell built-in, we'll probably end up computing a +- # maximum length that is only half of the actual maximum length, but +- # we can't tell. +- SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} +- while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \ ++ lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` ++ if test -n "$lt_cv_sys_max_cmd_len"; then ++ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` ++ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ++ else ++ SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} ++ while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \ + = "XX$teststring") >/dev/null 2>&1 && +- new_result=`expr "X$teststring" : ".*" 2>&1` && +- lt_cv_sys_max_cmd_len=$new_result && +- test $i != 17 # 1/2 MB should be enough +- do +- i=`expr $i + 1` +- teststring=$teststring$teststring +- done +- teststring= +- # Add a significant safety factor because C++ compilers can tack on massive +- # amounts of additional arguments before passing them to the linker. +- # It appears as though 1/2 is a usable value. +- lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` ++ new_result=`expr "X$teststring" : ".*" 2>&1` && ++ lt_cv_sys_max_cmd_len=$new_result && ++ test $i != 17 # 1/2 MB should be enough ++ do ++ i=`expr $i + 1` ++ teststring=$teststring$teststring ++ done ++ teststring= ++ # Add a significant safety factor because C++ compilers can tack on massive ++ # amounts of additional arguments before passing them to the linker. ++ # It appears as though 1/2 is a usable value. ++ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` ++ fi + ;; + esac + ]) + if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) + else + AC_MSG_RESULT(none) + fi +@@ -952,25 +1049,25 @@ else + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], +- [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], ++ [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], +- [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) ++ [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + +@@ -1026,25 +1123,26 @@ else + fi + ])# AC_LIBTOOL_DLOPEN_SELF + + + # AC_LIBTOOL_PROG_CC_C_O([TAGNAME]) + # --------------------------------- + # Check to see if options -c and -o are simultaneously supported by compiler + AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O], +-[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl ++[AC_REQUIRE([LT_AC_PROG_SED])dnl ++AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl + AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out +- printf "$lt_simple_compile_test_code" > conftest.$ac_ext ++ echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ +@@ -1174,16 +1272,17 @@ if test -n "$STRIP" && $STRIP -V 2>&1 | + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) + else + # FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" ++ old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; +@@ -1191,44 +1290,83 @@ fi + fi + ])# AC_LIBTOOL_SYS_LIB_STRIP + + + # AC_LIBTOOL_SYS_DYNAMIC_LINKER + # ----------------------------- + # PORTME Fill in your ld.so characteristics + AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER], +-[AC_MSG_CHECKING([dynamic linker characteristics]) ++[AC_REQUIRE([LT_AC_PROG_SED])dnl ++AC_MSG_CHECKING([dynamic linker characteristics]) + library_names_spec= + libname_spec='lib$name' + soname_spec= + shrext_cmds=".so" + postinstall_cmds= + postuninstall_cmds= + finish_cmds= + finish_eval= + shlibpath_var= + shlibpath_overrides_runpath=unknown + version_type=none + dynamic_linker="$host_os ld.so" + sys_lib_dlsearch_path_spec="/lib /usr/lib" ++m4_if($1,[],[ + if test "$GCC" = yes; then +- sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` +- if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then ++ case $host_os in ++ darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; ++ *) lt_awk_arg="/^libraries:/" ;; ++ esac ++ lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` ++ if echo "$lt_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. +- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` ++ lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e 's/;/ /g'` + else +- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ++ lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi ++ # Ok, now we have the path, separated by spaces, we can step through it ++ # and add multilib dir if necessary. ++ lt_tmp_lt_search_path_spec= ++ lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` ++ for lt_sys_path in $lt_search_path_spec; do ++ if test -d "$lt_sys_path/$lt_multi_os_dir"; then ++ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" ++ else ++ test -d "$lt_sys_path" && \ ++ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" ++ fi ++ done ++ lt_search_path_spec=`echo $lt_tmp_lt_search_path_spec | awk ' ++BEGIN {RS=" "; FS="/|\n";} { ++ lt_foo=""; ++ lt_count=0; ++ for (lt_i = NF; lt_i > 0; lt_i--) { ++ if ($lt_i != "" && $lt_i != ".") { ++ if ($lt_i == "..") { ++ lt_count++; ++ } else { ++ if (lt_count == 0) { ++ lt_foo="/" $lt_i lt_foo; ++ } else { ++ lt_count--; ++ } ++ } ++ } ++ } ++ if (lt_foo != "") { lt_freq[[lt_foo]]++; } ++ if (lt_freq[[lt_foo]] == 1) { print lt_foo; } ++}'` ++ sys_lib_search_path_spec=`echo $lt_search_path_spec` + else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +-fi ++fi]) + need_lib_prefix=unknown + hardcode_into_libs=no + + # when you set need_version to no, make sure it does not cause -set_version + # flags to be left without arguments + need_version=unknown + + case $host_os in +@@ -1236,17 +1374,17 @@ aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +-aix4* | aix5*) ++aix[[4-9]]*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH +@@ -1375,50 +1513,34 @@ darwin* | rhapsody*) + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +- # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. +- if test "$GCC" = yes; then +- sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` +- else +- sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' +- fi ++ m4_if([$1], [],[ ++ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + + dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + + freebsd1*) + dynamic_linker=no + ;; + +-kfreebsd*-gnu) +- version_type=linux +- need_lib_prefix=no +- need_version=no +- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' +- soname_spec='${libname}${release}${shared_ext}$major' +- shlibpath_var=LD_LIBRARY_PATH +- shlibpath_overrides_runpath=no +- hardcode_into_libs=yes +- dynamic_linker='GNU ld.so' +- ;; +- + freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[123]]*) objformat=aout ;; +@@ -1446,17 +1568,17 @@ freebsd* | dragonfly*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; +- freebsd*) # from 4.6 on ++ *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + + gnu*) + version_type=linux +@@ -1509,17 +1631,17 @@ hpux9* | hpux10* | hpux11*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +-interix3*) ++interix[[3-9]]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no +@@ -1564,57 +1686,45 @@ irix5* | irix6* | nonstopux*) + ;; + + # No shared lib support for Linux oldld, aout, or coff. + linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + + # This must be Linux ELF. +-linux*) ++linux* | k*bsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then +- lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` ++ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +-knetbsd*-gnu) +- version_type=linux +- need_lib_prefix=no +- need_version=no +- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' +- soname_spec='${libname}${release}${shared_ext}$major' +- shlibpath_var=LD_LIBRARY_PATH +- shlibpath_overrides_runpath=no +- hardcode_into_libs=yes +- dynamic_linker='GNU ld.so' +- ;; +- + netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' +@@ -1686,16 +1796,20 @@ osf3* | osf4* | osf5*) + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + ++rdos*) ++ dynamic_linker=no ++ ;; ++ + solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes +@@ -1781,27 +1895,35 @@ uts4*) + + *) + dynamic_linker=no + ;; + esac + AC_MSG_RESULT([$dynamic_linker]) + test "$dynamic_linker" = no && can_build_shared=no + ++AC_CACHE_VAL([lt_cv_sys_lib_search_path_spec], ++[lt_cv_sys_lib_search_path_spec="$sys_lib_search_path_spec"]) ++sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" ++AC_CACHE_VAL([lt_cv_sys_lib_dlsearch_path_spec], ++[lt_cv_sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec"]) ++sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" ++ + variables_saved_for_relink="PATH $shlibpath_var $runpath_var" + if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" + fi + ])# AC_LIBTOOL_SYS_DYNAMIC_LINKER + + + # _LT_AC_TAGCONFIG + # ---------------- + AC_DEFUN([_LT_AC_TAGCONFIG], +-[AC_ARG_WITH([tags], ++[AC_REQUIRE([LT_AC_PROG_SED])dnl ++AC_ARG_WITH([tags], + [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@], + [include additional configurations @<:@automatic@:>@])], + [tagnames="$withval"]) + + if test -f "$ltmain" && test -n "$tagnames"; then + if test ! -f "${ofile}"; then + AC_MSG_WARN([output file `$ofile' does not exist]) + fi +@@ -2052,17 +2174,17 @@ m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC + fi]) + EGREP=$ac_cv_prog_egrep + AC_SUBST([EGREP]) + ])]) + + + # AC_PATH_TOOL_PREFIX + # ------------------- +-# find a file program which can recognise shared library ++# find a file program which can recognize shared library + AC_DEFUN([AC_PATH_TOOL_PREFIX], + [AC_REQUIRE([AC_PROG_EGREP])dnl + AC_MSG_CHECKING([for $1]) + AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, + [case $MAGIC_CMD in + [[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +@@ -2115,17 +2237,17 @@ if test -n "$MAGIC_CMD"; then + else + AC_MSG_RESULT(no) + fi + ])# AC_PATH_TOOL_PREFIX + + + # AC_PATH_MAGIC + # ------------- +-# find a file program which can recognise a shared library ++# find a file program which can recognize a shared library + AC_DEFUN([AC_PATH_MAGIC], + [AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) + if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +@@ -2262,34 +2384,34 @@ esac + ])# AC_PROG_LD_RELOAD_FLAG + + + # AC_DEPLIBS_CHECK_METHOD + # ----------------------- + # how to check for library dependencies + # -- PORTME fill in with the dynamic library characteristics + AC_DEFUN([AC_DEPLIBS_CHECK_METHOD], +-[AC_CACHE_CHECK([how to recognise dependent libraries], ++[AC_CACHE_CHECK([how to recognize dependent libraries], + lt_cv_deplibs_check_method, + [lt_cv_file_magic_cmd='$MAGIC_CMD' + lt_cv_file_magic_test_file= + lt_cv_deplibs_check_method='unknown' + # Need to set the preceding variable on all platforms that support + # interlibrary dependencies. + # 'none' -- dependencies not supported. + # `unknown' -- same as none, but documents that we really don't know. + # 'pass_all' -- all dependencies passed with no checks. + # 'test_compile' -- check by making test program. + # 'file_magic [[regex]]' -- check by looking for files in library path + # which responds to the $file_magic_cmd with a given extended regex. + # If you have `file' or equivalent on your system and you're not sure + # whether `pass_all' will *always* work, you probably want this one. + + case $host_os in +-aix4* | aix5*) ++aix[[4-9]]*) + lt_cv_deplibs_check_method=pass_all + ;; + + beos*) + lt_cv_deplibs_check_method=pass_all + ;; + + bsdi[[45]]*) +@@ -2301,26 +2423,32 @@ bsdi[[45]]*) + cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + + mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by +- # func_win32_libid shell function, so use a weaker test based on 'objdump'. +- lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' +- lt_cv_file_magic_cmd='$OBJDUMP -f' ++ # func_win32_libid shell function, so use a weaker test based on 'objdump', ++ # unless we find 'file', for example because we are cross-compiling. ++ if ( file / ) >/dev/null 2>&1; then ++ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' ++ lt_cv_file_magic_cmd='func_win32_libid' ++ else ++ lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' ++ lt_cv_file_magic_cmd='$OBJDUMP -f' ++ fi + ;; + + darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +-freebsd* | kfreebsd*-gnu | dragonfly*) ++freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` +@@ -2348,33 +2476,33 @@ hpux10.20* | hpux11*) + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +-interix3*) ++interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + + irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + + # This must be Linux ELF. +-linux*) ++linux* | k*bsd*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' +@@ -2398,16 +2526,20 @@ openbsd*) + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + + osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + ++rdos*) ++ lt_cv_deplibs_check_method=pass_all ++ ;; ++ + solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + + sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' +@@ -2450,17 +2582,17 @@ test -z "$deplibs_check_method" && depli + # find the pathname to a BSD-compatible name lister + AC_DEFUN([AC_PROG_NM], + [AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM, + [if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" + else + lt_nm_to_check="${ac_tool_prefix}nm" +- if test -n "$ac_tool_prefix" && test "$build" = "$host"; then ++ if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" +@@ -2666,20 +2798,20 @@ AC_LANG_PUSH(C) + # Source file extension for C test sources. + ac_ext=c + + # Object file extension for compiled C test sources. + objext=o + _LT_AC_TAGVAR(objext, $1)=$objext + + # Code to be used in simple compile tests +-lt_simple_compile_test_code="int some_variable = 0;\n" ++lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests +-lt_simple_link_test_code='int main(){return(0);}\n' ++lt_simple_link_test_code='int main(){return(0);}' + + _LT_AC_SYS_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) +@@ -2705,17 +2837,17 @@ case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +-aix4* | aix5*) ++aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) +@@ -2762,29 +2894,30 @@ _LT_AC_TAGVAR(whole_archive_flag_spec, $ + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + + # Dependencies to place before and after the object being linked: + _LT_AC_TAGVAR(predep_objects, $1)= + _LT_AC_TAGVAR(postdep_objects, $1)= + _LT_AC_TAGVAR(predeps, $1)= + _LT_AC_TAGVAR(postdeps, $1)= + _LT_AC_TAGVAR(compiler_lib_search_path, $1)= ++_LT_AC_TAGVAR(compiler_lib_search_dirs, $1)= + + # Source file extension for C++ test sources. + ac_ext=cpp + + # Object file extension for compiled C++ test sources. + objext=o + _LT_AC_TAGVAR(objext, $1)=$objext + + # Code to be used in simple compile tests +-lt_simple_compile_test_code="int some_variable = 0;\n" ++lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests +-lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }\n' ++lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_AC_SYS_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + +@@ -2871,30 +3004,30 @@ fi + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; +- aix4* | aix5*) ++ aix[[4-9]]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. +- case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) ++ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done +@@ -2920,17 +3053,17 @@ case $host_os in + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 +- _LT_AC_TAGVAR(hardcode_direct, $1)=yes ++ : + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' +@@ -3030,69 +3163,41 @@ case $host_os in + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + darwin* | rhapsody*) +- case $host_os in +- rhapsody* | darwin1.[[012]]) +- _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' +- ;; +- *) # Darwin 1.3 on +- if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then +- _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' +- else +- case ${MACOSX_DEPLOYMENT_TARGET} in +- 10.[[012]]) +- _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' +- ;; +- 10.*) +- _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' +- ;; +- esac +- fi +- ;; +- esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes +- +- if test "$GXX" = yes ; then +- lt_int_apple_cc_single_mod=no ++ _LT_AC_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" ++ if test "$GXX" = yes ; then + output_verbose_link_cmd='echo' +- if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then +- lt_int_apple_cc_single_mod=yes ++ _LT_AC_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" ++ _LT_AC_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" ++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" ++ _LT_AC_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" ++ if test "$lt_cv_apple_cc_single_mod" != "yes"; then ++ _LT_AC_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" ++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" + fi +- if test "X$lt_int_apple_cc_single_mod" = Xyes ; then +- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' +- else +- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' +- fi +- _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' +- # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds +- if test "X$lt_int_apple_cc_single_mod" = Xyes ; then +- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' +- else +- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' +- fi +- _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' +- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' ++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds +- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; +@@ -3116,17 +3221,17 @@ case $host_os in + ;; + freebsd[[12]]*) + # C++ shared libraries reported to be fairly broken before switch to ELF + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + freebsd-elf*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + ;; +- freebsd* | kfreebsd*-gnu | dragonfly*) ++ freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + ;; + gnu*) + ;; + hpux9*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' +@@ -3165,19 +3270,17 @@ case $host_os in + esac + ;; + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in +- hppa*64*|ia64*) +- _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' +- ;; ++ hppa*64*|ia64*) ;; + *) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no +@@ -3235,17 +3338,17 @@ case $host_os in + fi + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; +- interix3*) ++ interix[[3-9]]*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, +@@ -3275,17 +3378,17 @@ case $host_os in + fi + fi + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; +- linux*) ++ linux* | k*bsd*-gnu) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' +@@ -3327,17 +3430,17 @@ case $host_os in + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; +- pgCC*) ++ pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + ;; +@@ -3355,16 +3458,39 @@ case $host_os in + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; ++ *) ++ case `$CC -V 2>&1 | sed 5q` in ++ *Sun\ C*) ++ # Sun C++ 5.9 ++ _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' ++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' ++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' ++ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' ++ ++ # Not sure whether something based on ++ # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 ++ # would be better. ++ output_verbose_link_cmd='echo' ++ ++ # Archives containing C++ object files must be created using ++ # "CC -xar", where "CC" is the Sun C++ compiler. This is ++ # necessary to make sure instantiated templates are included ++ # in the archive. ++ _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ++ ;; ++ esac ++ ;; + esac + ;; + lynxos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + m88k*) + # FIXME: insert proper C++ library support +@@ -3393,26 +3519,30 @@ case $host_os in + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + openbsd2*) + # C++ shared libraries are fairly broken + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + openbsd*) +- _LT_AC_TAGVAR(hardcode_direct, $1)=yes +- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no +- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' +- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' +- if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then +- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' +- _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' +- _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' ++ if test -f /usr/libexec/ld.so; then ++ _LT_AC_TAGVAR(hardcode_direct, $1)=yes ++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' ++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' ++ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then ++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' ++ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ++ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' ++ fi ++ output_verbose_link_cmd='echo' ++ else ++ _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi +- output_verbose_link_cmd='echo' + ;; + osf3*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library +@@ -3564,25 +3694,20 @@ case $host_os in + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) +- # The C++ compiler is used as linker so we must use $wl +- # flag to pass the commands to the underlying system +- # linker. We must also pass each convience library through +- # to the system linker between allextract/defaultextract. +- # The C++ compiler will combine linker options so we +- # cannot just pass the convience library names through +- # without $wl. ++ # The compiler driver will combine and reorder linker options, ++ # but understands `-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) +- _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ++ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is +@@ -3619,16 +3744,22 @@ case $host_os in + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + fi + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' ++ case $host_os in ++ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; ++ *) ++ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ++ ;; ++ esac + fi + ;; + esac + ;; + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no +@@ -3734,17 +3865,18 @@ lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld + ])# AC_LIBTOOL_LANG_CXX_CONFIG + + # AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) + # ------------------------------------ + # Figure out "hidden" library dependencies from verbose + # compiler output when linking a shared library. + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. +-AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[ ++AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP], ++[AC_REQUIRE([LT_AC_PROG_SED])dnl + dnl we can't use the lt_simple_compile_test_code here, + dnl because it contains code intended for an executable, + dnl not a library. It's possible we should let each + dnl tag define a new lt_????_link_test_code variable, + dnl but it's only used here... + ifelse([$1],[],[cat > conftest.$ac_ext <&1 | sed 5q` in ++ *Sun\ C*) ++ # Sun C++ 5.9 ++ # ++ # The more standards-conforming stlport4 library is ++ # incompatible with the Cstd library. Avoid specifying ++ # it if it's in CXXFLAGS. Ignore libCrun as ++ # -library=stlport4 depends on it. ++ case " $CXX $CXXFLAGS " in ++ *" -library=stlport4 "*) ++ solaris_use_stlport4=yes ++ ;; ++ esac ++ if test "$solaris_use_stlport4" != yes; then ++ _LT_AC_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' ++ fi ++ ;; ++ esac ++ ;; ++ + solaris*) + case $cc_basename in + CC*) ++ # The more standards-conforming stlport4 library is ++ # incompatible with the Cstd library. Avoid specifying ++ # it if it's in CXXFLAGS. Ignore libCrun as ++ # -library=stlport4 depends on it. ++ case " $CXX $CXXFLAGS " in ++ *" -library=stlport4 "*) ++ solaris_use_stlport4=yes ++ ;; ++ esac ++ + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. +- _LT_AC_TAGVAR(postdeps,$1)='-lCstd -lCrun' ++ if test "$solaris_use_stlport4" != yes; then ++ _LT_AC_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' ++ fi + ;; + esac + ;; + esac + ]) +- + case " $_LT_AC_TAGVAR(postdeps, $1) " in + *" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;; + esac + ])# AC_LIBTOOL_POSTDEP_PREDEP + + # AC_LIBTOOL_LANG_F77_CONFIG + # -------------------------- + # Ensure that the configuration vars for the C compiler are +@@ -3925,20 +4094,27 @@ _LT_AC_TAGVAR(enable_shared_with_static_ + # Source file extension for f77 test sources. + ac_ext=f + + # Object file extension for compiled f77 test sources. + objext=o + _LT_AC_TAGVAR(objext, $1)=$objext + + # Code to be used in simple compile tests +-lt_simple_compile_test_code=" subroutine t\n return\n end\n" ++lt_simple_compile_test_code="\ ++ subroutine t ++ return ++ end ++" + + # Code to be used in simple link tests +-lt_simple_link_test_code=" program t\n end\n" ++lt_simple_link_test_code="\ ++ program t ++ end ++" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_AC_SYS_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + +@@ -3960,17 +4136,17 @@ test "$can_build_shared" = "no" && enabl + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; +-aix4* | aix5*) ++aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) +@@ -4007,20 +4183,20 @@ AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG], + # Source file extension for Java test sources. + ac_ext=java + + # Object file extension for compiled Java test sources. + objext=o + _LT_AC_TAGVAR(objext, $1)=$objext + + # Code to be used in simple compile tests +-lt_simple_compile_test_code="class foo {}\n" ++lt_simple_compile_test_code="class foo {}" + + # Code to be used in simple link tests +-lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }\n' ++lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_AC_SYS_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + +@@ -4063,17 +4239,17 @@ AC_DEFUN([_LT_AC_LANG_RC_CONFIG], + # Source file extension for RC test sources. + ac_ext=rc + + # Object file extension for compiled RC test sources. + objext=o + _LT_AC_TAGVAR(objext, $1)=$objext + + # Code to be used in simple compile tests +-lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n' ++lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + + # Code to be used in simple link tests + lt_simple_link_test_code="$lt_simple_compile_test_code" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_AC_SYS_COMPILER + + # save warnings/boilerplate of simple test code +@@ -4137,31 +4313,33 @@ if test -f "$ltmain"; then + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) \ + _LT_AC_TAGVAR(old_archive_cmds, $1) \ + _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) \ + _LT_AC_TAGVAR(predep_objects, $1) \ + _LT_AC_TAGVAR(postdep_objects, $1) \ + _LT_AC_TAGVAR(predeps, $1) \ + _LT_AC_TAGVAR(postdeps, $1) \ + _LT_AC_TAGVAR(compiler_lib_search_path, $1) \ ++ _LT_AC_TAGVAR(compiler_lib_search_dirs, $1) \ + _LT_AC_TAGVAR(archive_cmds, $1) \ + _LT_AC_TAGVAR(archive_expsym_cmds, $1) \ + _LT_AC_TAGVAR(postinstall_cmds, $1) \ + _LT_AC_TAGVAR(postuninstall_cmds, $1) \ + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) \ + _LT_AC_TAGVAR(allow_undefined_flag, $1) \ + _LT_AC_TAGVAR(no_undefined_flag, $1) \ + _LT_AC_TAGVAR(export_symbols_cmds, $1) \ + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) \ + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) \ + _LT_AC_TAGVAR(hardcode_libdir_separator, $1) \ + _LT_AC_TAGVAR(hardcode_automatic, $1) \ + _LT_AC_TAGVAR(module_cmds, $1) \ + _LT_AC_TAGVAR(module_expsym_cmds, $1) \ + _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) \ ++ _LT_AC_TAGVAR(fix_srcfile_path, $1) \ + _LT_AC_TAGVAR(exclude_expsyms, $1) \ + _LT_AC_TAGVAR(include_expsyms, $1); do + + case $var in + _LT_AC_TAGVAR(old_archive_cmds, $1) | \ + _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) | \ + _LT_AC_TAGVAR(archive_cmds, $1) | \ + _LT_AC_TAGVAR(archive_expsym_cmds, $1) | \ +@@ -4198,17 +4376,17 @@ ifelse([$1], [], + cat <<__EOF__ >> "$cfgfile" + ifelse([$1], [], + [#! $SHELL + + # `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. + # Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) + # NOTE: Changes made to this file will be lost: look at ltmain.sh. + # +-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 ++# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 + # Free Software Foundation, Inc. + # + # This file is part of GNU Libtool: + # Originally by Gordon Matzigkeit , 1996 + # + # This program is free software; you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation; either version 2 of the License, or +@@ -4435,16 +4613,20 @@ postdep_objects=$lt_[]_LT_AC_TAGVAR(post + # Dependencies to place before the objects being linked to create a + # shared library. + predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) + + # Dependencies to place after the objects being linked to create a + # shared library. + postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) + ++# The directories searched by this compiler when creating a shared ++# library ++compiler_lib_search_dirs=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_dirs, $1) ++ + # The library search path used internally by the compiler when linking + # a shared library. + compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) + + # Method to check whether dependent libraries are shared objects. + deplibs_check_method=$lt_deplibs_check_method + + # Command to use when deplibs_check_method == file_magic. +@@ -4523,17 +4705,17 @@ link_all_deplibs=$_LT_AC_TAGVAR(link_all + + # Compile-time system search path for libraries + sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + + # Run-time system search path for libraries + sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + + # Fix the shell variable \$srcfile for the compiler. +-fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)" ++fix_srcfile_path=$lt_fix_srcfile_path + + # Set to yes if exported symbols are required. + always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) + + # The commands to list exported symbols. + export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1) + + # The commands to extract the exported symbol list from a shared archive. +@@ -4606,16 +4788,17 @@ if test "$GCC" = yes; then + fi + ])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI + + + # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE + # --------------------------------- + AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], + [AC_REQUIRE([AC_CANONICAL_HOST]) ++AC_REQUIRE([LT_AC_PROG_SED]) + AC_REQUIRE([AC_PROG_NM]) + AC_REQUIRE([AC_OBJEXT]) + # Check for command to grab the raw symbol name followed by C symbol from nm. + AC_MSG_CHECKING([command to parse $NM output from $compiler object]) + AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], + [ + # These are sane defaults that work on at least a few old systems. + # [They come from Ultrix. What could be older than Ultrix?!! ;)] +@@ -4642,17 +4825,17 @@ cygwin* | mingw* | pw32*) + ;; + hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +-linux*) ++linux* | k*bsd*-gnu) + if test "$host_cpu" = ia64; then + symcode='[[ABCDGIRSTW]]' + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + fi + ;; + irix* | nonstopux*) + symcode='[[BCDEGRST]]' +@@ -4783,17 +4966,17 @@ EOF + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi +- rm -f conftest* conftst* ++ rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi + done +@@ -4832,34 +5015,37 @@ AC_MSG_CHECKING([for $compiler option to + fi + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; +- beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) ++ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; +- mingw* | os2* | pw32*) ++ mingw* | cygwin* | os2* | pw32*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). +- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' ++ # Although the cygwin gcc ignores -fPIC, still need this for old-style ++ # (--disable-auto-import) libraries ++ m4_if([$1], [GCJ], [], ++ [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; +- interix3*) ++ interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; +@@ -4875,17 +5061,17 @@ AC_MSG_CHECKING([for $compiler option to + esac + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in +- aix4* | aix5*) ++ aix[[4-9]]*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; +@@ -4915,17 +5101,17 @@ AC_MSG_CHECKING([for $compiler option to + ghcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; +- freebsd* | kfreebsd*-gnu | dragonfly*) ++ freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then +@@ -4958,43 +5144,51 @@ AC_MSG_CHECKING([for $compiler option to + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; +- linux*) ++ linux* | k*bsd*-gnu) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + icpc* | ecpc*) + # Intel C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; +- pgCC*) ++ pgCC* | pgcpp*) + # Portland Group C++ compiler. + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) ++ case `$CC -V 2>&1 | sed 5q` in ++ *Sun\ C*) ++ # Sun C++ 5.9 ++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ++ ;; ++ esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) +@@ -5105,33 +5299,36 @@ AC_MSG_CHECKING([for $compiler option to + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + +- beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) ++ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + +- mingw* | pw32* | os2*) ++ mingw* | cygwin* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). +- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' ++ # Although the cygwin gcc ignores -fPIC, still need this for old-style ++ # (--disable-auto-import) libraries ++ m4_if([$1], [GCJ], [], ++ [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + +- interix3*) ++ interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no +@@ -5179,20 +5376,21 @@ AC_MSG_CHECKING([for $compiler option to + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + +- mingw* | pw32* | os2*) ++ mingw* | cygwin* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). +- _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' ++ m4_if([$1], [GCJ], [], ++ [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + + hpux9* | hpux10* | hpux11*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) +@@ -5212,17 +5410,17 @@ AC_MSG_CHECKING([for $compiler option to + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + newsos6) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + +- linux*) ++ linux* | k*bsd*-gnu) + case $cc_basename in + icc* | ecc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, +@@ -5231,25 +5429,45 @@ AC_MSG_CHECKING([for $compiler option to + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; ++ *) ++ case `$CC -V 2>&1 | sed 5q` in ++ *Sun\ C*) ++ # Sun C 5.9 ++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ++ ;; ++ *Sun\ F*) ++ # Sun Fortran 8.3 passes all unrecognized flags to the linker ++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='' ++ ;; ++ esac ++ ;; + esac + ;; + + osf3* | osf4* | osf5*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + ++ rdos*) ++ _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ++ ;; ++ + solaris*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; +@@ -5299,17 +5517,17 @@ AC_MSG_CHECKING([for $compiler option to + ]) + AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) + + # + # Check to make sure the PIC flag actually works. + # + if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then + AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], +- _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1), ++ _LT_AC_TAGVAR(lt_cv_prog_compiler_pic_works, $1), + [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) + fi +@@ -5323,50 +5541,52 @@ case $host_os in + ;; + esac + + # + # Check to make sure the static flag actually works. + # + wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_AC_TAGVAR(lt_prog_compiler_static, $1)\" + AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], +- _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), ++ _LT_AC_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) + ]) + + + # AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) + # ------------------------------------ + # See if the linker supports building shared libraries. + AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], +-[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) ++[AC_REQUIRE([LT_AC_PROG_SED])dnl ++AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + ifelse([$1],[CXX],[ + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in +- aix4* | aix5*) ++ aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw*) +- _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([[^ ]]*\) [[^ ]]*/\1 DATA/;/^I /d;/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' ++ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + ;; + *) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac ++ _LT_AC_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + ],[ + runpath_var= + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)= + _LT_AC_TAGVAR(archive_expsym_cmds, $1)= + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)= + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)= +@@ -5387,22 +5607,24 @@ ifelse([$1],[CXX],[ + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_AC_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. +- _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_" ++ _LT_AC_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. ++ # Exclude shared library initialization/finalization symbols. ++dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + _LT_CC_BASENAME([$compiler]) + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. +@@ -5442,17 +5664,17 @@ ifelse([$1],[CXX],[ + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in +- aix3* | aix4* | aix5*) ++ aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + + *** Warning: the GNU linker, at least up to release 2.9.1, is reported + *** to be unable to reliably create shared libraries on AIX. + *** Therefore, libtool is disabling shared libraries support. If you +@@ -5490,17 +5712,17 @@ EOF + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes +- _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' ++ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else +@@ -5508,32 +5730,32 @@ EOF + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + +- interix3*) ++ interix[[3-9]]*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + +- linux*) ++ gnu* | linux* | k*bsd*-gnu) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers +@@ -5541,23 +5763,32 @@ EOF + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac +- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' ++ case `$CC -V 2>&1 | sed 5q` in ++ *Sun\ C*) # Sun C 5.9 ++ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' ++ tmp_sharedflag='-G' ;; ++ *Sun\ F*) # Sun Fortran 8.3 ++ tmp_sharedflag='-G' ;; ++ *) ++ tmp_sharedflag='-shared' ;; ++ esac ++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ +- $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' ++ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then +@@ -5587,17 +5818,17 @@ EOF + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in +- *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) ++ *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + + *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not + *** reliably create shared libraries on SCO systems. Therefore, libtool + *** is disabling shared libraries support. We urge you to upgrade GNU + *** binutils to release 2.16.91.0.3 or newer. Another option is to modify + *** your PATH or compiler configuration so that the native linker is +@@ -5652,17 +5883,17 @@ _LT_EOF + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + +- aix4* | aix5*) ++ aix[[4-9]]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. +@@ -5672,17 +5903,17 @@ _LT_EOF + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. +- case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) ++ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac +@@ -5706,17 +5937,17 @@ _LT_EOF + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 +- _LT_AC_TAGVAR(hardcode_direct, $1)=yes ++ : + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' +@@ -5799,17 +6030,17 @@ _LT_EOF + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. +- _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs' ++ _LT_AC_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' +@@ -5832,29 +6063,28 @@ _LT_EOF + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' +- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' +- _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' +- # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds +- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' +- _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ++ _LT_AC_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" ++ _LT_AC_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" ++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" ++ _LT_AC_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' +- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' ++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds +- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; +@@ -5884,17 +6114,17 @@ _LT_EOF + freebsd2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. +- freebsd* | kfreebsd*-gnu | dragonfly*) ++ freebsd* | dragonfly*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then +@@ -6006,34 +6236,38 @@ _LT_EOF + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + openbsd*) +- _LT_AC_TAGVAR(hardcode_direct, $1)=yes +- _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no +- if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then +- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' +- _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' +- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' +- _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ++ if test -f /usr/libexec/ld.so; then ++ _LT_AC_TAGVAR(hardcode_direct, $1)=yes ++ _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ++ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then ++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ++ _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' ++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' ++ _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ++ else ++ case $host_os in ++ openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) ++ _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' ++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' ++ ;; ++ *) ++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ++ _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' ++ ;; ++ esac ++ fi + else +- case $host_os in +- openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) +- _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' +- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' +- ;; +- *) +- _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' +- _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' +- ;; +- esac ++ _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' +@@ -6082,27 +6316,26 @@ _LT_EOF + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) +- # The compiler driver will combine linker options so we +- # cannot just pass the convience library names through +- # without $wl, iff we do not link with $LD. +- # Luckily, gcc supports the same syntax we need for Sun Studio. ++ # The compiler driver will combine and reorder linker options, ++ # but understands `-z linker_flag'. GCC discards it without `$wl', ++ # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) +- case $wlarc in +- '') +- _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; +- *) +- _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; +- esac ;; ++ if test "$GCC" = yes; then ++ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ++ else ++ _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ++ fi ++ ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. +@@ -6149,17 +6382,17 @@ _LT_EOF + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + +- sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7*) ++ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' +@@ -6224,17 +6457,17 @@ x|xyes) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_MSG_CHECKING([whether -lc should be explicitly linked in]) + $rm conftest* +- printf "$lt_simple_compile_test_code" > conftest.$ac_ext ++ echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) +@@ -6327,16 +6560,40 @@ AC_DEFUN([LT_AC_PROG_GCJ], + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS) + ]) + + AC_DEFUN([LT_AC_PROG_RC], + [AC_CHECK_TOOL(RC, windres, no) + ]) + ++ ++# Cheap backport of AS_EXECUTABLE_P and required macros ++# from Autoconf 2.59; we should not use $as_executable_p directly. ++ ++# _AS_TEST_PREPARE ++# ---------------- ++m4_ifndef([_AS_TEST_PREPARE], ++[m4_defun([_AS_TEST_PREPARE], ++[if test -x / >/dev/null 2>&1; then ++ as_executable_p='test -x' ++else ++ as_executable_p='test -f' ++fi ++])])# _AS_TEST_PREPARE ++ ++# AS_EXECUTABLE_P ++# --------------- ++# Check whether a file is executable. ++m4_ifndef([AS_EXECUTABLE_P], ++[m4_defun([AS_EXECUTABLE_P], ++[AS_REQUIRE([_AS_TEST_PREPARE])dnl ++$as_executable_p $1[]dnl ++])])# AS_EXECUTABLE_P ++ + # NOTE: This macro has been submitted for inclusion into # + # GNU Autoconf as AC_PROG_SED. When it is available in # + # a released version of Autoconf we should remove this # + # macro and use it instead. # + # LT_AC_PROG_SED + # -------------- + # Check for a fully-functional sed program, that truncates + # as few characters as possible. Prefer GNU sed if found. +@@ -6347,22 +6604,23 @@ AC_CACHE_VAL(lt_cv_path_SED, + # Then use that list of sed's as ones to test for truncation. + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR + for as_dir in $PATH + do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do +- if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then ++ if AS_EXECUTABLE_P(["$as_dir/$lt_ac_prog$ac_exec_ext"]); then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done + done ++IFS=$as_save_IFS + lt_ac_max=0 + lt_ac_count=0 + # Add /usr/xpg4/bin/sed as it is typically found on Solaris + # along with /bin/sed that truncates output. + for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 +@@ -6385,16 +6643,17 @@ for lt_ac_sed in $lt_ac_sed_list /usr/xp + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done + done + ]) + SED=$lt_cv_path_SED ++AC_SUBST([SED]) + AC_MSG_RESULT([$SED]) + ]) + + # Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc. + # + # This file is free software; the Free Software Foundation + # gives unlimited permission to copy and/or distribute it, + # with or without modifications, as long as this notice is preserved. +diff --git a/toolkit/crashreporter/google-breakpad/configure b/toolkit/crashreporter/google-breakpad/configure +--- a/toolkit/crashreporter/google-breakpad/configure ++++ b/toolkit/crashreporter/google-breakpad/configure +@@ -854,22 +854,25 @@ am__fastdepCXX_FALSE + build + build_cpu + build_vendor + build_os + host + host_cpu + host_vendor + host_os ++SED + GREP + EGREP + LN_S + ECHO + AR + RANLIB ++DSYMUTIL ++NMEDIT + CXXCPP + F77 + FFLAGS + ac_ct_F77 + LIBTOOL + LIBTOOL_DEPS + SELFTEST_TRUE + SELFTEST_FALSE +@@ -4459,22 +4462,23 @@ else + # Then use that list of sed's as ones to test for truncation. + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR + for as_dir in $PATH + do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do +- if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then ++ if { test -f "$as_dir/$lt_ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$lt_ac_prog$ac_exec_ext"; }; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done + done ++IFS=$as_save_IFS + lt_ac_max=0 + lt_ac_count=0 + # Add /usr/xpg4/bin/sed as it is typically found on Solaris + # along with /bin/sed that truncates output. + for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 +@@ -4499,16 +4503,17 @@ for lt_ac_sed in $lt_ac_sed_list /usr/xp + lt_cv_path_SED=$lt_ac_sed + fi + done + done + + fi + + SED=$lt_cv_path_SED ++ + { echo "$as_me:$LINENO: result: $SED" >&5 + echo "${ECHO_T}$SED" >&6; } + + { echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 + echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; } + if test "${ac_cv_path_GREP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 + else +@@ -4860,18 +4865,18 @@ LN_S=$as_ln_s + if test "$LN_S" = "ln -s"; then + { echo "$as_me:$LINENO: result: yes" >&5 + echo "${ECHO_T}yes" >&6; } + else + { echo "$as_me:$LINENO: result: no, using $LN_S" >&5 + echo "${ECHO_T}no, using $LN_S" >&6; } + fi + +-{ echo "$as_me:$LINENO: checking how to recognise dependent libraries" >&5 +-echo $ECHO_N "checking how to recognise dependent libraries... $ECHO_C" >&6; } ++{ echo "$as_me:$LINENO: checking how to recognize dependent libraries" >&5 ++echo $ECHO_N "checking how to recognize dependent libraries... $ECHO_C" >&6; } + if test "${lt_cv_deplibs_check_method+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 + else + lt_cv_file_magic_cmd='$MAGIC_CMD' + lt_cv_file_magic_test_file= + lt_cv_deplibs_check_method='unknown' + # Need to set the preceding variable on all platforms that support + # interlibrary dependencies. +@@ -4880,17 +4885,17 @@ lt_cv_deplibs_check_method='unknown' + # 'pass_all' -- all dependencies passed with no checks. + # 'test_compile' -- check by making test program. + # 'file_magic [[regex]]' -- check by looking for files in library path + # which responds to the $file_magic_cmd with a given extended regex. + # If you have `file' or equivalent on your system and you're not sure + # whether `pass_all' will *always* work, you probably want this one. + + case $host_os in +-aix4* | aix5*) ++aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + + beos*) + lt_cv_deplibs_check_method=pass_all + ;; + + bsdi[45]*) +@@ -4902,26 +4907,32 @@ bsdi[45]*) + cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + + mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by +- # func_win32_libid shell function, so use a weaker test based on 'objdump'. +- lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' +- lt_cv_file_magic_cmd='$OBJDUMP -f' ++ # func_win32_libid shell function, so use a weaker test based on 'objdump', ++ # unless we find 'file', for example because we are cross-compiling. ++ if ( file / ) >/dev/null 2>&1; then ++ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' ++ lt_cv_file_magic_cmd='func_win32_libid' ++ else ++ lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' ++ lt_cv_file_magic_cmd='$OBJDUMP -f' ++ fi + ;; + + darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +-freebsd* | kfreebsd*-gnu | dragonfly*) ++freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` +@@ -4949,33 +4960,33 @@ hpux10.20* | hpux11*) + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +-interix3*) ++interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + + irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + + # This must be Linux ELF. +-linux*) ++linux* | k*bsd*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' +@@ -4999,16 +5010,20 @@ openbsd*) + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + + osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + ++rdos*) ++ lt_cv_deplibs_check_method=pass_all ++ ;; ++ + solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + + sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' +@@ -5086,17 +5101,17 @@ ia64-*-hpux*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; + *-*-irix6*) + # Find out which ABI we are using. +- echo '#line 5094 "configure"' > conftest.$ac_ext ++ echo '#line 5109 "configure"' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) +@@ -5121,43 +5136,50 @@ ia64-*-hpux*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +-x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) ++x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ ++s390*-*linux*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in ++ x86_64-*kfreebsd*-gnu) ++ LD="${LD-ld} -m elf_i386_fbsd" ++ ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in ++ x86_64-*kfreebsd*-gnu) ++ LD="${LD-ld} -m elf_x86_64_fbsd" ++ ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*) + LD="${LD-ld} -m elf64_s390" +@@ -5251,17 +5273,21 @@ sparc*-*solaris*) + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; +- *) LD="${LD-ld} -64" ;; ++ *) ++ if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then ++ LD="${LD-ld} -64" ++ fi ++ ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + + +@@ -6151,17 +6177,16 @@ ac_ext=c + ac_cpp='$CPP $CPPFLAGS' + ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' + ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' + ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + # Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! +- + # find the maximum length of command line arguments + { echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5 + echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6; } + if test "${lt_cv_sys_max_cmd_len+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 + else + i=0 + teststring="ABCD" +@@ -6238,50 +6263,54 @@ else + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) +- # If test is not a shell built-in, we'll probably end up computing a +- # maximum length that is only half of the actual maximum length, but +- # we can't tell. +- SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} +- while (test "X"`$SHELL $0 --fallback-echo "X$teststring" 2>/dev/null` \ ++ lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` ++ if test -n "$lt_cv_sys_max_cmd_len"; then ++ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` ++ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ++ else ++ SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} ++ while (test "X"`$SHELL $0 --fallback-echo "X$teststring" 2>/dev/null` \ + = "XX$teststring") >/dev/null 2>&1 && +- new_result=`expr "X$teststring" : ".*" 2>&1` && +- lt_cv_sys_max_cmd_len=$new_result && +- test $i != 17 # 1/2 MB should be enough +- do +- i=`expr $i + 1` +- teststring=$teststring$teststring +- done +- teststring= +- # Add a significant safety factor because C++ compilers can tack on massive +- # amounts of additional arguments before passing them to the linker. +- # It appears as though 1/2 is a usable value. +- lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` ++ new_result=`expr "X$teststring" : ".*" 2>&1` && ++ lt_cv_sys_max_cmd_len=$new_result && ++ test $i != 17 # 1/2 MB should be enough ++ do ++ i=`expr $i + 1` ++ teststring=$teststring$teststring ++ done ++ teststring= ++ # Add a significant safety factor because C++ compilers can tack on massive ++ # amounts of additional arguments before passing them to the linker. ++ # It appears as though 1/2 is a usable value. ++ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` ++ fi + ;; + esac + + fi + + if test -n $lt_cv_sys_max_cmd_len ; then + { echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5 + echo "${ECHO_T}$lt_cv_sys_max_cmd_len" >&6; } + else + { echo "$as_me:$LINENO: result: none" >&5 + echo "${ECHO_T}none" >&6; } + fi + + + + ++ + # Check for command to grab the raw symbol name followed by C symbol from nm. + { echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5 + echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6; } + if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 + else + + # These are sane defaults that work on at least a few old systems. +@@ -6309,17 +6338,17 @@ cygwin* | mingw* | pw32*) + ;; + hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[ABCDEGRST]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +-linux*) ++linux* | k*bsd*-gnu) + if test "$host_cpu" = ia64; then + symcode='[ABCDGIRSTW]' + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + fi + ;; + irix* | nonstopux*) + symcode='[BCDEGRST]' +@@ -6462,17 +6491,17 @@ EOF + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi +- rm -f conftest* conftst* ++ rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi + done +@@ -6860,17 +6889,17 @@ test -z "$MAGIC_CMD" && MAGIC_CMD=file + test -z "$NM" && NM=nm + test -z "$SED" && SED=sed + test -z "$OBJDUMP" && OBJDUMP=objdump + test -z "$RANLIB" && RANLIB=: + test -z "$STRIP" && STRIP=: + test -z "$ac_objext" && ac_objext=o + + # Determine commands to create old-style static archives. +-old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' ++old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' + old_postinstall_cmds='chmod 644 $oldlib' + old_postuninstall_cmds= + + if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; +@@ -7022,16 +7051,328 @@ fi + MAGIC_CMD=: + fi + fi + + fi + ;; + esac + ++ ++ case $host_os in ++ rhapsody* | darwin*) ++ if test -n "$ac_tool_prefix"; then ++ # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. ++set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 ++{ echo "$as_me:$LINENO: checking for $ac_word" >&5 ++echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } ++if test "${ac_cv_prog_DSYMUTIL+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ if test -n "$DSYMUTIL"; then ++ ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. ++else ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ++ ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" ++ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++done ++IFS=$as_save_IFS ++ ++fi ++fi ++DSYMUTIL=$ac_cv_prog_DSYMUTIL ++if test -n "$DSYMUTIL"; then ++ { echo "$as_me:$LINENO: result: $DSYMUTIL" >&5 ++echo "${ECHO_T}$DSYMUTIL" >&6; } ++else ++ { echo "$as_me:$LINENO: result: no" >&5 ++echo "${ECHO_T}no" >&6; } ++fi ++ ++ ++fi ++if test -z "$ac_cv_prog_DSYMUTIL"; then ++ ac_ct_DSYMUTIL=$DSYMUTIL ++ # Extract the first word of "dsymutil", so it can be a program name with args. ++set dummy dsymutil; ac_word=$2 ++{ echo "$as_me:$LINENO: checking for $ac_word" >&5 ++echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } ++if test "${ac_cv_prog_ac_ct_DSYMUTIL+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ if test -n "$ac_ct_DSYMUTIL"; then ++ ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. ++else ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ++ ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" ++ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++done ++IFS=$as_save_IFS ++ ++fi ++fi ++ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL ++if test -n "$ac_ct_DSYMUTIL"; then ++ { echo "$as_me:$LINENO: result: $ac_ct_DSYMUTIL" >&5 ++echo "${ECHO_T}$ac_ct_DSYMUTIL" >&6; } ++else ++ { echo "$as_me:$LINENO: result: no" >&5 ++echo "${ECHO_T}no" >&6; } ++fi ++ ++ if test "x$ac_ct_DSYMUTIL" = x; then ++ DSYMUTIL=":" ++ else ++ case $cross_compiling:$ac_tool_warned in ++yes:) ++{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools ++whose name does not start with the host triplet. If you think this ++configuration is useful to you, please write to autoconf@gnu.org." >&5 ++echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools ++whose name does not start with the host triplet. If you think this ++configuration is useful to you, please write to autoconf@gnu.org." >&2;} ++ac_tool_warned=yes ;; ++esac ++ DSYMUTIL=$ac_ct_DSYMUTIL ++ fi ++else ++ DSYMUTIL="$ac_cv_prog_DSYMUTIL" ++fi ++ ++ if test -n "$ac_tool_prefix"; then ++ # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. ++set dummy ${ac_tool_prefix}nmedit; ac_word=$2 ++{ echo "$as_me:$LINENO: checking for $ac_word" >&5 ++echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } ++if test "${ac_cv_prog_NMEDIT+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ if test -n "$NMEDIT"; then ++ ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. ++else ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ++ ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" ++ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++done ++IFS=$as_save_IFS ++ ++fi ++fi ++NMEDIT=$ac_cv_prog_NMEDIT ++if test -n "$NMEDIT"; then ++ { echo "$as_me:$LINENO: result: $NMEDIT" >&5 ++echo "${ECHO_T}$NMEDIT" >&6; } ++else ++ { echo "$as_me:$LINENO: result: no" >&5 ++echo "${ECHO_T}no" >&6; } ++fi ++ ++ ++fi ++if test -z "$ac_cv_prog_NMEDIT"; then ++ ac_ct_NMEDIT=$NMEDIT ++ # Extract the first word of "nmedit", so it can be a program name with args. ++set dummy nmedit; ac_word=$2 ++{ echo "$as_me:$LINENO: checking for $ac_word" >&5 ++echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } ++if test "${ac_cv_prog_ac_ct_NMEDIT+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ if test -n "$ac_ct_NMEDIT"; then ++ ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. ++else ++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR ++for as_dir in $PATH ++do ++ IFS=$as_save_IFS ++ test -z "$as_dir" && as_dir=. ++ for ac_exec_ext in '' $ac_executable_extensions; do ++ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ++ ac_cv_prog_ac_ct_NMEDIT="nmedit" ++ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 ++ break 2 ++ fi ++done ++done ++IFS=$as_save_IFS ++ ++fi ++fi ++ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT ++if test -n "$ac_ct_NMEDIT"; then ++ { echo "$as_me:$LINENO: result: $ac_ct_NMEDIT" >&5 ++echo "${ECHO_T}$ac_ct_NMEDIT" >&6; } ++else ++ { echo "$as_me:$LINENO: result: no" >&5 ++echo "${ECHO_T}no" >&6; } ++fi ++ ++ if test "x$ac_ct_NMEDIT" = x; then ++ NMEDIT=":" ++ else ++ case $cross_compiling:$ac_tool_warned in ++yes:) ++{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools ++whose name does not start with the host triplet. If you think this ++configuration is useful to you, please write to autoconf@gnu.org." >&5 ++echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools ++whose name does not start with the host triplet. If you think this ++configuration is useful to you, please write to autoconf@gnu.org." >&2;} ++ac_tool_warned=yes ;; ++esac ++ NMEDIT=$ac_ct_NMEDIT ++ fi ++else ++ NMEDIT="$ac_cv_prog_NMEDIT" ++fi ++ ++ ++ { echo "$as_me:$LINENO: checking for -single_module linker flag" >&5 ++echo $ECHO_N "checking for -single_module linker flag... $ECHO_C" >&6; } ++if test "${lt_cv_apple_cc_single_mod+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ lt_cv_apple_cc_single_mod=no ++ if test -z "${LT_MULTI_MODULE}"; then ++ # By default we will add the -single_module flag. You can override ++ # by either setting the environment variable LT_MULTI_MODULE ++ # non-empty at configure time, or by adding -multi_module to the ++ # link flags. ++ echo "int foo(void){return 1;}" > conftest.c ++ $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ ++ -dynamiclib ${wl}-single_module conftest.c ++ if test -f libconftest.dylib; then ++ lt_cv_apple_cc_single_mod=yes ++ rm -rf libconftest.dylib* ++ fi ++ rm conftest.c ++ fi ++fi ++{ echo "$as_me:$LINENO: result: $lt_cv_apple_cc_single_mod" >&5 ++echo "${ECHO_T}$lt_cv_apple_cc_single_mod" >&6; } ++ { echo "$as_me:$LINENO: checking for -exported_symbols_list linker flag" >&5 ++echo $ECHO_N "checking for -exported_symbols_list linker flag... $ECHO_C" >&6; } ++if test "${lt_cv_ld_exported_symbols_list+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ lt_cv_ld_exported_symbols_list=no ++ save_LDFLAGS=$LDFLAGS ++ echo "_main" > conftest.sym ++ LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" ++ cat >conftest.$ac_ext <<_ACEOF ++/* confdefs.h. */ ++_ACEOF ++cat confdefs.h >>conftest.$ac_ext ++cat >>conftest.$ac_ext <<_ACEOF ++/* end confdefs.h. */ ++ ++int ++main () ++{ ++ ++ ; ++ return 0; ++} ++_ACEOF ++rm -f conftest.$ac_objext conftest$ac_exeext ++if { (ac_try="$ac_link" ++case "(($ac_try" in ++ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; ++ *) ac_try_echo=$ac_try;; ++esac ++eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 ++ (eval "$ac_link") 2>conftest.er1 ++ ac_status=$? ++ grep -v '^ *+' conftest.er1 >conftest.err ++ rm -f conftest.er1 ++ cat conftest.err >&5 ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); } && { ++ test -z "$ac_c_werror_flag" || ++ test ! -s conftest.err ++ } && test -s conftest$ac_exeext && ++ $as_test_x conftest$ac_exeext; then ++ lt_cv_ld_exported_symbols_list=yes ++else ++ echo "$as_me: failed program was:" >&5 ++sed 's/^/| /' conftest.$ac_ext >&5 ++ ++ lt_cv_ld_exported_symbols_list=no ++fi ++ ++rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ ++ conftest$ac_exeext conftest.$ac_ext ++ LDFLAGS="$save_LDFLAGS" ++ ++fi ++{ echo "$as_me:$LINENO: result: $lt_cv_ld_exported_symbols_list" >&5 ++echo "${ECHO_T}$lt_cv_ld_exported_symbols_list" >&6; } ++ case $host_os in ++ rhapsody* | darwin1.[0123]) ++ _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; ++ darwin1.*) ++ _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; ++ darwin*) ++ # if running on 10.5 or later, the deployment target defaults ++ # to the OS version, if on x86, and 10.4, the deployment ++ # target defaults to 10.4. Don't you love it? ++ case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in ++ 10.0,*86*-darwin8*|10.0,*-darwin[91]*) ++ _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; ++ 10.[012]*) ++ _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; ++ 10.*) ++ _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; ++ esac ++ ;; ++ esac ++ if test "$lt_cv_apple_cc_single_mod" = "yes"; then ++ _lt_dar_single_mod='$single_module' ++ fi ++ if test "$lt_cv_ld_exported_symbols_list" = "yes"; then ++ _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' ++ else ++ _lt_dar_export_syms="~$NMEDIT -s \$output_objdir/\${libname}-symbols.expsym \${lib}" ++ fi ++ if test "$DSYMUTIL" != ":"; then ++ _lt_dsymutil="~$DSYMUTIL \$lib || :" ++ else ++ _lt_dsymutil= ++ fi ++ ;; ++ esac ++ ++ + enable_dlopen=no + enable_win32_dll=no + + # Check whether --enable-libtool-lock was given. + if test "${enable_libtool_lock+set}" = set; then + enableval=$enable_libtool_lock; + fi + +@@ -7060,76 +7401,76 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu + # Source file extension for C test sources. + ac_ext=c + + # Object file extension for compiled C test sources. + objext=o + objext=$objext + + # Code to be used in simple compile tests +-lt_simple_compile_test_code="int some_variable = 0;\n" ++lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests +-lt_simple_link_test_code='int main(){return(0);}\n' ++lt_simple_link_test_code='int main(){return(0);}' + + + # If no C compiler was specified, use CC. + LTCC=${LTCC-"$CC"} + + # If no C compiler flags were specified, use CFLAGS. + LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + + # Allow CC to be a program name with arguments. + compiler=$CC + + + # save warnings/boilerplate of simple test code + ac_outfile=conftest.$ac_objext +-printf "$lt_simple_compile_test_code" >conftest.$ac_ext ++echo "$lt_simple_compile_test_code" >conftest.$ac_ext + eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err + _lt_compiler_boilerplate=`cat conftest.err` + $rm conftest* + + ac_outfile=conftest.$ac_objext +-printf "$lt_simple_link_test_code" >conftest.$ac_ext ++echo "$lt_simple_link_test_code" >conftest.$ac_ext + eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err + _lt_linker_boilerplate=`cat conftest.err` +-$rm conftest* ++$rm -r conftest* + + + + lt_prog_compiler_no_builtin_flag= + + if test "$GCC" = yes; then + lt_prog_compiler_no_builtin_flag=' -fno-builtin' + + + { echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 + echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6; } + if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 + else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext +- printf "$lt_simple_compile_test_code" > conftest.$ac_ext ++ echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` +- (eval echo "\"\$as_me:7123: $lt_compile\"" >&5) ++ (eval echo "\"\$as_me:7464: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 +- echo "$as_me:7127: \$? = $ac_status" >&5 ++ echo "$as_me:7468: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi +@@ -7170,33 +7511,35 @@ echo $ECHO_N "checking for $compiler opt + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + +- beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) ++ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + +- mingw* | pw32* | os2*) ++ mingw* | cygwin* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). ++ # Although the cygwin gcc ignores -fPIC, still need this for old-style ++ # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + +- interix3*) ++ interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no +@@ -7244,17 +7587,17 @@ echo $ECHO_N "checking for $compiler opt + case $cc_basename in + xlc*) + lt_prog_compiler_pic='-qnocommon' + lt_prog_compiler_wl='-Wl,' + ;; + esac + ;; + +- mingw* | pw32* | os2*) ++ mingw* | cygwin* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but +@@ -7277,17 +7620,17 @@ echo $ECHO_N "checking for $compiler opt + lt_prog_compiler_static='-non_shared' + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + +- linux*) ++ linux* | k*bsd*-gnu) + case $cc_basename in + icc* | ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, +@@ -7296,25 +7639,45 @@ echo $ECHO_N "checking for $compiler opt + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; ++ *) ++ case `$CC -V 2>&1 | sed 5q` in ++ *Sun\ C*) ++ # Sun C 5.9 ++ lt_prog_compiler_pic='-KPIC' ++ lt_prog_compiler_static='-Bstatic' ++ lt_prog_compiler_wl='-Wl,' ++ ;; ++ *Sun\ F*) ++ # Sun Fortran 8.3 passes all unrecognized flags to the linker ++ lt_prog_compiler_pic='-KPIC' ++ lt_prog_compiler_static='-Bstatic' ++ lt_prog_compiler_wl='' ++ ;; ++ esac ++ ;; + esac + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + ++ rdos*) ++ lt_prog_compiler_static='-non_shared' ++ ;; ++ + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; +@@ -7367,53 +7730,53 @@ echo "${ECHO_T}$lt_prog_compiler_pic" >& + + # + # Check to make sure the PIC flag actually works. + # + if test -n "$lt_prog_compiler_pic"; then + + { echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 + echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic works... $ECHO_C" >&6; } +-if test "${lt_prog_compiler_pic_works+set}" = set; then +- echo $ECHO_N "(cached) $ECHO_C" >&6 +-else +- lt_prog_compiler_pic_works=no ++if test "${lt_cv_prog_compiler_pic_works+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext +- printf "$lt_simple_compile_test_code" > conftest.$ac_ext ++ echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` +- (eval echo "\"\$as_me:7391: $lt_compile\"" >&5) ++ (eval echo "\"\$as_me:7754: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 +- echo "$as_me:7395: \$? = $ac_status" >&5 ++ echo "$as_me:7758: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then +- lt_prog_compiler_pic_works=yes ++ lt_cv_prog_compiler_pic_works=yes + fi + fi + $rm conftest* + + fi +-{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works" >&5 +-echo "${ECHO_T}$lt_prog_compiler_pic_works" >&6; } +- +-if test x"$lt_prog_compiler_pic_works" = xyes; then ++{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_pic_works" >&5 ++echo "${ECHO_T}$lt_cv_prog_compiler_pic_works" >&6; } ++ ++if test x"$lt_cv_prog_compiler_pic_works" = xyes; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac + else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no + fi +@@ -7430,78 +7793,78 @@ case $host_os in + esac + + # + # Check to make sure the static flag actually works. + # + wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" + { echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 + echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } +-if test "${lt_prog_compiler_static_works+set}" = set; then +- echo $ECHO_N "(cached) $ECHO_C" >&6 +-else +- lt_prog_compiler_static_works=no ++if test "${lt_cv_prog_compiler_static_works+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ lt_cv_prog_compiler_static_works=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" +- printf "$lt_simple_link_test_code" > conftest.$ac_ext ++ echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then +- lt_prog_compiler_static_works=yes ++ lt_cv_prog_compiler_static_works=yes + fi + else +- lt_prog_compiler_static_works=yes ++ lt_cv_prog_compiler_static_works=yes + fi + fi +- $rm conftest* ++ $rm -r conftest* + LDFLAGS="$save_LDFLAGS" + + fi +-{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5 +-echo "${ECHO_T}$lt_prog_compiler_static_works" >&6; } +- +-if test x"$lt_prog_compiler_static_works" = xyes; then ++{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_static_works" >&5 ++echo "${ECHO_T}$lt_cv_prog_compiler_static_works" >&6; } ++ ++if test x"$lt_cv_prog_compiler_static_works" = xyes; then + : + else + lt_prog_compiler_static= + fi + + + { echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 + echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } + if test "${lt_cv_prog_compiler_c_o+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 + else + lt_cv_prog_compiler_c_o=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out +- printf "$lt_simple_compile_test_code" > conftest.$ac_ext ++ echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` +- (eval echo "\"\$as_me:7495: $lt_compile\"" >&5) ++ (eval echo "\"\$as_me:7858: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 +- echo "$as_me:7499: \$? = $ac_status" >&5 ++ echo "$as_me:7862: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes +@@ -7571,22 +7934,23 @@ echo $ECHO_N "checking whether the $comp + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. +- exclude_expsyms="_GLOBAL_OFFSET_TABLE_" ++ exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. ++ # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; +@@ -7635,17 +7999,17 @@ cc_basename=`$echo "X$cc_temp" | $Xsed - + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in +- aix3* | aix4* | aix5*) ++ aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + cat <&2 + + *** Warning: the GNU linker, at least up to release 2.9.1, is reported + *** to be unable to reliably create shared libraries on AIX. + *** Therefore, libtool is disabling shared libraries support. If you +@@ -7683,17 +8047,17 @@ EOF + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes +- export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' ++ export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else +@@ -7701,32 +8065,32 @@ EOF + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + +- interix3*) ++ interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + +- linux*) ++ gnu* | linux* | k*bsd*-gnu) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers +@@ -7734,23 +8098,32 @@ EOF + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac +- archive_cmds='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' ++ case `$CC -V 2>&1 | sed 5q` in ++ *Sun\ C*) # Sun C 5.9 ++ whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' ++ tmp_sharedflag='-G' ;; ++ *Sun\ F*) # Sun Fortran 8.3 ++ tmp_sharedflag='-G' ;; ++ *) ++ tmp_sharedflag='-shared' ;; ++ esac ++ archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ +- $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' ++ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then +@@ -7845,17 +8218,17 @@ _LT_EOF + hardcode_minus_L=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + +- aix4* | aix5*) ++ aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. +@@ -7865,17 +8238,17 @@ _LT_EOF + else + export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. +- case $host_os in aix4.[23]|aix4.[23].*|aix5*) ++ case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac +@@ -7899,17 +8272,17 @@ _LT_EOF + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 +- hardcode_direct=yes ++ : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' +@@ -7973,21 +8346,28 @@ eval "echo \"\$as_me:$LINENO: $ac_try_ec + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + +-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +-}'` ++lt_aix_libpath_sed=' ++ /Import File Strings/,/^$/ { ++ /^0/ { ++ s/^0 *\(.*\)$/\1/ ++ p ++ } ++ }' ++aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. +-if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +-}'`; fi ++if test -z "$aix_libpath"; then ++ aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` ++fi + else + echo "$as_me: failed program was:" >&5 + sed 's/^/| /' conftest.$ac_ext >&5 + + + fi + + rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ +@@ -8032,21 +8412,28 @@ eval "echo \"\$as_me:$LINENO: $ac_try_ec + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + +-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +-}'` ++lt_aix_libpath_sed=' ++ /Import File Strings/,/^$/ { ++ /^0/ { ++ s/^0 *\(.*\)$/\1/ ++ p ++ } ++ }' ++aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. +-if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +-}'`; fi ++if test -z "$aix_libpath"; then ++ aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` ++fi + else + echo "$as_me: failed program was:" >&5 + sed 's/^/| /' conftest.$ac_ext >&5 + + + fi + + rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ +@@ -8090,17 +8477,17 @@ if test -z "$aix_libpath"; then aix_libp + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_From_new_cmds='true' + # FIXME: Should let the user specify the lib program. +- old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs' ++ old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag='${wl}-undefined ${wl}suppress' +@@ -8123,29 +8510,28 @@ if test -z "$aix_libpath"; then aix_libp + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + whole_archive_flag_spec='' + link_all_deplibs=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' +- archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' +- module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' +- # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds +- archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' +- module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ++ archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" ++ module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" ++ archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" ++ module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' +- archive_cmds='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' ++ archive_cmds='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' + module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds +- archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ++ archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs=no + ;; + esac + fi + ;; +@@ -8175,17 +8561,17 @@ if test -z "$aix_libpath"; then aix_libp + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. +- freebsd* | kfreebsd*-gnu | dragonfly*) ++ freebsd* | dragonfly*) + archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test "$GCC" = yes; then +@@ -8297,34 +8683,38 @@ if test -z "$aix_libpath"; then aix_libp + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + openbsd*) +- hardcode_direct=yes +- hardcode_shlibpath_var=no +- if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then +- archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' +- archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' +- hardcode_libdir_flag_spec='${wl}-rpath,$libdir' +- export_dynamic_flag_spec='${wl}-E' +- else +- case $host_os in +- openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) +- archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' +- hardcode_libdir_flag_spec='-R$libdir' +- ;; +- *) +- archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' +- hardcode_libdir_flag_spec='${wl}-rpath,$libdir' +- ;; +- esac ++ if test -f /usr/libexec/ld.so; then ++ hardcode_direct=yes ++ hardcode_shlibpath_var=no ++ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then ++ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ++ archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' ++ hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ++ export_dynamic_flag_spec='${wl}-E' ++ else ++ case $host_os in ++ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) ++ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' ++ hardcode_libdir_flag_spec='-R$libdir' ++ ;; ++ *) ++ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ++ hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ++ ;; ++ esac ++ fi ++ else ++ ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' +@@ -8373,27 +8763,26 @@ if test -z "$aix_libpath"; then aix_libp + archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) +- # The compiler driver will combine linker options so we +- # cannot just pass the convience library names through +- # without $wl, iff we do not link with $LD. +- # Luckily, gcc supports the same syntax we need for Sun Studio. ++ # The compiler driver will combine and reorder linker options, ++ # but understands `-z linker_flag'. GCC discards it without `$wl', ++ # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) +- case $wlarc in +- '') +- whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; +- *) +- whole_archive_flag_spec='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; +- esac ;; ++ if test "$GCC" = yes; then ++ whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ++ else ++ whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ++ fi ++ ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. +@@ -8440,17 +8829,17 @@ if test -z "$aix_libpath"; then aix_libp + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + +- sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) ++ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='${wl}-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' +@@ -8517,17 +8906,17 @@ x|xyes) + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 + echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } + $rm conftest* +- printf "$lt_simple_compile_test_code" > conftest.$ac_ext ++ echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest +@@ -8575,27 +8964,65 @@ postinstall_cmds= + postuninstall_cmds= + finish_cmds= + finish_eval= + shlibpath_var= + shlibpath_overrides_runpath=unknown + version_type=none + dynamic_linker="$host_os ld.so" + sys_lib_dlsearch_path_spec="/lib /usr/lib" ++ + if test "$GCC" = yes; then +- sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` +- if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then ++ case $host_os in ++ darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; ++ *) lt_awk_arg="/^libraries:/" ;; ++ esac ++ lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` ++ if echo "$lt_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. +- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` +- else +- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` +- fi ++ lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e 's/;/ /g'` ++ else ++ lt_search_path_spec=`echo "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ++ fi ++ # Ok, now we have the path, separated by spaces, we can step through it ++ # and add multilib dir if necessary. ++ lt_tmp_lt_search_path_spec= ++ lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` ++ for lt_sys_path in $lt_search_path_spec; do ++ if test -d "$lt_sys_path/$lt_multi_os_dir"; then ++ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" ++ else ++ test -d "$lt_sys_path" && \ ++ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" ++ fi ++ done ++ lt_search_path_spec=`echo $lt_tmp_lt_search_path_spec | awk ' ++BEGIN {RS=" "; FS="/|\n";} { ++ lt_foo=""; ++ lt_count=0; ++ for (lt_i = NF; lt_i > 0; lt_i--) { ++ if ($lt_i != "" && $lt_i != ".") { ++ if ($lt_i == "..") { ++ lt_count++; ++ } else { ++ if (lt_count == 0) { ++ lt_foo="/" $lt_i lt_foo; ++ } else { ++ lt_count--; ++ } ++ } ++ } ++ } ++ if (lt_foo != "") { lt_freq[lt_foo]++; } ++ if (lt_freq[lt_foo] == 1) { print lt_foo; } ++}'` ++ sys_lib_search_path_spec=`echo $lt_search_path_spec` + else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + fi + need_lib_prefix=unknown + hardcode_into_libs=no + + # when you set need_version to no, make sure it does not cause -set_version + # flags to be left without arguments +@@ -8606,17 +9033,17 @@ aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +-aix4* | aix5*) ++aix[4-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH +@@ -8745,50 +9172,34 @@ darwin* | rhapsody*) + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +- # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. +- if test "$GCC" = yes; then +- sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` +- else +- sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' +- fi ++ ++ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + + dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + + freebsd1*) + dynamic_linker=no + ;; + +-kfreebsd*-gnu) +- version_type=linux +- need_lib_prefix=no +- need_version=no +- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' +- soname_spec='${libname}${release}${shared_ext}$major' +- shlibpath_var=LD_LIBRARY_PATH +- shlibpath_overrides_runpath=no +- hardcode_into_libs=yes +- dynamic_linker='GNU ld.so' +- ;; +- + freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; +@@ -8816,17 +9227,17 @@ freebsd* | dragonfly*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; +- freebsd*) # from 4.6 on ++ *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + + gnu*) + version_type=linux +@@ -8879,17 +9290,17 @@ hpux9* | hpux10* | hpux11*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +-interix3*) ++interix[3-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no +@@ -8934,57 +9345,45 @@ irix5* | irix6* | nonstopux*) + ;; + + # No shared lib support for Linux oldld, aout, or coff. + linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + + # This must be Linux ELF. +-linux*) ++linux* | k*bsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then +- lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` ++ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +-knetbsd*-gnu) +- version_type=linux +- need_lib_prefix=no +- need_version=no +- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' +- soname_spec='${libname}${release}${shared_ext}$major' +- shlibpath_var=LD_LIBRARY_PATH +- shlibpath_overrides_runpath=no +- hardcode_into_libs=yes +- dynamic_linker='GNU ld.so' +- ;; +- + netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' +@@ -9056,16 +9455,20 @@ osf3* | osf4* | osf5*) + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + ++rdos*) ++ dynamic_linker=no ++ ;; ++ + solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes +@@ -9152,16 +9555,31 @@ uts4*) + *) + dynamic_linker=no + ;; + esac + { echo "$as_me:$LINENO: result: $dynamic_linker" >&5 + echo "${ECHO_T}$dynamic_linker" >&6; } + test "$dynamic_linker" = no && can_build_shared=no + ++if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ lt_cv_sys_lib_search_path_spec="$sys_lib_search_path_spec" ++fi ++ ++sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" ++if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ lt_cv_sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec" ++fi ++ ++sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" ++ + variables_saved_for_relink="PATH $shlibpath_var $runpath_var" + if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" + fi + + { echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 + echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } + hardcode_action= +@@ -9209,16 +9627,17 @@ if test -n "$STRIP" && $STRIP -V 2>&1 | + { echo "$as_me:$LINENO: result: yes" >&5 + echo "${ECHO_T}yes" >&6; } + else + # FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" ++ old_striplib="$STRIP -S" + { echo "$as_me:$LINENO: result: yes" >&5 + echo "${ECHO_T}yes" >&6; } + else + { echo "$as_me:$LINENO: result: no" >&5 + echo "${ECHO_T}no" >&6; } + fi + ;; + *) +@@ -9470,17 +9889,17 @@ fi + + rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + LIBS=$ac_check_lib_save_LIBS + fi + { echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 + echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; } + if test $ac_cv_lib_dld_shl_load = yes; then +- lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" ++ lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" + else + { echo "$as_me:$LINENO: checking for dlopen" >&5 + echo $ECHO_N "checking for dlopen... $ECHO_C" >&6; } + if test "${ac_cv_func_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 + else + cat >conftest.$ac_ext <<_ACEOF + /* confdefs.h. */ +@@ -9746,17 +10165,17 @@ fi + + rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext + LIBS=$ac_check_lib_save_LIBS + fi + { echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 + echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6; } + if test $ac_cv_lib_dld_dld_link = yes; then +- lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" ++ lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" + fi + + + fi + + + fi + +@@ -9795,17 +10214,17 @@ if test "${lt_cv_dlopen_self+set}" = set + echo $ECHO_N "(cached) $ECHO_C" >&6 + else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self=cross + else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < + #endif + + #include + +@@ -9895,17 +10314,17 @@ if test "${lt_cv_dlopen_self_static+set} + echo $ECHO_N "(cached) $ECHO_C" >&6 + else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self_static=cross + else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < + #endif + + #include + +@@ -10022,17 +10441,17 @@ case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +-aix4* | aix5*) ++aix[4-9]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + { echo "$as_me:$LINENO: result: $enable_shared" >&5 + echo "${ECHO_T}$enable_shared" >&6; } + +@@ -10078,31 +10497,33 @@ if test -f "$ltmain"; then + enable_shared_with_static_runtimes \ + old_archive_cmds \ + old_archive_from_new_cmds \ + predep_objects \ + postdep_objects \ + predeps \ + postdeps \ + compiler_lib_search_path \ ++ compiler_lib_search_dirs \ + archive_cmds \ + archive_expsym_cmds \ + postinstall_cmds \ + postuninstall_cmds \ + old_archive_from_expsyms_cmds \ + allow_undefined_flag \ + no_undefined_flag \ + export_symbols_cmds \ + hardcode_libdir_flag_spec \ + hardcode_libdir_flag_spec_ld \ + hardcode_libdir_separator \ + hardcode_automatic \ + module_cmds \ + module_expsym_cmds \ + lt_cv_prog_compiler_c_o \ ++ fix_srcfile_path \ + exclude_expsyms \ + include_expsyms; do + + case $var in + old_archive_cmds | \ + old_archive_from_new_cmds | \ + archive_cmds | \ + archive_expsym_cmds | \ +@@ -10137,17 +10558,17 @@ echo "$as_me: creating $ofile" >&6;} + + cat <<__EOF__ >> "$cfgfile" + #! $SHELL + + # `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. + # Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) + # NOTE: Changes made to this file will be lost: look at ltmain.sh. + # +-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 ++# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 + # Free Software Foundation, Inc. + # + # This file is part of GNU Libtool: + # Originally by Gordon Matzigkeit , 1996 + # + # This program is free software; you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by + # the Free Software Foundation; either version 2 of the License, or +@@ -10373,16 +10794,20 @@ postdep_objects=$lt_postdep_objects + # Dependencies to place before the objects being linked to create a + # shared library. + predeps=$lt_predeps + + # Dependencies to place after the objects being linked to create a + # shared library. + postdeps=$lt_postdeps + ++# The directories searched by this compiler when creating a shared ++# library ++compiler_lib_search_dirs=$lt_compiler_lib_search_dirs ++ + # The library search path used internally by the compiler when linking + # a shared library. + compiler_lib_search_path=$lt_compiler_lib_search_path + + # Method to check whether dependent libraries are shared objects. + deplibs_check_method=$lt_deplibs_check_method + + # Command to use when deplibs_check_method == file_magic. +@@ -10461,17 +10886,17 @@ link_all_deplibs=$link_all_deplibs + + # Compile-time system search path for libraries + sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + + # Run-time system search path for libraries + sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + + # Fix the shell variable \$srcfile for the compiler. +-fix_srcfile_path="$fix_srcfile_path" ++fix_srcfile_path=$lt_fix_srcfile_path + + # Set to yes if exported symbols are required. + always_export_symbols=$always_export_symbols + + # The commands to list exported symbols. + export_symbols_cmds=$lt_export_symbols_cmds + + # The commands to extract the exported symbol list from a shared archive. +@@ -10621,54 +11046,55 @@ whole_archive_flag_spec_CXX= + enable_shared_with_static_runtimes_CXX=no + + # Dependencies to place before and after the object being linked: + predep_objects_CXX= + postdep_objects_CXX= + predeps_CXX= + postdeps_CXX= + compiler_lib_search_path_CXX= ++compiler_lib_search_dirs_CXX= + + # Source file extension for C++ test sources. + ac_ext=cpp + + # Object file extension for compiled C++ test sources. + objext=o + objext_CXX=$objext + + # Code to be used in simple compile tests +-lt_simple_compile_test_code="int some_variable = 0;\n" ++lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests +-lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n' ++lt_simple_link_test_code='int main(int, char *[]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + + # If no C compiler was specified, use CC. + LTCC=${LTCC-"$CC"} + + # If no C compiler flags were specified, use CFLAGS. + LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + + # Allow CC to be a program name with arguments. + compiler=$CC + + + # save warnings/boilerplate of simple test code + ac_outfile=conftest.$ac_objext +-printf "$lt_simple_compile_test_code" >conftest.$ac_ext ++echo "$lt_simple_compile_test_code" >conftest.$ac_ext + eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err + _lt_compiler_boilerplate=`cat conftest.err` + $rm conftest* + + ac_outfile=conftest.$ac_objext +-printf "$lt_simple_link_test_code" >conftest.$ac_ext ++echo "$lt_simple_link_test_code" >conftest.$ac_ext + eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err + _lt_linker_boilerplate=`cat conftest.err` +-$rm conftest* ++$rm -r conftest* + + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld +@@ -10865,30 +11291,30 @@ fi + { echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 + echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } + ld_shlibs_CXX=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; +- aix4* | aix5*) ++ aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. +- case $host_os in aix4.[23]|aix4.[23].*|aix5*) ++ case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done +@@ -10914,17 +11340,17 @@ case $host_os in + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 +- hardcode_direct_CXX=yes ++ : + else + # We have old collect2 + hardcode_direct_CXX=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_CXX=yes + hardcode_libdir_flag_spec_CXX='-L$libdir' +@@ -10988,21 +11414,28 @@ eval "echo \"\$as_me:$LINENO: $ac_try_ec + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + +-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +-}'` ++lt_aix_libpath_sed=' ++ /Import File Strings/,/^$/ { ++ /^0/ { ++ s/^0 *\(.*\)$/\1/ ++ p ++ } ++ }' ++aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. +-if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +-}'`; fi ++if test -z "$aix_libpath"; then ++ aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` ++fi + else + echo "$as_me: failed program was:" >&5 + sed 's/^/| /' conftest.$ac_ext >&5 + + + fi + + rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ +@@ -11048,21 +11481,28 @@ eval "echo \"\$as_me:$LINENO: $ac_try_ec + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + +-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +-}'` ++lt_aix_libpath_sed=' ++ /Import File Strings/,/^$/ { ++ /^0/ { ++ s/^0 *\(.*\)$/\1/ ++ p ++ } ++ }' ++aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. +-if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +-}'`; fi ++if test -z "$aix_libpath"; then ++ aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` ++fi + else + echo "$as_me: failed program was:" >&5 + sed 's/^/| /' conftest.$ac_ext >&5 + + + fi + + rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ +@@ -11122,69 +11562,41 @@ if test -z "$aix_libpath"; then aix_libp + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_CXX=no + fi + ;; + darwin* | rhapsody*) +- case $host_os in +- rhapsody* | darwin1.[012]) +- allow_undefined_flag_CXX='${wl}-undefined ${wl}suppress' +- ;; +- *) # Darwin 1.3 on +- if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then +- allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' +- else +- case ${MACOSX_DEPLOYMENT_TARGET} in +- 10.[012]) +- allow_undefined_flag_CXX='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' +- ;; +- 10.*) +- allow_undefined_flag_CXX='${wl}-undefined ${wl}dynamic_lookup' +- ;; +- esac +- fi +- ;; +- esac + archive_cmds_need_lc_CXX=no + hardcode_direct_CXX=no + hardcode_automatic_CXX=yes + hardcode_shlibpath_var_CXX=unsupported + whole_archive_flag_spec_CXX='' + link_all_deplibs_CXX=yes +- +- if test "$GXX" = yes ; then +- lt_int_apple_cc_single_mod=no ++ allow_undefined_flag_CXX="$_lt_dar_allow_undefined" ++ if test "$GXX" = yes ; then + output_verbose_link_cmd='echo' +- if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then +- lt_int_apple_cc_single_mod=yes +- fi +- if test "X$lt_int_apple_cc_single_mod" = Xyes ; then +- archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' +- else +- archive_cmds_CXX='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' +- fi +- module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' +- # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds +- if test "X$lt_int_apple_cc_single_mod" = Xyes ; then +- archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' +- else +- archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' +- fi +- module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ++ archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" ++ module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" ++ archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" ++ module_expsym_cmds_CXX="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" ++ if test "$lt_cv_apple_cc_single_mod" != "yes"; then ++ archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" ++ archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" ++ fi + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' +- archive_cmds_CXX='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' ++ archive_cmds_CXX='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' + module_cmds_CXX='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds +- archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ++ archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs_CXX=no + ;; + esac + fi + ;; +@@ -11208,17 +11620,17 @@ if test -z "$aix_libpath"; then aix_libp + ;; + freebsd[12]*) + # C++ shared libraries reported to be fairly broken before switch to ELF + ld_shlibs_CXX=no + ;; + freebsd-elf*) + archive_cmds_need_lc_CXX=no + ;; +- freebsd* | kfreebsd*-gnu | dragonfly*) ++ freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + ld_shlibs_CXX=yes + ;; + gnu*) + ;; + hpux9*) + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' +@@ -11257,19 +11669,17 @@ if test -z "$aix_libpath"; then aix_libp + esac + ;; + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + case $host_cpu in +- hppa*64*|ia64*) +- hardcode_libdir_flag_spec_ld_CXX='+b $libdir' +- ;; ++ hppa*64*|ia64*) ;; + *) + export_dynamic_flag_spec_CXX='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct_CXX=no +@@ -11327,17 +11737,17 @@ if test -z "$aix_libpath"; then aix_libp + fi + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; +- interix3*) ++ interix[3-9]*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, +@@ -11367,17 +11777,17 @@ if test -z "$aix_libpath"; then aix_libp + fi + fi + link_all_deplibs_CXX=yes + ;; + esac + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + ;; +- linux*) ++ linux* | k*bsd*-gnu) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' +@@ -11419,17 +11829,17 @@ if test -z "$aix_libpath"; then aix_libp + archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + archive_cmds_need_lc_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; +- pgCC*) ++ pgCC* | pgcpp*) + # Portland Group C++ compiler + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + ;; +@@ -11447,16 +11857,39 @@ if test -z "$aix_libpath"; then aix_libp + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; ++ *) ++ case `$CC -V 2>&1 | sed 5q` in ++ *Sun\ C*) ++ # Sun C++ 5.9 ++ no_undefined_flag_CXX=' -zdefs' ++ archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ++ archive_expsym_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' ++ hardcode_libdir_flag_spec_CXX='-R$libdir' ++ whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' ++ ++ # Not sure whether something based on ++ # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 ++ # would be better. ++ output_verbose_link_cmd='echo' ++ ++ # Archives containing C++ object files must be created using ++ # "CC -xar", where "CC" is the Sun C++ compiler. This is ++ # necessary to make sure instantiated templates are included ++ # in the archive. ++ old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ++ ;; ++ esac ++ ;; + esac + ;; + lynxos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + m88k*) + # FIXME: insert proper C++ library support +@@ -11485,26 +11918,30 @@ if test -z "$aix_libpath"; then aix_libp + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + openbsd2*) + # C++ shared libraries are fairly broken + ld_shlibs_CXX=no + ;; + openbsd*) +- hardcode_direct_CXX=yes +- hardcode_shlibpath_var_CXX=no +- archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' +- hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' +- if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then +- archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' +- export_dynamic_flag_spec_CXX='${wl}-E' +- whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' +- fi +- output_verbose_link_cmd='echo' ++ if test -f /usr/libexec/ld.so; then ++ hardcode_direct_CXX=yes ++ hardcode_shlibpath_var_CXX=no ++ archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' ++ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' ++ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then ++ archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' ++ export_dynamic_flag_spec_CXX='${wl}-E' ++ whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' ++ fi ++ output_verbose_link_cmd='echo' ++ else ++ ld_shlibs_CXX=no ++ fi + ;; + osf3*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library +@@ -11656,25 +12093,20 @@ if test -z "$aix_libpath"; then aix_libp + archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_shlibpath_var_CXX=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) +- # The C++ compiler is used as linker so we must use $wl +- # flag to pass the commands to the underlying system +- # linker. We must also pass each convience library through +- # to the system linker between allextract/defaultextract. +- # The C++ compiler will combine linker options so we +- # cannot just pass the convience library names through +- # without $wl. ++ # The compiler driver will combine and reorder linker options, ++ # but understands `-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) +- whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ++ whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' + ;; + esac + link_all_deplibs_CXX=yes + + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is +@@ -11711,16 +12143,22 @@ if test -z "$aix_libpath"; then aix_libp + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + fi + + hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' ++ case $host_os in ++ solaris2.[0-5] | solaris2.[0-5].*) ;; ++ *) ++ whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ++ ;; ++ esac + fi + ;; + esac + ;; + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag_CXX='${wl}-z,text' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no +@@ -11798,17 +12236,16 @@ if test -z "$aix_libpath"; then aix_libp + esac + { echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 + echo "${ECHO_T}$ld_shlibs_CXX" >&6; } + test "$ld_shlibs_CXX" = no && can_build_shared=no + + GCC_CXX="$GXX" + LD_CXX="$LD" + +- + cat > conftest.$ac_ext <&1 | sed 5q` in ++ *Sun\ C*) ++ # Sun C++ 5.9 ++ # ++ # The more standards-conforming stlport4 library is ++ # incompatible with the Cstd library. Avoid specifying ++ # it if it's in CXXFLAGS. Ignore libCrun as ++ # -library=stlport4 depends on it. ++ case " $CXX $CXXFLAGS " in ++ *" -library=stlport4 "*) ++ solaris_use_stlport4=yes ++ ;; ++ esac ++ if test "$solaris_use_stlport4" != yes; then ++ postdeps_CXX='-library=Cstd -library=Crun' ++ fi ++ ;; ++ esac ++ ;; ++ + solaris*) + case $cc_basename in + CC*) ++ # The more standards-conforming stlport4 library is ++ # incompatible with the Cstd library. Avoid specifying ++ # it if it's in CXXFLAGS. Ignore libCrun as ++ # -library=stlport4 depends on it. ++ case " $CXX $CXXFLAGS " in ++ *" -library=stlport4 "*) ++ solaris_use_stlport4=yes ++ ;; ++ esac ++ + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. +- postdeps_CXX='-lCstd -lCrun' +- ;; +- esac +- ;; +-esac +- ++ if test "$solaris_use_stlport4" != yes; then ++ postdeps_CXX='-library=Cstd -library=Crun' ++ fi ++ ;; ++ esac ++ ;; ++esac + + case " $postdeps_CXX " in + *" -lc "*) archive_cmds_need_lc_CXX=no ;; + esac + + lt_prog_compiler_wl_CXX= + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX= +@@ -11953,34 +12427,36 @@ echo $ECHO_N "checking for $compiler opt + fi + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' + ;; +- beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) ++ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; +- mingw* | os2* | pw32*) ++ mingw* | cygwin* | os2* | pw32*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). ++ # Although the cygwin gcc ignores -fPIC, still need this for old-style ++ # (--disable-auto-import) libraries + lt_prog_compiler_pic_CXX='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_CXX='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + lt_prog_compiler_pic_CXX= + ;; +- interix3*) ++ interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_CXX=-Kconform_pic + fi + ;; +@@ -11996,17 +12472,17 @@ echo $ECHO_N "checking for $compiler opt + esac + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + else + case $host_os in +- aix4* | aix5*) ++ aix[4-9]*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + else + lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' + fi + ;; +@@ -12036,17 +12512,17 @@ echo $ECHO_N "checking for $compiler opt + ghcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; +- freebsd* | kfreebsd*-gnu | dragonfly*) ++ freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then +@@ -12079,43 +12555,51 @@ echo $ECHO_N "checking for $compiler opt + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; +- linux*) ++ linux* | k*bsd*-gnu) + case $cc_basename in + KCC*) + # KAI C++ Compiler + lt_prog_compiler_wl_CXX='--backend -Wl,' + lt_prog_compiler_pic_CXX='-fPIC' + ;; + icpc* | ecpc*) + # Intel C++ + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-static' + ;; +- pgCC*) ++ pgCC* | pgcpp*) + # Portland Group C++ compiler. + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-fpic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + *) ++ case `$CC -V 2>&1 | sed 5q` in ++ *Sun\ C*) ++ # Sun C++ 5.9 ++ lt_prog_compiler_pic_CXX='-KPIC' ++ lt_prog_compiler_static_CXX='-Bstatic' ++ lt_prog_compiler_wl_CXX='-Qoption ld ' ++ ;; ++ esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) +@@ -12215,53 +12699,53 @@ echo "${ECHO_T}$lt_prog_compiler_pic_CXX + + # + # Check to make sure the PIC flag actually works. + # + if test -n "$lt_prog_compiler_pic_CXX"; then + + { echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 + echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... $ECHO_C" >&6; } +-if test "${lt_prog_compiler_pic_works_CXX+set}" = set; then +- echo $ECHO_N "(cached) $ECHO_C" >&6 +-else +- lt_prog_compiler_pic_works_CXX=no ++if test "${lt_cv_prog_compiler_pic_works_CXX+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ lt_cv_prog_compiler_pic_works_CXX=no + ac_outfile=conftest.$ac_objext +- printf "$lt_simple_compile_test_code" > conftest.$ac_ext ++ echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` +- (eval echo "\"\$as_me:12239: $lt_compile\"" >&5) ++ (eval echo "\"\$as_me:12723: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 +- echo "$as_me:12243: \$? = $ac_status" >&5 ++ echo "$as_me:12727: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then +- lt_prog_compiler_pic_works_CXX=yes ++ lt_cv_prog_compiler_pic_works_CXX=yes + fi + fi + $rm conftest* + + fi +-{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_CXX" >&5 +-echo "${ECHO_T}$lt_prog_compiler_pic_works_CXX" >&6; } +- +-if test x"$lt_prog_compiler_pic_works_CXX" = xyes; then ++{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 ++echo "${ECHO_T}$lt_cv_prog_compiler_pic_works_CXX" >&6; } ++ ++if test x"$lt_cv_prog_compiler_pic_works_CXX" = xyes; then + case $lt_prog_compiler_pic_CXX in + "" | " "*) ;; + *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; + esac + else + lt_prog_compiler_pic_CXX= + lt_prog_compiler_can_build_shared_CXX=no + fi +@@ -12278,78 +12762,78 @@ case $host_os in + esac + + # + # Check to make sure the static flag actually works. + # + wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" + { echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 + echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } +-if test "${lt_prog_compiler_static_works_CXX+set}" = set; then +- echo $ECHO_N "(cached) $ECHO_C" >&6 +-else +- lt_prog_compiler_static_works_CXX=no ++if test "${lt_cv_prog_compiler_static_works_CXX+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ lt_cv_prog_compiler_static_works_CXX=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" +- printf "$lt_simple_link_test_code" > conftest.$ac_ext ++ echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then +- lt_prog_compiler_static_works_CXX=yes ++ lt_cv_prog_compiler_static_works_CXX=yes + fi + else +- lt_prog_compiler_static_works_CXX=yes ++ lt_cv_prog_compiler_static_works_CXX=yes + fi + fi +- $rm conftest* ++ $rm -r conftest* + LDFLAGS="$save_LDFLAGS" + + fi +-{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_CXX" >&5 +-echo "${ECHO_T}$lt_prog_compiler_static_works_CXX" >&6; } +- +-if test x"$lt_prog_compiler_static_works_CXX" = xyes; then ++{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_static_works_CXX" >&5 ++echo "${ECHO_T}$lt_cv_prog_compiler_static_works_CXX" >&6; } ++ ++if test x"$lt_cv_prog_compiler_static_works_CXX" = xyes; then + : + else + lt_prog_compiler_static_CXX= + fi + + + { echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 + echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } + if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 + else + lt_cv_prog_compiler_c_o_CXX=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out +- printf "$lt_simple_compile_test_code" > conftest.$ac_ext ++ echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` +- (eval echo "\"\$as_me:12343: $lt_compile\"" >&5) ++ (eval echo "\"\$as_me:12827: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 +- echo "$as_me:12347: \$? = $ac_status" >&5 ++ echo "$as_me:12831: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_CXX=yes +@@ -12392,35 +12876,36 @@ else + need_locks=no + fi + + { echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 + echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; } + + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in +- aix4* | aix5*) ++ aix[4-9]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + export_symbols_cmds_CXX="$ltdll_cmds" + ;; + cygwin* | mingw*) +- export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([^ ]*\) [^ ]*/\1 DATA/;/^I /d;/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' ++ export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;/^.*[ ]__nm__/s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + ;; + *) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac ++ exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + + { echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 + echo "${ECHO_T}$ld_shlibs_CXX" >&6; } + test "$ld_shlibs_CXX" = no && can_build_shared=no + + # + # Do we need to explicitly link libc? + # +@@ -12436,17 +12921,17 @@ x|xyes) + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 + echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } + $rm conftest* +- printf "$lt_simple_compile_test_code" > conftest.$ac_ext ++ echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest +@@ -12494,30 +12979,17 @@ postinstall_cmds= + postuninstall_cmds= + finish_cmds= + finish_eval= + shlibpath_var= + shlibpath_overrides_runpath=unknown + version_type=none + dynamic_linker="$host_os ld.so" + sys_lib_dlsearch_path_spec="/lib /usr/lib" +-if test "$GCC" = yes; then +- sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` +- if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then +- # if the path contains ";" then we assume it to be the separator +- # otherwise default to the standard path separator (i.e. ":") - it is +- # assumed that no part of a normal pathname contains ";" but that should +- # okay in the real world where ";" in dirpaths is itself problematic. +- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` +- else +- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` +- fi +-else +- sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +-fi ++ + need_lib_prefix=unknown + hardcode_into_libs=no + + # when you set need_version to no, make sure it does not cause -set_version + # flags to be left without arguments + need_version=unknown + + case $host_os in +@@ -12525,17 +12997,17 @@ aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +-aix4* | aix5*) ++aix[4-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH +@@ -12664,50 +13136,33 @@ darwin* | rhapsody*) + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +- # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. +- if test "$GCC" = yes; then +- sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` +- else +- sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' +- fi ++ + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + + dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + + freebsd1*) + dynamic_linker=no + ;; + +-kfreebsd*-gnu) +- version_type=linux +- need_lib_prefix=no +- need_version=no +- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' +- soname_spec='${libname}${release}${shared_ext}$major' +- shlibpath_var=LD_LIBRARY_PATH +- shlibpath_overrides_runpath=no +- hardcode_into_libs=yes +- dynamic_linker='GNU ld.so' +- ;; +- + freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; +@@ -12735,17 +13190,17 @@ freebsd* | dragonfly*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; +- freebsd*) # from 4.6 on ++ *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + + gnu*) + version_type=linux +@@ -12798,17 +13253,17 @@ hpux9* | hpux10* | hpux11*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +-interix3*) ++interix[3-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no +@@ -12853,57 +13308,45 @@ irix5* | irix6* | nonstopux*) + ;; + + # No shared lib support for Linux oldld, aout, or coff. + linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + + # This must be Linux ELF. +-linux*) ++linux* | k*bsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then +- lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` ++ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +-knetbsd*-gnu) +- version_type=linux +- need_lib_prefix=no +- need_version=no +- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' +- soname_spec='${libname}${release}${shared_ext}$major' +- shlibpath_var=LD_LIBRARY_PATH +- shlibpath_overrides_runpath=no +- hardcode_into_libs=yes +- dynamic_linker='GNU ld.so' +- ;; +- + netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' +@@ -12975,16 +13418,20 @@ osf3* | osf4* | osf5*) + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + ++rdos*) ++ dynamic_linker=no ++ ;; ++ + solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes +@@ -13071,16 +13518,31 @@ uts4*) + *) + dynamic_linker=no + ;; + esac + { echo "$as_me:$LINENO: result: $dynamic_linker" >&5 + echo "${ECHO_T}$dynamic_linker" >&6; } + test "$dynamic_linker" = no && can_build_shared=no + ++if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ lt_cv_sys_lib_search_path_spec="$sys_lib_search_path_spec" ++fi ++ ++sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" ++if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ lt_cv_sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec" ++fi ++ ++sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" ++ + variables_saved_for_relink="PATH $shlibpath_var $runpath_var" + if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" + fi + + { echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 + echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } + hardcode_action_CXX= +@@ -13154,31 +13616,33 @@ if test -f "$ltmain"; then + enable_shared_with_static_runtimes_CXX \ + old_archive_cmds_CXX \ + old_archive_from_new_cmds_CXX \ + predep_objects_CXX \ + postdep_objects_CXX \ + predeps_CXX \ + postdeps_CXX \ + compiler_lib_search_path_CXX \ ++ compiler_lib_search_dirs_CXX \ + archive_cmds_CXX \ + archive_expsym_cmds_CXX \ + postinstall_cmds_CXX \ + postuninstall_cmds_CXX \ + old_archive_from_expsyms_cmds_CXX \ + allow_undefined_flag_CXX \ + no_undefined_flag_CXX \ + export_symbols_cmds_CXX \ + hardcode_libdir_flag_spec_CXX \ + hardcode_libdir_flag_spec_ld_CXX \ + hardcode_libdir_separator_CXX \ + hardcode_automatic_CXX \ + module_cmds_CXX \ + module_expsym_cmds_CXX \ + lt_cv_prog_compiler_c_o_CXX \ ++ fix_srcfile_path_CXX \ + exclude_expsyms_CXX \ + include_expsyms_CXX; do + + case $var in + old_archive_cmds_CXX | \ + old_archive_from_new_cmds_CXX | \ + archive_cmds_CXX | \ + archive_expsym_cmds_CXX | \ +@@ -13401,16 +13865,20 @@ postdep_objects=$lt_postdep_objects_CXX + # Dependencies to place before the objects being linked to create a + # shared library. + predeps=$lt_predeps_CXX + + # Dependencies to place after the objects being linked to create a + # shared library. + postdeps=$lt_postdeps_CXX + ++# The directories searched by this compiler when creating a shared ++# library ++compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX ++ + # The library search path used internally by the compiler when linking + # a shared library. + compiler_lib_search_path=$lt_compiler_lib_search_path_CXX + + # Method to check whether dependent libraries are shared objects. + deplibs_check_method=$lt_deplibs_check_method + + # Command to use when deplibs_check_method == file_magic. +@@ -13489,17 +13957,17 @@ link_all_deplibs=$link_all_deplibs_CXX + + # Compile-time system search path for libraries + sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + + # Run-time system search path for libraries + sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + + # Fix the shell variable \$srcfile for the compiler. +-fix_srcfile_path="$fix_srcfile_path_CXX" ++fix_srcfile_path=$lt_fix_srcfile_path + + # Set to yes if exported symbols are required. + always_export_symbols=$always_export_symbols_CXX + + # The commands to list exported symbols. + export_symbols_cmds=$lt_export_symbols_cmds_CXX + + # The commands to extract the exported symbol list from a shared archive. +@@ -13580,45 +14048,52 @@ enable_shared_with_static_runtimes_F77=n + # Source file extension for f77 test sources. + ac_ext=f + + # Object file extension for compiled f77 test sources. + objext=o + objext_F77=$objext + + # Code to be used in simple compile tests +-lt_simple_compile_test_code=" subroutine t\n return\n end\n" ++lt_simple_compile_test_code="\ ++ subroutine t ++ return ++ end ++" + + # Code to be used in simple link tests +-lt_simple_link_test_code=" program t\n end\n" ++lt_simple_link_test_code="\ ++ program t ++ end ++" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + + # If no C compiler was specified, use CC. + LTCC=${LTCC-"$CC"} + + # If no C compiler flags were specified, use CFLAGS. + LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + + # Allow CC to be a program name with arguments. + compiler=$CC + + + # save warnings/boilerplate of simple test code + ac_outfile=conftest.$ac_objext +-printf "$lt_simple_compile_test_code" >conftest.$ac_ext ++echo "$lt_simple_compile_test_code" >conftest.$ac_ext + eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err + _lt_compiler_boilerplate=`cat conftest.err` + $rm conftest* + + ac_outfile=conftest.$ac_objext +-printf "$lt_simple_link_test_code" >conftest.$ac_ext ++echo "$lt_simple_link_test_code" >conftest.$ac_ext + eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err + _lt_linker_boilerplate=`cat conftest.err` +-$rm conftest* ++$rm -r conftest* + + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + CC=${F77-"f77"} + compiler=$CC + compiler_F77=$CC + for cc_temp in $compiler""; do +@@ -13646,17 +14121,17 @@ test "$can_build_shared" = "no" && enabl + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; +-aix4* | aix5*) ++aix[4-9]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + { echo "$as_me:$LINENO: result: $enable_shared" >&5 + echo "${ECHO_T}$enable_shared" >&6; } + +@@ -13692,33 +14167,35 @@ echo $ECHO_N "checking for $compiler opt + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4' + ;; + +- beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) ++ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + +- mingw* | pw32* | os2*) ++ mingw* | cygwin* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). ++ # Although the cygwin gcc ignores -fPIC, still need this for old-style ++ # (--disable-auto-import) libraries + lt_prog_compiler_pic_F77='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_F77='-fno-common' + ;; + +- interix3*) ++ interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared_F77=no +@@ -13766,17 +14243,17 @@ echo $ECHO_N "checking for $compiler opt + case $cc_basename in + xlc*) + lt_prog_compiler_pic_F77='-qnocommon' + lt_prog_compiler_wl_F77='-Wl,' + ;; + esac + ;; + +- mingw* | pw32* | os2*) ++ mingw* | cygwin* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_F77='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl_F77='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but +@@ -13799,17 +14276,17 @@ echo $ECHO_N "checking for $compiler opt + lt_prog_compiler_static_F77='-non_shared' + ;; + + newsos6) + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + +- linux*) ++ linux* | k*bsd*-gnu) + case $cc_basename in + icc* | ecc*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, +@@ -13818,25 +14295,45 @@ echo $ECHO_N "checking for $compiler opt + lt_prog_compiler_pic_F77='-fpic' + lt_prog_compiler_static_F77='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl_F77='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static_F77='-non_shared' + ;; ++ *) ++ case `$CC -V 2>&1 | sed 5q` in ++ *Sun\ C*) ++ # Sun C 5.9 ++ lt_prog_compiler_pic_F77='-KPIC' ++ lt_prog_compiler_static_F77='-Bstatic' ++ lt_prog_compiler_wl_F77='-Wl,' ++ ;; ++ *Sun\ F*) ++ # Sun Fortran 8.3 passes all unrecognized flags to the linker ++ lt_prog_compiler_pic_F77='-KPIC' ++ lt_prog_compiler_static_F77='-Bstatic' ++ lt_prog_compiler_wl_F77='' ++ ;; ++ esac ++ ;; + esac + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl_F77='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static_F77='-non_shared' + ;; + ++ rdos*) ++ lt_prog_compiler_static_F77='-non_shared' ++ ;; ++ + solaris*) + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl_F77='-Qoption ld ';; + *) + lt_prog_compiler_wl_F77='-Wl,';; +@@ -13889,53 +14386,53 @@ echo "${ECHO_T}$lt_prog_compiler_pic_F77 + + # + # Check to make sure the PIC flag actually works. + # + if test -n "$lt_prog_compiler_pic_F77"; then + + { echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5 + echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... $ECHO_C" >&6; } +-if test "${lt_prog_compiler_pic_works_F77+set}" = set; then +- echo $ECHO_N "(cached) $ECHO_C" >&6 +-else +- lt_prog_compiler_pic_works_F77=no ++if test "${lt_cv_prog_compiler_pic_works_F77+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ lt_cv_prog_compiler_pic_works_F77=no + ac_outfile=conftest.$ac_objext +- printf "$lt_simple_compile_test_code" > conftest.$ac_ext ++ echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_F77" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` +- (eval echo "\"\$as_me:13913: $lt_compile\"" >&5) ++ (eval echo "\"\$as_me:14410: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 +- echo "$as_me:13917: \$? = $ac_status" >&5 ++ echo "$as_me:14414: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then +- lt_prog_compiler_pic_works_F77=yes ++ lt_cv_prog_compiler_pic_works_F77=yes + fi + fi + $rm conftest* + + fi +-{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_F77" >&5 +-echo "${ECHO_T}$lt_prog_compiler_pic_works_F77" >&6; } +- +-if test x"$lt_prog_compiler_pic_works_F77" = xyes; then ++{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_pic_works_F77" >&5 ++echo "${ECHO_T}$lt_cv_prog_compiler_pic_works_F77" >&6; } ++ ++if test x"$lt_cv_prog_compiler_pic_works_F77" = xyes; then + case $lt_prog_compiler_pic_F77 in + "" | " "*) ;; + *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;; + esac + else + lt_prog_compiler_pic_F77= + lt_prog_compiler_can_build_shared_F77=no + fi +@@ -13952,78 +14449,78 @@ case $host_os in + esac + + # + # Check to make sure the static flag actually works. + # + wl=$lt_prog_compiler_wl_F77 eval lt_tmp_static_flag=\"$lt_prog_compiler_static_F77\" + { echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 + echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } +-if test "${lt_prog_compiler_static_works_F77+set}" = set; then +- echo $ECHO_N "(cached) $ECHO_C" >&6 +-else +- lt_prog_compiler_static_works_F77=no ++if test "${lt_cv_prog_compiler_static_works_F77+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ lt_cv_prog_compiler_static_works_F77=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" +- printf "$lt_simple_link_test_code" > conftest.$ac_ext ++ echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then +- lt_prog_compiler_static_works_F77=yes ++ lt_cv_prog_compiler_static_works_F77=yes + fi + else +- lt_prog_compiler_static_works_F77=yes ++ lt_cv_prog_compiler_static_works_F77=yes + fi + fi +- $rm conftest* ++ $rm -r conftest* + LDFLAGS="$save_LDFLAGS" + + fi +-{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_F77" >&5 +-echo "${ECHO_T}$lt_prog_compiler_static_works_F77" >&6; } +- +-if test x"$lt_prog_compiler_static_works_F77" = xyes; then ++{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_static_works_F77" >&5 ++echo "${ECHO_T}$lt_cv_prog_compiler_static_works_F77" >&6; } ++ ++if test x"$lt_cv_prog_compiler_static_works_F77" = xyes; then + : + else + lt_prog_compiler_static_F77= + fi + + + { echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 + echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } + if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 + else + lt_cv_prog_compiler_c_o_F77=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out +- printf "$lt_simple_compile_test_code" > conftest.$ac_ext ++ echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` +- (eval echo "\"\$as_me:14017: $lt_compile\"" >&5) ++ (eval echo "\"\$as_me:14514: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 +- echo "$as_me:14021: \$? = $ac_status" >&5 ++ echo "$as_me:14518: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_F77=yes +@@ -14093,22 +14590,23 @@ echo $ECHO_N "checking whether the $comp + export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms_F77= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. +- exclude_expsyms_F77="_GLOBAL_OFFSET_TABLE_" ++ exclude_expsyms_F77='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. ++ # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; +@@ -14157,17 +14655,17 @@ cc_basename=`$echo "X$cc_temp" | $Xsed - + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in +- aix3* | aix4* | aix5*) ++ aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs_F77=no + cat <&2 + + *** Warning: the GNU linker, at least up to release 2.9.1, is reported + *** to be unable to reliably create shared libraries on AIX. + *** Therefore, libtool is disabling shared libraries support. If you +@@ -14205,17 +14703,17 @@ EOF + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, F77) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_F77='-L$libdir' + allow_undefined_flag_F77=unsupported + always_export_symbols_F77=no + enable_shared_with_static_runtimes_F77=yes +- export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' ++ export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds_F77='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else +@@ -14223,32 +14721,32 @@ EOF + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_F77=no + fi + ;; + +- interix3*) ++ interix[3-9]*) + hardcode_direct_F77=no + hardcode_shlibpath_var_F77=no + hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' + export_dynamic_flag_spec_F77='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_F77='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_F77='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + +- linux*) ++ gnu* | linux* | k*bsd*-gnu) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec_F77='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers +@@ -14256,23 +14754,32 @@ EOF + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac +- archive_cmds_F77='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' ++ case `$CC -V 2>&1 | sed 5q` in ++ *Sun\ C*) # Sun C 5.9 ++ whole_archive_flag_spec_F77='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' ++ tmp_sharedflag='-G' ;; ++ *Sun\ F*) # Sun Fortran 8.3 ++ tmp_sharedflag='-G' ;; ++ *) ++ tmp_sharedflag='-shared' ;; ++ esac ++ archive_cmds_F77='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ +- $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' ++ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + else + ld_shlibs_F77=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then +@@ -14367,17 +14874,17 @@ _LT_EOF + hardcode_minus_L_F77=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct_F77=unsupported + fi + ;; + +- aix4* | aix5*) ++ aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. +@@ -14387,17 +14894,17 @@ _LT_EOF + else + export_symbols_cmds_F77='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. +- case $host_os in aix4.[23]|aix4.[23].*|aix5*) ++ case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac +@@ -14421,17 +14928,17 @@ _LT_EOF + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 +- hardcode_direct_F77=yes ++ : + else + # We have old collect2 + hardcode_direct_F77=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_F77=yes + hardcode_libdir_flag_spec_F77='-L$libdir' +@@ -14485,21 +14992,28 @@ eval "echo \"\$as_me:$LINENO: $ac_try_ec + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_f77_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + +-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +-}'` ++lt_aix_libpath_sed=' ++ /Import File Strings/,/^$/ { ++ /^0/ { ++ s/^0 *\(.*\)$/\1/ ++ p ++ } ++ }' ++aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. +-if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +-}'`; fi ++if test -z "$aix_libpath"; then ++ aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` ++fi + else + echo "$as_me: failed program was:" >&5 + sed 's/^/| /' conftest.$ac_ext >&5 + + + fi + + rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ +@@ -14534,21 +15048,28 @@ eval "echo \"\$as_me:$LINENO: $ac_try_ec + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_f77_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + +-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +-}'` ++lt_aix_libpath_sed=' ++ /Import File Strings/,/^$/ { ++ /^0/ { ++ s/^0 *\(.*\)$/\1/ ++ p ++ } ++ }' ++aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. +-if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +-}'`; fi ++if test -z "$aix_libpath"; then ++ aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` ++fi + else + echo "$as_me: failed program was:" >&5 + sed 's/^/| /' conftest.$ac_ext >&5 + + + fi + + rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ +@@ -14592,17 +15113,17 @@ if test -z "$aix_libpath"; then aix_libp + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds_F77='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_From_new_cmds_F77='true' + # FIXME: Should let the user specify the lib program. +- old_archive_cmds_F77='lib /OUT:$oldlib$oldobjs$old_deplibs' ++ old_archive_cmds_F77='lib -OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path_F77='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes_F77=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag_F77='${wl}-undefined ${wl}suppress' +@@ -14625,29 +15146,28 @@ if test -z "$aix_libpath"; then aix_libp + archive_cmds_need_lc_F77=no + hardcode_direct_F77=no + hardcode_automatic_F77=yes + hardcode_shlibpath_var_F77=unsupported + whole_archive_flag_spec_F77='' + link_all_deplibs_F77=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' +- archive_cmds_F77='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' +- module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' +- # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds +- archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' +- module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ++ archive_cmds_F77="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" ++ module_cmds_F77="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" ++ archive_expsym_cmds_F77="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" ++ module_expsym_cmds_F77="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' +- archive_cmds_F77='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' ++ archive_cmds_F77='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' + module_cmds_F77='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds +- archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ++ archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs_F77=no + ;; + esac + fi + ;; +@@ -14677,17 +15197,17 @@ if test -z "$aix_libpath"; then aix_libp + freebsd2*) + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=yes + hardcode_minus_L_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. +- freebsd* | kfreebsd*-gnu | dragonfly*) ++ freebsd* | dragonfly*) + archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + hpux9*) + if test "$GCC" = yes; then +@@ -14799,34 +15319,38 @@ if test -z "$aix_libpath"; then aix_libp + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=yes + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_F77=: + hardcode_shlibpath_var_F77=no + ;; + + openbsd*) +- hardcode_direct_F77=yes +- hardcode_shlibpath_var_F77=no +- if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then +- archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' +- archive_expsym_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' +- hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' +- export_dynamic_flag_spec_F77='${wl}-E' +- else +- case $host_os in +- openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) +- archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' +- hardcode_libdir_flag_spec_F77='-R$libdir' +- ;; +- *) +- archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' +- hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' +- ;; +- esac ++ if test -f /usr/libexec/ld.so; then ++ hardcode_direct_F77=yes ++ hardcode_shlibpath_var_F77=no ++ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then ++ archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ++ archive_expsym_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' ++ hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' ++ export_dynamic_flag_spec_F77='${wl}-E' ++ else ++ case $host_os in ++ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) ++ archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' ++ hardcode_libdir_flag_spec_F77='-R$libdir' ++ ;; ++ *) ++ archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ++ hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' ++ ;; ++ esac ++ fi ++ else ++ ld_shlibs_F77=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_minus_L_F77=yes + allow_undefined_flag_F77=unsupported + archive_cmds_F77='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' +@@ -14875,27 +15399,26 @@ if test -z "$aix_libpath"; then aix_libp + archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_shlibpath_var_F77=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) +- # The compiler driver will combine linker options so we +- # cannot just pass the convience library names through +- # without $wl, iff we do not link with $LD. +- # Luckily, gcc supports the same syntax we need for Sun Studio. ++ # The compiler driver will combine and reorder linker options, ++ # but understands `-z linker_flag'. GCC discards it without `$wl', ++ # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) +- case $wlarc in +- '') +- whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' ;; +- *) +- whole_archive_flag_spec_F77='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; +- esac ;; ++ if test "$GCC" = yes; then ++ whole_archive_flag_spec_F77='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ++ else ++ whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' ++ fi ++ ;; + esac + link_all_deplibs_F77=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. +@@ -14942,17 +15465,17 @@ if test -z "$aix_libpath"; then aix_libp + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_F77=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs_F77=yes + fi + ;; + +- sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) ++ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag_F77='${wl}-z,text' + archive_cmds_need_lc_F77=no + hardcode_shlibpath_var_F77=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds_F77='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' +@@ -15019,17 +15542,17 @@ x|xyes) + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 + echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } + $rm conftest* +- printf "$lt_simple_compile_test_code" > conftest.$ac_ext ++ echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest +@@ -15077,30 +15600,17 @@ postinstall_cmds= + postuninstall_cmds= + finish_cmds= + finish_eval= + shlibpath_var= + shlibpath_overrides_runpath=unknown + version_type=none + dynamic_linker="$host_os ld.so" + sys_lib_dlsearch_path_spec="/lib /usr/lib" +-if test "$GCC" = yes; then +- sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` +- if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then +- # if the path contains ";" then we assume it to be the separator +- # otherwise default to the standard path separator (i.e. ":") - it is +- # assumed that no part of a normal pathname contains ";" but that should +- # okay in the real world where ";" in dirpaths is itself problematic. +- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` +- else +- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` +- fi +-else +- sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +-fi ++ + need_lib_prefix=unknown + hardcode_into_libs=no + + # when you set need_version to no, make sure it does not cause -set_version + # flags to be left without arguments + need_version=unknown + + case $host_os in +@@ -15108,17 +15618,17 @@ aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +-aix4* | aix5*) ++aix[4-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH +@@ -15247,50 +15757,33 @@ darwin* | rhapsody*) + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +- # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. +- if test "$GCC" = yes; then +- sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` +- else +- sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' +- fi ++ + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + + dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + + freebsd1*) + dynamic_linker=no + ;; + +-kfreebsd*-gnu) +- version_type=linux +- need_lib_prefix=no +- need_version=no +- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' +- soname_spec='${libname}${release}${shared_ext}$major' +- shlibpath_var=LD_LIBRARY_PATH +- shlibpath_overrides_runpath=no +- hardcode_into_libs=yes +- dynamic_linker='GNU ld.so' +- ;; +- + freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; +@@ -15318,17 +15811,17 @@ freebsd* | dragonfly*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; +- freebsd*) # from 4.6 on ++ *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + + gnu*) + version_type=linux +@@ -15381,17 +15874,17 @@ hpux9* | hpux10* | hpux11*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +-interix3*) ++interix[3-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no +@@ -15436,57 +15929,45 @@ irix5* | irix6* | nonstopux*) + ;; + + # No shared lib support for Linux oldld, aout, or coff. + linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + + # This must be Linux ELF. +-linux*) ++linux* | k*bsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then +- lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` ++ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +-knetbsd*-gnu) +- version_type=linux +- need_lib_prefix=no +- need_version=no +- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' +- soname_spec='${libname}${release}${shared_ext}$major' +- shlibpath_var=LD_LIBRARY_PATH +- shlibpath_overrides_runpath=no +- hardcode_into_libs=yes +- dynamic_linker='GNU ld.so' +- ;; +- + netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' +@@ -15558,16 +16039,20 @@ osf3* | osf4* | osf5*) + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + ++rdos*) ++ dynamic_linker=no ++ ;; ++ + solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes +@@ -15654,16 +16139,31 @@ uts4*) + *) + dynamic_linker=no + ;; + esac + { echo "$as_me:$LINENO: result: $dynamic_linker" >&5 + echo "${ECHO_T}$dynamic_linker" >&6; } + test "$dynamic_linker" = no && can_build_shared=no + ++if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ lt_cv_sys_lib_search_path_spec="$sys_lib_search_path_spec" ++fi ++ ++sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" ++if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ lt_cv_sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec" ++fi ++ ++sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" ++ + variables_saved_for_relink="PATH $shlibpath_var $runpath_var" + if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" + fi + + { echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 + echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } + hardcode_action_F77= +@@ -15737,31 +16237,33 @@ if test -f "$ltmain"; then + enable_shared_with_static_runtimes_F77 \ + old_archive_cmds_F77 \ + old_archive_from_new_cmds_F77 \ + predep_objects_F77 \ + postdep_objects_F77 \ + predeps_F77 \ + postdeps_F77 \ + compiler_lib_search_path_F77 \ ++ compiler_lib_search_dirs_F77 \ + archive_cmds_F77 \ + archive_expsym_cmds_F77 \ + postinstall_cmds_F77 \ + postuninstall_cmds_F77 \ + old_archive_from_expsyms_cmds_F77 \ + allow_undefined_flag_F77 \ + no_undefined_flag_F77 \ + export_symbols_cmds_F77 \ + hardcode_libdir_flag_spec_F77 \ + hardcode_libdir_flag_spec_ld_F77 \ + hardcode_libdir_separator_F77 \ + hardcode_automatic_F77 \ + module_cmds_F77 \ + module_expsym_cmds_F77 \ + lt_cv_prog_compiler_c_o_F77 \ ++ fix_srcfile_path_F77 \ + exclude_expsyms_F77 \ + include_expsyms_F77; do + + case $var in + old_archive_cmds_F77 | \ + old_archive_from_new_cmds_F77 | \ + archive_cmds_F77 | \ + archive_expsym_cmds_F77 | \ +@@ -15984,16 +16486,20 @@ postdep_objects=$lt_postdep_objects_F77 + # Dependencies to place before the objects being linked to create a + # shared library. + predeps=$lt_predeps_F77 + + # Dependencies to place after the objects being linked to create a + # shared library. + postdeps=$lt_postdeps_F77 + ++# The directories searched by this compiler when creating a shared ++# library ++compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_F77 ++ + # The library search path used internally by the compiler when linking + # a shared library. + compiler_lib_search_path=$lt_compiler_lib_search_path_F77 + + # Method to check whether dependent libraries are shared objects. + deplibs_check_method=$lt_deplibs_check_method + + # Command to use when deplibs_check_method == file_magic. +@@ -16072,17 +16578,17 @@ link_all_deplibs=$link_all_deplibs_F77 + + # Compile-time system search path for libraries + sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + + # Run-time system search path for libraries + sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + + # Fix the shell variable \$srcfile for the compiler. +-fix_srcfile_path="$fix_srcfile_path_F77" ++fix_srcfile_path=$lt_fix_srcfile_path + + # Set to yes if exported symbols are required. + always_export_symbols=$always_export_symbols_F77 + + # The commands to list exported symbols. + export_symbols_cmds=$lt_export_symbols_cmds_F77 + + # The commands to extract the exported symbol list from a shared archive. +@@ -16130,45 +16636,45 @@ CC="$lt_save_CC" + # Source file extension for Java test sources. + ac_ext=java + + # Object file extension for compiled Java test sources. + objext=o + objext_GCJ=$objext + + # Code to be used in simple compile tests +-lt_simple_compile_test_code="class foo {}\n" ++lt_simple_compile_test_code="class foo {}" + + # Code to be used in simple link tests +-lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }\n' ++lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + + # If no C compiler was specified, use CC. + LTCC=${LTCC-"$CC"} + + # If no C compiler flags were specified, use CFLAGS. + LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + + # Allow CC to be a program name with arguments. + compiler=$CC + + + # save warnings/boilerplate of simple test code + ac_outfile=conftest.$ac_objext +-printf "$lt_simple_compile_test_code" >conftest.$ac_ext ++echo "$lt_simple_compile_test_code" >conftest.$ac_ext + eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err + _lt_compiler_boilerplate=`cat conftest.err` + $rm conftest* + + ac_outfile=conftest.$ac_objext +-printf "$lt_simple_link_test_code" >conftest.$ac_ext ++echo "$lt_simple_link_test_code" >conftest.$ac_ext + eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err + _lt_linker_boilerplate=`cat conftest.err` +-$rm conftest* ++$rm -r conftest* + + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + CC=${GCJ-"gcj"} + compiler=$CC + compiler_GCJ=$CC + for cc_temp in $compiler""; do +@@ -16196,32 +16702,32 @@ if test "$GCC" = yes; then + + { echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 + echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6; } + if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 + else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext +- printf "$lt_simple_compile_test_code" > conftest.$ac_ext ++ echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` +- (eval echo "\"\$as_me:16215: $lt_compile\"" >&5) ++ (eval echo "\"\$as_me:16721: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 +- echo "$as_me:16219: \$? = $ac_status" >&5 ++ echo "$as_me:16725: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi +@@ -16262,33 +16768,35 @@ echo $ECHO_N "checking for $compiler opt + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_GCJ='-m68020 -resident32 -malways-restore-a4' + ;; + +- beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) ++ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + +- mingw* | pw32* | os2*) ++ mingw* | cygwin* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). +- lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' ++ # Although the cygwin gcc ignores -fPIC, still need this for old-style ++ # (--disable-auto-import) libraries ++ + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_GCJ='-fno-common' + ;; + +- interix3*) ++ interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared_GCJ=no +@@ -16336,20 +16844,20 @@ echo $ECHO_N "checking for $compiler opt + case $cc_basename in + xlc*) + lt_prog_compiler_pic_GCJ='-qnocommon' + lt_prog_compiler_wl_GCJ='-Wl,' + ;; + esac + ;; + +- mingw* | pw32* | os2*) ++ mingw* | cygwin* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). +- lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' ++ + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl_GCJ='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) +@@ -16369,17 +16877,17 @@ echo $ECHO_N "checking for $compiler opt + lt_prog_compiler_static_GCJ='-non_shared' + ;; + + newsos6) + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + +- linux*) ++ linux* | k*bsd*-gnu) + case $cc_basename in + icc* | ecc*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, +@@ -16388,25 +16896,45 @@ echo $ECHO_N "checking for $compiler opt + lt_prog_compiler_pic_GCJ='-fpic' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl_GCJ='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static_GCJ='-non_shared' + ;; ++ *) ++ case `$CC -V 2>&1 | sed 5q` in ++ *Sun\ C*) ++ # Sun C 5.9 ++ lt_prog_compiler_pic_GCJ='-KPIC' ++ lt_prog_compiler_static_GCJ='-Bstatic' ++ lt_prog_compiler_wl_GCJ='-Wl,' ++ ;; ++ *Sun\ F*) ++ # Sun Fortran 8.3 passes all unrecognized flags to the linker ++ lt_prog_compiler_pic_GCJ='-KPIC' ++ lt_prog_compiler_static_GCJ='-Bstatic' ++ lt_prog_compiler_wl_GCJ='' ++ ;; ++ esac ++ ;; + esac + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl_GCJ='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static_GCJ='-non_shared' + ;; + ++ rdos*) ++ lt_prog_compiler_static_GCJ='-non_shared' ++ ;; ++ + solaris*) + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl_GCJ='-Qoption ld ';; + *) + lt_prog_compiler_wl_GCJ='-Wl,';; +@@ -16459,53 +16987,53 @@ echo "${ECHO_T}$lt_prog_compiler_pic_GCJ + + # + # Check to make sure the PIC flag actually works. + # + if test -n "$lt_prog_compiler_pic_GCJ"; then + + { echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5 + echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... $ECHO_C" >&6; } +-if test "${lt_prog_compiler_pic_works_GCJ+set}" = set; then +- echo $ECHO_N "(cached) $ECHO_C" >&6 +-else +- lt_prog_compiler_pic_works_GCJ=no ++if test "${lt_cv_prog_compiler_pic_works_GCJ+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ lt_cv_prog_compiler_pic_works_GCJ=no + ac_outfile=conftest.$ac_objext +- printf "$lt_simple_compile_test_code" > conftest.$ac_ext ++ echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_GCJ" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` +- (eval echo "\"\$as_me:16483: $lt_compile\"" >&5) ++ (eval echo "\"\$as_me:17011: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 +- echo "$as_me:16487: \$? = $ac_status" >&5 ++ echo "$as_me:17015: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then +- lt_prog_compiler_pic_works_GCJ=yes ++ lt_cv_prog_compiler_pic_works_GCJ=yes + fi + fi + $rm conftest* + + fi +-{ echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_GCJ" >&5 +-echo "${ECHO_T}$lt_prog_compiler_pic_works_GCJ" >&6; } +- +-if test x"$lt_prog_compiler_pic_works_GCJ" = xyes; then ++{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_pic_works_GCJ" >&5 ++echo "${ECHO_T}$lt_cv_prog_compiler_pic_works_GCJ" >&6; } ++ ++if test x"$lt_cv_prog_compiler_pic_works_GCJ" = xyes; then + case $lt_prog_compiler_pic_GCJ in + "" | " "*) ;; + *) lt_prog_compiler_pic_GCJ=" $lt_prog_compiler_pic_GCJ" ;; + esac + else + lt_prog_compiler_pic_GCJ= + lt_prog_compiler_can_build_shared_GCJ=no + fi +@@ -16522,78 +17050,78 @@ case $host_os in + esac + + # + # Check to make sure the static flag actually works. + # + wl=$lt_prog_compiler_wl_GCJ eval lt_tmp_static_flag=\"$lt_prog_compiler_static_GCJ\" + { echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 + echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; } +-if test "${lt_prog_compiler_static_works_GCJ+set}" = set; then +- echo $ECHO_N "(cached) $ECHO_C" >&6 +-else +- lt_prog_compiler_static_works_GCJ=no ++if test "${lt_cv_prog_compiler_static_works_GCJ+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ lt_cv_prog_compiler_static_works_GCJ=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" +- printf "$lt_simple_link_test_code" > conftest.$ac_ext ++ echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then +- lt_prog_compiler_static_works_GCJ=yes ++ lt_cv_prog_compiler_static_works_GCJ=yes + fi + else +- lt_prog_compiler_static_works_GCJ=yes ++ lt_cv_prog_compiler_static_works_GCJ=yes + fi + fi +- $rm conftest* ++ $rm -r conftest* + LDFLAGS="$save_LDFLAGS" + + fi +-{ echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_GCJ" >&5 +-echo "${ECHO_T}$lt_prog_compiler_static_works_GCJ" >&6; } +- +-if test x"$lt_prog_compiler_static_works_GCJ" = xyes; then ++{ echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_static_works_GCJ" >&5 ++echo "${ECHO_T}$lt_cv_prog_compiler_static_works_GCJ" >&6; } ++ ++if test x"$lt_cv_prog_compiler_static_works_GCJ" = xyes; then + : + else + lt_prog_compiler_static_GCJ= + fi + + + { echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 + echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; } + if test "${lt_cv_prog_compiler_c_o_GCJ+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 + else + lt_cv_prog_compiler_c_o_GCJ=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out +- printf "$lt_simple_compile_test_code" > conftest.$ac_ext ++ echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` +- (eval echo "\"\$as_me:16587: $lt_compile\"" >&5) ++ (eval echo "\"\$as_me:17115: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 +- echo "$as_me:16591: \$? = $ac_status" >&5 ++ echo "$as_me:17119: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_GCJ=yes +@@ -16663,22 +17191,23 @@ echo $ECHO_N "checking whether the $comp + export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms_GCJ= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. +- exclude_expsyms_GCJ="_GLOBAL_OFFSET_TABLE_" ++ exclude_expsyms_GCJ='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. ++ # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; +@@ -16727,17 +17256,17 @@ cc_basename=`$echo "X$cc_temp" | $Xsed - + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in +- aix3* | aix4* | aix5*) ++ aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs_GCJ=no + cat <&2 + + *** Warning: the GNU linker, at least up to release 2.9.1, is reported + *** to be unable to reliably create shared libraries on AIX. + *** Therefore, libtool is disabling shared libraries support. If you +@@ -16775,17 +17304,17 @@ EOF + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, GCJ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_GCJ='-L$libdir' + allow_undefined_flag_GCJ=unsupported + always_export_symbols_GCJ=no + enable_shared_with_static_runtimes_GCJ=yes +- export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' ++ export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds_GCJ='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else +@@ -16793,32 +17322,32 @@ EOF + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_GCJ=no + fi + ;; + +- interix3*) ++ interix[3-9]*) + hardcode_direct_GCJ=no + hardcode_shlibpath_var_GCJ=no + hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' + export_dynamic_flag_spec_GCJ='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_GCJ='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_GCJ='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + +- linux*) ++ gnu* | linux* | k*bsd*-gnu) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec_GCJ='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers +@@ -16826,23 +17355,32 @@ EOF + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac +- archive_cmds_GCJ='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' ++ case `$CC -V 2>&1 | sed 5q` in ++ *Sun\ C*) # Sun C 5.9 ++ whole_archive_flag_spec_GCJ='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' ++ tmp_sharedflag='-G' ;; ++ *Sun\ F*) # Sun Fortran 8.3 ++ tmp_sharedflag='-G' ;; ++ *) ++ tmp_sharedflag='-shared' ;; ++ esac ++ archive_cmds_GCJ='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ +- $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' ++ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + else + ld_shlibs_GCJ=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then +@@ -16937,17 +17475,17 @@ _LT_EOF + hardcode_minus_L_GCJ=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct_GCJ=unsupported + fi + ;; + +- aix4* | aix5*) ++ aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. +@@ -16957,17 +17495,17 @@ _LT_EOF + else + export_symbols_cmds_GCJ='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. +- case $host_os in aix4.[23]|aix4.[23].*|aix5*) ++ case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac +@@ -16991,17 +17529,17 @@ _LT_EOF + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 +- hardcode_direct_GCJ=yes ++ : + else + # We have old collect2 + hardcode_direct_GCJ=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_GCJ=yes + hardcode_libdir_flag_spec_GCJ='-L$libdir' +@@ -17065,21 +17603,28 @@ eval "echo \"\$as_me:$LINENO: $ac_try_ec + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + +-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +-}'` ++lt_aix_libpath_sed=' ++ /Import File Strings/,/^$/ { ++ /^0/ { ++ s/^0 *\(.*\)$/\1/ ++ p ++ } ++ }' ++aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. +-if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +-}'`; fi ++if test -z "$aix_libpath"; then ++ aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` ++fi + else + echo "$as_me: failed program was:" >&5 + sed 's/^/| /' conftest.$ac_ext >&5 + + + fi + + rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ +@@ -17124,21 +17669,28 @@ eval "echo \"\$as_me:$LINENO: $ac_try_ec + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && + $as_test_x conftest$ac_exeext; then + +-aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +-}'` ++lt_aix_libpath_sed=' ++ /Import File Strings/,/^$/ { ++ /^0/ { ++ s/^0 *\(.*\)$/\1/ ++ p ++ } ++ }' ++aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. +-if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +-}'`; fi ++if test -z "$aix_libpath"; then ++ aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` ++fi + else + echo "$as_me: failed program was:" >&5 + sed 's/^/| /' conftest.$ac_ext >&5 + + + fi + + rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ +@@ -17182,17 +17734,17 @@ if test -z "$aix_libpath"; then aix_libp + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds_GCJ='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_From_new_cmds_GCJ='true' + # FIXME: Should let the user specify the lib program. +- old_archive_cmds_GCJ='lib /OUT:$oldlib$oldobjs$old_deplibs' ++ old_archive_cmds_GCJ='lib -OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path_GCJ='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes_GCJ=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[012]) + allow_undefined_flag_GCJ='${wl}-undefined ${wl}suppress' +@@ -17215,29 +17767,28 @@ if test -z "$aix_libpath"; then aix_libp + archive_cmds_need_lc_GCJ=no + hardcode_direct_GCJ=no + hardcode_automatic_GCJ=yes + hardcode_shlibpath_var_GCJ=unsupported + whole_archive_flag_spec_GCJ='' + link_all_deplibs_GCJ=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' +- archive_cmds_GCJ='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' +- module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' +- # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds +- archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' +- module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ++ archive_cmds_GCJ="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" ++ module_cmds_GCJ="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" ++ archive_expsym_cmds_GCJ="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" ++ module_expsym_cmds_GCJ="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' +- archive_cmds_GCJ='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' ++ archive_cmds_GCJ='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $xlcverstring' + module_cmds_GCJ='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds +- archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' ++ archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $xlcverstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + ld_shlibs_GCJ=no + ;; + esac + fi + ;; +@@ -17267,17 +17818,17 @@ if test -z "$aix_libpath"; then aix_libp + freebsd2*) + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=yes + hardcode_minus_L_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. +- freebsd* | kfreebsd*-gnu | dragonfly*) ++ freebsd* | dragonfly*) + archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + hpux9*) + if test "$GCC" = yes; then +@@ -17389,34 +17940,38 @@ if test -z "$aix_libpath"; then aix_libp + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=yes + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + hardcode_shlibpath_var_GCJ=no + ;; + + openbsd*) +- hardcode_direct_GCJ=yes +- hardcode_shlibpath_var_GCJ=no +- if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then +- archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' +- archive_expsym_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' +- hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' +- export_dynamic_flag_spec_GCJ='${wl}-E' +- else +- case $host_os in +- openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) +- archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' +- hardcode_libdir_flag_spec_GCJ='-R$libdir' +- ;; +- *) +- archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' +- hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' +- ;; +- esac ++ if test -f /usr/libexec/ld.so; then ++ hardcode_direct_GCJ=yes ++ hardcode_shlibpath_var_GCJ=no ++ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then ++ archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ++ archive_expsym_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' ++ hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' ++ export_dynamic_flag_spec_GCJ='${wl}-E' ++ else ++ case $host_os in ++ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) ++ archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' ++ hardcode_libdir_flag_spec_GCJ='-R$libdir' ++ ;; ++ *) ++ archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ++ hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' ++ ;; ++ esac ++ fi ++ else ++ ld_shlibs_GCJ=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_minus_L_GCJ=yes + allow_undefined_flag_GCJ=unsupported + archive_cmds_GCJ='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' +@@ -17465,27 +18020,26 @@ if test -z "$aix_libpath"; then aix_libp + archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_shlibpath_var_GCJ=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) +- # The compiler driver will combine linker options so we +- # cannot just pass the convience library names through +- # without $wl, iff we do not link with $LD. +- # Luckily, gcc supports the same syntax we need for Sun Studio. ++ # The compiler driver will combine and reorder linker options, ++ # but understands `-z linker_flag'. GCC discards it without `$wl', ++ # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) +- case $wlarc in +- '') +- whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' ;; +- *) +- whole_archive_flag_spec_GCJ='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; +- esac ;; ++ if test "$GCC" = yes; then ++ whole_archive_flag_spec_GCJ='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ++ else ++ whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' ++ fi ++ ;; + esac + link_all_deplibs_GCJ=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. +@@ -17532,17 +18086,17 @@ if test -z "$aix_libpath"; then aix_libp + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_GCJ=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs_GCJ=yes + fi + ;; + +- sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) ++ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag_GCJ='${wl}-z,text' + archive_cmds_need_lc_GCJ=no + hardcode_shlibpath_var_GCJ=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds_GCJ='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' +@@ -17609,17 +18163,17 @@ x|xyes) + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 + echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; } + $rm conftest* +- printf "$lt_simple_compile_test_code" > conftest.$ac_ext ++ echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest +@@ -17667,30 +18221,17 @@ postinstall_cmds= + postuninstall_cmds= + finish_cmds= + finish_eval= + shlibpath_var= + shlibpath_overrides_runpath=unknown + version_type=none + dynamic_linker="$host_os ld.so" + sys_lib_dlsearch_path_spec="/lib /usr/lib" +-if test "$GCC" = yes; then +- sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` +- if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then +- # if the path contains ";" then we assume it to be the separator +- # otherwise default to the standard path separator (i.e. ":") - it is +- # assumed that no part of a normal pathname contains ";" but that should +- # okay in the real world where ";" in dirpaths is itself problematic. +- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` +- else +- sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` +- fi +-else +- sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +-fi ++ + need_lib_prefix=unknown + hardcode_into_libs=no + + # when you set need_version to no, make sure it does not cause -set_version + # flags to be left without arguments + need_version=unknown + + case $host_os in +@@ -17698,17 +18239,17 @@ aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +-aix4* | aix5*) ++aix[4-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH +@@ -17837,50 +18378,33 @@ darwin* | rhapsody*) + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +- # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. +- if test "$GCC" = yes; then +- sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` +- else +- sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' +- fi ++ + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + + dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + + freebsd1*) + dynamic_linker=no + ;; + +-kfreebsd*-gnu) +- version_type=linux +- need_lib_prefix=no +- need_version=no +- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' +- soname_spec='${libname}${release}${shared_ext}$major' +- shlibpath_var=LD_LIBRARY_PATH +- shlibpath_overrides_runpath=no +- hardcode_into_libs=yes +- dynamic_linker='GNU ld.so' +- ;; +- + freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; +@@ -17908,17 +18432,17 @@ freebsd* | dragonfly*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; +- freebsd*) # from 4.6 on ++ *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + + gnu*) + version_type=linux +@@ -17971,17 +18495,17 @@ hpux9* | hpux10* | hpux11*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +-interix3*) ++interix[3-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no +@@ -18026,57 +18550,45 @@ irix5* | irix6* | nonstopux*) + ;; + + # No shared lib support for Linux oldld, aout, or coff. + linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + + # This must be Linux ELF. +-linux*) ++linux* | k*bsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then +- lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` ++ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +-knetbsd*-gnu) +- version_type=linux +- need_lib_prefix=no +- need_version=no +- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' +- soname_spec='${libname}${release}${shared_ext}$major' +- shlibpath_var=LD_LIBRARY_PATH +- shlibpath_overrides_runpath=no +- hardcode_into_libs=yes +- dynamic_linker='GNU ld.so' +- ;; +- + netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' +@@ -18148,16 +18660,20 @@ osf3* | osf4* | osf5*) + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + ++rdos*) ++ dynamic_linker=no ++ ;; ++ + solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes +@@ -18244,16 +18760,31 @@ uts4*) + *) + dynamic_linker=no + ;; + esac + { echo "$as_me:$LINENO: result: $dynamic_linker" >&5 + echo "${ECHO_T}$dynamic_linker" >&6; } + test "$dynamic_linker" = no && can_build_shared=no + ++if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ lt_cv_sys_lib_search_path_spec="$sys_lib_search_path_spec" ++fi ++ ++sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" ++if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ lt_cv_sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec" ++fi ++ ++sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" ++ + variables_saved_for_relink="PATH $shlibpath_var $runpath_var" + if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" + fi + + { echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 + echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; } + hardcode_action_GCJ= +@@ -18327,31 +18858,33 @@ if test -f "$ltmain"; then + enable_shared_with_static_runtimes_GCJ \ + old_archive_cmds_GCJ \ + old_archive_from_new_cmds_GCJ \ + predep_objects_GCJ \ + postdep_objects_GCJ \ + predeps_GCJ \ + postdeps_GCJ \ + compiler_lib_search_path_GCJ \ ++ compiler_lib_search_dirs_GCJ \ + archive_cmds_GCJ \ + archive_expsym_cmds_GCJ \ + postinstall_cmds_GCJ \ + postuninstall_cmds_GCJ \ + old_archive_from_expsyms_cmds_GCJ \ + allow_undefined_flag_GCJ \ + no_undefined_flag_GCJ \ + export_symbols_cmds_GCJ \ + hardcode_libdir_flag_spec_GCJ \ + hardcode_libdir_flag_spec_ld_GCJ \ + hardcode_libdir_separator_GCJ \ + hardcode_automatic_GCJ \ + module_cmds_GCJ \ + module_expsym_cmds_GCJ \ + lt_cv_prog_compiler_c_o_GCJ \ ++ fix_srcfile_path_GCJ \ + exclude_expsyms_GCJ \ + include_expsyms_GCJ; do + + case $var in + old_archive_cmds_GCJ | \ + old_archive_from_new_cmds_GCJ | \ + archive_cmds_GCJ | \ + archive_expsym_cmds_GCJ | \ +@@ -18574,16 +19107,20 @@ postdep_objects=$lt_postdep_objects_GCJ + # Dependencies to place before the objects being linked to create a + # shared library. + predeps=$lt_predeps_GCJ + + # Dependencies to place after the objects being linked to create a + # shared library. + postdeps=$lt_postdeps_GCJ + ++# The directories searched by this compiler when creating a shared ++# library ++compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_GCJ ++ + # The library search path used internally by the compiler when linking + # a shared library. + compiler_lib_search_path=$lt_compiler_lib_search_path_GCJ + + # Method to check whether dependent libraries are shared objects. + deplibs_check_method=$lt_deplibs_check_method + + # Command to use when deplibs_check_method == file_magic. +@@ -18662,17 +19199,17 @@ link_all_deplibs=$link_all_deplibs_GCJ + + # Compile-time system search path for libraries + sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + + # Run-time system search path for libraries + sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + + # Fix the shell variable \$srcfile for the compiler. +-fix_srcfile_path="$fix_srcfile_path_GCJ" ++fix_srcfile_path=$lt_fix_srcfile_path + + # Set to yes if exported symbols are required. + always_export_symbols=$always_export_symbols_GCJ + + # The commands to list exported symbols. + export_symbols_cmds=$lt_export_symbols_cmds_GCJ + + # The commands to extract the exported symbol list from a shared archive. +@@ -18719,17 +19256,17 @@ CC="$lt_save_CC" + # Source file extension for RC test sources. + ac_ext=rc + + # Object file extension for compiled RC test sources. + objext=o + objext_RC=$objext + + # Code to be used in simple compile tests +-lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n' ++lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + + # Code to be used in simple link tests + lt_simple_link_test_code="$lt_simple_compile_test_code" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + + # If no C compiler was specified, use CC. + LTCC=${LTCC-"$CC"} +@@ -18738,26 +19275,26 @@ LTCC=${LTCC-"$CC"} + LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + + # Allow CC to be a program name with arguments. + compiler=$CC + + + # save warnings/boilerplate of simple test code + ac_outfile=conftest.$ac_objext +-printf "$lt_simple_compile_test_code" >conftest.$ac_ext ++echo "$lt_simple_compile_test_code" >conftest.$ac_ext + eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err + _lt_compiler_boilerplate=`cat conftest.err` + $rm conftest* + + ac_outfile=conftest.$ac_objext +-printf "$lt_simple_link_test_code" >conftest.$ac_ext ++echo "$lt_simple_link_test_code" >conftest.$ac_ext + eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err + _lt_linker_boilerplate=`cat conftest.err` +-$rm conftest* ++$rm -r conftest* + + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + CC=${RC-"windres"} + compiler=$CC + compiler_RC=$CC + for cc_temp in $compiler""; do +@@ -18807,31 +19344,33 @@ if test -f "$ltmain"; then + enable_shared_with_static_runtimes_RC \ + old_archive_cmds_RC \ + old_archive_from_new_cmds_RC \ + predep_objects_RC \ + postdep_objects_RC \ + predeps_RC \ + postdeps_RC \ + compiler_lib_search_path_RC \ ++ compiler_lib_search_dirs_RC \ + archive_cmds_RC \ + archive_expsym_cmds_RC \ + postinstall_cmds_RC \ + postuninstall_cmds_RC \ + old_archive_from_expsyms_cmds_RC \ + allow_undefined_flag_RC \ + no_undefined_flag_RC \ + export_symbols_cmds_RC \ + hardcode_libdir_flag_spec_RC \ + hardcode_libdir_flag_spec_ld_RC \ + hardcode_libdir_separator_RC \ + hardcode_automatic_RC \ + module_cmds_RC \ + module_expsym_cmds_RC \ + lt_cv_prog_compiler_c_o_RC \ ++ fix_srcfile_path_RC \ + exclude_expsyms_RC \ + include_expsyms_RC; do + + case $var in + old_archive_cmds_RC | \ + old_archive_from_new_cmds_RC | \ + archive_cmds_RC | \ + archive_expsym_cmds_RC | \ +@@ -19054,16 +19593,20 @@ postdep_objects=$lt_postdep_objects_RC + # Dependencies to place before the objects being linked to create a + # shared library. + predeps=$lt_predeps_RC + + # Dependencies to place after the objects being linked to create a + # shared library. + postdeps=$lt_postdeps_RC + ++# The directories searched by this compiler when creating a shared ++# library ++compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_RC ++ + # The library search path used internally by the compiler when linking + # a shared library. + compiler_lib_search_path=$lt_compiler_lib_search_path_RC + + # Method to check whether dependent libraries are shared objects. + deplibs_check_method=$lt_deplibs_check_method + + # Command to use when deplibs_check_method == file_magic. +@@ -19142,17 +19685,17 @@ link_all_deplibs=$link_all_deplibs_RC + + # Compile-time system search path for libraries + sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + + # Run-time system search path for libraries + sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + + # Fix the shell variable \$srcfile for the compiler. +-fix_srcfile_path="$fix_srcfile_path_RC" ++fix_srcfile_path=$lt_fix_srcfile_path + + # Set to yes if exported symbols are required. + always_export_symbols=$always_export_symbols_RC + + # The commands to list exported symbols. + export_symbols_cmds=$lt_export_symbols_cmds_RC + + # The commands to extract the exported symbol list from a shared archive. +@@ -20194,23 +20737,23 @@ am__fastdepCXX_FALSE!$am__fastdepCXX_FAL + build!$build$ac_delim + build_cpu!$build_cpu$ac_delim + build_vendor!$build_vendor$ac_delim + build_os!$build_os$ac_delim + host!$host$ac_delim + host_cpu!$host_cpu$ac_delim + host_vendor!$host_vendor$ac_delim + host_os!$host_os$ac_delim ++SED!$SED$ac_delim + GREP!$GREP$ac_delim + EGREP!$EGREP$ac_delim + LN_S!$LN_S$ac_delim + ECHO!$ECHO$ac_delim + AR!$AR$ac_delim + RANLIB!$RANLIB$ac_delim +-CXXCPP!$CXXCPP$ac_delim + _ACEOF + + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then + break + elif $ac_last_try; then + { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 + echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } +@@ -20242,28 +20785,31 @@ rm -f conf$$subs.sed + cat >>$CONFIG_STATUS <<_ACEOF + CEOF$ac_eof + _ACEOF + + + ac_delim='%!_!# ' + for ac_last_try in false false false false false :; do + cat >conf$$subs.sed <<_ACEOF ++DSYMUTIL!$DSYMUTIL$ac_delim ++NMEDIT!$NMEDIT$ac_delim ++CXXCPP!$CXXCPP$ac_delim + F77!$F77$ac_delim + FFLAGS!$FFLAGS$ac_delim + ac_ct_F77!$ac_ct_F77$ac_delim + LIBTOOL!$LIBTOOL$ac_delim + LIBTOOL_DEPS!$LIBTOOL_DEPS$ac_delim + SELFTEST_TRUE!$SELFTEST_TRUE$ac_delim + SELFTEST_FALSE!$SELFTEST_FALSE$ac_delim + LIBOBJS!$LIBOBJS$ac_delim + LTLIBOBJS!$LTLIBOBJS$ac_delim + _ACEOF + +- if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 9; then ++ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 12; then + break + elif $ac_last_try; then + { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 + echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} + { (exit 1); exit 1; }; } + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +diff --git a/toolkit/crashreporter/google-breakpad/src/breakpad_googletest_includes.h b/toolkit/crashreporter/google-breakpad/src/breakpad_googletest_includes.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/breakpad_googletest_includes.h +@@ -0,0 +1,36 @@ ++// Copyright (c) 2009, 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 BREAKPAD_GOOGLETEST_INCLUDES_H__ ++#define BREAKPAD_GOOGLETEST_INCLUDES_H__ ++ ++#include "testing/gtest/include/gtest/gtest.h" ++#include "testing/include/gmock/gmock.h" ++ ++#endif // BREAKPAD_GOOGLETEST_INCLUDES_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/data/linux-gate-amd.sym b/toolkit/crashreporter/google-breakpad/src/client/linux/data/linux-gate-amd.sym +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/linux/data/linux-gate-amd.sym +@@ -0,0 +1,3 @@ ++MODULE Linux x86 B8CFDE93002D54DA1900A40AA1BD67690 linux-gate.so ++PUBLIC 400 0 __kernel_vsyscall ++STACK WIN 4 400 100 1 1 0 0 0 0 0 1 +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/data/linux-gate-intel.sym b/toolkit/crashreporter/google-breakpad/src/client/linux/data/linux-gate-intel.sym +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/linux/data/linux-gate-intel.sym +@@ -0,0 +1,3 @@ ++MODULE Linux x86 4FBDA58B5A1DF5A379E3CF19A235EA090 linux-gate.so ++PUBLIC 400 0 __kernel_vsyscall ++STACK WIN 4 400 200 3 3 0 0 0 0 0 1 +\ No newline at end of file +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/Makefile.in b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/Makefile.in +--- a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/Makefile.in ++++ b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/Makefile.in +@@ -44,17 +44,15 @@ include $(DEPTH)/config/autoconf.mk + MODULE = handler + LIBRARY_NAME = exception_handler_s + XPI_NAME = crashreporter + + LOCAL_INCLUDES = -I$(srcdir)/../../.. + + CPPSRCS = \ + exception_handler.cc \ +- minidump_generator.cc \ +- linux_thread.cc \ + $(NULL) + + # need static lib + FORCE_STATIC_LIB = 1 + FORCE_USE_PIC = 1 + + include $(topsrcdir)/config/rules.mk +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.cc b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.cc +--- a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.cc ++++ b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.cc +@@ -1,13 +1,11 @@ +-// Copyright (c) 2006, Google Inc. ++// Copyright (c) 2009, Google Inc. + // All rights reserved. + // +-// Author: Li Liu +-// + // 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 +@@ -24,244 +22,178 @@ + // 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 +-#include +-#include +-#include +-#include ++// The ExceptionHandler object installs signal handlers for a number of ++// signals. We rely on the signal handler running on the thread which crashed ++// in order to identify it. This is true of the synchronous signals (SEGV etc), ++// but not true of ABRT. Thus, if you send ABRT to yourself in a program which ++// uses ExceptionHandler, you need to use tgkill to direct it to the current ++// thread. ++// ++// The signal flow looks like this: ++// ++// SignalHandler (uses a global stack of ExceptionHandler objects to find ++// | one to handle the signal. If the first rejects it, try ++// | the second etc...) ++// V ++// HandleSignal ----------------------------| (clones a new process which ++// | | shares an address space with ++// (wait for cloned | the crashed process. This ++// process) | allows us to ptrace the crashed ++// | | process) ++// V V ++// (set signal handler to ThreadEntry (static function to bounce ++// SIG_DFL and rethrow, | back into the object) ++// killing the crashed | ++// process) V ++// DoDump (writes minidump) ++// | ++// V ++// sys_exit ++// + +-#include +-#include +-#include +-#include ++// This code is a little fragmented. Different functions of the ExceptionHandler ++// class run in a number of different contexts. Some of them run in a normal ++// context and are easy to code, others run in a compromised context and the ++// restrictions at the top of minidump_writer.cc apply: no libc and use the ++// alternative malloc. Each function should have comment above it detailing the ++// context which it runs in. + + #include "client/linux/handler/exception_handler.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "common/linux/linux_libc_support.h" ++#include "common/linux/linux_syscall_support.h" ++#include "common/linux/memory.h" ++#include "client/linux/minidump_writer/minidump_writer.h" + #include "common/linux/guid_creator.h" +-#include "google_breakpad/common/minidump_format.h" ++ ++// A wrapper for the tgkill syscall: send a signal to a specific thread. ++static int tgkill(pid_t tgid, pid_t tid, int sig) { ++ syscall(__NR_tgkill, tgid, tid, sig); ++ return 0; ++} + + namespace google_breakpad { + +-// Signals that we are interested. +-int SigTable[] = { +-#if defined(SIGSEGV) +- SIGSEGV, +-#endif +-#ifdef SIGABRT +- SIGABRT, +-#endif +-#ifdef SIGFPE +- SIGFPE, +-#endif +-#ifdef SIGILL +- SIGILL, +-#endif +-#ifdef SIGBUS +- SIGBUS, +-#endif ++// The list of signals which we consider to be crashes. The default action for ++// all these signals must be Core (see man 7 signal) because we rethrow the ++// signal after handling it and expect that it'll be fatal. ++static const int kExceptionSignals[] = { ++ SIGSEGV, SIGABRT, SIGFPE, SIGILL, SIGBUS, -1 + }; + +-std::vector *ExceptionHandler::handler_stack_ = NULL; +-int ExceptionHandler::handler_stack_index_ = 0; ++// We can stack multiple exception handlers. In that case, this is the global ++// which holds the stack. ++std::vector* ExceptionHandler::handler_stack_ = NULL; ++unsigned ExceptionHandler::handler_stack_index_ = 0; + pthread_mutex_t ExceptionHandler::handler_stack_mutex_ = +-PTHREAD_MUTEX_INITIALIZER; ++ PTHREAD_MUTEX_INITIALIZER; + +-ExceptionHandler::ExceptionHandler(const string &dump_path, ++// Runs before crashing: normal context. ++ExceptionHandler::ExceptionHandler(const std::string &dump_path, + FilterCallback filter, + MinidumpCallback callback, + void *callback_context, + bool install_handler) + : filter_(filter), + callback_(callback), + callback_context_(callback_context), + dump_path_(), +- installed_handler_(install_handler) { ++ handler_installed_(install_handler), ++ crash_handler_(NULL) { + set_dump_path(dump_path); + + if (install_handler) { +- SetupHandler(); ++ InstallHandlers(); ++ + pthread_mutex_lock(&handler_stack_mutex_); +- if (handler_stack_ == NULL) +- handler_stack_ = new std::vector; +- handler_stack_->push_back(this); ++ if (handler_stack_ == NULL) ++ handler_stack_ = new std::vector; ++ handler_stack_->push_back(this); + pthread_mutex_unlock(&handler_stack_mutex_); + } + } + ++// Runs before crashing: normal context. + ExceptionHandler::~ExceptionHandler() { +- TeardownAllHandler(); +- pthread_mutex_lock(&handler_stack_mutex_); +- if (handler_stack_->back() == this) { +- handler_stack_->pop_back(); +- } else { +- fprintf(stderr, "warning: removing Breakpad handler out of order\n"); +- for (std::vector::iterator iterator = +- handler_stack_->begin(); +- iterator != handler_stack_->end(); +- ++iterator) { +- if (*iterator == this) { +- handler_stack_->erase(iterator); +- } +- } ++ UninstallHandlers(); ++} ++ ++// Runs before crashing: normal context. ++bool ExceptionHandler::InstallHandlers() { ++ // We run the signal handlers on an alternative stack because we might have ++ // crashed because of a stack overflow. ++ ++ // We use this value rather than SIGSTKSZ because we would end up overrunning ++ // such a small stack. ++ static const unsigned kSigStackSize = 8192; ++ ++ signal_stack = malloc(kSigStackSize); ++ stack_t stack; ++ memset(&stack, 0, sizeof(stack)); ++ stack.ss_sp = signal_stack; ++ stack.ss_size = kSigStackSize; ++ ++ if (sigaltstack(&stack, NULL) == -1) ++ return false; ++ ++ struct sigaction sa; ++ memset(&sa, 0, sizeof(sa)); ++ sigemptyset(&sa.sa_mask); ++ ++ // mask all exception signals when we're handling one of them. ++ for (unsigned i = 0; kExceptionSignals[i] != -1; ++i) ++ sigaddset(&sa.sa_mask, kExceptionSignals[i]); ++ ++ sa.sa_sigaction = SignalHandler; ++ sa.sa_flags = SA_ONSTACK | SA_SIGINFO; ++ ++ for (unsigned i = 0; kExceptionSignals[i] != -1; ++i) { ++ struct sigaction* old = new struct sigaction; ++ if (sigaction(kExceptionSignals[i], &sa, old) == -1) ++ return false; ++ old_handlers_.push_back(std::make_pair(kExceptionSignals[i], old)); ++ } ++ return true; ++} ++ ++// Runs before crashing: normal context. ++void ExceptionHandler::UninstallHandlers() { ++ for (unsigned i = 0; i < old_handlers_.size(); ++i) { ++ struct sigaction *action = ++ reinterpret_cast(old_handlers_[i].second); ++ sigaction(old_handlers_[i].first, action, NULL); ++ delete action; + } + +- if (handler_stack_->empty()) { +- // When destroying the last ExceptionHandler that installed a handler, +- // clean up the handler stack. +- delete handler_stack_; +- handler_stack_ = NULL; +- } +- pthread_mutex_unlock(&handler_stack_mutex_); ++ old_handlers_.clear(); + } + +-bool ExceptionHandler::WriteMinidump() { +- bool success = InternalWriteMinidump(0, 0, NULL); +- UpdateNextID(); +- return success; +-} +- +-// static +-bool ExceptionHandler::WriteMinidump(const string &dump_path, +- MinidumpCallback callback, +- void *callback_context) { +- ExceptionHandler handler(dump_path, NULL, callback, +- callback_context, false); +- return handler.InternalWriteMinidump(0, 0, NULL); +-} +- +-void ExceptionHandler::SetupHandler() { +- // Signal on a different stack to avoid using the stack +- // of the crashing thread. +- struct sigaltstack sig_stack; +- sig_stack.ss_sp = malloc(MINSIGSTKSZ); +- if (sig_stack.ss_sp == NULL) +- return; +- sig_stack.ss_size = MINSIGSTKSZ; +- sig_stack.ss_flags = 0; +- +- if (sigaltstack(&sig_stack, NULL) < 0) +- return; +- for (size_t i = 0; i < sizeof(SigTable) / sizeof(SigTable[0]); ++i) +- SetupHandler(SigTable[i]); +-} +- +-void ExceptionHandler::SetupHandler(int signo) { +- struct sigaction act, old_act; +- act.sa_handler = HandleException; +- act.sa_flags = SA_ONSTACK; +- if (sigaction(signo, &act, &old_act) < 0) +- return; +- old_handlers_[signo] = old_act.sa_handler; +-} +- +-void ExceptionHandler::TeardownHandler(int signo) { +- if (old_handlers_.find(signo) != old_handlers_.end()) { +- struct sigaction act; +- act.sa_handler = old_handlers_[signo]; +- act.sa_flags = 0; +- sigaction(signo, &act, 0); +- } +-} +- +-void ExceptionHandler::TeardownAllHandler() { +- for (size_t i = 0; i < sizeof(SigTable) / sizeof(SigTable[0]); ++i) { +- TeardownHandler(SigTable[i]); +- } +-} +- +-// static +-void ExceptionHandler::HandleException(int signo) { +- // In Linux, the context information about the signal is put on the stack of +- // the signal handler frame as value parameter. For some reasons, the +- // prototype of the handler doesn't declare this information as parameter, we +- // will do it by hand. It is the second parameter above the signal number. +- // However, if we are being called by another signal handler passing the +- // signal up the chain, then we may not have this random extra parameter, +- // so we may have to walk the stack to find it. We do the actual work +- // on another thread, where it's a little safer, but we want the ebp +- // from this frame to find it. +- uintptr_t current_ebp = 0; +- asm volatile ("movl %%ebp, %0" +- :"=m"(current_ebp)); +- +- pthread_mutex_lock(&handler_stack_mutex_); +- ExceptionHandler *current_handler = +- handler_stack_->at(handler_stack_->size() - ++handler_stack_index_); +- pthread_mutex_unlock(&handler_stack_mutex_); +- +- // Restore original handler. +- current_handler->TeardownHandler(signo); +- +- struct sigcontext *sig_ctx = NULL; +- if (current_handler->InternalWriteMinidump(signo, current_ebp, &sig_ctx)) { +- // Fully handled this exception, safe to exit. +- exit(EXIT_FAILURE); +- } else { +- // Exception not fully handled, will call the next handler in stack to +- // process it. +- typedef void (*SignalHandler)(int signo, struct sigcontext); +- SignalHandler old_handler = +- reinterpret_cast(current_handler->old_handlers_[signo]); +- if (old_handler != NULL && sig_ctx != NULL) +- old_handler(signo, *sig_ctx); +- } +- +- pthread_mutex_lock(&handler_stack_mutex_); +- current_handler->SetupHandler(signo); +- --handler_stack_index_; +- // All the handlers in stack have been invoked to handle the exception, +- // normally the process should be terminated and should not reach here. +- // In case we got here, ask the OS to handle it to avoid endless loop, +- // normally the OS will generate a core and termiate the process. This +- // may be desired to debug the program. +- if (handler_stack_index_ == 0) +- signal(signo, SIG_DFL); +- pthread_mutex_unlock(&handler_stack_mutex_); +-} +- +-bool ExceptionHandler::InternalWriteMinidump(int signo, +- uintptr_t sighandler_ebp, +- struct sigcontext **sig_ctx) { +- if (filter_ && !filter_(callback_context_)) +- return false; +- +- bool success = false; +- // Block all the signals we want to process when writting minidump. +- // We don't want it to be interrupted. +- sigset_t sig_blocked, sig_old; +- bool blocked = true; +- sigfillset(&sig_blocked); +- for (size_t i = 0; i < sizeof(SigTable) / sizeof(SigTable[0]); ++i) +- sigdelset(&sig_blocked, SigTable[i]); +- if (sigprocmask(SIG_BLOCK, &sig_blocked, &sig_old) != 0) { +- blocked = false; +- fprintf(stderr, "google_breakpad::ExceptionHandler::HandleException: " +- "failed to block signals.\n"); +- } +- +- success = minidump_generator_.WriteMinidumpToFile( +- next_minidump_path_c_, signo, sighandler_ebp, sig_ctx); +- +- // Unblock the signals. +- if (blocked) { +- sigprocmask(SIG_SETMASK, &sig_old, &sig_old); +- } +- +- if (callback_) +- success = callback_(dump_path_c_, next_minidump_id_c_, +- callback_context_, success); +- return success; +-} +- ++// Runs before crashing: normal context. + void ExceptionHandler::UpdateNextID() { + GUID guid; + char guid_str[kGUIDStringLength + 1]; + if (CreateGUID(&guid) && GUIDToString(&guid, guid_str, sizeof(guid_str))) { + next_minidump_id_ = guid_str; + next_minidump_id_c_ = next_minidump_id_.c_str(); + + char minidump_path[PATH_MAX]; +@@ -269,9 +201,155 @@ void ExceptionHandler::UpdateNextID() { + dump_path_c_, + guid_str); + + next_minidump_path_ = minidump_path; + next_minidump_path_c_ = next_minidump_path_.c_str(); + } + } + ++// This function runs in a compromised context: see the top of the file. ++// Runs on the crashing thread. ++// static ++void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) { ++ // All the exception signals are blocked at this point. ++ ++ pthread_mutex_lock(&handler_stack_mutex_); ++ ++ if (!handler_stack_->size()) { ++ pthread_mutex_unlock(&handler_stack_mutex_); ++ return; ++ } ++ ++ for (int i = handler_stack_->size() - 1; i >= 0; --i) { ++ if ((*handler_stack_)[i]->HandleSignal(sig, info, uc)) { ++ // successfully handled: We are in an invalid state since an exception ++ // signal has been delivered. We don't call the exit handlers because ++ // they could end up corrupting on-disk state. ++ break; ++ } ++ } ++ ++ pthread_mutex_unlock(&handler_stack_mutex_); ++ ++ // Terminate ourselves with the same signal so that our parent knows that we ++ // crashed. The default action for all the signals which we catch is Core, so ++ // this is the end of us. ++ signal(sig, SIG_DFL); ++ tgkill(getpid(), sys_gettid(), sig); ++ ++ // not reached. ++} ++ ++struct ThreadArgument { ++ pid_t pid; // the crashing process ++ ExceptionHandler* handler; ++ const void* context; // a CrashContext structure ++ size_t context_size; ++}; ++ ++// This is the entry function for the cloned process. We are in a compromised ++// context here: see the top of the file. ++// static ++int ExceptionHandler::ThreadEntry(void *arg) { ++ const ThreadArgument *thread_arg = reinterpret_cast(arg); ++ return thread_arg->handler->DoDump(thread_arg->pid, thread_arg->context, ++ thread_arg->context_size) == false; ++} ++ ++// This function runs in a compromised context: see the top of the file. ++// Runs on the crashing thread. ++bool ExceptionHandler::HandleSignal(int sig, siginfo_t* info, void* uc) { ++ if (filter_ && !filter_(callback_context_)) ++ return false; ++ ++ // Allow ourselves to be dumped. ++ sys_prctl(PR_SET_DUMPABLE, 1); ++ ++ CrashContext context; ++ memcpy(&context.siginfo, info, sizeof(siginfo_t)); ++ memcpy(&context.context, uc, sizeof(struct ucontext)); ++ memcpy(&context.float_state, ((struct ucontext *)uc)->uc_mcontext.fpregs, ++ sizeof(context.float_state)); ++ context.tid = sys_gettid(); ++ ++ if (crash_handler_ && crash_handler_(&context, sizeof(context), ++ callback_context_)) ++ return true; ++ ++ return GenerateDump(&context); ++} ++ ++// This function may run in a compromised context: see the top of the file. ++bool ExceptionHandler::GenerateDump(CrashContext *context) { ++ static const unsigned kChildStackSize = 8000; ++ PageAllocator allocator; ++ uint8_t* stack = (uint8_t*) allocator.Alloc(kChildStackSize); ++ if (!stack) ++ return false; ++ // clone() needs the top-most address. (scrub just to be safe) ++ stack += kChildStackSize; ++ my_memset(stack - 16, 0, 16); ++ ++ ThreadArgument thread_arg; ++ thread_arg.handler = this; ++ thread_arg.pid = getpid(); ++ thread_arg.context = context; ++ thread_arg.context_size = sizeof(*context); ++ ++ const pid_t child = sys_clone( ++ ThreadEntry, stack, CLONE_FILES | CLONE_FS | CLONE_UNTRACED, ++ &thread_arg, NULL, NULL, NULL); ++ int r, status; ++ do { ++ r = sys_waitpid(child, &status, __WALL); ++ } while (r == -1 && errno == EINTR); ++ ++ if (r == -1) { ++ static const char msg[] = "ExceptionHandler::GenerateDump waitpid failed:"; ++ sys_write(2, msg, sizeof(msg) - 1); ++ sys_write(2, strerror(errno), strlen(strerror(errno))); ++ sys_write(2, "\n", 1); ++ } ++ ++ bool success = r != -1 && WIFEXITED(status) && WEXITSTATUS(status) == 0; ++ ++ if (callback_) ++ success = callback_(dump_path_c_, next_minidump_id_c_, ++ callback_context_, success); ++ ++ return success; ++} ++ ++// This function runs in a compromised context: see the top of the file. ++// Runs on the cloned process. ++bool ExceptionHandler::DoDump(pid_t crashing_process, const void* context, ++ size_t context_size) { ++ return google_breakpad::WriteMinidump( ++ next_minidump_path_c_, crashing_process, context, context_size); ++} ++ ++// static ++bool ExceptionHandler::WriteMinidump(const std::string &dump_path, ++ MinidumpCallback callback, ++ void* callback_context) { ++ ExceptionHandler eh(dump_path, NULL, callback, callback_context, false); ++ return eh.WriteMinidump(); ++} ++ ++bool ExceptionHandler::WriteMinidump() { ++ // Allow ourselves to be dumped. ++ sys_prctl(PR_SET_DUMPABLE, 1); ++ ++ CrashContext context; ++ int getcontext_result = getcontext(&context.context); ++ if (getcontext_result) ++ return false; ++ memcpy(&context.float_state, context.context.uc_mcontext.fpregs, ++ sizeof(context.float_state)); ++ context.tid = sys_gettid(); ++ ++ bool success = GenerateDump(&context); ++ UpdateNextID(); ++ return success; ++} ++ + } // namespace google_breakpad +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.h b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.h +--- a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.h ++++ b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler.h +@@ -1,13 +1,11 @@ +-// Copyright (c) 2006, Google Inc. ++// Copyright (c) 2009, Google Inc. + // All rights reserved. + // +-// Author: Li Liu +-// + // 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 +@@ -24,35 +22,26 @@ + // 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 CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H__ +-#define CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H__ ++#ifndef CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H_ ++#define CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H_ + +-#include ++#include ++#include + +-#include +-#include +-#include +- +-#include "client/linux/handler/minidump_generator.h" +- +-// Context information when exception occured. +-struct sigcontex; ++#include + + namespace google_breakpad { + +-using std::string; +- +-// + // ExceptionHandler + // + // ExceptionHandler can write a minidump file when an exception occurs, + // or when WriteMinidump() is called explicitly by your program. + // + // To have the exception handler write minidumps when an uncaught exception + // (crash) occurs, you should create an instance early in the execution + // of your program, and keep it around for the entire time you want to +@@ -67,17 +56,16 @@ using std::string; + // + // In either case, a callback function is called when a minidump is written, + // which receives the unqiue id of the minidump. The caller can use this + // id to collect and write additional application state, and to launch an + // external crash-reporting application. + // + // Caller should try to make the callbacks as crash-friendly as possible, + // it should avoid use heap memory allocation as much as possible. +-// + class ExceptionHandler { + public: + // A callback function to run before Breakpad performs any substantial + // processing of an exception. A FilterCallback is called before writing + // a minidump. context is the parameter supplied by the user as + // callback_context when the handler was created. + // + // If a FilterCallback returns true, Breakpad will continue processing, +@@ -102,116 +90,110 @@ class ExceptionHandler { + // should normally return the value of |succeeded|, or when they wish to + // not report an exception of handled, false. Callbacks will rarely want to + // return true directly (unless |succeeded| is true). + typedef bool (*MinidumpCallback)(const char *dump_path, + const char *minidump_id, + void *context, + bool succeeded); + ++ // In certain cases, a user may wish to handle the generation of the minidump ++ // themselves. In this case, they can install a handler callback which is ++ // called when a crash has occured. If this function returns true, no other ++ // processing of occurs and the process will shortly be crashed. If this ++ // returns false, the normal processing continues. ++ typedef bool (*HandlerCallback)(const void* crash_context, ++ size_t crash_context_size, ++ void* context); ++ + // Creates a new ExceptionHandler instance to handle writing minidumps. + // Before writing a minidump, the optional filter callback will be called. + // Its return value determines whether or not Breakpad should write a + // minidump. Minidump files will be written to dump_path, and the optional + // callback is called after writing the dump file, as described above. + // If install_handler is true, then a minidump will be written whenever + // an unhandled exception occurs. If it is false, minidumps will only + // be written when WriteMinidump is called. +- ExceptionHandler(const string &dump_path, ++ ExceptionHandler(const std::string &dump_path, + FilterCallback filter, MinidumpCallback callback, + void *callback_context, + bool install_handler); + ~ExceptionHandler(); + + // Get and set the minidump path. +- string dump_path() const { return dump_path_; } +- void set_dump_path(const string &dump_path) { ++ std::string dump_path() const { return dump_path_; } ++ void set_dump_path(const std::string &dump_path) { + dump_path_ = dump_path; + dump_path_c_ = dump_path_.c_str(); + UpdateNextID(); + } + ++ void set_crash_handler(HandlerCallback callback) { ++ crash_handler_ = callback; ++ } ++ + // Writes a minidump immediately. This can be used to capture the + // execution state independently of a crash. Returns true on success. + bool WriteMinidump(); + + // Convenience form of WriteMinidump which does not require an + // ExceptionHandler instance. +- static bool WriteMinidump(const string &dump_path, ++ static bool WriteMinidump(const std::string &dump_path, + MinidumpCallback callback, + void *callback_context); + +- private: +- // Setup crash handler. +- void SetupHandler(); +- // Setup signal handler for a signal. +- void SetupHandler(int signo); +- // Teardown the handler for a signal. +- void TeardownHandler(int signo); +- // Teardown all handlers. +- void TeardownAllHandler(); +- +- // Signal handler. +- static void HandleException(int signo); +- +- // If called from a signal handler, sighandler_ebp is the ebp of +- // that signal handler's frame, and sig_ctx is an out parameter +- // that will be set to point at the sigcontext that was placed +- // on the stack by the kernel. You can pass zero and NULL +- // for the second and third parameters if you are not calling +- // this from a signal handler. +- bool InternalWriteMinidump(int signo, uintptr_t sighandler_ebp, +- struct sigcontext **sig_ctx); +- +- // Generates a new ID and stores it in next_minidump_id, and stores the +- // path of the next minidump to be written in next_minidump_path_. +- void UpdateNextID(); ++ // This structure is passed to minidump_writer.h:WriteMinidump via an opaque ++ // blob. It shouldn't be needed in any user code. ++ struct CrashContext { ++ siginfo_t siginfo; ++ pid_t tid; // the crashing thread. ++ struct ucontext context; ++ struct _libc_fpstate float_state; ++ }; + + private: +- FilterCallback filter_; +- MinidumpCallback callback_; +- void *callback_context_; ++ bool InstallHandlers(); ++ void UninstallHandlers(); ++ void PreresolveSymbols(); ++ bool GenerateDump(CrashContext *context); + +- // The directory in which a minidump will be written, set by the dump_path +- // argument to the constructor, or set_dump_path. +- string dump_path_; ++ void UpdateNextID(); ++ static void SignalHandler(int sig, siginfo_t* info, void* uc); ++ bool HandleSignal(int sig, siginfo_t* info, void* uc); ++ static int ThreadEntry(void* arg); ++ bool DoDump(pid_t crashing_process, const void* context, ++ size_t context_size); + +- // The basename of the next minidump to be written, without the extension +- string next_minidump_id_; ++ const FilterCallback filter_; ++ const MinidumpCallback callback_; ++ void* const callback_context_; + +- // The full pathname of the next minidump to be written, including the file +- // extension +- string next_minidump_path_; ++ std::string dump_path_; ++ std::string next_minidump_path_; ++ std::string next_minidump_id_; + + // Pointers to C-string representations of the above. These are set + // when the above are set so we can avoid calling c_str during + // an exception. +- const char *dump_path_c_; +- const char *next_minidump_id_c_; +- const char *next_minidump_path_c_; ++ const char* dump_path_c_; ++ const char* next_minidump_path_c_; ++ const char* next_minidump_id_c_; + +- // True if the ExceptionHandler installed an unhandled exception filter +- // when created (with an install_handler parameter set to true). +- bool installed_handler_; +- +- // Keep the previous handlers for the signal. +- typedef void (*sighandler_t)(int); +- std::map old_handlers_; ++ const bool handler_installed_; ++ void* signal_stack; // the handler stack. ++ HandlerCallback crash_handler_; + + // The global exception handler stack. This is need becuase there may exist + // multiple ExceptionHandler instances in a process. Each will have itself + // registered in this stack. +- static std::vector *handler_stack_; ++ static std::vector *handler_stack_; + // The index of the handler that should handle the next exception. +- static int handler_stack_index_; ++ static unsigned handler_stack_index_; + static pthread_mutex_t handler_stack_mutex_; + +- // The minidump generator. +- MinidumpGenerator minidump_generator_; +- +- // disallow copy ctor and operator= +- explicit ExceptionHandler(const ExceptionHandler &); +- void operator=(const ExceptionHandler &); ++ // A vector of the old signal handlers. The void* is a pointer to a newly ++ // allocated sigaction structure to avoid pulling in too many includes. ++ std::vector > old_handlers_; + }; + + } // namespace google_breakpad + +-#endif // CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H__ ++#endif // CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H_ +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler_test.cc b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler_test.cc +deleted file mode 100644 +--- a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler_test.cc ++++ /dev/null +@@ -1,124 +0,0 @@ +-// Copyright (c) 2006, Google Inc. +-// All rights reserved. +-// +-// Author: Li Liu +-// +-// 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 +-#include +- +-#include +-#include +-#include +-#include +- +-#include "client/linux/handler/exception_handler.h" +-#include "client/linux/handler/linux_thread.h" +- +-using namespace google_breakpad; +- +-// Thread use this to see if it should stop working. +-static bool should_exit = false; +- +-static int foo2(int arg) { +- // Stack variable, used for debugging stack dumps. +- /*DDDebug*/printf("%s:%d\n", __FUNCTION__, __LINE__); +- int c = 0xcccccccc; +- fprintf(stderr, "Thread trying to crash: %x\n", getpid()); +- c = *reinterpret_cast(0x5); +- return c; +-} +- +-static int foo(int arg) { +- // Stack variable, used for debugging stack dumps. +- int b = 0xbbbbbbbb; +- b = foo2(b); +- return b; +-} +- +-static void *thread_crash(void *) { +- // Stack variable, used for debugging stack dumps. +- int a = 0xaaaaaaaa; +- sleep(1); +- a = foo(a); +- printf("%x\n", a); +- return NULL; +-} +- +-static void *thread_main(void *) { +- while (!should_exit) +- sleep(1); +- return NULL; +-} +- +-static void CreateCrashThread() { +- pthread_t h; +- pthread_create(&h, NULL, thread_crash, NULL); +- pthread_detach(h); +-} +- +-// Create working threads. +-static void CreateThread(int num) { +- pthread_t h; +- for (int i = 0; i < num; ++i) { +- pthread_create(&h, NULL, thread_main, NULL); +- pthread_detach(h); +- } +-} +- +-// Callback when minidump written. +-static bool MinidumpCallback(const char *dump_path, +- const char *minidump_id, +- void *context, +- bool succeeded) { +- int index = reinterpret_cast(context); +- printf("%d %s: %s is dumped\n", index, __FUNCTION__, minidump_id); +- if (index == 0) { +- should_exit = true; +- return true; +- } +- // Don't process it. +- return false; +-} +- +-int main(int argc, char *argv[]) { +- int handler_index = 0; +- ExceptionHandler handler_ignore(".", NULL, MinidumpCallback, +- (void*)handler_index, true); +- ++handler_index; +- ExceptionHandler handler_process(".", NULL, MinidumpCallback, +- (void*)handler_index, true); +- CreateCrashThread(); +- CreateThread(10); +- +- while (true) +- sleep(1); +- should_exit = true; +- +- return 0; +-} +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler_unittest.cc b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler_unittest.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/exception_handler_unittest.cc +@@ -0,0 +1,256 @@ ++// Copyright (c) 2009, 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 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "client/linux/handler//exception_handler.h" ++#include "client/linux/minidump_writer/minidump_writer.h" ++#include "common/linux/linux_libc_support.h" ++#include "common/linux/linux_syscall_support.h" ++#include "breakpad_googletest_includes.h" ++ ++// This provides a wrapper around system calls which may be ++// interrupted by a signal and return EINTR. See man 7 signal. ++#define HANDLE_EINTR(x) ({ \ ++ typeof(x) __eintr_result__; \ ++ do { \ ++ __eintr_result__ = x; \ ++ } while (__eintr_result__ == -1 && errno == EINTR); \ ++ __eintr_result__;\ ++}) ++ ++using namespace google_breakpad; ++ ++static void sigchld_handler(int signo) { } ++ ++class ExceptionHandlerTest : public ::testing::Test { ++ protected: ++ void SetUp() { ++ // We need to be able to wait for children, so SIGCHLD cannot be SIG_IGN. ++ struct sigaction sa; ++ memset(&sa, 0, sizeof(sa)); ++ sa.sa_handler = sigchld_handler; ++ ASSERT_NE(sigaction(SIGCHLD, &sa, &old_action), -1); ++ } ++ ++ void TearDown() { ++ sigaction(SIGCHLD, &old_action, NULL); ++ } ++ ++ struct sigaction old_action; ++}; ++ ++TEST(ExceptionHandlerTest, Simple) { ++ ExceptionHandler handler("/tmp", NULL, NULL, NULL, true); ++} ++ ++static bool DoneCallback(const char* dump_path, ++ const char* minidump_id, ++ void* context, ++ bool succeeded) { ++ if (!succeeded) ++ return succeeded; ++ ++ int fd = (intptr_t) context; ++ uint32_t len = my_strlen(minidump_id); ++ HANDLE_EINTR(sys_write(fd, &len, sizeof(len))); ++ HANDLE_EINTR(sys_write(fd, minidump_id, len)); ++ sys_close(fd); ++ ++ return true; ++} ++ ++TEST(ExceptionHandlerTest, ChildCrash) { ++ int fds[2]; ++ ASSERT_NE(pipe(fds), -1); ++ ++ const pid_t child = fork(); ++ if (child == 0) { ++ close(fds[0]); ++ ExceptionHandler handler("/tmp", NULL, DoneCallback, (void*) fds[1], ++ true); ++ *reinterpret_cast(NULL) = 0; ++ } ++ close(fds[1]); ++ ++ int status; ++ ASSERT_NE(HANDLE_EINTR(waitpid(child, &status, 0)), -1); ++ ASSERT_TRUE(WIFSIGNALED(status)); ++ ASSERT_EQ(WTERMSIG(status), SIGSEGV); ++ ++ struct pollfd pfd; ++ memset(&pfd, 0, sizeof(pfd)); ++ pfd.fd = fds[0]; ++ pfd.events = POLLIN | POLLERR; ++ ++ const int r = HANDLE_EINTR(poll(&pfd, 1, 0)); ++ ASSERT_EQ(r, 1); ++ ASSERT_TRUE(pfd.revents & POLLIN); ++ ++ uint32_t len; ++ ASSERT_EQ(read(fds[0], &len, sizeof(len)), sizeof(len)); ++ ASSERT_LT(len, 2048); ++ char* filename = reinterpret_cast(malloc(len + 1)); ++ ASSERT_EQ(read(fds[0], filename, len), len); ++ filename[len] = 0; ++ close(fds[0]); ++ ++ const std::string minidump_filename = std::string("/tmp/") + filename + ++ ".dmp"; ++ ++ struct stat st; ++ ASSERT_EQ(stat(minidump_filename.c_str(), &st), 0); ++ ASSERT_GT(st.st_size, 0u); ++ unlink(minidump_filename.c_str()); ++} ++ ++static const unsigned kControlMsgSize = ++ CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(struct ucred)); ++ ++static bool ++CrashHandler(const void* crash_context, size_t crash_context_size, ++ void* context) { ++ const int fd = (intptr_t) context; ++ int fds[2]; ++ pipe(fds); ++ ++ struct kernel_msghdr msg = {0}; ++ struct kernel_iovec iov; ++ iov.iov_base = const_cast(crash_context); ++ iov.iov_len = crash_context_size; ++ ++ msg.msg_iov = &iov; ++ msg.msg_iovlen = 1; ++ char cmsg[kControlMsgSize]; ++ memset(cmsg, 0, kControlMsgSize); ++ msg.msg_control = cmsg; ++ msg.msg_controllen = sizeof(cmsg); ++ ++ struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); ++ hdr->cmsg_level = SOL_SOCKET; ++ hdr->cmsg_type = SCM_RIGHTS; ++ hdr->cmsg_len = CMSG_LEN(sizeof(int)); ++ *((int*) CMSG_DATA(hdr)) = fds[1]; ++ hdr = CMSG_NXTHDR((struct msghdr*) &msg, hdr); ++ hdr->cmsg_level = SOL_SOCKET; ++ hdr->cmsg_type = SCM_CREDENTIALS; ++ hdr->cmsg_len = CMSG_LEN(sizeof(struct ucred)); ++ struct ucred *cred = reinterpret_cast(CMSG_DATA(hdr)); ++ cred->uid = getuid(); ++ cred->gid = getgid(); ++ cred->pid = getpid(); ++ ++ HANDLE_EINTR(sys_sendmsg(fd, &msg, 0)); ++ sys_close(fds[1]); ++ ++ char b; ++ HANDLE_EINTR(sys_read(fds[0], &b, 1)); ++ ++ return true; ++} ++ ++TEST(ExceptionHandlerTest, ExternalDumper) { ++ int fds[2]; ++ ASSERT_NE(socketpair(AF_UNIX, SOCK_DGRAM, 0, fds), -1); ++ static const int on = 1; ++ setsockopt(fds[0], SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); ++ setsockopt(fds[1], SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); ++ ++ const pid_t child = fork(); ++ if (child == 0) { ++ close(fds[0]); ++ ExceptionHandler handler("/tmp", NULL, NULL, (void*) fds[1], true); ++ handler.set_crash_handler(CrashHandler); ++ *reinterpret_cast(NULL) = 0; ++ } ++ ++ close(fds[1]); ++ struct msghdr msg = {0}; ++ struct iovec iov; ++ static const unsigned kCrashContextSize = ++ sizeof(ExceptionHandler::CrashContext); ++ char context[kCrashContextSize]; ++ char control[kControlMsgSize]; ++ iov.iov_base = context; ++ iov.iov_len = kCrashContextSize; ++ msg.msg_iov = &iov; ++ msg.msg_iovlen = 1; ++ msg.msg_control = control; ++ msg.msg_controllen = kControlMsgSize; ++ ++ const ssize_t n = HANDLE_EINTR(recvmsg(fds[0], &msg, 0)); ++ ASSERT_EQ(n, kCrashContextSize); ++ ASSERT_EQ(msg.msg_controllen, kControlMsgSize); ++ ASSERT_EQ(msg.msg_flags, 0); ++ ++ pid_t crashing_pid = -1; ++ int signal_fd = -1; ++ for (struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); hdr; ++ hdr = CMSG_NXTHDR(&msg, hdr)) { ++ if (hdr->cmsg_level != SOL_SOCKET) ++ continue; ++ if (hdr->cmsg_type == SCM_RIGHTS) { ++ const unsigned len = hdr->cmsg_len - ++ (((uint8_t*)CMSG_DATA(hdr)) - (uint8_t*)hdr); ++ ASSERT_EQ(len, sizeof(int)); ++ signal_fd = *((int *) CMSG_DATA(hdr)); ++ } else if (hdr->cmsg_type == SCM_CREDENTIALS) { ++ const struct ucred *cred = ++ reinterpret_cast(CMSG_DATA(hdr)); ++ crashing_pid = cred->pid; ++ } ++ } ++ ++ ASSERT_NE(crashing_pid, -1); ++ ASSERT_NE(signal_fd, -1); ++ ++ char templ[] = "/tmp/exception-handler-unittest-XXXXXX"; ++ mktemp(templ); ++ ASSERT_TRUE(WriteMinidump(templ, crashing_pid, context, ++ kCrashContextSize)); ++ static const char b = 0; ++ HANDLE_EINTR(write(signal_fd, &b, 1)); ++ ++ int status; ++ ASSERT_NE(HANDLE_EINTR(waitpid(child, &status, 0)), -1); ++ ASSERT_TRUE(WIFSIGNALED(status)); ++ ASSERT_EQ(WTERMSIG(status), SIGSEGV); ++ ++ struct stat st; ++ ASSERT_EQ(stat(templ, &st), 0); ++ ASSERT_GT(st.st_size, 0u); ++ unlink(templ); ++} +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/linux_thread.cc b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/linux_thread.cc +deleted file mode 100644 +--- a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/linux_thread.cc ++++ /dev/null +@@ -1,411 +0,0 @@ +-// Copyright (c) 2006, Google Inc. +-// All rights reserved. +-// +-// Author: Li Liu +-// +-// 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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +- +-#include "client/linux/handler/linux_thread.h" +- +-using namespace google_breakpad; +- +-// This unamed namespace contains helper function. +-namespace { +- +-// Context information for the callbacks when validating address by listing +-// modules. +-struct AddressValidatingContext { +- uintptr_t address; +- bool is_mapped; +- +- AddressValidatingContext() : address(0UL), is_mapped(false) { +- } +-}; +- +-// Convert from string to int. +-bool LocalAtoi(char *s, int *r) { +- assert(s != NULL); +- assert(r != NULL); +- char *endptr = NULL; +- int ret = strtol(s, &endptr, 10); +- if (endptr == s) +- return false; +- *r = ret; +- return true; +-} +- +-// Fill the proc path of a thread given its id. +-void FillProcPath(int pid, char *path, int path_size) { +- char pid_str[32]; +- snprintf(pid_str, sizeof(pid_str), "%d", pid); +- snprintf(path, path_size, "/proc/%s/", pid_str); +-} +- +-// Read thread info from /proc/$pid/status. +-bool ReadThreadInfo(int pid, ThreadInfo *info) { +- assert(info != NULL); +- char status_path[80]; +- // Max size we want to read from status file. +- static const int kStatusMaxSize = 1024; +- char status_content[kStatusMaxSize]; +- +- FillProcPath(pid, status_path, sizeof(status_path)); +- strcat(status_path, "status"); +- int fd = open(status_path, O_RDONLY, 0); +- if (fd < 0) +- return false; +- +- int num_read = read(fd, status_content, kStatusMaxSize - 1); +- if (num_read < 0) { +- close(fd); +- return false; +- } +- close(fd); +- status_content[num_read] = '\0'; +- +- char *tgid_start = strstr(status_content, "Tgid:"); +- if (tgid_start) +- sscanf(tgid_start, "Tgid:\t%d\n", &(info->tgid)); +- else +- // tgid not supported by kernel?? +- info->tgid = 0; +- +- tgid_start = strstr(status_content, "Pid:"); +- if (tgid_start) { +- sscanf(tgid_start, "Pid:\t%d\n" "PPid:\t%d\n", &(info->pid), +- &(info->ppid)); +- return true; +- } +- return false; +-} +- +-// Callback invoked for each mapped module. +-// It use the module's adderss range to validate the address. +-bool IsAddressInModuleCallback(const ModuleInfo &module_info, +- void *context) { +- AddressValidatingContext *addr = +- reinterpret_cast(context); +- addr->is_mapped = ((addr->address >= module_info.start_addr) && +- (addr->address <= module_info.start_addr + +- module_info.size)); +- return !addr->is_mapped; +-} +- +-#if defined(__i386__) && !defined(NO_FRAME_POINTER) +-void *GetNextFrame(void **last_ebp) { +- void *sp = *last_ebp; +- if ((unsigned long)sp == (unsigned long)last_ebp) +- return NULL; +- if ((unsigned long)sp & (sizeof(void *) - 1)) +- return NULL; +- if ((unsigned long)sp - (unsigned long)last_ebp > 100000) +- return NULL; +- return sp; +-} +-#else +-void *GetNextFrame(void **last_ebp) { +- return reinterpret_cast(last_ebp); +-} +-#endif +- +-// Suspend a thread by attaching to it. +-bool SuspendThread(int pid, void *context) { +- // This may fail if the thread has just died or debugged. +- errno = 0; +- if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) != 0 && +- errno != 0) { +- return false; +- } +- while (waitpid(pid, NULL, __WALL) < 0) { +- if (errno != EINTR) { +- ptrace(PTRACE_DETACH, pid, NULL, NULL); +- return false; +- } +- } +- return true; +-} +- +-// Resume a thread by detaching from it. +-bool ResumeThread(int pid, void *context) { +- return ptrace(PTRACE_DETACH, pid, NULL, NULL) >= 0; +-} +- +-// Callback to get the thread information. +-// Will be called for each thread found. +-bool ThreadInfoCallback(int pid, void *context) { +- CallbackParam *thread_callback = +- reinterpret_cast *>(context); +- ThreadInfo thread_info; +- if (ReadThreadInfo(pid, &thread_info) && thread_callback) { +- // Invoke callback from caller. +- return (thread_callback->call_back)(thread_info, thread_callback->context); +- } +- return false; +-} +- +-} // namespace +- +-namespace google_breakpad { +- +-LinuxThread::LinuxThread(int pid) : pid_(pid) , threads_suspened_(false) { +-} +- +-LinuxThread::~LinuxThread() { +- if (threads_suspened_) +- ResumeAllThreads(); +-} +- +-int LinuxThread::SuspendAllThreads() { +- CallbackParam callback_param(SuspendThread, NULL); +- int thread_count = 0; +- if ((thread_count = IterateProcSelfTask(pid_, &callback_param)) > 0) +- threads_suspened_ = true; +- return thread_count; +-} +- +-void LinuxThread::ResumeAllThreads() const { +- CallbackParam callback_param(ResumeThread, NULL); +- IterateProcSelfTask(pid_, &callback_param); +-} +- +-int LinuxThread::GetThreadCount() const { +- return IterateProcSelfTask(pid_, NULL); +-} +- +-int LinuxThread::ListThreads( +- CallbackParam *thread_callback_param) const { +- CallbackParam callback_param(ThreadInfoCallback, +- thread_callback_param); +- return IterateProcSelfTask(pid_, &callback_param); +-} +- +-bool LinuxThread::GetRegisters(int pid, user_regs_struct *regs) const { +- assert(regs); +- return (regs != NULL && +- (ptrace(PTRACE_GETREGS, pid, NULL, regs) == 0) && +- errno == 0); +-} +- +-// Get the floating-point registers of a thread. +-// The caller must get the thread pid by ListThreads. +-bool LinuxThread::GetFPRegisters(int pid, user_fpregs_struct *regs) const { +- assert(regs); +- return (regs != NULL && +- (ptrace(PTRACE_GETREGS, pid, NULL, regs) ==0) && +- errno == 0); +-} +- +-bool LinuxThread::GetFPXRegisters(int pid, user_fpxregs_struct *regs) const { +- assert(regs); +- return (regs != NULL && +- (ptrace(PTRACE_GETFPREGS, pid, NULL, regs) != 0) && +- errno == 0); +-} +- +-bool LinuxThread::GetDebugRegisters(int pid, DebugRegs *regs) const { +- assert(regs); +- +-#define GET_DR(name, num)\ +- name->dr##num = ptrace(PTRACE_PEEKUSER, pid,\ +- offsetof(struct user, u_debugreg[num]), NULL) +- GET_DR(regs, 0); +- GET_DR(regs, 1); +- GET_DR(regs, 2); +- GET_DR(regs, 3); +- GET_DR(regs, 4); +- GET_DR(regs, 5); +- GET_DR(regs, 6); +- GET_DR(regs, 7); +- return true; +-} +- +-int LinuxThread::GetThreadStackDump(uintptr_t current_ebp, +- uintptr_t current_esp, +- void *buf, +- int buf_size) const { +- assert(buf); +- assert(buf_size > 0); +- +- uintptr_t stack_bottom = GetThreadStackBottom(current_ebp); +- int size = stack_bottom - current_esp; +- size = buf_size > size ? size : buf_size; +- if (size > 0) +- memcpy(buf, reinterpret_cast(current_esp), size); +- return size; +-} +- +-// Get the stack bottom of a thread by stack walking. It works +-// unless the stack has been corrupted or the frame pointer has been omited. +-// This is just a temporary solution before we get better ideas about how +-// this can be done. +-// +-// We will check each frame address by checking into module maps. +-// TODO(liuli): Improve it. +-uintptr_t LinuxThread::GetThreadStackBottom(uintptr_t current_ebp) const { +- void **sp = reinterpret_cast(current_ebp); +- void **previous_sp = sp; +- while (sp && IsAddressMapped((uintptr_t)sp)) { +- previous_sp = sp; +- sp = reinterpret_cast(GetNextFrame(sp)); +- } +- return (uintptr_t)previous_sp; +-} +- +-int LinuxThread::GetModuleCount() const { +- return ListModules(NULL); +-} +- +-int LinuxThread::ListModules( +- CallbackParam *callback_param) const { +- char line[512]; +- const char *maps_path = "/proc/self/maps"; +- +- int module_count = 0; +- FILE *fp = fopen(maps_path, "r"); +- if (fp == NULL) +- return -1; +- +- uintptr_t start_addr; +- uintptr_t end_addr; +- while (fgets(line, sizeof(line), fp) != NULL) { +- if (sscanf(line, "%x-%x", &start_addr, &end_addr) == 2) { +- ModuleInfo module; +- memset(&module, 0, sizeof(module)); +- module.start_addr = start_addr; +- module.size = end_addr - start_addr; +- char *name = NULL; +- assert(module.size > 0); +- // Only copy name if the name is a valid path name. +- if ((name = strchr(line, '/')) != NULL) { +- // Get rid of the last '\n' in line +- char *last_return = strchr(line, '\n'); +- if (last_return != NULL) +- *last_return = '\0'; +- // Keep a space for the ending 0. +- strncpy(module.name, name, sizeof(module.name) - 1); +- ++module_count; +- } +- if (callback_param && +- !(callback_param->call_back(module, callback_param->context))) +- break; +- } +- } +- fclose(fp); +- return module_count; +-} +- +-// Parse /proc/$pid/tasks to list all the threads of the process identified by +-// pid. +-int LinuxThread::IterateProcSelfTask(int pid, +- CallbackParam *callback_param) const { +- char task_path[80]; +- FillProcPath(pid, task_path, sizeof(task_path)); +- strcat(task_path, "task"); +- +- DIR *dir = opendir(task_path); +- if (dir == NULL) +- return -1; +- +- int pid_number = 0; +- // Record the last pid we've found. This is used for duplicated thread +- // removal. Duplicated thread information can be found in /proc/$pid/tasks. +- int last_pid = -1; +- struct dirent *entry = NULL; +- while ((entry = readdir(dir)) != NULL) { +- if (strcmp(entry->d_name, ".") && +- strcmp(entry->d_name, "..")) { +- int tpid = 0; +- if (LocalAtoi(entry->d_name, &tpid) && +- last_pid != tpid) { +- last_pid = tpid; +- ++pid_number; +- // Invoke the callback. +- if (callback_param && +- !(callback_param->call_back)(tpid, callback_param->context)) +- break; +- } +- } +- } +- closedir(dir); +- return pid_number; +-} +- +-// Check if the address is a valid virtual address. +-// If the address is in any of the mapped modules, we take it as valid. +-// Otherwise it is invalid. +-bool LinuxThread::IsAddressMapped(uintptr_t address) const { +- AddressValidatingContext addr; +- addr.address = address; +- CallbackParam callback_param(IsAddressInModuleCallback, +- &addr); +- ListModules(&callback_param); +- return addr.is_mapped; +-} +- +-bool LinuxThread::FindSigContext(uintptr_t sighandler_ebp, +- struct sigcontext **sig_ctx) { +- uintptr_t previous_ebp; +- const int MAX_STACK_DEPTH = 10; +- int depth_counter = 0; +- +- do { +- // We're looking for a |struct sigcontext| as the second parameter +- // to a signal handler function call. Luckily, the sigcontext +- // has an ebp member which should match the ebp pointed to +- // by the ebp of the signal handler frame. +- previous_ebp = reinterpret_cast(GetNextFrame( +- reinterpret_cast(sighandler_ebp))); +- // The stack looks like this: +- // | previous ebp | previous eip | first param | second param |, +- // so we need to offset by 3 to get to the second parameter. +- *sig_ctx = reinterpret_cast(sighandler_ebp + +- 3 * sizeof(uintptr_t)); +- sighandler_ebp = previous_ebp; +- depth_counter++; +- } while(previous_ebp != (*sig_ctx)->ebp && sighandler_ebp != 0 && +- IsAddressMapped(sighandler_ebp) && depth_counter < MAX_STACK_DEPTH); +- +- return previous_ebp == (*sig_ctx)->ebp && previous_ebp != 0; +-} +- +-} // namespace google_breakpad +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/linux_thread.h b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/linux_thread.h +deleted file mode 100644 +--- a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/linux_thread.h ++++ /dev/null +@@ -1,204 +0,0 @@ +-// Copyright (c) 2006, Google Inc. +-// All rights reserved. +-// +-// Author: Li Liu +-// +-// 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 CLIENT_LINUX_HANDLER_LINUX_THREAD_H__ +-#define CLIENT_LINUX_HANDLER_LINUX_THREAD_H__ +- +-#include +-#include +- +-namespace google_breakpad { +- +-// Max module path name length. +-#define kMaxModuleNameLength 256 +- +-// Holding information about a thread in the process. +-struct ThreadInfo { +- // Id of the thread group. +- int tgid; +- // Id of the thread. +- int pid; +- // Id of the parent process. +- int ppid; +-}; +- +-// Holding infomaton about a module in the process. +-struct ModuleInfo { +- char name[kMaxModuleNameLength]; +- uintptr_t start_addr; +- int size; +-}; +- +-// Holding debug registers. +-struct DebugRegs { +- int dr0; +- int dr1; +- int dr2; +- int dr3; +- int dr4; +- int dr5; +- int dr6; +- int dr7; +-}; +- +-// A callback to run when got a thread in the process. +-// Return true will go on to the next thread while return false will stop the +-// iteration. +-typedef bool (*ThreadCallback)(const ThreadInfo &thread_info, void *context); +- +-// A callback to run when a new module is found in the process. +-// Return true will go on to the next module while return false will stop the +-// iteration. +-typedef bool (*ModuleCallback)(const ModuleInfo &module_info, void *context); +- +-// Holding the callback information. +-template +-struct CallbackParam { +- // Callback function address. +- CallbackFunc call_back; +- // Callback context; +- void *context; +- +- CallbackParam() : call_back(NULL), context(NULL) { +- } +- +- CallbackParam(CallbackFunc func, void *func_context) : +- call_back(func), context(func_context) { +- } +-}; +- +-/////////////////////////////////////////////////////////////////////////////// +- +-// +-// LinuxThread +-// +-// Provides handy support for operation on linux threads. +-// It uses ptrace to get thread registers. Since ptrace only works in a +-// different process other than the one being ptraced, user of this class +-// should create another process before using the class. +-// +-// The process should be created in the following way: +-// int cloned_pid = clone(ProcessEntryFunction, stack_address, +-// CLONE_VM | CLONE_FILES | CLONE_FS | CLONE_UNTRACED, +-// (void*)&arguments); +-// waitpid(cloned_pid, NULL, __WALL); +-// +-// If CLONE_VM is not used, GetThreadStackBottom, GetThreadStackDump +-// will not work since it just use memcpy to get the stack dump. +-// +-class LinuxThread { +- public: +- // Create a LinuxThread instance to list all the threads in a process. +- explicit LinuxThread(int pid); +- ~LinuxThread(); +- +- // Stop all the threads in the process. +- // Return the number of stopped threads in the process. +- // Return -1 means failed to stop threads. +- int SuspendAllThreads(); +- +- // Resume all the suspended threads. +- void ResumeAllThreads() const; +- +- // Get the count of threads in the process. +- // Return -1 means error. +- int GetThreadCount() const; +- +- // List the threads of process. +- // Whenever there is a thread found, the callback will be invoked to process +- // the information. +- // Return number of threads listed. +- int ListThreads(CallbackParam *thread_callback_param) const; +- +- // Get the general purpose registers of a thread. +- // The caller must get the thread pid by ListThreads. +- bool GetRegisters(int pid, user_regs_struct *regs) const; +- +- // Get the floating-point registers of a thread. +- // The caller must get the thread pid by ListThreads. +- bool GetFPRegisters(int pid, user_fpregs_struct *regs) const; +- +- // Get all the extended floating-point registers. May not work on all +- // machines. +- // The caller must get the thread pid by ListThreads. +- bool GetFPXRegisters(int pid, user_fpxregs_struct *regs) const; +- +- // Get the debug registers. +- // The caller must get the thread pid by ListThreads. +- bool GetDebugRegisters(int pid, DebugRegs *regs) const; +- +- // Get the stack memory dump. +- int GetThreadStackDump(uintptr_t current_ebp, +- uintptr_t current_esp, +- void *buf, +- int buf_size) const; +- +- // Get the module count of the current process. +- int GetModuleCount() const; +- +- // Get the mapped modules in the address space. +- // Whenever a module is found, the callback will be invoked to process the +- // information. +- // Return how may modules are found. +- int ListModules(CallbackParam *callback_param) const; +- +- // Get the bottom of the stack from ebp. +- uintptr_t GetThreadStackBottom(uintptr_t current_ebp) const; +- +- // Finds a sigcontext on the stack given the ebp of our signal handler. +- bool FindSigContext(uintptr_t sighandler_ebp, struct sigcontext **sig_ctx); +- +- private: +- // This callback will run when a new thread has been found. +- typedef bool (*PidCallback)(int pid, void *context); +- +- // Read thread information from /proc/$pid/task. +- // Whenever a thread has been found, and callback will be invoked with +- // the pid of the thread. +- // Return number of threads found. +- // Return -1 means the directory doesn't exist. +- int IterateProcSelfTask(int pid, +- CallbackParam *callback_param) const; +- +- // Check if the address is a valid virtual address. +- bool IsAddressMapped(uintptr_t address) const; +- +- private: +- // The pid of the process we are listing threads. +- int pid_; +- +- // Mark if we have suspended the threads. +- bool threads_suspened_; +-}; +- +-} // namespace google_breakpad +- +-#endif // CLIENT_LINUX_HANDLER_LINUX_THREAD_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/linux_thread_test.cc b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/linux_thread_test.cc +deleted file mode 100644 +--- a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/linux_thread_test.cc ++++ /dev/null +@@ -1,224 +0,0 @@ +-// Copyright (c) 2006, Google Inc. +-// All rights reserved. +-// +-// Author: Li Liu +-// +-// 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 +-#include +-#include +-#include +- +-#include +-#include +-#include +- +-#include "client/linux/handler/linux_thread.h" +- +-using namespace google_breakpad; +- +-// Thread use this to see if it should stop working. +-static bool should_exit = false; +- +-static void foo2(int *a) { +- // Stack variable, used for debugging stack dumps. +- int c = 0xcccccccc; +- c = c; +- while (!should_exit) +- sleep(1); +-} +- +-static void foo() { +- // Stack variable, used for debugging stack dumps. +- int a = 0xaaaaaaaa; +- foo2(&a); +-} +- +-static void *thread_main(void *) { +- // Stack variable, used for debugging stack dumps. +- int b = 0xbbbbbbbb; +- b = b; +- while (!should_exit) { +- foo(); +- } +- return NULL; +-} +- +-static void CreateThreads(int num) { +- pthread_t handle; +- for (int i = 0; i < num; i++) { +- if (0 != pthread_create(&handle, NULL, thread_main, NULL)) +- fprintf(stderr, "Failed to create thread.\n"); +- else +- pthread_detach(handle); +- } +-} +- +-static bool ProcessOneModule(const struct ModuleInfo &module_info, +- void *context) { +- printf("0x%x[%8d] %s\n", module_info.start_addr, module_info.size, +- module_info.name); +- return true; +-} +- +-static bool ProcessOneThread(const struct ThreadInfo &thread_info, +- void *context) { +- printf("\n\nPID: %d, TGID: %d, PPID: %d\n", +- thread_info.pid, +- thread_info.tgid, +- thread_info.ppid); +- +- struct user_regs_struct regs; +- struct user_fpregs_struct fp_regs; +- struct user_fpxregs_struct fpx_regs; +- struct DebugRegs dbg_regs; +- +- LinuxThread *threads = reinterpret_cast(context); +- memset(®s, 0, sizeof(regs)); +- if (threads->GetRegisters(thread_info.pid, ®s)) { +- printf(" gs = 0x%lx\n", regs.xgs); +- printf(" fs = 0x%lx\n", regs.xfs); +- printf(" es = 0x%lx\n", regs.xes); +- printf(" ds = 0x%lx\n", regs.xds); +- printf(" edi = 0x%lx\n", regs.edi); +- printf(" esi = 0x%lx\n", regs.esi); +- printf(" ebx = 0x%lx\n", regs.ebx); +- printf(" edx = 0x%lx\n", regs.edx); +- printf(" ecx = 0x%lx\n", regs.ecx); +- printf(" eax = 0x%lx\n", regs.eax); +- printf(" ebp = 0x%lx\n", regs.ebp); +- printf(" eip = 0x%lx\n", regs.eip); +- printf(" cs = 0x%lx\n", regs.xcs); +- printf(" eflags = 0x%lx\n", regs.eflags); +- printf(" esp = 0x%lx\n", regs.esp); +- printf(" ss = 0x%lx\n", regs.xss); +- } else { +- fprintf(stderr, "ERROR: Failed to get general purpose registers\n"); +- } +- memset(&fp_regs, 0, sizeof(fp_regs)); +- if (threads->GetFPRegisters(thread_info.pid, &fp_regs)) { +- printf("\n Floating point registers:\n"); +- printf(" fctl = 0x%lx\n", fp_regs.cwd); +- printf(" fstat = 0x%lx\n", fp_regs.swd); +- printf(" ftag = 0x%lx\n", fp_regs.twd); +- printf(" fioff = 0x%lx\n", fp_regs.fip); +- printf(" fiseg = 0x%lx\n", fp_regs.fcs); +- printf(" fooff = 0x%lx\n", fp_regs.foo); +- printf(" foseg = 0x%lx\n", fp_regs.fos); +- int st_space_size = sizeof(fp_regs.st_space) / sizeof(fp_regs.st_space[0]); +- printf(" st_space[%2d] = 0x", st_space_size); +- for (int i = 0; i < st_space_size; ++i) +- printf("%02lx", fp_regs.st_space[i]); +- printf("\n"); +- } else { +- fprintf(stderr, "ERROR: Failed to get floating-point registers\n"); +- } +- memset(&fpx_regs, 0, sizeof(fpx_regs)); +- if (threads->GetFPXRegisters(thread_info.pid, &fpx_regs)) { +- printf("\n Extended floating point registers:\n"); +- printf(" fctl = 0x%x\n", fpx_regs.cwd); +- printf(" fstat = 0x%x\n", fpx_regs.swd); +- printf(" ftag = 0x%x\n", fpx_regs.twd); +- printf(" fioff = 0x%lx\n", fpx_regs.fip); +- printf(" fiseg = 0x%lx\n", fpx_regs.fcs); +- printf(" fooff = 0x%lx\n", fpx_regs.foo); +- printf(" foseg = 0x%lx\n", fpx_regs.fos); +- printf(" fop = 0x%x\n", fpx_regs.fop); +- printf(" mxcsr = 0x%lx\n", fpx_regs.mxcsr); +- int space_size = sizeof(fpx_regs.st_space) / sizeof(fpx_regs.st_space[0]); +- printf(" st_space[%2d] = 0x", space_size); +- for (int i = 0; i < space_size; ++i) +- printf("%02lx", fpx_regs.st_space[i]); +- printf("\n"); +- space_size = sizeof(fpx_regs.xmm_space) / sizeof(fpx_regs.xmm_space[0]); +- printf(" xmm_space[%2d] = 0x", space_size); +- for (int i = 0; i < space_size; ++i) +- printf("%02lx", fpx_regs.xmm_space[i]); +- printf("\n"); +- } +- if (threads->GetDebugRegisters(thread_info.pid, &dbg_regs)) { +- printf("\n Debug registers:\n"); +- printf(" dr0 = 0x%x\n", dbg_regs.dr0); +- printf(" dr1 = 0x%x\n", dbg_regs.dr1); +- printf(" dr2 = 0x%x\n", dbg_regs.dr2); +- printf(" dr3 = 0x%x\n", dbg_regs.dr3); +- printf(" dr4 = 0x%x\n", dbg_regs.dr4); +- printf(" dr5 = 0x%x\n", dbg_regs.dr5); +- printf(" dr6 = 0x%x\n", dbg_regs.dr6); +- printf(" dr7 = 0x%x\n", dbg_regs.dr7); +- printf("\n"); +- } +- if (regs.esp != 0) { +- // Print the stack content. +- int size = 1024 * 2; +- char *buf = new char[size]; +- size = threads->GetThreadStackDump(regs.ebp, +- regs.esp, +- (void*)buf, size); +- printf(" Stack content: = 0x"); +- size /= sizeof(unsigned long); +- unsigned long *p_buf = (unsigned long *)(buf); +- for (int i = 0; i < size; i += 1) +- printf("%.8lx ", p_buf[i]); +- delete []buf; +- printf("\n"); +- } +- return true; +-} +- +-static int PrintAllThreads(void *argument) { +- int pid = (int)argument; +- +- LinuxThread threads(pid); +- int total_thread = threads.SuspendAllThreads(); +- printf("There are %d threads in the process: %d\n", total_thread, pid); +- int total_module = threads.GetModuleCount(); +- printf("There are %d modules in the process: %d\n", total_module, pid); +- CallbackParam module_callback(ProcessOneModule, &threads); +- threads.ListModules(&module_callback); +- CallbackParam thread_callback(ProcessOneThread, &threads); +- threads.ListThreads(&thread_callback); +- return 0; +-} +- +-int main(int argc, char **argv) { +- int pid = getpid(); +- printf("Main thread is %d\n", pid); +- CreateThreads(1); +- // Create stack for the process. +- char *stack = new char[1024 * 100]; +- int cloned_pid = clone(PrintAllThreads, stack + 1024 * 100, +- CLONE_VM | CLONE_FILES | CLONE_FS | CLONE_UNTRACED, +- (void*)getpid()); +- waitpid(cloned_pid, NULL, __WALL); +- should_exit = true; +- printf("Test finished.\n"); +- +- delete []stack; +- return 0; +-} +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/minidump_generator.cc b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/minidump_generator.cc +deleted file mode 100644 +--- a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/minidump_generator.cc ++++ /dev/null +@@ -1,816 +0,0 @@ +-// Copyright (c) 2006, Google Inc. +-// All rights reserved. +-// +-// Author: Li Liu +-// +-// 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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +- +-#include "common/linux/file_id.h" +-#include "client/linux/handler/linux_thread.h" +-#include "client/minidump_file_writer.h" +-#include "client/minidump_file_writer-inl.h" +-#include "google_breakpad/common/minidump_format.h" +-#include "client/linux/handler/minidump_generator.h" +- +-#ifndef CLONE_UNTRACED +-#define CLONE_UNTRACED 0x00800000 +-#endif +- +-// This unnamed namespace contains helper functions. +-namespace { +- +-using namespace google_breakpad; +- +-// Argument for the writer function. +-struct WriterArgument { +- MinidumpFileWriter *minidump_writer; +- +- // Context for the callback. +- void *version_context; +- +- // Pid of the thread who called WriteMinidumpToFile +- int requester_pid; +- +- // The stack bottom of the thread which caused the dump. +- // Mainly used to find the thread id of the crashed thread since signal +- // handler may not be called in the thread who caused it. +- uintptr_t crashed_stack_bottom; +- +- // Pid of the crashing thread. +- int crashed_pid; +- +- // Signal number when crash happed. Can be 0 if this is a requested dump. +- int signo; +- +- // The ebp of the signal handler frame. Can be zero if this +- // is a requested dump. +- uintptr_t sighandler_ebp; +- +- // Signal context when crash happed. Can be NULL if this is a requested dump. +- // This is actually an out parameter, but it will be filled in at the start +- // of the writer thread. +- struct sigcontext *sig_ctx; +- +- // Used to get information about the threads. +- LinuxThread *thread_lister; +-}; +- +-// Holding context information for the callback of finding the crashing thread. +-struct FindCrashThreadContext { +- const LinuxThread *thread_lister; +- uintptr_t crashing_stack_bottom; +- int crashing_thread_pid; +- +- FindCrashThreadContext() : +- thread_lister(NULL), +- crashing_stack_bottom(0UL), +- crashing_thread_pid(-1) { +- } +-}; +- +-// Callback for list threads. +-// It will compare the stack bottom of the provided thread with the stack +-// bottom of the crashed thread, it they are eqaul, this is thread is the one +-// who crashed. +-bool IsThreadCrashedCallback(const ThreadInfo &thread_info, void *context) { +- FindCrashThreadContext *crashing_context = +- static_cast(context); +- const LinuxThread *thread_lister = crashing_context->thread_lister; +- struct user_regs_struct regs; +- if (thread_lister->GetRegisters(thread_info.pid, ®s)) { +- uintptr_t last_ebp = regs.ebp; +- uintptr_t stack_bottom = thread_lister->GetThreadStackBottom(last_ebp); +- if (stack_bottom > last_ebp && +- stack_bottom == crashing_context->crashing_stack_bottom) { +- // Got it. Stop iteration. +- crashing_context->crashing_thread_pid = thread_info.pid; +- return false; +- } +- } +- return true; +-} +- +-// Find the crashing thread id. +-// This is done based on stack bottom comparing. +-int FindCrashingThread(uintptr_t crashing_stack_bottom, +- int requester_pid, +- const LinuxThread *thread_lister) { +- FindCrashThreadContext context; +- context.thread_lister = thread_lister; +- context.crashing_stack_bottom = crashing_stack_bottom; +- CallbackParam callback_param(IsThreadCrashedCallback, +- &context); +- thread_lister->ListThreads(&callback_param); +- return context.crashing_thread_pid; +-} +- +-// Write the thread stack info minidump. +-bool WriteThreadStack(uintptr_t last_ebp, +- uintptr_t last_esp, +- const LinuxThread *thread_lister, +- UntypedMDRVA *memory, +- MDMemoryDescriptor *loc) { +- // Maximum stack size for a thread. +- uintptr_t stack_bottom = thread_lister->GetThreadStackBottom(last_ebp); +- if (stack_bottom > last_esp) { +- int size = stack_bottom - last_esp; +- if (size > 0) { +- if (!memory->Allocate(size)) +- return false; +- memory->Copy(reinterpret_cast(last_esp), size); +- loc->start_of_memory_range = 0 | last_esp; +- loc->memory = memory->location(); +- } +- return true; +- } +- return false; +-} +- +-// Write CPU context based on signal context. +-bool WriteContext(MDRawContextX86 *context, const struct sigcontext *sig_ctx, +- const DebugRegs *debug_regs) { +- assert(sig_ctx != NULL); +- context->context_flags = MD_CONTEXT_X86_FULL; +- context->gs = sig_ctx->gs; +- context->fs = sig_ctx->fs; +- context->es = sig_ctx->es; +- context->ds = sig_ctx->ds; +- context->cs = sig_ctx->cs; +- context->ss = sig_ctx->ss; +- context->edi = sig_ctx->edi; +- context->esi = sig_ctx->esi; +- context->ebp = sig_ctx->ebp; +- context->esp = sig_ctx->esp; +- context->ebx = sig_ctx->ebx; +- context->edx = sig_ctx->edx; +- context->ecx = sig_ctx->ecx; +- context->eax = sig_ctx->eax; +- context->eip = sig_ctx->eip; +- context->eflags = sig_ctx->eflags; +- if (sig_ctx->fpstate != NULL) { +- context->context_flags = MD_CONTEXT_X86_FULL | +- MD_CONTEXT_X86_FLOATING_POINT; +- context->float_save.control_word = sig_ctx->fpstate->cw; +- context->float_save.status_word = sig_ctx->fpstate->sw; +- context->float_save.tag_word = sig_ctx->fpstate->tag; +- context->float_save.error_offset = sig_ctx->fpstate->ipoff; +- context->float_save.error_selector = sig_ctx->fpstate->cssel; +- context->float_save.data_offset = sig_ctx->fpstate->dataoff; +- context->float_save.data_selector = sig_ctx->fpstate->datasel; +- memcpy(context->float_save.register_area, sig_ctx->fpstate->_st, +- sizeof(context->float_save.register_area)); +- } +- +- if (debug_regs != NULL) { +- context->context_flags |= MD_CONTEXT_X86_DEBUG_REGISTERS; +- context->dr0 = debug_regs->dr0; +- context->dr1 = debug_regs->dr1; +- context->dr2 = debug_regs->dr2; +- context->dr3 = debug_regs->dr3; +- context->dr6 = debug_regs->dr6; +- context->dr7 = debug_regs->dr7; +- } +- return true; +-} +- +-// Write CPU context based on provided registers. +-bool WriteContext(MDRawContextX86 *context, +- const struct user_regs_struct *regs, +- const struct user_fpregs_struct *fp_regs, +- const DebugRegs *dbg_regs) { +- if (!context || !regs) +- return false; +- +- context->context_flags = MD_CONTEXT_X86_FULL; +- +- context->cs = regs->xcs; +- context->ds = regs->xds; +- context->es = regs->xes; +- context->fs = regs->xfs; +- context->gs = regs->xgs; +- context->ss = regs->xss; +- context->edi = regs->edi; +- context->esi = regs->esi; +- context->ebx = regs->ebx; +- context->edx = regs->edx; +- context->ecx = regs->ecx; +- context->eax = regs->eax; +- context->ebp = regs->ebp; +- context->eip = regs->eip; +- context->esp = regs->esp; +- context->eflags = regs->eflags; +- +- if (dbg_regs != NULL) { +- context->context_flags |= MD_CONTEXT_X86_DEBUG_REGISTERS; +- context->dr0 = dbg_regs->dr0; +- context->dr1 = dbg_regs->dr1; +- context->dr2 = dbg_regs->dr2; +- context->dr3 = dbg_regs->dr3; +- context->dr6 = dbg_regs->dr6; +- context->dr7 = dbg_regs->dr7; +- } +- +- if (fp_regs != NULL) { +- context->context_flags |= MD_CONTEXT_X86_FLOATING_POINT; +- context->float_save.control_word = fp_regs->cwd; +- context->float_save.status_word = fp_regs->swd; +- context->float_save.tag_word = fp_regs->twd; +- context->float_save.error_offset = fp_regs->fip; +- context->float_save.error_selector = fp_regs->fcs; +- context->float_save.data_offset = fp_regs->foo; +- context->float_save.data_selector = fp_regs->fos; +- context->float_save.data_selector = fp_regs->fos; +- +- memcpy(context->float_save.register_area, fp_regs->st_space, +- sizeof(context->float_save.register_area)); +- } +- return true; +-} +- +-// Write information about a crashed thread. +-// When a thread crash, kernel will write something on the stack for processing +-// signal. This makes the current stack not reliable, and our stack walker +-// won't figure out the whole call stack for this. So we write the stack at the +-// time of the crash into the minidump file, not the current stack. +-bool WriteCrashedThreadStream(MinidumpFileWriter *minidump_writer, +- const WriterArgument *writer_args, +- const ThreadInfo &thread_info, +- MDRawThread *thread) { +- assert(writer_args->sig_ctx != NULL); +- +- thread->thread_id = thread_info.pid; +- +- UntypedMDRVA memory(minidump_writer); +- if (!WriteThreadStack(writer_args->sig_ctx->ebp, +- writer_args->sig_ctx->esp, +- writer_args->thread_lister, +- &memory, +- &thread->stack)) +- return false; +- +- TypedMDRVA context(minidump_writer); +- if (!context.Allocate()) +- return false; +- thread->thread_context = context.location(); +- memset(context.get(), 0, sizeof(MDRawContextX86)); +- return WriteContext(context.get(), writer_args->sig_ctx, NULL); +-} +- +-// Write information about a thread. +-// This function only processes thread running normally at the crash. +-bool WriteThreadStream(MinidumpFileWriter *minidump_writer, +- const LinuxThread *thread_lister, +- const ThreadInfo &thread_info, +- MDRawThread *thread) { +- thread->thread_id = thread_info.pid; +- +- struct user_regs_struct regs; +- memset(®s, 0, sizeof(regs)); +- if (!thread_lister->GetRegisters(thread_info.pid, ®s)) { +- perror(NULL); +- return false; +- } +- +- UntypedMDRVA memory(minidump_writer); +- if (!WriteThreadStack(regs.ebp, +- regs.esp, +- thread_lister, +- &memory, +- &thread->stack)) +- return false; +- +- struct user_fpregs_struct fp_regs; +- DebugRegs dbg_regs; +- memset(&fp_regs, 0, sizeof(fp_regs)); +- // Get all the registers. +- thread_lister->GetFPRegisters(thread_info.pid, &fp_regs); +- thread_lister->GetDebugRegisters(thread_info.pid, &dbg_regs); +- +- // Write context +- TypedMDRVA context(minidump_writer); +- if (!context.Allocate()) +- return false; +- thread->thread_context = context.location(); +- memset(context.get(), 0, sizeof(MDRawContextX86)); +- return WriteContext(context.get(), ®s, &fp_regs, &dbg_regs); +-} +- +-bool WriteCPUInformation(MDRawSystemInfo *sys_info) { +- const char *proc_cpu_path = "/proc/cpuinfo"; +- char line[128]; +- char vendor_id[13]; +- const char vendor_id_name[] = "vendor_id"; +- const size_t vendor_id_name_length = sizeof(vendor_id_name) - 1; +- +- struct CpuInfoEntry { +- const char *info_name; +- int value; +- } cpu_info_table[] = { +- { "processor", -1 }, +- { "model", 0 }, +- { "stepping", 0 }, +- { "cpuid level", 0 }, +- { NULL, -1 }, +- }; +- +- memset(vendor_id, 0, sizeof(vendor_id)); +- +- FILE *fp = fopen(proc_cpu_path, "r"); +- if (fp != NULL) { +- while (fgets(line, sizeof(line), fp)) { +- CpuInfoEntry *entry = &cpu_info_table[0]; +- while (entry->info_name != NULL) { +- if (!strncmp(line, entry->info_name, strlen(entry->info_name))) { +- char *value = strchr(line, ':'); +- value++; +- if (value != NULL) +- sscanf(value, " %d", &(entry->value)); +- } +- entry++; +- } +- +- // special case for vendor_id +- if (!strncmp(line, vendor_id_name, vendor_id_name_length)) { +- char *value = strchr(line, ':'); +- if (value == NULL) +- continue; +- +- value++; +- while (*value && isspace(*value)) +- value++; +- if (*value) { +- size_t length = strlen(value); +- // we don't want the trailing newline +- if (value[length - 1] == '\n') +- length--; +- // ensure we have space for the value +- if (length < sizeof(vendor_id)) +- strncpy(vendor_id, value, length); +- } +- } +- } +- fclose(fp); +- } +- +- // /proc/cpuinfo contains cpu id, change it into number by adding one. +- cpu_info_table[0].value++; +- +- sys_info->number_of_processors = cpu_info_table[0].value; +- sys_info->processor_level = cpu_info_table[3].value; +- sys_info->processor_revision = cpu_info_table[1].value << 8 | +- cpu_info_table[2].value; +- +- sys_info->processor_architecture = MD_CPU_ARCHITECTURE_UNKNOWN; +- struct utsname uts; +- if (uname(&uts) == 0) { +- // Match i*86 and x86* as X86 architecture. +- if ((strstr(uts.machine, "x86") == uts.machine) || +- (strlen(uts.machine) == 4 && +- uts.machine[0] == 'i' && +- uts.machine[2] == '8' && +- uts.machine[3] == '6')) { +- sys_info->processor_architecture = MD_CPU_ARCHITECTURE_X86; +- if (vendor_id[0] != '\0') +- memcpy(sys_info->cpu.x86_cpu_info.vendor_id, vendor_id, +- sizeof(sys_info->cpu.x86_cpu_info.vendor_id)); +- } +- } +- return true; +-} +- +-bool WriteOSInformation(MinidumpFileWriter *minidump_writer, +- MDRawSystemInfo *sys_info) { +- sys_info->platform_id = MD_OS_LINUX; +- +- struct utsname uts; +- if (uname(&uts) == 0) { +- char os_version[512]; +- size_t space_left = sizeof(os_version); +- memset(os_version, 0, space_left); +- const char *os_info_table[] = { +- uts.sysname, +- uts.release, +- uts.version, +- uts.machine, +- "GNU/Linux", +- NULL +- }; +- for (const char **cur_os_info = os_info_table; +- *cur_os_info != NULL; +- cur_os_info++) { +- if (cur_os_info != os_info_table && space_left > 1) { +- strcat(os_version, " "); +- space_left--; +- } +- if (space_left > strlen(*cur_os_info)) { +- strcat(os_version, *cur_os_info); +- space_left -= strlen(*cur_os_info); +- } else { +- break; +- } +- } +- +- MDLocationDescriptor location; +- if (!minidump_writer->WriteString(os_version, 0, &location)) +- return false; +- sys_info->csd_version_rva = location.rva; +- } +- return true; +-} +- +-// Callback context for get writting thread information. +-struct ThreadInfoCallbackCtx { +- MinidumpFileWriter *minidump_writer; +- const WriterArgument *writer_args; +- TypedMDRVA *list; +- int thread_index; +-}; +- +-// Callback run for writing threads information in the process. +-bool ThreadInfomationCallback(const ThreadInfo &thread_info, +- void *context) { +- ThreadInfoCallbackCtx *callback_context = +- static_cast(context); +- bool success = true; +- MDRawThread thread; +- memset(&thread, 0, sizeof(MDRawThread)); +- if (thread_info.pid != callback_context->writer_args->crashed_pid || +- callback_context->writer_args->sig_ctx == NULL) { +- success = WriteThreadStream(callback_context->minidump_writer, +- callback_context->writer_args->thread_lister, +- thread_info, &thread); +- } else { +- success = WriteCrashedThreadStream(callback_context->minidump_writer, +- callback_context->writer_args, +- thread_info, &thread); +- } +- if (success) { +- callback_context->list->CopyIndexAfterObject( +- callback_context->thread_index++, +- &thread, sizeof(MDRawThread)); +- } +- return success; +-} +- +-// Stream writers +-bool WriteThreadListStream(MinidumpFileWriter *minidump_writer, +- const WriterArgument *writer_args, +- MDRawDirectory *dir) { +- // Get the thread information. +- const LinuxThread *thread_lister = writer_args->thread_lister; +- int thread_count = thread_lister->GetThreadCount(); +- if (thread_count < 0) +- return false; +- TypedMDRVA list(minidump_writer); +- if (!list.AllocateObjectAndArray(thread_count, sizeof(MDRawThread))) +- return false; +- dir->stream_type = MD_THREAD_LIST_STREAM; +- dir->location = list.location(); +- list.get()->number_of_threads = thread_count; +- +- ThreadInfoCallbackCtx context; +- context.minidump_writer = minidump_writer; +- context.writer_args = writer_args; +- context.list = &list; +- context.thread_index = 0; +- CallbackParam callback_param(ThreadInfomationCallback, +- &context); +- int written = thread_lister->ListThreads(&callback_param); +- return written == thread_count; +-} +- +-bool WriteCVRecord(MinidumpFileWriter *minidump_writer, +- MDRawModule *module, +- const char *module_path) { +- TypedMDRVA cv(minidump_writer); +- +- // Only return the last path component of the full module path +- const char *module_name = strrchr(module_path, '/'); +- // Increment past the slash +- if (module_name) +- ++module_name; +- else +- module_name = ""; +- +- size_t module_name_length = strlen(module_name); +- if (!cv.AllocateObjectAndArray(module_name_length + 1, sizeof(u_int8_t))) +- return false; +- if (!cv.CopyIndexAfterObject(0, const_cast(module_name), +- module_name_length)) +- return false; +- +- module->cv_record = cv.location(); +- MDCVInfoPDB70 *cv_ptr = cv.get(); +- memset(cv_ptr, 0, sizeof(MDCVInfoPDB70)); +- cv_ptr->cv_signature = MD_CVINFOPDB70_SIGNATURE; +- cv_ptr->age = 0; +- +- // Get the module identifier +- FileID file_id(module_path); +- unsigned char identifier[16]; +- +- if (file_id.ElfFileIdentifier(identifier)) { +- cv_ptr->signature.data1 = (uint32_t)identifier[0] << 24 | +- (uint32_t)identifier[1] << 16 | (uint32_t)identifier[2] << 8 | +- (uint32_t)identifier[3]; +- cv_ptr->signature.data2 = (uint32_t)identifier[4] << 8 | identifier[5]; +- cv_ptr->signature.data3 = (uint32_t)identifier[6] << 8 | identifier[7]; +- cv_ptr->signature.data4[0] = identifier[8]; +- cv_ptr->signature.data4[1] = identifier[9]; +- cv_ptr->signature.data4[2] = identifier[10]; +- cv_ptr->signature.data4[3] = identifier[11]; +- cv_ptr->signature.data4[4] = identifier[12]; +- cv_ptr->signature.data4[5] = identifier[13]; +- cv_ptr->signature.data4[6] = identifier[14]; +- cv_ptr->signature.data4[7] = identifier[15]; +- } +- return true; +-} +- +-struct ModuleInfoCallbackCtx { +- MinidumpFileWriter *minidump_writer; +- const WriterArgument *writer_args; +- TypedMDRVA *list; +- int module_index; +-}; +- +-bool ModuleInfoCallback(const ModuleInfo &module_info, +- void *context) { +- ModuleInfoCallbackCtx *callback_context = +- static_cast(context); +- // Skip those modules without name, or those that are not modules. +- if (strlen(module_info.name) == 0 || +- !strchr(module_info.name, '/')) +- return true; +- +- MDRawModule module; +- memset(&module, 0, sizeof(module)); +- MDLocationDescriptor loc; +- if (!callback_context->minidump_writer->WriteString(module_info.name, 0, +- &loc)) +- return false; +- module.base_of_image = (u_int64_t)module_info.start_addr; +- module.size_of_image = module_info.size; +- module.module_name_rva = loc.rva; +- +- if (!WriteCVRecord(callback_context->minidump_writer, &module, +- module_info.name)) +- return false; +- callback_context->list->CopyIndexAfterObject( +- callback_context->module_index++, &module, MD_MODULE_SIZE); +- return true; +-} +- +-bool WriteModuleListStream(MinidumpFileWriter *minidump_writer, +- const WriterArgument *writer_args, +- MDRawDirectory *dir) { +- TypedMDRVA list(minidump_writer); +- int module_count = writer_args->thread_lister->GetModuleCount(); +- if (module_count <= 0 || +- !list.AllocateObjectAndArray(module_count, MD_MODULE_SIZE)) +- return false; +- dir->stream_type = MD_MODULE_LIST_STREAM; +- dir->location = list.location(); +- list.get()->number_of_modules = module_count; +- ModuleInfoCallbackCtx context; +- context.minidump_writer = minidump_writer; +- context.writer_args = writer_args; +- context.list = &list; +- context.module_index = 0; +- CallbackParam callback(ModuleInfoCallback, &context); +- return writer_args->thread_lister->ListModules(&callback) == module_count; +-} +- +-bool WriteSystemInfoStream(MinidumpFileWriter *minidump_writer, +- const WriterArgument *writer_args, +- MDRawDirectory *dir) { +- TypedMDRVA sys_info(minidump_writer); +- if (!sys_info.Allocate()) +- return false; +- dir->stream_type = MD_SYSTEM_INFO_STREAM; +- dir->location = sys_info.location(); +- +- return WriteCPUInformation(sys_info.get()) && +- WriteOSInformation(minidump_writer, sys_info.get()); +-} +- +-bool WriteExceptionStream(MinidumpFileWriter *minidump_writer, +- const WriterArgument *writer_args, +- MDRawDirectory *dir) { +- // This happenes when this is not a crash, but a requested dump. +- if (writer_args->sig_ctx == NULL) +- return false; +- +- TypedMDRVA exception(minidump_writer); +- if (!exception.Allocate()) +- return false; +- +- dir->stream_type = MD_EXCEPTION_STREAM; +- dir->location = exception.location(); +- exception.get()->thread_id = writer_args->crashed_pid; +- exception.get()->exception_record.exception_code = writer_args->signo; +- exception.get()->exception_record.exception_flags = 0; +- if (writer_args->sig_ctx != NULL) { +- exception.get()->exception_record.exception_address = +- writer_args->sig_ctx->eip; +- } else { +- return true; +- } +- +- // Write context of the exception. +- TypedMDRVA context(minidump_writer); +- if (!context.Allocate()) +- return false; +- exception.get()->thread_context = context.location(); +- memset(context.get(), 0, sizeof(MDRawContextX86)); +- return WriteContext(context.get(), writer_args->sig_ctx, NULL); +-} +- +-bool WriteMiscInfoStream(MinidumpFileWriter *minidump_writer, +- const WriterArgument *writer_args, +- MDRawDirectory *dir) { +- TypedMDRVA info(minidump_writer); +- if (!info.Allocate()) +- return false; +- +- dir->stream_type = MD_MISC_INFO_STREAM; +- dir->location = info.location(); +- info.get()->size_of_info = sizeof(MDRawMiscInfo); +- info.get()->flags1 = MD_MISCINFO_FLAGS1_PROCESS_ID; +- info.get()->process_id = writer_args->requester_pid; +- +- return true; +-} +- +-bool WriteBreakpadInfoStream(MinidumpFileWriter *minidump_writer, +- const WriterArgument *writer_args, +- MDRawDirectory *dir) { +- TypedMDRVA info(minidump_writer); +- if (!info.Allocate()) +- return false; +- +- dir->stream_type = MD_BREAKPAD_INFO_STREAM; +- dir->location = info.location(); +- +- info.get()->validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID | +- MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID; +- info.get()->dump_thread_id = getpid(); +- info.get()->requesting_thread_id = writer_args->requester_pid; +- return true; +-} +- +-// Prototype of writer functions. +-typedef bool (*WriteStringFN)(MinidumpFileWriter *, +- const WriterArgument *, +- MDRawDirectory *); +- +-// Function table to writer a full minidump. +-WriteStringFN writers[] = { +- WriteThreadListStream, +- WriteModuleListStream, +- WriteSystemInfoStream, +- WriteExceptionStream, +- WriteMiscInfoStream, +- WriteBreakpadInfoStream, +-}; +- +-// Will call each writer function in the writers table. +-// It runs in a different process from the crashing process, but sharing +-// the same address space. This enables it to use ptrace functions. +-int Write(void *argument) { +- WriterArgument *writer_args = +- static_cast(argument); +- +- if (!writer_args->thread_lister->SuspendAllThreads()) +- return -1; +- +- if (writer_args->sighandler_ebp != 0 && +- writer_args->thread_lister->FindSigContext(writer_args->sighandler_ebp, +- &writer_args->sig_ctx)) { +- writer_args->crashed_stack_bottom = +- writer_args->thread_lister->GetThreadStackBottom( +- writer_args->sig_ctx->ebp); +- int crashed_pid = FindCrashingThread(writer_args->crashed_stack_bottom, +- writer_args->requester_pid, +- writer_args->thread_lister); +- if (crashed_pid > 0) +- writer_args->crashed_pid = crashed_pid; +- } +- +- +- MinidumpFileWriter *minidump_writer = writer_args->minidump_writer; +- TypedMDRVA header(minidump_writer); +- TypedMDRVA dir(minidump_writer); +- if (!header.Allocate()) +- return 0; +- +- int writer_count = sizeof(writers) / sizeof(writers[0]); +- // Need directory space for all writers. +- if (!dir.AllocateArray(writer_count)) +- return 0; +- header.get()->signature = MD_HEADER_SIGNATURE; +- header.get()->version = MD_HEADER_VERSION; +- header.get()->time_date_stamp = time(NULL); +- header.get()->stream_count = writer_count; +- header.get()->stream_directory_rva = dir.position(); +- +- int dir_index = 0; +- MDRawDirectory local_dir; +- for (int i = 0; i < writer_count; ++i) { +- if (writers[i](minidump_writer, writer_args, &local_dir)) +- dir.CopyIndex(dir_index++, &local_dir); +- } +- +- writer_args->thread_lister->ResumeAllThreads(); +- return 0; +-} +- +-} // namespace +- +-namespace google_breakpad { +- +-MinidumpGenerator::MinidumpGenerator() { +- AllocateStack(); +-} +- +-MinidumpGenerator::~MinidumpGenerator() { +-} +- +-void MinidumpGenerator::AllocateStack() { +- stack_.reset(new char[kStackSize]); +-} +- +-bool MinidumpGenerator::WriteMinidumpToFile(const char *file_pathname, +- int signo, +- uintptr_t sighandler_ebp, +- struct sigcontext **sig_ctx) const { +- assert(file_pathname != NULL); +- assert(stack_ != NULL); +- +- if (stack_ == NULL || file_pathname == NULL) +- return false; +- +- MinidumpFileWriter minidump_writer; +- if (minidump_writer.Open(file_pathname)) { +- WriterArgument argument; +- memset(&argument, 0, sizeof(argument)); +- LinuxThread thread_lister(getpid()); +- argument.thread_lister = &thread_lister; +- argument.minidump_writer = &minidump_writer; +- argument.requester_pid = getpid(); +- argument.crashed_pid = getpid(); +- argument.signo = signo; +- argument.sighandler_ebp = sighandler_ebp; +- argument.sig_ctx = NULL; +- +- int cloned_pid = clone(Write, stack_.get() + kStackSize, +- CLONE_VM | CLONE_FILES | CLONE_FS | CLONE_UNTRACED, +- (void*)&argument); +- waitpid(cloned_pid, NULL, __WALL); +- if (sig_ctx != NULL) +- *sig_ctx = argument.sig_ctx; +- return true; +- } +- +- return false; +-} +- +-} // namespace google_breakpad +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/minidump_generator.h b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/minidump_generator.h +deleted file mode 100644 +--- a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/minidump_generator.h ++++ /dev/null +@@ -1,73 +0,0 @@ +-// Copyright (c) 2006, Google Inc. +-// All rights reserved. +-// +-// Author: Li Liu +-// +-// 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 CLIENT_LINUX_HANDLER_MINIDUMP_GENERATOR_H__ +-#define CLIENT_LINUX_HANDLER_MINIDUMP_GENERATOR_H__ +- +-#include +- +-#include "google_breakpad/common/breakpad_types.h" +-#include "processor/scoped_ptr.h" +- +-struct sigcontext; +- +-namespace google_breakpad { +- +-// +-// MinidumpGenerator +-// +-// Write a minidump to file based on the signo and sig_ctx. +-// A minidump generator should be created before any exception happen. +-// +-class MinidumpGenerator { +- public: +- MinidumpGenerator(); +- +- ~MinidumpGenerator(); +- +- // Write minidump. +- bool WriteMinidumpToFile(const char *file_pathname, +- int signo, +- uintptr_t sighandler_ebp, +- struct sigcontext **sig_ctx) const; +- private: +- // Allocate memory for stack. +- void AllocateStack(); +- +- private: +- // Stack size of the writer thread. +- static const int kStackSize = 1024 * 1024; +- scoped_array stack_; +-}; +- +-} // namespace google_breakpad +- +-#endif // CLIENT_LINUX_HANDLER_MINIDUMP_GENERATOR_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/minidump_test.cc b/toolkit/crashreporter/google-breakpad/src/client/linux/handler/minidump_test.cc +deleted file mode 100644 +--- a/toolkit/crashreporter/google-breakpad/src/client/linux/handler/minidump_test.cc ++++ /dev/null +@@ -1,86 +0,0 @@ +-// Copyright (c) 2006, Google Inc. +-// All rights reserved. +-// +-// Author: Li Liu +-// +-// 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 +-#include +- +-#include +-#include +-#include +-#include +- +-#include "client/linux/handler/minidump_generator.h" +- +-using namespace google_breakpad; +- +-// Thread use this to see if it should stop working. +-static bool should_exit = false; +- +-static void foo2(int arg) { +- // Stack variable, used for debugging stack dumps. +- int c = arg; +- c = 0xcccccccc; +- while (!should_exit) +- sleep(1); +-} +- +-static void foo(int arg) { +- // Stack variable, used for debugging stack dumps. +- int b = arg; +- b = 0xbbbbbbbb; +- foo2(b); +-} +- +-static void *thread_main(void *) { +- // Stack variable, used for debugging stack dumps. +- int a = 0xaaaaaaaa; +- foo(a); +- return NULL; +-} +- +-static void CreateThread(int num) { +- pthread_t h; +- for (int i = 0; i < num; ++i) { +- pthread_create(&h, NULL, thread_main, NULL); +- pthread_detach(h); +- } +-} +- +-int main(int argc, char *argv[]) { +- CreateThread(10); +- google_breakpad::MinidumpGenerator mg; +- if (mg.WriteMinidumpToFile("minidump_test.out", -1, 0, NULL)) +- printf("Succeeded written minidump\n"); +- else +- printf("Failed to write minidump\n"); +- should_exit = true; +- return 0; +-} +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/Makefile.in b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/Makefile.in +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/Makefile.in +@@ -0,0 +1,60 @@ ++# ***** BEGIN LICENSE BLOCK ***** ++# Version: MPL 1.1/GPL 2.0/LGPL 2.1 ++# ++# The contents of this file are subject to the Mozilla Public License Version ++# 1.1 (the "License"); you may not use this file except in compliance with ++# the License. You may obtain a copy of the License at ++# http://www.mozilla.org/MPL/ ++# ++# Software distributed under the License is distributed on an "AS IS" basis, ++# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++# for the specific language governing rights and limitations under the ++# License. ++# ++# The Original Code is Mozilla Breakpad integration ++# ++# The Initial Developer of the Original Code is ++# The Mozilla Foundation. ++# Portions created by the Initial Developer are Copyright (C) 2009 ++# the Initial Developer. All Rights Reserved. ++# ++# Contributor(s): ++# Ted Mielczarek ++# ++# Alternatively, the contents of this file may be used under the terms of ++# either the GNU General Public License Version 2 or later (the "GPL"), or ++# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), ++# in which case the provisions of the GPL or the LGPL are applicable instead ++# of those above. If you wish to allow use of your version of this file only ++# under the terms of either the GPL or the LGPL, and not to allow others to ++# use your version of this file under the terms of the MPL, indicate your ++# decision by deleting the provisions above and replace them with the notice ++# and other provisions required by the GPL or the LGPL. If you do not delete ++# the provisions above, a recipient may use your version of this file under ++# the terms of any one of the MPL, the GPL or the LGPL. ++# ++# ***** END LICENSE BLOCK ***** ++ ++DEPTH = ../../../../../../.. ++topsrcdir = @top_srcdir@ ++srcdir = @srcdir@ ++VPATH = @srcdir@ ++ ++include $(DEPTH)/config/autoconf.mk ++ ++MODULE = writer ++LIBRARY_NAME = minidump_writer_s ++XPI_NAME = crashreporter ++ ++LOCAL_INCLUDES = -I$(srcdir)/../../.. ++ ++CPPSRCS = \ ++ linux_dumper.cc \ ++ minidump_writer.cc \ ++ $(NULL) ++ ++# need static lib ++FORCE_STATIC_LIB = 1 ++FORCE_USE_PIC = 1 ++ ++include $(topsrcdir)/config/rules.mk +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/directory_reader.h b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/directory_reader.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/directory_reader.h +@@ -0,0 +1,105 @@ ++// Copyright (c) 2009, 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 CLIENT_LINUX_MINIDUMP_WRITER_DIRECTORY_READER_H_ ++#define CLIENT_LINUX_MINIDUMP_WRITER_DIRECTORY_READER_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "common/linux/linux_syscall_support.h" ++ ++namespace google_breakpad { ++ ++// A class for enumerating a directory without using diropen/readdir or other ++// functions which may allocate memory. ++class DirectoryReader { ++ public: ++ DirectoryReader(int fd) ++ : fd_(fd), ++ buf_used_(0) { ++ } ++ ++ // Return the next entry from the directory ++ // name: (output) the NUL terminated entry name ++ // ++ // Returns true iff successful (false on EOF). ++ // ++ // After calling this, one must call |PopEntry| otherwise you'll get the same ++ // entry over and over. ++ bool GetNextEntry(const char** name) { ++ struct kernel_dirent* const dent = ++ reinterpret_cast(buf_); ++ ++ if (buf_used_ == 0) { ++ // need to read more entries. ++ const int n = sys_getdents(fd_, dent, sizeof(buf_)); ++ if (n < 0) { ++ return false; ++ } else if (n == 0) { ++ hit_eof_ = true; ++ } else { ++ buf_used_ += n; ++ } ++ } ++ ++ if (buf_used_ == 0 && hit_eof_) ++ return false; ++ ++ assert(buf_used_ > 0); ++ ++ *name = dent->d_name; ++ return true; ++ } ++ ++ void PopEntry() { ++ if (!buf_used_) ++ return; ++ ++ const struct kernel_dirent* const dent = ++ reinterpret_cast(buf_); ++ ++ buf_used_ -= dent->d_reclen; ++ memmove(buf_, buf_ + dent->d_reclen, buf_used_); ++ } ++ ++ private: ++ const int fd_; ++ bool hit_eof_; ++ unsigned buf_used_; ++ uint8_t buf_[sizeof(struct kernel_dirent) + NAME_MAX + 1]; ++}; ++ ++} // namespace google_breakpad ++ ++#endif // CLIENT_LINUX_MINIDUMP_WRITER_DIRECTORY_READER_H_ +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/directory_reader_unittest.cc b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/directory_reader_unittest.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/directory_reader_unittest.cc +@@ -0,0 +1,77 @@ ++// Copyright (c) 2009, 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 ++#include ++ ++#include ++#include ++#include ++ ++#include "client/linux/minidump_writer/directory_reader.h" ++#include "breakpad_googletest_includes.h" ++ ++using namespace google_breakpad; ++ ++namespace { ++typedef testing::Test DirectoryReaderTest; ++} ++ ++TEST(DirectoryReaderTest, CompareResults) { ++ std::set dent_set; ++ ++ DIR *const dir = opendir("/proc/self"); ++ ASSERT_TRUE(dir != NULL); ++ ++ struct dirent* dent; ++ while ((dent = readdir(dir))) ++ dent_set.insert(dent->d_name); ++ ++ closedir(dir); ++ ++ const int fd = open("/proc/self", O_DIRECTORY | O_RDONLY); ++ ASSERT_GE(fd, 0); ++ ++ DirectoryReader dir_reader(fd); ++ unsigned seen = 0; ++ ++ const char* name; ++ while (dir_reader.GetNextEntry(&name)) { ++ ASSERT_TRUE(dent_set.find(name) != dent_set.end()); ++ seen++; ++ dir_reader.PopEntry(); ++ } ++ ++ ASSERT_TRUE(dent_set.find("status") != dent_set.end()); ++ ASSERT_TRUE(dent_set.find("stat") != dent_set.end()); ++ ASSERT_TRUE(dent_set.find("cmdline") != dent_set.end()); ++ ++ ASSERT_EQ(dent_set.size(), seen); ++ close(fd); ++} +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/line_reader.h b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/line_reader.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/line_reader.h +@@ -0,0 +1,130 @@ ++// Copyright (c) 2009, 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 CLIENT_LINUX_MINIDUMP_WRITER_LINE_READER_H_ ++#define CLIENT_LINUX_MINIDUMP_WRITER_LINE_READER_H_ ++ ++#include ++#include ++#include ++ ++#include "common/linux/linux_syscall_support.h" ++ ++namespace google_breakpad { ++ ++// A class for reading a file, line by line, without using fopen/fgets or other ++// functions which may allocate memory. ++class LineReader { ++ public: ++ LineReader(int fd) ++ : fd_(fd), ++ hit_eof_(false), ++ buf_used_(0) { ++ } ++ ++ // The maximum length of a line. ++ static const size_t kMaxLineLen = 512; ++ ++ // Return the next line from the file. ++ // line: (output) a pointer to the start of the line. The line is NUL ++ // terminated. ++ // len: (output) the length of the line (not inc the NUL byte) ++ // ++ // Returns true iff successful (false on EOF). ++ // ++ // One must call |PopLine| after this function, otherwise you'll continue to ++ // get the same line over and over. ++ bool GetNextLine(const char **line, unsigned *len) { ++ for (;;) { ++ if (buf_used_ == 0 && hit_eof_) ++ return false; ++ ++ for (unsigned i = 0; i < buf_used_; ++i) { ++ if (buf_[i] == '\n' || buf_[i] == 0) { ++ buf_[i] = 0; ++ *len = i; ++ *line = buf_; ++ return true; ++ } ++ } ++ ++ if (buf_used_ == sizeof(buf_)) { ++ // we scanned the whole buffer and didn't find an end-of-line marker. ++ // This line is too long to process. ++ return false; ++ } ++ ++ // We didn't find any end-of-line terminators in the buffer. However, if ++ // this is the last line in the file it might not have one: ++ if (hit_eof_) { ++ assert(buf_used_); ++ // There's room for the NUL because of the buf_used_ == sizeof(buf_) ++ // check above. ++ buf_[buf_used_] = 0; ++ *len = buf_used_; ++ buf_used_ += 1; // since we appended the NUL. ++ *line = buf_; ++ return true; ++ } ++ ++ // Otherwise, we should pull in more data from the file ++ const ssize_t n = sys_read(fd_, buf_ + buf_used_, ++ sizeof(buf_) - buf_used_); ++ if (n < 0) { ++ return false; ++ } else if (n == 0) { ++ hit_eof_ = true; ++ } else { ++ buf_used_ += n; ++ } ++ ++ // At this point, we have either set the hit_eof_ flag, or we have more ++ // data to process... ++ } ++ } ++ ++ void PopLine(unsigned len) { ++ // len doesn't include the NUL byte at the end. ++ ++ assert(buf_used_ >= len + 1); ++ buf_used_ -= len + 1; ++ memmove(buf_, buf_ + len + 1, buf_used_); ++ } ++ ++ private: ++ const int fd_; ++ ++ bool hit_eof_; ++ unsigned buf_used_; ++ char buf_[kMaxLineLen]; ++}; ++ ++} // namespace google_breakpad ++ ++#endif // CLIENT_LINUX_MINIDUMP_WRITER_LINE_READER_H_ +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/line_reader_unittest.cc b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/line_reader_unittest.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/line_reader_unittest.cc +@@ -0,0 +1,184 @@ ++// Copyright (c) 2009, 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 ++#include ++#include ++ ++#include "client/linux/minidump_writer/line_reader.h" ++#include "breakpad_googletest_includes.h" ++ ++using namespace google_breakpad; ++ ++static int TemporaryFile() { ++ static const char templ[] = "/tmp/line-reader-unittest-XXXXXX"; ++ char templ_copy[sizeof(templ)]; ++ memcpy(templ_copy, templ, sizeof(templ)); ++ const int fd = mkstemp(templ_copy); ++ if (fd >= 0) ++ unlink(templ_copy); ++ ++ return fd; ++} ++ ++namespace { ++typedef testing::Test LineReaderTest; ++} ++ ++TEST(LineReaderTest, EmptyFile) { ++ const int fd = TemporaryFile(); ++ LineReader reader(fd); ++ ++ const char *line; ++ unsigned len; ++ ASSERT_FALSE(reader.GetNextLine(&line, &len)); ++ ++ close(fd); ++} ++ ++TEST(LineReaderTest, OneLineTerminated) { ++ const int fd = TemporaryFile(); ++ write(fd, "a\n", 2); ++ lseek(fd, 0, SEEK_SET); ++ LineReader reader(fd); ++ ++ const char *line; ++ unsigned len; ++ ASSERT_TRUE(reader.GetNextLine(&line, &len)); ++ ASSERT_EQ(len, 1); ++ ASSERT_EQ(line[0], 'a'); ++ ASSERT_EQ(line[1], 0); ++ reader.PopLine(len); ++ ++ ASSERT_FALSE(reader.GetNextLine(&line, &len)); ++ ++ close(fd); ++} ++ ++TEST(LineReaderTest, OneLine) { ++ const int fd = TemporaryFile(); ++ write(fd, "a", 1); ++ lseek(fd, 0, SEEK_SET); ++ LineReader reader(fd); ++ ++ const char *line; ++ unsigned len; ++ ASSERT_TRUE(reader.GetNextLine(&line, &len)); ++ ASSERT_EQ(len, 1); ++ ASSERT_EQ(line[0], 'a'); ++ ASSERT_EQ(line[1], 0); ++ reader.PopLine(len); ++ ++ ASSERT_FALSE(reader.GetNextLine(&line, &len)); ++ ++ close(fd); ++} ++ ++TEST(LineReaderTest, TwoLinesTerminated) { ++ const int fd = TemporaryFile(); ++ write(fd, "a\nb\n", 4); ++ lseek(fd, 0, SEEK_SET); ++ LineReader reader(fd); ++ ++ const char *line; ++ unsigned len; ++ ASSERT_TRUE(reader.GetNextLine(&line, &len)); ++ ASSERT_EQ(len, 1); ++ ASSERT_EQ(line[0], 'a'); ++ ASSERT_EQ(line[1], 0); ++ reader.PopLine(len); ++ ++ ASSERT_TRUE(reader.GetNextLine(&line, &len)); ++ ASSERT_EQ(len, 1); ++ ASSERT_EQ(line[0], 'b'); ++ ASSERT_EQ(line[1], 0); ++ reader.PopLine(len); ++ ++ ASSERT_FALSE(reader.GetNextLine(&line, &len)); ++ ++ close(fd); ++} ++ ++TEST(LineReaderTest, TwoLines) { ++ const int fd = TemporaryFile(); ++ write(fd, "a\nb", 3); ++ lseek(fd, 0, SEEK_SET); ++ LineReader reader(fd); ++ ++ const char *line; ++ unsigned len; ++ ASSERT_TRUE(reader.GetNextLine(&line, &len)); ++ ASSERT_EQ(len, 1); ++ ASSERT_EQ(line[0], 'a'); ++ ASSERT_EQ(line[1], 0); ++ reader.PopLine(len); ++ ++ ASSERT_TRUE(reader.GetNextLine(&line, &len)); ++ ASSERT_EQ(len, 1); ++ ASSERT_EQ(line[0], 'b'); ++ ASSERT_EQ(line[1], 0); ++ reader.PopLine(len); ++ ++ ASSERT_FALSE(reader.GetNextLine(&line, &len)); ++ ++ close(fd); ++} ++ ++TEST(LineReaderTest, MaxLength) { ++ const int fd = TemporaryFile(); ++ char l[LineReader::kMaxLineLen - 1]; ++ memset(l, 'a', sizeof(l)); ++ write(fd, l, sizeof(l)); ++ lseek(fd, 0, SEEK_SET); ++ LineReader reader(fd); ++ ++ const char *line; ++ unsigned len; ++ ASSERT_TRUE(reader.GetNextLine(&line, &len)); ++ ASSERT_EQ(len, sizeof(l)); ++ ASSERT_TRUE(memcmp(l, line, sizeof(l)) == 0); ++ ASSERT_EQ(line[len], 0); ++ ++ close(fd); ++} ++ ++TEST(LineReaderTest, TooLong) { ++ const int fd = TemporaryFile(); ++ char l[LineReader::kMaxLineLen]; ++ memset(l, 'a', sizeof(l)); ++ write(fd, l, sizeof(l)); ++ lseek(fd, 0, SEEK_SET); ++ LineReader reader(fd); ++ ++ const char *line; ++ unsigned len; ++ ASSERT_FALSE(reader.GetNextLine(&line, &len)); ++ ++ close(fd); ++} +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper.cc b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper.cc +@@ -0,0 +1,453 @@ ++// Copyright (c) 2009, 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. ++ ++// This code deals with the mechanics of getting information about a crashed ++// process. Since this code may run in a compromised address space, the same ++// rules apply as detailed at the top of minidump_writer.h: no libc calls and ++// use the alternative allocator. ++ ++#include "client/linux/minidump_writer/linux_dumper.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "client/linux/minidump_writer/directory_reader.h" ++#include "client/linux/minidump_writer/line_reader.h" ++#include "common/linux/file_id.h" ++#include "common/linux/linux_libc_support.h" ++#include "common/linux/linux_syscall_support.h" ++ ++// Suspend a thread by attaching to it. ++static bool SuspendThread(pid_t pid) { ++ // This may fail if the thread has just died or debugged. ++ errno = 0; ++ if (sys_ptrace(PTRACE_ATTACH, pid, NULL, NULL) != 0 && ++ errno != 0) { ++ return false; ++ } ++ while (sys_waitpid(pid, NULL, __WALL) < 0) { ++ if (errno != EINTR) { ++ sys_ptrace(PTRACE_DETACH, pid, NULL, NULL); ++ return false; ++ } ++ } ++ return true; ++} ++ ++// Resume a thread by detaching from it. ++static bool ResumeThread(pid_t pid) { ++ return sys_ptrace(PTRACE_DETACH, pid, NULL, NULL) >= 0; ++} ++ ++namespace google_breakpad { ++ ++LinuxDumper::LinuxDumper(int pid) ++ : pid_(pid), ++ threads_suspened_(false), ++ threads_(&allocator_, 8), ++ mappings_(&allocator_) { ++} ++ ++bool LinuxDumper::Init() { ++ return EnumerateThreads(&threads_) && ++ EnumerateMappings(&mappings_); ++} ++ ++bool LinuxDumper::ThreadsSuspend() { ++ if (threads_suspened_) ++ return true; ++ bool good = true; ++ for (size_t i = 0; i < threads_.size(); ++i) ++ good &= SuspendThread(threads_[i]); ++ threads_suspened_ = true; ++ return good; ++} ++ ++bool LinuxDumper::ThreadsResume() { ++ if (!threads_suspened_) ++ return false; ++ bool good = true; ++ for (size_t i = 0; i < threads_.size(); ++i) ++ good &= ResumeThread(threads_[i]); ++ threads_suspened_ = false; ++ return good; ++} ++ ++void ++LinuxDumper::BuildProcPath(char* path, pid_t pid, const char* node) const { ++ assert(path); ++ if (!path) { ++ return; ++ } ++ ++ path[0] = '\0'; ++ ++ const unsigned pid_len = my_int_len(pid); ++ ++ assert(node); ++ if (!node) { ++ return; ++ } ++ ++ size_t node_len = my_strlen(node); ++ assert(node_len < NAME_MAX); ++ if (node_len >= NAME_MAX) { ++ return; ++ } ++ ++ assert(node_len > 0); ++ if (node_len == 0) { ++ return; ++ } ++ ++ assert(pid > 0); ++ if (pid <= 0) { ++ return; ++ } ++ ++ const size_t total_length = 6 + pid_len + 1 + node_len; ++ ++ assert(total_length < NAME_MAX); ++ if (total_length >= NAME_MAX) { ++ return; ++ } ++ ++ memcpy(path, "/proc/", 6); ++ my_itos(path + 6, pid, pid_len); ++ memcpy(path + 6 + pid_len, "/", 1); ++ memcpy(path + 6 + pid_len + 1, node, node_len); ++ memcpy(path + total_length, "\0", 1); ++} ++ ++bool ++LinuxDumper::ElfFileIdentifierForMapping(unsigned int mapping_id, ++ uint8_t identifier[sizeof(MDGUID)]) ++{ ++ assert(mapping_id < mappings_.size()); ++ const MappingInfo* mapping = mappings_[mapping_id]; ++ int fd = sys_open(mapping->name, O_RDONLY, 0); ++ if (fd < 0) ++ return false; ++ struct kernel_stat st; ++ if (sys_fstat(fd, &st) != 0) { ++ sys_close(fd); ++ return false; ++ } ++#if defined(__x86_64) ++#define sys_mmap2 sys_mmap ++#endif ++ void* base = sys_mmap2(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); ++ sys_close(fd); ++ if (base == MAP_FAILED) ++ return false; ++ ++ bool success = FileID::ElfFileIdentifierFromMappedFile(base, identifier); ++ sys_munmap(base, st.st_size); ++ return success; ++} ++ ++void* ++LinuxDumper::FindBeginningOfLinuxGateSharedLibrary(const pid_t pid) const { ++ char auxv_path[80]; ++ BuildProcPath(auxv_path, pid, "auxv"); ++ ++ // If BuildProcPath errors out due to invalid input, we'll handle it when ++ // we try to sys_open the file. ++ ++ // Find the AT_SYSINFO_EHDR entry for linux-gate.so ++ // See http://www.trilithium.com/johan/2005/08/linux-gate/ for more ++ // information. ++ int fd = sys_open(auxv_path, O_RDONLY, 0); ++ if (fd < 0) { ++ return NULL; ++ } ++ ++ elf_aux_entry one_aux_entry; ++ while (sys_read(fd, ++ &one_aux_entry, ++ sizeof(elf_aux_entry)) == sizeof(elf_aux_entry) && ++ one_aux_entry.a_type != AT_NULL) { ++ if (one_aux_entry.a_type == AT_SYSINFO_EHDR) { ++ close(fd); ++ return reinterpret_cast(one_aux_entry.a_un.a_val); ++ } ++ } ++ close(fd); ++ return NULL; ++} ++ ++bool ++LinuxDumper::EnumerateMappings(wasteful_vector* result) const { ++ char maps_path[80]; ++ BuildProcPath(maps_path, pid_, "maps"); ++ ++ // linux_gate_loc is the beginning of the kernel's mapping of ++ // linux-gate.so in the process. It doesn't actually show up in the ++ // maps list as a filename, so we use the aux vector to find it's ++ // load location and special case it's entry when creating the list ++ // of mappings. ++ const void* linux_gate_loc; ++ linux_gate_loc = FindBeginningOfLinuxGateSharedLibrary(pid_); ++ ++ const int fd = sys_open(maps_path, O_RDONLY, 0); ++ if (fd < 0) ++ return false; ++ LineReader* const line_reader = new(allocator_) LineReader(fd); ++ ++ const char* line; ++ unsigned line_len; ++ while (line_reader->GetNextLine(&line, &line_len)) { ++ uintptr_t start_addr, end_addr, offset; ++ ++ const char* i1 = my_read_hex_ptr(&start_addr, line); ++ if (*i1 == '-') { ++ const char* i2 = my_read_hex_ptr(&end_addr, i1 + 1); ++ if (*i2 == ' ') { ++ const char* i3 = my_read_hex_ptr(&offset, i2 + 6 /* skip ' rwxp ' */); ++ if (*i3 == ' ') { ++ MappingInfo* const module = new(allocator_) MappingInfo; ++ memset(module, 0, sizeof(MappingInfo)); ++ module->start_addr = start_addr; ++ module->size = end_addr - start_addr; ++ module->offset = offset; ++ const char* name = NULL; ++ // Only copy name if the name is a valid path name, or if ++ // we've found the VDSO image ++ if ((name = my_strchr(line, '/')) != NULL) { ++ const unsigned l = my_strlen(name); ++ if (l < sizeof(module->name)) ++ memcpy(module->name, name, l); ++ } else if (linux_gate_loc && ++ reinterpret_cast(module->start_addr) == ++ linux_gate_loc) { ++ memcpy(module->name, ++ kLinuxGateLibraryName, ++ my_strlen(kLinuxGateLibraryName)); ++ module->offset = 0; ++ } ++ result->push_back(module); ++ } ++ } ++ } ++ line_reader->PopLine(line_len); ++ } ++ ++ sys_close(fd); ++ ++ return result->size() > 0; ++} ++ ++// Parse /proc/$pid/task to list all the threads of the process identified by ++// pid. ++bool LinuxDumper::EnumerateThreads(wasteful_vector* result) const { ++ char task_path[80]; ++ BuildProcPath(task_path, pid_, "task"); ++ ++ const int fd = sys_open(task_path, O_RDONLY | O_DIRECTORY, 0); ++ if (fd < 0) ++ return false; ++ DirectoryReader* dir_reader = new(allocator_) DirectoryReader(fd); ++ ++ // The directory may contain duplicate entries which we filter by assuming ++ // that they are consecutive. ++ int last_tid = -1; ++ const char* dent_name; ++ while (dir_reader->GetNextEntry(&dent_name)) { ++ if (my_strcmp(dent_name, ".") && ++ my_strcmp(dent_name, "..")) { ++ int tid = 0; ++ if (my_strtoui(&tid, dent_name) && ++ last_tid != tid) { ++ last_tid = tid; ++ result->push_back(tid); ++ } ++ } ++ dir_reader->PopEntry(); ++ } ++ ++ sys_close(fd); ++ return true; ++} ++ ++// Read thread info from /proc/$pid/status. ++// Fill out the |tgid|, |ppid| and |pid| members of |info|. If unavailible, ++// these members are set to -1. Returns true iff all three members are ++// availible. ++bool LinuxDumper::ThreadInfoGet(pid_t tid, ThreadInfo* info) { ++ assert(info != NULL); ++ char status_path[80]; ++ BuildProcPath(status_path, tid, "status"); ++ ++ const int fd = open(status_path, O_RDONLY); ++ if (fd < 0) ++ return false; ++ ++ LineReader* const line_reader = new(allocator_) LineReader(fd); ++ const char* line; ++ unsigned line_len; ++ ++ info->ppid = info->tgid = -1; ++ ++ while (line_reader->GetNextLine(&line, &line_len)) { ++ if (my_strncmp("Tgid:\t", line, 6) == 0) { ++ my_strtoui(&info->tgid, line + 6); ++ } else if (my_strncmp("PPid:\t", line, 6) == 0) { ++ my_strtoui(&info->ppid, line + 6); ++ } ++ ++ line_reader->PopLine(line_len); ++ } ++ ++ if (info->ppid == -1 || info->tgid == -1) ++ return false; ++ ++ if (sys_ptrace(PTRACE_GETREGS, tid, NULL, &info->regs) == -1 || ++ sys_ptrace(PTRACE_GETFPREGS, tid, NULL, &info->fpregs) == -1) { ++ return false; ++ } ++ ++#if defined(__i386) ++ if (sys_ptrace(PTRACE_GETFPXREGS, tid, NULL, &info->fpxregs) == -1) ++ return false; ++#endif ++ ++#if defined(__i386) || defined(__x86_64) ++ for (unsigned i = 0; i < ThreadInfo::kNumDebugRegisters; ++i) { ++ if (sys_ptrace( ++ PTRACE_PEEKUSER, tid, ++ reinterpret_cast (offsetof(struct user, ++ u_debugreg[0]) + i * ++ sizeof(debugreg_t)), ++ &info->dregs[i]) == -1) { ++ return false; ++ } ++ } ++#endif ++ ++ const uint8_t* stack_pointer; ++#if defined(__i386) ++ memcpy(&stack_pointer, &info->regs.esp, sizeof(info->regs.esp)); ++#elif defined(__x86_64) ++ memcpy(&stack_pointer, &info->regs.rsp, sizeof(info->regs.rsp)); ++#else ++#error "This code hasn't been ported to your platform yet." ++#endif ++ ++ if (!GetStackInfo(&info->stack, &info->stack_len, ++ (uintptr_t) stack_pointer)) ++ return false; ++ ++ return true; ++} ++ ++// Get information about the stack, given the stack pointer. We don't try to ++// walk the stack since we might not have all the information needed to do ++// unwind. So we just grab, up to, 32k of stack. ++bool LinuxDumper::GetStackInfo(const void** stack, size_t* stack_len, ++ uintptr_t int_stack_pointer) { ++#if defined(__i386) || defined(__x86_64) ++ static const bool stack_grows_down = true; ++ static const uintptr_t page_size = 4096; ++#else ++#error "This code has not been ported to your platform yet." ++#endif ++ // Move the stack pointer to the bottom of the page that it's in. ++ uint8_t* const stack_pointer = ++ reinterpret_cast(int_stack_pointer & ~(page_size - 1)); ++ ++ // The number of bytes of stack which we try to capture. ++ static ptrdiff_t kStackToCapture = 32 * 1024; ++ ++ const MappingInfo* mapping = FindMapping(stack_pointer); ++ if (!mapping) ++ return false; ++ if (stack_grows_down) { ++ const ptrdiff_t offset = stack_pointer - (uint8_t*) mapping->start_addr; ++ const ptrdiff_t distance_to_end = ++ static_cast(mapping->size) - offset; ++ *stack_len = distance_to_end > kStackToCapture ? ++ kStackToCapture : distance_to_end; ++ *stack = stack_pointer; ++ } else { ++ const ptrdiff_t offset = stack_pointer - (uint8_t*) mapping->start_addr; ++ *stack_len = offset > kStackToCapture ? kStackToCapture : offset; ++ *stack = stack_pointer - *stack_len; ++ } ++ ++ return true; ++} ++ ++// static ++void LinuxDumper::CopyFromProcess(void* dest, pid_t child, const void* src, ++ size_t length) { ++ unsigned long tmp; ++ size_t done = 0; ++ static const size_t word_size = sizeof(tmp); ++ uint8_t* const local = (uint8_t*) dest; ++ uint8_t* const remote = (uint8_t*) src; ++ ++ while (done < length) { ++ const size_t l = length - done > word_size ? word_size : length - done; ++ if (sys_ptrace(PTRACE_PEEKDATA, child, remote + done, &tmp) == -1) ++ tmp = 0; ++ memcpy(local + done, &tmp, l); ++ done += l; ++ } ++} ++ ++// Find the mapping which the given memory address falls in. ++const MappingInfo* LinuxDumper::FindMapping(const void* address) const { ++ const uintptr_t addr = (uintptr_t) address; ++ ++ for (size_t i = 0; i < mappings_.size(); ++i) { ++ const uintptr_t start = static_cast(mappings_[i]->start_addr); ++ if (addr >= start && addr - start < mappings_[i]->size) ++ return mappings_[i]; ++ } ++ ++ return NULL; ++} ++ ++} // namespace google_breakpad +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper.h b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper.h +@@ -0,0 +1,151 @@ ++// Copyright (c) 2009, 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 CLIENT_LINUX_MINIDUMP_WRITER_LINUX_DUMPER_H_ ++#define CLIENT_LINUX_MINIDUMP_WRITER_LINUX_DUMPER_H_ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "common/linux/memory.h" ++#include "google_breakpad/common/minidump_format.h" ++ ++namespace google_breakpad { ++ ++typedef typeof(((struct user*) 0)->u_debugreg[0]) debugreg_t; ++ ++// Typedef for our parsing of the auxv variables in /proc/pid/auxv. ++#if defined(__i386) ++typedef Elf32_auxv_t elf_aux_entry; ++#elif defined(__x86_64__) ++typedef Elf64_auxv_t elf_aux_entry; ++#endif ++// When we find the VDSO mapping in the process's address space, this ++// is the name we use for it when writing it to the minidump. ++// This should always be less than NAME_MAX! ++const char kLinuxGateLibraryName[] = "linux-gate.so"; ++ ++// We produce one of these structures for each thread in the crashed process. ++struct ThreadInfo { ++ pid_t tgid; // thread group id ++ pid_t ppid; // parent process ++ ++ // Even on platforms where the stack grows down, the following will point to ++ // the smallest address in the stack. ++ const void* stack; // pointer to the stack area ++ size_t stack_len; // length of the stack to copy ++ ++ user_regs_struct regs; ++ user_fpregs_struct fpregs; ++#if defined(__i386) ++ user_fpxregs_struct fpxregs; ++#endif ++ ++#if defined(__i386) || defined(__x86_64) ++ ++ static const unsigned kNumDebugRegisters = 8; ++ debugreg_t dregs[8]; ++#endif ++}; ++ ++// One of these is produced for each mapping in the process (i.e. line in ++// /proc/$x/maps). ++struct MappingInfo { ++ uintptr_t start_addr; ++ size_t size; ++ size_t offset; // offset into the backed file. ++ char name[NAME_MAX]; ++}; ++ ++class LinuxDumper { ++ public: ++ explicit LinuxDumper(pid_t pid); ++ ++ // Parse the data for |threads| and |mappings|. ++ bool Init(); ++ ++ // Suspend/resume all threads in the given process. ++ bool ThreadsSuspend(); ++ bool ThreadsResume(); ++ ++ // Read information about the given thread. Returns true on success. One must ++ // have called |ThreadsSuspend| first. ++ bool ThreadInfoGet(pid_t tid, ThreadInfo* info); ++ ++ // These are only valid after a call to |Init|. ++ const wasteful_vector &threads() { return threads_; } ++ const wasteful_vector &mappings() { return mappings_; } ++ const MappingInfo* FindMapping(const void* address) const; ++ ++ // Find a block of memory to take as the stack given the top of stack pointer. ++ // stack: (output) the lowest address in the memory area ++ // stack_len: (output) the length of the memory area ++ // stack_top: the current top of the stack ++ bool GetStackInfo(const void** stack, size_t* stack_len, uintptr_t stack_top); ++ ++ PageAllocator* allocator() { return &allocator_; } ++ ++ // memcpy from a remote process. ++ static void CopyFromProcess(void* dest, pid_t child, const void* src, ++ size_t length); ++ ++ // Builds a proc path for a certain pid for a node. path is a ++ // character array that is overwritten, and node is the final node ++ // without any slashes. ++ void BuildProcPath(char* path, pid_t pid, const char* node) const; ++ ++ // Generate a File ID from the .text section of a mapped entry ++ bool ElfFileIdentifierForMapping(unsigned int mapping_id, ++ uint8_t identifier[sizeof(MDGUID)]); ++ ++ // Utility method to find the location of where the kernel has ++ // mapped linux-gate.so in memory(shows up in /proc/pid/maps as ++ // [vdso], but we can't guarantee that it's the only virtual dynamic ++ // shared object. Parsing the auxilary vector for AT_SYSINFO_EHDR ++ // is the safest way to go.) ++ void* FindBeginningOfLinuxGateSharedLibrary(const pid_t pid) const; ++ private: ++ bool EnumerateMappings(wasteful_vector* result) const; ++ bool EnumerateThreads(wasteful_vector* result) const; ++ ++ const pid_t pid_; ++ ++ mutable PageAllocator allocator_; ++ ++ bool threads_suspened_; ++ wasteful_vector threads_; // the ids of all the threads ++ wasteful_vector mappings_; // info from /proc//maps ++}; ++ ++} // namespace google_breakpad ++ ++#endif // CLIENT_LINUX_HANDLER_LINUX_DUMPER_H_ +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper_unittest.cc b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper_unittest.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/linux_dumper_unittest.cc +@@ -0,0 +1,183 @@ ++// Copyright (c) 2009, 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 ++#include ++ ++#include "client/linux/minidump_writer/linux_dumper.h" ++#include "common/linux/file_id.h" ++#include "breakpad_googletest_includes.h" ++ ++using namespace google_breakpad; ++ ++// This provides a wrapper around system calls which may be ++// interrupted by a signal and return EINTR. See man 7 signal. ++#define HANDLE_EINTR(x) ({ \ ++ typeof(x) __eintr_result__; \ ++ do { \ ++ __eintr_result__ = x; \ ++ } while (__eintr_result__ == -1 && errno == EINTR); \ ++ __eintr_result__;\ ++}) ++ ++namespace { ++typedef testing::Test LinuxDumperTest; ++} ++ ++TEST(LinuxDumperTest, Setup) { ++ LinuxDumper dumper(getpid()); ++} ++ ++TEST(LinuxDumperTest, FindMappings) { ++ LinuxDumper dumper(getpid()); ++ ASSERT_TRUE(dumper.Init()); ++ ++ ASSERT_TRUE(dumper.FindMapping(reinterpret_cast(getpid))); ++ ASSERT_TRUE(dumper.FindMapping(reinterpret_cast(printf))); ++ ASSERT_FALSE(dumper.FindMapping(NULL)); ++} ++ ++TEST(LinuxDumperTest, ThreadList) { ++ LinuxDumper dumper(getpid()); ++ ASSERT_TRUE(dumper.Init()); ++ ++ ASSERT_GE(dumper.threads().size(), 1); ++ bool found = false; ++ for (size_t i = 0; i < dumper.threads().size(); ++i) { ++ if (dumper.threads()[i] == getpid()) { ++ found = true; ++ break; ++ } ++ } ++} ++ ++TEST(LinuxDumperTest, BuildProcPath) { ++ const pid_t pid = getpid(); ++ LinuxDumper dumper(pid); ++ ++ char maps_path[256] = "dummymappath"; ++ char maps_path_expected[256]; ++ snprintf(maps_path_expected, sizeof(maps_path_expected), ++ "/proc/%d/maps", pid); ++ dumper.BuildProcPath(maps_path, pid, "maps"); ++ ASSERT_STREQ(maps_path, maps_path_expected); ++ ++ // In release mode, we expect BuildProcPath to handle the invalid ++ // parameters correctly and fill map_path with an empty ++ // NULL-terminated string. ++#ifdef NDEBUG ++ snprintf(maps_path, sizeof(maps_path), "dummymappath"); ++ dumper.BuildProcPath(maps_path, 0, "maps"); ++ EXPECT_STREQ(maps_path, ""); ++ ++ snprintf(maps_path, sizeof(maps_path), "dummymappath"); ++ dumper.BuildProcPath(maps_path, getpid(), ""); ++ EXPECT_STREQ(maps_path, ""); ++ ++ snprintf(maps_path, sizeof(maps_path), "dummymappath"); ++ dumper.BuildProcPath(maps_path, getpid(), NULL); ++ EXPECT_STREQ(maps_path, ""); ++#endif ++} ++ ++TEST(LinuxDumperTest, MappingsIncludeLinuxGate) { ++ LinuxDumper dumper(getpid()); ++ ASSERT_TRUE(dumper.Init()); ++ ++ void* linux_gate_loc = dumper.FindBeginningOfLinuxGateSharedLibrary(getpid()); ++ if (linux_gate_loc) { ++ bool found_linux_gate = false; ++ ++ const wasteful_vector mappings = dumper.mappings(); ++ const MappingInfo* mapping; ++ for (unsigned i = 0; i < mappings.size(); ++i) { ++ mapping = mappings[i]; ++ if (!strcmp(mapping->name, kLinuxGateLibraryName)) { ++ found_linux_gate = true; ++ break; ++ } ++ } ++ EXPECT_TRUE(found_linux_gate); ++ EXPECT_EQ(linux_gate_loc, reinterpret_cast(mapping->start_addr)); ++ EXPECT_EQ(0, memcmp(linux_gate_loc, ELFMAG, SELFMAG)); ++ } ++} ++ ++TEST(LinuxDumperTest, FileIDsMatch) { ++ // Calculate the File ID of our binary using both ++ // FileID::ElfFileIdentifier and LinuxDumper::ElfFileIdentifierForMapping ++ // and ensure that we get the same result from both. ++ char exe_name[PATH_MAX]; ++ ssize_t len = readlink("/proc/self/exe", exe_name, PATH_MAX - 1); ++ ASSERT_NE(len, -1); ++ exe_name[len] = '\0'; ++ ++ int fds[2]; ++ ASSERT_NE(-1, pipe(fds)); ++ ++ // fork a child so we can ptrace it ++ const pid_t child = fork(); ++ if (child == 0) { ++ close(fds[1]); ++ // now wait forever for the parent ++ char b; ++ HANDLE_EINTR(read(fds[0], &b, sizeof(b))); ++ close(fds[0]); ++ syscall(__NR_exit); ++ } ++ close(fds[0]); ++ ++ LinuxDumper dumper(child); ++ ASSERT_TRUE(dumper.Init()); ++ const wasteful_vector mappings = dumper.mappings(); ++ bool found_exe = false; ++ unsigned i; ++ for (i = 0; i < mappings.size(); ++i) { ++ const MappingInfo* mapping = mappings[i]; ++ if (!strcmp(mapping->name, exe_name)) { ++ found_exe = true; ++ break; ++ } ++ } ++ ASSERT_TRUE(found_exe); ++ ++ uint8_t identifier1[sizeof(MDGUID)]; ++ uint8_t identifier2[sizeof(MDGUID)]; ++ EXPECT_TRUE(dumper.ElfFileIdentifierForMapping(i, identifier1)); ++ FileID fileid(exe_name); ++ EXPECT_TRUE(fileid.ElfFileIdentifier(identifier2)); ++ char identifier_string1[37]; ++ char identifier_string2[37]; ++ FileID::ConvertIdentifierToString(identifier1, identifier_string1, ++ 37); ++ FileID::ConvertIdentifierToString(identifier2, identifier_string2, ++ 37); ++ EXPECT_STREQ(identifier_string1, identifier_string2); ++ close(fds[1]); ++} +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/minidump_writer.cc b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/minidump_writer.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/minidump_writer.cc +@@ -0,0 +1,857 @@ ++// Copyright (c) 2009, 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. ++ ++// This code writes out minidump files: ++// http://msdn.microsoft.com/en-us/library/ms680378(VS.85,loband).aspx ++// ++// Minidumps are a Microsoft format which Breakpad uses for recording crash ++// dumps. This code has to run in a compromised environment (the address space ++// may have received SIGSEGV), thus the following rules apply: ++// * You may not enter the dynamic linker. This means that we cannot call ++// any symbols in a shared library (inc libc). Because of this we replace ++// libc functions in linux_libc_support.h. ++// * You may not call syscalls via the libc wrappers. This rule is a subset ++// of the first rule but it bears repeating. We have direct wrappers ++// around the system calls in linux_syscall_support.h. ++// * You may not malloc. There's an alternative allocator in memory.h and ++// a canonical instance in the LinuxDumper object. We use the placement ++// new form to allocate objects and we don't delete them. ++ ++#include "client/linux/minidump_writer/minidump_writer.h" ++#include "client/minidump_file_writer-inl.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "client/minidump_file_writer.h" ++#include "google_breakpad/common/minidump_format.h" ++#include "google_breakpad/common/minidump_cpu_amd64.h" ++#include "google_breakpad/common/minidump_cpu_x86.h" ++ ++#include "client/linux/handler/exception_handler.h" ++#include "client/linux/minidump_writer/line_reader.h" ++#include "client/linux/minidump_writer//linux_dumper.h" ++#include "common/linux/linux_libc_support.h" ++#include "common/linux/linux_syscall_support.h" ++ ++// These are additional minidump stream values which are specific to the linux ++// breakpad implementation. ++enum { ++ MD_LINUX_CPU_INFO = 0x47670003, /* /proc/cpuinfo */ ++ MD_LINUX_PROC_STATUS = 0x47670004, /* /proc/$x/status */ ++ MD_LINUX_LSB_RELEASE = 0x47670005, /* /etc/lsb-release */ ++ MD_LINUX_CMD_LINE = 0x47670006, /* /proc/$x/cmdline */ ++ MD_LINUX_ENVIRON = 0x47670007, /* /proc/$x/environ */ ++ MD_LINUX_AUXV = 0x47670008 /* /proc/$x/auxv */ ++}; ++ ++// Minidump defines register structures which are different from the raw ++// structures which we get from the kernel. These are platform specific ++// functions to juggle the ucontext and user structures into minidump format. ++#if defined(__i386) ++typedef MDRawContextX86 RawContextCPU; ++ ++// Write a uint16_t to memory ++// out: memory location to write to ++// v: value to write. ++static void U16(void* out, uint16_t v) { ++ memcpy(out, &v, sizeof(v)); ++} ++ ++// Write a uint32_t to memory ++// out: memory location to write to ++// v: value to write. ++static void U32(void* out, uint32_t v) { ++ memcpy(out, &v, sizeof(v)); ++} ++ ++// Juggle an x86 user_(fp|fpx|)regs_struct into minidump format ++// out: the minidump structure ++// info: the collection of register structures. ++static void CPUFillFromThreadInfo(MDRawContextX86 *out, ++ const google_breakpad::ThreadInfo &info) { ++ out->context_flags = MD_CONTEXT_X86_ALL; ++ ++ out->dr0 = info.dregs[0]; ++ out->dr1 = info.dregs[1]; ++ out->dr2 = info.dregs[2]; ++ out->dr3 = info.dregs[3]; ++ // 4 and 5 deliberatly omitted because they aren't included in the minidump ++ // format. ++ out->dr6 = info.dregs[6]; ++ out->dr7 = info.dregs[7]; ++ ++ out->gs = info.regs.xgs; ++ out->fs = info.regs.xfs; ++ out->es = info.regs.xes; ++ out->ds = info.regs.xds; ++ ++ out->edi = info.regs.edi; ++ out->esi = info.regs.esi; ++ out->ebx = info.regs.ebx; ++ out->edx = info.regs.edx; ++ out->ecx = info.regs.ecx; ++ out->eax = info.regs.eax; ++ ++ out->ebp = info.regs.ebp; ++ out->eip = info.regs.eip; ++ out->cs = info.regs.xcs; ++ out->eflags = info.regs.eflags; ++ out->esp = info.regs.esp; ++ out->ss = info.regs.xss; ++ ++ out->float_save.control_word = info.fpregs.cwd; ++ out->float_save.status_word = info.fpregs.swd; ++ out->float_save.tag_word = info.fpregs.twd; ++ out->float_save.error_offset = info.fpregs.fip; ++ out->float_save.error_selector = info.fpregs.fcs; ++ out->float_save.data_offset = info.fpregs.foo; ++ out->float_save.data_selector = info.fpregs.fos; ++ ++ // 8 registers * 10 bytes per register. ++ memcpy(out->float_save.register_area, info.fpregs.st_space, 10 * 8); ++ ++ // This matches the Intel fpsave format. ++ U16(out->extended_registers + 0, info.fpregs.cwd); ++ U16(out->extended_registers + 2, info.fpregs.swd); ++ U16(out->extended_registers + 4, info.fpregs.twd); ++ U16(out->extended_registers + 6, info.fpxregs.fop); ++ U32(out->extended_registers + 8, info.fpxregs.fip); ++ U16(out->extended_registers + 12, info.fpxregs.fcs); ++ U32(out->extended_registers + 16, info.fpregs.foo); ++ U16(out->extended_registers + 20, info.fpregs.fos); ++ U32(out->extended_registers + 24, info.fpxregs.mxcsr); ++ ++ memcpy(out->extended_registers + 32, &info.fpxregs.st_space, 128); ++ memcpy(out->extended_registers + 160, &info.fpxregs.xmm_space, 128); ++} ++ ++// Juggle an x86 ucontext into minidump format ++// out: the minidump structure ++// info: the collection of register structures. ++static void CPUFillFromUContext(MDRawContextX86 *out, const ucontext *uc, ++ const struct _libc_fpstate* fp) { ++ const greg_t* regs = uc->uc_mcontext.gregs; ++ ++ out->context_flags = MD_CONTEXT_X86_FULL | ++ MD_CONTEXT_X86_FLOATING_POINT; ++ ++ out->gs = regs[REG_GS]; ++ out->fs = regs[REG_FS]; ++ out->es = regs[REG_ES]; ++ out->ds = regs[REG_DS]; ++ ++ out->edi = regs[REG_EDI]; ++ out->esi = regs[REG_ESI]; ++ out->ebx = regs[REG_EBX]; ++ out->edx = regs[REG_EDX]; ++ out->ecx = regs[REG_ECX]; ++ out->eax = regs[REG_EAX]; ++ ++ out->ebp = regs[REG_EBP]; ++ out->eip = regs[REG_EIP]; ++ out->cs = regs[REG_CS]; ++ out->eflags = regs[REG_EFL]; ++ out->esp = regs[REG_UESP]; ++ out->ss = regs[REG_SS]; ++ ++ out->float_save.control_word = fp->cw; ++ out->float_save.status_word = fp->sw; ++ out->float_save.tag_word = fp->tag; ++ out->float_save.error_offset = fp->ipoff; ++ out->float_save.error_selector = fp->cssel; ++ out->float_save.data_offset = fp->dataoff; ++ out->float_save.data_selector = fp->datasel; ++ ++ // 8 registers * 10 bytes per register. ++ memcpy(out->float_save.register_area, fp->_st, 10 * 8); ++} ++ ++#elif defined(__x86_64) ++typedef MDRawContextAMD64 RawContextCPU; ++ ++static void CPUFillFromThreadInfo(MDRawContextAMD64 *out, ++ const google_breakpad::ThreadInfo &info) { ++ out->context_flags = MD_CONTEXT_AMD64_FULL | ++ MD_CONTEXT_AMD64_SEGMENTS; ++ ++ out->cs = info.regs.cs; ++ ++ out->ds = info.regs.ds; ++ out->es = info.regs.es; ++ out->fs = info.regs.fs; ++ out->gs = info.regs.gs; ++ ++ out->ss = info.regs.ss; ++ out->eflags = info.regs.eflags; ++ ++ out->dr0 = info.dregs[0]; ++ out->dr1 = info.dregs[1]; ++ out->dr2 = info.dregs[2]; ++ out->dr3 = info.dregs[3]; ++ // 4 and 5 deliberatly omitted because they aren't included in the minidump ++ // format. ++ out->dr6 = info.dregs[6]; ++ out->dr7 = info.dregs[7]; ++ ++ out->rax = info.regs.rax; ++ out->rcx = info.regs.rcx; ++ out->rdx = info.regs.rdx; ++ out->rbx = info.regs.rbx; ++ ++ out->rsp = info.regs.rsp; ++ ++ out->rbp = info.regs.rbp; ++ out->rsi = info.regs.rsi; ++ out->rdi = info.regs.rdi; ++ out->r8 = info.regs.r8; ++ out->r9 = info.regs.r9; ++ out->r10 = info.regs.r10; ++ out->r11 = info.regs.r11; ++ out->r12 = info.regs.r12; ++ out->r13 = info.regs.r13; ++ out->r14 = info.regs.r14; ++ out->r15 = info.regs.r15; ++ ++ out->rip = info.regs.rip; ++ ++ out->flt_save.control_word = info.fpregs.cwd; ++ out->flt_save.status_word = info.fpregs.swd; ++ out->flt_save.tag_word = info.fpregs.ftw; ++ out->flt_save.error_opcode = info.fpregs.fop; ++ out->flt_save.error_offset = info.fpregs.rip; ++ out->flt_save.error_selector = 0; // We don't have this. ++ out->flt_save.data_offset = info.fpregs.rdp; ++ out->flt_save.data_selector = 0; // We don't have this. ++ out->flt_save.mx_csr = info.fpregs.mxcsr; ++ out->flt_save.mx_csr_mask = info.fpregs.mxcr_mask; ++ memcpy(&out->flt_save.float_registers, &info.fpregs.st_space, 8 * 16); ++ memcpy(&out->flt_save.xmm_registers, &info.fpregs.xmm_space, 16 * 16); ++} ++ ++static void CPUFillFromUContext(MDRawContextAMD64 *out, const ucontext *uc, ++ const struct _libc_fpstate* fpregs) { ++ const greg_t* regs = uc->uc_mcontext.gregs; ++ ++ out->context_flags = MD_CONTEXT_AMD64_FULL; ++ ++ out->cs = regs[REG_CSGSFS] & 0xffff; ++ ++ out->fs = (regs[REG_CSGSFS] >> 32) & 0xffff; ++ out->gs = (regs[REG_CSGSFS] >> 16) & 0xffff; ++ ++ out->eflags = regs[REG_EFL]; ++ ++ out->rax = regs[REG_RAX]; ++ out->rcx = regs[REG_RCX]; ++ out->rdx = regs[REG_RDX]; ++ out->rbx = regs[REG_RBX]; ++ ++ out->rsp = regs[REG_RSP]; ++ out->rbp = regs[REG_RBP]; ++ out->rsi = regs[REG_RSI]; ++ out->rdi = regs[REG_RDI]; ++ out->r8 = regs[REG_R8]; ++ out->r9 = regs[REG_R9]; ++ out->r10 = regs[REG_R10]; ++ out->r11 = regs[REG_R11]; ++ out->r12 = regs[REG_R12]; ++ out->r13 = regs[REG_R13]; ++ out->r14 = regs[REG_R14]; ++ out->r15 = regs[REG_R15]; ++ ++ out->rip = regs[REG_RIP]; ++ ++ out->flt_save.control_word = fpregs->cwd; ++ out->flt_save.status_word = fpregs->swd; ++ out->flt_save.tag_word = fpregs->ftw; ++ out->flt_save.error_opcode = fpregs->fop; ++ out->flt_save.error_offset = fpregs->rip; ++ out->flt_save.data_offset = fpregs->rdp; ++ out->flt_save.error_selector = 0; // We don't have this. ++ out->flt_save.data_selector = 0; // We don't have this. ++ out->flt_save.mx_csr = fpregs->mxcsr; ++ out->flt_save.mx_csr_mask = fpregs->mxcr_mask; ++ memcpy(&out->flt_save.float_registers, &fpregs->_st, 8 * 16); ++ memcpy(&out->flt_save.xmm_registers, &fpregs->_xmm, 16 * 16); ++} ++ ++#else ++#error "This code has not been ported to your platform yet." ++#endif ++ ++namespace google_breakpad { ++ ++class MinidumpWriter { ++ public: ++ MinidumpWriter(const char* filename, ++ pid_t crashing_pid, ++ const ExceptionHandler::CrashContext* context) ++ : filename_(filename), ++ siginfo_(&context->siginfo), ++ ucontext_(&context->context), ++ float_state_(&context->float_state), ++ crashing_tid_(context->tid), ++ dumper_(crashing_pid) { ++ } ++ ++ bool Init() { ++ return dumper_.Init() && minidump_writer_.Open(filename_) && ++ dumper_.ThreadsSuspend(); ++ } ++ ++ ~MinidumpWriter() { ++ minidump_writer_.Close(); ++ dumper_.ThreadsResume(); ++ } ++ ++ bool Dump() { ++ // A minidump file contains a number of tagged streams. This is the number ++ // of stream which we write. ++ static const unsigned kNumWriters = 11; ++ ++ TypedMDRVA header(&minidump_writer_); ++ TypedMDRVA dir(&minidump_writer_); ++ if (!header.Allocate()) ++ return false; ++ if (!dir.AllocateArray(kNumWriters)) ++ return false; ++ memset(header.get(), 0, sizeof(MDRawHeader)); ++ ++ header.get()->signature = MD_HEADER_SIGNATURE; ++ header.get()->version = MD_HEADER_VERSION; ++ header.get()->time_date_stamp = time(NULL); ++ header.get()->stream_count = kNumWriters; ++ header.get()->stream_directory_rva = dir.position(); ++ ++ unsigned dir_index = 0; ++ MDRawDirectory dirent; ++ ++ if (!WriteThreadListStream(&dirent)) ++ return false; ++ dir.CopyIndex(dir_index++, &dirent); ++ ++ if (!WriteMappings(&dirent)) ++ return false; ++ dir.CopyIndex(dir_index++, &dirent); ++ ++ if (!WriteExceptionStream(&dirent)) ++ return false; ++ dir.CopyIndex(dir_index++, &dirent); ++ ++ if (!WriteSystemInfoStream(&dirent)) ++ return false; ++ dir.CopyIndex(dir_index++, &dirent); ++ ++ dirent.stream_type = MD_LINUX_CPU_INFO; ++ if (!WriteFile(&dirent.location, "/proc/cpuinfo")) ++ NullifyDirectoryEntry(&dirent); ++ dir.CopyIndex(dir_index++, &dirent); ++ ++ dirent.stream_type = MD_LINUX_PROC_STATUS; ++ if (!WriteProcFile(&dirent.location, crashing_tid_, "status")) ++ NullifyDirectoryEntry(&dirent); ++ dir.CopyIndex(dir_index++, &dirent); ++ ++ dirent.stream_type = MD_LINUX_LSB_RELEASE; ++ if (!WriteFile(&dirent.location, "/etc/lsb-release")) ++ NullifyDirectoryEntry(&dirent); ++ dir.CopyIndex(dir_index++, &dirent); ++ ++ dirent.stream_type = MD_LINUX_CMD_LINE; ++ if (!WriteProcFile(&dirent.location, crashing_tid_, "cmdline")) ++ NullifyDirectoryEntry(&dirent); ++ dir.CopyIndex(dir_index++, &dirent); ++ ++ dirent.stream_type = MD_LINUX_ENVIRON; ++ if (!WriteProcFile(&dirent.location, crashing_tid_, "environ")) ++ NullifyDirectoryEntry(&dirent); ++ dir.CopyIndex(dir_index++, &dirent); ++ ++ dirent.stream_type = MD_LINUX_AUXV; ++ if (!WriteProcFile(&dirent.location, crashing_tid_, "auxv")) ++ NullifyDirectoryEntry(&dirent); ++ dir.CopyIndex(dir_index++, &dirent); ++ ++ dirent.stream_type = MD_LINUX_AUXV; ++ if (!WriteProcFile(&dirent.location, crashing_tid_, "maps")) ++ NullifyDirectoryEntry(&dirent); ++ dir.CopyIndex(dir_index++, &dirent); ++ ++ // If you add more directory entries, don't forget to update kNumWriters, ++ // above. ++ ++ dumper_.ThreadsResume(); ++ return true; ++ } ++ ++ // Write information about the threads. ++ bool WriteThreadListStream(MDRawDirectory* dirent) { ++ const unsigned num_threads = dumper_.threads().size(); ++ ++ TypedMDRVA list(&minidump_writer_); ++ if (!list.AllocateObjectAndArray(num_threads, sizeof(MDRawThread))) ++ return false; ++ ++ dirent->stream_type = MD_THREAD_LIST_STREAM; ++ dirent->location = list.location(); ++ ++ *list.get() = num_threads; ++ ++ for (unsigned i = 0; i < num_threads; ++i) { ++ MDRawThread thread; ++ my_memset(&thread, 0, sizeof(thread)); ++ thread.thread_id = dumper_.threads()[i]; ++ // We have a different source of information for the crashing thread. If ++ // we used the actual state of the thread we would find it running in the ++ // signal handler with the alternative stack, which would be deeply ++ // unhelpful. ++ if ((pid_t)thread.thread_id == crashing_tid_) { ++ const void* stack; ++ size_t stack_len; ++ if (!dumper_.GetStackInfo(&stack, &stack_len, GetStackPointer())) ++ return false; ++ UntypedMDRVA memory(&minidump_writer_); ++ if (!memory.Allocate(stack_len)) ++ return false; ++ uint8_t* stack_copy = (uint8_t*) dumper_.allocator()->Alloc(stack_len); ++ dumper_.CopyFromProcess(stack_copy, thread.thread_id, stack, stack_len); ++ memory.Copy(stack_copy, stack_len); ++ thread.stack.start_of_memory_range = (uintptr_t) (stack); ++ thread.stack.memory = memory.location(); ++ TypedMDRVA cpu(&minidump_writer_); ++ if (!cpu.Allocate()) ++ return false; ++ my_memset(cpu.get(), 0, sizeof(RawContextCPU)); ++ CPUFillFromUContext(cpu.get(), ucontext_, float_state_); ++ thread.thread_context = cpu.location(); ++ crashing_thread_context_ = cpu.location(); ++ } else { ++ ThreadInfo info; ++ if (!dumper_.ThreadInfoGet(dumper_.threads()[i], &info)) ++ return false; ++ UntypedMDRVA memory(&minidump_writer_); ++ if (!memory.Allocate(info.stack_len)) ++ return false; ++ uint8_t* stack_copy = ++ (uint8_t*) dumper_.allocator()->Alloc(info.stack_len); ++ dumper_.CopyFromProcess(stack_copy, thread.thread_id, info.stack, ++ info.stack_len); ++ memory.Copy(stack_copy, info.stack_len); ++ thread.stack.start_of_memory_range = (uintptr_t)(info.stack); ++ thread.stack.memory = memory.location(); ++ TypedMDRVA cpu(&minidump_writer_); ++ if (!cpu.Allocate()) ++ return false; ++ my_memset(cpu.get(), 0, sizeof(RawContextCPU)); ++ CPUFillFromThreadInfo(cpu.get(), info); ++ thread.thread_context = cpu.location(); ++ } ++ ++ list.CopyIndexAfterObject(i, &thread, sizeof(thread)); ++ } ++ ++ return true; ++ } ++ ++ static bool ShouldIncludeMapping(const MappingInfo& mapping) { ++ if (mapping.name[0] == 0 || // we only want modules with filenames. ++ mapping.offset || // we only want to include one mapping per shared lib. ++ mapping.size < 4096) { // too small to get a signature for. ++ return false; ++ } ++ ++ return true; ++ } ++ ++ // Write information about the mappings in effect. Because we are using the ++ // minidump format, the information about the mappings is pretty limited. ++ // Because of this, we also include the full, unparsed, /proc/$x/maps file in ++ // another stream in the file. ++ bool WriteMappings(MDRawDirectory* dirent) { ++ const unsigned num_mappings = dumper_.mappings().size(); ++ unsigned num_output_mappings = 0; ++ ++ for (unsigned i = 0; i < dumper_.mappings().size(); ++i) { ++ const MappingInfo& mapping = *dumper_.mappings()[i]; ++ if (ShouldIncludeMapping(mapping)) ++ num_output_mappings++; ++ } ++ ++ TypedMDRVA list(&minidump_writer_); ++ if (!list.AllocateObjectAndArray(num_output_mappings, MD_MODULE_SIZE)) ++ return false; ++ ++ dirent->stream_type = MD_MODULE_LIST_STREAM; ++ dirent->location = list.location(); ++ *list.get() = num_output_mappings; ++ ++ for (unsigned i = 0, j = 0; i < num_mappings; ++i) { ++ const MappingInfo& mapping = *dumper_.mappings()[i]; ++ if (!ShouldIncludeMapping(mapping)) ++ continue; ++ ++ MDRawModule mod; ++ my_memset(&mod, 0, MD_MODULE_SIZE); ++ mod.base_of_image = mapping.start_addr; ++ mod.size_of_image = mapping.size; ++ const size_t filepath_len = my_strlen(mapping.name); ++ ++ // Figure out file name from path ++ const char* filename_ptr = mapping.name + filepath_len - 1; ++ while (filename_ptr >= mapping.name) { ++ if (*filename_ptr == '/') ++ break; ++ filename_ptr--; ++ } ++ filename_ptr++; ++ const size_t filename_len = mapping.name + filepath_len - filename_ptr; ++ ++ uint8_t cv_buf[MDCVInfoPDB70_minsize + NAME_MAX]; ++ uint8_t* cv_ptr = cv_buf; ++ UntypedMDRVA cv(&minidump_writer_); ++ if (!cv.Allocate(MDCVInfoPDB70_minsize + filename_len + 1)) ++ return false; ++ ++ const uint32_t cv_signature = MD_CVINFOPDB70_SIGNATURE; ++ memcpy(cv_ptr, &cv_signature, sizeof(cv_signature)); ++ cv_ptr += sizeof(cv_signature); ++ uint8_t* signature = cv_ptr; ++ cv_ptr += sizeof(MDGUID); ++ dumper_.ElfFileIdentifierForMapping(i, signature); ++ my_memset(cv_ptr, 0, sizeof(uint32_t)); // Set age to 0 on Linux. ++ cv_ptr += sizeof(uint32_t); ++ ++ // Write pdb_file_name ++ memcpy(cv_ptr, filename_ptr, filename_len + 1); ++ cv.Copy(cv_buf, MDCVInfoPDB70_minsize + filename_len + 1); ++ ++ mod.cv_record = cv.location(); ++ ++ MDLocationDescriptor ld; ++ if (!minidump_writer_.WriteString(mapping.name, filepath_len, &ld)) ++ return false; ++ mod.module_name_rva = ld.rva; ++ ++ list.CopyIndexAfterObject(j++, &mod, MD_MODULE_SIZE); ++ } ++ ++ return true; ++ } ++ ++ bool WriteExceptionStream(MDRawDirectory* dirent) { ++ TypedMDRVA exc(&minidump_writer_); ++ if (!exc.Allocate()) ++ return false; ++ my_memset(exc.get(), 0, sizeof(MDRawExceptionStream)); ++ ++ dirent->stream_type = MD_EXCEPTION_STREAM; ++ dirent->location = exc.location(); ++ ++ exc.get()->thread_id = crashing_tid_; ++ exc.get()->exception_record.exception_code = siginfo_->si_signo; ++ exc.get()->exception_record.exception_address = ++ (uintptr_t) siginfo_->si_addr; ++ exc.get()->thread_context = crashing_thread_context_; ++ ++ return true; ++ } ++ ++ bool WriteSystemInfoStream(MDRawDirectory* dirent) { ++ TypedMDRVA si(&minidump_writer_); ++ if (!si.Allocate()) ++ return false; ++ my_memset(si.get(), 0, sizeof(MDRawSystemInfo)); ++ ++ dirent->stream_type = MD_SYSTEM_INFO_STREAM; ++ dirent->location = si.location(); ++ ++ WriteCPUInformation(si.get()); ++ WriteOSInformation(si.get()); ++ ++ return true; ++ } ++ ++ private: ++#if defined(__i386) ++ uintptr_t GetStackPointer() { ++ return ucontext_->uc_mcontext.gregs[REG_ESP]; ++ } ++#elif defined(__x86_64) ++ uintptr_t GetStackPointer() { ++ return ucontext_->uc_mcontext.gregs[REG_RSP]; ++ } ++#else ++#error "This code has not been ported to your platform yet." ++#endif ++ ++ void NullifyDirectoryEntry(MDRawDirectory* dirent) { ++ dirent->stream_type = 0; ++ dirent->location.data_size = 0; ++ dirent->location.rva = 0; ++ } ++ ++ bool WriteCPUInformation(MDRawSystemInfo* sys_info) { ++ char vendor_id[sizeof(sys_info->cpu.x86_cpu_info.vendor_id) + 1] = {0}; ++ static const char vendor_id_name[] = "vendor_id"; ++ static const size_t vendor_id_name_length = sizeof(vendor_id_name) - 1; ++ ++ struct CpuInfoEntry { ++ const char* info_name; ++ int value; ++ bool found; ++ } cpu_info_table[] = { ++ { "processor", -1, false }, ++ { "model", 0, false }, ++ { "stepping", 0, false }, ++ { "cpu family", 0, false }, ++ }; ++ ++ // processor_architecture should always be set, do this first ++ sys_info->processor_architecture = ++#if defined(__i386) ++ MD_CPU_ARCHITECTURE_X86; ++#elif defined(__x86_64) ++ MD_CPU_ARCHITECTURE_AMD64; ++#else ++#error "Unknown CPU arch" ++#endif ++ ++ const int fd = sys_open("/proc/cpuinfo", O_RDONLY, 0); ++ if (fd < 0) ++ return false; ++ ++ { ++ PageAllocator allocator; ++ LineReader* const line_reader = new(allocator) LineReader(fd); ++ const char* line; ++ unsigned line_len; ++ while (line_reader->GetNextLine(&line, &line_len)) { ++ for (size_t i = 0; ++ i < sizeof(cpu_info_table) / sizeof(cpu_info_table[0]); ++ i++) { ++ CpuInfoEntry* entry = &cpu_info_table[i]; ++ if (entry->found) ++ continue; ++ if (!strncmp(line, entry->info_name, strlen(entry->info_name))) { ++ const char* value = strchr(line, ':'); ++ if (!value) ++ continue; ++ ++ // the above strncmp only matches the prefix, it might be the wrong ++ // line. i.e. we matched "model name" instead of "model". ++ // check and make sure there is only spaces between the prefix and ++ // the colon. ++ const char* space_ptr = line + strlen(entry->info_name); ++ for (; space_ptr < value; space_ptr++) { ++ if (!isspace(*space_ptr)) { ++ break; ++ } ++ } ++ if (space_ptr != value) ++ continue; ++ ++ sscanf(++value, " %d", &(entry->value)); ++ entry->found = true; ++ } ++ } ++ ++ // special case for vendor_id ++ if (!strncmp(line, vendor_id_name, vendor_id_name_length)) { ++ const char* value = strchr(line, ':'); ++ if (!value) ++ goto popline; ++ ++ // skip ':" and all the spaces that follows ++ do { ++ value++; ++ } while (isspace(*value)); ++ ++ if (*value) { ++ size_t length = strlen(value); ++ if (length == 0) ++ goto popline; ++ // we don't want the trailing newline ++ if (value[length - 1] == '\n') ++ length--; ++ // ensure we have space for the value ++ if (length < sizeof(vendor_id)) ++ strncpy(vendor_id, value, length); ++ } ++ } ++ ++popline: ++ line_reader->PopLine(line_len); ++ } ++ sys_close(fd); ++ } ++ ++ // make sure we got everything we wanted ++ for (size_t i = 0; ++ i < sizeof(cpu_info_table) / sizeof(cpu_info_table[0]); ++ i++) { ++ if (!cpu_info_table[i].found) { ++ return false; ++ } ++ } ++ // /proc/cpuinfo contains cpu id, change it into number by adding one. ++ cpu_info_table[0].value++; ++ ++ sys_info->number_of_processors = cpu_info_table[0].value; ++ sys_info->processor_level = cpu_info_table[3].value; ++ sys_info->processor_revision = cpu_info_table[1].value << 8 | ++ cpu_info_table[2].value; ++ ++ if (vendor_id[0] != '\0') { ++ memcpy(sys_info->cpu.x86_cpu_info.vendor_id, vendor_id, ++ sizeof(sys_info->cpu.x86_cpu_info.vendor_id)); ++ } ++ return true; ++ } ++ ++ bool WriteFile(MDLocationDescriptor* result, const char* filename) { ++ const int fd = sys_open(filename, O_RDONLY, 0); ++ if (fd < 0) ++ return false; ++ ++ // We can't stat the files because several of the files that we want to ++ // read are kernel seqfiles, which always have a length of zero. So we have ++ // to read as much as we can into a buffer. ++ static const unsigned kMaxFileSize = 1024; ++ uint8_t* data = (uint8_t*) dumper_.allocator()->Alloc(kMaxFileSize); ++ ++ size_t done = 0; ++ while (done < kMaxFileSize) { ++ ssize_t r; ++ do { ++ r = sys_read(fd, data + done, kMaxFileSize - done); ++ } while (r == -1 && errno == EINTR); ++ ++ if (r < 1) ++ break; ++ done += r; ++ } ++ sys_close(fd); ++ ++ if (!done) ++ return false; ++ ++ UntypedMDRVA memory(&minidump_writer_); ++ if (!memory.Allocate(done)) ++ return false; ++ memory.Copy(data, done); ++ *result = memory.location(); ++ return true; ++ } ++ ++ bool WriteOSInformation(MDRawSystemInfo* sys_info) { ++ sys_info->platform_id = MD_OS_LINUX; ++ ++ struct utsname uts; ++ if (uname(&uts)) ++ return false; ++ ++ static const size_t buf_len = 512; ++ char buf[buf_len] = {0}; ++ size_t space_left = buf_len - 1; ++ const char* info_table[] = { ++ uts.sysname, ++ uts.release, ++ uts.version, ++ uts.machine, ++ NULL ++ }; ++ bool first_item = true; ++ for (const char** cur_info = info_table; *cur_info; cur_info++) { ++ static const char* separator = " "; ++ size_t separator_len = strlen(separator); ++ size_t info_len = strlen(*cur_info); ++ if (info_len == 0) ++ continue; ++ ++ if (space_left < info_len + (first_item ? 0 : separator_len)) ++ break; ++ ++ if (!first_item) { ++ strcat(buf, separator); ++ space_left -= separator_len; ++ } ++ ++ first_item = false; ++ strcat(buf, *cur_info); ++ space_left -= info_len; ++ } ++ ++ MDLocationDescriptor location; ++ if (!minidump_writer_.WriteString(buf, 0, &location)) ++ return false; ++ sys_info->csd_version_rva = location.rva; ++ ++ return true; ++ } ++ ++ bool WriteProcFile(MDLocationDescriptor* result, pid_t pid, ++ const char* filename) { ++ char buf[80]; ++ memcpy(buf, "/proc/", 6); ++ const unsigned pid_len = my_int_len(pid); ++ my_itos(buf + 6, pid, pid_len); ++ buf[6 + pid_len] = '/'; ++ memcpy(buf + 6 + pid_len + 1, filename, my_strlen(filename) + 1); ++ return WriteFile(result, buf); ++ } ++ ++ const char* const filename_; // output filename ++ const siginfo_t* const siginfo_; // from the signal handler (see sigaction) ++ const struct ucontext* const ucontext_; // also from the signal handler ++ const struct _libc_fpstate* const float_state_; // ditto ++ const pid_t crashing_tid_; // the process which actually crashed ++ LinuxDumper dumper_; ++ MinidumpFileWriter minidump_writer_; ++ MDLocationDescriptor crashing_thread_context_; ++}; ++ ++bool WriteMinidump(const char* filename, pid_t crashing_process, ++ const void* blob, size_t blob_size) { ++ if (blob_size != sizeof(ExceptionHandler::CrashContext)) ++ return false; ++ const ExceptionHandler::CrashContext* context = ++ reinterpret_cast(blob); ++ MinidumpWriter writer(filename, crashing_process, context); ++ if (!writer.Init()) ++ return false; ++ return writer.Dump(); ++} ++ ++} // namespace google_breakpad +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/minidump_writer.h b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/minidump_writer.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/minidump_writer.h +@@ -0,0 +1,53 @@ ++// Copyright (c) 2009, 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 CLIENT_LINUX_MINIDUMP_WRITER_MINIDUMP_WRITER_H_ ++#define CLIENT_LINUX_MINIDUMP_WRITER_MINIDUMP_WRITER_H_ ++ ++#include ++#include ++ ++namespace google_breakpad { ++ ++// Write a minidump to the filesystem. This function does not malloc nor use ++// libc functions which may. Thus, it can be used in contexts where the state ++// of the heap may be corrupt. ++// filename: the filename to write to. This is opened O_EXCL and fails if ++// open fails. ++// crashing_process: the pid of the crashing process. This must be trusted. ++// blob: a blob of data from the crashing process. See exception_handler.h ++// blob_size: the length of |blob|, in bytes ++// ++// Returns true iff successful. ++bool WriteMinidump(const char* filename, pid_t crashing_process, ++ const void* blob, size_t blob_size); ++ ++} // namespace google_breakpad ++ ++#endif // CLIENT_LINUX_MINIDUMP_WRITER_MINIDUMP_WRITER_H_ +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/minidump_writer_unittest.cc b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/minidump_writer_unittest.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/minidump_writer_unittest.cc +@@ -0,0 +1,79 @@ ++// Copyright (c) 2009, 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 ++#include ++ ++#include "client/linux/handler/exception_handler.h" ++#include "client/linux/minidump_writer/minidump_writer.h" ++#include "breakpad_googletest_includes.h" ++ ++using namespace google_breakpad; ++ ++// This provides a wrapper around system calls which may be ++// interrupted by a signal and return EINTR. See man 7 signal. ++#define HANDLE_EINTR(x) ({ \ ++ typeof(x) __eintr_result__; \ ++ do { \ ++ __eintr_result__ = x; \ ++ } while (__eintr_result__ == -1 && errno == EINTR); \ ++ __eintr_result__;\ ++}) ++ ++namespace { ++typedef testing::Test MinidumpWriterTest; ++} ++ ++TEST(MinidumpWriterTest, Setup) { ++ int fds[2]; ++ ASSERT_NE(-1, pipe(fds)); ++ ++ const pid_t child = fork(); ++ if (child == 0) { ++ close(fds[1]); ++ char b; ++ HANDLE_EINTR(read(fds[0], &b, sizeof(b))); ++ close(fds[0]); ++ syscall(__NR_exit); ++ } ++ close(fds[0]); ++ ++ ExceptionHandler::CrashContext context; ++ memset(&context, 0, sizeof(context)); ++ ++ char templ[] = "/tmp/minidump-writer-unittest-XXXXXX"; ++ mktemp(templ); ++ ASSERT_TRUE(WriteMinidump(templ, child, &context, sizeof(context))); ++ struct stat st; ++ ASSERT_EQ(stat(templ, &st), 0); ++ ASSERT_GT(st.st_size, 0u); ++ unlink(templ); ++ ++ close(fds[1]); ++} +diff --git a/toolkit/crashreporter/google-breakpad/src/client/linux/sender/google_crash_report_sender.cc b/toolkit/crashreporter/google-breakpad/src/client/linux/sender/google_crash_report_sender.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/linux/sender/google_crash_report_sender.cc +@@ -0,0 +1,102 @@ ++// Copyright (c) 2009, 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 "common/linux/google_crashdump_uploader.h" ++#include "third_party/linux/include/glog/logging.h" ++#include "third_party/linux/include/gflags/gflags.h" ++#include ++ ++DEFINE_string(crash_server, "http://clients2.google.com/cr", ++ "The crash server to upload minidumps to."); ++DEFINE_string(product_name, "", ++ "The product name that the minidump corresponds to."); ++DEFINE_string(product_version, "", ++ "The version of the product that produced the minidump."); ++DEFINE_string(client_id, "", ++ "The client GUID"); ++DEFINE_string(minidump_path, "", ++ "The path of the minidump file."); ++DEFINE_string(ptime, "", ++ "The process uptime in milliseconds."); ++DEFINE_string(ctime, "", ++ "The cumulative process uptime in milliseconds."); ++DEFINE_string(email, "", ++ "The user's email address."); ++DEFINE_string(comments, "", ++ "Extra user comments"); ++DEFINE_string(proxy_host, "", ++ "Proxy host"); ++DEFINE_string(proxy_userpasswd, "", ++ "Proxy username/password in user:pass format."); ++ ++ ++bool CheckForRequiredFlagsOrDie() { ++ std::string error_text = ""; ++ if (FLAGS_product_name.empty()) { ++ error_text.append("\nProduct name must be specified."); ++ } ++ ++ if (FLAGS_product_version.empty()) { ++ error_text.append("\nProduct version must be specified."); ++ } ++ ++ if (FLAGS_client_id.empty()) { ++ error_text.append("\nClient ID must be specified."); ++ } ++ ++ if (FLAGS_minidump_path.empty()) { ++ error_text.append("\nMinidump pathname must be specified."); ++ } ++ ++ if (!error_text.empty()) { ++ LOG(ERROR) << error_text; ++ return false; ++ } ++ return true; ++} ++ ++int main(int argc, char *argv[]) { ++ google::InitGoogleLogging(argv[0]); ++ google::ParseCommandLineFlags(&argc, &argv, true); ++ if (!CheckForRequiredFlagsOrDie()) { ++ return 1; ++ } ++ google_breakpad::GoogleCrashdumpUploader g(FLAGS_product_name, ++ FLAGS_product_version, ++ FLAGS_client_id, ++ FLAGS_ptime, ++ FLAGS_ctime, ++ FLAGS_email, ++ FLAGS_comments, ++ FLAGS_minidump_path, ++ FLAGS_crash_server, ++ FLAGS_proxy_host, ++ FLAGS_proxy_userpasswd); ++ g.Upload(); ++} +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/Breakpad.xcodeproj/project.pbxproj b/toolkit/crashreporter/google-breakpad/src/client/mac/Breakpad.xcodeproj/project.pbxproj +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/Breakpad.xcodeproj/project.pbxproj +@@ -0,0 +1,2080 @@ ++// !$*UTF8*$! ++{ ++ archiveVersion = 1; ++ classes = { ++ }; ++ objectVersion = 42; ++ objects = { ++ ++/* Begin PBXAggregateTarget section */ ++ F94585840F782326009A47BF /* All */ = { ++ isa = PBXAggregateTarget; ++ buildConfigurationList = F94585930F78235C009A47BF /* Build configuration list for PBXAggregateTarget "All" */; ++ buildPhases = ( ++ ); ++ dependencies = ( ++ F94585880F78232B009A47BF /* PBXTargetDependency */, ++ F945858A0F78232E009A47BF /* PBXTargetDependency */, ++ F945858C0F782330009A47BF /* PBXTargetDependency */, ++ F945858E0F782333009A47BF /* PBXTargetDependency */, ++ F94585900F782336009A47BF /* PBXTargetDependency */, ++ F93DE3A70F830D1D00608B94 /* PBXTargetDependency */, ++ F95BB8B3101F94D300AA053B /* PBXTargetDependency */, ++ F95BB8B5101F94D300AA053B /* PBXTargetDependency */, ++ F95BB8B7101F94D300AA053B /* PBXTargetDependency */, ++ ); ++ name = All; ++ productName = All; ++ }; ++/* End PBXAggregateTarget section */ ++ ++/* Begin PBXBuildFile section */ ++ 3329D4ED0FA16D820007BBC5 /* Breakpad.nib in Resources */ = {isa = PBXBuildFile; fileRef = 3329D4EC0FA16D820007BBC5 /* Breakpad.nib */; }; ++ 33880C800F9E097100817F82 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 33880C7E0F9E097100817F82 /* InfoPlist.strings */; }; ++ 4084699D0F5D9CF900FDCA37 /* crash_report_sender.icns in Resources */ = {isa = PBXBuildFile; fileRef = 4084699C0F5D9CF900FDCA37 /* crash_report_sender.icns */; }; ++ 8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; }; ++ F91AF5D00FD60393009D8BE2 /* BreakpadFramework_Test.mm in Sources */ = {isa = PBXBuildFile; fileRef = F91AF5CF0FD60393009D8BE2 /* BreakpadFramework_Test.mm */; }; ++ F91AF6210FD60784009D8BE2 /* Breakpad.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* Breakpad.framework */; }; ++ F9286B3A0F7EB25800A4DCC8 /* InspectorMain.mm in Sources */ = {isa = PBXBuildFile; fileRef = F9286B390F7EB25800A4DCC8 /* InspectorMain.mm */; }; ++ F92C53B80ECCE7B3009BE4BA /* Inspector.mm in Sources */ = {isa = PBXBuildFile; fileRef = F92C53B70ECCE7B3009BE4BA /* Inspector.mm */; }; ++ F92C554C0ECCF534009BE4BA /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0867D69BFE84028FC02AAC07 /* Foundation.framework */; }; ++ F92C55D00ECD0064009BE4BA /* Breakpad.h in Headers */ = {isa = PBXBuildFile; fileRef = F92C55CE0ECD0064009BE4BA /* Breakpad.h */; settings = {ATTRIBUTES = (Public, ); }; }; ++ F92C55D10ECD0064009BE4BA /* Breakpad.mm in Sources */ = {isa = PBXBuildFile; fileRef = F92C55CF0ECD0064009BE4BA /* Breakpad.mm */; }; ++ F92C56330ECD0DF1009BE4BA /* OnDemandServer.h in Headers */ = {isa = PBXBuildFile; fileRef = F92C56310ECD0DF1009BE4BA /* OnDemandServer.h */; }; ++ F92C56340ECD0DF1009BE4BA /* OnDemandServer.mm in Sources */ = {isa = PBXBuildFile; fileRef = F92C56320ECD0DF1009BE4BA /* OnDemandServer.mm */; }; ++ F92C563F0ECD10CA009BE4BA /* convert_UTF.c in Sources */ = {isa = PBXBuildFile; fileRef = F92C53870ECCE6C0009BE4BA /* convert_UTF.c */; }; ++ F92C56400ECD10CA009BE4BA /* dynamic_images.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C536B0ECCE3FD009BE4BA /* dynamic_images.cc */; }; ++ F92C56410ECD10CA009BE4BA /* file_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53740ECCE635009BE4BA /* file_id.cc */; }; ++ F92C56420ECD10CA009BE4BA /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C537A0ECCE635009BE4BA /* macho_id.cc */; }; ++ F92C56430ECD10CA009BE4BA /* macho_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C537C0ECCE635009BE4BA /* macho_utilities.cc */; }; ++ F92C56440ECD10CA009BE4BA /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C537E0ECCE635009BE4BA /* macho_walker.cc */; }; ++ F92C56450ECD10CA009BE4BA /* MachIPC.mm in Sources */ = {isa = PBXBuildFile; fileRef = F92C53790ECCE635009BE4BA /* MachIPC.mm */; }; ++ F92C56460ECD10CA009BE4BA /* minidump_file_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C538F0ECCE70A009BE4BA /* minidump_file_writer.cc */; }; ++ F92C56470ECD10CA009BE4BA /* minidump_generator.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C536F0ECCE3FD009BE4BA /* minidump_generator.cc */; }; ++ F92C56480ECD10CA009BE4BA /* SimpleStringDictionary.mm in Sources */ = {isa = PBXBuildFile; fileRef = F92C53810ECCE635009BE4BA /* SimpleStringDictionary.mm */; }; ++ F92C56490ECD10CA009BE4BA /* string_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53820ECCE635009BE4BA /* string_utilities.cc */; }; ++ F92C564A0ECD10CA009BE4BA /* string_conversion.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53850ECCE6AD009BE4BA /* string_conversion.cc */; }; ++ F92C564C0ECD10DD009BE4BA /* breakpadUtilities.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F92C563C0ECD10B3009BE4BA /* breakpadUtilities.dylib */; }; ++ F92C56570ECD113E009BE4BA /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F92C554A0ECCF530009BE4BA /* Carbon.framework */; }; ++ F92C565C0ECD1158009BE4BA /* breakpadUtilities.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = F92C563C0ECD10B3009BE4BA /* breakpadUtilities.dylib */; }; ++ F92C565F0ECD116B009BE4BA /* protected_memory_allocator.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53720ECCE3FD009BE4BA /* protected_memory_allocator.cc */; }; ++ F92C56630ECD1179009BE4BA /* exception_handler.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C536D0ECCE3FD009BE4BA /* exception_handler.cc */; }; ++ F92C56650ECD1185009BE4BA /* breakpadUtilities.dylib in Resources */ = {isa = PBXBuildFile; fileRef = F92C563C0ECD10B3009BE4BA /* breakpadUtilities.dylib */; }; ++ F92C568A0ECD15F9009BE4BA /* Inspector in Resources */ = {isa = PBXBuildFile; fileRef = F92C53540ECCE349009BE4BA /* Inspector */; }; ++ F92C56A90ECE04C5009BE4BA /* crash_report_sender.m in Sources */ = {isa = PBXBuildFile; fileRef = F92C56A80ECE04C5009BE4BA /* crash_report_sender.m */; }; ++ F93803CD0F8083B7004D428B /* dynamic_images.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C536B0ECCE3FD009BE4BA /* dynamic_images.cc */; }; ++ F93803CE0F8083B7004D428B /* exception_handler.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C536D0ECCE3FD009BE4BA /* exception_handler.cc */; }; ++ F93803CF0F8083B7004D428B /* minidump_generator.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C536F0ECCE3FD009BE4BA /* minidump_generator.cc */; }; ++ F93803D00F8083B7004D428B /* minidump_file_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C538F0ECCE70A009BE4BA /* minidump_file_writer.cc */; }; ++ F93803D10F8083B7004D428B /* convert_UTF.c in Sources */ = {isa = PBXBuildFile; fileRef = F92C53870ECCE6C0009BE4BA /* convert_UTF.c */; }; ++ F93803D20F8083B7004D428B /* string_conversion.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53850ECCE6AD009BE4BA /* string_conversion.cc */; }; ++ F93803D30F8083B7004D428B /* file_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53740ECCE635009BE4BA /* file_id.cc */; }; ++ F93803D40F8083B7004D428B /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C537A0ECCE635009BE4BA /* macho_id.cc */; }; ++ F93803D50F8083B7004D428B /* macho_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C537C0ECCE635009BE4BA /* macho_utilities.cc */; }; ++ F93803D60F8083B7004D428B /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C537E0ECCE635009BE4BA /* macho_walker.cc */; }; ++ F93803D70F8083B7004D428B /* string_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53820ECCE635009BE4BA /* string_utilities.cc */; }; ++ F93803DA0F8083D8004D428B /* minidump_generator_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = F93803D90F8083D8004D428B /* minidump_generator_test.cc */; }; ++ F93DE2D80F82A70E00608B94 /* minidump_file_writer_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = F93DE2D70F82A70E00608B94 /* minidump_file_writer_unittest.cc */; }; ++ F93DE2D90F82A73500608B94 /* minidump_file_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C538F0ECCE70A009BE4BA /* minidump_file_writer.cc */; }; ++ F93DE2DA0F82A73500608B94 /* convert_UTF.c in Sources */ = {isa = PBXBuildFile; fileRef = F92C53870ECCE6C0009BE4BA /* convert_UTF.c */; }; ++ F93DE2DB0F82A73500608B94 /* string_conversion.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53850ECCE6AD009BE4BA /* string_conversion.cc */; }; ++ F93DE3350F82C66B00608B94 /* dynamic_images.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C536B0ECCE3FD009BE4BA /* dynamic_images.cc */; }; ++ F93DE3360F82C66B00608B94 /* exception_handler.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C536D0ECCE3FD009BE4BA /* exception_handler.cc */; }; ++ F93DE3370F82C66B00608B94 /* minidump_generator.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C536F0ECCE3FD009BE4BA /* minidump_generator.cc */; }; ++ F93DE3380F82C66B00608B94 /* minidump_file_writer.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C538F0ECCE70A009BE4BA /* minidump_file_writer.cc */; }; ++ F93DE3390F82C66B00608B94 /* convert_UTF.c in Sources */ = {isa = PBXBuildFile; fileRef = F92C53870ECCE6C0009BE4BA /* convert_UTF.c */; }; ++ F93DE33A0F82C66B00608B94 /* string_conversion.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53850ECCE6AD009BE4BA /* string_conversion.cc */; }; ++ F93DE33B0F82C66B00608B94 /* file_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53740ECCE635009BE4BA /* file_id.cc */; }; ++ F93DE33C0F82C66B00608B94 /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C537A0ECCE635009BE4BA /* macho_id.cc */; }; ++ F93DE33D0F82C66B00608B94 /* macho_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C537C0ECCE635009BE4BA /* macho_utilities.cc */; }; ++ F93DE33E0F82C66B00608B94 /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C537E0ECCE635009BE4BA /* macho_walker.cc */; }; ++ F93DE33F0F82C66B00608B94 /* string_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = F92C53820ECCE635009BE4BA /* string_utilities.cc */; }; ++ F93DE3410F82C68300608B94 /* exception_handler_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = F93DE3400F82C68300608B94 /* exception_handler_test.cc */; }; ++ F945849E0F280E3C009A47BF /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = F945849C0F280E3C009A47BF /* Localizable.strings */; }; ++ F9B630A0100FF96B00D0F4AC /* goArrow.png in Resources */ = {isa = PBXBuildFile; fileRef = F9B6309F100FF96B00D0F4AC /* goArrow.png */; }; ++ F9C44DB20EF07288003AEBAA /* Controller.m in Sources */ = {isa = PBXBuildFile; fileRef = F9C44DAC0EF07288003AEBAA /* Controller.m */; }; ++ F9C44DB30EF07288003AEBAA /* crashduringload in Resources */ = {isa = PBXBuildFile; fileRef = F9C44DAD0EF07288003AEBAA /* crashduringload */; }; ++ F9C44DB40EF07288003AEBAA /* crashInMain in Resources */ = {isa = PBXBuildFile; fileRef = F9C44DAE0EF07288003AEBAA /* crashInMain */; }; ++ F9C44DB60EF07288003AEBAA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F9C44DB00EF07288003AEBAA /* main.m */; }; ++ F9C44DB70EF07288003AEBAA /* TestClass.mm in Sources */ = {isa = PBXBuildFile; fileRef = F9C44DB10EF07288003AEBAA /* TestClass.mm */; }; ++ F9C44DBC0EF072A0003AEBAA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F9C44DB80EF072A0003AEBAA /* InfoPlist.strings */; }; ++ F9C44DBD0EF072A0003AEBAA /* MainMenu.nib in Resources */ = {isa = PBXBuildFile; fileRef = F9C44DBA0EF072A0003AEBAA /* MainMenu.nib */; }; ++ F9C44E000EF077CD003AEBAA /* Breakpad.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* Breakpad.framework */; }; ++ F9C44E3C0EF08B12003AEBAA /* Breakpad.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 8DC2EF5B0486A6940098B216 /* Breakpad.framework */; }; ++ F9C44E980EF09F56003AEBAA /* crash_report_sender.app in Resources */ = {isa = PBXBuildFile; fileRef = F92C56A00ECE04A7009BE4BA /* crash_report_sender.app */; }; ++ F9C44EA20EF09F93003AEBAA /* HTTPMultipartUpload.m in Sources */ = {isa = PBXBuildFile; fileRef = F92C53770ECCE635009BE4BA /* HTTPMultipartUpload.m */; }; ++ F9C44EE50EF0A006003AEBAA /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9C44EE40EF0A006003AEBAA /* SystemConfiguration.framework */; }; ++ F9C44EE90EF0A3C1003AEBAA /* GTMLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = F9C44EE80EF0A3C1003AEBAA /* GTMLogger.m */; }; ++ F9C77DE20F7DD7E30045F7DB /* SimpleStringDictionaryTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = F9C77DE10F7DD7E30045F7DB /* SimpleStringDictionaryTest.mm */; }; ++ F9C77DE40F7DD82F0045F7DB /* SimpleStringDictionary.mm in Sources */ = {isa = PBXBuildFile; fileRef = F92C53810ECCE635009BE4BA /* SimpleStringDictionary.mm */; }; ++ F9C77E130F7DDF810045F7DB /* GTMSenTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = F9C77E120F7DDF810045F7DB /* GTMSenTestCase.m */; }; ++/* End PBXBuildFile section */ ++ ++/* Begin PBXContainerItemProxy section */ ++ F91AF6370FD60A74009D8BE2 /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; ++ proxyType = 1; ++ remoteGlobalIDString = 8DC2EF4F0486A6940098B216; ++ remoteInfo = Breakpad; ++ }; ++ F92C564D0ECD10E5009BE4BA /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; ++ proxyType = 1; ++ remoteGlobalIDString = F92C563B0ECD10B3009BE4BA; ++ remoteInfo = breakpadUtilities; ++ }; ++ F92C56850ECD15EF009BE4BA /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; ++ proxyType = 1; ++ remoteGlobalIDString = F92C563B0ECD10B3009BE4BA; ++ remoteInfo = breakpadUtilities; ++ }; ++ F92C56870ECD15F1009BE4BA /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; ++ proxyType = 1; ++ remoteGlobalIDString = F92C53530ECCE349009BE4BA; ++ remoteInfo = Inspector; ++ }; ++ F93DE2FB0F82C3C600608B94 /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; ++ proxyType = 1; ++ remoteGlobalIDString = F93803BD0F80820F004D428B; ++ remoteInfo = generator_test; ++ }; ++ F93DE36F0F82CC1300608B94 /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; ++ proxyType = 1; ++ remoteGlobalIDString = F93DE32B0F82C55600608B94; ++ remoteInfo = handler_test; ++ }; ++ F93DE3A60F830D1D00608B94 /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; ++ proxyType = 1; ++ remoteGlobalIDString = F9C77DD90F7DD5CF0045F7DB; ++ remoteInfo = UnitTests; ++ }; ++ F94585870F78232B009A47BF /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; ++ proxyType = 1; ++ remoteGlobalIDString = 8DC2EF4F0486A6940098B216; ++ remoteInfo = Breakpad; ++ }; ++ F94585890F78232E009A47BF /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; ++ proxyType = 1; ++ remoteGlobalIDString = F92C53530ECCE349009BE4BA; ++ remoteInfo = Inspector; ++ }; ++ F945858B0F782330009A47BF /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; ++ proxyType = 1; ++ remoteGlobalIDString = F92C563B0ECD10B3009BE4BA; ++ remoteInfo = breakpadUtilities; ++ }; ++ F945858D0F782333009A47BF /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; ++ proxyType = 1; ++ remoteGlobalIDString = F92C569F0ECE04A7009BE4BA; ++ remoteInfo = crash_report_sender; ++ }; ++ F945858F0F782336009A47BF /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; ++ proxyType = 1; ++ remoteGlobalIDString = F9C44DA40EF060A8003AEBAA; ++ remoteInfo = BreakpadTest; ++ }; ++ F95BB884101F949F00AA053B /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = F95BB87C101F949F00AA053B /* crash_report.xcodeproj */; ++ proxyType = 2; ++ remoteGlobalIDString = 8DD76FA10486AA7600D96B5E /* crash_report */; ++ remoteInfo = crash_report; ++ }; ++ F95BB891101F94AC00AA053B /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = F95BB889101F94AC00AA053B /* dump_syms.xcodeproj */; ++ proxyType = 2; ++ remoteGlobalIDString = 8DD76FA10486AA7600D96B5E /* dump_syms */; ++ remoteInfo = dump_syms; ++ }; ++ F95BB89E101F94C000AA053B /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = F95BB894101F94C000AA053B /* symupload.xcodeproj */; ++ proxyType = 2; ++ remoteGlobalIDString = 8DD76FA10486AA7600D96B5E /* symupload */; ++ remoteInfo = symupload; ++ }; ++ F95BB8A0101F94C000AA053B /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = F95BB894101F94C000AA053B /* symupload.xcodeproj */; ++ proxyType = 2; ++ remoteGlobalIDString = 9BD835FB0B0544950055103E /* minidump_upload */; ++ remoteInfo = minidump_upload; ++ }; ++ F95BB8B2101F94D300AA053B /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = F95BB889101F94AC00AA053B /* dump_syms.xcodeproj */; ++ proxyType = 1; ++ remoteGlobalIDString = 8DD76F960486AA7600D96B5E /* dump_syms */; ++ remoteInfo = dump_syms; ++ }; ++ F95BB8B4101F94D300AA053B /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = F95BB894101F94C000AA053B /* symupload.xcodeproj */; ++ proxyType = 1; ++ remoteGlobalIDString = 8DD76F960486AA7600D96B5E /* symupload */; ++ remoteInfo = symupload; ++ }; ++ F95BB8B6101F94D300AA053B /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = F95BB87C101F949F00AA053B /* crash_report.xcodeproj */; ++ proxyType = 1; ++ remoteGlobalIDString = 8DD76F960486AA7600D96B5E /* crash_report */; ++ remoteInfo = crash_report; ++ }; ++ F9C44E190EF0790F003AEBAA /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; ++ proxyType = 1; ++ remoteGlobalIDString = 8DC2EF4F0486A6940098B216; ++ remoteInfo = Breakpad; ++ }; ++ F9C44E960EF09F4B003AEBAA /* PBXContainerItemProxy */ = { ++ isa = PBXContainerItemProxy; ++ containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; ++ proxyType = 1; ++ remoteGlobalIDString = F92C569F0ECE04A7009BE4BA; ++ remoteInfo = crash_report_sender; ++ }; ++/* End PBXContainerItemProxy section */ ++ ++/* Begin PBXCopyFilesBuildPhase section */ ++ F9C44E410EF08B17003AEBAA /* Copy Frameworks */ = { ++ isa = PBXCopyFilesBuildPhase; ++ buildActionMask = 2147483647; ++ dstPath = ""; ++ dstSubfolderSpec = 10; ++ files = ( ++ F9C44E3C0EF08B12003AEBAA /* Breakpad.framework in Copy Frameworks */, ++ ); ++ name = "Copy Frameworks"; ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++/* End PBXCopyFilesBuildPhase section */ ++ ++/* Begin PBXFileReference section */ ++ 0867D69BFE84028FC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; ++ 0867D6A5FE840307C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; ++ 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; ++ 32DBCF5E0370ADEE00C91783 /* Breakpad_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Breakpad_Prefix.pch; path = Framework/Breakpad_Prefix.pch; sourceTree = ""; }; ++ 3329D4EC0FA16D820007BBC5 /* Breakpad.nib */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = Breakpad.nib; path = sender/Breakpad.nib; sourceTree = ""; }; ++ 33880C7F0F9E097100817F82 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = sender/English.lproj/InfoPlist.strings; sourceTree = ""; }; ++ 4084699C0F5D9CF900FDCA37 /* crash_report_sender.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = crash_report_sender.icns; path = sender/crash_report_sender.icns; sourceTree = ""; }; ++ 8DC2EF5B0486A6940098B216 /* Breakpad.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Breakpad.framework; sourceTree = BUILT_PRODUCTS_DIR; }; ++ F91AF5CF0FD60393009D8BE2 /* BreakpadFramework_Test.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = BreakpadFramework_Test.mm; path = tests/BreakpadFramework_Test.mm; sourceTree = ""; }; ++ F9286B380F7EB25800A4DCC8 /* Inspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Inspector.h; path = crash_generation/Inspector.h; sourceTree = ""; }; ++ F9286B390F7EB25800A4DCC8 /* InspectorMain.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = InspectorMain.mm; path = crash_generation/InspectorMain.mm; sourceTree = ""; }; ++ F92C53540ECCE349009BE4BA /* Inspector */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Inspector; sourceTree = BUILT_PRODUCTS_DIR; }; ++ F92C53670ECCE3FD009BE4BA /* breakpad_exc_server.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = breakpad_exc_server.c; path = handler/breakpad_exc_server.c; sourceTree = SOURCE_ROOT; }; ++ F92C53680ECCE3FD009BE4BA /* breakpad_exc_server.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = breakpad_exc_server.h; path = handler/breakpad_exc_server.h; sourceTree = SOURCE_ROOT; }; ++ F92C53690ECCE3FD009BE4BA /* breakpad_nlist_64.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = breakpad_nlist_64.cc; path = handler/breakpad_nlist_64.cc; sourceTree = SOURCE_ROOT; }; ++ F92C536A0ECCE3FD009BE4BA /* breakpad_nlist_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = breakpad_nlist_64.h; path = handler/breakpad_nlist_64.h; sourceTree = SOURCE_ROOT; }; ++ F92C536B0ECCE3FD009BE4BA /* dynamic_images.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dynamic_images.cc; path = handler/dynamic_images.cc; sourceTree = SOURCE_ROOT; }; ++ F92C536C0ECCE3FD009BE4BA /* dynamic_images.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dynamic_images.h; path = handler/dynamic_images.h; sourceTree = SOURCE_ROOT; }; ++ F92C536D0ECCE3FD009BE4BA /* exception_handler.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = exception_handler.cc; path = handler/exception_handler.cc; sourceTree = SOURCE_ROOT; }; ++ F92C536E0ECCE3FD009BE4BA /* exception_handler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = exception_handler.h; path = handler/exception_handler.h; sourceTree = SOURCE_ROOT; }; ++ F92C536F0ECCE3FD009BE4BA /* minidump_generator.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = minidump_generator.cc; path = handler/minidump_generator.cc; sourceTree = SOURCE_ROOT; }; ++ F92C53700ECCE3FD009BE4BA /* minidump_generator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = minidump_generator.h; path = handler/minidump_generator.h; sourceTree = SOURCE_ROOT; }; ++ F92C53720ECCE3FD009BE4BA /* protected_memory_allocator.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = protected_memory_allocator.cc; path = handler/protected_memory_allocator.cc; sourceTree = SOURCE_ROOT; }; ++ F92C53730ECCE3FD009BE4BA /* protected_memory_allocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = protected_memory_allocator.h; path = handler/protected_memory_allocator.h; sourceTree = SOURCE_ROOT; }; ++ F92C53740ECCE635009BE4BA /* file_id.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = file_id.cc; path = ../../common/mac/file_id.cc; sourceTree = SOURCE_ROOT; }; ++ F92C53750ECCE635009BE4BA /* file_id.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = file_id.h; path = ../../common/mac/file_id.h; sourceTree = SOURCE_ROOT; }; ++ F92C53760ECCE635009BE4BA /* HTTPMultipartUpload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTTPMultipartUpload.h; path = ../../common/mac/HTTPMultipartUpload.h; sourceTree = SOURCE_ROOT; }; ++ F92C53770ECCE635009BE4BA /* HTTPMultipartUpload.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HTTPMultipartUpload.m; path = ../../common/mac/HTTPMultipartUpload.m; sourceTree = SOURCE_ROOT; }; ++ F92C53780ECCE635009BE4BA /* MachIPC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MachIPC.h; path = ../../common/mac/MachIPC.h; sourceTree = SOURCE_ROOT; }; ++ F92C53790ECCE635009BE4BA /* MachIPC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MachIPC.mm; path = ../../common/mac/MachIPC.mm; sourceTree = SOURCE_ROOT; }; ++ F92C537A0ECCE635009BE4BA /* macho_id.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = macho_id.cc; path = ../../common/mac/macho_id.cc; sourceTree = SOURCE_ROOT; }; ++ F92C537B0ECCE635009BE4BA /* macho_id.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = macho_id.h; path = ../../common/mac/macho_id.h; sourceTree = SOURCE_ROOT; }; ++ F92C537C0ECCE635009BE4BA /* macho_utilities.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = macho_utilities.cc; path = ../../common/mac/macho_utilities.cc; sourceTree = SOURCE_ROOT; }; ++ F92C537D0ECCE635009BE4BA /* macho_utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = macho_utilities.h; path = ../../common/mac/macho_utilities.h; sourceTree = SOURCE_ROOT; }; ++ F92C537E0ECCE635009BE4BA /* macho_walker.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = macho_walker.cc; path = ../../common/mac/macho_walker.cc; sourceTree = SOURCE_ROOT; }; ++ F92C537F0ECCE635009BE4BA /* macho_walker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = macho_walker.h; path = ../../common/mac/macho_walker.h; sourceTree = SOURCE_ROOT; }; ++ F92C53800ECCE635009BE4BA /* SimpleStringDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SimpleStringDictionary.h; path = ../../common/mac/SimpleStringDictionary.h; sourceTree = SOURCE_ROOT; }; ++ F92C53810ECCE635009BE4BA /* SimpleStringDictionary.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = SimpleStringDictionary.mm; path = ../../common/mac/SimpleStringDictionary.mm; sourceTree = SOURCE_ROOT; }; ++ F92C53820ECCE635009BE4BA /* string_utilities.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = string_utilities.cc; path = ../../common/mac/string_utilities.cc; sourceTree = SOURCE_ROOT; }; ++ F92C53830ECCE635009BE4BA /* string_utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = string_utilities.h; path = ../../common/mac/string_utilities.h; sourceTree = SOURCE_ROOT; }; ++ F92C53850ECCE6AD009BE4BA /* string_conversion.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = string_conversion.cc; path = ../../common/string_conversion.cc; sourceTree = SOURCE_ROOT; }; ++ F92C53860ECCE6AD009BE4BA /* string_conversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = string_conversion.h; path = ../../common/string_conversion.h; sourceTree = SOURCE_ROOT; }; ++ F92C53870ECCE6C0009BE4BA /* convert_UTF.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = convert_UTF.c; path = ../../common/convert_UTF.c; sourceTree = SOURCE_ROOT; }; ++ F92C53880ECCE6C0009BE4BA /* convert_UTF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = convert_UTF.h; path = ../../common/convert_UTF.h; sourceTree = SOURCE_ROOT; }; ++ F92C538E0ECCE70A009BE4BA /* minidump_file_writer-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "minidump_file_writer-inl.h"; path = "../minidump_file_writer-inl.h"; sourceTree = SOURCE_ROOT; }; ++ F92C538F0ECCE70A009BE4BA /* minidump_file_writer.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = minidump_file_writer.cc; path = ../minidump_file_writer.cc; sourceTree = SOURCE_ROOT; }; ++ F92C53900ECCE70A009BE4BA /* minidump_file_writer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = minidump_file_writer.h; path = ../minidump_file_writer.h; sourceTree = SOURCE_ROOT; }; ++ F92C53B70ECCE7B3009BE4BA /* Inspector.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = Inspector.mm; path = crash_generation/Inspector.mm; sourceTree = SOURCE_ROOT; }; ++ F92C554A0ECCF530009BE4BA /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = ""; }; ++ F92C55CE0ECD0064009BE4BA /* Breakpad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Breakpad.h; path = Framework/Breakpad.h; sourceTree = ""; }; ++ F92C55CF0ECD0064009BE4BA /* Breakpad.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = Breakpad.mm; path = Framework/Breakpad.mm; sourceTree = ""; }; ++ F92C56310ECD0DF1009BE4BA /* OnDemandServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OnDemandServer.h; path = Framework/OnDemandServer.h; sourceTree = ""; }; ++ F92C56320ECD0DF1009BE4BA /* OnDemandServer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = OnDemandServer.mm; path = Framework/OnDemandServer.mm; sourceTree = ""; }; ++ F92C563C0ECD10B3009BE4BA /* breakpadUtilities.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = breakpadUtilities.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; ++ F92C56A00ECE04A7009BE4BA /* crash_report_sender.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = crash_report_sender.app; sourceTree = BUILT_PRODUCTS_DIR; }; ++ F92C56A20ECE04A7009BE4BA /* crash_report_sender-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "crash_report_sender-Info.plist"; path = "sender/crash_report_sender-Info.plist"; sourceTree = ""; }; ++ F92C56A70ECE04C5009BE4BA /* crash_report_sender.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = crash_report_sender.h; path = sender/crash_report_sender.h; sourceTree = ""; }; ++ F92C56A80ECE04C5009BE4BA /* crash_report_sender.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = crash_report_sender.m; path = sender/crash_report_sender.m; sourceTree = ""; }; ++ F93803BE0F80820F004D428B /* generator_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = generator_test; sourceTree = BUILT_PRODUCTS_DIR; }; ++ F93803D90F8083D8004D428B /* minidump_generator_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = minidump_generator_test.cc; path = handler/minidump_generator_test.cc; sourceTree = ""; }; ++ F93DE2D10F82A67300608B94 /* minidump_file_writer_unittest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = minidump_file_writer_unittest; sourceTree = BUILT_PRODUCTS_DIR; }; ++ F93DE2D70F82A70E00608B94 /* minidump_file_writer_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = minidump_file_writer_unittest.cc; path = ../minidump_file_writer_unittest.cc; sourceTree = SOURCE_ROOT; }; ++ F93DE32C0F82C55600608B94 /* handler_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = handler_test; sourceTree = BUILT_PRODUCTS_DIR; }; ++ F93DE3400F82C68300608B94 /* exception_handler_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = exception_handler_test.cc; path = handler/exception_handler_test.cc; sourceTree = ""; }; ++ F945849D0F280E3C009A47BF /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = sender/English.lproj/Localizable.strings; sourceTree = ""; }; ++ F945859D0F78241E009A47BF /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Framework/Info.plist; sourceTree = ""; }; ++ F95BB87C101F949F00AA053B /* crash_report.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = crash_report.xcodeproj; path = ../../tools/mac/crash_report/crash_report.xcodeproj; sourceTree = SOURCE_ROOT; }; ++ F95BB889101F94AC00AA053B /* dump_syms.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = dump_syms.xcodeproj; path = ../../tools/mac/dump_syms/dump_syms.xcodeproj; sourceTree = SOURCE_ROOT; }; ++ F95BB894101F94C000AA053B /* symupload.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = symupload.xcodeproj; path = ../../tools/mac/symupload/symupload.xcodeproj; sourceTree = SOURCE_ROOT; }; ++ F9B6309F100FF96B00D0F4AC /* goArrow.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = goArrow.png; path = sender/goArrow.png; sourceTree = ""; }; ++ F9C44DA50EF060A8003AEBAA /* BreakpadTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BreakpadTest.app; sourceTree = BUILT_PRODUCTS_DIR; }; ++ F9C44DAC0EF07288003AEBAA /* Controller.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Controller.m; path = testapp/Controller.m; sourceTree = ""; }; ++ F9C44DAD0EF07288003AEBAA /* crashduringload */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; name = crashduringload; path = testapp/crashduringload; sourceTree = ""; }; ++ F9C44DAE0EF07288003AEBAA /* crashInMain */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; name = crashInMain; path = testapp/crashInMain; sourceTree = ""; }; ++ F9C44DAF0EF07288003AEBAA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = testapp/Info.plist; sourceTree = ""; }; ++ F9C44DB00EF07288003AEBAA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = testapp/main.m; sourceTree = ""; }; ++ F9C44DB10EF07288003AEBAA /* TestClass.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = TestClass.mm; path = testapp/TestClass.mm; sourceTree = ""; }; ++ F9C44DB90EF072A0003AEBAA /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = testapp/English.lproj/InfoPlist.strings; sourceTree = ""; }; ++ F9C44DBB0EF072A0003AEBAA /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = testapp/English.lproj/MainMenu.nib; sourceTree = ""; }; ++ F9C44DBF0EF0778F003AEBAA /* Controller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Controller.h; path = testapp/Controller.h; sourceTree = ""; }; ++ F9C44DC00EF0778F003AEBAA /* TestClass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TestClass.h; path = testapp/TestClass.h; sourceTree = ""; }; ++ F9C44EE40EF0A006003AEBAA /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = /System/Library/Frameworks/SystemConfiguration.framework; sourceTree = ""; }; ++ F9C44EE70EF0A3C1003AEBAA /* GTMLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTMLogger.h; path = ../../common/mac/GTMLogger.h; sourceTree = SOURCE_ROOT; }; ++ F9C44EE80EF0A3C1003AEBAA /* GTMLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTMLogger.m; path = ../../common/mac/GTMLogger.m; sourceTree = SOURCE_ROOT; }; ++ F9C77DDA0F7DD5CF0045F7DB /* UnitTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UnitTests.octest; sourceTree = BUILT_PRODUCTS_DIR; }; ++ F9C77DDB0F7DD5CF0045F7DB /* UnitTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "UnitTests-Info.plist"; sourceTree = ""; }; ++ F9C77DE00F7DD7E30045F7DB /* SimpleStringDictionaryTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SimpleStringDictionaryTest.h; path = tests/SimpleStringDictionaryTest.h; sourceTree = ""; }; ++ F9C77DE10F7DD7E30045F7DB /* SimpleStringDictionaryTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = SimpleStringDictionaryTest.mm; path = tests/SimpleStringDictionaryTest.mm; sourceTree = ""; }; ++ F9C77E110F7DDF810045F7DB /* GTMSenTestCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTMSenTestCase.h; path = ../../common/mac/testing/GTMSenTestCase.h; sourceTree = SOURCE_ROOT; }; ++ F9C77E120F7DDF810045F7DB /* GTMSenTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTMSenTestCase.m; path = ../../common/mac/testing/GTMSenTestCase.m; sourceTree = SOURCE_ROOT; }; ++/* End PBXFileReference section */ ++ ++/* Begin PBXFrameworksBuildPhase section */ ++ 8DC2EF560486A6940098B216 /* Frameworks */ = { ++ isa = PBXFrameworksBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ F92C565C0ECD1158009BE4BA /* breakpadUtilities.dylib in Frameworks */, ++ 8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ F92C53520ECCE349009BE4BA /* Frameworks */ = { ++ isa = PBXFrameworksBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ F92C564C0ECD10DD009BE4BA /* breakpadUtilities.dylib in Frameworks */, ++ F92C554C0ECCF534009BE4BA /* Foundation.framework in Frameworks */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ F92C563A0ECD10B3009BE4BA /* Frameworks */ = { ++ isa = PBXFrameworksBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ F92C56570ECD113E009BE4BA /* Carbon.framework in Frameworks */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ F92C569E0ECE04A7009BE4BA /* Frameworks */ = { ++ isa = PBXFrameworksBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ F9C44EE50EF0A006003AEBAA /* SystemConfiguration.framework in Frameworks */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ F93803BC0F80820F004D428B /* Frameworks */ = { ++ isa = PBXFrameworksBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ F93DE2CF0F82A67300608B94 /* Frameworks */ = { ++ isa = PBXFrameworksBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ F93DE32A0F82C55600608B94 /* Frameworks */ = { ++ isa = PBXFrameworksBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ F9C44DA30EF060A8003AEBAA /* Frameworks */ = { ++ isa = PBXFrameworksBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ F9C44E000EF077CD003AEBAA /* Breakpad.framework in Frameworks */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ F9C77DD70F7DD5CF0045F7DB /* Frameworks */ = { ++ isa = PBXFrameworksBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ F91AF6210FD60784009D8BE2 /* Breakpad.framework in Frameworks */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++/* End PBXFrameworksBuildPhase section */ ++ ++/* Begin PBXGroup section */ ++ 034768DFFF38A50411DB9C8B /* Products */ = { ++ isa = PBXGroup; ++ children = ( ++ 8DC2EF5B0486A6940098B216 /* Breakpad.framework */, ++ F92C53540ECCE349009BE4BA /* Inspector */, ++ F92C563C0ECD10B3009BE4BA /* breakpadUtilities.dylib */, ++ F92C56A00ECE04A7009BE4BA /* crash_report_sender.app */, ++ F9C44DA50EF060A8003AEBAA /* BreakpadTest.app */, ++ F9C77DDA0F7DD5CF0045F7DB /* UnitTests.octest */, ++ F93803BE0F80820F004D428B /* generator_test */, ++ F93DE2D10F82A67300608B94 /* minidump_file_writer_unittest */, ++ F93DE32C0F82C55600608B94 /* handler_test */, ++ ); ++ name = Products; ++ sourceTree = ""; ++ }; ++ 0867D691FE84028FC02AAC07 /* Breakpad */ = { ++ isa = PBXGroup; ++ children = ( ++ F95BB8A3101F94C300AA053B /* Tools */, ++ 32DBCF5E0370ADEE00C91783 /* Breakpad_Prefix.pch */, ++ F92C538D0ECCE6F2009BE4BA /* client */, ++ F92C53600ECCE3D6009BE4BA /* common */, ++ 0867D69AFE84028FC02AAC07 /* Frameworks */, ++ 034768DFFF38A50411DB9C8B /* Products */, ++ F9C77DDB0F7DD5CF0045F7DB /* UnitTests-Info.plist */, ++ ); ++ name = Breakpad; ++ sourceTree = ""; ++ }; ++ 0867D69AFE84028FC02AAC07 /* Frameworks */ = { ++ isa = PBXGroup; ++ children = ( ++ F9C44EE40EF0A006003AEBAA /* SystemConfiguration.framework */, ++ F92C554A0ECCF530009BE4BA /* Carbon.framework */, ++ 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */, ++ 0867D6A5FE840307C02AAC07 /* AppKit.framework */, ++ 0867D69BFE84028FC02AAC07 /* Foundation.framework */, ++ ); ++ name = Frameworks; ++ sourceTree = ""; ++ }; ++ F92C53590ECCE3BB009BE4BA /* handler */ = { ++ isa = PBXGroup; ++ children = ( ++ F93DE3400F82C68300608B94 /* exception_handler_test.cc */, ++ F93803D90F8083D8004D428B /* minidump_generator_test.cc */, ++ F92C53670ECCE3FD009BE4BA /* breakpad_exc_server.c */, ++ F92C53680ECCE3FD009BE4BA /* breakpad_exc_server.h */, ++ F92C53690ECCE3FD009BE4BA /* breakpad_nlist_64.cc */, ++ F92C536A0ECCE3FD009BE4BA /* breakpad_nlist_64.h */, ++ F92C536B0ECCE3FD009BE4BA /* dynamic_images.cc */, ++ F92C536C0ECCE3FD009BE4BA /* dynamic_images.h */, ++ F92C536D0ECCE3FD009BE4BA /* exception_handler.cc */, ++ F92C536E0ECCE3FD009BE4BA /* exception_handler.h */, ++ F92C536F0ECCE3FD009BE4BA /* minidump_generator.cc */, ++ F92C53700ECCE3FD009BE4BA /* minidump_generator.h */, ++ F92C53720ECCE3FD009BE4BA /* protected_memory_allocator.cc */, ++ F92C53730ECCE3FD009BE4BA /* protected_memory_allocator.h */, ++ ); ++ name = handler; ++ sourceTree = ""; ++ }; ++ F92C53600ECCE3D6009BE4BA /* common */ = { ++ isa = PBXGroup; ++ children = ( ++ F92C53870ECCE6C0009BE4BA /* convert_UTF.c */, ++ F92C53880ECCE6C0009BE4BA /* convert_UTF.h */, ++ F92C53850ECCE6AD009BE4BA /* string_conversion.cc */, ++ F92C53860ECCE6AD009BE4BA /* string_conversion.h */, ++ F92C53840ECCE68D009BE4BA /* mac */, ++ ); ++ name = common; ++ sourceTree = ""; ++ }; ++ F92C53840ECCE68D009BE4BA /* mac */ = { ++ isa = PBXGroup; ++ children = ( ++ F9C77E0F0F7DDF650045F7DB /* testing */, ++ F9C44EE70EF0A3C1003AEBAA /* GTMLogger.h */, ++ F9C44EE80EF0A3C1003AEBAA /* GTMLogger.m */, ++ F92C53740ECCE635009BE4BA /* file_id.cc */, ++ F92C53750ECCE635009BE4BA /* file_id.h */, ++ F92C53760ECCE635009BE4BA /* HTTPMultipartUpload.h */, ++ F92C53770ECCE635009BE4BA /* HTTPMultipartUpload.m */, ++ F92C53780ECCE635009BE4BA /* MachIPC.h */, ++ F92C53790ECCE635009BE4BA /* MachIPC.mm */, ++ F92C537A0ECCE635009BE4BA /* macho_id.cc */, ++ F92C537B0ECCE635009BE4BA /* macho_id.h */, ++ F92C537C0ECCE635009BE4BA /* macho_utilities.cc */, ++ F92C537D0ECCE635009BE4BA /* macho_utilities.h */, ++ F92C537E0ECCE635009BE4BA /* macho_walker.cc */, ++ F92C537F0ECCE635009BE4BA /* macho_walker.h */, ++ F92C53800ECCE635009BE4BA /* SimpleStringDictionary.h */, ++ F92C53810ECCE635009BE4BA /* SimpleStringDictionary.mm */, ++ F92C53820ECCE635009BE4BA /* string_utilities.cc */, ++ F92C53830ECCE635009BE4BA /* string_utilities.h */, ++ ); ++ name = mac; ++ sourceTree = ""; ++ }; ++ F92C538D0ECCE6F2009BE4BA /* client */ = { ++ isa = PBXGroup; ++ children = ( ++ F92C53990ECCE78E009BE4BA /* mac */, ++ F92C538E0ECCE70A009BE4BA /* minidump_file_writer-inl.h */, ++ F92C538F0ECCE70A009BE4BA /* minidump_file_writer.cc */, ++ F92C53900ECCE70A009BE4BA /* minidump_file_writer.h */, ++ F93DE2D70F82A70E00608B94 /* minidump_file_writer_unittest.cc */, ++ ); ++ name = client; ++ sourceTree = ""; ++ }; ++ F92C53990ECCE78E009BE4BA /* mac */ = { ++ isa = PBXGroup; ++ children = ( ++ F9C77DDF0F7DD7CF0045F7DB /* tests */, ++ F9C44DAB0EF0726F003AEBAA /* testapp */, ++ F92C56A60ECE04B6009BE4BA /* sender */, ++ F92C55CD0ECD0053009BE4BA /* Framework */, ++ F92C53B50ECCE799009BE4BA /* crash_generation */, ++ F92C53590ECCE3BB009BE4BA /* handler */, ++ ); ++ name = mac; ++ sourceTree = ""; ++ }; ++ F92C53B50ECCE799009BE4BA /* crash_generation */ = { ++ isa = PBXGroup; ++ children = ( ++ F9286B380F7EB25800A4DCC8 /* Inspector.h */, ++ F9286B390F7EB25800A4DCC8 /* InspectorMain.mm */, ++ F92C53B70ECCE7B3009BE4BA /* Inspector.mm */, ++ ); ++ name = crash_generation; ++ sourceTree = ""; ++ }; ++ F92C55CD0ECD0053009BE4BA /* Framework */ = { ++ isa = PBXGroup; ++ children = ( ++ F945859D0F78241E009A47BF /* Info.plist */, ++ F92C56310ECD0DF1009BE4BA /* OnDemandServer.h */, ++ F92C56320ECD0DF1009BE4BA /* OnDemandServer.mm */, ++ F92C55CE0ECD0064009BE4BA /* Breakpad.h */, ++ F92C55CF0ECD0064009BE4BA /* Breakpad.mm */, ++ ); ++ name = Framework; ++ sourceTree = ""; ++ }; ++ F92C56A60ECE04B6009BE4BA /* sender */ = { ++ isa = PBXGroup; ++ children = ( ++ F9B6309F100FF96B00D0F4AC /* goArrow.png */, ++ F92C56A70ECE04C5009BE4BA /* crash_report_sender.h */, ++ F92C56A80ECE04C5009BE4BA /* crash_report_sender.m */, ++ F945849C0F280E3C009A47BF /* Localizable.strings */, ++ 33880C7E0F9E097100817F82 /* InfoPlist.strings */, ++ 3329D4EC0FA16D820007BBC5 /* Breakpad.nib */, ++ 4084699C0F5D9CF900FDCA37 /* crash_report_sender.icns */, ++ F92C56A20ECE04A7009BE4BA /* crash_report_sender-Info.plist */, ++ ); ++ name = sender; ++ sourceTree = ""; ++ }; ++ F95BB87D101F949F00AA053B /* Products */ = { ++ isa = PBXGroup; ++ children = ( ++ F95BB885101F949F00AA053B /* crash_report */, ++ ); ++ name = Products; ++ sourceTree = ""; ++ }; ++ F95BB88A101F94AC00AA053B /* Products */ = { ++ isa = PBXGroup; ++ children = ( ++ F95BB892101F94AC00AA053B /* dump_syms */, ++ ); ++ name = Products; ++ sourceTree = ""; ++ }; ++ F95BB895101F94C000AA053B /* Products */ = { ++ isa = PBXGroup; ++ children = ( ++ F95BB89F101F94C000AA053B /* symupload */, ++ F95BB8A1101F94C000AA053B /* minidump_upload */, ++ ); ++ name = Products; ++ sourceTree = ""; ++ }; ++ F95BB8A3101F94C300AA053B /* Tools */ = { ++ isa = PBXGroup; ++ children = ( ++ F95BB894101F94C000AA053B /* symupload.xcodeproj */, ++ F95BB889101F94AC00AA053B /* dump_syms.xcodeproj */, ++ F95BB87C101F949F00AA053B /* crash_report.xcodeproj */, ++ ); ++ name = Tools; ++ sourceTree = ""; ++ }; ++ F9C44DAB0EF0726F003AEBAA /* testapp */ = { ++ isa = PBXGroup; ++ children = ( ++ F9C44DBF0EF0778F003AEBAA /* Controller.h */, ++ F9C44DC00EF0778F003AEBAA /* TestClass.h */, ++ F9C44DB80EF072A0003AEBAA /* InfoPlist.strings */, ++ F9C44DBA0EF072A0003AEBAA /* MainMenu.nib */, ++ F9C44DAC0EF07288003AEBAA /* Controller.m */, ++ F9C44DAD0EF07288003AEBAA /* crashduringload */, ++ F9C44DAE0EF07288003AEBAA /* crashInMain */, ++ F9C44DAF0EF07288003AEBAA /* Info.plist */, ++ F9C44DB00EF07288003AEBAA /* main.m */, ++ F9C44DB10EF07288003AEBAA /* TestClass.mm */, ++ ); ++ name = testapp; ++ sourceTree = ""; ++ }; ++ F9C77DDF0F7DD7CF0045F7DB /* tests */ = { ++ isa = PBXGroup; ++ children = ( ++ F9C77DE00F7DD7E30045F7DB /* SimpleStringDictionaryTest.h */, ++ F9C77DE10F7DD7E30045F7DB /* SimpleStringDictionaryTest.mm */, ++ F91AF5CF0FD60393009D8BE2 /* BreakpadFramework_Test.mm */, ++ ); ++ name = tests; ++ sourceTree = ""; ++ }; ++ F9C77E0F0F7DDF650045F7DB /* testing */ = { ++ isa = PBXGroup; ++ children = ( ++ F9C77E110F7DDF810045F7DB /* GTMSenTestCase.h */, ++ F9C77E120F7DDF810045F7DB /* GTMSenTestCase.m */, ++ ); ++ name = testing; ++ sourceTree = ""; ++ }; ++/* End PBXGroup section */ ++ ++/* Begin PBXHeadersBuildPhase section */ ++ 8DC2EF500486A6940098B216 /* Headers */ = { ++ isa = PBXHeadersBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ F92C55D00ECD0064009BE4BA /* Breakpad.h in Headers */, ++ F92C56330ECD0DF1009BE4BA /* OnDemandServer.h in Headers */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ F92C56380ECD10B3009BE4BA /* Headers */ = { ++ isa = PBXHeadersBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++/* End PBXHeadersBuildPhase section */ ++ ++/* Begin PBXNativeTarget section */ ++ 8DC2EF4F0486A6940098B216 /* Breakpad */ = { ++ isa = PBXNativeTarget; ++ buildConfigurationList = 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "Breakpad" */; ++ buildPhases = ( ++ F97A0E850ED4EC15008784D3 /* Change install name of breakpadUtilities */, ++ 8DC2EF500486A6940098B216 /* Headers */, ++ 8DC2EF520486A6940098B216 /* Resources */, ++ 8DC2EF540486A6940098B216 /* Sources */, ++ 8DC2EF560486A6940098B216 /* Frameworks */, ++ ); ++ buildRules = ( ++ ); ++ dependencies = ( ++ F92C56860ECD15EF009BE4BA /* PBXTargetDependency */, ++ F92C56880ECD15F1009BE4BA /* PBXTargetDependency */, ++ F9C44E970EF09F4B003AEBAA /* PBXTargetDependency */, ++ ); ++ name = Breakpad; ++ productInstallPath = "$(HOME)/Library/Frameworks"; ++ productName = Breakpad; ++ productReference = 8DC2EF5B0486A6940098B216 /* Breakpad.framework */; ++ productType = "com.apple.product-type.framework"; ++ }; ++ F92C53530ECCE349009BE4BA /* Inspector */ = { ++ isa = PBXNativeTarget; ++ buildConfigurationList = F92C53580ECCE36D009BE4BA /* Build configuration list for PBXNativeTarget "Inspector" */; ++ buildPhases = ( ++ F94584840F27FB40009A47BF /* Change install name of breakpadUtilities */, ++ F92C53510ECCE349009BE4BA /* Sources */, ++ F92C53520ECCE349009BE4BA /* Frameworks */, ++ ); ++ buildRules = ( ++ ); ++ dependencies = ( ++ F92C564E0ECD10E5009BE4BA /* PBXTargetDependency */, ++ ); ++ name = Inspector; ++ productName = Inspector; ++ productReference = F92C53540ECCE349009BE4BA /* Inspector */; ++ productType = "com.apple.product-type.tool"; ++ }; ++ F92C563B0ECD10B3009BE4BA /* breakpadUtilities */ = { ++ isa = PBXNativeTarget; ++ buildConfigurationList = F92C56670ECD11A3009BE4BA /* Build configuration list for PBXNativeTarget "breakpadUtilities" */; ++ buildPhases = ( ++ F92C56380ECD10B3009BE4BA /* Headers */, ++ F92C56390ECD10B3009BE4BA /* Sources */, ++ F92C563A0ECD10B3009BE4BA /* Frameworks */, ++ ); ++ buildRules = ( ++ ); ++ dependencies = ( ++ ); ++ name = breakpadUtilities; ++ productName = breakpadUtilities; ++ productReference = F92C563C0ECD10B3009BE4BA /* breakpadUtilities.dylib */; ++ productType = "com.apple.product-type.library.dynamic"; ++ }; ++ F92C569F0ECE04A7009BE4BA /* crash_report_sender */ = { ++ isa = PBXNativeTarget; ++ buildConfigurationList = F92C56A50ECE04A8009BE4BA /* Build configuration list for PBXNativeTarget "crash_report_sender" */; ++ buildPhases = ( ++ F92C569C0ECE04A7009BE4BA /* Resources */, ++ F92C569D0ECE04A7009BE4BA /* Sources */, ++ F92C569E0ECE04A7009BE4BA /* Frameworks */, ++ ); ++ buildRules = ( ++ ); ++ dependencies = ( ++ ); ++ name = crash_report_sender; ++ productName = crash_report_sender; ++ productReference = F92C56A00ECE04A7009BE4BA /* crash_report_sender.app */; ++ productType = "com.apple.product-type.application"; ++ }; ++ F93803BD0F80820F004D428B /* generator_test */ = { ++ isa = PBXNativeTarget; ++ buildConfigurationList = F93803C40F80822E004D428B /* Build configuration list for PBXNativeTarget "generator_test" */; ++ buildPhases = ( ++ F93803BB0F80820F004D428B /* Sources */, ++ F93803BC0F80820F004D428B /* Frameworks */, ++ ); ++ buildRules = ( ++ ); ++ dependencies = ( ++ ); ++ name = generator_test; ++ productName = generator_test; ++ productReference = F93803BE0F80820F004D428B /* generator_test */; ++ productType = "com.apple.product-type.tool"; ++ }; ++ F93DE2D00F82A67300608B94 /* minidump_file_writer_unittest */ = { ++ isa = PBXNativeTarget; ++ buildConfigurationList = F93DE2D60F82A67700608B94 /* Build configuration list for PBXNativeTarget "minidump_file_writer_unittest" */; ++ buildPhases = ( ++ F93DE2CE0F82A67300608B94 /* Sources */, ++ F93DE2CF0F82A67300608B94 /* Frameworks */, ++ ); ++ buildRules = ( ++ ); ++ dependencies = ( ++ ); ++ name = minidump_file_writer_unittest; ++ productName = minidump_file_writer_unittest; ++ productReference = F93DE2D10F82A67300608B94 /* minidump_file_writer_unittest */; ++ productType = "com.apple.product-type.tool"; ++ }; ++ F93DE32B0F82C55600608B94 /* handler_test */ = { ++ isa = PBXNativeTarget; ++ buildConfigurationList = F93DE3320F82C5D800608B94 /* Build configuration list for PBXNativeTarget "handler_test" */; ++ buildPhases = ( ++ F93DE3290F82C55600608B94 /* Sources */, ++ F93DE32A0F82C55600608B94 /* Frameworks */, ++ ); ++ buildRules = ( ++ ); ++ dependencies = ( ++ ); ++ name = handler_test; ++ productName = handler_test; ++ productReference = F93DE32C0F82C55600608B94 /* handler_test */; ++ productType = "com.apple.product-type.tool"; ++ }; ++ F9C44DA40EF060A8003AEBAA /* BreakpadTest */ = { ++ isa = PBXNativeTarget; ++ buildConfigurationList = F9C44DAA0EF060A9003AEBAA /* Build configuration list for PBXNativeTarget "BreakpadTest" */; ++ buildPhases = ( ++ F9C44DA10EF060A8003AEBAA /* Resources */, ++ F9C44DA20EF060A8003AEBAA /* Sources */, ++ F9C44DA30EF060A8003AEBAA /* Frameworks */, ++ F9C44E410EF08B17003AEBAA /* Copy Frameworks */, ++ ); ++ buildRules = ( ++ ); ++ dependencies = ( ++ F9C44E1A0EF0790F003AEBAA /* PBXTargetDependency */, ++ ); ++ name = BreakpadTest; ++ productName = BreakpadTest; ++ productReference = F9C44DA50EF060A8003AEBAA /* BreakpadTest.app */; ++ productType = "com.apple.product-type.application"; ++ }; ++ F9C77DD90F7DD5CF0045F7DB /* UnitTests */ = { ++ isa = PBXNativeTarget; ++ buildConfigurationList = F9C77DDE0F7DD5D00045F7DB /* Build configuration list for PBXNativeTarget "UnitTests" */; ++ buildPhases = ( ++ F9C77DD50F7DD5CF0045F7DB /* Resources */, ++ F9C77DD60F7DD5CF0045F7DB /* Sources */, ++ F9C77DD70F7DD5CF0045F7DB /* Frameworks */, ++ F9C77DD80F7DD5CF0045F7DB /* ShellScript */, ++ ); ++ buildRules = ( ++ ); ++ dependencies = ( ++ F93DE2FC0F82C3C600608B94 /* PBXTargetDependency */, ++ F93DE3700F82CC1300608B94 /* PBXTargetDependency */, ++ F91AF6380FD60A74009D8BE2 /* PBXTargetDependency */, ++ ); ++ name = UnitTests; ++ productName = UnitTests; ++ productReference = F9C77DDA0F7DD5CF0045F7DB /* UnitTests.octest */; ++ productType = "com.apple.product-type.bundle"; ++ }; ++/* End PBXNativeTarget section */ ++ ++/* Begin PBXProject section */ ++ 0867D690FE84028FC02AAC07 /* Project object */ = { ++ isa = PBXProject; ++ buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "Breakpad" */; ++ compatibilityVersion = "Xcode 2.4"; ++ hasScannedForEncodings = 1; ++ mainGroup = 0867D691FE84028FC02AAC07 /* Breakpad */; ++ productRefGroup = 034768DFFF38A50411DB9C8B /* Products */; ++ projectDirPath = ""; ++ projectReferences = ( ++ { ++ ProductGroup = F95BB87D101F949F00AA053B /* Products */; ++ ProjectRef = F95BB87C101F949F00AA053B /* crash_report.xcodeproj */; ++ }, ++ { ++ ProductGroup = F95BB88A101F94AC00AA053B /* Products */; ++ ProjectRef = F95BB889101F94AC00AA053B /* dump_syms.xcodeproj */; ++ }, ++ { ++ ProductGroup = F95BB895101F94C000AA053B /* Products */; ++ ProjectRef = F95BB894101F94C000AA053B /* symupload.xcodeproj */; ++ }, ++ ); ++ projectRoot = ""; ++ targets = ( ++ 8DC2EF4F0486A6940098B216 /* Breakpad */, ++ F92C53530ECCE349009BE4BA /* Inspector */, ++ F92C563B0ECD10B3009BE4BA /* breakpadUtilities */, ++ F92C569F0ECE04A7009BE4BA /* crash_report_sender */, ++ F9C44DA40EF060A8003AEBAA /* BreakpadTest */, ++ F94585840F782326009A47BF /* All */, ++ F9C77DD90F7DD5CF0045F7DB /* UnitTests */, ++ F93803BD0F80820F004D428B /* generator_test */, ++ F93DE2D00F82A67300608B94 /* minidump_file_writer_unittest */, ++ F93DE32B0F82C55600608B94 /* handler_test */, ++ ); ++ }; ++/* End PBXProject section */ ++ ++/* Begin PBXReferenceProxy section */ ++ F95BB885101F949F00AA053B /* crash_report */ = { ++ isa = PBXReferenceProxy; ++ fileType = "compiled.mach-o.executable"; ++ path = crash_report; ++ remoteRef = F95BB884101F949F00AA053B /* PBXContainerItemProxy */; ++ sourceTree = BUILT_PRODUCTS_DIR; ++ }; ++ F95BB892101F94AC00AA053B /* dump_syms */ = { ++ isa = PBXReferenceProxy; ++ fileType = "compiled.mach-o.executable"; ++ path = dump_syms; ++ remoteRef = F95BB891101F94AC00AA053B /* PBXContainerItemProxy */; ++ sourceTree = BUILT_PRODUCTS_DIR; ++ }; ++ F95BB89F101F94C000AA053B /* symupload */ = { ++ isa = PBXReferenceProxy; ++ fileType = "compiled.mach-o.executable"; ++ path = symupload; ++ remoteRef = F95BB89E101F94C000AA053B /* PBXContainerItemProxy */; ++ sourceTree = BUILT_PRODUCTS_DIR; ++ }; ++ F95BB8A1101F94C000AA053B /* minidump_upload */ = { ++ isa = PBXReferenceProxy; ++ fileType = "compiled.mach-o.executable"; ++ path = minidump_upload; ++ remoteRef = F95BB8A0101F94C000AA053B /* PBXContainerItemProxy */; ++ sourceTree = BUILT_PRODUCTS_DIR; ++ }; ++/* End PBXReferenceProxy section */ ++ ++/* Begin PBXResourcesBuildPhase section */ ++ 8DC2EF520486A6940098B216 /* Resources */ = { ++ isa = PBXResourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ F9C44E980EF09F56003AEBAA /* crash_report_sender.app in Resources */, ++ F92C568A0ECD15F9009BE4BA /* Inspector in Resources */, ++ F92C56650ECD1185009BE4BA /* breakpadUtilities.dylib in Resources */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ F92C569C0ECE04A7009BE4BA /* Resources */ = { ++ isa = PBXResourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ F945849E0F280E3C009A47BF /* Localizable.strings in Resources */, ++ 4084699D0F5D9CF900FDCA37 /* crash_report_sender.icns in Resources */, ++ 33880C800F9E097100817F82 /* InfoPlist.strings in Resources */, ++ 3329D4ED0FA16D820007BBC5 /* Breakpad.nib in Resources */, ++ F9B630A0100FF96B00D0F4AC /* goArrow.png in Resources */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ F9C44DA10EF060A8003AEBAA /* Resources */ = { ++ isa = PBXResourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ F9C44DB30EF07288003AEBAA /* crashduringload in Resources */, ++ F9C44DB40EF07288003AEBAA /* crashInMain in Resources */, ++ F9C44DBC0EF072A0003AEBAA /* InfoPlist.strings in Resources */, ++ F9C44DBD0EF072A0003AEBAA /* MainMenu.nib in Resources */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ F9C77DD50F7DD5CF0045F7DB /* Resources */ = { ++ isa = PBXResourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++/* End PBXResourcesBuildPhase section */ ++ ++/* Begin PBXShellScriptBuildPhase section */ ++ F94584840F27FB40009A47BF /* Change install name of breakpadUtilities */ = { ++ isa = PBXShellScriptBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ ); ++ inputPaths = ( ++ ); ++ name = "Change install name of breakpadUtilities"; ++ outputPaths = ( ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ shellPath = /bin/sh; ++ shellScript = "install_name_tool -id \"@executable_path/../Resources/breakpadUtilities.dylib\" \"${BUILT_PRODUCTS_DIR}/breakpadUtilities.dylib\"\n"; ++ }; ++ F97A0E850ED4EC15008784D3 /* Change install name of breakpadUtilities */ = { ++ isa = PBXShellScriptBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ ); ++ inputPaths = ( ++ ); ++ name = "Change install name of breakpadUtilities"; ++ outputPaths = ( ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ shellPath = /bin/sh; ++ shellScript = "#!/bin/bash\ninstall_name_tool -id \"@executable_path/../Frameworks/Breakpad.framework/Resources/breakpadUtilities.dylib\" \"${BUILT_PRODUCTS_DIR}/breakpadUtilities.dylib\"\n"; ++ }; ++ F9C77DD80F7DD5CF0045F7DB /* ShellScript */ = { ++ isa = PBXShellScriptBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ ); ++ inputPaths = ( ++ ); ++ outputPaths = ( ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ shellPath = /bin/sh; ++ shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n\necho running minidump generator tests...\n\"${BUILT_PRODUCTS_DIR}/generator_test\"\necho Running exception handler tests...\n\"${BUILT_PRODUCTS_DIR}/handler_test\"\n"; ++ }; ++/* End PBXShellScriptBuildPhase section */ ++ ++/* Begin PBXSourcesBuildPhase section */ ++ 8DC2EF540486A6940098B216 /* Sources */ = { ++ isa = PBXSourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ F92C565F0ECD116B009BE4BA /* protected_memory_allocator.cc in Sources */, ++ F92C56630ECD1179009BE4BA /* exception_handler.cc in Sources */, ++ F92C55D10ECD0064009BE4BA /* Breakpad.mm in Sources */, ++ F92C56340ECD0DF1009BE4BA /* OnDemandServer.mm in Sources */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ F92C53510ECCE349009BE4BA /* Sources */ = { ++ isa = PBXSourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ F92C53B80ECCE7B3009BE4BA /* Inspector.mm in Sources */, ++ F9286B3A0F7EB25800A4DCC8 /* InspectorMain.mm in Sources */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ F92C56390ECD10B3009BE4BA /* Sources */ = { ++ isa = PBXSourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ F92C563F0ECD10CA009BE4BA /* convert_UTF.c in Sources */, ++ F92C56400ECD10CA009BE4BA /* dynamic_images.cc in Sources */, ++ F92C56410ECD10CA009BE4BA /* file_id.cc in Sources */, ++ F92C56420ECD10CA009BE4BA /* macho_id.cc in Sources */, ++ F92C56430ECD10CA009BE4BA /* macho_utilities.cc in Sources */, ++ F92C56440ECD10CA009BE4BA /* macho_walker.cc in Sources */, ++ F92C56450ECD10CA009BE4BA /* MachIPC.mm in Sources */, ++ F92C56460ECD10CA009BE4BA /* minidump_file_writer.cc in Sources */, ++ F92C56470ECD10CA009BE4BA /* minidump_generator.cc in Sources */, ++ F92C56480ECD10CA009BE4BA /* SimpleStringDictionary.mm in Sources */, ++ F92C56490ECD10CA009BE4BA /* string_utilities.cc in Sources */, ++ F92C564A0ECD10CA009BE4BA /* string_conversion.cc in Sources */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ F92C569D0ECE04A7009BE4BA /* Sources */ = { ++ isa = PBXSourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ F9C44EA20EF09F93003AEBAA /* HTTPMultipartUpload.m in Sources */, ++ F92C56A90ECE04C5009BE4BA /* crash_report_sender.m in Sources */, ++ F9C44EE90EF0A3C1003AEBAA /* GTMLogger.m in Sources */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ F93803BB0F80820F004D428B /* Sources */ = { ++ isa = PBXSourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ F93803CD0F8083B7004D428B /* dynamic_images.cc in Sources */, ++ F93803CE0F8083B7004D428B /* exception_handler.cc in Sources */, ++ F93803CF0F8083B7004D428B /* minidump_generator.cc in Sources */, ++ F93803D00F8083B7004D428B /* minidump_file_writer.cc in Sources */, ++ F93803D10F8083B7004D428B /* convert_UTF.c in Sources */, ++ F93803D20F8083B7004D428B /* string_conversion.cc in Sources */, ++ F93803D30F8083B7004D428B /* file_id.cc in Sources */, ++ F93803D40F8083B7004D428B /* macho_id.cc in Sources */, ++ F93803D50F8083B7004D428B /* macho_utilities.cc in Sources */, ++ F93803D60F8083B7004D428B /* macho_walker.cc in Sources */, ++ F93803D70F8083B7004D428B /* string_utilities.cc in Sources */, ++ F93803DA0F8083D8004D428B /* minidump_generator_test.cc in Sources */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ F93DE2CE0F82A67300608B94 /* Sources */ = { ++ isa = PBXSourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ F93DE2D90F82A73500608B94 /* minidump_file_writer.cc in Sources */, ++ F93DE2DA0F82A73500608B94 /* convert_UTF.c in Sources */, ++ F93DE2DB0F82A73500608B94 /* string_conversion.cc in Sources */, ++ F93DE2D80F82A70E00608B94 /* minidump_file_writer_unittest.cc in Sources */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ F93DE3290F82C55600608B94 /* Sources */ = { ++ isa = PBXSourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ F93DE3350F82C66B00608B94 /* dynamic_images.cc in Sources */, ++ F93DE3360F82C66B00608B94 /* exception_handler.cc in Sources */, ++ F93DE3370F82C66B00608B94 /* minidump_generator.cc in Sources */, ++ F93DE3380F82C66B00608B94 /* minidump_file_writer.cc in Sources */, ++ F93DE3390F82C66B00608B94 /* convert_UTF.c in Sources */, ++ F93DE33A0F82C66B00608B94 /* string_conversion.cc in Sources */, ++ F93DE33B0F82C66B00608B94 /* file_id.cc in Sources */, ++ F93DE33C0F82C66B00608B94 /* macho_id.cc in Sources */, ++ F93DE33D0F82C66B00608B94 /* macho_utilities.cc in Sources */, ++ F93DE33E0F82C66B00608B94 /* macho_walker.cc in Sources */, ++ F93DE33F0F82C66B00608B94 /* string_utilities.cc in Sources */, ++ F93DE3410F82C68300608B94 /* exception_handler_test.cc in Sources */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ F9C44DA20EF060A8003AEBAA /* Sources */ = { ++ isa = PBXSourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ F9C44DB20EF07288003AEBAA /* Controller.m in Sources */, ++ F9C44DB60EF07288003AEBAA /* main.m in Sources */, ++ F9C44DB70EF07288003AEBAA /* TestClass.mm in Sources */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++ F9C77DD60F7DD5CF0045F7DB /* Sources */ = { ++ isa = PBXSourcesBuildPhase; ++ buildActionMask = 2147483647; ++ files = ( ++ F9C77DE40F7DD82F0045F7DB /* SimpleStringDictionary.mm in Sources */, ++ F9C77DE20F7DD7E30045F7DB /* SimpleStringDictionaryTest.mm in Sources */, ++ F9C77E130F7DDF810045F7DB /* GTMSenTestCase.m in Sources */, ++ F91AF5D00FD60393009D8BE2 /* BreakpadFramework_Test.mm in Sources */, ++ ); ++ runOnlyForDeploymentPostprocessing = 0; ++ }; ++/* End PBXSourcesBuildPhase section */ ++ ++/* Begin PBXTargetDependency section */ ++ F91AF6380FD60A74009D8BE2 /* PBXTargetDependency */ = { ++ isa = PBXTargetDependency; ++ target = 8DC2EF4F0486A6940098B216 /* Breakpad */; ++ targetProxy = F91AF6370FD60A74009D8BE2 /* PBXContainerItemProxy */; ++ }; ++ F92C564E0ECD10E5009BE4BA /* PBXTargetDependency */ = { ++ isa = PBXTargetDependency; ++ target = F92C563B0ECD10B3009BE4BA /* breakpadUtilities */; ++ targetProxy = F92C564D0ECD10E5009BE4BA /* PBXContainerItemProxy */; ++ }; ++ F92C56860ECD15EF009BE4BA /* PBXTargetDependency */ = { ++ isa = PBXTargetDependency; ++ target = F92C563B0ECD10B3009BE4BA /* breakpadUtilities */; ++ targetProxy = F92C56850ECD15EF009BE4BA /* PBXContainerItemProxy */; ++ }; ++ F92C56880ECD15F1009BE4BA /* PBXTargetDependency */ = { ++ isa = PBXTargetDependency; ++ target = F92C53530ECCE349009BE4BA /* Inspector */; ++ targetProxy = F92C56870ECD15F1009BE4BA /* PBXContainerItemProxy */; ++ }; ++ F93DE2FC0F82C3C600608B94 /* PBXTargetDependency */ = { ++ isa = PBXTargetDependency; ++ target = F93803BD0F80820F004D428B /* generator_test */; ++ targetProxy = F93DE2FB0F82C3C600608B94 /* PBXContainerItemProxy */; ++ }; ++ F93DE3700F82CC1300608B94 /* PBXTargetDependency */ = { ++ isa = PBXTargetDependency; ++ target = F93DE32B0F82C55600608B94 /* handler_test */; ++ targetProxy = F93DE36F0F82CC1300608B94 /* PBXContainerItemProxy */; ++ }; ++ F93DE3A70F830D1D00608B94 /* PBXTargetDependency */ = { ++ isa = PBXTargetDependency; ++ target = F9C77DD90F7DD5CF0045F7DB /* UnitTests */; ++ targetProxy = F93DE3A60F830D1D00608B94 /* PBXContainerItemProxy */; ++ }; ++ F94585880F78232B009A47BF /* PBXTargetDependency */ = { ++ isa = PBXTargetDependency; ++ target = 8DC2EF4F0486A6940098B216 /* Breakpad */; ++ targetProxy = F94585870F78232B009A47BF /* PBXContainerItemProxy */; ++ }; ++ F945858A0F78232E009A47BF /* PBXTargetDependency */ = { ++ isa = PBXTargetDependency; ++ target = F92C53530ECCE349009BE4BA /* Inspector */; ++ targetProxy = F94585890F78232E009A47BF /* PBXContainerItemProxy */; ++ }; ++ F945858C0F782330009A47BF /* PBXTargetDependency */ = { ++ isa = PBXTargetDependency; ++ target = F92C563B0ECD10B3009BE4BA /* breakpadUtilities */; ++ targetProxy = F945858B0F782330009A47BF /* PBXContainerItemProxy */; ++ }; ++ F945858E0F782333009A47BF /* PBXTargetDependency */ = { ++ isa = PBXTargetDependency; ++ target = F92C569F0ECE04A7009BE4BA /* crash_report_sender */; ++ targetProxy = F945858D0F782333009A47BF /* PBXContainerItemProxy */; ++ }; ++ F94585900F782336009A47BF /* PBXTargetDependency */ = { ++ isa = PBXTargetDependency; ++ target = F9C44DA40EF060A8003AEBAA /* BreakpadTest */; ++ targetProxy = F945858F0F782336009A47BF /* PBXContainerItemProxy */; ++ }; ++ F95BB8B3101F94D300AA053B /* PBXTargetDependency */ = { ++ isa = PBXTargetDependency; ++ name = dump_syms; ++ targetProxy = F95BB8B2101F94D300AA053B /* PBXContainerItemProxy */; ++ }; ++ F95BB8B5101F94D300AA053B /* PBXTargetDependency */ = { ++ isa = PBXTargetDependency; ++ name = symupload; ++ targetProxy = F95BB8B4101F94D300AA053B /* PBXContainerItemProxy */; ++ }; ++ F95BB8B7101F94D300AA053B /* PBXTargetDependency */ = { ++ isa = PBXTargetDependency; ++ name = crash_report; ++ targetProxy = F95BB8B6101F94D300AA053B /* PBXContainerItemProxy */; ++ }; ++ F9C44E1A0EF0790F003AEBAA /* PBXTargetDependency */ = { ++ isa = PBXTargetDependency; ++ target = 8DC2EF4F0486A6940098B216 /* Breakpad */; ++ targetProxy = F9C44E190EF0790F003AEBAA /* PBXContainerItemProxy */; ++ }; ++ F9C44E970EF09F4B003AEBAA /* PBXTargetDependency */ = { ++ isa = PBXTargetDependency; ++ target = F92C569F0ECE04A7009BE4BA /* crash_report_sender */; ++ targetProxy = F9C44E960EF09F4B003AEBAA /* PBXContainerItemProxy */; ++ }; ++/* End PBXTargetDependency section */ ++ ++/* Begin PBXVariantGroup section */ ++ 33880C7E0F9E097100817F82 /* InfoPlist.strings */ = { ++ isa = PBXVariantGroup; ++ children = ( ++ 33880C7F0F9E097100817F82 /* English */, ++ ); ++ name = InfoPlist.strings; ++ sourceTree = ""; ++ }; ++ F945849C0F280E3C009A47BF /* Localizable.strings */ = { ++ isa = PBXVariantGroup; ++ children = ( ++ F945849D0F280E3C009A47BF /* English */, ++ ); ++ name = Localizable.strings; ++ sourceTree = ""; ++ }; ++ F9C44DB80EF072A0003AEBAA /* InfoPlist.strings */ = { ++ isa = PBXVariantGroup; ++ children = ( ++ F9C44DB90EF072A0003AEBAA /* English */, ++ ); ++ name = InfoPlist.strings; ++ sourceTree = ""; ++ }; ++ F9C44DBA0EF072A0003AEBAA /* MainMenu.nib */ = { ++ isa = PBXVariantGroup; ++ children = ( ++ F9C44DBB0EF072A0003AEBAA /* English */, ++ ); ++ name = MainMenu.nib; ++ sourceTree = ""; ++ }; ++/* End PBXVariantGroup section */ ++ ++/* Begin XCBuildConfiguration section */ ++ 1DEB91AE08733DA50010E9CD /* Debug */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ COPY_PHASE_STRIP = NO; ++ DYLIB_COMPATIBILITY_VERSION = 1; ++ DYLIB_CURRENT_VERSION = 1; ++ FRAMEWORK_VERSION = A; ++ GCC_DYNAMIC_NO_PIC = NO; ++ GCC_ENABLE_FIX_AND_CONTINUE = YES; ++ GCC_MODEL_TUNING = G5; ++ GCC_OPTIMIZATION_LEVEL = 0; ++ GCC_PRECOMPILE_PREFIX_HEADER = YES; ++ GCC_PREFIX_HEADER = Framework/Breakpad_Prefix.pch; ++ HEADER_SEARCH_PATHS = "../..//**"; ++ INFOPLIST_FILE = Framework/Info.plist; ++ INSTALL_PATH = "@executable_path/../Frameworks"; ++ PRODUCT_NAME = Breakpad; ++ WRAPPER_EXTENSION = framework; ++ }; ++ name = Debug; ++ }; ++ 1DEB91AF08733DA50010E9CD /* Release */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ++ DYLIB_COMPATIBILITY_VERSION = 1; ++ DYLIB_CURRENT_VERSION = 1; ++ FRAMEWORK_VERSION = A; ++ GCC_PRECOMPILE_PREFIX_HEADER = YES; ++ GCC_PREFIX_HEADER = Framework/Breakpad_Prefix.pch; ++ HEADER_SEARCH_PATHS = "../..//**"; ++ INFOPLIST_FILE = Framework/Info.plist; ++ INSTALL_PATH = "@executable_path/../Frameworks"; ++ PRODUCT_NAME = Breakpad; ++ WRAPPER_EXTENSION = framework; ++ }; ++ name = Release; ++ }; ++ 1DEB91B208733DA50010E9CD /* Debug */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ARCHS = "$(ONLY_ACTIVE_ARCH_PRE_XCODE_3_1)"; ++ GCC_C_LANGUAGE_STANDARD = c99; ++ GCC_OPTIMIZATION_LEVEL = 0; ++ GCC_WARN_ABOUT_RETURN_TYPE = YES; ++ GCC_WARN_UNUSED_VARIABLE = YES; ++ ONLY_ACTIVE_ARCH_PRE_XCODE_3_1 = "$(NATIVE_ARCH)"; ++ PREBINDING = NO; ++ SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk; ++ }; ++ name = Debug; ++ }; ++ 1DEB91B308733DA50010E9CD /* Release */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ARCHS = "$(ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1)"; ++ ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1 = "ppc i386"; ++ GCC_C_LANGUAGE_STANDARD = c99; ++ GCC_WARN_ABOUT_RETURN_TYPE = YES; ++ GCC_WARN_UNUSED_VARIABLE = YES; ++ HEADER_SEARCH_PATHS = "../..//**"; ++ PREBINDING = NO; ++ SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk; ++ }; ++ name = Release; ++ }; ++ F92C53560ECCE34A009BE4BA /* Debug */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ COPY_PHASE_STRIP = NO; ++ GCC_DYNAMIC_NO_PIC = NO; ++ GCC_ENABLE_FIX_AND_CONTINUE = YES; ++ GCC_MODEL_TUNING = G5; ++ GCC_OPTIMIZATION_LEVEL = 0; ++ HEADER_SEARCH_PATHS = "../..//**"; ++ INSTALL_PATH = /usr/local/bin; ++ OTHER_LDFLAGS = ( ++ "-lcrypto", ++ "$(inherited)", ++ ); ++ PREBINDING = NO; ++ PRODUCT_NAME = Inspector; ++ }; ++ name = Debug; ++ }; ++ F92C53570ECCE34A009BE4BA /* Release */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ COPY_PHASE_STRIP = YES; ++ DEAD_CODE_STRIPPING = YES; ++ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ++ GCC_ENABLE_FIX_AND_CONTINUE = NO; ++ HEADER_SEARCH_PATHS = "../..//**"; ++ INSTALL_PATH = /usr/local/bin; ++ LD_GENERATE_MAP_FILE = YES; ++ OTHER_LDFLAGS = ( ++ "$(inherited)", ++ "-lcrypto", ++ ); ++ PREBINDING = NO; ++ PRODUCT_NAME = Inspector; ++ ZERO_LINK = NO; ++ }; ++ name = Release; ++ }; ++ F92C563D0ECD10B3009BE4BA /* Debug */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ COPY_PHASE_STRIP = NO; ++ DYLIB_COMPATIBILITY_VERSION = 1; ++ DYLIB_CURRENT_VERSION = 1; ++ GCC_DYNAMIC_NO_PIC = NO; ++ GCC_ENABLE_FIX_AND_CONTINUE = YES; ++ GCC_MODEL_TUNING = G5; ++ GCC_OPTIMIZATION_LEVEL = 0; ++ GCC_PRECOMPILE_PREFIX_HEADER = YES; ++ HEADER_SEARCH_PATHS = "../..//**"; ++ INSTALL_PATH = /usr/local/lib; ++ LD_DYLIB_INSTALL_NAME = "@executable_path/../Resources/$(EXECUTABLE_PATH)"; ++ OTHER_LDFLAGS = ( ++ "$(inherited)", ++ "-headerpad_max_install_names", ++ "-lcrypto", ++ ); ++ PREBINDING = NO; ++ PRODUCT_NAME = breakpadUtilities; ++ }; ++ name = Debug; ++ }; ++ F92C563E0ECD10B3009BE4BA /* Release */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ COPY_PHASE_STRIP = YES; ++ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ++ DYLIB_COMPATIBILITY_VERSION = 1; ++ DYLIB_CURRENT_VERSION = 1; ++ GCC_ENABLE_FIX_AND_CONTINUE = NO; ++ GCC_PRECOMPILE_PREFIX_HEADER = YES; ++ HEADER_SEARCH_PATHS = "../..//**"; ++ INSTALL_PATH = /usr/local/lib; ++ LD_DYLIB_INSTALL_NAME = "@executable_path/../Resources/$(EXECUTABLE_PATH)"; ++ OTHER_LDFLAGS = ( ++ "$(inherited)", ++ "-headerpad_max_install_names", ++ "-lcrypto", ++ ); ++ PREBINDING = NO; ++ PRODUCT_NAME = breakpadUtilities; ++ ZERO_LINK = NO; ++ }; ++ name = Release; ++ }; ++ F92C56A30ECE04A8009BE4BA /* Debug */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ COPY_PHASE_STRIP = NO; ++ GCC_DYNAMIC_NO_PIC = NO; ++ GCC_ENABLE_FIX_AND_CONTINUE = YES; ++ GCC_MODEL_TUNING = G5; ++ GCC_OPTIMIZATION_LEVEL = 0; ++ GCC_PRECOMPILE_PREFIX_HEADER = YES; ++ HEADER_SEARCH_PATHS = "../..//**"; ++ INFOPLIST_FILE = "sender/crash_report_sender-Info.plist"; ++ INSTALL_PATH = "$(HOME)/Applications"; ++ OTHER_LDFLAGS = ( ++ "-framework", ++ Foundation, ++ "-framework", ++ AppKit, ++ ); ++ PREBINDING = NO; ++ PRODUCT_NAME = crash_report_sender; ++ }; ++ name = Debug; ++ }; ++ F92C56A40ECE04A8009BE4BA /* Release */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ COPY_PHASE_STRIP = YES; ++ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ++ GCC_ENABLE_FIX_AND_CONTINUE = NO; ++ GCC_PRECOMPILE_PREFIX_HEADER = YES; ++ HEADER_SEARCH_PATHS = "../..//**"; ++ INFOPLIST_FILE = "sender/crash_report_sender-Info.plist"; ++ INSTALL_PATH = "$(HOME)/Applications"; ++ OTHER_LDFLAGS = ( ++ "-framework", ++ Foundation, ++ "-framework", ++ AppKit, ++ ); ++ PREBINDING = NO; ++ PRODUCT_NAME = crash_report_sender; ++ ZERO_LINK = NO; ++ }; ++ name = Release; ++ }; ++ F93803C00F808210004D428B /* Debug */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ COPY_PHASE_STRIP = NO; ++ GCC_DYNAMIC_NO_PIC = NO; ++ GCC_ENABLE_FIX_AND_CONTINUE = YES; ++ GCC_MODEL_TUNING = G5; ++ GCC_OPTIMIZATION_LEVEL = 0; ++ INSTALL_PATH = /usr/local/bin; ++ OTHER_LDFLAGS = ( ++ "-lcrypto", ++ "-framework", ++ Foundation, ++ ); ++ PREBINDING = NO; ++ PRODUCT_NAME = generator_test; ++ USER_HEADER_SEARCH_PATHS = ../../; ++ }; ++ name = Debug; ++ }; ++ F93803C10F808210004D428B /* Release */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ COPY_PHASE_STRIP = YES; ++ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ++ GCC_ENABLE_FIX_AND_CONTINUE = NO; ++ GCC_MODEL_TUNING = G5; ++ INSTALL_PATH = /usr/local/bin; ++ OTHER_LDFLAGS = ( ++ "-lcrypto", ++ "-framework", ++ Foundation, ++ ); ++ PREBINDING = NO; ++ PRODUCT_NAME = generator_test; ++ ZERO_LINK = NO; ++ }; ++ name = Release; ++ }; ++ F93DE2D30F82A67400608B94 /* Debug */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ COPY_PHASE_STRIP = NO; ++ GCC_CHAR_IS_UNSIGNED_CHAR = YES; ++ GCC_DYNAMIC_NO_PIC = NO; ++ GCC_ENABLE_FIX_AND_CONTINUE = YES; ++ GCC_MODEL_TUNING = G5; ++ GCC_OPTIMIZATION_LEVEL = 0; ++ INSTALL_PATH = /usr/local/bin; ++ OTHER_LDFLAGS = ( ++ "-framework", ++ Foundation, ++ "-framework", ++ AppKit, ++ ); ++ PREBINDING = NO; ++ PRODUCT_NAME = minidump_file_writer_unittest; ++ USER_HEADER_SEARCH_PATHS = ../../; ++ }; ++ name = Debug; ++ }; ++ F93DE2D40F82A67400608B94 /* Release */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ COPY_PHASE_STRIP = YES; ++ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ++ GCC_ENABLE_FIX_AND_CONTINUE = NO; ++ GCC_MODEL_TUNING = G5; ++ INSTALL_PATH = /usr/local/bin; ++ OTHER_LDFLAGS = ( ++ "-framework", ++ Foundation, ++ "-framework", ++ AppKit, ++ ); ++ PREBINDING = NO; ++ PRODUCT_NAME = minidump_file_writer_unittest; ++ ZERO_LINK = NO; ++ }; ++ name = Release; ++ }; ++ F93DE32E0F82C55700608B94 /* Debug */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ COPY_PHASE_STRIP = NO; ++ GCC_DYNAMIC_NO_PIC = NO; ++ GCC_ENABLE_FIX_AND_CONTINUE = YES; ++ GCC_MODEL_TUNING = G5; ++ GCC_OPTIMIZATION_LEVEL = 0; ++ INSTALL_PATH = /usr/local/bin; ++ OTHER_LDFLAGS = ( ++ "-lcrypto", ++ "-framework", ++ Foundation, ++ ); ++ PREBINDING = NO; ++ PRODUCT_NAME = handler_test; ++ USER_HEADER_SEARCH_PATHS = ../../; ++ }; ++ name = Debug; ++ }; ++ F93DE32F0F82C55700608B94 /* Release */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ COPY_PHASE_STRIP = YES; ++ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ++ GCC_ENABLE_FIX_AND_CONTINUE = NO; ++ GCC_MODEL_TUNING = G5; ++ INSTALL_PATH = /usr/local/bin; ++ OTHER_LDFLAGS = ( ++ "-lcrypto", ++ "-framework", ++ Foundation, ++ ); ++ PREBINDING = NO; ++ PRODUCT_NAME = handler_test; ++ ZERO_LINK = NO; ++ }; ++ name = Release; ++ }; ++ F93DE3B90F830E7000608B94 /* Debug With Code Coverage */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ARCHS = "$(ONLY_ACTIVE_ARCH_PRE_XCODE_3_1)"; ++ GCC_C_LANGUAGE_STANDARD = c99; ++ GCC_OPTIMIZATION_LEVEL = 0; ++ GCC_WARN_ABOUT_RETURN_TYPE = YES; ++ GCC_WARN_UNUSED_VARIABLE = YES; ++ ONLY_ACTIVE_ARCH_PRE_XCODE_3_1 = "$(NATIVE_ARCH)"; ++ PREBINDING = NO; ++ SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk; ++ }; ++ name = "Debug With Code Coverage"; ++ }; ++ F93DE3BA0F830E7000608B94 /* Debug With Code Coverage */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ COPY_PHASE_STRIP = NO; ++ DYLIB_COMPATIBILITY_VERSION = 1; ++ DYLIB_CURRENT_VERSION = 1; ++ FRAMEWORK_VERSION = A; ++ GCC_DYNAMIC_NO_PIC = NO; ++ GCC_ENABLE_FIX_AND_CONTINUE = YES; ++ GCC_MODEL_TUNING = G5; ++ GCC_OPTIMIZATION_LEVEL = 0; ++ GCC_PRECOMPILE_PREFIX_HEADER = YES; ++ GCC_PREFIX_HEADER = Framework/Breakpad_Prefix.pch; ++ HEADER_SEARCH_PATHS = "../..//**"; ++ INFOPLIST_FILE = Framework/Info.plist; ++ INSTALL_PATH = "@executable_path/../Frameworks"; ++ PRODUCT_NAME = Breakpad; ++ WRAPPER_EXTENSION = framework; ++ }; ++ name = "Debug With Code Coverage"; ++ }; ++ F93DE3BB0F830E7000608B94 /* Debug With Code Coverage */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ COPY_PHASE_STRIP = NO; ++ GCC_DYNAMIC_NO_PIC = NO; ++ GCC_ENABLE_FIX_AND_CONTINUE = YES; ++ GCC_MODEL_TUNING = G5; ++ GCC_OPTIMIZATION_LEVEL = 0; ++ HEADER_SEARCH_PATHS = "../..//**"; ++ INSTALL_PATH = /usr/local/bin; ++ OTHER_LDFLAGS = ( ++ "-lcrypto", ++ "$(inherited)", ++ ); ++ PREBINDING = NO; ++ PRODUCT_NAME = Inspector; ++ }; ++ name = "Debug With Code Coverage"; ++ }; ++ F93DE3BC0F830E7000608B94 /* Debug With Code Coverage */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ COPY_PHASE_STRIP = NO; ++ DYLIB_COMPATIBILITY_VERSION = 1; ++ DYLIB_CURRENT_VERSION = 1; ++ GCC_DYNAMIC_NO_PIC = NO; ++ GCC_ENABLE_FIX_AND_CONTINUE = YES; ++ GCC_MODEL_TUNING = G5; ++ GCC_OPTIMIZATION_LEVEL = 0; ++ GCC_PRECOMPILE_PREFIX_HEADER = YES; ++ HEADER_SEARCH_PATHS = "../..//**"; ++ INSTALL_PATH = /usr/local/lib; ++ LD_DYLIB_INSTALL_NAME = "@executable_path/../Resources/$(EXECUTABLE_PATH)"; ++ OTHER_LDFLAGS = ( ++ "$(inherited)", ++ "-headerpad_max_install_names", ++ "-lcrypto", ++ ); ++ PREBINDING = NO; ++ PRODUCT_NAME = breakpadUtilities; ++ }; ++ name = "Debug With Code Coverage"; ++ }; ++ F93DE3BD0F830E7000608B94 /* Debug With Code Coverage */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ COPY_PHASE_STRIP = NO; ++ GCC_DYNAMIC_NO_PIC = NO; ++ GCC_ENABLE_FIX_AND_CONTINUE = YES; ++ GCC_MODEL_TUNING = G5; ++ GCC_OPTIMIZATION_LEVEL = 0; ++ GCC_PRECOMPILE_PREFIX_HEADER = YES; ++ HEADER_SEARCH_PATHS = "../..//**"; ++ INFOPLIST_FILE = "sender/crash_report_sender-Info.plist"; ++ INSTALL_PATH = "$(HOME)/Applications"; ++ OTHER_LDFLAGS = ( ++ "-framework", ++ Foundation, ++ "-framework", ++ AppKit, ++ ); ++ PREBINDING = NO; ++ PRODUCT_NAME = crash_report_sender; ++ }; ++ name = "Debug With Code Coverage"; ++ }; ++ F93DE3BE0F830E7000608B94 /* Debug With Code Coverage */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ COPY_PHASE_STRIP = NO; ++ FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/build/$(CONFIGURATION)"; ++ GCC_DYNAMIC_NO_PIC = NO; ++ GCC_ENABLE_FIX_AND_CONTINUE = YES; ++ GCC_MODEL_TUNING = G5; ++ GCC_OPTIMIZATION_LEVEL = 0; ++ GCC_PRECOMPILE_PREFIX_HEADER = YES; ++ GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; ++ INFOPLIST_FILE = testapp/Info.plist; ++ INSTALL_PATH = "$(HOME)/Applications"; ++ OTHER_LDFLAGS = ( ++ "-framework", ++ Foundation, ++ "-framework", ++ AppKit, ++ ); ++ PREBINDING = NO; ++ PRODUCT_NAME = BreakpadTest; ++ }; ++ name = "Debug With Code Coverage"; ++ }; ++ F93DE3BF0F830E7000608B94 /* Debug With Code Coverage */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ COPY_PHASE_STRIP = NO; ++ GCC_DYNAMIC_NO_PIC = NO; ++ GCC_OPTIMIZATION_LEVEL = 0; ++ PRODUCT_NAME = All; ++ }; ++ name = "Debug With Code Coverage"; ++ }; ++ F93DE3C00F830E7000608B94 /* Debug With Code Coverage */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ COPY_PHASE_STRIP = NO; ++ FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks"; ++ GCC_DYNAMIC_NO_PIC = NO; ++ GCC_ENABLE_OBJC_EXCEPTIONS = YES; ++ GCC_GENERATE_TEST_COVERAGE_FILES = YES; ++ GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; ++ GCC_MODEL_TUNING = G5; ++ GCC_OPTIMIZATION_LEVEL = 0; ++ GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Cocoa.framework/Headers/Cocoa.h"; ++ INFOPLIST_FILE = "UnitTests-Info.plist"; ++ INSTALL_PATH = "$(USER_LIBRARY_DIR)/Bundles"; ++ LIBRARY_SEARCH_PATHS = ./gcov; ++ OTHER_LDFLAGS = ( ++ "-lgcov", ++ "-framework", ++ Cocoa, ++ "-framework", ++ SenTestingKit, ++ ); ++ PREBINDING = NO; ++ PRODUCT_NAME = UnitTests; ++ USER_HEADER_SEARCH_PATHS = "../../ ../../common/mac/**"; ++ WRAPPER_EXTENSION = octest; ++ }; ++ name = "Debug With Code Coverage"; ++ }; ++ F93DE3C10F830E7000608B94 /* Debug With Code Coverage */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ COPY_PHASE_STRIP = NO; ++ GCC_DYNAMIC_NO_PIC = NO; ++ GCC_ENABLE_FIX_AND_CONTINUE = YES; ++ GCC_GENERATE_TEST_COVERAGE_FILES = YES; ++ GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; ++ GCC_MODEL_TUNING = G5; ++ GCC_OPTIMIZATION_LEVEL = 0; ++ INSTALL_PATH = /usr/local/bin; ++ LIBRARY_SEARCH_PATHS = ./gcov; ++ OTHER_LDFLAGS = ( ++ "-lgcov", ++ "-lcrypto", ++ "-framework", ++ Foundation, ++ ); ++ PREBINDING = NO; ++ PRODUCT_NAME = generator_test; ++ USER_HEADER_SEARCH_PATHS = ../../; ++ }; ++ name = "Debug With Code Coverage"; ++ }; ++ F93DE3C20F830E7000608B94 /* Debug With Code Coverage */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ COPY_PHASE_STRIP = NO; ++ GCC_CHAR_IS_UNSIGNED_CHAR = YES; ++ GCC_DYNAMIC_NO_PIC = NO; ++ GCC_ENABLE_FIX_AND_CONTINUE = YES; ++ GCC_GENERATE_TEST_COVERAGE_FILES = YES; ++ GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; ++ GCC_MODEL_TUNING = G5; ++ GCC_OPTIMIZATION_LEVEL = 0; ++ INSTALL_PATH = /usr/local/bin; ++ LIBRARY_SEARCH_PATHS = ./gcov; ++ OTHER_LDFLAGS = ( ++ "-lgcov", ++ "-framework", ++ Foundation, ++ "-framework", ++ AppKit, ++ ); ++ PREBINDING = NO; ++ PRODUCT_NAME = minidump_file_writer_unittest; ++ USER_HEADER_SEARCH_PATHS = ../../; ++ }; ++ name = "Debug With Code Coverage"; ++ }; ++ F93DE3C30F830E7000608B94 /* Debug With Code Coverage */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ COPY_PHASE_STRIP = NO; ++ GCC_DYNAMIC_NO_PIC = NO; ++ GCC_ENABLE_FIX_AND_CONTINUE = YES; ++ GCC_GENERATE_TEST_COVERAGE_FILES = YES; ++ GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; ++ GCC_MODEL_TUNING = G5; ++ GCC_OPTIMIZATION_LEVEL = 0; ++ INSTALL_PATH = /usr/local/bin; ++ LIBRARY_SEARCH_PATHS = ./gcov; ++ OTHER_LDFLAGS = ( ++ "-lcrypto", ++ "-lgcov", ++ "-framework", ++ Foundation, ++ ); ++ PREBINDING = NO; ++ PRODUCT_NAME = handler_test; ++ USER_HEADER_SEARCH_PATHS = ../../; ++ }; ++ name = "Debug With Code Coverage"; ++ }; ++ F94585850F782326009A47BF /* Debug */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ COPY_PHASE_STRIP = NO; ++ GCC_DYNAMIC_NO_PIC = NO; ++ GCC_OPTIMIZATION_LEVEL = 0; ++ PRODUCT_NAME = All; ++ }; ++ name = Debug; ++ }; ++ F94585860F782326009A47BF /* Release */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ COPY_PHASE_STRIP = YES; ++ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ++ GCC_ENABLE_FIX_AND_CONTINUE = NO; ++ PRODUCT_NAME = All; ++ ZERO_LINK = NO; ++ }; ++ name = Release; ++ }; ++ F9C44DA80EF060A8003AEBAA /* Debug */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ COPY_PHASE_STRIP = NO; ++ FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/build/$(CONFIGURATION)"; ++ GCC_DYNAMIC_NO_PIC = NO; ++ GCC_ENABLE_FIX_AND_CONTINUE = YES; ++ GCC_MODEL_TUNING = G5; ++ GCC_OPTIMIZATION_LEVEL = 0; ++ GCC_PRECOMPILE_PREFIX_HEADER = YES; ++ GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/AppKit.framework/Headers/AppKit.h"; ++ INFOPLIST_FILE = testapp/Info.plist; ++ INSTALL_PATH = "$(HOME)/Applications"; ++ OTHER_LDFLAGS = ( ++ "-framework", ++ Foundation, ++ "-framework", ++ AppKit, ++ ); ++ PREBINDING = NO; ++ PRODUCT_NAME = BreakpadTest; ++ }; ++ name = Debug; ++ }; ++ F9C44DA90EF060A8003AEBAA /* Release */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ COPY_PHASE_STRIP = YES; ++ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ++ FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/build/$(CONFIGURATION)"; ++ GCC_ENABLE_FIX_AND_CONTINUE = NO; ++ INFOPLIST_FILE = testapp/Info.plist; ++ INSTALL_PATH = "$(HOME)/Applications"; ++ OTHER_LDFLAGS = ( ++ "-framework", ++ Foundation, ++ "-framework", ++ AppKit, ++ ); ++ PREBINDING = NO; ++ PRODUCT_NAME = BreakpadTest; ++ ZERO_LINK = NO; ++ }; ++ name = Release; ++ }; ++ F9C77DDC0F7DD5D00045F7DB /* Debug */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ COPY_PHASE_STRIP = NO; ++ FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks"; ++ GCC_DYNAMIC_NO_PIC = NO; ++ GCC_ENABLE_OBJC_EXCEPTIONS = YES; ++ GCC_MODEL_TUNING = G5; ++ GCC_OPTIMIZATION_LEVEL = 0; ++ GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Cocoa.framework/Headers/Cocoa.h"; ++ INFOPLIST_FILE = "UnitTests-Info.plist"; ++ INSTALL_PATH = "$(USER_LIBRARY_DIR)/Bundles"; ++ OTHER_LDFLAGS = ( ++ "-framework", ++ Cocoa, ++ "-framework", ++ SenTestingKit, ++ ); ++ PREBINDING = NO; ++ PRODUCT_NAME = UnitTests; ++ USER_HEADER_SEARCH_PATHS = "../../ ../../common/mac/**"; ++ WRAPPER_EXTENSION = octest; ++ }; ++ name = Debug; ++ }; ++ F9C77DDD0F7DD5D00045F7DB /* Release */ = { ++ isa = XCBuildConfiguration; ++ buildSettings = { ++ ALWAYS_SEARCH_USER_PATHS = NO; ++ COPY_PHASE_STRIP = YES; ++ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ++ FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks"; ++ GCC_ENABLE_FIX_AND_CONTINUE = NO; ++ GCC_ENABLE_OBJC_EXCEPTIONS = YES; ++ GCC_MODEL_TUNING = G5; ++ INFOPLIST_FILE = "UnitTests-Info.plist"; ++ INSTALL_PATH = "$(USER_LIBRARY_DIR)/Bundles"; ++ OTHER_LDFLAGS = ( ++ "-framework", ++ Cocoa, ++ "-framework", ++ SenTestingKit, ++ ); ++ PREBINDING = NO; ++ PRODUCT_NAME = UnitTests; ++ WRAPPER_EXTENSION = octest; ++ ZERO_LINK = NO; ++ }; ++ name = Release; ++ }; ++/* End XCBuildConfiguration section */ ++ ++/* Begin XCConfigurationList section */ ++ 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "Breakpad" */ = { ++ isa = XCConfigurationList; ++ buildConfigurations = ( ++ 1DEB91AE08733DA50010E9CD /* Debug */, ++ F93DE3BA0F830E7000608B94 /* Debug With Code Coverage */, ++ 1DEB91AF08733DA50010E9CD /* Release */, ++ ); ++ defaultConfigurationIsVisible = 0; ++ defaultConfigurationName = Release; ++ }; ++ 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "Breakpad" */ = { ++ isa = XCConfigurationList; ++ buildConfigurations = ( ++ 1DEB91B208733DA50010E9CD /* Debug */, ++ F93DE3B90F830E7000608B94 /* Debug With Code Coverage */, ++ 1DEB91B308733DA50010E9CD /* Release */, ++ ); ++ defaultConfigurationIsVisible = 0; ++ defaultConfigurationName = Release; ++ }; ++ F92C53580ECCE36D009BE4BA /* Build configuration list for PBXNativeTarget "Inspector" */ = { ++ isa = XCConfigurationList; ++ buildConfigurations = ( ++ F92C53560ECCE34A009BE4BA /* Debug */, ++ F93DE3BB0F830E7000608B94 /* Debug With Code Coverage */, ++ F92C53570ECCE34A009BE4BA /* Release */, ++ ); ++ defaultConfigurationIsVisible = 0; ++ defaultConfigurationName = Release; ++ }; ++ F92C56670ECD11A3009BE4BA /* Build configuration list for PBXNativeTarget "breakpadUtilities" */ = { ++ isa = XCConfigurationList; ++ buildConfigurations = ( ++ F92C563D0ECD10B3009BE4BA /* Debug */, ++ F93DE3BC0F830E7000608B94 /* Debug With Code Coverage */, ++ F92C563E0ECD10B3009BE4BA /* Release */, ++ ); ++ defaultConfigurationIsVisible = 0; ++ defaultConfigurationName = Release; ++ }; ++ F92C56A50ECE04A8009BE4BA /* Build configuration list for PBXNativeTarget "crash_report_sender" */ = { ++ isa = XCConfigurationList; ++ buildConfigurations = ( ++ F92C56A30ECE04A8009BE4BA /* Debug */, ++ F93DE3BD0F830E7000608B94 /* Debug With Code Coverage */, ++ F92C56A40ECE04A8009BE4BA /* Release */, ++ ); ++ defaultConfigurationIsVisible = 0; ++ defaultConfigurationName = Release; ++ }; ++ F93803C40F80822E004D428B /* Build configuration list for PBXNativeTarget "generator_test" */ = { ++ isa = XCConfigurationList; ++ buildConfigurations = ( ++ F93803C00F808210004D428B /* Debug */, ++ F93DE3C10F830E7000608B94 /* Debug With Code Coverage */, ++ F93803C10F808210004D428B /* Release */, ++ ); ++ defaultConfigurationIsVisible = 0; ++ defaultConfigurationName = Release; ++ }; ++ F93DE2D60F82A67700608B94 /* Build configuration list for PBXNativeTarget "minidump_file_writer_unittest" */ = { ++ isa = XCConfigurationList; ++ buildConfigurations = ( ++ F93DE2D30F82A67400608B94 /* Debug */, ++ F93DE3C20F830E7000608B94 /* Debug With Code Coverage */, ++ F93DE2D40F82A67400608B94 /* Release */, ++ ); ++ defaultConfigurationIsVisible = 0; ++ defaultConfigurationName = Release; ++ }; ++ F93DE3320F82C5D800608B94 /* Build configuration list for PBXNativeTarget "handler_test" */ = { ++ isa = XCConfigurationList; ++ buildConfigurations = ( ++ F93DE32E0F82C55700608B94 /* Debug */, ++ F93DE3C30F830E7000608B94 /* Debug With Code Coverage */, ++ F93DE32F0F82C55700608B94 /* Release */, ++ ); ++ defaultConfigurationIsVisible = 0; ++ defaultConfigurationName = Release; ++ }; ++ F94585930F78235C009A47BF /* Build configuration list for PBXAggregateTarget "All" */ = { ++ isa = XCConfigurationList; ++ buildConfigurations = ( ++ F94585850F782326009A47BF /* Debug */, ++ F93DE3BF0F830E7000608B94 /* Debug With Code Coverage */, ++ F94585860F782326009A47BF /* Release */, ++ ); ++ defaultConfigurationIsVisible = 0; ++ defaultConfigurationName = Release; ++ }; ++ F9C44DAA0EF060A9003AEBAA /* Build configuration list for PBXNativeTarget "BreakpadTest" */ = { ++ isa = XCConfigurationList; ++ buildConfigurations = ( ++ F9C44DA80EF060A8003AEBAA /* Debug */, ++ F93DE3BE0F830E7000608B94 /* Debug With Code Coverage */, ++ F9C44DA90EF060A8003AEBAA /* Release */, ++ ); ++ defaultConfigurationIsVisible = 0; ++ defaultConfigurationName = Release; ++ }; ++ F9C77DDE0F7DD5D00045F7DB /* Build configuration list for PBXNativeTarget "UnitTests" */ = { ++ isa = XCConfigurationList; ++ buildConfigurations = ( ++ F9C77DDC0F7DD5D00045F7DB /* Debug */, ++ F93DE3C00F830E7000608B94 /* Debug With Code Coverage */, ++ F9C77DDD0F7DD5D00045F7DB /* Release */, ++ ); ++ defaultConfigurationIsVisible = 0; ++ defaultConfigurationName = Release; ++ }; ++/* End XCConfigurationList section */ ++ }; ++ rootObject = 0867D690FE84028FC02AAC07 /* Project object */; ++} +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/Framework/Breakpad.h b/toolkit/crashreporter/google-breakpad/src/client/mac/Framework/Breakpad.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/Framework/Breakpad.h +@@ -0,0 +1,310 @@ ++// 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. ++// ++// Framework to provide a simple C API to crash reporting for ++// applications. By default, if any machine-level exception (e.g., ++// EXC_BAD_ACCESS) occurs, it will be handled by the BreakpadRef ++// object as follows: ++// ++// 1. Create a minidump file (see Breakpad for details) ++// 2. Prompt the user (using CFUserNotification) ++// 3. Invoke a command line reporting tool to send the minidump to a ++// server ++// ++// By specifying parameters to the BreakpadCreate function, you can ++// modify the default behavior to suit your needs and wants and ++// desires. ++ ++typedef void *BreakpadRef; ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include ++#include ++ ++ // Keys for configuration file ++#define kReporterMinidumpDirectoryKey "MinidumpDir" ++#define kReporterMinidumpIDKey "MinidumpID" ++ ++// The default subdirectory of the Library to put crash dumps in ++// The subdirectory is ++// ~/Library// ++#define kDefaultLibrarySubdirectory "Breakpad" ++ ++// Specify some special keys to be used in the configuration file that is ++// generated by Breakpad and consumed by the crash_sender. ++#define BREAKPAD_PRODUCT "BreakpadProduct" ++#define BREAKPAD_PRODUCT_DISPLAY "BreakpadProductDisplay" ++#define BREAKPAD_VERSION "BreakpadVersion" ++#define BREAKPAD_VENDOR "BreakpadVendor" ++#define BREAKPAD_URL "BreakpadURL" ++#define BREAKPAD_REPORT_INTERVAL "BreakpadReportInterval" ++#define BREAKPAD_SKIP_CONFIRM "BreakpadSkipConfirm" ++#define BREAKPAD_CONFIRM_TIMEOUT "BreakpadConfirmTimeout" ++#define BREAKPAD_SEND_AND_EXIT "BreakpadSendAndExit" ++#define BREAKPAD_DUMP_DIRECTORY "BreakpadMinidumpLocation" ++#define BREAKPAD_INSPECTOR_LOCATION "BreakpadInspectorLocation" ++#define BREAKPAD_REPORTER_EXE_LOCATION \ ++ "BreakpadReporterExeLocation" ++#define BREAKPAD_LOGFILES "BreakpadLogFiles" ++#define BREAKPAD_LOGFILE_UPLOAD_SIZE "BreakpadLogFileTailSize" ++#define BREAKPAD_REQUEST_COMMENTS "BreakpadRequestComments" ++#define BREAKPAD_COMMENTS "BreakpadComments" ++#define BREAKPAD_REQUEST_EMAIL "BreakpadRequestEmail" ++#define BREAKPAD_EMAIL "BreakpadEmail" ++#define BREAKPAD_SERVER_TYPE "BreakpadServerType" ++#define BREAKPAD_SERVER_PARAMETER_DICT "BreakpadServerParameters" ++ ++// The keys below are NOT user supplied, and are used internally. ++#define BREAKPAD_PROCESS_START_TIME "BreakpadProcStartTime" ++#define BREAKPAD_PROCESS_UP_TIME "BreakpadProcessUpTime" ++#define BREAKPAD_PROCESS_CRASH_TIME "BreakpadProcessCrashTime" ++#define BREAKPAD_LOGFILE_KEY_PREFIX "BreakpadAppLogFile" ++#define BREAKPAD_SERVER_PARAMETER_PREFIX "BreakpadServerParameterPrefix_" ++#define BREAKPAD_ON_DEMAND "BreakpadOnDemand" ++ ++// Optional user-defined function to dec to decide if we should handle ++// this crash or forward it along. ++// Return true if you want Breakpad to handle it. ++// Return false if you want Breakpad to skip it ++// The exception handler always returns false, as if SEND_AND_EXIT were false ++// (which means the next exception handler will take the exception) ++typedef bool (*BreakpadFilterCallback)(int exception_type, ++ int exception_code, ++ mach_port_t crashing_thread, ++ void *context); ++ ++// Create a new BreakpadRef object and install it as an exception ++// handler. The |parameters| will typically be the contents of your ++// bundle's Info.plist. ++// ++// You can also specify these additional keys for customizable behavior: ++// Key: Value: ++// BREAKPAD_PRODUCT Product name (e.g., "MyAwesomeProduct") ++// This one is used as the key to identify ++// the product when uploading ++// REQUIRED ++// ++// BREAKPAD_PRODUCT_DISPLAY This is the display name, e.g. a pretty ++// name for the product when the crash_sender ++// pops up UI for the user. Falls back to ++// BREAKPAD_PRODUCT if not specified. ++// ++// BREAKPAD_VERSION Product version (e.g., 1.2.3), used ++// as metadata for crash report ++// REQUIRED ++// ++// BREAKPAD_VENDOR Vendor name, used in UI (e.g. "A report has ++// been created that you can send to ") ++// ++// BREAKPAD_URL URL destination for reporting ++// REQUIRED ++// ++// BREAKPAD_REPORT_INTERVAL # of seconds between sending ++// reports. If an additional report is ++// generated within this time, it will ++// be ignored. Default: 3600sec. ++// Specify 0 to send all reports. ++// ++// BREAKPAD_SKIP_CONFIRM If true, the reporter will send the report ++// without any user intervention. ++// Defaults to NO ++// ++// BREAKPAD_CONFIRM_TIMEOUT Number of seconds before the upload ++// confirmation dialog will be automatically ++// dismissed (cancelling the upload). ++// Default: 300 seconds (min of 60). ++// Specify 0 to prevent timeout. ++// ++// BREAKPAD_SEND_AND_EXIT If true, the handler will exit after sending. ++// This will prevent any other handler (e.g., ++// CrashReporter) from getting the crash. ++// Defaults TO YES ++// ++// BREAKPAD_DUMP_DIRECTORY The directory to store crash-dumps ++// in. By default, we use ++// ~/Library/Breakpad/ ++// The path you specify here is tilde-expanded. ++// ++// BREAKPAD_INSPECTOR_LOCATION The full path to the Inspector executable. ++// Defaults to /Inspector ++// ++// BREAKPAD_REPORTER_EXE_LOCATION The full path to the Reporter/sender ++// executable. ++// Default: ++// /crash_report_sender.app ++// ++// BREAKPAD_LOGFILES Indicates an array of log file paths that ++// should be uploaded at crash time. ++// ++// BREAKPAD_REQUEST_COMMENTS If true, the message dialog will have a ++// text box for the user to enter comments. ++// Default: NO ++// ++// BREAKPAD_REQUEST_EMAIL If true and BREAKPAD_REQUEST_COMMENTS is also ++// true, the message dialog will have a text ++// box for the user to enter their email address. ++// Default: NO ++// ++// BREAKPAD_SERVER_TYPE A parameter that tells Breakpad how to ++// rewrite the upload parameters for a specific ++// server type. The currently valid values are ++// 'socorro' or 'google'. If you want to add ++// other types, see the function in ++// crash_report_sender.m that maps parameters to ++// URL parameters. Defaults to 'google'. ++// ++// BREAKPAD_SERVER_PARAMETER_DICT A plist dictionary of static ++// parameters that are uploaded to the ++// server. The parameters are sent as ++// is to the crash server. Their ++// content isn't added to the minidump ++// but pass as URL parameters when ++// uploading theminidump to the crash ++// server. ++//============================================================================= ++// The BREAKPAD_PRODUCT, BREAKPAD_VERSION and BREAKPAD_URL are ++// required to have non-NULL values. By default, the BREAKPAD_PRODUCT ++// will be the CFBundleName and the BREAKPAD_VERSION will be the ++// CFBundleVersion when these keys are present in the bundle's ++// Info.plist, which is usually passed in to BreakpadCreate() as an ++// NSDictionary (you could also pass in another dictionary that had ++// the same keys configured). If the BREAKPAD_PRODUCT or ++// BREAKPAD_VERSION are ultimately undefined, BreakpadCreate() will ++// fail. You have been warned. ++// ++// If you are running in a debugger, Breakpad will not install, unless the ++// BREAKPAD_IGNORE_DEBUGGER envionment variable is set and/or non-zero. ++// ++// The BREAKPAD_SKIP_CONFIRM and BREAKPAD_SEND_AND_EXIT default ++// values are NO and YES. However, they can be controlled by setting their ++// values in a user or global plist. ++// ++// It's easiest to use Breakpad via the Framework, but if you're compiling the ++// code in directly, BREAKPAD_INSPECTOR_LOCATION and ++// BREAKPAD_REPORTER_EXE_LOCATION allow you to specify custom paths ++// to the helper executables. ++// ++//============================================================================= ++// The following are NOT user-supplied but are documented here for ++// completeness. They are calculated by Breakpad during initialization & ++// crash-dump generation, or entered in by the user. ++// ++// BREAKPAD_PROCESS_START_TIME The time the process started. ++// ++// BREAKPAD_PROCESS_CRASH_TIME The time the process crashed. ++// ++// BREAKPAD_PROCESS_UP_TIME The total time the process has been ++// running. This parameter is not set ++// until the crash-dump-generation phase. ++// ++// BREAKPAD_LOGFILE_KEY_PREFIX Used to find out which parameters in the ++// parameter dictionary correspond to log ++// file paths. ++// ++// BREAKPAD_SERVER_PARAMETER_PREFIX This prefix is used by Breakpad ++// internally, because Breakpad uses ++// the same dictionary internally to ++// track both its internal ++// configuration parameters and ++// parameters meant to be uploaded ++// to the server. This string is ++// used internally by Breakpad to ++// prefix user-supplied parameter ++// names so those can be sent to the ++// server without leaking Breakpad's ++// internal values. ++// ++// BREAKPAD_ON_DEMAND Used internally to indicate to the ++// Reporter that we're sending on-demand, ++// not as result of a crash. ++// ++// BREAKPAD_COMMENTS The text the user provided as comments. ++// Only used in crash_report_sender. ++ ++// Returns a new BreakpadRef object on success, NULL otherwise. ++BreakpadRef BreakpadCreate(NSDictionary *parameters); ++ ++// Uninstall and release the data associated with |ref|. ++void BreakpadRelease(BreakpadRef ref); ++ ++// Clients may set an optional callback which gets called when a crash ++// occurs. The callback function should return |true| if we should ++// handle the crash, generate a crash report, etc. or |false| if we ++// should ignore it and forward the crash (normally to CrashReporter). ++// Context is a pointer to arbitrary data to make the callback with. ++void BreakpadSetFilterCallback(BreakpadRef ref, ++ BreakpadFilterCallback callback, ++ void *context); ++ ++// User defined key and value string storage. Generally this is used ++// to configure Breakpad's internal operation, such as whether the ++// crash_sender should prompt the user, or the filesystem location for ++// the minidump file. See Breakpad.h for some parameters that can be ++// set. Anything longer than 255 bytes will be truncated. Note that ++// the string is converted to UTF8 before truncation, so any multibyte ++// character that straddles the 255(256 - 1 for terminator) byte limit ++// will be mangled. ++// ++// A maximum number of 64 key/value pairs are supported. An assert() ++// will fire if more than this number are set. Unfortunately, right ++// now, the same dictionary is used for both Breakpad's parameters AND ++// the Upload parameters. ++// ++// TODO (nealsid): Investigate how necessary this is if we don't ++// automatically upload parameters to the server anymore. ++// TODO (nealsid): separate server parameter dictionary from the ++// dictionary used to configure Breakpad, and document limits for each ++// independently. ++void BreakpadSetKeyValue(BreakpadRef ref, NSString *key, NSString *value); ++NSString *BreakpadKeyValue(BreakpadRef ref, NSString *key); ++void BreakpadRemoveKeyValue(BreakpadRef ref, NSString *key); ++ ++// You can use this method to specify parameters that will be uploaded ++// to the crash server. They will be automatically encoded as ++// necessary. Note that as mentioned above there are limits on both ++// the number of keys and their length. ++void BreakpadAddUploadParameter(BreakpadRef ref, NSString *key, ++ NSString *value); ++ ++// This method will remove a previously-added parameter from the ++// upload parameter set. ++void BreakpadRemoveUploadParameter(BreakpadRef ref, NSString *key); ++ ++// Add a log file for Breakpad to read and send upon crash dump ++void BreakpadAddLogFile(BreakpadRef ref, NSString *logPathname); ++ ++// Generate a minidump and send ++void BreakpadGenerateAndSendReport(BreakpadRef ref); ++ ++#ifdef __cplusplus ++} ++#endif +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/Framework/Breakpad.mm b/toolkit/crashreporter/google-breakpad/src/client/mac/Framework/Breakpad.mm +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/Framework/Breakpad.mm +@@ -0,0 +1,993 @@ ++// 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. ++// ++ ++#define VERBOSE 0 ++ ++#if VERBOSE ++ static bool gDebugLog = true; ++#else ++ static bool gDebugLog = false; ++#endif ++ ++#define DEBUGLOG if (gDebugLog) fprintf ++#define IGNORE_DEBUGGER "BREAKPAD_IGNORE_DEBUGGER" ++ ++#import "common/mac/MachIPC.h" ++#import "common/mac/SimpleStringDictionary.h" ++ ++#import "client/mac/crash_generation/Inspector.h" ++#import "client/mac/handler/exception_handler.h" ++#import "client/mac/Framework/Breakpad.h" ++#import "client/mac/Framework/OnDemandServer.h" ++#import "client/mac/handler/protected_memory_allocator.h" ++ ++#import ++#import ++ ++#import ++ ++ ++using google_breakpad::KeyValueEntry; ++using google_breakpad::SimpleStringDictionary; ++using google_breakpad::SimpleStringDictionaryIterator; ++ ++//============================================================================= ++// We want any memory allocations which are used by breakpad during the ++// exception handling process (after a crash has happened) to be read-only ++// to prevent them from being smashed before a crash occurs. Unfortunately ++// we cannot protect against smashes to our exception handling thread's ++// stack. ++// ++// NOTE: Any memory allocations which are not used during the exception ++// handling process may be allocated in the normal ways. ++// ++// The ProtectedMemoryAllocator class provides an Allocate() method which ++// we'll using in conjunction with placement operator new() to control ++// allocation of C++ objects. Note that we don't use operator delete() ++// but instead call the objects destructor directly: object->~ClassName(); ++// ++ProtectedMemoryAllocator *gMasterAllocator = NULL; ++ProtectedMemoryAllocator *gKeyValueAllocator = NULL; ++ProtectedMemoryAllocator *gBreakpadAllocator = NULL; ++ ++// Mutex for thread-safe access to the key/value dictionary used by breakpad. ++// It's a global instead of an instance variable of Breakpad ++// since it can't live in a protected memory area. ++pthread_mutex_t gDictionaryMutex; ++ ++//============================================================================= ++// Stack-based object for thread-safe access to a memory-protected region. ++// It's assumed that normally the memory block (allocated by the allocator) ++// is protected (read-only). Creating a stack-based instance of ++// ProtectedMemoryLocker will unprotect this block after taking the lock. ++// Its destructor will first re-protect the memory then release the lock. ++class ProtectedMemoryLocker { ++public: ++ // allocator may be NULL, in which case no Protect() or Unprotect() calls ++ // will be made, but a lock will still be taken ++ ProtectedMemoryLocker(pthread_mutex_t *mutex, ++ ProtectedMemoryAllocator *allocator) ++ : mutex_(mutex), allocator_(allocator) { ++ // Lock the mutex ++ assert(pthread_mutex_lock(mutex_) == 0); ++ ++ // Unprotect the memory ++ if (allocator_ ) { ++ allocator_->Unprotect(); ++ } ++ } ++ ++ ~ProtectedMemoryLocker() { ++ // First protect the memory ++ if (allocator_) { ++ allocator_->Protect(); ++ } ++ ++ // Then unlock the mutex ++ assert(pthread_mutex_unlock(mutex_) == 0); ++ }; ++ ++private: ++ // Keep anybody from ever creating one of these things not on the stack. ++ ProtectedMemoryLocker() { } ++ ProtectedMemoryLocker(const ProtectedMemoryLocker&); ++ ProtectedMemoryLocker & operator=(ProtectedMemoryLocker&); ++ ++ pthread_mutex_t *mutex_; ++ ProtectedMemoryAllocator *allocator_; ++}; ++ ++//============================================================================= ++class Breakpad { ++ public: ++ // factory method ++ static Breakpad *Create(NSDictionary *parameters) { ++ // Allocate from our special allocation pool ++ Breakpad *breakpad = ++ new (gBreakpadAllocator->Allocate(sizeof(Breakpad))) ++ Breakpad(); ++ ++ if (!breakpad) ++ return NULL; ++ ++ if (!breakpad->Initialize(parameters)) { ++ // Don't use operator delete() here since we allocated from special pool ++ breakpad->~Breakpad(); ++ return NULL; ++ } ++ ++ return breakpad; ++ } ++ ++ ~Breakpad(); ++ ++ void SetKeyValue(NSString *key, NSString *value); ++ NSString *KeyValue(NSString *key); ++ void RemoveKeyValue(NSString *key); ++ ++ void GenerateAndSendReport(); ++ ++ void SetFilterCallback(BreakpadFilterCallback callback, void *context) { ++ filter_callback_ = callback; ++ filter_callback_context_ = context; ++ } ++ ++ private: ++ Breakpad() ++ : handler_(NULL), ++ config_params_(NULL), ++ send_and_exit_(true), ++ filter_callback_(NULL), ++ filter_callback_context_(NULL) { ++ inspector_path_[0] = 0; ++ } ++ ++ bool Initialize(NSDictionary *parameters); ++ ++ bool ExtractParameters(NSDictionary *parameters); ++ ++ // Dispatches to HandleException() ++ static bool ExceptionHandlerDirectCallback(void *context, ++ int exception_type, ++ int exception_code, ++ int exception_subcode, ++ mach_port_t crashing_thread); ++ ++ bool HandleException(int exception_type, ++ int exception_code, ++ int exception_subcode, ++ mach_port_t crashing_thread); ++ ++ // Since ExceptionHandler (w/o namespace) is defined as typedef in OSX's ++ // MachineExceptions.h, we have to explicitly name the handler. ++ google_breakpad::ExceptionHandler *handler_; // The actual handler (STRONG) ++ ++ char inspector_path_[PATH_MAX]; // Path to inspector tool ++ ++ SimpleStringDictionary *config_params_; // Create parameters (STRONG) ++ ++ OnDemandServer inspector_; ++ ++ bool send_and_exit_; // Exit after sending, if true ++ ++ BreakpadFilterCallback filter_callback_; ++ void *filter_callback_context_; ++}; ++ ++#pragma mark - ++#pragma mark Helper functions ++ ++//============================================================================= ++// Helper functions ++ ++//============================================================================= ++static BOOL IsDebuggerActive() { ++ BOOL result = NO; ++ NSUserDefaults *stdDefaults = [NSUserDefaults standardUserDefaults]; ++ ++ // We check both defaults and the environment variable here ++ ++ BOOL ignoreDebugger = [stdDefaults boolForKey:@IGNORE_DEBUGGER]; ++ ++ if (!ignoreDebugger) { ++ char *ignoreDebuggerStr = getenv(IGNORE_DEBUGGER); ++ ignoreDebugger = (ignoreDebuggerStr ? strtol(ignoreDebuggerStr, NULL, 10) : 0) != 0; ++ } ++ ++ if (!ignoreDebugger) { ++ pid_t pid = getpid(); ++ int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; ++ int mibSize = sizeof(mib) / sizeof(int); ++ size_t actualSize; ++ ++ if (sysctl(mib, mibSize, NULL, &actualSize, NULL, 0) == 0) { ++ struct kinfo_proc *info = (struct kinfo_proc *)malloc(actualSize); ++ ++ if (info) { ++ // This comes from looking at the Darwin xnu Kernel ++ if (sysctl(mib, mibSize, info, &actualSize, NULL, 0) == 0) ++ result = (info->kp_proc.p_flag & P_TRACED) ? YES : NO; ++ ++ free(info); ++ } ++ } ++ } ++ ++ return result; ++} ++ ++//============================================================================= ++bool Breakpad::ExceptionHandlerDirectCallback(void *context, ++ int exception_type, ++ int exception_code, ++ int exception_subcode, ++ mach_port_t crashing_thread) { ++ Breakpad *breakpad = (Breakpad *)context; ++ ++ // If our context is damaged or something, just return false to indicate that ++ // the handler should continue without us. ++ if (!breakpad) ++ return false; ++ ++ return breakpad->HandleException( exception_type, ++ exception_code, ++ exception_subcode, ++ crashing_thread); ++} ++ ++//============================================================================= ++#pragma mark - ++ ++#include ++ ++//============================================================================= ++// Returns the pathname to the Resources directory for this version of ++// Breakpad which we are now running. ++// ++// Don't make the function static, since _dyld_lookup_and_bind_fully needs a ++// simple non-static C name ++// ++extern "C" { ++NSString * GetResourcePath(); ++NSString * GetResourcePath() { ++ NSString *resourcePath = nil; ++ ++ // If there are multiple breakpads installed then calling bundleWithIdentifier ++ // will not work properly, so only use that as a backup plan. ++ // We want to find the bundle containing the code where this function lives ++ // and work from there ++ // ++ ++ // Get the pathname to the code which contains this function ++ void *address = nil; ++ NSModule module = nil; ++ _dyld_lookup_and_bind_fully("_GetResourcePath", ++ &address, ++ &module); ++ ++ if (module && address) { ++ const char* moduleName = NSNameOfModule(module); ++ if (moduleName) { ++ // The "Resources" directory should be in the same directory as the ++ // executable code, since that's how the Breakpad framework is built. ++ resourcePath = [NSString stringWithUTF8String:moduleName]; ++ resourcePath = [resourcePath stringByDeletingLastPathComponent]; ++ resourcePath = [resourcePath stringByAppendingPathComponent:@"Resources/"]; ++ } else { ++ DEBUGLOG(stderr, "Missing moduleName\n"); ++ } ++ } else { ++ DEBUGLOG(stderr, "Could not find GetResourcePath\n"); ++ // fallback plan ++ NSBundle *bundle = ++ [NSBundle bundleWithIdentifier:@"com.Google.BreakpadFramework"]; ++ resourcePath = [bundle resourcePath]; ++ } ++ ++ return resourcePath; ++} ++} // extern "C" ++ ++//============================================================================= ++bool Breakpad::Initialize(NSDictionary *parameters) { ++ // Initialize ++ config_params_ = NULL; ++ handler_ = NULL; ++ ++ // Check for debugger ++ if (IsDebuggerActive()) { ++ DEBUGLOG(stderr, "Debugger is active: Not installing handler\n"); ++ return true; ++ } ++ ++ // Gather any user specified parameters ++ if (!ExtractParameters(parameters)) { ++ return false; ++ } ++ ++ // Get path to Inspector executable. ++ NSString *inspectorPathString = KeyValue(@BREAKPAD_INSPECTOR_LOCATION); ++ ++ // Standardize path (resolve symlinkes, etc.) and escape spaces ++ inspectorPathString = [inspectorPathString stringByStandardizingPath]; ++ inspectorPathString = [[inspectorPathString componentsSeparatedByString:@" "] ++ componentsJoinedByString:@"\\ "]; ++ ++ // Create an on-demand server object representing the Inspector. ++ // In case of a crash, we simply need to call the LaunchOnDemand() ++ // method on it, then send a mach message to its service port. ++ // It will then launch and perform a process inspection of our crashed state. ++ // See the HandleException() method for the details. ++#define RECEIVE_PORT_NAME "com.Breakpad.Inspector" ++ ++ name_t portName; ++ snprintf(portName, sizeof(name_t), "%s%d", RECEIVE_PORT_NAME, getpid()); ++ ++ // Save the location of the Inspector ++ strlcpy(inspector_path_, [inspectorPathString fileSystemRepresentation], ++ sizeof(inspector_path_)); ++ ++ // Append a single command-line argument to the Inspector path ++ // representing the bootstrap name of the launch-on-demand receive port. ++ // When the Inspector is launched, it can use this to lookup the port ++ // by calling bootstrap_check_in(). ++ strlcat(inspector_path_, " ", sizeof(inspector_path_)); ++ strlcat(inspector_path_, portName, sizeof(inspector_path_)); ++ ++ kern_return_t kr = inspector_.Initialize(inspector_path_, ++ portName, ++ true); // shutdown on exit ++ ++ if (kr != KERN_SUCCESS) { ++ return false; ++ } ++ ++ // Create the handler (allocating it in our special protected pool) ++ handler_ = ++ new (gBreakpadAllocator->Allocate(sizeof(google_breakpad::ExceptionHandler))) ++ google_breakpad::ExceptionHandler( ++ Breakpad::ExceptionHandlerDirectCallback, this, true); ++ return true; ++} ++ ++//============================================================================= ++Breakpad::~Breakpad() { ++ // Note that we don't use operator delete() on these pointers, ++ // since they were allocated by ProtectedMemoryAllocator objects. ++ // ++ if (config_params_) { ++ config_params_->~SimpleStringDictionary(); ++ } ++ ++ if (handler_) ++ handler_->~ExceptionHandler(); ++} ++ ++//============================================================================= ++bool Breakpad::ExtractParameters(NSDictionary *parameters) { ++ NSUserDefaults *stdDefaults = [NSUserDefaults standardUserDefaults]; ++ NSString *skipConfirm = [stdDefaults stringForKey:@BREAKPAD_SKIP_CONFIRM]; ++ NSString *sendAndExit = [stdDefaults stringForKey:@BREAKPAD_SEND_AND_EXIT]; ++ ++ NSString *serverType = [parameters objectForKey:@BREAKPAD_SERVER_TYPE]; ++ NSString *display = [parameters objectForKey:@BREAKPAD_PRODUCT_DISPLAY]; ++ NSString *product = [parameters objectForKey:@BREAKPAD_PRODUCT]; ++ NSString *version = [parameters objectForKey:@BREAKPAD_VERSION]; ++ NSString *urlStr = [parameters objectForKey:@BREAKPAD_URL]; ++ NSString *interval = [parameters objectForKey:@BREAKPAD_REPORT_INTERVAL]; ++ NSString *inspectorPathString = ++ [parameters objectForKey:@BREAKPAD_INSPECTOR_LOCATION]; ++ NSString *reporterPathString = ++ [parameters objectForKey:@BREAKPAD_REPORTER_EXE_LOCATION]; ++ NSString *timeout = [parameters objectForKey:@BREAKPAD_CONFIRM_TIMEOUT]; ++ NSArray *logFilePaths = [parameters objectForKey:@BREAKPAD_LOGFILES]; ++ NSString *logFileTailSize = [parameters objectForKey:@BREAKPAD_LOGFILE_UPLOAD_SIZE]; ++ NSString *requestUserText = ++ [parameters objectForKey:@BREAKPAD_REQUEST_COMMENTS]; ++ NSString *requestEmail = [parameters objectForKey:@BREAKPAD_REQUEST_EMAIL]; ++ NSString *vendor = ++ [parameters objectForKey:@BREAKPAD_VENDOR]; ++ NSString *dumpSubdirectory = ++ [parameters objectForKey:@BREAKPAD_DUMP_DIRECTORY]; ++ ++ NSDictionary *serverParameters = ++ [parameters objectForKey:@BREAKPAD_SERVER_PARAMETER_DICT]; ++ ++ // These may have been set above as user prefs, which take priority. ++ if (!skipConfirm) { ++ skipConfirm = [parameters objectForKey:@BREAKPAD_SKIP_CONFIRM]; ++ } ++ if (!sendAndExit) { ++ sendAndExit = [parameters objectForKey:@BREAKPAD_SEND_AND_EXIT]; ++ } ++ ++ if (!product) ++ product = [parameters objectForKey:@"CFBundleName"]; ++ ++ if (!display) ++ display = product; ++ ++ if (!version) ++ version = [parameters objectForKey:@"CFBundleVersion"]; ++ ++ if (!interval) ++ interval = @"3600"; ++ ++ if (!timeout) ++ timeout = @"300"; ++ ++ if (!logFileTailSize) ++ logFileTailSize = @"200000"; ++ ++ if (!vendor) { ++ vendor = @"Vendor not specified"; ++ } ++ ++ // Normalize the values. ++ if (skipConfirm) { ++ skipConfirm = [skipConfirm uppercaseString]; ++ ++ if ([skipConfirm isEqualToString:@"YES"] || ++ [skipConfirm isEqualToString:@"TRUE"] || ++ [skipConfirm isEqualToString:@"1"]) ++ skipConfirm = @"YES"; ++ else ++ skipConfirm = @"NO"; ++ } else { ++ skipConfirm = @"NO"; ++ } ++ ++ send_and_exit_ = true; ++ if (sendAndExit) { ++ sendAndExit = [sendAndExit uppercaseString]; ++ ++ if ([sendAndExit isEqualToString:@"NO"] || ++ [sendAndExit isEqualToString:@"FALSE"] || ++ [sendAndExit isEqualToString:@"0"]) ++ send_and_exit_ = false; ++ } ++ ++ if (requestUserText) { ++ requestUserText = [requestUserText uppercaseString]; ++ ++ if ([requestUserText isEqualToString:@"YES"] || ++ [requestUserText isEqualToString:@"TRUE"] || ++ [requestUserText isEqualToString:@"1"]) ++ requestUserText = @"YES"; ++ else ++ requestUserText = @"NO"; ++ } else { ++ requestUserText = @"NO"; ++ } ++ ++ // Find the helper applications if not specified in user config. ++ NSString *resourcePath = nil; ++ if (!inspectorPathString || !reporterPathString) { ++ resourcePath = GetResourcePath(); ++ if (!resourcePath) { ++ DEBUGLOG(stderr, "Could not get resource path\n"); ++ return false; ++ } ++ } ++ ++ // Find Inspector. ++ if (!inspectorPathString) { ++ inspectorPathString = ++ [resourcePath stringByAppendingPathComponent:@"Inspector"]; ++ } ++ ++ // Verify that there is an Inspector tool. ++ if (![[NSFileManager defaultManager] fileExistsAtPath:inspectorPathString]) { ++ DEBUGLOG(stderr, "Cannot find Inspector tool\n"); ++ return false; ++ } ++ ++ // Find Reporter. ++ if (!reporterPathString) { ++ reporterPathString = ++ [resourcePath stringByAppendingPathComponent:@"crash_report_sender.app"]; ++ reporterPathString = [[NSBundle bundleWithPath:reporterPathString] executablePath]; ++ } ++ ++ // Verify that there is a Reporter application. ++ if (![[NSFileManager defaultManager] ++ fileExistsAtPath:reporterPathString]) { ++ DEBUGLOG(stderr, "Cannot find Reporter tool\n"); ++ return false; ++ } ++ ++ if (!dumpSubdirectory) { ++ dumpSubdirectory = @""; ++ } ++ ++ // The product, version, and URL are required values. ++ if (![product length]) { ++ DEBUGLOG(stderr, "Missing required product key.\n"); ++ return false; ++ } ++ ++ if (![version length]) { ++ DEBUGLOG(stderr, "Missing required version key.\n"); ++ return false; ++ } ++ ++ if (![urlStr length]) { ++ DEBUGLOG(stderr, "Missing required URL key.\n"); ++ return false; ++ } ++ ++ config_params_ = ++ new (gKeyValueAllocator->Allocate(sizeof(SimpleStringDictionary)) ) ++ SimpleStringDictionary(); ++ ++ SimpleStringDictionary &dictionary = *config_params_; ++ ++ dictionary.SetKeyValue(BREAKPAD_SERVER_TYPE, [serverType UTF8String]); ++ dictionary.SetKeyValue(BREAKPAD_PRODUCT_DISPLAY, [display UTF8String]); ++ dictionary.SetKeyValue(BREAKPAD_PRODUCT, [product UTF8String]); ++ dictionary.SetKeyValue(BREAKPAD_VERSION, [version UTF8String]); ++ dictionary.SetKeyValue(BREAKPAD_URL, [urlStr UTF8String]); ++ dictionary.SetKeyValue(BREAKPAD_REPORT_INTERVAL, [interval UTF8String]); ++ dictionary.SetKeyValue(BREAKPAD_SKIP_CONFIRM, [skipConfirm UTF8String]); ++ dictionary.SetKeyValue(BREAKPAD_CONFIRM_TIMEOUT, [timeout UTF8String]); ++ dictionary.SetKeyValue(BREAKPAD_INSPECTOR_LOCATION, ++ [inspectorPathString fileSystemRepresentation]); ++ dictionary.SetKeyValue(BREAKPAD_REPORTER_EXE_LOCATION, ++ [reporterPathString fileSystemRepresentation]); ++ dictionary.SetKeyValue(BREAKPAD_LOGFILE_UPLOAD_SIZE, ++ [logFileTailSize UTF8String]); ++ dictionary.SetKeyValue(BREAKPAD_REQUEST_COMMENTS, ++ [requestUserText UTF8String]); ++ dictionary.SetKeyValue(BREAKPAD_REQUEST_EMAIL, [requestEmail UTF8String]); ++ dictionary.SetKeyValue(BREAKPAD_VENDOR, [vendor UTF8String]); ++ dictionary.SetKeyValue(BREAKPAD_DUMP_DIRECTORY, ++ [dumpSubdirectory UTF8String]); ++ ++ struct timeval tv; ++ gettimeofday(&tv, NULL); ++ char timeStartedString[32]; ++ sprintf(timeStartedString, "%d", tv.tv_sec); ++ dictionary.SetKeyValue(BREAKPAD_PROCESS_START_TIME, ++ timeStartedString); ++ ++ if (logFilePaths) { ++ char logFileKey[255]; ++ for(unsigned int i = 0; i < [logFilePaths count]; i++) { ++ sprintf(logFileKey,"%s%d", BREAKPAD_LOGFILE_KEY_PREFIX, i); ++ dictionary.SetKeyValue(logFileKey, ++ [[logFilePaths objectAtIndex:i] ++ fileSystemRepresentation]); ++ } ++ } ++ ++ if (serverParameters) { ++ // For each key-value pair, call BreakpadAddUploadParameter() ++ NSEnumerator *keyEnumerator = [serverParameters keyEnumerator]; ++ NSString *aParameter; ++ while (aParameter = [keyEnumerator nextObject]) { ++ BreakpadAddUploadParameter(this, aParameter, ++ [serverParameters objectForKey:aParameter]); ++ } ++ } ++ return true; ++} ++ ++//============================================================================= ++void Breakpad::SetKeyValue(NSString *key, NSString *value) { ++ // We allow nil values. This is the same as removing the keyvalue. ++ if (!config_params_ || !key) ++ return; ++ ++ config_params_->SetKeyValue([key UTF8String], [value UTF8String]); ++} ++ ++//============================================================================= ++NSString * Breakpad::KeyValue(NSString *key) { ++ if (!config_params_ || !key) ++ return nil; ++ ++ const char *value = config_params_->GetValueForKey([key UTF8String]); ++ return value ? [NSString stringWithUTF8String:value] : nil; ++} ++ ++//============================================================================= ++void Breakpad::RemoveKeyValue(NSString *key) { ++ if (!config_params_ || !key) ++ return; ++ ++ config_params_->RemoveKey([key UTF8String]); ++} ++ ++//============================================================================= ++void Breakpad::GenerateAndSendReport() { ++ config_params_->SetKeyValue(BREAKPAD_ON_DEMAND, "YES"); ++ HandleException(0, 0, 0, mach_thread_self()); ++ config_params_->SetKeyValue(BREAKPAD_ON_DEMAND, "NO"); ++} ++ ++//============================================================================= ++bool Breakpad::HandleException(int exception_type, ++ int exception_code, ++ int exception_subcode, ++ mach_port_t crashing_thread) { ++ DEBUGLOG(stderr, "Breakpad: an exception occurred\n"); ++ ++ if (filter_callback_) { ++ bool should_handle = filter_callback_(exception_type, ++ exception_code, ++ crashing_thread, ++ filter_callback_context_); ++ if (!should_handle) return false; ++ } ++ ++ // We need to reset the memory protections to be read/write, ++ // since LaunchOnDemand() requires changing state. ++ gBreakpadAllocator->Unprotect(); ++ // Configure the server to launch when we message the service port. ++ // The reason we do this here, rather than at startup, is that we ++ // can leak a bootstrap service entry if this method is called and ++ // there never ends up being a crash. ++ inspector_.LaunchOnDemand(); ++ gBreakpadAllocator->Protect(); ++ ++ // The Inspector should send a message to this port to verify it ++ // received our information and has finished the inspection. ++ ReceivePort acknowledge_port; ++ ++ // Send initial information to the Inspector. ++ MachSendMessage message(kMsgType_InspectorInitialInfo); ++ message.AddDescriptor(mach_task_self()); // our task ++ message.AddDescriptor(crashing_thread); // crashing thread ++ message.AddDescriptor(mach_thread_self()); // exception-handling thread ++ message.AddDescriptor(acknowledge_port.GetPort());// message receive port ++ ++ InspectorInfo info; ++ info.exception_type = exception_type; ++ info.exception_code = exception_code; ++ info.exception_subcode = exception_subcode; ++ info.parameter_count = config_params_->GetCount(); ++ message.SetData(&info, sizeof(info)); ++ ++ MachPortSender sender(inspector_.GetServicePort()); ++ ++ kern_return_t result = sender.SendMessage(message, 2000); ++ ++ if (result == KERN_SUCCESS) { ++ // Now, send a series of key-value pairs to the Inspector. ++ const KeyValueEntry *entry = NULL; ++ SimpleStringDictionaryIterator iter(*config_params_); ++ ++ while ( (entry = iter.Next()) ) { ++ KeyValueMessageData keyvalue_data(*entry); ++ ++ MachSendMessage keyvalue_message(kMsgType_InspectorKeyValuePair); ++ keyvalue_message.SetData(&keyvalue_data, sizeof(keyvalue_data)); ++ ++ result = sender.SendMessage(keyvalue_message, 2000); ++ ++ if (result != KERN_SUCCESS) { ++ break; ++ } ++ } ++ ++ if (result == KERN_SUCCESS) { ++ // Wait for acknowledgement that the inspection has finished. ++ MachReceiveMessage acknowledge_messsage; ++ result = acknowledge_port.WaitForMessage(&acknowledge_messsage, 5000); ++ } ++ } ++ ++#if VERBOSE ++ PRINT_MACH_RESULT(result, "Breakpad: SendMessage "); ++ printf("Breakpad: Inspector service port = %#x\n", ++ inspector_.GetServicePort()); ++#endif ++ ++ // If we don't want any forwarding, return true here to indicate that we've ++ // processed things as much as we want. ++ if (send_and_exit_) ++ return true; ++ ++ return false; ++} ++ ++//============================================================================= ++//============================================================================= ++ ++#pragma mark - ++#pragma mark Public API ++ ++//============================================================================= ++BreakpadRef BreakpadCreate(NSDictionary *parameters) { ++ try { ++ // This is confusing. Our two main allocators for breakpad memory are: ++ // - gKeyValueAllocator for the key/value memory ++ // - gBreakpadAllocator for the Breakpad, ExceptionHandler, and other ++ // breakpad allocations which are accessed at exception handling time. ++ // ++ // But in order to avoid these two allocators themselves from being smashed, ++ // we'll protect them as well by allocating them with gMasterAllocator. ++ // ++ // gMasterAllocator itself will NOT be protected, but this doesn't matter, ++ // since once it does its allocations and locks the memory, smashes to itself ++ // don't affect anything we care about. ++ gMasterAllocator = ++ new ProtectedMemoryAllocator(sizeof(ProtectedMemoryAllocator) * 2); ++ ++ gKeyValueAllocator = ++ new (gMasterAllocator->Allocate(sizeof(ProtectedMemoryAllocator))) ++ ProtectedMemoryAllocator(sizeof(SimpleStringDictionary)); ++ ++ // Create a mutex for use in accessing the SimpleStringDictionary ++ int mutexResult = pthread_mutex_init(&gDictionaryMutex, NULL); ++ if (mutexResult == 0) { ++ ++ // With the current compiler, gBreakpadAllocator is allocating 1444 bytes. ++ // Let's round up to the nearest page size. ++ // ++ int breakpad_pool_size = 4096; ++ ++ /* ++ sizeof(Breakpad) ++ + sizeof(google_breakpad::ExceptionHandler) ++ + sizeof( STUFF ALLOCATED INSIDE ExceptionHandler ) ++ */ ++ ++ gBreakpadAllocator = ++ new (gMasterAllocator->Allocate(sizeof(ProtectedMemoryAllocator))) ++ ProtectedMemoryAllocator(breakpad_pool_size); ++ ++ // Stack-based autorelease pool for Breakpad::Create() obj-c code. ++ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; ++ Breakpad *breakpad = Breakpad::Create(parameters); ++ ++ if (breakpad) { ++ // Make read-only to protect against memory smashers ++ gMasterAllocator->Protect(); ++ gKeyValueAllocator->Protect(); ++ gBreakpadAllocator->Protect(); ++ // Can uncomment this line to figure out how much space was actually ++ // allocated using this allocator ++ // printf("gBreakpadAllocator allocated size = %d\n", ++ // gBreakpadAllocator->GetAllocatedSize() ); ++ [pool release]; ++ return (BreakpadRef)breakpad; ++ } ++ ++ [pool release]; ++ } ++ } catch(...) { // don't let exceptions leave this C API ++ fprintf(stderr, "BreakpadCreate() : error\n"); ++ } ++ ++ if (gKeyValueAllocator) { ++ gKeyValueAllocator->~ProtectedMemoryAllocator(); ++ gKeyValueAllocator = NULL; ++ } ++ ++ if (gBreakpadAllocator) { ++ gBreakpadAllocator->~ProtectedMemoryAllocator(); ++ gBreakpadAllocator = NULL; ++ } ++ ++ delete gMasterAllocator; ++ gMasterAllocator = NULL; ++ ++ return NULL; ++} ++ ++//============================================================================= ++void BreakpadRelease(BreakpadRef ref) { ++ try { ++ Breakpad *breakpad = (Breakpad *)ref; ++ ++ if (gMasterAllocator) { ++ gMasterAllocator->Unprotect(); ++ gKeyValueAllocator->Unprotect(); ++ gBreakpadAllocator->Unprotect(); ++ ++ breakpad->~Breakpad(); ++ ++ // Unfortunately, it's not possible to deallocate this stuff ++ // because the exception handling thread is still finishing up ++ // asynchronously at this point... OK, it could be done with ++ // locks, etc. But since BreakpadRelease() should usually only ++ // be called right before the process exits, it's not worth ++ // deallocating this stuff. ++#if 0 ++ gKeyValueAllocator->~ProtectedMemoryAllocator(); ++ gBreakpadAllocator->~ProtectedMemoryAllocator(); ++ delete gMasterAllocator; ++ ++ gMasterAllocator = NULL; ++ gKeyValueAllocator = NULL; ++ gBreakpadAllocator = NULL; ++#endif ++ ++ pthread_mutex_destroy(&gDictionaryMutex); ++ } ++ } catch(...) { // don't let exceptions leave this C API ++ fprintf(stderr, "BreakpadRelease() : error\n"); ++ } ++} ++ ++//============================================================================= ++void BreakpadSetKeyValue(BreakpadRef ref, NSString *key, NSString *value) { ++ try { ++ // Not called at exception time ++ Breakpad *breakpad = (Breakpad *)ref; ++ ++ if (breakpad && key && gKeyValueAllocator) { ++ ProtectedMemoryLocker locker(&gDictionaryMutex, gKeyValueAllocator); ++ ++ breakpad->SetKeyValue(key, value); ++ } ++ } catch(...) { // don't let exceptions leave this C API ++ fprintf(stderr, "BreakpadSetKeyValue() : error\n"); ++ } ++} ++ ++void BreakpadAddUploadParameter(BreakpadRef ref, ++ NSString *key, ++ NSString *value) { ++ // The only difference, internally, between an upload parameter and ++ // a key value one that is set with BreakpadSetKeyValue is that we ++ // prepend the keyname with a special prefix. This informs the ++ // crash sender that the parameter should be sent along with the ++ // POST of the crash dump upload. ++ try { ++ Breakpad *breakpad = (Breakpad *)ref; ++ ++ if (breakpad && key && gKeyValueAllocator) { ++ ProtectedMemoryLocker locker(&gDictionaryMutex, gKeyValueAllocator); ++ ++ NSString *prefixedKey = [@BREAKPAD_SERVER_PARAMETER_PREFIX ++ stringByAppendingString:key]; ++ breakpad->SetKeyValue(prefixedKey, value); ++ } ++ } catch(...) { // don't let exceptions leave this C API ++ fprintf(stderr, "BreakpadSetKeyValue() : error\n"); ++ } ++} ++ ++void BreakpadRemoveUploadParameter(BreakpadRef ref, ++ NSString *key) { ++ try { ++ // Not called at exception time ++ Breakpad *breakpad = (Breakpad *)ref; ++ ++ if (breakpad && key && gKeyValueAllocator) { ++ ProtectedMemoryLocker locker(&gDictionaryMutex, gKeyValueAllocator); ++ ++ NSString *prefixedKey = [NSString stringWithFormat:@"%@%@", ++ @BREAKPAD_SERVER_PARAMETER_PREFIX, key]; ++ breakpad->RemoveKeyValue(prefixedKey); ++ } ++ } catch(...) { // don't let exceptions leave this C API ++ fprintf(stderr, "BreakpadRemoveKeyValue() : error\n"); ++ } ++} ++//============================================================================= ++NSString *BreakpadKeyValue(BreakpadRef ref, NSString *key) { ++ NSString *value = nil; ++ ++ try { ++ // Not called at exception time ++ Breakpad *breakpad = (Breakpad *)ref; ++ ++ if (!breakpad || !key || !gKeyValueAllocator) ++ return nil; ++ ++ ProtectedMemoryLocker locker(&gDictionaryMutex, gKeyValueAllocator); ++ ++ value = breakpad->KeyValue(key); ++ } catch(...) { // don't let exceptions leave this C API ++ fprintf(stderr, "BreakpadKeyValue() : error\n"); ++ } ++ ++ return value; ++} ++ ++//============================================================================= ++void BreakpadRemoveKeyValue(BreakpadRef ref, NSString *key) { ++ try { ++ // Not called at exception time ++ Breakpad *breakpad = (Breakpad *)ref; ++ ++ if (breakpad && key && gKeyValueAllocator) { ++ ProtectedMemoryLocker locker(&gDictionaryMutex, gKeyValueAllocator); ++ ++ breakpad->RemoveKeyValue(key); ++ } ++ } catch(...) { // don't let exceptions leave this C API ++ fprintf(stderr, "BreakpadRemoveKeyValue() : error\n"); ++ } ++} ++ ++//============================================================================= ++void BreakpadGenerateAndSendReport(BreakpadRef ref) { ++ try { ++ Breakpad *breakpad = (Breakpad *)ref; ++ ++ if (breakpad && gKeyValueAllocator) { ++ ProtectedMemoryLocker locker(&gDictionaryMutex, gKeyValueAllocator); ++ ++ gBreakpadAllocator->Unprotect(); ++ breakpad->GenerateAndSendReport(); ++ gBreakpadAllocator->Protect(); ++ } ++ } catch(...) { // don't let exceptions leave this C API ++ fprintf(stderr, "BreakpadGenerateAndSendReport() : error\n"); ++ } ++} ++ ++//============================================================================= ++void BreakpadSetFilterCallback(BreakpadRef ref, ++ BreakpadFilterCallback callback, ++ void *context) { ++ ++ try { ++ Breakpad *breakpad = (Breakpad *)ref; ++ ++ if (breakpad && gBreakpadAllocator) { ++ // share the dictionary mutex here (we really don't need a mutex) ++ ProtectedMemoryLocker locker(&gDictionaryMutex, gBreakpadAllocator); ++ ++ breakpad->SetFilterCallback(callback, context); ++ } ++ } catch(...) { // don't let exceptions leave this C API ++ fprintf(stderr, "BreakpadSetFilterCallback() : error\n"); ++ } ++} ++ ++//============================================================================ ++void BreakpadAddLogFile(BreakpadRef ref, NSString *logPathname) { ++ int logFileCounter = 0; ++ ++ NSString *logFileKey = [NSString stringWithFormat:@"%@%d", ++ @BREAKPAD_LOGFILE_KEY_PREFIX, ++ logFileCounter]; ++ ++ NSString *existingLogFilename = nil; ++ existingLogFilename = BreakpadKeyValue(ref, logFileKey); ++ // Find the first log file key that we can use by testing for existence ++ while (existingLogFilename) { ++ if ([existingLogFilename isEqualToString:logPathname]) { ++ return; ++ } ++ logFileCounter++; ++ logFileKey = [NSString stringWithFormat:@"%@%d", ++ @BREAKPAD_LOGFILE_KEY_PREFIX, ++ logFileCounter]; ++ existingLogFilename = BreakpadKeyValue(ref, logFileKey); ++ } ++ ++ BreakpadSetKeyValue(ref, logFileKey, logPathname); ++} +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/Framework/Breakpad_Prefix.pch b/toolkit/crashreporter/google-breakpad/src/client/mac/Framework/Breakpad_Prefix.pch +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/Framework/Breakpad_Prefix.pch +@@ -0,0 +1,8 @@ ++// ++// Prefix header for all source files of the 'Breakpad' target in the ++// 'Breakpad' project. ++// ++ ++#ifdef __OBJC__ ++ #import ++#endif +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/Framework/Info.plist b/toolkit/crashreporter/google-breakpad/src/client/mac/Framework/Info.plist +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/Framework/Info.plist +@@ -0,0 +1,26 @@ ++ ++ ++ ++ ++ CFBundleDevelopmentRegion ++ English ++ CFBundleExecutable ++ ${EXECUTABLE_NAME} ++ CFBundleName ++ ${PRODUCT_NAME} ++ CFBundleIconFile ++ ++ CFBundleIdentifier ++ com.googlecode.google-breakpad ++ CFBundleInfoDictionaryVersion ++ 6.0 ++ CFBundlePackageType ++ FMWK ++ CFBundleSignature ++ ???? ++ CFBundleVersion ++ 1.0 ++ NSPrincipalClass ++ ++ ++ +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/Framework/OnDemandServer.h b/toolkit/crashreporter/google-breakpad/src/client/mac/Framework/OnDemandServer.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/Framework/OnDemandServer.h +@@ -0,0 +1,146 @@ ++// Copyright (c) 2007, 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 ++#import ++#import ++#import ++#import ++#import ++#import ++ ++//============================================================================== ++// class OnDemandServer : ++// A basic on-demand server launcher supporting a single named service port ++// ++// Example Usage : ++// ++// kern_return_t result; ++// OnDemandServer *server = OnDemandServer::Create("/tmp/myserver", ++// "com.MyCompany.MyServiceName", ++// true, ++// &result); ++// ++// if (server) { ++// server->LaunchOnDemand(); ++// mach_port_t service_port = GetServicePort(); ++// ++// // Send a mach message to service_port and "myserver" will be launched ++// } ++// ++// ++// ---- Now in the server code ---- ++// ++// // "myserver" should get the service port and read the message which ++// // launched it: ++// mach_port_t service_rcv_port_; ++// kern_return_t kr = bootstrap_check_in(bootstrap_port, ++// "com.MyCompany.MyServiceName", ++// &service_rcv_port_); ++// // mach_msg() read service_rcv_port_ .... ++// ++// .... ++// ++// // Later "myserver" may want to unregister the service if it doesn't ++// // want its bootstrap service to stick around after it exits. ++// ++// // DO NOT use mach_port_deallocate() here -- it will fail and the ++// // following bootstrap_register() will also fail leaving our service ++// // name hanging around forever (until reboot) ++// kern_return_t kr = mach_port_destroy(mach_task_self(), service_rcv_port_); ++// ++// kr = bootstrap_register(bootstrap_port, ++// "com.MyCompany.MyServiceName", ++// MACH_PORT_NULL); ++ ++class OnDemandServer { ++ public: ++ // must call Initialize() to be useful ++ OnDemandServer() ++ : server_port_(MACH_PORT_NULL), ++ service_port_(MACH_PORT_NULL), ++ unregister_on_cleanup_(true) { ++ } ++ ++ // Creates the bootstrap server and service ++ kern_return_t Initialize(const char *server_command, ++ const char *service_name, ++ bool unregister_on_cleanup); ++ ++ // Returns an OnDemandServer object if successful, or NULL if there's ++ // an error. The error result will be returned in out_result. ++ // ++ // server_command : the full path name including optional command-line ++ // arguments to the executable representing the server ++ // ++ // service_name : represents service name ++ // something like "com.company.ServiceName" ++ // ++ // unregister_on_cleanup : if true, unregisters the service name ++ // when the OnDemandServer is deleted -- unregistering will ++ // ONLY be possible if LaunchOnDemand() has NOT been called. ++ // If false, then the service will continue to be registered ++ // even after the current process quits. ++ // ++ // out_result : if non-NULL, returns the result ++ // this value will be KERN_SUCCESS if Create() returns non-NULL ++ // ++ static OnDemandServer *Create(const char *server_command, ++ const char *service_name, ++ bool unregister_on_cleanup, ++ kern_return_t *out_result); ++ ++ // Cleans up and if LaunchOnDemand() has not yet been called then ++ // the bootstrap service will be unregistered. ++ ~OnDemandServer(); ++ ++ // This must be called if we intend to commit to launching the server ++ // by sending a mach message to our service port. Do not call it otherwise ++ // or it will be difficult (impossible?) to unregister the service name. ++ void LaunchOnDemand(); ++ ++ // This is the port we need to send a mach message to after calling ++ // LaunchOnDemand(). Sending a message causing an immediate launch ++ // of the server ++ mach_port_t GetServicePort() { return service_port_; }; ++ ++ private: ++ // Disallow copy constructor ++ OnDemandServer(const OnDemandServer&); ++ ++ // Cleans up and if LaunchOnDemand() has not yet been called then ++ // the bootstrap service will be unregistered. ++ void Unregister(); ++ ++ name_t service_name_; ++ ++ mach_port_t server_port_; ++ mach_port_t service_port_; ++ bool unregister_on_cleanup_; ++}; +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/Framework/OnDemandServer.mm b/toolkit/crashreporter/google-breakpad/src/client/mac/Framework/OnDemandServer.mm +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/Framework/OnDemandServer.mm +@@ -0,0 +1,145 @@ ++// Copyright (c) 2007, 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 "OnDemandServer.h" ++ ++#if DEBUG ++ #define PRINT_MACH_RESULT(result_, message_) \ ++ printf(message_"%s (%d)\n", mach_error_string(result_), result_ ); ++#else ++ #define PRINT_MACH_RESULT(result_, message_) ++#endif ++ ++//============================================================================== ++OnDemandServer *OnDemandServer::Create(const char *server_command, ++ const char *service_name, ++ bool unregister_on_cleanup, ++ kern_return_t *out_result) { ++ OnDemandServer *server = new OnDemandServer(); ++ ++ if (!server) return NULL; ++ ++ kern_return_t result = server->Initialize(server_command, ++ service_name, ++ unregister_on_cleanup); ++ ++ if (out_result) { ++ *out_result = result; ++ } ++ ++ if (result == KERN_SUCCESS) { ++ return server; ++ } ++ ++ delete server; ++ return NULL; ++}; ++ ++//============================================================================== ++kern_return_t OnDemandServer::Initialize(const char *server_command, ++ const char *service_name, ++ bool unregister_on_cleanup) { ++ unregister_on_cleanup_ = unregister_on_cleanup; ++ ++ kern_return_t kr = ++ bootstrap_create_server(bootstrap_port, ++ const_cast(server_command), ++ geteuid(), // server uid ++ true, ++ &server_port_); ++ ++ if (kr != KERN_SUCCESS) { ++ PRINT_MACH_RESULT(kr, "bootstrap_create_server() : "); ++ return kr; ++ } ++ ++ strlcpy(service_name_, service_name, sizeof(service_name_)); ++ ++ // Create a service called service_name, and return send rights to ++ // that port in service_port_. ++ kr = bootstrap_create_service(server_port_, ++ const_cast(service_name), ++ &service_port_); ++ ++ if (kr != KERN_SUCCESS) { ++ PRINT_MACH_RESULT(kr, "bootstrap_create_service() : "); ++ ++ // perhaps the service has already been created - try to look it up ++ kr = bootstrap_look_up(bootstrap_port, (char*)service_name, &service_port_); ++ ++ if (kr != KERN_SUCCESS) { ++ PRINT_MACH_RESULT(kr, "bootstrap_look_up() : "); ++ Unregister(); // clean up server port ++ return kr; ++ } ++ } ++ ++ return KERN_SUCCESS; ++} ++ ++//============================================================================== ++OnDemandServer::~OnDemandServer() { ++ if (unregister_on_cleanup_) { ++ Unregister(); ++ } ++} ++ ++//============================================================================== ++void OnDemandServer::LaunchOnDemand() { ++ // We need to do this, since the launched server is another process ++ // and holding on to this port delays launching until the current process ++ // exits! ++ mach_port_deallocate(mach_task_self(), server_port_); ++ server_port_ = NULL; ++ ++ // Now, the service is still registered and all we need to do is send ++ // a mach message to the service port in order to launch the server. ++} ++ ++//============================================================================== ++void OnDemandServer::Unregister() { ++ if (service_port_ != MACH_PORT_NULL) { ++ mach_port_deallocate(mach_task_self(), service_port_); ++ service_port_ = MACH_PORT_NULL; ++ } ++ ++ if (server_port_ != MACH_PORT_NULL) { ++ // unregister the service ++ kern_return_t kr = bootstrap_register(server_port_, ++ service_name_, ++ MACH_PORT_NULL); ++ ++ if (kr != KERN_SUCCESS) { ++ PRINT_MACH_RESULT(kr, "Breakpad UNREGISTER : bootstrap_register() : "); ++ } ++ ++ mach_port_deallocate(mach_task_self(), server_port_); ++ server_port_ = MACH_PORT_NULL; ++ } ++} +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/UnitTests-Info.plist b/toolkit/crashreporter/google-breakpad/src/client/mac/UnitTests-Info.plist +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/UnitTests-Info.plist +@@ -0,0 +1,20 @@ ++ ++ ++ ++ ++ CFBundleDevelopmentRegion ++ English ++ CFBundleExecutable ++ ${EXECUTABLE_NAME} ++ CFBundleIdentifier ++ com.yourcompany.${PRODUCT_NAME:identifier} ++ CFBundleInfoDictionaryVersion ++ 6.0 ++ CFBundlePackageType ++ BNDL ++ CFBundleSignature ++ ???? ++ CFBundleVersion ++ 1.0 ++ ++ +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/crash_generation/Inspector.h b/toolkit/crashreporter/google-breakpad/src/client/mac/crash_generation/Inspector.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/crash_generation/Inspector.h +@@ -0,0 +1,193 @@ ++// Copyright (c) 2007, 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. ++// ++// Interface file between the Breakpad.framework and ++// the Inspector process. ++ ++#import "common/mac/SimpleStringDictionary.h" ++ ++#import ++#import "client/mac/handler/minidump_generator.h" ++ ++#define VERBOSE 0 ++ ++extern bool gDebugLog; ++ ++#define DEBUGLOG if (gDebugLog) fprintf ++ ++// Types of mach messsages (message IDs) ++enum { ++ kMsgType_InspectorInitialInfo = 0, // data is InspectorInfo ++ kMsgType_InspectorKeyValuePair = 1, // data is KeyValueMessageData ++ kMsgType_InspectorAcknowledgement = 2 // no data sent ++}; ++ ++// Initial information sent from the crashed process by ++// Breakpad.framework to the Inspector process ++// The mach message with this struct as data will also include ++// several descriptors for sending mach port rights to the crashed ++// task, etc. ++struct InspectorInfo { ++ int exception_type; ++ int exception_code; ++ int exception_subcode; ++ unsigned int parameter_count; // key-value pairs ++}; ++ ++// Key/value message data to be sent to the Inspector ++struct KeyValueMessageData { ++ public: ++ KeyValueMessageData() {} ++ KeyValueMessageData(const google_breakpad::KeyValueEntry &inEntry) { ++ strlcpy(key, inEntry.GetKey(), sizeof(key) ); ++ strlcpy(value, inEntry.GetValue(), sizeof(value) ); ++ } ++ ++ char key[google_breakpad::KeyValueEntry::MAX_STRING_STORAGE_SIZE]; ++ char value[google_breakpad::KeyValueEntry::MAX_STRING_STORAGE_SIZE]; ++}; ++ ++using std::string; ++using google_breakpad::MinidumpGenerator; ++ ++namespace google_breakpad { ++ ++static BOOL EnsureDirectoryPathExists(NSString *dirPath); ++ ++//============================================================================= ++class ConfigFile { ++ public: ++ ConfigFile() { ++ config_file_ = -1; ++ config_file_path_[0] = 0; ++ has_created_file_ = false; ++ }; ++ ++ ~ConfigFile() { ++ }; ++ ++ void WriteFile(const SimpleStringDictionary *configurationParameters, ++ const char *dump_dir, ++ const char *minidump_id); ++ ++ const char *GetFilePath() { return config_file_path_; } ++ ++ void Unlink() { ++ if (config_file_ != -1) ++ unlink(config_file_path_); ++ ++ config_file_ = -1; ++ } ++ ++ private: ++ BOOL WriteData(const void *data, size_t length); ++ ++ BOOL AppendConfigData(const char *key, ++ const void *data, ++ size_t length); ++ ++ BOOL AppendConfigString(const char *key, ++ const char *value); ++ ++ int config_file_; // descriptor for config file ++ char config_file_path_[PATH_MAX]; // Path to configuration file ++ bool has_created_file_; ++}; ++ ++//============================================================================= ++class MinidumpLocation { ++ public: ++ MinidumpLocation(const NSString *minidumpDir) { ++ // Ensure that the path exists. Fallback to /tmp if unable to locate path. ++ assert(minidumpDir); ++ if (!EnsureDirectoryPathExists(minidumpDir)) { ++ DEBUGLOG(stderr, "Unable to create: %s\n", [minidumpDir UTF8String]); ++ minidumpDir = @"/tmp"; ++ } ++ ++ strlcpy(minidump_dir_path_, [minidumpDir fileSystemRepresentation], ++ sizeof(minidump_dir_path_)); ++ ++ // now generate a unique ID ++ string dump_path(minidump_dir_path_); ++ string next_minidump_id; ++ ++ string next_minidump_path_ = ++ (MinidumpGenerator::UniqueNameInDirectory(dump_path, &next_minidump_id)); ++ ++ strlcpy(minidump_id_, next_minidump_id.c_str(), sizeof(minidump_id_)); ++ }; ++ ++ const char *GetPath() { return minidump_dir_path_; } ++ const char *GetID() { return minidump_id_; } ++ ++ private: ++ char minidump_dir_path_[PATH_MAX]; // Path to minidump directory ++ char minidump_id_[128]; ++}; ++ ++//============================================================================= ++class Inspector { ++ public: ++ Inspector() {}; ++ ++ // given a bootstrap service name, receives mach messages ++ // from a crashed process, then inspects it, creates a minidump file ++ // and asks the user if he wants to upload it to a server. ++ void Inspect(const char *receive_port_name); ++ ++ private: ++ kern_return_t ServiceCheckIn(const char *receive_port_name); ++ kern_return_t ServiceCheckOut(const char *receive_port_name); ++ ++ kern_return_t ReadMessages(); ++ ++ bool InspectTask(); ++ kern_return_t SendAcknowledgement(); ++ void LaunchReporter(const char *inConfigFilePath); ++ ++ void SetCrashTimeParameters(); ++ ++ mach_port_t service_rcv_port_; ++ ++ int exception_type_; ++ int exception_code_; ++ int exception_subcode_; ++ mach_port_t remote_task_; ++ mach_port_t crashing_thread_; ++ mach_port_t handler_thread_; ++ mach_port_t ack_port_; ++ ++ SimpleStringDictionary config_params_; ++ ++ ConfigFile config_file_; ++}; ++ ++ ++} // namespace google_breakpad +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/crash_generation/Inspector.mm b/toolkit/crashreporter/google-breakpad/src/client/mac/crash_generation/Inspector.mm +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/crash_generation/Inspector.mm +@@ -0,0 +1,553 @@ ++// Copyright (c) 2007, 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. ++// ++// Utility that can inspect another process and write a crash dump ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#import "client/mac/crash_generation/Inspector.h" ++ ++#import "client/mac/Framework/Breakpad.h" ++#import "client/mac/handler/minidump_generator.h" ++ ++#import "common/mac/SimpleStringDictionary.h" ++#import "common/mac/MachIPC.h" ++ ++#import ++ ++#if VERBOSE ++ bool gDebugLog = true; ++#else ++ bool gDebugLog = false; ++#endif ++ ++namespace google_breakpad { ++ ++//============================================================================= ++static BOOL EnsureDirectoryPathExists(NSString *dirPath) { ++ NSFileManager *mgr = [NSFileManager defaultManager]; ++ ++ // If we got a relative path, prepend the current directory ++ if (![dirPath isAbsolutePath]) ++ dirPath = [[mgr currentDirectoryPath] stringByAppendingPathComponent:dirPath]; ++ ++ NSString *path = dirPath; ++ ++ // Ensure that no file exists within the path which would block creation ++ while (1) { ++ BOOL isDir; ++ if ([mgr fileExistsAtPath:path isDirectory:&isDir]) { ++ if (isDir) ++ break; ++ ++ return NO; ++ } ++ ++ path = [path stringByDeletingLastPathComponent]; ++ } ++ ++ // Path now contains the first valid directory (or is empty) ++ if (![path length]) ++ return NO; ++ ++ NSString *common = ++ [dirPath commonPrefixWithString:path options:NSLiteralSearch]; ++ ++ // If everything is good ++ if ([common isEqualToString:dirPath]) ++ return YES; ++ ++ // Break up the difference into components ++ NSString *diff = [dirPath substringFromIndex:[common length] + 1]; ++ NSArray *components = [diff pathComponents]; ++ unsigned count = [components count]; ++ ++ // Rebuild the path one component at a time ++ NSDictionary *attrs = ++ [NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedLong:0750] ++ forKey:NSFilePosixPermissions]; ++ path = common; ++ for (unsigned i = 0; i < count; ++i) { ++ path = [path stringByAppendingPathComponent:[components objectAtIndex:i]]; ++ ++ if (![mgr createDirectoryAtPath:path attributes:attrs]) ++ return NO; ++ } ++ ++ return YES; ++} ++ ++//============================================================================= ++BOOL ConfigFile::WriteData(const void *data, size_t length) { ++ size_t result = write(config_file_, data, length); ++ ++ return result == length; ++} ++ ++//============================================================================= ++BOOL ConfigFile::AppendConfigData(const char *key, ++ const void *data, size_t length) { ++ assert(config_file_ != -1); ++ ++ if (!key) { ++ DEBUGLOG(stderr, "Breakpad: Missing Key\n"); ++ return NO; ++ } ++ ++ if (!data) { ++ DEBUGLOG(stderr, "Breakpad: Missing data for key: %s\n", key ? key : ++ ""); ++ return NO; ++ } ++ ++ // Write the key, \n, length of data (ascii integer), \n, data ++ char buffer[16]; ++ char nl = '\n'; ++ BOOL result = WriteData(key, strlen(key)); ++ ++ snprintf(buffer, sizeof(buffer) - 1, "\n%lu\n", length); ++ result &= WriteData(buffer, strlen(buffer)); ++ result &= WriteData(data, length); ++ result &= WriteData(&nl, 1); ++ return result; ++} ++ ++//============================================================================= ++BOOL ConfigFile::AppendConfigString(const char *key, ++ const char *value) { ++ return AppendConfigData(key, value, strlen(value)); ++} ++ ++//============================================================================= ++void ConfigFile::WriteFile(const SimpleStringDictionary *configurationParameters, ++ const char *dump_dir, ++ const char *minidump_id) { ++ ++ assert(config_file_ == -1); ++ ++ // Open and write out configuration file preamble ++ strlcpy(config_file_path_, "/tmp/Config-XXXXXX", ++ sizeof(config_file_path_)); ++ config_file_ = mkstemp(config_file_path_); ++ ++ if (config_file_ == -1) { ++ DEBUGLOG(stderr, ++ "mkstemp(config_file_path_) == -1 (%s)\n", ++ strerror(errno)); ++ return; ++ } ++ else { ++ DEBUGLOG(stderr, "Writing config file to (%s)\n", config_file_path_); ++ } ++ ++ has_created_file_ = true; ++ ++ // Add the minidump dir ++ AppendConfigString(kReporterMinidumpDirectoryKey, dump_dir); ++ AppendConfigString(kReporterMinidumpIDKey, minidump_id); ++ ++ // Write out the configuration parameters ++ BOOL result = YES; ++ const SimpleStringDictionary &dictionary = *configurationParameters; ++ ++ const KeyValueEntry *entry = NULL; ++ SimpleStringDictionaryIterator iter(dictionary); ++ ++ while ((entry = iter.Next())) { ++ DEBUGLOG(stderr, ++ "config: (%s) -> (%s)\n", ++ entry->GetKey(), ++ entry->GetValue()); ++ result = AppendConfigString(entry->GetKey(), entry->GetValue()); ++ ++ if (!result) ++ break; ++ } ++ ++ close(config_file_); ++ config_file_ = -1; ++} ++ ++//============================================================================= ++void Inspector::Inspect(const char *receive_port_name) { ++ kern_return_t result = ServiceCheckIn(receive_port_name); ++ ++ if (result == KERN_SUCCESS) { ++ result = ReadMessages(); ++ ++ if (result == KERN_SUCCESS) { ++ // Inspect the task and write a minidump file. ++ bool wrote_minidump = InspectTask(); ++ ++ // Send acknowledgement to the crashed process that the inspection ++ // has finished. It will then be able to cleanly exit. ++ // The return value is ignored because failure isn't fatal. If the process ++ // didn't get the message there's nothing we can do, and we still want to ++ // send the report. ++ SendAcknowledgement(); ++ ++ if (wrote_minidump) { ++ // Ask the user if he wants to upload the crash report to a server, ++ // and do so if he agrees. ++ LaunchReporter(config_file_.GetFilePath()); ++ } else { ++ fprintf(stderr, "Inspection of crashed process failed\n"); ++ } ++ ++ // Now that we're done reading messages, cleanup the service, but only ++ // if there was an actual exception ++ // Otherwise, it means the dump was generated on demand and the process ++ // lives on, and we might be needed again in the future. ++ if (exception_code_) { ++ ServiceCheckOut(receive_port_name); ++ } ++ } else { ++ PRINT_MACH_RESULT(result, "Inspector: WaitForMessage()"); ++ } ++ } ++} ++ ++//============================================================================= ++kern_return_t Inspector::ServiceCheckIn(const char *receive_port_name) { ++ // We need to get the mach port representing this service, so we can ++ // get information from the crashed process. ++ kern_return_t kr = bootstrap_check_in(bootstrap_port, ++ (char*)receive_port_name, ++ &service_rcv_port_); ++ ++ if (kr != KERN_SUCCESS) { ++#if VERBOSE ++ PRINT_MACH_RESULT(kr, "Inspector: bootstrap_check_in()"); ++#endif ++ } ++ ++ return kr; ++} ++ ++//============================================================================= ++kern_return_t Inspector::ServiceCheckOut(const char *receive_port_name) { ++ // We're done receiving mach messages from the crashed process, ++ // so clean up a bit. ++ kern_return_t kr; ++ ++ // DO NOT use mach_port_deallocate() here -- it will fail and the ++ // following bootstrap_register() will also fail leaving our service ++ // name hanging around forever (until reboot) ++ kr = mach_port_destroy(mach_task_self(), service_rcv_port_); ++ ++ if (kr != KERN_SUCCESS) { ++ PRINT_MACH_RESULT(kr, ++ "Inspector: UNREGISTERING: service_rcv_port mach_port_deallocate()"); ++ return kr; ++ } ++ ++ // Unregister the service associated with the receive port. ++ kr = bootstrap_register(bootstrap_port, ++ (char*)receive_port_name, ++ MACH_PORT_NULL); ++ ++ if (kr != KERN_SUCCESS) { ++ PRINT_MACH_RESULT(kr, "Inspector: UNREGISTERING: bootstrap_register()"); ++ } ++ ++ return kr; ++} ++ ++//============================================================================= ++kern_return_t Inspector::ReadMessages() { ++ // Wait for an initial message from the crashed process containing basic ++ // information about the crash. ++ ReceivePort receive_port(service_rcv_port_); ++ ++ MachReceiveMessage message; ++ kern_return_t result = receive_port.WaitForMessage(&message, 1000); ++ ++ if (result == KERN_SUCCESS) { ++ InspectorInfo &info = (InspectorInfo &)*message.GetData(); ++ exception_type_ = info.exception_type; ++ exception_code_ = info.exception_code; ++ exception_subcode_ = info.exception_subcode; ++ ++#if VERBOSE ++ printf("message ID = %d\n", message.GetMessageID()); ++#endif ++ ++ remote_task_ = message.GetTranslatedPort(0); ++ crashing_thread_ = message.GetTranslatedPort(1); ++ handler_thread_ = message.GetTranslatedPort(2); ++ ack_port_ = message.GetTranslatedPort(3); ++ ++#if VERBOSE ++ printf("exception_type = %d\n", exception_type_); ++ printf("exception_code = %d\n", exception_code_); ++ printf("exception_subcode = %d\n", exception_subcode_); ++ printf("remote_task = %d\n", remote_task_); ++ printf("crashing_thread = %d\n", crashing_thread_); ++ printf("handler_thread = %d\n", handler_thread_); ++ printf("ack_port_ = %d\n", ack_port_); ++ printf("parameter count = %d\n", info.parameter_count); ++#endif ++ ++ // In certain situations where multiple crash requests come ++ // through quickly, we can end up with the mach IPC messages not ++ // coming through correctly. Since we don't know what parameters ++ // we've missed, we can't do much besides abort the crash dump ++ // situation in this case. ++ unsigned int parameters_read = 0; ++ // The initial message contains the number of key value pairs that ++ // we are expected to read. ++ // Read each key/value pair, one mach message per key/value pair. ++ for (unsigned int i = 0; i < info.parameter_count; ++i) { ++ MachReceiveMessage message; ++ result = receive_port.WaitForMessage(&message, 1000); ++ ++ if(result == KERN_SUCCESS) { ++ KeyValueMessageData &key_value_data = ++ (KeyValueMessageData&)*message.GetData(); ++ // If we get a blank key, make sure we don't increment the ++ // parameter count; in some cases (notably on-demand generation ++ // many times in a short period of time) caused the Mach IPC ++ // messages to not come through correctly. ++ if (strlen(key_value_data.key) == 0) { ++ continue; ++ } ++ parameters_read++; ++ ++ config_params_.SetKeyValue(key_value_data.key, key_value_data.value); ++ } else { ++ PRINT_MACH_RESULT(result, "Inspector: key/value message"); ++ break; ++ } ++ } ++ if (parameters_read != info.parameter_count) { ++ DEBUGLOG(stderr, "Only read %d parameters instead of %d, aborting crash " ++ "dump generation.", parameters_read, info.parameter_count); ++ return KERN_FAILURE; ++ } ++ } ++ ++ return result; ++} ++ ++//============================================================================= ++// Sets keys in the parameters dictionary that are specific to process uptime. ++// The two we set are process up time, and process crash time. ++void Inspector::SetCrashTimeParameters() { ++ // Set process uptime parameter ++ struct timeval tv; ++ gettimeofday(&tv, NULL); ++ ++ char processUptimeString[32], processCrashtimeString[32]; ++ const char *processStartTimeString = ++ config_params_.GetValueForKey(BREAKPAD_PROCESS_START_TIME); ++ ++ // Set up time if we've received the start time. ++ if (processStartTimeString) { ++ time_t processStartTime = strtol(processStartTimeString, NULL, 10); ++ time_t processUptime = tv.tv_sec - processStartTime; ++ sprintf(processUptimeString, "%d", processUptime); ++ config_params_.SetKeyValue(BREAKPAD_PROCESS_UP_TIME, processUptimeString); ++ } ++ ++ sprintf(processCrashtimeString, "%d", tv.tv_sec); ++ config_params_.SetKeyValue(BREAKPAD_PROCESS_CRASH_TIME, ++ processCrashtimeString); ++} ++ ++bool Inspector::InspectTask() { ++ // keep the task quiet while we're looking at it ++ task_suspend(remote_task_); ++ DEBUGLOG(stderr, "Suspended Remote task\n"); ++ ++ NSString *minidumpDir; ++ ++ const char *minidumpDirectory = ++ config_params_.GetValueForKey(BREAKPAD_DUMP_DIRECTORY); ++ ++ SetCrashTimeParameters(); ++ // If the client app has not specified a minidump directory, ++ // use a default of Library// ++ if (!minidumpDirectory || 0 == strlen(minidumpDirectory)) { ++ NSArray *libraryDirectories = ++ NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, ++ NSUserDomainMask, ++ YES); ++ ++ NSString *applicationSupportDirectory = ++ [libraryDirectories objectAtIndex:0]; ++ NSString *library_subdirectory = [NSString ++ stringWithUTF8String:kDefaultLibrarySubdirectory]; ++ NSString *breakpad_product = [NSString ++ stringWithUTF8String:config_params_.GetValueForKey(BREAKPAD_PRODUCT)]; ++ ++ NSArray *path_components = [NSArray ++ arrayWithObjects:applicationSupportDirectory, ++ library_subdirectory, ++ breakpad_product, ++ nil]; ++ ++ minidumpDir = [NSString pathWithComponents:path_components]; ++ } else { ++ minidumpDir = [[NSString stringWithUTF8String:minidumpDirectory] ++ stringByExpandingTildeInPath]; ++ } ++ DEBUGLOG(stderr, ++ "Writing minidump to directory (%s)\n", ++ [minidumpDir UTF8String]); ++ ++ MinidumpLocation minidumpLocation(minidumpDir); ++ ++ // Obscure bug alert: ++ // Don't use [NSString stringWithFormat] to build up the path here since it ++ // assumes system encoding and in RTL locales will prepend an LTR override ++ // character for paths beginning with '/' which fileSystemRepresentation does ++ // not remove. Filed as rdar://6889706 . ++ NSString *path_ns = [NSString ++ stringWithUTF8String:minidumpLocation.GetPath()]; ++ NSString *pathid_ns = [NSString ++ stringWithUTF8String:minidumpLocation.GetID()]; ++ NSString *minidumpPath = [path_ns stringByAppendingPathComponent:pathid_ns]; ++ minidumpPath = [minidumpPath ++ stringByAppendingPathExtension:@"dmp"]; ++ ++ DEBUGLOG(stderr, ++ "minidump path (%s)\n", ++ [minidumpPath UTF8String]); ++ ++ ++ config_file_.WriteFile( &config_params_, ++ minidumpLocation.GetPath(), ++ minidumpLocation.GetID()); ++ ++ ++ MinidumpGenerator generator(remote_task_, handler_thread_); ++ ++ if (exception_type_ && exception_code_) { ++ generator.SetExceptionInformation(exception_type_, ++ exception_code_, ++ exception_subcode_, ++ crashing_thread_); ++ } ++ ++ ++ bool result = generator.Write([minidumpPath fileSystemRepresentation]); ++ ++ if (result) { ++ DEBUGLOG(stderr, "Wrote minidump - OK\n"); ++ } else { ++ DEBUGLOG(stderr, "Error writing minidump - errno=%s\n", strerror(errno)); ++ } ++ ++ // let the task continue ++ task_resume(remote_task_); ++ DEBUGLOG(stderr, "Resumed remote task\n"); ++ ++ return result; ++} ++ ++//============================================================================= ++// The crashed task needs to be told that the inspection has finished. ++// It will wait on a mach port (with timeout) until we send acknowledgement. ++kern_return_t Inspector::SendAcknowledgement() { ++ if (ack_port_ != MACH_PORT_DEAD) { ++ MachPortSender sender(ack_port_); ++ MachSendMessage ack_message(kMsgType_InspectorAcknowledgement); ++ ++ DEBUGLOG(stderr, "Inspector: trying to send acknowledgement to port %d\n", ++ ack_port_); ++ ++ kern_return_t result = sender.SendMessage(ack_message, 2000); ++ ++#if VERBOSE ++ PRINT_MACH_RESULT(result, "Inspector: sent acknowledgement"); ++#endif ++ ++ return result; ++ } ++ ++ DEBUGLOG(stderr, "Inspector: port translation failure!\n"); ++ return KERN_INVALID_NAME; ++} ++ ++//============================================================================= ++void Inspector::LaunchReporter(const char *inConfigFilePath) { ++ // Extract the path to the reporter executable. ++ const char *reporterExecutablePath = ++ config_params_.GetValueForKey(BREAKPAD_REPORTER_EXE_LOCATION); ++ DEBUGLOG(stderr, "reporter path = %s\n", reporterExecutablePath); ++ ++ // Setup and launch the crash dump sender. ++ const char *argv[3]; ++ argv[0] = reporterExecutablePath; ++ argv[1] = inConfigFilePath; ++ argv[2] = NULL; ++ ++ // Launch the reporter ++ pid_t pid = fork(); ++ ++ // If we're in the child, load in our new executable and run. ++ // The parent will not wait for the child to complete. ++ if (pid == 0) { ++ execv(argv[0], (char * const *)argv); ++ config_file_.Unlink(); // launch failed - get rid of config file ++ DEBUGLOG(stderr, "Inspector: unable to launch reporter app\n"); ++ _exit(1); ++ } ++ ++ // Wait until the Reporter child process exits. ++ // ++ ++ // We'll use a timeout of one minute. ++ int timeoutCount = 60; // 60 seconds ++ ++ while (timeoutCount-- > 0) { ++ int status; ++ pid_t result = waitpid(pid, &status, WNOHANG); ++ ++ if (result == 0) { ++ // The child has not yet finished. ++ sleep(1); ++ } else if (result == -1) { ++ DEBUGLOG(stderr, "Inspector: waitpid error (%d) waiting for reporter app\n", ++ errno); ++ break; ++ } else { ++ // child has finished ++ break; ++ } ++ } ++} ++ ++} // namespace google_breakpad ++ +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/crash_generation/InspectorMain.mm b/toolkit/crashreporter/google-breakpad/src/client/mac/crash_generation/InspectorMain.mm +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/crash_generation/InspectorMain.mm +@@ -0,0 +1,65 @@ ++// Copyright (c) 2007, 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. ++// ++// Main driver for Inspector ++ ++#import "client/mac/crash_generation/Inspector.h" ++#import ++ ++namespace google_breakpad { ++ ++//============================================================================= ++extern "C" { ++ ++int main(int argc, char *const argv[]) { ++#if DEBUG ++ // Since we're launched on-demand, this is necessary to see debugging ++ // output in the console window. ++ freopen("/dev/console", "w", stdout); ++ freopen("/dev/console", "w", stderr); ++#endif ++ ++ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; ++ ++ if (argc != 2) { ++ exit(0); ++ } ++ // Our first command-line argument contains the name of the service ++ // that we're providing. ++ google_breakpad::Inspector inspector; ++ inspector.Inspect(argv[1]); ++ ++ [pool release]; ++ ++ return 0; ++} ++ ++} // extern "C" ++ ++} // namespace google_breakpad +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/gcov/libgcov.a b/toolkit/crashreporter/google-breakpad/src/client/mac/gcov/libgcov.a +new file mode 100644 +index 0000000000000000000000000000000000000000..f45a58d71d01b554fbf4db03f4805f2123797e18 +GIT binary patch +literal 35048 +zc%1Eh4SZD9weLPNCvXB2WpOTa;5g&JXE1I{E-lSo1k&{z|piY6f$J}!a8WCnws +zBoij1IX$Ee0}GyNQrkl$%J%OkO^h(}kQCak`#UAE!@q`a@2SbNUBP +zw}afm!orm$zt*b+$yJYO^A7{a<$9ZPa4aO7RPd3#VZTToan4{q|mj>y>88{<<+6;Yn_!VorT4vrBOLmtJke8b4F#BI?G(eVH=fKhIMyV +zJ4?zUxr#{E8NsfP#R0Z*$ysYY3+(X;wMK<*z<|=aT9m +z0;hKL5G&(P31q-e>jXmbq29MAFbBi$C|*`r=yF!O!gUJ^^Rt)cN4D>XXYKKGVIm>B +zF(DFfxJ^lws}ig{h>WAq{xQ(aVrCAlezfVr!sS&}5&XQ&{LC=F9dwrlXeUIp`4{)v +z3P93wm?6q9Seysmt(K>Oj69&iQtxf`;TS5OIgG}K$xab~UL +zJDNb{gG>}@3OGTe@?tMkR>t{HxDu5d$=~jt1=2yr3CQlG4&0eT?agX-=2$3`WA+_2 +zJ@g0+0*{-~<2As}&mzYUG*Yo#E>k;f)N4^3vf{D9On?}-H8Q3KWI +zAmTJI9@6E-T4WYdY)XwQmUQfdqb5!Zo7ae{2} +zCAmV>G^0fisLhlDgPbSw#$Xb~ZBS9ck@GXGN)6Hgsis;{$r0(SV*Y%ZTtkzRvcv$K +zoS!HLDrk;LSz=am9-%oFWl4ezatjP#JW#58K4gcd__r6C$x2OVU`ctvF!PAx3ta}18o$7Y0NHswE&&?JtQ +zb0qnciU*LZi1lFZ^Q|*Gg<2Dz@8s9dzZrr`>P3Xg2_qE(a}*O;{wX*ecF%0p(WOHG +zGE+Teq!@*i6E*46$vGm23rGZkDS_@!V5}YWA7|QZDK4jcsv}@&%J~D?$HV +zn7j50#ki56rca47VWQpO107{B#c-F=!2|ex?)o@#N^lI +zBXpM;drWrs$OXMhc8^lf%OLk!XLb(@u)S>NG)1Zl1)fCL83kYu)L<${47icb7XyAu +zC3%S<@HkDH45Mtcumcwi^=V;(pdZ6`+J*e_90PTd>ZHM +zfEjK5fw7@hhulewNr&;TuQNeDOwe!q$bOJv5sVG3ROkK5Hq6pzfj8|}vJxP$H#~uZ +z@}GfhIxhDirKVjz(2h~)@KF@ngk>FX>lG$+zNq9&q9RIqKUSKs4J*ksEwgm?A-SL( +z>!nDFM-m-1$Lr!eF%I|9s!_80s9ba0N4pagN|bFVHceOgzmz6Ahy|id6aEuM|Ccd# +z99V^BI&cW`nhwvy^x-y0tEN#7V+pkk&8I199pAA8`M@b^7-W^lEFT_2Ko}c3u${jQ +zGWGKlWSUUsQ*(H55%lBINX_AQVbQi~?A5=Ij&VOV3f4fQY@_nC!baIgjk5nzWCNKB +zlBpnt>68;TkhgAvM{*qSKw(v^OsQPs^-(nh<*Wj|cf{c95PToSxZiF{Ka3GaKHP;}Q|l->7(@h%-dd2Q#!DvZo9z +zyAosvcJ#qQxPy1`sHJ-f(7+rF?MDM1<%2AX;98{k7on}&1(_uR +z;8*i-ujJ1~O(=?t4R=6JlWzeVsDV#b79W2BWOsi;5s7X5LHB9pKq7Ty_s^B=t14<`aN2iFiyXzb1H+Bq8l>x%hzn1rn26IG==w0^Tk|CqOt66CFy2SY +z9H0*AN)(|5^s+PX3#>pV2plTmD?&F`TGY>X3 +zZdwL~OE7VXiT+MV8nYz +z<5IE-f!R&BlN3ENMUvvrqd_Mh!xN1g6LG7%K(kOFDccZ5`s_m!3fg4`Et;cbA5{vDJGLRB>c$(J +zevC^E0~*Z}D8%BoWzf15y=cqs+dsunjq`f(Wg4RCY`(v@`v>5-9)rWb6m|A3qJvsW +z#o;Kr)9AcX_%!KM|5ff5l}br?Pi{ik1g1lnpqC^K6A&3@VCyd-Zj4)x7+?C>*B5K_ +zdoT#W3||Cj)54ub|0;|beu_u1{{m>n#p_VkyXaouz^B`_U1V#$%ilCxcY>43f*leO*SV6dfrDJXSb;_< +z4~V{FlDcDWdmpzTf`f{H@Igh(F1jGelo?b>|3kDiz%~cCQVGkucDB$01GH%?9 +z6Yv~N05cv5SfSJIH|Umhzf2L{eFI{UPGR?0TsbLhjlKnt-ED_I)EL}Z?=#>fZi|4C +zdpkO8exlT!{}Bk-BEamkuKc39DQH5~j6ZC`47o`PhE~+|W`rqb1U!F3m{izG(DM11=eQJQtemRzAf{VP8k0+|+W3 +z4?_M(Gnwvtz|Qr&KA1Kb(V>j)=+Y}oL=5%nP6GV|@1*!T4d;&lUwQL#Qc+pHVs+W- +zbt_YEtV(^rSy{EZe4Tae>Z-NHu98*OTddCN3TKJSS!%s;R!Wt1Wx0zc#zeNet9acy +zD8bvpuuX|9y9Wx2t#~)mT3YNXwnB+>3|Zk`SK@-M2)n7f+F2FdZZY0&4QsNZywZAO +zbienmcUG<_D}T(2_hun4syMr{5?Y1IA`2I+TVGyM?1~z0Rry+HSkEf!+Tsn?RmJO_ +z*5yv;I%}nKZTWg<>5Wxn5IykD^I&>}%6hNyhwzV*koX!o7*FpJ#uUbrU3l*kSD2-c +z_qBL>&od?;C}hWFLix9Nc`$~MB;fBHALdQKS8MnmnppcioGvg$w*L +z)Mq5Sh^9VV((n4VM*d7*Z~r((n>mf+^kN*N7dU-^Q-2)U)uNGG6c?%2gS_5!PR*PO +zQT2X5mf7u>W63T>lm8m<`!#yD0so?g&*JUoM76sK`0F)%>{!sYcYU(?@DfX~(N6|t=U%-G2BSYnwxBd0n}-;o#%NUYtPQl#F$20lR}|3zMZ +z6R%$vRo@Lf(bO;H^}jGGj6cl(B!=OxD~6T-meZeedW6%TaJrAvVov9CIwywdaZ3!@ +z^==H4{~TmYiV63J{Fo@7MDZVsVLKz=5yk&VWc@uOGQA%cS-)$=@c6#~8706Uj}P+` +zc>Ry{tbPxtr}a$Uaea86jzQiLJ*)52A +z(^oic=G4vU*Emh&6!xW|{`w%JS77~}6Igktru-Sm*e@_WcSPlXo42dr<%=}sxsW%H +zm*2|Ezrg9IgwZZekCSjaH1iRj{}SXMjSuJV<@w*`w4T$uqS~kOe0=tS{XYr)j)QM1 +ze4pm&zrc4dPfr2+9^&b-(D3J&hCIZ|8$6A;dYjjIm*JBbA^lB(Jv+hl-SPBs8%=M9 +z3b*hy;W}aZerS6yPk$eMiKo*b{Wwp*4E;UH)1@$HJ9v60q+jIe21uXe>BW%#Bc!h% +z<)zP$J|Q@dtYeYQDX~IKHwocqVv~e$ovE7ijhgf=nskaLovuk|YtoA}>H9V52Q}$p +zO?tH^{ir6rL6ff2q$k7oi}1xw_Y@p2e7`{0^DTU)j<&x6zSH149mhi0bF%Ajj5uca +zs*lzFd7pK1`Se6-KG)#uBt0!w3T +zOd^rbm(`D;`409uC=6U4dVH4+7r^e(p(h>u5r?GMlxi`6UMw7o{~bQrv&q$>uU(R} +zC0};0pk((tvJLLv@`iMy{3WJ;j2fTuGl_&_h^oin2SXx!`-<^1*KzBB_+bZ4!VnrM +ze!2;pf21S9&p8stk4?w=y%PLjd&I~L?LiANFn)4%ERAcJjf@;WMY`I_g%@7< +z&}sPfU*v*wh$9=rQ5RM^pIs+8-Y`D#ErOT|C5ud4$Z$B1I_?w+butD%SBm%BY_NgFy4#!`h6vM$M$%Cui!HF2YB6wDa1Rml^7!TKzNNj{{Il$>ozWt|pWEfoBHpu#)9KHV2Q=uVXj1(7m +z&5QGjbR@XgPQthdi~twd9&vH@GH}tyae?<6t_Bwgx#OL77Ii +zrYsTJ@&4Ccr9Z{SzD^;Wt%H5$yZqptuYIbot7qoXCRZZvK;==sps@anFQZZrAe-_; +zxu8cOviMD3hv4|geIB19^V4NG$R=kWMqb*-L425h{{Lui*Q)DvEa{KW@g$5%D;XM} +zkq3@BK-tOSYl+Va6`=oY_#E!K=ARLt6G#}7)5vAuvtmGiR$#p=#%E~v8G%pd)#CF< +zgy9S6Nbvc662@oW2=IyR5ufKT1D_JVE=##ed?pQt&*#Wc_^i6N_*4pdsFWT&=94IC +z;EH(b57*}+o_;lxE61yj^xqFgy`!PUE1kD1#cPT^WdOXczv}fK*Ufo+Uo{fEP96*8Gh&68{`?5KtZ588~U?IJunr%|qd2|4=xg_nReL%xVmZ+Z4bDN3z=_1BYv% +z#9#5i`q~93iS-#XkzD=yvwn#6XQc11&arFoGr;?+@Y%3S6ajF2H`Eu337L<#JIC>M;6f>Q3o?Q6_=@SwrH~KT=r+uM4=m*+^c7ZG +zK9|#loECAqo>L#EPjmW1PLK2cy#Mo`)BOX!pK5d1=gb)xhYtH(dqf=L0qoK{AODJk +zUo+$(OlN1SG4jHxfxUTB3e9Eovc5MqaK +zT|l=R))EQ8rT5fKuHHH=XuA`xb@mBl(Y{P_&*o_)V{;~%2h4$5 +zFxXs7a_wH7uI~Bs)%I55rRD|13||qx2KY+NvBZ>1#>ZfNkiQ|*OZFFmKD54<#M*Zf +zdoGFp*=&ezna>h4)ZO3(w9f|6WIh`_oBkZH+hERvdNsbYlPp-bxfY`Fvm^n_Kqo3c +zmyo3>J0!oJV4H5NpV30B-de0P{v#MG9eeXs+9na}+YxljU|e3BZ}Bdtb(^4`V4p@# +zdG4A}4Qsme3fRyi>384bC04bsBGtY-gT48src|^q+S1-i1l7J^*L~@Q5X6s|587)< +zg7+;Y>GV^O|F0AFz*wc5z4~Cr4w7gu63N2grNfxV^)z{>ni62_2`JC| +z@Ps|sC+hCFfh2hJ|7OlFF{OeIlBeWubM)M(_Mr1n1h(aU!x&eioGs7OJ(`5F2eN5M +z{~gn-aSR|sr;%}EoqVaH?i-^jR9Tzvf_WPbAKV@&3+0C8UHUDTBX03Ay`tr4^+CT$ +z+X0ve>+?OFE1+>eMW8WW57JAY0+qZi!~l88kTyZujQUesdSL!q00Wx-piBz&R~)>6 +z_KTXoR*Vn6v+)7MDa@Cl<_3~iCtETALz@u4vt>dYfN_sbXGZLzU*~6;Qa!q*v())a +zgFl<^AclhJrd0F=7?ZH27U%Lov%S>>xEmLbvhz!NUiIj8=DHmu1KJt@D>I;9lZOQI +zz>Wmk7(8S=_5*Q-%uwy^T?YCAHXO@ILe1?ub3QSpZoUEJ7lHg~q==3g$2S08qVdZ7 +z*3<{_L-iYJVen!+#*-zxOsU}KsBZ_0FLD2$`fkaj3W!nSU_OieZFxI*(X)JVwdWht +zX`hHwwcm7-VnbUO5nE7 +z-)&D96MI3{kvkwi-QF;+{po4s4*1@_J(HwDolJWP*=O&7vbTvH>f8ys--xzU?czhd +z2J#0SM{R%mc)=#KnU1Z1pPAf7o6>`X)IUND^(&2Cjbmucl{^ddyFJoqS3zw1IIVxw +zSRdSwo*{M=Wli}ptPv8%=Yk?BydG +z#xKAa+Q(iZbmbDmM9fF*ZTVN@SsK5lvY0j0d_=~HPX%n31Zz>|M!>nAwfE@tbR8I^ +zy(UIn>~KJV19bDOf^}~r_}MBV)&od!&e7hUg%hf47C{>1)|5O{UDHr9pzH|$2Yg2P +z{(@%a`;LMzYI0pX!oFeHke7vo}&4HP%lfOY1YqGJAWteLdJRzujW5S)((1;fl$-hKMzH +zTg){xrcdW +zL0VF6QSFX7TfGm_@o(qj-;O*VzZb^e3gh2p +z?}{3K*P!EXh4JswjDOD{<8RZ9e-DhmjgJ4%Fn+H+BXdWv1@#2G#~_yJp0A4to)h}r +z4uRMmX&StAEwy<@|Ysy{`}hjbY^wn;H!Hxg>UTE*aI9=B0bI3h<|5=8L-R>11U|5h*RMQ}-~DZ2^z5 +z1-Wn?18r{cluoX$D|xeeVesS4EH3HNA%CKGGT@l@t;>b9iS0RrQt*#vUmE(!C-2oQ +z+x!Ol8>Ih~4wnwF29es|{~T?%6lCdu=0VvB&liu+VzNjE@GpBO5s~w@G_YAJ%p3H9 +zduG9tb;{<+A!w(AFs^y3{nEU_;Ov%Q5XXXhAH44Li|2L5h{s)hXl%!^E~3pSEANY|9NK2NM*GmlO% +zgNjKoXXyX~?;eA8Y +z75&7!j$I$o>xp|H4#SvnpU^yxSOC}CGM*x498WkVj1mwdEFKCrZzgF+AA%SlfN!>E +z;C>k50>p+xXah(ef;!vTSUx@KeH(mSASdgK$bw~&2E0v9ZU!FW%{gd)8rq)$9~NLgCqTP%HMt<;CMx4J$T-7w$^)Ic +zxK3TrE|2SE1D$X`(E~aKK&J~(wiIM8tEX`{LZ<-8yP(mjSEEx8=+p~s`=ISbjShX# +z<|6cqaq|$H>x+j_2cF&sZK^SbqMzcJa9>KX!SuWUGH?&>0zLpX_Cj7S@E+6|_(tF_ +z0^b09AMnkP-h|hfz*lf=ErRs9I@U)9%%=;kIlEv!t+_;>%=bYv)cBPC2i1S$4EAGj +zO94wipx4kK&yMeC;F@5CcnQ~n4%owaV)eW24-sn($yH;k88HsHFf@;adJyw*esFJu +zcug-_S(5Heu_4BbN=l218f=-M_t}NP_x%ueA>RJ=op7up=Td>D!k#A;aOrym@aQGF +z^df=KnAMJZiuV`aX%%*Q+<{qj2mWGCn?hy$Z+4CG*PRjTIbgSTc__A(`nJPbGyNCU +z5B$!Qx}-sZnESpky9IqvFx35+%!2-t(lqNiUcY!@Uz7G05z-FRe(LL5deBb;*e3N2 +z$hSaT{jo3$>th_c(?N7R7B%3wQnwPJ_P|r-x~+8Wwxt*CB(;ecAO8BY+0As!hFZN3 +z_}+=>Mb8tMtFt(s42&&BINtYuxiHxCGM_gaUK6u85VtH8hd0J~!ZAVjj;g=!>##p~ +z264~_*X{z{M+5G~mtp^ed#jp?dTYP^G+ci~Ut28X!G|JPWA36TOG24MmJ6U_V3t_bhf;AAX?LpZzSeE!gU~uLX2%q4B?MplcyA +zzz6k3U29h9cHh1RdHrs`qTgO4V;j*rNV#X2@}gnN=M7UnW0-Qo(B-fy65qynu^D;z?t!K1HK6&tK7`4MM_GL-7wXSr +ze4Gb)C{G7|m!{m#__$@rgPa*$ULvO!P7REjE^@k$Q!l4^oaSM=WE(Eu=2R2ocFTwI0KhcfpQ3mYvptkr}LOT +zaT%o*SUFwvqZw=&*vikC}~5>2Z6k(8RxhrLw_B=h2j%(Naze)TvG!woI6cM2Gxj8G1AD{m#vWz7p^eEM+YWp{ +zQ+|l?hE`s_ANaGH@_mdqY~}r~;{7e5r$8<5? +zP{HJnY3KF#@%o^*xkXcd7vs?$wEk9BKbFsLtcSIWU8S`j@XPR7P*_fEggt@JW94yY +zS$)YB_B$+>Di|Mkj`b^*vHqlGoJvfO(cC{q^LZH^;Ixa=Gn`g%YGZyesxRE%s660% +zv^;#d{YD|KY-)ZR8Fh~FLKkm$CQ8ofFg|JhQ>@&0mX~{?%3X{%cJY4se2+?C{l|cw +z=2BKaW>*`1EgJc8?Z`vf+m)8@AkaS`L=1H2xOXClX?$Z@IXxYS?Z^c<($KlLq~F5*;Tdg|K4 +z{pny#x?McKS)1QRbekAIVGr_9o*OO~F0g0GsK3q@m7mDu2^Y2bZA9o}yg8lK6L_2y +z8a4GQpk4#7caWWn5K?%(#Be?QF;78a_9uOuo@Mp$EQ7WlIm+`fZWO8cZS*I`kvHe@ +zdV9E>7EZYzl0{MSaxuS+9#O&kN%+jw1a>e3Z)Nq&;BPtuC_l+~oe6m;hqyM$%*rPOpuCOox+LWHQhQD^@$%zPzKQWTZxfC~ +zIr@cxm+yh{GREslk%w}OClW7jgz`mO%&_tIB{C-QY=Jd7Xb9eI5b@=%WJ +z>^WY(ip@XrdJpn@>GSl7UA!E|kI&hW*KbFj(1Sl;Lae28YUebCQyZsAoX+4hky9(D +z37lFuHFIj>)WE64smLi|RMFn +zH0eZ5dX6TYu1VjeN#CtW-=|4`O_MIxq*rUwk80A7Y0`C?vEWfld>s|fY~Yy?JY}c; +z1OuM+z}K?ys2tj0I$=N6fIsDcu?v6NVe&PSfyedexsw0+=g6+j?>ZzdnwPaG`BwWC +z|Gq=X+KNGb=b>~%8Q96?US7C-^}15HvMXHWEUUnw|5y9~1R3JJW<19>$a%`!Qlih} +z4*WY11D|Wdwam(SK_mlzaG%r2Xy`1Io?-QJ&b8rB$I$j5AJ<$wV0Iwo`pdhana +z81Q^&`UZTSuiksi+(_(rE+g&hMDRU}XMl(Zi(f(Acg~QShppzC^y|!I->6a3^w;!pW=<^0Dr+y*?yHp=Z +zCojCf&g8tX*V8~Io}mSuEj($cMub_ +zO{&{r$-pyoo|1scll8V~%Omt$6g@N8TuWupXO*5Bi^;Pr-qgH+kml9k!w!gpkHE!o +zEiu<^KOTM_cLy;+-)8V}3;1}F+JDH;(I(f<&vW@TTRNwis^64DR_cA%-<}5FDd^ki~k=fQnd{H+*J3Ske{d5JwyFGWy?3fzh59?NXA`fOf@(B+N6;Y +zd3NmU;P(&q^Lq=lO^EV)3$#xFzqf+lC#dcJPJSQZ?}T2vP-?vj|F>xT|CZtXe~8~Y +z8QlE`ey?!||G(|F==T~UfB)nv_Qj3dZ}B^leen#9-{bu;-4*VOGuT()ey>A?r7PSQ +zdkMYYLHE|UFD_y<;`KXqUtGa;-N*YL%J21q*bK$B5<>dfl=^)~uunZ(2_Q=jof(CE +z#Bnag?ZBTwaBm;_87fJL@(cW^zF^|Mfbp(@?}7RKE6U?_KEHoOyu6(I3g!7xB^;}s +z+eshoGw~Xqxn7gLG0J~*8an)M!dyfDaX6y)&5^$oa~136D!y*wdwU~UHzke#;JvFW +z^dA8g%z$Ql2wOKX^9uckuA7o(-OM0^`j4L9Q`9$;tMVUu&u(D<;qN$T-fw92+%dKq +z)|TexSBbazEz;0@i8OAWN;bh-gXbIHu}>vl2cDgtO7IvC?sM(1cTLAMe(Ucbc6%)B +zXQA8+YZyP%WybU5&^}3956_wQuNw>$EH|avb!4g+YZ5OT_sDXjA(j;;Ro +zE`n=ol4DIUShHHc+fhnzeNBfpC@a1G2Dt9MnVq@HBEdkN?~k~zzt20Z|N9z)S?wCe +zhaMguQo`{;DAlZ$Nt{nWK58wUp;=4uwWAqi==d;R6BDeO^i7u&ABOl%o1`5nSR +z;)L@v5GO33$BFP~WN|`>`$vouScb7eE%$zxZrG;{6*sP3oS^RbS&9?d7!h&3KICsv +zUE?^>|9U<0cdGsyuh;FLU$2Kh+IJ#7E#dd6!GC7rbvwSpRM+swi1+q$*|l@1{WV%| +zQ@9^l{tK?xuX;Z|$nSMs`F?yb|FK8^&UNJPczy0aBl4fCSZ6=?pKG~a9rX9iuJt-J +zupeE6{pwZwQO4(f6#i&`D+B$=^UBSkJu84Q8=s%3zEtOYllc>W-wMjbYv@PnGnItT +Rh#w8PpBwbI-G=d_{{+ece?9;J + +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/exception_handler.cc b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/exception_handler.cc +--- a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/exception_handler.cc ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/exception_handler.cc +@@ -87,22 +87,25 @@ exception_mask_t s_exception_mask = EXC_ + EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC | EXC_MASK_BREAKPOINT; + + extern "C" + { + // Forward declarations for functions that need "C" style compilation + boolean_t exc_server(mach_msg_header_t *request, + mach_msg_header_t *reply); + ++ // This symbol must be visible to dlsym() - see ++ // http://code.google.com/p/google-breakpad/issues/detail?id=345 for details. + kern_return_t catch_exception_raise(mach_port_t target_port, + mach_port_t failed_thread, + mach_port_t task, + exception_type_t exception, + exception_data_t code, +- mach_msg_type_number_t code_count); ++ mach_msg_type_number_t code_count) ++ __attribute__((visibility("default"))); + + kern_return_t ForwardException(mach_port_t task, + mach_port_t failed_thread, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t code_count); + + kern_return_t exception_raise(mach_port_t target_port, +@@ -317,18 +320,18 @@ bool ExceptionHandler::WriteMinidumpWith + if (!dump_path_.empty()) { + MinidumpGenerator md; + if (exception_type && exception_code) { + // If this is a real exception, give the filter (if any) a chance to + // decided if this should be sent + if (filter_ && !filter_(callback_context_)) + return false; + +- md.SetExceptionInformation(exception_type, exception_code, exception_subcode, +- thread_name); ++ md.SetExceptionInformation(exception_type, exception_code, ++ exception_subcode, thread_name); + } + + result = md.Write(next_minidump_path_c_); + } + + // Call user specified callback (if any) + if (callback_) { + // If the user callback returned true and we're handling an exception +@@ -430,16 +433,19 @@ kern_return_t ForwardException(mach_port + } + + // Callback from exc_server() + kern_return_t catch_exception_raise(mach_port_t port, mach_port_t failed_thread, + mach_port_t task, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t code_count) { ++ if (task != mach_task_self()) { ++ return KERN_FAILURE; ++ } + return ForwardException(task, failed_thread, exception, code, code_count); + } + + // static + void *ExceptionHandler::WaitForMessage(void *exception_handler_class) { + ExceptionHandler *self = + reinterpret_cast(exception_handler_class); + ExceptionMessage receive; +@@ -488,17 +494,16 @@ void *ExceptionHandler::WaitForMessage(v + gBreakpadAllocator->Protect(); + #endif + + self->ResumeThreads(); + + if (self->use_minidump_write_mutex_) + pthread_mutex_unlock(&self->minidump_write_mutex_); + } else { +- + // When forking a child process with the exception handler installed, + // if the child crashes, it will send the exception back to the parent + // process. The check for task == self_task() ensures that only + // exceptions that occur in the parent process are caught and + // processed. If the exception was not caused by this task, we + // still need to call into the exception server and have it return + // KERN_FAILURE (see breakpad_exception_raise) in order for the kernel + // to move onto the host exception handler for the child task +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/exception_handler_test.cc b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/exception_handler_test.cc +--- a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/exception_handler_test.cc ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/exception_handler_test.cc +@@ -23,25 +23,17 @@ + // 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. + + /* +-g++ -framework CoreFoundation -I../../.. \ +- ../../minidump_file_writer.cc \ +- ../../../common/convert_UTF.c \ +- ../../../common/string_conversion.cc \ +- ../../../common/mac/string_utilities.cc \ +- exception_handler.cc \ +- minidump_generator.cc \ +- exception_handler_test.cc \ +- -o exception_handler_test ++g++ -framework CoreFoundation -I../../.. ../../minidump_file_writer.cc ../../../common/convert_UTF.c ../../../common/string_conversion.cc ../../../common/mac/string_utilities.cc exception_handler.cc minidump_generator.cc exception_handler_test.cc -o exception_handler_test -mmacosx-version-min=10.4 ../../../common/mac/file_id.cc dynamic_images.cc ../../../common/mac/macho_id.cc ../../../common/mac/macho_walker.cc -lcrypto ../../../common/mac/macho_utilities.cc + */ + + #include + #include + #include + + #include + +@@ -50,16 +42,17 @@ g++ -framework CoreFoundation -I../../.. + + using std::string; + using google_breakpad::ExceptionHandler; + + static void *SleepyFunction(void *) { + while (1) { + sleep(10000); + } ++ return NULL; + } + + static void Crasher() { + int *a = (int*)0x42; + + fprintf(stdout, "Going to crash...\n"); + fprintf(stdout, "A = %d", *a); + } +@@ -72,36 +65,35 @@ bool MDCallback(const char *dump_dir, co + void *context, bool success) { + string path(dump_dir); + string dest(dump_dir); + path.append(file_name); + path.append(".dmp"); + + fprintf(stdout, "Minidump: %s\n", path.c_str()); + // Indicate that we've handled the callback +- return true; ++ exit(0); + } + + int main(int argc, char * const argv[]) { + char buffer[PATH_MAX]; +- struct passwd *user = getpwuid(getuid()); + + // Home dir +- snprintf(buffer, sizeof(buffer), "/Users/%s/Desktop/", user->pw_name); ++ snprintf(buffer, sizeof(buffer), "/tmp/"); + + string path(buffer); + ExceptionHandler eh(path, NULL, MDCallback, NULL, true); + pthread_t t; + + if (pthread_create(&t, NULL, SleepyFunction, NULL) == 0) { + pthread_detach(t); + } else { + perror("pthread_create"); + } + +- // Dump a test +- eh.WriteMinidump(); ++// // Dump a test ++// eh.WriteMinidump(); + + // Test the handler + SoonToCrash(); + + return 0; + } +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator.cc b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator.cc +--- a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator.cc ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator.cc +@@ -169,17 +169,17 @@ bool MinidumpGenerator::Write(const char + &MinidumpGenerator::WriteModuleListStream, + &MinidumpGenerator::WriteMiscInfoStream, + &MinidumpGenerator::WriteBreakpadInfoStream, + // Exception stream needs to be the last entry in this array as it may + // be omitted in the case where the minidump is written without an + // exception. + &MinidumpGenerator::WriteExceptionStream, + }; +- bool result = true; ++ bool result = false; + + // If opening was successful, create the header, directory, and call each + // writer. The destructor for the TypedMDRVAs will cause the data to be + // flushed. The destructor for the MinidumpFileWriter will close the file. + if (writer_.Open(path)) { + TypedMDRVA header(&writer_); + TypedMDRVA dir(&writer_); + +@@ -200,16 +200,17 @@ bool MinidumpGenerator::Write(const char + MDRawHeader *header_ptr = header.get(); + header_ptr->signature = MD_HEADER_SIGNATURE; + header_ptr->version = MD_HEADER_VERSION; + time(reinterpret_cast(&(header_ptr->time_date_stamp))); + header_ptr->stream_count = writer_count; + header_ptr->stream_directory_rva = dir.position(); + + MDRawDirectory local_dir; ++ result = true; + for (int i = 0; (result) && (i < writer_count); ++i) { + result = (this->*writers[i])(&local_dir); + + if (result) + dir.CopyIndex(i, &local_dir); + } + } + return result; +@@ -317,56 +318,43 @@ bool MinidumpGenerator::WriteStackFromSt + return result; + } + + #if TARGET_CPU_PPC || TARGET_CPU_PPC64 + bool MinidumpGenerator::WriteStack(breakpad_thread_state_data_t state, + MDMemoryDescriptor *stack_location) { + breakpad_thread_state_t *machine_state = + reinterpret_cast(state); +-#if TARGET_CPU_PPC +- mach_vm_address_t start_addr = machine_state->r1; +-#else +- mach_vm_address_t start_addr = machine_state->__r1; +-#endif ++ mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, r1); + return WriteStackFromStartAddress(start_addr, stack_location); + } + + u_int64_t + MinidumpGenerator::CurrentPCForStack(breakpad_thread_state_data_t state) { + breakpad_thread_state_t *machine_state = + reinterpret_cast(state); + +-#if TARGET_CPU_PPC +- return machine_state->srr0; +-#else +- return machine_state->__srr0; +-#endif ++ return REGISTER_FROM_THREADSTATE(machine_state, srr0); + } + + bool MinidumpGenerator::WriteContext(breakpad_thread_state_data_t state, + MDLocationDescriptor *register_location) { + TypedMDRVA context(&writer_); + breakpad_thread_state_t *machine_state = + reinterpret_cast(state); + + if (!context.Allocate()) + return false; + + *register_location = context.location(); + MinidumpContext *context_ptr = context.get(); + context_ptr->context_flags = MD_CONTEXT_PPC_BASE; + +-#if TARGET_CPU_PPC64 +-#define AddReg(a) context_ptr->a = machine_state->__ ## a +-#define AddGPR(a) context_ptr->gpr[a] = machine_state->__r ## a +-#else +-#define AddReg(a) context_ptr->a = machine_state->a +-#define AddGPR(a) context_ptr->gpr[a] = machine_state->r ## a +-#endif ++#define AddReg(a) context_ptr->a = REGISTER_FROM_THREADSTATE(machine_state, a) ++#define AddGPR(a) context_ptr->gpr[a] = REGISTER_FROM_THREADSTATE(machine_state, r ## a) + + AddReg(srr0); + AddReg(cr); + AddReg(xer); + AddReg(ctr); + AddReg(lr); + AddReg(vrsave); + +@@ -415,51 +403,50 @@ bool MinidumpGenerator::WriteContext(bre + #elif TARGET_CPU_X86 || TARGET_CPU_X86_64 + + bool MinidumpGenerator::WriteStack(breakpad_thread_state_data_t state, + MDMemoryDescriptor *stack_location) { + breakpad_thread_state_t *machine_state = + reinterpret_cast(state); + + #if TARGET_CPU_X86_64 +- mach_vm_address_t start_addr = machine_state->__rsp; ++ mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, rsp); + #else +- mach_vm_address_t start_addr = machine_state->esp; ++ mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, esp); + #endif + return WriteStackFromStartAddress(start_addr, stack_location); + } + + u_int64_t + MinidumpGenerator::CurrentPCForStack(breakpad_thread_state_data_t state) { + breakpad_thread_state_t *machine_state = + reinterpret_cast(state); + + #if TARGET_CPU_X86_64 +- return machine_state->__rip; ++ return REGISTER_FROM_THREADSTATE(machine_state, rip); + #else +- return machine_state->eip; ++ return REGISTER_FROM_THREADSTATE(machine_state, eip); + #endif + } + + bool MinidumpGenerator::WriteContext(breakpad_thread_state_data_t state, + MDLocationDescriptor *register_location) { + TypedMDRVA context(&writer_); + breakpad_thread_state_t *machine_state = + reinterpret_cast(state); + + if (!context.Allocate()) + return false; + + *register_location = context.location(); + MinidumpContext *context_ptr = context.get(); + ++#define AddReg(a) context_ptr->a = REGISTER_FROM_THREADSTATE(machine_state, a) + #if TARGET_CPU_X86 + context_ptr->context_flags = MD_CONTEXT_X86; +- +-#define AddReg(a) context_ptr->a = machine_state->a + AddReg(eax); + AddReg(ebx); + AddReg(ecx); + AddReg(edx); + AddReg(esi); + AddReg(edi); + AddReg(ebp); + AddReg(esp); +@@ -469,18 +456,16 @@ bool MinidumpGenerator::WriteContext(bre + AddReg(ss); + AddReg(es); + AddReg(fs); + AddReg(gs); + AddReg(eflags); + + AddReg(eip); + #else +- +-#define AddReg(a) context_ptr->a = machine_state->__ ## a + context_ptr->context_flags = MD_CONTEXT_AMD64; + AddReg(rax); + AddReg(rbx); + AddReg(rcx); + AddReg(rdx); + AddReg(rdi); + AddReg(rsi); + AddReg(rbp); +@@ -498,16 +483,17 @@ bool MinidumpGenerator::WriteContext(bre + // not used in the flags register. Since the minidump format + // specifies 32 bits for the flags register, we can truncate safely + // with no loss. + context_ptr->eflags = machine_state->__rflags; + AddReg(cs); + AddReg(fs); + AddReg(gs); + #endif ++#undef AddReg(a) + + return true; + } + #endif + + bool MinidumpGenerator::WriteThreadStream(mach_port_t thread_id, + MDRawThread *thread) { + breakpad_thread_state_data_t state; +@@ -646,23 +632,38 @@ bool MinidumpGenerator::WriteSystemInfoS + int unused, unused2; + // get vendor id + cpuid(0, unused, info_ptr->cpu.x86_cpu_info.vendor_id[0], + info_ptr->cpu.x86_cpu_info.vendor_id[2], + info_ptr->cpu.x86_cpu_info.vendor_id[1]); + // get version and feature info + cpuid(1, info_ptr->cpu.x86_cpu_info.version_information, unused, unused2, + info_ptr->cpu.x86_cpu_info.feature_information); ++ + // family + info_ptr->processor_level = + (info_ptr->cpu.x86_cpu_info.version_information & 0xF00) >> 8; + // 0xMMSS (Model, Stepping) + info_ptr->processor_revision = + (info_ptr->cpu.x86_cpu_info.version_information & 0xF) | + ((info_ptr->cpu.x86_cpu_info.version_information & 0xF0) << 4); ++ ++ // decode extended model info ++ if (info_ptr->processor_level == 0xF || ++ info_ptr->processor_level == 0x6) { ++ info_ptr->processor_revision |= ++ ((info_ptr->cpu.x86_cpu_info.version_information & 0xF0000) >> 4); ++ } ++ ++ // decode extended family info ++ if (info_ptr->processor_level == 0xF) { ++ info_ptr->processor_level += ++ ((info_ptr->cpu.x86_cpu_info.version_information & 0xFF00000) >> 20); ++ } ++ + #endif // __i386__ + break; + default: + info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_UNKNOWN; + break; + } + + info_ptr->number_of_processors = number_of_processors; +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator.h b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator.h +--- a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator.h ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator.h +@@ -61,16 +61,28 @@ typedef MDRawContextX86 MinidumpContext; + #elif TARGET_CPU_PPC64 + typedef ppc_thread_state64_t breakpad_thread_state_t; + typedef MDRawContextPPC64 MinidumpContext; + #elif TARGET_CPU_PPC + typedef ppc_thread_state_t breakpad_thread_state_t; + typedef MDRawContextPPC MinidumpContext; + #endif + ++// Use the REGISTER_FROM_THREADSTATE to access a register name from the ++// breakpad_thread_state_t structure. ++#if __DARWIN_UNIX03 || TARGET_CPU_X86_64 || TARGET_CPU_PPC64 ++// In The 10.5 SDK Headers Apple prepended __ to the variable names in the ++// i386_thread_state_t structure. There's no good way to tell what version of ++// the SDK we're compiling against so we just toggle on the same preprocessor ++// symbol Apple's headers use. ++#define REGISTER_FROM_THREADSTATE(a, b) ((a)->__ ## b) ++#else ++#define REGISTER_FROM_THREADSTATE(a, b) (a->b) ++#endif ++ + // Creates a minidump file of the current process. If there is exception data, + // use SetExceptionInformation() to add this to the minidump. The minidump + // file is generated by the Write() function. + // Usage: + // MinidumpGenerator minidump(); + // minidump.Write("/tmp/minidump"); + // + class MinidumpGenerator { +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator_test.cc b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator_test.cc +--- a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator_test.cc ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_generator_test.cc +@@ -40,24 +40,23 @@ + using std::string; + using google_breakpad::MinidumpGenerator; + + static bool doneWritingReport = false; + + static void *Reporter(void *) { + char buffer[PATH_MAX]; + MinidumpGenerator md; +- struct passwd *user = getpwuid(getuid()); + + // Write it to the desktop + snprintf(buffer, + sizeof(buffer), +- "/Users/%s/Desktop/test.dmp", +- user->pw_name); +- ++ "/tmp/test.dmp"); ++ ++ + fprintf(stdout, "Writing %s\n", buffer); + unlink(buffer); + md.Write(buffer); + doneWritingReport = true; + + return NULL; + } + +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_test.xcodeproj/project.pbxproj b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_test.xcodeproj/project.pbxproj +--- a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_test.xcodeproj/project.pbxproj ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/minidump_test.xcodeproj/project.pbxproj +@@ -128,19 +128,19 @@ + F917C4F80E03265A00F86017 /* breakpad_exc_server.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = breakpad_exc_server.h; sourceTree = ""; }; + F93A88750E8B4C700026AF89 /* octestcases.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = octestcases.octest; sourceTree = BUILT_PRODUCTS_DIR; }; + F93A88760E8B4C700026AF89 /* obj-cTestCases-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "obj-cTestCases-Info.plist"; sourceTree = ""; }; + F9721F300E8B07E800D7E813 /* dwarftests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dwarftests.h; sourceTree = ""; }; + F9721F310E8B07E800D7E813 /* dwarftests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = dwarftests.mm; sourceTree = ""; }; + F9721F380E8B0CFC00D7E813 /* dump_syms.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dump_syms.h; path = ../../../common/mac/dump_syms.h; sourceTree = SOURCE_ROOT; }; + F9721F390E8B0D0D00D7E813 /* dump_syms.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = dump_syms.mm; path = ../../../common/mac/dump_syms.mm; sourceTree = SOURCE_ROOT; }; + F9721F6B0E8B0D7000D7E813 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; +- F9721F760E8B0DC700D7E813 /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/mac/dwarf/bytereader.cc; sourceTree = SOURCE_ROOT; }; +- F9721F770E8B0DC700D7E813 /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/mac/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; }; +- F9721F780E8B0DC700D7E813 /* functioninfo.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = functioninfo.cc; path = ../../../common/mac/dwarf/functioninfo.cc; sourceTree = SOURCE_ROOT; }; ++ F9721F760E8B0DC700D7E813 /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/dwarf/bytereader.cc; sourceTree = SOURCE_ROOT; }; ++ F9721F770E8B0DC700D7E813 /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; }; ++ F9721F780E8B0DC700D7E813 /* functioninfo.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = functioninfo.cc; path = ../../../common/dwarf/functioninfo.cc; sourceTree = SOURCE_ROOT; }; + F9721FA10E8B0E2300D7E813 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = /System/Library/Frameworks/SenTestingKit.framework; sourceTree = ""; }; + F9721FA80E8B0E4800D7E813 /* md5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = md5.c; path = ../../../common/md5.c; sourceTree = SOURCE_ROOT; }; + F982089A0DB3280D0017AECA /* breakpad_nlist_test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = breakpad_nlist_test.h; sourceTree = ""; }; + F982089B0DB3280D0017AECA /* breakpad_nlist_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = breakpad_nlist_test.cc; sourceTree = ""; }; + F98208A10DB32CAE0017AECA /* breakpad_nlist_64.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = breakpad_nlist_64.cc; sourceTree = ""; }; + F98208A20DB32CAE0017AECA /* breakpad_nlist_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = breakpad_nlist_64.h; sourceTree = ""; }; + F9AE19B50DB040E300C98454 /* minidump_tests32-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "minidump_tests32-Info.plist"; sourceTree = ""; }; + F9AE19C30DB04A9500C98454 /* minidump_tests64.cptest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = minidump_tests64.cptest; sourceTree = BUILT_PRODUCTS_DIR; }; +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/testcases/testdata/dump_syms_i386_breakpad.sym b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/testcases/testdata/dump_syms_i386_breakpad.sym +--- a/toolkit/crashreporter/google-breakpad/src/client/mac/handler/testcases/testdata/dump_syms_i386_breakpad.sym ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/handler/testcases/testdata/dump_syms_i386_breakpad.sym +@@ -75,49 +75,49 @@ FILE 73 /Developer/SDKs/MacOSX10.4u.sdk/ + FILE 74 ../../../common/mac/dwarf/dwarf2reader.h + FILE 75 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_stack.h + FILE 76 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/deque.tcc + FILE 77 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/list.tcc + FILE 78 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/vector.tcc + FILE 79 /Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/bits/stl_uninitialized.h + FILE 80 /var/tmp/gcc/gcc-5484~1/src/gcc/libgcc2.c + FUNC 162a 28 0 _OSSwapInt16 +-162a 10 44 1 +-163a 16 46 1 +-1650 2 47 1 ++162a 10 44 55 ++163a 16 46 55 ++1650 2 47 55 + FUNC 1652 1c 0 _OSSwapInt32 +-1652 f 53 1 +-1661 8 55 1 +-1669 3 56 1 +-166c 2 57 1 ++1652 f 53 55 ++1661 8 55 55 ++1669 3 56 55 ++166c 2 57 55 + FUNC 166e 2b 0 _OSSwapInt64 +-166e 12 64 1 +-1680 11 69 1 +-1691 6 70 1 +-1697 2 71 1 +-1699 1 71 1 ++166e 12 64 55 ++1680 11 69 55 ++1691 6 70 55 ++1697 2 71 55 ++1699 1 71 55 + FUNC 169a 1e 0 NXSwapShort +-169a 10 43 2 +-16aa c 45 2 +-16b6 2 46 2 ++169a 10 43 56 ++16aa c 45 56 ++16b6 2 46 56 + FUNC 16b8 19 0 NXSwapInt +-16b8 f 52 2 +-16c7 8 54 2 +-16cf 2 55 2 +-16d1 1 55 2 ++16b8 f 52 56 ++16c7 8 54 56 ++16cf 2 55 56 ++16d1 1 55 56 + FUNC 16d2 19 0 NXSwapLong +-16d2 f 61 2 +-16e1 8 63 2 +-16e9 2 64 2 +-16eb 1 64 2 ++16d2 f 61 56 ++16e1 8 63 56 ++16e9 2 64 56 ++16eb 1 64 56 + FUNC 16ec 1f 0 NXSwapLongLong +-16ec 12 70 2 +-16fe b 72 2 +-1709 2 73 2 +-170b 1 73 2 ++16ec 12 70 56 ++16fe b 72 56 ++1709 2 73 56 ++170b 1 73 56 + FUNC 170c 181 0 -[DumpSymbols convertCPlusPlusSymbols:] + 170c 14 128 3 + 1720 54 130 3 + 1774 f 132 3 + 1783 7 133 3 + 178a 1a 136 3 + 17a4 5 138 3 + 17a9 1a 139 3 +@@ -144,2237 +144,2201 @@ 19d0 1e 171 3 + 19ee 11 162 3 + 19ff 7 181 3 + 1a06 6 182 3 + 1a0c 5 184 3 + 1a11 15 185 3 + 1a26 6 18 4 + 1a2c 6 19 4 + 1a32 6 20 4 +-1a38 6 185 4 +-1a3e 28 186 4 +-1a66 21 187 4 +-1a87 1a 188 4 +-1aa1 a 190 4 +-1aab c 194 4 +-1ab7 43 198 4 +-1afa 21 199 4 +-1b1b 20 202 4 +-1b3b 2e 203 4 +-1b69 1e 194 4 +-1b87 c 184 4 +-1b93 17 207 4 +-1baa 7 208 4 +-1bb1 1 208 4 ++1a38 6 185 3 ++1a3e 28 186 3 ++1a66 21 187 3 ++1a87 1a 188 3 ++1aa1 a 190 3 ++1aab c 194 3 ++1ab7 43 198 3 ++1afa 21 199 3 ++1b1b 20 202 3 ++1b3b 2e 203 3 ++1b69 1e 194 3 ++1b87 c 184 3 ++1b93 17 207 3 ++1baa 7 208 3 ++1bb1 1 208 3 + FUNC 1bb2 4a2 0 -[DumpSymbols addFunction:line:address:section:] +-1bb2 21 211 4 +-1bd3 2f 212 4 +-1c02 e 214 4 +-1c10 4 219 4 +-1c14 2a 221 4 +-1c3e 22 223 4 +-1c60 6 224 4 +-1c66 2a 225 4 +-1c90 4 226 4 +-1c94 2e 230 4 +-1cc2 2e 233 4 +-1cf0 2e 236 4 +-1d1e a 239 4 +-1d28 2b 253 4 +-1d53 e 254 4 +-1d61 3c 255 4 ++1bb2 21 211 3 ++1bd3 2f 212 3 ++1c02 e 214 3 ++1c10 4 219 3 ++1c14 2a 221 3 ++1c3e 22 223 3 ++1c60 6 224 3 ++1c66 2a 225 3 ++1c90 4 226 3 ++1c94 2e 230 3 ++1cc2 2e 233 3 ++1cf0 2e 236 3 ++1d1e a 239 3 ++1d28 2b 253 3 ++1d53 e 254 3 ++1d61 3c 255 3 + 1d9d 22 32 4 +-1dbf 3 256 4 +-1dc2 6 259 4 +-1dc8 a 260 4 +-1dd2 3c 261 4 +-1e0e 25 262 4 +-1e33 2a 263 4 +-1e5d 22 265 4 +-1e7f 26 270 4 +-1ea5 6 272 4 +-1eab 37 273 4 +-1ee2 2a 274 4 +-1f0c 17 275 4 +-1f23 43 278 4 +-1f66 2e 279 4 +-1f94 23 282 4 +-1fb7 43 285 4 +-1ffa 52 287 4 +-204c 8 289 4 ++1dbf 3 256 3 ++1dc2 6 259 3 ++1dc8 a 260 3 ++1dd2 3c 261 3 ++1e0e 25 262 3 ++1e33 2a 263 3 ++1e5d 22 265 3 ++1e7f 26 270 3 ++1ea5 6 272 3 ++1eab 37 273 3 ++1ee2 2a 274 3 ++1f0c 17 275 3 ++1f23 43 278 3 ++1f66 2e 279 3 ++1f94 23 282 3 ++1fb7 43 285 3 ++1ffa 52 287 3 ++204c 8 289 3 + FUNC 2054 5a4 0 -[DumpSymbols processSymbolItem:stringTable:] +-2054 18 292 4 +-206c 8 293 4 +-2074 4 294 4 +-2078 16 297 4 +-208e c 298 4 +-209a f 300 4 +-20a9 b 301 4 +-20b4 16 303 4 +-20ca 4d 309 4 +-2117 38 311 4 +-214f 30 315 4 +-217f 60 317 4 +-21df d 322 4 +-21ec 2b 325 4 +-2217 3a 327 4 +-2251 f 332 4 +-2260 2d 333 4 +-228d 1a 334 4 +-22a7 32 335 4 +-22d9 20 342 4 +-22f9 c 343 4 +-2305 24 348 4 +-2329 a 349 4 +-2333 3c 350 4 +-236f 2a 352 4 +-2399 1c 353 4 +-23b5 9 354 4 +-23be f 356 4 +-23cd 2d 357 4 +-23fa 2f 358 4 +-2429 20 360 4 +-2449 c 361 4 +-2455 7 363 4 +-245c 21 365 4 +-247d 4a 368 4 +-24c7 9 370 4 +-24d0 1a 371 4 +-24ea 4b 372 4 +-2535 4 373 4 +-2539 5 371 4 +-253e 29 374 4 +-2567 2d 376 4 +-2594 4b 378 4 +-25df 4 379 4 +-25e3 a 382 4 +-25ed b 383 4 ++2054 18 292 3 ++206c 8 293 3 ++2074 4 294 3 ++2078 16 297 3 ++208e c 298 3 ++209a f 300 3 ++20a9 b 301 3 ++20b4 16 303 3 ++20ca 4d 309 3 ++2117 38 311 3 ++214f 30 315 3 ++217f 60 317 3 ++21df d 322 3 ++21ec 2b 325 3 ++2217 3a 327 3 ++2251 f 332 3 ++2260 2d 333 3 ++228d 1a 334 3 ++22a7 32 335 3 ++22d9 20 342 3 ++22f9 c 343 3 ++2305 24 348 3 ++2329 a 349 3 ++2333 3c 350 3 ++236f 2a 352 3 ++2399 1c 353 3 ++23b5 9 354 3 ++23be f 356 3 ++23cd 2d 357 3 ++23fa 2f 358 3 ++2429 20 360 3 ++2449 c 361 3 ++2455 7 363 3 ++245c 21 365 3 ++247d 4a 368 3 ++24c7 9 370 3 ++24d0 1a 371 3 ++24ea 4b 372 3 ++2535 4 373 3 ++2539 5 371 3 ++253e 29 374 3 ++2567 2d 376 3 ++2594 4b 378 3 ++25df 4 379 3 ++25e3 a 382 3 ++25ed b 383 3 + FUNC 25f8 c9 0 -[DumpSymbols loadSymbolInfo:offset:] +-25f8 13 391 4 +-260b 2b 392 4 +-2636 2a 393 4 +-2660 2d 395 4 +-268d 2e 398 4 +-26bb 6 399 4 +-26c1 1 399 4 ++25f8 13 391 3 ++260b 2b 392 3 ++2636 2a 393 3 ++2660 2d 395 3 ++268d 2e 398 3 ++26bb 6 399 3 ++26c1 1 399 3 + FUNC 26c2 2be 0 -[DumpSymbols loadSTABSSymbolInfo:offset:] +-26c2 16 537 4 +-26d8 9 538 4 +-26e1 10 539 4 +-26f1 2e 540 4 +-271f 9 542 4 +-2728 22 543 4 +-274a 4 544 4 +-274e a 546 4 +-2758 3c 547 4 +-2794 c 549 4 +-27a0 e 550 4 +-27ae 6 551 4 +-27b4 25 552 4 +-27d9 25 553 4 +-27fe 25 554 4 +-2823 c 555 4 +-282f c 556 4 +-283b c 559 4 +-2847 23 562 4 +-286a a 563 4 +-2874 a 564 4 +-287e 2e 565 4 +-28ac 39 566 4 +-28e5 2e 570 4 +-2913 4 571 4 +-2917 17 559 4 +-292e 25 575 4 +-2953 9 576 4 +-295c 17 549 4 +-2973 4 579 4 +-2977 9 580 4 ++26c2 16 537 3 ++26d8 9 538 3 ++26e1 10 539 3 ++26f1 2e 540 3 ++271f 9 542 3 ++2728 22 543 3 ++274a 4 544 3 ++274e a 546 3 ++2758 3c 547 3 ++2794 c 549 3 ++27a0 e 550 3 ++27ae 6 551 3 ++27b4 25 552 3 ++27d9 25 553 3 ++27fe 25 554 3 ++2823 c 555 3 ++282f c 556 3 ++283b c 559 3 ++2847 23 562 3 ++286a a 563 3 ++2874 a 564 3 ++287e 2e 565 3 ++28ac 39 566 3 ++28e5 2e 570 3 ++2913 4 571 3 ++2917 17 559 3 ++292e 25 575 3 ++2953 9 576 3 ++295c 17 549 3 ++2973 4 579 3 ++2977 9 580 3 + FUNC 2980 28a 0 -[DumpSymbols loadSymbolInfo64:offset:] +-2980 16 583 4 +-2996 9 585 4 +-299f 10 586 4 +-29af 2e 587 4 +-29dd 9 589 4 +-29e6 22 590 4 +-2a08 4 591 4 +-2a0c c 593 4 +-2a18 e 594 4 +-2a26 6 595 4 +-2a2c 25 596 4 +-2a51 25 597 4 +-2a76 25 598 4 +-2a9b 9 599 4 +-2aa4 c 600 4 +-2ab0 c 603 4 +-2abc 17 604 4 +-2ad3 23 609 4 +-2af6 a 610 4 +-2b00 a 611 4 +-2b0a 2e 612 4 +-2b38 37 613 4 +-2b6f 2e 615 4 +-2b9d 4 616 4 +-2ba1 17 603 4 +-2bb8 25 620 4 +-2bdd 9 621 4 +-2be6 17 593 4 +-2bfd 4 624 4 +-2c01 9 625 4 ++2980 16 583 3 ++2996 9 585 3 ++299f 10 586 3 ++29af 2e 587 3 ++29dd 9 589 3 ++29e6 22 590 3 ++2a08 4 591 3 ++2a0c c 593 3 ++2a18 e 594 3 ++2a26 6 595 3 ++2a2c 25 596 3 ++2a51 25 597 3 ++2a76 25 598 3 ++2a9b 9 599 3 ++2aa4 c 600 3 ++2ab0 c 603 3 ++2abc 17 604 3 ++2ad3 23 609 3 ++2af6 a 610 3 ++2b00 a 611 3 ++2b0a 2e 612 3 ++2b38 37 613 3 ++2b6f 2e 615 3 ++2b9d 4 616 3 ++2ba1 17 603 3 ++2bb8 25 620 3 ++2bdd 9 621 3 ++2be6 17 593 3 ++2bfd 4 624 3 ++2c01 9 625 3 + FUNC 2c0a 199 0 -[DumpSymbols loadSymbolInfoForArchitecture] +-2c0a 13 628 4 +-2c1d 41 630 4 +-2c5e 2b 631 4 +-2c89 1a 632 4 +-2ca3 40 634 4 +-2ce3 40 635 4 +-2d23 5f 637 4 +-2d82 17 639 4 +-2d99 4 640 4 +-2d9d 6 641 4 +-2da3 1 641 4 ++2c0a 13 628 3 ++2c1d 41 630 3 ++2c5e 2b 631 3 ++2c89 1a 632 3 ++2ca3 40 634 3 ++2ce3 40 635 3 ++2d23 5f 637 3 ++2d82 17 639 3 ++2d99 4 640 3 ++2d9d 6 641 3 ++2da3 1 641 3 + FUNC 2da4 3e5 0 -[DumpSymbols loadHeader:offset:] +-2da4 18 728 4 +-2dbc 9 729 4 +-2dc5 10 730 4 +-2dd5 2e 731 4 +-2e03 9 733 4 +-2e0c 2b 734 4 +-2e37 1e 736 4 +-2e55 c 738 4 +-2e61 e 739 4 +-2e6f 6 740 4 +-2e75 50 742 4 +-2ec5 2e 743 4 +-2ef3 2e 744 4 +-2f21 2e 745 4 +-2f4f 20 746 4 +-2f6f 1b7 755 4 +-3126 9 757 4 +-312f 25 761 4 +-3154 9 762 4 +-315d 17 738 4 +-3174 a 765 4 +-317e b 766 4 +-3189 1 766 4 ++2da4 18 728 3 ++2dbc 9 729 3 ++2dc5 10 730 3 ++2dd5 2e 731 3 ++2e03 9 733 3 ++2e0c 2b 734 3 ++2e37 1e 736 3 ++2e55 c 738 3 ++2e61 e 739 3 ++2e6f 6 740 3 ++2e75 50 742 3 ++2ec5 2e 743 3 ++2ef3 2e 744 3 ++2f21 2e 745 3 ++2f4f 20 746 3 ++2f6f 1b7 755 3 ++3126 9 757 3 ++312f 25 761 3 ++3154 9 762 3 ++315d 17 738 3 ++3174 a 765 3 ++317e b 766 3 ++3189 1 766 3 + FUNC 318a 41d 0 -[DumpSymbols loadHeader64:offset:] +-318a 18 769 4 +-31a2 9 771 4 +-31ab 10 772 4 +-31bb 2e 773 4 +-31e9 9 775 4 +-31f2 c 777 4 +-31fe 2b 778 4 +-3229 e 779 4 +-3237 6 780 4 +-323d 50 781 4 +-328d 49 782 4 +-32d6 49 783 4 +-331f 2e 784 4 +-334d 9 785 4 +-3356 29 786 4 +-337f 1c5 794 4 +-3544 9 795 4 +-354d 25 799 4 +-3572 9 800 4 +-357b 17 777 4 +-3592 a 803 4 +-359c b 804 4 +-35a7 1 804 4 ++318a 18 769 3 ++31a2 9 771 3 ++31ab 10 772 3 ++31bb 2e 773 3 ++31e9 9 775 3 ++31f2 c 777 3 ++31fe 2b 778 3 ++3229 e 779 3 ++3237 6 780 3 ++323d 50 781 3 ++328d 49 782 3 ++32d6 49 783 3 ++331f 2e 784 3 ++334d 9 785 3 ++3356 29 786 3 ++337f 1c5 794 3 ++3544 9 795 3 ++354d 25 799 3 ++3572 9 800 3 ++357b 17 777 3 ++3592 a 803 3 ++359c b 804 3 ++35a7 1 804 3 + FUNC 35a8 52a 0 -[DumpSymbols loadModuleInfo] +-35a8 14 807 4 +-35bc e 808 4 +-35ca 41 810 4 +-360b 1a 811 4 +-3625 6 812 4 +-362b 6 814 4 +-3631 17 815 4 +-3648 c 816 4 +-3654 29 820 4 +-367d 29 821 4 +-36a6 29 822 4 +-36cf 35 824 4 +-3704 12 826 4 +-3716 17 827 4 +-372d c 828 4 +-3739 3c 832 4 +-3775 a 834 4 +-377f 9 836 4 +-3788 25 837 4 +-37ad c 839 4 +-37b9 54 840 4 +-380d 57 841 4 +-3864 57 842 4 +-38bb 57 843 4 +-3912 57 844 4 +-3969 1c 846 4 +-3985 4b 847 4 +-39d0 49 849 4 +-3a19 13 839 4 +-3a2c 6 851 4 +-3a32 3c 852 4 +-3a6e 3a 854 4 +-3aa8 17 857 4 +-3abf c 858 4 +-3acb 7 859 4 ++35a8 14 807 3 ++35bc e 808 3 ++35ca 41 810 3 ++360b 1a 811 3 ++3625 6 812 3 ++362b 6 814 3 ++3631 17 815 3 ++3648 c 816 3 ++3654 29 820 3 ++367d 29 821 3 ++36a6 29 822 3 ++36cf 35 824 3 ++3704 12 826 3 ++3716 17 827 3 ++372d c 828 3 ++3739 3c 832 3 ++3775 a 834 3 ++377f 9 836 3 ++3788 25 837 3 ++37ad c 839 3 ++37b9 54 840 3 ++380d 57 841 3 ++3864 57 842 3 ++38bb 57 843 3 ++3912 57 844 3 ++3969 1c 846 3 ++3985 4b 847 3 ++39d0 49 849 3 ++3a19 13 839 3 ++3a2c 6 851 3 ++3a32 3c 852 3 ++3a6e 3a 854 3 ++3aa8 17 857 3 ++3abf c 858 3 ++3acb 7 859 3 + FUNC 3ad2 b6 0 WriteFormat +-3ad2 10 862 4 +-3ae2 6 867 4 +-3ae8 24 868 4 +-3b0c 27 869 4 +-3b33 40 870 4 +-3b73 c 873 4 +-3b7f 9 874 4 ++3ad2 10 862 3 ++3ae2 6 867 3 ++3ae8 24 868 3 ++3b0c 27 869 3 ++3b33 40 870 3 ++3b73 c 873 3 ++3b7f 9 874 3 + FUNC 3b88 35 0 -[DumpSymbols availableArchitectures] +-3b88 13 1140 4 +-3b9b 1c 1141 4 +-3bb7 6 1142 4 +-3bbd 1 1142 4 ++3b88 13 1140 3 ++3b9b 1c 1141 3 ++3bb7 6 1142 3 ++3bbd 1 1142 3 + FUNC 3bbe 1b4 0 -[DumpSymbols setArchitecture:] +-3bbe 13 1158 4 +-3bd1 1a 1159 4 +-3beb 4 1160 4 +-3bef 2a 1162 4 +-3c19 9 1163 4 +-3c22 2a 1165 4 +-3c4c 9 1166 4 +-3c55 9 1167 4 +-3c5e 2a 1169 4 +-3c88 6 1170 4 +-3c8e 2a 1172 4 +-3cb8 6 1173 4 +-3cbe 2a 1175 4 +-3ce8 4 1176 4 +-3cec 6 1179 4 +-3cf2 2c 1180 4 +-3d1e 9 1181 4 +-3d27 1c 1183 4 +-3d43 1f 1184 4 +-3d62 a 1187 4 +-3d6c 6 1188 4 ++3bbe 13 1158 3 ++3bd1 1a 1159 3 ++3beb 4 1160 3 ++3bef 2a 1162 3 ++3c19 9 1163 3 ++3c22 2a 1165 3 ++3c4c 9 1166 3 ++3c55 9 1167 3 ++3c5e 2a 1169 3 ++3c88 6 1170 3 ++3c8e 2a 1172 3 ++3cb8 6 1173 3 ++3cbe 2a 1175 3 ++3ce8 4 1176 3 ++3cec 6 1179 3 ++3cf2 2c 1180 3 ++3d1e 9 1181 3 ++3d27 1c 1183 3 ++3d43 1f 1184 3 ++3d62 a 1187 3 ++3d6c 6 1188 3 + FUNC 3d72 14 0 -[DumpSymbols architecture] +-3d72 c 1191 4 +-3d7e 6 1192 4 +-3d84 2 1193 4 ++3d72 c 1191 3 ++3d7e 6 1192 3 ++3d84 2 1193 3 + FUNC 3d86 e7 0 -[DumpSymbols writeSymbolFile:] +-3d86 13 1196 4 +-3d99 1a 1197 4 +-3db3 48 1200 4 +-3dfb 9 1201 4 +-3e04 1e 1203 4 +-3e22 6 1205 4 +-3e28 9 1206 4 +-3e31 21 1208 4 +-3e52 b 1210 4 +-3e5d a 1212 4 +-3e67 6 1213 4 +-3e6d 1 1213 4 ++3d86 13 1196 3 ++3d99 1a 1197 3 ++3db3 48 1200 3 ++3dfb 9 1201 3 ++3e04 1e 1203 3 ++3e22 6 1205 3 ++3e28 9 1206 3 ++3e31 21 1208 3 ++3e52 b 1210 3 ++3e5d a 1212 3 ++3e67 6 1213 3 ++3e6d 1 1213 3 + FUNC 3e6e 65 0 -[MachSection initWithMachSection:andNumber:] +-3e6e 13 1219 4 +-3e81 37 1220 4 +-3eb8 9 1221 4 +-3ec1 9 1222 4 +-3eca 3 1225 4 +-3ecd 6 1226 4 +-3ed3 1 1226 4 ++3e6e 13 1219 3 ++3e81 37 1220 3 ++3eb8 9 1221 3 ++3ec1 9 1222 3 ++3eca 3 1225 3 ++3ecd 6 1226 3 ++3ed3 1 1226 3 + FUNC 3ed4 14 0 -[MachSection sectionPointer] +-3ed4 c 1228 4 +-3ee0 6 1229 4 +-3ee6 2 1230 4 ++3ed4 c 1228 3 ++3ee0 6 1229 3 ++3ee6 2 1230 3 + FUNC 3ee8 14 0 -[MachSection sectionNumber] +-3ee8 c 1232 4 +-3ef4 6 1233 4 +-3efa 2 1234 4 ++3ee8 c 1232 3 ++3ef4 6 1233 3 ++3efa 2 1234 3 + FUNC 3efc 17c 0 -[DumpSymbols processDWARFSourceFileInfo:] +-3efc 14 459 4 +-3f10 a 460 4 +-3f1a 3c 461 4 +-3f56 20 463 4 +-3f76 5 464 4 +-3f7b 3a 465 4 +-3fb5 1d 466 4 +-3fd2 3a 467 4 +-400c 2a 468 4 +-4036 3b 464 4 +-4071 7 471 4 +-FUNC 4078 1d7 0 DumpFunctionMap +-4078 15 82 4 +-408d 13 83 4 +-40a0 1e 85 4 +-40be 42 89 4 +-4100 20 90 4 +-4120 2b 91 4 +-414b 1a 92 4 +-4165 23 93 4 +-4188 46 96 4 +-41ce 46 99 4 +-4214 33 83 4 +-4247 8 102 4 +-424f 1 102 4 ++3efc 14 459 3 ++3f10 a 460 3 ++3f1a 3c 461 3 ++3f56 20 463 3 ++3f76 5 464 3 ++3f7b 3a 465 3 ++3fb5 1d 466 3 ++3fd2 3a 467 3 ++400c 2a 468 3 ++4036 3b 464 3 ++4071 7 471 3 ++FUNC 4078 1d7 0 DumpFunctionMap(std::map, std::allocator > >) ++4078 15 82 3 ++408d 13 83 3 ++40a0 1e 85 3 ++40be 42 89 3 ++4100 20 90 3 ++4120 2b 91 3 ++414b 1a 92 3 ++4165 23 93 3 ++4188 46 96 3 ++41ce 46 99 3 ++4214 33 83 3 ++4247 8 102 3 ++424f 1 102 3 + FUNC 4250 3ef 0 -[DumpSymbols processDWARFFunctionInfo:] +-4250 15 473 4 +-4265 25 474 4 +-428a 1e 476 4 +-42a8 a 480 4 +-42b2 3c 481 4 +-42ee 3d 483 4 +-432b 23 485 4 +-434e 26 487 4 +-4374 6 489 4 +-437a 37 490 4 +-43b1 2a 491 4 +-43db 17 492 4 +-43f2 30 496 4 +-4422 3d 497 4 +-445f 2e 498 4 +-448d 30 502 4 +-44bd 64 504 4 +-4521 34 507 4 +-4555 9d 509 4 +-45f2 45 474 4 +-4637 8 513 4 +-463f 1 513 4 ++4250 15 473 3 ++4265 25 474 3 ++428a 1e 476 3 ++42a8 a 480 3 ++42b2 3c 481 3 ++42ee 3d 483 3 ++432b 23 485 3 ++434e 26 487 3 ++4374 6 489 3 ++437a 37 490 3 ++43b1 2a 491 3 ++43db 17 492 3 ++43f2 30 496 3 ++4422 3d 497 3 ++445f 2e 498 3 ++448d 30 502 3 ++44bd 64 504 3 ++4521 34 507 3 ++4555 9d 509 3 ++45f2 45 474 3 ++4637 8 513 3 ++463f 1 513 3 + FUNC 4640 1f5 0 -[DumpSymbols processDWARFLineNumberInfo:] +-4640 15 515 4 +-4655 25 516 4 +-467a 39 520 4 +-46b3 26 521 4 +-46d9 6 523 4 +-46df 37 524 4 +-4716 2a 525 4 +-4740 17 526 4 +-4757 30 529 4 +-4787 61 531 4 +-47e8 45 516 4 +-482d 8 534 4 +-4835 1 534 4 ++4640 15 515 3 ++4655 25 516 3 ++467a 39 520 3 ++46b3 26 521 3 ++46d9 6 523 3 ++46df 37 524 3 ++4716 2a 525 3 ++4740 17 526 3 ++4757 30 529 3 ++4787 61 531 3 ++47e8 45 516 3 ++482d 8 534 3 ++4835 1 534 3 + FUNC 4836 10f 0 -[DumpSymbols dealloc] +-4836 13 1145 4 +-4849 1c 1146 4 +-4865 1c 1147 4 +-4881 1c 1148 4 +-489d 1c 1149 4 +-48b9 1c 1150 4 +-48d5 1c 1151 4 +-48f1 25 1152 4 +-4916 29 1154 4 +-493f 6 1155 4 +-4945 1 1155 4 ++4836 13 1145 3 ++4849 1c 1146 3 ++4865 1c 1147 3 ++4881 1c 1148 3 ++489d 1c 1149 3 ++48b9 1c 1150 3 ++48d5 1c 1151 3 ++48f1 25 1152 3 ++4916 29 1154 3 ++493f 6 1155 3 ++4945 1 1155 3 + FUNC 4946 512 0 -[DumpSymbols loadDWARFSymbolInfo:offset:] +-4946 17 402 4 +-495d 9 405 4 +-4966 10 406 4 +-4976 2b 408 4 +-49a1 38 409 4 +-49d9 3a 410 4 +-4a13 2e 411 4 +-4a41 31 416 4 +-4a72 e 418 4 +-4a80 24 420 4 +-4aa4 5 422 4 +-4aa9 b 424 4 +-4ab4 b 425 4 +-4abf e 426 4 +-4acd 2b 427 4 +-4af8 2b 428 4 +-4b23 2c 431 4 +-4b4f 52 439 4 +-4ba1 34 444 4 +-4bd5 1a 446 4 +-4bef 21 451 4 +-4c10 1e 452 4 +-4c2e 21 453 4 +-4c4f 40 422 4 +-4c8f 6 453 4 +-4c95 170 422 4 +-4e05 43 456 4 +-4e48 10 457 4 ++4946 17 402 3 ++495d 9 405 3 ++4966 10 406 3 ++4976 2b 408 3 ++49a1 38 409 3 ++49d9 3a 410 3 ++4a13 2e 411 3 ++4a41 31 416 3 ++4a72 e 418 3 ++4a80 24 420 3 ++4aa4 5 422 3 ++4aa9 b 424 3 ++4ab4 b 425 3 ++4abf e 426 3 ++4acd 2b 427 3 ++4af8 2b 428 3 ++4b23 2c 431 3 ++4b4f 52 439 3 ++4ba1 34 444 3 ++4bd5 1a 446 3 ++4bef 21 451 3 ++4c10 1e 452 3 ++4c2e 21 453 3 ++4c4f 40 422 3 ++4c8f 6 453 3 ++4c95 170 422 3 ++4e05 43 456 3 ++4e48 10 457 3 + FUNC 4e58 4fd 0 -[DumpSymbols generateSectionDictionary:] +-4e58 18 663 4 +-4e70 10 665 4 +-4e80 2e 666 4 +-4eae 9 668 4 +-4eb7 2b 669 4 +-4ee2 7 670 4 +-4ee9 2e 672 4 +-4f17 d 676 4 +-4f24 32 678 4 +-4f56 29 680 4 +-4f7f a 684 4 +-4f89 3c 685 4 +-4fc5 31 688 4 +-4ff6 5d 689 4 +-5053 26 692 4 +-5079 21 694 4 +-509a c 698 4 +-50a6 e 699 4 +-50b4 6 700 4 +-50ba 9 701 4 +-50c3 2e 702 4 +-50f1 c 704 4 +-50fd 3c 706 4 +-5139 66 709 4 +-519f 1c 712 4 +-51bb fb 714 4 +-52b6 6 717 4 +-52bc 5 718 4 +-52c1 19 704 4 +-52da 25 714 4 +-52ff 2e 722 4 +-532d 9 723 4 +-5336 17 698 4 +-534d 8 725 4 +-5355 1 725 4 ++4e58 18 663 3 ++4e70 10 665 3 ++4e80 2e 666 3 ++4eae 9 668 3 ++4eb7 2b 669 3 ++4ee2 7 670 3 ++4ee9 2e 672 3 ++4f17 d 676 3 ++4f24 32 678 3 ++4f56 29 680 3 ++4f7f a 684 3 ++4f89 3c 685 3 ++4fc5 31 688 3 ++4ff6 5d 689 3 ++5053 26 692 3 ++5079 21 694 3 ++509a c 698 3 ++50a6 e 699 3 ++50b4 6 700 3 ++50ba 9 701 3 ++50c3 2e 702 3 ++50f1 c 704 3 ++50fd 3c 706 3 ++5139 66 709 3 ++519f 1c 712 3 ++51bb fb 714 3 ++52b6 6 717 3 ++52bc 5 718 3 ++52c1 19 704 3 ++52da 25 714 3 ++52ff 2e 722 3 ++532d 9 723 3 ++5336 17 698 3 ++534d 8 725 3 ++5355 1 725 3 + FUNC 5356 24a 0 -[DumpSymbols getSectionMapForArchitecture:] +-5356 14 643 4 +-536a 43 645 4 +-53ad 1a 648 4 +-53c7 1c 645 4 +-53e3 18 648 4 +-53fb 40 650 4 +-543b 20 651 4 +-545b 17 652 4 +-5472 16 651 4 +-5488 cb 652 4 +-5553 11 654 4 +-5564 32 657 4 +-5596 a 658 4 ++5356 14 643 3 ++536a 43 645 3 ++53ad 1a 648 3 ++53c7 1c 645 3 ++53e3 18 648 3 ++53fb 40 650 3 ++543b 20 651 3 ++545b 17 652 3 ++5472 16 651 3 ++5488 cb 652 3 ++5553 11 654 3 ++5564 32 657 3 ++5596 a 658 3 + FUNC 55a0 3fe 0 -[DumpSymbols initWithContentsOfFile:] +-55a0 14 1056 4 +-55b4 3b 1057 4 +-55ef 44 1059 4 +-5633 17 1060 4 +-564a c 1061 4 +-5656 1f 1064 4 +-5675 2b 1067 4 +-56a0 a 1069 4 +-56aa 35 1083 4 +-56df 2 1087 4 +-56e1 1a 1088 4 +-56fb 3d 1087 4 +-5738 33 1092 4 +-576b 6 1094 4 +-5771 e 1095 4 +-577f 17 1096 4 +-5796 c 1097 4 +-57a2 1c 1101 4 +-57be 1f 1103 4 +-57dd 18 1104 4 +-57f5 23 1107 4 +-5818 25 1109 4 +-583d 1c 1107 4 +-5859 17 1110 4 +-5870 c 1111 4 +-587c 2a 1115 4 +-58a6 8 1116 4 +-58ae a 1118 4 +-58b8 9 1119 4 +-58c1 d 1122 4 +-58ce 29 1124 4 +-58f7 20 1126 4 +-5917 20 1128 4 +-5937 57 1132 4 +-598e 9 1136 4 +-5997 7 1137 4 ++55a0 14 1056 3 ++55b4 3b 1057 3 ++55ef 44 1059 3 ++5633 17 1060 3 ++564a c 1061 3 ++5656 1f 1064 3 ++5675 2b 1067 3 ++56a0 a 1069 3 ++56aa 35 1083 3 ++56df 2 1087 3 ++56e1 1a 1088 3 ++56fb 3d 1087 3 ++5738 33 1092 3 ++576b 6 1094 3 ++5771 e 1095 3 ++577f 17 1096 3 ++5796 c 1097 3 ++57a2 1c 1101 3 ++57be 1f 1103 3 ++57dd 18 1104 3 ++57f5 23 1107 3 ++5818 25 1109 3 ++583d 1c 1107 3 ++5859 17 1110 3 ++5870 c 1111 3 ++587c 2a 1115 3 ++58a6 8 1116 3 ++58ae a 1118 3 ++58b8 9 1119 3 ++58c1 d 1122 3 ++58ce 29 1124 3 ++58f7 20 1126 3 ++5917 20 1128 3 ++5937 57 1132 3 ++598e 9 1136 3 ++5997 7 1137 3 + FUNC 599e d74 0 -[DumpSymbols outputSymbolFile:] +-599e 18 877 4 +-59b6 2e 879 4 +-59e4 30 880 4 +-5a14 5d 882 4 +-5a71 30 883 4 +-5aa1 5d 885 4 +-5afe 2e 888 4 +-5b2c 38 891 4 +-5b64 46 892 4 +-5baa 26 893 4 +-5bd0 20 895 4 +-5bf0 20 904 4 +-5c10 30 898 4 +-5c40 f 899 4 +-5c4f 1e 904 4 +-5c6d 17 907 4 +-5c84 17 908 4 +-5c9b 44 911 4 +-5cdf 44 914 4 +-5d23 a 917 4 +-5d2d 36 921 4 +-5d63 30 923 4 ++599e 18 877 3 ++59b6 2e 879 3 ++59e4 30 880 3 ++5a14 5d 882 3 ++5a71 30 883 3 ++5aa1 5d 885 3 ++5afe 2e 888 3 ++5b2c 38 891 3 ++5b64 46 892 3 ++5baa 26 893 3 ++5bd0 20 895 3 ++5bf0 20 904 3 ++5c10 30 898 3 ++5c40 f 899 3 ++5c4f 1e 904 3 ++5c6d 17 907 3 ++5c84 17 908 3 ++5c9b 44 911 3 ++5cdf 44 914 3 ++5d23 a 917 3 ++5d2d 36 921 3 ++5d63 30 923 3 + 5d93 9 18 4 + 5d9c 9 19 4 + 5da5 c 20 4 +-5db1 56 923 4 +-5e07 74 925 4 +-5e7b f 927 4 +-5e8a 44 932 4 +-5ece 20 933 4 +-5eee c 934 4 +-5efa 4e 935 4 +-5f48 41 936 4 +-5f89 f 937 4 +-5f98 14 934 4 +-5fac 7 941 4 +-5fb3 14 942 4 +-5fc7 14 943 4 +-5fdb 1d 946 4 +-5ff8 c 948 4 +-6004 24 949 4 +-6028 29 950 4 +-6051 9 953 4 +-605a 28 954 4 +-6082 2e 955 4 +-60b0 1e 957 4 +-60ce 7 959 4 +-60d5 26 962 4 +-60fb 2a 963 4 +-6125 2a 964 4 +-614f 6 966 4 +-6155 2a 967 4 +-617f e 971 4 +-618d 43 972 4 +-61d0 4c 974 4 +-621c 8 975 4 +-6224 2e 979 4 +-6252 2e 982 4 +-6280 2e 985 4 +-62ae 2e 988 4 +-62dc 2e 991 4 +-630a 2e 994 4 +-6338 2e 997 4 +-6366 2e 1000 4 +-6394 54 1004 4 +-63e8 c 1005 4 +-63f4 e 1007 4 +-6402 27 1008 4 +-6429 8 1009 4 +-6431 34 1010 4 +-6465 24 1012 4 +-6489 2 1013 4 +-648b 2a 1017 4 +-64b5 a 1019 4 +-64bf 14 1020 4 +-64d3 1d 1021 4 +-64f0 a 1025 4 +-64fa 32 1026 4 +-652c 33 1028 4 +-655f c 1029 4 +-656b 55 1034 4 +-65c0 f 1036 4 +-65cf 16 1040 4 +-65e5 61 1041 4 +-6646 f 1043 4 +-6655 47 1046 4 +-669c c 1048 4 +-66a8 11 948 4 +-66b9 4e 1052 4 +-6707 b 1053 4 +-FUNC 6712 11 0 operator new ++5db1 56 923 3 ++5e07 74 925 3 ++5e7b f 927 3 ++5e8a 44 932 3 ++5ece 20 933 3 ++5eee c 934 3 ++5efa 4e 935 3 ++5f48 41 936 3 ++5f89 f 937 3 ++5f98 14 934 3 ++5fac 7 941 3 ++5fb3 14 942 3 ++5fc7 14 943 3 ++5fdb 1d 946 3 ++5ff8 c 948 3 ++6004 24 949 3 ++6028 29 950 3 ++6051 9 953 3 ++605a 28 954 3 ++6082 2e 955 3 ++60b0 1e 957 3 ++60ce 7 959 3 ++60d5 26 962 3 ++60fb 2a 963 3 ++6125 2a 964 3 ++614f 6 966 3 ++6155 2a 967 3 ++617f e 971 3 ++618d 43 972 3 ++61d0 4c 974 3 ++621c 8 975 3 ++6224 2e 979 3 ++6252 2e 982 3 ++6280 2e 985 3 ++62ae 2e 988 3 ++62dc 2e 991 3 ++630a 2e 994 3 ++6338 2e 997 3 ++6366 2e 1000 3 ++6394 54 1004 3 ++63e8 c 1005 3 ++63f4 e 1007 3 ++6402 27 1008 3 ++6429 8 1009 3 ++6431 34 1010 3 ++6465 24 1012 3 ++6489 2 1013 3 ++648b 2a 1017 3 ++64b5 a 1019 3 ++64bf 14 1020 3 ++64d3 1d 1021 3 ++64f0 a 1025 3 ++64fa 32 1026 3 ++652c 33 1028 3 ++655f c 1029 3 ++656b 55 1034 3 ++65c0 f 1036 3 ++65cf 16 1040 3 ++65e5 61 1041 3 ++6646 f 1043 3 ++6655 47 1046 3 ++669c c 1048 3 ++66a8 11 948 3 ++66b9 4e 1052 3 ++6707 b 1053 3 ++FUNC 6712 11 0 operator new(unsigned long, void*) + 6712 c 94 5 + 671e 5 94 5 + 6723 1 94 5 +-FUNC 6724 e 0 operator delete ++FUNC 6724 e 0 operator delete(void*, void*) + 6724 c 98 5 + 6730 2 98 5 +-6732 c 74 6 + 673e 7 76 6 + 6745 2 77 6 + 6747 1a 78 6 + 6761 d 77 6 + 676e 3 79 6 + 6771 2 80 6 + 6773 1 80 6 +-6774 c 94 6 + 6780 d 95 6 + 678d 1 95 6 +-678e 13 127 7 +-67a1 2a 127 7 +-67cb 1 127 7 +-67cc 13 127 7 +-67df 2a 127 7 +-6809 1 127 7 +-680a 13 127 7 +-681d 2a 127 7 +-6847 1 127 7 ++678e 13 127 74 ++67a1 2a 127 74 ++67cb 1 127 74 ++67cc 13 127 74 ++67df 2a 127 74 ++6809 1 127 74 ++680a 13 127 74 ++681d 2a 127 74 ++6847 1 127 74 ++FUNC 6848 e 0 dwarf2reader::LineInfoHandler::DefineDir(std::string const&, unsigned int) + 6848 c 131 7 +-6854 2 131 7 ++6854 2 131 74 ++FUNC 6856 26 0 dwarf2reader::LineInfoHandler::DefineFile(std::string const&, int, unsigned int, unsigned long long, unsigned long long) + 6856 24 142 7 +-687a 2 142 7 ++687a 2 142 74 ++FUNC 687c 1a 0 dwarf2reader::LineInfoHandler::AddLine(unsigned long long, unsigned int, unsigned int, unsigned int) + 687c 18 150 7 +-6894 2 150 7 +-6896 12 299 7 +-68a8 12 299 7 +-68ba 13 301 7 +-68cd 2a 301 7 +-68f7 1 301 7 +-68f8 13 301 7 +-690b 2a 301 7 +-6935 1 301 7 +-6936 13 301 7 +-6949 2a 301 7 +-6973 1 301 7 ++6894 2 150 74 ++6896 12 299 74 ++68a8 12 299 74 ++68ba 13 301 74 ++68cd 2a 301 74 ++68f7 1 301 74 ++68f8 13 301 74 ++690b 2a 301 74 ++6935 1 301 74 ++6936 13 301 74 ++6949 2a 301 74 ++6973 1 301 74 ++FUNC 6974 44 0 dwarf2reader::Dwarf2Handler::StartCompilationUnit(unsigned long long, unsigned char, unsigned char, unsigned long long, unsigned char) + 6974 39 308 7 +-69ad b 308 7 ++69ad b 308 74 ++FUNC 69b8 1f 0 dwarf2reader::Dwarf2Handler::StartDIE(unsigned long long, dwarf2reader::DwarfTag, std::list, std::allocator > > const&) + 69b8 18 314 7 +-69d0 7 314 7 +-69d7 1 314 7 ++69d0 7 314 74 ++69d7 1 314 74 ++FUNC 69d8 26 0 dwarf2reader::Dwarf2Handler::ProcessAttributeUnsigned(unsigned long long, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm, unsigned long long) + 69d8 24 323 7 +-69fc 2 323 7 ++69fc 2 323 74 ++FUNC 69fe 26 0 dwarf2reader::Dwarf2Handler::ProcessAttributeSigned(unsigned long long, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm, long long) + 69fe 24 332 7 +-6a22 2 332 7 ++6a22 2 332 74 ++FUNC 6a24 26 0 dwarf2reader::Dwarf2Handler::ProcessAttributeBuffer(unsigned long long, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm, char const*, unsigned long long) + 6a24 24 345 7 +-6a48 2 345 7 ++6a48 2 345 74 ++FUNC 6a4a 1a 0 dwarf2reader::Dwarf2Handler::ProcessAttributeString(unsigned long long, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm, std::string const&) + 6a4a 18 354 7 +-6a62 2 354 7 ++6a62 2 354 74 ++FUNC 6a64 1a 0 dwarf2reader::Dwarf2Handler::EndDIE(unsigned long long) + 6a64 18 360 7 +-6a7c 2 360 7 ++6a7c 2 360 74 + 6a7e c 44 8 + 6a8a 2 44 8 +-6a8c 13 55 9 +-6a9f 35 55 9 +-6ad4 13 91 9 +-6ae7 73 96 9 +-6b5a 13 98 9 +-6b6d 35 98 9 +-6ba2 c 74 9 +-6bae 1a 75 9 +-6bc8 2 76 9 ++6a8c 13 55 32 ++6a9f 35 55 32 ++6ad4 13 91 32 ++6ae7 73 96 32 ++6b5a 13 98 32 ++6b6d 35 98 32 ++6bae 1a 75 3 ++6bc8 2 76 3 ++FUNC 6bca 20 0 std::_Rb_tree_const_iterator >::operator!=(std::_Rb_tree_const_iterator > const&) const + 6bca c 287 10 +-6bd6 14 288 10 ++6bd6 14 288 40 ++FUNC 6bea 16 0 std::_Rb_tree_const_iterator >::operator->() const + 6bea c 249 10 +-6bf6 a 250 10 +-6c00 c 613 11 +-6c0c 7 614 11 +-6c13 1 614 11 +-6c14 c 241 11 +-6c20 c 242 11 ++6bf6 a 250 40 ++6c0c 7 614 72 ++6c13 1 614 72 ++6c14 c 241 40 ++6c20 c 242 40 ++FUNC 6c2c 16 0 std::_Rb_tree_const_iterator >::operator*() const + 6c2c c 245 11 +-6c38 a 246 11 +-6c42 c 241 11 +-6c4e c 242 11 ++6c38 a 246 40 ++6c42 c 241 40 ++6c4e c 242 40 ++FUNC 6c5a 20 0 std::_Rb_tree_const_iterator > >::operator!=(std::_Rb_tree_const_iterator > > const&) const + 6c5a c 287 11 +-6c66 14 288 11 ++6c66 14 288 40 ++FUNC 6c7a 16 0 std::_Rb_tree_const_iterator > >::operator->() const + 6c7a c 249 11 +-6c86 a 250 11 +-6c90 c 185 12 +-6c9c 18 186 12 +-6cb4 c 203 12 +-6cc0 14 204 12 +-6cd4 c 69 13 +-6ce0 d 69 13 +-6ced 1 69 13 +-6cee c 89 13 +-6cfa 20 90 13 +-6d1a c 69 13 +-6d26 d 69 13 +-6d33 1 69 13 +-6d34 c 69 13 +-6d40 d 69 13 +-6d4d 1 69 13 ++6c86 a 250 40 ++6c90 c 185 34 ++6c9c 18 186 34 ++6cc0 14 204 34 ++6cd4 c 69 70 ++6ce0 d 69 70 ++6ced 1 69 70 ++6cee c 89 70 ++6cfa 20 90 70 ++6d1a c 69 70 ++6d26 d 69 70 ++6d33 1 69 70 ++6d34 c 69 70 ++6d40 d 69 70 ++6d4d 1 69 70 ++FUNC 6d4e 25 0 std::_Rb_tree_const_iterator >::operator++() + 6d4e c 253 13 +-6d5a 14 255 13 +-6d6e 5 256 13 +-6d73 1 256 13 ++6d5a 14 255 40 ++6d6e 5 256 40 ++6d73 1 256 40 ++FUNC 6d74 25 0 std::_Rb_tree_const_iterator > >::operator++() + 6d74 c 253 13 +-6d80 14 255 13 +-6d94 5 256 13 +-6d99 1 256 13 ++6d80 14 255 40 ++6d94 5 256 40 ++6d99 1 256 40 ++FUNC 6d9a 14 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_begin() + 6d9a c 461 13 +-6da6 8 462 13 ++6da6 8 462 40 ++FUNC 6dae 14 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_begin() + 6dae c 461 13 +-6dba 8 462 13 +-6dc2 c 65 14 +-6dce 2 65 14 +-6dd0 c 72 14 +-6ddc 2 72 14 +-6dde c 97 15 +-6dea d 97 15 +-6df7 1 97 15 +-6df8 c 105 15 +-6e04 d 105 15 +-6e11 1 105 15 +-6e12 c 105 15 +-6e1e d 105 15 +-6e2b 1 105 15 +-6e2c c 67 15 +-6e38 2 67 15 +-6e3a c 99 15 +-6e46 14 100 15 +-6e5a c 99 15 +-6e66 14 100 15 ++6dba 8 462 40 ++6dc2 c 65 68 ++6dce 2 65 68 ++6dd0 c 72 68 ++6ddc 2 72 68 ++6dde c 97 69 ++6dea d 97 69 ++6df7 1 97 69 ++6df8 c 105 69 ++6e04 d 105 69 ++6e11 1 105 69 ++6e12 c 105 69 ++6e1e d 105 69 ++6e2b 1 105 69 ++6e2c c 67 68 ++6e38 2 67 68 ++6e3a c 99 69 ++6e46 14 100 69 ++6e5a c 99 69 ++6e66 14 100 69 ++FUNC 6e7a 2b 0 std::_Vector_base >::get_allocator() const + 6e7a 10 93 16 +-6e8a 1b 94 16 +-6ea5 1 94 16 +-6ea6 c 65 16 +-6eb2 2 65 16 +-6eb4 c 72 16 +-6ec0 2 72 16 +-6ec2 c 97 16 +-6ece d 97 16 +-6edb 1 97 16 +-6edc c 105 16 +-6ee8 d 105 16 +-6ef5 1 105 16 +-6ef6 c 105 16 +-6f02 d 105 16 +-6f0f 1 105 16 +-6f10 c 67 16 +-6f1c 2 67 16 +-6f1e c 99 16 +-6f2a 14 100 16 +-6f3e c 99 16 +-6f4a 14 100 16 ++6e8a 1b 94 71 ++6ea5 1 94 71 ++6ea6 c 65 68 ++6eb2 2 65 68 ++6eb4 c 72 68 ++6ec0 2 72 68 ++6ec2 c 97 69 ++6ece d 97 69 ++6edb 1 97 69 ++6edc c 105 69 ++6ee8 d 105 69 ++6ef5 1 105 69 ++6ef6 c 105 69 ++6f02 d 105 69 ++6f0f 1 105 69 ++6f10 c 67 68 ++6f1c 2 67 68 ++6f1e c 99 69 ++6f2a 14 100 69 ++6f3e c 99 69 ++6f4a 14 100 69 ++FUNC 6f5e 2b 0 std::_Vector_base >::get_allocator() const + 6f5e 10 93 16 +-6f6e 1b 94 16 +-6f89 1 94 16 +-6f8a c 603 16 +-6f96 c 603 16 ++6f6e 1b 94 71 ++6f89 1 94 71 ++6f8a c 603 72 ++6f96 c 603 72 ++FUNC 6fa2 23 0 std::vector >::begin() + 6fa2 c 333 16 +-6fae 17 334 16 +-6fc5 1 334 16 ++6fae 17 334 71 ++6fc5 1 334 71 ++FUNC 6fc6 26 0 std::vector >::end() + 6fc6 c 351 16 +-6fd2 1a 352 16 +-6fec c 665 16 +-6ff8 5 666 16 +-6ffd 1 666 16 +-6ffe c 608 16 +-700a 14 609 16 +-701e c 665 16 +-702a 5 666 16 +-702f 1 666 16 ++6fd2 1a 352 71 ++6ff8 5 666 72 ++6ffd 1 666 72 ++6ffe c 608 72 ++700a 14 609 72 ++702a 5 666 72 ++702f 1 666 72 ++FUNC 7030 35 0 bool __gnu_cxx::operator!= > >(__gnu_cxx::__normal_iterator > > const&, __gnu_cxx::__normal_iterator > > const&) + 7030 d 693 16 +-703d 28 694 16 +-7065 1 694 16 +-7066 c 603 16 +-7072 c 603 16 +-707e c 628 16 +-708a 27 629 16 +-70b1 1 629 16 +-70b2 c 84 16 +-70be 1f 85 16 +-70dd 1 85 16 ++703d 28 694 72 ++7065 1 694 72 ++7066 c 603 72 ++7072 c 603 72 ++708a 27 629 72 ++70b1 1 629 72 ++70b2 c 84 70 ++70be 1f 85 70 ++70dd 1 85 70 ++FUNC 70de 32 0 std::pair, __gnu_cxx::hash, std::equal_to, std::allocator > >*> std::make_pair, __gnu_cxx::hash, std::equal_to, std::allocator > >*>(std::string, __gnu_cxx::hash_map, __gnu_cxx::hash, std::equal_to, std::allocator > >*) + 70de 10 144 16 +-70ee 22 145 16 +-7110 c 189 16 +-711c a 190 16 +-7126 c 193 16 +-7132 d 194 16 +-713f 1 194 16 +-7140 c 84 16 +-714c 17 85 16 +-7163 1 85 16 ++70ee 22 145 70 ++711c a 190 34 ++7132 d 194 34 ++713f 1 194 34 ++7140 c 84 70 ++714c 17 85 70 ++7163 1 85 70 ++FUNC 7164 2d 0 std::pair std::make_pair(char const*, unsigned long) + 7164 c 144 16 +-7170 21 145 16 +-7191 1 145 16 +-7192 c 84 16 +-719e 1d 85 16 +-71bb 1 85 16 ++7170 21 145 70 ++7191 1 145 70 ++7192 c 84 70 ++719e 1d 85 70 ++71bb 1 85 70 ++FUNC 71bc 30 0 std::pair > std::make_pair >(char*, std::pair) + 71bc 10 144 16 +-71cc 20 145 16 +-71ec c 89 16 +-71f8 20 90 16 +-7218 d 89 16 +-7225 70 90 16 +-7295 1 90 16 ++71cc 20 145 70 ++71ec c 89 70 ++71f8 20 90 70 ++7218 d 89 70 ++7225 70 90 70 ++7295 1 90 70 ++FUNC 7296 12 0 std::iterator_traits::iterator_category std::__iterator_category(unsigned long const* const&) + 7296 c 164 17 + 72a2 6 165 17 ++FUNC 72a8 1d 0 std::iterator_traits::difference_type std::__distance(unsigned long const*, unsigned long const*, std::random_access_iterator_tag) + 72a8 c 92 18 + 72b4 11 97 18 + 72c5 1 97 18 ++FUNC 72c6 33 0 std::iterator_traits::difference_type std::distance(unsigned long const*, unsigned long const*) + 72c6 c 114 18 + 72d2 27 118 18 + 72f9 1 118 18 ++FUNC 72fa 20 0 void std::__advance(unsigned long const*&, int, std::random_access_iterator_tag) + 72fa c 150 18 + 7306 14 155 18 ++FUNC 731a 33 0 void std::advance(unsigned long const*&, int) + 731a c 172 18 + 7326 27 175 18 + 734d 1 175 18 ++FUNC 734e 7a 0 unsigned long const* std::lower_bound(unsigned long const*, unsigned long const*, unsigned long const&) + 734e c 2625 19 + 735a 15 2642 19 + 736f 2 2646 19 + 7371 8 2648 19 + 7379 6 2649 19 + 737f 12 2650 19 + 7391 e 2651 19 + 739f 6 2653 19 + 73a5 4 2654 19 + 73a9 e 2655 19 + 73b7 6 2658 19 + 73bd 6 2646 19 + 73c3 5 2660 19 +-73c8 13 225 19 +-73db b 227 19 +-73e6 e 228 19 +-73f4 1c 229 19 +-7410 20 230 19 +-7430 6 231 19 +-7436 c 72 19 +-7442 2 72 19 +-7444 c 105 19 +-7450 d 105 19 +-745d 1 105 19 +-745e c 105 19 +-746a d 105 19 +-7477 1 105 19 +-7478 c 80 19 +-7484 d 80 19 +-7491 1 80 19 +-7492 c 67 19 +-749e 2 67 19 +-74a0 c 99 19 +-74ac 14 100 19 ++73db b 227 34 ++73e6 e 228 34 ++73f4 1c 229 34 ++7410 20 230 34 ++7430 6 231 34 ++7436 c 72 68 ++7442 2 72 68 ++7444 c 105 69 ++7450 d 105 69 ++745d 1 105 69 ++745e c 105 69 ++746a d 105 69 ++7477 1 105 69 ++7478 c 80 71 ++7484 d 80 71 ++7491 1 80 71 ++7492 c 67 68 ++749e 2 67 68 ++74a0 c 99 69 ++74ac 14 100 69 ++FUNC 74c0 2b 0 std::_Vector_base >::get_allocator() const + 74c0 10 93 19 +-74d0 1b 94 19 +-74eb 1 94 19 +-74ec c 238 19 +-74f8 a 239 19 ++74d0 1b 94 71 ++74eb 1 94 71 ++74ec c 238 40 ++74f8 a 239 40 ++FUNC 7502 26 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::begin() const + 7502 c 585 19 +-750e 1a 588 19 ++750e 1a 588 40 ++FUNC 7528 19 0 std::map, std::allocator > >::begin() const + 7528 c 243 20 +-7534 d 244 20 +-7541 1 244 20 ++7534 d 244 45 ++7541 1 244 45 ++FUNC 7542 26 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::end() const + 7542 c 596 20 +-754e 1a 597 20 ++754e 1a 597 40 ++FUNC 7568 19 0 std::map, std::allocator > >::end() const + 7568 c 260 20 +-7574 d 261 20 +-7581 1 261 20 +-7582 c 65 20 +-758e 2 65 20 +-7590 c 72 20 +-759c 2 72 20 +-759e c 97 20 +-75aa d 97 20 +-75b7 1 97 20 +-75b8 c 105 20 +-75c4 d 105 20 +-75d1 1 105 20 +-75d2 c 72 20 +-75de 2 72 20 +-75e0 c 105 20 +-75ec d 105 20 +-75f9 1 105 20 +-75fa c 397 20 +-7606 d 397 20 +-7613 1 397 20 +-7614 c 105 20 +-7620 d 105 20 +-762d 1 105 20 ++7574 d 261 45 ++7581 1 261 45 ++7582 c 65 68 ++758e 2 65 68 ++7590 c 72 68 ++759c 2 72 68 ++759e c 97 69 ++75aa d 97 69 ++75b7 1 97 69 ++75b8 c 105 69 ++75c4 d 105 69 ++75d1 1 105 69 ++75d2 c 72 68 ++75de 2 72 68 ++75e0 c 105 69 ++75ec d 105 69 ++75f9 1 105 69 ++75fa c 397 40 ++7606 d 397 40 ++7613 1 397 40 ++7614 c 105 69 ++7620 d 105 69 ++762d 1 105 69 ++FUNC 762e 14 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_S_right(std::_Rb_tree_node_base*) + 762e c 496 20 +-763a 8 497 20 ++763a 8 497 40 ++FUNC 7642 14 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_S_left(std::_Rb_tree_node_base*) + 7642 c 488 20 +-764e 8 489 20 +-7656 c 65 20 +-7662 2 65 20 +-7664 c 72 20 +-7670 2 72 20 +-7672 c 97 20 +-767e d 97 20 +-768b 1 97 20 +-768c c 105 20 +-7698 d 105 20 +-76a5 1 105 20 +-76a6 c 72 20 +-76b2 2 72 20 +-76b4 c 105 20 +-76c0 d 105 20 +-76cd 1 105 20 +-76ce c 397 20 +-76da d 397 20 +-76e7 1 397 20 +-76e8 c 105 20 +-76f4 d 105 20 +-7701 1 105 20 ++764e 8 489 40 ++7656 c 65 68 ++7662 2 65 68 ++7664 c 72 68 ++7670 2 72 68 ++7672 c 97 69 ++767e d 97 69 ++768b 1 97 69 ++768c c 105 69 ++7698 d 105 69 ++76a5 1 105 69 ++76a6 c 72 68 ++76b2 2 72 68 ++76b4 c 105 69 ++76c0 d 105 69 ++76cd 1 105 69 ++76ce c 397 40 ++76da d 397 40 ++76e7 1 397 40 ++76e8 c 105 69 ++76f4 d 105 69 ++7701 1 105 69 ++FUNC 7702 14 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_S_right(std::_Rb_tree_node_base*) + 7702 c 496 20 +-770e 8 497 20 ++770e 8 497 40 ++FUNC 7716 14 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_S_left(std::_Rb_tree_node_base*) + 7716 c 488 20 +-7722 8 489 20 +-772a c 84 20 +-7736 2f 85 20 +-7765 2 86 20 +-7767 1 86 20 +-7768 c 80 20 +-7774 d 80 20 +-7781 1 80 20 +-7782 c 96 20 +-778e 12 97 20 +-77a0 2 98 20 +-77a2 c 84 20 +-77ae 2f 85 20 +-77dd 2 86 20 +-77df 1 86 20 +-77e0 c 80 20 +-77ec d 80 20 +-77f9 1 80 20 +-77fa c 96 20 +-7806 12 97 20 +-7818 2 98 20 +-781a c 107 20 +-7826 d 107 20 +-7833 1 107 20 ++7722 8 489 40 ++772a c 84 71 ++7736 2f 85 71 ++7765 2 86 71 ++7767 1 86 71 ++7768 c 80 71 ++7774 d 80 71 ++7781 1 80 71 ++7782 c 96 71 ++778e 12 97 71 ++77a0 2 98 71 ++77a2 c 84 71 ++77ae 2f 85 71 ++77dd 2 86 71 ++77df 1 86 71 ++77e0 c 80 71 ++77ec d 80 71 ++77f9 1 80 71 ++77fa c 96 71 ++7806 12 97 71 ++7818 2 98 71 ++7826 d 107 68 ++7833 1 107 68 ++FUNC 7834 2e 0 void std::_Destroy >(std::string*, std::string*, std::allocator) + 7834 c 171 21 +-7840 2 173 21 +-7842 12 174 21 +-7854 c 173 21 +-7860 2 174 21 +-7862 c 167 21 +-786e a 168 21 ++7840 2 173 73 ++7842 12 174 73 ++7854 c 173 73 ++7860 2 174 73 ++7862 c 167 40 ++786e a 168 40 ++FUNC 7878 26 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::begin() + 7878 c 581 21 +-7884 1a 582 21 ++7884 1a 582 40 ++FUNC 789e 19 0 std::map, std::allocator > >::begin() + 789e c 234 21 +-78aa d 235 21 +-78b7 1 235 21 ++78aa d 235 45 ++78b7 1 235 45 ++FUNC 78b8 26 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::end() + 78b8 c 592 21 +-78c4 1a 593 21 ++78c4 1a 593 40 ++FUNC 78de 19 0 std::map, std::allocator > >::end() + 78de c 251 21 +-78ea d 252 21 +-78f7 1 252 21 +-78f8 c 167 21 +-7904 a 168 21 ++78ea d 252 45 ++78f7 1 252 45 ++78f8 c 167 40 ++7904 a 168 40 ++FUNC 790e 26 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::begin() + 790e c 581 21 +-791a 1a 582 21 ++791a 1a 582 40 ++FUNC 7934 19 0 std::map, std::less, std::allocator > > >::begin() + 7934 c 234 21 +-7940 d 235 21 +-794d 1 235 21 ++7940 d 235 45 ++794d 1 235 45 ++FUNC 794e 26 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::end() + 794e c 592 21 +-795a 1a 593 21 ++795a 1a 593 40 ++FUNC 7974 19 0 std::map, std::less, std::allocator > > >::end() + 7974 c 251 21 +-7980 d 252 21 +-798d 1 252 21 ++7980 d 252 45 ++798d 1 252 45 ++FUNC 798e 11 0 std::_Select1st, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >::operator()(std::pair, __gnu_cxx::hash, std::equal_to, std::allocator > >*>&) const + 798e c 546 22 +-799a 5 547 22 +-799f 1 547 22 +-79a0 c 128 22 +-79ac 13 129 22 +-79bf 1 129 22 +-79c0 c 395 22 +-79cc 22 396 22 +-79ee c 198 23 +-79fa d 199 23 +-7a07 1 199 23 +-7a08 c 65 23 +-7a14 2 65 23 +-7a16 c 72 23 +-7a22 2 72 23 +-7a24 c 97 23 +-7a30 d 97 23 +-7a3d 1 97 23 +-7a3e c 105 23 +-7a4a d 105 23 +-7a57 1 105 23 +-7a58 c 65 23 +-7a64 2 65 23 +-7a66 c 72 23 +-7a72 2 72 23 +-7a74 c 105 23 +-7a80 d 105 23 +-7a8d 1 105 23 +-7a8e c 97 23 +-7a9a d 97 23 +-7aa7 1 97 23 +-7aa8 c 72 23 +-7ab4 2 72 23 +-7ab6 c 105 23 +-7ac2 d 105 23 +-7acf 1 105 23 +-7ad0 c 93 23 +-7adc d 94 23 +-7ae9 1 94 23 ++799a 5 547 41 ++799f 1 547 41 ++79a0 c 128 34 ++79ac 13 129 34 ++79bf 1 129 34 ++79cc 22 396 34 ++79fa d 199 42 ++7a07 1 199 42 ++7a08 c 65 68 ++7a14 2 65 68 ++7a16 c 72 68 ++7a22 2 72 68 ++7a24 c 97 69 ++7a30 d 97 69 ++7a3d 1 97 69 ++7a3e c 105 69 ++7a4a d 105 69 ++7a57 1 105 69 ++7a58 c 65 68 ++7a64 2 65 68 ++7a66 c 72 68 ++7a72 2 72 68 ++7a74 c 105 69 ++7a80 d 105 69 ++7a8d 1 105 69 ++7a8e c 97 69 ++7a9a d 97 69 ++7aa7 1 97 69 ++7aa8 c 72 68 ++7ab4 2 72 68 ++7ab6 c 105 69 ++7ac2 d 105 69 ++7acf 1 105 69 ++7adc d 94 68 ++7ae9 1 94 68 ++FUNC 7aea 2f 0 std::_Vector_base >::_M_deallocate(dwarf2reader::CompilationUnit::Abbrev*, unsigned long) + 7aea c 120 23 +-7af6 6 122 23 +-7afc 1d 123 23 +-7b19 1 123 23 +-7b1a c 108 23 +-7b26 43 109 23 +-7b69 1 109 23 +-7b6a c 65 23 +-7b76 2 65 23 +-7b78 c 103 23 +-7b84 d 103 23 +-7b91 1 103 23 +-7b92 c 65 23 +-7b9e 2 65 23 +-7ba0 c 103 23 +-7bac d 103 23 +-7bb9 1 103 23 +-7bba c 93 23 +-7bc6 d 94 23 +-7bd3 1 94 23 ++7af6 6 122 71 ++7afc 1d 123 71 ++7b19 1 123 71 ++7b1a c 108 71 ++7b26 43 109 71 ++7b69 1 109 71 ++7b6a c 65 68 ++7b76 2 65 68 ++7b78 c 103 69 ++7b84 d 103 69 ++7b91 1 103 69 ++7b92 c 65 68 ++7b9e 2 65 68 ++7ba0 c 103 69 ++7bac d 103 69 ++7bb9 1 103 69 ++7bc6 d 94 68 ++7bd3 1 94 68 ++FUNC 7bd4 2f 0 std::_Vector_base >::_M_deallocate(dwarf2reader::SourceFileInfo*, unsigned long) + 7bd4 c 120 23 +-7be0 6 122 23 +-7be6 1d 123 23 +-7c03 1 123 23 +-7c04 c 108 23 +-7c10 43 109 23 +-7c53 1 109 23 +-7c54 c 188 23 +-7c60 12 189 23 +-7c72 2 190 23 +-7c74 c 35 23 +-7c80 d 35 23 +-7c8d 1 35 23 +-7c8e c 107 23 +-7c9a d 107 23 +-7ca7 1 107 23 ++7be0 6 122 71 ++7be6 1d 123 71 ++7c03 1 123 71 ++7c04 c 108 71 ++7c10 43 109 71 ++7c53 1 109 71 ++7c54 c 188 71 ++7c60 12 189 71 ++7c72 2 190 71 ++7c74 c 35 32 ++7c80 d 35 32 ++7c8d 1 35 32 ++7c9a d 107 68 ++7ca7 1 107 68 ++FUNC 7ca8 2e 0 void std::_Destroy >(dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo*, std::allocator) + 7ca8 c 171 23 +-7cb4 2 173 23 +-7cb6 12 174 23 +-7cc8 c 173 23 +-7cd4 2 174 23 +-7cd6 d 272 23 +-7ce3 8c 273 23 +-7d6f 1 273 23 +-7d70 c 93 23 +-7d7c d 94 23 +-7d89 1 94 23 ++7cb4 2 173 73 ++7cb6 12 174 73 ++7cc8 c 173 73 ++7cd4 2 174 73 ++7cd6 d 272 71 ++7ce3 8c 273 71 ++7d6f 1 273 71 ++7d7c d 94 68 ++7d89 1 94 68 ++FUNC 7d8a 2f 0 std::_Vector_base >::_M_deallocate(std::string*, unsigned long) + 7d8a c 120 23 +-7d96 6 122 23 +-7d9c 1d 123 23 +-7db9 1 123 23 +-7dba c 108 23 +-7dc6 3d 109 23 +-7e03 1 109 23 +-7e04 c 188 23 +-7e10 12 189 23 +-7e22 2 190 23 +-7e24 d 272 23 +-7e31 8c 273 23 +-7ebd 1 273 23 +-7ebe c 595 23 +-7eca 2b 596 23 +-7ef5 1 596 23 +-7ef6 c 613 23 +-7f02 7 614 23 +-7f09 1 614 23 +-7f0a c 65 23 +-7f16 2 65 23 +-7f18 c 72 23 +-7f24 2 72 23 +-7f26 c 103 23 +-7f32 d 103 23 +-7f3f 1 103 23 +-7f40 c 105 23 +-7f4c d 105 23 +-7f59 1 105 23 +-7f5a c 65 23 +-7f66 2 65 23 +-7f68 c 72 23 +-7f74 2 72 23 +-7f76 c 103 23 +-7f82 d 103 23 +-7f8f 1 103 23 +-7f90 c 105 23 +-7f9c d 105 23 +-7fa9 1 105 23 +-7faa c 105 23 +-7fb6 d 105 23 +-7fc3 1 105 23 +-7fc4 c 574 23 +-7fd0 d 575 23 +-7fdd 1 575 23 +-7fde c 574 23 +-7fea d 575 23 +-7ff7 1 575 23 ++7d96 6 122 71 ++7d9c 1d 123 71 ++7db9 1 123 71 ++7dba c 108 71 ++7dc6 3d 109 71 ++7e03 1 109 71 ++7e04 c 188 71 ++7e10 12 189 71 ++7e22 2 190 71 ++7e24 d 272 71 ++7e31 8c 273 71 ++7ebd 1 273 71 ++7eca 2b 596 34 ++7ef5 1 596 34 ++7f02 7 614 72 ++7f09 1 614 72 ++7f0a c 65 68 ++7f16 2 65 68 ++7f18 c 72 68 ++7f24 2 72 68 ++7f26 c 103 69 ++7f32 d 103 69 ++7f3f 1 103 69 ++7f40 c 105 69 ++7f4c d 105 69 ++7f59 1 105 69 ++7f5a c 65 68 ++7f66 2 65 68 ++7f68 c 72 68 ++7f74 2 72 68 ++7f76 c 103 69 ++7f82 d 103 69 ++7f8f 1 103 69 ++7f90 c 105 69 ++7f9c d 105 69 ++7fa9 1 105 69 ++7faa c 105 69 ++7fb6 d 105 69 ++7fc3 1 105 69 ++7fd0 d 575 34 ++7fdd 1 575 34 ++7fea d 575 34 ++7ff7 1 575 34 ++FUNC 7ff8 11 0 std::_Select1st, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >::operator()(std::pair, __gnu_cxx::hash, std::equal_to, std::allocator > >*> const&) const + 7ff8 c 550 23 +-8004 5 551 23 +-8009 1 551 23 +-800a c 599 23 +-8016 2f 600 23 +-8045 1 600 23 +-8046 c 84 23 +-8052 1e 85 23 ++8004 5 551 41 ++8009 1 551 41 ++8016 2f 600 34 ++8045 1 600 34 ++8046 c 84 70 ++8052 1e 85 70 ++FUNC 8070 11 0 std::_Select1st > >::operator()(std::pair >&) const + 8070 c 546 23 +-807c 5 547 23 +-8081 1 547 23 ++807c 5 547 41 ++8081 1 547 41 ++FUNC 8082 11 0 std::_Select1st > >::operator()(std::pair > const&) const + 8082 c 550 23 +-808e 5 551 23 +-8093 1 551 23 +-8094 c 128 23 +-80a0 13 129 23 +-80b3 1 129 23 +-80b4 c 84 23 +-80c0 1e 85 23 +-80de c 65 23 +-80ea 2 65 23 +-80ec c 103 23 +-80f8 d 103 23 +-8105 1 103 23 +-8106 c 65 23 +-8112 2 65 23 +-8114 c 72 23 +-8120 2 72 23 +-8122 c 105 23 +-812e d 105 23 +-813b 1 105 23 +-813c c 103 23 +-8148 d 103 23 +-8155 1 103 23 +-8156 c 105 23 +-8162 d 105 23 +-816f 1 105 23 +-8170 c 80 23 +-817c d 80 23 +-8189 1 80 23 +-818a c 67 23 +-8196 2 67 23 +-8198 c 99 23 +-81a4 14 100 23 ++808e 5 551 41 ++8093 1 551 41 ++8094 c 128 34 ++80a0 13 129 34 ++80b3 1 129 34 ++80b4 c 84 70 ++80c0 1e 85 70 ++80de c 65 68 ++80ea 2 65 68 ++80ec c 103 69 ++80f8 d 103 69 ++8105 1 103 69 ++8106 c 65 68 ++8112 2 65 68 ++8114 c 72 68 ++8120 2 72 68 ++8122 c 105 69 ++812e d 105 69 ++813b 1 105 69 ++813c c 103 69 ++8148 d 103 69 ++8155 1 103 69 ++8156 c 105 69 ++8162 d 105 69 ++816f 1 105 69 ++8170 c 80 71 ++817c d 80 71 ++8189 1 80 71 ++818a c 67 68 ++8196 2 67 68 ++8198 c 99 69 ++81a4 14 100 69 ++FUNC 81b8 2b 0 std::_Vector_base<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::get_allocator() const + 81b8 10 93 23 +-81c8 1b 94 23 +-81e3 1 94 23 +-81e4 c 99 23 +-81f0 14 100 23 +-8204 c 107 23 +-8210 2 107 23 ++81c8 1b 94 71 ++81e3 1 94 71 ++81e4 c 99 69 ++81f0 14 100 69 ++8210 2 107 68 ++FUNC 8212 2e 0 void std::_Destroy<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >(__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*>) + 8212 c 171 23 +-821e 2 173 23 +-8220 12 174 23 +-8232 c 173 23 +-823e 2 174 23 +-8240 c 107 23 +-824c d 107 23 +-8259 1 107 23 +-825a c 67 23 +-8266 2 67 23 +-8268 c 99 23 +-8274 14 100 23 +-8288 c 403 23 +-8294 1c 404 23 +-82b0 a 406 23 +-82ba a 407 23 +-82c4 c 408 23 +-82d0 e 409 23 +-82de c 553 23 +-82ea 36 554 23 +-8320 2 555 23 +-8322 c 103 23 +-832e d 103 23 +-833b 1 103 23 ++821e 2 173 73 ++8220 12 174 73 ++8232 c 173 73 ++823e 2 174 73 ++824c d 107 68 ++8259 1 107 68 ++825a c 67 68 ++8266 2 67 68 ++8268 c 99 69 ++8274 14 100 69 ++8288 c 403 40 ++8294 1c 404 40 ++82b0 a 406 40 ++82ba a 407 40 ++82c4 c 408 40 ++82d0 e 409 40 ++82de c 553 40 ++82ea 36 554 40 ++8320 2 555 40 ++8322 c 103 69 ++832e d 103 69 ++833b 1 103 69 ++FUNC 833c 2b 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::get_allocator() const + 833c 10 350 23 +-834c 1b 351 23 +-8367 1 351 23 +-8368 c 69 23 +-8374 2 69 23 +-8376 c 107 23 +-8382 d 107 23 +-838f 1 107 23 +-8390 c 93 23 +-839c d 94 23 +-83a9 1 94 23 ++834c 1b 351 40 ++8367 1 351 40 ++8368 c 69 70 ++8374 2 69 70 ++8382 d 107 68 ++838f 1 107 68 ++839c d 94 68 ++83a9 1 94 68 ++FUNC 83aa 2a 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_put_node(std::_Rb_tree_node >*) + 83aa c 359 23 +-83b6 1e 360 23 ++83b6 1e 360 40 ++FUNC 83d4 59 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::destroy_node(std::_Rb_tree_node >*) + 83d4 d 387 23 +-83e1 35 389 23 +-8416 17 390 23 +-842d 1 390 23 ++83e1 35 389 40 ++8416 17 390 40 ++842d 1 390 40 ++FUNC 842e 56 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_erase(std::_Rb_tree_node >*) + 842e c 1051 23 +-843a 2 1054 23 +-843c 1a 1056 23 +-8456 e 1057 23 +-8464 12 1058 23 +-8476 6 1059 23 +-847c 6 1054 23 +-8482 2 1059 23 +-8484 d 569 23 +-8491 58 570 23 +-84e9 1 570 23 +-84ea c 147 23 +-84f6 31 148 23 +-8527 1 148 23 +-8528 c 92 23 +-8534 d 92 23 +-8541 1 92 23 +-8542 c 67 23 +-854e 2 67 23 +-8550 c 99 23 +-855c 14 100 23 +-8570 c 403 23 +-857c 1c 404 23 +-8598 a 406 23 +-85a2 a 407 23 +-85ac c 408 23 +-85b8 e 409 23 +-85c6 c 553 23 +-85d2 36 554 23 +-8608 2 555 23 +-860a c 103 23 +-8616 d 103 23 +-8623 1 103 23 ++843a 2 1054 40 ++843c 1a 1056 40 ++8456 e 1057 40 ++8464 12 1058 40 ++8476 6 1059 40 ++847c 6 1054 40 ++8482 2 1059 40 ++8484 d 569 40 ++8491 58 570 40 ++84e9 1 570 40 ++84ea c 147 45 ++84f6 31 148 45 ++8527 1 148 45 ++8528 c 92 45 ++8534 d 92 45 ++8541 1 92 45 ++8542 c 67 68 ++854e 2 67 68 ++8550 c 99 69 ++855c 14 100 69 ++8570 c 403 40 ++857c 1c 404 40 ++8598 a 406 40 ++85a2 a 407 40 ++85ac c 408 40 ++85b8 e 409 40 ++85c6 c 553 40 ++85d2 36 554 40 ++8608 2 555 40 ++860a c 103 69 ++8616 d 103 69 ++8623 1 103 69 ++FUNC 8624 2b 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::get_allocator() const + 8624 10 350 23 +-8634 1b 351 23 +-864f 1 351 23 +-8650 c 69 23 +-865c d 69 23 +-8669 1 69 23 +-866a c 69 23 +-8676 30 69 23 +-86a6 c 107 23 +-86b2 d 107 23 +-86bf 1 107 23 +-86c0 c 93 23 +-86cc d 94 23 +-86d9 1 94 23 ++8634 1b 351 40 ++864f 1 351 40 ++8650 c 69 70 ++865c d 69 70 ++8669 1 69 70 ++866a c 69 70 ++8676 30 69 70 ++86b2 d 107 68 ++86bf 1 107 68 ++86cc d 94 68 ++86d9 1 94 68 ++FUNC 86da 2a 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_put_node(std::_Rb_tree_node > >*) + 86da c 359 23 +-86e6 1e 360 23 ++86e6 1e 360 40 ++FUNC 8704 59 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::destroy_node(std::_Rb_tree_node > >*) + 8704 d 387 23 +-8711 35 389 23 +-8746 17 390 23 +-875d 1 390 23 ++8711 35 389 40 ++8746 17 390 40 ++875d 1 390 40 ++FUNC 875e 56 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_erase(std::_Rb_tree_node > >*) + 875e c 1051 23 +-876a 2 1054 23 +-876c 1a 1056 23 +-8786 e 1057 23 +-8794 12 1058 23 +-87a6 6 1059 23 +-87ac 6 1054 23 +-87b2 2 1059 23 +-87b4 d 569 23 +-87c1 58 570 23 +-8819 1 570 23 +-881a c 147 23 +-8826 31 148 23 +-8857 1 148 23 +-8858 c 92 23 +-8864 d 92 23 +-8871 1 92 23 +-8872 c 603 23 +-887e c 603 23 ++876a 2 1054 40 ++876c 1a 1056 40 ++8786 e 1057 40 ++8794 12 1058 40 ++87a6 6 1059 40 ++87ac 6 1054 40 ++87b2 2 1059 40 ++87b4 d 569 40 ++87c1 58 570 40 ++8819 1 570 40 ++881a c 147 45 ++8826 31 148 45 ++8857 1 148 45 ++8858 c 92 45 ++8864 d 92 45 ++8871 1 92 45 ++8872 c 603 72 ++887e c 603 72 ++FUNC 888a 23 0 std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::begin() + 888a c 333 23 +-8896 17 334 23 +-88ad 1 334 23 +-88ae c 653 23 +-88ba 2a 654 23 ++8896 17 334 71 ++88ad 1 334 71 ++88ba 2a 654 72 ++FUNC 88e4 42 0 std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::operator[](unsigned long) + 88e4 c 494 23 +-88f0 36 495 23 ++88f0 36 495 71 ++FUNC 8926 26 0 std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::end() + 8926 c 351 23 +-8932 1a 352 23 ++8932 1a 352 71 ++FUNC 894c 28 0 bool std::operator==, std::allocator >(std::basic_string, std::allocator > const&, std::basic_string, std::allocator > const&) + 894c c 2115 24 +-8958 1c 2116 24 ++8958 1c 2116 37 ++FUNC 8974 23 0 std::equal_to::operator()(std::string const&, std::string const&) const + 8974 c 199 24 +-8980 17 200 24 +-8997 1 200 24 +-8998 c 80 24 +-89a4 d 80 24 +-89b1 1 80 24 +-89b2 c 67 24 +-89be 2 67 24 +-89c0 c 99 24 +-89cc 14 100 24 ++8980 17 200 41 ++8997 1 200 41 ++8998 c 80 71 ++89a4 d 80 71 ++89b1 1 80 71 ++89b2 c 67 68 ++89be 2 67 68 ++89c0 c 99 69 ++89cc 14 100 69 ++FUNC 89e0 2b 0 std::_Vector_base<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::get_allocator() const + 89e0 10 93 24 +-89f0 1b 94 24 +-8a0b 1 94 24 +-8a0c c 99 24 +-8a18 14 100 24 +-8a2c c 84 24 +-8a38 2f 85 24 +-8a67 2 86 24 +-8a69 1 86 24 +-8a6a c 96 24 +-8a76 12 97 24 +-8a88 2 98 24 +-8a8a c 107 24 +-8a96 2 107 24 ++89f0 1b 94 71 ++8a0b 1 94 71 ++8a0c c 99 69 ++8a18 14 100 69 ++8a2c c 84 71 ++8a38 2f 85 71 ++8a67 2 86 71 ++8a69 1 86 71 ++8a6a c 96 71 ++8a76 12 97 71 ++8a88 2 98 71 ++8a96 2 107 68 ++FUNC 8a98 2e 0 void std::_Destroy<__gnu_cxx::_Hashtable_node > >**, std::allocator<__gnu_cxx::_Hashtable_node > >*> >(__gnu_cxx::_Hashtable_node > >**, __gnu_cxx::_Hashtable_node > >**, std::allocator<__gnu_cxx::_Hashtable_node > >*>) + 8a98 c 171 24 +-8aa4 2 173 24 +-8aa6 12 174 24 +-8ab8 c 173 24 +-8ac4 2 174 24 ++8aa4 2 173 73 ++8aa6 12 174 73 ++8ab8 c 173 73 ++8ac4 2 174 73 ++FUNC 8ac6 13 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::max_size() const + 8ac6 c 407 24 +-8ad2 7 408 24 +-8ad9 1 408 24 +-8ada c 603 24 +-8ae6 c 603 24 ++8ad2 7 408 71 ++8ad9 1 408 71 ++8ada c 603 72 ++8ae6 c 603 72 ++FUNC 8af2 26 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::end() + 8af2 c 351 24 +-8afe 1a 352 24 ++8afe 1a 352 71 ++FUNC 8b18 23 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::begin() + 8b18 c 333 24 +-8b24 17 334 24 +-8b3b 1 334 24 +-8b3c c 653 24 +-8b48 2a 654 24 +-8b72 c 613 24 +-8b7e 7 614 24 +-8b85 1 614 24 ++8b24 17 334 71 ++8b3b 1 334 71 ++8b48 2a 654 72 ++8b7e 7 614 72 ++8b85 1 614 72 ++FUNC 8b86 42 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::operator[](unsigned long) + 8b86 c 494 24 +-8b92 36 495 24 +-8bc8 c 107 24 +-8bd4 d 107 24 +-8be1 1 107 24 ++8b92 36 495 71 ++8bd4 d 107 68 ++8be1 1 107 68 ++FUNC 8be2 28 0 void std::swap<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**>(__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**&, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**&) + 8be2 c 92 25 +-8bee 8 97 25 +-8bf6 a 98 25 +-8c00 a 99 25 ++8bee 8 97 61 ++8bf6 a 98 61 ++8c00 a 99 61 ++FUNC 8c0a 50 0 std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::swap(std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >&) + 8c0a c 733 25 +-8c16 12 735 25 +-8c28 18 736 25 +-8c40 1a 737 25 +-8c5a c 595 25 +-8c66 2b 596 25 +-8c91 1 596 25 +-8c92 c 599 25 +-8c9e 2f 600 25 +-8ccd 1 600 25 ++8c16 12 735 71 ++8c28 18 736 71 ++8c40 1a 737 71 ++8c66 2b 596 34 ++8c91 1 596 34 ++8c9e 2f 600 34 ++8ccd 1 600 34 ++FUNC 8cce 28 0 void std::swap<__gnu_cxx::_Hashtable_node > >**>(__gnu_cxx::_Hashtable_node > >**&, __gnu_cxx::_Hashtable_node > >**&) + 8cce c 92 25 +-8cda 8 97 25 +-8ce2 a 98 25 +-8cec a 99 25 ++8cda 8 97 61 ++8ce2 a 98 61 ++8cec a 99 61 ++FUNC 8cf6 50 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::swap(std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >&) + 8cf6 c 733 25 +-8d02 12 735 25 +-8d14 18 736 25 +-8d2c 1a 737 25 +-8d46 c 84 25 +-8d52 2f 85 25 +-8d81 2 86 25 +-8d83 1 86 25 +-8d84 c 96 25 +-8d90 12 97 25 +-8da2 2 98 25 ++8d02 12 735 71 ++8d14 18 736 71 ++8d2c 1a 737 71 ++8d46 c 84 71 ++8d52 2f 85 71 ++8d81 2 86 71 ++8d83 1 86 71 ++8d84 c 96 71 ++8d90 12 97 71 ++8da2 2 98 71 ++FUNC 8da4 13 0 std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::max_size() const + 8da4 c 407 25 +-8db0 7 408 25 +-8db7 1 408 25 +-8db8 c 93 25 +-8dc4 d 94 25 +-8dd1 1 94 25 ++8db0 7 408 71 ++8db7 1 408 71 ++8dc4 d 94 68 ++8dd1 1 94 68 ++FUNC 8dd2 2f 0 std::_Vector_base<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::_M_deallocate(__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, unsigned long) + 8dd2 c 120 25 +-8dde 6 122 25 +-8de4 1d 123 25 +-8e01 1 123 25 +-8e02 c 108 25 +-8e0e 3d 109 25 +-8e4b 1 109 25 +-8e4c c 272 25 +-8e58 4b 273 25 +-8ea3 1 273 25 +-8ea4 c 188 25 +-8eb0 12 189 25 +-8ec2 2 190 25 +-8ec4 c 603 25 +-8ed0 c 603 25 ++8dde 6 122 71 ++8de4 1d 123 71 ++8e01 1 123 71 ++8e02 c 108 71 ++8e0e 3d 109 71 ++8e4b 1 109 71 ++8e4c c 272 71 ++8e58 4b 273 71 ++8ea3 1 273 71 ++8ea4 c 188 71 ++8eb0 12 189 71 ++8ec2 2 190 71 ++8ec4 c 603 72 ++8ed0 c 603 72 ++FUNC 8edc 2b 0 std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::begin() const + 8edc c 342 25 +-8ee8 1f 343 25 +-8f07 1 343 25 ++8ee8 1f 343 71 ++8f07 1 343 71 ++FUNC 8f08 2c 0 std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::end() const + 8f08 c 360 25 +-8f14 20 361 25 +-8f34 c 665 25 +-8f40 5 666 25 +-8f45 1 666 25 +-8f46 d 758 25 +-8f53 2b 759 25 ++8f14 20 361 71 ++8f40 5 666 72 ++8f45 1 666 72 ++8f53 2b 759 72 ++FUNC 8f7e 3c 0 std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::size() const + 8f7e c 402 25 +-8f8a 30 403 25 +-8fba c 587 25 +-8fc6 26 588 25 +-8fec c 509 25 +-8ff8 15 511 25 +-900d 79 513 25 +-9086 21 517 25 +-90a7 1 517 25 +-90a8 c 224 25 +-90b4 14 225 25 +-90c8 c 591 25 +-90d4 26 592 25 ++8f8a 30 403 71 ++8fc6 26 588 34 ++8ff8 15 511 34 ++900d 79 513 34 ++9086 21 517 34 ++90a7 1 517 34 ++90b4 14 225 42 ++90d4 26 592 34 ++FUNC 90fa 49 0 std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::capacity() const + 90fa c 449 25 +-9106 3d 451 25 +-9143 1 451 25 +-9144 c 103 25 +-9150 d 103 25 +-915d 1 103 25 +-915e 10 285 25 +-916e 1b 286 25 +-9189 1 286 25 +-918a c 93 25 +-9196 d 94 25 +-91a3 1 94 25 +-91a4 c 300 25 +-91b0 1e 301 25 +-91ce d 620 25 +-91db 56 622 25 +-9231 17 623 25 +-9248 c 1078 25 +-9254 9 1080 25 +-925d 1a 1082 25 +-9277 2 1083 25 +-9279 8 1085 25 +-9281 12 1086 25 +-9293 6 1087 25 +-9299 6 1083 25 +-929f 1b 1089 25 +-92ba 1d 1080 25 +-92d7 c 1091 25 +-92e3 1 1091 25 +-92e4 d 360 25 +-92f1 77 361 25 +-9368 c 93 25 +-9374 d 93 25 +-9381 1 93 25 +-9382 c 72 25 +-938e 2 72 25 +-9390 c 105 25 +-939c d 105 25 +-93a9 1 105 25 +-93aa c 301 26 +-93b6 d 301 26 +-93c3 1 301 26 +-93c4 c 93 26 +-93d0 d 94 26 +-93dd 1 94 26 ++9106 3d 451 71 ++9143 1 451 71 ++9144 c 103 69 ++9150 d 103 69 ++915d 1 103 69 ++916e 1b 286 34 ++9189 1 286 34 ++9196 d 94 68 ++91a3 1 94 68 ++91b0 1e 301 34 ++91db 56 622 34 ++9231 17 623 34 ++9254 9 1080 34 ++925d 1a 1082 34 ++9277 2 1083 34 ++9279 8 1085 34 ++9281 12 1086 34 ++9293 6 1087 34 ++9299 6 1083 34 ++929f 1b 1089 34 ++92ba 1d 1080 34 ++92d7 c 1091 34 ++92e3 1 1091 34 ++92e4 d 360 34 ++92f1 77 361 34 ++9368 c 93 42 ++9374 d 93 42 ++9381 1 93 42 ++9382 c 72 68 ++938e 2 72 68 ++9390 c 105 69 ++939c d 105 69 ++93a9 1 105 69 ++93aa c 301 66 ++93b6 d 301 66 ++93c3 1 301 66 ++93d0 d 94 68 ++93dd 1 94 68 ++FUNC 93de 2f 0 std::_Vector_base<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::_M_deallocate(__gnu_cxx::_Hashtable_node > >**, unsigned long) + 93de c 120 26 +-93ea 6 122 26 +-93f0 1d 123 26 +-940d 1 123 26 +-940e c 108 26 +-941a 3d 109 26 +-9457 1 109 26 +-9458 c 188 26 +-9464 12 189 26 +-9476 2 190 26 +-9478 c 272 26 +-9484 4b 273 26 +-94cf 1 273 26 +-94d0 c 603 26 +-94dc c 603 26 ++93ea 6 122 71 ++93f0 1d 123 71 ++940d 1 123 71 ++940e c 108 71 ++941a 3d 109 71 ++9457 1 109 71 ++9458 c 188 71 ++9464 12 189 71 ++9476 2 190 71 ++9478 c 272 71 ++9484 4b 273 71 ++94cf 1 273 71 ++94d0 c 603 72 ++94dc c 603 72 ++FUNC 94e8 2b 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::begin() const + 94e8 c 342 26 +-94f4 1f 343 26 +-9513 1 343 26 ++94f4 1f 343 71 ++9513 1 343 71 ++FUNC 9514 2c 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::end() const + 9514 c 360 26 +-9520 20 361 26 +-9540 c 661 26 +-954c 2d 662 26 +-9579 1 662 26 ++9520 20 361 71 ++954c 2d 662 72 ++9579 1 662 72 ++FUNC 957a 2d 0 unsigned long const& std::max(unsigned long const&, unsigned long const&) + 957a c 206 26 +-9586 e 211 26 +-9594 8 212 26 +-959c b 213 26 +-95a7 1 213 26 +-95a8 c 649 26 +-95b4 19 650 26 +-95cd 1 650 26 +-95ce c 665 26 +-95da 5 666 26 +-95df 1 666 26 +-95e0 d 758 26 +-95ed 2b 759 26 +-9618 c 665 26 +-9624 5 666 26 +-9629 1 666 26 +-962a d 758 26 +-9637 2b 759 26 ++9586 e 211 61 ++9594 8 212 61 ++959c b 213 61 ++95a7 1 213 61 ++95b4 19 650 72 ++95cd 1 650 72 ++95da 5 666 72 ++95df 1 666 72 ++95ed 2b 759 72 ++9624 5 666 72 ++9629 1 666 72 ++9637 2b 759 72 ++FUNC 9662 49 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::capacity() const + 9662 c 449 26 +-966e 3d 451 26 +-96ab 1 451 26 ++966e 3d 451 71 ++96ab 1 451 71 ++FUNC 96ac 3c 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::size() const + 96ac c 402 26 +-96b8 30 403 26 +-96e8 c 587 26 +-96f4 26 588 26 +-971a c 591 26 +-9726 26 592 26 +-974c c 103 26 +-9758 d 103 26 +-9765 1 103 26 +-9766 10 285 26 +-9776 1b 286 26 +-9791 1 286 26 +-9792 c 93 26 +-979e d 94 26 +-97ab 1 94 26 +-97ac c 300 26 +-97b8 1e 301 26 +-97d6 d 620 26 +-97e3 56 622 26 +-9839 17 623 26 +-9850 c 1078 26 +-985c 9 1080 26 +-9865 1a 1082 26 +-987f 2 1083 26 +-9881 8 1085 26 +-9889 12 1086 26 +-989b 6 1087 26 +-98a1 6 1083 26 +-98a7 1b 1089 26 +-98c2 1d 1080 26 +-98df c 1091 26 +-98eb 1 1091 26 +-98ec d 360 26 +-98f9 77 361 26 +-9970 c 69 26 +-997c 20 69 26 +-999c d 103 26 +-99a9 5c 104 26 +-9a05 1 104 26 +-9a06 c 69 26 +-9a12 2c 69 26 +-9a3e d 103 26 +-9a4b 5c 104 26 +-9aa7 1 104 26 +-9aa8 c 661 26 +-9ab4 2d 662 26 +-9ae1 1 662 26 +-9ae2 c 649 26 +-9aee 19 650 26 +-9b07 1 650 26 +-9b08 c 665 26 +-9b14 5 666 26 +-9b19 1 666 26 +-9b1a d 758 26 +-9b27 2b 759 26 +-9b52 c 72 26 +-9b5e 2 72 26 +-9b60 c 105 26 +-9b6c d 105 26 +-9b79 1 105 26 +-9b7a c 69 26 +-9b86 2 69 26 +-9b88 c 107 26 +-9b94 d 107 26 +-9ba1 1 107 26 +-9ba2 c 93 26 +-9bae d 94 26 +-9bbb 1 94 26 ++96b8 30 403 71 ++96f4 26 588 34 ++9726 26 592 34 ++974c c 103 69 ++9758 d 103 69 ++9765 1 103 69 ++9776 1b 286 34 ++9791 1 286 34 ++979e d 94 68 ++97ab 1 94 68 ++97b8 1e 301 34 ++97e3 56 622 34 ++9839 17 623 34 ++985c 9 1080 34 ++9865 1a 1082 34 ++987f 2 1083 34 ++9881 8 1085 34 ++9889 12 1086 34 ++989b 6 1087 34 ++98a1 6 1083 34 ++98a7 1b 1089 34 ++98c2 1d 1080 34 ++98df c 1091 34 ++98eb 1 1091 34 ++98ec d 360 34 ++98f9 77 361 34 ++9970 c 69 70 ++997c 20 69 70 ++99a9 5c 104 68 ++9a05 1 104 68 ++9a06 c 69 70 ++9a12 2c 69 70 ++9a4b 5c 104 68 ++9aa7 1 104 68 ++9ab4 2d 662 72 ++9ae1 1 662 72 ++9aee 19 650 72 ++9b07 1 650 72 ++9b14 5 666 72 ++9b19 1 666 72 ++9b27 2b 759 72 ++9b52 c 72 68 ++9b5e 2 72 68 ++9b60 c 105 69 ++9b6c d 105 69 ++9b79 1 105 69 ++9b7a c 69 70 ++9b86 2 69 70 ++9b94 d 107 68 ++9ba1 1 107 68 ++9bae d 94 68 ++9bbb 1 94 68 ++FUNC 9bbc 2a 0 std::_List_base, std::allocator > >::_M_put_node(std::_List_node >*) + 9bbc c 315 26 +-9bc8 1e 316 26 ++9bc8 1e 316 66 ++FUNC 9be6 35 0 bool __gnu_cxx::operator!=<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > > const&, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > > const&) + 9be6 d 699 26 +-9bf3 28 700 26 +-9c1b 1 700 26 +-9c1c c 621 26 +-9c28 d 623 26 +-9c35 5 624 26 +-FUNC 9c3a 4b 0 fill<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, __gnu_cxx::_Hashtable_node > >*> +-9c3a c 539 26 +-9c46 8 541 26 +-9c4e 2 542 26 +-9c50 12 543 26 +-9c62 21 542 26 +-9c83 2 543 26 +-9c85 1 543 26 ++9bf3 28 700 72 ++9c1b 1 700 72 ++9c28 d 623 72 ++9c35 5 624 72 ++FUNC 9c3a 4b 0 void std::__fill::fill<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, __gnu_cxx::_Hashtable_node > >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, __gnu_cxx::_Hashtable_node > >* const&) ++9c3a c 539 61 ++9c46 8 541 61 ++9c4e 2 542 61 ++9c50 12 543 61 ++9c62 21 542 61 ++9c83 2 543 61 ++9c85 1 543 61 ++FUNC 9c86 2b 0 void std::fill<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, __gnu_cxx::_Hashtable_node > >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, __gnu_cxx::_Hashtable_node > >* const&) + 9c86 c 560 26 +-9c92 4 567 26 +-9c96 1b 568 26 +-9cb1 1 568 26 ++9c92 4 567 61 ++9c96 1b 568 61 ++9cb1 1 568 61 ++FUNC 9cb2 4b 0 void std::_Destroy<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, std::allocator<__gnu_cxx::_Hashtable_node > >*> >(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, std::allocator<__gnu_cxx::_Hashtable_node > >*>) + 9cb2 c 171 26 +-9cbe 2 173 26 +-9cc0 1a 174 26 +-9cda 21 173 26 +-9cfb 2 174 26 +-9cfd 1 174 26 +-9cfe c 97 26 +-9d0a 7 98 26 +-9d11 1 98 26 +-9d12 c 83 26 +-9d1e 1d 85 26 +-9d3b 5 86 26 +-9d40 16 88 26 +-9d56 c 296 26 +-9d62 1d 297 26 +-9d7f 1 297 26 +-9d80 d 603 26 +-9d8d e 605 26 +-9d9b 9 606 26 +-9da4 3c 609 26 +-9de0 b 610 26 +-9deb 11 609 26 +-9dfc b 612 26 +-9e07 12 614 26 +-9e19 b 615 26 +-9e24 13 612 26 +-9e37 8 615 26 +-9e3f 1 615 26 +-9e40 d 749 26 +-9e4d 15 751 26 +-9e62 1a 752 26 +-9e7c b 754 26 +-9e87 49 755 26 +-9ed0 3b 756 26 +-9f0b 12 754 26 +-9f1d 15 758 26 +-9f32 8 759 26 +-9f3a 1c 760 26 +-9f56 f 761 26 +-9f65 41 762 26 +-9fa6 c 97 26 +-9fb2 7 98 26 +-9fb9 1 98 26 +-9fba c 83 26 +-9fc6 1d 85 26 +-9fe3 5 86 26 +-9fe8 17 88 26 +-9fff 1 88 26 +-a000 c 296 26 +-a00c 1d 297 26 +-a029 1 297 26 +-a02a d 603 26 +-a037 e 605 26 +-a045 9 606 26 +-a04e 3c 609 26 +-a08a b 610 26 +-a095 11 609 26 +-a0a6 b 612 26 +-a0b1 12 614 26 +-a0c3 b 615 26 +-a0ce 13 612 26 +-a0e1 8 615 26 +-a0e9 1 615 26 +-a0ea d 749 26 +-a0f7 15 751 26 +-a10c 1a 752 26 +-a126 b 754 26 +-a131 49 755 26 +-a17a 3b 756 26 +-a1b5 12 754 26 +-a1c7 15 758 26 +-a1dc 8 759 26 +-a1e4 1c 760 26 +-a200 f 761 26 +-a20f 41 762 26 ++9cbe 2 173 73 ++9cc0 1a 174 73 ++9cda 21 173 73 ++9cfb 2 174 73 ++9cfd 1 174 73 ++9d0a 7 98 68 ++9d11 1 98 68 ++9d1e 1d 85 68 ++9d3b 5 86 68 ++9d40 16 88 68 ++9d62 1d 297 34 ++9d7f 1 297 34 ++9d8d e 605 34 ++9d9b 9 606 34 ++9da4 3c 609 34 ++9de0 b 610 34 ++9deb 11 609 34 ++9dfc b 612 34 ++9e07 12 614 34 ++9e19 b 615 34 ++9e24 13 612 34 ++9e37 8 615 34 ++9e3f 1 615 34 ++9e4d 15 751 34 ++9e62 1a 752 34 ++9e7c b 754 34 ++9e87 49 755 34 ++9ed0 3b 756 34 ++9f0b 12 754 34 ++9f1d 15 758 34 ++9f32 8 759 34 ++9f3a 1c 760 34 ++9f56 f 761 34 ++9f65 41 762 34 ++9fb2 7 98 68 ++9fb9 1 98 68 ++9fc6 1d 85 68 ++9fe3 5 86 68 ++9fe8 17 88 68 ++9fff 1 88 68 ++a00c 1d 297 34 ++a029 1 297 34 ++a037 e 605 34 ++a045 9 606 34 ++a04e 3c 609 34 ++a08a b 610 34 ++a095 11 609 34 ++a0a6 b 612 34 ++a0b1 12 614 34 ++a0c3 b 615 34 ++a0ce 13 612 34 ++a0e1 8 615 34 ++a0e9 1 615 34 ++a0f7 15 751 34 ++a10c 1a 752 34 ++a126 b 754 34 ++a131 49 755 34 ++a17a 3b 756 34 ++a1b5 12 754 34 ++a1c7 15 758 34 ++a1dc 8 759 34 ++a1e4 1c 760 34 ++a200 f 761 34 ++a20f 41 762 34 ++FUNC a250 35 0 bool __gnu_cxx::operator!=<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > > const&, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > > const&) + a250 d 699 26 +-a25d 28 700 26 +-a285 1 700 26 +-a286 c 621 26 +-a292 d 623 26 +-a29f 5 624 26 +-FUNC a2a4 4b 0 fill<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node >**, std::vector<__gnu_cxx::_Hashtable_node >*, std::allocator<__gnu_cxx::_Hashtable_node >*> > >, __gnu_cxx::_Hashtable_node >*> +-a2a4 c 539 26 +-a2b0 8 541 26 +-a2b8 2 542 26 +-a2ba 12 543 26 +-a2cc 21 542 26 +-a2ed 2 543 26 +-a2ef 1 543 26 ++a25d 28 700 72 ++a285 1 700 72 ++a292 d 623 72 ++a29f 5 624 72 ++FUNC a2a4 4b 0 void std::__fill::fill<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >* const&) ++a2a4 c 539 61 ++a2b0 8 541 61 ++a2b8 2 542 61 ++a2ba 12 543 61 ++a2cc 21 542 61 ++a2ed 2 543 61 ++a2ef 1 543 61 ++FUNC a2f0 2b 0 void std::fill<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >* const&) + a2f0 c 560 26 +-a2fc 4 567 26 +-a300 1b 568 26 +-a31b 1 568 26 ++a2fc 4 567 61 ++a300 1b 568 61 ++a31b 1 568 61 ++FUNC a31c 4b 0 void std::_Destroy<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*>) + a31c c 171 26 +-a328 2 173 26 +-a32a 1a 174 26 +-a344 21 173 26 +-a365 2 174 26 +-a367 1 174 26 +-a368 c 65 26 +-a374 2 65 26 +-a376 c 103 26 +-a382 d 103 26 +-a38f 1 103 26 ++a328 2 173 73 ++a32a 1a 174 73 ++a344 21 173 73 ++a365 2 174 73 ++a367 1 174 73 ++a368 c 65 68 ++a374 2 65 68 ++a376 c 103 69 ++a382 d 103 69 ++a38f 1 103 69 ++FUNC a390 2b 0 std::_List_base, std::allocator > >::get_allocator() const + a390 10 322 26 +-a3a0 1b 324 26 +-a3bb 1 324 26 ++a3a0 1b 324 66 ++a3bb 1 324 66 ++FUNC a3bc 7b 0 std::_List_base, std::allocator > >::_M_clear() + a3bc d 69 27 +-a3c9 8 72 27 +-a3d1 2 73 27 +-a3d3 6 75 27 +-a3d9 8 76 27 +-a3e1 35 77 27 +-a416 12 78 27 +-a428 a 73 27 +-a432 5 78 27 +-a437 1 78 27 +-a438 c 331 27 +-a444 18 332 27 +-a45c c 392 27 +-a468 d 392 27 +-a475 1 392 27 +-a476 c 211 27 +-a482 10 211 27 +-a492 c 107 27 +-a49e d 107 27 +-a4ab 1 107 27 ++a3c9 8 72 77 ++a3d1 2 73 77 ++a3d3 6 75 77 ++a3d9 8 76 77 ++a3e1 35 77 77 ++a416 12 78 77 ++a428 a 73 77 ++a432 5 78 77 ++a437 1 78 77 ++a438 c 331 66 ++a444 18 332 66 ++a45c c 392 66 ++a468 d 392 66 ++a475 1 392 66 ++a476 c 211 74 ++a482 10 211 74 ++a49e d 107 68 ++a4ab 1 107 68 ++FUNC a4ac 2e 0 void std::_Destroy >(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, std::allocator) + a4ac c 171 27 +-a4b8 2 173 27 +-a4ba 12 174 27 +-a4cc c 173 27 +-a4d8 2 174 27 +-a4da c 272 27 +-a4e6 4b 273 27 +-a531 1 273 27 +-a532 13 196 27 +-a545 10 196 27 +-a555 2f 197 27 +-a584 1a 198 27 +-a59e 13 196 27 +-a5b1 10 196 27 +-a5c1 2f 197 27 +-a5f0 1a 198 27 +-a60a c 97 27 +-a616 7 98 27 +-a61d 1 98 27 +-a61e c 83 27 +-a62a 1d 85 27 +-a647 5 86 27 +-a64c 10 88 27 ++a4b8 2 173 73 ++a4ba 12 174 73 ++a4cc c 173 73 ++a4d8 2 174 73 ++a4da c 272 71 ++a4e6 4b 273 71 ++a531 1 273 71 ++a532 13 196 74 ++a545 10 196 74 ++a555 2f 197 74 ++a584 1a 198 74 ++a59e 13 196 74 ++a5b1 10 196 74 ++a5c1 2f 197 74 ++a5f0 1a 198 74 ++a616 7 98 68 ++a61d 1 98 68 ++a62a 1d 85 68 ++a647 5 86 68 ++a64c 10 88 68 ++FUNC a65c 2a 0 std::_Vector_base<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::_M_allocate(unsigned long) + a65c c 116 27 +-a668 1e 117 27 +-a686 d 100 27 +-a693 12 101 27 +-a6a5 19 103 27 +-a6be b 104 27 +-a6c9 3a 105 27 +-a703 1 105 27 +-a704 c 97 27 +-a710 7 98 27 +-a717 1 98 27 +-a718 c 83 27 +-a724 1d 85 27 +-a741 5 86 27 +-a746 10 88 27 ++a668 1e 117 71 ++a686 d 100 71 ++a693 12 101 71 ++a6a5 19 103 71 ++a6be b 104 71 ++a6c9 3a 105 71 ++a703 1 105 71 ++a710 7 98 68 ++a717 1 98 68 ++a724 1d 85 68 ++a741 5 86 68 ++a746 10 88 68 ++FUNC a756 2a 0 std::_Vector_base<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::_M_allocate(unsigned long) + a756 c 116 27 +-a762 1e 117 27 +-a780 d 100 27 +-a78d 12 101 27 +-a79f 19 103 27 +-a7b8 b 104 27 +-a7c3 3a 105 27 +-a7fd 1 105 27 +-FUNC a7fe 60 0 copy_b<__gnu_cxx::_Hashtable_node > >*> +-a7fe d 422 27 +-a80b 12 424 27 +-a81d 2e 425 27 +-a84b 13 426 27 +-a85e c 432 27 +-a86a 4 440 27 +-a86e 1b 443 27 +-a889 1 443 27 +-FUNC a88a 64 0 copy_b_n<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > > > +-a88a e 480 27 +-a898 56 482 27 +-a8ee c 504 27 +-a8fa 4 514 27 +-a8fe 4 515 27 +-a902 1b 517 27 +-a91d 1 517 27 +-FUNC a91e 32 0 fill_n<__gnu_cxx::_Hashtable_node >**, long unsigned int, __gnu_cxx::_Hashtable_node >*> +-a91e c 614 27 +-a92a 8 616 27 +-a932 2 617 27 +-a934 8 618 27 +-a93c f 617 27 +-a94b 5 619 27 +-a950 c 636 27 +-a95c 4 641 27 +-a960 1b 642 27 +-a97b 1 642 27 ++a762 1e 117 71 ++a780 d 100 71 ++a78d 12 101 71 ++a79f 19 103 71 ++a7b8 b 104 71 ++a7c3 3a 105 71 ++a7fd 1 105 71 ++a80b 12 424 61 ++a81d 2e 425 61 ++a84b 13 426 61 ++a86a 4 440 61 ++a86e 1b 443 61 ++a889 1 443 61 ++a898 56 482 61 ++a8fa 4 514 61 ++a8fe 4 515 61 ++a902 1b 517 61 ++a91d 1 517 61 ++a92a 8 616 61 ++a932 2 617 61 ++a934 8 618 61 ++a93c f 617 61 ++a94b 5 619 61 ++a95c 4 641 61 ++a960 1b 642 61 ++a97b 1 642 61 ++FUNC a97c 27 0 void std::__uninitialized_fill_n_aux<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*>(__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >* const&, __true_type) + a97c c 182 28 +-a988 1b 183 28 +-a9a3 1 183 28 ++a988 1b 183 79 ++a9a3 1 183 79 ++FUNC a9a4 2f 0 void std::uninitialized_fill_n<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*>(__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >* const&) + a9a4 c 214 28 +-a9b0 23 218 28 +-a9d3 1 218 28 ++a9b0 23 218 79 ++a9d3 1 218 79 ++FUNC a9d4 27 0 void std::__uninitialized_fill_n_a<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*>(__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >* const&, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*>) + a9d4 c 308 28 +-a9e0 1b 310 28 +-a9fb 1 310 28 +-a9fc c 200 28 +-aa08 19 201 28 +-aa21 42 203 28 +-aa63 15 205 28 +-aa78 d 990 28 +-aa85 11 992 28 +-aa96 c 993 28 +-aaa2 15 995 28 +-aab7 c 996 28 +-aac3 4a 998 28 +-ab0d f 1001 28 +-ab1c 1c 998 28 +-ab38 1a 1003 28 +-ab52 5 1004 28 +-ab57 1f 1007 28 +-ab76 1c 1008 28 +-ab92 19 1009 28 +-abab 19 1010 28 +-abc4 1a 1011 28 +-abde a 1004 28 +-abe8 11 1001 28 +-abf9 15 1014 28 +-ac0e 13 1028 28 +-ac21 b 1016 28 +-ac2c 9 1018 28 +-ac35 19 1023 28 +-ac4e 23 1024 28 +-ac71 19 1025 28 +-ac8a 1d 1021 28 +-aca7 1a 1018 28 +-acc1 b 1028 28 +-accc b 1016 28 +-acd7 1e 1028 28 +-acf5 1 1028 28 +-acf6 10 436 28 +-ad06 16 438 28 +-ad1c 37 439 28 +-ad53 1 439 28 +-ad54 10 211 28 +-ad64 37 212 28 +-ad9b 1 212 28 +-FUNC ad9c 32 0 fill_n<__gnu_cxx::_Hashtable_node > >**, long unsigned int, __gnu_cxx::_Hashtable_node > >*> +-ad9c c 614 28 +-ada8 8 616 28 +-adb0 2 617 28 +-adb2 8 618 28 +-adba f 617 28 +-adc9 5 619 28 +-adce c 636 28 +-adda 4 641 28 +-adde 1b 642 28 +-adf9 1 642 28 ++a9e0 1b 310 79 ++a9fb 1 310 79 ++a9fc c 200 71 ++aa08 19 201 71 ++aa21 42 203 71 ++aa63 15 205 71 ++aa85 11 992 34 ++aa96 c 993 34 ++aaa2 15 995 34 ++aab7 c 996 34 ++aac3 4a 998 34 ++ab0d f 1001 34 ++ab1c 1c 998 34 ++ab38 1a 1003 34 ++ab52 5 1004 34 ++ab57 1f 1007 34 ++ab76 1c 1008 34 ++ab92 19 1009 34 ++abab 19 1010 34 ++abc4 1a 1011 34 ++abde a 1004 34 ++abe8 11 1001 34 ++abf9 15 1014 34 ++ac0e 13 1028 34 ++ac21 b 1016 34 ++ac2c 9 1018 34 ++ac35 19 1023 34 ++ac4e 23 1024 34 ++ac71 19 1025 34 ++ac8a 1d 1021 34 ++aca7 1a 1018 34 ++acc1 b 1028 34 ++accc b 1016 34 ++acd7 1e 1028 34 ++acf5 1 1028 34 ++ad06 16 438 34 ++ad1c 37 439 34 ++ad53 1 439 34 ++ad64 37 212 42 ++ad9b 1 212 42 ++ada8 8 616 61 ++adb0 2 617 61 ++adb2 8 618 61 ++adba f 617 61 ++adc9 5 619 61 ++adda 4 641 61 ++adde 1b 642 61 ++adf9 1 642 61 ++FUNC adfa 27 0 void std::__uninitialized_fill_n_aux<__gnu_cxx::_Hashtable_node > >**, unsigned long, __gnu_cxx::_Hashtable_node > >*>(__gnu_cxx::_Hashtable_node > >**, unsigned long, __gnu_cxx::_Hashtable_node > >* const&, __true_type) + adfa c 182 28 +-ae06 1b 183 28 +-ae21 1 183 28 ++ae06 1b 183 79 ++ae21 1 183 79 ++FUNC ae22 2f 0 void std::uninitialized_fill_n<__gnu_cxx::_Hashtable_node > >**, unsigned long, __gnu_cxx::_Hashtable_node > >*>(__gnu_cxx::_Hashtable_node > >**, unsigned long, __gnu_cxx::_Hashtable_node > >* const&) + ae22 c 214 28 +-ae2e 23 218 28 +-ae51 1 218 28 ++ae2e 23 218 79 ++ae51 1 218 79 ++FUNC ae52 27 0 void std::__uninitialized_fill_n_a<__gnu_cxx::_Hashtable_node > >**, unsigned long, __gnu_cxx::_Hashtable_node > >*, __gnu_cxx::_Hashtable_node > >*>(__gnu_cxx::_Hashtable_node > >**, unsigned long, __gnu_cxx::_Hashtable_node > >* const&, std::allocator<__gnu_cxx::_Hashtable_node > >*>) + ae52 c 308 28 +-ae5e 1b 310 28 +-ae79 1 310 28 +-ae7a c 200 28 +-ae86 19 201 28 +-ae9f 42 203 28 +-aee1 15 205 28 +-aef6 d 990 28 +-af03 11 992 28 +-af14 c 993 28 +-af20 15 995 28 +-af35 c 996 28 +-af41 4a 998 28 +-af8b f 1001 28 +-af9a 1c 998 28 +-afb6 1a 1003 28 +-afd0 5 1004 28 +-afd5 1f 1007 28 +-aff4 1c 1008 28 +-b010 19 1009 28 +-b029 19 1010 28 +-b042 1a 1011 28 +-b05c a 1004 28 +-b066 11 1001 28 +-b077 15 1014 28 +-b08c 13 1028 28 +-b09f b 1016 28 +-b0aa 9 1018 28 +-b0b3 19 1023 28 +-b0cc 23 1024 28 +-b0ef 19 1025 28 +-b108 1d 1021 28 +-b125 1a 1018 28 +-b13f b 1028 28 +-b14a b 1016 28 +-b155 1e 1028 28 +-b173 1 1028 28 +-b174 10 436 28 +-b184 16 438 28 +-b19a 37 439 28 +-b1d1 1 439 28 +-b1d2 10 211 28 +-b1e2 37 212 28 +-b219 1 212 28 +-FUNC b21a 60 0 copy_b<__gnu_cxx::_Hashtable_node >*> +-b21a d 422 28 +-b227 12 424 28 +-b239 2e 425 28 +-b267 13 426 28 +-b27a c 432 28 +-b286 4 440 28 +-b28a 1b 443 28 +-b2a5 1 443 28 +-FUNC b2a6 64 0 copy_b_n<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node >**, std::vector<__gnu_cxx::_Hashtable_node >*, std::allocator<__gnu_cxx::_Hashtable_node >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node >**, std::vector<__gnu_cxx::_Hashtable_node >*, std::allocator<__gnu_cxx::_Hashtable_node >*> > > > +-b2a6 e 480 28 +-b2b4 56 482 28 +-b30a c 504 28 +-b316 4 514 28 +-b31a 4 515 28 +-b31e 1b 517 28 +-b339 1 517 28 +-FUNC b33a 43 0 fill_n<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, long unsigned int, __gnu_cxx::_Hashtable_node > >*> +-b33a c 614 28 +-b346 8 616 28 +-b34e 2 617 28 +-b350 12 618 28 +-b362 16 617 28 +-b378 5 619 28 +-b37d 1 619 28 +-b37e c 636 28 +-b38a 4 641 28 +-b38e 1b 642 28 +-b3a9 1 642 28 ++ae5e 1b 310 79 ++ae79 1 310 79 ++ae7a c 200 71 ++ae86 19 201 71 ++ae9f 42 203 71 ++aee1 15 205 71 ++af03 11 992 34 ++af14 c 993 34 ++af20 15 995 34 ++af35 c 996 34 ++af41 4a 998 34 ++af8b f 1001 34 ++af9a 1c 998 34 ++afb6 1a 1003 34 ++afd0 5 1004 34 ++afd5 1f 1007 34 ++aff4 1c 1008 34 ++b010 19 1009 34 ++b029 19 1010 34 ++b042 1a 1011 34 ++b05c a 1004 34 ++b066 11 1001 34 ++b077 15 1014 34 ++b08c 13 1028 34 ++b09f b 1016 34 ++b0aa 9 1018 34 ++b0b3 19 1023 34 ++b0cc 23 1024 34 ++b0ef 19 1025 34 ++b108 1d 1021 34 ++b125 1a 1018 34 ++b13f b 1028 34 ++b14a b 1016 34 ++b155 1e 1028 34 ++b173 1 1028 34 ++b184 16 438 34 ++b19a 37 439 34 ++b1d1 1 439 34 ++b1e2 37 212 42 ++b219 1 212 42 ++b227 12 424 61 ++b239 2e 425 61 ++b267 13 426 61 ++b286 4 440 61 ++b28a 1b 443 61 ++b2a5 1 443 61 ++b2b4 56 482 61 ++b316 4 514 61 ++b31a 4 515 61 ++b31e 1b 517 61 ++b339 1 517 61 ++b346 8 616 61 ++b34e 2 617 61 ++b350 12 618 61 ++b362 16 617 61 ++b378 5 619 61 ++b37d 1 619 61 ++b38a 4 641 61 ++b38e 1b 642 61 ++b3a9 1 642 61 ++FUNC b3aa 27 0 void std::__uninitialized_fill_n_aux<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node > >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node > >* const&, __true_type) + b3aa c 182 28 +-b3b6 1b 183 28 +-b3d1 1 183 28 ++b3b6 1b 183 79 ++b3d1 1 183 79 ++FUNC b3d2 2f 0 void std::uninitialized_fill_n<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node > >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node > >* const&) + b3d2 c 214 28 +-b3de 23 218 28 +-b401 1 218 28 ++b3de 23 218 79 ++b401 1 218 79 ++FUNC b402 27 0 void std::__uninitialized_fill_n_a<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node > >*, __gnu_cxx::_Hashtable_node > >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node > >* const&, std::allocator<__gnu_cxx::_Hashtable_node > >*>) + b402 c 308 28 +-b40e 1b 310 28 +-b429 1 310 28 +-FUNC b42a 43 0 fill_n<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node >**, std::vector<__gnu_cxx::_Hashtable_node >*, std::allocator<__gnu_cxx::_Hashtable_node >*> > >, long unsigned int, __gnu_cxx::_Hashtable_node >*> +-b42a c 614 28 +-b436 8 616 28 +-b43e 2 617 28 +-b440 12 618 28 +-b452 16 617 28 +-b468 5 619 28 +-b46d 1 619 28 +-b46e c 636 28 +-b47a 4 641 28 +-b47e 1b 642 28 +-b499 1 642 28 ++b40e 1b 310 79 ++b429 1 310 79 ++b436 8 616 61 ++b43e 2 617 61 ++b440 12 618 61 ++b452 16 617 61 ++b468 5 619 61 ++b46d 1 619 61 ++b47a 4 641 61 ++b47e 1b 642 61 ++b499 1 642 61 ++FUNC b49a 27 0 void std::__uninitialized_fill_n_aux<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >* const&, __true_type) + b49a c 182 28 +-b4a6 1b 183 28 +-b4c1 1 183 28 ++b4a6 1b 183 79 ++b4c1 1 183 79 ++FUNC b4c2 2f 0 void std::uninitialized_fill_n<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >* const&) + b4c2 c 214 28 +-b4ce 23 218 28 +-b4f1 1 218 28 ++b4ce 23 218 79 ++b4f1 1 218 79 ++FUNC b4f2 27 0 void std::__uninitialized_fill_n_a<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*>(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >* const&, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*>) + b4f2 c 308 28 +-b4fe 1b 310 28 +-b519 1 310 28 +-FUNC b51a 3f 0 copy<__gnu_cxx::_Hashtable_node > >*> +-b51a c 298 28 +-b526 22 300 28 +-b548 11 301 28 +-b559 1 301 28 +-b55a c 307 28 +-b566 4 315 28 +-b56a 1b 317 28 +-b585 1 317 28 +-FUNC b586 27 0 copy_n<__gnu_cxx::_Hashtable_node > >**, __gnu_cxx::_Hashtable_node > >**> +-b586 c 325 28 +-b592 1b 326 28 +-b5ad 1 326 28 +-b5ae c 376 28 +-b5ba 4 384 28 +-b5be 4 385 28 +-b5c2 1b 387 28 +-b5dd 1 387 28 +-b5de c 73 28 +-b5ea 1b 74 28 +-b605 1 74 28 +-b606 c 108 28 +-b612 23 113 28 +-b635 1 113 28 +-b636 c 252 28 +-b642 1b 254 28 +-b65d 1 254 28 +-FUNC b65e 66 0 _M_allocate_and_copy<__gnu_cxx::_Hashtable_node > >**> +-b65e c 761 28 +-b66a 15 763 28 +-b67f 40 766 28 +-b6bf 3 768 28 +-b6c2 2 773 28 ++b4fe 1b 310 79 ++b519 1 310 79 ++b526 22 300 61 ++b548 11 301 61 ++b559 1 301 61 ++b566 4 315 61 ++b56a 1b 317 61 ++b585 1 317 61 ++b592 1b 326 61 ++b5ad 1 326 61 ++b5ba 4 384 61 ++b5be 4 385 61 ++b5c2 1b 387 61 ++b5dd 1 387 61 ++b5ea 1b 74 79 ++b605 1 74 79 ++b612 23 113 79 ++b635 1 113 79 ++b642 1b 254 79 ++b65d 1 254 79 ++b66a 15 763 71 ++b67f 40 766 71 ++b6bf 3 768 71 ++b6c2 2 773 71 ++FUNC b6c4 124 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::reserve(unsigned long) + b6c4 13 69 29 +-b6d7 15 71 29 +-b6ec e 72 29 +-b6fa 19 73 29 +-b713 e 75 29 +-b721 28 78 29 +-b749 3e 79 29 +-b787 30 81 29 +-b7b7 8 84 29 +-b7bf 11 85 29 +-b7d0 18 86 29 +-FUNC b7e8 40 0 copy_n<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, __gnu_cxx::_Hashtable_node > >**> +-b7e8 d 334 29 +-b7f5 33 335 29 +-b828 c 376 29 +-b834 4 384 29 +-b838 4 385 29 +-b83c 1b 387 29 +-b857 1 387 29 +-b858 c 73 29 +-b864 1b 74 29 +-b87f 1 74 29 +-b880 c 108 29 +-b88c 23 113 29 +-b8af 1 113 29 +-b8b0 c 252 29 +-b8bc 1b 254 29 +-b8d7 1 254 29 +-FUNC b8d8 64 0 copy_n<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > > > +-b8d8 e 352 29 +-b8e6 56 354 29 +-b93c c 376 29 +-b948 4 384 29 +-b94c 4 385 29 +-b950 1b 387 29 +-b96b 1 387 29 +-b96c c 73 29 +-b978 1b 74 29 +-b993 1 74 29 +-b994 c 108 29 +-b9a0 23 113 29 +-b9c3 1 113 29 +-b9c4 c 252 29 +-b9d0 1b 254 29 +-b9eb 1 254 29 ++b6d7 15 71 78 ++b6ec e 72 78 ++b6fa 19 73 78 ++b713 e 75 78 ++b721 28 78 78 ++b749 3e 79 78 ++b787 30 81 78 ++b7b7 8 84 78 ++b7bf 11 85 78 ++b7d0 18 86 78 ++b7f5 33 335 61 ++b834 4 384 61 ++b838 4 385 61 ++b83c 1b 387 61 ++b857 1 387 61 ++b864 1b 74 79 ++b87f 1 74 79 ++b88c 23 113 79 ++b8af 1 113 79 ++b8bc 1b 254 79 ++b8d7 1 254 79 ++b8e6 56 354 61 ++b948 4 384 61 ++b94c 4 385 61 ++b950 1b 387 61 ++b96b 1 387 61 ++b978 1b 74 79 ++b993 1 74 79 ++b9a0 23 113 79 ++b9c3 1 113 79 ++b9d0 1b 254 79 ++b9eb 1 254 79 ++FUNC b9ec 46e 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::_M_fill_insert(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node > >* const&) + b9ec 14 311 29 +-ba00 b 313 29 +-ba0b 24 315 29 +-ba2f 8 318 29 +-ba37 23 319 29 +-ba5a 15 320 29 +-ba6f c 321 29 +-ba7b 51 323 29 +-bacc 14 327 29 +-bae0 30 328 29 +-bb10 35 330 29 +-bb45 48 334 29 +-bb8d 17 338 29 +-bba4 43 339 29 +-bbe7 14 342 29 +-bbfb 1e 343 29 +-bc19 e 348 29 +-bc27 1e 349 29 +-bc45 e 350 29 +-bc53 1d 353 29 +-bc70 8 354 29 +-bc78 e 355 29 +-bc86 27 357 29 +-bcad 6 358 29 +-bcb3 4d 361 29 +-bd00 40 365 29 +-bd40 18 367 29 +-bd58 4d 368 29 +-bda5 3e 379 29 +-bde3 30 381 29 +-be13 12 384 29 +-be25 13 385 29 +-be38 22 386 29 ++ba00 b 313 78 ++ba0b 24 315 78 ++ba2f 8 318 78 ++ba37 23 319 78 ++ba5a 15 320 78 ++ba6f c 321 78 ++ba7b 51 323 78 ++bacc 14 327 78 ++bae0 30 328 78 ++bb10 35 330 78 ++bb45 48 334 78 ++bb8d 17 338 78 ++bba4 43 339 78 ++bbe7 14 342 78 ++bbfb 1e 343 78 ++bc19 e 348 78 ++bc27 1e 349 78 ++bc45 e 350 78 ++bc53 1d 353 78 ++bc70 8 354 78 ++bc78 e 355 78 ++bc86 27 357 78 ++bcad 6 358 78 ++bcb3 4d 361 78 ++bd00 40 365 78 ++bd40 18 367 78 ++bd58 4d 368 78 ++bda5 3e 379 78 ++bde3 30 381 78 ++be13 12 384 78 ++be25 13 385 78 ++be38 22 386 78 ++FUNC be5a 2e 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::insert(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node > >**, std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> > >, unsigned long, __gnu_cxx::_Hashtable_node > >* const&) + be5a c 657 29 +-be66 22 658 29 +-be88 c 578 29 +-be94 15 580 29 +-bea9 15 581 29 +-bebe 37 582 29 +-bef5 c 583 29 +-bf01 1 583 29 +-bf02 d 335 29 +-bf0f 4e 337 29 +-bf5d 4d 338 29 +-bfaa d 134 29 +-bfb7 65 135 29 +-FUNC c01c 3f 0 copy<__gnu_cxx::_Hashtable_node >*> +-c01c c 298 29 +-c028 22 300 29 +-c04a 11 301 29 +-c05b 1 301 29 +-c05c c 307 29 +-c068 4 315 29 +-c06c 1b 317 29 +-c087 1 317 29 +-FUNC c088 27 0 copy_n<__gnu_cxx::_Hashtable_node >**, __gnu_cxx::_Hashtable_node >**> +-c088 c 325 29 +-c094 1b 326 29 +-c0af 1 326 29 +-c0b0 c 376 29 +-c0bc 4 384 29 +-c0c0 4 385 29 +-c0c4 1b 387 29 +-c0df 1 387 29 +-c0e0 c 73 29 +-c0ec 1b 74 29 +-c107 1 74 29 +-c108 c 108 29 +-c114 23 113 29 +-c137 1 113 29 +-c138 c 252 29 +-c144 1b 254 29 +-c15f 1 254 29 +-FUNC c160 66 0 _M_allocate_and_copy<__gnu_cxx::_Hashtable_node >**> +-c160 c 761 29 +-c16c 15 763 29 +-c181 40 766 29 +-c1c1 3 768 29 +-c1c4 2 773 29 ++be66 22 658 71 ++be94 15 580 34 ++bea9 15 581 34 ++bebe 37 582 34 ++bef5 c 583 34 ++bf01 1 583 34 ++bf02 d 335 34 ++bf0f 4e 337 34 ++bf5d 4d 338 34 ++bfaa d 134 42 ++bfb7 65 135 42 ++c028 22 300 61 ++c04a 11 301 61 ++c05b 1 301 61 ++c068 4 315 61 ++c06c 1b 317 61 ++c087 1 317 61 ++c094 1b 326 61 ++c0af 1 326 61 ++c0bc 4 384 61 ++c0c0 4 385 61 ++c0c4 1b 387 61 ++c0df 1 387 61 ++c0ec 1b 74 79 ++c107 1 74 79 ++c114 23 113 79 ++c137 1 113 79 ++c144 1b 254 79 ++c15f 1 254 79 ++c16c 15 763 71 ++c181 40 766 71 ++c1c1 3 768 71 ++c1c4 2 773 71 ++FUNC c1c6 124 0 std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::reserve(unsigned long) + c1c6 13 69 29 +-c1d9 15 71 29 +-c1ee e 72 29 +-c1fc 19 73 29 +-c215 e 75 29 +-c223 28 78 29 +-c24b 3e 79 29 +-c289 30 81 29 +-c2b9 8 84 29 +-c2c1 11 85 29 +-c2d2 18 86 29 +-FUNC c2ea 40 0 copy_n<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node >**, std::vector<__gnu_cxx::_Hashtable_node >*, std::allocator<__gnu_cxx::_Hashtable_node >*> > >, __gnu_cxx::_Hashtable_node >**> +-c2ea d 334 29 +-c2f7 33 335 29 +-c32a c 376 29 +-c336 4 384 29 +-c33a 4 385 29 +-c33e 1b 387 29 +-c359 1 387 29 +-c35a c 73 29 +-c366 1b 74 29 +-c381 1 74 29 +-c382 c 108 29 +-c38e 23 113 29 +-c3b1 1 113 29 +-c3b2 c 252 29 +-c3be 1b 254 29 +-c3d9 1 254 29 +-FUNC c3da 64 0 copy_n<__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node >**, std::vector<__gnu_cxx::_Hashtable_node >*, std::allocator<__gnu_cxx::_Hashtable_node >*> > >, __gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node >**, std::vector<__gnu_cxx::_Hashtable_node >*, std::allocator<__gnu_cxx::_Hashtable_node >*> > > > +-c3da e 352 29 +-c3e8 56 354 29 +-c43e c 376 29 +-c44a 4 384 29 +-c44e 4 385 29 +-c452 1b 387 29 +-c46d 1 387 29 +-c46e c 73 29 +-c47a 1b 74 29 +-c495 1 74 29 +-c496 c 108 29 +-c4a2 23 113 29 +-c4c5 1 113 29 +-c4c6 c 252 29 +-c4d2 1b 254 29 +-c4ed 1 254 29 ++c1d9 15 71 78 ++c1ee e 72 78 ++c1fc 19 73 78 ++c215 e 75 78 ++c223 28 78 78 ++c24b 3e 79 78 ++c289 30 81 78 ++c2b9 8 84 78 ++c2c1 11 85 78 ++c2d2 18 86 78 ++c2f7 33 335 61 ++c336 4 384 61 ++c33a 4 385 61 ++c33e 1b 387 61 ++c359 1 387 61 ++c366 1b 74 79 ++c381 1 74 79 ++c38e 23 113 79 ++c3b1 1 113 79 ++c3be 1b 254 79 ++c3d9 1 254 79 ++c3e8 56 354 61 ++c44a 4 384 61 ++c44e 4 385 61 ++c452 1b 387 61 ++c46d 1 387 61 ++c47a 1b 74 79 ++c495 1 74 79 ++c4a2 23 113 79 ++c4c5 1 113 79 ++c4d2 1b 254 79 ++c4ed 1 254 79 ++FUNC c4ee 46e 0 std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::_M_fill_insert(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >* const&) + c4ee 14 311 29 +-c502 b 313 29 +-c50d 24 315 29 +-c531 8 318 29 +-c539 23 319 29 +-c55c 15 320 29 +-c571 c 321 29 +-c57d 51 323 29 +-c5ce 14 327 29 +-c5e2 30 328 29 +-c612 35 330 29 +-c647 48 334 29 +-c68f 17 338 29 +-c6a6 43 339 29 +-c6e9 14 342 29 +-c6fd 1e 343 29 +-c71b e 348 29 +-c729 1e 349 29 +-c747 e 350 29 +-c755 1d 353 29 +-c772 8 354 29 +-c77a e 355 29 +-c788 27 357 29 +-c7af 6 358 29 +-c7b5 4d 361 29 +-c802 40 365 29 +-c842 18 367 29 +-c85a 4d 368 29 +-c8a7 3e 379 29 +-c8e5 30 381 29 +-c915 12 384 29 +-c927 13 385 29 +-c93a 22 386 29 ++c502 b 313 78 ++c50d 24 315 78 ++c531 8 318 78 ++c539 23 319 78 ++c55c 15 320 78 ++c571 c 321 78 ++c57d 51 323 78 ++c5ce 14 327 78 ++c5e2 30 328 78 ++c612 35 330 78 ++c647 48 334 78 ++c68f 17 338 78 ++c6a6 43 339 78 ++c6e9 14 342 78 ++c6fd 1e 343 78 ++c71b e 348 78 ++c729 1e 349 78 ++c747 e 350 78 ++c755 1d 353 78 ++c772 8 354 78 ++c77a e 355 78 ++c788 27 357 78 ++c7af 6 358 78 ++c7b5 4d 361 78 ++c802 40 365 78 ++c842 18 367 78 ++c85a 4d 368 78 ++c8a7 3e 379 78 ++c8e5 30 381 78 ++c915 12 384 78 ++c927 13 385 78 ++c93a 22 386 78 ++FUNC c95c 2e 0 std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> >::insert(__gnu_cxx::__normal_iterator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >**, std::vector<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*, std::allocator<__gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >*> > >, unsigned long, __gnu_cxx::_Hashtable_node, __gnu_cxx::hash, std::equal_to, std::allocator > >*> >* const&) + c95c c 657 29 +-c968 22 658 29 +-c98a c 578 29 +-c996 15 580 29 +-c9ab 15 581 29 +-c9c0 37 582 29 +-c9f7 c 583 29 +-ca03 1 583 29 +-ca04 d 335 29 +-ca11 4e 337 29 +-ca5f 4d 338 29 +-caac d 134 29 +-cab9 65 135 29 +-cb1e 39 135 30 ++c968 22 658 71 ++c996 15 580 34 ++c9ab 15 581 34 ++c9c0 37 582 34 ++c9f7 c 583 34 ++ca03 1 583 34 ++ca04 d 335 34 ++ca11 4e 337 34 ++ca5f 4d 338 34 ++caac d 134 42 ++cab9 65 135 42 ++FUNC cb1e 44 0 dwarf2reader::CUFunctionInfoHandler::StartCompilationUnit(unsigned long long, unsigned char, unsigned char, unsigned long long, unsigned char) ++cb1e 39 135 42 + cb57 5 102 30 + cb5c 6 103 30 ++FUNC cb62 41 0 dwarf2reader::CUFunctionInfoHandler::ProcessAttributeString(unsigned long long, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm, std::string const&) + cb62 18 136 30 + cb7a 10 137 30 + cb8a 17 138 30 + cba1 2 139 30 + cba3 1 139 30 ++FUNC cba4 2a5 0 dwarf2reader::CUFunctionInfoHandler::ProcessAttributeUnsigned(unsigned long long, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm, unsigned long long) + cba4 2d 144 30 + cbd1 a 145 30 + cbdb 58 146 30 + cc33 35 147 30 + cc68 32 146 30 + cc9a 2a 147 30 + ccc4 82 152 30 + cd46 18 153 30 +@@ -2386,47 +2350,52 @@ cddf 12 157 30 + cdf1 2 158 30 + cdf3 12 160 30 + ce05 2 161 30 + ce07 c 163 30 + ce13 2 164 30 + ce15 2c 166 30 + ce41 8 172 30 + ce49 1 172 30 ++FUNC ce4a 19c 0 dwarf2reader::CULineInfoHandler::AddLine(unsigned long long, unsigned int, unsigned int, unsigned int) + ce4a 20 84 30 + ce6a 1c 85 30 + ce86 9c 87 30 + cf22 4f 89 30 + cf71 19 87 30 + cf8a 25 90 30 + cfaf 30 93 30 + cfdf 7 95 30 ++FUNC cfe6 9f 0 dwarf2reader::CUFunctionInfoHandler::EndDIE(unsigned long long) + cfe6 19 174 30 + cfff 1c 175 30 + d01b 65 177 30 + d080 5 178 30 + d085 1 178 30 ++FUNC d086 164 0 dwarf2reader::CUFunctionInfoHandler::StartDIE(unsigned long long, dwarf2reader::DwarfTag, std::list, std::allocator > > const&) + d086 20 111 30 + d0a6 1c 112 30 + d0c2 c 126 30 + d0ce 23 115 30 + d0f1 26 116 30 + d117 1a 117 30 + d131 d 118 30 + d13e 1b 119 30 + d159 5f 120 30 + d1b8 c 124 30 + d1c4 1c 115 30 + d1e0 3 126 30 + d1e3 7 129 30 ++FUNC d1ea 73 0 dwarf2reader::CULineInfoHandler::DefineDir(std::string const&, unsigned int) + d1ea 13 52 30 + d1fd 45 54 30 + d242 15 55 30 + d257 6 56 30 + d25d 1 56 30 ++FUNC d25e 23b 0 dwarf2reader::CULineInfoHandler::DefineFile(std::string const&, int, unsigned int, unsigned long long, unsigned long long) + d25e 2c 60 30 + d28a 45 62 30 + d2cf 2f 65 30 + d2fe 24 66 30 + d322 b 68 30 + d32d e 69 30 + d33b 19 71 30 + d354 17 72 30 +@@ -2452,548 +2421,576 @@ d6ba 41 43 30 + d6fb 41 44 30 + d73c 67 45 30 + d7a3 10 46 30 + d7b3 13 45 30 + d7c6 15 47 30 + d7db e 48 30 + d7e9 3d 49 30 + d826 20 50 30 +-d846 12 125 31 +-d858 12 125 31 ++d846 12 125 74 ++d858 12 125 74 + d86a 13 55 32 + d87d 35 55 32 + d8b2 13 98 32 + d8c5 35 98 32 + d8fa c 35 32 + d906 d 35 32 + d913 1 35 32 + d914 d 22 32 + d921 40 22 32 + d961 1 22 32 +-d962 c 89 33 +-d96e 1e 90 33 +-d98c c 207 34 ++d962 c 89 70 ++d96e 1e 90 70 + d998 14 208 34 +-d9ac c 190 35 +-d9b8 a 190 35 +-d9c2 c 259 35 +-d9ce 21 259 35 +-d9ef 1 259 35 ++d9ac c 190 67 ++d9b8 a 190 67 ++d9c2 c 259 67 ++d9ce 21 259 67 ++d9ef 1 259 67 ++FUNC d9f0 13 0 std::auto_ptr::operator->() const + d9f0 c 283 35 +-d9fc 7 286 35 +-da03 1 286 35 +-da04 d 103 36 +-da11 5c 104 36 +-da6d 1 104 36 ++d9fc 7 286 67 ++da03 1 286 67 ++da11 5c 104 68 ++da6d 1 104 68 ++FUNC da6e 28 0 bool std::operator==, std::allocator >(std::basic_string, std::allocator > const&, char const*) + da6e c 2139 37 + da7a 1c 2140 37 ++FUNC da96 5d 0 std::basic_string, std::allocator > std::operator+, std::allocator >(std::basic_string, std::allocator > const&, char const*) + da96 d 2081 37 + daa3 12 2083 37 + dab5 1a 2084 37 + dacf 24 2085 37 + daf3 1 2085 37 ++FUNC daf4 5d 0 std::basic_string, std::allocator > std::operator+, std::allocator >(std::basic_string, std::allocator > const&, std::basic_string, std::allocator > const&) + daf4 d 2044 37 + db01 12 2046 37 + db13 1a 2047 37 + db2d 24 2048 37 + db51 1 2048 37 +-db52 c 84 37 +-db5e 17 85 37 +-db75 1 85 37 ++db52 c 84 70 ++db5e 17 85 70 ++db75 1 85 70 ++FUNC db76 2d 0 std::pair std::make_pair(char const*, unsigned int) + db76 c 144 37 +-db82 21 145 37 +-dba3 1 145 37 +-dba4 c 84 37 +-dbb0 23 85 37 +-dbd3 1 85 37 ++db82 21 145 70 ++dba3 1 145 70 ++dba4 c 84 70 ++dbb0 23 85 70 ++dbd3 1 85 70 ++FUNC dbd4 3c 0 std::pair > std::make_pair >(unsigned long long, std::pair) + dbd4 1c 144 37 +-dbf0 20 145 37 +-dc10 d 89 37 +-dc1d 64 90 37 +-dc81 1 90 37 +-dc82 c 89 37 +-dc8e 2a 90 37 +-dcb8 c 84 37 +-dcc4 1d 85 37 +-dce1 1 85 37 ++dbf0 20 145 70 ++dc10 d 89 70 ++dc1d 64 90 70 ++dc81 1 90 70 ++dc82 c 89 70 ++dc8e 2a 90 70 ++dcb8 c 84 70 ++dcc4 1d 85 70 ++dce1 1 85 70 ++FUNC dce2 3c 0 std::pair std::make_pair(unsigned long long, dwarf2reader::FunctionInfo*) + dce2 1c 144 37 +-dcfe 20 145 37 +-dd1e c 189 37 +-dd2a a 190 37 +-dd34 c 193 37 +-dd40 d 194 37 +-dd4d 1 194 37 +-dd4e c 603 38 +-dd5a c 603 38 ++dcfe 20 145 70 ++dd2a a 190 34 ++dd40 d 194 34 ++dd4d 1 194 34 ++dd4e c 603 72 ++dd5a c 603 72 ++FUNC dd66 2b 0 std::vector >::begin() const + dd66 c 342 39 +-dd72 1f 343 39 +-dd91 1 343 39 ++dd72 1f 343 71 ++dd91 1 343 71 ++FUNC dd92 2c 0 std::vector >::end() const + dd92 c 360 39 +-dd9e 20 361 39 +-ddbe c 665 39 +-ddca 5 666 39 +-ddcf 1 666 39 +-ddd0 d 758 39 +-dddd 2b 759 39 ++dd9e 20 361 71 ++ddca 5 666 72 ++ddcf 1 666 72 ++dddd 2b 759 72 ++FUNC de08 3c 0 std::vector >::size() const + de08 c 402 39 +-de14 30 403 39 ++de14 30 403 71 ++FUNC de44 2b 0 std::vector >::begin() const + de44 c 342 39 +-de50 1f 343 39 +-de6f 1 343 39 ++de50 1f 343 71 ++de6f 1 343 71 ++FUNC de70 2c 0 std::vector >::end() const + de70 c 360 39 +-de7c 20 361 39 +-de9c d 758 39 +-dea9 31 759 39 ++de7c 20 361 71 ++dea9 31 759 72 ++FUNC deda 3c 0 std::vector >::size() const + deda c 402 39 +-dee6 30 403 39 +-df16 c 603 39 +-df22 c 603 39 ++dee6 30 403 71 ++df16 c 603 72 ++df22 c 603 72 ++FUNC df2e 26 0 std::vector >::end() + df2e c 351 39 +-df3a 1a 352 39 +-df54 c 613 39 +-df60 7 614 39 +-df67 1 614 39 ++df3a 1a 352 71 ++df60 7 614 72 ++df67 1 614 72 ++FUNC df68 13 0 std::vector >::max_size() const + df68 c 407 39 +-df74 7 408 39 +-df7b 1 408 39 +-df7c c 665 39 +-df88 5 666 39 +-df8d 1 666 39 +-df8e c 621 39 +-df9a d 623 39 +-dfa7 5 624 39 ++df74 7 408 71 ++df7b 1 408 71 ++df88 5 666 72 ++df8d 1 666 72 ++df9a d 623 72 ++dfa7 5 624 72 ++FUNC dfac 23 0 std::vector >::begin() + dfac c 333 39 +-dfb8 17 334 39 +-dfcf 1 334 39 +-dfd0 c 35 39 +-dfdc 26 35 39 +-e002 d 103 39 +-e00f 5c 104 39 +-e06b 1 104 39 +-e06c c 613 39 +-e078 7 614 39 +-e07f 1 614 39 +-FUNC e080 35 0 operator= +-e080 c 0 39 +-e08c 29 35 39 +-e0b5 1 35 39 ++dfb8 17 334 71 ++dfcf 1 334 71 ++dfd0 c 35 32 ++dfdc 26 35 32 ++e00f 5c 104 68 ++e06b 1 104 68 ++e078 7 614 72 ++e07f 1 614 72 ++FUNC e080 35 0 dwarf2reader::SourceFileInfo::operator=(dwarf2reader::SourceFileInfo const&) ++e080 c 35 39 ++e08c 29 35 32 ++e0b5 1 35 32 ++FUNC e0b6 13 0 std::vector >::max_size() const + e0b6 c 407 39 +-e0c2 7 408 39 +-e0c9 1 408 39 +-e0ca c 621 39 +-e0d6 d 623 39 +-e0e3 5 624 39 ++e0c2 7 408 71 ++e0c9 1 408 71 ++e0d6 d 623 72 ++e0e3 5 624 72 ++FUNC e0e8 3c 0 std::vector >::_M_range_check(unsigned long) const + e0e8 13 515 39 +-e0fb 15 517 39 +-e110 14 518 39 ++e0fb 15 517 71 ++e110 14 518 71 ++FUNC e124 3c 0 std::vector >::_M_range_check(unsigned long) const + e124 13 515 39 +-e137 15 517 39 +-e14c 14 518 39 +-e160 c 653 39 +-e16c 2a 654 39 ++e137 15 517 71 ++e14c 14 518 71 ++e16c 2a 654 72 ++FUNC e196 42 0 std::vector >::operator[](unsigned long) + e196 c 494 39 +-e1a2 36 495 39 ++e1a2 36 495 71 ++FUNC e1d8 32 0 std::vector >::at(unsigned long) + e1d8 c 534 39 +-e1e4 12 536 39 +-e1f6 14 537 39 +-e20a c 653 39 +-e216 32 654 39 ++e1e4 12 536 71 ++e1f6 14 537 71 ++e216 32 654 72 ++FUNC e248 42 0 std::vector >::operator[](unsigned long) + e248 c 494 39 +-e254 36 495 39 ++e254 36 495 71 ++FUNC e28a 32 0 std::vector >::at(unsigned long) + e28a c 534 39 +-e296 12 536 39 +-e2a8 14 537 39 ++e296 12 536 71 ++e2a8 14 537 71 ++FUNC e2bc 14 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_end() + e2bc c 472 40 + e2c8 8 473 40 ++FUNC e2d0 11 0 std::_Select1st > >::operator()(std::pair > const&) const + e2d0 c 550 41 + e2dc 5 551 41 + e2e1 1 551 41 ++FUNC e2e2 53 0 std::less::operator()(unsigned long long const&, unsigned long long const&) const + e2e2 c 226 41 + e2ee 47 227 41 + e335 1 227 41 ++FUNC e336 20 0 std::_Rb_tree_iterator > >::operator==(std::_Rb_tree_iterator > > const&) const + e336 c 209 41 +-e342 14 210 41 +-e356 c 84 41 +-e362 18 85 41 ++e342 14 210 40 ++e356 c 84 70 ++e362 18 85 70 ++FUNC e37a 14 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_end() + e37a c 472 41 +-e386 8 473 41 ++e386 8 473 40 ++FUNC e38e 11 0 std::_Select1st >::operator()(std::pair const&) const + e38e c 550 41 + e39a 5 551 41 + e39f 1 551 41 ++FUNC e3a0 20 0 std::_Rb_tree_iterator >::operator==(std::_Rb_tree_iterator > const&) const + e3a0 c 209 41 +-e3ac 14 210 41 +-e3c0 c 84 41 +-e3cc 18 85 41 +-e3e4 c 180 41 +-e3f0 13 181 41 +-e403 1 181 41 +-e404 c 408 41 +-e410 22 409 41 +-e432 c 206 42 ++e3ac 14 210 40 ++e3c0 c 84 70 ++e3cc 18 85 70 ++e3e4 c 180 34 ++e3f0 13 181 34 ++e403 1 181 34 ++e410 22 409 34 + e43e d 207 42 + e44b 1 207 42 ++FUNC e44c 35 0 bool __gnu_cxx::operator!= > >(__gnu_cxx::__normal_iterator > > const&, __gnu_cxx::__normal_iterator > > const&) + e44c d 699 42 +-e459 28 700 42 +-e481 1 700 42 ++e459 28 700 72 ++e481 1 700 72 ++FUNC e482 4b 0 void std::_Destroy<__gnu_cxx::__normal_iterator > >, std::allocator >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, std::allocator) + e482 c 171 43 +-e48e 2 173 43 +-e490 1a 174 43 +-e4aa 21 173 43 +-e4cb 2 174 43 +-e4cd 1 174 43 ++e48e 2 173 73 ++e490 1a 174 73 ++e4aa 21 173 73 ++e4cb 2 174 73 ++e4cd 1 174 73 ++FUNC e4ce 35 0 bool __gnu_cxx::operator!= > >(__gnu_cxx::__normal_iterator > > const&, __gnu_cxx::__normal_iterator > > const&) + e4ce d 699 43 +-e4db 28 700 43 +-e503 1 700 43 ++e4db 28 700 72 ++e503 1 700 72 ++FUNC e504 4b 0 void std::_Destroy<__gnu_cxx::__normal_iterator > >, std::allocator >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, std::allocator) + e504 c 171 43 +-e510 2 173 43 +-e512 1a 174 43 +-e52c 21 173 43 +-e54d 2 174 43 +-e54f 1 174 43 ++e510 2 173 73 ++e512 1a 174 73 ++e52c 21 173 73 ++e54d 2 174 73 ++e54f 1 174 73 ++FUNC e550 14 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_S_value(std::_Rb_tree_node > > const*) + e550 c 480 43 +-e55c 8 481 43 ++e55c 8 481 40 ++FUNC e564 28 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_S_key(std::_Rb_tree_node > > const*) + e564 c 484 43 +-e570 1c 485 43 ++e570 1c 485 40 ++FUNC e58c 25 0 std::_Rb_tree_iterator >::operator--() + e58c c 194 43 +-e598 14 196 43 +-e5ac 5 197 43 +-e5b1 1 197 43 ++e598 14 196 40 ++e5ac 5 197 40 ++e5b1 1 197 40 ++FUNC e5b2 25 0 std::_Rb_tree_iterator > >::operator--() + e5b2 c 194 43 +-e5be 14 196 43 +-e5d2 5 197 43 +-e5d7 1 197 43 ++e5be 14 196 40 ++e5d2 5 197 40 ++e5d7 1 197 40 ++FUNC e5d8 14 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_S_value(std::_Rb_tree_node_base const*) + e5d8 c 504 43 +-e5e4 8 505 43 ++e5e4 8 505 40 ++FUNC e5ec 28 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_S_key(std::_Rb_tree_node_base const*) + e5ec c 508 43 +-e5f8 1c 509 43 ++e5f8 1c 509 40 ++FUNC e614 14 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_S_value(std::_Rb_tree_node > const*) + e614 c 480 43 +-e620 8 481 43 ++e620 8 481 40 ++FUNC e628 28 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_S_key(std::_Rb_tree_node > const*) + e628 c 484 43 +-e634 1c 485 43 ++e634 1c 485 40 ++FUNC e650 14 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_S_value(std::_Rb_tree_node_base const*) + e650 c 504 43 +-e65c 8 505 43 ++e65c 8 505 40 ++FUNC e664 28 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_S_key(std::_Rb_tree_node_base const*) + e664 c 508 43 +-e670 1c 509 43 +-e68c c 613 43 +-e698 7 614 43 +-e69f 1 614 43 +-e6a0 c 97 43 +-e6ac 7 98 43 +-e6b3 1 98 43 +-e6b4 c 83 43 +-e6c0 1d 85 43 +-e6dd 5 86 43 +-e6e2 10 88 43 ++e670 1c 509 40 ++e698 7 614 72 ++e69f 1 614 72 ++e6ac 7 98 68 ++e6b3 1 98 68 ++e6c0 1d 85 68 ++e6dd 5 86 68 ++e6e2 10 88 68 ++FUNC e6f2 2a 0 std::_Vector_base >::_M_allocate(unsigned long) + e6f2 c 116 43 +-e6fe 1e 117 43 +-e71c c 97 43 +-e728 7 98 43 +-e72f 1 98 43 +-e730 c 83 43 +-e73c 1d 85 43 +-e759 5 86 43 +-e75e 16 88 43 ++e6fe 1e 117 71 ++e728 7 98 68 ++e72f 1 98 68 ++e73c 1d 85 68 ++e759 5 86 68 ++e75e 16 88 68 ++FUNC e774 2a 0 std::_Vector_base >::_M_allocate(unsigned long) + e774 c 116 43 +-e780 1e 117 43 +-e79e c 103 43 +-e7aa 3a 104 43 +-e7e4 c 653 43 +-e7f0 2a 654 43 ++e780 1e 117 71 ++e7aa 3a 104 68 ++e7f0 2a 654 72 ++FUNC e81a 42 0 std::vector<__gnu_cxx::_Hashtable_node > >*, std::allocator<__gnu_cxx::_Hashtable_node > >*> >::operator[](unsigned long) const + e81a c 509 43 +-e826 36 510 43 +-FUNC e85c 4e 0 copy_b +-e85c c 408 44 +-e868 14 411 44 +-e87c 1e 412 44 +-e89a b 411 44 +-e8a5 5 413 44 ++e826 36 510 71 ++FUNC e85c 4e 0 std::string* std::__copy_backward::copy_b(std::string*, std::string*, std::string*) ++e85c c 408 61 ++e868 14 411 61 ++e87c 1e 412 61 ++e89a b 411 61 ++e8a5 5 413 61 ++FUNC e8aa 2b 0 std::string* std::__copy_backward_aux(std::string*, std::string*, std::string*) + e8aa c 432 44 +-e8b6 4 440 44 +-e8ba 1b 443 44 +-e8d5 1 443 44 +-FUNC e8d6 64 0 copy_b_n<__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > > > +-e8d6 e 480 44 +-e8e4 56 482 44 +-e93a c 504 44 +-e946 4 514 44 +-e94a 4 515 44 +-e94e 1b 517 44 +-e969 1 517 44 ++e8b6 4 440 61 ++e8ba 1b 443 61 ++e8d5 1 443 61 ++e8e4 56 482 61 ++e946 4 514 61 ++e94a 4 515 61 ++e94e 1b 517 61 ++e969 1 517 61 ++FUNC e96a 69 0 void std::_Construct(std::string*, std::string const&) + e96a d 77 44 +-e977 5c 81 44 +-e9d3 1 81 44 +-FUNC e9d4 54 0 copy_b +-e9d4 c 408 44 +-e9e0 1a 411 44 +-e9fa 1e 412 44 +-ea18 b 411 44 +-ea23 5 413 44 ++e977 5c 81 73 ++e9d3 1 81 73 ++FUNC e9d4 54 0 dwarf2reader::SourceFileInfo* std::__copy_backward::copy_b(dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo*) ++e9d4 c 408 61 ++e9e0 1a 411 61 ++e9fa 1e 412 61 ++ea18 b 411 61 ++ea23 5 413 61 ++FUNC ea28 2b 0 dwarf2reader::SourceFileInfo* std::__copy_backward_aux(dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo*) + ea28 c 432 44 +-ea34 4 440 44 +-ea38 1b 443 44 +-ea53 1 443 44 +-FUNC ea54 64 0 copy_b_n<__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > > > +-ea54 e 480 44 +-ea62 56 482 44 +-eab8 c 504 44 +-eac4 4 514 44 +-eac8 4 515 44 +-eacc 1b 517 44 +-eae7 1 517 44 ++ea34 4 440 61 ++ea38 1b 443 61 ++ea53 1 443 61 ++ea62 56 482 61 ++eac4 4 514 61 ++eac8 4 515 61 ++eacc 1b 517 61 ++eae7 1 517 61 ++FUNC eae8 69 0 void std::_Construct(dwarf2reader::SourceFileInfo*, dwarf2reader::SourceFileInfo const&) + eae8 d 77 44 +-eaf5 5c 81 44 +-eb51 1 81 44 +-eb52 c 69 44 +-eb5e 20 69 44 +-eb7e c 69 44 +-eb8a 2a 69 44 +-ebb4 d 103 44 +-ebc1 5c 104 44 +-ec1d 1 104 44 +-ec1e c 521 44 +-ec2a 15 523 44 +-ec3f 79 525 44 +-ecb8 21 529 44 +-ecd9 1 529 44 +-ecda c 228 44 +-ece6 14 229 44 +-ecfa c 97 44 +-ed06 7 98 44 +-ed0d 1 98 44 +-ed0e c 83 44 +-ed1a 1d 85 44 +-ed37 5 86 44 +-ed3c 10 88 44 ++eaf5 5c 81 73 ++eb51 1 81 73 ++eb52 c 69 70 ++eb5e 20 69 70 ++eb7e c 69 70 ++eb8a 2a 69 70 ++ebc1 5c 104 68 ++ec1d 1 104 68 ++ec2a 15 523 34 ++ec3f 79 525 34 ++ecb8 21 529 34 ++ecd9 1 529 34 ++ece6 14 229 42 ++ed06 7 98 68 ++ed0d 1 98 68 ++ed1a 1d 85 68 ++ed37 5 86 68 ++ed3c 10 88 68 ++FUNC ed4c 29 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_get_node() + ed4c c 355 44 +-ed58 1d 356 44 +-ed75 1 356 44 ++ed58 1d 356 40 ++ed75 1 356 40 ++FUNC ed76 b6 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_create_node(std::pair > const&) + ed76 d 363 44 +-ed83 e 365 44 +-ed91 3c 367 44 +-edcd b 373 44 +-edd8 11 367 44 +-ede9 b 368 44 +-edf4 12 370 44 +-ee06 b 371 44 +-ee11 13 368 44 +-ee24 8 373 44 ++ed83 e 365 40 ++ed91 3c 367 40 ++edcd b 373 40 ++edd8 11 367 40 ++ede9 b 368 40 ++edf4 12 370 40 ++ee06 b 371 40 ++ee11 13 368 40 ++ee24 8 373 40 ++FUNC ee2c cd 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::_M_insert(std::_Rb_tree_node_base*, std::_Rb_tree_node_base*, std::pair > const&) + ee2c d 787 44 +-ee39 15 789 44 +-ee4e 5d 792 44 +-eeab 24 796 44 +-eecf f 798 44 +-eede 1b 799 44 +-eef9 1 799 44 ++ee39 15 789 40 ++ee4e 5d 792 40 ++eeab 24 796 40 ++eecf f 798 40 ++eede 1b 799 40 ++eef9 1 799 40 ++FUNC eefa 1ef 0 std::_Rb_tree >, std::_Select1st > >, std::less, std::allocator > > >::insert_unique(std::pair > const&) + eefa d 869 44 +-ef07 e 871 44 +-ef15 e 872 44 +-ef23 4 873 44 +-ef27 2 874 44 +-ef29 6 876 44 +-ef2f 35 877 44 +-ef64 2a 878 44 +-ef8e 6 874 44 +-ef94 12 880 44 +-efa6 a 881 44 +-efb0 24 882 44 +-efd4 51 883 44 +-f025 b 885 44 +-f030 36 886 44 +-f066 4e 887 44 +-f0b4 35 888 44 +-f0e9 1 888 44 ++ef07 e 871 40 ++ef15 e 872 40 ++ef23 4 873 40 ++ef27 2 874 40 ++ef29 6 876 40 ++ef2f 35 877 40 ++ef64 2a 878 40 ++ef8e 6 874 40 ++ef94 12 880 40 ++efa6 a 881 40 ++efb0 24 882 40 ++efd4 51 883 40 ++f025 b 885 40 ++f030 36 886 40 ++f066 4e 887 40 ++f0b4 35 888 40 ++f0e9 1 888 40 ++FUNC f0ea 20 0 std::map, std::less, std::allocator > > >::insert(std::pair > const&) + f0ea c 359 45 + f0f6 14 360 45 +-f10a c 97 45 +-f116 7 98 45 +-f11d 1 98 45 +-f11e c 83 45 +-f12a 1d 85 45 +-f147 5 86 45 +-f14c 1d 88 45 +-f169 1 88 45 ++f116 7 98 68 ++f11d 1 98 68 ++f12a 1d 85 68 ++f147 5 86 68 ++f14c 1d 88 68 ++f169 1 88 68 ++FUNC f16a 29 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_get_node() + f16a c 355 45 +-f176 1d 356 45 +-f193 1 356 45 ++f176 1d 356 40 ++f193 1 356 40 ++FUNC f194 5f 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_create_node(std::pair const&) + f194 d 363 45 +-f1a1 e 365 45 +-f1af 3c 367 45 +-f1eb 8 373 45 +-f1f3 1 373 45 ++f1a1 e 365 40 ++f1af 3c 367 40 ++f1eb 8 373 40 ++f1f3 1 373 40 ++FUNC f1f4 cd 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::_M_insert(std::_Rb_tree_node_base*, std::_Rb_tree_node_base*, std::pair const&) + f1f4 d 787 45 +-f201 15 789 45 +-f216 5d 792 45 +-f273 24 796 45 +-f297 f 798 45 +-f2a6 1b 799 45 +-f2c1 1 799 45 ++f201 15 789 40 ++f216 5d 792 40 ++f273 24 796 40 ++f297 f 798 40 ++f2a6 1b 799 40 ++f2c1 1 799 40 ++FUNC f2c2 1ef 0 std::_Rb_tree, std::_Select1st >, std::less, std::allocator > >::insert_unique(std::pair const&) + f2c2 d 869 45 +-f2cf e 871 45 +-f2dd e 872 45 +-f2eb 4 873 45 +-f2ef 2 874 45 +-f2f1 6 876 45 +-f2f7 35 877 45 +-f32c 2a 878 45 +-f356 6 874 45 +-f35c 12 880 45 +-f36e a 881 45 +-f378 24 882 45 +-f39c 51 883 45 +-f3ed b 885 45 +-f3f8 36 886 45 +-f42e 4e 887 45 +-f47c 35 888 45 +-f4b1 1 888 45 ++f2cf e 871 40 ++f2dd e 872 40 ++f2eb 4 873 40 ++f2ef 2 874 40 ++f2f1 6 876 40 ++f2f7 35 877 40 ++f32c 2a 878 40 ++f356 6 874 40 ++f35c 12 880 40 ++f36e a 881 40 ++f378 24 882 40 ++f39c 51 883 40 ++f3ed b 885 40 ++f3f8 36 886 40 ++f42e 4e 887 40 ++f47c 35 888 40 ++f4b1 1 888 40 ++FUNC f4b2 20 0 std::map, std::allocator > >::insert(std::pair const&) + f4b2 c 359 45 + f4be 14 360 45 ++FUNC f4d2 19 0 void std::_Destroy(std::string*) + f4d2 c 106 45 +-f4de d 107 45 +-f4eb 1 107 45 ++f4de d 107 73 ++f4eb 1 107 73 ++FUNC f4ec 44 0 void std::__destroy_aux<__gnu_cxx::__normal_iterator > > >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, __false_type) + f4ec c 119 45 +-f4f8 2 121 45 +-f4fa 13 122 45 +-f50d 21 121 45 +-f52e 2 122 45 ++f4f8 2 121 73 ++f4fa 13 122 73 ++f50d 21 121 73 ++f52e 2 122 73 ++FUNC f530 28 0 void std::_Destroy<__gnu_cxx::__normal_iterator > > >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >) + f530 c 148 45 +-f53c 1c 155 45 +-f558 d 80 46 +-f565 6 82 46 +-f56b 2 85 46 +-f56d 24 86 46 +-f591 2c 85 46 +-f5bd b 87 46 +-f5c8 b 89 46 +-f5d3 12 91 46 +-f5e5 b 92 46 +-f5f0 13 89 46 +-f603 9 92 46 +-f60c c 108 46 +-f618 23 113 46 +-f63b 1 113 46 +-f63c c 252 46 +-f648 1b 254 46 +-f663 1 254 46 ++f53c 1c 155 73 ++f565 6 82 79 ++f56b 2 85 79 ++f56d 24 86 79 ++f591 2c 85 79 ++f5bd b 87 79 ++f5c8 b 89 79 ++f5d3 12 91 79 ++f5e5 b 92 79 ++f5f0 13 89 79 ++f603 9 92 79 ++f618 23 113 79 ++f63b 1 113 79 ++f648 1b 254 79 ++f663 1 254 79 ++FUNC f664 430 0 std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, std::string const&) + f664 14 249 47 +-f678 14 251 47 +-f68c 22 253 47 +-f6ae f 255 47 +-f6bd 12 256 47 +-f6cf 55 257 47 +-f724 4b 260 47 +-f76f e 264 47 +-f77d 15 265 47 +-f792 e 266 47 +-f7a0 1d 271 47 +-f7bd 8 272 47 +-f7c5 e 273 47 +-f7d3 27 275 47 +-f7fa 6 276 47 +-f800 55 279 47 +-f855 25 284 47 +-f87a b 285 47 +-f885 4f 286 47 +-f8d4 3 284 47 +-f8d7 13 279 47 +-f8ea e 286 47 +-f8f8 4d 298 47 +-f945 30 299 47 +-f975 12 302 47 +-f987 13 303 47 +-f99a 23 304 47 +-f9bd 3 298 47 +-f9c0 13 286 47 +-f9d3 b 292 47 +-f9de 39 294 47 +-fa17 23 295 47 +-fa3a 8 296 47 +-fa42 16 294 47 +-fa58 3 296 47 +-fa5b 19 292 47 +-fa74 19 298 47 +-fa8d 7 304 47 ++f678 14 251 78 ++f68c 22 253 78 ++f6ae f 255 78 ++f6bd 12 256 78 ++f6cf 55 257 78 ++f724 4b 260 78 ++f76f e 264 78 ++f77d 15 265 78 ++f792 e 266 78 ++f7a0 1d 271 78 ++f7bd 8 272 78 ++f7c5 e 273 78 ++f7d3 27 275 78 ++f7fa 6 276 78 ++f800 55 279 78 ++f855 25 284 78 ++f87a b 285 78 ++f885 4f 286 78 ++f8d4 3 284 78 ++f8d7 13 279 78 ++f8ea e 286 78 ++f8f8 4d 298 78 ++f945 30 299 78 ++f975 12 302 78 ++f987 13 303 78 ++f99a 23 304 78 ++f9bd 3 298 78 ++f9c0 13 286 78 ++f9d3 b 292 78 ++f9de 39 294 78 ++fa17 23 295 78 ++fa3a 8 296 78 ++fa42 16 294 78 ++fa58 3 296 78 ++fa5b 19 292 78 ++fa74 19 298 78 ++fa8d 7 304 78 ++FUNC fa94 70 0 std::vector >::push_back(std::string const&) + fa94 c 602 47 +-faa0 10 604 47 +-fab0 1e 606 47 +-face 11 607 47 +-fadf 25 610 47 ++faa0 10 604 71 ++fab0 1e 606 71 ++face 11 607 71 ++fadf 25 610 71 ++FUNC fb04 19 0 void std::_Destroy(dwarf2reader::SourceFileInfo*) + fb04 c 106 47 +-fb10 d 107 47 +-fb1d 1 107 47 ++fb10 d 107 73 ++fb1d 1 107 73 ++FUNC fb1e 44 0 void std::__destroy_aux<__gnu_cxx::__normal_iterator > > >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, __false_type) + fb1e c 119 47 +-fb2a 2 121 47 +-fb2c 13 122 47 +-fb3f 21 121 47 +-fb60 2 122 47 ++fb2a 2 121 73 ++fb2c 13 122 73 ++fb3f 21 121 73 ++fb60 2 122 73 ++FUNC fb62 28 0 void std::_Destroy<__gnu_cxx::__normal_iterator > > >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >) + fb62 c 148 47 +-fb6e 1c 155 47 +-fb8a d 80 47 +-fb97 6 82 47 +-fb9d 2 85 47 +-fb9f 24 86 47 +-fbc3 2c 85 47 +-fbef b 87 47 +-fbfa b 89 47 +-fc05 12 91 47 +-fc17 b 92 47 +-fc22 13 89 47 +-fc35 9 92 47 +-fc3e c 108 47 +-fc4a 23 113 47 +-fc6d 1 113 47 +-fc6e c 252 47 +-fc7a 1b 254 47 +-fc95 1 254 47 ++fb6e 1c 155 73 ++fb97 6 82 79 ++fb9d 2 85 79 ++fb9f 24 86 79 ++fbc3 2c 85 79 ++fbef b 87 79 ++fbfa b 89 79 ++fc05 12 91 79 ++fc17 b 92 79 ++fc22 13 89 79 ++fc35 9 92 79 ++fc4a 23 113 79 ++fc6d 1 113 79 ++fc7a 1b 254 79 ++fc95 1 254 79 ++FUNC fc96 43d 0 std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, dwarf2reader::SourceFileInfo const&) + fc96 14 249 47 +-fcaa 14 251 47 +-fcbe 22 253 47 +-fce0 f 255 47 +-fcef 12 256 47 +-fd01 55 257 47 +-fd56 4b 260 47 +-fda1 e 264 47 +-fdaf 15 265 47 +-fdc4 e 266 47 +-fdd2 1d 271 47 +-fdef 8 272 47 +-fdf7 e 273 47 +-fe05 27 275 47 +-fe2c 6 276 47 +-fe32 55 279 47 +-fe87 25 284 47 +-feac b 285 47 +-feb7 4f 286 47 +-ff06 3 284 47 +-ff09 13 279 47 +-ff1c e 286 47 +-ff2a 4d 298 47 +-ff77 36 299 47 +-ffad 12 302 47 +-ffbf 13 303 47 +-ffd2 2a 304 47 +-fffc 3 298 47 +-ffff 13 286 47 +-10012 b 292 47 +-1001d 39 294 47 +-10056 23 295 47 +-10079 8 296 47 +-10081 16 294 47 +-10097 3 296 47 +-1009a 19 292 47 +-100b3 19 298 47 +-100cc 7 304 47 +-100d3 1 304 47 ++fcaa 14 251 78 ++fcbe 22 253 78 ++fce0 f 255 78 ++fcef 12 256 78 ++fd01 55 257 78 ++fd56 4b 260 78 ++fda1 e 264 78 ++fdaf 15 265 78 ++fdc4 e 266 78 ++fdd2 1d 271 78 ++fdef 8 272 78 ++fdf7 e 273 78 ++fe05 27 275 78 ++fe2c 6 276 78 ++fe32 55 279 78 ++fe87 25 284 78 ++feac b 285 78 ++feb7 4f 286 78 ++ff06 3 284 78 ++ff09 13 279 78 ++ff1c e 286 78 ++ff2a 4d 298 78 ++ff77 36 299 78 ++ffad 12 302 78 ++ffbf 13 303 78 ++ffd2 2a 304 78 ++fffc 3 298 78 ++ffff 13 286 78 ++10012 b 292 78 ++1001d 39 294 78 ++10056 23 295 78 ++10079 8 296 78 ++10081 16 294 78 ++10097 3 296 78 ++1009a 19 292 78 ++100b3 19 298 78 ++100cc 7 304 78 ++100d3 1 304 78 ++FUNC 100d4 70 0 std::vector >::push_back(dwarf2reader::SourceFileInfo const&) + 100d4 c 602 47 +-100e0 10 604 47 +-100f0 1e 606 47 +-1010e 11 607 47 +-1011f 25 610 47 ++100e0 10 604 71 ++100f0 1e 606 71 ++1010e 11 607 71 ++1011f 25 610 71 + FUNC 10144 16c 0 Start +-10144 17 610 48 ++10144 17 610 71 + 1015b 40 49 48 + 1019b 6 51 48 + 101a1 3f 53 48 + 101e0 7 54 48 + 101e7 5 55 48 + 101ec 2a 58 48 + 10216 61 61 48 + 10277 7 62 48 +@@ -3049,56 +3046,59 @@ 107fd c 141 48 + 10809 6 142 48 + 1080f 1 142 48 + 10810 c 47 49 + 1081c 1a 48 49 + 10836 2 49 49 + 10838 c 47 49 + 10844 1a 48 49 + 1085e 2 49 49 ++FUNC 10860 cb 0 google_breakpad::FileID::FileIdentifier(unsigned char*) + 10860 f 51 49 + 1086f 16 52 49 + 10885 6 53 49 + 1088b f 54 49 + 1089a b 57 49 + 108a5 7 62 49 + 108ac 2 63 49 + 108ae 1c 64 49 + 108ca 32 63 49 + 108fc b 67 49 + 10907 12 68 49 + 10919 10 70 49 + 10929 2 71 49 + 1092b 1 71 49 ++FUNC 1092c f2 0 google_breakpad::FileID::MachoIdentifier(int, unsigned char*) + 1092c 10 73 49 + 1093c 15 74 49 + 10951 20 76 49 + 10971 f 77 49 + 10980 20 79 49 + 109a0 c 80 49 + 109ac 69 82 49 + 10a15 9 83 49 ++FUNC 10a1e fb 0 google_breakpad::FileID::ConvertIdentifierToString(unsigned char const*, char*, int) + 10a1e c 87 49 + 10a2a 7 88 49 + 10a31 c 89 49 + 10a3d 15 90 49 + 10a52 12 91 49 + 10a64 18 93 49 + 10a7c e 94 49 + 10a8a 2b 96 49 + 10ab5 2b 97 49 + 10ae0 17 89 49 + 10af7 20 101 49 + 10b17 2 102 49 + 10b19 1 102 49 + FUNC 10b1a 13 0 NXHostByteOrder +-10b1a c 144 50 +-10b26 5 147 50 +-10b2b 2 153 50 +-10b2d 1 153 50 ++10b1a c 144 56 ++10b26 5 147 56 ++10b2b 2 153 56 ++10b2d 1 153 56 + 10b2e c 56 51 + 10b3a 1a 57 51 + 10b54 1e 58 51 + 10b72 2 59 51 + 10b74 c 56 51 + 10b80 1a 57 51 + 10b9a 1e 58 51 + 10bb8 2 59 51 +@@ -3107,16 +3107,17 @@ 10bc6 e 62 51 + 10bd4 11 63 51 + 10be5 2 64 51 + 10be7 1 64 51 + 10be8 c 61 51 + 10bf4 e 62 51 + 10c02 11 63 51 + 10c13 2 64 51 + 10c15 1 64 51 ++FUNC 10c16 477 0 MacFileUtilities::MachoID::UpdateCRC(unsigned char*, unsigned long) + 10c16 c 74 51 + 10c22 11 82 51 + 10c33 14 83 51 + 10c47 5 86 51 + 10c4c 9 87 51 + 10c55 7 88 51 + 10c5c 18b 90 51 + 10de7 6 91 51 +@@ -3132,48 +3133,53 @@ 10ffa c 99 51 + 11006 13 105 51 + 11019 8 106 51 + 11021 10 104 51 + 11031 23 108 51 + 11054 23 109 51 + 11077 14 110 51 + 1108b 2 112 51 + 1108d 1 112 51 ++FUNC 1108e 2c 0 MacFileUtilities::MachoID::UpdateMD5(unsigned char*, unsigned long) + 1108e c 114 51 + 1109a 1e 115 51 + 110b8 2 116 51 ++FUNC 110ba 2c 0 MacFileUtilities::MachoID::UpdateSHA1(unsigned char*, unsigned long) + 110ba c 118 51 + 110c6 1e 119 51 + 110e4 2 120 51 ++FUNC 110e6 121 0 MacFileUtilities::MachoID::Update(MacFileUtilities::MachoWalker*, unsigned long, unsigned long) + 110e6 f 122 51 + 110f5 1b 123 51 + 11110 e 129 51 + 1111e 5 130 51 + 11123 9 131 51 + 1112c 7 132 51 + 11133 a 133 51 + 1113d 6 135 51 + 11143 7 136 51 + 1114a 35 139 51 + 1117f 6c 142 51 + 111eb 10 143 51 + 111fb a 130 51 + 11205 2 145 51 + 11207 1 145 51 ++FUNC 11208 cf 0 MacFileUtilities::MachoID::UUIDCommand(int, unsigned char*) + 11208 14 147 51 + 1121c 25 149 51 + 11241 7 151 51 + 11248 19 152 51 + 11261 9 153 51 + 1126a 8 157 51 + 11272 1f 158 51 + 11291 9 159 51 + 1129a 36 162 51 + 112d0 7 163 51 + 112d7 1 163 51 ++FUNC 112d8 224 0 MacFileUtilities::MachoID::IDCommand(int, unsigned char*) + 112d8 15 165 51 + 112ed 25 167 51 + 11312 7 169 51 + 11319 19 170 51 + 11332 c 171 51 + 1133e c 175 51 + 1134a 6 180 51 + 11350 7 181 51 +@@ -3192,45 +3198,49 @@ 1143f 10 195 51 + 1144f d 196 51 + 1145c 17 197 51 + 11473 17 198 51 + 1148a 17 199 51 + 114a1 14 200 51 + 114b5 9 202 51 + 114be 36 205 51 + 114f4 8 206 51 ++FUNC 114fc d1 0 MacFileUtilities::MachoID::Adler32(int) + 114fc 14 208 51 + 11510 25 209 51 + 11535 27 210 51 + 1155c d 211 51 + 11569 19 213 51 + 11582 9 214 51 + 1158b 3b 216 51 + 115c6 7 217 51 + 115cd 1 217 51 ++FUNC 115ce f8 0 MacFileUtilities::MachoID::MD5(int, unsigned char*) + 115ce 14 219 51 + 115e2 25 220 51 + 11607 27 221 51 + 1162e 19 223 51 + 11647 19 224 51 + 11660 9 225 51 + 11669 17 227 51 + 11680 9 228 51 + 11689 36 231 51 + 116bf 7 232 51 ++FUNC 116c6 f8 0 MacFileUtilities::MachoID::SHA1(int, unsigned char*) + 116c6 14 234 51 + 116da 25 235 51 + 116ff 27 236 51 + 11726 19 238 51 + 1173f 19 239 51 + 11758 9 240 51 + 11761 17 242 51 + 11778 9 243 51 + 11781 36 246 51 + 117b7 7 247 51 ++FUNC 117be 378 0 MacFileUtilities::MachoID::WalkerCB(MacFileUtilities::MachoWalker*, load_command*, long long, bool, void*) + 117be 2b 251 51 + 117e9 6 252 51 + 117ef e 254 51 + 117fd 38 257 51 + 11835 f 258 51 + 11844 9 260 51 + 1184d 17 261 51 + 11864 20 266 51 +@@ -3259,53 +3269,55 @@ 11a75 f 308 51 + 11a84 9 310 51 + 11a8d 1f 311 51 + 11aac 1a 315 51 + 11ac6 39 316 51 + 11aff d 318 51 + 11b0c 11 306 51 + 11b1d 10 323 51 + 11b2d 9 324 51 ++FUNC 11b36 95 0 MacFileUtilities::MachoID::UUIDWalkerCB(MacFileUtilities::MachoWalker*, load_command*, long long, bool, void*) + 11b36 1e 328 51 + 11b54 a 329 51 + 11b5e 6 331 51 + 11b64 2f 333 51 + 11b93 9 335 51 + 11b9c 6 337 51 + 11ba2 14 338 51 + 11bb6 9 340 51 + 11bbf a 344 51 + 11bc9 2 345 51 + 11bcb 1 345 51 ++FUNC 11bcc 95 0 MacFileUtilities::MachoID::IDWalkerCB(MacFileUtilities::MachoWalker*, load_command*, long long, bool, void*) + 11bcc 1e 349 51 + 11bea a 350 51 + 11bf4 6 351 51 + 11bfa 2f 353 51 + 11c29 9 354 51 + 11c32 6 356 51 + 11c38 14 357 51 + 11c4c 9 359 51 + 11c55 a 363 51 + 11c5f 2 364 51 + 11c61 1 364 51 + FUNC 11c62 1c 0 _OSSwapInt32 +-11c62 f 53 52 +-11c71 8 55 52 +-11c79 3 56 52 +-11c7c 2 57 52 ++11c62 f 53 55 ++11c71 8 55 55 ++11c79 3 56 55 ++11c7c 2 57 55 + FUNC 11c7e 19 0 NXSwapInt +-11c7e f 52 53 +-11c8d 8 54 53 +-11c95 2 55 53 +-11c97 1 55 53 ++11c7e f 52 56 ++11c8d 8 54 56 ++11c95 2 55 56 ++11c97 1 55 56 + FUNC 11c98 13 0 NXHostByteOrder +-11c98 c 144 53 +-11ca4 5 147 53 +-11ca9 2 153 53 +-11cab 1 153 53 ++11c98 c 144 56 ++11ca4 5 147 56 ++11ca9 2 153 56 ++11cab 1 153 56 + 11cac c 52 54 + 11cb8 12 54 54 + 11cca 1a 55 54 + 11ce4 2 56 54 + 11ce6 c 52 54 + 11cf2 12 54 54 + 11d04 1a 55 54 + 11d1e 2 56 54 +@@ -3314,36 +3326,40 @@ 11d2c a 59 54 + 11d36 d 60 54 + 11d43 2 61 54 + 11d45 1 61 54 + 11d46 c 58 54 + 11d52 a 59 54 + 11d5c d 60 54 + 11d69 2 61 54 + 11d6b 1 61 54 ++FUNC 11d6c 37 0 MacFileUtilities::MachoWalker::ValidateCPUType(int) + 11d6c c 63 54 + 11d78 6 66 54 + 11d7e 8 67 54 + 11d86 6 68 54 + 11d8c b 69 54 + 11d97 7 74 54 + 11d9e 3 80 54 + 11da1 2 81 54 + 11da3 1 81 54 ++FUNC 11da4 50 0 MacFileUtilities::MachoWalker::ReadBytes(void*, unsigned long, long long) + 11da4 18 96 54 + 11dbc 36 97 54 + 11df2 2 98 54 ++FUNC 11df4 73 0 MacFileUtilities::MachoWalker::CurrentHeader(mach_header_64*, long long*) + 11df4 c 100 54 + 11e00 a 101 54 + 11e0a 37 102 54 + 11e41 11 103 54 + 11e52 9 104 54 + 11e5b a 107 54 + 11e65 2 108 54 + 11e67 1 108 54 ++FUNC 11e68 2a6 0 MacFileUtilities::MachoWalker::FindHeader(int, long long&) + 11e68 c 110 54 + 11e74 15 111 54 + 11e89 31 114 54 + 11eba c 115 54 + 11ec6 10 117 54 + 11ed6 4 120 54 + 11eda 14 121 54 + 11eee 4 122 54 +@@ -3371,44 +3387,47 @@ 1208f f 162 54 + 1209e 1c 163 54 + 120ba 8 165 54 + 120c2 10 166 54 + 120d2 9 167 54 + 120db 16 170 54 + 120f1 11 158 54 + 12102 a 174 54 + 1210c 2 175 54 ++FUNC 1210e 109 0 MacFileUtilities::MachoWalker::WalkHeaderCore(long long, unsigned int, bool) + 1210e 1e 224 54 + 1212c c 225 54 + 12138 2f 227 54 + 12167 c 228 54 + 12173 6 230 54 + 12179 14 231 54 + 1218d 5b 234 54 + 121e8 12 237 54 + 121fa 11 225 54 + 1220b a 240 54 + 12215 2 241 54 + 12217 1 241 54 ++FUNC 12218 10e 0 MacFileUtilities::MachoWalker::WalkHeader64AtOffset(long long) + 12218 18 203 54 + 12230 2f 205 54 + 1225f c 206 54 + 1226b e 208 54 + 12279 6 209 54 + 1227f 14 210 54 + 12293 9 212 54 + 1229c a 213 54 + 122a6 f 214 54 + 122b5 15 215 54 + 122ca 2b 216 54 + 122f5 a 217 54 + 122ff a 218 54 + 12309 11 219 54 + 1231a a 220 54 + 12324 2 221 54 ++FUNC 12326 143 0 MacFileUtilities::MachoWalker::WalkHeaderAtOffset(long long) + 12326 18 177 54 + 1233e 2f 179 54 + 1236d c 180 54 + 12379 e 182 54 + 12387 6 183 54 + 1238d 14 184 54 + 123a1 2e 189 54 + 123cf 7 190 54 +@@ -3418,16 +3437,17 @@ 123e9 f 194 54 + 123f8 15 195 54 + 1240d 2b 196 54 + 12438 a 197 54 + 12442 a 198 54 + 1244c 11 199 54 + 1245d a 200 54 + 12467 2 201 54 + 12469 1 201 54 ++FUNC 1246a 99 0 MacFileUtilities::MachoWalker::WalkHeader(int) + 1246a c 83 54 + 12476 15 84 54 + 1248b 1d 86 54 + 124a8 d 87 54 + 124b5 21 88 54 + 124d6 21 90 54 + 124f7 a 93 54 + 12501 2 94 54 +@@ -3448,46 +3468,46 @@ 1254c f 61 56 + 1255b 8 63 56 + 12563 2 64 56 + 12565 1 64 56 + FUNC 12566 1f 0 NXSwapLongLong + 12566 12 70 56 + 12578 b 72 56 + 12583 2 73 56 + 12585 1 73 56 +-FUNC 12586 32 0 breakpad_swap_uuid_command ++FUNC 12586 32 0 breakpad_swap_uuid_command(breakpad_uuid_command*, NXByteOrder) + 12586 c 37 57 + 12592 11 39 57 + 125a3 13 40 57 + 125b6 2 41 57 +-FUNC 125b8 da 0 breakpad_swap_segment_command_64 ++FUNC 125b8 da 0 breakpad_swap_segment_command_64(segment_command_64*, NXByteOrder) + 125b8 c 44 57 + 125c4 11 46 57 + 125d5 13 47 57 + 125e8 17 49 57 + 125ff 17 50 57 + 12616 17 51 57 + 1262d 17 52 57 + 12644 13 54 57 + 12657 13 55 57 + 1266a 13 56 57 + 1267d 13 57 57 + 12690 2 58 57 +-FUNC 12692 a4 0 breakpad_swap_mach_header_64 ++FUNC 12692 a4 0 breakpad_swap_mach_header_64(mach_header_64*, NXByteOrder) + 12692 c 61 57 + 1269e 11 63 57 + 126af 13 64 57 + 126c2 13 65 57 + 126d5 13 66 57 + 126e8 13 67 57 + 126fb 13 68 57 + 1270e 13 69 57 + 12721 13 70 57 + 12734 2 71 57 +-FUNC 12736 1d1 0 breakpad_swap_section_64 ++FUNC 12736 1d1 0 breakpad_swap_section_64(section_64*, unsigned int, NXByteOrder) + 12736 d 75 57 + 12743 c 77 57 + 1274f 33 78 57 + 12782 33 79 57 + 127b5 2d 81 57 + 127e2 2d 82 57 + 1280f 2d 83 57 + 1283c 2d 84 57 +@@ -3509,70 +3529,76 @@ 129d0 13 14 58 + 129e3 2a 14 58 + 12a0d 1 14 58 + 12a0e 13 14 58 + 12a21 2a 14 58 + 12a4b 1 14 58 + 12a4c 13 14 58 + 12a5f 2a 14 58 + 12a89 1 14 58 ++FUNC 12a8a bb 0 dwarf2reader::ByteReader::SetOffsetSize(unsigned char) + 12a8a 19 16 58 + 12aa3 a 17 58 + 12aad 48 18 58 + 12af5 6 19 58 + 12afb 23 20 58 + 12b1e 21 22 58 + 12b3f 6 24 58 + 12b45 1 24 58 ++FUNC 12b46 bb 0 dwarf2reader::ByteReader::SetAddressSize(unsigned char) + 12b46 19 26 58 + 12b5f a 27 58 + 12b69 48 28 58 + 12bb1 6 29 58 + 12bb7 23 30 58 + 12bda 21 32 58 + 12bfb 6 34 58 + 12c01 1 34 58 ++FUNC 12c02 a2 0 dwarf2reader::ByteReader::ReadFourBytes(char const*) const + 12c02 c 24 59 +-12c0e c 25 59 +-12c1a d 26 59 +-12c27 f 27 59 +-12c36 f 28 59 +-12c45 b 29 59 +-12c50 27 30 59 +-12c77 2b 32 59 +-12ca2 2 34 59 ++12c0e c 25 64 ++12c1a d 26 64 ++12c27 f 27 64 ++12c36 f 28 64 ++12c45 b 29 64 ++12c50 27 30 64 ++12c77 2b 32 64 ++12ca2 2 34 64 ++FUNC 12ca4 40e 0 dwarf2reader::ByteReader::ReadEightBytes(char const*) const + 12ca4 11 36 59 +-12cb5 1a 37 59 +-12ccf 1b 38 59 +-12cea 1d 39 59 +-12d07 1d 40 59 +-12d24 1d 41 59 +-12d41 1d 42 59 +-12d5e 1d 43 59 +-12d7b 1d 44 59 +-12d98 f 45 59 +-12da7 18f 47 59 +-12f36 172 50 59 +-130a8 a 52 59 +-130b2 2 52 59 ++12cb5 1a 37 64 ++12ccf 1b 38 64 ++12cea 1d 39 64 ++12d07 1d 40 64 ++12d24 1d 41 64 ++12d41 1d 42 64 ++12d5e 1d 43 64 ++12d7b 1d 44 64 ++12d98 f 45 64 ++12da7 18f 47 64 ++12f36 172 50 64 ++130a8 a 52 64 ++130b2 2 52 64 ++FUNC 130b4 a6 0 ReadInitialLength + 130b4 15 29 60 + 130c9 18 30 60 + 130e1 6 31 60 + 130e7 d 35 60 + 130f4 13 36 60 + 13107 9 37 60 + 13110 1a 38 60 + 1312a 13 40 60 + 1313d 9 41 60 + 13146 12 43 60 + 13158 2 44 60 + 1315a 1f 47 60 + 13179 65 50 60 + 131de 1f 47 60 + 131fd 65 50 60 ++FUNC 13262 393 0 dwarf2reader::CompilationUnit::SkipAttribute(char const*, dwarf2reader::DwarfForm) + 13262 14 133 60 + 13276 82 136 60 + 132f8 1f 139 60 + 13317 a 140 60 + 13321 21 141 60 + 13342 c 147 60 + 1334e e 151 60 + 1335c e 155 60 +@@ -3594,16 +3620,17 @@ 1350f 23 195 60 + 13532 22 198 60 + 13554 15 199 60 + 13569 1b 203 60 + 13584 30 206 60 + 135b4 30 208 60 + 135e4 a 209 60 + 135ee 7 210 60 + 135f5 1 210 60 ++FUNC 135f6 29b 0 dwarf2reader::CompilationUnit::ReadHeader() + 135f6 14 217 60 + 1360a 9 218 60 + 13613 4e 221 60 + 13661 17 223 60 + 13678 a 224 60 + 13682 f 225 60 + 13691 4e 227 60 + 136df 1e 228 60 +@@ -3614,16 +3641,17 @@ 1377f 18 233 60 + 13797 4c 235 60 + 137e3 1d 236 60 + 13800 1c 237 60 + 1381c 5 238 60 + 13821 9 240 60 + 1382a 60 245 60 + 1388a 7 247 60 + 13891 1 247 60 ++FUNC 13892 a57 0 dwarf2reader::CompilationUnit::ProcessAttribute(unsigned long long, char const*, dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm) + 13892 24 299 60 + 138b6 8a 302 60 + 13940 1f 307 60 + 1395f a 308 60 + 13969 36 309 60 + 1399f 5b 316 60 + 139fa c 317 60 + 13a06 5b 322 60 +@@ -3678,30 +3706,33 @@ 14309 3a 491 60 + 14343 a 492 60 + 1434d 6 493 60 + 14353 1 493 60 + 14354 1f 489 60 + 14373 3a 491 60 + 143ad a 492 60 + 143b7 6 493 60 + 143bd 1 493 60 ++FUNC 143be b5 0 dwarf2reader::CompilationUnit::ProcessDIE(unsigned long long, char const*, dwarf2reader::CompilationUnit::Abbrev const&) + 143be 19 426 60 + 143d7 13 427 60 + 143ea 46 430 60 + 14430 3a 427 60 + 1446a 3 432 60 + 1446d 6 433 60 + 14473 1 433 60 ++FUNC 14474 85 0 dwarf2reader::CompilationUnit::SkipDIE(char const*, dwarf2reader::CompilationUnit::Abbrev const&) + 14474 c 122 60 + 14480 13 123 60 + 14493 27 126 60 + 144ba 3a 123 60 + 144f4 3 128 60 + 144f7 2 129 60 + 144f9 1 129 60 ++FUNC 144fa be4 0 dwarf2reader::LineInfo::ProcessOneOpcode(dwarf2reader::ByteReader*, dwarf2reader::LineInfoHandler*, dwarf2reader::LineInfoHeader const&, char const*, dwarf2reader::LineStateMachine*, unsigned long*, unsigned long, bool*) + 144fa 18 593 60 + 14512 a 594 60 + 1451c 18 596 60 + 14534 8 597 60 + 1453c 5 598 60 + 14541 19 602 60 + 1455a f 603 60 + 14569 50 605 60 +@@ -3778,16 +3809,17 @@ 15040 a 758 60 + 1504a 9 759 60 + 15053 1c 761 60 + 1506f d 762 60 + 1507c e 763 60 + 1508a 2e 759 60 + 150b8 b 769 60 + 150c3 10 770 60 + 150d3 b 771 60 ++FUNC 150de 14b 0 dwarf2reader::LineInfo::ReadLines() + 150de e 773 60 + 150ec 9 778 60 + 150f5 17 782 60 + 1510c 8 783 60 + 15114 6 785 60 + 1511a 9 787 60 + 15123 5 788 60 + 15128 19 789 60 +@@ -3796,16 +3828,17 @@ 15146 4a 793 60 + 15190 6 794 60 + 15196 4a 796 60 + 151e0 a 797 60 + 151ea f 790 60 + 151f9 15 788 60 + 1520e 14 801 60 + 15222 7 802 60 + 15229 1 802 60 ++FUNC 1522a 4fd 0 dwarf2reader::CompilationUnit::ReadAbbrevs() + 1522a 18 60 60 + 15242 e 61 60 + 15250 58 65 60 + 152a8 38 66 60 + 152e0 44 65 60 + 15324 2a 66 60 + 1534e 45 68 60 + 15393 16 69 60 +@@ -3838,16 +3871,17 @@ 15637 c 107 60 + 15643 6 111 60 + 15649 6 112 60 + 1564f 32 113 60 + 15681 47 115 60 + 156c8 30 116 60 + 156f8 24 79 60 + 1571c b 118 60 + 15727 1 118 60 ++FUNC 15728 5dc 0 dwarf2reader::LineInfo::ReadHeader() + 15728 18 503 60 + 15740 9 504 60 + 15749 17 508 60 + 15760 a 510 60 + 1576a f 511 60 + 15779 60 512 60 + 157d9 44 516 60 + 1581d 1e 518 60 +@@ -3895,22 +3929,24 @@ 15bc5 22 573 60 + 15be7 a 574 60 + 15bf1 ba 576 60 + 15cab 5 577 60 + 15cb0 16 563 60 + 15cc6 25 576 60 + 15ceb 5 580 60 + 15cf0 9 582 60 + 15cf9 b 583 60 ++FUNC 15d04 3d 0 dwarf2reader::LineInfo::Start() + 15d04 c 495 60 + 15d10 b 496 60 + 15d1b b 497 60 + 15d26 19 498 60 + 15d3f 2 499 60 + 15d41 1 499 60 ++FUNC 15d42 304 0 dwarf2reader::CompilationUnit::ProcessDIEs() + 15d42 11 435 60 + 15d53 9 436 60 + 15d5c 9 441 60 + 15d65 17 445 60 + 15d7c 8 446 60 + 15d84 6 448 60 + 15d8a 6c 453 60 + 15df6 8 455 60 +@@ -3930,16 +3966,17 @@ 15f22 42 474 60 + 15f64 1e 475 60 + 15f82 2a 477 60 + 15fac b 480 60 + 15fb7 1e 481 60 + 15fd5 26 483 60 + 15ffb 1d 455 60 + 16018 24 485 60 + 1603c a 486 60 ++FUNC 16046 35f 0 dwarf2reader::CompilationUnit::Start() + 16046 18 249 60 + 1605e 58 251 60 + 160b6 35 252 60 + 160eb 32 251 60 + 1611d 2a 252 60 + 16147 20 255 60 + 16167 37 256 60 + 1619e b 259 60 +@@ -3954,1208 +3991,1310 @@ 16296 58 282 60 + 162ee 2f 283 60 + 1631d 32 282 60 + 1634f 14 284 60 + 16363 1a 285 60 + 1637d b 289 60 + 16388 12 291 60 + 1639a b 292 60 + 163a5 1 292 60 ++FUNC 163a6 3a 0 std::fill(unsigned char*, unsigned char*, unsigned char const&) + 163a6 c 573 61 + 163b2 9 576 61 + 163bb 23 577 61 + 163de 2 578 61 ++FUNC 163e0 33 0 std::__deque_buf_size(unsigned long) + 163e0 c 83 62 + 163ec 27 84 62 + 16413 1 84 62 ++FUNC 16414 18 0 dwarf2reader::ByteReader::OffsetSize() const + 16414 c 38 63 + 16420 c 38 63 ++FUNC 1642c 18 0 dwarf2reader::ByteReader::AddressSize() const + 1642c c 41 63 + 16438 c 41 63 ++FUNC 16444 17 0 dwarf2reader::ByteReader::ReadOneByte(char const*) const + 16444 c 10 64 + 16450 9 11 64 + 16459 2 12 64 + 1645b 1 12 64 ++FUNC 1645c 63 0 dwarf2reader::ByteReader::ReadTwoBytes(char const*) const + 1645c c 14 64 + 16468 d 15 64 + 16475 e 16 64 + 16483 b 17 64 + 1648e 17 18 64 + 164a5 18 20 64 + 164bd 2 22 64 + 164bf 1 22 64 ++FUNC 164c0 98 0 dwarf2reader::ByteReader::ReadUnsignedLEB128(char const*, unsigned long*) const + 164c0 e 59 64 + 164ce e 60 64 + 164dc 7 61 64 + 164e3 7 62 64 + 164ea e 66 64 + 164f8 5 67 64 + 164fd 38 69 64 + 16535 6 71 64 + 1653b 8 65 64 + 16543 8 75 64 + 1654b 6 77 64 + 16551 7 78 64 ++FUNC 16558 ee 0 dwarf2reader::ByteReader::ReadSignedLEB128(char const*, unsigned long*) const + 16558 e 84 64 + 16566 e 85 64 + 16574 7 86 64 + 1657b 7 87 64 + 16582 e 91 64 + 16590 5 92 64 + 16595 44 93 64 + 165d9 6 94 64 + 165df 8 90 64 + 165e7 14 97 64 + 165fb 36 98 64 + 16631 8 99 64 + 16639 6 100 64 + 1663f 7 101 64 ++FUNC 16646 a2 0 dwarf2reader::ByteReader::ReadOffset(char const*) const + 16646 13 103 64 + 16659 3f 104 64 + 16698 4a 105 64 + 166e2 6 106 64 ++FUNC 166e8 a2 0 dwarf2reader::ByteReader::ReadAddress(char const*) const + 166e8 13 108 64 + 166fb 3f 109 64 + 1673a 4a 110 64 + 16784 6 111 64 ++FUNC 1678a 61 0 dwarf2reader::LineStateMachine::Reset(bool) + 1678a 12 12 65 + 1679c 9 13 65 + 167a5 11 14 65 + 167b6 11 15 65 + 167c7 a 16 65 + 167d1 a 17 65 + 167db 7 18 65 + 167e2 7 19 65 + 167e9 2 20 65 + 167eb 1 20 65 ++FUNC 167ec 20 0 std::_List_const_iterator >::operator!=(std::_List_const_iterator > const&) const + 167ec c 253 66 + 167f8 14 254 66 ++FUNC 1680c 25 0 std::_List_const_iterator >::operator++(int) + 1680c c 226 66 + 16818 8 228 66 + 16820 c 229 66 + 1682c 5 230 66 + 16831 1 230 66 ++FUNC 16832 16 0 std::_List_const_iterator >::operator->() const + 16832 c 215 66 + 1683e a 216 66 + 16848 c 190 67 + 16854 a 190 67 ++FUNC 1685e 13 0 std::auto_ptr > > >::operator->() const + 1685e c 283 67 + 1686a 7 286 67 + 16871 1 286 67 + 16872 c 65 68 + 1687e 2 65 68 + 16880 c 97 69 + 1688c d 97 69 + 16899 1 97 69 + 1689a c 99 69 + 168a6 14 100 69 + 168ba c 97 69 + 168c6 d 97 69 + 168d3 1 97 69 + 168d4 c 84 70 + 168e0 17 85 70 + 168f7 1 85 70 ++FUNC 168f8 2d 0 std::pair std::make_pair(dwarf2reader::DwarfAttribute, dwarf2reader::DwarfForm) + 168f8 c 144 70 + 16904 21 145 70 + 16925 1 145 70 +-16926 c 202 70 +-16932 a 203 70 ++16926 c 202 66 ++16932 a 203 66 ++FUNC 1693c 25 0 std::list, std::allocator > >::begin() const + 1693c c 588 70 +-16948 19 589 70 +-16961 1 589 70 ++16948 19 589 66 ++16961 1 589 66 ++FUNC 16962 23 0 std::list, std::allocator > >::end() const + 16962 c 605 70 +-1696e 17 606 70 +-16985 1 606 70 +-16986 c 65 70 +-16992 2 65 70 +-16994 c 72 70 +-169a0 2 72 70 +-169a2 c 97 70 +-169ae d 97 70 +-169bb 1 97 70 +-169bc c 105 70 +-169c8 d 105 70 +-169d5 1 105 70 +-169d6 c 105 70 +-169e2 d 105 70 +-169ef 1 105 70 +-169f0 c 67 70 +-169fc 2 67 70 +-169fe c 99 70 +-16a0a 14 100 70 +-16a1e c 99 70 +-16a2a 14 100 70 +-16a3e c 129 70 +-16a4a 30 131 70 +-16a7a c 65 70 +-16a86 2 65 70 +-16a88 c 72 70 +-16a94 2 72 70 +-16a96 c 97 70 +-16aa2 d 97 70 +-16aaf 1 97 70 +-16ab0 c 105 70 +-16abc d 105 70 +-16ac9 1 105 70 +-16aca c 105 70 +-16ad6 d 105 70 +-16ae3 1 105 70 +-16ae4 c 67 70 +-16af0 2 67 70 +-16af2 c 99 70 +-16afe 14 100 70 +-16b12 c 99 70 +-16b1e 14 100 70 ++1696e 17 606 66 ++16985 1 606 66 ++16986 c 65 68 ++16992 2 65 68 ++16994 c 72 68 ++169a0 2 72 68 ++169a2 c 97 69 ++169ae d 97 69 ++169bb 1 97 69 ++169bc c 105 69 ++169c8 d 105 69 ++169d5 1 105 69 ++169d6 c 105 69 ++169e2 d 105 69 ++169ef 1 105 69 ++169f0 c 67 68 ++169fc 2 67 68 ++169fe c 99 69 ++16a0a 14 100 69 ++16a1e c 99 69 ++16a2a 14 100 69 ++16a3e c 129 62 ++16a4a 30 131 62 ++16a7a c 65 68 ++16a86 2 65 68 ++16a88 c 72 68 ++16a94 2 72 68 ++16a96 c 97 69 ++16aa2 d 97 69 ++16aaf 1 97 69 ++16ab0 c 105 69 ++16abc d 105 69 ++16ac9 1 105 69 ++16aca c 105 69 ++16ad6 d 105 69 ++16ae3 1 105 69 ++16ae4 c 67 68 ++16af0 2 67 68 ++16af2 c 99 69 ++16afe 14 100 69 ++16b12 c 99 69 ++16b1e 14 100 69 ++FUNC 16b32 2b 0 std::_Vector_base >::get_allocator() const + 16b32 10 93 71 + 16b42 1b 94 71 + 16b5d 1 94 71 +-16b5e c 613 72 + 16b6a 7 614 72 + 16b71 1 614 72 +-16b72 c 80 72 +-16b7e d 80 72 +-16b8b 1 80 72 +-16b8c c 107 72 +-16b98 2 107 72 ++16b72 c 80 71 ++16b7e d 80 71 ++16b8b 1 80 71 ++16b98 2 107 68 ++FUNC 16b9a 2d 0 void std::_Destroy >(unsigned char*, unsigned char*, std::allocator) + 16b9a c 171 73 + 16ba6 2 173 73 + 16ba8 12 174 73 + 16bba b 173 73 + 16bc5 2 174 73 + 16bc7 1 174 73 +-16bc8 c 84 73 +-16bd4 2f 85 73 +-16c03 2 86 73 +-16c05 1 86 73 +-16c06 c 96 73 +-16c12 12 97 73 +-16c24 2 98 73 ++16bc8 c 84 71 ++16bd4 2f 85 71 ++16c03 2 86 71 ++16c05 1 86 71 ++16c06 c 96 71 ++16c12 12 97 71 ++16c24 2 98 71 ++FUNC 16c26 1f 0 std::_List_base, std::allocator > >::_M_init() + 16c26 c 338 73 +-16c32 8 340 73 +-16c3a b 341 73 +-16c45 1 341 73 +-16c46 c 105 73 +-16c52 d 105 73 +-16c5f 1 105 73 +-16c60 c 125 73 +-16c6c a 126 73 ++16c32 8 340 66 ++16c3a b 341 66 ++16c45 1 341 66 ++16c46 c 105 69 ++16c52 d 105 69 ++16c5f 1 105 69 ++16c60 c 125 66 ++16c6c a 126 66 ++FUNC 16c76 25 0 std::list, std::allocator > >::begin() + 16c76 c 579 73 +-16c82 19 580 73 +-16c9b 1 580 73 ++16c82 19 580 66 ++16c9b 1 580 66 ++FUNC 16c9c 23 0 std::list, std::allocator > >::end() + 16c9c c 597 73 +-16ca8 17 597 73 +-16cbf 1 597 73 +-16cc0 c 603 73 +-16ccc c 603 73 ++16ca8 17 597 66 ++16cbf 1 597 66 ++16cc0 c 603 72 ++16ccc c 603 72 ++FUNC 16cd8 2b 0 std::vector >::begin() const + 16cd8 c 342 73 +-16ce4 1f 343 73 +-16d03 1 343 73 ++16ce4 1f 343 71 ++16d03 1 343 71 ++FUNC 16d04 2c 0 std::vector >::end() const + 16d04 c 360 73 +-16d10 20 361 73 +-16d30 c 665 73 +-16d3c 5 666 73 +-16d41 1 666 73 +-16d42 d 758 73 +-16d4f 31 759 73 ++16d10 20 361 71 ++16d3c 5 666 72 ++16d41 1 666 72 ++16d4f 31 759 72 ++FUNC 16d80 3c 0 std::vector >::size() const + 16d80 c 402 73 +-16d8c 30 403 73 +-16dbc c 603 73 +-16dc8 c 603 73 ++16d8c 30 403 71 ++16dbc c 603 72 ++16dc8 c 603 72 ++FUNC 16dd4 23 0 std::vector >::begin() + 16dd4 c 333 73 +-16de0 17 334 73 +-16df7 1 334 73 +-16df8 c 653 73 +-16e04 33 654 73 +-16e37 1 654 73 ++16de0 17 334 71 ++16df7 1 334 71 ++16e04 33 654 72 ++16e37 1 654 72 ++FUNC 16e38 26 0 std::vector >::end() + 16e38 c 351 73 +-16e44 1a 352 73 +-16e5e c 613 73 +-16e6a 7 614 73 +-16e71 1 614 73 ++16e44 1a 352 71 ++16e6a 7 614 72 ++16e71 1 614 72 ++FUNC 16e72 42 0 std::vector >::operator[](unsigned long) + 16e72 c 494 73 +-16e7e 36 495 73 ++16e7e 36 495 71 ++FUNC 16eb4 13 0 std::vector >::max_size() const + 16eb4 c 407 73 +-16ec0 7 408 73 +-16ec7 1 408 73 +-16ec8 c 665 73 +-16ed4 5 666 73 +-16ed9 1 666 73 +-16eda c 621 73 +-16ee6 d 623 73 +-16ef3 5 624 73 +-16ef8 c 382 73 +-16f04 d 382 73 +-16f11 1 382 73 ++16ec0 7 408 71 ++16ec7 1 408 71 ++16ed4 5 666 72 ++16ed9 1 666 72 ++16ee6 d 623 72 ++16ef3 5 624 72 ++16ef8 c 382 62 ++16f04 d 382 62 ++16f11 1 382 62 ++FUNC 16f12 2b 0 std::_Deque_base >::get_allocator() const + 16f12 10 360 73 +-16f22 1b 361 73 +-16f3d 1 361 73 ++16f22 1b 361 62 ++16f3d 1 361 62 ++FUNC 16f3e 2d 0 std::deque >::get_allocator() const + 16f3e 10 764 73 +-16f4e 1d 765 73 +-16f6b 1 765 73 ++16f4e 1d 765 62 ++16f6b 1 765 62 ++FUNC 16f6c 13 0 std::_Deque_iterator::operator*() const + 16f6c c 134 73 +-16f78 7 135 73 +-16f7f 1 135 73 +-16f80 c 107 73 +-16f8c 2 107 73 +-16f8e c 129 73 +-16f9a 30 131 73 ++16f78 7 135 62 ++16f7f 1 135 62 ++16f8c 2 107 68 ++16f8e c 129 62 ++16f9a 30 131 62 ++FUNC 16fca 2c 0 std::deque >::end() const + 16fca 10 799 73 +-16fda 1c 800 73 ++16fda 1c 800 62 ++FUNC 16ff6 2c 0 std::deque >::begin() const + 16ff6 10 781 73 +-17006 1c 782 73 ++17006 1c 782 62 ++FUNC 17022 2e 0 std::deque >::end() + 17022 10 790 73 +-17032 1e 791 73 ++17032 1e 791 62 ++FUNC 17050 3c 0 std::vector >::_M_range_check(unsigned long) const + 17050 13 515 73 +-17063 15 517 73 +-17078 14 518 73 ++17063 15 517 71 ++17078 14 518 71 ++FUNC 1708c 32 0 std::vector >::at(unsigned long) + 1708c c 534 73 +-17098 12 536 73 +-170aa 14 537 73 +-170be c 103 73 +-170ca 2e 104 73 +-170f8 c 84 73 +-17104 2f 85 73 +-17133 2 86 73 +-17135 1 86 73 +-17136 c 96 73 +-17142 12 97 73 +-17154 2 98 73 +-17156 c 603 73 +-17162 c 603 73 ++17098 12 536 71 ++170aa 14 537 71 ++170ca 2e 104 68 ++170f8 c 84 71 ++17104 2f 85 71 ++17133 2 86 71 ++17135 1 86 71 ++17136 c 96 71 ++17142 12 97 71 ++17154 2 98 71 ++17156 c 603 72 ++17162 c 603 72 ++FUNC 1716e 23 0 std::vector >::begin() + 1716e c 333 73 +-1717a 17 334 73 +-17191 1 334 73 +-17192 c 653 73 +-1719e 27 654 73 +-171c5 1 654 73 ++1717a 17 334 71 ++17191 1 334 71 ++1719e 27 654 72 ++171c5 1 654 72 ++FUNC 171c6 42 0 std::vector >::operator[](unsigned long) + 171c6 c 494 73 +-171d2 36 495 73 ++171d2 36 495 71 ++FUNC 17208 26 0 std::vector >::end() + 17208 c 351 73 +-17214 1a 352 73 +-1722e c 93 73 +-1723a d 94 73 +-17247 1 94 73 ++17214 1a 352 71 ++1723a d 94 68 ++17247 1 94 68 ++FUNC 17248 2f 0 std::_Vector_base >::_M_deallocate(unsigned char*, unsigned long) + 17248 c 120 73 +-17254 6 122 73 +-1725a 1d 123 73 +-17277 1 123 73 +-17278 c 108 73 +-17284 3a 109 73 +-172be c 188 73 +-172ca 12 189 73 +-172dc 2 190 73 +-172de c 272 73 +-172ea 4b 273 73 +-17335 1 273 73 ++17254 6 122 71 ++1725a 1d 123 71 ++17277 1 123 71 ++17278 c 108 71 ++17284 3a 109 71 ++172be c 188 71 ++172ca 12 189 71 ++172dc 2 190 71 ++172de c 272 71 ++172ea 4b 273 71 ++17335 1 273 71 + 17336 13 62 74 + 17349 10 62 74 + 17359 a 63 74 + 17363 25 64 74 + 17388 1a 66 74 + 173a2 13 62 74 + 173b5 10 62 74 + 173c5 a 63 74 + 173cf 25 64 74 + 173f4 1a 66 74 +-1740e c 188 74 +-1741a 12 189 74 +-1742c 2 190 74 +-1742e d 758 74 +-1743b 31 759 74 +-1746c c 65 74 +-17478 2 65 74 +-1747a c 103 74 +-17486 d 103 74 +-17493 1 103 74 ++1740e c 188 71 ++1741a 12 189 71 ++1742c 2 190 71 ++1743b 31 759 72 ++1746c c 65 68 ++17478 2 65 68 ++1747a c 103 69 ++17486 d 103 69 ++17493 1 103 69 ++FUNC 17494 2d 0 std::list, std::allocator > >::get_allocator() const + 17494 10 570 74 +-174a4 1d 571 74 +-174c1 1 571 74 +-174c2 c 103 74 +-174ce 2e 104 74 ++174a4 1d 571 66 ++174c1 1 571 66 ++174ce 2e 104 68 ++FUNC 174fc 20 0 std::_List_iterator >::operator!=(std::_List_iterator > const&) const + 174fc c 172 74 +-17508 14 173 74 ++17508 14 173 66 ++FUNC 1751c 1d 0 std::_List_const_iterator >::operator++() + 1751c c 219 74 +-17528 c 221 74 +-17534 5 222 74 +-17539 1 222 74 ++17528 c 221 66 ++17534 5 222 66 ++17539 1 222 66 ++FUNC 1753a 1d 0 std::_List_iterator >::operator++() + 1753a c 138 74 +-17546 c 140 74 +-17552 5 141 74 +-17557 1 141 74 ++17546 c 140 66 ++17552 5 141 66 ++17557 1 141 66 ++FUNC 17558 16 0 std::_List_const_iterator >::operator*() const + 17558 c 211 74 +-17564 a 212 74 ++17564 a 212 66 ++FUNC 1756e 16 0 std::_List_iterator >::operator*() const + 1756e c 130 74 +-1757a a 131 74 ++1757a a 131 66 ++FUNC 17584 20 0 std::_List_const_iterator >::operator==(std::_List_const_iterator > const&) const + 17584 c 249 74 +-17590 14 250 74 ++17590 14 250 66 ++FUNC 175a4 35 0 bool __gnu_cxx::operator!= > >(__gnu_cxx::__normal_iterator > > const&, __gnu_cxx::__normal_iterator > > const&) + 175a4 d 699 74 +-175b1 28 700 74 +-175d9 1 700 74 ++175b1 28 700 72 ++175d9 1 700 72 ++FUNC 175da 4b 0 void std::_Destroy<__gnu_cxx::__normal_iterator > >, std::allocator >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, std::allocator) + 175da c 171 74 +-175e6 2 173 74 +-175e8 1a 174 74 +-17602 21 173 74 +-17623 2 174 74 +-17625 1 174 74 +-17626 c 127 74 +-17632 29 127 74 +-1765b 1 127 74 +-1765c c 388 74 +-17668 41 389 74 +-176a9 2 390 74 +-176ab 1 390 74 +-176ac c 93 74 +-176b8 d 94 74 +-176c5 1 94 74 ++175e6 2 173 73 ++175e8 1a 174 73 ++17602 21 173 73 ++17623 2 174 73 ++17625 1 174 73 ++17626 c 127 62 ++17632 29 127 62 ++1765b 1 127 62 ++1765c c 388 62 ++17668 41 389 62 ++176a9 2 390 62 ++176ab 1 390 62 ++176b8 d 94 68 ++176c5 1 94 68 ++FUNC 176c6 20 0 bool std::operator==(std::_Deque_iterator const&, std::_Deque_iterator const&) + 176c6 c 243 74 +-176d2 14 244 74 ++176d2 14 244 62 ++FUNC 176e6 26 0 bool std::operator!=(std::_Deque_iterator const&, std::_Deque_iterator const&) + 176e6 c 256 74 +-176f2 1a 257 74 ++176f2 1a 257 62 ++FUNC 1770c 1a 0 std::_Deque_iterator::_S_buffer_size() + 1770c c 106 74 +-17718 e 107 74 ++17718 e 107 62 ++FUNC 17726 3e 0 std::_Deque_iterator::_M_set_node(unsigned long long**) + 17726 d 229 74 +-17733 9 231 74 +-1773c b 232 74 +-17747 1d 233 74 ++17733 9 231 62 ++1773c b 232 62 ++17747 1d 233 62 ++FUNC 17764 50 0 std::_Deque_iterator::operator++() + 17764 c 142 74 +-17770 d 144 74 +-1777d f 145 74 +-1778c 18 147 74 +-177a4 b 148 74 +-177af 5 150 74 ++17770 d 144 62 ++1777d f 145 62 ++1778c 18 147 62 ++177a4 b 148 62 ++177af 5 150 62 ++FUNC 177b4 4b 0 void std::_Destroy, std::allocator >(std::_Deque_iterator, std::_Deque_iterator, std::allocator) + 177b4 c 171 74 +-177c0 2 173 74 +-177c2 1a 174 74 +-177dc 21 173 74 +-177fd 2 174 74 +-177ff 1 174 74 ++177c0 2 173 73 ++177c2 1a 174 73 ++177dc 21 173 73 ++177fd 2 174 73 ++177ff 1 174 73 ++FUNC 17800 50 0 std::_Deque_iterator::operator--() + 17800 c 162 74 +-1780c f 164 74 +-1781b 18 166 74 +-17833 b 167 74 +-1783e d 169 74 +-1784b 5 170 74 ++1780c f 164 62 ++1781b 18 166 62 ++17833 b 167 62 ++1783e d 169 62 ++1784b 5 170 62 ++FUNC 17850 39 0 std::deque >::back() + 17850 c 988 74 +-1785c 15 990 74 +-17871 b 991 74 +-1787c d 992 74 +-17889 1 992 74 ++1785c 15 990 62 ++17871 b 991 62 ++1787c d 992 62 ++17889 1 992 62 ++FUNC 1788a 19 0 std::stack > >::top() + 1788a c 163 75 + 17896 d 166 75 + 178a3 1 166 75 ++FUNC 178a4 66 0 std::_Deque_iterator::difference_type std::operator-(std::_Deque_iterator const&, std::_Deque_iterator const&) + 178a4 d 328 75 +-178b1 59 333 75 ++178b1 59 333 62 ++FUNC 1790a 26 0 std::deque >::size() const + 1790a c 840 75 +-17916 1a 841 75 +-17930 c 661 75 +-1793c 36 662 75 +-17972 c 649 75 +-1797e 23 650 75 +-179a1 1 650 75 +-179a2 c 67 75 +-179ae 2 67 75 +-179b0 c 99 75 +-179bc 14 100 75 +-179d0 c 303 75 +-179dc 12 304 75 +-179ee 2 305 75 +-179f0 c 326 75 +-179fc 2f 327 75 +-17a2b d 328 75 +-17a38 c 457 75 +-17a44 14 458 75 +-17a58 c 211 75 +-17a64 2d 211 75 +-17a91 1 211 75 +-17a92 c 97 75 +-17a9e 7 98 75 +-17aa5 1 98 75 +-17aa6 c 83 75 +-17ab2 1d 85 75 +-17acf 5 86 75 +-17ad4 17 88 75 +-17aeb 1 88 75 ++17916 1a 841 62 ++1793c 36 662 72 ++1797e 23 650 72 ++179a1 1 650 72 ++179a2 c 67 68 ++179ae 2 67 68 ++179b0 c 99 69 ++179bc 14 100 69 ++179d0 c 303 66 ++179dc 12 304 66 ++179ee 2 305 66 ++179f0 c 326 66 ++179fc 2f 327 66 ++17a2b d 328 66 ++17a38 c 457 66 ++17a44 14 458 66 ++17a58 c 211 74 ++17a64 2d 211 74 ++17a91 1 211 74 ++17a9e 7 98 68 ++17aa5 1 98 68 ++17ab2 1d 85 68 ++17acf 5 86 68 ++17ad4 17 88 68 ++17aeb 1 88 68 ++FUNC 17aec 2a 0 std::_Vector_base >::_M_allocate(unsigned long) + 17aec c 116 75 +-17af8 1e 117 75 +-17b16 c 93 75 +-17b22 d 94 75 +-17b2f 1 94 75 ++17af8 1e 117 71 ++17b22 d 94 68 ++17b2f 1 94 68 ++FUNC 17b30 34 0 std::_Deque_base >::_M_deallocate_node(unsigned long long*) + 17b30 c 402 75 +-17b3c 28 403 75 ++17b3c 28 403 62 ++FUNC 17b64 38 0 std::_Deque_base >::_M_destroy_nodes(unsigned long long**, unsigned long long**) + 17b64 c 504 75 +-17b70 8 506 75 +-17b78 14 507 75 +-17b8c e 506 75 +-17b9a 2 507 75 ++17b70 8 506 62 ++17b78 14 507 62 ++17b8c e 506 62 ++17b9a 2 507 62 ++FUNC 17b9c 62 0 std::deque >::_M_pop_back_aux() + 17b9c c 391 76 + 17ba8 15 393 76 + 17bbd 1b 394 76 + 17bd8 f 395 76 + 17be7 17 396 76 ++FUNC 17bfe 4f 0 std::deque >::pop_back() + 17bfe c 1081 76 +-17c0a 10 1083 76 +-17c1a f 1086 76 +-17c29 17 1087 76 +-17c40 d 1090 76 +-17c4d 1 1090 76 ++17c0a 10 1083 62 ++17c1a f 1086 62 ++17c29 17 1087 62 ++17c40 d 1090 62 ++17c4d 1 1090 62 ++FUNC 17c4e 19 0 std::stack > >::pop() + 17c4e c 205 76 +-17c5a d 208 76 +-17c67 1 208 76 +-17c68 c 72 76 +-17c74 2 72 76 +-17c76 c 105 76 +-17c82 d 105 76 +-17c8f 1 105 76 +-17c90 c 603 76 +-17c9c c 603 76 ++17c5a d 208 75 ++17c67 1 208 75 ++17c68 c 72 68 ++17c74 2 72 68 ++17c76 c 105 69 ++17c82 d 105 69 ++17c8f 1 105 69 ++17c90 c 603 72 ++17c9c c 603 72 ++FUNC 17ca8 2b 0 std::vector >::begin() const + 17ca8 c 342 76 +-17cb4 1f 343 76 +-17cd3 1 343 76 ++17cb4 1f 343 71 ++17cd3 1 343 71 ++FUNC 17cd4 2c 0 std::vector >::end() const + 17cd4 c 360 76 +-17ce0 20 361 76 +-17d00 c 665 76 +-17d0c 5 666 76 +-17d11 1 666 76 +-17d12 d 758 76 +-17d1f 28 759 76 +-17d47 1 759 76 ++17ce0 20 361 71 ++17d0c 5 666 72 ++17d11 1 666 72 ++17d1f 28 759 72 ++17d47 1 759 72 ++FUNC 17d48 3c 0 std::vector >::size() const + 17d48 c 402 76 +-17d54 30 403 76 +-17d84 c 621 76 +-17d90 d 623 76 +-17d9d 5 624 76 +-17da2 c 665 76 +-17dae 5 666 76 +-17db3 1 666 76 ++17d54 30 403 71 ++17d90 d 623 72 ++17d9d 5 624 72 ++17dae 5 666 72 ++17db3 1 666 72 ++FUNC 17db4 35 0 bool __gnu_cxx::operator!= > >(__gnu_cxx::__normal_iterator > > const&, __gnu_cxx::__normal_iterator > > const&) + 17db4 d 699 76 +-17dc1 28 700 76 +-17de9 1 700 76 ++17dc1 28 700 72 ++17de9 1 700 72 ++FUNC 17dea 4b 0 void std::_Destroy<__gnu_cxx::__normal_iterator > >, std::allocator >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, std::allocator) + 17dea c 171 76 +-17df6 2 173 76 +-17df8 1a 174 76 +-17e12 21 173 76 +-17e33 2 174 76 +-17e35 1 174 76 +-17e36 d 758 76 +-17e43 28 759 76 +-17e6b 1 759 76 +-17e6c c 661 76 +-17e78 2a 662 76 ++17df6 2 173 73 ++17df8 1a 174 73 ++17e12 21 173 73 ++17e33 2 174 73 ++17e35 1 174 73 ++17e43 28 759 72 ++17e6b 1 759 72 ++17e78 2a 662 72 ++FUNC 17ea2 13 0 std::vector >::max_size() const + 17ea2 c 407 76 +-17eae 7 408 76 +-17eb5 1 408 76 +-17eb6 c 649 76 +-17ec2 16 650 76 +-17ed8 c 97 76 +-17ee4 7 98 76 +-17eeb 1 98 76 +-17eec c 83 76 +-17ef8 1d 85 76 +-17f15 5 86 76 +-17f1a 10 88 76 ++17eae 7 408 71 ++17eb5 1 408 71 ++17ec2 16 650 72 ++17ee4 7 98 68 ++17eeb 1 98 68 ++17ef8 1d 85 68 ++17f15 5 86 68 ++17f1a 10 88 68 ++FUNC 17f2a 29 0 std::_List_base, std::allocator > >::_M_get_node() + 17f2a c 311 76 +-17f36 1d 312 76 +-17f53 1 312 76 ++17f36 1d 312 66 ++17f53 1 312 66 ++FUNC 17f54 5f 0 std::list, std::allocator > >::_M_create_node(std::pair const&) + 17f54 d 435 76 +-17f61 e 437 76 +-17f6f 3c 440 76 +-17fab 8 447 76 +-17fb3 1 447 76 ++17f61 e 437 66 ++17f6f 3c 440 66 ++17fab 8 447 66 ++17fb3 1 447 66 ++FUNC 17fb4 35 0 std::list, std::allocator > >::_M_insert(std::_List_iterator >, std::pair const&) + 17fb4 c 1149 76 +-17fc0 15 1151 76 +-17fd5 14 1152 76 +-17fe9 1 1152 76 +-FUNC 17fea 52 0 _M_insert_dispatch > > +-17fea c 1126 76 +-17ff6 2 1128 76 +-17ff8 21 1129 76 +-18019 21 1128 76 +-1803a 2 1129 76 +-FUNC 1803c 36 0 insert > > +-1803c c 838 76 +-18048 2a 842 76 +-18072 e 491 76 +-18080 32 492 76 +-180b2 64 493 76 +-18116 c 211 76 +-18122 3d 211 76 +-1815f 1 211 76 +-18160 d 103 76 +-1816d 5c 104 76 +-181c9 1 104 76 ++17fc0 15 1151 66 ++17fd5 14 1152 66 ++17fe9 1 1152 66 ++FUNC 17fea 52 0 void std::list, std::allocator > >::_M_insert_dispatch > >(std::_List_iterator >, std::_List_const_iterator >, std::_List_const_iterator >, __false_type) ++17fea c 1126 66 ++17ff6 2 1128 66 ++17ff8 21 1129 66 ++18019 21 1128 66 ++1803a 2 1129 66 ++FUNC 1803c 36 0 void std::list, std::allocator > >::insert > >(std::_List_iterator >, std::_List_const_iterator >, std::_List_const_iterator >) ++1803c c 838 66 ++18048 2a 842 66 ++18072 e 491 66 ++18080 32 492 66 ++180b2 64 493 66 ++18116 c 211 74 ++18122 3d 211 74 ++1815f 1 211 74 ++1816d 5c 104 68 ++181c9 1 104 68 ++FUNC 181ca 31 0 std::list, std::allocator > >::push_back(std::pair const&) + 181ca c 772 76 +-181d6 25 773 76 +-181fb 1 773 76 ++181d6 25 773 66 ++181fb 1 773 66 ++FUNC 181fc 69 0 void std::_Construct(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev const&) + 181fc d 77 76 +-18209 5c 81 76 +-18265 1 81 76 +-18266 c 97 76 +-18272 7 98 76 +-18279 1 98 76 +-1827a c 83 76 +-18286 1d 85 76 +-182a3 5 86 76 +-182a8 10 88 76 +-182b8 c 65 76 +-182c4 2 65 76 +-182c6 c 103 76 +-182d2 d 103 76 +-182df 1 103 76 ++18209 5c 81 73 ++18265 1 81 73 ++18272 7 98 68 ++18279 1 98 68 ++18286 1d 85 68 ++182a3 5 86 68 ++182a8 10 88 68 ++182b8 c 65 68 ++182c4 2 65 68 ++182c6 c 103 69 ++182d2 d 103 69 ++182df 1 103 69 ++FUNC 182e0 4d 0 std::_Deque_base >::_M_get_map_allocator() const + 182e0 11 394 76 +-182f1 3c 395 76 +-1832d 1 395 76 ++182f1 3c 395 62 ++1832d 1 395 62 ++FUNC 1832e 75 0 std::_Deque_base >::_M_allocate_map(unsigned long) + 1832e d 406 76 +-1833b 68 407 76 +-183a3 1 407 76 ++1833b 68 407 62 ++183a3 1 407 62 ++FUNC 183a4 47 0 std::_Deque_base >::_M_deallocate_map(unsigned long long**, unsigned long) + 183a4 c 410 76 +-183b0 3b 411 76 +-183eb 1 411 76 +-183ec c 424 76 +-183f8 9 426 76 +-18401 22 428 76 +-18423 2b 430 76 +-1844e c 714 76 +-1845a 70 715 76 +-184ca c 111 76 +-184d6 d 111 76 +-184e3 1 111 76 +-184e4 c 259 76 +-184f0 26 259 76 +-18516 c 97 76 +-18522 7 98 76 +-18529 1 98 76 +-1852a c 83 76 +-18536 1d 85 76 +-18553 5 86 76 +-18558 10 88 76 ++183b0 3b 411 62 ++183eb 1 411 62 ++183ec c 424 62 ++183f8 9 426 62 ++18401 22 428 62 ++18423 2b 430 62 ++1844e c 714 62 ++1845a 70 715 62 ++184ca c 111 75 ++184d6 d 111 75 ++184e3 1 111 75 ++184e4 c 259 67 ++184f0 26 259 67 ++18522 7 98 68 ++18529 1 98 68 ++18536 1d 85 68 ++18553 5 86 68 ++18558 10 88 68 ++FUNC 18568 33 0 std::_Deque_base >::_M_allocate_node() + 18568 c 398 76 +-18574 27 399 76 +-1859b 1 399 76 ++18574 27 399 62 ++1859b 1 399 62 ++FUNC 1859c 82 0 std::_Deque_base >::_M_create_nodes(unsigned long long**, unsigned long long**) + 1859c d 486 76 +-185a9 8 491 76 +-185b1 12 492 76 +-185c3 13 491 76 +-185d6 b 494 76 +-185e1 19 496 76 +-185fa b 497 76 +-18605 13 494 76 +-18618 6 497 76 ++185a9 8 491 62 ++185b1 12 492 62 ++185c3 13 491 62 ++185d6 b 494 62 ++185e1 19 496 62 ++185fa b 497 62 ++18605 13 494 62 ++18618 6 497 62 ++FUNC 1861e 17b 0 std::_Deque_base >::_M_initialize_map(unsigned long) + 1861e d 447 76 +-1862b 1e 450 76 +-18649 2a 452 76 +-18673 1c 454 76 +-1868f 19 462 76 +-186a8 c 463 76 +-186b4 1e 466 76 +-186d2 b 467 76 +-186dd 1e 469 76 +-186fb 9 470 76 +-18704 a 471 76 +-1870e b 472 76 +-18719 13 467 76 +-1872c 15 475 76 +-18741 18 476 76 +-18759 c 477 76 +-18765 34 478 76 +-18799 1 478 76 +-1879a d 366 76 +-187a7 12 367 76 +-187b9 39 368 76 +-187f2 c 645 76 +-187fe 1c 646 76 +-FUNC 1881a 4d 0 fill<__gnu_cxx::__normal_iterator > >, unsigned char> +-1881a c 539 76 +-18826 9 541 76 +-1882f 2 542 76 +-18831 13 543 76 +-18844 21 542 76 +-18865 2 543 76 +-18867 1 543 76 ++1862b 1e 450 62 ++18649 2a 452 62 ++18673 1c 454 62 ++1868f 19 462 62 ++186a8 c 463 62 ++186b4 1e 466 62 ++186d2 b 467 62 ++186dd 1e 469 62 ++186fb 9 470 62 ++18704 a 471 62 ++1870e b 472 62 ++18719 13 467 62 ++1872c 15 475 62 ++18741 18 476 62 ++18759 c 477 62 ++18765 34 478 62 ++18799 1 478 62 ++1879a d 366 62 ++187a7 12 367 62 ++187b9 39 368 62 ++187f2 c 645 62 ++187fe 1c 646 62 ++FUNC 1881a 4d 0 void std::__fill::fill<__gnu_cxx::__normal_iterator > >, unsigned char>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, unsigned char const&) ++1881a c 539 61 ++18826 9 541 61 ++1882f 2 542 61 ++18831 13 543 61 ++18844 21 542 61 ++18865 2 543 61 ++18867 1 543 61 ++FUNC 18868 2b 0 void std::fill<__gnu_cxx::__normal_iterator > >, unsigned char>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, unsigned char const&) + 18868 c 560 76 +-18874 4 567 76 +-18878 1b 568 76 +-18893 1 568 76 ++18874 4 567 61 ++18878 1b 568 61 ++18893 1 568 61 ++FUNC 18894 6a 0 std::list, std::allocator > >::_M_erase(std::_List_iterator >) + 18894 d 1157 76 +-188a1 b 1159 76 +-188ac 6 1160 76 +-188b2 35 1161 76 +-188e7 17 1162 76 ++188a1 b 1159 66 ++188ac 6 1160 66 ++188b2 35 1161 66 ++188e7 17 1162 66 ++FUNC 188fe 37 0 std::list, std::allocator > >::erase(std::_List_iterator >) + 188fe c 95 77 + 1890a 14 97 77 + 1891e 12 98 77 + 18930 5 99 77 + 18935 1 99 77 ++FUNC 18936 3e 0 std::list, std::allocator > >::erase(std::_List_iterator >, std::_List_iterator >) + 18936 c 883 77 +-18942 2 885 77 +-18944 15 886 77 +-18959 16 885 77 +-1896f 5 887 77 ++18942 2 885 66 ++18944 15 886 66 ++18959 16 885 66 ++1896f 5 887 66 ++FUNC 18974 129 0 std::list, std::allocator > >::operator=(std::list, std::allocator > > const&) + 18974 e 120 77 + 18982 c 122 77 + 1898e e 124 77 + 1899c e 125 77 + 189aa e 126 77 + 189b8 e 127 77 + 189c6 2 128 77 + 189c8 20 130 77 + 189e8 5a 128 77 + 18a42 16 131 77 + 18a58 1b 132 77 + 18a73 20 134 77 + 18a93 a 136 77 + 18a9d 1 136 77 +-FUNC 18a9e 4c 0 operator= +-18a9e c 0 77 +-18aaa 40 211 77 +-FUNC 18aea 52 0 copy +-18aea c 280 77 +-18af6 1a 283 77 +-18b10 12 285 77 +-18b22 4 286 77 +-18b26 6 287 77 +-18b2c b 283 77 +-18b37 5 289 77 ++FUNC 18a9e 4c 0 dwarf2reader::CompilationUnit::Abbrev::operator=(dwarf2reader::CompilationUnit::Abbrev const&) ++18a9e c 211 77 ++18aaa 40 211 74 ++FUNC 18aea 52 0 dwarf2reader::CompilationUnit::Abbrev* std::__copy::copy(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*) ++18aea c 280 61 ++18af6 1a 283 61 ++18b10 12 285 61 ++18b22 4 286 61 ++18b26 6 287 61 ++18b2c b 283 61 ++18b37 5 289 61 ++FUNC 18b3c 2b 0 dwarf2reader::CompilationUnit::Abbrev* std::__copy_aux(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*) + 18b3c c 307 77 +-18b48 4 315 77 +-18b4c 1b 317 77 +-18b67 1 317 77 +-FUNC 18b68 64 0 copy_n<__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > > > +-18b68 e 352 77 +-18b76 56 354 77 +-18bcc c 376 77 +-18bd8 4 384 77 +-18bdc 4 385 77 +-18be0 1b 387 77 +-18bfb 1 387 77 ++18b48 4 315 61 ++18b4c 1b 317 61 ++18b67 1 317 61 ++18b76 56 354 61 ++18bd8 4 384 61 ++18bdc 4 385 61 ++18be0 1b 387 61 ++18bfb 1 387 61 ++FUNC 18bfc ac 0 std::vector >::erase(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >) + 18bfc d 122 78 + 18c09 26 124 78 + 18c2f 43 125 78 + 18c72 2e 126 78 + 18ca0 8 127 78 +-FUNC 18ca8 54 0 copy_b +-18ca8 c 408 78 +-18cb4 1a 411 78 +-18cce 1e 412 78 +-18cec b 411 78 +-18cf7 5 413 78 ++FUNC 18ca8 54 0 dwarf2reader::CompilationUnit::Abbrev* std::__copy_backward::copy_b(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*) ++18ca8 c 408 61 ++18cb4 1a 411 61 ++18cce 1e 412 61 ++18cec b 411 61 ++18cf7 5 413 61 ++FUNC 18cfc 2b 0 dwarf2reader::CompilationUnit::Abbrev* std::__copy_backward_aux(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*) + 18cfc c 432 78 +-18d08 4 440 78 +-18d0c 1b 443 78 +-18d27 1 443 78 +-FUNC 18d28 64 0 copy_b_n<__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > > > +-18d28 e 480 78 +-18d36 56 482 78 +-18d8c c 504 78 +-18d98 4 514 78 +-18d9c 4 515 78 +-18da0 1b 517 78 +-18dbb 1 517 78 +-FUNC 18dbc 4d 0 fill<__gnu_cxx::__normal_iterator > >, dwarf2reader::CompilationUnit::Abbrev> +-18dbc c 526 78 +-18dc8 2 528 78 +-18dca 1c 529 78 +-18de6 21 528 78 +-18e07 2 529 78 +-18e09 1 529 78 ++18d08 4 440 61 ++18d0c 1b 443 61 ++18d27 1 443 61 ++18d36 56 482 61 ++18d98 4 514 61 ++18d9c 4 515 61 ++18da0 1b 517 61 ++18dbb 1 517 61 ++FUNC 18dbc 4d 0 void std::__fill::fill<__gnu_cxx::__normal_iterator > >, dwarf2reader::CompilationUnit::Abbrev>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, dwarf2reader::CompilationUnit::Abbrev const&) ++18dbc c 526 61 ++18dc8 2 528 61 ++18dca 1c 529 61 ++18de6 21 528 61 ++18e07 2 529 61 ++18e09 1 529 61 ++FUNC 18e0a 2b 0 void std::fill<__gnu_cxx::__normal_iterator > >, dwarf2reader::CompilationUnit::Abbrev>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, dwarf2reader::CompilationUnit::Abbrev const&) + 18e0a c 560 78 +-18e16 4 567 78 +-18e1a 1b 568 78 +-18e35 1 568 78 +-FUNC 18e36 3f 0 copy +-18e36 c 298 78 +-18e42 22 300 78 +-18e64 11 301 78 +-18e75 1 301 78 ++18e16 4 567 61 ++18e1a 1b 568 61 ++18e35 1 568 61 ++FUNC 18e36 3f 0 unsigned char* std::__copy::copy(unsigned char const*, unsigned char const*, unsigned char*) ++18e36 c 298 61 ++18e42 22 300 61 ++18e64 11 301 61 ++18e75 1 301 61 ++FUNC 18e76 2b 0 unsigned char* std::__copy_aux(unsigned char*, unsigned char*, unsigned char*) + 18e76 c 307 78 +-18e82 4 315 78 +-18e86 1b 317 78 +-18ea1 1 317 78 +-FUNC 18ea2 64 0 copy_n<__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > > > +-18ea2 e 352 78 +-18eb0 56 354 78 +-18f06 c 376 78 +-18f12 4 384 78 +-18f16 4 385 78 +-18f1a 1b 387 78 +-18f35 1 387 78 ++18e82 4 315 61 ++18e86 1b 317 61 ++18ea1 1 317 61 ++18eb0 56 354 61 ++18f12 4 384 61 ++18f16 4 385 61 ++18f1a 1b 387 61 ++18f35 1 387 61 ++FUNC 18f36 a0 0 std::vector >::erase(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >) + 18f36 d 122 78 + 18f43 26 124 78 + 18f69 43 125 78 + 18fac 22 126 78 + 18fce 8 127 78 +-18fd6 c 97 78 +-18fe2 7 98 78 +-18fe9 1 98 78 +-18fea c 83 78 +-18ff6 1d 85 78 +-19013 5 86 78 +-19018 d 88 78 +-19025 1 88 78 ++18fe2 7 98 68 ++18fe9 1 98 68 ++18ff6 1d 85 68 ++19013 5 86 68 ++19018 d 88 68 ++19025 1 88 68 ++FUNC 19026 2a 0 std::_Vector_base >::_M_allocate(unsigned long) + 19026 c 116 78 +-19032 1e 117 78 +-19050 c 73 79 ++19032 1e 117 71 + 1905c 1b 74 79 + 19077 1 74 79 +-19078 c 108 79 + 19084 23 113 79 + 190a7 1 113 79 +-190a8 c 252 79 + 190b4 1b 254 79 + 190cf 1 254 79 ++FUNC 190d0 19 0 void std::_Destroy(dwarf2reader::CompilationUnit::Abbrev*) + 190d0 c 106 79 +-190dc d 107 79 +-190e9 1 107 79 ++190dc d 107 73 ++190e9 1 107 73 ++FUNC 190ea 44 0 void std::__destroy_aux<__gnu_cxx::__normal_iterator > > >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, __false_type) + 190ea c 119 79 +-190f6 2 121 79 +-190f8 13 122 79 +-1910b 21 121 79 +-1912c 2 122 79 ++190f6 2 121 73 ++190f8 13 122 73 ++1910b 21 121 73 ++1912c 2 122 73 ++FUNC 1912e 28 0 void std::_Destroy<__gnu_cxx::__normal_iterator > > >(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >) + 1912e c 148 79 +-1913a 1c 155 79 ++1913a 1c 155 73 ++FUNC 19156 8d 0 void std::__uninitialized_fill_n_aux<__gnu_cxx::__normal_iterator > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev>(__gnu_cxx::__normal_iterator > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&, __false_type) + 19156 d 188 79 + 19163 6 190 79 + 19169 2 193 79 + 1916b 1c 194 79 + 19187 1b 193 79 + 191a2 b 196 79 + 191ad 12 198 79 + 191bf b 199 79 + 191ca 13 196 79 + 191dd 6 199 79 + 191e3 1 199 79 ++FUNC 191e4 2f 0 void std::uninitialized_fill_n<__gnu_cxx::__normal_iterator > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev>(__gnu_cxx::__normal_iterator > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&) + 191e4 c 214 79 + 191f0 23 218 79 + 19213 1 218 79 ++FUNC 19214 27 0 void std::__uninitialized_fill_n_a<__gnu_cxx::__normal_iterator > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev, dwarf2reader::CompilationUnit::Abbrev>(__gnu_cxx::__normal_iterator > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&, std::allocator) + 19214 c 308 79 + 19220 1b 310 79 + 1923b 1 310 79 +-1923c d 80 79 + 19249 6 82 79 + 1924f 2 85 79 + 19251 24 86 79 + 19275 2c 85 79 + 192a1 b 87 79 + 192ac b 89 79 + 192b7 12 91 79 + 192c9 b 92 79 + 192d4 13 89 79 + 192e7 9 92 79 +-192f0 c 108 79 + 192fc 23 113 79 + 1931f 1 113 79 +-19320 c 252 79 + 1932c 1b 254 79 + 19347 1 254 79 ++FUNC 19348 409 0 std::vector >::_M_insert_aux(__gnu_cxx::__normal_iterator > >, dwarf2reader::CompilationUnit::Abbrev const&) + 19348 14 249 79 +-1935c 14 251 79 +-19370 22 253 79 +-19392 f 255 79 +-193a1 12 256 79 +-193b3 55 257 79 +-19408 4b 260 79 +-19453 e 264 79 +-19461 15 265 79 +-19476 e 266 79 +-19484 1d 271 79 +-194a1 8 272 79 +-194a9 e 273 79 +-194b7 27 275 79 +-194de 6 276 79 +-194e4 55 279 79 +-19539 25 284 79 +-1955e b 285 79 +-19569 4f 286 79 +-195b8 3 284 79 +-195bb 13 279 79 +-195ce e 286 79 +-195dc 4d 298 79 +-19629 36 299 79 +-1965f 12 302 79 +-19671 13 303 79 +-19684 2e 304 79 +-196b2 13 286 79 +-196c5 b 292 79 +-196d0 39 294 79 +-19709 23 295 79 +-1972c b 296 79 +-19737 13 292 79 +-1974a 7 304 79 +-19751 1 304 79 ++1935c 14 251 78 ++19370 22 253 78 ++19392 f 255 78 ++193a1 12 256 78 ++193b3 55 257 78 ++19408 4b 260 78 ++19453 e 264 78 ++19461 15 265 78 ++19476 e 266 78 ++19484 1d 271 78 ++194a1 8 272 78 ++194a9 e 273 78 ++194b7 27 275 78 ++194de 6 276 78 ++194e4 55 279 78 ++19539 25 284 78 ++1955e b 285 78 ++19569 4f 286 78 ++195b8 3 284 78 ++195bb 13 279 78 ++195ce e 286 78 ++195dc 4d 298 78 ++19629 36 299 78 ++1965f 12 302 78 ++19671 13 303 78 ++19684 2e 304 78 ++196b2 13 286 78 ++196c5 b 292 78 ++196d0 39 294 78 ++19709 23 295 78 ++1972c b 296 78 ++19737 13 292 78 ++1974a 7 304 78 ++19751 1 304 78 ++FUNC 19752 70 0 std::vector >::push_back(dwarf2reader::CompilationUnit::Abbrev const&) + 19752 c 602 79 +-1975e 10 604 79 +-1976e 1e 606 79 +-1978c 11 607 79 +-1979d 25 610 79 +-FUNC 197c2 50 0 copy_b +-197c2 d 422 79 +-197cf f 424 79 +-197de 24 425 79 +-19802 10 426 79 ++1975e 10 604 71 ++1976e 1e 606 71 ++1978c 11 607 71 ++1979d 25 610 71 ++FUNC 197c2 50 0 unsigned char* std::__copy_backward::copy_b(unsigned char const*, unsigned char const*, unsigned char*) ++197c2 d 422 61 ++197cf f 424 61 ++197de 24 425 61 ++19802 10 426 61 ++FUNC 19812 2b 0 unsigned char* std::__copy_backward_aux(unsigned char*, unsigned char*, unsigned char*) + 19812 c 432 79 +-1981e 4 440 79 +-19822 1b 443 79 +-1983d 1 443 79 +-FUNC 1983e 64 0 copy_b_n<__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > > > +-1983e e 480 79 +-1984c 56 482 79 +-198a2 c 504 79 +-198ae 4 514 79 +-198b2 4 515 79 +-198b6 1b 517 79 +-198d1 1 517 79 ++1981e 4 440 61 ++19822 1b 443 61 ++1983d 1 443 61 ++1984c 56 482 61 ++198ae 4 514 61 ++198b2 4 515 61 ++198b6 1b 517 61 ++198d1 1 517 61 ++FUNC 198d2 32 0 unsigned char* std::fill_n(unsigned char*, unsigned long, unsigned char const&) + 198d2 c 647 79 +-198de 1e 649 79 +-198fc 8 650 79 ++198de 1e 649 61 ++198fc 8 650 61 ++FUNC 19904 27 0 void std::__uninitialized_fill_n_aux(unsigned char*, unsigned long, unsigned char const&, __true_type) + 19904 c 182 79 + 19910 1b 183 79 + 1992b 1 183 79 ++FUNC 1992c 2f 0 void std::uninitialized_fill_n(unsigned char*, unsigned long, unsigned char const&) + 1992c c 214 79 + 19938 23 218 79 + 1995b 1 218 79 ++FUNC 1995c 27 0 void std::__uninitialized_fill_n_a(unsigned char*, unsigned long, unsigned char const&, std::allocator) + 1995c c 308 79 + 19968 1b 310 79 + 19983 1 310 79 ++FUNC 19984 27 0 void std::__destroy_aux(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, __false_type) + 19984 c 119 79 +-19990 2 121 79 +-19992 b 122 79 +-1999d c 121 79 +-199a9 2 122 79 +-199ab 1 122 79 ++19990 2 121 73 ++19992 b 122 73 ++1999d c 121 73 ++199a9 2 122 73 ++199ab 1 122 73 ++FUNC 199ac 28 0 void std::_Destroy(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*) + 199ac c 148 79 +-199b8 1c 155 79 ++199b8 1c 155 73 ++FUNC 199d4 88 0 dwarf2reader::CompilationUnit::Abbrev* std::__uninitialized_copy_aux(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, __false_type) + 199d4 d 80 79 + 199e1 6 82 79 + 199e7 2 85 79 + 199e9 12 86 79 + 199fb 12 85 79 + 19a0d b 87 79 + 19a18 b 89 79 + 19a23 12 91 79 + 19a35 b 92 79 + 19a40 13 89 79 + 19a53 9 92 79 ++FUNC 19a5c 2f 0 dwarf2reader::CompilationUnit::Abbrev* std::uninitialized_copy(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*) + 19a5c c 108 79 + 19a68 23 113 79 + 19a8b 1 113 79 ++FUNC 19a8c 27 0 dwarf2reader::CompilationUnit::Abbrev* std::__uninitialized_copy_a(dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev*, std::allocator) + 19a8c c 252 79 + 19a98 1b 254 79 + 19ab3 1 254 79 ++FUNC 19ab4 7e 0 void std::__uninitialized_fill_n_aux(dwarf2reader::CompilationUnit::Abbrev*, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&, __false_type) + 19ab4 d 188 79 + 19ac1 6 190 79 + 19ac7 2 193 79 + 19ac9 12 194 79 + 19adb 16 193 79 + 19af1 b 196 79 + 19afc 12 198 79 + 19b0e b 199 79 + 19b19 13 196 79 + 19b2c 6 199 79 ++FUNC 19b32 2f 0 void std::uninitialized_fill_n(dwarf2reader::CompilationUnit::Abbrev*, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&) + 19b32 c 214 79 + 19b3e 23 218 79 + 19b61 1 218 79 ++FUNC 19b62 27 0 void std::__uninitialized_fill_n_a(dwarf2reader::CompilationUnit::Abbrev*, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&, std::allocator) + 19b62 c 308 79 + 19b6e 1b 310 79 + 19b89 1 310 79 ++FUNC 19b8a a5 0 dwarf2reader::CompilationUnit::Abbrev* std::__uninitialized_copy_aux<__gnu_cxx::__normal_iterator > >, dwarf2reader::CompilationUnit::Abbrev*>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, dwarf2reader::CompilationUnit::Abbrev*, __false_type) + 19b8a d 80 79 + 19b97 6 82 79 + 19b9d 2 85 79 + 19b9f 1a 86 79 + 19bb9 27 85 79 + 19be0 b 87 79 + 19beb b 89 79 + 19bf6 12 91 79 + 19c08 b 92 79 + 19c13 13 89 79 + 19c26 9 92 79 + 19c2f 1 92 79 ++FUNC 19c30 2f 0 dwarf2reader::CompilationUnit::Abbrev* std::uninitialized_copy<__gnu_cxx::__normal_iterator > >, dwarf2reader::CompilationUnit::Abbrev*>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, dwarf2reader::CompilationUnit::Abbrev*) + 19c30 c 108 79 + 19c3c 23 113 79 + 19c5f 1 113 79 ++FUNC 19c60 27 0 dwarf2reader::CompilationUnit::Abbrev* std::__uninitialized_copy_a<__gnu_cxx::__normal_iterator > >, dwarf2reader::CompilationUnit::Abbrev*, dwarf2reader::CompilationUnit::Abbrev>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, dwarf2reader::CompilationUnit::Abbrev*, std::allocator) + 19c60 c 252 79 + 19c6c 1b 254 79 + 19c87 1 254 79 ++FUNC 19c88 5f8 0 std::vector >::_M_fill_insert(__gnu_cxx::__normal_iterator > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&) + 19c88 15 311 79 +-19c9d b 313 79 +-19ca8 2a 315 79 +-19cd2 12 318 79 +-19ce4 23 319 79 +-19d07 15 320 79 +-19d1c c 321 79 +-19d28 5a 323 79 +-19d82 1c 327 79 +-19d9e 35 328 79 +-19dd3 16 323 79 +-19de9 30 330 79 +-19e19 10 343 79 +-19e29 48 334 79 +-19e71 21 338 79 +-19e92 3d 339 79 +-19ecf 13 334 79 +-19ee2 b 339 79 +-19eed 1c 342 79 +-19f09 1e 343 79 +-19f27 13 339 79 +-19f3a 24 343 79 +-19f5e e 348 79 +-19f6c 1e 349 79 +-19f8a e 350 79 +-19f98 1d 353 79 +-19fb5 8 354 79 +-19fbd e 355 79 +-19fcb 27 357 79 +-19ff2 6 358 79 +-19ff8 4d 361 79 +-1a045 40 365 79 +-1a085 18 367 79 +-1a09d 44 368 79 +-1a0e1 3 365 79 +-1a0e4 19 361 79 +-1a0fd 13 365 79 +-1a110 e 368 79 +-1a11e 3e 379 79 +-1a15c 36 381 79 +-1a192 12 384 79 +-1a1a4 13 385 79 +-1a1b7 2e 386 79 +-1a1e5 e 368 79 +-1a1f3 b 372 79 +-1a1fe 39 374 79 +-1a237 23 376 79 +-1a25a b 377 79 +-1a265 13 372 79 +-1a278 8 386 79 ++19c9d b 313 78 ++19ca8 2a 315 78 ++19cd2 12 318 78 ++19ce4 23 319 78 ++19d07 15 320 78 ++19d1c c 321 78 ++19d28 5a 323 78 ++19d82 1c 327 78 ++19d9e 35 328 78 ++19dd3 16 323 78 ++19de9 30 330 78 ++19e19 10 343 78 ++19e29 48 334 78 ++19e71 21 338 78 ++19e92 3d 339 78 ++19ecf 13 334 78 ++19ee2 b 339 78 ++19eed 1c 342 78 ++19f09 1e 343 78 ++19f27 13 339 78 ++19f3a 24 343 78 ++19f5e e 348 78 ++19f6c 1e 349 78 ++19f8a e 350 78 ++19f98 1d 353 78 ++19fb5 8 354 78 ++19fbd e 355 78 ++19fcb 27 357 78 ++19ff2 6 358 78 ++19ff8 4d 361 78 ++1a045 40 365 78 ++1a085 18 367 78 ++1a09d 44 368 78 ++1a0e1 3 365 78 ++1a0e4 19 361 78 ++1a0fd 13 365 78 ++1a110 e 368 78 ++1a11e 3e 379 78 ++1a15c 36 381 78 ++1a192 12 384 78 ++1a1a4 13 385 78 ++1a1b7 2e 386 78 ++1a1e5 e 368 78 ++1a1f3 b 372 78 ++1a1fe 39 374 78 ++1a237 23 376 78 ++1a25a b 377 78 ++1a265 13 372 78 ++1a278 8 386 78 ++FUNC 1a280 2e 0 std::vector >::insert(__gnu_cxx::__normal_iterator > >, unsigned long, dwarf2reader::CompilationUnit::Abbrev const&) + 1a280 c 657 79 +-1a28c 22 658 79 ++1a28c 22 658 71 ++FUNC 1a2ae ab 0 std::vector >::resize(unsigned long, dwarf2reader::CompilationUnit::Abbrev const&) + 1a2ae d 422 79 +-1a2bb 15 424 79 +-1a2d0 48 425 79 +-1a318 41 427 79 +-1a359 1 427 79 ++1a2bb 15 424 71 ++1a2d0 48 425 71 ++1a318 41 427 71 ++1a359 1 427 71 ++FUNC 1a35a 63 0 std::vector >::resize(unsigned long) + 1a35a d 441 79 +-1a367 56 442 79 +-1a3bd 1 442 79 ++1a367 56 442 71 ++1a3bd 1 442 71 ++FUNC 1a3be 13 0 std::_Deque_iterator::operator*() const + 1a3be c 134 79 +-1a3ca 7 135 79 +-1a3d1 1 135 79 +-FUNC 1a3d2 3f 0 copy +-1a3d2 c 298 79 +-1a3de 22 300 79 +-1a400 11 301 79 +-1a411 1 301 79 ++1a3ca 7 135 62 ++1a3d1 1 135 62 ++FUNC 1a3d2 3f 0 unsigned long long** std::__copy::copy(unsigned long long* const*, unsigned long long* const*, unsigned long long**) ++1a3d2 c 298 61 ++1a3de 22 300 61 ++1a400 11 301 61 ++1a411 1 301 61 ++FUNC 1a412 2b 0 unsigned long long** std::__copy_aux(unsigned long long**, unsigned long long**, unsigned long long**) + 1a412 c 307 79 +-1a41e 4 315 79 +-1a422 1b 317 79 +-1a43d 1 317 79 +-FUNC 1a43e 27 0 copy_n +-1a43e c 325 79 +-1a44a 1b 326 79 +-1a465 1 326 79 ++1a41e 4 315 61 ++1a422 1b 317 61 ++1a43d 1 317 61 ++FUNC 1a43e 27 0 unsigned long long** std::__copy_normal::copy_n(unsigned long long**, unsigned long long**, unsigned long long**) ++1a43e c 325 61 ++1a44a 1b 326 61 ++1a465 1 326 61 ++FUNC 1a466 2f 0 unsigned long long** std::copy(unsigned long long**, unsigned long long**, unsigned long long**) + 1a466 c 376 79 +-1a472 4 384 79 +-1a476 4 385 79 +-1a47a 1b 387 79 +-1a495 1 387 79 +-FUNC 1a496 60 0 copy_b +-1a496 d 422 79 +-1a4a3 12 424 79 +-1a4b5 2e 425 79 +-1a4e3 13 426 79 ++1a472 4 384 61 ++1a476 4 385 61 ++1a47a 1b 387 61 ++1a495 1 387 61 ++FUNC 1a496 60 0 unsigned long long** std::__copy_backward::copy_b(unsigned long long* const*, unsigned long long* const*, unsigned long long**) ++1a496 d 422 61 ++1a4a3 12 424 61 ++1a4b5 2e 425 61 ++1a4e3 13 426 61 ++FUNC 1a4f6 2b 0 unsigned long long** std::__copy_backward_aux(unsigned long long**, unsigned long long**, unsigned long long**) + 1a4f6 c 432 79 +-1a502 4 440 79 +-1a506 1b 443 79 +-1a521 1 443 79 +-FUNC 1a522 27 0 copy_b_n +-1a522 c 451 79 +-1a52e 1b 452 79 +-1a549 1 452 79 ++1a502 4 440 61 ++1a506 1b 443 61 ++1a521 1 443 61 ++FUNC 1a522 27 0 unsigned long long** std::__copy_backward_normal::copy_b_n(unsigned long long**, unsigned long long**, unsigned long long**) ++1a522 c 451 61 ++1a52e 1b 452 61 ++1a549 1 452 61 ++FUNC 1a54a 2f 0 unsigned long long** std::copy_backward(unsigned long long**, unsigned long long**, unsigned long long**) + 1a54a c 504 79 +-1a556 4 514 79 +-1a55a 4 515 79 +-1a55e 1b 517 79 +-1a579 1 517 79 ++1a556 4 514 61 ++1a55a 4 515 61 ++1a55e 1b 517 61 ++1a579 1 517 61 ++FUNC 1a57a 1df 0 std::deque >::_M_reallocate_map(unsigned long, bool) + 1a57a 13 723 79 +-1a58d 1b 726 79 +-1a5a8 9 727 79 +-1a5b1 13 730 79 +-1a5c4 39 732 79 +-1a5fd b 735 79 +-1a608 27 736 79 +-1a62f 2f 740 79 +-1a65e 26 748 79 +-1a684 15 750 79 +-1a699 36 751 79 +-1a6cf 22 753 79 +-1a6f1 1e 756 79 +-1a70f 8 758 79 +-1a717 9 759 79 +-1a720 15 762 79 +-1a735 24 763 79 +-1a759 1 763 79 ++1a58d 1b 726 76 ++1a5a8 9 727 76 ++1a5b1 13 730 76 ++1a5c4 39 732 76 ++1a5fd b 735 76 ++1a608 27 736 76 ++1a62f 2f 740 76 ++1a65e 26 748 76 ++1a684 15 750 76 ++1a699 36 751 76 ++1a6cf 22 753 76 ++1a6f1 1e 756 76 ++1a70f 8 758 76 ++1a717 9 759 76 ++1a720 15 762 76 ++1a735 24 763 76 ++1a759 1 763 76 ++FUNC 1a75a 59 0 std::deque >::_M_reserve_map_at_back(unsigned long) + 1a75a e 1443 79 +-1a768 2a 1445 79 +-1a792 21 1447 79 +-1a7b3 1 1447 79 ++1a768 2a 1445 62 ++1a792 21 1447 62 ++1a7b3 1 1447 62 ++FUNC 1a7b4 8c 0 std::deque >::_M_push_back_aux(unsigned long long const&) + 1a7b4 c 345 79 +-1a7c0 e 347 79 +-1a7ce 13 348 79 +-1a7e1 18 349 79 +-1a7f9 1e 352 79 +-1a817 1b 353 79 +-1a832 c 355 79 +-1a83e 2 360 79 ++1a7c0 e 347 76 ++1a7ce 13 348 76 ++1a7e1 18 349 76 ++1a7f9 1e 352 76 ++1a817 1b 353 76 ++1a832 c 355 76 ++1a83e 2 360 76 ++FUNC 1a840 62 0 std::deque >::push_back(unsigned long long const&) + 1a840 c 1039 79 +-1a84c 13 1041 79 +-1a85f 1e 1044 79 +-1a87d 11 1045 79 +-1a88e 14 1048 79 ++1a84c 13 1041 62 ++1a85f 1e 1044 62 ++1a87d 11 1045 62 ++1a88e 14 1048 62 ++FUNC 1a8a2 20 0 std::stack > >::push(unsigned long long const&) + 1a8a2 c 190 79 +-1a8ae 14 191 79 +-FUNC 1a8c2 27 0 copy_n +-1a8c2 c 325 79 +-1a8ce 1b 326 79 +-1a8e9 1 326 79 ++1a8ae 14 191 75 ++FUNC 1a8c2 27 0 unsigned char* std::__copy_normal::copy_n(unsigned char*, unsigned char*, unsigned char*) ++1a8c2 c 325 61 ++1a8ce 1b 326 61 ++1a8e9 1 326 61 ++FUNC 1a8ea 2f 0 unsigned char* std::copy(unsigned char*, unsigned char*, unsigned char*) + 1a8ea c 376 79 +-1a8f6 4 384 79 +-1a8fa 4 385 79 +-1a8fe 1b 387 79 +-1a919 1 387 79 ++1a8f6 4 384 61 ++1a8fa 4 385 61 ++1a8fe 1b 387 61 ++1a919 1 387 61 ++FUNC 1a91a 27 0 unsigned char* std::__uninitialized_copy_aux(unsigned char*, unsigned char*, unsigned char*, __true_type) + 1a91a c 73 79 + 1a926 1b 74 79 + 1a941 1 74 79 ++FUNC 1a942 2f 0 unsigned char* std::uninitialized_copy(unsigned char*, unsigned char*, unsigned char*) + 1a942 c 108 79 + 1a94e 23 113 79 + 1a971 1 113 79 ++FUNC 1a972 27 0 unsigned char* std::__uninitialized_copy_a(unsigned char*, unsigned char*, unsigned char*, std::allocator) + 1a972 c 252 79 + 1a97e 1b 254 79 + 1a999 1 254 79 +-FUNC 1a99a 40 0 copy_n<__gnu_cxx::__normal_iterator > >, unsigned char*> +-1a99a d 334 79 +-1a9a7 33 335 79 ++FUNC 1a99a 40 0 unsigned char* std::__copy_normal::copy_n<__gnu_cxx::__normal_iterator > >, unsigned char*>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, unsigned char*) ++1a99a d 334 61 ++1a9a7 33 335 61 ++FUNC 1a9da 2f 0 unsigned char* std::copy<__gnu_cxx::__normal_iterator > >, unsigned char*>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, unsigned char*) + 1a9da c 376 79 +-1a9e6 4 384 79 +-1a9ea 4 385 79 +-1a9ee 1b 387 79 +-1aa09 1 387 79 ++1a9e6 4 384 61 ++1a9ea 4 385 61 ++1a9ee 1b 387 61 ++1aa09 1 387 61 ++FUNC 1aa0a 27 0 unsigned char* std::__uninitialized_copy_aux<__gnu_cxx::__normal_iterator > >, unsigned char*>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, unsigned char*, __true_type) + 1aa0a c 73 79 + 1aa16 1b 74 79 + 1aa31 1 74 79 ++FUNC 1aa32 2f 0 unsigned char* std::uninitialized_copy<__gnu_cxx::__normal_iterator > >, unsigned char*>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, unsigned char*) + 1aa32 c 108 79 + 1aa3e 23 113 79 + 1aa61 1 113 79 ++FUNC 1aa62 27 0 unsigned char* std::__uninitialized_copy_a<__gnu_cxx::__normal_iterator > >, unsigned char*, unsigned char>(__gnu_cxx::__normal_iterator > >, __gnu_cxx::__normal_iterator > >, unsigned char*, std::allocator) + 1aa62 c 252 79 + 1aa6e 1b 254 79 + 1aa89 1 254 79 +-FUNC 1aa8a 45 0 fill_n<__gnu_cxx::__normal_iterator > >, long unsigned int, unsigned char> +-1aa8a c 614 79 +-1aa96 9 616 79 +-1aa9f 2 617 79 +-1aaa1 13 618 79 +-1aab4 16 617 79 +-1aaca 5 619 79 +-1aacf 1 619 79 +-1aad0 c 636 79 +-1aadc 4 641 79 +-1aae0 1b 642 79 +-1aafb 1 642 79 ++1aa96 9 616 61 ++1aa9f 2 617 61 ++1aaa1 13 618 61 ++1aab4 16 617 61 ++1aaca 5 619 61 ++1aacf 1 619 61 ++1aadc 4 641 61 ++1aae0 1b 642 61 ++1aafb 1 642 61 ++FUNC 1aafc 27 0 void std::__uninitialized_fill_n_aux<__gnu_cxx::__normal_iterator > >, unsigned long, unsigned char>(__gnu_cxx::__normal_iterator > >, unsigned long, unsigned char const&, __true_type) + 1aafc c 182 79 + 1ab08 1b 183 79 + 1ab23 1 183 79 ++FUNC 1ab24 2f 0 void std::uninitialized_fill_n<__gnu_cxx::__normal_iterator > >, unsigned long, unsigned char>(__gnu_cxx::__normal_iterator > >, unsigned long, unsigned char const&) + 1ab24 c 214 79 + 1ab30 23 218 79 + 1ab53 1 218 79 ++FUNC 1ab54 27 0 void std::__uninitialized_fill_n_a<__gnu_cxx::__normal_iterator > >, unsigned long, unsigned char, unsigned char>(__gnu_cxx::__normal_iterator > >, unsigned long, unsigned char const&, std::allocator) + 1ab54 c 308 79 + 1ab60 1b 310 79 + 1ab7b 1 310 79 ++FUNC 1ab7c 45a 0 std::vector >::_M_fill_insert(__gnu_cxx::__normal_iterator > >, unsigned long, unsigned char const&) + 1ab7c 14 311 79 +-1ab90 b 313 79 +-1ab9b 21 315 79 +-1abbc 9 318 79 +-1abc5 23 319 79 +-1abe8 15 320 79 +-1abfd c 321 79 +-1ac09 4e 323 79 +-1ac57 11 327 79 +-1ac68 30 328 79 +-1ac98 35 330 79 +-1accd 48 334 79 +-1ad15 14 338 79 +-1ad29 43 339 79 +-1ad6c 11 342 79 +-1ad7d 1e 343 79 +-1ad9b e 348 79 +-1ada9 1e 349 79 +-1adc7 e 350 79 +-1add5 1d 353 79 +-1adf2 8 354 79 +-1adfa e 355 79 +-1ae08 27 357 79 +-1ae2f 6 358 79 +-1ae35 4d 361 79 +-1ae82 40 365 79 +-1aec2 18 367 79 +-1aeda 4d 368 79 +-1af27 3e 379 79 +-1af65 2d 381 79 +-1af92 12 384 79 +-1afa4 13 385 79 +-1afb7 1f 386 79 ++1ab90 b 313 78 ++1ab9b 21 315 78 ++1abbc 9 318 78 ++1abc5 23 319 78 ++1abe8 15 320 78 ++1abfd c 321 78 ++1ac09 4e 323 78 ++1ac57 11 327 78 ++1ac68 30 328 78 ++1ac98 35 330 78 ++1accd 48 334 78 ++1ad15 14 338 78 ++1ad29 43 339 78 ++1ad6c 11 342 78 ++1ad7d 1e 343 78 ++1ad9b e 348 78 ++1ada9 1e 349 78 ++1adc7 e 350 78 ++1add5 1d 353 78 ++1adf2 8 354 78 ++1adfa e 355 78 ++1ae08 27 357 78 ++1ae2f 6 358 78 ++1ae35 4d 361 78 ++1ae82 40 365 78 ++1aec2 18 367 78 ++1aeda 4d 368 78 ++1af27 3e 379 78 ++1af65 2d 381 78 ++1af92 12 384 78 ++1afa4 13 385 78 ++1afb7 1f 386 78 ++FUNC 1afd6 2e 0 std::vector >::insert(__gnu_cxx::__normal_iterator > >, unsigned long, unsigned char const&) + 1afd6 c 657 79 +-1afe2 22 658 79 ++1afe2 22 658 71 ++FUNC 1b004 ab 0 std::vector >::resize(unsigned long, unsigned char const&) + 1b004 d 422 79 +-1b011 15 424 79 +-1b026 48 425 79 +-1b06e 41 427 79 +-1b0af 1 427 79 ++1b011 15 424 71 ++1b026 48 425 71 ++1b06e 41 427 71 ++1b0af 1 427 71 ++FUNC 1b0b0 2b 0 std::vector >::resize(unsigned long) + 1b0b0 c 441 79 +-1b0bc 1f 442 79 +-1b0db 1 442 79 ++1b0bc 1f 442 71 ++1b0db 1 442 71 ++FUNC 1b0dc 1a 0 std::_Deque_iterator::_S_buffer_size() + 1b0dc c 106 79 +-1b0e8 e 107 79 ++1b0e8 e 107 62 ++FUNC 1b0f6 66 0 std::_Deque_iterator::difference_type std::operator-(std::_Deque_iterator const&, std::_Deque_iterator const&) + 1b0f6 d 328 79 +-1b103 59 333 79 ++1b103 59 333 62 ++FUNC 1b15c 3e 0 std::_Deque_iterator::_M_set_node(unsigned long long**) + 1b15c d 229 79 +-1b169 9 231 79 +-1b172 b 232 79 +-1b17d 1d 233 79 ++1b169 9 231 62 ++1b172 b 232 62 ++1b17d 1d 233 62 ++FUNC 1b19a 50 0 std::_Deque_iterator::operator++() + 1b19a c 142 79 +-1b1a6 d 144 79 +-1b1b3 f 145 79 +-1b1c2 18 147 79 +-1b1da b 148 79 +-1b1e5 5 150 79 +-FUNC 1b1ea 84 0 copy, std::_Deque_iterator > +-1b1ea e 280 79 +-1b1f8 17 283 79 +-1b20f 20 285 79 +-1b22f b 286 79 +-1b23a b 287 79 +-1b245 b 283 79 +-1b250 1e 289 79 ++1b1a6 d 144 62 ++1b1b3 f 145 62 ++1b1c2 18 147 62 ++1b1da b 148 62 ++1b1e5 5 150 62 ++FUNC 1b1ea 84 0 std::_Deque_iterator std::__copy::copy, std::_Deque_iterator >(std::_Deque_iterator, std::_Deque_iterator, std::_Deque_iterator) ++1b1ea e 280 61 ++1b1f8 17 283 61 ++1b20f 20 285 61 ++1b22f b 286 61 ++1b23a b 287 61 ++1b245 b 283 61 ++1b250 1e 289 61 ++FUNC 1b26e 7e 0 std::_Deque_iterator std::__copy_aux, std::_Deque_iterator >(std::_Deque_iterator, std::_Deque_iterator, std::_Deque_iterator) + 1b26e 11 307 79 +-1b27f 4 315 79 +-1b283 69 317 79 +-FUNC 1b2ec 7a 0 copy_n, std::_Deque_iterator > +-1b2ec 11 325 79 +-1b2fd 69 326 79 ++1b27f 4 315 61 ++1b283 69 317 61 ++FUNC 1b2ec 7a 0 std::_Deque_iterator std::__copy_normal::copy_n, std::_Deque_iterator >(std::_Deque_iterator, std::_Deque_iterator, std::_Deque_iterator) ++1b2ec 11 325 61 ++1b2fd 69 326 61 ++FUNC 1b366 82 0 std::_Deque_iterator std::copy, std::_Deque_iterator >(std::_Deque_iterator, std::_Deque_iterator, std::_Deque_iterator) + 1b366 11 376 79 +-1b377 4 384 79 +-1b37b 4 385 79 +-1b37f 69 387 79 ++1b377 4 384 61 ++1b37b 4 385 61 ++1b37f 69 387 61 ++FUNC 1b3e8 7a 0 std::_Deque_iterator std::__uninitialized_copy_aux, std::_Deque_iterator >(std::_Deque_iterator, std::_Deque_iterator, std::_Deque_iterator, __true_type) + 1b3e8 11 73 79 + 1b3f9 69 74 79 ++FUNC 1b462 82 0 std::_Deque_iterator std::uninitialized_copy, std::_Deque_iterator >(std::_Deque_iterator, std::_Deque_iterator, std::_Deque_iterator) + 1b462 11 108 79 + 1b473 71 113 79 ++FUNC 1b4e4 7a 0 std::_Deque_iterator std::__uninitialized_copy_a, std::_Deque_iterator, unsigned long long>(std::_Deque_iterator, std::_Deque_iterator, std::_Deque_iterator, std::allocator) + 1b4e4 11 252 79 + 1b4f5 69 254 79 +-1b55e 10 679 79 +-1b56e 64 680 79 +-1b5d2 e8 681 79 +-1b6ba c 143 79 +-1b6c6 14 144 79 +-1b6da 6 144 79 ++1b55e 10 679 62 ++1b56e 64 680 62 ++1b5d2 e8 681 62 ++1b6ba c 143 75 ++1b6c6 14 144 75 ++1b6da 6 144 75 + FUNC 1b6e0 4d 0 __eprintf + 1b6e0 6 1826 80 + 1b6e6 3 1832 80 + 1b6e9 c 1826 80 + 1b6f5 29 1832 80 + 1b71e a 1837 80 + 1b728 5 1838 80 + 1b72d e8d3 1838 80 +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/sender/Breakpad.nib/classes.nib b/toolkit/crashreporter/google-breakpad/src/client/mac/sender/Breakpad.nib/classes.nib +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/sender/Breakpad.nib/classes.nib +@@ -0,0 +1,69 @@ ++ ++ ++ ++ ++ IBClasses ++ ++ ++ CLASS ++ LengthLimitingTextField ++ LANGUAGE ++ ObjC ++ SUPERCLASS ++ NSTextField ++ ++ ++ ACTIONS ++ ++ cancel ++ id ++ sendReport ++ id ++ showPrivacyPolicy ++ id ++ ++ CLASS ++ Reporter ++ LANGUAGE ++ ObjC ++ OUTLETS ++ ++ alertWindow_ ++ NSWindow ++ cancelButton_ ++ NSButton ++ commentMessage_ ++ NSTextField ++ commentsEntryField_ ++ LengthLimitingTextField ++ countdownLabel_ ++ NSTextField ++ dialogTitle_ ++ NSTextField ++ emailEntryField_ ++ LengthLimitingTextField ++ emailLabel_ ++ NSTextField ++ emailMessage_ ++ NSTextField ++ emailSectionBox_ ++ NSBox ++ headerBox_ ++ NSBox ++ preEmailBox_ ++ NSBox ++ privacyLinkArrow_ ++ NSView ++ privacyLinkLabel_ ++ NSTextField ++ sendButton_ ++ NSButton ++ ++ SUPERCLASS ++ NSObject ++ ++ ++ IBVersion ++ 1 ++ ++ +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/sender/Breakpad.nib/info.nib b/toolkit/crashreporter/google-breakpad/src/client/mac/sender/Breakpad.nib/info.nib +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/sender/Breakpad.nib/info.nib +@@ -0,0 +1,20 @@ ++ ++ ++ ++ ++ IBFramework Version ++ 676 ++ IBLastKnownRelativeProjectPath ++ ../Breakpad.xcodeproj ++ IBOldestOS ++ 5 ++ IBOpenObjects ++ ++ 132 ++ ++ IBSystem Version ++ 9J61 ++ targetFramework ++ IBCocoaFramework ++ ++ +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/sender/Breakpad.nib/keyedobjects.nib b/toolkit/crashreporter/google-breakpad/src/client/mac/sender/Breakpad.nib/keyedobjects.nib +new file mode 100644 +index 0000000000000000000000000000000000000000..e370206c166426f1ec3ff2a9578fe891ac3a5190 +GIT binary patch +literal 14674 +zc%1Ee33L?2`fpWrPi9Fn=~*OXCdu?{tVwqg_C+8hED;ESgb+v|OeRe-GMNc86GDJM +zjev?PiwX!Tt6oGz+^*MMK~cFXE(jtZsJMXpu2Zxh;`@)f&oOcmM1Tlz3DwKe8w)rW_s0Y9U_1nmz!j(wPs1MEgj;YF +zufR9p)p!lwi0{JN@xAy#yc<7*pT&FeKKv4X1^*Mjj^D%w@mu&XK7x&W$FHMxVVC3lj$$lc@~vYp&V{zi6?-DD5>2YHgbNcN&cvX8t(UMBm=YvceqNZumv +zk;CK|IZjTJ)8tcfmV8ORBj1x>$RFfShA<4HVYG~%Nny;)6^waF}E|e<}v1< +z%*V_p%xUIR<}>DV<_qQwbC&s%`HK0P`G)zH`HuOX`GNV7`HA_N`Gxs|#cV&;$6n3O +zVf}0a8(@QMBRiK3v0*mCHnH>AW_CW?!Y*JJvWwVObe3JrE@3GfWv^kEvdh@z?6vH5 +z?Dgml^aHzsy@9=vy@|bhsOPjLmB{QeI)BT7bk +zl!7>9Kt^OjW^@JWf>Kdel!h$GiqcUA%0xEABRg^+CvqV->V~?b9;hekg?ghbl#K)= +zqMY*L(#gSKq}=88d&1!v#ibKt!41(HR>HVIZkNL49)FVrEosH2`ChLS4*P0+eqW?z +zqOUgo4Eh!X0|Dp^ITNldE-m&nNXj^HJvsz8&B4%|8SNv=Po~3sFo1kHBi`Y^nkYVY +zFeFQk4hA9&ep%L&MPsFkBpQ!c@H}HpfU*uoV@cLNo-HGNCEr0gIGMktxNc@EPkl8jYcoc5@aq +z78RkZ&^R<6O+dwHA}T?X&}3AK%Fq;4j;5jtG!0Ehm8c5MKr>M_nuR=6OVem?I*6{N +z>*)r1H{C?H&~0=(y^rpoJLxXEo9>~H&`0Ux^a=VTeVV>NUwId1^`crNq1mVo!qEr5 +zE0n?!U%(?r2`sfV*c9?gQ;SQ-duk*5(O_suq!9cAPni>x>2lIuC!> +zUNho6j9DrLYGVnbgn=A3o6#1u6>US?(Y@$CaH?$R@)$;dBWEiUP@{81FQoiYgMl?y +zjc@Y$YCU5@9*BroQrwSrZb3WIkn$L4luSyFweLm`Z9@;CJrH7Yy2P}W7g8kyg&dsn +zO-%L?^yqfg^fh0Mu+QYFj3`>g1RmVno5_z*~OX%fza_ps6+LNZ!3^|~! +z7YFnK2j#mWt3+;&9K?NFTaPG_`))j9SE57c +zJ#-iyLGPoZpxZHYyqYtBSv=l3b)jHWptd0B4~D=TWssrDwUITP8$o+eo@P=TwHVPz +z7Ew1uZb=A&&)ZTG^!vOmmpK0vIR9hW%iY?&oRoeD1Wuz*(P!v$^aVPD&Y~~TS5swY +zz(iH?@6tw(SE`KP$U!5=F_1HVuug$!7j<$8)Isg#r7huz)KKM(xl)mT2WI#beFvle +zfPRFLr`G!-(1l~hZg1+#Rg-KZV1FFt&`K{`%x +zp1MZn#KyxIlWmy9;!;UAxyNXqe;D*MSLC5<7a};w{cZegb +zMK+uWag+sdH1KFFj&O2&B<0Dmgi|nw4cLfHax~#CXs-f06GOf_fNlSUUCv4eP>~8W +z2e_>qYT48Z`|NlrP#38m?`!Y@%GY(!%)D^nzyVqOASJK{$uTylwe@J{z`|CXjt=1r +zbQs$J4v%6jcA{qN#@&!xy4V(W}G{j;;^-A?HdXA(&FZmD}c?%ZG5wqb3Nq +zEF%Zurlq;GUq!G{&TWsslfQ5;bQbqk{MDECk^N)t1q{S~y@Py~c +z^1gs9Um3$kWk}d?Z>OuN$;d;gMTgQM^fr!gn69A+qG#d40eM+`UOxqX`VIp4={pd@ +zB+g!NC7rY#5UdW*#MO8fpqGwT(pmJT6KD>u0n>OPoNHyU!xB_IvvD1oi|c_q{D7~< +zbFd#b-~bNdMhNQ=e1_0o&~apNepySStfOKIInBTbWw3{Y8$BV|4CU=17=rkc#h}B) +z*|Wn^B*rq8E+xURPmZb??fYkWj9E;l<+MyghZ``*A;^#^&}MC0OEaCcS;p$N`-QMJ +zya*zGFb3aauZz6n@O7T?(9 +zp9culu{%Hz5Q3%v+x7z1|29dC{~KDKrD +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 +zh`vV;(m;#p~2;Gj%~mV|Fsa`<39&& +z|K6{jom`ZA@ow7TwO`Mw_A9g(fo;70V40a}4&CX&yYz^yW +zYgvh%&DOE?^eg%`{f2%^zoXyNALx(tC;Bt}h5kx^qrcOC(Ld;)^c+1O#VCq#6q6`s +zqL__hRTL*gu{w%1QLK$(T@)uqaZ(f~N3lMNQ=*uQVnY-gqu3P1<|w`*in~N{Y7}>k +z;lC@~)- +zkCO9D0+Y;GnQW$rnF9Qh;3!BVOOztvb)&F*%#Qo>^}B&_FeWA`x*N! +z`@O2Cs<$dzC8}~&eN_Ea15|@lLsVC)hO6>b1*%c1F{&cfIMoEzMAal!scMR9s%o05 +zQZ+*rP%Tm|SKX|-RkcdBMs>UDan&oTgQ~--ld3bSA5`ZPZ~~K{N>C^05)u=V6H*eg +z5(Xp`B#cTJlTef}KA||FBw=#GoPMm+tEvQGRC#Wmcv(z=} +zTJ>yoz4~gkUmZ|4szd6Cx+HIoy572M-5}ja-56b!Zl-RQu0~g@Yt}8( +zU8`H6Tdmum+ogM4_k!+q-6`Gox*v5v>weY!p6E;*lsF{u%EaM``H2OIqZ7v@7A1~L +zoRC+pNduAw +zB@IoQlvJ8DC24BXv?OnmKWT0fO?oAnO8s2`*sr=O;;)X&gY>pl7!eXYJu@6*rGH|T@pu!aPK#-KB#7z~CC!!W}L!$?D+VYFe4p~x`K;5Do>+-ulv +z*kgFa@R;H6hJP5IGCX5=&hUa^pW$`GF~b*zUk$$-{xF;~CK&a`RAahPG!8TlHx?Vq +zjUMCG#<|87#+Alh#@)s}#z%~g8UJp4#`uQupz&?vyT((-kB#3Me>X8Et*MtO%Osd` +zOnIh0rhcXYrV`U~({-j5rW;K+n{G9&GOaP)W7=#wYC2{*VLEC0$n>%4wCOX`7pAkO +zuS`Fiel`8e^rzWkPB&+od9%apGIukJ=3MhY^I-E(^DuL@*<<#aC3BtmYV#a(gE?rv +z-n_%S)4a>P+q}p8i21S9&8e@Y{xkKB)Pt#Sr@otdIQ2;C(bQw9CsKdzYVFE*b#!%g +z?bfwN*Ir$Fcg;?VrahVVblS6N&!@eZwm0piwEbzXrX5IoJ?*`;BWWL`9Z&l`?T@r` +z7Gxn7){qhGn)`RJ6x;uSjdPRCmdNh4S`l|Ge>6_EHrf*NbKYeHV6X{Q;Kb`(;`rGLrq<@tD +zb^0$EBtxIkH6tfuLdL|5Ng1UXQ!=Jz)Mm`in457!#(fz(GInO{%GjN;C*#?S=QB=a +ze4KGQAYn17%DfIrTEXD4>n +zo?zG5b@ndy?)IMc-u7&}Xdhu8X)m;owvV-!*gbZyU9#8NefE%jseQTqI{OOyjrMi+ +z9rm5}UH0AfJ@&o!llC+A9~~yg6^>L#n#1bIaM&D!9K#)x9hHt6#{$O&$9BhkjvbDj +zj$Mx3jy;Y?9IrW!I8Hmha(v_X-tnX37sqeTWT)NP%PBgCI%hbmogSyxDLLz$KIa_g +z66X!hwa)d%um9(R7|Jmvh@dD{7z^9$!$=U2{eoZmTraQ@`{#rd1_ +zU(P?B=Uv#vxKu8+OY1Va%&smjmn+*f!Zp%W;2Q5Lbp>1tUCUf6T&rETx%RqVa_x7$ +z>N?jj=Mf|opOEbI_>(*^@Z!K>nqncu3ufhyWQ^Y?w;=6 +z?rgW{&UN>3_j3<$4{{H2U+Et1&UY8MN4dwii`?Vf6WrzQ3ind?a`$!a7493|H@k0j +zuX3+(-|k-PUhm%EzRP`&d$W71d%OES_YU_?_kQ;~?q9nv>%Oh~o*rxuzDHK?ZoS9$ +zF7F-gy&&ss)^FKYWIM78vS()pv*%{d%buUTAbV-{^6VS3Z_2(Udu{gm>~jJVh`{O$d|BKt9u(ge-w}_Ar(!RW35k8Pn^C7f@!S6eAATCT + +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/sender/English.lproj/InfoPlist.strings b/toolkit/crashreporter/google-breakpad/src/client/mac/sender/English.lproj/InfoPlist.strings +new file mode 100644 +index 0000000000000000000000000000000000000000..65d161818a12f785bc58a885664ac859f1e755ff +GIT binary patch +literal 156 +zc%1wHPl>^q!HvO*p_CzyA%!7_A(g?8A(0^$NGmZYFxUbyNJSA)te7DK$O{6>6fooi +fMM{9IBA~1_0~Z6PDJ~3|Kph1@b|OP1S!MzN$P60z + +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/sender/English.lproj/Localizable.strings b/toolkit/crashreporter/google-breakpad/src/client/mac/sender/English.lproj/Localizable.strings +new file mode 100644 +index 0000000000000000000000000000000000000000..70626567c95f166a7ac0bf7d3b89d695264e4b1b +GIT binary patch +literal 2270 +zc%0=`%Wl&^6uoP{Vib{07mi>FLZTETBwDBl{eY?M#F6|WV>jgIfiq{u_L$hIRCR|e +zJM*}YbI!dp`SW`v7oub>jqGJ7rEJAuzL5%ZC3l#m9DT(~1B(sbSTx5K>=nKnd^O$} +zmKq)z#uu`Z7qSS}KEgvw4*RWqMpP{cV=rL+4(~#Kz$#^|8c%+bX({jV%@|L~Pie8! +zVANtam0$2l;nCom!22i>V!l0t;sz_*iTnn>hH(m_DG^VRf9BPgMrb^`2SzFBq2wO3 +zl=wB2+5{LQtX<;WV^&k~Cg3;t#kA1gOA&{r?GaurEi^3+J)BL|E9S-)dyYH`XcOAG +zdLDg5i@8Ro3Yl|q@AR_@S~geDUQ3H2CWn&j_MV|*W9NJ7GE{ON$Nx~xSMqYEqJ^)W +zL%WpMv#LOp@<$q +z3k~+;QH^%KmYrS)-zBN%RrH*!CXGj6Mim*5UE}wjiVv(l^}BC+4QeX;Ks3imuiKG@ +z!o2dGeGD>po%KEF)eqp+kaZcvTlYN}+79=s<_WeKrv0x1i|`D0ai_h$$(I?WDMyjFL3eSO0gl?#KKiE!<{3%%d6SWSaMvPPRc)PRX?x=)4Qu-cT^ZZw2Vt9gD +zc5YaaCDk({OLt4S`j)8``$Ksm`-2MwU-w7iN2m +JU6^k^+h4Dxg ++ ++ ++ ++ ActiveLayerIndex ++ 0 ++ ApplicationVersion ++ ++ com.omnigroup.OmniGrafflePro ++ 137.6.0.106738 ++ ++ AutoAdjust ++ ++ BackgroundGraphic ++ ++ Bounds ++ {{0, 0}, {512, 512}} ++ Class ++ SolidGraphic ++ FontInfo ++ ++ Font ++ CalisMTBol ++ Size ++ 112 ++ ++ ID ++ 2 ++ Style ++ ++ fill ++ ++ Color ++ ++ a ++ 0 ++ b ++ 0 ++ g ++ 0.852018 ++ r ++ 0.998962 ++ ++ ++ shadow ++ ++ Draws ++ NO ++ ++ stroke ++ ++ Draws ++ NO ++ ++ ++ ++ CanvasOrigin ++ {0, 0} ++ CanvasSize ++ {512, 512} ++ ColumnAlign ++ 1 ++ ColumnSpacing ++ 36 ++ CreationDate ++ 2008-11-14 16:58:15 -0700 ++ Creator ++ John P. Developer ++ DisplayScale ++ 1 pt = 1 px ++ FileType ++ flat ++ GraphDocumentVersion ++ 6 ++ GraphicsList ++ ++ ++ Bounds ++ {{33.9443, 35.3885}, {444.111, 437.112}} ++ Class ++ ShapedGraphic ++ FontInfo ++ ++ Font ++ CalisMTBol ++ Size ++ 112 ++ ++ ID ++ 31 ++ Rotation ++ 270 ++ Shape ++ Bezier ++ ShapeData ++ ++ UnitPoints ++ ++ {-0.5, -0.439247} ++ {-0.5, -0.485429} ++ {-0.446294, -0.512626} ++ {-0.409932, -0.494153} ++ {-0.373569, -0.47568} ++ {0.436363, -0.0733799} ++ {0.472729, -0.0549059} ++ {0.50909, -0.0364333} ++ {0.509091, 0.0364345} ++ {0.472729, 0.0549059} ++ {0.436368, 0.0733802} ++ {-0.373569, 0.475681} ++ {-0.409932, 0.494153} ++ {-0.446294, 0.512626} ++ {-0.500001, 0.485429} ++ {-0.5, 0.439247} ++ {-0.49998, 0.393072} ++ {-0.500002, -0.393066} ++ ++ ++ Style ++ ++ fill ++ ++ Color ++ ++ b ++ 0 ++ g ++ 0.770962 ++ r ++ 0.997971 ++ ++ Draws ++ NO ++ FillType ++ 3 ++ GradientCenter ++ {-0.609524, 0} ++ GradientColor ++ ++ b ++ 0 ++ g ++ 0.911574 ++ r ++ 0.998779 ++ ++ MiddleFraction ++ 0.6111111044883728 ++ ++ shadow ++ ++ Color ++ ++ a ++ 0.43 ++ b ++ 0 ++ g ++ 0 ++ r ++ 0 ++ ++ Draws ++ NO ++ Fuzziness ++ 7.2213706970214844 ++ ShadowVector ++ {0, 6} ++ ++ stroke ++ ++ Color ++ ++ b ++ 0 ++ g ++ 0.766903 ++ r ++ 0.997925 ++ ++ Width ++ 7 ++ ++ ++ Text ++ ++ Pad ++ 0 ++ VerticalPad ++ 0 ++ ++ TextPlacement ++ 0 ++ TextRelativeArea ++ {{0.06, 0.17}, {0.88, 0.5}} ++ TextRotation ++ 90 ++ Wrap ++ NO ++ ++ ++ Bounds ++ {{3.89085, 67.8908}, {404.218, 332}} ++ Class ++ ShapedGraphic ++ FontInfo ++ ++ Font ++ CalisMTBol ++ Size ++ 112 ++ ++ ID ++ 30 ++ Rotation ++ 270 ++ Shape ++ Bezier ++ ShapeData ++ ++ UnitPoints ++ ++ {-0.5, -0.5} ++ {-0.459695, -0.475464} ++ {0.429465, 0.0537758} ++ {0.469773, 0.0783133} ++ {0.510074, 0.102849} ++ {0.510077, 0.198357} ++ {0.469773, 0.222892} ++ {0.429473, 0.247428} ++ {-0.00521517, 0.499998} ++ {-0.00521785, 0.5} ++ {-0.00521713, -0.113381} ++ {-0.44962, -0.458615} ++ ++ ++ Style ++ ++ fill ++ ++ Color ++ ++ a ++ 0 ++ b ++ 1 ++ g ++ 1 ++ r ++ 1 ++ ++ FillType ++ 2 ++ GradientAngle ++ 180 ++ GradientCenter ++ {-0.609524, 0} ++ GradientColor ++ ++ a ++ 0.5 ++ w ++ 1 ++ ++ MiddleFraction ++ 0.6111111044883728 ++ ++ shadow ++ ++ Color ++ ++ a ++ 0.51 ++ b ++ 0 ++ g ++ 0 ++ r ++ 0 ++ ++ Draws ++ NO ++ Fuzziness ++ 3.3371961116790771 ++ ShadowVector ++ {0, 2} ++ ++ stroke ++ ++ Color ++ ++ b ++ 0 ++ g ++ 0.766903 ++ r ++ 0.997925 ++ ++ Draws ++ NO ++ Width ++ 2 ++ ++ ++ Text ++ ++ Pad ++ 0 ++ VerticalPad ++ 0 ++ ++ TextPlacement ++ 0 ++ TextRelativeArea ++ {{0.06, 0.17}, {0.88, 0.5}} ++ TextRotation ++ 90 ++ Wrap ++ NO ++ ++ ++ Bounds ++ {{33.9443, 35.3886}, {444.112, 437.111}} ++ Class ++ ShapedGraphic ++ FontInfo ++ ++ Font ++ CalisMTBol ++ Size ++ 112 ++ ++ ID ++ 29 ++ Rotation ++ 270 ++ Shape ++ Bezier ++ ShapeData ++ ++ UnitPoints ++ ++ {-0.5, -0.439247} ++ {-0.500001, -0.485429} ++ {-0.446295, -0.512626} ++ {-0.409932, -0.494153} ++ {-0.373568, -0.475681} ++ {0.436363, -0.0733802} ++ {0.472729, -0.0549062} ++ {0.509089, -0.0364334} ++ {0.509092, 0.0364341} ++ {0.472729, 0.0549056} ++ {0.436369, 0.0733803} ++ {-0.373568, 0.475681} ++ {-0.409932, 0.494153} ++ {-0.446294, 0.512626} ++ {-0.500001, 0.485428} ++ {-0.5, 0.439248} ++ {-0.499978, 0.39307} ++ {-0.500003, -0.393066} ++ ++ ++ Style ++ ++ fill ++ ++ Color ++ ++ a ++ 0.2 ++ b ++ 1 ++ g ++ 1 ++ r ++ 1 ++ ++ FillType ++ 2 ++ GradientAngle ++ 90 ++ GradientCenter ++ {-0.609524, 0} ++ GradientColor ++ ++ a ++ 0 ++ w ++ 1 ++ ++ MiddleFraction ++ 0.6111111044883728 ++ ++ shadow ++ ++ Color ++ ++ a ++ 0.51 ++ b ++ 0 ++ g ++ 0 ++ r ++ 0 ++ ++ Draws ++ NO ++ Fuzziness ++ 3.3371961116790771 ++ ShadowVector ++ {0, 2} ++ ++ stroke ++ ++ Color ++ ++ b ++ 0 ++ g ++ 0.766903 ++ r ++ 0.997925 ++ ++ Draws ++ NO ++ Width ++ 2 ++ ++ ++ Text ++ ++ Pad ++ 0 ++ VerticalPad ++ 0 ++ ++ TextPlacement ++ 0 ++ TextRelativeArea ++ {{0.06, 0.17}, {0.88, 0.5}} ++ TextRotation ++ 90 ++ Wrap ++ NO ++ ++ ++ Bounds ++ {{176, 102.384}, {158.841, 537.616}} ++ Class ++ ShapedGraphic ++ FontInfo ++ ++ Font ++ CalisMTBol ++ Size ++ 425 ++ ++ ID ++ 26 ++ Shape ++ Rectangle ++ Style ++ ++ fill ++ ++ Draws ++ NO ++ ++ shadow ++ ++ Draws ++ NO ++ ++ stroke ++ ++ Draws ++ NO ++ ++ ++ Text ++ ++ Pad ++ 0 ++ Text ++ {\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf350 ++{\fonttbl\f0\fnil\fcharset0 CalistoMT;} ++{\colortbl;\red255\green255\blue255;} ++\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural ++ ++\f0\b\fs850 \cf1 !} ++ VerticalPad ++ 0 ++ ++ Wrap ++ NO ++ ++ ++ Bounds ++ {{176, 104}, {158.841, 537.616}} ++ Class ++ ShapedGraphic ++ FontInfo ++ ++ Color ++ ++ b ++ 0 ++ g ++ 0.749523 ++ r ++ 0.997726 ++ ++ Font ++ CalisMTBol ++ Size ++ 425 ++ ++ ID ++ 27 ++ Shape ++ Rectangle ++ Style ++ ++ fill ++ ++ Draws ++ NO ++ ++ shadow ++ ++ Draws ++ NO ++ ++ stroke ++ ++ Draws ++ NO ++ ++ ++ Text ++ ++ Pad ++ 0 ++ RTFD ++ ++ BAtzdHJlYW10eXBlZIHoA4QBQISEhBJOU0F0dHJpYnV0 ++ ZWRTdHJpbmcAhIQITlNPYmplY3QAhZKEhIQITlNTdHJp ++ bmcBlIQBKwEhhoQCaUkBAZKEhIQMTlNEaWN0aW9uYXJ5 ++ AJSEAWkEkoSWlhBOU1BhcmFncmFwaFN0eWxlhpKEhIQQ ++ TlNQYXJhZ3JhcGhTdHlsZQCUhARDQ0BTAgCEhIQHTlNB ++ cnJheQCUmQyShISECU5TVGV4dFRhYgCUhAJDZgAchpKE ++ n54AOIaShJ+eAFSGkoSfngBwhpKEn54AgYwAhpKEn54A ++ gagAhpKEn54AgcQAhpKEn54AgeAAhpKEn54AgfwAhpKE ++ n54AgRgBhpKEn54AgTQBhpKEn54AgVABhoYAhpKElpYG ++ TlNGb250hpKEhIQGTlNGb250HpSZIIQFWzMyY10GAAAA ++ FgAAAP/+QwBhAGwAaQBzAE0AVABCAG8AbAAAAIQBZoGp ++ AYQBYwCiAaIAogCGkoSWlg1OU1N0cm9rZVdpZHRohpKE ++ hIQITlNOdW1iZXIAhIQHTlNWYWx1ZQCUhAEqhIQBZKYD ++ hpKElpYHTlNDb2xvcoaShISEB05TQ29sb3IAlKIChARm ++ ZmZmAYN4dz8/AAGGhoY= ++ ++ Text ++ {\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf350 ++{\fonttbl\f0\fnil\fcharset0 CalistoMT;} ++{\colortbl;\red255\green255\blue255;\red254\green191\blue0;} ++\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural ++ ++\f0\b\fs850 \cf2 \outl\strokewidth60 \strokec2 !} ++ VerticalPad ++ 0 ++ ++ Wrap ++ NO ++ ++ ++ Bounds ++ {{33.9441, 35.3884}, {444.112, 437.111}} ++ Class ++ ShapedGraphic ++ FontInfo ++ ++ Font ++ CalisMTBol ++ Size ++ 112 ++ ++ ID ++ 16 ++ Rotation ++ 270 ++ Shape ++ Bezier ++ ShapeData ++ ++ UnitPoints ++ ++ {-0.5, -0.439247} ++ {-0.5, -0.485429} ++ {-0.446295, -0.512626} ++ {-0.409933, -0.494153} ++ {-0.373569, -0.47568} ++ {0.436363, -0.073379} ++ {0.472729, -0.0549049} ++ {0.50909, -0.0364324} ++ {0.509091, 0.0364344} ++ {0.472729, 0.0549058} ++ {0.436368, 0.0733801} ++ {-0.373569, 0.47568} ++ {-0.409933, 0.494153} ++ {-0.446295, 0.512626} ++ {-0.500001, 0.485429} ++ {-0.5, 0.439247} ++ {-0.49998, 0.393072} ++ {-0.500002, -0.393066} ++ ++ ++ Style ++ ++ fill ++ ++ Color ++ ++ b ++ 0 ++ g ++ 0.770962 ++ r ++ 0.997971 ++ ++ FillType ++ 3 ++ GradientCenter ++ {-0.609524, 0} ++ GradientColor ++ ++ b ++ 0 ++ g ++ 0.911574 ++ r ++ 0.998779 ++ ++ MiddleFraction ++ 0.6111111044883728 ++ ++ shadow ++ ++ Color ++ ++ a ++ 0.9 ++ b ++ 0 ++ g ++ 0 ++ r ++ 0 ++ ++ Fuzziness ++ 8.0632610321044922 ++ ShadowVector ++ {0, 9} ++ ++ stroke ++ ++ Color ++ ++ b ++ 0 ++ g ++ 0.766903 ++ r ++ 0.997925 ++ ++ Draws ++ NO ++ Width ++ 2 ++ ++ ++ Text ++ ++ Pad ++ 0 ++ VerticalPad ++ 0 ++ ++ TextPlacement ++ 0 ++ TextRelativeArea ++ {{0.06, 0.17}, {0.88, 0.5}} ++ TextRotation ++ 90 ++ Wrap ++ NO ++ ++ ++ GridInfo ++ ++ GridSpacing ++ 4 ++ ShowsGrid ++ YES ++ SnapsToGrid ++ YES ++ ++ GuidesLocked ++ NO ++ GuidesVisible ++ YES ++ HPages ++ 1 ++ ImageCounter ++ 2 ++ KeepToScale ++ ++ Layers ++ ++ ++ Lock ++ NO ++ Name ++ Layer 1 ++ Print ++ YES ++ View ++ YES ++ ++ ++ LayoutInfo ++ ++ Animate ++ NO ++ circoMinDist ++ 18 ++ circoSeparation ++ 0.0 ++ layoutEngine ++ dot ++ neatoSeparation ++ 0.0 ++ twopiSeparation ++ 0.0 ++ ++ LinksVisible ++ NO ++ MagnetsVisible ++ NO ++ MasterSheets ++ ++ ModificationDate ++ 2008-11-17 11:41:28 -0700 ++ Modifier ++ Preston Jackson ++ NotesVisible ++ NO ++ Orientation ++ 2 ++ OriginVisible ++ NO ++ PageBreaks ++ YES ++ PrintInfo ++ ++ NSBottomMargin ++ ++ float ++ 41 ++ ++ NSLeftMargin ++ ++ float ++ 18 ++ ++ NSPaperSize ++ ++ size ++ {612, 792} ++ ++ NSRightMargin ++ ++ float ++ 18 ++ ++ NSTopMargin ++ ++ float ++ 18 ++ ++ ++ PrintOnePage ++ ++ QuickLookPreview ++ ++ JVBERi0xLjMKJcTl8uXrp/Og0MTGCjQgMCBvYmoKPDwgL0xlbmd0aCA1IDAgUiAvRmls ++ dGVyIC9GbGF0ZURlY29kZSA+PgpzdHJlYW0KeAGVlktvJEUQhO/9K5IbHFyuR9brioEV ++ nFh5JM5o5MWsPIA9IP4+X2b12gPrBbHWSt3lzkdFREb6Ud7Ko0R+asr+/+lOfpBfJIYW ++ /Z/8LNc35yTHsyROh/ZYxyTgfJTrN/zip7NcxVD3r1+e9oQbCd/J9fd3T8e7337/48cH ++ eSLjm3O2wEfR2ry8tiJ5hDJSVEk9pF7jkONJrr89JfnqV/p8uz1KK1YpJynNHlKVk2gJ ++ JZWqdqZz9iklBc21ZmkxlJoin0/vsEonTo6b9lC79iQzh6azSc7FYjINZWIkk4MCKtrG ++ ejhyRpZeRYcSNIbk7oXmtk5m4mRaD/NvYcOK1bKnpnkuu4qt6jqEVujLmtuOvFgdrXv7 ++ mcjWQxut71ds5LcbAIADIcTkDgpt4TKmyigWoXNzVAYtfYzdUe5fOT25ACxMtZAQiPeX ++ xEVTSCkNeaBLDbXWDhwfnxH1QHJX0sfiulDDhhpMgMnUJZAGDLkCea3T6b+9T3K+N/pf ++ F6qL8+ZW0hYDjM4ESlFubyTlAFd/kvfwRKilj3IFRdTQHJsk6EwzW5UvDwBY1xf2cNVL ++ SDWiyTa2AyL8JgXr8fBOPv/sCzm8l68PNERtwm0wGIb4yTrK2LiYt3+rI5+uY1df7JW8 ++ CD9tS/XNGUdxFSUs1e+yiQPuXPUMyVI9lL2qeh2bq16Rjet+qRdVLcWrceySz8+S30+A ++ zyTPTNiYWMQSe10Z64vY+/OoudZNus9dudwRqE+rVVty97v63bZd7iZHL7PkjnfYe5xw ++ vvTOAJtW5+gMv3vFB8RetF6yzYQ5x3/L08wKeQZ3t1pin5Fp1GpD0ORKy7AnlLN/kbPS ++ 2ofZwIlqwA1G35aT5d3JyGncLARwMKZb0Tt2gIAHLOBGpTJExgtaxZ/MjxbK+B8mYdQ0 ++ 5QuYoSumBgvBBXEsP0n9khlidnI8xrK6LZqBzVm2bFzEhIjMiIwcPyGGeQqjdjrwT7h+ ++ LYHiADxbwGHg6+Uux+3+4u1/I6yj5DSiaKw0CBBXpRSDluldCFM4zgHvPa9zujJygMR3 ++ RXlB+JWt1t0PvmNg35PwHxsOE4mw1Weu0cykNci2JJjJhX+sVUm1pt4BgIOOr6HBGsLd ++ eYUt0uRFYFIEgAl4n6yrBqw6QuzKxtA0wdf4g/OZ2QWMAd4DfUgXOqHaYjtc4/Gjshmh ++ y/PP/YQ62VDzj4dlZttYGh2ZHAwCzaCeVcoaJty3VGm2b4bnZwuhC2LommlOA9lxF2ub ++ WDS6QrjdWjcjNZJ3Uzh/OyA6IjK7cIVwj0t8fPwuD05ya6b+F7C1v1cKZW5kc3RyZWFt ++ CmVuZG9iago1IDAgb2JqCjk4MwplbmRvYmoKMiAwIG9iago8PCAvVHlwZSAvUGFnZSAv ++ UGFyZW50IDMgMCBSIC9SZXNvdXJjZXMgNiAwIFIgL0NvbnRlbnRzIDQgMCBSIC9NZWRp ++ YUJveCBbMCAwIDUxMiA1MTJdCj4+CmVuZG9iago2IDAgb2JqCjw8IC9Qcm9jU2V0IFsg ++ L1BERiAvVGV4dCAvSW1hZ2VCIC9JbWFnZUMgL0ltYWdlSSBdIC9Db2xvclNwYWNlIDw8 ++ IC9DczIgMTIgMCBSCi9DczEgNyAwIFIgPj4gL0V4dEdTdGF0ZSA8PCAvR3MxIDE3IDAg ++ UiAvR3MyIDE4IDAgUiA+PiAvRm9udCA8PCAvRjEuMCAxMSAwIFIKPj4gL1hPYmplY3Qg ++ PDwgL0ltMiAxMyAwIFIgL0ltMSA4IDAgUiAvSW0zIDE1IDAgUiA+PiAvU2hhZGluZyA8 ++ PCAvU2gxIDEwIDAgUgo+PiA+PgplbmRvYmoKMTAgMCBvYmoKPDwgL0NvbG9yU3BhY2Ug ++ NyAwIFIgL1NoYWRpbmdUeXBlIDMgL0Nvb3JkcyBbIC0yNzEuMzA2MyAwIDAgLTI3MS4z ++ MDYzIDAgNTQwLjI2NApdIC9Eb21haW4gWyAwIDEgXSAvRXh0ZW5kIFsgZmFsc2UgZmFs ++ c2UgXSAvRnVuY3Rpb24gMTkgMCBSID4+CmVuZG9iagoxMyAwIG9iago8PCAvTGVuZ3Ro ++ IDE0IDAgUiAvVHlwZSAvWE9iamVjdCAvU3VidHlwZSAvSW1hZ2UgL1dpZHRoIDI1NiAv ++ SGVpZ2h0IDI1NiAvQ29sb3JTcGFjZQo3IDAgUiAvU01hc2sgMjAgMCBSIC9CaXRzUGVy ++ Q29tcG9uZW50IDggL0ZpbHRlciAvRmxhdGVEZWNvZGUgPj4Kc3RyZWFtCngB7dABAQAA ++ CAKg/p+2Bx4QJpBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIAB ++ AwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBg ++ wIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYM ++ GDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIAB ++ AwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBg ++ wIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYM ++ GDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIAB ++ AwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBg ++ wIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYM ++ GDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIAB ++ AwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBg ++ wIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYM ++ GDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIAB ++ AwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBg ++ wIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYM ++ GDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIAB ++ AwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDBgwIABAwYMGDDQBg4DBgwYMGDA ++ wNjAA65NNU0KZW5kc3RyZWFtCmVuZG9iagoxNCAwIG9iago4ODMKZW5kb2JqCjggMCBv ++ YmoKPDwgL0xlbmd0aCA5IDAgUiAvVHlwZSAvWE9iamVjdCAvU3VidHlwZSAvSW1hZ2Ug ++ L1dpZHRoIDkxMiAvSGVpZ2h0IDkyNiAvQ29sb3JTcGFjZQoyMiAwIFIgL1NNYXNrIDIz ++ IDAgUiAvQml0c1BlckNvbXBvbmVudCA4IC9GaWx0ZXIgL0ZsYXRlRGVjb2RlID4+CnN0 ++ cmVhbQp4Ae3QgQAAAADDoPlTH+SFUGHAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ gAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY ++ MGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAED ++ BgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDA ++ wMvAAKraAAEKZW5kc3RyZWFtCmVuZG9iago5IDAgb2JqCjExMDcwCmVuZG9iagoxNSAw ++ IG9iago8PCAvTGVuZ3RoIDE2IDAgUiAvVHlwZSAvWE9iamVjdCAvU3VidHlwZSAvSW1h ++ Z2UgL1dpZHRoIDI1NiAvSGVpZ2h0IDI1NiAvQ29sb3JTcGFjZQo3IDAgUiAvU01hc2sg ++ MjUgMCBSIC9CaXRzUGVyQ29tcG9uZW50IDggL0ZpbHRlciAvRmxhdGVEZWNvZGUgPj4K ++ c3RyZWFtCngB7dKBDQAgDMMw/n+6SHBGvA+aeXMKFAucd8XlNiuw8U9BuQD/5e/bzj8D ++ 5QL8l79vO/8MlAvwX/6+7fwzUC7Af/n7tvPPQLkA/+Xv284/A+UC/Je/bzv/DJQL8F/+ ++ vu38M1AuwH/5+7bzz0C5AP/l79vOPwPlAvyXv287/wyUC/Bf/r7t/DNQLsB/+fu2889A ++ uQD/5e/bzj8D5QL8l79vO/8MlAvwX/6+7fwzUC7Af/n7tvPPQLkA/+Xv284/A+UC/Je/ ++ bzv/DJQL8F/+vu38M1AuwH/5+7bzz0C5AP/l79vOPwPlAvyXv287/wyUC/Bf/r7t/DNQ ++ LsB/+fu2889AuQD/5e/bzj8D5QL8l79vO/8MlAvwX/6+7fwzUC7Af/n7tvPPQLkA/+Xv ++ 284/A+UC/Je/bzv/DJQL8F/+vu38M1AuwH/5+7bzz0C5AP/l79vOPwPlAvyXv287/wyU ++ C/Bf/r7t/DNQLsB/+fu2889AuQD/5e/bzj8D5QL8l79vO/8MlAvwX/6+7fwzUC7Af/n7 ++ tvPPQLkA/+Xv284/A+UC/Je/bzv/DJQL8F/+vu38M1AuwH/5+7bzz0C5AP/l79vOPwPl ++ AvyXv287/wyUC/Bf/r7t/DNQLsB/+fu2889AuQD/5e/bzj8D5QL8l79vO/8MlAvwX/6+ ++ 7fwzUC7Af/n7tvPPQLkA/+Xv284/A+UC/Je/bzv/DJQL8F/+vu38M1AuwH/5+7bzz0C5 ++ AP/l79vOPwPlAvyXv287/wyUC/Bf/r7t/DNQLsB/+fu2889AuQD/5e/bzj8D5QL8l79v ++ O/8MlAvwX/6+7fwzUC7Af/n7tvPPQLkA/+Xv284/A+UC/Je/bzv/DJQL8F/+vu38M1Au ++ wH/5+7bzz0C5AP/l79vOPwPlAvyXv287/wyUC/Bf/r7t/DNQLsB/+fu2889AuQD/5e/b ++ zj8D5QL8l79vO/8MlAvwX/6+7fwzUC7Af/n7tvPPQLkA/+Xv284/A+UC/Je/bzv/DJQL ++ 8F/+vu38M1AuwH/5+7bzz0C5AP/l79vOPwPlAvyXv287/wyUC/Bf/r7t/DNQLsB/+fu2 ++ 889AuQD/5e/bzj8D5QL8l79vO/8MlAvwX/6+7fwzUC7Af/n7tvPPQLkA/+Xv284/A+UC ++ /Je/bzv/DJQL8F/+vu38M1AuwH/5+7bzz0C5AP/l79vOPwPlAvyXv287/wyUC/Bf/r7t ++ /DNQLsB/+fu2889AuQD/5e/bzj8D5QL8l79vO/8MlAvwX/6+7fwzUC7Af/n7tvPPQLkA ++ /+Xv284/A+UC/Je/bzv/DJQL8F/+vu38M1AuwH/5+7bzz0C5AP/l79vOPwPlAvyXv287 ++ /wyUC/Bf/r7t/DNQLsB/+fu2889AuQD/5e/bzj8D5QL8l79vO/8MlAvwX/6+7fwzUC7A ++ f/n7tvPPQLkA/+Xv284/A+UC/Je/bzv/DJQL8F/+vu38M1AuwH/5+7bzz0C5AP/l79vO ++ PwPlAvyXv287/wyUC/Bf/r7t/DNQLsB/+fu2889AuQD/5e/bzj8D5QL8l79vO/8MlAvw ++ X/6+7fwzUC7Af/n7tvPPQLkA/+Xv284/A+UC/Je/bzv/DJQL8F/+vu3f/wUgwjJ6CmVu ++ ZHN0cmVhbQplbmRvYmoKMTYgMCBvYmoKMTIxNAplbmRvYmoKMjMgMCBvYmoKPDwgL0xl ++ bmd0aCAyNCAwIFIgL1R5cGUgL1hPYmplY3QgL1N1YnR5cGUgL0ltYWdlIC9XaWR0aCA5 ++ MTIgL0hlaWdodCA5MjYgL0NvbG9yU3BhY2UKL0RldmljZUdyYXkgL0JpdHNQZXJDb21w ++ b25lbnQgOCAvRmlsdGVyIC9GbGF0ZURlY29kZSA+PgpzdHJlYW0KeAHsnYlfTV37/288 ++ j4xJUVJRGtCEoggliZCxyFQUlUiGNCgJIXOFyFTKlCljmUMlUaZK4XY/N31fv//jd621 ++ 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 ++ 5IiRegajjceajhs/cbKF5RRriMrp021nzJg5c6YdPmgByVkAHH/GDFvb6dOnTbWZYmUx ++ edIEM1OTMYYGo3R1ZNFIdjl6BI4sJGlEwtbHwEGwGzlcR1ffYLTRGIhJs/ETJk6abGFh ++ YWlpZWU1BR+0gOQsAI5vZWkJMTB50sTx5uMgFoGMo/RGjtCmuhHY2NPRCEEJi1aGkb8P ++ GjwUQhIoCTFpCEFpYmoKcWlmZm5uPh4ftIDkLACOb25mNm6cqanJ2DHGRqMNRunr6kAw ++ wkJ1IFmpqiAaCSXZiKSQJCEJmBypq6c/ygDC0tDIyMgYnjH4oAUkZgHi98ZGRoaGo0cb ++ QCjqQSwOBzIOgZQqKcdRUTSSiKS7kb/++huEJFByyFCtYRCUI3QgLHX19PT0uWcUPmgB ++ aViAc3lwf13dkSMhEodr01gEMrJo7FndSMOQ9y8MJJmQBDEJQQlRCWFJn+H4oAWkaAHG ++ /YcN09ICLA5mYpGsU3s4icOLQ94faUhCGR1gEjj5+8CBgwYNGjx48BD5MxQfTbSA/APh ++ n2QW+JkPJXvJEIhCiMNBA4GKvw8Y0B9iEZapqiUjLyJh3UqyO/36wdr1t/79IS5JYOKD ++ FpCyBSAKIBZ+I6FIY7Entzf4wdfdn2lQsmH5Kzy/4YMWkKgFiP+TOCSRCFjs0a3G7uKv ++ m39Ofh0eGAc+aAHpWoAJA3VDsZugxH+MFkALoAXQAmgBtABaAC2AFkALoAXQAmgBtABa ++ AC2AFkALoAXQAmgBtABaoFct8P/b5umcCmVuZHN0cmVhbQplbmRvYmoKMjQgMCBvYmoK ++ NDQ4NjUKZW5kb2JqCjIwIDAgb2JqCjw8IC9MZW5ndGggMjEgMCBSIC9UeXBlIC9YT2Jq ++ ZWN0IC9TdWJ0eXBlIC9JbWFnZSAvV2lkdGggMjU2IC9IZWlnaHQgMjU2IC9Db2xvclNw ++ YWNlCi9EZXZpY2VHcmF5IC9CaXRzUGVyQ29tcG9uZW50IDggL0ZpbHRlciAvRmxhdGVE ++ ZWNvZGUgPj4Kc3RyZWFtCngB7dCFQQIAAABBsTswEAxsBQWD/XdzkL8b4Vartj8MGDBg ++ IDnwiwEDBgwkB34wYMCAgeTANwYMGDCQHFhiwIABA8mBBQYMGDCQHPjCgAEDBpIDnxgw ++ YMCAgeDAHAMGDBhIDswwYMCAgeTABwYMGDCQHHjHgAEDBpIDbxgwYMBAcuAVAwYMGEgO ++ vGDAgAEDBoIDzxgwYMBAcuAJAwYMGEgOPGLAgAEDyYEHDBgwYCA5MMWAAQMGkgP3GDBg ++ wEBy4A4DBgwYSA7cYsCAAQMGggM3GDBgwEByYIIBAwYMJAfGGDBgIDpwjQED2YERBgxk ++ B64wYCA7cIkBA9mBCwyEB84xYCA7MMSAgezAGQYMZAdOMWAgO3CCAQPZgWMMGMgOHGHA ++ QHbgEAMGsgMHGDCQHdjHQHhgDwMGsgO7GDCQHdjBgIHswDYGDGQHtjBgIDuwiQED2YEN ++ DBjIDqxjwEB2YIABA9mBNQyEB/4BLgXylgplbmRzdHJlYW0KZW5kb2JqCjIxIDAgb2Jq ++ CjM2NgplbmRvYmoKMjUgMCBvYmoKPDwgL0xlbmd0aCAyNiAwIFIgL1R5cGUgL1hPYmpl ++ Y3QgL1N1YnR5cGUgL0ltYWdlIC9XaWR0aCAyNTYgL0hlaWdodCAyNTYgL0NvbG9yU3Bh ++ Y2UKL0RldmljZUdyYXkgL0JpdHNQZXJDb21wb25lbnQgOCAvRmlsdGVyIC9GbGF0ZURl ++ Y29kZSA+PgpzdHJlYW0KeAHt3Qs/k2EYB+A5j2HOZpjz+TxzNkQSSSJJJJEkkkgStq/e ++ B+n6CPtte9/nuQ//K51KPT483N//vbv7c3v7++bm1/X11dXPy8sfFxffz8/Pzr6dnn49 ++ OflyfPz56Ojw8NPBwcf9/Q97e7u773d23m1vv93aerO5ubHxen391dray9XVFysry8vP ++ l5aeLS4+XViYn38yNzc7OzOTTCanp6empiYnJyYmxsfHxsZGR0dGEonE8HA8Hh8aGhwc ++ HBjo7+/v6+vt7e3p6e7u6urq7Ozo6Ghvb2tra21taWlpbm5qampsbGiIxWL19XV1dbW1 ++ 0Wi0piYSiVRXV1VVVVZWVJSXl5eVlZaWlpSEw+Hi4qKiosLCUChUUJCfHwwG8/Jyc3Nz ++ crKzs7OyMjMzMzICgbTP7/v3+/f/9/zz/Pf+8/53/nH+c/51/nf/cf9z/3X/V/9Q/1H/ ++ Uv9T/1T/Vf9W/9f/0P/R/9L/0//U/9X/1v83/2D+w/yL+R/zT+a/zL+Z/zP/aP7T/Kv5 ++ X/PP5r/Nv5v/t/9g/8P+i/0f+0/2v+y/2f+z/2j/0/6r/V/7z/a/7b/b/5d/IP9B/oX8 ++ D/kn8l/k38j/kX8k/0n+lfwv+Wfy3+Tfyf+Tfyj/Uf6l/E/5p/Jf5d/K/5V/LP9Z/rX8 ++ b/nn8t/l38v/5x/wH/gX/A/+Cf+Ff8P/4R/xn/hX/C/+Gf+Nf8f/4x/yH/mX/E/+Kf+V ++ f8v/5R/zn/nX/G/+Of89IxBIp1L8d/47/53/zn/nv/Pf+e/8d/47/53/zn/nv/Pf+e/8 ++ d/47/53/zn/nv/Pf+e/8d/47/53/zn/nv/Pf+e/8d/47/53/zn/nv/Pf+e/8d/47/53/ ++ zn/nv/Pf+e/8d/47/53/zn/nv/Pf+e/8d/47/53/zn/nv/Pf+e/8d/47/53/zn/nv/Pf ++ +e/8d/47/53/zn/nv/Pf+e/8d/47/53/zn/nv/Pf+e/8d/47/53/zn/nv/Pf+e/8d/47 ++ /53/zn/nv/Pf+e/8d/47/53/zn/nv/Pf+e/8d/47/53/zn/nv/Pf+e/8d/47/53/zn/n ++ vwfSqdTjw3/sv/8DK6twSQplbmRzdHJlYW0KZW5kb2JqCjI2IDAgb2JqCjgxNwplbmRv ++ YmoKMTcgMCBvYmoKPDwgL1R5cGUgL0V4dEdTdGF0ZSAvY2EgMCA+PgplbmRvYmoKMTgg ++ MCBvYmoKPDwgL1R5cGUgL0V4dEdTdGF0ZSAvY2EgMSA+PgplbmRvYmoKMjcgMCBvYmoK ++ PDwgL0xlbmd0aCAyOCAwIFIgL04gMSAvQWx0ZXJuYXRlIC9EZXZpY2VHcmF5IC9GaWx0 ++ ZXIgL0ZsYXRlRGVjb2RlID4+CnN0cmVhbQp4AYVST0gUURz+zTYShIhBhXiIdwoJlSms ++ rKDadnVZlW1bldKiGGffuqOzM9Ob2TXFkwRdojx1D6JjdOzQoZuXosCsS9cgqSAIPHXo ++ +83s6iiEb3k73/v9/X7fe0RtnabvOylBVHNDlSulp25OTYuDHylFHdROWKYV+OlicYyx ++ 67mSv7vX1mfS2LLex7V2+/Y9tZVlYCHqLba3EPohkWYAH5mfKGWAs8Adlq/YPgE8WA6s ++ GvAjogMPmrkw09GcdKWyLZFT5qIoKq9iO0mu+/m5xr6LtYmD/lyPZtaOvbPqqtFM1LT3 ++ RKG8D65EGc9fVPZsNRSnDeOcSEMaKfKu1d8rTMcRkSsQSgZSNWS5n2pOnXXgdRi7XbqT ++ 4/j2EKU+yWCoibXpspkdhX0AdirL7BDwBejxsmIP54F7Yf9bUcOTwCdhP2SHedatH/YX ++ rlPge4Q9NeDOFK7F8dqKH14tAUP3VCNojHNNxNPXOXOkiO8x1BmY90Y5pgsxd5aqEzeA ++ O2EfWapmCrFd+67qJe57AnfT4zvRmzkLXKAcSXKxFdkU0DwJWBR9i7BJDjw+zh5V4Heo ++ mMAcuYnczSj3HtURG2ejUoFWeo1Xxk/jufHF+GVsGM+Afqx213t8/+njFXXXtj48+Y16 ++ 3DmuvZ0bVWFWcWUL3f/HMoSP2Sc5psHToVlYa9h25A+azEywDCjEfwU+l/qSE1Xc1e7t ++ uEUSzFA+LGwluktUbinU6j2DSqwcK9gAdnCSxCxaHLhTa7o5eHfYInpt+U1XsuuG/vr2 ++ evva8h5tyqgpKBPNs0RmlLFbo+TdeNv9ZpERnzg6vue9ilrJ/klFED+FOVoq8hRV9FZQ ++ 1sRvZw5+G7Z+XD+l5/VB/TwJPa2f0a/ooxG+DHRJz8JzUR+jSfCwaSHiEqCKgzPUTlRj ++ jQPiKfHytFtkkf0PQBn9ZgplbmRzdHJlYW0KZW5kb2JqCjI4IDAgb2JqCjcwNAplbmRv ++ YmoKMTIgMCBvYmoKWyAvSUNDQmFzZWQgMjcgMCBSIF0KZW5kb2JqCjI5IDAgb2JqCjw8 ++ IC9MZW5ndGggMzAgMCBSIC9OIDMgL0FsdGVybmF0ZSAvRGV2aWNlUkdCIC9GaWx0ZXIg ++ L0ZsYXRlRGVjb2RlID4+CnN0cmVhbQp4Aa2TzWsTQRjGn02QCtZQi0jx4oJSPERdkhbb ++ W9t8SOwSlySlfhw02d1soslm3d1ErR561H+gFEQQPOjBmxc9tSeR4ieC9OBdUU9a6qGU ++ 9Z0Zd4Ng8eK7zMxvH555Z+adXSC+UXWcVgxA2/bd0qkZ+ey58/LAOiQcQgJJyFXdc6Y1 ++ TSXLDrH5gdwU74+xXF9iz7c+fdtz58Li7bXDSw9bO0wK5YRLCwJSkoT9luApxjXBFcbX ++ fMcnT4Ox3qgaxLeIk26llCF+RJywBD9lXBP8gnFPt9jcdWLFNpo2ENtNPGGYnk48RWwZ ++ nt4mpjwS2u0O5Y+znEd1x6W58bfER1hdaKS4mgAmv5J+r69dPAE8WQMOaH1tdBkYvgQ8 ++ m+xrP97wWkkjNa+eTvF00uBBYNdqEHwPgAHyb78Ogq3lINheojU2gJWi3nV73EsblF4B ++ /3oXZxbZgXd0Bgp+R39nURfuUoAHq0BlEVBpvEvj6E9g301AA+lUpnQ6bKKGJAN7szlV ++ lVNjynhem+fKf+zarS7dFY9h6gftWvEMjSPUPju+RpsS7PXKuZDrzXwhZKOanQ15oZEp ++ hlx386WQL1dPswPynKY9Vw7ZafFv//daM5Hf9HKRZ6FRYWfmHrdbmgv5Smc28htmNtqb ++ 3Sqy/4n7m34h2j+yyEGlR0YKY1AwjjyVfV58kzQDQ4+B+0PKyXR55eNLJvwRvnmd33Wm ++ 49xwm1bDl6fpjzSTcsHWjyfllKJM4BeDarM/CmVuZHN0cmVhbQplbmRvYmoKMzAgMCBv ++ YmoKNTY1CmVuZG9iagoyMiAwIG9iagpbIC9JQ0NCYXNlZCAyOSAwIFIgXQplbmRvYmoK ++ MzEgMCBvYmoKPDwgL0xlbmd0aCAzMiAwIFIgL04gMyAvQWx0ZXJuYXRlIC9EZXZpY2VS ++ R0IgL0ZpbHRlciAvRmxhdGVEZWNvZGUgPj4Kc3RyZWFtCngBhZRNSBRhGMf/s40EsQbR ++ lwjF0MEkVCYLUgLT9StTtmXVTAlinX13nRxnp5ndLUUihOiYdYwuVkSHiE7hoUOnOkQE ++ mXWJoKNFEAVeIrb/O5O7Y1S+MDO/eZ7/+3y9wwBVj1KOY0U0YMrOu8nemHZ6dEzb/BpV ++ qEYUXCnDczoSiQGfqZXP9Wv1LRRpWWqUsdb7NnyrdpkQUDQqd2QDPix5PODjki/knTw1 ++ ZyQbE6k02SE3uEPJTvIt8tZsiMdDnBaeAVS1U5MzHJdxIjvILUUjK2M+IOt22rTJ76U9 ++ 7RlT1LDfyDc5C9q48v1A2x5g04uKbcwDHtwDdtdVbPU1wM4RYPFQxfY96c9H2fXKyxxq ++ 9sMp0Rhr+lAqfa8DNt8Afl4vlX7cLpV+3mEO1vHUMgpu0deyMOUlENQb7Gb85Br9i4Oe ++ fFULsMA5jmwB+q8ANz8C+x8C2x8DiWpgqBWRy2w3uPLiIucCdOacadfMTuS1Zl0/onXw ++ aIXWZxtNDVrKsjTf5Wmu8IRbFOkmTFkFztlf23iPCnt4kE/2F7kkvO7frMylU12cJZrY ++ 1qe06OomN5DvZ8yePnI9r/cZt2c4YOWAme8bCjhyyrbiPBepidTY4/GTZMZXVCcfk/OQ ++ POcVB2VM334udSJBrqU9OZnrl5pd3Ns+MzHEM5KsWDMTnfHf/MYtJGXefdTcdSz/m2dt ++ kWcYhQUBEzbvNjQk0YsYGuHARQ4ZekwqTFqlX9BqwsPkX5UWEuVdFhW9WOGeFX/PeRS4 ++ W8Y/hVgccw3lCJr+Tv+iL+sL+l3983xtob7imXPPmsara18ZV2aW1ci4QY0yvqwpiG+w ++ 2g56LWRpneIV9OSV9Y3h6jL2fG3Zo8kc4mp8NdSlCGVqxDjjya5l90WyxTfh51vL9q/p ++ Uft89klNJdeyunhmKfp8NlwNa/+zq2DSsqvw5I2QLjxroe5VD6p9aovaCk09prarbWoX ++ 346qA+Udw5yViQus22X1KfZgY5reyklXZovg38Ivhv+lXmEL1zQ0+Q9NuLmMaQnfEdw2 ++ cIeU/8NfswMN3gplbmRzdHJlYW0KZW5kb2JqCjMyIDAgb2JqCjc5MgplbmRvYmoKNyAw ++ IG9iagpbIC9JQ0NCYXNlZCAzMSAwIFIgXQplbmRvYmoKMTkgMCBvYmoKPDwgL0xlbmd0 ++ aCAzMyAwIFIgL0Z1bmN0aW9uVHlwZSAwIC9CaXRzUGVyU2FtcGxlIDggL1NpemUgWyAx ++ MzY1IF0gL0RvbWFpbgpbIDAgMSBdIC9SYW5nZSBbIDAgMSAwIDEgMCAxIF0gL0ZpbHRl ++ ciAvRmxhdGVEZWNvZGUgPj4Kc3RyZWFtCngBzcLXcQJAEAXByT8vjLDCO4HwIoobfRPA ++ K7arW4f22V1akT1anX3ae/t85hfWOcAih1jnCIscY50TLHKKdX5jkTMsco51LrDIJda5 ++ wiLXWOcGQ7cYusPEPYYeMPEHQ4+YeMLQXww9Y+IFQ6+YeMPQO4Y+MPGJoX+Y+MLAf+tF ++ vN4KZW5kc3RyZWFtCmVuZG9iagozMyAwIG9iagoxMzAKZW5kb2JqCjMgMCBvYmoKPDwg ++ L1R5cGUgL1BhZ2VzIC9NZWRpYUJveCBbMCAwIDUxMiA1MTJdIC9Db3VudCAxIC9LaWRz ++ IFsgMiAwIFIgXSA+PgplbmRvYmoKMzQgMCBvYmoKPDwgL1R5cGUgL0NhdGFsb2cgL1Bh ++ Z2VzIDMgMCBSIC9WZXJzaW9uIC8xLjQgPj4KZW5kb2JqCjM1IDAgb2JqCjw8IC9MZW5n ++ dGggMzYgMCBSIC9MZW5ndGgxIDUwMzIgL0ZpbHRlciAvRmxhdGVEZWNvZGUgPj4Kc3Ry ++ ZWFtCngB7TiNfxNVtufcOzOZNkDT0pbQAJl0aJWm2QIKlEJpaJKWNkILVDepsCb9kADF ++ Flo+n9Iqq2L4sK7a1d+u6K6rFaw6bZENRZevxdUVfn6ivLfig4X14z0R9Af7VoHOO5Nq ++ BZd9f8Gbk3vn3nPOveeej3vu3AACwBBoAw7u2mXhJpBhGmEOU7HWrmpR3tm342NqnwaQ ++ V9zetGhZ6hcziZ4QABDKFzWsvT0yatrbAEN/RzyvR+rDdWeXqscBhjVQf3KEEMPGCEQf ++ ZtDHRpa1rJH3Yxf1X6e+3NBYG4Y6SKc+8YC0LLymiT0q3k39Y9RX7ggvqx+59bl11P8H ++ 9dWmxuYWvQpuB0gaRf3sphX1TWeOuN6jvpfWEyYcEhjPEJCoADgMjNgLILbBGCojeA9k ++ 6hf0v1L5zCj9s4j2NCT31wDwEmpvi4+/qhJP0OyeAZT+L56rBlyzMzAQDE2Ncu2nHMxQ ++ AltABAsI8Az1zsJxuA8klGEyJEM+vIAfgQcq4R4shJ8TTwaUwQuwGz7ARfolEPSgfgCW ++ QidOIv0zoAAWwF44T3x/gp9CGNZAK96j30XWSYQxkAk3kDVXwDo4SRwJkAY2yMQsNo0f ++ gxE0sgHaYAPsFir0Z/XjNCaBoAKeheegH6sxou/STxEmH6aCD+bDHcT7AIqYJo7R/6Kf ++ 18/DRFrnQlhE8yyHx2AXmnA4OvEPrIh3wDjSsxGaIAod8Ev4M2bjm7xS3w4uggkwh+a7 ++ FWpozi3QB2/ANyixGraGvcB28RX8ogDCUfFtyae/ph+hyBXBSmMKaMRtFE+Lad4H4R34 ++ EP4KX8HXmIaZOAEn4wwsw6WsQTJLP9X30BgzjAaFbJADebTSAigmmEe2uBMehS54BV4l ++ OABfokJwHcE4vBWfwR48xZKYwg6zd9g3PJ/7+aOCVVgo3Ck+Jp6UcnSPvosslQJ2UGEK ++ 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 ++ Q1aLMVmjIaszPu5HsroMcqchq8uQ1WXI6nR3xmWhb/H8YrJVoFuG4qBnwcC7l5kTyT0h ++ myNYHPfTNId1va2PXcACMNMpMoQ+PoZSMVzomumaSSQP88RJw4zvku9I1vXTHLY+LGAX ++ 4iQLoZMpaPAHLxmtZmdzc/PKFqpaVkLLSoJm4miOU5zQMsBMwfi/LcjbTgplbmRzdHJl ++ YW0KZW5kb2JqCjM2IDAgb2JqCjM0NTYKZW5kb2JqCjM3IDAgb2JqCjw8IC9UeXBlIC9G ++ b250RGVzY3JpcHRvciAvQXNjZW50IDc1MSAvQ2FwSGVpZ2h0IDY5NSAvRGVzY2VudCAt ++ MzE5IC9GbGFncyAzMgovRm9udEJCb3ggWy0xNzYgLTIyNyAxMDc2IDkxM10gL0ZvbnRO ++ YW1lIC9EUUJQSVYrQ2FsaXNNVEJvbCAvSXRhbGljQW5nbGUgMAovU3RlbVYgMCAvTGVh ++ ZGluZyAxMTEgL01heFdpZHRoIDEwOTQgL1hIZWlnaHQgNDcxIC9Gb250RmlsZTIgMzUg ++ MCBSID4+CmVuZG9iagozOCAwIG9iagpbIDM0NCBdCmVuZG9iagoxMSAwIG9iago8PCAv ++ VHlwZSAvRm9udCAvU3VidHlwZSAvVHJ1ZVR5cGUgL0Jhc2VGb250IC9EUUJQSVYrQ2Fs ++ aXNNVEJvbCAvRm9udERlc2NyaXB0b3IKMzcgMCBSIC9XaWR0aHMgMzggMCBSIC9GaXJz ++ dENoYXIgMzMgL0xhc3RDaGFyIDMzIC9FbmNvZGluZyAvTWFjUm9tYW5FbmNvZGluZwo+ ++ PgplbmRvYmoKMSAwIG9iago8PCAvVGl0bGUgKFVudGl0bGVkKSAvQXV0aG9yIChQcmVz ++ dG9uIEphY2tzb24pIC9DcmVhdG9yIChPbW5pR3JhZmZsZSBQcm9mZXNzaW9uYWwpCi9Q ++ cm9kdWNlciAoTWFjIE9TIFggMTAuNS41IFF1YXJ0eiBQREZDb250ZXh0KSAvQ3JlYXRp ++ b25EYXRlIChEOjIwMDgxMTE3MTg0NzE0WjAwJzAwJykKL01vZERhdGUgKEQ6MjAwODEx ++ MTcxODQ3MTRaMDAnMDAnKSA+PgplbmRvYmoKeHJlZgowIDM5CjAwMDAwMDAwMDAgNjU1 ++ MzUgZiAKMDAwMDA2OTExNCAwMDAwMCBuIAowMDAwMDAxMDk4IDAwMDAwIG4gCjAwMDAw ++ NjQ5NjMgMDAwMDAgbiAKMDAwMDAwMDAyMiAwMDAwMCBuIAowMDAwMDAxMDc5IDAwMDAw ++ IG4gCjAwMDAwMDEyMDIgMDAwMDAgbiAKMDAwMDA2NDYxNCAwMDAwMCBuIAowMDAwMDAy ++ Njk4IDAwMDAwIG4gCjAwMDAwMTM5NDkgMDAwMDAgbiAKMDAwMDAwMTQ1NSAwMDAwMCBu ++ IAowMDAwMDY4OTM5IDAwMDAwIG4gCjAwMDAwNjI5MzcgMDAwMDAgbiAKMDAwMDAwMTYx ++ MyAwMDAwMCBuIAowMDAwMDAyNjc4IDAwMDAwIG4gCjAwMDAwMTM5NzAgMDAwMDAgbiAK ++ MDAwMDAxNTM2NiAwMDAwMCBuIAowMDAwMDYyMDE5IDAwMDAwIG4gCjAwMDAwNjIwNjQg ++ MDAwMDAgbiAKMDAwMDA2NDY1MCAwMDAwMCBuIAowMDAwMDYwNDQ4IDAwMDAwIG4gCjAw ++ MDAwNjA5ODggMDAwMDAgbiAKMDAwMDA2MzY2MiAwMDAwMCBuIAowMDAwMDE1Mzg3IDAw ++ MDAwIG4gCjAwMDAwNjA0MjYgMDAwMDAgbiAKMDAwMDA2MTAwOCAwMDAwMCBuIAowMDAw ++ MDYxOTk5IDAwMDAwIG4gCjAwMDAwNjIxMDkgMDAwMDAgbiAKMDAwMDA2MjkxNyAwMDAw ++ MCBuIAowMDAwMDYyOTc0IDAwMDAwIG4gCjAwMDAwNjM2NDIgMDAwMDAgbiAKMDAwMDA2 ++ MzY5OSAwMDAwMCBuIAowMDAwMDY0NTk0IDAwMDAwIG4gCjAwMDAwNjQ5NDMgMDAwMDAg ++ biAKMDAwMDA2NTA0NiAwMDAwMCBuIAowMDAwMDY1MTEwIDAwMDAwIG4gCjAwMDAwNjg2 ++ NTYgMDAwMDAgbiAKMDAwMDA2ODY3NyAwMDAwMCBuIAowMDAwMDY4OTE1IDAwMDAwIG4g ++ CnRyYWlsZXIKPDwgL1NpemUgMzkgL1Jvb3QgMzQgMCBSIC9JbmZvIDEgMCBSIC9JRCBb ++ IDw0OWU2MjQzZGUwYzBiMTQ0NmRmMDQzNjRjNzc1ZGNlZj4KPDQ5ZTYyNDNkZTBjMGIx ++ NDQ2ZGYwNDM2NGM3NzVkY2VmPiBdID4+CnN0YXJ0eHJlZgo2OTMzNgolJUVPRgoxIDAg ++ b2JqCjw8L0F1dGhvciAoUHJlc3RvbiBKYWNrc29uKS9DcmVhdGlvbkRhdGUgKEQ6MjAw ++ ODExMTQyMzU4MDBaKS9DcmVhdG9yIChPbW5pR3JhZmZsZSBQcm9mZXNzaW9uYWwgNS4x ++ IHJjIDEpL01vZERhdGUgKEQ6MjAwODExMTcxODQxMDBaKS9Qcm9kdWNlciAoTWFjIE9T ++ IFggMTAuNS41IFF1YXJ0eiBQREZDb250ZXh0KS9UaXRsZSAoUmVwb3J0ZXJJY29uLmdy ++ YWZmbGUpPj4KZW5kb2JqCnhyZWYKMSAxCjAwMDAwNzAyNzQgMDAwMDAgbiAKdHJhaWxl ++ cgo8PC9JRCBbPDQ5ZTYyNDNkZTBjMGIxNDQ2ZGYwNDM2NGM3NzVkY2VmPiA8NDllNjI0 ++ M2RlMGMwYjE0NDZkZjA0MzY0Yzc3NWRjZWY+XSAvSW5mbyAxIDAgUiAvUHJldiA2OTMz ++ NiAvUm9vdCAzNCAwIFIgL1NpemUgMzk+PgpzdGFydHhyZWYKNzA0OTgKJSVFT0YK ++ ++ QuickLookThumbnail ++ ++ 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 ++ ++ ReadOnly ++ NO ++ RowAlign ++ 1 ++ RowSpacing ++ 36 ++ SheetTitle ++ Canvas 1 ++ SmartAlignmentGuidesActive ++ NO ++ SmartDistanceGuidesActive ++ NO ++ UniqueID ++ 1 ++ UseEntirePage ++ ++ VPages ++ 1 ++ WindowInfo ++ ++ CurrentSheet ++ 0 ++ ExpandedCanvases ++ ++ ++ name ++ Canvas 1 ++ ++ ++ Frame ++ {{2002, 20}, {1215, 1180}} ++ ListView ++ ++ OutlineWidth ++ 142 ++ RightSidebar ++ ++ Sidebar ++ ++ SidebarWidth ++ 157 ++ VisibleRegion ++ {{-4.5, 0.5}, {522, 535.5}} ++ Zoom ++ 2 ++ ZoomValues ++ ++ ++ Canvas 1 ++ 2 ++ 4 ++ ++ ++ ++ saveQuickLookFiles ++ YES ++ ++ +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/sender/crash_report_sender-Info.plist b/toolkit/crashreporter/google-breakpad/src/client/mac/sender/crash_report_sender-Info.plist +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/sender/crash_report_sender-Info.plist +@@ -0,0 +1,32 @@ ++ ++ ++ ++ ++ CFBundleDevelopmentRegion ++ English ++ CFBundleDisplayName ++ ${EXECUTABLE_NAME} ++ CFBundleExecutable ++ ${EXECUTABLE_NAME} ++ CFBundleIconFile ++ crash_report_sender ++ CFBundleIdentifier ++ com.Breakpad.${PRODUCT_NAME:identifier} ++ CFBundleInfoDictionaryVersion ++ 6.0 ++ CFBundleName ++ ${EXECUTABLE_NAME} ++ CFBundlePackageType ++ APPL ++ CFBundleSignature ++ ???? ++ CFBundleVersion ++ 1.0 ++ LSHasLocalizedDisplayName ++ ++ NSMainNibFile ++ MainMenu ++ NSPrincipalClass ++ NSApplication ++ ++ +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/sender/crash_report_sender.h b/toolkit/crashreporter/google-breakpad/src/client/mac/sender/crash_report_sender.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/sender/crash_report_sender.h +@@ -0,0 +1,139 @@ ++// 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. ++// ++// This component uses the HTTPMultipartUpload of the breakpad project to send ++// the minidump and associated data to the crash reporting servers. ++// It will perform throttling based on the parameters passed to it and will ++// prompt the user to send the minidump. ++ ++#include ++ ++#include "client/mac/Framework/Breakpad.h" ++ ++#define kClientIdPreferenceKey @"clientid" ++ ++extern NSString *const kGoogleServerType; ++extern NSString *const kSocorroServerType; ++extern NSString *const kDefaultServerType; ++ ++// We're sublcassing NSTextField in order to override a particular ++// method (see the implementation) that lets us reject changes if they ++// are longer than a particular length. Bindings would normally solve ++// this problem, but when we implemented a validation method, and ++// returned NO for strings that were too long, the UI was not updated ++// right away, which was a poor user experience. The UI would be ++// updated as soon as the text field lost first responder status, ++// which isn't soon enough. It is a known bug that the UI KVO didn't ++// work in the middle of a validation. ++@interface LengthLimitingTextField : NSTextField { ++ @private ++ unsigned int maximumLength_; ++} ++ ++- (void) setMaximumLength:(unsigned int)maxLength; ++@end ++ ++@interface Reporter : NSObject { ++ @public ++ IBOutlet NSWindow *alertWindow_; // The alert window ++ ++ // Grouping boxes used for resizing. ++ IBOutlet NSBox *headerBox_; ++ IBOutlet NSBox *preEmailBox_; ++ IBOutlet NSBox *emailSectionBox_; ++ // Localized elements (or things that need to be moved during localization). ++ IBOutlet NSTextField *dialogTitle_; ++ IBOutlet NSTextField *commentMessage_; ++ IBOutlet NSTextField *emailMessage_; ++ IBOutlet NSTextField *emailLabel_; ++ IBOutlet NSTextField *privacyLinkLabel_; ++ IBOutlet NSButton *sendButton_; ++ IBOutlet NSButton *cancelButton_; ++ IBOutlet LengthLimitingTextField *emailEntryField_; ++ IBOutlet LengthLimitingTextField *commentsEntryField_; ++ IBOutlet NSTextField *countdownLabel_; ++ IBOutlet NSView *privacyLinkArrow_; ++ ++ // Text field bindings, for user input. ++ NSString *commentsValue_; // Comments from the user ++ NSString *emailValue_; // Email from the user ++ NSString *countdownMessage_; // Message indicating time ++ // left for input. ++ @private ++ int configFile_; // File descriptor for config file ++ NSMutableDictionary *parameters_; // Key value pairs of data (STRONG) ++ NSData *minidumpContents_; // The data in the minidump (STRONG) ++ NSData *logFileData_; // An NSdata for the tar, ++ // bz2'd log file. ++ NSTimeInterval remainingDialogTime_; // Keeps track of how long ++ // we have until we cancel ++ // the dialog ++ NSTimer *messageTimer_; // Timer we use to update ++ // the dialog ++ NSMutableDictionary *serverDictionary_; // The dictionary mapping a ++ // server type name to a ++ // dictionary of server ++ // parameter names. ++ NSMutableDictionary *socorroDictionary_; // The dictionary for ++ // Socorro. ++ NSMutableDictionary *googleDictionary_; // The dictionary for ++ // Google. ++ NSMutableDictionary *extraServerVars_; // A dictionary containing ++ // extra key/value pairs ++ // that are uploaded to the ++ // crash server with the ++ // minidump. ++} ++ ++// Stops the modal panel with an NSAlertDefaultReturn value. This is the action ++// invoked by the "Send Report" button. ++- (IBAction)sendReport:(id)sender; ++// Stops the modal panel with an NSAlertAlternateReturn value. This is the ++// action invoked by the "Cancel" button. ++- (IBAction)cancel:(id)sender; ++// Opens the Privacy Policy url in the default web browser. ++- (IBAction)showPrivacyPolicy:(id)sender; ++ ++// Delegate methods for the NSTextField for comments. We want to capture the ++// Return key and use it to send the message when no text has been entered. ++// Otherwise, we want Return to add a carriage return to the comments field. ++- (BOOL)control:(NSControl *)control textView:(NSTextView *)textView ++ doCommandBySelector:(SEL)commandSelector; ++ ++// Accessors to make bindings work ++- (NSString *)commentsValue; ++- (void)setCommentsValue:(NSString *)value; ++ ++- (NSString *)emailValue; ++- (void)setEmailValue:(NSString *)value; ++ ++- (NSString *)countdownMessage; ++- (void)setCountdownMessage:(NSString *)value; ++ ++@end +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/sender/crash_report_sender.icns b/toolkit/crashreporter/google-breakpad/src/client/mac/sender/crash_report_sender.icns +new file mode 100644 +index 0000000000000000000000000000000000000000..e8c21242bf84a70a1efb7e005f47684a882eabe1 +GIT binary patch +literal 170816 +zc%1CL1$Yz7_dmQFPij=4E>NT1Qa38JK!FOyOM&9K18JwbE>JGq3%t+&d42=6oO3=$=FH5Q*<^R>_*wH2(r*8$^PPJj2x)dKLP8NV +z5uuR~>x0$^DIWfI8b6JY;t&Q2@n~&s^*~6m@b{DWJNy(v;vy^(;w*0k|6C9f2Vs$s +zqjgcn((^n3UlbfTr!gQtg1m?A*_pqE&w&v(z43;qM~9!H}Dr3iGMCC +zDt%E{$QQ3h$S7i5URG2jtmF#?h51H+y!yUSB&c~+&J*OwY; +z8X!Yni>2af$fNm{Bof$Ht6{Rt0{LHOPc}x}Mqynt)I!?p}73 +zc!U8g@pkX4hoEr?jpn^ddfbKQT% +z*i99LfIMotcjQAyLt|~=ByhUN98dG0e5F>^YI90O@yWF^6>?jZ|`8XwUZrNKr+H~ +zQ;-i3>3E=x0VKc&TrQX6M8Y9$DF^;0QVx>4zlCJL0Md@smUzV9&G?dzTlu?8(!oeUUs2kuw +z8;#2_oFcaiCb3i^5#JAiJ;*}OKB|>Usw*F!0sX5=Mta{D*Hl*BmsZ~I1N%r7 +zMUFqNtb5*!KP`QD96?i%P9!9-K~nh=Z^iFd*476iq_s#V6gm2^rt&c^$E8(OO-B)Q +z4WdCpeCoyGswTi#Q(aRn@kL0s@mGB2M1y2YLO7HITwGYY6LxkN65=KWFH35R-{KGWCB?;}qB3{5 +zu&9!dolk3};)+tib6myVJG +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 +zEA4V5r345E%o +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 +zu`z_WYJIGV~0y +z)3LP$>Z}Y@4PAqST=bN5%*-v!i8x~2NQ7%`>hwESr%YN4c8N?aAD<2)Ng>h$b3ot% +z1oYWh+gNw+rq`v5F7OO4p3uAYBaQFyE(M`7Rb0N_Z&(kqQxE7L0xv(<5tlXMtSQ~Q +zTf+T2W=1#tsOcN?B+!JZAWV=TRF;W<2ieH_nDuS-xQ(?n$BG0Lu`QI%&CNbe5#N)G +z)b;R`-`>v)^F%%Vy6Qk&=iszoO~LF?=niUajagycQCN&&=BOD+LlV$~nJ9g7Fr$m< +zXntiND}lL!tgK?KxYR&~lODUxFX9@A;*tyINFg@(m@R5!gIS|iKp$p_!ovb;n_HL( +zU7<}M)6;_6`!1iV0xpp^f>KIJNgGsl-Me#utsHZ%8QYZIjRS<)#vCKekZXVeX*RGG +z(`I);Iy--e@gZL+W)oxcN$8jP$=Yo{3PbD(oRwQLizv20ul*fx{a7H!i@=k{r&0@HI9_{ +zw5*h)hWvH|NQgx_-rCyI(gNSyV)45TKoR9a{6pIZzvUnBLgjz{Jn&C#6l5vh{PFY3 +z&G=G;^3Os)uc3%$-6x-&ZpG^~ero_I$fD0aRln$W1^`7mN&fcH@m5^i={E*|g3SBk +zt^jj?UjR@JeU)%r0NBuig4-NR*4TOGP`|DOj9d$t3uN(oN-s-5M0DO4^q@UM5y_Hf& +z0l59^0zlko;hXBeb_1uM*HCzW#(&T+!>|9U0Ki*Kef@q#pSD)K*DneHabJsn)Gxy? +z|C-GhajUFQWg +zK(pOX4FDP0`vdO70POvl0U#mP?|;C3;s$osKQRDgWakgL4+F6C=LLYc1Nx7+4+HSV +z@}~uWjBM@TMuZ)=7JSRk3IGW)ef5Lx6K{tx{Ye2JBO89$eHeiCKPLbr#N_!8yAK2K +z-1w(dV#Mv(epo#WK=RKBK-;Yk|Aqcm{IS7L2mo=fxqqP^1|aso2LMHMAN(u#iQ5V2 +z{O16Wk=6gweHegM|Mg4~MLIYBOZQ;_8an^S0Kn@EKQ{A!+GPLrx&(@7)ctGsVF0A+ +z|0w_zWWj%MpLhfJe+dAJsMY@Cj`v$lj@PLEhX7EJ+5gFX7=T&-J^*dEll)Km<#?si +zzYYL#=hpwE9tL3Qznuh8g!#3D_8$#EDf3?jfVeZ~e^d_xF!A37pzT2(|5^XPK9(mV +zV}FACFaR;n6=H0Q6f2?LXG!cmer`13*TG|0MVS +z<*_`P^OM|%0m%7r_rHD6{-XvA`oRDY_u&0$`oH?zfN#4W_7l~^0EGQe0RH)){m0r@ +zo_p|Z_y75z{l}Ud5BY%re9uAqkF_5!~gu=R|x9zRLjO30=QH|92kC|Ik7EkG0nCIhOyC +zgZ3Y5GW_^IXJ7} +zfOrh&uX3L_mbdw40LaL$U+Dfn9?KI?ef)Lq!vMVf*0DT%%H+R2Z2P{}f^Y3O0K`)* +zf2I2{0I$tD3;=wJ=C5_1xJ^Na5BVaVck+w%x8g5MItTz6S^LY~hXGjg^#GuV;nQF4 +zJ`BK9!>^X2WF+A?xDNvm|Fr<1h~A^$;64n%L%pvAfD9k#^c&Q}0I@|Vv1pEeo3^78H%koXJ7vMhT{hvl|EOG +zkWGdhfAl-tZ*AHgto@Y=jBXYg|3`jt$**mq+_TGj8+`SWAYI>U*z|=5SGMjJ##)ST97Lid@~>^A-|-Qh|7-uxw5j7AJrE@2CHPf&T7-#- +z3M+vHe%G3`VCkG`b9$IS9>vda@N)|I*=6dK3G+Tav6@1s6Dg%Oe)f!cZOPRMe03W? +zVd5l3k%c1UkI%OzDV_}620I=P#|I)k5ai1TV1M>Eg^r>h|KpK}G9;r^3I##&XhhQ_ +zV)*cw_W#2pB8KA=5OoCYKX&@q2@CBOx!U)zcLF(kKne7dLdW=C$we6s2?{teko67x(-PMSgQJ0tnS&Cb|9<@G7V#!P*B=hcxEzI_sn +zoIf;qfN?|jdHlQY%~ohOZg%WBZtqo#nuXG(XXxjfx9abtZ(Zfg%cRvEtr#(GrTZ@L +zbJ<}G)sfG}jX1L)VruM?(}zTMl!1Gq)~7wRH7z!~@3q<>e2wcfmqq&IH&2@a-Q9iW +zKU#a^QP>^YV7+kNKL>aB=y@o|qd<$F+6mZw_s+@}?$`$PhUIf;m$!M8Us|^_!CQag +zJHd&kXNom5Z}mF7c+E1Q?mMUV<}A;@@T2{ThTeZ~6*A@4xr=70_G*sKl>^sil84DZx9jQCcW{Rqiuv42~ +zvktF$>Daj>&~R1PwY4KGR$Xj*H>KaW&ezhSh1TRKN0zwG!hLM&tTm!EpAYMdR@K-! +zls2SKk2xvQzc!^xvtN~EmUy-?JKv9dAf{!{Rqlr4Rg3+U_AGVo`G!B`g56x#se?5) +zP_$p|ZdrddLoiCVUUz?dw94kQRmtNc?_BU6xpYn-|D0Bx_1V@zXO}f#`s2B%!y^Cd +z>w`QxwVdOe*JX3|G4PoyCazPTb+F{c$v1vWEQ`ZkQjNNwbL!?HeZMPmYy6XBNlXIU +zBNdgIR|R!jy~91A;s@0P>wDVJk5pQ8$$VH^{bFcYUh139sc*FI +zHm^bKdW`Vje022aU5%R}raq4`c$)slwUEU)Pr>zyurGoR?ICgusg8OsdXQFOxHErw)E3%>3l)+ +z{^eCgGCPBf>T|_j2USzL9kdXkI@sm`7L1mK)6069_1DM}PbPZW#4zVfc%m|AXWh}* +zdCGq*Slr~nZKO;vYplq)-SxYNpCW>Q2}&u!1vT|D{9IN#sd@O0?3 +zjlIr1?J;*|w=ng_^JFdmmJrQp$EWUV93v?5x^hI!ntx(X-HdcPANj*(qe0@hv?oWp +zzAb#d@^XaJ{n4iDq!-RTL{lyDXM4^I-My&9_nJ2|1bw>o;eo)@)Q1f@#kHiWGfuls +zMON6n(MZf1IP7Wmknu{O57IjUG-$*>>P6bnQ;H8t5JozH%BYyz232KPnRhM(|2y|{;toS*XC=v +z9!uwBoqKYB|EA`XnGvnAZ@3dZAK{T>%nw;+t8UZi98tA4E&5*S@vw+-e%Qjdn`456 +zE4sbhKlbsa4hHji=W?B8eGex=|O0aaFy +zeD2M>aAeTs)n3z{1m6&oyQV_xR4j +z`NELch-Z{;eFM+$btn+{T%T1|@P2CKde4PN#R=%^VDG3=xiNNk!>5|AUbd>+-142w +zCa>!8(@eadU77UiUVnOc`hh{(GYy^OU3&+w+jiJ3WWMm;oxa`&igvX`o%w?`rbTVh +zdj9Inw{Q2nbVqqxHQ$yW_TDz^UBSf2!yX&X%EgZodQGkE>#G~|!XThz#S&W$y7z#~ +zQ7&B{MZ5hmS6_w?$l9tu>{_a)W%rRb@r;myakI9bP8Y15%*zaWb)m#<@;=i|Nt0Qw +zec!iCh+5VCobsb;m$SzGGNSt|id^0~Niexz^5Y8|O +zDLI}YK8?~pt(q2d2Ry>cr(JxKc$quYjB0X^`SSjVxd%=MI-Ba<8DNDkNYQob`)rPy +zPSf)VKD)vOq}S*#3men$4f&UDEk7Bb#YCb7_lvA{o92#D*4olt!hWR+zra}8Mn0g@ax*%R~k24 +zj=wJmU+917rcvCVTg)_WSCEc0z7HOhxQBhxZ`8)%t+uYUYxa3pcvaoC(porV@b*vPp97#nF9c^jNdKwL$8AHieVyw=UF!Ri!U7{}6F-t4@Gpie9%U+u2F; +z_i)9!LFb=m?V#>!$XyyV`VW?*i_V6zjcKLEqi1*BAWsQk=`t6Miwk>|mSVd;ru$SH% +zTunQWB^DZUMSiq7ZLvL{R>W}VDRVQf;N_de+#2}m*nZ_3_5R216s?=^!artV +zvqov&%o{WIK#KXDOUvK9*ca*8Hv_i{S!8Hzxc!{v?aNOh2AW<^*;_UGJt<_@v(@U? +zbjD|RE{jur@t%Be9OfOYHe^mNweaD?7j_eGrpBI#8nW%c(Bf2^OP%{VJRSX#$qj#d +zP2nX4bw8+K5a1n)id;v`Sg~4`)6K45PRz7- +zyi>M^dLG~PICRSh@~(VC|E>{uSkeBMYZg%VMP>9$!jmOGzL-MuwB+im!(gC-Lgmz7`ON;~enrVKgr%EXKs?X~$#@|q3D +zggm1MMo%qQb#@m_V#>ouy6lU;l2LrHcH*EZ)hkl#jU7j%MrhoAALF@tmFciD*0Bo1 +ztI0k8STOVAd?VL=NsZEUj#^^U*!7iHgK +zNo4;)4u_A^ZkfFB%-F(nHQc*)-deSLXNMvY;nR}~&rO^@O4TWH^bM1(W|QsnNT-|l +z1HCSjD%bd3H8h)VH1t4tYw@u=m(0kH<2dPtb)#cTV34Uv%#k(oH9RgXo9KM+}!&+kMVSqD*X*iST|$qhrYYm +z@ajglsN}kcv9ER;>F!6K_22IrB_uh+A8-BGyb)VQNb +zn$6wAo~vE=df#tLatf0&q2%D+m)GtGnZr4oGhRB)~e_^UC;WLJsq}t_xf;U!%E3v>Diq9 +zD$zU44=>)()n0Zdw147>vJlA?=6&%qSw{He +z!zv9MFAl3KJLNwvy_Gt~Wx-nO{YK$Ydp*XzjPfmMxh2VXr!uO0Jslh4w2BU`0-@@%_@r??nf_OdlWN1VhnlC@L5)6 +z`#T*u+F6UFI@BsfR#?5ydzE9;2abf(bI%2jKCrzq<6=wBL!pCJH||8z_&Ipx|dN#RK2=$lXd#k2EC=q2c2r~9WvUj +zYPsR{MeCboQBhk1Da)d^dDV5>V}1P0$^68c^*gh!E-m_FGa5WGOzCa&;B@x2y@h>( +z-V_*?>v>v@l`dIjZ5Fs=xK^2i)5?|%^BtS!ADXnc>tH#%^69yv#JT-X3YN{IvqH+#E^=wsJ|TBH}8Gc!Rfsl&99lB +zKo3m$b3xKU?SjxNdd6oTWroc0blQyeUO8F)Osqx8t(g3+)oZV64(WU`wu#K%#CyJe}~rH)gI9Gan~2pGY?0OzqO-;)Vp=yk>|CK%(6`8bb4N& +zF=FDlU9&vLPTEQ%XI;4PrqVd9d+e&Qt8N}Vk#Hm7LrDD4?#u+9o6o6Ps-g^0?dz@O +z$Ly1M)7ZX|yHoBMk3W&7F5?(i6fT)Pw0mIXW|zK8D82P-y9B4b@VC%-rjul#m#1PG +zUT?K~{agEhXUgTbV&g9L*k5xd_sTpiZl~0D9;$}qlq})GD(w^ZFH`$J);hCGx_oE9 +zoDqC%a8npQ`i1H3(jE<)k0kD?ELlTe+)~lM4)7bbl(#W#S +zLjLi+K9loTTpd(pEz7>Lc=5=ktHK9|YV3a((=sCYJ&9jfbwi+kANnC_I+Wd**#3pz^k9cdTpq)iMjVh +zrpK9SrS>CrcNrqldLBiqkB*@Qo}EBro3t#*pylo`i70k>Hn8@>Xlj6d_Q=HorsU$w +zW?9U@!~O;%7ub8e^}-#MHw^bpxsv}FkFu^>_{e7uQa0L#67}#cJB9D?=6daun|afX +zIXUP1StUz)TdeK%#|f@M^TVc?gdi8QP2n3}SxtW>H0bwaW6u4Oh)HQ~!`3g_UuNNZ +z`KDu^q@KmI^0$?ZUCEHvRy1vRKbAaX;z{qjoy&61N^Vo$yZiT4pQb#2u#J06=K1I~ +ze$9VrK +z>lypZ%cj3waA)p@Su6L)*{@!Eotw8Xn3rn7m^md!E8I0CO4_4m(qPx6%MagTruH&< +z8-JR;RP!3WK16wkf6rd;UaXp%yQN{lLh9mh?}KHW^O+;2^{dX%)7bRPp{#km1vY8% +zG}6;1;T+4?mvTC5NBi=udeuJ}H0#*3z?~Yolh$rNGtuTiNnF73tB$3q+o{y3=cnzt +zdG*sJJ=V^1n(&~m%ah8Hnp*L5RC*`aBFS|D*C$_pUc{+=X?;$|ds)z?x?72<>Hf!x +zot_&{nsCW=FlY6yVI%LU`Udw;t1p$^PR-*Cy2M!VXk}=&xrTm$&X!v$jN^$>Q-c$o +zYZ*s1nO7g1pX!p~H1=|3Z|*23be{i{5J#J){*0K7caNI&s9ch9=%N4laLuRcix-k| +z1X=of)P_HNW0arOZMIRl^2716cej$Q64jX3&&O)b#)euRnNH~v60rE-QJx^t*#GDd +z&WR;AVk?I%d9!2T!DAvvSM8etBbP5eyXVB2S2`ujMQ+ +z9B3ncwr}!M-rMltAzos)(a}TdxLS3cwKkQ;C$H-|aqWz*53nGmBU95E>wQ)wh6Jye +zU>96_t!fy3Q#V0m&gyA>Ufk3r8jK;Uj +zKr(yY?$_BhM5kOD-8^aD>7EXw@y^ep+1Yg4E$=tWPL}U18mN16e5lr>mN}I-yuB|_=C@fQMxj^ +z*|0fhp6-oaM7sW1n75`!Z{L7!U0-*BN9A_Mj-8yu+PcPOyOGg8t&#Ea{Dj3H5-%P; +zb*5LvKv80?D$6`{&F~YnC5LWJ_Liv3rA1zL+hWi^euIg)*O&!K)31ticO_iISDIe) +zx$uG(J*#d)Yu_COHg}B+$6)fPt+$O;jt?DTt-9RX`A%L$FTZlMclUnRZjPJ#Ualcaec{)~bG( +zToL$n#KPJ;kK+z&TuK`g-e2f_DO=OAS-XX(?$I*4yZ!l+gaRU4Mtl$-YywM4a;$gT +zy-i(*tR<;{Sr8x_B;GF`UM6xoaAl4})0hmgZpQyI +z@{r%OEs1~&%-Z;*#V5ZZ0yxJuyoy(V(ekrKC*!(%;nH~j1}pz|7a-GR7`CSSN+S=% +zhP$gCMo1JmoQd#nkQ+5|AJrHp=1ug19}g+f<8tncF=ViXuSao+M|Y7+HcN +z1heC=x|v;)Bh9M)KPei(F|m} +z-iClFQFBu*h_zJo6F!YRsZ0}fX0Mz$SBW=%`UOLRcuHr9lU0XLVS3*MT!4~((4Jt~ +z%71_@JS~9wlmymR5aV89pvF%DA&PD#L|wlPF>xC-{$D1wkyP>TNH~B{T43Car5#O& +zpnkQoMBB)dN%B~s`RR9Rt>n|FdewncOw4e<>wUd3pDhwQrzbO@kvZ|W)DI}C3yDNN +zRGJ|5D$aM6RER=R|8Q|Gi~GO)LiD2%LuADTt;Z!AMs3lF#dqTvz)#C5wB`ap_!MH= +zXK}-duXoG9;I(JuIt#Qf{N9dGeTu|_q%i*#!a_=*YH%TEI6}o6;a0M9rLZ>9+n`gg +zaiIqDM0Pn0`rFFVg@LSasv9zxD;ZV<%P|!pB|r0_P4@bMl-88AqoViW8h_)!Uz`2s +zo6pc}MF}Gh8`#ycc`Rrxloa_)O$Qybb4O>28HALJgU +zr;PY;6(HO#z{DzirE31cnej41P}f@XyhGVh6Zi}^`H2QizOYyN=OqOMG$TG0tM~h? +zl_HNToPIceJuk<&TG;9Ay&n(;$cv%cQWA^b>Z?AQ!Z6a8IH5TQl+`_9#zD?A4*dkS +z?(E}Wv>?t>J1sy-jq8zTVLX+fEpli$BR`HAo(9vu4Vpy1<=Bg3LL_FUMz(@HgPQNW +ztHW>AzXE5YfN1+pERUPBWW4o6Q033C2C8k>v|rl@Z0X6paVVriT4i>G?tK;uhvr%Y +zXwDu}z-{vDx9vv>0+m`?8#PHpb*!YpH$w^Jhk*>kItvIO +z)8|;Yxg_+5>57aDG25z!_t#{q!BMr6jM=o0KbdwkOoa@oUNpmubPOLbZVxy#*Q*mG +zjXX(V)#Io5Kn2RrEqca_x!<@7fyWUF8GGm(QrxW)mNrrx9HXlYaS_1qdjUbaqwT{Y +za(`QrxPwZ7p?ocPD0^vYe6b`^x1c@A4qwR6_yOIrsR^U@I9}SenwEz{Hz5c!1wWR# +z-{%gj3Fw|(ZE>;jENA!{cf*4sK$UaKXpAl|q&o%sY$=S>AQA&;&35~oN=#^l`7i%W +zK1tf1ka%S_AXBUHT&#;&zWcc5sVxy<`P3#N9J>1G)cjKUk-{oK4hwTYYd8nJ@Xn?e0<^Z*0-{cLKuS +zo1fzjYg|ej6W(9weJNYhsJ2Dm5;yl~=W4SkXjtbSxvTqFnB5l&pWV&)X_v-cKW#9T +zFc>ZbRu1^92Ybj{biMCFoGJD8(JWwbJt5J=j0SgpDyvsG{(-+oRJ7KtQWpgBc!%@s +zSnfdm1Msi_XR}Sl`h-f$pGb;?M$_RDgk7z33i8ACBwtj!wPo5q@$sdk>?VWt*S8zb +z-8J2E6%=Ge+y#|zS_vTUtIJD?>&NB5`S|eu$gOPo&y|#c6ky(lbsdu`VOld4Gd0?m +zd+1Gb{-J_#+{*s46Y;O{HC(vQdMh`42>Xy}3g5v@s5=ewFYW{ak!I5U6^BPO86gyfjIehOulRR2**>SKZ +z)*2-?@Gl#4D2gjLg99gHMHz8?5cB9ir_#qhhXU@U_bTnfpv!sikroN0F;%fp@cz=| +zy411Qy$MKTxZjC!;)~CU5%pL;vxpL_`HTs-aUPx&;rGyUx9qz&O-F*3Yl!)}6zTzJr@3gUnG_ +zO#4E4`u|s^8z-JvchSP~@^-A>J0wU?a+*-F72B5??p#~KS<+bv2K1=K+5Z3~X96Tm +z!h2y~_pM#gL^t36S-ejOi?(rn5?TL7C?(_hb~S;ndn0zQvVuD(r3F-0TP9aX8>yf? +z&y;W|)-YXVb7T( +zTZOkoC0_eukvtinUzE-5p!Fm$Hzj*QNVbp)Nd#xK?ZmSgq)z<7qOx$7on?BOfSBdq +zJj|8BvOXl0L~Osai65b+ih4^&GnI;_t}#+73$(T` +z@stZZ2$K@WT^8|ibTU;XfdKdlWL!`c?rK6({_d`){rG#@AoL))?yCqxN_ORTsa4eN +z9Q|O|h}tnULhXD7%Rb>SKIHOg*m=hiyAt;xWQ~f0rGp4o`aCURxa8#EUqrzw;N_!D +zczdTKm;Y8f*~LDL$C-@CN5uXT{47heY1)3B=fu0xx>5-?^|@%2-CZSDOWfi}#z(lX_v%<+IRm!FV!TY|k{Tvo*ZLM47FreNyt@7#eMk0Oa=iWXY4A +z)PaVjFhbW{!SfA3;QxVe%wi4E-Jr!E?zmFE+?!&D9^sE}G?+NOr;31WSsb2Ggty)E +zM2O(ILfkZeCGm7ANJYJFHCI-c)4koV2mHDk=b_l*B^*2dPvh35ZY{xLgn~(gLrJ1j +z#`o@Gc^tungRE+=v?il2c8`%3B|G+)?)Fim?2fCIV*-oN@C`+}wZmDZcO3Nx7W$(l +zia?xCPQy;X)b^87Xm8M_=b9{F$l*A%=8o&lu`zL6K&8$4uRJ4|o>ld-(?>|^cv7imm!%+_wUxCDiH6(8s +zh(tD+st*L*z=~Vzr5=w5aJ7%}Co`T#7}>>`9q>Uj+K12M7l8IceC;X{g-&c?jVum3{y8%1rStc)R`Btu)COz=g{j@!X +zFIxLuzSB(|Id0_NsLK@7PWb{l|`X1X;I7(__uBgt31 +z(8K09Q~i}MixwTo(UA_#AePD_;cB;)Q&_FKu4m4~o|H#D=?xKX;ILdNud{88$1#OS +zxr9WD;llP;HQ-;HgHQbjpn!XTV>7S}4H3z}Jf{GP5?8k?3<64}*q%=@MH+og= +zpt5Eo+ix!2kI4e^WJj^t%N*WJd^1L8u(?EPpd{{dEf0xk6XCPLsIr{|qgQ2?SbCxW +zz6z-sL~j*e6DZV$6V>X+j=^7t@8nTsraR%uW8j@CJNZu7%*BhT9_4O1ic$Kem5P?Q +zSp$Nz(gp)OV>N%w;hZ}j-@~4K%Fv1vC3@u&)pDy5CxP;HBw?LtWTxb18(2}@b98nC^}8_jM@0G6Z1#47XT>F%>V3RS +zi8=j=rje8;>0c@7ruL#Upo5T$4|4brR-dT*)k=9n<`2hQrYlfs2a`(rYJzg$odXQQ +z0oS_a{$vK{M5G5ra?_0oiwvmYyDq~8IU?7CDvfb10pR+wqrsnQ9sg$t9j}CGU}rql +zl`*Uz8$qB`>gCe89AH%~*$v{rE6<1GweQu{_gDtJ&x)dD?B=i1t0rlt@+w760{n4G +zQztevZuzL>x1klbNAnyYAHp!z|3z*>6g*3J9zChTRR^gk?bt=*9Xd0Wy%OU|%~bcL +z+=0d|K9On;?vT~zy^B@HHThZP(L~tVZH#dFpkk`vMN)e!`jFen&UzAA2wU#Nn!VzQ +zT~GShyCWR4%a*itoLr+9t{Ly&WF(G}@gv(FBr2lkPonPUpla8yA`_)jdj%b~mxmc@c6Q~pV?RRt{ +zpXL(kD{whbWHUG^)}JbsIx7jcDG-6kn+g5z&e+3CU?s43K)im}#OLh*ipvZy%jHwD +z!$v>nwB^IR?TulUDGB?Ajqqq+5oJ&!|2VBQ46F}zr}fwae`!16!yp87z{ra=X*UW? +zSy_aSIR|lYoHS_)O~)qw*89wH=L=kk!vS0d!~ONiV=g}=;T>|c +zShVWAYGh0i0%Birrs`woIUJX9yTU^l+>l;0H#xetyI!ghdLMp)(0@bYB{_qmFo7{L +zSllr(3ZVIl2tR`CSX3yML#GG=N{RWfV>ba@S +zf+Ltka-Vf=c&nBeTOPo(;{xAz!VdlK^`1`@KSTAtPt+#8z7n|L0Sdm`%(x4p4`qxt +z-rtgsXPMo|VSI-5x}~3Gu_hyZAts-g)CSjs)A +z#}^@3>WJvinS!B)O@ov2#X8$wNuzaub@Nu-Y833(Qt_`wZ>g++@u20cgx83xUmR+I +zA^a1g@3>FhJPl39m*+(k=P+bRik)TVC&vL8%Bm3YX=D +zVP=$Unsh9{npo(>tnLb0t-#{%$VRUb7ddJN$$S_bO^ky)5j4#H;`ku2GwaKNB|jZY +z6f98*MJqFz_f;WGEpi(c +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 +zteDY;!-6^ +z6gAh~rSt~$voM3QjlBXgRg0p;#Kv=#wtP+{5a~ydk +zFatWJ%{siTxIz;~(!n{mb>G+c2tsv32fgYuDMpC@6=bv3w)o%(5P*zyku}st_j` +zCiNMDmPkZOwn?lZnu}%2S4$I_Xo4z6>H?a|t&;^bzBi`f=&RB0J=4mF+XIIL%}=h^ +zYeqkJ!~`gY0uIl1OeEy4(BS%?S-{c0&3Mpa8^xF~tgDdlplAzCj3OT;!F>_BdklKZp8p|%N}_pqKaxy+tqFG@zEHCa +zcr4=F=AWMeXSQ{#R59niM!@X)&k+S9wDX=nSRbZ`&rBCv72lRKjBib_gzfCvR$~7P +zInjkUwtg_gMVKwoT9Blm@yBCMJjeJPI= +zlpnd#?mnOV6XzU2jPkZypO_rN@EB%ts(!j$U^IAJLpO7T8NOJRwfdHDH$;o-YC`Hv +zL2bNr!kl>uuUujYdd5=SCC?=CpKp^>PzrP0f?IH%f#=L9IO(&u3@P@CMo`mDgrZt*+XU!oF?J*zn~+oEwRGE6oBy$CJ(Md +zEIK^LaOA^i{r;|dBHINO+jnTS^2Hf#h#?B|^T(1AIxMO-=WPjGjIJO7VizzKWx~d6 +zoVvZWh#GxyX>q||o`~?^wHE3dWO|nK>-B*Hs+SI)h;GQ+Z9uek0G#Bj{j7l`2$+e+2VzHe%hQ2Hf05Y5IQ@KYB5J8ibxX7h}Ae95(2CLz%|jak?o1a5j>0@JrO2SpV{EJC`$p&@&f_-_Yza4$rG-hy*f-Y6P&|8v-75`-DO +zMo+$cl{vnmkS3RLMCt+Z5GbBs +zSnwDwy(Eob0CRoDQo;T=K8iY(c5`lIRt%{&U_xJcHG9}Xs1By#qWXatsfBCXd_4&SE>r;t^M{V3e20 +z4xc<;Wc<%Gudau8%JW8=VZZN>r_3;#5H-Nq8@e6#4fjG(@Lgm#=s6lrq5*i6C}dpP +zg7O;dc^0790H2NKP5_j%VK5lYq7+Jhg?@c6qO3N@knEbzQER_EyA!CzJC=-)pUQlR +zj7b{unm;*M#qy&nK6JcGuZDyYOYTi+5Di&c6DQb15v_W*KQ<2xENTZ^0sgEat<}X3 +zav|uW2f~^U+^0`krW&}kEO)c2TW2Bhcncmv^R}g|rntDM0?!|D1xQF-Nabt<2{dVu +zCq)JCoaP5MW;{c|`c#Z^LZ4iAYL&4_`QpcJHQd_;mRCa7d4^VwH;t(u3JC`+cCjpE +zH>#3Ps5ySAG|n~<1(Rw6HhLQ_ZWT~AAaC3v@mv8=@Ty5+USrfy@A6)@B2#{r`0G1H +zTQDqIediv4=kv9TXa+9zc^G(mmy^4 +zNtL^g0Q({{uf6-cvT09G_kZ7ocHaDjy#H +z5T(>Err=5k3Zh@UqiE9MNk`xN62pr{Ebnz^_!!FiE=j~>@ru~^eB6<3e$PSDyOG071&lvPnwX&`(|a(iYkaP5ra~LI +z209{{D%ST~#2E_P5F-%eiB3mU_9<|t^gqgNl^7}0QEu}U464CP8Mc1BB1R4J_Q%+T +z(5MD970;OQ1RY>y)ZQ9wI6UQnW0CcS?5vS7zL``GdE(C@PKd?wnbC_f?SnI0*P#6e*0R}-f4kS6f#)G3ZciL662`YC9&uD!aThII +z5T5F@B*bV&`a;wUK(%e6Grg|q*<=oWF(#TS_jVgN1gg!7^AdC{a@qVR=6|1?PPXX; +z;_EqzYjiN=TBRSzS%;F=)6750ahVf$}F0u +zEq-rX;6Sr{4<*9t43xQ`o>(k*XoD$q{E4J$K@2wv!MW2D6V`XvWJP7HTCbc{c6As8 +z8ylVz|5T5=UT`UWOAnNuPVZt&S1iLyv1vR3c{Q8idrE9?ux1c{}Jtp^F>@g#fEN%r-$+k1}jvO4ypUs?kbhK +zD_(-v>Wu-Yh63^tfL5N^BewU2ZZr)sQ&%g?#sg65EjSnI{OR^ks6|u9#HL97D+}mL +z&EGBdlTtES&k4a)P5n#;wueR?Z%xTww$~+`cgV5nWQl~hm=-4AEyLahMZ-~X*-gq? +zb=G^LVq5Pb}HdpcP7(Re*Zz*b8{6mp-pX@xS+DAYvI|3QAv}q6SldD9o~d +zhgL$zE6>_@(&ekmp#C$fUaLP6&);`Lx_86*$J4PwlXnnt^2dwn>Jllm)Gl`hZo}MT +zfEgLOgZmnWy&V5;@iH$@tJ_LWJ+7G=YJJ-8J|YXBp49TLz3Nf#yC+YxmzI-=Dn`%2 +z0qa@ES;l0=Vkx8Lrm~ZfyWHV05kcl;u!`UC=dFwO5o>F);jb^?1=(WVqV?dwY3PdQ +zTXvIEs~)b^f+K=-OvGf3tqkVlliO-bZT?cg2U +zf%z|xsvtwvi6D>LqQna@pR?R?b2A!MxpRHNQVhMZ+fZe9fcn(DYZ7i?iitBF)EeaB +z4Aczy2RF)-qS-)h@F}B&;=3Df&ZPXLeqSK|I4m$U92p3W+U`V9&IMJ67ZN?nmw2pWE5D?d!K6w`2b| +zZ$EEkAGfSLKW^53-LL(tks~oRgzcwPY4|VlZ9A(oh9C8s1HjL)tX@=Z}Ttd|tCh6zv +zAkAlFGU);rdYYeINGP1*H^#z)n8nrd(@py^!Zq_W4$(YsRCmt`)y}J%0_%0qn|b&& +z*A|o5dTAT$hSqbw)YIeTiw;~domJn`5S=uf3Sk0}!PsCzMiAmyUqnc0MTQ%d7j0Kt +zIpA_z%(t?}DvwIyoP;D3KvH_3B-X~^K5GzETkU@b*WNj1u;VPupvzFr4p^_DcYL!nprrw@?8i><(=Y(sRuZ1CA6_)hmxDCQL4KGf0n>@=T3a11{rO&o91gvUQm7@Y-Z)DEc7=1YC@gLsf?uW|6JNp^)( +z>#YFw5Gl*ua=MB!@|<;kD~pIQB`vN|vSMopeSgH-Smv2R?tu_SM|_L%@+0MbvVUlf +zg=!TQ_4gRrw`csFv>i3pq`UXqlaxr+EuyJWG!hIWzKslWa{7A~yP(nJccb~yQ({Z6 +z#7ldq-uw8L!-6kl^`x_na%9Awv?%7Q&iO= +zg|V4|k6qWUs31}x)k7;nk5B^>tB+HRBnXuuI++Pkm7Bazf{Y@kLek)|PO^hYmmu|C<9R}jU3V~F^Z>0} +ziA5OJ^L|;f8BG*BaMSGrW}vQfR=2dRHjhv`{}Bg}#8q|{SzMS1uU7s2gY5k*Mepn< +zD8@mkFR?`fqxTIv_7;hkR!EE_^0eI&rslDYj7cn=+j77!Ue|FHxx3xM_m*auZ@3t`q +zq!Si(cvS}66GiUqXExGWQ_gX_0U+u1+{;ib!_q&X#$HB6cME@`-V@&qKX%E2@Xsv$56$$Y3X^bzOIhs +zog+(OW0G3k`1;wA71#``s@rxHmIr?c_}n;%+!!zcP!%|E^5DrrtL2% +z!Pf%k>?Ie78jr7Do-+U%2{OMwf5}N|LXRehWw1`9>cJrrdb9K^(qLvl3QnG#w61se +zeR@mcEmEG)@UO~+1Au>itfLLzrEtPPGQ0RS0!v>svZDuG3U&&4u)|)N*88^|f+D2A +zm;{fAe}G1lHq+cW&W;bcsP*ula#d$?DU7D(7)_!QnX}tfV&vJfq{MH79jqhhu=bY1 +zx;56|JxXyUW9f}!pu)krzpG60#)D`&V_#ErtrUX#Tn32IiDI+_W4epHUBX-zE=c`! +zyK+DiZHD+XF{{P7-E$ckG33Z5d%#6r?DZ8e#!>bb@RK_uo1IGI +zsVt5EaSE5}?h}=hFn%h@3IO_repj~~JL-^P9D-?6(OKia*y^UI3wGbXhI$lC^iP9B +z$$^hE!jBjKfXp+>$>-k)?-=D5Wzk}kNB&KUOu}=S#U9n%0qdPVjr+05JPam-WjVGv +zVY;jE4q`M?0jvv?xTJn=LZGU>%4c%a>JP68(HfG;kZx76$tmx-^xA3D?pfW_=%oqz +z)609qCK5{C7Q&cMOs5(O6oXZ@4JhIA5lxk!I59N1<5e$n)d4P0SKLplhj*7LcLaQU +z_%SQBeS0R?4z1f4@I1s{xu{SOKd?3(@rxxg9Q#&=#B7t6Uom*PxkE?G6~c{|0*z7H +z>_Y@uhRCz8)+47IefG`l +z(VYUu6oB!WrRsWZP6H6$x30I9z{9X1WJDez+n+O6q+ZGb*Kfg0`E5x3%NY5 +zkix<=6zM1tX`GW{FNA!7b?O17>zwzOOLC?0-FVgqKeIYG%%9y|A~8WD%75A^|!!Z~r)QAH;|ff(&E&%=m(6c+vw#HH^3c(cT)ktAEQI<{?Fdu-dbZQ~gm +zdu-dbZQHiF$JTw{@0@#b?(MA3s!F<6(v|LX>Q8m8`1p4*UQ~xkRf|jX9)b!g2Kupmjck8O@=o=ux_gExPu{Q&6D#qNxrW +z)Ls7OEMXt|r9~hd=bBc73pJ8dd4*2mCClCzRTNYHY0%o4AK;&BL;e^yQ+5Clf*vNj +z+V&|LR};?~kA=TKbf<&_z5aelEdRUF^PMJ0Q)SiV9(p4VkbL34q +z5^MVlYvVfY5XJxgY5`QdIxge(zJZTCRU_x9=ur-~(v$Z7PPUHbSct^+=TF$)1K#O^ +z_FyZ^fH4WB_!zt+N@+3BR6h!6zjE6^X8ZlmBvZ+cIBPwa +ze70o~?T~f8Mz~0l3WBbhey01WP11G1K7mjJ^48Bd(tIKAbRj{~nbP&1 +z-au{vU#L`tyBRa*J^f=uE7}ERBDh@QB?3;x0YwkJ9h(<-;gn2l8JP*D&XeJ_snxdQL+$sMp_c-)y+iFKSppdSD&xQy6!D8DY9Xb<-P(RDjy+;g0ABV +z6lWi?jE@E7-4DyvrVaj$0Z#gsb_&R$k6QNQU6Xi)Zq8z}38VGNT)5LvsPNOFkpi&& +zd}x#gKc-c?Tkt-e9ZiEzqn2-LKqns28CfHwHNgWjZ0822W;lzMv8g708Ml +z9=Fo&9V#HLg!$93M`P~ZuO?V_XHp2=53ZAn|8I07Q)ugpLlvLb(}uZNcfhUD=cw?T +z!f-o6CuCN2{Mb0Upvg*Nl-_HV`H|&(h;t2`EO`i+N;(}%Z_>Jk;8**eKep{uz@_#Q}!MBBz~2N@*` +z$lq#v3p9%{_$|<~G3e@2IDeY(Xet9P09Sa2JkiYA2l33NxwarOp)xyKj^$M9?MBr& +zvsa(+aMO2LtqW +zs5={%WcR$7fe6?IUxv2THOqXm7~U70yuZx +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 +zzwTUDytCWqW7gkw*U<08s1sF0a>Ku +zsFM?gbud)^tUjKKR#mro*G@SD8quDGH+7~!FJ%|~N8Xhi*Vf5l5f2H3i%OLek247c +zio7b}?5ItOt8xWb(L@0jSMoN#l7`cwdX#>{3$cZ5HR!RYEJ<}Qx4{5<;uX+2{&cAm +z+7oQKH5^tN`bl?d$FrFt(_Z;@skA_zRX<{^(rojmrNFp``lb!}zte>j +zhR~Hp{yt3V_{YSrDLvG`WW=Bp +zQmh>L&e)S9ccqx2(^U+1Y)PJDpj +zVZ~AoR2zs}4^CdG*90;0;8hLd^H^ROnbetqJCd(H?#bV1{c%IC$EO|O(n +zygU8Aus!ERfgT4nbarS5KHsk2I&3~aIlr`}+XCt}KQ;cn{>ra&7j58=&sWd3DUTl^ +z-+HV8(_Wsl%1!aEP|}uq9NSDzCx=U2msT#UIorBPK?sIP4=|cQ4SsfCB;x6p~?oiACS4HK>kKv$I^!HElM9v>i!aOTlwI!GQzpb3 +zYK~l9LP`4gaHJWRTA%05E^eo)f<|Thm*lb5#EMGHSq!6O-U7PfE(d5(4kU=0#3IA= +z>p2_o6zEME7Sllphd^sn8$4NqHFzb#w_H^6m#q_xYa~B^)ZEIOXY5wpyO9*=*@21x +zAVo32nm-$l9Kf>X@CX{|*Ku{{?%~0~c +zcw(}1MbeIYt|@0wx(YOpeUZodU5&(r-6$5?tfBlrzu?8|z(d>YKd1^+97Df2GJ92E +zt~^!?4ny?Z<~cesdtczXkR-^30T3AE$?wf>BK*9Hrbz;xC*HY; +z{~U@dS9-v%)Akb+3NpVG3uelQI +z@pBjI(|kw^?RWeZ)J})&o;uiV3`~#ElOI8Frv}|+Il>$=GkN_9Ij}v1AE{jxT#s^Y +z3b6G=jf2NJGWkp3aX&CU042H|6|ET +zfmwr&bDh574eb`|kK=Q6_}J6-+E)wni@$=;W$aUXyj|aCjzP0KcC5YwIGl} +zAPnVTX&<*Q-?wL)=;XVv06s0tPTo8~xy-mJ2qG-hKg|Df$g2TJg+P2wWCaTUs +z7$!&n@x+i%9;xJP`Pilb*ySl8ub +zZEG+w8h-q$TzGDdjRMClWuV`I$+GoV#jrS?EMb_2dU^%EBiHK4Hr3IG!FGysB)CHf +zZz*mKU-#3VvkE4sn{wM!j2Jcv7pF((9N03?4j5mhEP2Zu$@Y}A3|%rJf^KO2a;=)r +zQnJ{B5x<2lw{Xz=pdq;YQXELY;+67?&T2$@;rwwd-GzT^`4Vi!Wu_p%Uuh3&k@s?J +zG(5g%YzR(Jg1-Z;x9`E|1GY=@4gFNe1hk@MbKG0k*l*zC&;f=EH`mG)F<-kqavnS` +zNyGGcb|lh$Ko$VG-bonNn4x|`C5TQBg4suyZY`0_jk}Z@ZLhxMZDmrL{zA4+mq<%LsS +z=<>R&Q+7jDrlHj|Iqf-J-Wl1MDW?8XJ0ywZo>_QWzZCTTfpyM(bYR?Xf+QY6^a-xk +zJ-%HnMJ*C83N2^Z%@1@N9l*&#(n7w5d{8~rB3_({JcurItY)|Szy=NLWNf-$ogGy5 +zp+Ky)QO1L~P}ySrQ46T|QR~x$a+_yw89rqk?NI=oLS4$pp&50K$y%5P4XnLZs^|pu +zq+4E1sKCWuxCX>>3&F{Swb!W?#QBHdlOF~MMQYq-WL3zL8%~g_v0=?l_v-DK5FUXD +z9T({{?wJD0Qi3Ass&Q`_3^Xk)*;aT@pbx#G8PlzsGiGB84#&)dnBtanuVWh?f<70z +z+7s5I5t5NVR*53OgM9oXd0a)|v%T;BhggV#tI4W +zPXpX8$6fI!b+TP$J=wW9d0kXpO2&Vk4{BI`dl?>F +zkLy7Ve){JiRr^cyI=}GA@bN(r%Aha$fSL0}(koY9 +zgOck3L87}uimY1LynhnkSkh4~Q<&Z1;T8Px_^*m#6NFpq-ZpfnX@=_GeJnJ;=ns-} +zc!yXnMfiXOu>05Pe4@u(hmJ3P`$ye!K;#q=!BmGNgA +zkNqeaQYmR^z0$)Br)M^x>}yG+MsRSDBe@a+bZ}+in$&~;I_s`32 +z%rnbhoZ7T-BCuMinh`fxw+tlKu~9Nza_nwRj7g3Q!Am_9dm!iHaW8D2W)-AL#fYln +z>r6|)ni!if6c9^-`O#eYJ_Y=E>wH4Zic+o5hne`-&$#GKt9ov+h1ey_k|hQ2!rBhV&Sc6-)Qv2y}_A%$LrQ^7hTbv@+0kC`}*32vR(91 +zy#v^8qdFKK_(OpidF_`ZylrmN?&8#wcO(2nH_Vhk*{Ao1AO&cNbMB-9dcOYXQGQ31 +z4WJeHbzy2MNFfZa@NTC(N$HfOQqA%8^F7dd8)Mo`442B20d|Va0Qh0B>B}={YT|mP +zULOP`oqro-p)VGFZANg8T(sIDp(%HLVLj(-VxIT~|J#+~r +zrk7v;ER^Kj!cbSZ)UTU^#p+GO~f0SSdy!J|YtLT;D)#_evig{|V_NDN35>FdR@Me<~@$N(Q~ +zXc{zP(^jwIKP#FD$KF0l$c#VZpCQdqmE+tf8 +z@T%fRkTfTOfFO`Rs0W3f7ujqt)Y~FEX=6Zb_zC~XKS>7uvkk#?xJvt`9>54i(a&YA +zrNn(NT(8o)tl6XR=td +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 +zjJmsJ?p<%oC0()sR_qwm4MSCgg>o0dH +z3BR^|d~-0!Q#=IdG@iAy%{Xvw`C`8NG93E%P_ohTMue6d04&Pc^^k2}u +zBIC0>g`e#ZV{9Sd(oCfEIwM}a^9lo{jQ25{KYp#{8gYZZ%bzt%9raDzwntg~*A+F+ +zuMKo6c3qX&$rZ1=HxjjA4K>;B)i)=Hwc%`)H`xIg_K0#^PlJDE_TOY3a4~@!xPD;^ +zOf`1amR*RnM<=vfbJ))jOHVC#UQ$s>EvCPQ;Hl*zh9L~{iLe9Fz+Lk0`bsE2#SLK9 +z%dt{_#qH^o_3(%A<_~XY4lYMBk(ZUOrT(I#HB@UVC{7>l!~abS>T=JhgSvwbVG=`J +zrx>2-&z3535u5k)RQ|WWmMKsH-(L)$g%^zwIUc}9kXZUY(gS3q8AM}&jPT6*OS=Yz +zmpetxZvMk3efN%SdU58cbSFI*Zx54JCvH_*=p(N5BmZ1qLA^C)yzTd=*k)1h>TR>2 +z!;%x@i_hqAg5)iW!_n~}uFYsiAfSk$>E~b5nr=KAiCR$0tLMVquw$S6Z&;K!9A*9I +zFLpr}Iis6+{4s*g(aZW?YyWqv!A+ynr;Wgtrb1r+`iG +zgArsDiT`JYU9I`-Ks|A)2bS}a+Y>~jREA(ARdWe}qVil{SyH|I-LJk +z9$jQ`=?KFF=-S(3Y~!}STm^x&9svj5=OSXeAlRaT%V(3f$FX^m;cxaQN!@sXcE@T-Z48 +zYG~i`I#z50*h(a`s;w#o-eG`5!wJ~~8iVP)y +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 +zI*`DgBX0}N^BCshfT0hdvt3jX9Q49%(yQ_ +z0dq&7D?{#_PfD#v4mqE;9vj$t-VC*YWApKnv9)iL7nTCKyv`#=7_~ljZuX#+-)(Mc +zMQe5hS+Xi?K_U7JryeRpFBp7yiYI_XPO@giQgE6FSdqt!litNFG#@0$rH;2;L$wVU +zb+hHiZmjDnFNS9U-X2KG302I0>wTLQna=b{V-M?VFM$UrrX9GP<+1>)d>uT{Qo#RG +zF7t(}z%NfGR`x))Yf#$QE#0Cgl(P7)1cSU4)~PctO&*apge9(*19tZuzZ)}$4jI1Da!b|_5FJ`<%_=awKkc6~p`sqG +zkyCjgiBs}hW%!01%fNT*(#hjT`}o{8z71Eh1e{;d0O%KkLkkVy^|}%V)zO0Br=zQ= +zeD7-o`X9mUd!;YFMBhvw&Nsph%{8Vrk#N*55n=dj8eo`5g4U-I1dfX$q=3>QMuN4b +zLN}EqdUH0-gUoMecJ}Z>jVxg&QZ!+&q)55yLRZ6UMc>-SW*|_h79|o2FfwtRIkPlC +z1;uNusS}p0`29x#THV#{T~=NtA7lEGYIztBMp!X^IDb%)vtb3qYm>|@Icz!Wp1N3= +zccmk1fj0SHdZjG%#nN$3(XOfr9KaHXut$XbWq47k)|ACK4`L|L*nzCXfxOVmq9OBp +zi(9Q!$V@@jT{i*n=II5gZhAp406p-{(1%R}VNA5Z8%WKyT8|fT%7>43mSApC!~kY&uaF2dLL9sk*XQewqLyDdOf(__grwkqO)p{tZa`}7`iFl +z;jNu<^}Jnby^B0iVx|bW7jr{?c(kJVlY!bV-tbpY!kzuzm0oEi%t-tNG)g +zP;L~BZ`BX(O#OIF-P1RncRY_pg+awplKsg^$HO>?FC_mM@eXFMAKOfR-p=7r&{I*vlDl<*MP{IrpME>e`VmQ%_ +z6WYDM8N4hR4QSKTBoXbKquLW^pL0l>Y+pJN`1++?(Jp8cKQd2ruhMkJ(eP+U?Rc +zCi%D(C=Q6vHxH-ab_Xba;0Y|93(G1DTWH)1gGR1PU7y7CJC>g5G#ps$P~#MLTUV>DV+(T|2ajriN2M=?^CM=ON(QxdUh!1N +z6ZV^aL8*;83L2D(#JTRi?Q_rQAJ@?Qfa)LFl0%ZGn~$wr3Wjhn_Q4j>&RDwzw$GHG +zy;P}PbbBJxtpyOfh?eH=+(^yLoYcE$!2)*09o?O{N-?Y+Sl{1Z<8`p@14$Wcz)&8# +z=O;u+e+AV2PykyeAMo4r!=5ZAu_$BvGlap@0uYY>E4_6?OHhCKzt{;kXZJJfIq}F* +zS%mE{iIT*)n1H0Q>i&gsib?KET0Ujmrc{e832X?rdl*1hf7C}g2*pNzEO##iWz_(u +z>ES-J8V@~#Dnj3_8k{nb$@VT*>|s9}eCqLtA*wk}f-hcP-qV|P4}_F!tEJ|vuM98- +zsM4mr#>9U-xCmHAO{?kpaCMi{k~uW|(t16Ii-cTrr4chJbUS_KmLAF&K;T-|*@u_e +z^xwuYrO_T%<4mGrvkQXVfG*v$ysd9Md%sLODN$>+ZO40n!x58{Bq5ZrX^A+C5k!V_ +zK#&ITEXGV(SHo&!EabdcBw{-lT`%lr!(oq}93xNA$(BI8ruK>HZFSw8pe>_Hq- +z4$yTuK1=$!9qF80QW&v|Awwt643lN=D<1tO`xH>nLC+$L`@W@X)F+ +z`bAND{IX>6=vo$K;U`#m(!BdORSY)#<^$v6Dz^ko=5IygxhZIE+zxS`E2q?As9(d` +zn_A*ED;Y#95IXkt7uk$2xGyX4_HcP++wM=RPF8!)gTv$8RT_XgAhj?Zxm^`;TpFmB +zY{qM8B%O-XaxgYJ6P)BsK +z=By3Vl*{#wUpxx|5^wKSdVLr2sW=B`=XLlONfJF|XJeaOTVr)l`iZy_dw-JfT3G*V +zq?9El@q5&jrqd&Oc+tqDx(P^WzDfi#C2WYL5vq*54SLeJ{gk}*(4!bGV3IJ}4Z%rZ +zAtojm0^~)~VD78hi^uwb<#s(^3?f|bC9`r*$pKw2tW$a3h!g?ixfQ&OGvx{uU7Go`VEX?Ppe*qrxa|?;7q5H +z7zC@q!_!VeawuPh>L!syyw5z(7`h{<#dYJJ+d8x6U6fT_`;m>^+v+O`LU<&Q!Mia7 +zhU=AXOfvo4UEG2uz<)5arh49=N-^ydcVXch_i@8UxTd_G+vIXQo#Oi(bUjFycUhQ$ +zOiLhuyiHorZyCfR5t9Xe%7s*Ch8P=NqHjxT9qHiV!r4u_NH!(-#3g)3L=VOB>3%Ln>y9NicEBEdj%5NMuL1gAtu_<71EH`wgq6Cr%9H?MuQ;?tOjRx}Nf1Xoo+u{VjwaM3FosJNZmcGU8?TVyzqf-yBG7wDXEUK +zV?BIKtPG`eV0YGR?4VBm%ViTkv>PBpjvR7G#uMXw{3o1(2%PD9Ag)%1=`)Dcx$QN3 +z7|((zy&0LxcC9s+y*l61D1Uc=sD-zWIRPf|l1>Nwd1qE!pM3s_a!MD_qCjlw{&14N +ztUf%6L|(D_$J(?uR||!R`eQl3lCMedL#P1+1;=3jE)>fT?~y$0Q_Ls{+c-RGi1RbX +zGt&^LLff>Jtyx|syX?e5kjQM|WtsT$58q0tlfca3Y4rq$t?xKm=BSfxDt7ZslKqV2avm +z7gH%hag7<>7hX5HCT~eTieI{}u<8}k+S98PiF_(e2gas*?6Ip+l;8}3w;6co76_Vo +zz?j^A@3wvR`b^ZvsiA-Du#7;^SpgQk?sq|Ay-HRWI?MMi_n+@RTl37cJ#H}TGs*!6 +z)w*YvLIq-WKBL7msL+}|&r#8D<_dWEAIJmjFbp$D!u5v^nXZMfwA5`DyogKAVAm~7 +zT$1t=fUG34t2iKh4%TNDSz)73(KASn*;v1mT&RmVkwWIW`m*=R2-f{5+hyGLbLyji +z2tD*?eQlc>@0}XhrPY|yE;EL>bsh4+`z216nAeNP9|*mTXHzDeXmi?7TPa#=9PTSO +zTn-4OhbO;ujohn&=rXMejC${*sU#zx4MKsZa|;9{HO;ZpZ;~UpC%ICR>*tLVY>xA| +zRrtFLpj@SV?ifX0Tcu%|D2GbbkS!xplu>BB=LPJ!ned}rf~4Ym$8aaPBNS;^E05s8 +zg;EP9V}GBTx)rhhVLw3)Pa4J17D8({^xRVyES`;>h5ct|4_nx}^j9$7MSe(J-MzSP +zhP049WDOFHicsM7;fAX*o;AkZy^m?AEo=4nRv}?79ZDd6>!FDh$%u%I+RD|RuV%6a +zaJns9?O>E+8XAtZ|2`Uz#%oEJDftwfwJKka;25!^;+xkn={(cJ4VwXUMTF`4k3I0v +zHN{vH#yLqvFa&Iu67dS=*~{-lEwpNJq;5f{DS%a-I#`h+Z#LKM8F3(20kiL8LT8PWOAcAcCX$1_zu@Kx1y!m=e%QxMMtht;Fx*abigk64r +zdTU1EUodp{4P#>^*5f-}@ +zE!`}RWmf|ywe9z9%toD-i%OH=?t!17G-}@c^HV(z9qQ+W_&tNR8WVJ)VxR4_nsDVc +zCsN-<=bQ$I>3Oye&GKRb^80@q@L{nH +z+6tU28_3c_H%sBXHDp0Ii~Ai~S46y0qcbi)jj{_XuhG?c^1{f-w^(oLldcE>3Q;8} +zK6~OcTn^_&HR3xDQ~Pz;m@CeKiVNLqQ<2)gnvw4#CKtsGYD?#9`H?*x1$?L6Or4%T +z4otSS)xzFS9# +zEAHTLfq+*tji?>DsBpLJfXMOAKYiAK_2!jxtk~IuQrwk=Cgy|qN=RaNA7!1r->Fo_ +ziGY#K(QV%+;ouV(2w=YyZl3?jeeNC!0kGbr=NRO>Pj-iQDQ;;Tsn4?2tAwQ%gka>7 +z#1S^3EM5(qFN7ZdSzn_Qnt5q^iSV!dXiToPajphMbL;YfNHwHb?uCJdhnqfd0{=;n +zm}cu+I2nqS6tx0rn4tNIfyx<{Rxev!pgnw1mw3|RUIFWSx9q(t7Os?xB@0%3TVQSiS50UB#W02`#Yke=tW;dEmSV_R0vBER8Vqe;oNbgU=ccnyP<2Z*Q +zTKdNi0LKnH+{ifXDpYAORq%A;nP%!gwD-*;&wO!fOEzN`czrl{-!$KMvju5I;vlz-*}ZBk;2fFOY5i`XB2 +zu~-vuYpCmre(Hd3ifN!^t8d@~*D8{93*rtmj&jHk3`h&h>J8(#>7bq|Nc4qjpUbKP +z+=HFn?Nzv=u9yO3tTr*IEwN$pa^Us1nDmd*;uk8bj=Dqx@ni)PnfyTnv<{Xtb6Klu +z?V5@JnVN5is8?zc27Z +zuHKzE+lI{DJ3&O+@qsI$LmSh{tzfd{RjtKbvhqH{ +zV$;ke?zq2HjUaNrYiYdulAaM7HqIo3Bzp*D2h0Cpe1(TFmzwv +z|NlJ!x+fW5ZGmrAzma{UupP0d3Dw%|kQ8F9KMXto&-Wx=3W+faXX7pg{%*4)ZLg$Q +zqC14K_x1FL?bVPc=}49B#oW`Xb-iCi#a1X4@rV)M;Pv|tGQG=^=~7Mi4&fOmm0LIB +z8FS1QvezefXe>2j32Cu07xLxot~h|gIU?qN_CKd7^9+o&w9Zy^Xh3hgK-BR0W?wOZ +z%qKzXEUWB>&BTV!VY80sZ5**<_eu|x9Du+z-)YvJ7dX}%5wC50$;AX8Eh!0-u6vewyM=v6?mT|2d#IJn@l +zZfV+b@fKeB8czR`+;4UjHqUn7DQ!}k`6&tiG_TFp1&k8il@%|=>9~UHk)Hnxbe~fW +zdmCiXdTOMWJbcnQA}0-3l&=#Evl9o;3S`_RFFJPuackweM=klfDC-(T;gzu2|y9#^2 +zG0&lj9lz=rU$Jh%YCaXff0nJ=VMc7KOdw{h5P67~P)-`Bk?sy8`IKHyxwVcELj!mX +z-ZrOdi#2LpC3nLz$*5zoDY{4QT&CB0+q%34X%{20i_-}|uJ1!D>vGPqN4;i3au35^tP=&tO&%pXWUDP#?%KK`RONwe*o?v3 +zvwZTRkyXc_A04~C^9B}=|6Xf@ovb_Qy-ys8o~PX$9$N`chHLeph<4~?WbpPguM#GA +zpwZnTNk5^GDKru!F{xL`Y(uW$qC?m(ma}P*-~IKcj!u +zLxQ3CAcf3#JXtopktbcd)VVo#Ox13y70IZmaS1x#$$^n8lfAqMlXu4XdFX=(DPCj4-n)i_v)`!mePUomUqvndNgv=PXZd +zj|F}u-^F7wJI7B*I%#7yfbU@F(Tw^uv3{yF{5{ +z@*n&nDK7#&?A7=U00$c?};f76CZKxrU7V +z5Z@An79W6mcXd#Hcx2zbC|Z-TNurmASfHLOGvN#oX8n65l!q+<-R`^DV3N(#%{+gF +zS&Gbh4pJ<(!okYbNK<nkQ3juyB$&i!&{4zZn|75e7 +zCX*q8qfBA1MI{ANMowG^bkqBp)c^RH%bTtn`32S{Pd^J-KlVNY(odg>i2hlBQ-c2q +zTu+tEIjY-fXD~A`Wmh(egNJ3Vv36D`p&1=XVklU#-BH5mo+TXaa1EHr2|AomI+6}y +z$7Ohn)ugM;Bub}XBiRxaN+b`)2+XdBKd6gvtfCgRb8^xS-eAPLva^(jseaG1E=Cis +z5j|djdzZo~IpqIEd)<7c-m@$;nX5#juM*KMK|0?twQ^E_-8)s&Gkxwd;Y#nFqHE(; +zi;nH;>$|~#QJ;tWDg{BATWFouj_y_0_;7r;2b(KB{ftc6fBboJ_@Pi%iOFjagq+rb +zlk&)Al|`XN6jTGlyXk%y1}NZ@J8Sy%Fb&0GP7Tf3_yf3*b>MuUoz6^^ovd%woC1H? +z&O16gkfPFZj>{1?UMU_5z3rl7yPhv16`ZK37O-`?6@aj+aW?heu!bOBdOKf)7pH@Y +zIJx5+(U^Ne-4ixJA~er;B_6o*MDCW3*gWiLU7NGDV)-JHTSmRI$#tf8S6V2`gYG22#*O3a~=7{L!spZ^5oM#>P-Ui +z5e$!Wksb^QdEyOxpEF=BIb+)}-+wgSK$}+zs|_$LMX(T8gl`#9Vm)K#so`x<$ +z2JP8$g58#of&Y$g#yP;zIy?iGRUeAbCq*U0>bUY}{wcTe+Mn$N!Mz-ydj%M8G050a +z!&cvHV}RwV79TowLJrb5a-;k*R0#0`=mcYL_bp-=d~YYvS-$dcd~Oz+eJ;9q<>Rs} +z4L0+t9aLrh9odA{%`J(06#jO$IwNO+ED0J?%SKBy=mEUy@l%>A)L4wl6+|z)n-wdF +zgA2n50VHO9#9&?t|FeL|B*3_(M5KQ^0T_wAIJlOpPgjo^Grb21D-Zy!ip^^aFb$U6 +zo}Hr|Q#N(@LrO?9MNBJ!V2BMAV#{1(2rhc+wu)HNq+Zv@Hnj6`iw&T=a!NML+X897 +z?GfUzlc(Dx+9NDa{61Ks#co*g=Z`;YX&JhsMnyZ~+4x#ypo4u<$UqL%Yu1|?Hh9U5 +zgZM}>Ucl&)gd(AZKKp)3zBLN(<09IgujybRl-)jY7mp!PtGpJ*dpryT#=;ys*dg)7 +z?H0PfIUb^}ilmriD;Y^6%f8O8odo0G?`Ba`i>b3KJF1X<+0>UG_uHynJ{0$KfIDoF +zAw6hRx?XOn{C9m1jKTvtR3c#hZ(I!3+I=win=czmn~v3^y +zMRwt;pHwxcQ1m(@Mc3WRKnX(b5A5NX_e)yo9vn&cxD&Njqu?GtZeSpRMZw2}mG6+@+A75Aphw?(25q*y5=!QRJTcoTS2n^0z@1DiimuD%} +z<{Gcv0!k*pNrsaWUQc>8aUpn=2zUL +zjv(rj>+n!m@E?Ez%~c2!vFA{M7Xh@>eSEq_OmzbE`m&oPP@EaMa|Jn)8+~sz?wSWL1MR%?ICo +zpPmPdG>B!8@Gz_kx{`19_{xu|kP-tqc>W+rh!L?R2B%!_=$5iV0}?UJaad1PVvXcBkxWLv!WpK>W(h-99e#hSY48W+PF +zpWi#2kPC8vCHtS3x^4bjiGH0xlzqU+oLrTK^hkRH411$OAmWP6fzV!`lmR{p5))d+ +zd61 +zquDBWLAqbQFSo87A3mn4P=68CwH3t{9SxKfS}ysJS7qJdBU07@l0UXxK$PJp +z#>+|m8?9j#u2yCy+7z>J^TGs8HXYv7f$3X$vJUKvxR^Rje3jLzLM!9w4n~&sDT?L6 +zUftGB!*6aZ`nO=qnizW0&p6P*SlAIF*fX!gW}**k(E*XNG1WQN1SWbcNc`^UVm@Ux +zP+f3vHfS@w(z%Nvq6i +zimIsdp5o`9gD<^JN%MuC6ZrbbK!+1cIV~OCi0uUpgA=pXd+tqy_X1`=nu`^Ng3D4= +zjL8UvMPWU4iImtkD|D{766LOEhmsFfA2v3$shXyxnyk+TIU-qTiJp-^d5lvN!r7SB4y?(b=SnR2cxANlfEC9uD69*3rHIAW7Wr0lT#a +z9=!b%aT=i?Dqu;`c(=fgs5FrSudJbG!7;KsLh5 +zu@>gPO!p^QNqWSo*P$D+Dh-XVy=0_-6Fwg6ov1RS4JF>JA>@u%d;_yg=Mv3z%T +z$dHVSu`G4@YyEgA4_HUBGHef;}w`{jM +z#fr$SmP>37Nodk_nt`22E}*_nc=^$vVMA4Nx>1{~j=oV}9g`J4PwuI@H+t!SAP`_+ +zjrF~=HfE`9tFQ>LW +z_<#^eb88AF)j>>0%|1U?ZjofP-9 +zw?ZD!ancdIh7L9V^06oZQ5A@3pZCA~R`5zcdeCN|j%BcQbbwB&fL5_izF>rgl2*~h +z2}Zv?<7OQutRB^I4lBK`CxbunpNVWp +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 +z^zGzvDx4TX4PNPDI~E$&=B6 +zpJOuk+Y--gKxa`}81VYU{8FhEIL0a8ep8)6b(pW=m_6zhj{vMo2kFkcEgh1QDmRkC +zd$Xw!XDz=m^|pfh+OyyXwMT*|w5PNRgG)ZkDZxd`a?m{gP8=PQL2^(yDs2+eJ=)n- +zG9M_VMDVUA=1NBvcjq^0qYxICM}?tP148O8z=;E0ZYco3f7K|<;Ih_AKfUI4E!64j +z{zy)zFWp!C5RpJyV7E1!wm9mI^0Hpd8zjniF!fph3yo(^$17c59jq=YAX}P_4v-p& +z?{Oqe5J6~zDtmFVj*hI5m`GtG?7EF +z_^Zkh_J(dc`Dp?AM>tle>z@)Cj{eyoe2ICI-Lf(8$AN-VYam3ntRPw_l;bB9jq@?d +zZjZV6I)kNRR`I0P(`J;~mC^2M9JY4#)0B7@hrN_qvI!Yl;tl8QR3RhkZs9}S-YsJ2 +z@H{0!XfoNEPqxW+=kmEhEW+(Zd?b2Iwio8--Q^~94%;HgupO)oFV*1pCFJ#X1)l74 +zU3t$-V2tsAB}-2=GDC%>fTYREvuZSY^wjX8p+7AC*hRpT{OXxYI-m9-dcROY7bzg~ +zP7H{cO@J#_D8W_{iLR86TMSL?i)2J>RF(%?_opL2_k=nh$@sIYp@Je&b&pX*HM?3T +zA-ez->p1F92kIQ9NC51gv*Ib=Q!4+%q&SF3(>drD(v4k`bRfnhN^tmxD_}}a*J#)f<9_%2cuGM&{ +z>d8YWSW*NJB669Rwu{dLh9)N}&#PNf-izD}B=m6A^xj24lE9>tt>43KcIO=AmhM5; +zN3wyW>$wm4s^|dl_Gg)u*rO9ZZ?yb({$p0sYS77npoR#JMo=vqCc}uQF67WC1weoFED0&Yyc7 +zIsVMlHrDXchoZS|v+(6|^qLYDa>Bq}G!BcY$PM;v&Iq-H3zTSqgQopJ_7ZT=pb<|N +zsgniDMlFl+O}s?(=*cTS#%-v^>h>#>!a&6x6!lPd_aB-JwrpQ4apd@;JZ6q!p+_Gd +zy?Po4UMlA*W;*wP8G-a7#4__g*9*YbWKPJiT&kaAvO1ajRAbS>I8RYEX8qIj8sPFKCnMBB1t#BIt7$(_-1c@# +zdMDRT`y}Tn-4gyghrMQNCaZ&(E|92>+(uXaWLaM0cyWEy6%_wSffLx!!4}8<7s>NH&fPq<~>Q1d#IZ?XYa~0U>MTJ$fIA)<-V?!PcX^7VQD7Di|MODZc +z-MJq-AEra;s--VRTZ8Q6WuV%Q`FNLNbQv3_@}q +zN6*MRskT%*Pj$*Me#@qmVPLdKhYqfUdT!90;8&xIB+8?i&O2r&dC~mObSe}6>jaoo +zP?IoyI}t;F`p9|cmi*Zl#I{KA)*u^&E43Y7;}+;-)#M+6ZmNW$LQe_Vv1!9h&>-M4 +zWq4@cPtoXU-*%dLl9~tZIf}{-&p9BpiO`|J8u$9SFj&=OslU3g!UD_d;&M4rV#V$u +z(ry=@V^;EaQG0i0q738~bm~seJS;~_l*$1o$F?{*8Gn*g^;7`&V}T*41o?_Du>?g$ +z;xJ+#BEJB%dq|4M`U###K#ZkLthC6pER;|H_8E)LYzxM$gW7AO6fCEx +zR!sE}VC7`5F~6$b6tjYPjnXo6owzwshHeC{oMlX%M!#%JCXXqI@XXR@9H8LfDp1cA +zw5RuGS2Xeo5&wrCB~^` +z`qg7Jh}tF7H$569k=ox6)Q6>dWzDp-c%DBn&a{i6?j~JOC}VR?&0hA$MLbB$X@ZZa +zB{*L~d;4{=UI4FZ=lxrkTqWO@DQo`b|J`hC>1SPJizdp~wNdOIdY2hfK^Kl#0)A~b +z&Hp8`eHq?B`kUFg|~xpzn~WZJZYE5i>cC& +zS_y!Zgz1&S+Q8F$vY(JHnD15b@Kxki6wbP5_U}1tCUA0DHXyuPuAr6lkziS;K&EX^ +z#Wr$#8Vjw8;3TOk=_e=NSWqh}MhAeG;=wvHsFXeo2)4oHIDwAwin!o`C#sP#Vd?sw +zbEzJzW*#tavm)|ww~Awofju5N3N&+;-)4GDdAtC^svw*wEbU8X$4wF>U_1E>V$mXw +zpd7xVq;5jZ0gt!#s_Zd`24eNXLu_Ri3xF$GdimxN`bIKt3U3$Z{0&6{?ZNk?i#)Z; +zo)i0iWRx!DLh0;2D&;ATjt&{_7FYyt^5=<6fGEYCik#>6){oBBY?#WR0ifO7cI%V+ +z0swW*;i%*i2A&`iW}m$d$k_AKC&@EshQ&!Ui9?Ekd%Jjo +zWdR^S>LR3#rwdF%sn$og?GSISk^y>1AYR{s3_>^HEu9Jd~q)i4A=$nU6m@k&Q81|W=qn&wy!JZ464x`vMK9o)O$dYb|>iLFVI&_4n#AACt_;Qd_;#KrqV +z0B0ryeqS#cu+X|Es4X6wLxqr_*F_mMPQSE0nzvmv_w1FDLqgffZhQOsj>V$7VPeeBWe#rX>$GiHlp6RCa +zv%eVQIT2YujxHf!RHl0QFMhEaQ1Jh(-Pd1$5_ozrtzJoz-S=9Og=VVKe;O}ZXq4Ac +zg>W|scDVLTTK-94`6R+UVl;(CN{uF$N4>7-7Sv%(>(uNFTyG71&uf+j)4+5VA?d%+ +zzwsUvQ8|KCzMUJ{EQ>tG&xo`RO^6vQTa`!XLVOj=6AIH!rXv%H)LEAT3%wD2_C>Gx +zeJihbr6|&@cH!nq!TZBmTQp-sWYwZ{EiuzQ!Wx1ffE?SsD`5Vht7bLa+!W{5C2Q^Y +zTUVR39ZQ$|YEQ0488eaV^%?wThHc5!9cK0@K6xBN_S%^CD)LobZIpjMUI6@gtuhN2 +z{TWUSP6k8LKr@^|kdon*Qom766pYzXkLKpvJ`y7GK@M(s%&MKk-P>b%Wk82L(}1QN +z`Wr;;jM{lEq4|5GzGH6k+C?5R_DsKPDKgYt>`R<{lFu#hfH?m1RRtY|&eWjGDsr=k +zb4Z@*6`$8^=x7I6Mks^mNL^zEqPa@V$bDSu2LP!01M0@d5a%pYC}fp-ap~62HQYy! +zJH!&4lN++13cTF}taxuNX$esFGa4qcu8U)WpT`na05+ab5qbYH!&Pc-WzcSLtnv&= +zl#+A~(*p}nSEP-kyWbIGgK9SLq%(2BovOuKJ#Nzk2^e}qhs%^S$+k+K;HpZgyLeBu +zHQIjAtMS4+mN6cvOD&yK^^$|2?fiHl98T~8&?{o+^O(p_$ZP0;3W&Wq@Vp(ai#Gs>fN;`Uv_TJsHZz1Z*NN|_TCn= +zIdZ)fS8)*2?T@IOG5KI7KhGERg{;YO^io;=GLI-Y)8T~p2FGgii7|>h(q4&RtenCQ +zuca0Kj8gS_4p0d(X`Mw78l#A(zRE5DhYT-{D-de7lnxAp8X=GcjgK^@(-h{v4{5O^ +zJQ$8m(8FfV$=IzeB9Y_Vv+L@XUrRKekF=0@IPSV(HpnV82O@9 +zoST^taKZ-EV7@f7_uER?jaY6+s%Z98ip7eNJJn_AL5m=VJfAp=8|RO@y`PtmC9>d5 +zEa}>#7!P~qL_K8Ub}z9*4&9F_cS11v(;jVE$;XoK}k(1IH|{u +z7wvhGm!aZZgay~wfZt`nqObwWC+6)6XOf;@{qpAQS;>A`4BuY1AQ>Jh`Aqw$2fMtO4H6Sf|G9~!hx&*My9jPk2l>Y6$EhJxOc;v(34Vh0WoCc|pqO92Qq{bLHbW;4lz@q=V)c&DAiua2jS8jSIl=&zgH=du{;yH$+2w +zG&01=7DT0Shb=ULcDn)0YHfU1C$@xKJ084(TmDyf8M<(iVR}4il}mS#$90fiFHk9Q +z53dnD;ElhLGPT5aer8u$?q6^DYJzbg$)4G-3 +zLX7N(WibgS0mEel;fLLTgt~uhe;C~@li+Oe=M2BWEg{xCa-(+%QV2eIzW6@?B|zH0 +zpjS$1id7+!08gOWycb`eYkB=pAkfQ54`J2}Bwn40x3;LS4k4 +z-iPd#M6}BFp7WCn`R~JpE(yPY?6EBV%?V?{=$cv|fxQ|;hU)yxC!6u~a)t!xUP394xn`OXI!b*<8Y>)H+fm3ZOxzAJt5=m} +z$pfe86lde_zl(|`&HnN$p{y-hOhGb@ycxO9(FZT%WX^luIG&nIGhcxo%j#jl6(0K1 +z^5v?8;^~%O=9qUSWVItVxll*zqmL&qxN>zs4LlcoUsp?l!hUtFP@UW>-GFA +zlBw601GOoR2t6=LSplwmSQ&Lgi$?Nfr_)m|NgU8ZnZWP{nIU9tx{T^mS64&-WbFkZ +zP|tdTNcC@Xs^6t0ELOe|Pz&8KbK)FBjAtxa7a6#&{_N*hGH>=t{Hy82KpRgHo-WSm +z917RBPHSzF?VxZh4?{UE$m6^%0_F=#-$NPw(qhykBDOOA3mF|}_~j9*)ua`gmLv~V +z7qIsJhp!y*qQ5(`m?Qz}$jY!cWpc>Zn9`oZJ&SMop?fHcKrZF|?1%1U6Nk+%L$Qt# +zEX@2K$)CowJPhtK5G$HapS&A7>z>QK2_eSDtOz^=8tb3*pU)}bgic4FSQtFWa37)cnQk7DiU%7?$V+#S>K=fi#*ZkukCW8-!0z(JNhj=`;gh>u2o#`GjF>O +z#ZVrV;_dP!_nzQ%?$Azg0!QVXdW^3Go-I(3Xw+t7RW#iyTrDI{iHv0UijAwn6+-z` +zigC5O`sy|S=by_q+qwjns%;e%y>Mx=qjNk3%BjFt*ra_)2LX49oh$ZrS21WKrtC~a +zL)umF)6IxqnrLey|z}@Z}OP?x(WYmz;a#q +zuw%+cJ>MGHZbqS1w)8B(Ik6=lh1=i~oy_<6rA!(f3Ah}m1 +zON^y*-Z@32<1dMatnOR<(W$_NxHE8?5fSToBC#&-hzA +z?feMX;4PV+`eRnFZ+rXvti%e`@iwFfrSKXIi6KW-?>jv+vy7kUjZri)A06+Dcle~D +zqI!SB)0=gML}z6CZYI#e1NppTD{F!nYZ4d{JX`&MAxg`kP;VRwk$({^Rxq;PsNs0@ +zK?2i)tAZ6Z&fdhZJqFI`jHQ?BYbDhOVopc0)Q4!kj_RNaHvUJ%#bw2m%#k0i)Xt$^ +z2$}BhRT;-|t4-)sN49d6e8oSSZZ&*6KBwRK#>YbWc_J?FR#`-E$~mCH!5}&BWbT{l +znaV^QAEswdQ4G_?#2V2*#a63g67U{%yqGnSFO8^j&DUoBfHQ&ut|?a70XRfAP3fvs +za$I6rXnkVps;Qt8|5gvBQRE;QIUjDn!RfBMb*JTj!h;)4_c(C?k7J)%$&<#1NSu_p +zEO}=9VqUXsHACBmjb(US_!k!pP=9M>Kl+8AFOmQzC$~%>6>ziL<~Yu!(mm?N#f=n2{TARA8DP8111&C%G;8*5tL$)M4%KK$x*aR#Y$neSq +z7!C@}=j?LCQyD#m-zx>FtiE1%$2RX0P!IYrm1MQ@9!+-lNCAsG{2K9{K$vtYyke`; +zXL!-s11{f4*^;q#M|r54Dy>+A2+(#PdbI|O06MP+WI3dROkF`f8qizOhr5AMYQa!M +zPgy+$0D&~Z>p0f-1{P+Bs2(f?iiR|^vYSR4cS5R&jI1j`%o)gOtRX8&+@;lomu@n+ +z`%^DdLu-0FD~_VKolsiC*3Q4W6D5<-bu~Mbf4qwl8Kc$T0~+(%-Sx-^)J6*<`zXCy +zu8^w3T-3{fcbjtG#@^MUD6~JKD3+)4*w3yE-eTMAdb}w;bj*M +z>W8M{iz}tH86c?!RY2S8cz&vr9LmInLRasDAY?Y@`8H~n2*j*y)LLhN^sa@|LxBMs8>O$Ej38Z#_ +zt-qmnObvzIA9zoYsi+zu@oZQxsD8EY;%mtS_E_K{^gWpQ@N&LxLKMO8KvqyGETRzi +z$H{*K2O6kA%C_#JkoFQRiRP;iz9j5osqXjo7km{fjEw|vDnM>8N@ih%6UGigUkp5F +z`OQ;rx|mC9pJ&xP=QK)0l;@6j)R3XsT=AKh9ENzCKjz&?^olz|+78&2RBbC?^lIo# +zbsS_P5D$UXSWa5T+@&kNv`Q9Nz!&qtw?SUCI~ihlmJr-l8xkl>$XML@Ia~7agUeK0 +z8;&9P1dm)r4Pvj`!WM2*bA({2-nMA_e}_q7EfwN+OkZyIs)PP0US+eD +zkTnqnph)kzf21Yh7bi#(6s8(eJrlM{&Yd#Wd=&NAtUiNAKRqp*9+At8!*V)hjqn#mq2{2Q0H( +zNEPnZb6~%@0ac_2Ilu>$4G6cVRl||vCq9Z{)YbQl{EpnQ?6hKdPLQ{{;U%DC&OyQNYZH7A5(Wbc6u$*@oeW&5*z9HiG*dN5xG%S*>_G +z>LBDd7hVS(C?S~dI0&GY3=PZ*Vyn5JR~ouYllnY%ex;ud-Ev4ZK_1badrY_C(lBLh +zZ>stml7?N%IbBboBT3iU>5&q7Zawg{^g1OEWkk0R5~=C0PQjczDZ1- +z&^Fh~ksALZE2glb+6t}nnt}gYAltP#nt>td6hbw}9wEs=p&~!_n{oi%d~r6H5w&cs +zeL-kBw1B7*mEbxj{IX5C%Xx5wX(i^Gs38Ovsj)pELA{rgk`&|v#wB$vaIv2g+E@B +zcMSNTeJVYt9@$74o3mzVJJ%0gKIF)+*z`tMcvvkb>d?h&;?8%_K3)y5y+v|*vpEL)@Th)jY@y&m>7j(p*V<2s99p>Gv@d!f;` +zq$~ptJ+Vu%<&?Q`Q`m+jref`I1G@aRPd#^xOh^9OM1QtB(Qa?Ma#ea7uj(+0nsBZh +zU;GAO`etWFySPnYsD1-NBogF +z6LZ01IQb;*o6?a&d(a3C{RvVdkKq&0d~{yz!KxEmEe3vSB@3V3?j$RKh<3mqX=C&T +z0r3y#phydQTa#Q^kelbzFTc_3f8u-b6vn2+!N#gN +zVaRhm!@XH|Pckf^5 +zunN`BpHVOOya7$-Zcwxw^dv5scN;wEf9}C79gEC`^)|^O!efo=?T~id8Xp9(r4K(d +zz+6qVbmszIY^mmn8Lcpk(aX2#`i>yWMW_|eVnQX0DtEHxi?X*n!cP)3F7CY#+(;gm +z?jDbL0~3*`qyJ7T%O!+k(CZ%naoAS10n^{{XC2+qa99-I5(d;YF1h!L^A@&XRd`JM +z$So0xu&%&UGYElL7@HL+6H#6eT?SBaA1A{9GLymXMek85(b3D7THhXKF73{%Wu??cB +zZfh<{Ow~FM6@{LEf{$knVP=VtOVFJ_=RCzXiW|6Y4TUEz{Z>j*CDG9Y3B}Q_rK$D2 +zBPA`j;X|L`=6NP;ojqqPMr%r9sb#aBj#g-CmcNG~4X`B0^yh +z@LBJ;;RB1Fclcx|tbhdC+o(Nqn8y>}Gl6@2ITHG;L}~C%B~5>saCkpto)a_BH#Qtg +z*zt<@lOKyzbY&CS^I;XX=OYI`=9P%vb8XnSwN-&-?byUH9ZQJ9(S0R*nKDX487Yqf +zEn?7Z?aYT)z=SF%)hlW0tP_7oUMAV0T#?-YyJ;0#0qiK?aL<$72}F@Zic}Qp6JE%6 +zhZX`zqxxK=eC$yeD&RHSfBnEcP(SbbQ>~;sP(Q>cx8NHGt`6MhEXXW9n9%7}C{BFj*%z^XC1fJAE8 +z(7--b1~ylUS3ktWR-Wn@nyUqv_=nw6NKePPP1+BwK{!WVdj*A6?2xPp@Oy-KU5{jr +zW@Gl-#m*T;ozBT+QsS4{XkOt(lXSAD;&rdF$foI}-f1cUX}8`CwD!=FU!jN_vO?2_ +zumlDsctRPa1m$GJ70d^BiijbVP8eTEg+M1L=nBQ8fB9dxezZfhdb)u2RTt8oF>${U +zdd+RI3f#(vow#`1wgZH}ka?E)o|?)=Xegna8%cV{@M^nFP?aEyFr$N3Nq))6d2|P_ +zEx>`HcFoQ_jO_GQ>BYzQ2{Ifu)^+Iev>|H@%P)P*9TPq28rF@12FB>%v21GoN_bnI +zGEBY=NVfGS;DK*6p_4Gh`c==khuQ(17dWt@#A +z74!$(A)Y(CFD%m!<^NzZrfNDIoB2l~2X+5=2s7y8PNhZra;mv(}Auv&dQ)h +zX`2yINJmi!V`vbrfpFt|i^hc4jWkV!pv(l#Geq6~LxfH^X6_0e^7aHKBqY8wkcbMDzZ$^&=L!3%0euFr@d_^PnX4WqJd^Q_z77803P9Tk) +zxJCN&L=mbH+XaF5s8iO2fkGAQ&5x1=TrLYIpGkV#G;4!8udqsHd6-Jg4?h4UPg{y3 +zrO=JTpJCIbDgOqR_m{%AUFEG}g*H&pv?#)$*clJYL05NftkSqge)EE8kqkHX_z<0D +zsEUo5IFDv$9e@eK;N*3$@06boVsI=OKR4(>ytiw*s3Kf#9a>B>=xZ^?wmxGio+vl2 +z-l}Q_=;ktKO=vSvMY==zCuL$-)ju>AJ7wV5Tgw9z*uxFrZ;d +zLnql*f?K@AE@-PNtbh96eJ5otd%!ftn!83Q$rq)>fm_Azf1*oS03Bjd6KV=9j~F-d +zj^#|%U12&R_dRzhw{Jd4RXW$!5mrTt-A{Yf@VpiD6*?v)^GxOi$s!NEKBifepPP4D +z@jZ5AzuVe-`;;M6AG1|O(TLz9#$y}r6@{-?(;=Ob9MtEze40$dH3`)(ngLLU8xYZ6 +z>R{mBf1uy=i6p0XO7q*U@V8$Yeb~H@s{Zd6NX`m62aoEylNtK}`fiB?V%G)pd;$`e +z<(yyE4{-ggfDiw4KHUfc#=)O=KctY7s)exMrLTwpWj&i9%+tq!uSrcnk*vCi-8nhi +zh+fKG83lCc5rh~AbSQ<9^;;7#bN8lGY+;4)e9^?h_gH`XucKs}AV=;A?hwX{t4W~G +z^~2a~b-{M@*_UDIpw!-M!1uuG%q$H>IlmBOyG~PFiADptppua9_4lhqU53gWVZTtY +zB`XO3fBrN=RCkI>{~r=JCc;8n8|;nbt6FU6YC|$7xid6xa32tIc&~svzQN6CEM}y~ +zp_hkOE8dHjOXDbN&Mk^+qs^VTDr=ph1*6pLKzTj%Kmz?P^_Z!zU|f +zr4k%zf@T?p?Oywjlse%opVglRR4?~0D=3a;2SC~ddJF$%_ +zR$zbmucDQS!QnSoqkjd?a(x=%>@XCKb^ro$%59$dl5qk}ts`Q>n(c5$=jB=Qz{OO* +zAubwpoU~OI>Y`_R9(v3(U}K3<&`?AD^Z=i6VW5A9oP@f!?m=Zs2hefyWihvp$)_2na$Pu2I!b`zqox`S +zhjJfhC_@NWx?T0W*x`3El4iSPTR``PI^q3CQ&}%O=K9(zd$tnsF +zfE*ZI|To+`W4oMD?C!Bb?yCoO3#J_&UZ)n@X9`H5+0; +zDpyJN^9#kmXq`O)kvLM<9CD;1(Up9x5vjIq>;Ne=KF?5Dr!(hSzV6%^Rp*y%*)u3i +z8m^cW%DC+X;EMGLOKA~ +zPpoJRvTDb(w8Fh_;E@Bwd>7C_%BjV~dV^bnzOkHbIr6Q>ql1(YW>%Y25{|EmX_Q3w +zUz~}e>*2WY?WcgPxHu_oT6i{ykJn4M*clcD=Y%0F(ChClOI+vco3}2QQpTjJVN6;7 +zbTfqBlLhdGUmFVjW(y)bc~e40Vs8LL&ZgwtY9D{k(+Fxp2UN9n7y`(ls73a^0x$$M +zcfMdX8zU~*DbN>a42|=TYrxa0u0#TjQoI2O=N^+$Ddib)cupg1==t8YkOgj(WJ`8$ +zM+!gMlgZ#4T>mEy`4nULxzExr{56bnej(~tnR;ak*t8AQ6wF0+{*qMoPlN%ZR@+D+ +z+X_BT7^?w4*&}k)F7+WezrgMoUKQSN;FpEJbsuA#N-NP*DO!* +zCgZH&@w#f(>5_gsy#+o@)eI)4xzW0r`F5LGaxcgY7QYf)oVTR+Y~IS~mw^SyP!p-p +z`d8nFCX|NJ|91Y1(RM!lp=ePoHir|n3vTO1lz*Br7oo!2U`6Snq~@G~$B15{C2Ui- +zt+HI0j-AizrW6k)3X?{qie!D*80hQE{2B;xggqCh9I$SAuU|1zC+@OojdYlbN`#?II5mrtG_ +z!e5`2pNtNsMPTQ~wXE&oI+)UPW~%~9JqMt5@}whYYrLipEJ?Ho;Y48%YZA<>C|Q)% +z!w<4ALqkw}b9i9+h5FO^VEpfr`M4f5)-qTrVBU1FA+I&@-eR15=KYVYF~p$5B3gRw +zjo-Fb4cu1;dShrbY>cT2%?V=CW7#58E|Jn_^!gnNb%$@NIF!|PXkLfDBw@ei*{$8R +zIz%bj`XB5sIJMI$RpVeH(1lt>;1f+5*S%vH0nGe3{}fiCT=WyFB0(`m(%P{RgR-2b +z71t7{Nbks0E11~J=umgt(_Cj17pq7)PObEaIGyyXjj-7fR+zyn#hgh*Zyf#)FlZFq +zlYh@+`Ons&6tW#TL*?4DJE`-#NW=59{^K~Kfr;qi=)pcDXB^#bxt8omxuNgeG=TLp +z#F?C!dhF$t?9amwM(R1x&gmh%(1WW&@PBrFlAQfOBQy$n{?X_SU$jWd8rcEKno@!_ +zIVX5%H$bE>UJM3G*EfP;fDCJ9X5g$WnaY%TVlfv(*@l0sN8nb@mea>pE0r5_nQR-Q +z?rV{HuwqvzqgC>5eKyY|6c@T3ct}}qBLIfB3-e(LV&V|R5~g=4G3E-|-TmYStt6$G +zZO9^0^#iidbEnVn_zO{HvLh)bPpuB#{(dVrD192@gJeC_%9Nx78VQ6~3rTVDEdzp6Zt6B71=bv6O +zcyz%EA7498(U#zE$>x*=VYE=z21|lYyHv&kOwgYd5lmLncHQwVNkkdTHkP8K&#iO? +zn1^6|K>Lx-S*OkkvP+?G2_vch2CMExlLLZ~c=N6qiOF#_o!p3GTjLuo;n-wFYZDb% +zrWsOsVnX1rSf_BR)vlCI_&^P3u&H!OAek{Rq1;SG +zLW~eR3~(4diBqe9y2V-lKyc-6e$(czzL&zho}Qo4(Vtx +z;f-dm)?D){jYsgo>|Do}##R&kemL8G<6#MwJ$6YtT@MO*+mq=FF^C~o+}n|G7RiqQ +zOVUYik^n+QE&m08J=tMXAn}5e=nwN6ub%iTmSMHr9v|EyT;HQnkOf{elA~>DOX4i; +zEmkha(NyFPsuH&Hz?3q3W4n%WXlBg0F*;MuOTh3*q5~UqFQ94*W)GIQVp%$vu{l*T +z_UA<1nH8%=t6;>9yb$!%)U7s+!zpPHBPSEiYS=54K@{e@n-l|1|* +zqWobSUAO!x+COu3lfXG^zis~SOP|R9L0eO#Hz{>lkHCz_*c@-iZH3mHFjHa_dWRpu&_lS$6 +zU2@u@!5G$1pyvgUel%Rk3V3-lZ28YB5~7yL_9@Rv1xwLFUvY{e99#xLK)u0nXbsaP +zW*(Wyj!77jS(qC5eGH&vV|iCiFKQyXnK<&auRRa4MI-D;aqMe+IiTM03Rw5BBh%sS +zGX}igKbq(ax<Q5jJddOe26wVCW! +z6r>{uH@cdXh^XfXvaGWl8go8RlWwa9`{SG3%P=|tHVQ{nE!bctxoCMX^@n~HOJ)aQ +ze)?wLejz?|ka@vPHp@6EP=?N(Cuux`T}KKg?C@j#II$8#_o9Y +zXCDqwd0-AaQc3V9S*%R)0(QA}g(q#0!rO)A)fj@hi5>(eBuQv52|#g3IZQx##D75& +z{6G^FxBp39vmIWgUQi>7w423QF_bNiM?~AchzMa%I<*9*jnhKp^#A?FE1Q#K^)4Fz!dY( +zDn^;_hU_HVUZ^>LSm9@LqTyXG1zO)5ntPZ$xnCZ_=+ep4o?A1s?k^I~qF#yh>`C#U +z^0`iPu;~2ngAT>ZRU$rzG_X`>V!F{B%x-G&LW-TlFMpv23fOJia4j;gKbe*)$FPA~ +zGb(>Ip%5IYId#pp5BJs?_KlDbBUpFMo`MJC9R3*vXrr8#2npN&MOOB3k)+73QlI7H +z~Aox9Z8>2Tk4@ft}p%)OF@~-0QSux`1#P4RMVb? +zauA@u6DeSH#D4zxy_u|}qVX}Z)oI9=1Vhw6Q}K1H>x%+_4STWxY-_CJz|jlzlan3? +zxsI(ZHFC;wGcq~eeb(wtmV+d!%0{5L01*X?{}(KkJOnu=Kmjle;}c{G1D3H{g#T+F +zQT@s+SS*{FC_x~BN1SSC+^wI83^WEU$ybt49|nqx5IO;780;6&L?ZIy398HCBOVNB +z5_%>R5YCRoYflQ9>`zrZ`~N_q;VsjXnF^}tO7Q4>!gY@53bPqr#T9kP5c9LUwTcl$ +zOb4rvO(|m#^g}qQ5f}&h%txI`?Q-p0gmyi9Ox+g3W>U^*=Ib-~xDWFfHD)X35r?Fl +z>a-~Ki!hmBF!&3Mz+(^wo*l?0k$>`*M(}40-v>>_NQMYQt@ha}FY<~gv>NKaHq+$^ +zecB4Fk)$1_4Xz+fZ=h8gdM$g0B%Fg$l>j|_UNVMHL3 +z{7dDi>r?+xj}S4KAAA>NdKcjzEs`L-(_C&!J}@U$a&ii#qANyeFPZRkFC;E5mkl1m +z1=r +z7adn}&x%g^kKuh=5Bqk~`ns{cuBNbltw#M?>-xHY{aq+xeOm8*yFEUxpZ`Oqkj#2{ +z&Qi0Ged(mg&3iEf +z>8{549tx$ohUhD^*jClBQ^mmH<)m#+k9APK+$$$SCJZiHoxsrN46Ot(r;!Myw12Yj +zgD8gPC_j6mG#Xn1AivCc3&mr)zjoOXR3ZyI<&@~94MiqYBkV5$6qeTeWG!jWm_Vsw +z%jp4Nnn=ynRnn?M#@A(~V3Jr&hB`sc+Aqr4Y4H3sab!Y{qkEE}gB1T1pUgPe$b23N +z1<-sT#X}ygvgObBfAz!ZHD_?V4bSM3#7s1-H-Cv7k{;AI8>`4z-`roS2fkdGA91v! +zxM%n!cE?o!>GG-<^Wz&K2I>V^&8|0#(Q71p@n2pyJHgmXyzMjtCe*|zrQ9675GqbB +zLw89@4|teH_jX_OTQYLGl_E1;bb_^%V?>2a4OQ(F3~@?eZ(m<= +zh!mVnx?n0Xb22s)?zK(t(O4g+C*(jn)sQ@eJS?(tF?6Nr-(3GD;XI!tO&J>TgIfG^ +z>Z6a=8E(<*loBhRt=N@&$oVyPYSg#WGRqG^ds%6_d%9o)4Imub-Bm8iCTnUI%M!%Z +zRIM!8(TkF+I|$Gd>eBn6Rjg#`r-}eVCz#$*o3NRHfg;Yk%ya2V`gkH`>ZaeN92l!% +zR}=HlpHOZHjhL=%c7%(qaZk%JxS+3bli1a0CkCjVLPCq$#bh($TG?q~II>2Spd<8$ +z8hiF;f!gMNzMiIH*w~>E!0c2G4>hzr6*PUxMw5jdjoKl}QtyCE#os+H=XgYMt&&)@ +z^H4hhi>!*!C2$A`#*A+4(&_dzeKr*Sa4FC +z7P)j&L^!jseM7gN{V8P_2=h8F>hIv>&+feW{`$F97b=_h{(7nZB&%D1ef$?S0$*pJ +z=Iz`s!0p}QASYH#(G#bEU;^sE(FCvDgsIiXn)Ex{zBbw?_LE=!BhGo<+ixzGh5MywXO^=TJect;0W1iW9x^mrnn;%G6A+MA&`?!P{|XYRNfNXP2sD^&K43Uvn*_nt +z9f+(vUyWYQxNbW&xMPekq#{kxYWiNmO%gZ{pz;6%a0#(5iTCvxN +zBkm4Hw}O9AMuKEda*+e$j;M{0zKY)$ +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 +z580T7(}dTiVFBW!EA&@dlw3M;lCntd +ze)>qZISgd8*=3>r^hsQ&W?7bf{BDE9xGhco!%KKh79jamJHqVJ=inQQj?#H(Y9Utc +zDirO#7ynOLK*FS~_tPw#Bj)Ogr{{;r-%MY7E$nLJ7=sr>mg}Rti_$0_?*Z!~@+^}mNYqEP>U32V!|cN9mK8*Xo^>eLa#UXS_`K9uw7iH +z&8e|Cx$H%WYpxxzN1XRH>FUu>DPq#BA93k5L=SsrHj*IiGnh^Tm#Y+tz+z!Fh6_mPm0eV3? +z1a(p2`sWRzQ5Ka%(`oSe3zWH4-Bxq(K6OX(9a$g1*(PR6#r7=r^SeScrA@U9H9oi; +z6P0mBSX1}Sp78gtVD*<*7{|}y+nN6UGRm;D`7#tp0;b8w+rgrEGC1ET{IaZVwLRn} +zVt88uYpZrBRgxB`hM=7SM%BU!7TwdixPf}jRd?Vo@KG)}2r6{t(4*&v*S&K27uYcn +zuP$R9YR>V#@&7HDx_fR>ox{H4_*uWg$^I6H@Ut=eE5G4c&#OY`)u5RE76v^_Is?UJxgql8%+( +z&-;4@B@ZLBkmPq;x8!QRX}N#BIIebiAMWwaFu_TX|2nCs@p^2)b$k0yJha8oDeBLi +zdSZpu{jx$swUqx!H8Zg36OsIP;4lQIWmJYTPr7r9V%3BR)@Hh2Xw}3SryqPjhMEl!Ij~uE>GD&|3J-@|KwdeA&vrrq+j#MoSeIoWw +z2;Ut)kN+IS(oNMRkV}w4B<_tWEb +zJeCsSgdCt&ob9VWev<6lf4%kRZ=-#tX9cD?Y>04xDPbGmy2&~>DUb#{mEsI_*nw$t +z5}*avA{SqAY`Z03`3M$xlAXPx+{vUammx2~=&=6lP*il^5~b|ydz +zt7m)#Ae?I;aR+#Wn1L5AC!=B#_fL<<=J@&>m2t2iylNsMZ&d{p%4Xu$+TlV$+Q4@2 +z@{BE&$HFC)Y;lvU6pNDZRtG~rwm6D$T%vqcJYD<3tEe{5cMIKU4W3SOvw+52_@FHqaQH4QXk!y+V*5%Ec3rMPpjCoLfZ+(_K +zUD-m!S@G7i4NT}mJ!}<~&4ZrF1@lPeIoHErDF+T#dXs4ahUJ^40|F1h{o;;tma&?R=&+{8glAL9pO +z!U9S{z=f?B?k3`(-MgY-Nix^@dbT4mJ^R#pc$S +z2RztX=3lT|i>@w^!pmj7uw&i(%KWhzoG#X2Nerbe-8ZSv1nj&4%r&q-gL2NYIL!(1 +zmmUd`Hu3ck#U+iafH0N;miXVRI)pVmaVFmX87a9Gd)N;RdR2p$ABwi+gnUcBPI@>> +zr&3`~chDlXiG3QF2C^OONiVqV)Lx2OX-axhd2p0CzXvk!NB(!ELf}tLiR~JYYuQNl +zsF=jgpe09&lWi&ypd&}W%+nKRebDZR5MBz`TD#|;k@8u$GawMMe?7$Qrsl?-)rx}` +zxe=x)7)wMUdM=UA{{(i*4F}a*zhY-YwE!_d&c7q6edEi} +z4!>DP0OGxtZRQG8YLmN~Zlp(XFVgGm7ALEyl4ji6D{0@GRL*y_E@*eTgh>iqtD#oi +zUi6ahrVN5%yzM0ba3ckjaFlooC#m~Qc9FB?y~Ub5{P}qE&`@V;v=xKyrl=U|4FnOj^=C35-1P=Rs-V*Mrirz-CwWxh)&nQdf{bT(gq!lzGtE+cNOJkU54}U +z(uCu1s`|V()W-`SK%2M`7XymiZjSuVXr*uKvk0bP +zfIXPysUni2I~YY%0o(vbt@4tz29!k`H-HBhr)qfBf6__q|b7QFBOtU(YfLKW~k&x +z73gI;j8KwUec*2F4J8lzHvopNn`1F|Z*k +zmS~WF7UY1?$W2Gktj6^sHwNn10Ge5jfc@g>K_ZX;fB$?aojqN<05bW^RW@)<%qD*e +zAlK4LQ)$|2z}vfkt$t4mzLi#J%56cr2ZbapQ({^`00000000000%As0T^VuUR;mXJ +zUkb+Mos(|43xEHAh?R1Z{`*%x+3?F?Yhw)tfl3;5qwG&;kJ3_Jd}i%0oKzOFTf;iKg;LB64bFUxul%SLR3|?egka{11m63hY<7q{k?6-M?OW+T#y2 +zajNO1@SGPZo>)^bH%qX*k~WE72ei<>`R$$8 +zi%t$hTta;QXsy>MH-dT+CC^HV{!)kE{Jm!JB7NR>e-YLD^Zqp)?MB1Z2;~v}0Y5SE{#OnuyeU7e7xQ? +zlBLuwNK(N=;rbBO7k+(TJe^vkIaXnMyEGXeeFYKXB?kA$$kcY%H}G$7kK +zXs6mW4ijj52|x-^ZVaiho-BOWl*XWQ3gZ#!qrE8fJqAqM;>kBDIhE#)n9nnp27v{p +zeG-6<*o)W;E^D{+x!U)l_Vm&FddU5u-|gCK>ge0Pu8%)%p#I&VzO8e< +zt)Tt7=cD^|=l#1HzM$*s>T3GB+rFVr`nFd3x`6Mir5ozh-`l+3w{(ARLBF?i^gp*^ +zf7`R~+8_IR&;7l7e$ems?KSmvyU(B3m+jWi+rL-Uym!^nKkeU;>iF_3_3Ez5dYXDL +zk7x{Y<(J+U)6CN+6jh93i^T1SY#nX4lLKZ2Wo#4fWY6D-av*qLNbE$_^DZ-p&y&6P +zi(3RL76E+!G&&e-GDJ;D;%eC(r3H3q2g6o7_C-a5c#{|uB-ya7n;iIkO#dANmE~?h +z75gfeycZ(7fjJ*7i?md;Om`zpd&bXq$01eS12Zr;SZQZ&>^A)5tZ6n$;Xv96QzEiv +zOxwM$ho~fDr9AdJ2p@;@zZLCC*vQF)45cpg;QiZGKP?vI&`H?m(>Knc(AW4DqV>Bd-Bs3Qz0C +z2#6=rPW_Kr2#^Lsm?re%=93${tUB^KmN_%? +zBTwh`UNmvviKC%MI=QaJ#osDfgJeKIJHSs>JTe?00L#5ea1MPkrul{fg9N>}?68#VN5WhxW^d51P-Eln9~|5&Cw +zRoOxQ0NJA8HXp*b3Ej$Z72I-2eVux(#%Id1ji~*mhKKVGRt$1_3)h=463Un=LPH=k +z_`MV&^(s`&6_?nQh9ST8Dq5^JA-8yh?hxH>oSkecG!^ebo;Lu|LKgm>5b*kW!}j%S +z3sryqyv7=Rr<+PPSe8qIoOHOg?;>DY8-@aeV${+r19A?$hej4f0G}@dFzzZskJe(J +znmKh5VbfrZta6WNBB#`lD>nGbPhf`^auPspQ4x4o8;=Wyx?T?%#W8Kmu$3^$WN}i? +z^``b+o(1xw{vX2RDW;fXQ$tIkrO)~Zyv9;(UfdovIk4RNCy+{N>H6PnQZbNQ)o&lH +z=#39hphZsr`m@4;cMd2Lp|2PGX_EmDFDY~+lQp=3+u6jV5Tw4h=~ukuxE%$SaUYtA +zVLfPQXOj;gWM#z;^+Jbvf=UP5aC*ts*+*;?htz$%t<$iIa@vG(z9Z7`7%d+de5N1c +zr_$;xJU`Q8AEIPQc$}Uz3t;YHqI8|uYtG5+4a8+Q6G2m-XcFk&I>%y*#IVx0Uq|3s +zD)6R-*7!6@i2@(5AoGQm2U~-Om!wFP{3WH7Gf_@t&-VqM&peB*tx%mjgfeNMJM-3^ +zW4OG9@X#?xhr|^6WYBzEQ(*bkf?p4Z{o8kDUDzAq2|&*us&U5HF>!}2F)f`SMNc_( +zyiN9yett+!_~*M9p(vOUk1oW)!a)c +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 +z3{PUi>?G#nrb@*Omfqob~^>bVq)|#E1qiu0F +z90Wz<8oKfKZefcD;{*#Rghd+{k2dLhS@KEwe?&=i`(ob>PM;;T16pD=&&Y+7f+xu>m=$*4w`saPxC3DMul7^=j)Ydavhx}khC!0Rfr<4|Vr&3_ +z{UqlU$ptj*&Z~fmFiVjXX>1&W7_@cmxhm&NGPh8*)g1doI0jPl%%F__A?Mm1BYDyC +znQmsCigf)wf#ZOSnXj7FA?A^d{N8)85kzK&WUky@l`=3zRZx +z;ly9c>J|Z8N`eASzSqP+SA_Fh7KgFuHHg@!+Y71{Q>2msx?O|{zF84k)~JLvGVBKY +zz~$MM7)(bU!e?^B27VKy0Vn@Fu?d(k{=<1enT@R^X&$WdD*$`ofz`O^asqtffK9s= +zft~D5GJP|~Ug*mj-P)vN-J_5BV#t0rm@+Q`jCO|+&_wXxy5)d$cP^mN%hVH@KB^Jo&1ds%C05U;;N7T~5 +zf0sMIl2?)ORI%&^^_vH#aXi{{yVTj`+G|77}iV^Qox+X#7zf#nlfU +zn6gkBRhuMWXkisHX@TJSR`caaOB3zpspy$>g%;%*(Gb(xvz>oC-qs*vRR#v+!l+|8 +zaBVauIZbe_C-%_F{gP!dO7(qDQPx0JOWrhnwowIYYAdysl6O``aAMKcVb)7<^I^El +zf;jcW+2Vl)T|rgpb`OdHw=dVn=NCdM9vrqagoZ7G`qkh?X$nZ!O1s|>f#t0`1o)TL +zEZR7>8cGHp;LXm6hQ=GvW;))Rb;HI8+ole$54L2d%Sq8=C36h^qT){4cVFuJ5>{r0 +z0bTBw?4q$98jyLz-3216r!Rl)j$+1FJ|JMHb4;o8KKIw!MY-GVFDqaQsF=H8N&!Wc +zmJ&l(^UNwk7cby$2U2aT5CXc~sWtU9E)~!6^=S3u(lfIjRU-A{C%AU5jKu@|`i@|k +zQ!s7~z0hqkm5&XEDajKki!a_%vXU7(rF|$eAX@L6TaE$pX_9e7sOf(0dBrceC2~!* +zUcd%dtwL108riHywMwKB_io55mZSG8R0+fT@keT<$iz-3UF9q=B^E4KgIgq7lU&@5 +zJ_MHlHJV9!E4)l&kx)XTM!h~B)l&wLN&{^4G}#?J+Se7+l? +z|9mqSzit11tcYSuRoFW=ddkWN9z#(qEJ-vY5+5~$ipI5}l;?MKEpelGFJXJMTzn=- +zsE5k4;Z>zj=<9G_rK`_pm{zfrYN3d2b!FA=yoPB6m?2mFD13QFAnEUTNzjcaY=ASm +zCVYUTS>EF_J?l01^^q|N0=-;*vR96 +zsGz_Vyz-XKi!N;>A<2=V8SyqC_HYOV)+aGolmTMGCZZ;S_W^yi4eO#K|6-f+z9BX< +zv5%_IeQmuAH(WGyUHn5FIXi}hrJ)fUv;<4UKE=~N@RP#dVB6muXs{gC6sW(1p}HM2 +z5EQFDIC`wKMN0>zcO3quq-KNZL|^EMEj=gxs1T<^f%Btnz7x;dFnn{=i1IXf-E!Vq +zUdFfTY7@TZ-+skKs+Rk95qJfOgt=Pmyx$KKM`a;zks((3JqvI`Ujc%Wk~bj}G~p$NN6jNYJyG!qex!*4ZZs=$3m_%T@iiu$QC)a{ +znfyqY^6uRQNDJ05rbrY(lzqLMbl4K+Bbt156-qwhl_vB2eXw!UaGO5qZHu@FfD_rE +zP(n1Ab|?}B53P}3TGz53XxdHQr{xXeCjWK7MOC_3rIK;FYOi}Q>&($04G^!xZ`p#A +z9}tQUI;c-Qq<0j)Q&0Idd)U^+beBFML}M%f$pUCVoMFgTyY?{m +z1cHd96=v1CiR052Hm8bdVAYKsLg8lRS{T5@JOJfXZhJjp&T&%&`ut))hM16*Il{J= +zALQosUTeE>E)wRh=(dhh(ibEX!`JJ)noW@fG_Nw)qm_SZ)O~I@!!bp5q^FGS*pKyi +zILT<^?$)jCMFkE +z@(R#jYWYLQQ5`rUiyKVk(zKBvMymcMH&=GoacF +zBk7VxTUZ>-E2R?h#mAr4*ZXt-Ot>XC$vP;xCM_Yb8oW>cElwv5nAX%S$ORWcf_|5~Qbu&e|kr6stzhcI3hxXUa-)M-h(7ZMvJbZM%-*ap!cc4e#PcjBDB!{lyv@% +zp4FFav-cXT5@vFIQ#qB-q8&(ckq}uhyP>nIJ-|JD*AN;UjpDkRDE>eFu}OVl&-Z~Q +zZH;i1>KvV@*wW}+ZAfC_36YjvUqjgd(1^=|H!VgxF!>Z44a_x%)i(5jZoxXaDZiq~ +zqwq7>{z>!1?>VG?p~pSGU;E$A*Kae=h&fJ8|Qp?S#ps^2Mo%;a3bFm4{;0W!s5*V1Q5mA$S#OYy +z@7s8*q%4+$B}dVhX)Y~#@m}Ep$dbee003Q&1E3*|pQm7S$Vh|$#M`$j4LsS-n0c`= +z7{+&>j5_{+8BWh#y3gdxg6cJT!qwX;a$J`k@hS@>92@PeBAcPxpSnab>>^ey2CfPX +zeZl*Qa4urv@t%Np5tPrh{{Ytl!ZVM-U(JBiHxUK{|1V=*83Z +z1k=xJZ}5Y}@$K+BjYb3*U>t^Np~%_4ry2R*-`A)p8;x7+&ry-_lB-<0BN^ +z7IN94Z1uKs-&XQP<>$;!vO`F~x+@=2R%5>lK!9Irmo@t1gq&yYe`M+N4YzWm2w4t? +z9THbVn3q0GDdf0NL$q&Htxi_3KZi8g%;y*DnO17Q$ih(ROeZu45}6aS!(^uZPk)Sa +zUu#K>$-&;_^qa|#MO5jdwjugdxhY~}_%y_-kDoCM7^og-Z=#(*J@%s0_at;T{14yA +z53c%9ft{e1b#*mBTQ(Qd$V)hSH4;{xwJ(2Zb_+VJ^t+A1e#zYdEEP%Fh1!F>@tceD +z!cSM1?xf&xr)|6xH+Z71fP&hlbs3+(Z%LLKe|IJ&Vm7cg?UYJw>bPgD8p}}ZL&|CX +zHEg7$fR};wJVvN5NTpKGgp%p-;hINdzXRrsc=!jVvz^k;qL2vLk5%C@bbJRzu8S~* +zMYyXhfQhL9?^wAl1^F1#@EB6w&dLjbwDK*?isBXg2c9BD>?_0&p^f6rgJUUcsvYu1BQrABd4{ljTLyIF<=iM>0iA!n=U +z?=|lMvxQ|x?LuP)T%`6aT5u?_=252bFXRRCuB|Z6YhwWcSckp}Pw#TuPRbHha*+oY +zZ>)F4)^dt0jr#e8mIVPteDH$>f +zv1%_-YI6bIq>_c{IYm16L&PYzTl(>hG#@ZbBtXx8rjx4>c3eg-FSFX*ruzQ`P>eYK +z2fnB4#^V{M5J?sVMofUZqO9tl`%9FIELd*zJFjCc}W5eqIew{fd +zvnb#Pu-U`J!t!*uNk-W7@z!2J&Nb +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 +zd4!il!?Ry#ru_^A!y$`w>E6$Wyt +zTv;)z#Wks|ybf;T6loWXD9t2IK~W`^`&TmCv?ruROoq+A8>R!r +z1b~4!eMY|XRlrc(6krA%zuCSV=v-&>`q-14#o!=F=?!HF&W|*%6xP`HsBzYaSnsgJ0t2o=gsHy5 +zIRWBrE%NV2B`vN;q$>4`&dYF=4mYld;%dO}DD +zyoy4VW1{E4fQCPL{lNKRf&~tP0 +zftt3nq0u0dS9?&%C)ZNr^@QZ}^V8?h;Lw@OB6lfPlS~QvjsG`U(qs>ygc@UX@B%q) +z&Yz#^%DlQBjN^OD^}P6twW)zR(5%v3B*=wqB{~~lG!@z*$x;!z-=APJf_1x@g0|8K|R_&nmvJuQ4 +z;n3*02oi?xZ(_%-@Tt4puP)iH(f9>&*`8V}X@J!xy^6C=#aA&66FeN^{%!k~T`oOo +zbUM@e*5zxMzLxf#fRnzVS`BHm#=DR-IyrbFJsXn#iB+DRihPhzxkYcLvyY<6S11vu +zV?lv0z5V|m+|NVh7^r$(|C~w;RJ6!OXj*4v0|g__o$y2 +zzPt;I{*kc78t)_~|2G7)FTBC@77O!%4dB_Ad-;$+#Y(I`gQ-5eDv4$HZOO(Y&E>V>qJImEY~|*_rEwoPZg0-_6sj0}+{2P6 +z3IH6?G4I&6ZQHhO+qP}nwr$(CZO`PTD#FUDca|^QN=$PPnm#!x=hqZG+%% +z!wkrC>3g`{H4LNY=dZBzQXT#U&7+A(Cj423xLmdE+%!ylc2UvVbv8yjnSSmkSy*$q +zqDsgzpBatYXHdj4d>k{j7Ja?z4>!`RA@!)Dg;gzbl%Sj7p7VRHV^OzMnFXopA+iYm +z7QQq5D66K$)=g$#7$S@WlV6~XyvyZ{qX~_vrJNUfR4vZBB`@e*AUBSD;A@#Mz+~E8 +z?^R!6<7H_1t_ElcX(Q2v?Qn&TT-jcbl(uFkUvRomi8^gYFR1W`P^g+S<+Eu59w%gP +zEN1c!7)xepbmEy26vG#6y;FCK2peYE;qTsAVEArW-7LyZZ?Nrhz7GlqQ(Ww(;i8C4 +zq@h|*i11Exh`hzO&UnO%|QmR-$O?sP*5Vt(p8YY|8Wyw5?7(hyfuE%o1*d*aPaY+BvzV(dbUp1Jg( +zFHFC0G=}pS1?~`VtCMwJ+(Q-ztx7)*P*ovDGmA%|iNrV +zaS5v@ZDft*WJ7iDhtJ7Jl0;_)>DXS)(M+(hBZoflslJchUyvl~TSKzrVrR>XvMm*t +zUfY^d^^&y(=9Y^&n$+1iMQX(|e2g#UZNdG0AEF4J{i3+H?b;avIZvHdek))uNX}D@ +zjaUpcobH~~Xy@5((;x|!(IK`tABpud^-pQJjwLZBK9AYtz!)K^h4)b7jACBGPwxtX +z{$$zzv686*+gLL((}XX0u${3E#buBXHW_pRNpJAf17#=Yq^cJnX?ydg_3QfMlfI#3 +zn(bi#ka;eI8w6_2ugm!fh?~Et3c$;W&XP#ClHX-vsvxf}`fn~m+Xg_SL#HxQjbvjo +zP<~$Yf2Z#O6UwCuYg;maSFBr4&tyLyZA#WQ1LGhimO%Pc_G#hrU+HF?fNsYiuhD-r +zn&4X-TZ8PJBK(G?DCg#7Fbix +zcp4Jzci}Vs!77hVd5?X_Y7Uavqo9|xf)D$3o}XAEL26|=@A$5j>@ZjkZniGojMcqbG`;;L`Yr_zwp@e7oV +zaow4Ots_qgMy}$7)IidID?hDQf#p}~2CTr{CJFZQVw}nAV(o8zakZ&jCa+C4`KHJP +zs;>xz3J0Gfgp!hIIk-v%_Lt)n{bbL~Wtf|#86gHzwwy5y@uw(+Q^TUR9$VQ6BJPtk +zXuVJ~>K1}i(K?X1V{zH>3GnfmHqX@dOAhgsQi5FurjE=OLxK>YsaxCyETNP7dW@6N`$L{!TIKayl;8^(a1zUvj`A1!L}28+x3Uo%-h5ZRxOQx42)gwbdpCq|*FA|!teETC4X@XR6@<~Sl3+J- +zX5Ujro`z+eO*UqLnz4PS!N$~b?0mS?pr6cW9$Zf7 +zy`R!%(wq0l6>YLq&82}-{Mx7<4Csp?&Va?;9OtMRI3Ol^>8w)j_G$*_ouCQX_+-zh +zMYVS^-7jv-r~!+0Zn)7md(Df6Dov-cVNyHRCw%!)ZF5~fQ9&fQrjTGQEe93jOqoT!r@dcy4h~L9a+}krD +zArSUcJ}3M~Y38l9V+}UwDQnR9&a}=&2bu^`iCiqHnE#kG$4ethoLH1iBCPLuF>d6d +zH-mX1Up#{m{t+%Duo6B^uHzwl2jz-0T2@R`0>&wan-5pEqBeDk8Kao#?g>0aFoEN% +z@@}dR;*JM6cJb?71kvHx{1Eun+y@26|158>c~^!_3nu0d#+Y9TdKfeIHQN-XkWr=w +ze!4`LY3*?z3`-mfmU)yr72V(e-mew|h{%%a3qnvHtJnN0 +zL;){V96DV-pyUuWni~2g3n<2y_4!(fds}_|5L&y?YvwB?D5KNLqb}ESF98zx@kU#5 +z3>@scFa9dp?&{rWW{U|n^d(Xto*QcZ;U5gGg555IHbFF;D{@~%%GUp;T-Qb;xSQo= +zRDJN66H>#EOp|?eB3-sY$D$&VG4j`1!lKf*s4JnkwR^_I(Qyo9_Y%KHratg5ssA`f|%de!kstqgP-XM +zD_T_%N_1}0&CUn?xNAfX@;n+AxvgsQ$D#@Zk0)I4qLIJGl3UclYhrt +zS73;8X~89-yOz)KTZ|6h>IB8l0D7d*h#EM_U194&)Hn;Jvjm=xOgQyxhq3WZ=351c +z7cU*l(&hjT20*+4y9rW!<_;4ta4k=^iAPo-E;uPP8Q+MI(`Vrzg}v?9T4$;_P^{(z +zQ>f+CN&25$)91spSO1(T_Dee*M;T%PGYVMN^(*qaFRZAhYbIa%Um*9mJ-!c?p +z0v+Y+qVr<<10jg?>C*7W57XoopZCk3!=JJpGoFS67xG5i*}JTGW&e7^zSqLkJG{Q& +zBHO22Tm9=p)E_@Q04X?Ht{4|u_@NJ}PE=(L!#@gr{kDIkBvon;!tOrDJ?vCF%n;h9 +zqtRSI()zzz%j*3}rtKIE}uj(h(d +znPG7!Q0WIA^aHObD#ncNZQ(J}j;HBE-nk}^0A|YFlxWNRnWUQWqGo}@-aGBnSf{ZO +zYXK##NG~WF;~&@)P~|KewB8S%JyKBt+R0No&~< +zCzG}WT=g)0{cOrIJ>!mc7_L=`k9w%W2|mBN1I;>Ioo9$@bNuOi>pTV$8YN5@qjR5= +zD0c`>0lWTE?I@1=2{61td+2%p!Fdg!DBBIBi)ijE-OxrP)*DEM%Q3K25r67eGt@N4#Zj77y}^%Cn?MG +z-yN4fHub$`uGd$JFE8f*Y5eTcZLRx#d7l4twtRU){dB#2c_RLF?G$~v6#aDG{uK1J +z)%$I2)ZHNcvHh2=<9mI9{&Mkqedhb}r2pw5@ZAl3_6r^M8`4qR#PaD0-?KAr+r;U! +zeb-a7)%@&I`so7v@>Kunq4(WQ +z@W*_b3svm_$O!0K;yU^5ti)MaVXjCs=5G4N-De@&AeWB}e;1~JKP>+su(!T@fqe;p +z6pZ9VS)M`;g5d~=$P}?ipk7V^s5K7_nMJrPV+nlLh2y2OfsF#J5#wXU_3L~t)?E$5 +z6HmC`sTV*H$bV58vU{xG&GMY=khR@j$O!{NJ@|Od1x$S&)F4W4!EMN%Aud8o1oi`KC*yZZz-kYX5*^~7Vb(I<8i0Uvu3^1vZ +zK-Tlal(f@NmJ@#`vk%Mi?EQx$*Q1w73%hFOu* +zsc~G4Bo~5+%f_`p=PzuIS5o^7$Vm*_AnF5z>e{Lw3R(H0r +z2OQWiF38s+Eng$~%2*d^+A!01`$f6^pRY7Zv8^nv7c$3}H;OL8gbdM@p<0mH3GJZy +z!Hl-g9ubFn2`2@hE6UT!$DTlsqw{q3?R*Ae4Oo +z1hsMWIU0WV2fP@g%(|g9>&U(mhT~2!o0rad4Gr7Ih95NouHqx*QC-e9Vz8Jj)^G$? +z@V`X@3x>d%{_ueIJKNL|@>q0mc_r2RiH~)2Ax6fF0FqVFEJgi)bNISM9DC&ab$VB| +z4g<`Yr)o&E9-8#nz$#u3jWbQf!gI@@Yr%S-c^A;V8=H3&M|nyQagmuHRqxOC!k0)m +zpoWH(_TNH~)E_47d~g$J`I}+1_1>|FlxP$1Nr|3z+4#S;F18Mrj71=Lqk3)F8`SJ% +z!mE#%ELrI}E*b^jsOf;!C-b~ls!e#MJ@09MC<{7>JuC#%Bx5OIQYSY5Tm0FIl?z>L +zdhUP?dIBZ08#M*>hG#u=jMwy8Q7a|bBm`i}kArsr$98>I?cO|Z_?0RLesC*3N}MJ1f0;sG`I#64Sz!#Q8`OHBE*?Uo$whCfu&6UG8pT`O0@#azl{Y<{RRz?P0$D@WsOAy +z&Hu^v87sTt$!Y8hwO`?r?!#O%=6n1U&T1Mx-yXI!=)Z$7m$qFXOHpWSR(4TVqY)jnUmt(bM-ly5Tky4?qduCiUJjduYd)Bu*) +z!SpT$v;yhf7V8pPE$)RyKHSolmN?d`BneLDsxtzHk3~Q*Wd*}YtlXjQ5ON!zy|AU5t$kJtn4y|cB +z#c%iPWiGl|kj5vV1m#CAD%VbTaV}x!)n#|J=stPu%=RVPej5!EaF1{f#K7kb*(7zf +zV5U{}z+C?wG(W%GCms?G>tbU=EiyGy)#3551VuqFU7_r1)M51`y!=~PlN2d2$`E?A +ze7HAKo-UtZuRjxm3%6+*cDcCKHIX!G?XN^m0zkMZ+3IIi^gg)B)B_c3aV)eFk;Uv) +z1ltkodZ$UbwSvy(%IVwapL0-{Z(ya>*|V>Z!EwC$ +z)(^%WOoa3FYMmL=9?vX%-NmdK(+@TECn2zmNvTV}v|Vow`(n6XR)O(bdcZJ&1>^ys +zMie;MaTA{%#TLiID`Hdz+Z>P-_3_pbS@m?+CFn`&*ax{St+qr3Xt=Re7s^0ee-xlH +znv3nnk;SAPaDEVum(}Ic%3VGj1qhMLZ~(GLc+dtu<9*AulU+&td!|ZQ%*QC+@VE=O(>AqmyZN8>KM)o!0YTY%~Fq#fm~6(3YSipP +z$KB(LUl>;A<4%ej9g29WB^1ZD7>Jo+?$2Efz`_+H<4o}ar_h+_=Yp^UYSMi4lwb!q +z-GR%y_==%Z$q_p~y72Zij#R+&X2^drV)RHkMHXQ`O)LPlEZjAUfIwUKK@?%HPB;ep +z(!!-m8(ACji3(4R{?&bQiw)4b>b?LW%SDe+Wl0Ny=*&O|p>{t$ +zLd)+^dNJ7`CQc8Es*Y0r*et2-7i8kO#c7F;d$PyqiYj0ZJS>;F>oq4^%3Koa);(Az +zcyk6h1sf8zq(>C%;yH&(?$w`7BoM7fASa3#IOrh+V$M_PD>(l0sAoG4poI%fN$zOA +zO$hoJ80s`el#X#Ls@KbdA)MA>pOM<=9`?ax(MroM8-jq#8-zcaK|_~4Xye=Ebki?7 +zF^b`+lDM0IBsSXjs=6_RiE+f7bpyONCAE+keC+cs_oe<#Is9IKU~O;5RB|LuYZ{bLucETH1;fI8oO2cmIKVihqXCP|&b!uTDNN#@PstH&kx +zISPc;-aUz`SD(BZ^7v%YI5X?Urh9aFJeiSgA#zB0U}wa{>k_C0_alB`Z?y$ta8GQd +zKcCN%OAeU}HB1_1{{RHNGk8*v>ed-Bag~kSG!hk~T=;D+oV5}G-9Y4F0%Yn|Vieak*C@djBGzXPn3{_-Om%g8OoE%Gi5$5i1MPn`btTD(i0QR?-mF8+F&F^2odpgY#gl2lzE4q=~ijCVc+TUY%s|FizY~4*YCyd0p93 +zf&mR~k)ZGL?kq5qe+4-$*%{C0L5+|BMU!#&`j#P#-pJ5xO8Jj96Ab((TSM;^p#>d* +zAc#EHTIVEAV_WvD^+sG=mTd(SqirLx0c~+p^9#jCqdNQg5xEv#+@{Fw#na3?YzcLg +z)5RMFsS<YI+YsKm<`;eVmM2N1%pZp}lw>zunproeFAm@=avKkGj=Y2%#2h#!Sk=LN^ +zooYXM@@N(#5b1op2fghwRV}>^f$X!9T5yT*5GVsVK0@6O#fbWf@Qo%y(x+~IV}T05 +z$!}Ir0kF(&RA!c(Kz`+B=<5dgNWA0ihkox4G8k(C#!F2M;p4-!0bs2Gz-KK{PYTMV +z$dKX3#BYKy-LCrc%1uT$*TZjUBzc`BcMTYt*nVIO)1Al6&h3$)G0riTDi>j5jf-ygeOm@2dA;uJ6LW +z!_JNpRQ87x|Ma4Dmijn=`3Y#YL8jH~@#k;{G9qWmoyF4v{jp;Cnhfzd4Ch*y(p1ey +z3JfHeZ0+ymrQ6H6wCP?_$ix76Vk&h&r3x|gt|aXBDjc5gGE7Y}(jQy!Gue2W%N +zSMF2th|GyHQ^G(_VTE)CnwKF-!=`JAb8hX^8 +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 +zEiNGIQdJ%y-{4)p(yR(TgTp``o731H +z=n?+qTJw?WrvbC_nopCCjlQ2y9Iebvy*C#SN8w&-=>oBy+B=+d6#+Tr`$ankOd$B0 +zgHw;p2Id{-ZuKE(vxN*VEr3p1yJar_ldd-Q_9Ur%02jzwGcfc|CGNMFNC%W_nl3A& +zHz$Y%3Ql~C0omfOYF7+3^DI%QUjy{Z2+KdtHlWMa}kwx4pO +z-?39i9s)X2u=XSMtaISr=>TzPlI+BRQ-D8=dW|8?msoU3`LX)|F7^9%U<1=I2QM*~ +zS9~$PEPG%HkpL$VXE;h2__(N8YYSmCyJzY*&x*?gf4QlnORtBUqlVj#Jpfk_{joz4 +z)lS?Gr-e{SLa%>lT0(H==5@Yg6%hYan&;<~f^f9&!UTx?!!Oj`CxD?$NwEhmqR<V}wEm#@Xzk3=@(b!w11UatEyv3Zq3skHXoo9v*2w2q+X-l9tcX|d2(GdD5w0U_q_I0!+))C4g_l229@&Fn +zNSND;1jCHLmbClYo_02 +zNtHP-R6F +zIdwXc*RzDn&16=G8I}oQ26$?Fh|Wz)>v7?gT(rUBE3A;~@8HZeq4R}hFjY;c_v#=! +z6L44avL`&NMTA$;>5Wr?kY0|JKSXA1KC;LI&V!v=d5pMZyu0(teY8Ig;|x=CfeN)~ +zE7=}bQ@hqyx)g$Pg1Mrkt|gI +ztaxDGRqSOMN>sSP0Up5OytR`2D3-Fnu)5&sGlSk+ej;_Q#6WJyo5?FLoM@x>Ojz-V +z<&Y;*(znxxyGItgc~a?~+P3{y4WWd}4i?5FV}>{3uNG_HwFx +zl}GVMLJ#F(UnE2!{zU-xquW +zBVbM-;WidS&IC90TnO@#u+_ih*M9MtkXd0zP+QT8kiaakMlIH9WyZfF2UJa6x*Cg+ +z{eEVEKn*ni*F|&Xdl8Eh3vW2fkc~}^tZ4^lEU0I{}$M<})7h0>-MK@Q~W+mSUNmq+$&o^!rDn{*ND$0^UCxm010tjgu +z`G>4T_Yax+*EB-|2?k*z_JfsWF*H`2ZtD51P;|++Eta(ZOAu|MR#l~uQ>7D(I5jt3 +z3zmLE31q4!8=1kZyUEveNk>NWWP+N>yzHkKD*Kom1XpFA> +z;@1nvwx*46Cge-c-QjRUDO7e;rDeT_#l@}xC_3~AY4jjF9tKMuo_8PpJ9bNg3!MPmEpDtpkB|`n>SLc^wQ=ksY}|&O_a7t +zoM7!`C9%yP#lRbW;6c+uc_$o4?BNDR2#)`D>5?qPGuJ`{oEAiv9b(SOu_hh5wQA<% +z!yRmvUF%pV2Nmc85IAGjteRBVI4l%5?OhP@gvEi$;4(8M5^v+vCM!qnJu04`|9*_> +zbM;lH_5cUJY@WsBDAiQZrP(@32I_+Op^3ssZS8DgW3^)6;1bi6el|4)Dv$BPaB0Xg +z(a?p|H_1+Dpr}oFAEsLa(gV!r@efcoKWpG2(>Q4;IFZ|HYz~^6u_HM9aREaUMb%$d +zz$IO%sKhIIYDu7lUV7K&g}}#uxd1sxiCVy-%FpQnP-|S_~{Bd7)r`_yLxD+osA=cXgv~zvr)*GQ^g)@~K +z%Am0l43h$Uqj$)@q^VFrD6ZKeek-NhF7@Xrv`VMA?Qu-4o}na{Qw&x7zDXCP^9>PdSlyTcUOQ1O&G;LS+Ii3f(U}XWd&)^g +zdPF=|_cBwbKt+^6p`wL`&gW0d;A*wHGztfB!vkD9+@y_L-4WY}d+=}+B82wtgA7;dXP5;j5O48VcG6I=SDt)T&(7*hFj6D5QG#Q)cmk +z%(LumES2Hbv*EbfbPOe7nzL0~Oqyld>Go0--KD$(OW+hm`aT(`}9H*7`O#BEo;()y1dE7|iKGCwkB>Ug+iP?Y&LYfN~@V7soo9&=T4X>=| +z;oOh*$7rPHG$#oO=g&`+9>TGB(~IXg;>qukEr)(x&4>2qRqlP|nViit4cQ=$o$xaLWWoW`ypvZzqr}z`|Ax^j}QD4LCpfCd?8F1*$~eiM?k=X?rS(d +z3PaZwB~R*Uh-bM6@fUw`upEyB>06OnYiG8hHM5J_zb^&T;S35d?> +zCX4`b@iQ?;_F+X`ChKwr8<-^#4)8PJn&l}AWH4oj9%`UAk7HM8uV3(=2a^PR_rK~v +z*g$w?_@vFW|L;IsR)@w2c`KRi9hyp&#iTig^=a_wQWyxW5}R3zU1|F6^w9tio`Sq= +zoZsmMlz&NRt3zK~v|Y5~j()i$i&d3#w5&k^RlL<3UT`QaJ&3rH;>ROtum6jOufdv6 +znLAW9W%Ta?B{3+ZUcjjoXZAqOiX)N=^|^vMUq)k0DxAQ{ylRZ9sXt#z=WO*Yj{@&4 +zrPWpK`1_fJHo`k~;+!#R*LP;j{MvdLrq?Xs3}_#YFMlK-8(zNMi0unPliY;5kT5JQ +zOms!iE%nFIKew+o>RGbzb*aN$r;a|B-js#NuwKsm8YQtTB*xNROE;NLV@}IR +zH*>3me8z62ikiv{=kTA{?ey3~{OiyP<>p!O)leT2|8lX!72zdQ$e8;Qh@J`G!E}>T +z&Si0+WLq6(y7dwD=D`+{EEH)T@bxv9Twchpm9)Ew=hH6w*?*@cGc_X;eQuTWp-q}> +z4mV+kqa;ITH4(=L1f&yGb0u;X@bU9Vz8u|1_p1eBD>ZlS-SN-8^(uR0Y1)@2fui$7 +zql|CqWoyuhlc|n6?J->f<{00z2oxOPHzh96yQw0gAIe>A$TLC2od(v$F}Q8&SltV@ +zlcBTFZaN>V!7}#X#mR+9FJbIH>xIqfSD&`LwZGl#=8Xt6qX}=AuDusT`(J5Gc+^qWLy6-!ItwfW{9a*Ul4T~$G#5ZBZv!iHC5P@4I +z)+LNf2efqP{zU4RRe9t3IHXTFd03rATX +zVooy`qEZ@GZ?6{BUAJ&^sQ<@=Ggql5LvgHa>|(E#IJC!FId+b>@vTVic~ZcQ7ntcR +z2+)+8A8CViXoHNg?Qu~!UmAk1 +zLU!VD58Kx9$es-J%r%AnEeeVuSV`@cxSLQLYBYm*N%W78o)a#>W=k#ocj*qPeB*r&OY6oIPJk7NjG_I=dZ*0ab#1w}dDUot +zI8(kMp^;pm;jleij7tr{0biB0V-lAF{a}+_TDt{G0JJ)SvEPV||NEe)O8;2W<^qhr +zaf5njrKgA=$I3ya{_vX8)A-l>Nu!!1}B&vpu|Dbt&Mwl#Am +zggvJ-H+U0p4T+_hL_N9JFVVtyQf_pOyt%v4&+H7@$=GyrU|6VEVQ5&krwB56oRn$+ +z1rSL(0iX$a>;cM8{(Av|Ac9{heu?WR^9BJ4x`t!rcmu!QraVf~ar}w%5;KU;?N2-2 +zKlkYUb!zn^HaeT!A00iA5VZ#rRaZn +zHI5R)F~R;z4T)t)Dt)+6F?uVfofU>76X%OJx~ncEX;xL;f#m;|P@o(8_Mo+7z33!} +zS^g|alan&CglfZJEa=!UU_jPegg#sb7Gh&dTC=}IP!l8jo00gjJggm{j8?fVnwK!~ +zF_O$ZI;E-kZ({o$3hdY5WLeOuAayvoS8{?u&?=1X!7=GEz+t`x35!V!FcPx1wuA7C|2)Qb)#Jk1$82B|crT3=7?3Bi}P5S5S^kgAT#G>Q&7`h(GeS&Yr +zM3vwp{BybdyevlDe{Pj_>9`~&juvl&ul~Mn7cTO%oT8qcYYRU(IVr0kG9)NmdVK6z +zt=_RifO4shZ*E*ebNzqn?`3t}QG_J&?{mxApDhDO_gLjmVu +zAWdBuzY}90-%_FvB)WRpN%d;z)+OvBJ1Q>W68PP%NzH07tFK7eOV*0`Ju72;L8Mrv +zRDlT}J}QFp84@BXEC&Dp6o%t(75c(zLZjvz|Lx>o6~p-#$g8z40>4!RCs4nWN9W0( +zEijVyB;cga(WxJWyXz$zWT2^lkysG8aY~cbPH&?%t*3gb>{aqD6k;|Cq3rmy<}?4k`X)$T=f(3K@f)=}R@sjZJ7!(qb}OFTLJO)C +zeIo=1B>RV3G7!?#2XL9Dc*8l*<64nSRuRaPa>PXj_an%o-)YZV%>D7V)?Tw(Kv +zczCH;)pQ$v9d^5t@lH^GYCAY5b6!7`HhQ}%X?ru40GV9Byf^TY +zxdO*h;Oh5FM!0S>!PV7$_s7c-2J&EPPP;LVD+_V==hF%Q?9{MC0BZrNxdTYhJ8K^1 +zbOemZ0tp>y?r%|^LVY{-QnBRkdcD8eWU3wItXLU8j_PCODk14NH2nf;_6_z#}bdrjPB= +zQZM%siJew-GF=yNRK|Rz;pYGV8jT(t2^HM9ORY+49q&UsYk5&!nf#LqmUp+- +z1mbt$#SV9pcM1o?&RRrc=ZZIO+vH~_Ie(;GU1r^;kR7S+tYiSMA9g)@!^SGYVUg-- +z-->`CZrTHwxyj*iMTJM{BcE+0BUE51Q1ahMU|5W6E5@v}(^qpteDFRY3iY3-)3ORj +zd}DnJ5_x6q&aG>CD_?@t4Nw#T%OkQvp4$p|^RS}lZqWwRf}SS;=CTO$7|+J&oP&va +zK~x3&IP`p?TtB|qkDVLQEgcRRBT=D#k%E2Eev0C#q=6#+RItGdb +z{KkmreU4yA;N1u?@6|*~{%{5cqD41UuQ|v*p!1jMyb(1Q%r&|6{_F9oU#pll!`y=$ +zuX~Hm-X8)H?Z5KW!%cH0Qb?`(bVSbv@39e47f~a@R@D_JWl$wEAn#az005{>36M}T +z39^XSSz#%{7m{iaV@zErIchPL1S-0TBoRg|Lm$L~Ab>T)zSm#Bj3Ox$DIeuKU4uUl +z(b>x?xy~L*@p4fuyiX36diM&T;w{0RVauLxNnfs2uqtPSPi_43zJK`*uj-;piIiebO!ft +z*ZVJeKw;#i!iJyCb>k!pXysy>V{i9wN2hHi!sE|^&x-QKE;Jl7p({B1RwWZ1A!L*D4< +zC6=cD0w0=bG<0sW@IF4JG6Vy&?=3XyO}2paBOR$u!R{wv0N`_$mjR3|go0GT#LHR< +zpq^LypDNa7=9HmF;+S}u1zEOcUl +z|B$OLYnD3LXDLcj@&gdbAHGh53|uJw2LLoc%fA@f^yI1t24*3ANLvk+kHsZ`!CwJH +z$S70-e`ot(d??+zP8KsnKm1P-+##~cW~S)b}btocH79pKX*1W +zmv+5MKBMWM-CZ!;DOVdTnm!&t2@9iCrwi^OY5*R9i145phC2aT|8k--<6l)u;N8Oz +zOTKb>la`cq5E!m#|IOj~fh=Q_L#)ibVe-~1w!DV>3{Lw +z-ofvee9%c*P_)Kk4(v{CMnR$u-AVRf&TFQGGBt3A31z;##K{TJ^dA|c++MATSgM+S +zp)QYj3PJ;49UKM~ClnSrh8IuYZGXdB&J-~_o)0|qlrn-rC3V>{Kqy+}f9~wX?HY*Z +znXzHNex&C*04xv-I^6w+LrkyG1?QjWFG_Qzhce(}qwlU2-;`p>3oB5h>VQw?@9NL` +z?kk-@gU87Wg)g8p%}KQqU0=53@n*?ZP+!dRh`|K7jNu5-B*5wj0Arf}Uh1GW3AztJ +zRzHT}LPyv?n$RY9oaw*@f+Jm|#A+*Wgr(*_u?%T8dil-DnGK_7ReF9KUKIp%xKkKz +z0Dc#LGY6-xk9`5YE(3L33K3b{lX8%y6gA#FZZ1@hej>7mCp3#V%9vUl77(qr(F +zPhxbSo$um;(fusAO$-=ym-C^o{-j~esE#xaXHzONG$=1MWY=k*lc7TVeT3AMmq6d72CE?;c2y1~rmtIX^EFh2Ix}gt*O)D!;J1 +zB9u*dmBkg?(Ayz@bR4IlHtOGnC-wm?0zOmPycnCigxQiVaWu3;4W0BPxV#BTQ^e{2 +z7ZNrVUr?%Uyp}3WI}GN_KN0?T-lkCGJkxkqQyGQEWO2>zL@r^uohi-^9Fcb(E!s;) +zKSidqp=8Cy_^!&#y23d*iI)uqZZb|^(f@~f`=@TF#MQm~U^1|B6Kba`_4d#Aj{0NH +z2j;8^Tt(KDAl&t3NMebHe5P*GqyXz#DNw3>0K+o`lwo?ZRSZEC(JnHrYzIlh^;*H`(kRQZ_*Ars_2AGP(Ynhrf2t5L)JUNr__ru69g +zW!|`wpbDyU?-HTOwL_(a&N%`(k8^^4W2A8=?i;yVS68-0MhB-tU+BknAF-Y0f5Ds9 +z^v4jMt#ZzCqAKu=rwFby{+!rq;X$5ljcF+gl=cKtg$;Wg>*gpDwQ93jF{wRctJ}{+ +z=Bmirg-P$o-5Kv_l@UF7C=NVavMftKjqz*C&-2mdIP2gu91w8Sx{8h{9$f~VwlkW@ +zH$>)@q4SH#eG3G&{)LP|giouy3+W@(Fdd$%VzF$f_?Q(K6Ex8ET_*1+?uRz6Cu3DE +z2#fmp*+b9lchQxK^Ms3|vdS|DCT;h%mq1NdpAtbqYO~P9)`dMZNEa_a|0g6+Qn~H>m0Q4rb9yM;l=6JHpALV+3Q=q7=U@v +z +zr8HQ#K9P&;GbF~^aAc*~y!O +zAOYGw@yh2~9_IS@b{`J5?~ +z4i5^|-L-Z+!k@}qOpg*wS_Rzntb;@URz)COvfxY}0pd2%)JLeV*L$mj$uTq3B)(2wj@hc)m@HSp}}l +z*xIe1M)v~!M+waw(1t{?>8sBA2~4U@gfCL=lK8pNSns|h<<&^Et3=qpqU4LS_XVi>)^ +z*e{Za-WFIcTv1I%y9h8s^ZHwcF&dxrDQ*0y<%Bm%iZPg-_l!;W9>}LlGw5dnVF$_Y~e742~0$oq<{oKA|aiBoje!{qfhve +zG>*QZ=qu`}x{O%R54|yIPOwghXY3|C{Yv~KuFd5!g+zuW>6pQ;R$j#Aq|uqOX}z~f +zjYMWzz_e|{-SS$j-_h*WC|%-6+j|HUy@ro+)s9Fv=X+HcriuBeg4J7X1&NK7i!Md7 +z|2YaZ!*!G|KKK3BcMU32;+RKAN99!`?}lvh=B2l^6nK5e0d>H& +z9Z=EI?Y|-aDXqjUKvLD}(NDG63>Yhlsy@MyV>&z3&NNBX;cHGf439!G5c=Xjtsy=9 +z20-uv8ALva-L3+8=;^$=FkJ19XVsBo$Tn?%M#X5rJNe(W4%&oo%oBF-(NabL4g^_$- +zmI>$+Qk|`GH{syn@!toRHFf(uMOB)$lBeIF6Ni%oz@Z&1ee-k$v0_1x?T~eh)q#&n +zJZA}ecjWT)rk}`n#Idh-`8n~;K=CkLu{|jT%_z*HawDrH%T=8?HU6nTtUH#Jea!tQ +z_8_`|5zl|&ygMZVKmD=jv7w1PqsjSiNJR3}ptYn!h{#iehfHNtmg_(=CZ@}HCV +zBE6VK2J>aY&W>3{M6Fl!!P>}Yekbj9jg5kky3OsiqU5?W-q%sHI*wS{BKhPU3z1n5|C5U*6Sh +zz?=Eg#3$T=TmJTnuF!0oN;-n!M@c~qRZHR^1%_DlAjnThzXf91vxNL&h+&AesICC9 +zl*)CTKxhsgJtthVH8e+kMd}y;P~dJhF^%$Mc7Gb_*hFa$D>p-50p^|6cdie9n)O>I +z)Fo{$2mP$Of>meLd)xsoW{hK3MxxyC2ZGtRba*{lJqEv6Vxabd_`e-JNt{2O@+bwy +zv{$+1TI``$K`Qq4CrrAu@=nlD>7V)0u^mA}5XOYUCh_;3ciZm0ai6TPVz*uBNHIyg +zn;i01wl*d&pK}o}W^=lJKfxe_YIyq(N>%F@Tm!UIidVnAI*d&)d)zP3H&0$9JEey$ +z@%eYGZWKaG?D|X>jWmQ3_;2Gbs4lg}VBx38%y<4|-8a|g-;?(giCVSooGi)bkK4}f +z`J23(wM09qfw!N-{M!@LY3-4ARz%8T75_&+PDR%Sa85CLfv+T5VPP?iD;XksvGkl@ +zxs$}%WaC3BIxX$H7Z082je4*_@;AAh+ABOg9)&fD(dO@ +za00VRmw5^5I2J~HsNJhp>UDEpaQ(1MH6dp5yrQv9W)1T<!aGQBRU33>rVOuMY(9J2{%Xg-Ag)j?ypD1**dH1N_&Njr +zA`B>=tY19oUCU+K_~$!3#YNgJOvTW!Xx9ntBh1*3Hw`Lp`x8u~iIIC_scBlruj4ed +zR$RF>?U>h3Jud5-C#Ua3*B_1@z{=2pbClNqyKfasdF6{cs +zLkBCeKqS`6ZRp}>(moxgzEV>@iI7$CBV_+C;%e1YC6LEoJHqs2?kfl>?pFUgKAtsm +z01wZT?8;MZ)EmV!PbC#cGjJH|0zyqLLHHM`;?R-gCfjiwGD}ZVbc^Nx0@%cPMVrGHJ6R +zYsysVpzJ>Vm;8NcFouRC)&M6+6lhPX!`BcVshqwvxuie5pdgmyZcNTF0H)KjMv_7S +z&&`C+@vWNkQE0G}(!RN+PC?8K4U0)dDt| +zX?#bwJWzy!?HD2|0tptOhbTj3V1e;)&CS)3p&7uE9oM7da{nykOa{m_nj*^PR*0nH +z_eM}Gl`PjC!{r8UtCU!oM|wZTNFac_a5kb2fPG$GEw10G%^KrPH_l0-G>X4qH<>^A +z@8WEn3$e;(3D!hM&{NeJSpT7KvJ&{Wgpm;p)ES9Yx#}_e}{Eojc;5u +zuUyhTszwXHK%@OFZ3Dkg9CLW@lo8TXs_vpyj0X~S4&~T=eTIX}@NRJ|1o?QGh0m@t +zp&1-pGojLvy67>tEffdTV)j1Zn~g-{rd+20%b~cejjE8h*@2N=7RbE!*{P;C*_Q$O +z>R{fP*JgA3ZF#^g4Jj*s{$)O85Ls9`Sku8ElIAn6#D}nUYrNZEhmt8G|li+%dg$Pit$4=L}0G7Ex5&_9oGsyN=%gd|da|ZHa-(-K_fk +zKl5QJ*d`8X02_{}@pgK#j#-Zw-JUG7;s165#)?U2-aXhtUhpGpPfSfk8{6@$8HHAE +zX@R*v^IFwrbMWM_bOX6DvxhHVaCOu?3Yf*9MlbxCmF7g&YlTW^5^Aj~3j-4eG?TuD +zP>X0t0JR@bi6lGI{j@%frt=vtp1sBM;nAe~PvCt|e=`D4K9F?9cP{D7WYacLB6UC# +z`KWXn`;HHcG{okmOe9zYw#Cx?N5u9c>Dc?qWK*>ITmt@)+AAQiuyyn+g#SN@%Td47 +zKsqX2m;me;UT=Q-0CX4L$^ve!Mbb&iq7KQtm~*7L4__}n7B(yzoR)biq7HAcFU?5% +zmTN@**syY+MCF6$?k%Q7jTL}y$b1(19p~@gC{SHsZydV0?E!lcH7j9`+@G@_2&zX^ +zQ2Wz{2N>Y02aUaY&*bkpkfCaj2|Y`7|3IeaL*G7_Zix}*1k>1MfhOy?>vKK@kqLY{ +z42fi8i%GNJe=Igr+jD$C1A7RTRtqswL9tzL!4>!4MLE>dAij6BG0bWhUg#ekjhZ&) +z=4%*c@`&{w3?&cmZsKzf(Hbw>PO2P=d_kN?Qcf%9f`~3VnUy_W%alY0Qt)G`@h(6g +zp4Jw>bh1$!N)!oGyS6{4cnIi>7=r7OzvTx#7d0I+?w>}WH%N}$qbfYL_O4g&MerE~ +zB>JOOoKo&2wyu{d!|AWb>lE7O9<3c-O2anr6}4%B{LSNL>mbTD8g-S~uBYqJfX=+p +zOoFaViD#QRvXV9|dMC3@flEQfg^h%Zi9))_5N)-e(60-Z-VXR|Xw$yLFNkNMi^1+Z+}2Ou+tL!?DAT0zolG|5K~3a6jQ5A +zER7le34<40_LZ?C{~W7Q*V{ZqMBSj&b<9ZCq@9XQW7LDhA6~$-#uvBs;ncwl2z#l4 +zkI9zdui$OA=QAjB+oaBlP3Oa+%Aeom;+>v<@lh)_u^wk}d*p3T_yC8ZtlM32&*+qZksBf#$0m4Atm +zD-)nRzc;a{Nk*0dCCQ$BsbO!acQzlY_}lUs{7uzyS_|+R^WUQR!M!Z{1ZKu8oD&g% +zy|Ac>_`p0k^<86FYp%^V8(Yt@36$q_Rmz+G1mOu+2Mn6UM6>BI) +zB6&7HUf|zBb8O{3B(v>B!x{%0yiJZu7~Rr+0RJ*oBfu9UVtkWiTu(`Uv@`AnR&E!M +zI~I$6vVm#+iQ5bq)5Q<@K9_eiE6!8UVL|F*g;9As_Fi?PQ +zS}2V6FGD8GNiY4wMpwEJ391aPiqH0VP{M4-uk(nD#e6>mU&0Byq?B-k#aKy$Y`%pG +zbDMPIDDNiVp^u(=zwUnc>Bo=dI)34B7OV-2oJ(#*E!w +z4Nn4b2Tjl0Hn~bbsL89gx2p0b{)p2q%EZeI!_*;534YDid3N9XhKL} +z&_35WfO;H!TZd3BvVg^TcH4P1r~58p8ZQ6{gm2uP)GkQX#{4|>|LXKi-+9)L)(7{r$wc~=Qtm4ImBE9oJGA& +ze`ib8h-o^>^=jrGoV`F5X$9JwRK>^CRL +zv!wyiCW^CQ6!_3nDVhphsizKUj~~>Nc=Sa7qS+p)+R%DxW4214MR#rlEm?vS?i*` +z<{;fyLHu?RHqOVXEY+Xx*?lv~uq55I=T{s134vqtlxeLLE3lxge@=Y+ctmT>4%%sDYr9Dvi&{S_d-aV9N@h4NS}e8bxy|k6X2tV;xnSCU}mhC +z2Lj~e6~k0G4*xvi?2f`pM0C|UcWSK9VVt5V&eKAr>2f|&3k&>c&yK;rVsd<;hdG4} +z*l$C&wECy_5qE~OLfjt&5dSK&iQC7&bRU)Y{KfMqH?-r@03i +z8ZK_1@UF%7sz>aWOPg19Z*21rYtELlb4gMtzPmT~>66`%W)hmZsR~6Txjprg3L>U? +zH%=+G?6~TztN^J1$W?;jh;whiR`iJVou5J}6N}co9t;89dq#37D60Q2RyhLY6X(r7?}V-o)fnl8VeD7U(F&nrN*rKbRW?vyupp +z37+LYxuo3V^s6~3$!;GJ;9G#pOBj=2z7{zN8kKB=Xh(gMozpZw`apCX0m%$J&RiYZ +zR}5iBRG7cZ9y=_a!uaU%w|YHgO~4a~ +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 +zNgD++#XvJISkoC&mIPt$ +zy!c6w*Ir`$?k-T-ddl(E?>Nm9t=uwYtb4UKK9QR+rknmqNuLE$8=MxJLFVzzu4o*) +zC3@B{#1pHBxB-C98CYP`H9S;7e57LF_#gTJYE5pgMR1`FW8-7V@(q9pxDm+)=)twK +z3-vm+1A@Yio=d-(${*K_rBCyPS$>CuuEj%KSxlIUKSE)CZTvc0OK>a6Dym75d(hI~ +zgz6dZGx#>VG;lMjx~42dn^Pcaat8@AWN=p6H3CV!$s&}jsIPdc54DZ>m<8Amq0jlr +zKHsc)fbNlifg#Dshl>KaCOC2EG?|HUJFzNwnTo(mY>oi1sl#jOVbE$MRbP8doE}c6 +z4U32Sp5A>arm=up&s8Wz=a@hw5pWsvM5S){mW;6u?p*K;&y;H_Dbrk#!(ph=15JdX +zKd0~cu{N81FbT!i`w8g+q69}PLB6J0w#S(j3PhQULhl>fM%4LevGCU^0g~$=K!NNT +zu;|UQCR)$M<%^K$fXO$H!Lvg4gkAjg@+%`UiQ>X0bF>I)9na7dw?W(HMumQ-PzQ6- +zd|Z=RwmVbB0(DI{=k)`Y#v&|Uhml#MiU33WiE9+89LDOJGXOMvLReeB7DYi(aQ985 +z&RBo#)^&wfPk^NWkMm(efj{zrUf1IKlY^t7=WuyKScYykdk&&w`1utbV%^S43N!|w +z16mLJ|BJFa7hL2saycK>ELg5%)vz@QF!vxh$PCNtBGf)u1R=31k9qErP +zAEMl647fyt$sl(Gf>PuC^2oM^)u}a?yE2{#&c1ZT_6+i#)6S3HXV8H)*fp?hzL&v1 +zF(i%GdO$oZKPT$;>_*6M$~xpAZh(~{P6R6DvAB#6J31?@85B04FEIP)Jk_wl4!zpE +z&F!S0l#*b1?k5{>13VNDon3mWX>s6xsy#|J6>@qscWxDY-QjME=QFkX+4-D^GqRBM +z@Zb87l^v^bEX|nJnSdZT+KZwX9!B-K%eDw`>PAg&_=>V>oNASlU9JP~P@p|k0-biwWg%J;I)mr{r@&rGo!q$^C-Z5s&&#o3&epRV +zD0_iXl3oyy+Tn`LQ;DiC#5^p2LcV6A8}zh)Ne?iAlj( +zK)=I@L#k0sDaHQ*+D>rcm2{qDcd<$?Fz$ibE6ozL;0#yORQE9_JqvtP+nHn +zpfc;zo?j{RtW=Wc+W~$bamfb;s%{K*faS~r{}QXkp5zGlPw#Xc2f7Xx`|nYzs*DCI +zazG(Y7c>?jWF1-GLYd+}2eE+aMOs6ofI5m=2MAZR6q3e{4Lr={#3%dm6-@=?;!_QX +zX$%sm;h%Ub5s6&o354VDjfN-lDpux0g;R6~3e&GhBwmE%v3IU<`*I9wSF&dxs9CuKELv(cd$hi%2Y3dG?npnr1Q@MO2JT`pK +z(v-@^TVUqFwHNQzU-;J~e7N>{So={Yl&UdK=|OE(SBU%MmUzAA;>HtNFius$HJX`- +z*y-!38bZ?ts~Sc;f#stGPut9j{KZec%p6g22|Z}Y+w--~-!k&?HDj;jg1U_+#k0yc +zWCYeqvRLs(ay2ldTCRAm5Y+}64eCV)!`FC6r@%Dw!qaZ6q*DA`9tt%w0i4gfnt(sL +z?lDMhXH0lz1+ANhaJ!)TU=XQPX&$Su0OMODYp2dEl8g-k4x5y_!b5*>Z+b1O1&#*k +z+K-zdVH&Ur##_@U2rv6&@LDWoprlbTNuoJ26DUI#OUT7Dpq1scXJqSRSMLsD>c^ov +zBd9QX+8a-RmsyZL7vPX@t=I48TjQ9t>z^ezP>Y-6RTAy3;;@gbta+tcgtkMdzsKZc +zfkGg)%Q@?8D$Y(8PIAfMb0}C=>iPv!{QI-akd@CuUy$f!W10>9BR;hNy4Q`=V;~S| +z%Z^oR@k~?*NgpZ>XaK}(iIQ{hBZ+bput}W|A*10gA!fSGu8Lu7Eydy*2o`FpyZv+x +zMfz|oTInQ)efCL+E8h@D{yAy{|5q^2Yfx;P|Y +zDU(5#nMcN$Ra*uE)8!*j9qtZ&aVfixriEF427HYMC +z40k0BS^db2Csm5nU{i;_C!k5SOG?LO%@GX32i(f>K<1}no10i3kh$gQT9v2q8{W`% +z;J3UOtbtLc97${hvLZejEw(6M?_~&>b +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 +z8>d)TY1)DX3{%!_=m@>^RhY32e;l=&!? +z{BM}6mZ=!!c0j}nh@&&^cb`eDWXX3tyWB`R^K{N~(i&;xzcCY_D3_I8H1GpR)GUYh +zo*oiu*#gVqP2G5Wj!vue)RPAb@Lq{*x2r1lDAPCV<{)5|eRLsK9W0a?6s1hp7Z6wr +zsAg^8VfTWsC{PW@*!wx=Xi*QF;ms4}>pptXH^CG7 +z3G}%B$4R;uv740Em9H0#M=nGcci6WEbc`B%_c2XTO=5vIxNqeEkD9mtGykLojOH$ufHV +zbyFZCk~76zc4$P1f=<^kg2{%#eOs?tZp@9(F{6ImtiM`%T!haMDxS$ +zi4pgOHF1#mW?>>NMb1^RIxuny!2n2`jLb{L@_rp13-6d|j?rNN+Emq+ifX9DRlh)eZJqEp^dA9pPY_rY1fQ|j;d4jLM> +zQT{W=6`Y$1b(>R<`8v!)_^xmuvE50is!w>q4Kms255P^z(18S?9liB{NR{0Emr86M +z`IMH9AoLCfnu9)iXWToQm)LYWGp4o=cFX@(9Xm-7m!-GOm?S)s;R|0iKX3E9ZAtzp}Qw%3Ja02QrQOkhEe#Ah+?#ki)zy=ge$Nm!@Z={GX*uM +z&Z%1ZVy`-6OPey|zfKmUo=Q0Jdh^QWE=7eM;3iISwn9CF!~*6r#7(+9b!%6XjG*DA +z>vWR)fdtHikis2G)8p4W;}Ozl32rkTI*%`;R50J4gXYJg#?kFaa1P~9;>#Fk!SM8! +zREJHfwmj1L3oX)ds;q`V_WT4VGiA +zA&)7L#9iyaS2L@S6pSJWt12&VxbR81#IxqbEiP9`)Sa;3K=tzr|1W8Roj{gF7p2Tp +z1unC!#z;u*-9NW5SDN&v4BVE@v!5F%vjIZzh^cC1NL|-?puzFQUQhZ>R&t2fKS&2@ +zS~U|oxkehJPvV*nX84RS%x2V)*;b6a0mVe;vRZ%rS$!`nNHMl4NB$9)SGbpVpslA= +z->9UGK^4bNwwzRYfaUW|gqa$(NZMTVpt&@yjBT^)UU5`J*J7a(a-Qt=6t+wJ7zw<` +zstt7LPzwU7DuqIVKRUYdqC+15!@ +zSe5U$ix*=gG96Yq06GZ5)PVfp-q`JjHw&~oYJI|iI^rOx7P5&wT*wdZ3I#yLUy+pI +z5Qk{jT6u6J+IJSTQ-ULdz8~jro-B$05%`j`lmI6ioK7t*nFzibDyH~RBV9^u@B>7$ +zzlqs6=lWrjzd|o^(;xZ0ohb;ieN+RUJkh$?RE^uRL4(JmZhK=2T5gYz3*Le*a5wz0 +zW`+K?W$()e4-~dN2B(npicts0L@hpbP{8kTX}JFJ6TEIQkf?!Wm)5iUAE|6YMpGn-ET7Qm=;9tgbKMsSC2Hno5$$*m_AY8YzI4p_0G=n@j8? +z$%k~S*WJd&I8jC*r%q&br-Y4;==L6?MBm*WEx3oLl9ShO+^NVVMKz5^w2VnS{Q>a` +zFN4gyICV$#HWZPBML%jrO)!XB(OaPRE7uHf2F?SwhGIC5ueMANoPgtc-sVb1GTbfV +zUiS*0vmADj)j3=cGeH$QSwaAVs{M6ypyD$*c$<|Mf&Y6;;;OBuGz%k8vNEqF13i2; +zw3k#hwz9!?S=Ezr8QX3#(C`I7{#o?}-}Bg$;PEy!9sc?vy~K(&-o6^w28VivS3wKQ*ki_dVgwP4CSG!z +zU4CThI@?vW{G5C`wmJEAv)wJV#=?gm$YOB +z9+)_tCeSUaFH?v321DA`C3;eNtyJ~#Myx?1X6SA7H_szo65ONO7UK{RG?x)&Y%C|b +z-ui0gYjo33jp>%b@w=m_?#i|)ShXQR*131*GOa&iLI0h1Q;aSQpySxKZQHhO+qP}n +z`o^}-%o*FZJ!foV|4la8+}GRmv3+TpCe^Et*tJ}xHe*Lp{-xS~j#~(m4>%wdwg5_$ +z6KKS26}d{V9kvx9Es*Lnb)eENWUV= +zY}H6$aMo>qq7rz9`^3gAw%4+17&d(Cc|pQySdAdHKIlx8oACLfC|jvEzd2Ty7c!<7 +zer-FWrPy=QRyEcvW4d-rtKAW8N_8S{HiA0u(XWyHXl%St1^W%~M7m(FRIO44 +ze+$Aqkw#AuWLT9w-*k9X{}zbtxhEi`$#*>PkZ?j{$tXZoFoXH7)Z40QafdE#ev<^E +zm-RgDUy^9n+S}L(G)0)k^y{RaI-pa}EV9^^N`A7=No^0r6^#bb;NH&5vKdW +zWAvsZ7$zeuhA~Hr`=s)Lw7g_g@q=CrRPz-~U{Ly-Cl(~&`Hb8G5R+ODmIq(n7?`eF +z-DFSFkj|2GoL29s!Zs&u(2rLg#28Nf)ofc4K=&7q8Y+iIGOMMDm;*}n{MBM#iDqx; +z1Ppdg0hDN!Af9DVbEl0CkZRuWi-sx8POX~=(RUM0Ez@-1gW9n8K1wxPqZO*>kdJU% +zR|%vn=pT#SQ`6wtr~`w#(*KM%n7uFg@GBfzuez#*FF9<=|3gC)+mqE-)RM-ePDaix +zg9NYd;V*|2ahgL&MOVIOi@?I3{w2XFMlbC53TZ8{btaYH{rDG+^l}4+Ea-4jx1XT! +z-Czxavvp?4-Mi4_v2d|Y6i2o0v${H(VetBO&A8||b3Pm^f<$R^(r*@k{t#rdI0^dF +zk>4X8sVdbh!P!(+^-iH4FCAwgW5PI3wU>6yg`{`A<6dVs$DB*%&%fAsM~b8vrQI)KZS?q?XAc3k-j6-Ixd_iCc(p{;WN5U+_XNI{Ou9Z%=JOf7g3 +zL%Mi(pzuaYG~peElIy;@H2~`WA_0dmn$>xic5nCJ6sGxG!NC-8rt9i5k-e7`?xDR7 +zSKs*CQMuJ;p!2^$*zlWxe7R`!w9Tl^MF+Icau}~B^6nGETSqBjev5|%syaMr0q=>7 +zvJ9Qc4KSxJnqVgt7P%%6PojgGFllLAON8zH +z%h(-b6N4+1Xago?a06!sw?y`RD>KmNeEQ#-{)4(rcn@3islTWOh +zsdc23bvhh+=M%{X^}Yg)vXft_4of#`Hy}8**zcVJXlPJ!a$(dDTD8S*lF|$L+xsdm +z#yeI86(!Er!poi4uQzOFcR;ZC%3-`2S)6Ec4w=XY(eHMVZrkPU^DT6S$zG_8`V7z` +zuV8Sgl6|Of3GYGyH#*p1JSJ5piL`U&cgB}8en{y>jkqCtW7bQ0*t|vnkLyAyJSB6i +z;nZQ3OK$u$?5w5Q3K&{&?-$bh5_Z7t5~^2?;dl~yKyz8)Vg(WzA#7}~==d&K@Z~RN +z5QVWkHUFq>gx{aN3OeD;&_a@}MfkJhlsVGYKEt5Z9SxpQ-{}@_1vV%e*^JR^Qh>K9 +z720I=$kuoOy*MO0XERDn07K5;WiLOW0 +zekc^FwFqscdyJH2)^MV`Y(n|r>;w@Y +z_0+sN;&1})hz{Z1W#rk}!3@F+;B)Dz_9HXo1f%_2^LWybtd&hNGZT^&5b^6`UyMQ~ +z;|fA1AF>T7OBXY5r5}_qj&2c1axRFcX3w@y!kGb5tX#v&!)YaL0;KAV=emOZdDcVX +zS~SAu-f@5Y7gd%PC31o`5<}hjAZYf=kPSiTHTa+z{*eBJl|FQKJ+YRQ8GzcRLqTbG +zY!}g%g8_B!KYEs&HZy$k4^C>hjDo^HB4U-q|Hz5Q32M4?v-G`~2W2MObVgKjQ5$a! +z`Ec$F9J$pR{alOFBEf5hf+)NyZylgRrnhEA;^>K$G?1op;>W3?rrD*ezIjQk2r$EB +zBAV_F>h!n|kpibEz41LKWN|_!%xAAnt43;r20zdiKGcF+FI>D{V6-7VfJAmjc;X7< +zB&cXXIt47f2Z4G{fiFtjR}ZjA!Fx@PQKzIjN%C;tO&6Ox{{<+gPAtZ`ct~x +z|F>nc)|gQ6m5IU$1JfeUHD0C;%W_dah-6Vr=GwAJS`&> +zUn*Ryw;sV-B +z2!+KqBwRWWNtRHp?|AmAz*@s*+kI1y_WPj=B17r=N32>T1~Ky!$qyZ(C|OA{8IR|k +zE}=DcrE +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 +z7yb>m3bsidtGrt&i&Yp0S72!$%N +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 +zalzfOx=H_<0QNq1xw +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 +zf1;Z^g@8U^KEIULpk#Ze~-a<-{g$o*JJpd +zKl+Sj>B_rPU*C_G9CAmcN8UXbl+e_)kIPw9kl(2X9B8_H5NgaLWe-i+PbXbgY3mS< +zF%R2@B+c~Kp)muyz_vLDsjQ+U1~Yu~%&lE*9HFDvfI7P?N$_|R#Ni&=iI4Y`Jo(p* +zXc%_$A(_}iSrTHN%OBDabjI8nVq<5&>26`A%(IHOG8HfU@dM9V<=>Gs^Xsb#9 + +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/sender/crash_report_sender.m b/toolkit/crashreporter/google-breakpad/src/client/mac/sender/crash_report_sender.m +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/sender/crash_report_sender.m +@@ -0,0 +1,1215 @@ ++// 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 ++#import ++#import ++ ++#import ++#import ++ ++#import "common/mac/HTTPMultipartUpload.h" ++ ++#import "crash_report_sender.h" ++#import "common/mac/GTMLogger.h" ++ ++ ++#define kLastSubmission @"LastSubmission" ++const int kMinidumpFileLengthLimit = 800000; ++const int kUserCommentsMaxLength = 1500; ++const int kEmailMaxLength = 64; ++ ++#define kApplePrefsSyncExcludeAllKey \ ++ @"com.apple.PreferenceSync.ExcludeAllSyncKeys" ++ ++NSString *const kGoogleServerType = @"google"; ++NSString *const kSocorroServerType = @"socorro"; ++NSString *const kDefaultServerType = @"google"; ++ ++#pragma mark - ++ ++@interface NSView (ResizabilityExtentions) ++// Shifts the view vertically by the given amount. ++- (void)breakpad_shiftVertically:(float)offset; ++ ++// Shifts the view horizontally by the given amount. ++- (void)breakpad_shiftHorizontally:(float)offset; ++@end ++ ++@implementation NSView (ResizabilityExtentions) ++- (void)breakpad_shiftVertically:(float)offset { ++ NSPoint origin = [self frame].origin; ++ origin.y += offset; ++ [self setFrameOrigin:origin]; ++} ++ ++- (void)breakpad_shiftHorizontally:(float)offset { ++ NSPoint origin = [self frame].origin; ++ origin.x += offset; ++ [self setFrameOrigin:origin]; ++} ++@end ++ ++@interface NSWindow (ResizabilityExtentions) ++// Adjusts the window height by heightDelta relative to its current height, ++// keeping all the content at the same size. ++- (void)breakpad_adjustHeight:(float)heightDelta; ++@end ++ ++@implementation NSWindow (ResizabilityExtentions) ++- (void)breakpad_adjustHeight:(float)heightDelta { ++ [[self contentView] setAutoresizesSubviews:NO]; ++ ++ NSRect windowFrame = [self frame]; ++ windowFrame.size.height += heightDelta; ++ [self setFrame:windowFrame display:YES]; ++ // For some reason the content view is resizing, but not adjusting its origin, ++ // so correct it manually. ++ [[self contentView] setFrameOrigin:NSMakePoint(0, 0)]; ++ ++ [[self contentView] setAutoresizesSubviews:YES]; ++} ++@end ++ ++@interface NSTextField (ResizabilityExtentions) ++// Grows or shrinks the height of the field to the minimum required to show the ++// current text, preserving the existing width and origin. ++// Returns the change in height. ++- (float)breakpad_adjustHeightToFit; ++ ++// Grows or shrinks the width of the field to the minimum required to show the ++// current text, preserving the existing height and origin. ++// Returns the change in width. ++- (float)breakpad_adjustWidthToFit; ++@end ++ ++@implementation NSTextField (ResizabilityExtentions) ++- (float)breakpad_adjustHeightToFit { ++ NSRect oldFrame = [self frame]; ++ // Starting with the 10.5 SDK, height won't grow, so make it huge to start. ++ NSRect presizeFrame = oldFrame; ++ presizeFrame.size.height = MAXFLOAT; ++ // sizeToFit will blow out the width rather than making the field taller, so ++ // we do it manually. ++ NSSize newSize = [[self cell] cellSizeForBounds:presizeFrame]; ++ NSRect newFrame = NSMakeRect(oldFrame.origin.x, oldFrame.origin.y, ++ NSWidth(oldFrame), newSize.height); ++ [self setFrame:newFrame]; ++ ++ return newSize.height - NSHeight(oldFrame); ++} ++ ++- (float)breakpad_adjustWidthToFit { ++ NSRect oldFrame = [self frame]; ++ [self sizeToFit]; ++ return NSWidth([self frame]) - NSWidth(oldFrame); ++} ++@end ++ ++@interface NSButton (ResizabilityExtentions) ++// Resizes to fit the label using IB-style size-to-fit metrics and enforcing a ++// minimum width of 70, while preserving the right edge location. ++// Returns the change in width. ++- (float)breakpad_smartSizeToFit; ++@end ++ ++@implementation NSButton (ResizabilityExtentions) ++- (float)breakpad_smartSizeToFit { ++ NSRect oldFrame = [self frame]; ++ [self sizeToFit]; ++ NSRect newFrame = [self frame]; ++ // sizeToFit gives much worse results that IB's Size to Fit option. This is ++ // the amount of padding IB adds over a sizeToFit, empirically determined. ++ const float kExtraPaddingAmount = 12; ++ const float kMinButtonWidth = 70; // The default button size in IB. ++ newFrame.size.width = NSWidth(newFrame) + kExtraPaddingAmount; ++ if (NSWidth(newFrame) < kMinButtonWidth) ++ newFrame.size.width = kMinButtonWidth; ++ // Preserve the right edge location. ++ newFrame.origin.x = NSMaxX(oldFrame) - NSWidth(newFrame); ++ [self setFrame:newFrame]; ++ return NSWidth(newFrame) - NSWidth(oldFrame); ++} ++@end ++ ++#pragma mark - ++ ++ ++@interface Reporter(PrivateMethods) +++ (uid_t)consoleUID; ++ ++- (id)initWithConfigurationFD:(int)fd; ++ ++- (NSString *)readString; ++- (NSData *)readData:(ssize_t)length; ++ ++- (BOOL)readConfigurationData; ++- (BOOL)readMinidumpData; ++- (BOOL)readLogFileData; ++ ++// Returns YES if it has been long enough since the last report that we should ++// submit a report for this crash. ++- (BOOL)reportIntervalElapsed; ++ ++// Returns YES if we should send the report without asking the user first. ++- (BOOL)shouldSubmitSilently; ++ ++// Returns YES if the minidump was generated on demand. ++- (BOOL)isOnDemand; ++ ++// Returns YES if we should ask the user to provide comments. ++- (BOOL)shouldRequestComments; ++ ++// Returns YES if we should ask the user to provide an email address. ++- (BOOL)shouldRequestEmail; ++ ++// Shows UI to the user to ask for permission to send and any extra information ++// we've been instructed to request. Returns YES if the user allows the report ++// to be sent. ++- (BOOL)askUserPermissionToSend; ++ ++// Returns the short description of the crash, suitable for use as a dialog ++// title (e.g., "The application Foo has quit unexpectedly"). ++- (NSString*)shortDialogMessage; ++ ++// Return explanatory text about the crash and the reporter, suitable for the ++// body text of a dialog. ++- (NSString*)explanatoryDialogText; ++ ++// Returns the amount of time the UI should be shown before timing out. ++- (NSTimeInterval)messageTimeout; ++ ++// Preps the comment-prompting alert window for display: ++// * localizes all the elements ++// * resizes and adjusts layout as necessary for localization ++// * removes the email section if includeEmail is NO ++- (void)configureAlertWindowIncludingEmail:(BOOL)includeEmail; ++ ++// Rmevoes the email section of the dialog, adjusting the rest of the window ++// as necessary. ++- (void)removeEmailPrompt; ++ ++// Run an alert window with the given timeout. Returns ++// NSRunStoppedResponse if the timeout is exceeded. A timeout of 0 ++// queues the message immediately in the modal run loop. ++- (int)runModalWindow:(NSWindow*)window withTimeout:(NSTimeInterval)timeout; ++ ++// Returns a unique client id (user-specific), creating a persistent ++// one in the user defaults, if necessary. ++- (NSString*)clientID; ++ ++// Returns a dictionary that can be used to map Breakpad parameter names to ++// URL parameter names. ++- (NSMutableDictionary *)dictionaryForServerType:(NSString *)serverType; ++ ++// Helper method to set HTTP parameters based on server type. This is ++// called right before the upload - crashParameters will contain, on exit, ++// URL parameters that should be sent with the minidump. ++- (BOOL)populateServerDictionary:(NSMutableDictionary *)crashParameters; ++ ++// Initialization helper to create dictionaries mapping Breakpad ++// parameters to URL parameters ++- (void)createServerParameterDictionaries; ++ ++// Accessor method for the URL parameter dictionary ++- (NSMutableDictionary *)urlParameterDictionary; ++ ++// This method adds a key/value pair to the dictionary that ++// will be uploaded to the crash server. ++- (void)addServerParameter:(id)value forKey:(NSString *)key; ++ ++// This method is used to periodically update the UI with how many ++// seconds are left in the dialog display. ++- (void)updateSecondsLeftInDialogDisplay:(NSTimer*)theTimer; ++ ++// When we receive this notification, it means that the user has ++// begun editing the email address or comments field, and we disable ++// the timers so that the user has as long as they want to type ++// in their comments/email. ++- (void)controlTextDidBeginEditing:(NSNotification *)aNotification; ++ ++@end ++ ++@implementation Reporter ++//============================================================================= +++ (uid_t)consoleUID { ++ SCDynamicStoreRef store = ++ SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("Reporter"), NULL, NULL); ++ uid_t uid = -2; // Default to "nobody" ++ if (store) { ++ CFStringRef user = SCDynamicStoreCopyConsoleUser(store, &uid, NULL); ++ ++ if (user) ++ CFRelease(user); ++ else ++ uid = -2; ++ ++ CFRelease(store); ++ } ++ ++ return uid; ++} ++ ++//============================================================================= ++- (id)initWithConfigurationFD:(int)fd { ++ if ((self = [super init])) { ++ configFile_ = fd; ++ remainingDialogTime_ = 0; ++ } ++ ++ // Because the reporter is embedded in the framework (and many copies ++ // of the framework may exist) its not completely certain that the OS ++ // will obey the com.apple.PreferenceSync.ExcludeAllSyncKeys in our ++ // Info.plist. To make sure, also set the key directly if needed. ++ NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; ++ if (![ud boolForKey:kApplePrefsSyncExcludeAllKey]) { ++ [ud setBool:YES forKey:kApplePrefsSyncExcludeAllKey]; ++ } ++ ++ [self createServerParameterDictionaries]; ++ ++ return self; ++} ++ ++//============================================================================= ++- (NSString *)readString { ++ NSMutableString *str = [NSMutableString stringWithCapacity:32]; ++ char ch[2] = { 0 }; ++ ++ while (read(configFile_, &ch[0], 1) == 1) { ++ if (ch[0] == '\n') { ++ // Break if this is the first newline after reading some other string ++ // data. ++ if ([str length]) ++ break; ++ } else { ++ [str appendString:[NSString stringWithUTF8String:ch]]; ++ } ++ } ++ ++ return str; ++} ++ ++//============================================================================= ++- (NSData *)readData:(ssize_t)length { ++ NSMutableData *data = [NSMutableData dataWithLength:length]; ++ char *bytes = (char *)[data bytes]; ++ ++ if (read(configFile_, bytes, length) != length) ++ return nil; ++ ++ return data; ++} ++ ++//============================================================================= ++- (BOOL)readConfigurationData { ++ parameters_ = [[NSMutableDictionary alloc] init]; ++ ++ while (1) { ++ NSString *key = [self readString]; ++ ++ if (![key length]) ++ break; ++ ++ // Read the data. Try to convert to a UTF-8 string, or just save ++ // the data ++ NSString *lenStr = [self readString]; ++ ssize_t len = [lenStr intValue]; ++ NSData *data = [self readData:len]; ++ id value = [[NSString alloc] initWithData:data ++ encoding:NSUTF8StringEncoding]; ++ ++ // If the keyname is prefixed by BREAKPAD_SERVER_PARAMETER_PREFIX ++ // that indicates that it should be uploaded to the server along ++ // with the minidump, so we treat it specially. ++ if ([key hasPrefix:@BREAKPAD_SERVER_PARAMETER_PREFIX]) { ++ NSString *urlParameterKey = ++ [key substringFromIndex:[@BREAKPAD_SERVER_PARAMETER_PREFIX length]]; ++ if ([urlParameterKey length]) { ++ if (value) { ++ [self addServerParameter:value ++ forKey:urlParameterKey]; ++ } else { ++ [self addServerParameter:data ++ forKey:urlParameterKey]; ++ } ++ } ++ } else { ++ [parameters_ setObject:(value ? value : data) forKey:key]; ++ } ++ [value release]; ++ } ++ ++ // generate a unique client ID based on this host's MAC address ++ // then add a key/value pair for it ++ NSString *clientID = [self clientID]; ++ [parameters_ setObject:clientID forKey:@"guid"]; ++ ++ close(configFile_); ++ configFile_ = -1; ++ ++ return YES; ++} ++ ++// Per user per machine ++- (NSString *)clientID { ++ NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; ++ NSString *crashClientID = [ud stringForKey:kClientIdPreferenceKey]; ++ if (crashClientID) { ++ return crashClientID; ++ } ++ ++ // Otherwise, if we have no client id, generate one! ++ srandom([[NSDate date] timeIntervalSince1970]); ++ long clientId1 = random(); ++ long clientId2 = random(); ++ long clientId3 = random(); ++ crashClientID = [NSString stringWithFormat:@"%x%x%x", ++ clientId1, clientId2, clientId3]; ++ ++ [ud setObject:crashClientID forKey:kClientIdPreferenceKey]; ++ [ud synchronize]; ++ return crashClientID; ++} ++ ++//============================================================================= ++- (BOOL)readLogFileData { ++ unsigned int logFileCounter = 0; ++ ++ NSString *logPath; ++ int logFileTailSize = [[parameters_ objectForKey:@BREAKPAD_LOGFILE_UPLOAD_SIZE] ++ intValue]; ++ ++ NSMutableArray *logFilenames; // An array of NSString, one per log file ++ logFilenames = [[NSMutableArray alloc] init]; ++ ++ char tmpDirTemplate[80] = "/tmp/CrashUpload-XXXXX"; ++ char *tmpDir = mkdtemp(tmpDirTemplate); ++ ++ // Construct key names for the keys we expect to contain log file paths ++ for(logFileCounter = 0;; logFileCounter++) { ++ NSString *logFileKey = [NSString stringWithFormat:@"%@%d", ++ @BREAKPAD_LOGFILE_KEY_PREFIX, ++ logFileCounter]; ++ ++ logPath = [parameters_ objectForKey:logFileKey]; ++ ++ // They should all be consecutive, so if we don't find one, assume ++ // we're done ++ ++ if (!logPath) { ++ break; ++ } ++ ++ NSData *entireLogFile = [[NSData alloc] initWithContentsOfFile:logPath]; ++ ++ if (entireLogFile == nil) { ++ continue; ++ } ++ ++ NSRange fileRange; ++ ++ // Truncate the log file, only if necessary ++ ++ if ([entireLogFile length] <= logFileTailSize) { ++ fileRange = NSMakeRange(0, [entireLogFile length]); ++ } else { ++ fileRange = NSMakeRange([entireLogFile length] - logFileTailSize, ++ logFileTailSize); ++ } ++ ++ char tmpFilenameTemplate[100]; ++ ++ // Generate a template based on the log filename ++ sprintf(tmpFilenameTemplate,"%s/%s-XXXX", tmpDir, ++ [[logPath lastPathComponent] fileSystemRepresentation]); ++ ++ char *tmpFile = mktemp(tmpFilenameTemplate); ++ ++ NSData *logSubdata = [entireLogFile subdataWithRange:fileRange]; ++ NSString *tmpFileString = [NSString stringWithUTF8String:tmpFile]; ++ [logSubdata writeToFile:tmpFileString atomically:NO]; ++ ++ [logFilenames addObject:[tmpFileString lastPathComponent]]; ++ [entireLogFile release]; ++ } ++ ++ if ([logFilenames count] == 0) { ++ [logFilenames release]; ++ logFileData_ = nil; ++ return NO; ++ } ++ ++ // now, bzip all files into one ++ NSTask *tarTask = [[NSTask alloc] init]; ++ ++ [tarTask setCurrentDirectoryPath:[NSString stringWithUTF8String:tmpDir]]; ++ [tarTask setLaunchPath:@"/usr/bin/tar"]; ++ ++ NSMutableArray *bzipArgs = [NSMutableArray arrayWithObjects:@"-cjvf", ++ @"log.tar.bz2",nil]; ++ [bzipArgs addObjectsFromArray:logFilenames]; ++ ++ [logFilenames release]; ++ ++ [tarTask setArguments:bzipArgs]; ++ [tarTask launch]; ++ [tarTask waitUntilExit]; ++ [tarTask release]; ++ ++ NSString *logTarFile = [NSString stringWithFormat:@"%s/log.tar.bz2",tmpDir]; ++ logFileData_ = [[NSData alloc] initWithContentsOfFile:logTarFile]; ++ if (logFileData_ == nil) { ++ GTMLoggerDebug(@"Cannot find temp tar log file: %@", logTarFile); ++ return NO; ++ } ++ return YES; ++ ++} ++ ++//============================================================================= ++- (BOOL)readMinidumpData { ++ NSString *minidumpDir = [parameters_ objectForKey:@kReporterMinidumpDirectoryKey]; ++ NSString *minidumpID = [parameters_ objectForKey:@kReporterMinidumpIDKey]; ++ ++ if (![minidumpID length]) ++ return NO; ++ ++ NSString *path = [minidumpDir stringByAppendingPathComponent:minidumpID]; ++ path = [path stringByAppendingPathExtension:@"dmp"]; ++ ++ // check the size of the minidump and limit it to a reasonable size ++ // before attempting to load into memory and upload ++ const char *fileName = [path fileSystemRepresentation]; ++ struct stat fileStatus; ++ ++ BOOL success = YES; ++ ++ if (!stat(fileName, &fileStatus)) { ++ if (fileStatus.st_size > kMinidumpFileLengthLimit) { ++ fprintf(stderr, "Breakpad Reporter: minidump file too large " \ ++ "to upload : %d\n", (int)fileStatus.st_size); ++ success = NO; ++ } ++ } else { ++ fprintf(stderr, "Breakpad Reporter: unable to determine minidump " \ ++ "file length\n"); ++ success = NO; ++ } ++ ++ if (success) { ++ minidumpContents_ = [[NSData alloc] initWithContentsOfFile:path]; ++ success = ([minidumpContents_ length] ? YES : NO); ++ } ++ ++ if (!success) { ++ // something wrong with the minidump file -- delete it ++ unlink(fileName); ++ } ++ ++ return success; ++} ++ ++//============================================================================= ++- (BOOL)askUserPermissionToSend { ++ // Initialize Cocoa, needed to display the alert ++ NSApplicationLoad(); ++ ++ // Get the timeout value for the notification. ++ NSTimeInterval timeout = [self messageTimeout]; ++ ++ int buttonPressed = NSAlertAlternateReturn; ++ // Determine whether we should create a text box for user feedback. ++ if ([self shouldRequestComments]) { ++ BOOL didLoadNib = [NSBundle loadNibNamed:@"Breakpad" owner:self]; ++ if (!didLoadNib) { ++ return NO; ++ } ++ ++ [self configureAlertWindowIncludingEmail:[self shouldRequestEmail]]; ++ ++ buttonPressed = [self runModalWindow:alertWindow_ withTimeout:timeout]; ++ ++ // Extract info from the user into the parameters_ dictionary ++ if ([self commentsValue]) { ++ [parameters_ setObject:[self commentsValue] forKey:@BREAKPAD_COMMENTS]; ++ } ++ if ([self emailValue]) { ++ [parameters_ setObject:[self emailValue] forKey:@BREAKPAD_EMAIL]; ++ } ++ } else { ++ // Create an alert panel to tell the user something happened ++ NSPanel* alert = NSGetAlertPanel([self shortDialogMessage], ++ [self explanatoryDialogText], ++ NSLocalizedString(@"sendReportButton", @""), ++ NSLocalizedString(@"cancelButton", @""), ++ nil); ++ ++ // Pop the alert with an automatic timeout, and wait for the response ++ buttonPressed = [self runModalWindow:alert withTimeout:timeout]; ++ ++ // Release the panel memory ++ NSReleaseAlertPanel(alert); ++ } ++ return buttonPressed == NSAlertDefaultReturn; ++} ++ ++- (void)configureAlertWindowIncludingEmail:(BOOL)includeEmail { ++ // Swap in localized values, making size adjustments to impacted elements as ++ // we go. Remember that the origin is in the bottom left, so elements above ++ // "fall" as text areas are shrunk from their overly-large IB sizes. ++ ++ // Localize the header. No resizing needed, as it has plenty of room. ++ [dialogTitle_ setStringValue:[self shortDialogMessage]]; ++ ++ // Localize the explanatory text field. ++ [commentMessage_ setStringValue:[NSString stringWithFormat:@"%@\n\n%@", ++ [self explanatoryDialogText], ++ NSLocalizedString(@"commentsMsg", @"")]]; ++ float commentHeightDelta = [commentMessage_ breakpad_adjustHeightToFit]; ++ [headerBox_ breakpad_shiftVertically:commentHeightDelta]; ++ [alertWindow_ breakpad_adjustHeight:commentHeightDelta]; ++ ++ // Either localize the email explanation field or remove the whole email ++ // section depending on whether or not we are asking for email. ++ if (includeEmail) { ++ [emailMessage_ setStringValue:NSLocalizedString(@"emailMsg", @"")]; ++ float emailHeightDelta = [emailMessage_ breakpad_adjustHeightToFit]; ++ [preEmailBox_ breakpad_shiftVertically:emailHeightDelta]; ++ [alertWindow_ breakpad_adjustHeight:emailHeightDelta]; ++ } else { ++ [self removeEmailPrompt]; // Handles necessary resizing. ++ } ++ ++ // Localize the email label, and shift the associated text field. ++ [emailLabel_ setStringValue:NSLocalizedString(@"emailLabel", @"")]; ++ float emailLabelWidthDelta = [emailLabel_ breakpad_adjustWidthToFit]; ++ [emailEntryField_ breakpad_shiftHorizontally:emailLabelWidthDelta]; ++ ++ // Localize the privacy policy label, and keep it right-aligned to the arrow. ++ [privacyLinkLabel_ setStringValue:NSLocalizedString(@"privacyLabel", @"")]; ++ float privacyLabelWidthDelta = [privacyLinkLabel_ breakpad_adjustWidthToFit]; ++ [privacyLinkLabel_ breakpad_shiftHorizontally:(-privacyLabelWidthDelta)]; ++ ++ // Localize the buttons, and keep the cancel button at the right distance. ++ [sendButton_ setTitle:NSLocalizedString(@"sendReportButton", @"")]; ++ float sendButtonWidthDelta = [sendButton_ breakpad_smartSizeToFit]; ++ [cancelButton_ breakpad_shiftHorizontally:(-sendButtonWidthDelta)]; ++ [cancelButton_ setTitle:NSLocalizedString(@"cancelButton", @"")]; ++ [cancelButton_ breakpad_smartSizeToFit]; ++} ++ ++- (void)removeEmailPrompt { ++ [emailSectionBox_ setHidden:YES]; ++ float emailSectionHeight = NSHeight([emailSectionBox_ frame]); ++ [preEmailBox_ breakpad_shiftVertically:(-emailSectionHeight)]; ++ [alertWindow_ breakpad_adjustHeight:(-emailSectionHeight)]; ++} ++ ++- (int)runModalWindow:(NSWindow*)window withTimeout:(NSTimeInterval)timeout { ++ // Queue a |stopModal| message to be performed in |timeout| seconds. ++ if (timeout > 0.001) { ++ remainingDialogTime_ = timeout; ++ SEL updateSelector = @selector(updateSecondsLeftInDialogDisplay:); ++ messageTimer_ = [NSTimer scheduledTimerWithTimeInterval:1.0 ++ target:self ++ selector:updateSelector ++ userInfo:nil ++ repeats:YES]; ++ } ++ ++ // Run the window modally and wait for either a |stopModal| message or a ++ // button click. ++ [NSApp activateIgnoringOtherApps:YES]; ++ int returnMethod = [NSApp runModalForWindow:window]; ++ ++ return returnMethod; ++} ++ ++- (IBAction)sendReport:(id)sender { ++ // Force the text fields to end editing so text for the currently focused ++ // field will be commited. ++ [alertWindow_ makeFirstResponder:alertWindow_]; ++ ++ [alertWindow_ orderOut:self]; ++ // Use NSAlertDefaultReturn so that the return value of |runModalWithWindow| ++ // matches the AppKit function NSRunAlertPanel() ++ [NSApp stopModalWithCode:NSAlertDefaultReturn]; ++} ++ ++// UI Button Actions ++//============================================================================= ++- (IBAction)cancel:(id)sender { ++ [alertWindow_ orderOut:self]; ++ // Use NSAlertDefaultReturn so that the return value of |runModalWithWindow| ++ // matches the AppKit function NSRunAlertPanel() ++ [NSApp stopModalWithCode:NSAlertAlternateReturn]; ++} ++ ++- (IBAction)showPrivacyPolicy:(id)sender { ++ // Get the localized privacy policy URL and open it in the default browser. ++ NSURL* privacyPolicyURL = ++ [NSURL URLWithString:NSLocalizedString(@"privacyPolicyURL", @"")]; ++ [[NSWorkspace sharedWorkspace] openURL:privacyPolicyURL]; ++} ++ ++// Text Field Delegate Methods ++//============================================================================= ++- (BOOL) control:(NSControl*)control ++ textView:(NSTextView*)textView ++doCommandBySelector:(SEL)commandSelector { ++ BOOL result = NO; ++ // If the user has entered text on the comment field, don't end ++ // editing on "return". ++ if (control == commentsEntryField_ && ++ commandSelector == @selector(insertNewline:) ++ && [[textView string] length] > 0) { ++ [textView insertNewlineIgnoringFieldEditor:self]; ++ result = YES; ++ } ++ return result; ++} ++ ++- (void)controlTextDidBeginEditing:(NSNotification *)aNotification { ++ [messageTimer_ invalidate]; ++ [self setCountdownMessage:@""]; ++} ++ ++- (void)updateSecondsLeftInDialogDisplay:(NSTimer*)theTimer { ++ remainingDialogTime_ -= 1; ++ ++ NSString *countdownMessage; ++ NSString *formatString; ++ ++ int displayedTimeLeft; // This can be either minutes or seconds. ++ ++ if (remainingDialogTime_ > 59) { ++ // calculate minutes remaining for UI purposes ++ displayedTimeLeft = (remainingDialogTime_ / 60); ++ ++ if (displayedTimeLeft == 1) { ++ formatString = NSLocalizedString(@"countdownMsgMinuteSingular", @""); ++ } else { ++ formatString = NSLocalizedString(@"countdownMsgMinutesPlural", @""); ++ } ++ } else { ++ displayedTimeLeft = remainingDialogTime_; ++ if (remainingDialogTime_ == 1) { ++ formatString = NSLocalizedString(@"countdownMsgSecondSingular", @""); ++ } else { ++ formatString = NSLocalizedString(@"countdownMsgSecondsPlural", @""); ++ } ++ } ++ countdownMessage = [NSString stringWithFormat:formatString, ++ displayedTimeLeft]; ++ if (remainingDialogTime_ <= 30) { ++ [countdownLabel_ setTextColor:[NSColor redColor]]; ++ } ++ [self setCountdownMessage:countdownMessage]; ++ if (remainingDialogTime_ <= 0) { ++ [messageTimer_ invalidate]; ++ [NSApp stopModal]; ++ } ++} ++ ++ ++ ++#pragma mark Accessors ++#pragma mark - ++//============================================================================= ++ ++- (NSString *)commentsValue { ++ return [[commentsValue_ retain] autorelease]; ++} ++ ++- (void)setCommentsValue:(NSString *)value { ++ if (commentsValue_ != value) { ++ [commentsValue_ release]; ++ commentsValue_ = [value copy]; ++ } ++} ++ ++- (NSString *)emailValue { ++ return [[emailValue_ retain] autorelease]; ++} ++ ++- (void)setEmailValue:(NSString *)value { ++ if (emailValue_ != value) { ++ [emailValue_ release]; ++ emailValue_ = [value copy]; ++ } ++} ++ ++- (NSString *)countdownMessage { ++ return [[countdownMessage_ retain] autorelease]; ++} ++ ++- (void)setCountdownMessage:(NSString *)value { ++ if (countdownMessage_ != value) { ++ [countdownMessage_ release]; ++ countdownMessage_ = [value copy]; ++ } ++} ++ ++#pragma mark - ++//============================================================================= ++- (BOOL)reportIntervalElapsed { ++ float interval = [[parameters_ objectForKey:@BREAKPAD_REPORT_INTERVAL] ++ floatValue]; ++ NSString *program = [parameters_ objectForKey:@BREAKPAD_PRODUCT]; ++ NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; ++ NSMutableDictionary *programDict = ++ [NSMutableDictionary dictionaryWithDictionary:[ud dictionaryForKey:program]]; ++ NSNumber *lastTimeNum = [programDict objectForKey:kLastSubmission]; ++ NSTimeInterval lastTime = lastTimeNum ? [lastTimeNum floatValue] : 0; ++ NSTimeInterval now = CFAbsoluteTimeGetCurrent(); ++ NSTimeInterval spanSeconds = (now - lastTime); ++ ++ [programDict setObject:[NSNumber numberWithFloat:now] forKey:kLastSubmission]; ++ [ud setObject:programDict forKey:program]; ++ [ud synchronize]; ++ ++ // If we've specified an interval and we're within that time, don't ask the ++ // user if we should report ++ GTMLoggerDebug(@"Reporter Interval: %f", interval); ++ if (interval > spanSeconds) { ++ GTMLoggerDebug(@"Within throttling interval, not sending report"); ++ return NO; ++ } ++ return YES; ++} ++ ++- (BOOL)isOnDemand { ++ return [[parameters_ objectForKey:@BREAKPAD_ON_DEMAND] ++ isEqualToString:@"YES"]; ++} ++ ++- (BOOL)shouldSubmitSilently { ++ return [[parameters_ objectForKey:@BREAKPAD_SKIP_CONFIRM] ++ isEqualToString:@"YES"]; ++} ++ ++- (BOOL)shouldRequestComments { ++ return [[parameters_ objectForKey:@BREAKPAD_REQUEST_COMMENTS] ++ isEqualToString:@"YES"]; ++} ++ ++- (BOOL)shouldRequestEmail { ++ return [[parameters_ objectForKey:@BREAKPAD_REQUEST_EMAIL] ++ isEqualToString:@"YES"]; ++} ++ ++- (NSString*)shortDialogMessage { ++ NSString *displayName = [parameters_ objectForKey:@BREAKPAD_PRODUCT_DISPLAY]; ++ if (![displayName length]) ++ displayName = [parameters_ objectForKey:@BREAKPAD_PRODUCT]; ++ ++ if ([self isOnDemand]) { ++ return [NSString ++ stringWithFormat:NSLocalizedString(@"noCrashDialogHeader", @""), ++ displayName]; ++ } else { ++ return [NSString ++ stringWithFormat:NSLocalizedString(@"crashDialogHeader", @""), ++ displayName]; ++ } ++} ++ ++- (NSString*)explanatoryDialogText { ++ NSString *displayName = [parameters_ objectForKey:@BREAKPAD_PRODUCT_DISPLAY]; ++ if (![displayName length]) ++ displayName = [parameters_ objectForKey:@BREAKPAD_PRODUCT]; ++ ++ NSString *vendor = [parameters_ objectForKey:@BREAKPAD_VENDOR]; ++ if (![vendor length]) ++ vendor = @"unknown vendor"; ++ ++ if ([self isOnDemand]) { ++ return [NSString ++ stringWithFormat:NSLocalizedString(@"noCrashDialogMsg", @""), ++ vendor, displayName]; ++ } else { ++ return [NSString ++ stringWithFormat:NSLocalizedString(@"crashDialogMsg", @""), ++ vendor]; ++ } ++} ++ ++- (NSTimeInterval)messageTimeout { ++ // Get the timeout value for the notification. ++ NSTimeInterval timeout = [[parameters_ objectForKey:@BREAKPAD_CONFIRM_TIMEOUT] ++ floatValue]; ++ // Require a timeout of at least a minute (except 0, which means no timeout). ++ if (timeout > 0.001 && timeout < 60.0) { ++ timeout = 60.0; ++ } ++ return timeout; ++} ++ ++- (void)createServerParameterDictionaries { ++ serverDictionary_ = [[NSMutableDictionary alloc] init]; ++ socorroDictionary_ = [[NSMutableDictionary alloc] init]; ++ googleDictionary_ = [[NSMutableDictionary alloc] init]; ++ extraServerVars_ = [[NSMutableDictionary alloc] init]; ++ ++ [serverDictionary_ setObject:socorroDictionary_ forKey:kSocorroServerType]; ++ [serverDictionary_ setObject:googleDictionary_ forKey:kGoogleServerType]; ++ ++ [googleDictionary_ setObject:@"ptime" forKey:@BREAKPAD_PROCESS_UP_TIME]; ++ [googleDictionary_ setObject:@"email" forKey:@BREAKPAD_EMAIL]; ++ [googleDictionary_ setObject:@"comments" forKey:@BREAKPAD_COMMENTS]; ++ [googleDictionary_ setObject:@"prod" forKey:@BREAKPAD_PRODUCT]; ++ [googleDictionary_ setObject:@"ver" forKey:@BREAKPAD_VERSION]; ++ ++ [socorroDictionary_ setObject:@"Comments" forKey:@BREAKPAD_COMMENTS]; ++ [socorroDictionary_ setObject:@"CrashTime" ++ forKey:@BREAKPAD_PROCESS_CRASH_TIME]; ++ [socorroDictionary_ setObject:@"StartupTime" ++ forKey:@BREAKPAD_PROCESS_START_TIME]; ++ [socorroDictionary_ setObject:@"Version" ++ forKey:@BREAKPAD_VERSION]; ++ [socorroDictionary_ setObject:@"ProductName" ++ forKey:@BREAKPAD_PRODUCT]; ++ [socorroDictionary_ setObject:@"ProductName" ++ forKey:@BREAKPAD_PRODUCT]; ++} ++ ++- (NSMutableDictionary *)dictionaryForServerType:(NSString *)serverType { ++ if (serverType == nil || [serverType length] == 0) { ++ return [serverDictionary_ objectForKey:kDefaultServerType]; ++ } ++ return [serverDictionary_ objectForKey:serverType]; ++} ++ ++- (NSMutableDictionary *)urlParameterDictionary { ++ NSString *serverType = [parameters_ objectForKey:@BREAKPAD_SERVER_TYPE]; ++ return [self dictionaryForServerType:serverType]; ++ ++} ++ ++- (BOOL)populateServerDictionary:(NSMutableDictionary *)crashParameters { ++ NSDictionary *urlParameterNames = [self urlParameterDictionary]; ++ ++ id key; ++ NSEnumerator *enumerator = [parameters_ keyEnumerator]; ++ ++ while ((key = [enumerator nextObject])) { ++ // The key from parameters_ corresponds to a key in ++ // urlParameterNames. The value in parameters_ gets stored in ++ // crashParameters with a key that is the value in ++ // urlParameterNames. ++ ++ // For instance, if parameters_ has [PRODUCT_NAME => "FOOBAR"] and ++ // urlParameterNames has [PRODUCT_NAME => "pname"] the final HTTP ++ // URL parameter becomes [pname => "FOOBAR"]. ++ NSString *breakpadParameterName = (NSString *)key; ++ NSString *urlParameter = [urlParameterNames ++ objectForKey:breakpadParameterName]; ++ if (urlParameter) { ++ [crashParameters setObject:[parameters_ objectForKey:key] ++ forKey:urlParameter]; ++ } ++ } ++ ++ // Now, add the parameters that were added by the application. ++ enumerator = [extraServerVars_ keyEnumerator]; ++ ++ while ((key = [enumerator nextObject])) { ++ NSString *urlParameterName = (NSString *)key; ++ NSString *urlParameterValue = ++ [extraServerVars_ objectForKey:urlParameterName]; ++ [crashParameters setObject:urlParameterValue ++ forKey:urlParameterName]; ++ } ++ return YES; ++} ++ ++- (void)addServerParameter:(id)value forKey:(NSString *)key { ++ [extraServerVars_ setObject:value forKey:key]; ++} ++ ++//============================================================================= ++- (void)report { ++ NSURL *url = [NSURL URLWithString:[parameters_ objectForKey:@BREAKPAD_URL]]; ++ HTTPMultipartUpload *upload = [[HTTPMultipartUpload alloc] initWithURL:url]; ++ NSMutableDictionary *uploadParameters = [NSMutableDictionary dictionary]; ++ ++ if (![self populateServerDictionary:uploadParameters]) { ++ return; ++ } ++ ++ [upload setParameters:uploadParameters]; ++ ++ // Add minidump file ++ if (minidumpContents_) { ++ [upload addFileContents:minidumpContents_ name:@"upload_file_minidump"]; ++ ++ // Send it ++ NSError *error = nil; ++ NSData *data = [upload send:&error]; ++ NSString *result = [[NSString alloc] initWithData:data ++ encoding:NSUTF8StringEncoding]; ++ const char *reportID = "ERR"; ++ ++ if (error) { ++ fprintf(stderr, "Breakpad Reporter: Send Error: %s\n", ++ [[error description] UTF8String]); ++ } else { ++ NSCharacterSet *trimSet = [NSCharacterSet whitespaceAndNewlineCharacterSet]; ++ reportID = [[result stringByTrimmingCharactersInSet:trimSet] UTF8String]; ++ } ++ ++ // rename the minidump file according to the id returned from the server ++ NSString *minidumpDir = [parameters_ objectForKey:@kReporterMinidumpDirectoryKey]; ++ NSString *minidumpID = [parameters_ objectForKey:@kReporterMinidumpIDKey]; ++ ++ NSString *srcString = [NSString stringWithFormat:@"%@/%@.dmp", ++ minidumpDir, minidumpID]; ++ NSString *destString = [NSString stringWithFormat:@"%@/%s.dmp", ++ minidumpDir, reportID]; ++ ++ const char *src = [srcString fileSystemRepresentation]; ++ const char *dest = [destString fileSystemRepresentation]; ++ ++ if (rename(src, dest) == 0) { ++ GTMLoggerInfo(@"Breakpad Reporter: Renamed %s to %s after successful " \ ++ "upload",src, dest); ++ } ++ else { ++ // can't rename - don't worry - it's not important for users ++ GTMLoggerDebug(@"Breakpad Reporter: successful upload report ID = %s\n", ++ reportID ); ++ } ++ [result release]; ++ } ++ ++ if (logFileData_) { ++ HTTPMultipartUpload *logUpload = [[HTTPMultipartUpload alloc] initWithURL:url]; ++ ++ [uploadParameters setObject:@"log" forKey:@"type"]; ++ [logUpload setParameters:uploadParameters]; ++ [logUpload addFileContents:logFileData_ name:@"log"]; ++ ++ NSError *error = nil; ++ NSData *data = [logUpload send:&error]; ++ NSString *result = [[NSString alloc] initWithData:data ++ encoding:NSUTF8StringEncoding]; ++ [result release]; ++ [logUpload release]; ++ } ++ ++ [upload release]; ++} ++ ++//============================================================================= ++- (void)dealloc { ++ [parameters_ release]; ++ [minidumpContents_ release]; ++ [logFileData_ release]; ++ [googleDictionary_ release]; ++ [socorroDictionary_ release]; ++ [serverDictionary_ release]; ++ [extraServerVars_ release]; ++ [super dealloc]; ++} ++ ++- (void)awakeFromNib { ++ [emailEntryField_ setMaximumLength:kEmailMaxLength]; ++ [commentsEntryField_ setMaximumLength:kUserCommentsMaxLength]; ++} ++ ++@end ++ ++//============================================================================= ++@implementation LengthLimitingTextField ++ ++- (void) setMaximumLength:(unsigned int)maxLength { ++ maximumLength_ = maxLength; ++} ++ ++// This is the method we're overriding in NSTextField, which lets us ++// limit the user's input if it makes the string too long. ++- (BOOL) textView:(NSTextView *)textView ++shouldChangeTextInRange:(NSRange)affectedCharRange ++ replacementString:(NSString *)replacementString { ++ ++ // Sometimes the range comes in invalid, so reject if we can't ++ // figure out if the replacement text is too long. ++ if (affectedCharRange.location == NSNotFound) { ++ return NO; ++ } ++ // Figure out what the new string length would be, taking into ++ // account user selections. ++ int newStringLength = ++ [[textView string] length] - affectedCharRange.length + ++ [replacementString length]; ++ if (newStringLength > maximumLength_) { ++ return NO; ++ } else { ++ return YES; ++ } ++} ++ ++// Cut, copy, and paste have to be caught specifically since there is no menu. ++- (BOOL)performKeyEquivalent:(NSEvent*)event { ++ // Only handle the key equivalent if |self| is the text field with focus. ++ NSText* fieldEditor = [self currentEditor]; ++ if (fieldEditor != nil) { ++ // Check for a single "Command" modifier ++ unsigned int modifiers = [event modifierFlags]; ++ modifiers &= NSDeviceIndependentModifierFlagsMask; ++ if (modifiers == NSCommandKeyMask) { ++ // Now, check for Select All, Cut, Copy, or Paste key equivalents. ++ NSString* characters = [event characters]; ++ // Select All is Command-A. ++ if ([characters isEqualToString:@"a"]) { ++ [fieldEditor selectAll:self]; ++ return YES; ++ // Cut is Command-X. ++ } else if ([characters isEqualToString:@"x"]) { ++ [fieldEditor cut:self]; ++ return YES; ++ // Copy is Command-C. ++ } else if ([characters isEqualToString:@"c"]) { ++ [fieldEditor copy:self]; ++ return YES; ++ // Paste is Command-V. ++ } else if ([characters isEqualToString:@"v"]) { ++ [fieldEditor paste:self]; ++ return YES; ++ } ++ } ++ } ++ // Let the super class handle the rest (e.g. Command-Period will cancel). ++ return [super performKeyEquivalent:event]; ++} ++ ++@end ++ ++//============================================================================= ++int main(int argc, const char *argv[]) { ++ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; ++#if DEBUG ++ // Log to stderr in debug builds. ++ [GTMLogger setSharedLogger:[GTMLogger standardLoggerWithStderr]]; ++#endif ++ GTMLoggerDebug(@"Reporter Launched, argc=%d", argc); ++ // The expectation is that there will be one argument which is the path ++ // to the configuration file ++ if (argc != 2) { ++ exit(1); ++ } ++ ++ // Open the file before (potentially) switching to console user ++ int configFile = open(argv[1], O_RDONLY, 0600); ++ ++ if (configFile == -1) { ++ GTMLoggerDebug(@"Couldn't open config file %s - %s", ++ argv[1], ++ strerror(errno)); ++ } ++ ++ // we want to avoid a build-up of old config files even if they ++ // have been incorrectly written by the framework ++ unlink(argv[1]); ++ ++ if (configFile == -1) { ++ GTMLoggerDebug(@"Couldn't unlink config file %s - %s", ++ argv[1], ++ strerror(errno)); ++ exit(1); ++ } ++ ++ Reporter *reporter = [[Reporter alloc] initWithConfigurationFD:configFile]; ++ ++ // Gather the configuration data ++ if (![reporter readConfigurationData]) { ++ GTMLoggerDebug(@"reporter readConfigurationData failed"); ++ exit(1); ++ } ++ ++ // Read the minidump into memory before we (potentially) switch from the ++ // root user ++ [reporter readMinidumpData]; ++ ++ [reporter readLogFileData]; ++ ++ // only submit a report if we have not recently crashed in the past ++ BOOL shouldSubmitReport = [reporter reportIntervalElapsed]; ++ BOOL okayToSend = NO; ++ ++ // ask user if we should send ++ if (shouldSubmitReport) { ++ if ([reporter shouldSubmitSilently]) { ++ GTMLoggerDebug(@"Skipping confirmation and sending report"); ++ okayToSend = YES; ++ } else { ++ okayToSend = [reporter askUserPermissionToSend]; ++ } ++ } ++ ++ // If we're running as root, switch over to nobody ++ if (getuid() == 0 || geteuid() == 0) { ++ struct passwd *pw = getpwnam("nobody"); ++ ++ // If we can't get a non-root uid, don't send the report ++ if (!pw) { ++ GTMLoggerDebug(@"!pw - %s", strerror(errno)); ++ exit(0); ++ } ++ ++ if (setgid(pw->pw_gid) == -1) { ++ GTMLoggerDebug(@"setgid(pw->pw_gid) == -1 - %s", strerror(errno)); ++ exit(0); ++ } ++ ++ if (setuid(pw->pw_uid) == -1) { ++ GTMLoggerDebug(@"setuid(pw->pw_uid) == -1 - %s", strerror(errno)); ++ exit(0); ++ } ++ } ++ else { ++ GTMLoggerDebug(@"getuid() !=0 || geteuid() != 0"); ++ } ++ ++ if (okayToSend && shouldSubmitReport) { ++ GTMLoggerDebug(@"Sending Report"); ++ [reporter report]; ++ GTMLoggerDebug(@"Report Sent!"); ++ } else { ++ GTMLoggerDebug(@"Not sending crash report okayToSend=%d, "\ ++ "shouldSubmitReport=%d", okayToSend, shouldSubmitReport); ++ } ++ ++ GTMLoggerDebug(@"Exiting with no errors"); ++ // Cleanup ++ [reporter release]; ++ [pool release]; ++ return 0; ++} +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/sender/goArrow.png b/toolkit/crashreporter/google-breakpad/src/client/mac/sender/goArrow.png +new file mode 100644 +index 0000000000000000000000000000000000000000..f318a56711d43d1b8925f1c26e709da0872dd607 +GIT binary patch +literal 3591 +zc$@(T4*2njP)4Tx0C=30*LgIQeH#bx>z*0LGR7D?VPuzmU$SqBvSv$3c7~adBxOm;nk5u1 +zDB2V)Br00S5|TnfQQ1Stl4agML=Xsy={{Fh|>zw<(fA@XP=leSs04t9>l}bhd +zKwwa4u&tRP$;sJ;gzW+humAy6K+D}Dglb@IZ3+Ll<~soa0O*i)r&7smFS9a!<~Td} +zo7lc+P4bue=lcKv03Yn+>;izu004*2daVxt9Q)U6djQ}#6iN*RKzsp!!^79z699<> +z0GVKWTO$DE8UWyZ*6T_D!0%tL8vp#dr +zj^90z2LN2|0EH>Pd$YEH006?(7UHd}1ONaC&JcjEpGKP%2f$_ktftdw%Y`)B>SX|Q +zFF-BX<6v;uum6Q0Edc*^z5dO=78(IS0U)ACF)9KbiHW2;MjwrhWjM}g%vi^ClKB)a +zfh8GVLGWcuC#JJ!aGc@H;>zOA;i==J@aJvH6SyGQKsqQ~xcRb3o7fTYVu^OCW70Rb +zbjrrc-IDK7JgIb7`J-yGT7~+6W~x?|_K;4d?i0N+gKWcRMw2GFruAks=9jiNSD$}y_Ho~*{Wy<@o?pDadJp*w`;PdH +z25^#}27U{gq)bt#4}1@v37HF>JNP4P{?J1B;^C!;pGQ_ASB|bmNkzYlMUJE5&?hkQ +zbSLRgVG|e<8IzcjnNx77ET{2ltm%XdwoKv~_AHKU&K$0@+~;_5dGq+r^IzC>QQ(qb +zzEA%ydiZ{`sR2E`IgLW*;4s3g*%FO74IqCS1DJmP^*}K +z5LT)FP@_t#TKmz~$6KH1JXx!Ws?~d{|IFaI;R~ZWOkG^P$xG7)vqtkK^Jb>zq*oR# +zmaRM6@NK7GTesW1vF#vsWW2R|XWzN2i>oWA+wr|qkIM(X4|%<=eXjj`J_>%k^vP{t +z-=Oed;phEdJidAki47GGdyn{x`i@DB-5B?u2>3>xl%2di6*NuxPMuMlxjP#?7xE)? +zUUj}=A#5>x>G03P%Ua9TD@Rr%*L2pN&}aaN2nvsyMmJ+_(q+;|Vtp9w8I71!m?dx$ +zEIfE_RvrQm8z)hmU6MnC(~@g1cL+}^Zz*3h|EK`Fpqh{m>8$We5kyo+?11b +zY4Vn8S+tyie7eGbl9Y11N|&0nI#r`ii(5N<>nmL@J&OJ_Ls6q6#_gtpX5rf&n=e@? +zT6*os+SzW6w=uH~w=1%L>%iow?{vWVf=m7GsXan_t=uB^6}s2$ANAz)((`umIp&-1 +zSL@#wuoTE1w1r|!^*s<7oEB0TT7Ix0?8Bk4@c9Vz5w=LuQJG_^QTovqF;=m=kME1~ +zIzf&PJsEr|Iw3mocv3=gMoLm@?&))BIqB&c=QA_TWM`etzLsca&P99o_}=V +z(Z#w;ukzaqItn{3cU<{U^rd+C>fp7n*QaiLzd2Phd28nOROxux#GT>01NR2+_msC+ +zG(M=UeDJWe>U?#^qv*$hPj=T>)NXw${fzi*>G`J@O?CI{GhYTb*fpv(@i)<$dtTjd +zNo;j#6KNZIeXsrK8GPQ{d%sG2ofxVbjv3iL$~oFMc4eGAp*pelt#LAAYWKA0^u+gjGm*1qbHuss +zA4T(&1)Gqax7S=qk)nIz74?`WWm922+MQ +z#(1Wa%!#<|xMr3VdabCx%kFONTO(|G|`fj+@Y +zLiwZu;eyQtB9}$4h!u$!OI($_CUsrfPkL<24VezNd0uwL+~z +zy+R{gV^On8t4h0i>m!}Vy2o_a^lJ2L4W1f4GkR_uXM!=QGp#p!xvjyxaeI?Rk|oaa +z)sB{(tyXQ;X*L9#cH1|09rkZ`bvk4_ayfQ6bvwUz>Dis<%J15{r*H2^w@>>%xfkpg +z-aqK^+4GCnSMOpU@%04p9}BoimLX64SBlL3l_HggH4ZOD{5-N8xpH*%*jf}V24Ycv +zB?!kmb22Ukm&$UQHI0zY_E(m0<#3+lX!OI?3M2bX<#jlEQ +zq)Ca)E!o?0e`JYrxk`oV1NBPvhZ;nLxR|Cl20^pDfU{?qbzXd?T4S?$!fHez%y(XaO1OcT(1!TL< +z#`ysV5I_Lrz!01v1k#`k77-F+frKO1kXB?E#fmaR#h@OeR?s@=7<4^)1tW}c#uQ_I +z(3#Smpev=DqBo;2pdZ3=VqLM18L$kR3~>zOj9QEo##$y>rf8;0W;}BY^LrczE(kZm +zV#0EqWdQGvf5wVt^=6$Q*buS_t858uGej+75xY8j5&IN}8^;2tA7=&E7Ot1v-aJ^I +z8@yt?hj{1sF7TW2&u+>W5EY0NLVHIf;O&8lG&L=)7aZ}Pr +z^176vG@JCmmU}WMWnJZz<#F=E3NI83m131WRm@an)Y#Ql)Q2>3H1V3XT4mY=ThHj6 +z(v8wPq<_GGZ0Kj?YwT+hU>al=y6uR0-1gHJd6w6ARPJoF>b3rEi?tK9*Vtv}Ky^%Y +zy6ybhW!9BvkM3S?x3qoL?js)Do@QQ$y-WOf{H+5L$#p>}iUBp|!1ECLP>X{Z;i88r +z5sxC7j=CHxiK4~W$DvNR#y>d4o^T+sJtZr3Da|dtK2!coZcfPA&$)Jabr)~vixphB +z%w0^lntC07_U6PE+1B>gVIB4F +zs9pTs4ZY%h-5(PN^uCk~d5#E;_Iz`g;+pQ7$(?gsm{=-bj-v6ZGP(uBg0aG6VLs52==|u)=oaaX=ugwX +z$BJPOVxKb*89W&(8JQVf8E-RTnD#Q=XJ%sdV6MS&;;6V57HO6gmI=HizLb@PmBQLd +z&?j7B!?T64eIS|=@352DGuYQSLO8y0`g4wPk-28LL%HX9B6tzrWIjH=8~mF5^_v_v +zjS55y@(NZ6*$9o1;)TV98#V`taEm+<^$^2}Jrxg<5R!N!nIL5-wJKe`B~nI5Wk8`;^)Uu$gBio`MpMS) +zCPSvPX5-s_Y)4seSaR=B+^K72Wo>H{V0+ju&;IVNR}LQ>SDZOqQSzuG!IB|ip^aezheE=eB1Dd)MvfhGj%tWe +zi!F*Ho=81OJe8fula!aDn%bJ?mHsm`B}+Z~>)DIB{^xgHl**?on7I6`sQl`=>+v@| +zZn>74-qErt{2r<{0J$To7)A#S`z2|IF&mIzb2_tgg-J%ZX64oX@8mC$vgMUv$Y^1SpLhh&AQ}Yj>Du3|1|tt@Grk_G;6iWe%t*m +z_n+PVFSR}cemwrxe^(pU^LMwgH~y5Htn^!MHvNX(3z{2xuVilcEg^0QzE`1 +zWm}C~U0Az9OQO*L*5@Sv0AMnrkSW0=OC#fd8Sehy6-Yj~@eTw4a9%;X>;QlW0Gq%F +zC_n}Z1Oo{y!3c~2)@L;U0D1zzc}D<%n#Cj0e}8VMS9mA@fDwgyIM~m}Hq=-Ed<7005&&L_t(2k&V(l3c^4ThT&%u +z5K@VVtq{lwwDJaC!ZwHUPJI*^S&3CsIs{85dETMz%GtU8NSrt1^i<=yGOtq)$vhKxa9CN&5QIRO>nh$t{j`-Kt_y7$#9ND ++ ++#import ++ ++enum BreakpadForkBehavior { ++ DONOTHING = 0, ++ UNINSTALL, ++ RESETEXCEPTIONPORT ++}; ++ ++enum BreakpadForkTestCrashPoint { ++ DURINGLAUNCH = 5, ++ AFTERLAUNCH = 6, ++ BETWEENFORKEXEC = 7 ++}; ++ ++@interface Controller : NSObject { ++ IBOutlet NSWindow *window_; ++ IBOutlet NSWindow *forkTestOptions_; ++ ++ BreakpadRef breakpad_; ++ ++ enum BreakpadForkBehavior bpForkOption; ++ ++ BOOL useVFork; ++ enum BreakpadForkTestCrashPoint progCrashPoint; ++} ++ ++- (IBAction)crash:(id)sender; ++- (IBAction)forkTestOptions:(id)sender; ++- (IBAction)forkTestGo:(id)sender; ++- (IBAction)showForkTestWindow:(id) sender; ++- (void)generateReportWithoutCrash:(id)sender; ++- (void)awakeFromNib; ++ ++@end +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/Controller.m b/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/Controller.m +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/Controller.m +@@ -0,0 +1,260 @@ ++// 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 ++ ++#import "Controller.h" ++#import "TestClass.h" ++#include ++#include ++ ++@implementation Controller ++ ++- (void)causeCrash { ++ float *aPtr = nil; ++ NSLog(@"Crash!"); ++ NSLog(@"Bad programmer: %f", *aPtr); ++} ++ ++- (void)generateReportWithoutCrash:(id)sender { ++ BreakpadGenerateAndSendReport(breakpad_); ++} ++ ++- (IBAction)showForkTestWindow:(id) sender { ++ [forkTestOptions_ setIsVisible:YES]; ++} ++ ++- (IBAction)forkTestOptions:(id)sender { ++ int tag = [[sender selectedCell] tag]; ++ NSLog(@"sender tag: %d", tag); ++ if (tag <= 2) { ++ bpForkOption = tag; ++ } ++ ++ if (tag == 3) { ++ useVFork = NO; ++ } ++ ++ if (tag == 4) { ++ useVFork = YES; ++ } ++ ++ if (tag >= 5 && tag <= 7) { ++ progCrashPoint = tag; ++ } ++ ++} ++ ++- (IBAction)forkTestGo:(id)sender { ++ ++ NSString *resourcePath = [[NSBundle bundleForClass: ++ [self class]] resourcePath]; ++ NSString *execProgname; ++ if (progCrashPoint == DURINGLAUNCH) { ++ execProgname = [resourcePath stringByAppendingString:@"/crashduringload"]; ++ } else if (progCrashPoint == AFTERLAUNCH) { ++ execProgname = [resourcePath stringByAppendingString:@"/crashInMain"]; ++ } ++ ++ const char *progName = NULL; ++ if (progCrashPoint != BETWEENFORKEXEC) { ++ progName = [execProgname UTF8String]; ++ } ++ ++ int pid; ++ ++ if (bpForkOption == UNINSTALL) { ++ BreakpadRelease(breakpad_); ++ } ++ ++ if (useVFork) { ++ pid = vfork(); ++ } else { ++ pid = fork(); ++ } ++ ++ if (pid == 0) { ++ sleep(3); ++ NSLog(@"Child continuing"); ++ FILE *fd = fopen("/tmp/childlog.txt","wt"); ++ kern_return_t kr; ++ if (bpForkOption == RESETEXCEPTIONPORT) { ++ kr = task_set_exception_ports(mach_task_self(), ++ EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION | ++ EXC_MASK_ARITHMETIC | EXC_MASK_BREAKPOINT, ++ MACH_PORT_NULL, ++ EXCEPTION_DEFAULT, ++ THREAD_STATE_NONE); ++ fprintf(fd,"task_set_exception_ports returned %d\n", kr); ++ } ++ ++ if (progCrashPoint == BETWEENFORKEXEC) { ++ fprintf(fd,"crashing post-fork\n"); ++ int *a = NULL; ++ printf("%d\n",*a++); ++ } ++ ++ fprintf(fd,"about to call exec with %s\n", progName); ++ fclose(fd); ++ int i = execl(progName, progName, NULL); ++ fprintf(fd, "exec returned! %d\n", i); ++ fclose(fd); ++ } ++} ++ ++- (IBAction)crash:(id)sender { ++ int tag = [sender tag]; ++ ++ if (tag == 1) { ++ [NSObject cancelPreviousPerformRequestsWithTarget:self]; ++ [self performSelector:@selector(causeCrash) withObject:nil afterDelay:10]; ++ [sender setState:NSOnState]; ++ return; ++ } ++ ++ if (tag == 2 && breakpad_) { ++ BreakpadRelease(breakpad_); ++ breakpad_ = NULL; ++ return; ++ } ++ ++ [self causeCrash]; ++} ++ ++- (void)anotherThread { ++ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; ++ TestClass *tc = [[TestClass alloc] init]; ++ ++ [tc wait]; ++ ++ [pool release]; ++} ++ ++- (void)awakeFromNib { ++ NSBundle *bundle = [NSBundle mainBundle]; ++ NSDictionary *info = [bundle infoDictionary]; ++ ++ ++ breakpad_ = BreakpadCreate(info); ++ ++ // Do some unit tests with keys ++ // first a series of bogus values ++ BreakpadSetKeyValue(breakpad_, nil, @"bad2"); ++ BreakpadSetKeyValue(nil, @"bad3", @"bad3"); ++ ++ // Now some good ones ++ BreakpadSetKeyValue(breakpad_,@"key1", @"value1"); ++ BreakpadSetKeyValue(breakpad_,@"key2", @"value2"); ++ BreakpadSetKeyValue(breakpad_,@"key3", @"value3"); ++ ++ // Look for a bogus one that we didn't try to set ++ NSString *test = BreakpadKeyValue(breakpad_, @"bad4"); ++ if (test) { ++ NSLog(@"Bad BreakpadKeyValue (bad4)"); ++ } ++ ++ // Look for a bogus one we did try to set ++ test = BreakpadKeyValue(breakpad_, @"bad1"); ++ if (test) { ++ NSLog(@"Bad BreakpadKeyValue (bad1)"); ++ } ++ ++ // Test some bad args for BreakpadKeyValue ++ test = BreakpadKeyValue(nil, @"bad5"); ++ if (test) { ++ NSLog(@"Bad BreakpadKeyValue (bad5)"); ++ } ++ ++ test = BreakpadKeyValue(breakpad_, nil); ++ if (test) { ++ NSLog(@"Bad BreakpadKeyValue (nil)"); ++ } ++ ++ // Find some we did set ++ test = BreakpadKeyValue(breakpad_, @"key1"); ++ if (![test isEqualToString:@"value1"]) { ++ NSLog(@"Can't find BreakpadKeyValue (key1)"); ++ } ++ test = BreakpadKeyValue(breakpad_, @"key2"); ++ if (![test isEqualToString:@"value2"]) { ++ NSLog(@"Can't find BreakpadKeyValue (key2)"); ++ } ++ test = BreakpadKeyValue(breakpad_, @"key3"); ++ if (![test isEqualToString:@"value3"]) { ++ NSLog(@"Can't find BreakpadKeyValue (key3)"); ++ } ++ ++ // Bad args for BreakpadRemoveKeyValue ++ BreakpadRemoveKeyValue(nil, @"bad6"); ++ BreakpadRemoveKeyValue(breakpad_, nil); ++ ++ // Remove one that is valid ++ BreakpadRemoveKeyValue(breakpad_, @"key3"); ++ ++ // Try and find it ++ test = BreakpadKeyValue(breakpad_, @"key3"); ++ if (test) { ++ NSLog(@"Shouldn't find BreakpadKeyValue (key3)"); ++ } ++ ++ // Try and remove it again ++ BreakpadRemoveKeyValue(breakpad_, @"key3"); ++ ++ // Try removal by setting to nil ++ BreakpadSetKeyValue(breakpad_,@"key2", nil); ++ // Try and find it ++ test = BreakpadKeyValue(breakpad_, @"key2"); ++ if (test) { ++ NSLog(@"Shouldn't find BreakpadKeyValue (key2)"); ++ } ++ ++ BreakpadAddUploadParameter(breakpad_, ++ @"MeaningOfLife", ++ @"42"); ++ [NSThread detachNewThreadSelector:@selector(anotherThread) ++ toTarget:self withObject:nil]; ++ ++ NSUserDefaults *args = [NSUserDefaults standardUserDefaults]; ++ ++ // If the user specified autocrash on the command line, toggle ++ // Breakpad to not confirm and crash immediately. This is for ++ // automated testing. ++ if ([args boolForKey:@"autocrash"]) { ++ BreakpadSetKeyValue(breakpad_, ++ @BREAKPAD_SKIP_CONFIRM, ++ @"YES"); ++ [self causeCrash]; ++ } ++ ++ progCrashPoint = DURINGLAUNCH; ++ [window_ center]; ++ [window_ makeKeyAndOrderFront:self]; ++} ++ ++@end +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/English.lproj/InfoPlist.strings b/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/English.lproj/InfoPlist.strings +new file mode 100644 +index 0000000000000000000000000000000000000000..b8c6c6bf0ba1a55cea7e4656822a4ee5d65546b8 +GIT binary patch +literal 192 +zc$_Vb%?`m(5Ju0sPtjO5g4kGyl?4*9;0dZ)1Z~qI;f=f`jvJZG&;90`bKf8OB*ZMK +z$VfSJ?QU;qRVqq*Y%i<}UxjmzI`~_zswdr#;7Vjh#)=JdZd~M+tlg(_Q?_2^ +kOeNG_G!ph40%Kx!cv)v|EA^kV`~Ncw(~yBN(l;jh0-VJm6#xJL + +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/English.lproj/MainMenu.nib/classes.nib b/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/English.lproj/MainMenu.nib/classes.nib +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/English.lproj/MainMenu.nib/classes.nib +@@ -0,0 +1,47 @@ ++ ++ ++ ++ ++ IBClasses ++ ++ ++ ACTIONS ++ ++ crash ++ id ++ forkTestGo ++ id ++ forkTestOptions ++ id ++ generateReportWithoutCrash ++ id ++ showForkTestWindow ++ id ++ ++ CLASS ++ Controller ++ LANGUAGE ++ ObjC ++ OUTLETS ++ ++ forkTestOptions_ ++ NSWindow ++ window_ ++ NSWindow ++ ++ SUPERCLASS ++ NSObject ++ ++ ++ CLASS ++ FirstResponder ++ LANGUAGE ++ ObjC ++ SUPERCLASS ++ NSObject ++ ++ ++ IBVersion ++ 1 ++ ++ +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/English.lproj/MainMenu.nib/info.nib b/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/English.lproj/MainMenu.nib/info.nib +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/English.lproj/MainMenu.nib/info.nib +@@ -0,0 +1,22 @@ ++ ++ ++ ++ ++ IBFramework Version ++ 670 ++ IBLastKnownRelativeProjectPath ++ ../GoogleBreakpadTest.xcodeproj ++ IBOldestOS ++ 5 ++ IBOpenObjects ++ ++ 221 ++ 29 ++ 2 ++ ++ IBSystem Version ++ 9F33 ++ targetFramework ++ IBCocoaFramework ++ ++ +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/English.lproj/MainMenu.nib/keyedobjects.nib b/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/English.lproj/MainMenu.nib/keyedobjects.nib +new file mode 100644 +index 0000000000000000000000000000000000000000..1c6baaf7b83cf03445585669d076ca65adf51031 +GIT binary patch +literal 34374 +zc%1CL1y~zP8!$SvyUFgN8>}s*C3UQnLWQhA9D#+}&&2tD+i^L_W;=YRg^`O+qt%#OS^ukFr|n3bNElk4Ge9zZ|<5>P+_q<{q` +z?Q7?2vvbmPnX1~kx~vYhHQ7n2X{f4wZCzqFZBlNI6@WwLo&hvqI)$`y*HqB7w?R3qesGvPvb +z5se6M!iMlAS`w{@Kq7<)ClrK|h$T7`3FvAvkxFC`Sws&a8#W?xh+c$13?K#)Lx|zT +zC}Jiti&#LcAXX9^h>fWAHewgC4~=w?I6<65zt0jEiEF6$O|kba;sNmx)jlI$5$}ml +z#AlKrS<-^EBP)@Pq@3^~>yXZ*JJFJCh})B%q&KSbC0mk##3wQYn3ADnI2l1kk_s}0 +zj3qmeT}Ta?NG6dfWG0zS=8(B$9@&c=Kn^5FlB38!$noTKat1k*oJGzfmy*lK<>U%- +z4Y`@zLT)8@k$;l=$fM*j@;F&UUL-G(m&q&SP4XW3n0!sXA-|Ac$?p`TSjvR5qO2)f +zstP5iYEyNnx>P;NmGY##s791GNEGmcUji3&v +z`j8P+U#cH9kQzaaq()I=sVUS{Y8o}0T0||TmQYKnmDC1mBejXzOzog{Q-`R-)Dh|g +zb&fhuU7#*fSE)PHUFsfnpL$HaqFz&PsJGNd>Ie0cDwY6A2T7bHRgxp=CFw2cBN;3i +zD;XylFPS2lCYdRjC7B~xDp@C4FWDy9F4-YDAUQ5MAvq~IFS#JOD7huMBY7-&B6%r! +zCHW*7Ck0X#eVRzkr1sJp(wfp*QaALwzO;eVOWH`7Bo`XGIXK1?5> +zkJ88Jt_N#CMx(|72*^ga4M +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 +zoUkEm2|H0C3@S0NJl_p1*E9r6*OE +zq*QsLHc6A0qm}Er$}`eXz>BUV_e@VqM6eQ72z#PxM}zw>1_bFmj>%&*$!R*h$rJ4% +zQJrv{PdH-N+`7aTihcAklIZXdH4NyLLk=rHq81#1kt6DesErj-bHWimQskO+aUg`B +z4q=xm;wDYt9DYSg(-m>ffYSx683|Xyji^t!6AcItq9NfKZ$LxjB+g@KvqXksf#7@d +zSyu8rXg&1cd$#Z05bJF3Qf@Wj3+E9{dC`EkC7Kb<`GWaG3&Mxb;jtG%_!0g@0OB}u +zjza#9HgD}-hDow7bTOujEDfpJ&{xffBzzXdH*Lb+}=kflZ~ubuijBtSJ&5# +z8#jJkt5&U}4h{|@S(f$r7h_6nZEf?SqoZ#xUAnaR+O=!NU%q@P{`&Q6@ztwWi32d~zrXnV_wU6Oz0RLMU)-lppHFq_)ahBlSR}$D +zuv@oo4>xVvRQ%$_i{hU@f0n*~{PR;^l9 +zeCW`j;%CpE6~BG^w)n$`590gXyLaL@u6z0NW%1dwXN%XYSyLPu8afa6H5#W;mQpDtdxa^+{-7nI3```Wc@ +zzh1m}QEYer{{7-7Po9YQJ%9eZw2a5Y*YG@ez6~2Te8qi@$C)*2)^mIv&x>)wbinxF +z_nS9w#BW@OuVEPP+__UcZQ8Wwzl>8mGc&UYkAdgLG{H3e`0=ACJ6MJ=pYU%yCWZ~e +z)xCT7A|t#+I=j2OPuRC_-&c$W<`3>`%zOO)_U)U*nS*!HCYlz`NE72?=M> +zJU>gusOW{|6XEp}x5a&a;X7#t0@7`*@yzjpXTjiQM2auEW<1V>tfZ8Z*p+;VnS#Iq1E?@SbC+Yi(%ryD^M$G%>WT +zZQ!fBpYrVIBVoB~ +z&u`MIihrQAMK+ocLG6ahHYxgY04^u$%PL$h$j!<{rg)eQ)dnKrP?0x;p7d0Fl*PvcIhE +zU5rR8Xjhce)yq??f@ZA{e{L2RzpD!XJsyA`ir0R^*=aq`d5W1HB+T +z3BW)7*5hn=kx-O2N+P9M6H{{wOU}yL#;#Ij`>GDr9pyD^)vjC5$=TJdeglt&o?eZc +zH1%%Q!pGMypk=GpZ32UWLqfyCBcq}fF-ldex*bBKV|=I137W*DWNp`!)U9XZ3R<2sLdd=E(>(_7CxM}m2ty{Nk-?4M&u0MD0*}He&{sRXO +z9XfpE=&@tRPn2kq*rfA^b%`v^7v7q8usowCM61V(6)1Acuh-hs~1BB~fKvbCqV4*@>KZJg5 +z0Vyy?Hl-G52m(M1vU0t_1h4`e1b0C(bcFs;0|&$9D2)D0$cZqbfLKJFB?;1t)RI%l +zQuF3&6IAEey7{g?a7Z?kD*bK16x?HjwHm8w_T +zQ#r8;Rb{2U%Kl5$i4N`#r>bRFx2e9vF-dMN-&rHIW|f*nwT9PjS^G4Z2;bztVkZgDxI^4XZZ%?s?5?ccZzDhcwA<8t)z6tXXr{7FB&1U&{A` +z-!uP50e4znZgsx(g*NBfUJtw$bU*k_CSpk5O!ixuKH8Hc_XyTh#t` +zT#b$y@mo55Nr>t)SMxq8EO}{HNlHTMfo=`DPtRa73w5u1WM)6l&B*&u(7z|sYkVJ< +zz6bkvZmE+a0F8Zo-rn0w=9OlUvJV)BWp!>7m0tUl|`oR#zXFNj;z +zV2Sn8Z_DqkJidC*+O6w1Z(O~3Ow#cavM9O63ZKqin2$fr~zsy}s-`XH$$ +z$&wt9R+Z*Ti|G1vJUxnj$;2>QSvjj>N3b7Fl1(m{2AK+`JIy@JR+!f{pKnpaVxDDf +z%Vk^xZY%dg)>>9%)ye9mHE&~Uv%dFy&viK&HsJC%a%`DKW_7+?eoAlL7#$)!)(H9 +zM0i97M8!mRjTx_8p*k3QM_t^$dI$eFO~=9UD>|L+{7n;+*gt7a^6joxDM6`y(l&N` +zk&&D^Uw5ZRO%zrx%YBvKq@aH<+ulii*7qa($MVaB;(_WxYlg7H_Km19QW$k_bkLZU +zbNzx*QKq0 +zyRqM9({0Y%x9^PDb!T_MUWt05n_- +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 +z$&cWNtCc--a%F+YwU#xD||V_cwrj&UJB +zR@}aTA7O0RRNTJMxCwrU(WC4k#yNc90%9C7kC>18PvB?#&9;VLNWK)2{Jx&(r6eDZ +zCLf)^$-}jpe62h&TdV1wrAd|}`etfN@_;yx_)pIgt~NYNxK^A)e3lT}qgf`QStjb| +zs1ci)mYJ5DhUB`JR^F;)Dx*otry4gC9>f+g)i{}-QkH7mfm4k;`KcwT#@+f<<6b_8 +zpH`A;JizDk)Bg$N!v>I#8i9NbfjkR=JW~&H3|fTg@?1?$_kB#6Y$my +zc|lrksvPh1l$TzRix<)|b&>B;h}Y#rXsSb`(Y!j{Le2;q2I#Bnx1rwqsQ7{?3z +z+!7ow>v6n_aGY0y;|+x4{0@5g@bv6^?JwAtKIKl_F<^QRVLH~p{-p@ZCA>$h_)KYe +zpdKTjo`^s#@EpvW68kIUfUf!k74{6F5&L@75=BW3E|6un9X^kx31HJ15?vy$| +z>(S(^)%x3{|KKf4B{2c7us;=>2ylo@`WsiQla^@#Vp3j=*Ul +zg0qL;TLz9l1}A{uR{~CJJveOK!`7;Lsc?=L5Cw!M2J=81l5 +z!$yrz(Yq;PUIJ&|+snO?ho`rv*44`!akT7*VUQ>?dOjI#xMOeFmZia6eROxr7+lYJ6qw;dowYh)YiB7g7+w+z9Q~a3F&Y;218g2W1 +z&wtQw`)wbAg1HP7$tf}r^9|d7ah)bNFB?_=vJ3d00aq>mqWpyih6}5Ixj;TN97*t% +z_rCHMVZSPh`!n)+$)N-&*u(<=jsI>C_>w~aJiN)6LO{$itBzp<4cUKS%vc(PTx$?S-EOl0P +zn(>x-${DW?0h;}0c~JGyjP9jN(;m-hE!qX`JXFwN`(ZVZJAQ%9RyezbKMqkJxH6W#hFKWwzf3Uf%l+`4}>Lf +zRZ|StW5mnt^jAeu`DN9AGA!;?qs0vmP+bt}iTnuxI$+%ET(4+DHA`LwK+lTCor}bNo-x=+ +zTpE_bt;kFJ^^^idkGNcIb_PCi#~A$O)CvrKBLOz8Xqwe%nl;8M0ttN+gNlf4ovzE# +zDhfIo437A-ywIWWKreLb_!nh!?xOz0b2b;CPepU?H9FlwT+uBIBnv>!YxyND*W}1M +z=|B@t)8n(Nl6zEgGtNG)8*xe&BPvfxt9TOj5>}1@DpImiU2r;kS;RjnZE!7 +z^h}G>n{RxEh(Z&WBmO{Tqp>ejSMb=a1sGV-*w@k6H;l(_Bfz$X6BqCu0!31668bV4 +z@FDdG4;U=Ku!;tJiUxdU%%KngIR|4v?fIx +zuIZ^W_Nb}%)CW9SgaD%}n(Q+DEe#SBd!se+@w^wc=m!qoxsUN +z53XfSbh;)jQ-!>*=7!KlLhuD^I5qM}#)6X)DflR1D1l%lrV=xWIkjA32~|jMwL|gh +zNr^2rlNg881rbrLQBR}FGii#gd{HR@Ei=-vx2$#XG)I%^D^o92&A#e*gh!jtu +zBodLM5}5&8QI{num@82umu?>Nnr`uO0jhYk@KdOSl%D$*i$Ho +zekZ_8w1W9@NN4de0_?!I5b)VZ*?bjbBLz5Bfb9i1l&{U-7ZnJSN2K{VK0||CmEk``33VFB=EdDQQwF<;hk_U!M@{N_CT7d2J&C^9s1s|QK +z6~8k<68g+R!teI4VJi;+>LwXd9t6oy1Vp4{gz*t&k}=|eQHdGa%)Is`rzT<85bfhi +zPLdH|$M#Bm@K%yGr*n?JvC&yzhBJ&L6D5-*lSSvNlK>M0*x6t!C1de{O?nQ^;0xy_ +zaFz-9SP=by_#`$lDwoU#L*^sY{QrB5|C?^{3Hq}dwHT0!*oOK`HW{ldtpK|kR8}fd +zR2q;ks;rhGzm)$H3_MgB7-*=9rapwGK5RU7ngF{Q+N+eBe61pp6! +zbW@_0qsaW1K#Fl&8Le6v7z%HdG4vi^xR5*vyGm?fD-;Q$m7K{p@0?JQiV@jsEF{k) +z&m}KJA;}ToYysxBk3d>hF9iA#-yly)(h{k}rbu17i#h_SmSLg-n*JNH1}DMkGO?Ca +zlN2Msk=(}UMHneD0p|avFXbpDjr&R&Ofp)4g+`rwsshu}wFdm9Y$^Uy3#4)+=8{Gd +zKZz+a0cH{gsq&i03|0~~Y#&kArHHCFRn)*pM-CP3qqG9nNgcp&X*FZk^%Y=01MAvF +zWoa|r-Q5+s-%(+Uv~C$D2rpMe1*B#95=0PELPtD`Tz}+Y2|jLR_%!4T=YchR6%+<1 +z;3HScos5Xt^q2Feq)p0Z#1IcDolPC1&DUn<{=2AAVk1nP(E({LkpjZn2s +zPAf$(vJ5>XU$_!k%)Sy&vK@69+2Qxt5+hrymZ*^7F-3NZKZT49ws8?9W)4}UG06J- +zTLm+^+@dl2@4Hoq{cUNUv6C+Cg}T)d;MfvJU4Y|MI8Rf8eD5;kd9<=9XL1#CK=#08 +zIPiUftobWm{hPU9JWMDz7X~pvfRoDRn%us`xh=hMSNLocOLUT +z8%KN-#W7a%p}0Cg)OM&x0czSp>^KZ{LGa;@sHH1*E6v0U(-ACY;zcv;)QvXKpEkqv +zZ}&GoHukVp2zSR{y=+M}6n>kNbCB7niPm%tVm>vRV5lz0^KK$>LEg8U#9dM!TteRT +zLF8rYeQYoAOwts4+1U5~XD^$2kNj+dmyLXE)xY+#v5)PKkR>Yiv$Ju&U<1}VQ$_oL +zv`%~MRJ&sL+5vmuXeG@N{cvOqrz10hR_;2!i|A*UIN6CfCo)X*vylt_@BQou(cLTY +zv$2ys(cov7Fr}-=6gq`YrPJtcbay(P&Y&}C9i2t@ptI>5I+xC)^XUS*knTzMqI=VQ +z=)QD6xx236OdI!Ce-X*|=0$e1(#R6O+z@-A#c*_O2LVzm;xJrPCJZl8FR)FgS +zxL$x81h`Rvn*_L7fLjE(Re;+BxLtrd1h`XxyF`EGPXX>0;2r_)72rMr?ib(z0Ui|K +zApsudQ6O;(`AQFlP0(>aIM*@5-Kona&72q=gJ{KVJq+SZ} +zl>lE0@Qnc93J^)xdjWnB;70*|QtKZ=OW-PDeJ95UG|QcgZihIdFj&0eR6d?^?pPY* +z)NdSbI9gVY(_K2wM%)aZiDGj(2oWDY%s?flUman9#&-O5)?a2x;0#C7$?+k5a;N{_ +zH>4Wl)i8nMjNrrGGy=%ds0u-gYGg(=V$R4}$5s9f4So~EVOq5LTTK7m0e`>1*E%m3 +z!D9Pce*AKRD{$^?%*px<GTf;D +zMKHu%5~{N@sxwSyByyg}sV)a!NpjA(QIiC&OSu{UzkiVM7eMuyT~z7vw=!ycUZZn) +zOv=twM;GjkFO3q +z&*MX-$%iPEQ%n3nJR+n9q@qxv9mvN40!T)IT~|c(+aMj@BUlu;b=L~tN +zG2rkMgAW%Rj(C+uB+mLjv4R7U(saLg$o5wh47Nd$2amkps{CX8S6hPlU;(xgBMts7 +ziZVV6&=&`tHYjfDgF`0E(ol(ShO-9thI@&&Vraxy;bRSvk>Li!7XeE6%Hm&pnWGPg +z`0D&RF$O}h5dTRZ1zqO-aQG9)-!l$@c!d}Noi&Pq#PFxC`1fO^e68{~8%#=rAZE5G +zOw1f+E;Emr&n#dTGK-kS%o1iPvy55JtYB6$tC-cy8fGoCj#b~3w|KbhUk9%e7IkJ-;0U=A{en8VBw<|uQFInJD5PBN#MBIY!6hB?ceW6m=d +zn2XFM<}!1IxyoE)t}{27o6IfdHgku$%iLq`GY^=D%p>M8^MrZIJY$|SFPN9iE9N!x +zhIz}pW8O0#n2*dS<}>q!`O17_zB50VpG+|eSjZAA$x^I@m9jL;uqz%5CTC81d7xp +z0wEO$S|At{wF`uaK$r@InLwBegoQv@3Irz*GJ&uX2y20`5eQp>uoH+%0#R8YstAO= +zKvWe72Z5+25Y+|3Q6S_3Q9~eV3Pde|s4Wn61fs4$)Ds9Nfp8WG7lCjU2seSKFA(km +z(Lf+P1fropcnXAt1j1h+0tBL^K(rEw +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 +z>2LH7{lk9BjZ-_8NPgy}{14^Xvk9 +zv%S^cZSS>@*~jghcB%b~U1pctckO$2gw +zI$-M7o1DZ56)Fq +zpEYESSW_0mTCkSvY1W3tvKLr4)|>TZNo*hsu?X{7217QMWwLQBi>+pB**dn7ea7-x +z0o%+9*><*%9bkvqQC7mPuxsomR>sQR+TJ=)cwW%)&0%=-M#DHbN}l;a4X#^ +zUW3=-b$C5qpEu-9|WlldtAI)9TJ+~Slw+~tC&@&M1^C_0KxB35)3aUxzMh#ula(OdKr{l&{-h!`q{ +zi4h`Mj1;5A8{#ct3Mw4Ig(uQPP=rNPWC$%X#W?XVF;PqwQ^j;KQ_L1~#e9)17K)F> +zCt`_MCRU2oB1dcxxguW_h)rUPC=^@8cCk|wiM`^0I3$jUZ^a2wEKZ3t;;c9?E{eG(rKy!^jnf9F%}!gAb||eR +z?Rr{epmv~hzzWO^YzPzujt3s4H&5@9-amarx=hbVFHXM^j0wgEM+DyrW(7Y8t_Xe^ +zEDru0d>E<|Y7-g|dNpK(!l4PF&7rfQ^3a2DOgJe#CY%w@3NH@lg)fJ1g&#-iM4Cln +zBT13;$dt&MNMYnsq%>MT+BVuFIwI;sL(#?2)zP)loapD#FQS{G+oL=DJ^p_Gpnupu +z>L2%u{nLJlf8M|7U-qx~*ZiOSpZ#0@ZNJR_-M{PK_bdE|{$r>PHK7jFg9gwDnm`P+ +zfL72N+Cc|+7Gj|b#6di~0NtPmBtmcK2T3ph2Eh<`1%^X1jD*oJ22#KP0yZ$QewiYcK|Rk{i* +zUnw;<}bzePDkFXj(fwi$7Ho!*M6q{p9dhgo|-0F2fbL3fEu`uE&k|8RlaFZo(~Ch+A0MVJb;Jr +z2p+@Z_#K|a(|88Y;(5G?m+=Z-!|Qkhf5uyQ8_Td9@8BPJA1m-7KEf(pUDwpLbzNOw +zH`I-FQyrsQ=$86v-CDQP9dsuht2^uG^z*u_PSD+TPo1cH>%RIW-Cw_=hwE4MYkHJ^ +zUB97Iw5f@ ++ ++ ++ ++ CFBundleDevelopmentRegion ++ English ++ CFBundleExecutable ++ ${EXECUTABLE_NAME} ++ CFBundleIconFile ++ bomb ++ CFBundleIdentifier ++ com.Google.BreakpadTest ++ CFBundleInfoDictionaryVersion ++ 6.0 ++ CFBundleName ++ ${PRODUCT_NAME} ++ CFBundlePackageType ++ APPL ++ CFBundleSignature ++ ???? ++ CFBundleVersion ++ 1.0 ++ NSMainNibFile ++ MainMenu ++ NSPrincipalClass ++ NSApplication ++ BreakpadProductDisplay ++ Breakpad Tester ++ BreakpadProduct ++ Breakpad_Tester ++ BreakpadVersion ++ 1.2.3.4 ++ BreakpadReportInterval ++ 10 ++ BreakpadSkipConfirm ++ NO ++ BreakpadSendAndExit ++ YES ++ BreakpadRequestEmail ++ YES ++ BreakpadRequestComments ++ YES ++ BreakpadVendor ++ Foo Bar Corp, Incorporated, LTD, LLC ++ BreakpadServerParameters ++ ++ Param1 ++ Value1 ++ Param2 ++ Value2 ++ ++ LSUIElement ++ 1 ++ ++ +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/TestClass.h b/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/TestClass.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/TestClass.h +@@ -0,0 +1,37 @@ ++// 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 ++ ++@interface TestClass : NSObject { ++} ++ ++- (void)wait; ++ ++@end +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/TestClass.mm b/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/TestClass.mm +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/TestClass.mm +@@ -0,0 +1,95 @@ ++// 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. ++ ++#include ++ ++#import "TestClass.h" ++ ++struct AStruct { ++ int x; ++ float y; ++ double z; ++}; ++ ++class InternalTestClass { ++ public: ++ InternalTestClass(int a) : a_(a) {} ++ ~InternalTestClass() {} ++ ++ void snooze(float a); ++ void snooze(int a); ++ int snooze(int a, float b); ++ ++ protected: ++ int a_; ++ AStruct s_; ++ ++ static void InternalFunction(AStruct &s); ++ static float kStaticFloatValue; ++}; ++ ++void InternalTestClass::snooze(float a) { ++ InternalFunction(s_); ++ sleep(a_ * a); ++} ++ ++void InternalTestClass::snooze(int a) { ++ InternalFunction(s_); ++ sleep(a_ * a); ++} ++ ++int InternalTestClass::snooze(int a, float b) { ++ InternalFunction(s_); ++ sleep(a_ * a * b); ++ ++ return 33; ++} ++ ++void InternalTestClass::InternalFunction(AStruct &s) { ++ s.x = InternalTestClass::kStaticFloatValue; ++} ++ ++float InternalTestClass::kStaticFloatValue = 42; ++ ++static float PlainOldFunction() { ++ return 3.14145; ++} ++ ++@implementation TestClass ++ ++- (void)wait { ++ InternalTestClass t(10); ++ float z = PlainOldFunction(); ++ ++ while (1) { ++ t.snooze(z); ++ } ++} ++ ++@end +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/bomb.icns b/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/bomb.icns +new file mode 100644 +index 0000000000000000000000000000000000000000..c360dbf618946920498958680eddb253a1ff677f +GIT binary patch +literal 23659 +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 +zhj=`%Er0NHUE*1o))XM&$72fp& +z5miSk5^IAuFV->sbr)^$oCP|@V~$p9Z}@8+<6pPb248(+qFbAy1)iUyb3Fd$r#Zi` +z?(vBGHD3J9&gg@W6Ex*d(F-2SG`z`hDc27l6Ewnev-E_=3XN_uJ$};{U$g!HTfO1& +zsRp-sws-W$$E2G1(R#$=4a=JFl9T%6iMm8 +zz3>0sPN?sIxq8OqA8LlC;9y_#@nYR=tLhs8KZODKmsFg^ll3wH9v`WG(lF5w{MV|V`7JU8AA738^L2RC +zrp6|!;tNk0gg-|WUvkbM`~|A`=DI%eP;M(!J$ARcWf1;Wt_r^6BZKgFse19DvHo{o +z){0c^z}9yS!rv!Q!M7|k2!Fe(4aiiNXYH!(dsTO#!qW!fFH(UAqXL8Q=c(dz*BgW{ +zSH*{9gYZ?KLw{iqemj-?-iE+Gbydj^Q1)D3*H&hsl5b;(1@NGWO1_}L0Q|*j-g?vb +z=>uz@sm2>ZfGgC!^492y-uWf!o`RVi(mQ{>+B49v^o@V4{y9twb#K?`!c=a)Z%nN3 +z1DJkl@p?aiy7S>{i0@mleh=VQ)^q}IoUd1Yw;J#O{q>1IQu8xl^Gh{nQ)?SqBOYLy +z{_qz}HQ?Ld)*C-s13bWFec^9fX~eg}_xOh%8sq6sT=$QGw0rk2OxN4c8dZl5DtbV7FCA7}sj`<})tP9EF7YqJ +zw8R5g>+&#Sq}F(ng1S46`?^+N7lbK)ky?98ujQ9cJ%85;ep5})oK@NYU95v^HC^_V +z6`<}duuQAh?*48)>iRBDN*%v1@~P9iP_HJ{`6D~KUA4zw=~P!bnIxgM_k=qfbbu!d +zsnt#4lPTJM(xcMM6SbcQ`OS1iXRTGPcJzDWbyoQ|Cg`fg_a8Unb=32JHPOJsnu(H& +zlWV%ku5Ah0EPYTD{OQg}bN$d+<2Xd`SMz$_?`LLu==-Z)lP06qUQ+T|!0WP2W1H1_ +zr_;(frXFE2i+((H3<$L383g{$1Y%PwCue6zE16hes1KR-YX1jQ +C-1BPy + +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/crashInMain b/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/crashInMain +new file mode 100755 +index 0000000000000000000000000000000000000000..03bb3172769307065261123d239ca253e4dbf1cf +GIT binary patch +literal 12588 +zc%1E<&ui0g6u`e(GgrE~71=>lT#X{gS%-^N&;rP15Lr&fuP1INCMTFjn6(At)}6RiVmfsoChXZ*x0Bap +zj=!lco1Xi@_`3s)Jwe^)#W;wp>cwQrrlIM%HaUI_pgZWk{XP5hdHoN^Q*qyoh;I+P +z{{Zv%pH)o7-~ZwGe!lm8{ri9%EBS2u9Q}~v4C*6tVE^}=*pad1#H6?TA>Mn$>%WWp +zyR{Z7g_3M4>AcF?#E1Akj``{Z-AC$tm)@Bf9T~rw7#{f@eU;aS9D~CCx(M#&B(H&I +z@GVV?(U{{*i}6t?&0T_xWLsSfy;l@>)8^ANgtC!|vbDg{gfgO454}s^k6s?SQo*uC7v>|EWdZB1F*lCwDTKG8sJCmMEm +zEzz);SW8Lbnsot_icc&eq~)}xXEi-1&#U>8YVZ+xd9I>ot^j{6E+)bKu}mL +zgdi=n2cgivpojL-v&CLY!BhVLp$a)z+JjK&p>}5X)m?wYo0P(QVDe^P<~uVlyO)K@ +z&aZF3+ZbaaSPR%yusyg~hgAR@0+Xan>R$R`dUAsKL|Ic%x8>@l)3ej3G*REjx~;q} +zbK`Aw+4jRv>y19f99$#5#wEnoe2r4JE#1_b^Ydv?|(QooeF#r51fJb +zFS20&IoXzj{h!sx_}NeN9{_Sxja>5_G04$_>jgQm{}op|GM1T`^iMy?dyo75xAAzd +z)?%ell59C^sH};;ouA`Mpk5g70Q2sp|ICbzj6X;ZkNj2N;k6-0zi_fHf@itTYjnc0 +z3F}K(JHRqLM&yRtcGmp-$n(MTzsGxzzaQ2ZsFbY%L(dNIpS+v*5L)ehxAOYS`&UnI +zmR@WQMOt|e0=w|BKLb9m=Yh2oyq4Re*zH!&8ghP7*EHR(x-qwdF>ZCi?-@)}6serN +zm4x>7EYBO%2tx6UW~y4Y)k5;_v4|iDf*=TjAc#w0k=6E{y&uj&wEiemn@_Nfv2blP +z5puSL4_{k^&#)D)i_UgveXH^lE;<|ipsEcgSYrm>I}RI|WcKK-1WSEQfzP8|Z?C>K +zAu_UJ`01P-x-JZ +zJFpO#``$dp_8_&&}IRMCf=JCJjg`#2Zv{l7p! +zHLC}Foa^pzQ{qszRJJQwDXW_~-PEMKYLrxqkH||46;qLnV)1dM=TZl5Q1E23d5Im2KIwVRKoB&yuB^_5x#n +E0DI)!$N&HU + +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/main.m b/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/main.m +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/testapp/main.m +@@ -0,0 +1,34 @@ ++// 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 ++ ++int main(int argc, char *argv[]) { ++ return NSApplicationMain(argc, (const char **) argv); ++} +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/tests/BreakpadFramework_Test.mm b/toolkit/crashreporter/google-breakpad/src/client/mac/tests/BreakpadFramework_Test.mm +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/tests/BreakpadFramework_Test.mm +@@ -0,0 +1,217 @@ ++// Copyright (c) 2009, 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. ++// ++// BreakpadFramework_Test.mm ++// Test case file for Breakpad.h/mm. ++// ++ ++#import "GTMSenTestCase.h" ++#import "Breakpad.h" ++ ++#include ++ ++@interface BreakpadFramework_Test : GTMTestCase { ++ @private ++ int last_exception_code_; ++ int last_exception_type_; ++ mach_port_t last_exception_thread_; ++ // We're not using Obj-C BOOL because we need to interop with ++ // Breakpad's callback. ++ bool shouldHandleException_; ++} ++ ++// This method is used by a callback used by test cases to determine ++// whether to return true or false to Breakpad when handling an ++// exception. ++- (bool)shouldHandleException; ++// This method returns a minimal dictionary that has what ++// Breakpad needs to initialize. ++- (NSMutableDictionary *)breakpadInitializationDictionary; ++// This method is used by the exception handling callback ++// to communicate to test cases the properites of the last ++// exception. ++- (void)setLastExceptionType:(int)type andCode:(int)code ++ andThread:(mach_port_t)thread; ++@end ++ ++// Callback for Breakpad exceptions ++bool myBreakpadCallback(int exception_type, ++ int exception_code, ++ mach_port_t crashing_thread, ++ void *context); ++ ++bool myBreakpadCallback(int exception_type, ++ int exception_code, ++ mach_port_t crashing_thread, ++ void *context) { ++ BreakpadFramework_Test *testCaseClass = ++ (BreakpadFramework_Test *)context; ++ [testCaseClass setLastExceptionType:exception_type ++ andCode:exception_code ++ andThread:crashing_thread]; ++ bool shouldHandleException = ++ [testCaseClass shouldHandleException]; ++ NSLog(@"Callback returning %d", shouldHandleException); ++ return shouldHandleException; ++} ++const int kNoLastExceptionCode = -1; ++const int kNoLastExceptionType = -1; ++const mach_port_t kNoLastExceptionThread = MACH_PORT_NULL; ++ ++@implementation BreakpadFramework_Test ++- (void) initializeExceptionStateVariables { ++ last_exception_code_ = kNoLastExceptionCode; ++ last_exception_type_ = kNoLastExceptionType; ++ last_exception_thread_ = kNoLastExceptionThread; ++} ++ ++- (NSMutableDictionary *)breakpadInitializationDictionary { ++ NSMutableDictionary *breakpadParams = ++ [NSMutableDictionary dictionaryWithCapacity:3]; ++ ++ [breakpadParams setObject:@"UnitTests" forKey:@BREAKPAD_PRODUCT]; ++ [breakpadParams setObject:@"1.0" forKey:@BREAKPAD_VERSION]; ++ [breakpadParams setObject:@"http://staging" forKey:@BREAKPAD_URL]; ++ return breakpadParams; ++} ++ ++- (bool)shouldHandleException { ++ return shouldHandleException_; ++} ++ ++- (void)setLastExceptionType:(int)type ++ andCode:(int)code ++ andThread:(mach_port_t)thread { ++ last_exception_type_ = type; ++ last_exception_code_ = code; ++ last_exception_thread_ = thread; ++} ++ ++// Test that the parameters mark required actually enable Breakpad to ++// be initialized. ++- (void)testBreakpadInstantiationWithRequiredParameters { ++ BreakpadRef b = BreakpadCreate([self breakpadInitializationDictionary]); ++ STAssertNotNULL(b, @"BreakpadCreate failed with required parameters"); ++ BreakpadRelease(b); ++} ++ ++// Test that Breakpad fails to initialize cleanly when required ++// parameters are not present. ++- (void)testBreakpadInstantiationWithoutRequiredParameters { ++ NSMutableDictionary *breakpadDictionary = ++ [self breakpadInitializationDictionary]; ++ ++ // Skip setting version, so that BreakpadCreate fails. ++ [breakpadDictionary removeObjectForKey:@BREAKPAD_VERSION]; ++ BreakpadRef b = BreakpadCreate(breakpadDictionary); ++ STAssertNULL(b, @"BreakpadCreate did not fail when missing a required" ++ " parameter!"); ++ ++ breakpadDictionary = [self breakpadInitializationDictionary]; ++ // Now test with no product ++ [breakpadDictionary removeObjectForKey:@BREAKPAD_PRODUCT]; ++ b = BreakpadCreate(breakpadDictionary); ++ STAssertNULL(b, @"BreakpadCreate did not fail when missing a required" ++ " parameter!"); ++ ++ breakpadDictionary = [self breakpadInitializationDictionary]; ++ // Now test with no URL ++ [breakpadDictionary removeObjectForKey:@BREAKPAD_URL]; ++ b = BreakpadCreate(breakpadDictionary); ++ STAssertNULL(b, @"BreakpadCreate did not fail when missing a required" ++ " parameter!"); ++ BreakpadRelease(b); ++} ++ ++// Test to ensure that when we call BreakpadAddUploadParameter, ++// it's added to the dictionary correctly(this test depends on ++// some internal details of Breakpad, namely, the special prefix ++// that it uses to figure out which key/value pairs to upload). ++- (void)testAddingBreakpadServerVariable { ++ NSMutableDictionary *breakpadDictionary = ++ [self breakpadInitializationDictionary]; ++ ++ BreakpadRef b = BreakpadCreate(breakpadDictionary); ++ STAssertNotNULL(b, @"BreakpadCreate failed with valid dictionary!"); ++ ++ BreakpadAddUploadParameter(b, ++ @"key", ++ @"value"); ++ ++ // Test that it did not add the key/value directly, e.g. without ++ // prepending the key with the prefix. ++ STAssertNil(BreakpadKeyValue(b, @"key"), ++ @"AddUploadParameter added key directly to dictionary" ++ " instead of prepending it!"); ++ ++ NSString *prependedKeyname = ++ [@BREAKPAD_SERVER_PARAMETER_PREFIX stringByAppendingString:@"key"]; ++ ++ STAssertEqualStrings(BreakpadKeyValue(b, prependedKeyname), ++ @"value", ++ @"Calling BreakpadAddUploadParameter did not prepend " ++ "key name"); ++ BreakpadRelease(b); ++} ++ ++// Test that when we do on-demand minidump generation, ++// the exception code/type/thread are set properly. ++- (void)testFilterCallbackReturnsFalse { ++ NSMutableDictionary *breakpadDictionary = ++ [self breakpadInitializationDictionary]; ++ ++ BreakpadRef b = BreakpadCreate(breakpadDictionary); ++ STAssertNotNULL(b, @"BreakpadCreate failed with valid dictionary!"); ++ BreakpadSetFilterCallback(b, &myBreakpadCallback, self); ++ ++ // This causes the callback to return false, meaning ++ // Breakpad won't take the exception ++ shouldHandleException_ = false; ++ ++ [self initializeExceptionStateVariables]; ++ STAssertEquals(last_exception_type_, kNoLastExceptionType, ++ @"Last exception type not initialized correctly."); ++ STAssertEquals(last_exception_code_, kNoLastExceptionCode, ++ @"Last exception code not initialized correctly."); ++ STAssertEquals(last_exception_thread_, kNoLastExceptionThread, ++ @"Last exception thread is not initialized correctly."); ++ ++ // Cause Breakpad's exception handler to be invoked. ++ BreakpadGenerateAndSendReport(b); ++ ++ STAssertEquals(last_exception_type_, 0, ++ @"Last exception type is not 0 for on demand"); ++ STAssertEquals(last_exception_code_, 0, ++ @"Last exception code is not 0 for on demand"); ++ STAssertEquals(last_exception_thread_, mach_thread_self(), ++ @"Last exception thread is not mach_thread_self() " ++ "for on demand"); ++} ++ ++@end +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/tests/SimpleStringDictionaryTest.h b/toolkit/crashreporter/google-breakpad/src/client/mac/tests/SimpleStringDictionaryTest.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/tests/SimpleStringDictionaryTest.h +@@ -0,0 +1,40 @@ ++// Copyright (c) 2008, 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 ++#import "SimpleStringDictionary.h" ++ ++@interface SimpleStringDictionaryTest : GTMTestCase { ++ ++} ++ ++- (void)testKeyValueEntry; ++- (void)testSimpleStringDictionary; ++- (void)testSimpleStringDictionaryIterator; ++@end +diff --git a/toolkit/crashreporter/google-breakpad/src/client/mac/tests/SimpleStringDictionaryTest.mm b/toolkit/crashreporter/google-breakpad/src/client/mac/tests/SimpleStringDictionaryTest.mm +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/mac/tests/SimpleStringDictionaryTest.mm +@@ -0,0 +1,243 @@ ++// Copyright (c) 2008, 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 "SimpleStringDictionaryTest.h" ++#import "SimpleStringDictionary.h" ++ ++using google_breakpad::KeyValueEntry; ++using google_breakpad::SimpleStringDictionary; ++using google_breakpad::SimpleStringDictionaryIterator; ++ ++@implementation SimpleStringDictionaryTest ++ ++//============================================================================== ++- (void)testKeyValueEntry { ++ KeyValueEntry entry; ++ ++ // Verify that initial state is correct ++ STAssertFalse(entry.IsActive(), @"Initial key value entry is active!"); ++ STAssertEquals(strlen(entry.GetKey()), (size_t)0, @"Empty key value did not " ++ @"have length 0"); ++ STAssertEquals(strlen(entry.GetValue()), (size_t)0, @"Empty key value did not " ++ @"have length 0"); ++ ++ // Try setting a key/value and then verify ++ entry.SetKeyValue("key1", "value1"); ++ STAssertEqualCStrings(entry.GetKey(), "key1", @"key was not equal to key1"); ++ STAssertEqualCStrings(entry.GetValue(), "value1", @"value was not equal"); ++ ++ // Try setting a new value ++ entry.SetValue("value3"); ++ ++ // Make sure the new value took ++ STAssertEqualCStrings(entry.GetValue(), "value3", @"value was not equal"); ++ ++ // Make sure the key didn't change ++ STAssertEqualCStrings(entry.GetKey(), "key1", @"key changed after setting " ++ @"value!"); ++ ++ // Try setting a new key/value and then verify ++ entry.SetKeyValue("key2", "value2"); ++ STAssertEqualCStrings(entry.GetKey(), "key2", @"New key was not equal to " ++ @"key2"); ++ STAssertEqualCStrings(entry.GetValue(), "value2", @"New value was not equal " ++ @"to value2"); ++ ++ // Clear the entry and verify the key and value are empty strings ++ entry.Clear(); ++ STAssertFalse(entry.IsActive(), @"Key value clear did not clear object"); ++ STAssertEquals(strlen(entry.GetKey()), (size_t)0, @"Length of cleared key " ++ @"was not 0"); ++ STAssertEquals(strlen(entry.GetValue()), (size_t)0, @"Length of cleared " ++ @"value was not 0!"); ++} ++ ++- (void)testEmptyKeyValueCombos { ++ KeyValueEntry entry; ++ entry.SetKeyValue(NULL, NULL); ++ STAssertEqualCStrings(entry.GetKey(), "", @"Setting NULL key did not return " ++ @"empty key!"); ++ STAssertEqualCStrings(entry.GetValue(), "", @"Setting NULL value did not " ++ @"set empty string value!"); ++} ++ ++ ++//============================================================================== ++- (void)testSimpleStringDictionary { ++ // Make a new dictionary ++ SimpleStringDictionary *dict = new SimpleStringDictionary(); ++ STAssertTrue(dict != NULL, nil); ++ ++ // try passing in NULL for key ++ //dict->SetKeyValue(NULL, "bad"); // causes assert() to fire ++ ++ // Set three distinct values on three keys ++ dict->SetKeyValue("key1", "value1"); ++ dict->SetKeyValue("key2", "value2"); ++ dict->SetKeyValue("key3", "value3"); ++ ++ STAssertTrue(!strcmp(dict->GetValueForKey("key1"), "value1"), nil); ++ STAssertTrue(!strcmp(dict->GetValueForKey("key2"), "value2"), nil); ++ STAssertTrue(!strcmp(dict->GetValueForKey("key3"), "value3"), nil); ++ STAssertEquals(dict->GetCount(), 3, @"GetCount did not return 3"); ++ // try an unknown key ++ STAssertTrue(dict->GetValueForKey("key4") == NULL, nil); ++ ++ // try a NULL key ++ //STAssertTrue(dict->GetValueForKey(NULL) == NULL, nil); // asserts ++ ++ // Remove a key ++ dict->RemoveKey("key3"); ++ ++ // Now make sure it's not there anymore ++ STAssertTrue(dict->GetValueForKey("key3") == NULL, nil); ++ ++ // Remove a NULL key ++ //dict->RemoveKey(NULL); // will cause assert() to fire ++ ++ // Remove by setting value to NULL ++ dict->SetKeyValue("key2", NULL); ++ ++ // Now make sure it's not there anymore ++ STAssertTrue(dict->GetValueForKey("key2") == NULL, nil); ++} ++ ++//============================================================================== ++// The idea behind this test is to add a bunch of values to the dictionary, ++// remove some in the middle, then add a few more in. We then create a ++// SimpleStringDictionaryIterator and iterate through the dictionary, taking ++// note of the key/value pairs we see. We then verify that it iterates ++// through exactly the number of key/value pairs we expect, and that they ++// match one-for-one with what we would expect. In all cases we're setting ++// key value pairs of the form: ++// ++// key/value (like key0/value0, key17,value17, etc.) ++// ++- (void)testSimpleStringDictionaryIterator { ++ SimpleStringDictionary *dict = new SimpleStringDictionary(); ++ STAssertTrue(dict != NULL, nil); ++ ++ char key[KeyValueEntry::MAX_STRING_STORAGE_SIZE]; ++ char value[KeyValueEntry::MAX_STRING_STORAGE_SIZE]; ++ ++ const int kDictionaryCapacity = SimpleStringDictionary::MAX_NUM_ENTRIES; ++ const int kPartitionIndex = kDictionaryCapacity - 5; ++ ++ // We assume at least this size in the tests below ++ STAssertTrue(kDictionaryCapacity >= 64, nil); ++ ++ // We'll keep track of the number of key/value pairs we think should ++ // be in the dictionary ++ int expectedDictionarySize = 0; ++ ++ // Set a bunch of key/value pairs like key0/value0, key1/value1, ... ++ for (int i = 0; i < kPartitionIndex; ++i) { ++ sprintf(key, "key%d", i); ++ sprintf(value, "value%d", i); ++ dict->SetKeyValue(key, value); ++ } ++ expectedDictionarySize = kPartitionIndex; ++ ++ // set a couple of the keys twice (with the same value) - should be nop ++ dict->SetKeyValue("key2", "value2"); ++ dict->SetKeyValue("key4", "value4"); ++ dict->SetKeyValue("key15", "value15"); ++ ++ // Remove some random elements in the middle ++ dict->RemoveKey("key7"); ++ dict->RemoveKey("key18"); ++ dict->RemoveKey("key23"); ++ dict->RemoveKey("key31"); ++ expectedDictionarySize -= 4; // we just removed four key/value pairs ++ ++ // Set some more key/value pairs like key59/value59, key60/value60, ... ++ for (int i = kPartitionIndex; i < kDictionaryCapacity; ++i) { ++ sprintf(key, "key%d", i); ++ sprintf(value, "value%d", i); ++ dict->SetKeyValue(key, value); ++ } ++ expectedDictionarySize += kDictionaryCapacity - kPartitionIndex; ++ ++ // Now create an iterator on the dictionary ++ SimpleStringDictionaryIterator iter(*dict); ++ ++ // We then verify that it iterates through exactly the number of ++ // key/value pairs we expect, and that they match one-for-one with what we ++ // would expect. The ordering of the iteration does not matter... ++ ++ // used to keep track of number of occurrences found for key/value pairs ++ int count[kDictionaryCapacity]; ++ memset(count, 0, sizeof(count)); ++ ++ int totalCount = 0; ++ ++ const KeyValueEntry *entry; ++ ++ while ((entry = iter.Next())) { ++ totalCount++; ++ ++ // Extract keyNumber from a string of the form key ++ int keyNumber; ++ sscanf(entry->GetKey(), "key%d", &keyNumber); ++ ++ // Extract valueNumber from a string of the form value ++ int valueNumber; ++ sscanf(entry->GetValue(), "value%d", &valueNumber); ++ ++ // The value number should equal the key number since that's how we set them ++ STAssertTrue(keyNumber == valueNumber, nil); ++ ++ // Key and value numbers should be in proper range: ++ // 0 <= keyNumber < kDictionaryCapacity ++ bool isKeyInGoodRange = ++ (keyNumber >= 0 && keyNumber < kDictionaryCapacity); ++ bool isValueInGoodRange = ++ (valueNumber >= 0 && valueNumber < kDictionaryCapacity); ++ STAssertTrue(isKeyInGoodRange, nil); ++ STAssertTrue(isValueInGoodRange, nil); ++ ++ if (isKeyInGoodRange && isValueInGoodRange) { ++ ++count[keyNumber]; ++ } ++ } ++ ++ // Make sure each of the key/value pairs showed up exactly one time, except ++ // for the ones which we removed. ++ for (int i = 0; i < kDictionaryCapacity; ++i) { ++ // Skip over key7, key18, key23, and key31, since we removed them ++ if (!(i == 7 || i == 18 || i == 23 || i == 31)) { ++ STAssertTrue(count[i] == 1, nil); ++ } ++ } ++ ++ // Make sure the number of iterations matches the expected dictionary size. ++ STAssertTrue(totalCount == expectedDictionarySize, nil); ++} ++ ++@end +diff --git a/toolkit/crashreporter/google-breakpad/src/client/minidump_file_writer.cc b/toolkit/crashreporter/google-breakpad/src/client/minidump_file_writer.cc +--- a/toolkit/crashreporter/google-breakpad/src/client/minidump_file_writer.cc ++++ b/toolkit/crashreporter/google-breakpad/src/client/minidump_file_writer.cc +@@ -32,43 +32,53 @@ + // See minidump_file_writer.h for documentation. + + #include + #include + #include + #include + #include + ++#include "common/linux/linux_syscall_support.h" ++#include "common/linux/linux_libc_support.h" + #include "client/minidump_file_writer-inl.h" + #include "common/string_conversion.h" + + namespace google_breakpad { + + const MDRVA MinidumpFileWriter::kInvalidMDRVA = static_cast(-1); + + MinidumpFileWriter::MinidumpFileWriter() : file_(-1), position_(0), size_(0) { + } + + MinidumpFileWriter::~MinidumpFileWriter() { + Close(); + } + + bool MinidumpFileWriter::Open(const char *path) { + assert(file_ == -1); ++#if __linux__ ++ file_ = sys_open(path, O_WRONLY | O_CREAT | O_EXCL, 0600); ++#else + file_ = open(path, O_WRONLY | O_CREAT | O_EXCL, 0600); ++#endif + + return file_ != -1; + } + + bool MinidumpFileWriter::Close() { + bool result = true; + + if (file_ != -1) { + ftruncate(file_, position_); ++#if __linux__ ++ result = (sys_close(file_) == 0); ++#else + result = (close(file_) == 0); ++#endif + file_ = -1; + } + + return result; + } + + bool MinidumpFileWriter::CopyStringToMDString(const wchar_t *str, + unsigned int length, +@@ -222,19 +232,26 @@ bool MinidumpFileWriter::Copy(MDRVA posi + assert(size); + assert(file_ != -1); + + // Ensure that the data will fit in the allocated space + if (size + position > size_) + return false; + + // Seek and write the data +- if (lseek(file_, position, SEEK_SET) == static_cast(position)) +- if (write(file_, src, size) == size) ++#if __linux__ ++ if (sys_lseek(file_, position, SEEK_SET) == static_cast(position)) { ++ if (sys_write(file_, src, size) == size) { ++#else ++ if (lseek(file_, position, SEEK_SET) == static_cast(position)) { ++ if (write(file_, src, size) == size) { ++#endif + return true; ++ } ++ } + + return false; + } + + bool UntypedMDRVA::Allocate(size_t size) { + assert(size_ == 0); + size_ = size; + position_ = writer_->Allocate(size_); +diff --git a/toolkit/crashreporter/google-breakpad/src/client/minidump_file_writer_unittest.cc b/toolkit/crashreporter/google-breakpad/src/client/minidump_file_writer_unittest.cc +--- a/toolkit/crashreporter/google-breakpad/src/client/minidump_file_writer_unittest.cc ++++ b/toolkit/crashreporter/google-breakpad/src/client/minidump_file_writer_unittest.cc +@@ -121,27 +121,32 @@ static bool CompareFile(const char *path + 0x01000002, 0x00000003, 0x02000003, 0x00000004, 0x03000004, 0x00000005, + 0x04000005, 0x00000006, 0x05000006, 0x00000007, 0x06000007, 0x00000008, + 0x07000008, 0x00000009, 0x08000009, 0x0000000a, 0x0900000a, 0x0000000b, + 0x0000000a, 0x00000001, 0x00000002, 0x01000002, 0x00000003, 0x02000003, + 0x00000004, 0x03000004, 0x00000005, 0x04000005, 0x00000006, 0x05000006, + 0x00000007, 0x06000007, 0x00000008, 0x07000008, 0x00000009, 0x08000009, + 0x0000000a, 0x0900000a, 0x0000000b, 0x00000000 + #else +- 0x0000beef, 0x0000001e, 0x00000018, 0x00000020, 0x00000038, 0x00000000, +- 0x00000018, 0x00690046, 0x00730072, 0x00200074, 0x00740053, 0x00690072, +- 0x0067006e, 0x00000000, 0x0000001a, 0x00650053, 0x006f0063, 0x0064006e, +- 0x00530020, 0x00720074, 0x006e0069, 0x00000067, 0x0001da00, 0x00000002, +- 0x0002da01, 0x00000003, 0x0003da02, 0x00000004, 0x0004da03, 0x00000005, +- 0x0005da04, 0x00000006, 0x0006da05, 0x00000007, 0x0007da06, 0x00000008, +- 0x0008da07, 0x00000009, 0x0009da08, 0x0000000a, 0x000ada09, 0x0000000b, +- 0x0000000a, 0x00018700, 0x00000002, 0x00028701, 0x00000003, 0x00038702, +- 0x00000004, 0x00048703, 0x00000005, 0x00058704, 0x00000006, 0x00068705, +- 0x00000007, 0x00078706, 0x00000008, 0x00088707, 0x00000009, 0x00098708, +- 0x0000000a, 0x000a8709, 0x0000000b, 0x00000000, ++ 0x0000beef, 0x0000001e, 0x00000018, 0x00000020, ++ 0x00000038, 0x00000000, 0x00000018, 0x00690046, ++ 0x00730072, 0x00200074, 0x00740053, 0x00690072, ++ 0x0067006e, 0x00000000, 0x0000001a, 0x00650053, ++ 0x006f0063, 0x0064006e, 0x00530020, 0x00720074, ++ 0x006e0069, 0x00000067, 0x00011e00, 0x00000002, ++ 0x00021e01, 0x00000003, 0x00031e02, 0x00000004, ++ 0x00041e03, 0x00000005, 0x00051e04, 0x00000006, ++ 0x00061e05, 0x00000007, 0x00071e06, 0x00000008, ++ 0x00081e07, 0x00000009, 0x00091e08, 0x0000000a, ++ 0x000a1e09, 0x0000000b, 0x0000000a, 0x00011c00, ++ 0x00000002, 0x00021c01, 0x00000003, 0x00031c02, ++ 0x00000004, 0x00041c03, 0x00000005, 0x00051c04, ++ 0x00000006, 0x00061c05, 0x00000007, 0x00071c06, ++ 0x00000008, 0x00081c07, 0x00000009, 0x00091c08, ++ 0x0000000a, 0x000a1c09, 0x0000000b, 0x00000000, + #endif + }; + unsigned int expected_byte_count = sizeof(expected); + int fd = open(path, O_RDONLY, 0600); + void *buffer = malloc(expected_byte_count); + ASSERT_NE(fd, -1); + ASSERT_TRUE(buffer); + ASSERT_EQ(read(fd, buffer, expected_byte_count), expected_byte_count); +@@ -151,17 +156,16 @@ static bool CompareFile(const char *path + b2 = (char*)expected; + while (*b1 == *b2) { + b1++; + b2++; + } + + printf("%d\n",b1 - (char*)buffer); + +- + ASSERT_EQ(memcmp(buffer, expected, expected_byte_count), 0); + return true; + } + + static bool RunTests() { + const char *path = "/tmp/minidump_file_writer_unittest.dmp"; + ASSERT_TRUE(WriteFile(path)); + ASSERT_TRUE(CompareFile(path)); +diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/breakpad_client.sln b/toolkit/crashreporter/google-breakpad/src/client/windows/breakpad_client.sln +--- a/toolkit/crashreporter/google-breakpad/src/client/windows/breakpad_client.sln ++++ b/toolkit/crashreporter/google-breakpad/src/client/windows/breakpad_client.sln +@@ -5,16 +5,18 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C9 + ProjectSection(ProjectDependencies) = postProject + {A820AF62-6239-4693-8430-4F516C1838F4} = {A820AF62-6239-4693-8430-4F516C1838F4} + EndProjectSection + EndProject + Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crash_report_sender", "sender\crash_report_sender.vcproj", "{9946A048-043B-4F8F-9E07-9297B204714C}" + EndProject + Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crash_generation", "crash_generation\crash_generation.vcproj", "{A820AF62-6239-4693-8430-4F516C1838F4}" + EndProject ++Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "exception_handler_test", "handler\exception_handler_test\exception_handler_test.vcproj", "{89094A11-CF25-4037-AF43-EACFA751405E}" ++EndProject + Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + DebugStaticCRT|Win32 = DebugStaticCRT|Win32 + Release|Win32 = Release|Win32 + ReleaseStaticCRT|Win32 = ReleaseStaticCRT|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution +@@ -37,13 +39,21 @@ Global + {A820AF62-6239-4693-8430-4F516C1838F4}.Debug|Win32.ActiveCfg = Debug|Win32 + {A820AF62-6239-4693-8430-4F516C1838F4}.Debug|Win32.Build.0 = Debug|Win32 + {A820AF62-6239-4693-8430-4F516C1838F4}.DebugStaticCRT|Win32.ActiveCfg = DebugStaticCRT|Win32 + {A820AF62-6239-4693-8430-4F516C1838F4}.DebugStaticCRT|Win32.Build.0 = DebugStaticCRT|Win32 + {A820AF62-6239-4693-8430-4F516C1838F4}.Release|Win32.ActiveCfg = Release|Win32 + {A820AF62-6239-4693-8430-4F516C1838F4}.Release|Win32.Build.0 = Release|Win32 + {A820AF62-6239-4693-8430-4F516C1838F4}.ReleaseStaticCRT|Win32.ActiveCfg = ReleaseStaticCRT|Win32 + {A820AF62-6239-4693-8430-4F516C1838F4}.ReleaseStaticCRT|Win32.Build.0 = ReleaseStaticCRT|Win32 ++ {89094A11-CF25-4037-AF43-EACFA751405E}.Debug|Win32.ActiveCfg = Debug|Win32 ++ {89094A11-CF25-4037-AF43-EACFA751405E}.Debug|Win32.Build.0 = Debug|Win32 ++ {89094A11-CF25-4037-AF43-EACFA751405E}.DebugStaticCRT|Win32.ActiveCfg = Debug|Win32 ++ {89094A11-CF25-4037-AF43-EACFA751405E}.DebugStaticCRT|Win32.Build.0 = Debug|Win32 ++ {89094A11-CF25-4037-AF43-EACFA751405E}.Release|Win32.ActiveCfg = Release|Win32 ++ {89094A11-CF25-4037-AF43-EACFA751405E}.Release|Win32.Build.0 = Release|Win32 ++ {89094A11-CF25-4037-AF43-EACFA751405E}.ReleaseStaticCRT|Win32.ActiveCfg = Release|Win32 ++ {89094A11-CF25-4037-AF43-EACFA751405E}.ReleaseStaticCRT|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + EndGlobal +diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/common/ipc_protocol.h b/toolkit/crashreporter/google-breakpad/src/client/windows/common/ipc_protocol.h +--- a/toolkit/crashreporter/google-breakpad/src/client/windows/common/ipc_protocol.h ++++ b/toolkit/crashreporter/google-breakpad/src/client/windows/common/ipc_protocol.h +@@ -90,17 +90,17 @@ enum MessageTag { + MESSAGE_TAG_NONE = 0, + MESSAGE_TAG_REGISTRATION_REQUEST = 1, + MESSAGE_TAG_REGISTRATION_RESPONSE = 2, + MESSAGE_TAG_REGISTRATION_ACK = 3 + }; + + struct CustomClientInfo { + const CustomInfoEntry* entries; +- int count; ++ size_t count; + }; + + // Message structure for IPC between crash client and crash server. + struct ProtocolMessage { + ProtocolMessage() + : tag(MESSAGE_TAG_NONE), + pid(0), + dump_type(MiniDumpNormal), +diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_server.cc b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_server.cc +--- a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_server.cc ++++ b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_server.cc +@@ -124,16 +124,29 @@ CrashGenerationServer::CrashGenerationSe + dump_generator_.reset(new MinidumpGenerator(*dump_path)); + } + } + + CrashGenerationServer::~CrashGenerationServer() { + // Indicate to existing threads that server is shutting down. + shutting_down_ = true; + ++ // Even if there are no current worker threads running, it is possible that ++ // an I/O request is pending on the pipe right now but not yet done. In fact, ++ // it's very likely this is the case unless we are in an ERROR state. If we ++ // don't wait for the pending I/O to be done, then when the I/O completes, ++ // it may write to invalid memory. AppVerifier will flag this problem too. ++ // So we disconnect from the pipe and then wait for the server to get into ++ // error state so that the pending I/O will fail and get cleared. ++ DisconnectNamedPipe(pipe_); ++ int num_tries = 100; ++ while (num_tries-- && server_state_ != IPC_SERVER_STATE_ERROR) { ++ Sleep(10); ++ } ++ + // Unregister wait on the pipe. + if (pipe_wait_handle_) { + // Wait for already executing callbacks to finish. + UnregisterWaitEx(pipe_wait_handle_, INVALID_HANDLE_VALUE); + } + + // Close the pipe to avoid further client connections. + if (pipe_) { +@@ -200,22 +213,24 @@ bool CrashGenerationServer::Start() { + TRUE, // Manual reset. + FALSE, // Initially signaled. + NULL); // Name. + if (!overlapped_.hEvent) { + return false; + } + + // Register a callback with the thread pool for the client connection. +- RegisterWaitForSingleObject(&pipe_wait_handle_, +- overlapped_.hEvent, +- OnPipeConnected, +- this, +- INFINITE, +- kPipeIOThreadFlags); ++ if (!RegisterWaitForSingleObject(&pipe_wait_handle_, ++ overlapped_.hEvent, ++ OnPipeConnected, ++ this, ++ INFINITE, ++ kPipeIOThreadFlags)) { ++ return false; ++ } + + pipe_ = CreateNamedPipe(pipe_name_.c_str(), + kPipeAttr, + kPipeMode, + 1, + kOutBufferSize, + kInBufferSize, + 0, +@@ -624,16 +639,24 @@ bool CrashGenerationServer::RespondToCli + + return success || GetLastError() == ERROR_IO_PENDING; + } + + // The server thread servicing the clients runs this method. The method + // implements the state machine described in ReadMe.txt along with the + // helper methods HandleXXXState. + void CrashGenerationServer::HandleConnectionRequest() { ++ // If we are shutting doen then get into ERROR state, reset the event so more ++ // workers don't run and return immediately. ++ if (shutting_down_) { ++ server_state_ = IPC_SERVER_STATE_ERROR; ++ ResetEvent(overlapped_.hEvent); ++ return; ++ } ++ + switch (server_state_) { + case IPC_SERVER_STATE_ERROR: + HandleErrorState(); + break; + + case IPC_SERVER_STATE_INITIAL: + HandleInitialState(); + break; +diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_server.h b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_server.h +--- a/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_server.h ++++ b/toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/crash_generation_server.h +@@ -236,17 +236,17 @@ class CrashGenerationServer { + + // Instance of a mini dump generator. + scoped_ptr dump_generator_; + + // State of the server in performing the IPC with the client. + // Note that since we restrict the pipe to one instance, we + // only need to keep one state of the server. Otherwise, server + // would have one state per client it is talking to. +- IPCServerState server_state_; ++ volatile IPCServerState server_state_; + + // Whether the server is shutting down. + volatile bool shutting_down_; + + // Overlapped instance for async I/O on the pipe. + OVERLAPPED overlapped_; + + // Message object used in IPC with the client. +diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.cc b/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.cc +--- a/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.cc ++++ b/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.cc +@@ -35,22 +35,23 @@ + #include "common/windows/string_utils-inl.h" + + #include "client/windows/common/ipc_protocol.h" + #include "client/windows/handler/exception_handler.h" + #include "common/windows/guid_string.h" + + namespace google_breakpad { + ++static const int kWaitForHandlerThreadMs = 60000; + static const int kExceptionHandlerThreadInitialStackSize = 64 * 1024; + + vector* ExceptionHandler::handler_stack_ = NULL; + LONG ExceptionHandler::handler_stack_index_ = 0; + CRITICAL_SECTION ExceptionHandler::handler_stack_critical_section_; +-bool ExceptionHandler::handler_stack_critical_section_initialized_ = false; ++volatile LONG ExceptionHandler::instance_count_ = 0; + + ExceptionHandler::ExceptionHandler(const wstring& dump_path, + FilterCallback filter, + MinidumpCallback callback, + void* callback_context, + int handler_types, + MINIDUMP_TYPE dump_type, + const wchar_t* pipe_name, +@@ -83,16 +84,17 @@ ExceptionHandler::ExceptionHandler(const + void ExceptionHandler::Initialize(const wstring& dump_path, + FilterCallback filter, + MinidumpCallback callback, + void* callback_context, + int handler_types, + MINIDUMP_TYPE dump_type, + const wchar_t* pipe_name, + const CustomClientInfo* custom_info) { ++ LONG instance_count = InterlockedIncrement(&instance_count_); + filter_ = filter; + callback_ = callback; + callback_context_ = callback_context; + dump_path_c_ = NULL; + next_minidump_id_c_ = NULL; + next_minidump_path_c_ = NULL; + dbghelp_module_ = NULL; + minidump_write_dump_ = NULL; +@@ -101,16 +103,17 @@ void ExceptionHandler::Initialize(const + uuid_create_ = NULL; + handler_types_ = handler_types; + previous_filter_ = NULL; + #if _MSC_VER >= 1400 // MSVC 2005/8 + previous_iph_ = NULL; + #endif // _MSC_VER >= 1400 + previous_pch_ = NULL; + handler_thread_ = NULL; ++ is_shutdown_ = false; + handler_start_semaphore_ = NULL; + handler_finish_semaphore_ = NULL; + requesting_thread_id_ = 0; + exception_info_ = NULL; + assertion_ = NULL; + handler_return_value_ = false; + handle_debug_exceptions_ = false; + +@@ -172,22 +175,32 @@ void ExceptionHandler::Initialize(const + GetProcAddress(rpcrt4_module_, "UuidCreate")); + } + + // set_dump_path calls UpdateNextID. This sets up all of the path and id + // strings, and their equivalent c_str pointers. + set_dump_path(dump_path); + } + ++ // There is a race condition here. If the first instance has not yet ++ // initialized the critical section, the second (and later) instances may ++ // try to use uninitialized critical section object. The feature of multiple ++ // instances in one module is not used much, so leave it as is for now. ++ // One way to solve this in the current design (that is, keeping the static ++ // handler stack) is to use spin locks with volatile bools to synchronize ++ // the handler stack. This works only if the compiler guarantees to generate ++ // cache coherent code for volatile. ++ // TODO(munjal): Fix this in a better way by changing the design if possible. ++ ++ // Lazy initialization of the handler_stack_critical_section_ ++ if (instance_count == 1) { ++ InitializeCriticalSection(&handler_stack_critical_section_); ++ } ++ + if (handler_types != HANDLER_NONE) { +- if (!handler_stack_critical_section_initialized_) { +- InitializeCriticalSection(&handler_stack_critical_section_); +- handler_stack_critical_section_initialized_ = true; +- } +- + EnterCriticalSection(&handler_stack_critical_section_); + + // The first time an ExceptionHandler that installs a handler is + // created, set up the handler stack. + if (!handler_stack_) { + handler_stack_ = new vector(); + } + handler_stack_->push_back(this); +@@ -231,22 +244,22 @@ ExceptionHandler::~ExceptionHandler() { + _set_purecall_handler(previous_pch_); + + if (handler_stack_->back() == this) { + handler_stack_->pop_back(); + } else { + // TODO(mmentovai): use advapi32!ReportEvent to log the warning to the + // system's application event log. + fprintf(stderr, "warning: removing Breakpad handler out of order\n"); +- for (vector::iterator iterator = +- handler_stack_->begin(); +- iterator != handler_stack_->end(); +- ++iterator) { ++ vector::iterator iterator = handler_stack_->begin(); ++ while (iterator != handler_stack_->end()) { + if (*iterator == this) { +- handler_stack_->erase(iterator); ++ iterator = handler_stack_->erase(iterator); ++ } else { ++ ++iterator; + } + } + } + + if (handler_stack_->empty()) { + // When destroying the last ExceptionHandler that installed a handler, + // clean up the handler stack. + delete handler_stack_; +@@ -254,45 +267,76 @@ ExceptionHandler::~ExceptionHandler() { + } + + LeaveCriticalSection(&handler_stack_critical_section_); + } + + // Some of the objects were only initialized if out of process + // registration was not done. + if (!IsOutOfProcess()) { +- // Clean up the handler thread and synchronization primitives. ++#ifdef BREAKPAD_NO_TERMINATE_THREAD ++ // Clean up the handler thread and synchronization primitives. The handler ++ // thread is either waiting on the semaphore to handle a crash or it is ++ // handling a crash. Coming out of the wait is fast but wait more in the ++ // eventuality a crash is handled. This compilation option results in a ++ // deadlock if the exception handler is destroyed while executing code ++ // inside DllMain. ++ is_shutdown_ = true; ++ ReleaseSemaphore(handler_start_semaphore_, 1, NULL); ++ WaitForSingleObject(handler_thread_, kWaitForHandlerThreadMs); ++#else + TerminateThread(handler_thread_, 1); ++#endif // BREAKPAD_NO_TERMINATE_THREAD ++ ++ CloseHandle(handler_thread_); ++ handler_thread_ = NULL; + DeleteCriticalSection(&handler_critical_section_); + CloseHandle(handler_start_semaphore_); + CloseHandle(handler_finish_semaphore_); + } ++ ++ // There is a race condition in the code below: if this instance is ++ // deleting the static critical section and a new instance of the class ++ // is created, then there is a possibility that the critical section be ++ // initialized while the same critical section is being deleted. Given the ++ // usage pattern for the code, this race condition is unlikely to hit, but it ++ // is a race condition nonetheless. ++ if (InterlockedDecrement(&instance_count_) == 0) { ++ DeleteCriticalSection(&handler_stack_critical_section_); ++ } + } + + // static + DWORD ExceptionHandler::ExceptionHandlerThreadMain(void* lpParameter) { + ExceptionHandler* self = reinterpret_cast(lpParameter); + assert(self); + assert(self->handler_start_semaphore_ != NULL); + assert(self->handler_finish_semaphore_ != NULL); + + while (true) { + if (WaitForSingleObject(self->handler_start_semaphore_, INFINITE) == + WAIT_OBJECT_0) { + // Perform the requested action. +- self->handler_return_value_ = self->WriteMinidumpWithException( +- self->requesting_thread_id_, self->exception_info_, self->assertion_); ++ if (self->is_shutdown_) { ++ // The instance of the exception handler is being destroyed. ++ break; ++ } else { ++ self->handler_return_value_ = ++ self->WriteMinidumpWithException(self->requesting_thread_id_, ++ self->exception_info_, ++ self->assertion_); ++ } + + // Allow the requesting thread to proceed. + ReleaseSemaphore(self->handler_finish_semaphore_, 1, NULL); + } + } + +- // Not reached. This thread will be terminated by ExceptionHandler's +- // destructor. ++ // This statement is not reached when the thread is unconditionally ++ // terminated by the ExceptionHandler destructor. + return 0; + } + + // HandleException and HandleInvalidParameter must create an + // AutoExceptionHandler object to maintain static state and to determine which + // ExceptionHandler instance to use. The constructor locates the correct + // instance, and makes it available through get_handler(). The destructor + // restores the state in effect prior to allocating the AutoExceptionHandler. +diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.h b/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.h +--- a/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.h ++++ b/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler.h +@@ -335,16 +335,22 @@ class ExceptionHandler { + + // The CRT allows you to override the default handler for pure + // virtual function calls. + _purecall_handler previous_pch_; + + // The exception handler thread. + HANDLE handler_thread_; + ++ // True if the exception handler is being destroyed. ++ // Starting with MSVC 2005, Visual C has stronger guarantees on volatile vars. ++ // It has release semantics on write and acquire semantics on reads. ++ // See the msdn documentation. ++ volatile bool is_shutdown_; ++ + // The critical section enforcing the requirement that only one exception be + // handled by a handler at a time. + CRITICAL_SECTION handler_critical_section_; + + // Semaphores used to move exception handling between the exception thread + // and the handler thread. handler_start_semaphore_ is signalled by the + // exception thread to wake up the handler thread when an exception occurs. + // handler_finish_semaphore_ is signalled by the handler thread to wake up +@@ -385,21 +391,22 @@ class ExceptionHandler { + + // The index of the ExceptionHandler in handler_stack_ that will handle the + // next exception. Note that 0 means the last entry in handler_stack_, 1 + // means the next-to-last entry, and so on. This is used by HandleException + // to support multiple stacked Breakpad handlers. + static LONG handler_stack_index_; + + // handler_stack_critical_section_ guards operations on handler_stack_ and +- // handler_stack_index_. ++ // handler_stack_index_. The critical section is initialized by the ++ // first instance of the class and destroyed by the last instance of it. + static CRITICAL_SECTION handler_stack_critical_section_; + +- // True when handler_stack_critical_section_ has been initialized. +- static bool handler_stack_critical_section_initialized_; ++ // The number of instances of this class. ++ volatile static LONG instance_count_; + + // disallow copy ctor and operator= + explicit ExceptionHandler(const ExceptionHandler &); + void operator=(const ExceptionHandler &); + }; + + } // namespace google_breakpad + +diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler_test/exception_handler_test.cc b/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler_test/exception_handler_test.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler_test/exception_handler_test.cc +@@ -0,0 +1,164 @@ ++// Copyright 2009, 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 "breakpad_googletest_includes.h" ++#include "client/windows/crash_generation/crash_generation_server.h" ++#include "client/windows/handler/exception_handler.h" ++#include ++#include ++#include ++#include ++#include ++ ++namespace { ++const wchar_t kPipeName[] = L"\\\\.\\pipe\\BreakpadCrashTest\\TestCaseServer"; ++const char kSuccessIndicator[] = "success"; ++const char kFailureIndicator[] = "failure"; ++ ++// Utility function to test for a path's existence. ++BOOL DoesPathExist(const TCHAR *path_name); ++ ++class ExceptionHandlerDeathTest : public ::testing::Test { ++protected: ++ // Member variable for each test that they can use ++ // for temporary storage. ++ TCHAR temp_path_[MAX_PATH]; ++ // Actually constructs a temp path name. ++ virtual void SetUp(); ++ // A helper method that tests can use to crash. ++ void DoCrash(); ++}; ++ ++void ExceptionHandlerDeathTest::SetUp() { ++ const ::testing::TestInfo* const test_info = ++ ::testing::UnitTest::GetInstance()->current_test_info(); ++ TCHAR temp_path[MAX_PATH] = { '\0' }; ++ TCHAR test_name_wide[MAX_PATH] = { '\0' }; ++ // We want the temporary directory to be what the OS returns ++ // to us, + the test case name. ++ GetTempPath(MAX_PATH, temp_path); ++ // THe test case name is exposed to use as a c-style string, ++ // But we might be working in UNICODE here on Windows. ++ int dwRet = MultiByteToWideChar(CP_ACP, 0, test_info->name(), ++ (int)strlen(test_info->name()), test_name_wide, MAX_PATH); ++ if (!dwRet) { ++ assert(false); ++ } ++ StringCchPrintfW(temp_path_, MAX_PATH, L"%s%s", temp_path, test_name_wide); ++ CreateDirectory(temp_path_, NULL); ++} ++ ++BOOL DoesPathExist(const TCHAR *path_name) { ++ DWORD flags = GetFileAttributes(path_name); ++ if (flags == INVALID_FILE_ATTRIBUTES) { ++ return FALSE; ++ } ++ return TRUE; ++} ++ ++bool MinidumpWrittenCallback(const wchar_t* dump_path, ++ const wchar_t* minidump_id, ++ void* context, ++ EXCEPTION_POINTERS* exinfo, ++ MDRawAssertionInfo* assertion, ++ bool succeeded) { ++ if (succeeded && DoesPathExist(dump_path)) { ++ fprintf(stderr, kSuccessIndicator); ++ } else { ++ fprintf(stderr, kFailureIndicator); ++ } ++ // If we don't flush, the output doesn't get sent before ++ // this process dies. ++ fflush(stderr); ++ return succeeded; ++} ++ ++TEST_F(ExceptionHandlerDeathTest, InProcTest) { ++ // For the in-proc test, we just need to instantiate an exception ++ // handler in in-proc mode, and crash. Since the entire test is ++ // reexecuted in the child process, we don't have to worry about ++ // the semantics of the exception handler being inherited/not ++ // inherited across CreateProcess(). ++ ASSERT_TRUE(DoesPathExist(temp_path_)); ++ google_breakpad::ExceptionHandler *exc = ++ new google_breakpad::ExceptionHandler( ++ temp_path_, NULL, &MinidumpWrittenCallback, NULL, ++ google_breakpad::ExceptionHandler::HANDLER_ALL); ++ int *i = NULL; ++ ASSERT_DEATH((*i)++, kSuccessIndicator); ++ delete exc; ++} ++ ++static bool gDumpCallbackCalled = false; ++ ++void clientDumpCallback(void *dump_context, ++ const google_breakpad::ClientInfo *client_info, ++ const std::wstring *dump_path){ ++ ++ gDumpCallbackCalled = true; ++} ++ ++void ExceptionHandlerDeathTest::DoCrash() { ++ google_breakpad::ExceptionHandler *exc = ++ new google_breakpad::ExceptionHandler( ++ temp_path_, NULL, NULL, NULL, ++ google_breakpad::ExceptionHandler::HANDLER_ALL, MiniDumpNormal, kPipeName, ++ NULL); ++ // Although this is executing in the child process of the death test, ++ // if it's not true we'll still get an error rather than the crash ++ // being expected. ++ ASSERT_TRUE(exc->IsOutOfProcess()); ++ int *i = NULL; ++ printf("%d\n", (*i)++); ++} ++ ++TEST_F(ExceptionHandlerDeathTest, OutOfProcTest) { ++ // We can take advantage of a detail of google test here to save some ++ // complexity in testing: when you do a death test, it actually forks. ++ // So we can make the main test harness the crash generation server, ++ // and call ASSERT_DEATH on a NULL dereference, it to expecting test ++ // the out of process scenario, since it's happening in a different ++ // process! This is different from the above because, above, we pass ++ // a NULL pipe name, and we also don't start a crash generation server. ++ ++ ASSERT_TRUE(DoesPathExist(temp_path_)); ++ std::wstring dump_path(temp_path_); ++ google_breakpad::CrashGenerationServer server( ++ kPipeName, NULL, NULL, NULL, &clientDumpCallback, NULL, NULL, NULL, true, ++ &dump_path); ++ ++ // This HAS to be EXPECT_, because when this test case is executed in the ++ // child process, the server registration will fail due to the named pipe ++ // being the same. ++ EXPECT_TRUE(server.Start()); ++ EXPECT_FALSE(gDumpCallbackCalled); ++ ASSERT_DEATH(this->DoCrash(), ""); ++ EXPECT_TRUE(gDumpCallbackCalled); ++} ++} +\ No newline at end of file +diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler_test/exception_handler_test.vcproj b/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler_test/exception_handler_test.vcproj +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/client/windows/handler/exception_handler_test/exception_handler_test.vcproj +@@ -0,0 +1,266 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/sender/crash_report_sender.cc b/toolkit/crashreporter/google-breakpad/src/client/windows/sender/crash_report_sender.cc +--- a/toolkit/crashreporter/google-breakpad/src/client/windows/sender/crash_report_sender.cc ++++ b/toolkit/crashreporter/google-breakpad/src/client/windows/sender/crash_report_sender.cc +@@ -64,17 +64,17 @@ ReportResult CrashReportSender::SendCras + if (today == last_sent_date_ && + max_reports_per_day_ != -1 && + reports_sent_ >= max_reports_per_day_) { + return RESULT_THROTTLED; + } + + int http_response = 0; + bool result = HTTPUpload::SendRequest( +- url, parameters, dump_file_name, L"upload_file_minidump", report_code, ++ url, parameters, dump_file_name, L"upload_file_minidump", NULL, report_code, + &http_response); + + if (result) { + ReportSent(today); + return RESULT_SUCCEEDED; + } else if (http_response == 400) { // TODO: update if/when the server + // switches to a different code + return RESULT_REJECTED; +diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/sender/crash_report_sender.vcproj b/toolkit/crashreporter/google-breakpad/src/client/windows/sender/crash_report_sender.vcproj +--- a/toolkit/crashreporter/google-breakpad/src/client/windows/sender/crash_report_sender.vcproj ++++ b/toolkit/crashreporter/google-breakpad/src/client/windows/sender/crash_report_sender.vcproj +@@ -41,18 +41,18 @@ + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="..\..\.." + PreprocessorDefinitions="WIN32;_DEBUG;_LIB;WIN32_LEAN_AND_MEAN" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="3" + UsePrecompiledHeader="0" +- WarningLevel="3" +- Detect64BitPortabilityProblems="true" ++ WarningLevel="4" ++ Detect64BitPortabilityProblems="false" + DebugInformationFormat="4" + /> + + +diff --git a/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.cc b/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.cc +--- a/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.cc ++++ b/toolkit/crashreporter/google-breakpad/src/client/windows/tests/crash_generation_app/crash_generation_app.cc +@@ -178,17 +178,17 @@ bool ShowDumpResults(const wchar_t* dump + int result = swprintf_s(text, + kMaximumLineLength, + TEXT("Dump generation request %s\r\n"), + succeeded ? TEXT("succeeded") : TEXT("failed")); + if (result == -1) { + delete [] text; + } + +- AppendTextWorker(text); ++ QueueUserWorkItem(AppendTextWorker, text, WT_EXECUTEDEFAULT); + return succeeded; + } + + static void _cdecl ShowClientConnected(void* context, + const ClientInfo* client_info) { + TCHAR* line = new TCHAR[kMaximumLineLength]; + line[0] = _T('\0'); + int result = swprintf_s(line, +@@ -462,16 +462,17 @@ int APIENTRY _tWinMain(HINSTANCE instanc + UNREFERENCED_PARAMETER(previous_instance); + UNREFERENCED_PARAMETER(command_line); + + cs_edit = new CRITICAL_SECTION(); + InitializeCriticalSection(cs_edit); + + CustomClientInfo custom_info = {kCustomInfoEntries, kCustomInfoCount}; + ++ CrashServerStart(); + // This is needed for CRT to not show dialog for invalid param + // failures and instead let the code handle it. + _CrtSetReportMode(_CRT_ASSERT, 0); + handler = new ExceptionHandler(L"C:\\dumps\\", + NULL, + google_breakpad::ShowDumpResults, + NULL, + ExceptionHandler::HANDLER_ALL, +diff --git a/toolkit/crashreporter/google-breakpad/src/common/Makefile.in b/toolkit/crashreporter/google-breakpad/src/common/Makefile.in +--- a/toolkit/crashreporter/google-breakpad/src/common/Makefile.in ++++ b/toolkit/crashreporter/google-breakpad/src/common/Makefile.in +@@ -42,16 +42,20 @@ VPATH = @srcdir@ + include $(DEPTH)/config/autoconf.mk + + MODULE = breakpad_common + LIBRARY_NAME = breakpad_common_s + HOST_LIBRARY_NAME = host_breakpad_common_s + + LOCAL_INCLUDES = -I$(srcdir)/.. + ++ifeq ($(OS_ARCH),Darwin) ++DIRS = dwarf ++endif ++ + CPPSRCS = \ + string_conversion.cc \ + $(NULL) + + CSRCS = \ + convert_UTF.c \ + md5.c \ + $(NULL) +@@ -60,14 +64,8 @@ HOST_CPPSRCS = $(CPPSRCS) + + HOST_CSRCS = $(CSRCS) + + # need static lib + FORCE_STATIC_LIB = 1 + FORCE_USE_PIC = 1 + + include $(topsrcdir)/config/rules.mk +- +-# XXX, bug 417045, make -jN combines badly with -save-temps in +-# CFLAGS/CXXFLAGS (for stabs symbols with XCode3) +-ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) +-.NOTPARALLEL: +-endif +diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/Makefile.in b/toolkit/crashreporter/google-breakpad/src/common/dwarf/Makefile.in +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/Makefile.in +@@ -0,0 +1,61 @@ ++# ***** BEGIN LICENSE BLOCK ***** ++# Version: MPL 1.1/GPL 2.0/LGPL 2.1 ++# ++# The contents of this file are subject to the Mozilla Public License Version ++# 1.1 (the "License"); you may not use this file except in compliance with ++# the License. You may obtain a copy of the License at ++# http://www.mozilla.org/MPL/ ++# ++# Software distributed under the License is distributed on an "AS IS" basis, ++# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License ++# for the specific language governing rights and limitations under the ++# License. ++# ++# The Original Code is Mozilla Breakpad integration ++# ++# The Initial Developer of the Original Code is ++# The Mozilla Foundation ++# Portions created by the Initial Developer are Copyright (C) 2008 ++# the Initial Developer. All Rights Reserved. ++# ++# Contributor(s): ++# Ted Mielczarek ++# ++# Alternatively, the contents of this file may be used under the terms of ++# either the GNU General Public License Version 2 or later (the "GPL"), or ++# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), ++# in which case the provisions of the GPL or the LGPL are applicable instead ++# of those above. If you wish to allow use of your version of this file only ++# under the terms of either the GPL or the LGPL, and not to allow others to ++# use your version of this file under the terms of the MPL, indicate your ++# decision by deleting the provisions above and replace them with the notice ++# and other provisions required by the GPL or the LGPL. If you do not delete ++# the provisions above, a recipient may use your version of this file under ++# the terms of any one of the MPL, the GPL or the LGPL. ++# ++# ***** END LICENSE BLOCK ***** ++ ++DEPTH = ../../../../../.. ++topsrcdir = @top_srcdir@ ++srcdir = @srcdir@ ++VPATH = @srcdir@ ++ ++include $(DEPTH)/config/autoconf.mk ++ ++MODULE = breakpad_dwarf ++HOST_LIBRARY_NAME = host_breakpad_dwarf_s ++ ++LOCAL_INCLUDES = -I$(srcdir)/../.. ++ ++HOST_CPPSRCS = \ ++ bytereader.cc \ ++ dwarf2reader.cc \ ++ functioninfo.cc \ ++ $(NULL) ++ ++HOST_CXXFLAGS += -funsigned-char ++ ++# need static lib ++FORCE_STATIC_LIB = 1 ++ ++include $(topsrcdir)/config/rules.mk +diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader-inl.h b/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader-inl.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader-inl.h +@@ -0,0 +1,149 @@ ++// Copyright 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. ++ ++#ifndef UTIL_DEBUGINFO_BYTEREADER_INL_H__ ++#define UTIL_DEBUGINFO_BYTEREADER_INL_H__ ++ ++#include ++ ++#include "common/dwarf/bytereader.h" ++ ++namespace dwarf2reader { ++ ++inline uint8 ByteReader::ReadOneByte(const char* buffer) const { ++ return buffer[0]; ++} ++ ++inline uint16 ByteReader::ReadTwoBytes(const char* signed_buffer) const { ++ const unsigned char *buffer ++ = reinterpret_cast(signed_buffer); ++ const uint16 buffer0 = buffer[0]; ++ const uint16 buffer1 = buffer[1]; ++ if (endian_ == ENDIANNESS_LITTLE) { ++ return buffer0 | buffer1 << 8; ++ } else { ++ return buffer1 | buffer0 << 8; ++ } ++} ++ ++inline uint64 ByteReader::ReadFourBytes(const char* signed_buffer) const { ++ const unsigned char *buffer ++ = reinterpret_cast(signed_buffer); ++ const uint32 buffer0 = buffer[0]; ++ const uint32 buffer1 = buffer[1]; ++ const uint32 buffer2 = buffer[2]; ++ const uint32 buffer3 = buffer[3]; ++ if (endian_ == ENDIANNESS_LITTLE) { ++ return buffer0 | buffer1 << 8 | buffer2 << 16 | buffer3 << 24; ++ } else { ++ return buffer3 | buffer2 << 8 | buffer1 << 16 | buffer0 << 24; ++ } ++} ++ ++inline uint64 ByteReader::ReadEightBytes(const char* signed_buffer) const { ++ const unsigned char *buffer ++ = reinterpret_cast(signed_buffer); ++ const uint64 buffer0 = buffer[0]; ++ const uint64 buffer1 = buffer[1]; ++ const uint64 buffer2 = buffer[2]; ++ const uint64 buffer3 = buffer[3]; ++ const uint64 buffer4 = buffer[4]; ++ const uint64 buffer5 = buffer[5]; ++ const uint64 buffer6 = buffer[6]; ++ const uint64 buffer7 = buffer[7]; ++ if (endian_ == ENDIANNESS_LITTLE) { ++ return buffer0 | buffer1 << 8 | buffer2 << 16 | buffer3 << 24 | ++ buffer4 << 32 | buffer5 << 40 | buffer6 << 48 | buffer7 << 56; ++ } else { ++ return buffer7 | buffer6 << 8 | buffer5 << 16 | buffer4 << 24 | ++ buffer3 << 32 | buffer2 << 40 | buffer1 << 48 | buffer0 << 56; ++ } ++} ++ ++// Read an unsigned LEB128 number. Each byte contains 7 bits of ++// information, plus one bit saying whether the number continues or ++// not. ++ ++inline uint64 ByteReader::ReadUnsignedLEB128(const char* buffer, ++ size_t* len) const { ++ uint64 result = 0; ++ size_t num_read = 0; ++ unsigned int shift = 0; ++ unsigned char byte; ++ ++ do { ++ byte = *buffer++; ++ num_read++; ++ ++ result |= (static_cast(byte & 0x7f)) << shift; ++ ++ shift += 7; ++ ++ } while (byte & 0x80); ++ ++ *len = num_read; ++ ++ return result; ++} ++ ++// Read a signed LEB128 number. These are like regular LEB128 ++// numbers, except the last byte may have a sign bit set. ++ ++inline int64 ByteReader::ReadSignedLEB128(const char* buffer, ++ size_t* len) const { ++ int64 result = 0; ++ unsigned int shift = 0; ++ size_t num_read = 0; ++ unsigned char byte; ++ ++ do { ++ byte = *buffer++; ++ num_read++; ++ result |= (static_cast(byte & 0x7f) << shift); ++ shift += 7; ++ } while (byte & 0x80); ++ ++ if ((shift < 8 * sizeof (result)) && (byte & 0x40)) ++ result |= -((static_cast(1)) << shift); ++ *len = num_read; ++ return result; ++} ++ ++inline uint64 ByteReader::ReadOffset(const char* buffer) const { ++ assert(this->offset_reader_); ++ return (this->*offset_reader_)(buffer); ++} ++ ++inline uint64 ByteReader::ReadAddress(const char* buffer) const { ++ assert(this->address_reader_); ++ return (this->*address_reader_)(buffer); ++} ++ ++} // namespace dwarf2reader ++ ++#endif // UTIL_DEBUGINFO_BYTEREADER_INL_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader.cc b/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader.cc +@@ -0,0 +1,63 @@ ++// Copyright 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. ++ ++#include ++ ++#include "common/dwarf/bytereader-inl.h" ++#include "common/dwarf/bytereader.h" ++ ++namespace dwarf2reader { ++ ++ByteReader::ByteReader(enum Endianness endian) ++ :offset_reader_(NULL), address_reader_(NULL), endian_(endian), ++ address_size_(0), offset_size_(0) ++{ } ++ ++ByteReader::~ByteReader() { } ++ ++void ByteReader::SetOffsetSize(uint8 size) { ++ offset_size_ = size; ++ assert(size == 4 || size == 8); ++ if (size == 4) { ++ this->offset_reader_ = &ByteReader::ReadFourBytes; ++ } else { ++ this->offset_reader_ = &ByteReader::ReadEightBytes; ++ } ++} ++ ++void ByteReader::SetAddressSize(uint8 size) { ++ address_size_ = size; ++ assert(size == 4 || size == 8); ++ if (size == 4) { ++ this->address_reader_ = &ByteReader::ReadFourBytes; ++ } else { ++ this->address_reader_ = &ByteReader::ReadEightBytes; ++ } ++} ++ ++} // namespace dwarf2reader +diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader.h b/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader.h +@@ -0,0 +1,132 @@ ++// Copyright 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. ++ ++#ifndef COMMON_DWARF_BYTEREADER_H__ ++#define COMMON_DWARF_BYTEREADER_H__ ++ ++#include ++#include "common/dwarf/types.h" ++ ++namespace dwarf2reader { ++ ++// We can't use the obvious name of LITTLE_ENDIAN and BIG_ENDIAN ++// because it conflicts with a macro ++enum Endianness { ++ ENDIANNESS_BIG, ++ ENDIANNESS_LITTLE ++}; ++ ++// Class that knows how to read both big endian and little endian ++// numbers, for use in DWARF2/3 reader. ++// Takes an endianness argument. ++// To read addresses and offsets, SetAddressSize and SetOffsetSize ++// must be called first. ++class ByteReader { ++ public: ++ explicit ByteReader(enum Endianness endian); ++ virtual ~ByteReader(); ++ ++ // Set the address size to SIZE, which sets up the ReadAddress member ++ // so that it works. ++ void SetAddressSize(uint8 size); ++ ++ // Set the offset size to SIZE, which sets up the ReadOffset member ++ // so that it works. ++ void SetOffsetSize(uint8 size); ++ ++ // Return the current offset size ++ uint8 OffsetSize() const { return offset_size_; } ++ ++ // Return the current address size ++ uint8 AddressSize() const { return address_size_; } ++ ++ // Read a single byte from BUFFER and return it as an unsigned 8 bit ++ // number. ++ uint8 ReadOneByte(const char* buffer) const; ++ ++ // Read two bytes from BUFFER and return it as an unsigned 16 bit ++ // number. ++ uint16 ReadTwoBytes(const char* buffer) const; ++ ++ // Read four bytes from BUFFER and return it as an unsigned 32 bit ++ // number. This function returns a uint64 so that it is compatible ++ // with ReadAddress and ReadOffset. The number it returns will ++ // never be outside the range of an unsigned 32 bit integer. ++ uint64 ReadFourBytes(const char* buffer) const; ++ ++ // Read eight bytes from BUFFER and return it as an unsigned 64 bit ++ // number ++ uint64 ReadEightBytes(const char* buffer) const; ++ ++ // Read an unsigned LEB128 (Little Endian Base 128) number from ++ // BUFFER and return it as an unsigned 64 bit integer. LEN is set ++ // to the length read. Everybody seems to reinvent LEB128 as a ++ // variable size integer encoding, DWARF has had it for a long time. ++ uint64 ReadUnsignedLEB128(const char* buffer, size_t* len) const; ++ ++ // Read a signed LEB128 number from BUFFER and return it as an ++ // signed 64 bit integer. LEN is set to the length read. ++ int64 ReadSignedLEB128(const char* buffer, size_t* len) const; ++ ++ // Read an offset from BUFFER and return it as an unsigned 64 bit ++ // integer. DWARF2/3 define offsets as either 4 or 8 bytes, ++ // generally depending on the amount of DWARF2/3 info present. ++ uint64 ReadOffset(const char* buffer) const; ++ ++ // Read an address from BUFFER and return it as an unsigned 64 bit ++ // integer. DWARF2/3 allow addresses to be any size from 0-255 ++ // bytes currently. Internally we support 4 and 8 byte addresses, ++ // and will CHECK on anything else. ++ uint64 ReadAddress(const char* buffer) const; ++ ++ private: ++ ++ // Function pointer type for our address and offset readers. ++ typedef uint64 (ByteReader::*AddressReader)(const char*) const; ++ ++ // Read an offset from BUFFER and return it as an unsigned 64 bit ++ // integer. DWARF2/3 define offsets as either 4 or 8 bytes, ++ // generally depending on the amount of DWARF2/3 info present. ++ // This function pointer gets set by SetOffsetSize. ++ AddressReader offset_reader_; ++ ++ // Read an address from BUFFER and return it as an unsigned 64 bit ++ // integer. DWARF2/3 allow addresses to be any size from 0-255 ++ // bytes currently. Internally we support 4 and 8 byte addresses, ++ // and will CHECK on anything else. ++ // This function pointer gets set by SetAddressSize. ++ AddressReader address_reader_; ++ ++ Endianness endian_; ++ uint8 address_size_; ++ uint8 offset_size_; ++}; ++ ++} // namespace dwarf2reader ++ ++#endif // COMMON_DWARF_BYTEREADER_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2enums.h b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2enums.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2enums.h +@@ -0,0 +1,490 @@ ++// Copyright 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. ++ ++#ifndef COMMON_DWARF_DWARF2ENUMS_H__ ++#define COMMON_DWARF_DWARF2ENUMS_H__ ++ ++namespace dwarf2reader { ++ ++// These enums do not follow the google3 style only because they are ++// known universally (specs, other implementations) by the names in ++// exactly this capitalization. ++// Tag names and codes. ++enum DwarfTag { ++ DW_TAG_padding = 0x00, ++ DW_TAG_array_type = 0x01, ++ DW_TAG_class_type = 0x02, ++ DW_TAG_entry_point = 0x03, ++ DW_TAG_enumeration_type = 0x04, ++ DW_TAG_formal_parameter = 0x05, ++ DW_TAG_imported_declaration = 0x08, ++ DW_TAG_label = 0x0a, ++ DW_TAG_lexical_block = 0x0b, ++ DW_TAG_member = 0x0d, ++ DW_TAG_pointer_type = 0x0f, ++ DW_TAG_reference_type = 0x10, ++ DW_TAG_compile_unit = 0x11, ++ DW_TAG_string_type = 0x12, ++ DW_TAG_structure_type = 0x13, ++ DW_TAG_subroutine_type = 0x15, ++ DW_TAG_typedef = 0x16, ++ DW_TAG_union_type = 0x17, ++ DW_TAG_unspecified_parameters = 0x18, ++ DW_TAG_variant = 0x19, ++ DW_TAG_common_block = 0x1a, ++ DW_TAG_common_inclusion = 0x1b, ++ DW_TAG_inheritance = 0x1c, ++ DW_TAG_inlined_subroutine = 0x1d, ++ DW_TAG_module = 0x1e, ++ DW_TAG_ptr_to_member_type = 0x1f, ++ DW_TAG_set_type = 0x20, ++ DW_TAG_subrange_type = 0x21, ++ DW_TAG_with_stmt = 0x22, ++ DW_TAG_access_declaration = 0x23, ++ DW_TAG_base_type = 0x24, ++ DW_TAG_catch_block = 0x25, ++ DW_TAG_const_type = 0x26, ++ DW_TAG_constant = 0x27, ++ DW_TAG_enumerator = 0x28, ++ DW_TAG_file_type = 0x29, ++ DW_TAG_friend = 0x2a, ++ DW_TAG_namelist = 0x2b, ++ DW_TAG_namelist_item = 0x2c, ++ DW_TAG_packed_type = 0x2d, ++ DW_TAG_subprogram = 0x2e, ++ DW_TAG_template_type_param = 0x2f, ++ DW_TAG_template_value_param = 0x30, ++ DW_TAG_thrown_type = 0x31, ++ DW_TAG_try_block = 0x32, ++ DW_TAG_variant_part = 0x33, ++ DW_TAG_variable = 0x34, ++ DW_TAG_volatile_type = 0x35, ++ // DWARF 3. ++ DW_TAG_dwarf_procedure = 0x36, ++ DW_TAG_restrict_type = 0x37, ++ DW_TAG_interface_type = 0x38, ++ DW_TAG_namespace = 0x39, ++ DW_TAG_imported_module = 0x3a, ++ DW_TAG_unspecified_type = 0x3b, ++ DW_TAG_partial_unit = 0x3c, ++ DW_TAG_imported_unit = 0x3d, ++ // SGI/MIPS Extensions. ++ DW_TAG_MIPS_loop = 0x4081, ++ // HP extensions. See: ++ // ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz ++ DW_TAG_HP_array_descriptor = 0x4090, ++ // GNU extensions. ++ DW_TAG_format_label = 0x4101, // For FORTRAN 77 and Fortran 90. ++ DW_TAG_function_template = 0x4102, // For C++. ++ DW_TAG_class_template = 0x4103, // For C++. ++ DW_TAG_GNU_BINCL = 0x4104, ++ DW_TAG_GNU_EINCL = 0x4105, ++ // Extensions for UPC. See: http://upc.gwu.edu/~upc. ++ DW_TAG_upc_shared_type = 0x8765, ++ DW_TAG_upc_strict_type = 0x8766, ++ DW_TAG_upc_relaxed_type = 0x8767, ++ // PGI (STMicroelectronics) extensions. No documentation available. ++ DW_TAG_PGI_kanji_type = 0xA000, ++ DW_TAG_PGI_interface_block = 0xA020 ++}; ++ ++ ++enum DwarfHasChild { ++ DW_children_no = 0, ++ DW_children_yes = 1 ++}; ++ ++// Form names and codes. ++enum DwarfForm { ++ DW_FORM_addr = 0x01, ++ DW_FORM_block2 = 0x03, ++ DW_FORM_block4 = 0x04, ++ DW_FORM_data2 = 0x05, ++ DW_FORM_data4 = 0x06, ++ DW_FORM_data8 = 0x07, ++ DW_FORM_string = 0x08, ++ DW_FORM_block = 0x09, ++ DW_FORM_block1 = 0x0a, ++ DW_FORM_data1 = 0x0b, ++ DW_FORM_flag = 0x0c, ++ DW_FORM_sdata = 0x0d, ++ DW_FORM_strp = 0x0e, ++ DW_FORM_udata = 0x0f, ++ DW_FORM_ref_addr = 0x10, ++ DW_FORM_ref1 = 0x11, ++ DW_FORM_ref2 = 0x12, ++ DW_FORM_ref4 = 0x13, ++ DW_FORM_ref8 = 0x14, ++ DW_FORM_ref_udata = 0x15, ++ DW_FORM_indirect = 0x16 ++}; ++ ++// Attribute names and codes ++enum DwarfAttribute { ++ DW_AT_sibling = 0x01, ++ DW_AT_location = 0x02, ++ DW_AT_name = 0x03, ++ DW_AT_ordering = 0x09, ++ DW_AT_subscr_data = 0x0a, ++ DW_AT_byte_size = 0x0b, ++ DW_AT_bit_offset = 0x0c, ++ DW_AT_bit_size = 0x0d, ++ DW_AT_element_list = 0x0f, ++ DW_AT_stmt_list = 0x10, ++ DW_AT_low_pc = 0x11, ++ DW_AT_high_pc = 0x12, ++ DW_AT_language = 0x13, ++ DW_AT_member = 0x14, ++ DW_AT_discr = 0x15, ++ DW_AT_discr_value = 0x16, ++ DW_AT_visibility = 0x17, ++ DW_AT_import = 0x18, ++ DW_AT_string_length = 0x19, ++ DW_AT_common_reference = 0x1a, ++ DW_AT_comp_dir = 0x1b, ++ DW_AT_const_value = 0x1c, ++ DW_AT_containing_type = 0x1d, ++ DW_AT_default_value = 0x1e, ++ DW_AT_inline = 0x20, ++ DW_AT_is_optional = 0x21, ++ DW_AT_lower_bound = 0x22, ++ DW_AT_producer = 0x25, ++ DW_AT_prototyped = 0x27, ++ DW_AT_return_addr = 0x2a, ++ DW_AT_start_scope = 0x2c, ++ DW_AT_stride_size = 0x2e, ++ DW_AT_upper_bound = 0x2f, ++ DW_AT_abstract_origin = 0x31, ++ DW_AT_accessibility = 0x32, ++ DW_AT_address_class = 0x33, ++ DW_AT_artificial = 0x34, ++ DW_AT_base_types = 0x35, ++ DW_AT_calling_convention = 0x36, ++ DW_AT_count = 0x37, ++ DW_AT_data_member_location = 0x38, ++ DW_AT_decl_column = 0x39, ++ DW_AT_decl_file = 0x3a, ++ DW_AT_decl_line = 0x3b, ++ DW_AT_declaration = 0x3c, ++ DW_AT_discr_list = 0x3d, ++ DW_AT_encoding = 0x3e, ++ DW_AT_external = 0x3f, ++ DW_AT_frame_base = 0x40, ++ DW_AT_friend = 0x41, ++ DW_AT_identifier_case = 0x42, ++ DW_AT_macro_info = 0x43, ++ DW_AT_namelist_items = 0x44, ++ DW_AT_priority = 0x45, ++ DW_AT_segment = 0x46, ++ DW_AT_specification = 0x47, ++ DW_AT_static_link = 0x48, ++ DW_AT_type = 0x49, ++ DW_AT_use_location = 0x4a, ++ DW_AT_variable_parameter = 0x4b, ++ DW_AT_virtuality = 0x4c, ++ DW_AT_vtable_elem_location = 0x4d, ++ // DWARF 3 values. ++ DW_AT_allocated = 0x4e, ++ DW_AT_associated = 0x4f, ++ DW_AT_data_location = 0x50, ++ DW_AT_stride = 0x51, ++ DW_AT_entry_pc = 0x52, ++ DW_AT_use_UTF8 = 0x53, ++ DW_AT_extension = 0x54, ++ DW_AT_ranges = 0x55, ++ DW_AT_trampoline = 0x56, ++ DW_AT_call_column = 0x57, ++ DW_AT_call_file = 0x58, ++ DW_AT_call_line = 0x59, ++ // SGI/MIPS extensions. ++ DW_AT_MIPS_fde = 0x2001, ++ DW_AT_MIPS_loop_begin = 0x2002, ++ DW_AT_MIPS_tail_loop_begin = 0x2003, ++ DW_AT_MIPS_epilog_begin = 0x2004, ++ DW_AT_MIPS_loop_unroll_factor = 0x2005, ++ DW_AT_MIPS_software_pipeline_depth = 0x2006, ++ DW_AT_MIPS_linkage_name = 0x2007, ++ DW_AT_MIPS_stride = 0x2008, ++ DW_AT_MIPS_abstract_name = 0x2009, ++ DW_AT_MIPS_clone_origin = 0x200a, ++ DW_AT_MIPS_has_inlines = 0x200b, ++ // HP extensions. ++ DW_AT_HP_block_index = 0x2000, ++ DW_AT_HP_unmodifiable = 0x2001, // Same as DW_AT_MIPS_fde. ++ DW_AT_HP_actuals_stmt_list = 0x2010, ++ DW_AT_HP_proc_per_section = 0x2011, ++ DW_AT_HP_raw_data_ptr = 0x2012, ++ DW_AT_HP_pass_by_reference = 0x2013, ++ DW_AT_HP_opt_level = 0x2014, ++ DW_AT_HP_prof_version_id = 0x2015, ++ DW_AT_HP_opt_flags = 0x2016, ++ DW_AT_HP_cold_region_low_pc = 0x2017, ++ DW_AT_HP_cold_region_high_pc = 0x2018, ++ DW_AT_HP_all_variables_modifiable = 0x2019, ++ DW_AT_HP_linkage_name = 0x201a, ++ DW_AT_HP_prof_flags = 0x201b, // In comp unit of procs_info for -g. ++ // GNU extensions. ++ DW_AT_sf_names = 0x2101, ++ DW_AT_src_info = 0x2102, ++ DW_AT_mac_info = 0x2103, ++ DW_AT_src_coords = 0x2104, ++ DW_AT_body_begin = 0x2105, ++ DW_AT_body_end = 0x2106, ++ DW_AT_GNU_vector = 0x2107, ++ // VMS extensions. ++ DW_AT_VMS_rtnbeg_pd_address = 0x2201, ++ // UPC extension. ++ DW_AT_upc_threads_scaled = 0x3210, ++ // PGI (STMicroelectronics) extensions. ++ DW_AT_PGI_lbase = 0x3a00, ++ DW_AT_PGI_soffset = 0x3a01, ++ DW_AT_PGI_lstride = 0x3a02 ++}; ++ ++ ++// Line number opcodes. ++enum DwarfLineNumberOps { ++ DW_LNS_extended_op = 0, ++ DW_LNS_copy = 1, ++ DW_LNS_advance_pc = 2, ++ DW_LNS_advance_line = 3, ++ DW_LNS_set_file = 4, ++ DW_LNS_set_column = 5, ++ DW_LNS_negate_stmt = 6, ++ DW_LNS_set_basic_block = 7, ++ DW_LNS_const_add_pc = 8, ++ DW_LNS_fixed_advance_pc = 9, ++ // DWARF 3. ++ DW_LNS_set_prologue_end = 10, ++ DW_LNS_set_epilogue_begin = 11, ++ DW_LNS_set_isa = 12 ++}; ++ ++// Line number extended opcodes. ++enum DwarfLineNumberExtendedOps { ++ DW_LNE_end_sequence = 1, ++ DW_LNE_set_address = 2, ++ DW_LNE_define_file = 3, ++ // HP extensions. ++ DW_LNE_HP_negate_is_UV_update = 0x11, ++ DW_LNE_HP_push_context = 0x12, ++ DW_LNE_HP_pop_context = 0x13, ++ DW_LNE_HP_set_file_line_column = 0x14, ++ DW_LNE_HP_set_routine_name = 0x15, ++ DW_LNE_HP_set_sequence = 0x16, ++ DW_LNE_HP_negate_post_semantics = 0x17, ++ DW_LNE_HP_negate_function_exit = 0x18, ++ DW_LNE_HP_negate_front_end_logical = 0x19, ++ DW_LNE_HP_define_proc = 0x20 ++}; ++ ++// Type encoding names and codes ++enum DwarfEncoding { ++ DW_ATE_address =0x1, ++ DW_ATE_boolean =0x2, ++ DW_ATE_complex_float =0x3, ++ DW_ATE_float =0x4, ++ DW_ATE_signed =0x5, ++ DW_ATE_signed_char =0x6, ++ DW_ATE_unsigned =0x7, ++ DW_ATE_unsigned_char =0x8, ++ // DWARF3/DWARF3f ++ DW_ATE_imaginary_float =0x9, ++ DW_ATE_packed_decimal =0xa, ++ DW_ATE_numeric_string =0xb, ++ DW_ATE_edited =0xc, ++ DW_ATE_signed_fixed =0xd, ++ DW_ATE_unsigned_fixed =0xe, ++ DW_ATE_decimal_float =0xf, ++ DW_ATE_lo_user =0x80, ++ DW_ATE_hi_user =0xff ++}; ++ ++// Location virtual machine opcodes ++enum DwarfOpcode { ++ DW_OP_addr =0x03, ++ DW_OP_deref =0x06, ++ DW_OP_const1u =0x08, ++ DW_OP_const1s =0x09, ++ DW_OP_const2u =0x0a, ++ DW_OP_const2s =0x0b, ++ DW_OP_const4u =0x0c, ++ DW_OP_const4s =0x0d, ++ DW_OP_const8u =0x0e, ++ DW_OP_const8s =0x0f, ++ DW_OP_constu =0x10, ++ DW_OP_consts =0x11, ++ DW_OP_dup =0x12, ++ DW_OP_drop =0x13, ++ DW_OP_over =0x14, ++ DW_OP_pick =0x15, ++ DW_OP_swap =0x16, ++ DW_OP_rot =0x17, ++ DW_OP_xderef =0x18, ++ DW_OP_abs =0x19, ++ DW_OP_and =0x1a, ++ DW_OP_div =0x1b, ++ DW_OP_minus =0x1c, ++ DW_OP_mod =0x1d, ++ DW_OP_mul =0x1e, ++ DW_OP_neg =0x1f, ++ DW_OP_not =0x20, ++ DW_OP_or =0x21, ++ DW_OP_plus =0x22, ++ DW_OP_plus_uconst =0x23, ++ DW_OP_shl =0x24, ++ DW_OP_shr =0x25, ++ DW_OP_shra =0x26, ++ DW_OP_xor =0x27, ++ DW_OP_bra =0x28, ++ DW_OP_eq =0x29, ++ DW_OP_ge =0x2a, ++ DW_OP_gt =0x2b, ++ DW_OP_le =0x2c, ++ DW_OP_lt =0x2d, ++ DW_OP_ne =0x2e, ++ DW_OP_skip =0x2f, ++ DW_OP_lit0 =0x30, ++ DW_OP_lit1 =0x31, ++ DW_OP_lit2 =0x32, ++ DW_OP_lit3 =0x33, ++ DW_OP_lit4 =0x34, ++ DW_OP_lit5 =0x35, ++ DW_OP_lit6 =0x36, ++ DW_OP_lit7 =0x37, ++ DW_OP_lit8 =0x38, ++ DW_OP_lit9 =0x39, ++ DW_OP_lit10 =0x3a, ++ DW_OP_lit11 =0x3b, ++ DW_OP_lit12 =0x3c, ++ DW_OP_lit13 =0x3d, ++ DW_OP_lit14 =0x3e, ++ DW_OP_lit15 =0x3f, ++ DW_OP_lit16 =0x40, ++ DW_OP_lit17 =0x41, ++ DW_OP_lit18 =0x42, ++ DW_OP_lit19 =0x43, ++ DW_OP_lit20 =0x44, ++ DW_OP_lit21 =0x45, ++ DW_OP_lit22 =0x46, ++ DW_OP_lit23 =0x47, ++ DW_OP_lit24 =0x48, ++ DW_OP_lit25 =0x49, ++ DW_OP_lit26 =0x4a, ++ DW_OP_lit27 =0x4b, ++ DW_OP_lit28 =0x4c, ++ DW_OP_lit29 =0x4d, ++ DW_OP_lit30 =0x4e, ++ DW_OP_lit31 =0x4f, ++ DW_OP_reg0 =0x50, ++ DW_OP_reg1 =0x51, ++ DW_OP_reg2 =0x52, ++ DW_OP_reg3 =0x53, ++ DW_OP_reg4 =0x54, ++ DW_OP_reg5 =0x55, ++ DW_OP_reg6 =0x56, ++ DW_OP_reg7 =0x57, ++ DW_OP_reg8 =0x58, ++ DW_OP_reg9 =0x59, ++ DW_OP_reg10 =0x5a, ++ DW_OP_reg11 =0x5b, ++ DW_OP_reg12 =0x5c, ++ DW_OP_reg13 =0x5d, ++ DW_OP_reg14 =0x5e, ++ DW_OP_reg15 =0x5f, ++ DW_OP_reg16 =0x60, ++ DW_OP_reg17 =0x61, ++ DW_OP_reg18 =0x62, ++ DW_OP_reg19 =0x63, ++ DW_OP_reg20 =0x64, ++ DW_OP_reg21 =0x65, ++ DW_OP_reg22 =0x66, ++ DW_OP_reg23 =0x67, ++ DW_OP_reg24 =0x68, ++ DW_OP_reg25 =0x69, ++ DW_OP_reg26 =0x6a, ++ DW_OP_reg27 =0x6b, ++ DW_OP_reg28 =0x6c, ++ DW_OP_reg29 =0x6d, ++ DW_OP_reg30 =0x6e, ++ DW_OP_reg31 =0x6f, ++ DW_OP_breg0 =0x70, ++ DW_OP_breg1 =0x71, ++ DW_OP_breg2 =0x72, ++ DW_OP_breg3 =0x73, ++ DW_OP_breg4 =0x74, ++ DW_OP_breg5 =0x75, ++ DW_OP_breg6 =0x76, ++ DW_OP_breg7 =0x77, ++ DW_OP_breg8 =0x78, ++ DW_OP_breg9 =0x79, ++ DW_OP_breg10 =0x7a, ++ DW_OP_breg11 =0x7b, ++ DW_OP_breg12 =0x7c, ++ DW_OP_breg13 =0x7d, ++ DW_OP_breg14 =0x7e, ++ DW_OP_breg15 =0x7f, ++ DW_OP_breg16 =0x80, ++ DW_OP_breg17 =0x81, ++ DW_OP_breg18 =0x82, ++ DW_OP_breg19 =0x83, ++ DW_OP_breg20 =0x84, ++ DW_OP_breg21 =0x85, ++ DW_OP_breg22 =0x86, ++ DW_OP_breg23 =0x87, ++ DW_OP_breg24 =0x88, ++ DW_OP_breg25 =0x89, ++ DW_OP_breg26 =0x8a, ++ DW_OP_breg27 =0x8b, ++ DW_OP_breg28 =0x8c, ++ DW_OP_breg29 =0x8d, ++ DW_OP_breg30 =0x8e, ++ DW_OP_breg31 =0x8f, ++ DW_OP_regX =0x90, ++ DW_OP_fbreg =0x91, ++ DW_OP_bregX =0x92, ++ DW_OP_piece =0x93, ++ DW_OP_deref_size =0x94, ++ DW_OP_xderef_size =0x95, ++ DW_OP_nop =0x96, ++ // DWARF3/DWARF3f ++ DW_OP_push_object_address =0x97, ++ DW_OP_call2 =0x98, ++ DW_OP_call4 =0x99, ++ DW_OP_call_ref =0x9a, ++ DW_OP_form_tls_address =0x9b, ++ DW_OP_call_frame_cfa =0x9c, ++ DW_OP_bit_piece =0x9d, ++ DW_OP_lo_user =0xe0, ++ DW_OP_hi_user =0xff, ++ // GNU extensions ++ DW_OP_GNU_push_tls_address =0xe0 ++}; ++ ++} // namespace dwarf2reader ++#endif // COMMON_DWARF_DWARF2ENUMS_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader.cc b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader.cc +@@ -0,0 +1,825 @@ ++// Copyright 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. ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "common/dwarf/bytereader-inl.h" ++#include "common/dwarf/dwarf2reader.h" ++#include "common/dwarf/bytereader.h" ++#include "common/dwarf/line_state_machine.h" ++ ++namespace dwarf2reader { ++ ++// Read a DWARF2/3 initial length field from START, using READER, and ++// report the length in LEN. Return the actual initial length. ++ ++static uint64 ReadInitialLength(const char* start, ++ ByteReader* reader, size_t* len) { ++ const uint64 initial_length = reader->ReadFourBytes(start); ++ start += 4; ++ ++ // In DWARF2/3, if the initial length is all 1 bits, then the offset ++ // size is 8 and we need to read the next 8 bytes for the real length. ++ if (initial_length == 0xffffffff) { ++ reader->SetOffsetSize(8); ++ *len = 12; ++ return reader->ReadOffset(start); ++ } else { ++ reader->SetOffsetSize(4); ++ *len = 4; ++ } ++ return initial_length; ++} ++ ++CompilationUnit::CompilationUnit(const SectionMap& sections, uint64 offset, ++ ByteReader* reader, Dwarf2Handler* handler) ++ : offset_from_section_start_(offset), reader_(reader), ++ sections_(sections), handler_(handler), abbrevs_(NULL), ++ string_buffer_(NULL), string_buffer_length_(0) {} ++ ++// Read a DWARF2/3 abbreviation section. ++// Each abbrev consists of a abbreviation number, a tag, a byte ++// specifying whether the tag has children, and a list of ++// attribute/form pairs. ++// The list of forms is terminated by a 0 for the attribute, and a ++// zero for the form. The entire abbreviation section is terminated ++// by a zero for the code. ++ ++void CompilationUnit::ReadAbbrevs() { ++ if (abbrevs_) ++ return; ++ ++ // First get the debug_abbrev section ++ SectionMap::const_iterator iter = sections_.find("__debug_abbrev"); ++ assert(iter != sections_.end()); ++ ++ abbrevs_ = new vector; ++ abbrevs_->resize(1); ++ ++ // The only way to check whether we are reading over the end of the ++ // buffer would be to first compute the size of the leb128 data by ++ // reading it, then go back and read it again. ++ const char* abbrev_start = iter->second.first + ++ header_.abbrev_offset; ++ const char* abbrevptr = abbrev_start; ++#ifndef NDEBUG ++ const uint64 abbrev_length = iter->second.second - header_.abbrev_offset; ++#endif ++ ++ while (1) { ++ CompilationUnit::Abbrev abbrev; ++ size_t len; ++ const uint32 number = reader_->ReadUnsignedLEB128(abbrevptr, &len); ++ ++ if (number == 0) ++ break; ++ abbrev.number = number; ++ abbrevptr += len; ++ ++ assert(abbrevptr < abbrev_start + abbrev_length); ++ const uint32 tag = reader_->ReadUnsignedLEB128(abbrevptr, &len); ++ abbrevptr += len; ++ abbrev.tag = static_cast(tag); ++ ++ assert(abbrevptr < abbrev_start + abbrev_length); ++ abbrev.has_children = reader_->ReadOneByte(abbrevptr); ++ abbrevptr += 1; ++ ++ assert(abbrevptr < abbrev_start + abbrev_length); ++ ++ while (1) { ++ const uint32 nametemp = reader_->ReadUnsignedLEB128(abbrevptr, &len); ++ abbrevptr += len; ++ ++ assert(abbrevptr < abbrev_start + abbrev_length); ++ const uint32 formtemp = reader_->ReadUnsignedLEB128(abbrevptr, &len); ++ abbrevptr += len; ++ if (nametemp == 0 && formtemp == 0) ++ break; ++ ++ const enum DwarfAttribute name = ++ static_cast(nametemp); ++ const enum DwarfForm form = static_cast(formtemp); ++ abbrev.attributes.push_back(make_pair(name, form)); ++ } ++ assert(abbrev.number == abbrevs_->size()); ++ abbrevs_->push_back(abbrev); ++ } ++} ++ ++// Skips a single DIE's attributes. ++const char* CompilationUnit::SkipDIE(const char* start, ++ const Abbrev& abbrev) { ++ for (AttributeList::const_iterator i = abbrev.attributes.begin(); ++ i != abbrev.attributes.end(); ++ i++) { ++ start = SkipAttribute(start, i->second); ++ } ++ return start; ++} ++ ++// Skips a single attribute form's data. ++const char* CompilationUnit::SkipAttribute(const char* start, ++ enum DwarfForm form) { ++ size_t len; ++ ++ switch (form) { ++ case DW_FORM_indirect: ++ form = static_cast(reader_->ReadUnsignedLEB128(start, ++ &len)); ++ start += len; ++ return SkipAttribute(start, form); ++ break; ++ ++ case DW_FORM_data1: ++ case DW_FORM_flag: ++ case DW_FORM_ref1: ++ return start + 1; ++ break; ++ case DW_FORM_ref2: ++ case DW_FORM_data2: ++ return start + 2; ++ break; ++ case DW_FORM_ref4: ++ case DW_FORM_data4: ++ return start + 4; ++ break; ++ case DW_FORM_ref8: ++ case DW_FORM_data8: ++ return start + 8; ++ break; ++ case DW_FORM_string: ++ return start + strlen(start) + 1; ++ break; ++ case DW_FORM_udata: ++ case DW_FORM_ref_udata: ++ reader_->ReadUnsignedLEB128(start, &len); ++ return start + len; ++ break; ++ ++ case DW_FORM_sdata: ++ reader_->ReadSignedLEB128(start, &len); ++ return start + len; ++ break; ++ case DW_FORM_addr: ++ return start + reader_->AddressSize(); ++ break; ++ case DW_FORM_ref_addr: ++ // DWARF2 and 3 differ on whether ref_addr is address size or ++ // offset size. ++ assert(header_.version == 2 || header_.version == 3); ++ if (header_.version == 2) { ++ return start + reader_->AddressSize(); ++ } else if (header_.version == 3) { ++ return start + reader_->OffsetSize(); ++ } ++ break; ++ ++ case DW_FORM_block1: ++ return start + 1 + reader_->ReadOneByte(start); ++ break; ++ case DW_FORM_block2: ++ return start + 2 + reader_->ReadTwoBytes(start); ++ break; ++ case DW_FORM_block4: ++ return start + 4 + reader_->ReadFourBytes(start); ++ break; ++ case DW_FORM_block: { ++ uint64 size = reader_->ReadUnsignedLEB128(start, &len); ++ return start + size + len; ++ } ++ break; ++ case DW_FORM_strp: ++ return start + reader_->OffsetSize(); ++ break; ++ default: ++ fprintf(stderr,"Unhandled form type"); ++ } ++ fprintf(stderr,"Unhandled form type"); ++ return NULL; ++} ++ ++// Read a DWARF2/3 header. ++// The header is variable length in DWARF3 (and DWARF2 as extended by ++// most compilers), and consists of an length field, a version number, ++// the offset in the .debug_abbrev section for our abbrevs, and an ++// address size. ++void CompilationUnit::ReadHeader() { ++ const char* headerptr = buffer_; ++ size_t initial_length_size; ++ ++ assert(headerptr + 4 < buffer_ + buffer_length_); ++ const uint64 initial_length = ReadInitialLength(headerptr, reader_, ++ &initial_length_size); ++ headerptr += initial_length_size; ++ header_.length = initial_length; ++ ++ assert(headerptr + 2 < buffer_ + buffer_length_); ++ header_.version = reader_->ReadTwoBytes(headerptr); ++ headerptr += 2; ++ ++ assert(headerptr + reader_->OffsetSize() < buffer_ + buffer_length_); ++ header_.abbrev_offset = reader_->ReadOffset(headerptr); ++ headerptr += reader_->OffsetSize(); ++ ++ assert(headerptr + 1 < buffer_ + buffer_length_); ++ header_.address_size = reader_->ReadOneByte(headerptr); ++ reader_->SetAddressSize(header_.address_size); ++ headerptr += 1; ++ ++ after_header_ = headerptr; ++ ++ // This check ensures that we don't have to do checking during the ++ // reading of DIEs. header_.length does not include the size of the ++ // initial length. ++ assert(buffer_ + initial_length_size + header_.length <= ++ buffer_ + buffer_length_); ++} ++ ++uint64 CompilationUnit::Start() { ++ // First get the debug_info section ++ SectionMap::const_iterator iter = sections_.find("__debug_info"); ++ assert(iter != sections_.end()); ++ ++ // Set up our buffer ++ buffer_ = iter->second.first + offset_from_section_start_; ++ buffer_length_ = iter->second.second - offset_from_section_start_; ++ ++ // Read the header ++ ReadHeader(); ++ ++ // Figure out the real length from the end of the initial length to ++ // the end of the compilation unit, since that is the value we ++ // return. ++ uint64 ourlength = header_.length; ++ if (reader_->OffsetSize() == 8) ++ ourlength += 12; ++ else ++ ourlength += 4; ++ ++ // See if the user wants this compilation unit, and if not, just return. ++ if (!handler_->StartCompilationUnit(offset_from_section_start_, ++ reader_->AddressSize(), ++ reader_->OffsetSize(), ++ header_.length, ++ header_.version)) ++ return ourlength; ++ ++ // Otherwise, continue by reading our abbreviation entries. ++ ReadAbbrevs(); ++ ++ // Set the string section if we have one. ++ iter = sections_.find("__debug_str"); ++ if (iter != sections_.end()) { ++ string_buffer_ = iter->second.first; ++ string_buffer_length_ = iter->second.second; ++ } ++ ++ // Now that we have our abbreviations, start processing DIE's. ++ ProcessDIEs(); ++ ++ return ourlength; ++} ++ ++// If one really wanted, you could merge SkipAttribute and ++// ProcessAttribute ++// This is all boring data manipulation and calling of the handler. ++const char* CompilationUnit::ProcessAttribute( ++ uint64 dieoffset, const char* start, enum DwarfAttribute attr, ++ enum DwarfForm form) { ++ size_t len; ++ ++ switch (form) { ++ // DW_FORM_indirect is never used because it is such a space ++ // waster. ++ case DW_FORM_indirect: ++ form = static_cast(reader_->ReadUnsignedLEB128(start, ++ &len)); ++ start += len; ++ return ProcessAttribute(dieoffset, start, attr, form); ++ break; ++ ++ case DW_FORM_data1: ++ case DW_FORM_flag: ++ case DW_FORM_ref1: ++ handler_->ProcessAttributeUnsigned(dieoffset, attr, form, ++ reader_->ReadOneByte(start)); ++ return start + 1; ++ break; ++ case DW_FORM_ref2: ++ case DW_FORM_data2: ++ handler_->ProcessAttributeUnsigned(dieoffset, attr, form, ++ reader_->ReadTwoBytes(start)); ++ return start + 2; ++ break; ++ case DW_FORM_ref4: ++ case DW_FORM_data4: ++ handler_->ProcessAttributeUnsigned(dieoffset, attr, form, ++ reader_->ReadFourBytes(start)); ++ return start + 4; ++ break; ++ case DW_FORM_ref8: ++ case DW_FORM_data8: ++ handler_->ProcessAttributeUnsigned(dieoffset, attr, form, ++ reader_->ReadEightBytes(start)); ++ return start + 8; ++ break; ++ case DW_FORM_string: { ++ const char* str = start; ++ handler_->ProcessAttributeString(dieoffset, attr, form, ++ str); ++ return start + strlen(str) + 1; ++ } ++ break; ++ case DW_FORM_udata: ++ case DW_FORM_ref_udata: ++ handler_->ProcessAttributeUnsigned(dieoffset, attr, form, ++ reader_->ReadUnsignedLEB128(start, ++ &len)); ++ return start + len; ++ break; ++ ++ case DW_FORM_sdata: ++ handler_->ProcessAttributeSigned(dieoffset, attr, form, ++ reader_->ReadSignedLEB128(start, &len)); ++ return start + len; ++ break; ++ case DW_FORM_addr: ++ handler_->ProcessAttributeUnsigned(dieoffset, attr, form, ++ reader_->ReadAddress(start)); ++ return start + reader_->AddressSize(); ++ break; ++ case DW_FORM_ref_addr: ++ // DWARF2 and 3 differ on whether ref_addr is address size or ++ // offset size. ++ assert(header_.version == 2 || header_.version == 3); ++ if (header_.version == 2) { ++ handler_->ProcessAttributeUnsigned(dieoffset, attr, form, ++ reader_->ReadAddress(start)); ++ return start + reader_->AddressSize(); ++ } else if (header_.version == 3) { ++ handler_->ProcessAttributeUnsigned(dieoffset, attr, form, ++ reader_->ReadOffset(start)); ++ return start + reader_->OffsetSize(); ++ } ++ break; ++ ++ case DW_FORM_block1: { ++ uint64 datalen = reader_->ReadOneByte(start); ++ handler_->ProcessAttributeBuffer(dieoffset, attr, form, start + 1, ++ datalen); ++ return start + 1 + datalen; ++ } ++ break; ++ case DW_FORM_block2: { ++ uint64 datalen = reader_->ReadTwoBytes(start); ++ handler_->ProcessAttributeBuffer(dieoffset, attr, form, start + 2, ++ datalen); ++ return start + 2 + datalen; ++ } ++ break; ++ case DW_FORM_block4: { ++ uint64 datalen = reader_->ReadFourBytes(start); ++ handler_->ProcessAttributeBuffer(dieoffset, attr, form, start + 4, ++ datalen); ++ return start + 4 + datalen; ++ } ++ break; ++ case DW_FORM_block: { ++ uint64 datalen = reader_->ReadUnsignedLEB128(start, &len); ++ handler_->ProcessAttributeBuffer(dieoffset, attr, form, start + len, ++ datalen); ++ return start + datalen + len; ++ } ++ break; ++ case DW_FORM_strp: { ++ assert(string_buffer_ != NULL); ++ ++ const uint64 offset = reader_->ReadOffset(start); ++ assert(string_buffer_ + offset < string_buffer_ + string_buffer_length_); ++ ++ const char* str = string_buffer_ + offset; ++ handler_->ProcessAttributeString(dieoffset, attr, form, ++ str); ++ return start + reader_->OffsetSize(); ++ } ++ break; ++ default: ++ fprintf(stderr, "Unhandled form type"); ++ } ++ fprintf(stderr, "Unhandled form type"); ++ return NULL; ++} ++ ++const char* CompilationUnit::ProcessDIE(uint64 dieoffset, ++ const char* start, ++ const Abbrev& abbrev) { ++ for (AttributeList::const_iterator i = abbrev.attributes.begin(); ++ i != abbrev.attributes.end(); ++ i++) { ++ start = ProcessAttribute(dieoffset, start, i->first, i->second); ++ } ++ return start; ++} ++ ++void CompilationUnit::ProcessDIEs() { ++ const char* dieptr = after_header_; ++ size_t len; ++ ++ // lengthstart is the place the length field is based on. ++ // It is the point in the header after the initial length field ++ const char* lengthstart = buffer_; ++ ++ // In 64 bit dwarf, the initial length is 12 bytes, because of the ++ // 0xffffffff at the start. ++ if (reader_->OffsetSize() == 8) ++ lengthstart += 12; ++ else ++ lengthstart += 4; ++ ++ // we need semantics of boost scoped_ptr here - no intention of trasnferring ++ // ownership of the stack. use const, but then we limit ourselves to not ++ // ever being able to call .reset() on the smart pointer. ++ std::auto_ptr > const die_stack(new stack); ++ ++ while (dieptr < (lengthstart + header_.length)) { ++ // We give the user the absolute offset from the beginning of ++ // debug_info, since they need it to deal with ref_addr forms. ++ uint64 absolute_offset = (dieptr - buffer_) + offset_from_section_start_; ++ ++ uint64 abbrev_num = reader_->ReadUnsignedLEB128(dieptr, &len); ++ ++ dieptr += len; ++ ++ // Abbrev == 0 represents the end of a list of children. ++ if (abbrev_num == 0) { ++ const uint64 offset = die_stack->top(); ++ die_stack->pop(); ++ handler_->EndDIE(offset); ++ continue; ++ } ++ ++ const Abbrev& abbrev = abbrevs_->at(abbrev_num); ++ const enum DwarfTag tag = abbrev.tag; ++ if (!handler_->StartDIE(absolute_offset, tag, abbrev.attributes)) { ++ dieptr = SkipDIE(dieptr, abbrev); ++ } else { ++ dieptr = ProcessDIE(absolute_offset, dieptr, abbrev); ++ } ++ ++ if (abbrev.has_children) { ++ die_stack->push(absolute_offset); ++ } else { ++ handler_->EndDIE(absolute_offset); ++ } ++ } ++} ++ ++LineInfo::LineInfo(const char* buffer, uint64 buffer_length, ++ ByteReader* reader, LineInfoHandler* handler): ++ handler_(handler), reader_(reader), buffer_(buffer), ++ buffer_length_(buffer_length) { ++ header_.std_opcode_lengths = NULL; ++} ++ ++uint64 LineInfo::Start() { ++ ReadHeader(); ++ ReadLines(); ++ return after_header_ - buffer_; ++} ++ ++// The header for a debug_line section is mildly complicated, because ++// the line info is very tightly encoded. ++void LineInfo::ReadHeader() { ++ const char* lineptr = buffer_; ++ size_t initial_length_size; ++ ++ const uint64 initial_length = ReadInitialLength(lineptr, reader_, ++ &initial_length_size); ++ ++ lineptr += initial_length_size; ++ header_.total_length = initial_length; ++ assert(buffer_ + initial_length_size + header_.total_length <= ++ buffer_ + buffer_length_); ++ ++ // Address size *must* be set by CU ahead of time. ++ assert(reader_->AddressSize() != 0); ++ ++ header_.version = reader_->ReadTwoBytes(lineptr); ++ lineptr += 2; ++ ++ header_.prologue_length = reader_->ReadOffset(lineptr); ++ lineptr += reader_->OffsetSize(); ++ ++ header_.min_insn_length = reader_->ReadOneByte(lineptr); ++ lineptr += 1; ++ ++ header_.default_is_stmt = reader_->ReadOneByte(lineptr); ++ lineptr += 1; ++ ++ header_.line_base = *reinterpret_cast(lineptr); ++ lineptr += 1; ++ ++ header_.line_range = reader_->ReadOneByte(lineptr); ++ lineptr += 1; ++ ++ header_.opcode_base = reader_->ReadOneByte(lineptr); ++ lineptr += 1; ++ ++ header_.std_opcode_lengths = new vector; ++ header_.std_opcode_lengths->resize(header_.opcode_base + 1); ++ (*header_.std_opcode_lengths)[0] = 0; ++ for (int i = 1; i < header_.opcode_base; i++) { ++ (*header_.std_opcode_lengths)[i] = reader_->ReadOneByte(lineptr); ++ lineptr += 1; ++ } ++ ++ // It is legal for the directory entry table to be empty. ++ if (*lineptr) { ++ uint32 dirindex = 1; ++ while (*lineptr) { ++ const char* dirname = lineptr; ++ handler_->DefineDir(dirname, dirindex); ++ lineptr += strlen(dirname) + 1; ++ dirindex++; ++ } ++ } ++ lineptr++; ++ ++ // It is also legal for the file entry table to be empty. ++ if (*lineptr) { ++ uint32 fileindex = 1; ++ size_t len; ++ while (*lineptr) { ++ const char* filename = lineptr; ++ lineptr += strlen(filename) + 1; ++ ++ uint64 dirindex = reader_->ReadUnsignedLEB128(lineptr, &len); ++ lineptr += len; ++ ++ uint64 mod_time = reader_->ReadUnsignedLEB128(lineptr, &len); ++ lineptr += len; ++ ++ uint64 filelength = reader_->ReadUnsignedLEB128(lineptr, &len); ++ lineptr += len; ++ handler_->DefineFile(filename, fileindex, dirindex, mod_time, ++ filelength); ++ fileindex++; ++ } ++ } ++ lineptr++; ++ ++ after_header_ = lineptr; ++} ++ ++/* static */ ++bool LineInfo::ProcessOneOpcode(ByteReader* reader, ++ LineInfoHandler* handler, ++ const struct LineInfoHeader &header, ++ const char* start, ++ struct LineStateMachine* lsm, ++ size_t* len, ++ uintptr pc, ++ bool *lsm_passes_pc) { ++ size_t oplen = 0; ++ size_t templen; ++ uint8 opcode = reader->ReadOneByte(start); ++ oplen++; ++ start++; ++ ++ // If the opcode is great than the opcode_base, it is a special ++ // opcode. Most line programs consist mainly of special opcodes. ++ if (opcode >= header.opcode_base) { ++ opcode -= header.opcode_base; ++ const int64 advance_address = (opcode / header.line_range) ++ * header.min_insn_length; ++ const int64 advance_line = (opcode % header.line_range) ++ + header.line_base; ++ ++ // Check if the lsm passes "pc". If so, mark it as passed. ++ if (lsm_passes_pc && ++ lsm->address <= pc && pc < lsm->address + advance_address) { ++ *lsm_passes_pc = true; ++ } ++ ++ lsm->address += advance_address; ++ lsm->line_num += advance_line; ++ lsm->basic_block = true; ++ *len = oplen; ++ return true; ++ } ++ ++ // Otherwise, we have the regular opcodes ++ switch (opcode) { ++ case DW_LNS_copy: { ++ lsm->basic_block = false; ++ *len = oplen; ++ return true; ++ } ++ ++ case DW_LNS_advance_pc: { ++ uint64 advance_address = reader->ReadUnsignedLEB128(start, &templen); ++ oplen += templen; ++ ++ // Check if the lsm passes "pc". If so, mark it as passed. ++ if (lsm_passes_pc && lsm->address <= pc && ++ pc < lsm->address + header.min_insn_length * advance_address) { ++ *lsm_passes_pc = true; ++ } ++ ++ lsm->address += header.min_insn_length * advance_address; ++ } ++ break; ++ case DW_LNS_advance_line: { ++ const int64 advance_line = reader->ReadSignedLEB128(start, &templen); ++ oplen += templen; ++ lsm->line_num += advance_line; ++ ++ // With gcc 4.2.1, we can get the line_no here for the first time ++ // since DW_LNS_advance_line is called after DW_LNE_set_address is ++ // called. So we check if the lsm passes "pc" here, not in ++ // DW_LNE_set_address. ++ if (lsm_passes_pc && lsm->address == pc) { ++ *lsm_passes_pc = true; ++ } ++ } ++ break; ++ case DW_LNS_set_file: { ++ const uint64 fileno = reader->ReadUnsignedLEB128(start, &templen); ++ oplen += templen; ++ lsm->file_num = fileno; ++ } ++ break; ++ case DW_LNS_set_column: { ++ const uint64 colno = reader->ReadUnsignedLEB128(start, &templen); ++ oplen += templen; ++ lsm->column_num = colno; ++ } ++ break; ++ case DW_LNS_negate_stmt: { ++ lsm->is_stmt = !lsm->is_stmt; ++ } ++ break; ++ case DW_LNS_set_basic_block: { ++ lsm->basic_block = true; ++ } ++ break; ++ case DW_LNS_fixed_advance_pc: { ++ const uint16 advance_address = reader->ReadTwoBytes(start); ++ oplen += 2; ++ ++ // Check if the lsm passes "pc". If so, mark it as passed. ++ if (lsm_passes_pc && ++ lsm->address <= pc && pc < lsm->address + advance_address) { ++ *lsm_passes_pc = true; ++ } ++ ++ lsm->address += advance_address; ++ } ++ break; ++ case DW_LNS_const_add_pc: { ++ const int64 advance_address = header.min_insn_length ++ * ((255 - header.opcode_base) ++ / header.line_range); ++ ++ // Check if the lsm passes "pc". If so, mark it as passed. ++ if (lsm_passes_pc && ++ lsm->address <= pc && pc < lsm->address + advance_address) { ++ *lsm_passes_pc = true; ++ } ++ ++ lsm->address += advance_address; ++ } ++ break; ++ case DW_LNS_extended_op: { ++ const size_t extended_op_len = reader->ReadUnsignedLEB128(start, ++ &templen); ++ start += templen; ++ oplen += templen + extended_op_len; ++ ++ const uint64 extended_op = reader->ReadOneByte(start); ++ start++; ++ ++ switch (extended_op) { ++ case DW_LNE_end_sequence: { ++ lsm->end_sequence = true; ++ *len = oplen; ++ return true; ++ } ++ break; ++ case DW_LNE_set_address: { ++ // With gcc 4.2.1, we cannot tell the line_no here since ++ // DW_LNE_set_address is called before DW_LNS_advance_line is ++ // called. So we do not check if the lsm passes "pc" here. See ++ // also the comment in DW_LNS_advance_line. ++ uint64 address = reader->ReadAddress(start); ++ lsm->address = address; ++ } ++ break; ++ case DW_LNE_define_file: { ++ const char* filename = start; ++ ++ templen = strlen(filename) + 1; ++ start += templen; ++ ++ uint64 dirindex = reader->ReadUnsignedLEB128(start, &templen); ++ oplen += templen; ++ ++ const uint64 mod_time = reader->ReadUnsignedLEB128(start, ++ &templen); ++ oplen += templen; ++ ++ const uint64 filelength = reader->ReadUnsignedLEB128(start, ++ &templen); ++ oplen += templen; ++ ++ if (handler) { ++ handler->DefineFile(filename, -1, dirindex, mod_time, ++ filelength); ++ } ++ } ++ break; ++ } ++ } ++ break; ++ ++ default: { ++ // Ignore unknown opcode silently ++ if (header.std_opcode_lengths) { ++ for (int i = 0; i < (*header.std_opcode_lengths)[opcode]; i++) { ++ size_t templen; ++ reader->ReadUnsignedLEB128(start, &templen); ++ start += templen; ++ oplen += templen; ++ } ++ } ++ } ++ break; ++ } ++ *len = oplen; ++ return false; ++} ++ ++void LineInfo::ReadLines() { ++ struct LineStateMachine lsm; ++ ++ // lengthstart is the place the length field is based on. ++ // It is the point in the header after the initial length field ++ const char* lengthstart = buffer_; ++ ++ // In 64 bit dwarf, the initial length is 12 bytes, because of the ++ // 0xffffffff at the start. ++ if (reader_->OffsetSize() == 8) ++ lengthstart += 12; ++ else ++ lengthstart += 4; ++ ++ const char* lineptr = after_header_; ++ while (lineptr < lengthstart + header_.total_length) { ++ lsm.Reset(header_.default_is_stmt); ++ while (!lsm.end_sequence) { ++ size_t oplength; ++ bool add_line = ProcessOneOpcode(reader_, handler_, header_, ++ lineptr, &lsm, &oplength, (uintptr)-1, ++ NULL); ++ if (add_line) ++ handler_->AddLine(lsm.address, lsm.file_num, lsm.line_num, ++ lsm.column_num); ++ lineptr += oplength; ++ } ++ } ++ ++ after_header_ = lengthstart + header_.total_length; ++} ++ ++} // namespace dwarf2reader +diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader.h b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader.h +@@ -0,0 +1,393 @@ ++// Copyright 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. ++ ++// This file contains definitions related to the DWARF2/3 reader and ++// it's handler interfaces. ++// The DWARF2/3 specification can be found at ++// http://dwarf.freestandards.org and should be considered required ++// reading if you wish to modify the implementation. ++// Only a cursory attempt is made to explain terminology that is ++// used here, as it is much better explained in the standard documents ++#ifndef COMMON_DWARF_DWARF2READER_H__ ++#define COMMON_DWARF_DWARF2READER_H__ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "common/dwarf/dwarf2enums.h" ++#include "common/dwarf/types.h" ++ ++using namespace std; ++ ++namespace dwarf2reader { ++struct LineStateMachine; ++class ByteReader; ++class Dwarf2Handler; ++class LineInfoHandler; ++ ++// This maps from a string naming a section to a pair containing a ++// the data for the section, and the size of the section. ++typedef map > SectionMap; ++typedef list > AttributeList; ++typedef AttributeList::iterator AttributeIterator; ++typedef AttributeList::const_iterator ConstAttributeIterator; ++ ++struct LineInfoHeader { ++ uint64 total_length; ++ uint16 version; ++ uint64 prologue_length; ++ uint8 min_insn_length; // insn stands for instructin ++ bool default_is_stmt; // stmt stands for statement ++ int8 line_base; ++ uint8 line_range; ++ uint8 opcode_base; ++ // Use a pointer so that signalsafe_addr2line is able to use this structure ++ // without heap allocation problem. ++ vector *std_opcode_lengths; ++}; ++ ++class LineInfo { ++ public: ++ ++ // Initializes a .debug_line reader. Buffer and buffer length point ++ // to the beginning and length of the line information to read. ++ // Reader is a ByteReader class that has the endianness set ++ // properly. ++ LineInfo(const char* buffer_, uint64 buffer_length, ++ ByteReader* reader, LineInfoHandler* handler); ++ ++ virtual ~LineInfo() { ++ if (header_.std_opcode_lengths) { ++ delete header_.std_opcode_lengths; ++ } ++ } ++ ++ // Start processing line info, and calling callbacks in the handler. ++ // Consumes the line number information for a single compilation unit. ++ // Returns the number of bytes processed. ++ uint64 Start(); ++ ++ // Process a single line info opcode at START using the state ++ // machine at LSM. Return true if we should define a line using the ++ // current state of the line state machine. Place the length of the ++ // opcode in LEN. ++ // If LSM_PASSES_PC is non-NULL, this function also checks if the lsm ++ // passes the address of PC. In other words, LSM_PASSES_PC will be ++ // set to true, if the following condition is met. ++ // ++ // lsm's old address < PC <= lsm's new address ++ static bool ProcessOneOpcode(ByteReader* reader, ++ LineInfoHandler* handler, ++ const struct LineInfoHeader &header, ++ const char* start, ++ struct LineStateMachine* lsm, ++ size_t* len, ++ uintptr pc, ++ bool *lsm_passes_pc); ++ ++ private: ++ // Reads the DWARF2/3 header for this line info. ++ void ReadHeader(); ++ ++ // Reads the DWARF2/3 line information ++ void ReadLines(); ++ ++ // The associated handler to call processing functions in ++ LineInfoHandler* handler_; ++ ++ // The associated ByteReader that handles endianness issues for us ++ ByteReader* reader_; ++ ++ // A DWARF2/3 line info header. This is not the same size as ++ // in the actual file, as the one in the file may have a 32 bit or ++ // 64 bit lengths ++ ++ struct LineInfoHeader header_; ++ ++ // buffer is the buffer for our line info, starting at exactly where ++ // the line info to read is. after_header is the place right after ++ // the end of the line information header. ++ const char* buffer_; ++ uint64 buffer_length_; ++ const char* after_header_; ++}; ++ ++// This class is the main interface between the line info reader and ++// the client. The virtual functions inside this get called for ++// interesting events that happen during line info reading. The ++// default implementation does nothing ++ ++class LineInfoHandler { ++ public: ++ LineInfoHandler() { } ++ ++ virtual ~LineInfoHandler() { } ++ ++ // Called when we define a directory. NAME is the directory name, ++ // DIR_NUM is the directory number ++ virtual void DefineDir(const string& name, uint32 dir_num) { } ++ ++ // Called when we define a filename. NAME is the filename, FILE_NUM ++ // is the file number which is -1 if the file index is the next ++ // index after the last numbered index (this happens when files are ++ // dynamically defined by the line program), DIR_NUM is the ++ // directory index for the directory name of this file, MOD_TIME is ++ // the modification time of the file, and LENGTH is the length of ++ // the file ++ virtual void DefineFile(const string& name, int32 file_num, ++ uint32 dir_num, uint64 mod_time, ++ uint64 length) { } ++ ++ // Called when the line info reader has a new line, address pair ++ // ready for us. ADDRESS is the address of the code, FILE_NUM is ++ // the file number containing the code, LINE_NUM is the line number in ++ // that file for the code, and COLUMN_NUM is the column number the code ++ // starts at, if we know it (0 otherwise). ++ virtual void AddLine(uint64 address, uint32 file_num, uint32 line_num, ++ uint32 column_num) { } ++}; ++ ++// The base of DWARF2/3 debug info is a DIE (Debugging Information ++// Entry. ++// DWARF groups DIE's into a tree and calls the root of this tree a ++// "compilation unit". Most of the time, there is one compilation ++// unit in the .debug_info section for each file that had debug info ++// generated. ++// Each DIE consists of ++ ++// 1. a tag specifying a thing that is being described (ie ++// DW_TAG_subprogram for functions, DW_TAG_variable for variables, etc ++// 2. attributes (such as DW_AT_location for location in memory, ++// DW_AT_name for name), and data for each attribute. ++// 3. A flag saying whether the DIE has children or not ++ ++// In order to gain some amount of compression, the format of ++// each DIE (tag name, attributes and data forms for the attributes) ++// are stored in a separate table called the "abbreviation table". ++// This is done because a large number of DIEs have the exact same tag ++// and list of attributes, but different data for those attributes. ++// As a result, the .debug_info section is just a stream of data, and ++// requires reading of the .debug_abbrev section to say what the data ++// means. ++ ++// As a warning to the user, it should be noted that the reason for ++// using absolute offsets from the beginning of .debug_info is that ++// DWARF2/3 supports referencing DIE's from other DIE's by their offset ++// from either the current compilation unit start, *or* the beginning ++// of the .debug_info section. This means it is possible to reference ++// a DIE in one compilation unit from a DIE in another compilation ++// unit. This style of reference is usually used to eliminate ++// duplicated information that occurs across compilation ++// units, such as base types, etc. GCC 3.4+ support this with ++// -feliminate-dwarf2-dups. Other toolchains will sometimes do ++// duplicate elimination in the linker. ++ ++class CompilationUnit { ++ public: ++ ++ // Initialize a compilation unit. This requires a map of sections, ++ // the offset of this compilation unit in the .debug_info section, a ++ // ByteReader, and a Dwarf2Handler class to call callbacks in. ++ CompilationUnit(const SectionMap& sections, uint64 offset, ++ ByteReader* reader, Dwarf2Handler* handler); ++ virtual ~CompilationUnit() { ++ if (abbrevs_) delete abbrevs_; ++ } ++ ++ // Begin reading a Dwarf2 compilation unit, and calling the ++ // callbacks in the Dwarf2Handler ++ ++ // Return the full length of the compilation unit, including ++ // headers. This plus the starting offset passed to the constructor ++ // is the offset of the end of the compilation unit --- and the ++ // start of the next compilation unit, if there is one. ++ uint64 Start(); ++ ++ private: ++ ++ // This struct represents a single DWARF2/3 abbreviation ++ // The abbreviation tells how to read a DWARF2/3 DIE, and consist of a ++ // tag and a list of attributes, as well as the data form of each attribute. ++ struct Abbrev { ++ uint32 number; ++ enum DwarfTag tag; ++ bool has_children; ++ AttributeList attributes; ++ }; ++ ++ // A DWARF2/3 compilation unit header. This is not the same size as ++ // in the actual file, as the one in the file may have a 32 bit or ++ // 64 bit length. ++ struct CompilationUnitHeader { ++ uint64 length; ++ uint16 version; ++ uint64 abbrev_offset; ++ uint8 address_size; ++ } header_; ++ ++ // Reads the DWARF2/3 header for this compilation unit. ++ void ReadHeader(); ++ ++ // Reads the DWARF2/3 abbreviations for this compilation unit ++ void ReadAbbrevs(); ++ ++ // Processes a single DIE for this compilation unit and return a new ++ // pointer just past the end of it ++ const char* ProcessDIE(uint64 dieoffset, ++ const char* start, ++ const Abbrev& abbrev); ++ ++ // Processes a single attribute and return a new pointer just past the ++ // end of it ++ const char* ProcessAttribute(uint64 dieoffset, ++ const char* start, ++ enum DwarfAttribute attr, ++ enum DwarfForm form); ++ ++ // Processes all DIEs for this compilation unit ++ void ProcessDIEs(); ++ ++ // Skips the die with attributes specified in ABBREV starting at ++ // START, and return the new place to position the stream to. ++ const char* SkipDIE(const char* start, ++ const Abbrev& abbrev); ++ ++ // Skips the attribute starting at START, with FORM, and return the ++ // new place to position the stream to. ++ const char* SkipAttribute(const char* start, ++ enum DwarfForm form); ++ ++ // Offset from section start is the offset of this compilation unit ++ // from the beginning of the .debug_info section. ++ uint64 offset_from_section_start_; ++ ++ // buffer is the buffer for our CU, starting at .debug_info + offset ++ // passed in from constructor. ++ // after_header points to right after the compilation unit header. ++ const char* buffer_; ++ uint64 buffer_length_; ++ const char* after_header_; ++ ++ // The associated ByteReader that handles endianness issues for us ++ ByteReader* reader_; ++ ++ // The map of sections in our file to buffers containing their data ++ const SectionMap& sections_; ++ ++ // The associated handler to call processing functions in ++ Dwarf2Handler* handler_; ++ ++ // Set of DWARF2/3 abbreviations for this compilation unit. Indexed ++ // by abbreviation number, which means that abbrevs_[0] is not ++ // valid. ++ vector* abbrevs_; ++ ++ // String section buffer and length, if we have a string section. ++ // This is here to avoid doing a section lookup for strings in ++ // ProcessAttribute, which is in the hot path for DWARF2 reading. ++ const char* string_buffer_; ++ uint64 string_buffer_length_; ++}; ++ ++// This class is the main interface between the reader and the ++// client. The virtual functions inside this get called for ++// interesting events that happen during DWARF2 reading. ++// The default implementation skips everything. ++ ++class Dwarf2Handler { ++ public: ++ Dwarf2Handler() { } ++ ++ virtual ~Dwarf2Handler() { } ++ ++ // Start to process a compilation unit at OFFSET from the beginning of the ++ // .debug_info section. Return false if you would like to skip this ++ // compilation unit. ++ virtual bool StartCompilationUnit(uint64 offset, uint8 address_size, ++ uint8 offset_size, uint64 cu_length, ++ uint8 dwarf_version) { return false; } ++ ++ // Start to process a DIE at OFFSET from the beginning of the .debug_info ++ // section. Return false if you would like to skip this DIE. ++ virtual bool StartDIE(uint64 offset, enum DwarfTag tag, ++ const AttributeList& attrs) { return false; } ++ ++ // Called when we have an attribute with unsigned data to give to our ++ // handler. The attribute is for the DIE at OFFSET from the beginning of the ++ // .debug_info section. Its name is ATTR, its form is FORM, and its value is ++ // DATA. ++ virtual void ProcessAttributeUnsigned(uint64 offset, ++ enum DwarfAttribute attr, ++ enum DwarfForm form, ++ uint64 data) { } ++ ++ // Called when we have an attribute with signed data to give to our handler. ++ // The attribute is for the DIE at OFFSET from the beginning of the ++ // .debug_info section. Its name is ATTR, its form is FORM, and its value is ++ // DATA. ++ virtual void ProcessAttributeSigned(uint64 offset, ++ enum DwarfAttribute attr, ++ enum DwarfForm form, ++ int64 data) { } ++ ++ // Called when we have an attribute with a buffer of data to give to our ++ // handler. The attribute is for the DIE at OFFSET from the beginning of the ++ // .debug_info section. Its name is ATTR, its form is FORM, DATA points to ++ // the buffer's contents, and its length in bytes is LENGTH. The buffer is ++ // owned by the caller, not the callee, and may not persist for very long. ++ // If you want the data to be available later, it needs to be copied. ++ virtual void ProcessAttributeBuffer(uint64 offset, ++ enum DwarfAttribute attr, ++ enum DwarfForm form, ++ const char* data, ++ uint64 len) { } ++ ++ // Called when we have an attribute with string data to give to our handler. ++ // The attribute is for the DIE at OFFSET from the beginning of the ++ // .debug_info section. Its name is ATTR, its form is FORM, and its value is ++ // DATA. ++ virtual void ProcessAttributeString(uint64 offset, ++ enum DwarfAttribute attr, ++ enum DwarfForm form, ++ const string& data) { } ++ ++ // Called when finished processing the DIE at OFFSET. ++ // Because DWARF2/3 specifies a tree of DIEs, you may get starts ++ // before ends of the previous DIE, as we process children before ++ // ending the parent. ++ virtual void EndDIE(uint64 offset) { } ++ ++}; ++ ++ ++} // namespace dwarf2reader ++ ++#endif // UTIL_DEBUGINFO_DWARF2READER_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/functioninfo.cc b/toolkit/crashreporter/google-breakpad/src/common/dwarf/functioninfo.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/functioninfo.cc +@@ -0,0 +1,231 @@ ++// Copyright 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. ++ ++// This is a client for the dwarf2reader to extract function and line ++// information from the debug info. ++ ++#include ++ ++#include ++#include ++#include ++ ++#include "common/dwarf/functioninfo.h" ++ ++#include "common/dwarf/bytereader.h" ++ ++ ++namespace dwarf2reader { ++ ++// Given an offset value, its form, and the base offset of the ++// compilation unit containing this value, return an absolute offset ++// within the .debug_info section. ++uint64 GetAbsoluteOffset(uint64 offset, ++ enum DwarfForm form, ++ uint64 compilation_unit_base) { ++ switch (form) { ++ case DW_FORM_ref1: ++ case DW_FORM_ref2: ++ case DW_FORM_ref4: ++ case DW_FORM_ref8: ++ case DW_FORM_ref_udata: ++ return offset + compilation_unit_base; ++ case DW_FORM_ref_addr: ++ default: ++ return offset; ++ } ++} ++ ++CULineInfoHandler::CULineInfoHandler(vector* files, ++ vector* dirs, ++ LineMap* linemap):linemap_(linemap), ++ files_(files), ++ dirs_(dirs) { ++ // The dirs and files are 1 indexed, so just make sure we put ++ // nothing in the 0 vector. ++ assert(dirs->size() == 0); ++ assert(files->size() == 0); ++ dirs->push_back(""); ++ SourceFileInfo s; ++ s.name = ""; ++ s.lowpc = ULLONG_MAX; ++ files->push_back(s); ++} ++ ++void CULineInfoHandler::DefineDir(const string& name, uint32 dir_num) { ++ // These should never come out of order, actually ++ assert(dir_num == dirs_->size()); ++ dirs_->push_back(name); ++} ++ ++void CULineInfoHandler::DefineFile(const string& name, ++ int32 file_num, uint32 dir_num, ++ uint64 mod_time, uint64 length) { ++ assert(dir_num >= 0); ++ assert(dir_num < dirs_->size()); ++ ++ // These should never come out of order, actually. ++ if (file_num == (int32)files_->size() || file_num == -1) { ++ string dir = dirs_->at(dir_num); ++ ++ SourceFileInfo s; ++ s.lowpc = ULLONG_MAX; ++ ++ if (dir == "") { ++ s.name = name; ++ } else { ++ s.name = dir + "/" + name; ++ } ++ ++ files_->push_back(s); ++ } else { ++ fprintf(stderr, "error in DefineFile"); ++ } ++} ++ ++void CULineInfoHandler::AddLine(uint64 address, uint32 file_num, ++ uint32 line_num, uint32 column_num) { ++ if (file_num < files_->size()) { ++ linemap_->insert(make_pair(address, make_pair(files_->at(file_num).name.c_str(), ++ line_num))); ++ ++ if(address < files_->at(file_num).lowpc) { ++ files_->at(file_num).lowpc = address; ++ } ++ } else { ++ fprintf(stderr,"error in AddLine"); ++ } ++} ++ ++bool CUFunctionInfoHandler::StartCompilationUnit(uint64 offset, ++ uint8 address_size, ++ uint8 offset_size, ++ uint64 cu_length, ++ uint8 dwarf_version) { ++ current_compilation_unit_offset_ = offset; ++ return true; ++} ++ ++ ++// For function info, we only care about subprograms and inlined ++// subroutines. For line info, the DW_AT_stmt_list lives in the ++// compile unit tag. ++ ++bool CUFunctionInfoHandler::StartDIE(uint64 offset, enum DwarfTag tag, ++ const AttributeList& attrs) { ++ switch (tag) { ++ case DW_TAG_subprogram: ++ case DW_TAG_inlined_subroutine: { ++ current_function_info_ = new FunctionInfo; ++ current_function_info_->lowpc = current_function_info_->highpc = 0; ++ current_function_info_->name = ""; ++ current_function_info_->line = 0; ++ current_function_info_->file = ""; ++ offset_to_funcinfo_->insert(make_pair(offset, current_function_info_)); ++ }; ++ // FALLTHROUGH ++ case DW_TAG_compile_unit: ++ return true; ++ default: ++ return false; ++ } ++ return false; ++} ++ ++// Only care about the name attribute for functions ++ ++void CUFunctionInfoHandler::ProcessAttributeString(uint64 offset, ++ enum DwarfAttribute attr, ++ enum DwarfForm form, ++ const string &data) { ++ if (current_function_info_) { ++ if (attr == DW_AT_name) ++ current_function_info_->name = data; ++ else if(attr == DW_AT_MIPS_linkage_name) ++ current_function_info_->mangled_name = data; ++ } ++} ++ ++void CUFunctionInfoHandler::ProcessAttributeUnsigned(uint64 offset, ++ enum DwarfAttribute attr, ++ enum DwarfForm form, ++ uint64 data) { ++ if (attr == DW_AT_stmt_list) { ++ SectionMap::const_iterator iter = sections_.find("__debug_line"); ++ assert(iter != sections_.end()); ++ ++ // this should be a scoped_ptr but we dont' use boost :-( ++ auto_ptr lireader(new LineInfo(iter->second.first + data, ++ iter->second.second - data, ++ reader_, linehandler_)); ++ lireader->Start(); ++ } else if (current_function_info_) { ++ switch (attr) { ++ case DW_AT_low_pc: ++ current_function_info_->lowpc = data; ++ break; ++ case DW_AT_high_pc: ++ current_function_info_->highpc = data; ++ break; ++ case DW_AT_decl_line: ++ current_function_info_->line = data; ++ break; ++ case DW_AT_decl_file: ++ current_function_info_->file = files_->at(data).name; ++ break; ++ case DW_AT_specification: { ++ // Some functions have a "specification" attribute ++ // which means they were defined elsewhere. The name ++ // attribute is not repeated, and must be taken from ++ // the specification DIE. Here we'll assume that ++ // any DIE referenced in this manner will already have ++ // been seen, but that's not really required by the spec. ++ uint64 abs_offset = GetAbsoluteOffset(data, form, current_compilation_unit_offset_); ++ FunctionMap::iterator iter = offset_to_funcinfo_->find(abs_offset); ++ if (iter != offset_to_funcinfo_->end()) { ++ current_function_info_->name = iter->second->name; ++ current_function_info_->mangled_name = iter->second->mangled_name; ++ } else { ++ // If you hit this, this code probably needs to be rewritten. ++ fprintf(stderr, "Error: DW_AT_specification was seen before the referenced DIE! (Looking for DIE at offset %08llx, in DIE at offset %08llx)\n", abs_offset, offset); ++ } ++ break; ++ } ++ default: ++ break; ++ } ++ } ++} ++ ++void CUFunctionInfoHandler::EndDIE(uint64 offset) { ++ if (current_function_info_ && current_function_info_->lowpc) ++ address_to_funcinfo_->insert(make_pair(current_function_info_->lowpc, ++ current_function_info_)); ++} ++ ++} // namespace dwarf2reader +diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/functioninfo.h b/toolkit/crashreporter/google-breakpad/src/common/dwarf/functioninfo.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/functioninfo.h +@@ -0,0 +1,178 @@ ++// Copyright 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. ++ ++ ++// This file contains the definitions for a DWARF2/3 information ++// collector that uses the DWARF2/3 reader interface to build a mapping ++// of addresses to files, lines, and functions. ++ ++#ifndef COMMON_DWARF_FUNCTIONINFO_H__ ++#define COMMON_DWARF_FUNCTIONINFO_H__ ++ ++#include ++#include ++#include ++#include ++ ++#include "common/dwarf/dwarf2reader.h" ++ ++ ++namespace dwarf2reader { ++ ++struct FunctionInfo { ++ // Name of the function ++ string name; ++ // Mangled name of the function ++ string mangled_name; ++ // File containing this function ++ string file; ++ // Line number for start of function. ++ uint32 line; ++ // Beginning address for this function ++ uint64 lowpc; ++ // End address for this function. ++ uint64 highpc; ++}; ++ ++struct SourceFileInfo { ++ // Name of the source file name ++ string name; ++ // Low address of source file name ++ uint64 lowpc; ++}; ++ ++typedef map FunctionMap; ++typedef map > LineMap; ++ ++// This class is a basic line info handler that fills in the dirs, ++// file, and linemap passed into it with the data produced from the ++// LineInfoHandler. ++class CULineInfoHandler: public LineInfoHandler { ++ public: ++ ++ // ++ CULineInfoHandler(vector* files, ++ vector* dirs, ++ LineMap* linemap); ++ virtual ~CULineInfoHandler() { } ++ ++ // Called when we define a directory. We just place NAME into dirs_ ++ // at position DIR_NUM. ++ virtual void DefineDir(const string& name, uint32 dir_num); ++ ++ // Called when we define a filename. We just place ++ // concat(dirs_[DIR_NUM], NAME) into files_ at position FILE_NUM. ++ virtual void DefineFile(const string& name, int32 file_num, ++ uint32 dir_num, uint64 mod_time, uint64 length); ++ ++ ++ // Called when the line info reader has a new line, address pair ++ // ready for us. ADDRESS is the address of the code, FILE_NUM is ++ // the file number containing the code, LINE_NUM is the line number ++ // in that file for the code, and COLUMN_NUM is the column number ++ // the code starts at, if we know it (0 otherwise). ++ virtual void AddLine(uint64 address, uint32 file_num, uint32 line_num, ++ uint32 column_num); ++ ++ ++ private: ++ LineMap* linemap_; ++ vector* files_; ++ vector* dirs_; ++}; ++ ++class CUFunctionInfoHandler: public Dwarf2Handler { ++ public: ++ CUFunctionInfoHandler(vector* files, ++ vector* dirs, ++ LineMap* linemap, ++ FunctionMap* offset_to_funcinfo, ++ FunctionMap* address_to_funcinfo, ++ CULineInfoHandler* linehandler, ++ const SectionMap& sections, ++ ByteReader* reader) ++ : files_(files), dirs_(dirs), linemap_(linemap), ++ offset_to_funcinfo_(offset_to_funcinfo), ++ address_to_funcinfo_(address_to_funcinfo), ++ linehandler_(linehandler), sections_(sections), ++ reader_(reader), current_function_info_(NULL) { } ++ ++ virtual ~CUFunctionInfoHandler() { } ++ ++ // Start to process a compilation unit at OFFSET from the beginning of the ++ // .debug_info section. We want to see all compilation units, so we ++ // always return true. ++ ++ virtual bool StartCompilationUnit(uint64 offset, uint8 address_size, ++ uint8 offset_size, uint64 cu_length, ++ uint8 dwarf_version); ++ ++ // Start to process a DIE at OFFSET from the beginning of the ++ // .debug_info section. We only care about function related DIE's. ++ virtual bool StartDIE(uint64 offset, enum DwarfTag tag, ++ const AttributeList& attrs); ++ ++ // Called when we have an attribute with unsigned data to give to ++ // our handler. The attribute is for the DIE at OFFSET from the ++ // beginning of the .debug_info section, has a name of ATTR, a form of ++ // FORM, and the actual data of the attribute is in DATA. ++ virtual void ProcessAttributeUnsigned(uint64 offset, ++ enum DwarfAttribute attr, ++ enum DwarfForm form, ++ uint64 data); ++ ++ // Called when we have an attribute with string data to give to ++ // our handler. The attribute is for the DIE at OFFSET from the ++ // beginning of the .debug_info section, has a name of ATTR, a form of ++ // FORM, and the actual data of the attribute is in DATA. ++ virtual void ProcessAttributeString(uint64 offset, ++ enum DwarfAttribute attr, ++ enum DwarfForm form, ++ const string& data); ++ ++ // Called when finished processing the DIE at OFFSET. ++ // Because DWARF2/3 specifies a tree of DIEs, you may get starts ++ // before ends of the previous DIE, as we process children before ++ // ending the parent. ++ virtual void EndDIE(uint64 offset); ++ ++ private: ++ vector* files_; ++ vector* dirs_; ++ LineMap* linemap_; ++ FunctionMap* offset_to_funcinfo_; ++ FunctionMap* address_to_funcinfo_; ++ CULineInfoHandler* linehandler_; ++ const SectionMap& sections_; ++ ByteReader* reader_; ++ FunctionInfo* current_function_info_; ++ uint64 current_compilation_unit_offset_; ++}; ++ ++} // namespace dwarf2reader ++#endif // COMMON_DWARF_FUNCTIONINFO_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/line_state_machine.h b/toolkit/crashreporter/google-breakpad/src/common/dwarf/line_state_machine.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/line_state_machine.h +@@ -0,0 +1,61 @@ ++// Copyright 2008 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 COMMON_DWARF_LINE_STATE_MACHINE_H__ ++#define COMMON_DWARF_LINE_STATE_MACHINE_H__ ++ ++namespace dwarf2reader { ++ ++// This is the format of a DWARF2/3 line state machine that we process ++// opcodes using. There is no need for anything outside the lineinfo ++// processor to know how this works. ++struct LineStateMachine { ++ void Reset(bool default_is_stmt) { ++ file_num = 1; ++ address = 0; ++ line_num = 1; ++ column_num = 0; ++ is_stmt = default_is_stmt; ++ basic_block = false; ++ end_sequence = false; ++ } ++ ++ uint32 file_num; ++ uint64 address; ++ uint64 line_num; ++ uint32 column_num; ++ bool is_stmt; // stmt means statement. ++ bool basic_block; ++ bool end_sequence; ++}; ++ ++} // namespace dwarf2reader ++ ++ ++#endif // COMMON_DWARF_LINE_STATE_MACHINE_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/types.h b/toolkit/crashreporter/google-breakpad/src/common/dwarf/types.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/dwarf/types.h +@@ -0,0 +1,53 @@ ++// Copyright 2008 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. ++ ++ ++// This file contains some typedefs for basic types ++ ++ ++#ifndef _COMMON_DWARF_TYPES_H__ ++#define _COMMON_DWARF_TYPES_H__ ++ ++typedef signed char int8; ++typedef short int16; ++typedef int int32; ++typedef long long int64; ++ ++typedef unsigned char uint8; ++typedef unsigned short uint16; ++typedef unsigned int uint32; ++typedef unsigned long long uint64; ++ ++#ifdef __PTRDIFF_TYPE__ ++typedef __PTRDIFF_TYPE__ intptr; ++typedef unsigned __PTRDIFF_TYPE__ uintptr; ++#else ++#error "Can't find pointer-sized integral types." ++#endif ++ ++#endif // _COMMON_DWARF_TYPES_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/Makefile.in b/toolkit/crashreporter/google-breakpad/src/common/linux/Makefile.in +--- a/toolkit/crashreporter/google-breakpad/src/common/linux/Makefile.in ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/Makefile.in +@@ -42,27 +42,27 @@ VPATH = @srcdir@ + include $(DEPTH)/config/autoconf.mk + + MODULE = breakpad_linux_common + LIBRARY_NAME = breakpad_linux_common_s + HOST_LIBRARY_NAME = host_breakpad_linux_common_s + + LOCAL_INCLUDES = -I$(srcdir)/../.. + +-# not compiling http_upload.cc currently +-# since it depends on libcurl + CPPSRCS = \ +- dump_symbols.cc \ + file_id.cc \ + guid_creator.cc \ ++ http_upload.cc \ + $(NULL) + + HOST_CPPSRCS = \ + dump_symbols.cc \ + file_id.cc \ + guid_creator.cc \ ++ module.cc \ ++ stabs_reader.cc \ + $(NULL) + + # need static lib + FORCE_STATIC_LIB = 1 + FORCE_USE_PIC = 1 + + include $(topsrcdir)/config/rules.mk +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc +--- a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc +@@ -22,136 +22,70 @@ + // 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 +-#include +-#include ++#include + #include +-#include + #include + #include + #include + #include ++#include + #include +-#include + #include + #include + #include ++ + #include +- ++#include ++#include ++#include ++#include + #include + #include ++#include ++#include + #include +-#include + + #include "common/linux/dump_symbols.h" + #include "common/linux/file_id.h" +-#include "common/linux/guid_creator.h" +-#include "processor/scoped_ptr.h" ++#include "common/linux/module.h" ++#include "common/linux/stabs_reader.h" + + // This namespace contains helper functions. + namespace { + +-// Infomation of a line. +-struct LineInfo { +- // The index into string table for the name of the source file which +- // this line belongs to. +- // Load from stab symbol. +- uint32_t source_name_index; +- // Offset from start of the function. +- // Load from stab symbol. +- ElfW(Off) rva_to_func; +- // Offset from base of the loading binary. +- ElfW(Off) rva_to_base; +- // Size of the line. +- // It is the difference of the starting address of the line and starting +- // address of the next N_SLINE, N_FUN or N_SO. +- uint32_t size; +- // Line number. +- uint32_t line_num; +- // Id of the source file for this line. +- int source_id; +-}; +- +-typedef std::list LineInfoList; +- +-// Information of a function. +-struct FuncInfo { +- // Name of the function. +- const char *name; +- // Offset from the base of the loading address. +- ElfW(Off) rva_to_base; +- // Virtual address of the function. +- // Load from stab symbol. +- ElfW(Addr) addr; +- // Size of the function. +- // It is the difference of the starting address of the function and starting +- // address of the next N_FUN or N_SO. +- uint32_t size; +- // Total size of stack parameters. +- uint32_t stack_param_size; +- // Is there any lines included from other files? +- bool has_sol; +- // Line information array. +- LineInfoList line_info; +-}; +- +-typedef std::list FuncInfoList; +- +-// Information of a source file. +-struct SourceFileInfo { +- // Name string index into the string table. +- uint32_t name_index; +- // Name of the source file. +- const char *name; +- // Starting address of the source file. +- ElfW(Addr) addr; +- // Id of the source file. +- int source_id; +- // Functions information. +- FuncInfoList func_info; +-}; +- +-typedef std::list SourceFileInfoList; +- +-// Information of a symbol table. +-// This is the root of all types of symbol. +-struct SymbolInfo { +- SourceFileInfoList source_file_info; +- +- // The next source id for newly found source file. +- int next_source_id; +-}; ++using google_breakpad::Module; ++using std::vector; + + // Stab section name. + static const char *kStabName = ".stab"; + + // Demangle using abi call. + // Older GCC may not support it. +-static std::string Demangle(const char *mangled) { ++static std::string Demangle(const std::string &mangled) { + int status = 0; +- char *demangled = abi::__cxa_demangle(mangled, NULL, NULL, &status); ++ char *demangled = abi::__cxa_demangle(mangled.c_str(), NULL, NULL, &status); + if (status == 0 && demangled != NULL) { + std::string str(demangled); + free(demangled); + return str; + } + return std::string(mangled); + } + + // Fix offset into virtual address by adding the mapped base into offsets. + // Make life easier when want to find something by offset. + static void FixAddress(void *obj_base) { +- ElfW(Word) base = reinterpret_cast(obj_base); ++ ElfW(Addr) base = reinterpret_cast(obj_base); + ElfW(Ehdr) *elf_header = static_cast(obj_base); + elf_header->e_phoff += base; + elf_header->e_shoff += base; + ElfW(Shdr) *sections = reinterpret_cast(elf_header->e_shoff); + for (int i = 0; i < elf_header->e_shnum; ++i) + sections[i].sh_offset += base; + } + +@@ -164,28 +98,16 @@ static ElfW(Addr) GetLoadingAddress(cons + if (header.p_type == PT_LOAD && + header.p_offset == 0) + return header.p_vaddr; + } + // For other types of ELF, return 0. + return 0; + } + +-static bool WriteFormat(int fd, const char *fmt, ...) { +- va_list list; +- char buffer[4096]; +- ssize_t expected, written; +- va_start(list, fmt); +- vsnprintf(buffer, sizeof(buffer), fmt, list); +- expected = strlen(buffer); +- written = write(fd, buffer, strlen(buffer)); +- va_end(list); +- return expected == written; +-} +- + static bool IsValidElf(const ElfW(Ehdr) *elf_header) { + return memcmp(elf_header, ELFMAG, SELFMAG) == 0; + } + + static const ElfW(Shdr) *FindSectionByName(const char *name, + const ElfW(Shdr) *sections, + const ElfW(Shdr) *strtab, + int nsection) { +@@ -194,508 +116,251 @@ static const ElfW(Shdr) *FindSectionByNa + assert(nsection > 0); + + int name_len = strlen(name); + if (name_len == 0) + return NULL; + + for (int i = 0; i < nsection; ++i) { + const char *section_name = +- (char*)(strtab->sh_offset + sections[i].sh_name); ++ reinterpret_cast(strtab->sh_offset + sections[i].sh_name); + if (!strncmp(name, section_name, name_len)) + return sections + i; + } + return NULL; + } + +-// TODO(liuli): Computer the stack parameter size. +-// Expect parameter variables are immediately following the N_FUN symbol. +-// Will need to parse the type information to get a correct size. +-static int LoadStackParamSize(struct nlist *list, +- struct nlist *list_end, +- struct FuncInfo *func_info) { +- struct nlist *cur_list = list; +- assert(cur_list->n_type == N_FUN); +- ++cur_list; +- int step = 1; +- while (cur_list < list_end && cur_list->n_type == N_PSYM) { +- ++cur_list; +- ++step; +- } +- func_info->stack_param_size = 0; +- return step; ++// Our handler class for STABS data. ++class DumpStabsHandler: public google_breakpad::StabsHandler { ++ public: ++ DumpStabsHandler(Module *module) : ++ module_(module), ++ comp_unit_base_address_(0), ++ current_function_(NULL), ++ current_source_file_(NULL), ++ current_source_file_name_(NULL) { } ++ ++ bool StartCompilationUnit(const char *name, uint64_t address, ++ const char *build_directory); ++ bool EndCompilationUnit(uint64_t address); ++ bool StartFunction(const std::string &name, uint64_t address); ++ bool EndFunction(uint64_t address); ++ bool Line(uint64_t address, const char *name, int number); ++ void Warning(const char *format, ...); ++ ++ // Do any final processing necessary to make module_ contain all the ++ // data provided by the STABS reader. ++ // ++ // Because STABS does not provide reliable size information for ++ // functions and lines, we need to make a pass over the data after ++ // processing all the STABS to compute those sizes. We take care of ++ // that here. ++ void Finalize(); ++ ++ private: ++ ++ // An arbitrary, but very large, size to use for functions whose ++ // size we can't compute properly. ++ static const uint64_t kFallbackSize = 0x10000000; ++ ++ // The module we're contributing debugging info to. ++ Module *module_; ++ ++ // The functions we've generated so far. We don't add these to ++ // module_ as we parse them. Instead, we wait until we've computed ++ // their ending address, and their lines' ending addresses. ++ // ++ // We could just stick them in module_ from the outset, but if ++ // module_ already contains data gathered from other debugging ++ // formats, that would complicate the size computation. ++ vector functions_; ++ ++ // Boundary addresses. STABS doesn't necessarily supply sizes for ++ // functions and lines, so we need to compute them ourselves by ++ // finding the next object. ++ vector boundaries_; ++ ++ // The base address of the current compilation unit. We use this to ++ // recognize functions we should omit from the symbol file. (If you ++ // know the details of why we omit these, please patch this ++ // comment.) ++ Module::Address comp_unit_base_address_; ++ ++ // The function we're currently contributing lines to. ++ Module::Function *current_function_; ++ ++ // The last Module::File we got a line number in. ++ Module::File *current_source_file_; ++ ++ // The pointer in the .stabstr section of the name that ++ // current_source_file_ is built from. This allows us to quickly ++ // recognize when the current line is in the same file as the ++ // previous one (which it usually is). ++ const char *current_source_file_name_; ++}; ++ ++bool DumpStabsHandler::StartCompilationUnit(const char *name, uint64_t address, ++ const char *build_directory) { ++ assert(! comp_unit_base_address_); ++ current_source_file_name_ = name; ++ current_source_file_ = module_->FindFile(name); ++ comp_unit_base_address_ = address; ++ boundaries_.push_back(static_cast(address)); ++ return true; + } + +-static int LoadLineInfo(struct nlist *list, +- struct nlist *list_end, +- const struct SourceFileInfo &source_file_info, +- struct FuncInfo *func_info) { +- struct nlist *cur_list = list; +- func_info->has_sol = false; +- // Records which source file the following lines belongs. Default +- // to the file we are handling. This helps us handling inlined source. +- // When encountering N_SOL, we will change this to the source file +- // specified by N_SOL. +- int current_source_name_index = source_file_info.name_index; +- do { +- // Skip non line information. +- while (cur_list < list_end && cur_list->n_type != N_SLINE) { +- // Only exit when got another function, or source file. +- if (cur_list->n_type == N_FUN || cur_list->n_type == N_SO) +- return cur_list - list; +- // N_SOL means source lines following it will be from +- // another source file. +- if (cur_list->n_type == N_SOL) { +- func_info->has_sol = true; +- +- if (cur_list->n_un.n_strx > 0 && +- cur_list->n_un.n_strx != current_source_name_index) { +- // The following lines will be from this source file. +- current_source_name_index = cur_list->n_un.n_strx; +- } +- } +- ++cur_list; +- } +- struct LineInfo line; +- while (cur_list < list_end && cur_list->n_type == N_SLINE) { +- line.source_name_index = current_source_name_index; +- line.rva_to_func = cur_list->n_value; +- // n_desc is a signed short +- line.line_num = (unsigned short)cur_list->n_desc; +- // Don't set it here. +- // Will be processed in later pass. +- line.source_id = -1; +- func_info->line_info.push_back(line); +- ++cur_list; +- } +- } while (list < list_end); +- +- return cur_list - list; ++bool DumpStabsHandler::EndCompilationUnit(uint64_t address) { ++ assert(comp_unit_base_address_); ++ comp_unit_base_address_ = 0; ++ current_source_file_ = NULL; ++ current_source_file_name_ = NULL; ++ if (address) ++ boundaries_.push_back(static_cast(address)); ++ return true; + } + +-static int LoadFuncSymbols(struct nlist *list, +- struct nlist *list_end, +- const ElfW(Shdr) *stabstr_section, +- struct SourceFileInfo *source_file_info) { +- struct nlist *cur_list = list; +- assert(cur_list->n_type == N_SO); +- ++cur_list; +- source_file_info->func_info.clear(); +- while (cur_list < list_end) { +- // Go until the function symbol. +- while (cur_list < list_end && cur_list->n_type != N_FUN) { +- if (cur_list->n_type == N_SO) { +- return cur_list - list; +- } +- ++cur_list; +- continue; +- } +- if (cur_list->n_type == N_FUN) { +- struct FuncInfo func_info; +- func_info.name = +- reinterpret_cast(cur_list->n_un.n_strx + +- stabstr_section->sh_offset); +- func_info.addr = cur_list->n_value; +- func_info.rva_to_base = 0; +- func_info.size = 0; +- func_info.stack_param_size = 0; +- func_info.has_sol = 0; ++bool DumpStabsHandler::StartFunction(const std::string &name, ++ uint64_t address) { ++ assert(! current_function_); ++ Module::Function *f = new Module::Function; ++ f->name_ = Demangle(name); ++ f->address_ = address; ++ f->size_ = 0; // We compute this in DumpStabsHandler::Finalize(). ++ f->parameter_size_ = 0; // We don't provide this information. ++ current_function_ = f; ++ boundaries_.push_back(static_cast(address)); ++ return true; ++} + +- // Stack parameter size. +- cur_list += LoadStackParamSize(cur_list, list_end, &func_info); +- // Line info. +- cur_list += LoadLineInfo(cur_list, +- list_end, +- *source_file_info, +- &func_info); ++bool DumpStabsHandler::EndFunction(uint64_t address) { ++ assert(current_function_); ++ // Functions in this compilation unit should have address bigger ++ // than the compilation unit's starting address. There may be a lot ++ // of duplicated entries for functions in the STABS data; only one ++ // entry can meet this requirement. ++ // ++ // (I don't really understand the above comment; just bringing it ++ // along from the previous code, and leaving the behaivor unchanged. ++ // If you know the whole story, please patch this comment. --jimb) ++ if (current_function_->address_ >= comp_unit_base_address_) ++ functions_.push_back(current_function_); ++ else ++ delete current_function_; ++ current_function_ = NULL; ++ if (address) ++ boundaries_.push_back(static_cast(address)); ++ return true; ++} + +- // Functions in this module should have address bigger than the module +- // startring address. +- // There maybe a lot of duplicated entry for a function in the symbol, +- // only one of them can met this. +- if (func_info.addr >= source_file_info->addr) { +- source_file_info->func_info.push_back(func_info); +- } ++bool DumpStabsHandler::Line(uint64_t address, const char *name, int number) { ++ assert(current_function_); ++ assert(current_source_file_); ++ if (name != current_source_file_name_) { ++ current_source_file_ = module_->FindFile(name); ++ current_source_file_name_ = name; ++ } ++ Module::Line line; ++ line.address_ = address; ++ line.size_ = 0; // We compute this in DumpStabsHandler::Finalize(). ++ line.file_ = current_source_file_; ++ line.number_ = number; ++ current_function_->lines_.push_back(line); ++ return true; ++} ++ ++void DumpStabsHandler::Warning(const char *format, ...) { ++ va_list args; ++ va_start(args, format); ++ vfprintf(stderr, format, args); ++ va_end(args); ++} ++ ++void DumpStabsHandler::Finalize() { ++ // Sort our boundary list, so we can search it quickly. ++ sort(boundaries_.begin(), boundaries_.end()); ++ // Sort all functions by address, just for neatness. ++ sort(functions_.begin(), functions_.end(), ++ Module::Function::CompareByAddress); ++ for (vector::iterator func_it = functions_.begin(); ++ func_it != functions_.end(); ++ func_it++) { ++ Module::Function *f = *func_it; ++ // Compute the function f's size. ++ vector::iterator boundary ++ = std::upper_bound(boundaries_.begin(), boundaries_.end(), f->address_); ++ if (boundary != boundaries_.end()) ++ f->size_ = *boundary - f->address_; ++ else ++ // If this is the last function in the module, and the STABS ++ // reader was unable to give us its ending address, then assign ++ // it a bogus, very large value. This will happen at most once ++ // per module: since we've added all functions' addresses to the ++ // boundary table, only one can be the last. ++ f->size_ = kFallbackSize; ++ ++ // Compute sizes for each of the function f's lines --- if it has any. ++ if (! f->lines_.empty()) { ++ stable_sort(f->lines_.begin(), f->lines_.end(), ++ Module::Line::CompareByAddress); ++ vector::iterator last_line = f->lines_.end() - 1; ++ for (vector::iterator line_it = f->lines_.begin(); ++ line_it != last_line; line_it++) ++ line_it[0].size_ = line_it[1].address_ - line_it[0].address_; ++ // Compute the size of the last line from f's end address. ++ last_line->size_ = (f->address_ + f->size_) - last_line->address_; + } + } +- return cur_list - list; +-} +- +-// Comapre the address. +-// The argument should have a memeber named "addr" +-template +-static bool CompareAddress(T1 *a, T2 *b) { +- return a->addr < b->addr; +-} +- +-// Sort the array into increasing ordered array based on the virtual address. +-// Return vector of pointers to the elements in the incoming array. So caller +-// should make sure the returned vector lives longer than the incoming vector. +-template +-static std::vector SortByAddress( +- Container *container) { +- typedef typename Container::iterator It; +- typedef typename Container::value_type T; +- std::vector sorted_array_ptr; +- sorted_array_ptr.reserve(container->size()); +- for (It it = container->begin(); it != container->end(); it++) +- sorted_array_ptr.push_back(&(*it)); +- std::sort(sorted_array_ptr.begin(), +- sorted_array_ptr.end(), +- std::ptr_fun(CompareAddress)); +- +- return sorted_array_ptr; +-} +- +-// Find the address of the next function or source file symbol in the symbol +-// table. The address should be bigger than the current function's address. +-static ElfW(Addr) NextAddress( +- std::vector *sorted_functions, +- std::vector *sorted_files, +- const struct FuncInfo &func_info) { +- std::vector::iterator next_func_iter = +- std::find_if(sorted_functions->begin(), +- sorted_functions->end(), +- std::bind1st( +- std::ptr_fun( +- CompareAddress +- ), +- &func_info) +- ); +- if (next_func_iter != sorted_functions->end()) +- return (*next_func_iter)->addr; +- +- std::vector::iterator next_file_iter = +- std::find_if(sorted_files->begin(), +- sorted_files->end(), +- std::bind1st( +- std::ptr_fun( +- CompareAddress +- ), +- &func_info) +- ); +- if (next_file_iter != sorted_files->end()) { +- return (*next_file_iter)->addr; +- } +- return 0; +-} +- +-static int FindFileByNameIdx(uint32_t name_index, +- SourceFileInfoList &files) { +- for (SourceFileInfoList::iterator it = files.begin(); +- it != files.end(); it++) { +- if (it->name_index == name_index) +- return it->source_id; +- } +- +- return -1; +-} +- +-// Add included file information. +-// Also fix the source id for the line info. +-static void AddIncludedFiles(struct SymbolInfo *symbols, +- const ElfW(Shdr) *stabstr_section) { +- for (SourceFileInfoList::iterator source_file_it = +- symbols->source_file_info.begin(); +- source_file_it != symbols->source_file_info.end(); +- ++source_file_it) { +- struct SourceFileInfo &source_file = *source_file_it; +- +- for (FuncInfoList::iterator func_info_it = source_file.func_info.begin(); +- func_info_it != source_file.func_info.end(); +- ++func_info_it) { +- struct FuncInfo &func_info = *func_info_it; +- +- for (LineInfoList::iterator line_info_it = func_info.line_info.begin(); +- line_info_it != func_info.line_info.end(); ++line_info_it) { +- struct LineInfo &line_info = *line_info_it; +- +- assert(line_info.source_name_index > 0); +- assert(source_file.name_index > 0); +- +- // Check if the line belongs to the source file by comparing the +- // name index into string table. +- if (line_info.source_name_index != source_file.name_index) { +- // This line is not from the current source file, check if this +- // source file has been added before. +- int found_source_id = FindFileByNameIdx(line_info.source_name_index, +- symbols->source_file_info); +- if (found_source_id < 0) { +- // Got a new included file. +- // Those included files don't have address or line information. +- SourceFileInfo new_file; +- new_file.name_index = line_info.source_name_index; +- new_file.name = reinterpret_cast(new_file.name_index + +- stabstr_section->sh_offset); +- new_file.addr = 0; +- new_file.source_id = symbols->next_source_id++; +- line_info.source_id = new_file.source_id; +- symbols->source_file_info.push_back(new_file); +- } else { +- // The file has been added. +- line_info.source_id = found_source_id; +- } +- } else { +- // The line belongs to the file. +- line_info.source_id = source_file.source_id; +- } +- } // for each line. +- } // for each function. +- } // for each source file. +- +-} +- +-// Compute size and rva information based on symbols loaded from stab section. +-static bool ComputeSizeAndRVA(ElfW(Addr) loading_addr, +- struct SymbolInfo *symbols) { +- std::vector sorted_files = +- SortByAddress(&(symbols->source_file_info)); +- for (size_t i = 0; i < sorted_files.size(); ++i) { +- struct SourceFileInfo &source_file = *sorted_files[i]; +- std::vector sorted_functions = +- SortByAddress(&(source_file.func_info)); +- for (size_t j = 0; j < sorted_functions.size(); ++j) { +- struct FuncInfo &func_info = *sorted_functions[j]; +- assert(func_info.addr >= loading_addr); +- func_info.rva_to_base = func_info.addr - loading_addr; +- func_info.size = 0; +- ElfW(Addr) next_addr = NextAddress(&sorted_functions, +- &sorted_files, +- func_info); +- // I've noticed functions with an address bigger than any other functions +- // and source files modules, this is probably the last function in the +- // module, due to limitions of Linux stab symbol, it is impossible to get +- // the exact size of this kind of function, thus we give it a default +- // very big value. This should be safe since this is the last function. +- // But it is a ugly hack..... +- // The following code can reproduce the case: +- // template +- // void Foo(T value) { +- // } +- // +- // int main(void) { +- // Foo(10); +- // Foo(std::string("hello")); +- // return 0; +- // } +- // TODO(liuli): Find a better solution. +- static const int kDefaultSize = 0x10000000; +- static int no_next_addr_count = 0; +- if (next_addr != 0) { +- func_info.size = next_addr - func_info.addr; +- } else { +- if (no_next_addr_count > 1) { +- fprintf(stderr, "Got more than one funtion without the \ +- following symbol. Igore this function.\n"); +- fprintf(stderr, "The dumped symbol may not correct.\n"); +- assert(!"This should not happen!\n"); +- func_info.size = 0; +- continue; +- } +- +- no_next_addr_count++; +- func_info.size = kDefaultSize; +- } +- // Compute line size. +- for (LineInfoList::iterator line_info_it = func_info.line_info.begin(); +- line_info_it != func_info.line_info.end(); line_info_it++) { +- struct LineInfo &line_info = *line_info_it; +- LineInfoList::iterator next_line_info_it = line_info_it; +- next_line_info_it++; +- line_info.size = 0; +- if (next_line_info_it != func_info.line_info.end()) { +- line_info.size = +- next_line_info_it->rva_to_func - line_info.rva_to_func; +- } else { +- // The last line in the function. +- // If we can find a function or source file symbol immediately +- // following the line, we can get the size of the line by computing +- // the difference of the next address to the starting address of this +- // line. +- // Otherwise, we need to set a default big enough value. This occurs +- // mostly because the this function is the last one in the module. +- if (next_addr != 0) { +- ElfW(Off) next_addr_offset = next_addr - func_info.addr; +- line_info.size = next_addr_offset - line_info.rva_to_func; +- } else { +- line_info.size = kDefaultSize; +- } +- } +- line_info.rva_to_base = line_info.rva_to_func + func_info.rva_to_base; +- } // for each line. +- } // for each function. +- } // for each source file. +- return true; ++ // Now that everything has a size, add our functions to the module, and ++ // dispose of our private list. ++ module_->AddFunctions(functions_.begin(), functions_.end()); ++ functions_.clear(); + } + + static bool LoadSymbols(const ElfW(Shdr) *stab_section, + const ElfW(Shdr) *stabstr_section, +- ElfW(Addr) loading_addr, +- struct SymbolInfo *symbols) { ++ Module *module) { + if (stab_section == NULL || stabstr_section == NULL) + return false; + +- struct nlist *lists = +- reinterpret_cast(stab_section->sh_offset); +- int nstab = stab_section->sh_size / sizeof(struct nlist); +- // First pass, load all symbols from the object file. +- for (int i = 0; i < nstab; ) { +- int step = 1; +- struct nlist *cur_list = lists + i; +- if (cur_list->n_type == N_SO) { +- // FUNC
+- struct SourceFileInfo source_file_info; +- source_file_info.name_index = cur_list->n_un.n_strx; +- source_file_info.name = reinterpret_cast(cur_list->n_un.n_strx + +- stabstr_section->sh_offset); +- source_file_info.addr = cur_list->n_value; +- if (strchr(source_file_info.name, '.')) +- source_file_info.source_id = symbols->next_source_id++; +- else +- source_file_info.source_id = -1; +- step = LoadFuncSymbols(cur_list, lists + nstab, +- stabstr_section, &source_file_info); +- symbols->source_file_info.push_back(source_file_info); +- } +- i += step; +- } +- +- // Second pass, compute the size of functions and lines. +- if (ComputeSizeAndRVA(loading_addr, symbols)) { +- // Third pass, check for included source code, especially for header files. +- // Until now, we only have compiling unit information, but they can +- // have code from include files, add them here. +- AddIncludedFiles(symbols, stabstr_section); +- return true; +- } +- return false; ++ // A callback object to handle data from the STABS reader. ++ DumpStabsHandler handler(module); ++ // Find the addresses of the STABS data, and create a STABS reader object. ++ uint8_t *stabs = reinterpret_cast(stab_section->sh_offset); ++ uint8_t *stabstr = reinterpret_cast(stabstr_section->sh_offset); ++ google_breakpad::StabsReader reader(stabs, stab_section->sh_size, ++ stabstr, stabstr_section->sh_size, ++ &handler); ++ // Read the STABS data, and do post-processing. ++ if (! reader.Process()) ++ return false; ++ handler.Finalize(); ++ return true; + } + +-static bool LoadSymbols(ElfW(Ehdr) *elf_header, struct SymbolInfo *symbols) { ++static bool LoadSymbols(ElfW(Ehdr) *elf_header, Module *module) { + // Translate all offsets in section headers into address. + FixAddress(elf_header); + ElfW(Addr) loading_addr = GetLoadingAddress( + reinterpret_cast(elf_header->e_phoff), + elf_header->e_phnum); ++ module->SetLoadAddress(loading_addr); + + const ElfW(Shdr) *sections = + reinterpret_cast(elf_header->e_shoff); + const ElfW(Shdr) *strtab = sections + elf_header->e_shstrndx; + const ElfW(Shdr) *stab_section = + FindSectionByName(kStabName, sections, strtab, elf_header->e_shnum); + if (stab_section == NULL) { + fprintf(stderr, "Stab section not found.\n"); + return false; + } + const ElfW(Shdr) *stabstr_section = stab_section->sh_link + sections; + + // Load symbols. +- return LoadSymbols(stab_section, stabstr_section, loading_addr, symbols); +-} +- +-static bool WriteModuleInfo(int fd, +- ElfW(Half) arch, +- const std::string &obj_file) { +- const char *arch_name = NULL; +- if (arch == EM_386) +- arch_name = "x86"; +- else if (arch == EM_X86_64) +- arch_name = "x86_64"; +- else +- return false; +- +- unsigned char identifier[16]; +- google_breakpad::FileID file_id(obj_file.c_str()); +- if (file_id.ElfFileIdentifier(identifier)) { +- char identifier_str[40]; +- file_id.ConvertIdentifierToString(identifier, +- identifier_str, sizeof(identifier_str)); +- char id_no_dash[40]; +- int id_no_dash_len = 0; +- memset(id_no_dash, 0, sizeof(id_no_dash)); +- for (int i = 0; identifier_str[i] != '\0'; ++i) +- if (identifier_str[i] != '-') +- id_no_dash[id_no_dash_len++] = identifier_str[i]; +- // Add an extra "0" by the end. +- id_no_dash[id_no_dash_len++] = '0'; +- std::string filename = obj_file; +- size_t slash_pos = obj_file.find_last_of("/"); +- if (slash_pos != std::string::npos) +- filename = obj_file.substr(slash_pos + 1); +- return WriteFormat(fd, "MODULE Linux %s %s %s\n", arch_name, +- id_no_dash, filename.c_str()); +- } +- return false; +-} +- +-static bool WriteSourceFileInfo(int fd, const struct SymbolInfo &symbols) { +- for (SourceFileInfoList::const_iterator it = +- symbols.source_file_info.begin(); +- it != symbols.source_file_info.end(); it++) { +- if (it->source_id != -1) { +- const char *name = it->name; +- if (!WriteFormat(fd, "FILE %d %s\n", it->source_id, name)) +- return false; +- } +- } +- return true; +-} +- +-static bool WriteOneFunction(int fd, +- const struct FuncInfo &func_info){ +- // Discard the ending part of the name. +- std::string func_name(func_info.name); +- std::string::size_type last_colon = func_name.find_last_of(':'); +- if (last_colon != std::string::npos) +- func_name = func_name.substr(0, last_colon); +- func_name = Demangle(func_name.c_str()); +- +- if (func_info.size <= 0) +- return true; +- +- if (WriteFormat(fd, "FUNC %lx %lx %d %s\n", +- func_info.rva_to_base, +- func_info.size, +- func_info.stack_param_size, +- func_name.c_str())) { +- for (LineInfoList::const_iterator it = func_info.line_info.begin(); +- it != func_info.line_info.end(); it++) { +- const struct LineInfo &line_info = *it; +- if (!WriteFormat(fd, "%lx %lx %d %d\n", +- line_info.rva_to_base, +- line_info.size, +- line_info.line_num, +- line_info.source_id)) +- return false; +- } +- return true; +- } +- return false; +-} +- +-static bool WriteFunctionInfo(int fd, const struct SymbolInfo &symbols) { +- for (SourceFileInfoList::const_iterator it = +- symbols.source_file_info.begin(); +- it != symbols.source_file_info.end(); it++) { +- const struct SourceFileInfo &file_info = *it; +- for (FuncInfoList::const_iterator fiIt = file_info.func_info.begin(); +- fiIt != file_info.func_info.end(); fiIt++) { +- const struct FuncInfo &func_info = *fiIt; +- if (!WriteOneFunction(fd, func_info)) +- return false; +- } +- } +- return true; +-} +- +-static bool DumpStabSymbols(int fd, const struct SymbolInfo &symbols) { +- return WriteSourceFileInfo(fd, symbols) && +- WriteFunctionInfo(fd, symbols); ++ return LoadSymbols(stab_section, stabstr_section, module); + } + + // + // FDWrapper + // + // Wrapper class to make sure opened file is closed. + // + class FDWrapper { +@@ -740,43 +405,95 @@ class MmapWrapper { + size_ = 0; + } + + private: + void *base_; + size_t size_; + }; + ++// Return the breakpad symbol file identifier for the architecture of ++// ELF_HEADER. ++const char *ElfArchitecture(const ElfW(Ehdr) *elf_header) { ++ ElfW(Half) arch = elf_header->e_machine; ++ if (arch == EM_386) ++ return "x86"; ++ else if (arch == EM_X86_64) ++ return "x86_64"; ++ else ++ return NULL; ++} ++ ++// Format the Elf file identifier in IDENTIFIER as a UUID with the ++// dashes removed. ++std::string FormatIdentifier(unsigned char identifier[16]) { ++ char identifier_str[40]; ++ google_breakpad::FileID::ConvertIdentifierToString( ++ identifier, ++ identifier_str, ++ sizeof(identifier_str)); ++ std::string id_no_dash; ++ for (int i = 0; identifier_str[i] != '\0'; ++i) ++ if (identifier_str[i] != '-') ++ id_no_dash += identifier_str[i]; ++ // Add an extra "0" by the end. PDB files on Windows have an 'age' ++ // number appended to the end of the file identifier; this isn't ++ // really used or necessary on other platforms, but let's preserve ++ // the pattern. ++ id_no_dash += '0'; ++ return id_no_dash; ++} ++ ++// Return the non-directory portion of FILENAME: the portion after the ++// last slash, or the whole filename if there are no slashes. ++std::string BaseFileName(const std::string &filename) { ++ // Lots of copies! basename's behavior is less than ideal. ++ char *c_filename = strdup(filename.c_str()); ++ std::string base = basename(c_filename); ++ free(c_filename); ++ return base; ++} ++ + } // namespace + + namespace google_breakpad { + + bool DumpSymbols::WriteSymbolFile(const std::string &obj_file, +- int sym_fd) { ++ FILE *sym_file) { + int obj_fd = open(obj_file.c_str(), O_RDONLY); + if (obj_fd < 0) + return false; + FDWrapper obj_fd_wrapper(obj_fd); + struct stat st; + if (fstat(obj_fd, &st) != 0 && st.st_size <= 0) + return false; + void *obj_base = mmap(NULL, st.st_size, + PROT_READ | PROT_WRITE, MAP_PRIVATE, obj_fd, 0); +- if (!obj_base) ++ if (obj_base == MAP_FAILED) + return false; + MmapWrapper map_wrapper(obj_base, st.st_size); + ElfW(Ehdr) *elf_header = reinterpret_cast(obj_base); + if (!IsValidElf(elf_header)) + return false; +- struct SymbolInfo symbols; +- symbols.next_source_id = 0; + +- if (!LoadSymbols(elf_header, &symbols)) +- return false; +- // Write to symbol file. +- if (WriteModuleInfo(sym_fd, elf_header->e_machine, obj_file) && +- DumpStabSymbols(sym_fd, symbols)) +- return true; ++ unsigned char identifier[16]; ++ google_breakpad::FileID file_id(obj_file.c_str()); ++ if (! file_id.ElfFileIdentifier(identifier)) ++ return false; + +- return false; ++ const char *architecture = ElfArchitecture(elf_header); ++ if (! architecture) ++ return false; ++ ++ std::string name = BaseFileName(obj_file); ++ std::string os = "Linux"; ++ std::string id = FormatIdentifier(identifier); ++ ++ Module module(name, os, architecture, id); ++ if (!LoadSymbols(elf_header, &module)) ++ return false; ++ if (!module.Write(sym_file)) ++ return false; ++ ++ return true; + } + + } // namespace google_breakpad +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.h b/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.h +--- a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.h ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.h +@@ -29,20 +29,21 @@ + // + // dump_symbols.cc: Implements a linux stab debugging format dumper. + // + + #ifndef COMMON_LINUX_DUMP_SYMBOLS_H__ + #define COMMON_LINUX_DUMP_SYMBOLS_H__ + + #include ++#include + + namespace google_breakpad { + + class DumpSymbols { + public: + bool WriteSymbolFile(const std::string &obj_file, +- int sym_fd); ++ FILE *sym_file); + }; + + } // namespace google_breakpad + + #endif // COMMON_LINUX_DUMP_SYMBOLS_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/file_id.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/file_id.cc +--- a/toolkit/crashreporter/google-breakpad/src/common/linux/file_id.cc ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/file_id.cc +@@ -27,114 +27,148 @@ + // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + // + // file_id.cc: Return a unique identifier for a file + // + // See file_id.h for documentation + // + +-#include +-#include ++#include "common/linux/file_id.h" ++#include "common/linux/linux_libc_support.h" ++#include "common/linux/linux_syscall_support.h" ++ ++#include + #include + #include + #include ++#include + #include +-#include + #include + +-#include "common/linux/file_id.h" +-#include "common/md5.h" ++#include ++#include ++#include + + namespace google_breakpad { + +-static bool FindElfTextSection(const void *elf_mapped_base, +- const void **text_start, +- int *text_size) { ++FileID::FileID(const char* path) { ++ strncpy(path_, path, sizeof(path_)); ++} ++ ++// These two functions are also used inside the crashed process, so be safe ++// and use the syscall/libc wrappers instead of direct syscalls or libc. ++ static bool FindElfTextSection(const void *elf_mapped_base, ++ const void **text_start, ++ int *text_size) { + assert(elf_mapped_base); + assert(text_start); + assert(text_size); + +- const unsigned char *elf_base = +- static_cast(elf_mapped_base); +- const ElfW(Ehdr) *elf_header = +- reinterpret_cast(elf_base); +- if (memcmp(elf_header, ELFMAG, SELFMAG) != 0) ++ const char* elf_base = ++ static_cast(elf_mapped_base); ++ const ElfW(Ehdr)* elf_header = ++ reinterpret_cast(elf_base); ++ if (my_strncmp(elf_base, ELFMAG, SELFMAG) != 0) ++ return false; ++#if __ELF_NATIVE_CLASS == 32 ++#define ELFCLASS ELFCLASS32 ++#else ++#define ELFCLASS ELFCLASS64 ++#endif ++ //TODO: support dumping 32-bit binaries from a 64-bit dump_syms? ++ if (elf_header->e_ident[EI_CLASS] != ELFCLASS) + return false; + *text_start = NULL; + *text_size = 0; +- const ElfW(Shdr) *sections = +- reinterpret_cast(elf_base + elf_header->e_shoff); +- const char *text_section_name = ".text"; +- int name_len = strlen(text_section_name); +- const ElfW(Shdr) *string_section = sections + elf_header->e_shstrndx; +- const ElfW(Shdr) *text_section = NULL; ++ const ElfW(Shdr)* sections = ++ reinterpret_cast(elf_base + elf_header->e_shoff); ++ const char* text_section_name = ".text"; ++ int name_len = my_strlen(text_section_name); ++ const ElfW(Shdr)* string_section = sections + elf_header->e_shstrndx; ++ const ElfW(Shdr)* text_section = NULL; + for (int i = 0; i < elf_header->e_shnum; ++i) { + if (sections[i].sh_type == SHT_PROGBITS) { +- const char *section_name = (char*)(elf_base + ++ const char* section_name = (char*)(elf_base + + string_section->sh_offset + + sections[i].sh_name); +- if (!strncmp(section_name, text_section_name, name_len)) { ++ if (!my_strncmp(section_name, text_section_name, name_len)) { + text_section = §ions[i]; + break; + } + } + } + if (text_section != NULL && text_section->sh_size > 0) { +- int text_section_size = text_section->sh_size; + *text_start = elf_base + text_section->sh_offset; +- *text_size = text_section_size; ++ *text_size = text_section->sh_size; + } + return true; + } + +-FileID::FileID(const char *path) { +- strncpy(path_, path, sizeof(path_)); ++// static ++bool FileID::ElfFileIdentifierFromMappedFile(void* base, ++ uint8_t identifier[kMDGUIDSize]) ++{ ++ const void* text_section = NULL; ++ int text_size = 0; ++ bool success = false; ++ if (FindElfTextSection(base, &text_section, &text_size) && (text_size > 0)) { ++ my_memset(identifier, 0, kMDGUIDSize); ++ const uint8_t* ptr = reinterpret_cast(text_section); ++ const uint8_t* ptr_end = ptr + std::min(text_size, 4096); ++ while (ptr < ptr_end) { ++ for (unsigned i = 0; i < kMDGUIDSize; i++) ++ identifier[i] ^= ptr[i]; ++ ptr += kMDGUIDSize; ++ } ++ success = true; ++ } ++ return success; + } + +-bool FileID::ElfFileIdentifier(unsigned char identifier[16]) { ++bool FileID::ElfFileIdentifier(uint8_t identifier[kMDGUIDSize]) { + int fd = open(path_, O_RDONLY); + if (fd < 0) + return false; + struct stat st; +- if (fstat(fd, &st) != 0 && st.st_size <= 0) { ++ if (fstat(fd, &st) != 0) { + close(fd); + return false; + } +- void *base = mmap(NULL, st.st_size, ++ void* base = mmap(NULL, st.st_size, + PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); +- if (!base) { +- close(fd); ++ close(fd); ++ if (base == MAP_FAILED) + return false; +- } +- bool success = false; +- const void *text_section = NULL; +- int text_size = 0; +- if (FindElfTextSection(base, &text_section, &text_size) && (text_size > 0)) { +- struct MD5Context md5; +- MD5Init(&md5); +- MD5Update(&md5, +- static_cast(text_section), +- text_size); +- MD5Final(identifier, &md5); +- success = true; +- } + +- close(fd); ++ bool success = ElfFileIdentifierFromMappedFile(base, identifier); + munmap(base, st.st_size); + return success; + } + + // static +-void FileID::ConvertIdentifierToString(const unsigned char identifier[16], +- char *buffer, int buffer_length) { ++void FileID::ConvertIdentifierToString(const uint8_t identifier[kMDGUIDSize], ++ char* buffer, int buffer_length) { ++ uint8_t identifier_swapped[kMDGUIDSize]; ++ ++ // Endian-ness swap to match dump processor expectation. ++ memcpy(identifier_swapped, identifier, kMDGUIDSize); ++ uint32_t* data1 = reinterpret_cast(identifier_swapped); ++ *data1 = htonl(*data1); ++ uint16_t* data2 = reinterpret_cast(identifier_swapped + 4); ++ *data2 = htons(*data2); ++ uint16_t* data3 = reinterpret_cast(identifier_swapped + 6); ++ *data3 = htons(*data3); ++ + int buffer_idx = 0; +- for (int idx = 0; (buffer_idx < buffer_length) && (idx < 16); ++idx) { +- int hi = (identifier[idx] >> 4) & 0x0F; +- int lo = (identifier[idx]) & 0x0F; ++ for (unsigned int idx = 0; ++ (buffer_idx < buffer_length) && (idx < kMDGUIDSize); ++ ++idx) { ++ int hi = (identifier_swapped[idx] >> 4) & 0x0F; ++ int lo = (identifier_swapped[idx]) & 0x0F; + + if (idx == 4 || idx == 6 || idx == 8 || idx == 10) + buffer[buffer_idx++] = '-'; + + buffer[buffer_idx++] = (hi >= 10) ? 'A' + hi - 10 : '0' + hi; + buffer[buffer_idx++] = (lo >= 10) ? 'A' + lo - 10 : '0' + lo; + } + +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/file_id.h b/toolkit/crashreporter/google-breakpad/src/common/linux/file_id.h +--- a/toolkit/crashreporter/google-breakpad/src/common/linux/file_id.h ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/file_id.h +@@ -30,37 +30,47 @@ + // file_id.h: Return a unique identifier for a file + // + + #ifndef COMMON_LINUX_FILE_ID_H__ + #define COMMON_LINUX_FILE_ID_H__ + + #include + ++#include "common/linux/guid_creator.h" ++ + namespace google_breakpad { + ++static const size_t kMDGUIDSize = sizeof(MDGUID); ++ + class FileID { + public: +- FileID(const char *path); +- ~FileID() {}; ++ explicit FileID(const char* path); ++ ~FileID() {} + + // Load the identifier for the elf file path specified in the constructor into + // |identifier|. Return false if the identifier could not be created for the + // file. +- // The current implementation will return the MD5 hash of the file's bytes. +- bool ElfFileIdentifier(unsigned char identifier[16]); ++ // The current implementation will XOR the first 4096 bytes of the ++ // .text section to generate an identifier. ++ bool ElfFileIdentifier(uint8_t identifier[kMDGUIDSize]); ++ ++ // Load the identifier for the elf file mapped into memory at |base| into ++ // |identifier|. Return false if the identifier could not be created for the ++ // file. ++ static bool ElfFileIdentifierFromMappedFile(void* base, ++ uint8_t identifier[kMDGUIDSize]); + + // Convert the |identifier| data to a NULL terminated string. The string will + // be formatted as a UUID (e.g., 22F065BB-FC9C-49F7-80FE-26A7CEBD7BCE). + // The |buffer| should be at least 37 bytes long to receive all of the data + // and termination. Shorter buffers will contain truncated data. +- static void ConvertIdentifierToString(const unsigned char identifier[16], +- char *buffer, int buffer_length); ++ static void ConvertIdentifierToString(const uint8_t identifier[kMDGUIDSize], ++ char* buffer, int buffer_length); + + private: + // Storage for the path specified + char path_[PATH_MAX]; + }; + + } // namespace google_breakpad + + #endif // COMMON_LINUX_FILE_ID_H__ +- +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/file_id_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/file_id_unittest.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/file_id_unittest.cc +@@ -0,0 +1,76 @@ ++// Copyright (c) 2009, 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. ++ ++// Unit tests for FileID ++ ++#include ++ ++#include "common/linux/file_id.h" ++#include "breakpad_googletest_includes.h" ++ ++using namespace google_breakpad; ++ ++ ++namespace { ++typedef testing::Test FileIDTest; ++} ++ ++TEST(FileIDTest, FileIDStrip) { ++ // Calculate the File ID of our binary using ++ // FileID::ElfFileIdentifier, then make a copy of our binary, ++ // strip it, and ensure that we still get the same result. ++ char exe_name[PATH_MAX]; ++ ssize_t len = readlink("/proc/self/exe", exe_name, PATH_MAX - 1); ++ ASSERT_NE(len, -1); ++ exe_name[len] = '\0'; ++ ++ // copy our binary to a temp file, and strip it ++ char templ[] = "/tmp/file-id-unittest-XXXXXX"; ++ mktemp(templ); ++ char cmdline[4096]; ++ sprintf(cmdline, "cp \"%s\" \"%s\"", exe_name, templ); ++ ASSERT_EQ(system(cmdline), 0); ++ sprintf(cmdline, "strip \"%s\"", templ); ++ ASSERT_EQ(system(cmdline), 0); ++ ++ uint8_t identifier1[sizeof(MDGUID)]; ++ uint8_t identifier2[sizeof(MDGUID)]; ++ FileID fileid1(exe_name); ++ EXPECT_TRUE(fileid1.ElfFileIdentifier(identifier1)); ++ FileID fileid2(templ); ++ EXPECT_TRUE(fileid2.ElfFileIdentifier(identifier2)); ++ char identifier_string1[37]; ++ char identifier_string2[37]; ++ FileID::ConvertIdentifierToString(identifier1, identifier_string1, ++ 37); ++ FileID::ConvertIdentifierToString(identifier2, identifier_string2, ++ 37); ++ EXPECT_STREQ(identifier_string1, identifier_string2); ++ unlink(templ); ++} +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.cc +@@ -0,0 +1,196 @@ ++// Copyright (c) 2009, 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 "common/linux/google_crashdump_uploader.h" ++#include "common/linux/libcurl_wrapper.h" ++#include "third_party/linux/include/glog/logging.h" ++ ++#include ++#include ++#include ++ ++namespace google_breakpad { ++ ++GoogleCrashdumpUploader::GoogleCrashdumpUploader(const std::string& product, ++ const std::string& version, ++ const std::string& guid, ++ const std::string& ptime, ++ const std::string& ctime, ++ const std::string& email, ++ const std::string& comments, ++ const std::string& minidump_pathname, ++ const std::string& crash_server, ++ const std::string& proxy_host, ++ const std::string& proxy_userpassword) { ++ LibcurlWrapper* http_layer = new LibcurlWrapper(); ++ Init(product, ++ version, ++ guid, ++ ptime, ++ ctime, ++ email, ++ comments, ++ minidump_pathname, ++ crash_server, ++ proxy_host, ++ proxy_userpassword, ++ http_layer); ++} ++ ++GoogleCrashdumpUploader::GoogleCrashdumpUploader(const std::string& product, ++ const std::string& version, ++ const std::string& guid, ++ const std::string& ptime, ++ const std::string& ctime, ++ const std::string& email, ++ const std::string& comments, ++ const std::string& minidump_pathname, ++ const std::string& crash_server, ++ const std::string& proxy_host, ++ const std::string& proxy_userpassword, ++ LibcurlWrapper* http_layer) { ++ Init(product, ++ version, ++ guid, ++ ptime, ++ ctime, ++ email, ++ comments, ++ minidump_pathname, ++ crash_server, ++ proxy_host, ++ proxy_userpassword, ++ http_layer); ++} ++ ++void GoogleCrashdumpUploader::Init(const std::string& product, ++ const std::string& version, ++ const std::string& guid, ++ const std::string& ptime, ++ const std::string& ctime, ++ const std::string& email, ++ const std::string& comments, ++ const std::string& minidump_pathname, ++ const std::string& crash_server, ++ const std::string& proxy_host, ++ const std::string& proxy_userpassword, ++ LibcurlWrapper* http_layer) { ++ product_ = product; ++ version_ = version; ++ guid_ = guid; ++ ptime_ = ptime; ++ ctime_ = ctime; ++ email_ = email; ++ comments_ = comments; ++ http_layer_ = http_layer; ++ ++ crash_server_ = crash_server; ++ proxy_host_ = proxy_host; ++ proxy_userpassword_ = proxy_userpassword; ++ minidump_pathname_ = minidump_pathname; ++ LOG(INFO) << "Uploader initializing"; ++ LOG(INFO) << "\tProduct: " << product_; ++ LOG(INFO) << "\tVersion: " << version_; ++ LOG(INFO) << "\tGUID: " << guid_; ++ if (!ptime_.empty()) { ++ LOG(INFO) << "\tProcess uptime: " << ptime_; ++ } ++ if (!ctime_.empty()) { ++ LOG(INFO) << "\tCumulative Process uptime: " << ctime_; ++ } ++ if (!email_.empty()) { ++ LOG(INFO) << "\tEmail: " << email_; ++ } ++ if (!comments_.empty()) { ++ LOG(INFO) << "\tComments: " << comments_; ++ } ++} ++ ++bool GoogleCrashdumpUploader::CheckRequiredParametersArePresent() { ++ std::string error_text; ++ if (product_.empty()) { ++ error_text.append("\nProduct name must be specified."); ++ } ++ ++ if (version_.empty()) { ++ error_text.append("\nProduct version must be specified."); ++ } ++ ++ if (guid_.empty()) { ++ error_text.append("\nClient ID must be specified."); ++ } ++ ++ if (minidump_pathname_.empty()) { ++ error_text.append("\nMinidump pathname must be specified."); ++ } ++ ++ if (!error_text.empty()) { ++ LOG(ERROR) << error_text; ++ return false; ++ } ++ return true; ++ ++} ++ ++bool GoogleCrashdumpUploader::Upload() { ++ bool ok = http_layer_->Init(); ++ if (!ok) { ++ LOG(WARNING) << "http layer init failed"; ++ return ok; ++ } ++ ++ if (!CheckRequiredParametersArePresent()) { ++ return false; ++ } ++ ++ struct stat st; ++ int err = stat(minidump_pathname_.c_str(), &st); ++ if (err) { ++ LOG(WARNING) << minidump_pathname_ << " could not be found: " << errno; ++ return false; ++ } ++ ++ parameters_["prod"] = product_; ++ parameters_["ver"] = version_; ++ parameters_["guid"] = guid_; ++ parameters_["ptime"] = ptime_; ++ parameters_["ctime"] = ctime_; ++ parameters_["email"] = email_; ++ parameters_["comments_"] = comments_; ++ if (!http_layer_->AddFile(minidump_pathname_, ++ "upload_file_minidump")) { ++ return false; ++ } ++ LOG(INFO) << "Sending request to " << crash_server_; ++ return http_layer_->SendRequest(crash_server_, ++ parameters_, ++ NULL); ++} ++} +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.h b/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.h +@@ -0,0 +1,98 @@ ++// Copyright (c) 2009, 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 ++#include ++ ++namespace google_breakpad { ++ ++class LibcurlWrapper; ++ ++class GoogleCrashdumpUploader { ++ public: ++ GoogleCrashdumpUploader(const std::string& product, ++ const std::string& version, ++ const std::string& guid, ++ const std::string& ptime, ++ const std::string& ctime, ++ const std::string& email, ++ const std::string& comments, ++ const std::string& minidump_pathname, ++ const std::string& crash_server, ++ const std::string& proxy_host, ++ const std::string& proxy_userpassword); ++ ++ GoogleCrashdumpUploader(const std::string& product, ++ const std::string& version, ++ const std::string& guid, ++ const std::string& ptime, ++ const std::string& ctime, ++ const std::string& email, ++ const std::string& comments, ++ const std::string& minidump_pathname, ++ const std::string& crash_server, ++ const std::string& proxy_host, ++ const std::string& proxy_userpassword, ++ LibcurlWrapper* http_layer); ++ ++ void Init(const std::string& product, ++ const std::string& version, ++ const std::string& guid, ++ const std::string& ptime, ++ const std::string& ctime, ++ const std::string& email, ++ const std::string& comments, ++ const std::string& minidump_pathname, ++ const std::string& crash_server, ++ const std::string& proxy_host, ++ const std::string& proxy_userpassword, ++ LibcurlWrapper* http_layer); ++ bool Upload(); ++ ++ private: ++ bool CheckRequiredParametersArePresent(); ++ ++ LibcurlWrapper* http_layer_; ++ std::string product_; ++ std::string version_; ++ std::string guid_; ++ std::string ptime_; ++ std::string ctime_; ++ std::string email_; ++ std::string comments_; ++ std::string minidump_pathname_; ++ ++ std::string crash_server_; ++ std::string proxy_host_; ++ std::string proxy_userpassword_; ++ ++ std::map parameters_; ++}; ++} +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader_test.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader_test.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader_test.cc +@@ -0,0 +1,166 @@ ++// Copyright (c) 2009, 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. ++ ++// Unit test for crash dump uploader. ++ ++#include "common/linux/google_crashdump_uploader.h" ++#include "common/linux/libcurl_wrapper.h" ++#include "breakpad_googletest_includes.h" ++ ++namespace google_breakpad { ++ ++using ::testing::Return; ++using ::testing::_; ++ ++class MockLibcurlWrapper : public LibcurlWrapper { ++ public: ++ MOCK_METHOD0(Init, bool()); ++ MOCK_METHOD2(SetProxy, bool(const std::string& proxy_host, ++ const std::string& proxy_userpwd)); ++ MOCK_METHOD2(AddFile, bool(const std::string& upload_file_path, ++ const std::string& basename)); ++ MOCK_METHOD3(SendRequest, ++ bool(const std::string& url, ++ const std::map& parameters, ++ std::string* server_response)); ++}; ++ ++class GoogleCrashdumpUploaderTest : public ::testing::Test { ++}; ++ ++TEST_F(GoogleCrashdumpUploaderTest, InitFailsCausesUploadFailure) { ++ MockLibcurlWrapper m; ++ EXPECT_CALL(m, Init()).Times(1).WillOnce(Return(false)); ++ GoogleCrashdumpUploader *uploader = new GoogleCrashdumpUploader("foobar", ++ "1.0", ++ "AAA-BBB", ++ "", ++ "", ++ "test@test.com", ++ "none", ++ "/tmp/foo.dmp", ++ "http://foo.com", ++ "", ++ "", ++ &m); ++ ASSERT_FALSE(uploader->Upload()); ++} ++ ++TEST_F(GoogleCrashdumpUploaderTest, TestSendRequestHappensWithValidParameters) { ++ // Create a temp file ++ char tempfn[80] = "/tmp/googletest-upload-XXXXXX"; ++ int fd = mkstemp(tempfn); ++ ASSERT_NE(fd, -1); ++ close(fd); ++ ++ MockLibcurlWrapper m; ++ EXPECT_CALL(m, Init()).Times(1).WillOnce(Return(true)); ++ EXPECT_CALL(m, AddFile(tempfn, _)).WillOnce(Return(true)); ++ EXPECT_CALL(m, ++ SendRequest("http://foo.com",_,_)).Times(1).WillOnce(Return(true)); ++ GoogleCrashdumpUploader *uploader = new GoogleCrashdumpUploader("foobar", ++ "1.0", ++ "AAA-BBB", ++ "", ++ "", ++ "test@test.com", ++ "none", ++ tempfn, ++ "http://foo.com", ++ "", ++ "", ++ &m); ++ ASSERT_TRUE(uploader->Upload()); ++} ++ ++ ++TEST_F(GoogleCrashdumpUploaderTest, InvalidPathname) { ++ MockLibcurlWrapper m; ++ EXPECT_CALL(m, Init()).Times(1).WillOnce(Return(true)); ++ EXPECT_CALL(m, SendRequest(_,_,_)).Times(0); ++ GoogleCrashdumpUploader *uploader = new GoogleCrashdumpUploader("foobar", ++ "1.0", ++ "AAA-BBB", ++ "", ++ "", ++ "test@test.com", ++ "none", ++ "/tmp/foo.dmp", ++ "http://foo.com", ++ "", ++ "", ++ &m); ++ ASSERT_FALSE(uploader->Upload()); ++} ++ ++TEST_F(GoogleCrashdumpUploaderTest, TestRequiredParametersMustBePresent) { ++ // Test with empty product name. ++ GoogleCrashdumpUploader uploader("", ++ "1.0", ++ "AAA-BBB", ++ "", ++ "", ++ "test@test.com", ++ "none", ++ "/tmp/foo.dmp", ++ "http://foo.com", ++ "", ++ ""); ++ ASSERT_FALSE(uploader.Upload()); ++ ++ // Test with empty product version. ++ GoogleCrashdumpUploader uploader1("product", ++ "", ++ "AAA-BBB", ++ "", ++ "", ++ "", ++ "", ++ "/tmp/foo.dmp", ++ "", ++ "", ++ ""); ++ ++ ASSERT_FALSE(uploader1.Upload()); ++ ++ // Test with empty client GUID. ++ GoogleCrashdumpUploader uploader2("product", ++ "1.0", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "/tmp/foo.dmp", ++ "", ++ "", ++ ""); ++ ASSERT_FALSE(uploader2.Upload()); ++} ++} +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/guid_creator.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/guid_creator.cc +--- a/toolkit/crashreporter/google-breakpad/src/common/linux/guid_creator.cc ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/guid_creator.cc +@@ -44,22 +44,36 @@ + // crash to happen very offen. + // + class GUIDGenerator { + public: + GUIDGenerator() { + srandom(time(NULL)); + } + ++ static u_int32_t BytesToUInt32(const u_int8_t bytes[]) { ++ return ((u_int32_t) bytes[0] ++ | ((u_int32_t) bytes[1] << 8) ++ | ((u_int32_t) bytes[2] << 16) ++ | ((u_int32_t) bytes[3] << 24)); ++ } ++ ++ static void UInt32ToBytes(u_int8_t bytes[], u_int32_t n) { ++ bytes[0] = n & 0xff; ++ bytes[1] = (n >> 8) & 0xff; ++ bytes[2] = (n >> 16) & 0xff; ++ bytes[3] = (n >> 24) & 0xff; ++ } ++ + bool CreateGUID(GUID *guid) const { + guid->data1 = random(); + guid->data2 = (u_int16_t)(random()); + guid->data3 = (u_int16_t)(random()); +- *reinterpret_cast(&guid->data4[0]) = random(); +- *reinterpret_cast(&guid->data4[4]) = random(); ++ UInt32ToBytes(&guid->data4[0], random()); ++ UInt32ToBytes(&guid->data4[4], random()); + return true; + } + }; + + // Guid generator. + const GUIDGenerator kGuidGenerator; + + bool CreateGUID(GUID *guid) { +@@ -67,16 +81,16 @@ bool CreateGUID(GUID *guid) { + } + + // Parse guid to string. + bool GUIDToString(const GUID *guid, char *buf, int buf_len) { + // Should allow more space the the max length of GUID. + assert(buf_len > kGUIDStringLength); + int num = snprintf(buf, buf_len, kGUIDFormatString, + guid->data1, guid->data2, guid->data3, +- *reinterpret_cast(&(guid->data4[0])), +- *reinterpret_cast(&(guid->data4[4]))); ++ GUIDGenerator::BytesToUInt32(&(guid->data4[0])), ++ GUIDGenerator::BytesToUInt32(&(guid->data4[4]))); + if (num != kGUIDStringLength) + return false; + + buf[num] = '\0'; + return true; + } +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.cc +@@ -0,0 +1,209 @@ ++// Copyright (c) 2009, 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 ++#include ++#include ++#include ++ ++#include ++ ++#include "common/linux/libcurl_wrapper.h" ++#include "third_party/linux/include/glog/logging.h" ++ ++namespace google_breakpad { ++LibcurlWrapper::LibcurlWrapper() ++ : init_ok_(false), ++ formpost_(NULL), ++ lastptr_(NULL), ++ headerlist_(NULL) { ++ curl_lib_ = dlopen("libcurl.so", RTLD_NOW); ++ if (!curl_lib_) { ++ curl_lib_ = dlopen("libcurl.so.4", RTLD_NOW); ++ } ++ if (!curl_lib_) { ++ curl_lib_ = dlopen("libcurl.so.3", RTLD_NOW); ++ } ++ if (!curl_lib_) { ++ LOG(WARNING) << "Could not find libcurl via dlopen"; ++ return; ++ } ++ LOG(INFO) << "LibcurlWrapper init succeeded"; ++ init_ok_ = true; ++ return; ++} ++ ++bool LibcurlWrapper::SetProxy(const std::string& proxy_host, ++ const std::string& proxy_userpwd) { ++ if (!init_ok_) { ++ return false; ++ } ++ // Set proxy information if necessary. ++ if (!proxy_host.empty()) { ++ (*easy_setopt_)(curl_, CURLOPT_PROXY, proxy_host.c_str()); ++ } else { ++ LOG(WARNING) << "SetProxy called with empty proxy host."; ++ return false; ++ } ++ if (!proxy_userpwd.empty()) { ++ (*easy_setopt_)(curl_, CURLOPT_PROXYUSERPWD, proxy_userpwd.c_str()); ++ } else { ++ LOG(WARNING) << "SetProxy called with empty proxy username/password."; ++ return false; ++ } ++ LOG(INFO) << "Set proxy host to " << proxy_host; ++ return true; ++} ++ ++bool LibcurlWrapper::AddFile(const std::string& upload_file_path, ++ const std::string& basename) { ++ if (!init_ok_) { ++ return false; ++ } ++ LOG(INFO) << "Adding " << upload_file_path << " to form upload."; ++ // Add form file. ++ (*formadd_)(&formpost_, &lastptr_, ++ CURLFORM_COPYNAME, basename.c_str(), ++ CURLFORM_FILE, upload_file_path.c_str(), ++ CURLFORM_END); ++ ++ return true; ++} ++ ++// Callback to get the response data from server. ++static size_t WriteCallback(void *ptr, size_t size, ++ size_t nmemb, void *userp) { ++ if (!userp) ++ return 0; ++ ++ std::string *response = reinterpret_cast(userp); ++ size_t real_size = size * nmemb; ++ response->append(reinterpret_cast(ptr), real_size); ++ return real_size; ++} ++ ++bool LibcurlWrapper::SendRequest(const std::string& url, ++ const std::map& parameters, ++ std::string* server_response) { ++ (*easy_setopt_)(curl_, CURLOPT_URL, url.c_str()); ++ std::map::const_iterator iter = parameters.begin(); ++ for (; iter != parameters.end(); ++iter) ++ (*formadd_)(&formpost_, &lastptr_, ++ CURLFORM_COPYNAME, iter->first.c_str(), ++ CURLFORM_COPYCONTENTS, iter->second.c_str(), ++ CURLFORM_END); ++ ++ (*easy_setopt_)(curl_, CURLOPT_HTTPPOST, formpost_); ++ if (server_response != NULL) { ++ (*easy_setopt_)(curl_, CURLOPT_WRITEFUNCTION, WriteCallback); ++ (*easy_setopt_)(curl_, CURLOPT_WRITEDATA, ++ reinterpret_cast(server_response)); ++ } ++ ++ CURLcode err_code = CURLE_OK; ++ err_code = (*easy_perform_)(curl_); ++ *(void**) (&easy_strerror_) = dlsym(curl_lib_, "curl_easy_strerror"); ++#ifndef NDEBUG ++ if (err_code != CURLE_OK) ++ fprintf(stderr, "Failed to send http request to %s, error: %s\n", ++ url.c_str(), ++ (*easy_strerror_)(err_code)); ++#endif ++ if (headerlist_ != NULL) { ++ (*slist_free_all_)(headerlist_); ++ } ++ ++ (*easy_cleanup_)(curl_); ++ if (formpost_ != NULL) { ++ (*formfree_)(formpost_); ++ } ++ ++ return err_code == CURLE_OK; ++} ++ ++bool LibcurlWrapper::Init() { ++ if (!init_ok_) { ++ LOG(WARNING) << "Init_OK was not true in LibcurlWrapper::Init(), check earlier log messages"; ++ return false; ++ } ++ ++ if (!SetFunctionPointers()) { ++ LOG(WARNING) << "Could not find function pointers"; ++ init_ok_ = false; ++ return false; ++ } ++ ++ curl_ = (*easy_init_)(); ++ ++ last_curl_error_ = "No Error"; ++ ++ if (!curl_) { ++ dlclose(curl_lib_); ++ LOG(WARNING) << "Curl initialization failed"; ++ return false; ++ } ++ ++ // Disable 100-continue header. ++ char buf[] = "Expect:"; ++ ++ headerlist_ = (*slist_append_)(headerlist_, buf); ++ (*easy_setopt_)(curl_, CURLOPT_HTTPHEADER, headerlist_); ++ return true; ++} ++ ++#define SET_AND_CHECK_FUNCTION_POINTER(var, function_name) \ ++ *(void**) (&var) = dlsym(curl_lib_, function_name); \ ++ if (!var) { \ ++ LOG(WARNING) << "Could not find libcurl function " << function_name; \ ++ init_ok_ = false; \ ++ return false; \ ++ } ++ ++bool LibcurlWrapper::SetFunctionPointers() { ++ ++ SET_AND_CHECK_FUNCTION_POINTER(easy_init_, ++ "curl_easy_init"); ++ SET_AND_CHECK_FUNCTION_POINTER(easy_setopt_, ++ "curl_easy_setopt"); ++ SET_AND_CHECK_FUNCTION_POINTER(formadd_, ++ "curl_formadd"); ++ SET_AND_CHECK_FUNCTION_POINTER(slist_append_, ++ "curl_slist_append"); ++ SET_AND_CHECK_FUNCTION_POINTER(easy_perform_, ++ "curl_easy_perform"); ++ SET_AND_CHECK_FUNCTION_POINTER(easy_cleanup_, ++ "curl_easy_cleanup"); ++ SET_AND_CHECK_FUNCTION_POINTER(slist_free_all_, ++ "curl_slist_free_all"); ++ SET_AND_CHECK_FUNCTION_POINTER(formfree_, ++ "curl_formfree"); ++ return true; ++} ++ ++} +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.h b/toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.h +@@ -0,0 +1,82 @@ ++// Copyright (c) 2009, 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. ++ ++// A wrapper for libcurl to do HTTP Uploads, to support easy mocking ++// and unit testing of the HTTPUpload class. ++ ++#include ++#include ++#include ++ ++namespace google_breakpad { ++class LibcurlWrapper { ++ public: ++ LibcurlWrapper(); ++ virtual bool Init(); ++ virtual bool SetProxy(const std::string& proxy_host, ++ const std::string& proxy_userpwd); ++ virtual bool AddFile(const std::string& upload_file_path, ++ const std::string& basename); ++ virtual bool SendRequest(const std::string& url, ++ const std::map& parameters, ++ std::string* server_response); ++ private: ++ // This function initializes class state corresponding to function ++ // pointers into the CURL library. ++ bool SetFunctionPointers(); ++ ++ bool init_ok_; // Whether init succeeded ++ void* curl_lib_; // Pointer to result of dlopen() on ++ // curl library ++ std::string last_curl_error_; // The text of the last error when ++ // dealing ++ // with CURL. ++ ++ CURL *curl_; // Pointer for handle for CURL calls. ++ ++ CURL* (*easy_init_)(void); ++ ++ // Stateful pointers for calling into curl_formadd() ++ struct curl_httppost *formpost_; ++ struct curl_httppost *lastptr_; ++ struct curl_slist *headerlist_; ++ ++ // Function pointers into CURL library ++ CURLcode (*easy_setopt_)(CURL *, CURLoption, ...); ++ CURLFORMcode (*formadd_)(struct curl_httppost **, ++ struct curl_httppost **, ...); ++ struct curl_slist* (*slist_append_)(struct curl_slist *, const char *); ++ void (*slist_free_all_)(struct curl_slist *); ++ CURLcode (*easy_perform_)(CURL *); ++ const char* (*easy_strerror_)(CURLcode); ++ void (*easy_cleanup_)(CURL *); ++ void (*formfree_)(struct curl_httppost *); ++ ++}; ++} +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support.h b/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support.h +@@ -0,0 +1,178 @@ ++// Copyright (c) 2009, 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. ++ ++// This header provides replacements for libc functions that we need. We if ++// call the libc functions directly we risk crashing in the dynamic linker as ++// it tries to resolve uncached PLT entries. ++ ++#ifndef CLIENT_LINUX_LINUX_LIBC_SUPPORT_H_ ++#define CLIENT_LINUX_LINUX_LIBC_SUPPORT_H_ ++ ++#include ++#include ++#include ++ ++extern "C" { ++ ++static inline size_t ++my_strlen(const char* s) { ++ size_t len = 0; ++ while (*s++) len++; ++ return len; ++} ++ ++static inline int ++my_strcmp(const char* a, const char* b) { ++ for (;;) { ++ if (*a < *b) ++ return -1; ++ else if (*a > *b) ++ return 1; ++ else if (*a == 0) ++ return 0; ++ a++; ++ b++; ++ } ++} ++ ++static inline int ++my_strncmp(const char* a, const char* b, size_t len) { ++ for (size_t i = 0; i < len; ++i) { ++ if (*a < *b) ++ return -1; ++ else if (*a > *b) ++ return 1; ++ else if (*a == 0) ++ return 0; ++ a++; ++ b++; ++ } ++ ++ return 0; ++} ++ ++// Parse a non-negative integer. ++// result: (output) the resulting non-negative integer ++// s: a NUL terminated string ++// Return true iff successful. ++static inline bool ++my_strtoui(int* result, const char* s) { ++ if (*s == 0) ++ return false; ++ int r = 0; ++ for (;; s++) { ++ if (*s == 0) ++ break; ++ const int old_r = r; ++ r *= 10; ++ if (*s < '0' || *s > '9') ++ return false; ++ r += *s - '0'; ++ if (r < old_r) ++ return false; ++ } ++ ++ *result = r; ++ return true; ++} ++ ++// Return the length of the given, non-negative integer when expressed in base ++// 10. ++static inline unsigned ++my_int_len(int i) { ++ if (!i) ++ return 1; ++ ++ int len = 0; ++ while (i) { ++ len++; ++ i /= 10; ++ } ++ ++ return len; ++} ++ ++// Convert a non-negative integer to a string ++// output: (output) the resulting string is written here. This buffer must be ++// large enough to hold the resulting string. Call |my_int_len| to get the ++// required length. ++// i: the non-negative integer to serialise. ++// i_len: the length of the integer in base 10 (see |my_int_len|). ++static inline void ++my_itos(char* output, int i, unsigned i_len) { ++ for (unsigned index = i_len; index; --index, i /= 10) ++ output[index - 1] = '0' + (i % 10); ++} ++ ++static inline const char* ++my_strchr(const char* haystack, char needle) { ++ while (*haystack && *haystack != needle) ++ haystack++; ++ if (*haystack == needle) ++ return haystack; ++ return (const char*) 0; ++} ++ ++// Read a hex value ++// result: (output) the resulting value ++// s: a string ++// Returns a pointer to the first invalid charactor. ++static inline const char* ++my_read_hex_ptr(uintptr_t* result, const char* s) { ++ uintptr_t r = 0; ++ ++ for (;; ++s) { ++ if (*s >= '0' && *s <= '9') { ++ r <<= 4; ++ r += *s - '0'; ++ } else if (*s >= 'a' && *s <= 'f') { ++ r <<= 4; ++ r += (*s - 'a') + 10; ++ } else if (*s >= 'A' && *s <= 'F') { ++ r <<= 4; ++ r += (*s - 'A') + 10; ++ } else { ++ break; ++ } ++ } ++ ++ *result = r; ++ return s; ++} ++ ++static inline void ++my_memset(void* ip, char c, size_t len) { ++ char* p = (char *) ip; ++ while (len--) ++ *p++ = c; ++} ++ ++} // extern "C" ++ ++#endif // CLIENT_LINUX_LINUX_LIBC_SUPPORT_H_ +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support_unittest.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support_unittest.cc +@@ -0,0 +1,153 @@ ++// Copyright (c) 2009, 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 "common/linux/linux_libc_support.h" ++#include "testing/gtest/include/gtest/gtest.h" ++ ++namespace { ++typedef testing::Test LinuxLibcSupportTest; ++} ++ ++TEST(LinuxLibcSupportTest, strlen) { ++ static const char* test_data[] = { "", "a", "aa", "aaa", "aabc", NULL }; ++ for (unsigned i = 0; ; ++i) { ++ if (!test_data[i]) ++ break; ++ ASSERT_EQ(strlen(test_data[i]), my_strlen(test_data[i])); ++ } ++} ++ ++TEST(LinuxLibcSupportTest, strcmp) { ++ static const char* test_data[] = { ++ "", "", ++ "a", "", ++ "", "a", ++ "a", "b", ++ "a", "a", ++ "ab", "aa", ++ "abc", "ab", ++ "abc", "abc", ++ NULL, ++ }; ++ ++ for (unsigned i = 0; ; ++i) { ++ if (!test_data[i*2]) ++ break; ++ ASSERT_EQ(my_strcmp(test_data[i*2], test_data[i*2 + 1]), ++ strcmp(test_data[i*2], test_data[i*2 + 1])); ++ } ++} ++ ++TEST(LinuxLibcSupportTest, strtoui) { ++ int result; ++ ++ ASSERT_FALSE(my_strtoui(&result, "")); ++ ASSERT_FALSE(my_strtoui(&result, "-1")); ++ ASSERT_FALSE(my_strtoui(&result, "-")); ++ ASSERT_FALSE(my_strtoui(&result, "a")); ++ ASSERT_FALSE(my_strtoui(&result, "23472893472938472987987398472398")); ++ ++ ASSERT_TRUE(my_strtoui(&result, "0")); ++ ASSERT_EQ(result, 0); ++ ASSERT_TRUE(my_strtoui(&result, "1")); ++ ASSERT_EQ(result, 1); ++ ASSERT_TRUE(my_strtoui(&result, "12")); ++ ASSERT_EQ(result, 12); ++ ASSERT_TRUE(my_strtoui(&result, "123")); ++ ASSERT_EQ(result, 123); ++ ASSERT_TRUE(my_strtoui(&result, "0123")); ++ ASSERT_EQ(result, 123); ++} ++ ++TEST(LinuxLibcSupportTest, int_len) { ++ ASSERT_EQ(my_int_len(0), 1); ++ ASSERT_EQ(my_int_len(2), 1); ++ ASSERT_EQ(my_int_len(5), 1); ++ ASSERT_EQ(my_int_len(9), 1); ++ ASSERT_EQ(my_int_len(10), 2); ++ ASSERT_EQ(my_int_len(99), 2); ++ ASSERT_EQ(my_int_len(100), 3); ++ ASSERT_EQ(my_int_len(101), 3); ++ ASSERT_EQ(my_int_len(1000), 4); ++} ++ ++TEST(LinuxLibcSupportTest, itos) { ++ char buf[10]; ++ ++ my_itos(buf, 0, 1); ++ ASSERT_EQ(0, memcmp(buf, "0", 1)); ++ ++ my_itos(buf, 1, 1); ++ ASSERT_EQ(0, memcmp(buf, "1", 1)); ++ ++ my_itos(buf, 10, 2); ++ ASSERT_EQ(0, memcmp(buf, "10", 2)); ++ ++ my_itos(buf, 63, 2); ++ ASSERT_EQ(0, memcmp(buf, "63", 2)); ++ ++ my_itos(buf, 101, 3); ++ ASSERT_EQ(0, memcmp(buf, "101", 2)); ++} ++ ++TEST(LinuxLibcSupportTest, strchr) { ++ ASSERT_EQ(NULL, my_strchr("abc", 'd')); ++ ASSERT_EQ(NULL, my_strchr("", 'd')); ++ ASSERT_EQ(NULL, my_strchr("efghi", 'd')); ++ ++ ASSERT_TRUE(my_strchr("a", 'a')); ++ ASSERT_TRUE(my_strchr("abc", 'a')); ++ ASSERT_TRUE(my_strchr("bcda", 'a')); ++ ASSERT_TRUE(my_strchr("sdfasdf", 'a')); ++} ++ ++TEST(LinuxLibcSupportTest, read_hex_ptr) { ++ uintptr_t result; ++ const char* last; ++ ++ last = my_read_hex_ptr(&result, ""); ++ ASSERT_EQ(result, 0); ++ ASSERT_EQ(*last, 0); ++ ++ last = my_read_hex_ptr(&result, "0"); ++ ASSERT_EQ(result, 0); ++ ASSERT_EQ(*last, 0); ++ ++ last = my_read_hex_ptr(&result, "0123"); ++ ASSERT_EQ(result, 0x123); ++ ASSERT_EQ(*last, 0); ++ ++ last = my_read_hex_ptr(&result, "0123a"); ++ ASSERT_EQ(result, 0x123a); ++ ASSERT_EQ(*last, 0); ++ ++ last = my_read_hex_ptr(&result, "0123a-"); ++ ASSERT_EQ(result, 0x123a); ++ ASSERT_EQ(*last, '-'); ++} +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/linux_syscall_support.h b/toolkit/crashreporter/google-breakpad/src/common/linux/linux_syscall_support.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/linux_syscall_support.h +@@ -0,0 +1,2800 @@ ++/* Copyright (c) 2005-2008, 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. ++ * ++ * --- ++ * Author: Markus Gutschke ++ */ ++ ++/* This file includes Linux-specific support functions common to the ++ * coredumper and the thread lister; primarily, this is a collection ++ * of direct system calls, and a couple of symbols missing from ++ * standard header files. ++ * There are a few options that the including file can set to control ++ * the behavior of this file: ++ * ++ * SYS_CPLUSPLUS: ++ * The entire header file will normally be wrapped in 'extern "C" { }", ++ * making it suitable for compilation as both C and C++ source. If you ++ * do not want to do this, you can set the SYS_CPLUSPLUS macro to inhibit ++ * the wrapping. N.B. doing so will suppress inclusion of all prerequisite ++ * system header files, too. It is the caller's responsibility to provide ++ * the necessary definitions. ++ * ++ * SYS_ERRNO: ++ * All system calls will update "errno" unless overriden by setting the ++ * SYS_ERRNO macro prior to including this file. SYS_ERRNO should be ++ * an l-value. ++ * ++ * SYS_INLINE: ++ * New symbols will be defined "static inline", unless overridden by ++ * the SYS_INLINE macro. ++ * ++ * SYS_LINUX_SYSCALL_SUPPORT_H ++ * This macro is used to avoid multiple inclusions of this header file. ++ * If you need to include this file more than once, make sure to ++ * unset SYS_LINUX_SYSCALL_SUPPORT_H before each inclusion. ++ * ++ * SYS_PREFIX: ++ * New system calls will have a prefix of "sys_" unless overridden by ++ * the SYS_PREFIX macro. Valid values for this macro are [0..9] which ++ * results in prefixes "sys[0..9]_". It is also possible to set this ++ * macro to -1, which avoids all prefixes. ++ * ++ * This file defines a few internal symbols that all start with "LSS_". ++ * Do not access these symbols from outside this file. They are not part ++ * of the supported API. ++ */ ++#ifndef SYS_LINUX_SYSCALL_SUPPORT_H ++#define SYS_LINUX_SYSCALL_SUPPORT_H ++ ++/* We currently only support x86-32, x86-64, ARM, MIPS, and PPC on Linux. ++ * Porting to other related platforms should not be difficult. ++ */ ++#if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) || \ ++ defined(__mips__) || defined(__PPC__)) && defined(__linux) ++ ++#ifndef SYS_CPLUSPLUS ++#ifdef __cplusplus ++/* Some system header files in older versions of gcc neglect to properly ++ * handle being included from C++. As it appears to be harmless to have ++ * multiple nested 'extern "C"' blocks, just add another one here. ++ */ ++extern "C" { ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef __mips__ ++/* Include definitions of the ABI currently in use. */ ++#include ++#endif ++ ++#endif ++ ++/* As glibc often provides subtly incompatible data structures (and implicit ++ * wrapper functions that convert them), we provide our own kernel data ++ * structures for use by the system calls. ++ * These structures have been developed by using Linux 2.6.23 headers for ++ * reference. Note though, we do not care about exact API compatibility ++ * with the kernel, and in fact the kernel often does not have a single ++ * API that works across architectures. Instead, we try to mimic the glibc ++ * API where reasonable, and only guarantee ABI compatibility with the ++ * kernel headers. ++ * Most notably, here are a few changes that were made to the structures ++ * defined by kernel headers: ++ * ++ * - we only define structures, but not symbolic names for kernel data ++ * types. For the latter, we directly use the native C datatype ++ * (i.e. "unsigned" instead of "mode_t"). ++ * - in a few cases, it is possible to define identical structures for ++ * both 32bit (e.g. i386) and 64bit (e.g. x86-64) platforms by ++ * standardizing on the 64bit version of the data types. In particular, ++ * this means that we use "unsigned" where the 32bit headers say ++ * "unsigned long". ++ * - overall, we try to minimize the number of cases where we need to ++ * conditionally define different structures. ++ * - the "struct kernel_sigaction" class of structures have been ++ * modified to more closely mimic glibc's API by introducing an ++ * anonymous union for the function pointer. ++ * - a small number of field names had to have an underscore appended to ++ * them, because glibc defines a global macro by the same name. ++ */ ++ ++/* include/linux/dirent.h */ ++struct kernel_dirent64 { ++ unsigned long long d_ino; ++ long long d_off; ++ unsigned short d_reclen; ++ unsigned char d_type; ++ char d_name[256]; ++}; ++ ++/* include/linux/dirent.h */ ++struct kernel_dirent { ++ long d_ino; ++ long d_off; ++ unsigned short d_reclen; ++ char d_name[256]; ++}; ++ ++/* include/linux/uio.h */ ++struct kernel_iovec { ++ void *iov_base; ++ unsigned long iov_len; ++}; ++ ++/* include/linux/socket.h */ ++struct kernel_msghdr { ++ void *msg_name; ++ int msg_namelen; ++ struct kernel_iovec*msg_iov; ++ unsigned long msg_iovlen; ++ void *msg_control; ++ unsigned long msg_controllen; ++ unsigned msg_flags; ++}; ++ ++/* include/asm-generic/poll.h */ ++struct kernel_pollfd { ++ int fd; ++ short events; ++ short revents; ++}; ++ ++/* include/linux/resource.h */ ++struct kernel_rlimit { ++ unsigned long rlim_cur; ++ unsigned long rlim_max; ++}; ++ ++/* include/linux/time.h */ ++struct kernel_timespec { ++ long tv_sec; ++ long tv_nsec; ++}; ++ ++/* include/linux/time.h */ ++struct kernel_timeval { ++ long tv_sec; ++ long tv_usec; ++}; ++ ++/* include/linux/resource.h */ ++struct kernel_rusage { ++ struct kernel_timeval ru_utime; ++ struct kernel_timeval ru_stime; ++ long ru_maxrss; ++ long ru_ixrss; ++ long ru_idrss; ++ long ru_isrss; ++ long ru_minflt; ++ long ru_majflt; ++ long ru_nswap; ++ long ru_inblock; ++ long ru_oublock; ++ long ru_msgsnd; ++ long ru_msgrcv; ++ long ru_nsignals; ++ long ru_nvcsw; ++ long ru_nivcsw; ++}; ++ ++struct siginfo; ++#if defined(__i386__) || defined(__ARM_ARCH_3__) || defined(__PPC__) ++ ++/* include/asm-{arm,i386,mips,ppc}/signal.h */ ++struct kernel_old_sigaction { ++ union { ++ void (*sa_handler_)(int); ++ void (*sa_sigaction_)(int, struct siginfo *, void *); ++ }; ++ unsigned long sa_mask; ++ unsigned long sa_flags; ++ void (*sa_restorer)(void); ++} __attribute__((packed,aligned(4))); ++#elif (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) ++ #define kernel_old_sigaction kernel_sigaction ++#endif ++ ++/* Some kernel functions (e.g. sigaction() in 2.6.23) require that the ++ * exactly match the size of the signal set, even though the API was ++ * intended to be extensible. We define our own KERNEL_NSIG to deal with ++ * this. ++ * Please note that glibc provides signals [1.._NSIG-1], whereas the ++ * kernel (and this header) provides the range [1..KERNEL_NSIG]. The ++ * actual number of signals is obviously the same, but the constants ++ * differ by one. ++ */ ++#ifdef __mips__ ++#define KERNEL_NSIG 128 ++#else ++#define KERNEL_NSIG 64 ++#endif ++ ++/* include/asm-{arm,i386,mips,x86_64}/signal.h */ ++struct kernel_sigset_t { ++ unsigned long sig[(KERNEL_NSIG + 8*sizeof(unsigned long) - 1)/ ++ (8*sizeof(unsigned long))]; ++}; ++ ++/* include/asm-{arm,i386,mips,x86_64,ppc}/signal.h */ ++struct kernel_sigaction { ++#ifdef __mips__ ++ unsigned long sa_flags; ++ union { ++ void (*sa_handler_)(int); ++ void (*sa_sigaction_)(int, struct siginfo *, void *); ++ }; ++ struct kernel_sigset_t sa_mask; ++#else ++ union { ++ void (*sa_handler_)(int); ++ void (*sa_sigaction_)(int, struct siginfo *, void *); ++ }; ++ unsigned long sa_flags; ++ void (*sa_restorer)(void); ++ struct kernel_sigset_t sa_mask; ++#endif ++}; ++ ++/* include/linux/socket.h */ ++struct kernel_sockaddr { ++ unsigned short sa_family; ++ char sa_data[14]; ++}; ++ ++/* include/asm-{arm,i386,mips,ppc}/stat.h */ ++#ifdef __mips__ ++#if _MIPS_SIM == _MIPS_SIM_ABI64 ++struct kernel_stat { ++#else ++struct kernel_stat64 { ++#endif ++ unsigned st_dev; ++ unsigned __pad0[3]; ++ unsigned long long st_ino; ++ unsigned st_mode; ++ unsigned st_nlink; ++ unsigned st_uid; ++ unsigned st_gid; ++ unsigned st_rdev; ++ unsigned __pad1[3]; ++ long long st_size; ++ unsigned st_atime_; ++ unsigned st_atime_nsec_; ++ unsigned st_mtime_; ++ unsigned st_mtime_nsec_; ++ unsigned st_ctime_; ++ unsigned st_ctime_nsec_; ++ unsigned st_blksize; ++ unsigned __pad2; ++ unsigned long long st_blocks; ++}; ++#elif defined __PPC__ ++struct kernel_stat64 { ++ unsigned long long st_dev; ++ unsigned long long st_ino; ++ unsigned st_mode; ++ unsigned st_nlink; ++ unsigned st_uid; ++ unsigned st_gid; ++ unsigned long long st_rdev; ++ unsigned short int __pad2; ++ long long st_size; ++ long st_blksize; ++ long long st_blocks; ++ long st_atime_; ++ unsigned long st_atime_nsec_; ++ long st_mtime_; ++ unsigned long st_mtime_nsec_; ++ long st_ctime_; ++ unsigned long st_ctime_nsec_; ++ unsigned long __unused4; ++ unsigned long __unused5; ++}; ++#else ++struct kernel_stat64 { ++ unsigned long long st_dev; ++ unsigned char __pad0[4]; ++ unsigned __st_ino; ++ unsigned st_mode; ++ unsigned st_nlink; ++ unsigned st_uid; ++ unsigned st_gid; ++ unsigned long long st_rdev; ++ unsigned char __pad3[4]; ++ long long st_size; ++ unsigned st_blksize; ++ unsigned long long st_blocks; ++ unsigned st_atime_; ++ unsigned st_atime_nsec_; ++ unsigned st_mtime_; ++ unsigned st_mtime_nsec_; ++ unsigned st_ctime_; ++ unsigned st_ctime_nsec_; ++ unsigned long long st_ino; ++}; ++#endif ++ ++/* include/asm-{arm,i386,mips,x86_64,ppc}/stat.h */ ++#if defined(__i386__) || defined(__ARM_ARCH_3__) ++struct kernel_stat { ++ /* The kernel headers suggest that st_dev and st_rdev should be 32bit ++ * quantities encoding 12bit major and 20bit minor numbers in an interleaved ++ * format. In reality, we do not see useful data in the top bits. So, ++ * we'll leave the padding in here, until we find a better solution. ++ */ ++ unsigned short st_dev; ++ short pad1; ++ unsigned st_ino; ++ unsigned short st_mode; ++ unsigned short st_nlink; ++ unsigned short st_uid; ++ unsigned short st_gid; ++ unsigned short st_rdev; ++ short pad2; ++ unsigned st_size; ++ unsigned st_blksize; ++ unsigned st_blocks; ++ unsigned st_atime_; ++ unsigned st_atime_nsec_; ++ unsigned st_mtime_; ++ unsigned st_mtime_nsec_; ++ unsigned st_ctime_; ++ unsigned st_ctime_nsec_; ++ unsigned __unused4; ++ unsigned __unused5; ++}; ++#elif defined(__x86_64__) ++struct kernel_stat { ++ unsigned long st_dev; ++ unsigned long st_ino; ++ unsigned long st_nlink; ++ unsigned st_mode; ++ unsigned st_uid; ++ unsigned st_gid; ++ unsigned __pad0; ++ unsigned long st_rdev; ++ long st_size; ++ long st_blksize; ++ long st_blocks; ++ unsigned long st_atime_; ++ unsigned long st_atime_nsec_; ++ unsigned long st_mtime_; ++ unsigned long st_mtime_nsec_; ++ unsigned long st_ctime_; ++ unsigned long st_ctime_nsec_; ++ long __unused[3]; ++}; ++#elif defined(__PPC__) ++struct kernel_stat { ++ unsigned st_dev; ++ unsigned long st_ino; // ino_t ++ unsigned long st_mode; // mode_t ++ unsigned short st_nlink; // nlink_t ++ unsigned st_uid; // uid_t ++ unsigned st_gid; // gid_t ++ unsigned st_rdev; ++ long st_size; // off_t ++ unsigned long st_blksize; ++ unsigned long st_blocks; ++ unsigned long st_atime_; ++ unsigned long st_atime_nsec_; ++ unsigned long st_mtime_; ++ unsigned long st_mtime_nsec_; ++ unsigned long st_ctime_; ++ unsigned long st_ctime_nsec_; ++ unsigned long __unused4; ++ unsigned long __unused5; ++}; ++#elif (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI64) ++struct kernel_stat { ++ unsigned st_dev; ++ int st_pad1[3]; ++ unsigned st_ino; ++ unsigned st_mode; ++ unsigned st_nlink; ++ unsigned st_uid; ++ unsigned st_gid; ++ unsigned st_rdev; ++ int st_pad2[2]; ++ long st_size; ++ int st_pad3; ++ long st_atime_; ++ long st_atime_nsec_; ++ long st_mtime_; ++ long st_mtime_nsec_; ++ long st_ctime_; ++ long st_ctime_nsec_; ++ int st_blksize; ++ int st_blocks; ++ int st_pad4[14]; ++}; ++#endif ++ ++/* include/asm-{arm,i386,mips,x86_64,ppc}/statfs.h */ ++#ifdef __mips__ ++#if _MIPS_SIM != _MIPS_SIM_ABI64 ++struct kernel_statfs64 { ++ unsigned long f_type; ++ unsigned long f_bsize; ++ unsigned long f_frsize; ++ unsigned long __pad; ++ unsigned long long f_blocks; ++ unsigned long long f_bfree; ++ unsigned long long f_files; ++ unsigned long long f_ffree; ++ unsigned long long f_bavail; ++ struct { int val[2]; } f_fsid; ++ unsigned long f_namelen; ++ unsigned long f_spare[6]; ++}; ++#endif ++#elif !defined(__x86_64__) ++struct kernel_statfs64 { ++ unsigned long f_type; ++ unsigned long f_bsize; ++ unsigned long long f_blocks; ++ unsigned long long f_bfree; ++ unsigned long long f_bavail; ++ unsigned long long f_files; ++ unsigned long long f_ffree; ++ struct { int val[2]; } f_fsid; ++ unsigned long f_namelen; ++ unsigned long f_frsize; ++ unsigned long f_spare[5]; ++}; ++#endif ++ ++/* include/asm-{arm,i386,mips,x86_64,ppc,generic}/statfs.h */ ++#ifdef __mips__ ++struct kernel_statfs { ++ long f_type; ++ long f_bsize; ++ long f_frsize; ++ long f_blocks; ++ long f_bfree; ++ long f_files; ++ long f_ffree; ++ long f_bavail; ++ struct { int val[2]; } f_fsid; ++ long f_namelen; ++ long f_spare[6]; ++}; ++#else ++struct kernel_statfs { ++ /* x86_64 actually defines all these fields as signed, whereas all other */ ++ /* platforms define them as unsigned. Leaving them at unsigned should not */ ++ /* cause any problems. */ ++ unsigned long f_type; ++ unsigned long f_bsize; ++ unsigned long f_blocks; ++ unsigned long f_bfree; ++ unsigned long f_bavail; ++ unsigned long f_files; ++ unsigned long f_ffree; ++ struct { int val[2]; } f_fsid; ++ unsigned long f_namelen; ++ unsigned long f_frsize; ++ unsigned long f_spare[5]; ++}; ++#endif ++ ++ ++/* Definitions missing from the standard header files */ ++#ifndef O_DIRECTORY ++#if defined(__ARM_ARCH_3__) ++#define O_DIRECTORY 0040000 ++#else ++#define O_DIRECTORY 0200000 ++#endif ++#endif ++#ifndef NT_PRXFPREG ++#define NT_PRXFPREG 0x46e62b7f ++#endif ++#ifndef PTRACE_GETFPXREGS ++#define PTRACE_GETFPXREGS ((enum __ptrace_request)18) ++#endif ++#ifndef PR_GET_DUMPABLE ++#define PR_GET_DUMPABLE 3 ++#endif ++#ifndef PR_SET_DUMPABLE ++#define PR_SET_DUMPABLE 4 ++#endif ++#ifndef AT_FDCWD ++#define AT_FDCWD (-100) ++#endif ++#ifndef AT_SYMLINK_NOFOLLOW ++#define AT_SYMLINK_NOFOLLOW 0x100 ++#endif ++#ifndef AT_REMOVEDIR ++#define AT_REMOVEDIR 0x200 ++#endif ++#ifndef MREMAP_FIXED ++#define MREMAP_FIXED 2 ++#endif ++#ifndef SA_RESTORER ++#define SA_RESTORER 0x04000000 ++#endif ++ ++#if defined(__i386__) ++#ifndef __NR_setresuid ++#define __NR_setresuid 164 ++#define __NR_setresgid 170 ++#endif ++#ifndef __NR_rt_sigaction ++#define __NR_rt_sigaction 174 ++#define __NR_rt_sigprocmask 175 ++#define __NR_rt_sigpending 176 ++#define __NR_rt_sigsuspend 179 ++#endif ++#ifndef __NR_pread64 ++#define __NR_pread64 180 ++#endif ++#ifndef __NR_pwrite64 ++#define __NR_pwrite64 181 ++#endif ++#ifndef __NR_ugetrlimit ++#define __NR_ugetrlimit 191 ++#endif ++#ifndef __NR_stat64 ++#define __NR_stat64 195 ++#endif ++#ifndef __NR_fstat64 ++#define __NR_fstat64 197 ++#endif ++#ifndef __NR_setresuid32 ++#define __NR_setresuid32 208 ++#define __NR_setresgid32 210 ++#endif ++#ifndef __NR_setfsuid32 ++#define __NR_setfsuid32 215 ++#define __NR_setfsgid32 216 ++#endif ++#ifndef __NR_getdents64 ++#define __NR_getdents64 220 ++#endif ++#ifndef __NR_gettid ++#define __NR_gettid 224 ++#endif ++#ifndef __NR_readahead ++#define __NR_readahead 225 ++#endif ++#ifndef __NR_setxattr ++#define __NR_setxattr 226 ++#endif ++#ifndef __NR_lsetxattr ++#define __NR_lsetxattr 227 ++#endif ++#ifndef __NR_getxattr ++#define __NR_getxattr 229 ++#endif ++#ifndef __NR_lgetxattr ++#define __NR_lgetxattr 230 ++#endif ++#ifndef __NR_futex ++#define __NR_futex 240 ++#endif ++#ifndef __NR_sched_setaffinity ++#define __NR_sched_setaffinity 241 ++#define __NR_sched_getaffinity 242 ++#endif ++#ifndef __NR_set_tid_address ++#define __NR_set_tid_address 258 ++#endif ++#ifndef __NR_statfs64 ++#define __NR_statfs64 268 ++#endif ++#ifndef __NR_fstatfs64 ++#define __NR_fstatfs64 269 ++#endif ++#ifndef __NR_fadvise64_64 ++#define __NR_fadvise64_64 272 ++#endif ++#ifndef __NR_openat ++#define __NR_openat 295 ++#endif ++#ifndef __NR_fstatat64 ++#define __NR_fstatat64 300 ++#endif ++#ifndef __NR_unlinkat ++#define __NR_unlinkat 301 ++#endif ++#ifndef __NR_move_pages ++#define __NR_move_pages 317 ++#endif ++/* End of i386 definitions */ ++#elif defined(__ARM_ARCH_3__) ++#ifndef __NR_setresuid ++#define __NR_setresuid (__NR_SYSCALL_BASE + 164) ++#define __NR_setresgid (__NR_SYSCALL_BASE + 170) ++#endif ++#ifndef __NR_rt_sigaction ++#define __NR_rt_sigaction (__NR_SYSCALL_BASE + 174) ++#define __NR_rt_sigprocmask (__NR_SYSCALL_BASE + 175) ++#define __NR_rt_sigpending (__NR_SYSCALL_BASE + 176) ++#define __NR_rt_sigsuspend (__NR_SYSCALL_BASE + 179) ++#endif ++#ifndef __NR_pread64 ++#define __NR_pread64 (__NR_SYSCALL_BASE + 180) ++#endif ++#ifndef __NR_pwrite64 ++#define __NR_pwrite64 (__NR_SYSCALL_BASE + 181) ++#endif ++#ifndef __NR_ugetrlimit ++#define __NR_ugetrlimit (__NR_SYSCALL_BASE + 191) ++#endif ++#ifndef __NR_stat64 ++#define __NR_stat64 (__NR_SYSCALL_BASE + 195) ++#endif ++#ifndef __NR_fstat64 ++#define __NR_fstat64 (__NR_SYSCALL_BASE + 197) ++#endif ++#ifndef __NR_setresuid32 ++#define __NR_setresuid32 (__NR_SYSCALL_BASE + 208) ++#define __NR_setresgid32 (__NR_SYSCALL_BASE + 210) ++#endif ++#ifndef __NR_setfsuid32 ++#define __NR_setfsuid32 (__NR_SYSCALL_BASE + 215) ++#define __NR_setfsgid32 (__NR_SYSCALL_BASE + 216) ++#endif ++#ifndef __NR_getdents64 ++#define __NR_getdents64 (__NR_SYSCALL_BASE + 217) ++#endif ++#ifndef __NR_gettid ++#define __NR_gettid (__NR_SYSCALL_BASE + 224) ++#endif ++#ifndef __NR_readahead ++#define __NR_readahead (__NR_SYSCALL_BASE + 225) ++#endif ++#ifndef __NR_setxattr ++#define __NR_setxattr (__NR_SYSCALL_BASE + 226) ++#endif ++#ifndef __NR_lsetxattr ++#define __NR_lsetxattr (__NR_SYSCALL_BASE + 227) ++#endif ++#ifndef __NR_getxattr ++#define __NR_getxattr (__NR_SYSCALL_BASE + 229) ++#endif ++#ifndef __NR_lgetxattr ++#define __NR_lgetxattr (__NR_SYSCALL_BASE + 230) ++#endif ++#ifndef __NR_futex ++#define __NR_futex (__NR_SYSCALL_BASE + 240) ++#endif ++#ifndef __NR_sched_setaffinity ++#define __NR_sched_setaffinity (__NR_SYSCALL_BASE + 241) ++#define __NR_sched_getaffinity (__NR_SYSCALL_BASE + 242) ++#endif ++#ifndef __NR_set_tid_address ++#define __NR_set_tid_address (__NR_SYSCALL_BASE + 256) ++#endif ++#ifndef __NR_statfs64 ++#define __NR_statfs64 (__NR_SYSCALL_BASE + 266) ++#endif ++#ifndef __NR_fstatfs64 ++#define __NR_fstatfs64 (__NR_SYSCALL_BASE + 267) ++#endif ++#ifndef __NR_move_pages ++#define __NR_move_pages (__NR_SYSCALL_BASE + 344) ++#endif ++/* End of ARM 3 definitions */ ++#elif defined(__x86_64__) ++#ifndef __NR_setresuid ++#define __NR_setresuid 117 ++#define __NR_setresgid 119 ++#endif ++#ifndef __NR_gettid ++#define __NR_gettid 186 ++#endif ++#ifndef __NR_readahead ++#define __NR_readahead 187 ++#endif ++#ifndef __NR_setxattr ++#define __NR_setxattr 188 ++#endif ++#ifndef __NR_lsetxattr ++#define __NR_lsetxattr 189 ++#endif ++#ifndef __NR_getxattr ++#define __NR_getxattr 191 ++#endif ++#ifndef __NR_lgetxattr ++#define __NR_lgetxattr 192 ++#endif ++#ifndef __NR_futex ++#define __NR_futex 202 ++#endif ++#ifndef __NR_sched_setaffinity ++#define __NR_sched_setaffinity 203 ++#define __NR_sched_getaffinity 204 ++#endif ++#ifndef __NR_getdents64 ++#define __NR_getdents64 217 ++#endif ++#ifndef __NR_set_tid_address ++#define __NR_set_tid_address 218 ++#endif ++#ifndef __NR_fadvise64 ++#define __NR_fadvise64 221 ++#endif ++#ifndef __NR_openat ++#define __NR_openat 257 ++#endif ++#ifndef __NR_newfstatat ++#define __NR_newfstatat 262 ++#endif ++#ifndef __NR_unlinkat ++#define __NR_unlinkat 263 ++#endif ++#ifndef __NR_move_pages ++#define __NR_move_pages 279 ++#endif ++/* End of x86-64 definitions */ ++#elif defined(__mips__) ++#if _MIPS_SIM == _MIPS_SIM_ABI32 ++#ifndef __NR_setresuid ++#define __NR_setresuid (__NR_Linux + 185) ++#define __NR_setresgid (__NR_Linux + 190) ++#endif ++#ifndef __NR_rt_sigaction ++#define __NR_rt_sigaction (__NR_Linux + 194) ++#define __NR_rt_sigprocmask (__NR_Linux + 195) ++#define __NR_rt_sigpending (__NR_Linux + 196) ++#define __NR_rt_sigsuspend (__NR_Linux + 199) ++#endif ++#ifndef __NR_pread64 ++#define __NR_pread64 (__NR_Linux + 200) ++#endif ++#ifndef __NR_pwrite64 ++#define __NR_pwrite64 (__NR_Linux + 201) ++#endif ++#ifndef __NR_stat64 ++#define __NR_stat64 (__NR_Linux + 213) ++#endif ++#ifndef __NR_fstat64 ++#define __NR_fstat64 (__NR_Linux + 215) ++#endif ++#ifndef __NR_getdents64 ++#define __NR_getdents64 (__NR_Linux + 219) ++#endif ++#ifndef __NR_gettid ++#define __NR_gettid (__NR_Linux + 222) ++#endif ++#ifndef __NR_readahead ++#define __NR_readahead (__NR_Linux + 223) ++#endif ++#ifndef __NR_setxattr ++#define __NR_setxattr (__NR_Linux + 224) ++#endif ++#ifndef __NR_lsetxattr ++#define __NR_lsetxattr (__NR_Linux + 225) ++#endif ++#ifndef __NR_getxattr ++#define __NR_getxattr (__NR_Linux + 227) ++#endif ++#ifndef __NR_lgetxattr ++#define __NR_lgetxattr (__NR_Linux + 228) ++#endif ++#ifndef __NR_futex ++#define __NR_futex (__NR_Linux + 238) ++#endif ++#ifndef __NR_sched_setaffinity ++#define __NR_sched_setaffinity (__NR_Linux + 239) ++#define __NR_sched_getaffinity (__NR_Linux + 240) ++#endif ++#ifndef __NR_set_tid_address ++#define __NR_set_tid_address (__NR_Linux + 252) ++#endif ++#ifndef __NR_statfs64 ++#define __NR_statfs64 (__NR_Linux + 255) ++#endif ++#ifndef __NR_fstatfs64 ++#define __NR_fstatfs64 (__NR_Linux + 256) ++#endif ++#ifndef __NR_openat ++#define __NR_openat (__NR_Linux + 288) ++#endif ++#ifndef __NR_fstatat ++#define __NR_fstatat (__NR_Linux + 293) ++#endif ++#ifndef __NR_unlinkat ++#define __NR_unlinkat (__NR_Linux + 294) ++#endif ++#ifndef __NR_move_pages ++#define __NR_move_pages (__NR_Linux + 308) ++#endif ++/* End of MIPS (old 32bit API) definitions */ ++#elif _MIPS_SIM == _MIPS_SIM_ABI64 ++#ifndef __NR_setresuid ++#define __NR_setresuid (__NR_Linux + 115) ++#define __NR_setresgid (__NR_Linux + 117) ++#endif ++#ifndef __NR_gettid ++#define __NR_gettid (__NR_Linux + 178) ++#endif ++#ifndef __NR_readahead ++#define __NR_readahead (__NR_Linux + 179) ++#endif ++#ifndef __NR_setxattr ++#define __NR_setxattr (__NR_Linux + 180) ++#endif ++#ifndef __NR_lsetxattr ++#define __NR_lsetxattr (__NR_Linux + 181) ++#endif ++#ifndef __NR_getxattr ++#define __NR_getxattr (__NR_Linux + 183) ++#endif ++#ifndef __NR_lgetxattr ++#define __NR_lgetxattr (__NR_Linux + 184) ++#endif ++#ifndef __NR_futex ++#define __NR_futex (__NR_Linux + 194) ++#endif ++#ifndef __NR_sched_setaffinity ++#define __NR_sched_setaffinity (__NR_Linux + 195) ++#define __NR_sched_getaffinity (__NR_Linux + 196) ++#endif ++#ifndef __NR_set_tid_address ++#define __NR_set_tid_address (__NR_Linux + 212) ++#endif ++#ifndef __NR_openat ++#define __NR_openat (__NR_Linux + 247) ++#endif ++#ifndef __NR_fstatat ++#define __NR_fstatat (__NR_Linux + 252) ++#endif ++#ifndef __NR_unlinkat ++#define __NR_unlinkat (__NR_Linux + 253) ++#endif ++#ifndef __NR_move_pages ++#define __NR_move_pages (__NR_Linux + 267) ++#endif ++/* End of MIPS (64bit API) definitions */ ++#else ++#ifndef __NR_setresuid ++#define __NR_setresuid (__NR_Linux + 115) ++#define __NR_setresgid (__NR_Linux + 117) ++#endif ++#ifndef __NR_gettid ++#define __NR_gettid (__NR_Linux + 178) ++#endif ++#ifndef __NR_readahead ++#define __NR_readahead (__NR_Linux + 179) ++#endif ++#ifndef __NR_setxattr ++#define __NR_setxattr (__NR_Linux + 180) ++#endif ++#ifndef __NR_lsetxattr ++#define __NR_lsetxattr (__NR_Linux + 181) ++#endif ++#ifndef __NR_getxattr ++#define __NR_getxattr (__NR_Linux + 183) ++#endif ++#ifndef __NR_lgetxattr ++#define __NR_lgetxattr (__NR_Linux + 184) ++#endif ++#ifndef __NR_futex ++#define __NR_futex (__NR_Linux + 194) ++#endif ++#ifndef __NR_sched_setaffinity ++#define __NR_sched_setaffinity (__NR_Linux + 195) ++#define __NR_sched_getaffinity (__NR_Linux + 196) ++#endif ++#ifndef __NR_set_tid_address ++#define __NR_set_tid_address (__NR_Linux + 213) ++#endif ++#ifndef __NR_statfs64 ++#define __NR_statfs64 (__NR_Linux + 217) ++#endif ++#ifndef __NR_fstatfs64 ++#define __NR_fstatfs64 (__NR_Linux + 218) ++#endif ++#ifndef __NR_openat ++#define __NR_openat (__NR_Linux + 251) ++#endif ++#ifndef __NR_fstatat ++#define __NR_fstatat (__NR_Linux + 256) ++#endif ++#ifndef __NR_unlinkat ++#define __NR_unlinkat (__NR_Linux + 257) ++#endif ++#ifndef __NR_move_pages ++#define __NR_move_pages (__NR_Linux + 271) ++#endif ++/* End of MIPS (new 32bit API) definitions */ ++#endif ++/* End of MIPS definitions */ ++#elif defined(__PPC__) ++#ifndef __NR_setfsuid ++#define __NR_setfsuid 138 ++#define __NR_setfsgid 139 ++#endif ++#ifndef __NR_setresuid ++#define __NR_setresuid 164 ++#define __NR_setresgid 169 ++#endif ++#ifndef __NR_rt_sigaction ++#define __NR_rt_sigaction 173 ++#define __NR_rt_sigprocmask 174 ++#define __NR_rt_sigpending 175 ++#define __NR_rt_sigsuspend 178 ++#endif ++#ifndef __NR_pread64 ++#define __NR_pread64 179 ++#endif ++#ifndef __NR_pwrite64 ++#define __NR_pwrite64 180 ++#endif ++#ifndef __NR_ugetrlimit ++#define __NR_ugetrlimit 190 ++#endif ++#ifndef __NR_readahead ++#define __NR_readahead 191 ++#endif ++#ifndef __NR_stat64 ++#define __NR_stat64 195 ++#endif ++#ifndef __NR_fstat64 ++#define __NR_fstat64 197 ++#endif ++#ifndef __NR_getdents64 ++#define __NR_getdents64 202 ++#endif ++#ifndef __NR_gettid ++#define __NR_gettid 207 ++#endif ++#ifndef __NR_setxattr ++#define __NR_setxattr 209 ++#endif ++#ifndef __NR_lsetxattr ++#define __NR_lsetxattr 210 ++#endif ++#ifndef __NR_getxattr ++#define __NR_getxattr 212 ++#endif ++#ifndef __NR_lgetxattr ++#define __NR_lgetxattr 213 ++#endif ++#ifndef __NR_futex ++#define __NR_futex 221 ++#endif ++#ifndef __NR_sched_setaffinity ++#define __NR_sched_setaffinity 222 ++#define __NR_sched_getaffinity 223 ++#endif ++#ifndef __NR_set_tid_address ++#define __NR_set_tid_address 232 ++#endif ++#ifndef __NR_statfs64 ++#define __NR_statfs64 252 ++#endif ++#ifndef __NR_fstatfs64 ++#define __NR_fstatfs64 253 ++#endif ++#ifndef __NR_fadvise64_64 ++#define __NR_fadvise64_64 254 ++#endif ++#ifndef __NR_openat ++#define __NR_openat 286 ++#endif ++#ifndef __NR_fstatat64 ++#define __NR_fstatat64 291 ++#endif ++#ifndef __NR_unlinkat ++#define __NR_unlinkat 292 ++#endif ++#ifndef __NR_move_pages ++#define __NR_move_pages 301 ++#endif ++/* End of powerpc defininitions */ ++#endif ++ ++ ++/* After forking, we must make sure to only call system calls. */ ++#if __BOUNDED_POINTERS__ ++ #error "Need to port invocations of syscalls for bounded ptrs" ++#else ++ /* The core dumper and the thread lister get executed after threads ++ * have been suspended. As a consequence, we cannot call any functions ++ * that acquire locks. Unfortunately, libc wraps most system calls ++ * (e.g. in order to implement pthread_atfork, and to make calls ++ * cancellable), which means we cannot call these functions. Instead, ++ * we have to call syscall() directly. ++ */ ++ #undef LSS_ERRNO ++ #ifdef SYS_ERRNO ++ /* Allow the including file to override the location of errno. This can ++ * be useful when using clone() with the CLONE_VM option. ++ */ ++ #define LSS_ERRNO SYS_ERRNO ++ #else ++ #define LSS_ERRNO errno ++ #endif ++ ++ #undef LSS_INLINE ++ #ifdef SYS_INLINE ++ #define LSS_INLINE SYS_INLINE ++ #else ++ #define LSS_INLINE static inline ++ #endif ++ ++ /* Allow the including file to override the prefix used for all new ++ * system calls. By default, it will be set to "sys_". ++ */ ++ #undef LSS_NAME ++ #ifndef SYS_PREFIX ++ #define LSS_NAME(name) sys_##name ++ #elif SYS_PREFIX < 0 ++ #define LSS_NAME(name) name ++ #elif SYS_PREFIX == 0 ++ #define LSS_NAME(name) sys0_##name ++ #elif SYS_PREFIX == 1 ++ #define LSS_NAME(name) sys1_##name ++ #elif SYS_PREFIX == 2 ++ #define LSS_NAME(name) sys2_##name ++ #elif SYS_PREFIX == 3 ++ #define LSS_NAME(name) sys3_##name ++ #elif SYS_PREFIX == 4 ++ #define LSS_NAME(name) sys4_##name ++ #elif SYS_PREFIX == 5 ++ #define LSS_NAME(name) sys5_##name ++ #elif SYS_PREFIX == 6 ++ #define LSS_NAME(name) sys6_##name ++ #elif SYS_PREFIX == 7 ++ #define LSS_NAME(name) sys7_##name ++ #elif SYS_PREFIX == 8 ++ #define LSS_NAME(name) sys8_##name ++ #elif SYS_PREFIX == 9 ++ #define LSS_NAME(name) sys9_##name ++ #endif ++ ++ #undef LSS_RETURN ++ #if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__)) ++ /* Failing system calls return a negative result in the range of ++ * -1..-4095. These are "errno" values with the sign inverted. ++ */ ++ #define LSS_RETURN(type, res) \ ++ do { \ ++ if ((unsigned long)(res) >= (unsigned long)(-4095)) { \ ++ LSS_ERRNO = -(res); \ ++ res = -1; \ ++ } \ ++ return (type) (res); \ ++ } while (0) ++ #elif defined(__mips__) ++ /* On MIPS, failing system calls return -1, and set errno in a ++ * separate CPU register. ++ */ ++ #define LSS_RETURN(type, res, err) \ ++ do { \ ++ if (err) { \ ++ LSS_ERRNO = (res); \ ++ res = -1; \ ++ } \ ++ return (type) (res); \ ++ } while (0) ++ #elif defined(__PPC__) ++ /* On PPC, failing system calls return -1, and set errno in a ++ * separate CPU register. See linux/unistd.h. ++ */ ++ #define LSS_RETURN(type, res, err) \ ++ do { \ ++ if (err & 0x10000000 ) { \ ++ LSS_ERRNO = (res); \ ++ res = -1; \ ++ } \ ++ return (type) (res); \ ++ } while (0) ++ #endif ++ #if defined(__i386__) ++ /* In PIC mode (e.g. when building shared libraries), gcc for i386 ++ * reserves ebx. Unfortunately, most distribution ship with implementations ++ * of _syscallX() which clobber ebx. ++ * Also, most definitions of _syscallX() neglect to mark "memory" as being ++ * clobbered. This causes problems with compilers, that do a better job ++ * at optimizing across __asm__ calls. ++ * So, we just have to redefine all of the _syscallX() macros. ++ */ ++ #undef LSS_BODY ++ #define LSS_BODY(type,args...) \ ++ long __res; \ ++ __asm__ __volatile__("push %%ebx\n" \ ++ "movl %2,%%ebx\n" \ ++ "int $0x80\n" \ ++ "pop %%ebx" \ ++ args \ ++ : "memory"); \ ++ LSS_RETURN(type,__res) ++ #undef _syscall0 ++ #define _syscall0(type,name) \ ++ type LSS_NAME(name)(void) { \ ++ long __res; \ ++ __asm__ volatile("int $0x80" \ ++ : "=a" (__res) \ ++ : "0" (__NR_##name) \ ++ : "memory"); \ ++ LSS_RETURN(type,__res); \ ++ } ++ #undef _syscall1 ++ #define _syscall1(type,name,type1,arg1) \ ++ type LSS_NAME(name)(type1 arg1) { \ ++ LSS_BODY(type, \ ++ : "=a" (__res) \ ++ : "0" (__NR_##name), "ri" ((long)(arg1))); \ ++ } ++ #undef _syscall2 ++ #define _syscall2(type,name,type1,arg1,type2,arg2) \ ++ type LSS_NAME(name)(type1 arg1,type2 arg2) { \ ++ LSS_BODY(type, \ ++ : "=a" (__res) \ ++ : "0" (__NR_##name),"ri" ((long)(arg1)), "c" ((long)(arg2))); \ ++ } ++ #undef _syscall3 ++ #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ ++ type LSS_NAME(name)(type1 arg1,type2 arg2,type3 arg3) { \ ++ LSS_BODY(type, \ ++ : "=a" (__res) \ ++ : "0" (__NR_##name), "ri" ((long)(arg1)), "c" ((long)(arg2)), \ ++ "d" ((long)(arg3))); \ ++ } ++ #undef _syscall4 ++ #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ ++ LSS_BODY(type, \ ++ : "=a" (__res) \ ++ : "0" (__NR_##name), "ri" ((long)(arg1)), "c" ((long)(arg2)), \ ++ "d" ((long)(arg3)),"S" ((long)(arg4))); \ ++ } ++ #undef _syscall5 ++ #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ ++ type5,arg5) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ ++ type5 arg5) { \ ++ long __res; \ ++ __asm__ __volatile__("push %%ebx\n" \ ++ "movl %2,%%ebx\n" \ ++ "movl %1,%%eax\n" \ ++ "int $0x80\n" \ ++ "pop %%ebx" \ ++ : "=a" (__res) \ ++ : "i" (__NR_##name), "ri" ((long)(arg1)), \ ++ "c" ((long)(arg2)), "d" ((long)(arg3)), \ ++ "S" ((long)(arg4)), "D" ((long)(arg5)) \ ++ : "memory"); \ ++ LSS_RETURN(type,__res); \ ++ } ++ #undef _syscall6 ++ #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ ++ type5,arg5,type6,arg6) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ ++ type5 arg5, type6 arg6) { \ ++ long __res; \ ++ struct { long __a1; long __a6; } __s = { (long)arg1, (long) arg6 }; \ ++ __asm__ __volatile__("push %%ebp\n" \ ++ "push %%ebx\n" \ ++ "movl 4(%2),%%ebp\n" \ ++ "movl 0(%2), %%ebx\n" \ ++ "movl %1,%%eax\n" \ ++ "int $0x80\n" \ ++ "pop %%ebx\n" \ ++ "pop %%ebp" \ ++ : "=a" (__res) \ ++ : "i" (__NR_##name), "0" ((long)(&__s)), \ ++ "c" ((long)(arg2)), "d" ((long)(arg3)), \ ++ "S" ((long)(arg4)), "D" ((long)(arg5)) \ ++ : "memory"); \ ++ LSS_RETURN(type,__res); \ ++ } ++ LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack, ++ int flags, void *arg, int *parent_tidptr, ++ void *newtls, int *child_tidptr) { ++ long __res; ++ __asm__ __volatile__(/* if (fn == NULL) ++ * return -EINVAL; ++ */ ++ "movl %3,%%ecx\n" ++ "jecxz 1f\n" ++ ++ /* if (child_stack == NULL) ++ * return -EINVAL; ++ */ ++ "movl %4,%%ecx\n" ++ "jecxz 1f\n" ++ ++ /* Set up alignment of the child stack: ++ * child_stack = (child_stack & ~0xF) - 20; ++ */ ++ "andl $-16,%%ecx\n" ++ "subl $20,%%ecx\n" ++ ++ /* Push "arg" and "fn" onto the stack that will be ++ * used by the child. ++ */ ++ "movl %6,%%eax\n" ++ "movl %%eax,4(%%ecx)\n" ++ "movl %3,%%eax\n" ++ "movl %%eax,(%%ecx)\n" ++ ++ /* %eax = syscall(%eax = __NR_clone, ++ * %ebx = flags, ++ * %ecx = child_stack, ++ * %edx = parent_tidptr, ++ * %esi = newtls, ++ * %edi = child_tidptr) ++ * Also, make sure that %ebx gets preserved as it is ++ * used in PIC mode. ++ */ ++ "movl %8,%%esi\n" ++ "movl %7,%%edx\n" ++ "movl %5,%%eax\n" ++ "movl %9,%%edi\n" ++ "pushl %%ebx\n" ++ "movl %%eax,%%ebx\n" ++ "movl %2,%%eax\n" ++ "int $0x80\n" ++ ++ /* In the parent: restore %ebx ++ * In the child: move "fn" into %ebx ++ */ ++ "popl %%ebx\n" ++ ++ /* if (%eax != 0) ++ * return %eax; ++ */ ++ "test %%eax,%%eax\n" ++ "jnz 1f\n" ++ ++ /* In the child, now. Terminate frame pointer chain. ++ */ ++ "movl $0,%%ebp\n" ++ ++ /* Call "fn". "arg" is already on the stack. ++ */ ++ "call *%%ebx\n" ++ ++ /* Call _exit(%ebx). Unfortunately older versions ++ * of gcc restrict the number of arguments that can ++ * be passed to asm(). So, we need to hard-code the ++ * system call number. ++ */ ++ "movl %%eax,%%ebx\n" ++ "movl $1,%%eax\n" ++ "int $0x80\n" ++ ++ /* Return to parent. ++ */ ++ "1:\n" ++ : "=a" (__res) ++ : "0"(-EINVAL), "i"(__NR_clone), ++ "m"(fn), "m"(child_stack), "m"(flags), "m"(arg), ++ "m"(parent_tidptr), "m"(newtls), "m"(child_tidptr) ++ : "memory", "ecx", "edx", "esi", "edi"); ++ LSS_RETURN(int, __res); ++ } ++ ++ #define __NR__fadvise64_64 __NR_fadvise64_64 ++ LSS_INLINE _syscall6(int, _fadvise64_64, int, fd, ++ unsigned, offset_lo, unsigned, offset_hi, ++ unsigned, len_lo, unsigned, len_hi, ++ int, advice) ++ ++ LSS_INLINE int LSS_NAME(fadvise64)(int fd, loff_t offset, ++ loff_t len, int advice) { ++ return LSS_NAME(_fadvise64_64)(fd, ++ (unsigned)offset, (unsigned)(offset >>32), ++ (unsigned)len, (unsigned)(len >> 32), ++ advice); ++ } ++ ++ LSS_INLINE void (*LSS_NAME(restore_rt)(void))(void) { ++ /* On i386, the kernel does not know how to return from a signal ++ * handler. Instead, it relies on user space to provide a ++ * restorer function that calls the {rt_,}sigreturn() system call. ++ * Unfortunately, we cannot just reference the glibc version of this ++ * function, as glibc goes out of its way to make it inaccessible. ++ */ ++ void (*res)(void); ++ __asm__ __volatile__("call 2f\n" ++ "0:.align 16\n" ++ "1:movl %1,%%eax\n" ++ "int $0x80\n" ++ "2:popl %0\n" ++ "addl $(1b-0b),%0\n" ++ : "=a" (res) ++ : "i" (__NR_rt_sigreturn)); ++ return res; ++ } ++ LSS_INLINE void (*LSS_NAME(restore)(void))(void) { ++ /* On i386, the kernel does not know how to return from a signal ++ * handler. Instead, it relies on user space to provide a ++ * restorer function that calls the {rt_,}sigreturn() system call. ++ * Unfortunately, we cannot just reference the glibc version of this ++ * function, as glibc goes out of its way to make it inaccessible. ++ */ ++ void (*res)(void); ++ __asm__ __volatile__("call 2f\n" ++ "0:.align 16\n" ++ "1:pop %%eax\n" ++ "movl %1,%%eax\n" ++ "int $0x80\n" ++ "2:popl %0\n" ++ "addl $(1b-0b),%0\n" ++ : "=a" (res) ++ : "i" (__NR_sigreturn)); ++ return res; ++ } ++ #elif defined(__x86_64__) ++ /* There are no known problems with any of the _syscallX() macros ++ * currently shipping for x86_64, but we still need to be able to define ++ * our own version so that we can override the location of the errno ++ * location (e.g. when using the clone() system call with the CLONE_VM ++ * option). ++ */ ++ #undef LSS_BODY ++ #define LSS_BODY(type,name, ...) \ ++ long __res; \ ++ __asm__ __volatile__("syscall" : "=a" (__res) : "0" (__NR_##name), \ ++ ##__VA_ARGS__ : "r11", "rcx", "memory"); \ ++ LSS_RETURN(type, __res) ++ #undef _syscall0 ++ #define _syscall0(type,name) \ ++ type LSS_NAME(name)() { \ ++ LSS_BODY(type, name); \ ++ } ++ #undef _syscall1 ++ #define _syscall1(type,name,type1,arg1) \ ++ type LSS_NAME(name)(type1 arg1) { \ ++ LSS_BODY(type, name, "D" ((long)(arg1))); \ ++ } ++ #undef _syscall2 ++ #define _syscall2(type,name,type1,arg1,type2,arg2) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2) { \ ++ LSS_BODY(type, name, "D" ((long)(arg1)), "S" ((long)(arg2))); \ ++ } ++ #undef _syscall3 ++ #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ ++ LSS_BODY(type, name, "D" ((long)(arg1)), "S" ((long)(arg2)), \ ++ "d" ((long)(arg3))); \ ++ } ++ #undef _syscall4 ++ #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ ++ long __res; \ ++ __asm__ __volatile__("movq %5,%%r10; syscall" : \ ++ "=a" (__res) : "0" (__NR_##name), \ ++ "D" ((long)(arg1)), "S" ((long)(arg2)), "d" ((long)(arg3)), \ ++ "g" ((long)(arg4)) : "r10", "r11", "rcx", "memory"); \ ++ LSS_RETURN(type, __res); \ ++ } ++ #undef _syscall5 ++ #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ ++ type5,arg5) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ ++ type5 arg5) { \ ++ long __res; \ ++ __asm__ __volatile__("movq %5,%%r10; movq %6,%%r8; syscall" : \ ++ "=a" (__res) : "0" (__NR_##name), \ ++ "D" ((long)(arg1)), "S" ((long)(arg2)), "d" ((long)(arg3)), \ ++ "g" ((long)(arg4)), "g" ((long)(arg5)) : \ ++ "r8", "r10", "r11", "rcx", "memory"); \ ++ LSS_RETURN(type, __res); \ ++ } ++ #undef _syscall6 ++ #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ ++ type5,arg5,type6,arg6) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ ++ type5 arg5, type6 arg6) { \ ++ long __res; \ ++ __asm__ __volatile__("movq %5,%%r10; movq %6,%%r8; movq %7,%%r9;" \ ++ "syscall" : \ ++ "=a" (__res) : "0" (__NR_##name), \ ++ "D" ((long)(arg1)), "S" ((long)(arg2)), "d" ((long)(arg3)), \ ++ "g" ((long)(arg4)), "g" ((long)(arg5)), "g" ((long)(arg6)) : \ ++ "r8", "r9", "r10", "r11", "rcx", "memory"); \ ++ LSS_RETURN(type, __res); \ ++ } ++ LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack, ++ int flags, void *arg, int *parent_tidptr, ++ void *newtls, int *child_tidptr) { ++ long __res; ++ { ++ register void *__tls __asm__("r8") = newtls; ++ register int *__ctid __asm__("r10") = child_tidptr; ++ __asm__ __volatile__(/* if (fn == NULL) ++ * return -EINVAL; ++ */ ++ "testq %4,%4\n" ++ "jz 1f\n" ++ ++ /* if (child_stack == NULL) ++ * return -EINVAL; ++ */ ++ "testq %5,%5\n" ++ "jz 1f\n" ++ ++ /* childstack -= 2*sizeof(void *); ++ */ ++ "subq $16,%5\n" ++ ++ /* Push "arg" and "fn" onto the stack that will be ++ * used by the child. ++ */ ++ "movq %7,8(%5)\n" ++ "movq %4,0(%5)\n" ++ ++ /* %rax = syscall(%rax = __NR_clone, ++ * %rdi = flags, ++ * %rsi = child_stack, ++ * %rdx = parent_tidptr, ++ * %r8 = new_tls, ++ * %r10 = child_tidptr) ++ */ ++ "movq %2,%%rax\n" ++ "syscall\n" ++ ++ /* if (%rax != 0) ++ * return; ++ */ ++ "testq %%rax,%%rax\n" ++ "jnz 1f\n" ++ ++ /* In the child. Terminate frame pointer chain. ++ */ ++ "xorq %%rbp,%%rbp\n" ++ ++ /* Call "fn(arg)". ++ */ ++ "popq %%rax\n" ++ "popq %%rdi\n" ++ "call *%%rax\n" ++ ++ /* Call _exit(%ebx). ++ */ ++ "movq %%rax,%%rdi\n" ++ "movq %3,%%rax\n" ++ "syscall\n" ++ ++ /* Return to parent. ++ */ ++ "1:\n" ++ : "=a" (__res) ++ : "0"(-EINVAL), "i"(__NR_clone), "i"(__NR_exit), ++ "r"(fn), "S"(child_stack), "D"(flags), "r"(arg), ++ "d"(parent_tidptr), "r"(__tls), "r"(__ctid) ++ : "memory", "r11", "rcx"); ++ } ++ LSS_RETURN(int, __res); ++ } ++ LSS_INLINE _syscall4(int, fadvise64, int, fd, loff_t, offset, loff_t, len, ++ int, advice) ++ ++ LSS_INLINE void (*LSS_NAME(restore_rt)(void))(void) { ++ /* On x86-64, the kernel does not know how to return from ++ * a signal handler. Instead, it relies on user space to provide a ++ * restorer function that calls the rt_sigreturn() system call. ++ * Unfortunately, we cannot just reference the glibc version of this ++ * function, as glibc goes out of its way to make it inaccessible. ++ */ ++ void (*res)(void); ++ __asm__ __volatile__("call 2f\n" ++ "0:.align 16\n" ++ "1:movq %1,%%rax\n" ++ "syscall\n" ++ "2:popq %0\n" ++ "addq $(1b-0b),%0\n" ++ : "=a" (res) ++ : "i" (__NR_rt_sigreturn)); ++ return res; ++ } ++ #elif defined(__ARM_ARCH_3__) ++ /* Most definitions of _syscallX() neglect to mark "memory" as being ++ * clobbered. This causes problems with compilers, that do a better job ++ * at optimizing across __asm__ calls. ++ * So, we just have to redefine all fo the _syscallX() macros. ++ */ ++ #undef LSS_REG ++ #define LSS_REG(r,a) register long __r##r __asm__("r"#r) = (long)a ++ #undef LSS_BODY ++ #define LSS_BODY(type,name,args...) \ ++ register long __res_r0 __asm__("r0"); \ ++ long __res; \ ++ __asm__ __volatile__ (__syscall(name) \ ++ : "=r"(__res_r0) : args : "lr", "memory"); \ ++ __res = __res_r0; \ ++ LSS_RETURN(type, __res) ++ #undef _syscall0 ++ #define _syscall0(type, name) \ ++ type LSS_NAME(name)() { \ ++ LSS_BODY(type, name); \ ++ } ++ #undef _syscall1 ++ #define _syscall1(type, name, type1, arg1) \ ++ type LSS_NAME(name)(type1 arg1) { \ ++ LSS_REG(0, arg1); LSS_BODY(type, name, "r"(__r0)); \ ++ } ++ #undef _syscall2 ++ #define _syscall2(type, name, type1, arg1, type2, arg2) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2) { \ ++ LSS_REG(0, arg1); LSS_REG(1, arg2); \ ++ LSS_BODY(type, name, "r"(__r0), "r"(__r1)); \ ++ } ++ #undef _syscall3 ++ #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ ++ LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \ ++ LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2)); \ ++ } ++ #undef _syscall4 ++ #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ ++ LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \ ++ LSS_REG(3, arg4); \ ++ LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3)); \ ++ } ++ #undef _syscall5 ++ #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ ++ type5,arg5) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ ++ type5 arg5) { \ ++ LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \ ++ LSS_REG(3, arg4); LSS_REG(4, arg5); \ ++ LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3), \ ++ "r"(__r4)); \ ++ } ++ #undef _syscall6 ++ #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ ++ type5,arg5,type6,arg6) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ ++ type5 arg5, type6 arg6) { \ ++ LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \ ++ LSS_REG(3, arg4); LSS_REG(4, arg5); LSS_REG(5, arg6); \ ++ LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3), \ ++ "r"(__r4), "r"(__r5)); \ ++ } ++ LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack, ++ int flags, void *arg, int *parent_tidptr, ++ void *newtls, int *child_tidptr) { ++ long __res; ++ { ++ register int __flags __asm__("r0") = flags; ++ register void *__stack __asm__("r1") = child_stack; ++ register void *__ptid __asm__("r2") = parent_tidptr; ++ register void *__tls __asm__("r3") = newtls; ++ register int *__ctid __asm__("r4") = child_tidptr; ++ __asm__ __volatile__(/* if (fn == NULL || child_stack == NULL) ++ * return -EINVAL; ++ */ ++ "cmp %2,#0\n" ++ "cmpne %3,#0\n" ++ "moveq %0,%1\n" ++ "beq 1f\n" ++ ++ /* Push "arg" and "fn" onto the stack that will be ++ * used by the child. ++ */ ++ "str %5,[%3,#-4]!\n" ++ "str %2,[%3,#-4]!\n" ++ ++ /* %r0 = syscall(%r0 = flags, ++ * %r1 = child_stack, ++ * %r2 = parent_tidptr, ++ * %r3 = newtls, ++ * %r4 = child_tidptr) ++ */ ++ __syscall(clone)"\n" ++ ++ /* if (%r0 != 0) ++ * return %r0; ++ */ ++ "movs %0,r0\n" ++ "bne 1f\n" ++ ++ /* In the child, now. Call "fn(arg)". ++ */ ++ "ldr r0,[sp, #4]\n" ++ "mov lr,pc\n" ++ "ldr pc,[sp]\n" ++ ++ /* Call _exit(%r0). ++ */ ++ __syscall(exit)"\n" ++ "1:\n" ++ : "=r" (__res) ++ : "i"(-EINVAL), ++ "r"(fn), "r"(__stack), "r"(__flags), "r"(arg), ++ "r"(__ptid), "r"(__tls), "r"(__ctid) ++ : "lr", "memory"); ++ } ++ LSS_RETURN(int, __res); ++ } ++ #elif defined(__mips__) ++ #undef LSS_REG ++ #define LSS_REG(r,a) register unsigned long __r##r __asm__("$"#r) = \ ++ (unsigned long)(a) ++ #undef LSS_BODY ++ #define LSS_BODY(type,name,r7,...) \ ++ register unsigned long __v0 __asm__("$2") = __NR_##name; \ ++ __asm__ __volatile__ ("syscall\n" \ ++ : "=&r"(__v0), r7 (__r7) \ ++ : "0"(__v0), ##__VA_ARGS__ \ ++ : "$8", "$9", "$10", "$11", "$12", \ ++ "$13", "$14", "$15", "$24", "memory"); \ ++ LSS_RETURN(type, __v0, __r7) ++ #undef _syscall0 ++ #define _syscall0(type, name) \ ++ type LSS_NAME(name)() { \ ++ register unsigned long __r7 __asm__("$7"); \ ++ LSS_BODY(type, name, "=r"); \ ++ } ++ #undef _syscall1 ++ #define _syscall1(type, name, type1, arg1) \ ++ type LSS_NAME(name)(type1 arg1) { \ ++ register unsigned long __r7 __asm__("$7"); \ ++ LSS_REG(4, arg1); LSS_BODY(type, name, "=r", "r"(__r4)); \ ++ } ++ #undef _syscall2 ++ #define _syscall2(type, name, type1, arg1, type2, arg2) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2) { \ ++ register unsigned long __r7 __asm__("$7"); \ ++ LSS_REG(4, arg1); LSS_REG(5, arg2); \ ++ LSS_BODY(type, name, "=r", "r"(__r4), "r"(__r5)); \ ++ } ++ #undef _syscall3 ++ #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ ++ register unsigned long __r7 __asm__("$7"); \ ++ LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \ ++ LSS_BODY(type, name, "=r", "r"(__r4), "r"(__r5), "r"(__r6)); \ ++ } ++ #undef _syscall4 ++ #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ ++ LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \ ++ LSS_REG(7, arg4); \ ++ LSS_BODY(type, name, "+r", "r"(__r4), "r"(__r5), "r"(__r6)); \ ++ } ++ #undef _syscall5 ++ #if _MIPS_SIM == _MIPS_SIM_ABI32 ++ /* The old 32bit MIPS system call API passes the fifth and sixth argument ++ * on the stack, whereas the new APIs use registers "r8" and "r9". ++ */ ++ #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ ++ type5,arg5) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ ++ type5 arg5) { \ ++ LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \ ++ LSS_REG(7, arg4); \ ++ register unsigned long __v0 __asm__("$2"); \ ++ __asm__ __volatile__ (".set noreorder\n" \ ++ "lw $2, %6\n" \ ++ "subu $29, 32\n" \ ++ "sw $2, 16($29)\n" \ ++ "li $2, %2\n" \ ++ "syscall\n" \ ++ "addiu $29, 32\n" \ ++ ".set reorder\n" \ ++ : "=&r"(__v0), "+r" (__r7) \ ++ : "i" (__NR_##name), "r"(__r4), "r"(__r5), \ ++ "r"(__r6), "m" ((unsigned long)arg5) \ ++ : "$8", "$9", "$10", "$11", "$12", \ ++ "$13", "$14", "$15", "$24", "memory"); \ ++ LSS_RETURN(type, __v0, __r7); \ ++ } ++ #else ++ #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ ++ type5,arg5) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ ++ type5 arg5) { \ ++ LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \ ++ LSS_REG(7, arg4); LSS_REG(8, arg5); \ ++ LSS_BODY(type, name, "+r", "r"(__r4), "r"(__r5), "r"(__r6), \ ++ "r"(__r8)); \ ++ } ++ #endif ++ #undef _syscall6 ++ #if _MIPS_SIM == _MIPS_SIM_ABI32 ++ /* The old 32bit MIPS system call API passes the fifth and sixth argument ++ * on the stack, whereas the new APIs use registers "r8" and "r9". ++ */ ++ #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ ++ type5,arg5,type6,arg6) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ ++ type5 arg5, type6 arg6) { \ ++ LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \ ++ LSS_REG(7, arg4); \ ++ register unsigned long __v0 __asm__("$2"); \ ++ __asm__ __volatile__ (".set noreorder\n" \ ++ "lw $2, %6\n" \ ++ "lw $8, %7\n" \ ++ "subu $29, 32\n" \ ++ "sw $2, 16($29)\n" \ ++ "sw $8, 20($29)\n" \ ++ "li $2, %2\n" \ ++ "syscall\n" \ ++ "addiu $29, 32\n" \ ++ ".set reorder\n" \ ++ : "=&r"(__v0), "+r" (__r7) \ ++ : "i" (__NR_##name), "r"(__r4), "r"(__r5), \ ++ "r"(__r6), "r" ((unsigned long)arg5), \ ++ "r" ((unsigned long)arg6) \ ++ : "$8", "$9", "$10", "$11", "$12", \ ++ "$13", "$14", "$15", "$24", "memory"); \ ++ LSS_RETURN(type, __v0, __r7); \ ++ } ++ #else ++ #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ ++ type5,arg5,type6,arg6) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ ++ type5 arg5,type6 arg6) { \ ++ LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3); \ ++ LSS_REG(7, arg4); LSS_REG(8, arg5); LSS_REG(9, arg6); \ ++ LSS_BODY(type, name, "+r", "r"(__r4), "r"(__r5), "r"(__r6), \ ++ "r"(__r8), "r"(__r9)); \ ++ } ++ #endif ++ LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack, ++ int flags, void *arg, int *parent_tidptr, ++ void *newtls, int *child_tidptr) { ++ register unsigned long __v0 __asm__("$2"); ++ register unsigned long __r7 __asm__("$7") = (unsigned long)newtls; ++ { ++ register int __flags __asm__("$4") = flags; ++ register void *__stack __asm__("$5") = child_stack; ++ register void *__ptid __asm__("$6") = parent_tidptr; ++ register int *__ctid __asm__("$8") = child_tidptr; ++ __asm__ __volatile__( ++ #if _MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32 ++ "subu $29,24\n" ++ #elif _MIPS_SIM == _MIPS_SIM_NABI32 ++ "sub $29,16\n" ++ #else ++ "dsubu $29,16\n" ++ #endif ++ ++ /* if (fn == NULL || child_stack == NULL) ++ * return -EINVAL; ++ */ ++ "li %0,%2\n" ++ "beqz %5,1f\n" ++ "beqz %6,1f\n" ++ ++ /* Push "arg" and "fn" onto the stack that will be ++ * used by the child. ++ */ ++ #if _MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32 ++ "subu %6,32\n" ++ "sw %5,0(%6)\n" ++ "sw %8,4(%6)\n" ++ #elif _MIPS_SIM == _MIPS_SIM_NABI32 ++ "sub %6,32\n" ++ "sw %5,0(%6)\n" ++ "sw %8,8(%6)\n" ++ #else ++ "dsubu %6,32\n" ++ "sd %5,0(%6)\n" ++ "sd %8,8(%6)\n" ++ #endif ++ ++ /* $7 = syscall($4 = flags, ++ * $5 = child_stack, ++ * $6 = parent_tidptr, ++ * $7 = newtls, ++ * $8 = child_tidptr) ++ */ ++ "li $2,%3\n" ++ "syscall\n" ++ ++ /* if ($7 != 0) ++ * return $2; ++ */ ++ "bnez $7,1f\n" ++ "bnez $2,1f\n" ++ ++ /* In the child, now. Call "fn(arg)". ++ */ ++ #if _MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32 ++ "lw $25,0($29)\n" ++ "lw $4,4($29)\n" ++ #elif _MIPS_SIM == _MIPS_SIM_NABI32 ++ "lw $25,0($29)\n" ++ "lw $4,8($29)\n" ++ #else ++ "ld $25,0($29)\n" ++ "ld $4,8($29)\n" ++ #endif ++ "jalr $25\n" ++ ++ /* Call _exit($2) ++ */ ++ "move $4,$2\n" ++ "li $2,%4\n" ++ "syscall\n" ++ ++ "1:\n" ++ #if _MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32 ++ "addu $29, 24\n" ++ #elif _MIPS_SIM == _MIPS_SIM_NABI32 ++ "add $29, 16\n" ++ #else ++ "daddu $29,16\n" ++ #endif ++ : "=&r" (__v0), "=r" (__r7) ++ : "i"(-EINVAL), "i"(__NR_clone), "i"(__NR_exit), ++ "r"(fn), "r"(__stack), "r"(__flags), "r"(arg), ++ "r"(__ptid), "r"(__r7), "r"(__ctid) ++ : "$9", "$10", "$11", "$12", "$13", "$14", "$15", ++ "$24", "memory"); ++ } ++ LSS_RETURN(int, __v0, __r7); ++ } ++ #elif defined (__PPC__) ++ #undef LSS_LOADARGS_0 ++ #define LSS_LOADARGS_0(name, dummy...) \ ++ __sc_0 = __NR_##name ++ #undef LSS_LOADARGS_1 ++ #define LSS_LOADARGS_1(name, arg1) \ ++ LSS_LOADARGS_0(name); \ ++ __sc_3 = (unsigned long) (arg1) ++ #undef LSS_LOADARGS_2 ++ #define LSS_LOADARGS_2(name, arg1, arg2) \ ++ LSS_LOADARGS_1(name, arg1); \ ++ __sc_4 = (unsigned long) (arg2) ++ #undef LSS_LOADARGS_3 ++ #define LSS_LOADARGS_3(name, arg1, arg2, arg3) \ ++ LSS_LOADARGS_2(name, arg1, arg2); \ ++ __sc_5 = (unsigned long) (arg3) ++ #undef LSS_LOADARGS_4 ++ #define LSS_LOADARGS_4(name, arg1, arg2, arg3, arg4) \ ++ LSS_LOADARGS_3(name, arg1, arg2, arg3); \ ++ __sc_6 = (unsigned long) (arg4) ++ #undef LSS_LOADARGS_5 ++ #define LSS_LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5) \ ++ LSS_LOADARGS_4(name, arg1, arg2, arg3, arg4); \ ++ __sc_7 = (unsigned long) (arg5) ++ #undef LSS_LOADARGS_6 ++ #define LSS_LOADARGS_6(name, arg1, arg2, arg3, arg4, arg5, arg6) \ ++ LSS_LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5); \ ++ __sc_8 = (unsigned long) (arg6) ++ #undef LSS_ASMINPUT_0 ++ #define LSS_ASMINPUT_0 "0" (__sc_0) ++ #undef LSS_ASMINPUT_1 ++ #define LSS_ASMINPUT_1 LSS_ASMINPUT_0, "1" (__sc_3) ++ #undef LSS_ASMINPUT_2 ++ #define LSS_ASMINPUT_2 LSS_ASMINPUT_1, "2" (__sc_4) ++ #undef LSS_ASMINPUT_3 ++ #define LSS_ASMINPUT_3 LSS_ASMINPUT_2, "3" (__sc_5) ++ #undef LSS_ASMINPUT_4 ++ #define LSS_ASMINPUT_4 LSS_ASMINPUT_3, "4" (__sc_6) ++ #undef LSS_ASMINPUT_5 ++ #define LSS_ASMINPUT_5 LSS_ASMINPUT_4, "5" (__sc_7) ++ #undef LSS_ASMINPUT_6 ++ #define LSS_ASMINPUT_6 LSS_ASMINPUT_5, "6" (__sc_8) ++ #undef LSS_BODY ++ #define LSS_BODY(nr, type, name, args...) \ ++ long __sc_ret, __sc_err; \ ++ { \ ++ register unsigned long __sc_0 __asm__ ("r0"); \ ++ register unsigned long __sc_3 __asm__ ("r3"); \ ++ register unsigned long __sc_4 __asm__ ("r4"); \ ++ register unsigned long __sc_5 __asm__ ("r5"); \ ++ register unsigned long __sc_6 __asm__ ("r6"); \ ++ register unsigned long __sc_7 __asm__ ("r7"); \ ++ register unsigned long __sc_8 __asm__ ("r8"); \ ++ \ ++ LSS_LOADARGS_##nr(name, args); \ ++ __asm__ __volatile__ \ ++ ("sc\n\t" \ ++ "mfcr %0" \ ++ : "=&r" (__sc_0), \ ++ "=&r" (__sc_3), "=&r" (__sc_4), \ ++ "=&r" (__sc_5), "=&r" (__sc_6), \ ++ "=&r" (__sc_7), "=&r" (__sc_8) \ ++ : LSS_ASMINPUT_##nr \ ++ : "cr0", "ctr", "memory", \ ++ "r9", "r10", "r11", "r12"); \ ++ __sc_ret = __sc_3; \ ++ __sc_err = __sc_0; \ ++ } \ ++ LSS_RETURN(type, __sc_ret, __sc_err) ++ #undef _syscall0 ++ #define _syscall0(type, name) \ ++ type LSS_NAME(name)(void) { \ ++ LSS_BODY(0, type, name); \ ++ } ++ #undef _syscall1 ++ #define _syscall1(type, name, type1, arg1) \ ++ type LSS_NAME(name)(type1 arg1) { \ ++ LSS_BODY(1, type, name, arg1); \ ++ } ++ #undef _syscall2 ++ #define _syscall2(type, name, type1, arg1, type2, arg2) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2) { \ ++ LSS_BODY(2, type, name, arg1, arg2); \ ++ } ++ #undef _syscall3 ++ #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ ++ LSS_BODY(3, type, name, arg1, arg2, arg3); \ ++ } ++ #undef _syscall4 ++ #define _syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \ ++ type4, arg4) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ ++ LSS_BODY(4, type, name, arg1, arg2, arg3, arg4); \ ++ } ++ #undef _syscall5 ++ #define _syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \ ++ type4, arg4, type5, arg5) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ ++ type5 arg5) { \ ++ LSS_BODY(5, type, name, arg1, arg2, arg3, arg4, arg5); \ ++ } ++ #undef _syscall6 ++ #define _syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \ ++ type4, arg4, type5, arg5, type6, arg6) \ ++ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ ++ type5 arg5, type6 arg6) { \ ++ LSS_BODY(6, type, name, arg1, arg2, arg3, arg4, arg5, arg6); \ ++ } ++ /* clone function adapted from glibc 2.3.6 clone.S */ ++ /* TODO(csilvers): consider wrapping some args up in a struct, like we ++ * do for i386's _syscall6, so we can compile successfully on gcc 2.95 ++ */ ++ LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack, ++ int flags, void *arg, int *parent_tidptr, ++ void *newtls, int *child_tidptr) { ++ long __ret, __err; ++ { ++ register int (*__fn)(void *) __asm__ ("r8") = fn; ++ register void *__cstack __asm__ ("r4") = child_stack; ++ register int __flags __asm__ ("r3") = flags; ++ register void * __arg __asm__ ("r9") = arg; ++ register int * __ptidptr __asm__ ("r5") = parent_tidptr; ++ register void * __newtls __asm__ ("r6") = newtls; ++ register int * __ctidptr __asm__ ("r7") = child_tidptr; ++ __asm__ __volatile__( ++ /* check for fn == NULL ++ * and child_stack == NULL ++ */ ++ "cmpwi cr0, %6, 0\n\t" ++ "cmpwi cr1, %7, 0\n\t" ++ "cror cr0*4+eq, cr1*4+eq, cr0*4+eq\n\t" ++ "beq- cr0, 1f\n\t" ++ ++ /* set up stack frame for child */ ++ "clrrwi %7, %7, 4\n\t" ++ "li 0, 0\n\t" ++ "stwu 0, -16(%7)\n\t" ++ ++ /* fn, arg, child_stack are saved across the syscall: r28-30 */ ++ "mr 28, %6\n\t" ++ "mr 29, %7\n\t" ++ "mr 27, %9\n\t" ++ ++ /* syscall */ ++ "li 0, %4\n\t" ++ /* flags already in r3 ++ * child_stack already in r4 ++ * ptidptr already in r5 ++ * newtls already in r6 ++ * ctidptr already in r7 ++ */ ++ "sc\n\t" ++ ++ /* Test if syscall was successful */ ++ "cmpwi cr1, 3, 0\n\t" ++ "crandc cr1*4+eq, cr1*4+eq, cr0*4+so\n\t" ++ "bne- cr1, 1f\n\t" ++ ++ /* Do the function call */ ++ "mtctr 28\n\t" ++ "mr 3, 27\n\t" ++ "bctrl\n\t" ++ ++ /* Call _exit(r3) */ ++ "li 0, %5\n\t" ++ "sc\n\t" ++ ++ /* Return to parent */ ++ "1:\n" ++ "mfcr %1\n\t" ++ "mr %0, 3\n\t" ++ : "=r" (__ret), "=r" (__err) ++ : "0" (-1), "1" (EINVAL), ++ "i" (__NR_clone), "i" (__NR_exit), ++ "r" (__fn), "r" (__cstack), "r" (__flags), ++ "r" (__arg), "r" (__ptidptr), "r" (__newtls), ++ "r" (__ctidptr) ++ : "cr0", "cr1", "memory", "ctr", ++ "r0", "r29", "r27", "r28"); ++ } ++ LSS_RETURN(int, __ret, __err); ++ } ++ #endif ++ #define __NR__exit __NR_exit ++ #define __NR__gettid __NR_gettid ++ #define __NR__mremap __NR_mremap ++ LSS_INLINE _syscall1(int, chdir, const char *,p) ++ LSS_INLINE _syscall1(int, close, int, f) ++ LSS_INLINE _syscall1(int, dup, int, f) ++ LSS_INLINE _syscall2(int, dup2, int, s, ++ int, d) ++ LSS_INLINE _syscall3(int, execve, const char*, f, ++ const char*const*,a,const char*const*, e) ++ LSS_INLINE _syscall1(int, _exit, int, e) ++ LSS_INLINE _syscall3(int, fcntl, int, f, ++ int, c, long, a) ++ LSS_INLINE _syscall0(pid_t, fork) ++ LSS_INLINE _syscall2(int, fstat, int, f, ++ struct kernel_stat*, b) ++ LSS_INLINE _syscall2(int, fstatfs, int, f, ++ struct kernel_statfs*, b) ++ LSS_INLINE _syscall4(int, futex, int*, a, ++ int, o, int, v, ++ struct kernel_timespec*, t) ++ LSS_INLINE _syscall3(int, getdents, int, f, ++ struct kernel_dirent*, d, int, c) ++ LSS_INLINE _syscall3(int, getdents64, int, f, ++ struct kernel_dirent64*, d, int, c) ++ LSS_INLINE _syscall0(gid_t, getegid) ++ LSS_INLINE _syscall0(uid_t, geteuid) ++ LSS_INLINE _syscall0(pid_t, getpgrp) ++ LSS_INLINE _syscall0(pid_t, getpid) ++ LSS_INLINE _syscall0(pid_t, getppid) ++ LSS_INLINE _syscall2(int, getpriority, int, a, ++ int, b) ++ LSS_INLINE _syscall2(int, getrlimit, int, r, ++ struct kernel_rlimit*, l) ++ LSS_INLINE _syscall1(pid_t, getsid, pid_t, p) ++ LSS_INLINE _syscall0(pid_t, _gettid) ++ LSS_INLINE _syscall5(int, setxattr, const char *,p, ++ const char *, n, const void *,v, ++ size_t, s, int, f) ++ LSS_INLINE _syscall5(int, lsetxattr, const char *,p, ++ const char *, n, const void *,v, ++ size_t, s, int, f) ++ LSS_INLINE _syscall4(ssize_t, getxattr, const char *,p, ++ const char *, n, void *, v, size_t, s) ++ LSS_INLINE _syscall4(ssize_t, lgetxattr, const char *,p, ++ const char *, n, void *, v, size_t, s) ++ LSS_INLINE _syscall2(int, kill, pid_t, p, ++ int, s) ++ LSS_INLINE _syscall3(off_t, lseek, int, f, ++ off_t, o, int, w) ++ LSS_INLINE _syscall2(int, munmap, void*, s, ++ size_t, l) ++ LSS_INLINE _syscall6(long, move_pages, pid_t, p, ++ unsigned long, n, void **,g, int *, d, ++ int *, s, int, f) ++ LSS_INLINE _syscall5(void*, _mremap, void*, o, ++ size_t, os, size_t, ns, ++ unsigned long, f, void *, a) ++ LSS_INLINE _syscall3(int, open, const char*, p, ++ int, f, int, m) ++ LSS_INLINE _syscall3(int, poll, struct kernel_pollfd*, u, ++ unsigned int, n, int, t) ++ LSS_INLINE _syscall2(int, prctl, int, o, ++ long, a) ++ LSS_INLINE _syscall4(long, ptrace, int, r, ++ pid_t, p, void *, a, void *, d) ++ LSS_INLINE _syscall3(ssize_t, read, int, f, ++ void *, b, size_t, c) ++ LSS_INLINE _syscall3(int, readlink, const char*, p, ++ char*, b, size_t, s) ++ LSS_INLINE _syscall4(int, rt_sigaction, int, s, ++ const struct kernel_sigaction*, a, ++ struct kernel_sigaction*, o, size_t, c) ++ LSS_INLINE _syscall2(int, rt_sigpending, struct kernel_sigset_t *, s, ++ size_t, c) ++ LSS_INLINE _syscall4(int, rt_sigprocmask, int, h, ++ const struct kernel_sigset_t*, s, ++ struct kernel_sigset_t*, o, size_t, c) ++ LSS_INLINE _syscall2(int, rt_sigsuspend, ++ const struct kernel_sigset_t*, s, size_t, c) ++ LSS_INLINE _syscall3(int, sched_getaffinity,pid_t, p, ++ unsigned int, l, unsigned long *, m) ++ LSS_INLINE _syscall3(int, sched_setaffinity,pid_t, p, ++ unsigned int, l, unsigned long *, m) ++ LSS_INLINE _syscall0(int, sched_yield) ++ LSS_INLINE _syscall1(long, set_tid_address, int *, t) ++ LSS_INLINE _syscall1(int, setfsgid, gid_t, g) ++ LSS_INLINE _syscall1(int, setfsuid, uid_t, u) ++ LSS_INLINE _syscall2(int, setpgid, pid_t, p, ++ pid_t, g) ++ LSS_INLINE _syscall3(int, setpriority, int, a, ++ int, b, int, p) ++ LSS_INLINE _syscall3(int, setresgid, gid_t, r, ++ gid_t, e, gid_t, s) ++ LSS_INLINE _syscall3(int, setresuid, uid_t, r, ++ uid_t, e, uid_t, s) ++ LSS_INLINE _syscall2(int, setrlimit, int, r, ++ const struct kernel_rlimit*, l) ++ LSS_INLINE _syscall0(pid_t, setsid) ++ LSS_INLINE _syscall2(int, sigaltstack, const stack_t*, s, ++ const stack_t*, o) ++ LSS_INLINE _syscall2(int, stat, const char*, f, ++ struct kernel_stat*, b) ++ LSS_INLINE _syscall2(int, statfs, const char*, f, ++ struct kernel_statfs*, b) ++ LSS_INLINE _syscall1(int, unlink, const char*, f) ++ LSS_INLINE _syscall3(ssize_t, write, int, f, ++ const void *, b, size_t, c) ++ LSS_INLINE _syscall3(ssize_t, writev, int, f, ++ const struct kernel_iovec*, v, size_t, c) ++ #if defined(__x86_64__) || \ ++ (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI32) ++ LSS_INLINE _syscall3(int, recvmsg, int, s, ++ struct kernel_msghdr*, m, int, f) ++ LSS_INLINE _syscall3(int, sendmsg, int, s, ++ const struct kernel_msghdr*, m, int, f) ++ LSS_INLINE _syscall6(int, sendto, int, s, ++ const void*, m, size_t, l, ++ int, f, ++ const struct kernel_sockaddr*, a, int, t) ++ LSS_INLINE _syscall2(int, shutdown, int, s, ++ int, h) ++ LSS_INLINE _syscall3(int, socket, int, d, ++ int, t, int, p) ++ LSS_INLINE _syscall4(int, socketpair, int, d, ++ int, t, int, p, int*, s) ++ #endif ++ #if defined(__x86_64__) ++ LSS_INLINE _syscall6(void*, mmap, void*, s, ++ size_t, l, int, p, ++ int, f, int, d, ++ __off64_t, o) ++ LSS_INLINE _syscall4(int, newfstatat, int, d, ++ const char *, p, ++ struct kernel_stat*, b, int, f) ++ ++ LSS_INLINE int LSS_NAME(setfsgid32)(gid_t gid) { ++ return LSS_NAME(setfsgid)(gid); ++ } ++ ++ LSS_INLINE int LSS_NAME(setfsuid32)(uid_t uid) { ++ return LSS_NAME(setfsuid)(uid); ++ } ++ ++ LSS_INLINE int LSS_NAME(setresgid32)(gid_t rgid, gid_t egid, gid_t sgid) { ++ return LSS_NAME(setresgid)(rgid, egid, sgid); ++ } ++ ++ LSS_INLINE int LSS_NAME(setresuid32)(uid_t ruid, uid_t euid, uid_t suid) { ++ return LSS_NAME(setresuid)(ruid, euid, suid); ++ } ++ ++ LSS_INLINE int LSS_NAME(sigaction)(int signum, ++ const struct kernel_sigaction *act, ++ struct kernel_sigaction *oldact) { ++ /* On x86_64, the kernel requires us to always set our own ++ * SA_RESTORER in order to be able to return from a signal handler. ++ * This function must have a "magic" signature that the "gdb" ++ * (and maybe the kernel?) can recognize. ++ */ ++ if (act != NULL && !(act->sa_flags & SA_RESTORER)) { ++ struct kernel_sigaction a = *act; ++ a.sa_flags |= SA_RESTORER; ++ a.sa_restorer = LSS_NAME(restore_rt)(); ++ return LSS_NAME(rt_sigaction)(signum, &a, oldact, ++ (KERNEL_NSIG+7)/8); ++ } else { ++ return LSS_NAME(rt_sigaction)(signum, act, oldact, ++ (KERNEL_NSIG+7)/8); ++ } ++ } ++ ++ LSS_INLINE int LSS_NAME(sigpending)(struct kernel_sigset_t *set) { ++ return LSS_NAME(rt_sigpending)(set, (KERNEL_NSIG+7)/8); ++ } ++ ++ LSS_INLINE int LSS_NAME(sigprocmask)(int how, ++ const struct kernel_sigset_t *set, ++ struct kernel_sigset_t *oldset) { ++ return LSS_NAME(rt_sigprocmask)(how, set, oldset, (KERNEL_NSIG+7)/8); ++ } ++ ++ LSS_INLINE int LSS_NAME(sigsuspend)(const struct kernel_sigset_t *set) { ++ return LSS_NAME(rt_sigsuspend)(set, (KERNEL_NSIG+7)/8); ++ } ++ #endif ++ #if defined(__x86_64__) || defined(__ARM_ARCH_3__) || \ ++ (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI32) ++ LSS_INLINE _syscall4(pid_t, wait4, pid_t, p, ++ int*, s, int, o, ++ struct kernel_rusage*, r) ++ ++ LSS_INLINE pid_t LSS_NAME(waitpid)(pid_t pid, int *status, int options){ ++ return LSS_NAME(wait4)(pid, status, options, 0); ++ } ++ #endif ++ #if defined(__i386__) || defined(__x86_64__) ++ LSS_INLINE _syscall4(int, openat, int, d, const char *, p, int, f, int, m) ++ LSS_INLINE _syscall3(int, unlinkat, int, d, const char *, p, int, f) ++ #endif ++ #if defined(__i386__) || defined(__ARM_ARCH_3__) ++ #define __NR__setfsgid32 __NR_setfsgid32 ++ #define __NR__setfsuid32 __NR_setfsuid32 ++ #define __NR__setresgid32 __NR_setresgid32 ++ #define __NR__setresuid32 __NR_setresuid32 ++ LSS_INLINE _syscall2(int, ugetrlimit, int, r, ++ struct kernel_rlimit*, l) ++ LSS_INLINE _syscall1(int, _setfsgid32, gid_t, f) ++ LSS_INLINE _syscall1(int, _setfsuid32, uid_t, f) ++ LSS_INLINE _syscall3(int, _setresgid32, gid_t, r, ++ gid_t, e, gid_t, s) ++ LSS_INLINE _syscall3(int, _setresuid32, uid_t, r, ++ uid_t, e, uid_t, s) ++ ++ LSS_INLINE int LSS_NAME(setfsgid32)(gid_t gid) { ++ int rc; ++ if ((rc = LSS_NAME(_setfsgid32)(gid)) < 0 && ++ LSS_ERRNO == ENOSYS) { ++ if ((unsigned int)gid & ~0xFFFFu) { ++ rc = EINVAL; ++ } else { ++ rc = LSS_NAME(setfsgid)(gid); ++ } ++ } ++ return rc; ++ } ++ ++ LSS_INLINE int LSS_NAME(setfsuid32)(uid_t uid) { ++ int rc; ++ if ((rc = LSS_NAME(_setfsuid32)(uid)) < 0 && ++ LSS_ERRNO == ENOSYS) { ++ if ((unsigned int)uid & ~0xFFFFu) { ++ rc = EINVAL; ++ } else { ++ rc = LSS_NAME(setfsuid)(uid); ++ } ++ } ++ return rc; ++ } ++ ++ LSS_INLINE int LSS_NAME(setresgid32)(gid_t rgid, gid_t egid, gid_t sgid) { ++ int rc; ++ if ((rc = LSS_NAME(_setresgid32)(rgid, egid, sgid)) < 0 && ++ LSS_ERRNO == ENOSYS) { ++ if ((unsigned int)rgid & ~0xFFFFu || ++ (unsigned int)egid & ~0xFFFFu || ++ (unsigned int)sgid & ~0xFFFFu) { ++ rc = EINVAL; ++ } else { ++ rc = LSS_NAME(setresgid)(rgid, egid, sgid); ++ } ++ } ++ return rc; ++ } ++ ++ LSS_INLINE int LSS_NAME(setresuid32)(uid_t ruid, uid_t euid, uid_t suid) { ++ int rc; ++ if ((rc = LSS_NAME(_setresuid32)(ruid, euid, suid)) < 0 && ++ LSS_ERRNO == ENOSYS) { ++ if ((unsigned int)ruid & ~0xFFFFu || ++ (unsigned int)euid & ~0xFFFFu || ++ (unsigned int)suid & ~0xFFFFu) { ++ rc = EINVAL; ++ } else { ++ rc = LSS_NAME(setresuid)(ruid, euid, suid); ++ } ++ } ++ return rc; ++ } ++ #endif ++ LSS_INLINE int LSS_NAME(sigemptyset)(struct kernel_sigset_t *set) { ++ memset(&set->sig, 0, sizeof(set->sig)); ++ return 0; ++ } ++ ++ LSS_INLINE int LSS_NAME(sigfillset)(struct kernel_sigset_t *set) { ++ memset(&set->sig, -1, sizeof(set->sig)); ++ return 0; ++ } ++ ++ LSS_INLINE int LSS_NAME(sigaddset)(struct kernel_sigset_t *set, ++ int signum) { ++ if (signum < 1 || signum > (int)(8*sizeof(set->sig))) { ++ LSS_ERRNO = EINVAL; ++ return -1; ++ } else { ++ set->sig[(signum - 1)/(8*sizeof(set->sig[0]))] ++ |= 1UL << ((signum - 1) % (8*sizeof(set->sig[0]))); ++ return 0; ++ } ++ } ++ ++ LSS_INLINE int LSS_NAME(sigdelset)(struct kernel_sigset_t *set, ++ int signum) { ++ if (signum < 1 || signum > (int)(8*sizeof(set->sig))) { ++ LSS_ERRNO = EINVAL; ++ return -1; ++ } else { ++ set->sig[(signum - 1)/(8*sizeof(set->sig[0]))] ++ &= ~(1UL << ((signum - 1) % (8*sizeof(set->sig[0])))); ++ return 0; ++ } ++ } ++ ++ LSS_INLINE int LSS_NAME(sigismember)(struct kernel_sigset_t *set, ++ int signum) { ++ if (signum < 1 || signum > (int)(8*sizeof(set->sig))) { ++ LSS_ERRNO = EINVAL; ++ return -1; ++ } else { ++ return !!(set->sig[(signum - 1)/(8*sizeof(set->sig[0]))] & ++ (1UL << ((signum - 1) % (8*sizeof(set->sig[0]))))); ++ } ++ } ++ #if defined(__i386__) || defined(__ARM_ARCH_3__) || \ ++ (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || defined(__PPC__) ++ #define __NR__sigaction __NR_sigaction ++ #define __NR__sigpending __NR_sigpending ++ #define __NR__sigprocmask __NR_sigprocmask ++ #define __NR__sigsuspend __NR_sigsuspend ++ #define __NR__socketcall __NR_socketcall ++ LSS_INLINE _syscall2(int, fstat64, int, f, ++ struct kernel_stat64 *, b) ++ LSS_INLINE _syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, ++ loff_t *, res, uint, wh) ++ LSS_INLINE _syscall1(void*, mmap, void*, a) ++ LSS_INLINE _syscall6(void*, mmap2, void*, s, ++ size_t, l, int, p, ++ int, f, int, d, ++ __off64_t, o) ++ LSS_INLINE _syscall3(int, _sigaction, int, s, ++ const struct kernel_old_sigaction*, a, ++ struct kernel_old_sigaction*, o) ++ LSS_INLINE _syscall1(int, _sigpending, unsigned long*, s) ++ LSS_INLINE _syscall3(int, _sigprocmask, int, h, ++ const unsigned long*, s, ++ unsigned long*, o) ++ #ifdef __PPC__ ++ LSS_INLINE _syscall1(int, _sigsuspend, unsigned long, s) ++ #else ++ LSS_INLINE _syscall3(int, _sigsuspend, const void*, a, ++ int, b, ++ unsigned long, s) ++ #endif ++ LSS_INLINE _syscall2(int, stat64, const char *, p, ++ struct kernel_stat64 *, b) ++ ++ LSS_INLINE int LSS_NAME(sigaction)(int signum, ++ const struct kernel_sigaction *act, ++ struct kernel_sigaction *oldact) { ++ int old_errno = LSS_ERRNO; ++ int rc; ++ struct kernel_sigaction a; ++ if (act != NULL) { ++ a = *act; ++ #ifdef __i386__ ++ /* On i386, the kernel requires us to always set our own ++ * SA_RESTORER when using realtime signals. Otherwise, it does not ++ * know how to return from a signal handler. This function must have ++ * a "magic" signature that the "gdb" (and maybe the kernel?) can ++ * recognize. ++ * Apparently, a SA_RESTORER is implicitly set by the kernel, when ++ * using non-realtime signals. ++ * ++ * TODO: Test whether ARM needs a restorer ++ */ ++ if (!(a.sa_flags & SA_RESTORER)) { ++ a.sa_flags |= SA_RESTORER; ++ a.sa_restorer = (a.sa_flags & SA_SIGINFO) ++ ? LSS_NAME(restore_rt)() : LSS_NAME(restore)(); ++ } ++ #endif ++ } ++ rc = LSS_NAME(rt_sigaction)(signum, act ? &a : act, oldact, ++ (KERNEL_NSIG+7)/8); ++ if (rc < 0 && LSS_ERRNO == ENOSYS) { ++ struct kernel_old_sigaction oa, ooa, *ptr_a = &oa, *ptr_oa = &ooa; ++ if (!act) { ++ ptr_a = NULL; ++ } else { ++ oa.sa_handler_ = act->sa_handler_; ++ memcpy(&oa.sa_mask, &act->sa_mask, sizeof(oa.sa_mask)); ++ #ifndef __mips__ ++ oa.sa_restorer = act->sa_restorer; ++ #endif ++ oa.sa_flags = act->sa_flags; ++ } ++ if (!oldact) { ++ ptr_oa = NULL; ++ } ++ LSS_ERRNO = old_errno; ++ rc = LSS_NAME(_sigaction)(signum, ptr_a, ptr_oa); ++ if (rc == 0 && oldact) { ++ if (act) { ++ memcpy(oldact, act, sizeof(*act)); ++ } else { ++ memset(oldact, 0, sizeof(*oldact)); ++ } ++ oldact->sa_handler_ = ptr_oa->sa_handler_; ++ oldact->sa_flags = ptr_oa->sa_flags; ++ memcpy(&oldact->sa_mask, &ptr_oa->sa_mask, sizeof(ptr_oa->sa_mask)); ++ #ifndef __mips__ ++ oldact->sa_restorer = ptr_oa->sa_restorer; ++ #endif ++ } ++ } ++ return rc; ++ } ++ ++ LSS_INLINE int LSS_NAME(sigpending)(struct kernel_sigset_t *set) { ++ int old_errno = LSS_ERRNO; ++ int rc = LSS_NAME(rt_sigpending)(set, (KERNEL_NSIG+7)/8); ++ if (rc < 0 && LSS_ERRNO == ENOSYS) { ++ LSS_ERRNO = old_errno; ++ LSS_NAME(sigemptyset)(set); ++ rc = LSS_NAME(_sigpending)(&set->sig[0]); ++ } ++ return rc; ++ } ++ ++ LSS_INLINE int LSS_NAME(sigprocmask)(int how, ++ const struct kernel_sigset_t *set, ++ struct kernel_sigset_t *oldset) { ++ int olderrno = LSS_ERRNO; ++ int rc = LSS_NAME(rt_sigprocmask)(how, set, oldset, (KERNEL_NSIG+7)/8); ++ if (rc < 0 && LSS_ERRNO == ENOSYS) { ++ LSS_ERRNO = olderrno; ++ if (oldset) { ++ LSS_NAME(sigemptyset)(oldset); ++ } ++ rc = LSS_NAME(_sigprocmask)(how, ++ set ? &set->sig[0] : NULL, ++ oldset ? &oldset->sig[0] : NULL); ++ } ++ return rc; ++ } ++ ++ LSS_INLINE int LSS_NAME(sigsuspend)(const struct kernel_sigset_t *set) { ++ int olderrno = LSS_ERRNO; ++ int rc = LSS_NAME(rt_sigsuspend)(set, (KERNEL_NSIG+7)/8); ++ if (rc < 0 && LSS_ERRNO == ENOSYS) { ++ LSS_ERRNO = olderrno; ++ rc = LSS_NAME(_sigsuspend)( ++ #ifndef __PPC__ ++ set, 0, ++ #endif ++ set->sig[0]); ++ } ++ return rc; ++ } ++ #endif ++ #if defined(__PPC__) ++ #undef LSS_SC_LOADARGS_0 ++ #define LSS_SC_LOADARGS_0(dummy...) ++ #undef LSS_SC_LOADARGS_1 ++ #define LSS_SC_LOADARGS_1(arg1) \ ++ __sc_4 = (unsigned long) (arg1) ++ #undef LSS_SC_LOADARGS_2 ++ #define LSS_SC_LOADARGS_2(arg1, arg2) \ ++ LSS_SC_LOADARGS_1(arg1); \ ++ __sc_5 = (unsigned long) (arg2) ++ #undef LSS_SC_LOADARGS_3 ++ #define LSS_SC_LOADARGS_3(arg1, arg2, arg3) \ ++ LSS_SC_LOADARGS_2(arg1, arg2); \ ++ __sc_6 = (unsigned long) (arg3) ++ #undef LSS_SC_LOADARGS_4 ++ #define LSS_SC_LOADARGS_4(arg1, arg2, arg3, arg4) \ ++ LSS_SC_LOADARGS_3(arg1, arg2, arg3); \ ++ __sc_7 = (unsigned long) (arg4) ++ #undef LSS_SC_LOADARGS_5 ++ #define LSS_SC_LOADARGS_5(arg1, arg2, arg3, arg4, arg5) \ ++ LSS_SC_LOADARGS_4(arg1, arg2, arg3, arg4); \ ++ __sc_8 = (unsigned long) (arg5) ++ #undef LSS_SC_BODY ++ #define LSS_SC_BODY(nr, type, opt, args...) \ ++ long __sc_ret, __sc_err; \ ++ { \ ++ register unsigned long __sc_0 __asm__ ("r0") = __NR_socketcall; \ ++ register unsigned long __sc_3 __asm__ ("r3") = opt; \ ++ register unsigned long __sc_4 __asm__ ("r4"); \ ++ register unsigned long __sc_5 __asm__ ("r5"); \ ++ register unsigned long __sc_6 __asm__ ("r6"); \ ++ register unsigned long __sc_7 __asm__ ("r7"); \ ++ register unsigned long __sc_8 __asm__ ("r8"); \ ++ LSS_SC_LOADARGS_##nr(args); \ ++ __asm__ __volatile__ \ ++ ("stwu 1, -48(1)\n\t" \ ++ "stw 4, 20(1)\n\t" \ ++ "stw 5, 24(1)\n\t" \ ++ "stw 6, 28(1)\n\t" \ ++ "stw 7, 32(1)\n\t" \ ++ "stw 8, 36(1)\n\t" \ ++ "addi 4, 1, 20\n\t" \ ++ "sc\n\t" \ ++ "mfcr %0" \ ++ : "=&r" (__sc_0), \ ++ "=&r" (__sc_3), "=&r" (__sc_4), \ ++ "=&r" (__sc_5), "=&r" (__sc_6), \ ++ "=&r" (__sc_7), "=&r" (__sc_8) \ ++ : LSS_ASMINPUT_##nr \ ++ : "cr0", "ctr", "memory"); \ ++ __sc_ret = __sc_3; \ ++ __sc_err = __sc_0; \ ++ } \ ++ LSS_RETURN(type, __sc_ret, __sc_err) ++ ++ LSS_INLINE ssize_t LSS_NAME(recvmsg)(int s,struct kernel_msghdr *msg, ++ int flags){ ++ LSS_SC_BODY(3, ssize_t, 17, s, msg, flags); ++ } ++ ++ LSS_INLINE ssize_t LSS_NAME(sendmsg)(int s, ++ const struct kernel_msghdr *msg, ++ int flags) { ++ LSS_SC_BODY(3, ssize_t, 16, s, msg, flags); ++ } ++ ++ // TODO(csilvers): why is this ifdef'ed out? ++#if 0 ++ LSS_INLINE ssize_t LSS_NAME(sendto)(int s, const void *buf, size_t len, ++ int flags, ++ const struct kernel_sockaddr *to, ++ unsigned int tolen) { ++ LSS_BODY(6, ssize_t, 11, s, buf, len, flags, to, tolen); ++ } ++#endif ++ ++ LSS_INLINE int LSS_NAME(shutdown)(int s, int how) { ++ LSS_SC_BODY(2, int, 13, s, how); ++ } ++ ++ LSS_INLINE int LSS_NAME(socket)(int domain, int type, int protocol) { ++ LSS_SC_BODY(3, int, 1, domain, type, protocol); ++ } ++ ++ LSS_INLINE int LSS_NAME(socketpair)(int d, int type, int protocol, ++ int sv[2]) { ++ LSS_SC_BODY(4, int, 8, d, type, protocol, sv); ++ } ++ #endif ++ #if defined(__i386__) || defined(__ARM_ARCH_3__) || \ ++ (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) ++ #define __NR__socketcall __NR_socketcall ++ LSS_INLINE _syscall2(int, _socketcall, int, c, ++ va_list, a) ++ ++ LSS_INLINE int LSS_NAME(socketcall)(int op, ...) { ++ int rc; ++ va_list ap; ++ va_start(ap, op); ++ rc = LSS_NAME(_socketcall)(op, ap); ++ va_end(ap); ++ return rc; ++ } ++ ++ LSS_INLINE ssize_t LSS_NAME(recvmsg)(int s,struct kernel_msghdr *msg, ++ int flags){ ++ return (ssize_t)LSS_NAME(socketcall)(17, s, msg, flags); ++ } ++ ++ LSS_INLINE ssize_t LSS_NAME(sendmsg)(int s, ++ const struct kernel_msghdr *msg, ++ int flags) { ++ return (ssize_t)LSS_NAME(socketcall)(16, s, msg, flags); ++ } ++ ++ LSS_INLINE ssize_t LSS_NAME(sendto)(int s, const void *buf, size_t len, ++ int flags, ++ const struct kernel_sockaddr *to, ++ unsigned int tolen) { ++ return (ssize_t)LSS_NAME(socketcall)(11, s, buf, len, flags, to, tolen); ++ } ++ ++ LSS_INLINE int LSS_NAME(shutdown)(int s, int how) { ++ return LSS_NAME(socketcall)(13, s, how); ++ } ++ ++ LSS_INLINE int LSS_NAME(socket)(int domain, int type, int protocol) { ++ return LSS_NAME(socketcall)(1, domain, type, protocol); ++ } ++ ++ LSS_INLINE int LSS_NAME(socketpair)(int d, int type, int protocol, ++ int sv[2]) { ++ return LSS_NAME(socketcall)(8, d, type, protocol, sv); ++ } ++ #endif ++ #if defined(__i386__) || defined(__PPC__) ++ LSS_INLINE _syscall4(int, fstatat64, int, d, ++ const char *, p, ++ struct kernel_stat64 *, b, int, f) ++ #endif ++ #if defined(__i386__) || defined(__PPC__) || \ ++ (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) ++ LSS_INLINE _syscall3(pid_t, waitpid, pid_t, p, ++ int*, s, int, o) ++ #endif ++ #if defined(__mips__) ++ /* sys_pipe() on MIPS has non-standard calling conventions, as it returns ++ * both file handles through CPU registers. ++ */ ++ LSS_INLINE int LSS_NAME(pipe)(int *p) { ++ register unsigned long __v0 __asm__("$2") = __NR_pipe; ++ register unsigned long __v1 __asm__("$3"); ++ register unsigned long __r7 __asm__("$7"); ++ __asm__ __volatile__ ("syscall\n" ++ : "=&r"(__v0), "=&r"(__v1), "+r" (__r7) ++ : "0"(__v0) ++ : "$8", "$9", "$10", "$11", "$12", ++ "$13", "$14", "$15", "$24", "memory"); ++ if (__r7) { ++ LSS_ERRNO = __v0; ++ return -1; ++ } else { ++ p[0] = __v0; ++ p[1] = __v1; ++ return 0; ++ } ++ } ++ #else ++ LSS_INLINE _syscall1(int, pipe, int *, p) ++ #endif ++ /* TODO(csilvers): see if ppc can/should support this as well */ ++ #if defined(__i386__) || defined(__ARM_ARCH_3__) || \ ++ (defined(__mips__) && _MIPS_SIM != _MIPS_SIM_ABI64) ++ #define __NR__statfs64 __NR_statfs64 ++ #define __NR__fstatfs64 __NR_fstatfs64 ++ LSS_INLINE _syscall3(int, _statfs64, const char*, p, ++ size_t, s,struct kernel_statfs64*, b) ++ LSS_INLINE _syscall3(int, _fstatfs64, int, f, ++ size_t, s,struct kernel_statfs64*, b) ++ LSS_INLINE int LSS_NAME(statfs64)(const char *p, ++ struct kernel_statfs64 *b) { ++ return LSS_NAME(_statfs64)(p, sizeof(*b), b); ++ } ++ LSS_INLINE int LSS_NAME(fstatfs64)(int f,struct kernel_statfs64 *b) { ++ return LSS_NAME(_fstatfs64)(f, sizeof(*b), b); ++ } ++ #endif ++ ++ LSS_INLINE int LSS_NAME(execv)(const char *path, const char *const argv[]) { ++ extern char **environ; ++ return LSS_NAME(execve)(path, argv, (const char *const *)environ); ++ } ++ ++ LSS_INLINE pid_t LSS_NAME(gettid)() { ++ pid_t tid = LSS_NAME(_gettid)(); ++ if (tid != -1) { ++ return tid; ++ } ++ return LSS_NAME(getpid)(); ++ } ++ ++ LSS_INLINE void *LSS_NAME(mremap)(void *old_address, size_t old_size, ++ size_t new_size, int flags, ...) { ++ va_list ap; ++ void *new_address, *rc; ++ va_start(ap, flags); ++ new_address = va_arg(ap, void *); ++ rc = LSS_NAME(_mremap)(old_address, old_size, new_size, ++ flags, new_address); ++ va_end(ap); ++ return rc; ++ } ++ ++ LSS_INLINE int LSS_NAME(ptrace_detach)(pid_t pid) { ++ /* PTRACE_DETACH can sometimes forget to wake up the tracee and it ++ * then sends job control signals to the real parent, rather than to ++ * the tracer. We reduce the risk of this happening by starting a ++ * whole new time slice, and then quickly sending a SIGCONT signal ++ * right after detaching from the tracee. ++ */ ++ int rc, err; ++ LSS_NAME(sched_yield)(); ++ rc = LSS_NAME(ptrace)(PTRACE_DETACH, pid, (void *)0, (void *)0); ++ err = LSS_ERRNO; ++ LSS_NAME(kill)(pid, SIGCONT); ++ LSS_ERRNO = err; ++ return rc; ++ } ++ ++ LSS_INLINE int LSS_NAME(raise)(int sig) { ++ return LSS_NAME(kill)(LSS_NAME(getpid)(), sig); ++ } ++ ++ LSS_INLINE int LSS_NAME(setpgrp)() { ++ return LSS_NAME(setpgid)(0, 0); ++ } ++ ++ LSS_INLINE int LSS_NAME(sysconf)(int name) { ++ extern int __getpagesize(void); ++ switch (name) { ++ case _SC_OPEN_MAX: { ++ struct kernel_rlimit limit; ++ return LSS_NAME(getrlimit)(RLIMIT_NOFILE, &limit) < 0 ++ ? 8192 : limit.rlim_cur; ++ } ++ case _SC_PAGESIZE: ++ return __getpagesize(); ++ default: ++ errno = ENOSYS; ++ return -1; ++ } ++ } ++ #if defined(__x86_64__) || \ ++ (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI64) ++ /* pread64() and pwrite64() do not exist on 64-bit systems... */ ++ LSS_INLINE _syscall3(int, readahead, int, f, ++ loff_t, o, unsigned, c) ++ #else ++ #define __NR__pread64 __NR_pread64 ++ #define __NR__pwrite64 __NR_pwrite64 ++ #define __NR__readahead __NR_readahead ++ LSS_INLINE _syscall5(ssize_t, _pread64, int, f, ++ void *, b, size_t, c, unsigned, o1, ++ unsigned, o2) ++ LSS_INLINE _syscall5(ssize_t, _pwrite64, int, f, ++ const void *, b, size_t, c, unsigned, o1, ++ long, o2) ++ LSS_INLINE _syscall4(int, _readahead, int, f, ++ unsigned, o1, unsigned, o2, size_t, c) ++ /* We force 64bit-wide parameters onto the stack, then access each ++ * 32-bit component individually. This guarantees that we build the ++ * correct parameters independent of the native byte-order of the ++ * underlying architecture. ++ */ ++ LSS_INLINE ssize_t LSS_NAME(pread64)(int fd, void *buf, size_t count, ++ loff_t off) { ++ union { loff_t off; unsigned arg[2]; } o = { off }; ++ return LSS_NAME(_pread64)(fd, buf, count, o.arg[0], o.arg[1]); ++ } ++ LSS_INLINE ssize_t LSS_NAME(pwrite64)(int fd, const void *buf, ++ size_t count, loff_t off) { ++ union { loff_t off; unsigned arg[2]; } o = { off }; ++ return LSS_NAME(_pwrite64)(fd, buf, count, o.arg[0], o.arg[1]); ++ } ++ LSS_INLINE int LSS_NAME(readahead)(int fd, loff_t off, int len) { ++ union { loff_t off; unsigned arg[2]; } o = { off }; ++ return LSS_NAME(_readahead)(fd, o.arg[0], o.arg[1], len); ++ } ++ #endif ++#endif ++ ++#if defined(__cplusplus) && !defined(SYS_CPLUSPLUS) ++} ++#endif ++ ++#endif ++#endif +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/memory.h b/toolkit/crashreporter/google-breakpad/src/common/linux/memory.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/memory.h +@@ -0,0 +1,181 @@ ++// Copyright (c) 2009, 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 CLIENT_LINUX_HANDLER_MEMORY_H_ ++#define CLIENT_LINUX_HANDLER_MEMORY_H_ ++ ++#include ++#include ++#include ++#include ++ ++#include "common/linux/linux_syscall_support.h" ++ ++namespace google_breakpad { ++ ++// This is very simple allocator which fetches pages from the kernel directly. ++// Thus, it can be used even when the heap may be corrupted. ++// ++// There is no free operation. The pages are only freed when the object is ++// destroyed. ++class PageAllocator { ++ public: ++ PageAllocator() ++ : page_size_(getpagesize()), ++ last_(NULL), ++ current_page_(NULL), ++ page_offset_(0) { ++ } ++ ++ ~PageAllocator() { ++ FreeAll(); ++ } ++ ++ void *Alloc(unsigned bytes) { ++ if (!bytes) ++ return NULL; ++ ++ if (current_page_ && page_size_ - page_offset_ >= bytes) { ++ uint8_t *const ret = current_page_ + page_offset_; ++ page_offset_ += bytes; ++ if (page_offset_ == page_size_) { ++ page_offset_ = 0; ++ current_page_ = NULL; ++ } ++ ++ return ret; ++ } ++ ++ const unsigned pages = ++ (bytes + sizeof(PageHeader) + page_size_ - 1) / page_size_; ++ uint8_t *const ret = GetNPages(pages); ++ if (!ret) ++ return NULL; ++ ++ page_offset_ = (page_size_ - (page_size_ * pages - (bytes + sizeof(PageHeader)))) % page_size_; ++ current_page_ = page_offset_ ? ret + page_size_ * (pages - 1) : NULL; ++ ++ return ret + sizeof(PageHeader); ++ } ++ ++ private: ++ uint8_t *GetNPages(unsigned num_pages) { ++#ifdef __x86_64 ++ void *a = sys_mmap(NULL, page_size_ * num_pages, PROT_READ | PROT_WRITE, ++ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ++#else ++ void *a = sys_mmap2(NULL, page_size_ * num_pages, PROT_READ | PROT_WRITE, ++ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ++#endif ++ if (a == MAP_FAILED) ++ return NULL; ++ ++ struct PageHeader *header = reinterpret_cast(a); ++ header->next = last_; ++ header->num_pages = num_pages; ++ last_ = header; ++ ++ return reinterpret_cast(a); ++ } ++ ++ void FreeAll() { ++ PageHeader *next; ++ ++ for (PageHeader *cur = last_; cur; cur = next) { ++ next = cur->next; ++ sys_munmap(cur, cur->num_pages * page_size_); ++ } ++ } ++ ++ struct PageHeader { ++ PageHeader *next; // pointer to the start of the next set of pages. ++ unsigned num_pages; // the number of pages in this set. ++ }; ++ ++ const unsigned page_size_; ++ PageHeader *last_; ++ uint8_t *current_page_; ++ unsigned page_offset_; ++}; ++ ++// A wasteful vector is like a normal std::vector, except that it's very much ++// simplier and it allocates memory from a PageAllocator. It's wasteful ++// because, when resizing, it always allocates a whole new array since the ++// PageAllocator doesn't support realloc. ++template ++class wasteful_vector { ++ public: ++ wasteful_vector(PageAllocator *allocator, unsigned size_hint = 16) ++ : allocator_(allocator), ++ a_((T*) allocator->Alloc(sizeof(T) * size_hint)), ++ allocated_(size_hint), ++ used_(0) { ++ } ++ ++ void push_back(const T& new_element) { ++ if (used_ == allocated_) ++ Realloc(allocated_ * 2); ++ a_[used_++] = new_element; ++ } ++ ++ size_t size() const { ++ return used_; ++ } ++ ++ T& operator[](size_t index) { ++ return a_[index]; ++ } ++ ++ const T& operator[](size_t index) const { ++ return a_[index]; ++ } ++ ++ private: ++ void Realloc(unsigned new_size) { ++ T *new_array = ++ reinterpret_cast(allocator_->Alloc(sizeof(T) * new_size)); ++ memcpy(new_array, a_, used_ * sizeof(T)); ++ a_ = new_array; ++ allocated_ = new_size; ++ } ++ ++ PageAllocator *const allocator_; ++ T *a_; // pointer to an array of |allocated_| elements. ++ unsigned allocated_; // size of |a_|, in elements. ++ unsigned used_; // number of used slots in |a_|. ++}; ++ ++} // namespace google_breakpad ++ ++inline void* operator new(size_t nbytes, ++ google_breakpad::PageAllocator& allocator) { ++ return allocator.Alloc(nbytes); ++} ++ ++#endif // CLIENT_LINUX_HANDLER_MEMORY_H_ +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/memory_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/memory_unittest.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/memory_unittest.cc +@@ -0,0 +1,84 @@ ++// Copyright (c) 2009, 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 "common/linux/memory.h" ++#include "testing/gtest/include/gtest/gtest.h" ++ ++using namespace google_breakpad; ++ ++namespace { ++typedef testing::Test PageAllocatorTest; ++} ++ ++TEST(PageAllocatorTest, Setup) { ++ PageAllocator allocator; ++} ++ ++TEST(PageAllocatorTest, SmallObjects) { ++ PageAllocator allocator; ++ ++ for (unsigned i = 1; i < 1024; ++i) { ++ uint8_t *p = reinterpret_cast(allocator.Alloc(i)); ++ ASSERT_FALSE(p == NULL); ++ memset(p, 0, i); ++ } ++} ++ ++TEST(PageAllocatorTest, LargeObject) { ++ PageAllocator allocator; ++ ++ uint8_t *p = reinterpret_cast(allocator.Alloc(10000)); ++ ASSERT_FALSE(p == NULL); ++ for (unsigned i = 1; i < 10; ++i) { ++ uint8_t *p = reinterpret_cast(allocator.Alloc(i)); ++ ASSERT_FALSE(p == NULL); ++ memset(p, 0, i); ++ } ++} ++ ++namespace { ++typedef testing::Test WastefulVectorTest; ++} ++ ++TEST(WastefulVectorTest, Setup) { ++ PageAllocator allocator_; ++ wasteful_vector v(&allocator_); ++ ASSERT_EQ(v.size(), 0u); ++} ++ ++TEST(WastefulVectorTest, Simple) { ++ PageAllocator allocator_; ++ wasteful_vector v(&allocator_); ++ ++ for (unsigned i = 0; i < 256; ++i) ++ v.push_back(i); ++ ASSERT_EQ(v.size(), 256u); ++ for (unsigned i = 0; i < 256; ++i) ++ ASSERT_EQ(v[i], i); ++} +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/module.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/module.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/module.cc +@@ -0,0 +1,167 @@ ++// Copyright (c) 2009, 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 ++#include ++#include "common/linux/module.h" ++ ++namespace google_breakpad { ++ ++Module::Module(const string &name, const string &os, ++ const string &architecture, const string &id) : ++ name_(name), ++ os_(os), ++ architecture_(architecture), ++ id_(id), ++ load_address_(0) { } ++ ++Module::~Module() { ++ for (FileByNameMap::iterator it = files_.begin(); it != files_.end(); it++) ++ delete it->second; ++ for (vector::iterator it = functions_.begin(); ++ it != functions_.end(); it++) ++ delete *it; ++} ++ ++void Module::SetLoadAddress(Address address) { ++ load_address_ = address; ++} ++ ++void Module::AddFunction(Function *function) { ++ functions_.push_back(function); ++} ++ ++void Module::AddFunctions(vector::iterator begin, ++ vector::iterator end) { ++ functions_.insert(functions_.end(), begin, end); ++} ++ ++Module::File *Module::FindFile(const string &name) { ++ // A tricky bit here. The key of each map entry needs to be a ++ // pointer to the entry's File's name string. This means that we ++ // can't do the initial lookup with any operation that would create ++ // an empty entry for us if the name isn't found (like, say, ++ // operator[] or insert do), because such a created entry's key will ++ // be a pointer the string passed as our argument. Since the key of ++ // a map's value type is const, we can't fix it up once we've ++ // created our file. lower_bound does the lookup without doing an ++ // insertion, and returns a good hint iterator to pass to insert. ++ // Our "destiny" is where we belong, whether we're there or not now. ++ FileByNameMap::iterator destiny = files_.lower_bound(&name); ++ if (destiny == files_.end() ++ || *destiny->first != name) { // Repeated string comparison, boo hoo. ++ File *file = new File; ++ file->name_ = name; ++ file->source_id_ = -1; ++ destiny = files_.insert(destiny, ++ FileByNameMap::value_type(&file->name_, file)); ++ } ++ return destiny->second; ++} ++ ++Module::File *Module::FindFile(const char *name) { ++ string name_string = name; ++ return FindFile(name_string); ++} ++ ++void Module::AssignSourceIds() { ++ // First, give every source file an id of -1. ++ for (FileByNameMap::iterator file_it = files_.begin(); ++ file_it != files_.end(); file_it++) ++ file_it->second->source_id_ = -1; ++ ++ // Next, mark all files actually cited by our functions' line number ++ // info, by setting each one's source id to zero. ++ for (vector::const_iterator func_it = functions_.begin(); ++ func_it != functions_.end(); func_it++) { ++ Function *func = *func_it; ++ for (vector::iterator line_it = func->lines_.begin(); ++ line_it != func->lines_.end(); line_it++) ++ line_it->file_->source_id_ = 0; ++ } ++ ++ // Finally, assign source ids to those files that have been marked. ++ // We could have just assigned source id numbers while traversing ++ // the line numbers, but doing it this way numbers the files in ++ // lexicographical order by name, which is neat. ++ int next_source_id = 0; ++ for (FileByNameMap::iterator file_it = files_.begin(); ++ file_it != files_.end(); file_it++) ++ if (! file_it->second->source_id_) ++ file_it->second->source_id_ = next_source_id++; ++} ++ ++bool Module::ReportError() { ++ fprintf(stderr, "error writing symbol file: %s\n", ++ strerror (errno)); ++ return false; ++} ++ ++bool Module::Write(FILE *stream) { ++ if (0 > fprintf(stream, "MODULE %s %s %s %s\n", ++ os_.c_str(), architecture_.c_str(), id_.c_str(), ++ name_.c_str())) ++ return ReportError(); ++ ++ // Write out files. ++ AssignSourceIds(); ++ for (FileByNameMap::iterator file_it = files_.begin(); ++ file_it != files_.end(); file_it++) { ++ File *file = file_it->second; ++ if (file->source_id_ >= 0) { ++ if (0 > fprintf(stream, "FILE %d %s\n", ++ file->source_id_, file->name_.c_str())) ++ return ReportError(); ++ } ++ } ++ ++ // Write out functions and their lines. ++ for (vector::const_iterator func_it = functions_.begin(); ++ func_it != functions_.end(); func_it++) { ++ Function *func = *func_it; ++ if (0 > fprintf(stream, "FUNC %lx %lx %lu %s\n", ++ (unsigned long) (func->address_ - load_address_), ++ (unsigned long) func->size_, ++ (unsigned long) func->parameter_size_, ++ func->name_.c_str())) ++ return ReportError(); ++ for (vector::iterator line_it = func->lines_.begin(); ++ line_it != func->lines_.end(); line_it++) ++ if (0 > fprintf(stream, "%lx %lx %d %d\n", ++ (unsigned long) (line_it->address_ - load_address_), ++ (unsigned long) line_it->size_, ++ line_it->number_, ++ line_it->file_->source_id_)) ++ return ReportError(); ++ } ++ ++ return true; ++} ++ ++} // namespace google_breakpad +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/module.h b/toolkit/crashreporter/google-breakpad/src/common/linux/module.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/module.h +@@ -0,0 +1,193 @@ ++// Copyright (c) 2009, Google Inc. -*- mode: c++ -*- ++// 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. ++ ++// module.h: defines google_breakpad::Module, for writing breakpad symbol files ++ ++#ifndef COMMON_LINUX_MODULE_H__ ++#define COMMON_LINUX_MODULE_H__ ++ ++#include ++#include ++#include ++#include ++ ++#include "google_breakpad/common/breakpad_types.h" ++ ++namespace google_breakpad { ++ ++using std::string; ++using std::vector; ++using std::map; ++ ++// A Module represents the contents of a module, and supports methods ++// for adding information produced by parsing STABS or DWARF data ++// --- possibly both from the same file --- and then writing out the ++// unified contents as a Breakpad-format symbol file. ++class Module { ++ public: ++ // The type of addresses and sizes in a symbol table. ++ typedef u_int64_t Address; ++ struct File; ++ struct Function; ++ struct Line; ++ ++ // Addresses appearing in File, Function, and Line structures are ++ // absolute, not relative to the the module's load address. That ++ // is, if the module were loaded at its nominal load address, the ++ // addresses would be correct. ++ ++ // A source file. ++ struct File { ++ // The name of the source file. ++ string name_; ++ ++ // The file's source id. The Write member function clears this ++ // field and assigns source ids a fresh, so any value placed here ++ // before calling Write will be lost. ++ int source_id_; ++ }; ++ ++ // A function. ++ struct Function { ++ // For sorting by address. (Not style-guide compliant, but it's ++ // stupid not to put this in the struct.) ++ static bool CompareByAddress(const Function *x, const Function *y) { ++ return x->address_ < y->address_; ++ } ++ ++ // The function's name. ++ string name_; ++ ++ // The start address and length of the function's code. ++ Address address_, size_; ++ ++ // The function's parameter size. ++ Address parameter_size_; ++ ++ // Source lines belonging to this function, sorted by increasing ++ // address. ++ vector lines_; ++ }; ++ ++ // A source line. ++ struct Line { ++ // For sorting by address. (Not style-guide compliant, but it's ++ // stupid not to put this in the struct.) ++ static bool CompareByAddress(const Module::Line &x, const Module::Line &y) { ++ return x.address_ < y.address_; ++ } ++ ++ Address address_, size_; // The address and size of the line's code. ++ File *file_; // The source file. ++ int number_; // The source line number. ++ }; ++ ++ // Create a new module with the given name, operating system, ++ // architecture, and ID string. ++ Module(const string &name, const string &os, const string &architecture, ++ const string &id); ++ ~Module(); ++ ++ // Set the module's load address to LOAD_ADDRESS; addresses given ++ // for functions and lines will be written to the Breakpad symbol ++ // file as offsets from this address. Construction initializes this ++ // module's load address to zero: addresses written to the symbol ++ // file will be the same as they appear in the File and Line ++ // structures. ++ void SetLoadAddress(Address load_address); ++ ++ // Add FUNCTION to the module. ++ // Destroying this module frees all Function objects that have been ++ // added with this function. ++ void AddFunction(Function *function); ++ ++ // Add all the functions in [BEGIN,END) to the module. ++ // Destroying this module frees all Function objects that have been ++ // added with this function. ++ void AddFunctions(vector::iterator begin, ++ vector::iterator end); ++ ++ // If this module has a file named NAME, return a pointer to it. If ++ // it has none, then create one and return a pointer to the new ++ // file. Destroying this module frees all File objects that have ++ // been created using this function, or with Insert. ++ File *FindFile(const string &name); ++ File *FindFile(const char *name); ++ ++ // Write this module to STREAM in the breakpad symbol format. ++ // Return true if all goes well, or false if an error occurs. This ++ // method writes out: ++ // - a header based on the values given to the constructor, ++ // - the source files added via FindFile, and finally ++ // - the functions added via AddFunctions, each with its lines. ++ // Addresses in the output are all relative to the load address ++ // established by SetLoadAddress. ++ bool Write(FILE *stream); ++ ++private: ++ ++ // Find those files in this module that are actually referred to by ++ // functions' line number data, and assign them source id numbers. ++ // Set the source id numbers for all other files --- unused by the ++ // source line data --- to -1. We do this before writing out the ++ // symbol file, at which point we omit any unused files. ++ void AssignSourceIds(); ++ ++ // Report an error that has occurred writing the symbol file, using ++ // errno to find the appropriate cause. Return false. ++ static bool ReportError(); ++ ++ // Module header entries. ++ string name_, os_, architecture_, id_; ++ ++ // The module's nominal load address. Addresses for functions and ++ // lines are absolute, assuming the module is loaded at this ++ // address. ++ Address load_address_; ++ ++ // Relation for maps whose keys are strings shared with some other ++ // structure. ++ struct CompareStringPtrs { ++ bool operator()(const string *x, const string *y) { return *x < *y; }; ++ }; ++ ++ // A map from filenames to File structures. The map's keys are ++ // pointers to the Files' names. ++ typedef map FileByNameMap; ++ ++ // The module owns all the files and functions that have been added ++ // to it; destroying the module frees the Files and Functions these ++ // point to. ++ FileByNameMap files_; // This module's source files. ++ vector functions_; // This module's functions. ++}; ++ ++} // namespace google_breakpad ++ ++#endif // COMMON_LINUX_MODULE_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/stabs_reader.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/stabs_reader.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/stabs_reader.cc +@@ -0,0 +1,200 @@ ++// Copyright 2009 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. ++ ++// This file implements the google_breakpad::StabsReader class. ++ ++#include ++#include ++#include ++#include ++ ++#include "common/linux/stabs_reader.h" ++ ++namespace google_breakpad { ++ ++StabsReader::StabsReader(const uint8_t *stab, size_t stab_size, ++ const uint8_t *stabstr, size_t stabstr_size, ++ StabsHandler *handler) : ++ stabstr_(stabstr), ++ stabstr_size_(stabstr_size), ++ handler_(handler), ++ symbol_(NULL), ++ current_source_file_(NULL) { ++ symbols_ = reinterpret_cast(stab); ++ symbols_end_ = symbols_ + (stab_size / sizeof (*symbols_)); ++} ++ ++const char *StabsReader::SymbolString() { ++ ptrdiff_t offset = symbol_->n_un.n_strx; ++ if (offset < 0 || (size_t) offset >= stabstr_size_) { ++ handler_->Warning("symbol %d: name offset outside the string section", ++ symbol_ - symbols_); ++ // Return our null string, to keep our promise about all names being ++ // taken from the string section. ++ offset = 0; ++ } ++ return reinterpret_cast(stabstr_ + offset); ++} ++ ++bool StabsReader::Process() { ++ symbol_ = symbols_; ++ while (symbol_ < symbols_end_) { ++ if (symbol_->n_type == N_SO) { ++ if (! ProcessCompilationUnit()) ++ return false; ++ } else ++ symbol_++; ++ } ++ return true; ++} ++ ++bool StabsReader::ProcessCompilationUnit() { ++ assert(symbol_ < symbols_end_ && symbol_->n_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; ++ symbol_++; ++ } ++ } ++ ++ // We expect to see an N_SO entry with a filename next, indicating ++ // the start of the compilation unit. ++ { ++ if (symbol_ >= symbols_end_ || symbol_->n_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. ++ symbol_++; ++ return true; ++ } ++ current_source_file_ = name; ++ } ++ ++ if (! handler_->StartCompilationUnit(current_source_file_, ++ SymbolValue(), ++ build_directory)) ++ return false; ++ ++ symbol_++; ++ ++ // 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 (symbol_ < symbols_end_ && symbol_->n_type != N_SO) { ++ if (symbol_->n_type == N_FUN) { ++ if (! ProcessFunction()) ++ return false; ++ } else ++ // Ignore anything else. ++ symbol_++; ++ } ++ ++ // An N_SO with an empty name indicates the end of the compilation ++ // unit. Default to zero. ++ uint64_t ending_address = 0; ++ if (symbol_ < symbols_end_) { ++ assert(symbol_->n_type == N_SO); ++ const char *name = SymbolString(); ++ if (name[0] == '\0') { ++ ending_address = SymbolValue(); ++ symbol_++; ++ } ++ } ++ ++ if (! handler_->EndCompilationUnit(ending_address)) ++ return false; ++ ++ return true; ++} ++ ++bool StabsReader::ProcessFunction() { ++ assert(symbol_ < symbols_end_ && symbol_->n_type == N_FUN); ++ ++ uint64_t function_address = SymbolValue(); ++ // 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; ++ symbol_++; ++ ++ while (symbol_ < symbols_end_) { ++ if (symbol_->n_type == N_SO || symbol_->n_type == N_FUN) ++ break; ++ else if (symbol_->n_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 + SymbolValue(); ++ // 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 = symbol_->n_desc; ++ if (! handler_->Line(line_address, current_source_file_, line_number)) ++ return false; ++ symbol_++; ++ } else if (symbol_->n_type == N_SOL) { ++ current_source_file_ = SymbolString(); ++ symbol_++; ++ } else ++ // Ignore anything else. ++ symbol_++; ++ } ++ ++ // If there is a subsequent N_SO or N_FUN entry, its address is our ++ // end address. ++ uint64_t ending_address = 0; ++ if (symbol_ < symbols_end_) { ++ assert(symbol_->n_type == N_SO || symbol_->n_type == N_FUN); ++ ending_address = SymbolValue(); ++ // Note: we do not increment symbol_ here, since we haven't consumed it. ++ } ++ ++ if (! handler_->EndFunction(ending_address)) ++ return false; ++ ++ return true; ++} ++ ++} // namespace google_breakpad +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/stabs_reader.h b/toolkit/crashreporter/google-breakpad/src/common/linux/stabs_reader.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/stabs_reader.h +@@ -0,0 +1,192 @@ ++// Copyright 2009 Google Inc. All Rights Reserved. -*- mode: c++ -*- ++// ++// 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. ++ ++// This file contains definitions related to the STABS reader and ++// its handler interfaces. ++// A description of the STABS debugging format can be found at ++// http://sourceware.org/gdb/current/onlinedocs/stabs_toc.html ++// The comments here assume you understand the format. ++// ++// This reader assumes that the system's and ++// headers accurately describe the layout of the STABS data; this code ++// is not cross-platform safe. ++ ++#ifndef COMMON_LINUX_STABS_READER_H__ ++#define COMMON_LINUX_STABS_READER_H__ ++ ++#include ++#include ++#include ++ ++#include ++ ++namespace google_breakpad { ++ ++class StabsHandler; ++ ++class StabsReader { ++ public: ++ // Create a reader for the STABS debug information whose .stab ++ // section is the STAB_SIZE bytes at STAB, and whose .stabstr ++ // section is the STABSTR_SIZE bytes at STABSTR. The reader will ++ // call the member functions of HANDLER to report the information it ++ // finds, when the reader's 'Process' member function is called. ++ // ++ // Note that, in ELF, the .stabstr section should be found using the ++ // 'sh_link' field of the .stab section header, not by name. ++ StabsReader(const uint8_t *stab, size_t stab_size, ++ const uint8_t *stabstr, size_t stabstr_size, ++ StabsHandler *handler); ++ ++ // Process the STABS data, calling the handler's member functions to ++ // report what we find. While the handler functions return true, ++ // continue to process until we reach the end of the section. If we ++ // processed the entire section and all handlers returned true, ++ // return true. If any handler returned false, return false. ++ bool Process(); ++ ++ private: ++ // Return the name of the current symbol. ++ const char *SymbolString(); ++ ++ // Return the value of the current symbol. ++ const uint64_t SymbolValue() { ++ return symbol_->n_value; ++ } ++ ++ // Process a compilation unit starting at symbol_. Return true ++ // to continue processing, or false to abort. ++ bool ProcessCompilationUnit(); ++ ++ // Process a function in current_source_file_ starting at symbol_. ++ // Return true to continue processing, or false to abort. ++ bool ProcessFunction(); ++ ++ // The debugging information we're reading. ++ const struct nlist *symbols_, *symbols_end_; ++ const uint8_t *stabstr_; ++ size_t stabstr_size_; ++ ++ StabsHandler *handler_; ++ ++ // The current symbol we're processing. ++ const struct nlist *symbol_; ++ ++ // The current source file name. ++ const char *current_source_file_; ++}; ++ ++// Consumer-provided callback structure for the STABS reader. Clients ++// of the STABS reader provide an instance of this structure. The ++// reader then invokes the member functions of that instance to report ++// the information it finds. ++// ++// The default definitions of the member functions do nothing, and return ++// true so processing will continue. ++class StabsHandler { ++ public: ++ StabsHandler() { } ++ virtual ~StabsHandler() { } ++ ++ // Some general notes about the handler callback functions: ++ ++ // Processing proceeds until the end of the .stabs section, or until ++ // one of these functions returns false. ++ ++ // The addresses given are as reported in the STABS info, without ++ // regard for whether the module may be loaded at different ++ // addresses at different times (a shared library, say). When ++ // processing STABS from an ELF shared library, the addresses given ++ // all assume the library is loaded at its nominal load address. ++ // They are *not* offsets from the nominal load address. If you ++ // want offsets, you must subtract off the library's nominal load ++ // address. ++ ++ // The arguments to these functions named FILENAME are all ++ // references to strings stored in the .stabstr section. Because ++ // both the Linux and Solaris linkers factor out duplicate strings ++ // from the .stabstr section, the consumer can assume that if two ++ // FILENAME values are different addresses, they represent different ++ // file names. ++ // ++ // Thus, it's safe to use (say) std::map, which does ++ // string address comparisons, not string content comparisons. ++ // Since all the strings are in same array of characters --- the ++ // .stabstr section --- comparing their addresses produces ++ // predictable, if not lexicographically meaningful, results. ++ ++ // Begin processing a compilation unit whose main source file is ++ // named FILENAME, and whose base address is ADDRESS. If ++ // BUILD_DIRECTORY is non-NULL, it is the name of the build ++ // directory in which the compilation occurred. ++ virtual bool StartCompilationUnit(const char *filename, uint64_t address, ++ const char *build_directory) { ++ return true; ++ } ++ ++ // Finish processing the compilation unit. If ADDRESS is non-zero, ++ // it is the ending address of the compilation unit. If ADDRESS is ++ // zero, then the compilation unit's ending address is not ++ // available, and the consumer must infer it by other means. ++ virtual bool EndCompilationUnit(uint64_t address) { return true; } ++ ++ // Begin processing a function named NAME, whose starting address is ++ // ADDRESS. This function belongs to the compilation unit that was ++ // most recently started but not ended. ++ // ++ // Note that, unlike filenames, NAME is not a pointer into the ++ // .stabstr section; this is because the name as it appears in the ++ // STABS data is followed by type information. The value passed to ++ // StartFunction is the function name alone. ++ // ++ // In languages that use name mangling, like C++, NAME is mangled. ++ virtual bool StartFunction(const std::string &name, uint64_t address) { ++ return true; ++ } ++ ++ // Finish processing the function. If ADDRESS is non-zero, it is ++ // the ending address for the function. If ADDRESS is zero, then ++ // the function's ending address is not available, and the consumer ++ // must infer it by other means. ++ virtual bool EndFunction(uint64_t address) { return true; } ++ ++ // Report that the code at ADDRESS is attributable to line NUMBER of ++ // the source file named FILENAME. The caller must infer the ending ++ // address of the line. ++ virtual bool Line(uint64_t address, const char *filename, int number) { ++ return true; ++ } ++ ++ // Report a warning. FORMAT is a printf-like format string, ++ // specifying how to format the subsequent arguments. ++ virtual void Warning(const char *format, ...) = 0; ++}; ++ ++} // namespace google_breakpad ++ ++#endif // COMMON_LINUX_STABS_READER_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/stabs_reader_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/stabs_reader_unittest.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/stabs_reader_unittest.cc +@@ -0,0 +1,548 @@ ++// Copyright (c) 2009, 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. ++ ++// stabs_reader_unittest.cc: Unit tests for StabsReader. ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "breakpad_googletest_includes.h" ++#include "common/linux/stabs_reader.h" ++ ++using std::istream; ++using std::istringstream; ++using std::map; ++using std::ostream; ++using std::ostringstream; ++using std::string; ++ ++using ::testing::_; ++using ::testing::InSequence; ++using ::testing::Return; ++using ::testing::Sequence; ++using ::testing::StrEq; ++ ++using google_breakpad::StabsHandler; ++using google_breakpad::StabsReader; ++ ++namespace { ++ ++// Mock stabs file parser ++// ++// In order to test StabsReader, we parse a human-readable input file ++// describing STABS entries into in-memory .stab and .stabstr ++// sections, and then pass those to StabsReader to look at. The ++// human-readable file is called a "mock stabs file". ++// ++// Each line of a mock stabs file should have the following form: ++// ++// TYPE OTHER DESC VALUE NAME ++// ++// where all data is Latin-1 bytes and fields are separated by single ++// space characters, except for NAME, which may contain spaces and ++// continues to the end of the line. The fields have the following ++// meanings: ++// ++// - TYPE: the name of the stabs symbol type; like SO or FUN. These are ++// the names from /usr/include/bits/stab.def, without the leading N_. ++// ++// - OTHER, DESC, VALUE: numeric values for the n_other, n_desc, and ++// n_value fields of the stab. These can be decimal or hex, ++// using C++ notation (10, 0x10) ++// ++// - NAME: textual data for the entry. STABS packs all kinds of ++// interesting data into entries' NAME fields, so calling it a NAME ++// is misleading, but that's how it is. For SO, this may be a ++// filename; for FUN, this is the function name, plus type data; and ++// so on. ++ ++// I don't know if the whole parser/handler pattern is really worth ++// the bureaucracy in this case. But just writing it out as ++// old-fashioned functions wasn't astonishingly clear either, so it ++// seemed worth a try. ++ ++// A handler class for mock stabs data. ++class MockStabsHandler { ++ public: ++ MockStabsHandler() { } ++ virtual ~MockStabsHandler() { } ++ // The mock stabs parser calls this member function for each entry ++ // it parses, passing it the contents of the entry. If this function ++ // returns true, the parser continues; if it returns false, the parser ++ // stops, and its Process member function returns false. ++ virtual bool Entry(enum __stab_debug_code type, char other, short desc, ++ unsigned long value, const string &name) { return true; } ++ // Report an error in parsing the mock stabs data. If this returns true, ++ // the parser continues; if it returns false, the parser stops and ++ // its Process member function returns false. ++ virtual bool Error(const char *format, ...) = 0; ++}; ++ ++// A class for parsing mock stabs files. ++class MockStabsParser { ++ public: ++ // Create a parser reading input from STREAM and passing data to HANDLER. ++ // Use FILENAME when reporting errors. ++ MockStabsParser(const string &filename, istream *stream, ++ MockStabsHandler *handler); ++ // Parse data from the STREAM, invoking HANDLER->Entry for each ++ // entry we get. Return true if we parsed all the data succesfully, ++ // or false if we stopped early because Entry returned false, or if ++ // there were any errors during parsing. ++ bool Process(); ++ private: ++ // A type for maps from stab type names ("SO", "SLINE", etc.) to ++ // n_type values. ++ typedef map StabTypeNameTable; ++ ++ // Initialize the table mapping STAB type names to n_type values. ++ void InitializeTypeNames(); ++ ++ // Parse LINE, one line of input from a mock stabs file, and pass ++ // its contents to handler_->Entry and return the boolean value that ++ // returns. If we encounter an error parsing the line, report it ++ // using handler->Error. ++ bool ParseLine(const string &line); ++ ++ const string &filename_; ++ istream *stream_; ++ MockStabsHandler *handler_; ++ int line_number_; ++ StabTypeNameTable type_names_; ++}; ++ ++MockStabsParser::MockStabsParser(const string &filename, istream *stream, ++ MockStabsHandler *handler): ++ filename_(filename), stream_(stream), handler_(handler), ++ line_number_(0) { ++ InitializeTypeNames(); ++} ++ ++bool MockStabsParser::Process() { ++ // Iterate once per line, including a line at EOF without a ++ // terminating newline. ++ for(;;) { ++ string line; ++ std::getline(*stream_, line, '\n'); ++ if (line.empty() && stream_->eof()) ++ break; ++ line_number_++; ++ if (! ParseLine(line)) ++ return false; ++ } ++ return true; ++} ++ ++void MockStabsParser::InitializeTypeNames() { ++ // On GLIBC-based systems, is a file containing a ++ // call to an unspecified macro __define_stab for each stab type. ++ // uses it to define the __stab_debug_code enum type. We ++ // use it here to initialize our mapping from type names to enum ++ // values. ++ // ++ // This isn't portable to non-GLIBC systems. Feel free to just ++ // hard-code the values if this becomes a problem. ++# define __define_stab(name, code, str) type_names_[string(str)] = code; ++# include ++# undef __define_stab ++} ++ ++bool MockStabsParser::ParseLine(const string &line) { ++ istringstream linestream(line); ++ // Allow "0x" prefix for hex, and so on. ++ linestream.unsetf(istringstream::basefield); ++ // Parse and validate the stabs type. ++ string typeName; ++ linestream >> typeName; ++ StabTypeNameTable::const_iterator typeIt = type_names_.find(typeName); ++ if (typeIt == type_names_.end()) ++ return handler_->Error("%s:%d: unrecognized stab type: %s\n", ++ filename_.c_str(), line_number_, typeName.c_str()); ++ // These are int, not char and unsigned char, to ensure they're parsed ++ // as decimal numbers, not characters. ++ int otherInt, descInt; ++ unsigned long value; ++ linestream >> otherInt >> descInt >> value; ++ if (linestream.fail()) ++ return handler_->Error("%s:%d: malformed mock stabs input line\n", ++ filename_.c_str(), line_number_); ++ if (linestream.peek() == ' ') ++ linestream.get(); ++ string name; ++ getline(linestream, name, '\n'); ++ return handler_->Entry(static_cast<__stab_debug_code>(typeIt->second), ++ otherInt, descInt, value, name); ++} ++ ++// A class for constructing .stab sections. ++// ++// A .stab section is an array of struct nlist entries. These ++// entries' n_un.n_strx fields are indices into an accompanying ++// .stabstr section. ++class StabSection { ++ public: ++ StabSection(): used_(0), size_(1) { ++ entries_ = (struct nlist *) malloc(sizeof(*entries_) * size_); ++ } ++ ~StabSection() { free(entries_); } ++ ++ // Append a new 'struct nlist' entry to the end of the section, and ++ // return a pointer to it. This pointer is valid until the next ++ // call to Append. The caller should initialize the returned entry ++ // as needed. ++ struct nlist *Append(); ++ // Set SECTION to the contents of a .stab section holding the ++ // accumulated list of entries added with Append. ++ void GetSection(string *section); ++ ++ private: ++ // The array of stabs entries, ++ struct nlist *entries_; ++ // The number of elements of entries_ that are used, and the allocated size ++ // of the array. ++ size_t used_, size_; ++}; ++ ++struct nlist *StabSection::Append() { ++ if (used_ == size_) { ++ size_ *= 2; ++ entries_ = (struct nlist *) realloc(entries_, sizeof(*entries_) * size_); ++ } ++ assert(used_ < size_); ++ return &entries_[used_++]; ++} ++ ++void StabSection::GetSection(string *section) { ++ section->assign(reinterpret_cast(entries_), ++ sizeof(*entries_) * used_); ++} ++ ++// A class for building .stabstr sections. ++// ++// A .stabstr section is an array of characters containing a bunch of ++// null-terminated strings. A string is identified by the index of ++// its initial character in the array. The array always starts with a ++// null byte, so that an index of zero refers to the empty string. ++// ++// This implementation also ensures that if two strings are equal, we ++// assign them the same indices; most linkers do this, and some ++// clients may rely upon it. (Note that this is not quite the same as ++// ensuring that a string only appears once in the section; you could ++// share space when one string is a suffix of another, but we don't.) ++class StabstrSection { ++ public: ++ StabstrSection(): next_byte_(1) { string_indices_[""] = 0; } ++ // Ensure STR is present in the string section, and return its index. ++ size_t Insert(const string &str); ++ // Set SECTION to the contents of a .stabstr section in which the ++ // strings passed to Insert appear at the indices we promised. ++ void GetSection(string *section); ++ private: ++ // Maps from strings to .stabstr indices and back. ++ typedef map StringToIndex; ++ typedef map IndexToString; ++ ++ // A map from strings to the indices we've assigned them. ++ StringToIndex string_indices_; ++ ++ // The next unused byte in the section. The next string we add ++ // will get this index. ++ size_t next_byte_; ++}; ++ ++size_t StabstrSection::Insert(const string &str) { ++ StringToIndex::iterator it = string_indices_.find(str); ++ size_t index; ++ if (it != string_indices_.end()) { ++ index = it->second; ++ } else { ++ // This is the first time we've seen STR; add it to the table. ++ string_indices_[str] = next_byte_; ++ index = next_byte_; ++ next_byte_ += str.size() + 1; ++ } ++ return index; ++} ++ ++void StabstrSection::GetSection(string *section) { ++ // First we have to invert the map. ++ IndexToString byIndex; ++ for (StringToIndex::const_iterator it = string_indices_.begin(); ++ it != string_indices_.end(); it++) ++ byIndex[it->second] = &it->first; ++ // Now we build the .stabstr section. ++ section->clear(); ++ for (IndexToString::const_iterator it = byIndex.begin(); ++ it != byIndex.end(); it++) { ++ // Make sure we're actually assigning it the index we claim to be. ++ assert(it->first == section->size()); ++ *section += *(it->second); ++ *section += '\0'; ++ } ++} ++ ++// A mock stabs parser handler class that builds .stab and .stabstr ++// sections. ++class StabsSectionsBuilder: public MockStabsHandler { ++ public: ++ // Construct a handler that will receive data from a MockStabsParser ++ // and construct .stab and .stabstr sections. FILENAME should be ++ // the name of the mock stabs input file; we use it in error ++ // messages. ++ StabsSectionsBuilder(const string &filename): ++ filename_(filename), error_count_(0) { } ++ ++ // Overridden virtual member functions. ++ bool Entry(enum __stab_debug_code type, char other, short desc, ++ unsigned long value, const string &name); ++ virtual bool Error(const char *format, ...); ++ ++ // Set SECTION to the contents of a .stab or .stabstr section ++ // reflecting the entries that have been passed to us via Entry. ++ void GetStab(string *section); ++ void GetStabstr(string *section); ++ ++ private: ++ StabSection stab_; // stabs entries we've seen ++ StabstrSection stabstr_; // and the strings they love ++ const string &filename_; // input filename, for error messages ++ int error_count_; // number of errors we've seen so far ++}; ++ ++bool StabsSectionsBuilder::Entry(enum __stab_debug_code type, char other, ++ short desc, unsigned long value, ++ const string &name) { ++ struct nlist *entry = stab_.Append(); ++ entry->n_type = type; ++ entry->n_other = other; ++ entry->n_desc = desc; ++ entry->n_value = value; ++ entry->n_un.n_strx = stabstr_.Insert(name); ++ return true; ++} ++ ++bool StabsSectionsBuilder::Error(const char *format, ...) { ++ va_list args; ++ va_start(args, format); ++ vfprintf(stderr, format, args); ++ va_end(args); ++ error_count_++; ++ if (error_count_ >= 20) { ++ fprintf(stderr, ++ "%s: lots of errors; is this really a mock stabs file?\n", ++ filename_.c_str()); ++ return false; ++ } ++ return true; ++} ++ ++void StabsSectionsBuilder::GetStab(string *section) { ++ stab_.GetSection(section); ++} ++ ++void StabsSectionsBuilder::GetStabstr(string *section) { ++ stabstr_.GetSection(section); ++} ++ ++class MockStabsReaderHandler: public StabsHandler { ++ public: ++ MOCK_METHOD3(StartCompilationUnit, ++ bool(const char *, uint64_t, const char *)); ++ MOCK_METHOD1(EndCompilationUnit, bool(uint64_t)); ++ MOCK_METHOD2(StartFunction, bool(const std::string &, uint64_t)); ++ MOCK_METHOD1(EndFunction, bool(uint64_t)); ++ MOCK_METHOD3(Line, bool(uint64_t, const char *, int)); ++ void Warning(const char *format, ...) { MockWarning(format); } ++ MOCK_METHOD1(MockWarning, void(const char *)); ++}; ++ ++// Create a StabsReader to parse the mock stabs data in INPUT_FILE, ++// passing the parsed information to HANDLER. If all goes well, return ++// the result of calling the reader's Process member function. ++// Otherwise, return false. INPUT_FILE should be relative to the top ++// of the source tree. ++static bool ApplyHandlerToMockStabsData(StabsHandler *handler, ++ const string &input_file) { ++ string full_input_file ++ = string(getenv("srcdir") ? getenv("srcdir") : ".") + "/" + input_file; ++ ++ // Open the input file. ++ std::ifstream stream(full_input_file.c_str()); ++ if (stream.fail()) { ++ fprintf(stderr, "error opening mock stabs input file %s: %s\n", ++ full_input_file.c_str(), strerror(errno)); ++ return false; ++ } ++ ++ // Parse the mock stabs data, and produce stabs sections to use as ++ // test input to the reader. ++ StabsSectionsBuilder builder(full_input_file); ++ MockStabsParser mock_parser(full_input_file, &stream, &builder); ++ if (!mock_parser.Process()) ++ return false; ++ string stab, stabstr; ++ builder.GetStab(&stab); ++ builder.GetStabstr(&stabstr); ++ ++ // Run the parser on the test input, passing whatever we find to HANDLER. ++ StabsReader reader( ++ reinterpret_cast(stab.data()), stab.size(), ++ reinterpret_cast(stabstr.data()), stabstr.size(), ++ handler); ++ return reader.Process(); ++} ++ ++TEST(StabsReaderTestCase, MockStabsInput) { ++ MockStabsReaderHandler mock_handler; ++ ++ { ++ InSequence s; ++ ++ EXPECT_CALL(mock_handler, StartCompilationUnit(StrEq("file1.c"), ++ 0x42, StrEq("builddir1/"))) ++ .WillOnce(Return(true)); ++ EXPECT_CALL(mock_handler, StartFunction(StrEq("fun1"), 0x62)) ++ .WillOnce(Return(true)); ++ EXPECT_CALL(mock_handler, Line(0xe4, StrEq("file1.c"), 91)) ++ .WillOnce(Return(true)); ++ EXPECT_CALL(mock_handler, Line(0x164, StrEq("header.h"), 111)) ++ .WillOnce(Return(true)); ++ EXPECT_CALL(mock_handler, EndFunction(0x112)) ++ .WillOnce(Return(true)); ++ EXPECT_CALL(mock_handler, StartFunction(StrEq("fun2"), 0x112)) ++ .WillOnce(Return(true)); ++ EXPECT_CALL(mock_handler, Line(0x234, StrEq("header.h"), 131)) ++ .WillOnce(Return(true)); ++ EXPECT_CALL(mock_handler, Line(0x254, StrEq("file1.c"), 151)) ++ .WillOnce(Return(true)); ++ EXPECT_CALL(mock_handler, EndFunction(0x152)) ++ .WillOnce(Return(true)); ++ EXPECT_CALL(mock_handler, EndCompilationUnit(0x152)) ++ .WillOnce(Return(true)); ++ EXPECT_CALL(mock_handler, StartCompilationUnit(StrEq("file3.c"), ++ 0x182, NULL)) ++ .WillOnce(Return(true)); ++ EXPECT_CALL(mock_handler, EndCompilationUnit(0x192)) ++ .WillOnce(Return(true)); ++ } ++ ++ ASSERT_TRUE(ApplyHandlerToMockStabsData( ++ &mock_handler, ++ "common/linux/testdata/stabs_reader_unittest.input1")); ++} ++ ++TEST(StabsReaderTestCase, AbruptCU) { ++ MockStabsReaderHandler mock_handler; ++ ++ { ++ InSequence s; ++ ++ EXPECT_CALL(mock_handler, ++ StartCompilationUnit(StrEq("file2-1.c"), 0x12, NULL)) ++ .WillOnce(Return(true)); ++ EXPECT_CALL(mock_handler, EndCompilationUnit(NULL)) ++ .WillOnce(Return(true)); ++ } ++ ++ ASSERT_TRUE(ApplyHandlerToMockStabsData( ++ &mock_handler, ++ "common/linux/testdata/stabs_reader_unittest.input2")); ++} ++ ++TEST(StabsReaderTestCase, AbruptFunction) { ++ MockStabsReaderHandler mock_handler; ++ ++ { ++ InSequence s; ++ ++ EXPECT_CALL(mock_handler, ++ StartCompilationUnit(StrEq("file3-1.c"), 0x12, NULL)) ++ .WillOnce(Return(true)); ++ EXPECT_CALL(mock_handler, StartFunction(StrEq("fun3_1"), 0x22)) ++ .WillOnce(Return(true)); ++ EXPECT_CALL(mock_handler, EndFunction(NULL)) ++ .WillOnce(Return(true)); ++ EXPECT_CALL(mock_handler, EndCompilationUnit(NULL)) ++ .WillOnce(Return(true)); ++ } ++ ++ ASSERT_TRUE(ApplyHandlerToMockStabsData( ++ &mock_handler, ++ "common/linux/testdata/stabs_reader_unittest.input3")); ++} ++ ++TEST(StabsReaderTestCase, NoCU) { ++ MockStabsReaderHandler mock_handler; ++ ++ EXPECT_CALL(mock_handler, StartCompilationUnit(_, _, _)) ++ .Times(0); ++ EXPECT_CALL(mock_handler, StartFunction(_, _)) ++ .Times(0); ++ ++ ASSERT_TRUE(ApplyHandlerToMockStabsData( ++ &mock_handler, ++ "common/linux/testdata/stabs_reader_unittest.input4")); ++ ++} ++ ++TEST(StabsReaderTestCase, NoCUEnd) { ++ MockStabsReaderHandler mock_handler; ++ ++ { ++ InSequence s; ++ ++ EXPECT_CALL(mock_handler, ++ StartCompilationUnit(StrEq("file5-1.c"), 0x12, NULL)) ++ .WillOnce(Return(true)); ++ EXPECT_CALL(mock_handler, EndCompilationUnit(NULL)) ++ .WillOnce(Return(true)); ++ EXPECT_CALL(mock_handler, ++ StartCompilationUnit(StrEq("file5-2.c"), 0x22, NULL)) ++ .WillOnce(Return(true)); ++ EXPECT_CALL(mock_handler, EndCompilationUnit(NULL)) ++ .WillOnce(Return(true)); ++ } ++ ++ ASSERT_TRUE(ApplyHandlerToMockStabsData( ++ &mock_handler, ++ "common/linux/testdata/stabs_reader_unittest.input5")); ++ ++} ++ ++} // anonymous namespace +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/testdata/stabs_reader_unittest.input1 b/toolkit/crashreporter/google-breakpad/src/common/linux/testdata/stabs_reader_unittest.input1 +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/testdata/stabs_reader_unittest.input1 +@@ -0,0 +1,19 @@ ++SO 10 11 0x02 builddir/ ++FUN 20 21 0x12 not the SO with source file name we expected ++SO 30 31 0x22 ++SO 40 41 0x32 builddir1/ ++SO 50 51 0x42 file1.c ++LSYM 60 61 0x52 not the FUN we're looking for ++FUN 70 71 0x62 fun1 ++BINCL 80 81 0x72 something to ignore in a FUN body ++SLINE 90 91 0x82 ++SOL 100 101 0x92 header.h ++SLINE 110 111 0x102 ++FUN 120 121 0x112 fun2:some stabs type info here, to trim from the name ++SLINE 130 131 0x122 ++SOL 140 141 0x132 file1.c ++SLINE 150 151 0x142 ++SO 160 161 0x152 ++LSYM 170 171 0x162 ++SO 180 181 0x182 file3.c ++SO 190 191 0x192 +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/testdata/stabs_reader_unittest.input2 b/toolkit/crashreporter/google-breakpad/src/common/linux/testdata/stabs_reader_unittest.input2 +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/testdata/stabs_reader_unittest.input2 +@@ -0,0 +1,1 @@ ++SO 10 11 0x12 file2-1.c +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/testdata/stabs_reader_unittest.input3 b/toolkit/crashreporter/google-breakpad/src/common/linux/testdata/stabs_reader_unittest.input3 +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/testdata/stabs_reader_unittest.input3 +@@ -0,0 +1,2 @@ ++SO 10 11 0x12 file3-1.c ++FUN 20 21 0x22 fun3_1 +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/testdata/stabs_reader_unittest.input4 b/toolkit/crashreporter/google-breakpad/src/common/linux/testdata/stabs_reader_unittest.input4 +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/testdata/stabs_reader_unittest.input4 +@@ -0,0 +1,1 @@ ++SO 10 11 0x12 build-directory/ +diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/testdata/stabs_reader_unittest.input5 b/toolkit/crashreporter/google-breakpad/src/common/linux/testdata/stabs_reader_unittest.input5 +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/linux/testdata/stabs_reader_unittest.input5 +@@ -0,0 +1,2 @@ ++SO 10 11 0x12 file5-1.c ++SO 20 21 0x22 file5-2.c +diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/GTMDefines.h b/toolkit/crashreporter/google-breakpad/src/common/mac/GTMDefines.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/mac/GTMDefines.h +@@ -0,0 +1,241 @@ ++// ++// GTMDefines.h ++// ++// Copyright 2008 Google Inc. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); you may not ++// use this file except in compliance with the License. You may obtain a copy ++// of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT ++// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the ++// License for the specific language governing permissions and limitations under ++// the License. ++// ++ ++// ============================================================================ ++ ++#include ++#include ++ ++// Not all MAC_OS_X_VERSION_10_X macros defined in past SDKs ++#ifndef MAC_OS_X_VERSION_10_5 ++ #define MAC_OS_X_VERSION_10_5 1050 ++#endif ++#ifndef MAC_OS_X_VERSION_10_6 ++ #define MAC_OS_X_VERSION_10_6 1060 ++#endif ++ ++// ---------------------------------------------------------------------------- ++// CPP symbols that can be overridden in a prefix to control how the toolbox ++// is compiled. ++// ---------------------------------------------------------------------------- ++ ++ ++// By setting the GTM_CONTAINERS_VALIDATION_FAILED_LOG and ++// GTM_CONTAINERS_VALIDATION_FAILED_ASSERT macros you can control what happens ++// when a validation fails. If you implement your own validators, you may want ++// to control their internals using the same macros for consistency. ++#ifndef GTM_CONTAINERS_VALIDATION_FAILED_ASSERT ++ #define GTM_CONTAINERS_VALIDATION_FAILED_ASSERT 0 ++#endif ++ ++// Give ourselves a consistent way to do inlines. Apple's macros even use ++// a few different actual definitions, so we're based off of the foundation ++// one. ++#if !defined(GTM_INLINE) ++ #if defined (__GNUC__) && (__GNUC__ == 4) ++ #define GTM_INLINE static __inline__ __attribute__((always_inline)) ++ #else ++ #define GTM_INLINE static __inline__ ++ #endif ++#endif ++ ++// Give ourselves a consistent way of doing externs that links up nicely ++// when mixing objc and objc++ ++#if !defined (GTM_EXTERN) ++ #if defined __cplusplus ++ #define GTM_EXTERN extern "C" ++ #else ++ #define GTM_EXTERN extern ++ #endif ++#endif ++ ++// Give ourselves a consistent way of exporting things if we have visibility ++// set to hidden. ++#if !defined (GTM_EXPORT) ++ #define GTM_EXPORT __attribute__((visibility("default"))) ++#endif ++ ++// _GTMDevLog & _GTMDevAssert ++// ++// _GTMDevLog & _GTMDevAssert are meant to be a very lightweight shell for ++// developer level errors. This implementation simply macros to NSLog/NSAssert. ++// It is not intended to be a general logging/reporting system. ++// ++// Please see http://code.google.com/p/google-toolbox-for-mac/wiki/DevLogNAssert ++// for a little more background on the usage of these macros. ++// ++// _GTMDevLog log some error/problem in debug builds ++// _GTMDevAssert assert if conditon isn't met w/in a method/function ++// in all builds. ++// ++// To replace this system, just provide different macro definitions in your ++// prefix header. Remember, any implementation you provide *must* be thread ++// safe since this could be called by anything in what ever situtation it has ++// been placed in. ++// ++ ++// We only define the simple macros if nothing else has defined this. ++#ifndef _GTMDevLog ++ ++#ifdef DEBUG ++ #define _GTMDevLog(...) NSLog(__VA_ARGS__) ++#else ++ #define _GTMDevLog(...) do { } while (0) ++#endif ++ ++#endif // _GTMDevLog ++ ++// Declared here so that it can easily be used for logging tracking if ++// necessary. See GTMUnitTestDevLog.h for details. ++@class NSString; ++GTM_EXTERN void _GTMUnitTestDevLog(NSString *format, ...); ++ ++#ifndef _GTMDevAssert ++// we directly invoke the NSAssert handler so we can pass on the varargs ++// (NSAssert doesn't have a macro we can use that takes varargs) ++#if !defined(NS_BLOCK_ASSERTIONS) ++ #define _GTMDevAssert(condition, ...) \ ++ do { \ ++ if (!(condition)) { \ ++ [[NSAssertionHandler currentHandler] \ ++ handleFailureInFunction:[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \ ++ file:[NSString stringWithUTF8String:__FILE__] \ ++ lineNumber:__LINE__ \ ++ description:__VA_ARGS__]; \ ++ } \ ++ } while(0) ++#else // !defined(NS_BLOCK_ASSERTIONS) ++ #define _GTMDevAssert(condition, ...) do { } while (0) ++#endif // !defined(NS_BLOCK_ASSERTIONS) ++ ++#endif // _GTMDevAssert ++ ++// _GTMCompileAssert ++// _GTMCompileAssert is an assert that is meant to fire at compile time if you ++// want to check things at compile instead of runtime. For example if you ++// want to check that a wchar is 4 bytes instead of 2 you would use ++// _GTMCompileAssert(sizeof(wchar_t) == 4, wchar_t_is_4_bytes_on_OS_X) ++// Note that the second "arg" is not in quotes, and must be a valid processor ++// symbol in it's own right (no spaces, punctuation etc). ++ ++// Wrapping this in an #ifndef allows external groups to define their own ++// compile time assert scheme. ++#ifndef _GTMCompileAssert ++ // We got this technique from here: ++ // http://unixjunkie.blogspot.com/2007/10/better-compile-time-asserts_29.html ++ ++ #define _GTMCompileAssertSymbolInner(line, msg) _GTMCOMPILEASSERT ## line ## __ ## msg ++ #define _GTMCompileAssertSymbol(line, msg) _GTMCompileAssertSymbolInner(line, msg) ++ #define _GTMCompileAssert(test, msg) \ ++ typedef char _GTMCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ] ++#endif // _GTMCompileAssert ++ ++// Macro to allow fast enumeration when building for 10.5 or later, and ++// reliance on NSEnumerator for 10.4. Remember, NSDictionary w/ FastEnumeration ++// does keys, so pick the right thing, nothing is done on the FastEnumeration ++// side to be sure you're getting what you wanted. ++#ifndef GTM_FOREACH_OBJECT ++ #if TARGET_OS_IPHONE || (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) ++ #define GTM_FOREACH_OBJECT(element, collection) \ ++ for (element in collection) ++ #define GTM_FOREACH_KEY(element, collection) \ ++ for (element in collection) ++ #else ++ #define GTM_FOREACH_OBJECT(element, collection) \ ++ for (NSEnumerator * _ ## element ## _enum = [collection objectEnumerator]; \ ++ (element = [_ ## element ## _enum nextObject]) != nil; ) ++ #define GTM_FOREACH_KEY(element, collection) \ ++ for (NSEnumerator * _ ## element ## _enum = [collection keyEnumerator]; \ ++ (element = [_ ## element ## _enum nextObject]) != nil; ) ++ #endif ++#endif ++ ++// ============================================================================ ++ ++// ---------------------------------------------------------------------------- ++// CPP symbols defined based on the project settings so the GTM code has ++// simple things to test against w/o scattering the knowledge of project ++// setting through all the code. ++// ---------------------------------------------------------------------------- ++ ++// Provide a single constant CPP symbol that all of GTM uses for ifdefing ++// iPhone code. ++#if TARGET_OS_IPHONE // iPhone SDK ++ // For iPhone specific stuff ++ #define GTM_IPHONE_SDK 1 ++ #if TARGET_IPHONE_SIMULATOR ++ #define GTM_IPHONE_SIMULATOR 1 ++ #else ++ #define GTM_IPHONE_DEVICE 1 ++ #endif // TARGET_IPHONE_SIMULATOR ++#else ++ // For MacOS specific stuff ++ #define GTM_MACOS_SDK 1 ++#endif ++ ++// Provide a symbol to include/exclude extra code for GC support. (This mainly ++// just controls the inclusion of finalize methods). ++#ifndef GTM_SUPPORT_GC ++ #if GTM_IPHONE_SDK ++ // iPhone never needs GC ++ #define GTM_SUPPORT_GC 0 ++ #else ++ // We can't find a symbol to tell if GC is supported/required, so best we ++ // do on Mac targets is include it if we're on 10.5 or later. ++ #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 ++ #define GTM_SUPPORT_GC 0 ++ #else ++ #define GTM_SUPPORT_GC 1 ++ #endif ++ #endif ++#endif ++ ++// To simplify support for 64bit (and Leopard in general), we provide the type ++// defines for non Leopard SDKs ++#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 ++ // NSInteger/NSUInteger and Max/Mins ++ #ifndef NSINTEGER_DEFINED ++ #if __LP64__ || NS_BUILD_32_LIKE_64 ++ typedef long NSInteger; ++ typedef unsigned long NSUInteger; ++ #else ++ typedef int NSInteger; ++ typedef unsigned int NSUInteger; ++ #endif ++ #define NSIntegerMax LONG_MAX ++ #define NSIntegerMin LONG_MIN ++ #define NSUIntegerMax ULONG_MAX ++ #define NSINTEGER_DEFINED 1 ++ #endif // NSINTEGER_DEFINED ++ // CGFloat ++ #ifndef CGFLOAT_DEFINED ++ #if defined(__LP64__) && __LP64__ ++ // This really is an untested path (64bit on Tiger?) ++ typedef double CGFloat; ++ #define CGFLOAT_MIN DBL_MIN ++ #define CGFLOAT_MAX DBL_MAX ++ #define CGFLOAT_IS_DOUBLE 1 ++ #else /* !defined(__LP64__) || !__LP64__ */ ++ typedef float CGFloat; ++ #define CGFLOAT_MIN FLT_MIN ++ #define CGFLOAT_MAX FLT_MAX ++ #define CGFLOAT_IS_DOUBLE 0 ++ #endif /* !defined(__LP64__) || !__LP64__ */ ++ #define CGFLOAT_DEFINED 1 ++ #endif // CGFLOAT_DEFINED ++#endif // MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4 +diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/GTMGarbageCollection.h b/toolkit/crashreporter/google-breakpad/src/common/mac/GTMGarbageCollection.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/mac/GTMGarbageCollection.h +@@ -0,0 +1,72 @@ ++// ++// GTMGarbageCollection.h ++// ++// Copyright 2007-2008 Google Inc. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); you may not ++// use this file except in compliance with the License. You may obtain a copy ++// of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT ++// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the ++// License for the specific language governing permissions and limitations under ++// the License. ++// ++ ++#import ++ ++#import "GTMDefines.h" ++ ++// This allows us to easily move our code from GC to non GC. ++// They are no-ops unless we are require Leopard or above. ++// See ++// http://developer.apple.com/documentation/Cocoa/Conceptual/GarbageCollection/index.html ++// and ++// http://developer.apple.com/documentation/Cocoa/Conceptual/GarbageCollection/Articles/gcCoreFoundation.html#//apple_ref/doc/uid/TP40006687-SW1 ++// for details. ++ ++#if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) && !GTM_IPHONE_SDK ++// General use would be to call this through GTMCFAutorelease ++// but there may be a reason the you want to make something collectable ++// but not autoreleased, especially in pure GC code where you don't ++// want to bother with the nop autorelease. Done as a define instead of an ++// inline so that tools like Clang's scan-build don't report code as leaking. ++#define GTMNSMakeCollectable(cf) ((id)NSMakeCollectable(cf)) ++ ++// GTMNSMakeUncollectable is for global maps, etc. that we don't ++// want released ever. You should still retain these in non-gc code. ++GTM_INLINE void GTMNSMakeUncollectable(id object) { ++ [[NSGarbageCollector defaultCollector] disableCollectorForPointer:object]; ++} ++ ++// Hopefully no code really needs this, but GTMIsGarbageCollectionEnabled is ++// a common way to check at runtime if GC is on. ++// There are some places where GC doesn't work w/ things w/in Apple's ++// frameworks, so this is here so GTM unittests and detect it, and not run ++// individual tests to work around bugs in Apple's frameworks. ++GTM_INLINE BOOL GTMIsGarbageCollectionEnabled(void) { ++ return ([NSGarbageCollector defaultCollector] != nil); ++} ++ ++#else ++ ++#define GTMNSMakeCollectable(cf) ((id)(cf)) ++ ++GTM_INLINE void GTMNSMakeUncollectable(id object) { ++} ++ ++GTM_INLINE BOOL GTMIsGarbageCollectionEnabled(void) { ++ return NO; ++} ++ ++#endif ++ ++// GTMCFAutorelease makes a CF object collectable in GC mode, or adds it ++// to the autorelease pool in non-GC mode. Either way it is taken care ++// of. Done as a define instead of an inline so that tools like Clang's ++// scan-build don't report code as leaking. ++#define GTMCFAutorelease(cf) ([GTMNSMakeCollectable(cf) autorelease]) ++ +diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/GTMLogger.h b/toolkit/crashreporter/google-breakpad/src/common/mac/GTMLogger.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/mac/GTMLogger.h +@@ -0,0 +1,458 @@ ++// ++// GTMLogger.h ++// ++// Copyright 2007-2008 Google Inc. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); you may not ++// use this file except in compliance with the License. You may obtain a copy ++// of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT ++// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the ++// License for the specific language governing permissions and limitations under ++// the License. ++// ++ ++// Key Abstractions ++// ---------------- ++// ++// This file declares multiple classes and protocols that are used by the ++// GTMLogger logging system. The 4 main abstractions used in this file are the ++// following: ++// ++// * logger (GTMLogger) - The main logging class that users interact with. It ++// has methods for logging at different levels and uses a log writer, a log ++// formatter, and a log filter to get the job done. ++// ++// * log writer (GTMLogWriter) - Writes a given string to some log file, where ++// a "log file" can be a physical file on disk, a POST over HTTP to some URL, ++// or even some in-memory structure (e.g., a ring buffer). ++// ++// * log formatter (GTMLogFormatter) - Given a format string and arguments as ++// a va_list, returns a single formatted NSString. A "formatted string" could ++// be a string with the date prepended, a string with values in a CSV format, ++// or even a string of XML. ++// ++// * log filter (GTMLogFilter) - Given a formatted log message as an NSString ++// and the level at which the message is to be logged, this class will decide ++// whether the given message should be logged or not. This is a flexible way ++// to filter out messages logged at a certain level, messages that contain ++// certain text, or filter nothing out at all. This gives the caller the ++// flexibility to dynamically enable debug logging in Release builds. ++// ++// This file also declares some classes to handle the common log writer, log ++// formatter, and log filter cases. Callers can also create their own writers, ++// formatters, and filters and they can even build them on top of the ones ++// declared here. Keep in mind that your custom writer/formatter/filter may be ++// called from multiple threads, so it must be thread-safe. ++ ++#import ++#import "GTMDefines.h" ++ ++// Predeclaration of used protocols that are declared later in this file. ++@protocol GTMLogWriter, GTMLogFormatter, GTMLogFilter; ++ ++#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 ++#define CHECK_FORMAT_NSSTRING(a, b) __attribute__((format(__NSString__, a, b))) ++#else ++#define CHECK_FORMAT_NSSTRING(a, b) ++#endif ++ ++// GTMLogger ++// ++// GTMLogger is the primary user-facing class for an object-oriented logging ++// system. It is built on the concept of log formatters (GTMLogFormatter), log ++// writers (GTMLogWriter), and log filters (GTMLogFilter). When a message is ++// sent to a GTMLogger to log a message, the message is formatted using the log ++// formatter, then the log filter is consulted to see if the message should be ++// logged, and if so, the message is sent to the log writer to be written out. ++// ++// GTMLogger is intended to be a flexible and thread-safe logging solution. Its ++// flexibility comes from the fact that GTMLogger instances can be customized ++// with user defined formatters, filters, and writers. And these writers, ++// filters, and formatters can be combined, stacked, and customized in arbitrary ++// ways to suit the needs at hand. For example, multiple writers can be used at ++// the same time, and a GTMLogger instance can even be used as another ++// GTMLogger's writer. This allows for arbitrarily deep logging trees. ++// ++// A standard GTMLogger uses a writer that sends messages to standard out, a ++// formatter that smacks a timestamp and a few other bits of interesting ++// information on the message, and a filter that filters out debug messages from ++// release builds. Using the standard log settings, a log message will look like ++// the following: ++// ++// 2007-12-30 10:29:24.177 myapp[4588/0xa07d0f60] [lvl=1] foo= ++// ++// The output contains the date and time of the log message, the name of the ++// process followed by its process ID/thread ID, the log level at which the ++// message was logged (in the previous example the level was 1: ++// kGTMLoggerLevelDebug), and finally, the user-specified log message itself (in ++// this case, the log message was @"foo=%@", foo). ++// ++// Multiple instances of GTMLogger can be created, each configured their own ++// way. Though GTMLogger is not a singleton (in the GoF sense), it does provide ++// access to a shared (i.e., globally accessible) GTMLogger instance. This makes ++// it convenient for all code in a process to use the same GTMLogger instance. ++// The shared GTMLogger instance can also be configured in an arbitrary, and ++// these configuration changes will affect all code that logs through the shared ++// instance. ++ ++// ++// Log Levels ++// ---------- ++// GTMLogger has 3 different log levels: Debug, Info, and Error. GTMLogger ++// doesn't take any special action based on the log level; it simply forwards ++// this information on to formatters, filters, and writers, each of which may ++// optionally take action based on the level. Since log level filtering is ++// performed at runtime, log messages are typically not filtered out at compile ++// time. The exception to this rule is that calls to the GTMLoggerDebug() macro ++// *ARE* filtered out of non-DEBUG builds. This is to be backwards compatible ++// with behavior that many developers are currently used to. Note that this ++// means that GTMLoggerDebug(@"hi") will be compiled out of Release builds, but ++// [[GTMLogger sharedLogger] logDebug:@"hi"] will NOT be compiled out. ++// ++// Standard loggers are created with the GTMLogLevelFilter log filter, which ++// filters out certain log messages based on log level, and some other settings. ++// ++// In addition to the -logDebug:, -logInfo:, and -logError: methods defined on ++// GTMLogger itself, there are also C macros that make usage of the shared ++// GTMLogger instance very convenient. These macros are: ++// ++// GTMLoggerDebug(...) ++// GTMLoggerInfo(...) ++// GTMLoggerError(...) ++// ++// Again, a notable feature of these macros is that GTMLogDebug() calls *will be ++// compiled out of non-DEBUG builds*. ++// ++// Standard Loggers ++// ---------------- ++// GTMLogger has the concept of "standard loggers". A standard logger is simply ++// a logger that is pre-configured with some standard/common writer, formatter, ++// and filter combination. Standard loggers are created using the creation ++// methods beginning with "standard". The alternative to a standard logger is a ++// regular logger, which will send messages to stdout, with no special ++// formatting, and no filtering. ++// ++// How do I use GTMLogger? ++// ---------------------- ++// The typical way you will want to use GTMLogger is to simply use the ++// GTMLogger*() macros for logging from code. That way we can easily make ++// changes to the GTMLogger class and simply update the macros accordingly. Only ++// your application startup code (perhaps, somewhere in main()) should use the ++// GTMLogger class directly in order to configure the shared logger, which all ++// of the code using the macros will be using. Again, this is just the typical ++// situation. ++// ++// To be complete, there are cases where you may want to use GTMLogger directly, ++// or even create separate GTMLogger instances for some reason. That's fine, ++// too. ++// ++// Examples ++// -------- ++// The following show some common GTMLogger use cases. ++// ++// 1. You want to log something as simply as possible. Also, this call will only ++// appear in debug builds. In non-DEBUG builds it will be completely removed. ++// ++// GTMLoggerDebug(@"foo = %@", foo); ++// ++// 2. The previous example is similar to the following. The major difference is ++// that the previous call (example 1) will be compiled out of Release builds ++// but this statement will not be compiled out. ++// ++// [[GTMLogger sharedLogger] logDebug:@"foo = %@", foo]; ++// ++// 3. Send all logging output from the shared logger to a file. We do this by ++// creating an NSFileHandle for writing associated with a file, and setting ++// that file handle as the logger's writer. ++// ++// NSFileHandle *f = [NSFileHandle fileHandleForWritingAtPath:@"/tmp/f.log" ++// create:YES]; ++// [[GTMLogger sharedLogger] setWriter:f]; ++// GTMLoggerError(@"hi"); // This will be sent to /tmp/f.log ++// ++// 4. Create a new GTMLogger that will log to a file. This example differs from ++// the previous one because here we create a new GTMLogger that is different ++// from the shared logger. ++// ++// GTMLogger *logger = [GTMLogger standardLoggerWithPath:@"/tmp/temp.log"]; ++// [logger logInfo:@"hi temp log file"]; ++// ++// 5. Create a logger that writes to stdout and does NOT do any formatting to ++// the log message. This might be useful, for example, when writing a help ++// screen for a command-line tool to standard output. ++// ++// GTMLogger *logger = [GTMLogger logger]; ++// [logger logInfo:@"%@ version 0.1 usage", progName]; ++// ++// 6. Send log output to stdout AND to a log file. The trick here is that ++// NSArrays function as composite log writers, which means when an array is ++// set as the log writer, it forwards all logging messages to all of its ++// contained GTMLogWriters. ++// ++// // Create array of GTMLogWriters ++// NSArray *writers = [NSArray arrayWithObjects: ++// [NSFileHandle fileHandleForWritingAtPath:@"/tmp/f.log" create:YES], ++// [NSFileHandle fileHandleWithStandardOutput], nil]; ++// ++// GTMLogger *logger = [GTMLogger standardLogger]; ++// [logger setWriter:writers]; ++// [logger logInfo:@"hi"]; // Output goes to stdout and /tmp/f.log ++// ++// For futher details on log writers, formatters, and filters, see the ++// documentation below. ++// ++// NOTE: GTMLogger is application level logging. By default it does nothing ++// with _GTMDevLog/_GTMDevAssert (see GTMDefines.h). An application can choose ++// to bridge _GTMDevLog/_GTMDevAssert to GTMLogger by providing macro ++// definitions in its prefix header (see GTMDefines.h for how one would do ++// that). ++// ++@interface GTMLogger : NSObject { ++ @private ++ id writer_; ++ id formatter_; ++ id filter_; ++} ++ ++// ++// Accessors for the shared logger instance ++// ++ ++// Returns a shared/global standard GTMLogger instance. Callers should typically ++// use this method to get a GTMLogger instance, unless they explicitly want ++// their own instance to configure for their own needs. This is the only method ++// that returns a shared instance; all the rest return new GTMLogger instances. +++ (id)sharedLogger; ++ ++// Sets the shared logger instance to |logger|. Future calls to +sharedLogger ++// will return |logger| instead. +++ (void)setSharedLogger:(GTMLogger *)logger; ++ ++// ++// Creation methods ++// ++ ++// Returns a new autoreleased GTMLogger instance that will log to stdout, using ++// the GTMLogStandardFormatter, and the GTMLogLevelFilter filter. +++ (id)standardLogger; ++ ++// Same as +standardLogger, but logs to stderr. +++ (id)standardLoggerWithStderr; ++ ++// Returns a new standard GTMLogger instance with a log writer that will ++// write to the file at |path|, and will use the GTMLogStandardFormatter and ++// GTMLogLevelFilter classes. If |path| does not exist, it will be created. +++ (id)standardLoggerWithPath:(NSString *)path; ++ ++// Returns an autoreleased GTMLogger instance that will use the specified ++// |writer|, |formatter|, and |filter|. +++ (id)loggerWithWriter:(id)writer ++ formatter:(id)formatter ++ filter:(id)filter; ++ ++// Returns an autoreleased GTMLogger instance that logs to stdout, with the ++// basic formatter, and no filter. The returned logger differs from the logger ++// returned by +standardLogger because this one does not do any filtering and ++// does not do any special log formatting; this is the difference between a ++// "regular" logger and a "standard" logger. +++ (id)logger; ++ ++// Designated initializer. This method returns a GTMLogger initialized with the ++// specified |writer|, |formatter|, and |filter|. See the setter methods below ++// for what values will be used if nil is passed for a parameter. ++- (id)initWithWriter:(id)writer ++ formatter:(id)formatter ++ filter:(id)filter; ++ ++// ++// Logging methods ++// ++ ++// Logs a message at the debug level (kGTMLoggerLevelDebug). ++- (void)logDebug:(NSString *)fmt, ... CHECK_FORMAT_NSSTRING(1, 2); ++// Logs a message at the info level (kGTMLoggerLevelInfo). ++- (void)logInfo:(NSString *)fmt, ... CHECK_FORMAT_NSSTRING(1, 2); ++// Logs a message at the error level (kGTMLoggerLevelError). ++- (void)logError:(NSString *)fmt, ... CHECK_FORMAT_NSSTRING(1, 2); ++// Logs a message at the assert level (kGTMLoggerLevelAssert). ++- (void)logAssert:(NSString *)fmt, ... CHECK_FORMAT_NSSTRING(1, 2); ++ ++ ++// ++// Accessors ++// ++ ++// Accessor methods for the log writer. If the log writer is set to nil, ++// [NSFileHandle fileHandleWithStandardOutput] is used. ++- (id)writer; ++- (void)setWriter:(id)writer; ++ ++// Accessor methods for the log formatter. If the log formatter is set to nil, ++// GTMLogBasicFormatter is used. This formatter will format log messages in a ++// plain printf style. ++- (id)formatter; ++- (void)setFormatter:(id)formatter; ++ ++// Accessor methods for the log filter. If the log filter is set to nil, ++// GTMLogNoFilter is used, which allows all log messages through. ++- (id)filter; ++- (void)setFilter:(id)filter; ++ ++@end // GTMLogger ++ ++ ++// Helper functions that are used by the convenience GTMLogger*() macros that ++// enable the logging of function names. ++@interface GTMLogger (GTMLoggerMacroHelpers) ++- (void)logFuncDebug:(const char *)func msg:(NSString *)fmt, ... ++ CHECK_FORMAT_NSSTRING(2, 3); ++- (void)logFuncInfo:(const char *)func msg:(NSString *)fmt, ... ++ CHECK_FORMAT_NSSTRING(2, 3); ++- (void)logFuncError:(const char *)func msg:(NSString *)fmt, ... ++ CHECK_FORMAT_NSSTRING(2, 3); ++- (void)logFuncAssert:(const char *)func msg:(NSString *)fmt, ... ++ CHECK_FORMAT_NSSTRING(2, 3); ++@end // GTMLoggerMacroHelpers ++ ++ ++// Convenience macros that log to the shared GTMLogger instance. These macros ++// are how users should typically log to GTMLogger. Notice that GTMLoggerDebug() ++// calls will be compiled out of non-Debug builds. ++#define GTMLoggerDebug(...) \ ++ [[GTMLogger sharedLogger] logFuncDebug:__func__ msg:__VA_ARGS__] ++#define GTMLoggerInfo(...) \ ++ [[GTMLogger sharedLogger] logFuncInfo:__func__ msg:__VA_ARGS__] ++#define GTMLoggerError(...) \ ++ [[GTMLogger sharedLogger] logFuncError:__func__ msg:__VA_ARGS__] ++#define GTMLoggerAssert(...) \ ++ [[GTMLogger sharedLogger] logFuncAssert:__func__ msg:__VA_ARGS__] ++ ++// If we're not in a debug build, remove the GTMLoggerDebug statements. This ++// makes calls to GTMLoggerDebug "compile out" of Release builds ++#ifndef DEBUG ++#undef GTMLoggerDebug ++#define GTMLoggerDebug(...) do {} while(0) ++#endif ++ ++// Log levels. ++typedef enum { ++ kGTMLoggerLevelUnknown, ++ kGTMLoggerLevelDebug, ++ kGTMLoggerLevelInfo, ++ kGTMLoggerLevelError, ++ kGTMLoggerLevelAssert, ++} GTMLoggerLevel; ++ ++ ++// ++// Log Writers ++// ++ ++// Protocol to be implemented by a GTMLogWriter instance. ++@protocol GTMLogWriter ++// Writes the given log message to where the log writer is configured to write. ++- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level; ++@end // GTMLogWriter ++ ++ ++// Simple category on NSFileHandle that makes NSFileHandles valid log writers. ++// This is convenient because something like, say, +fileHandleWithStandardError ++// now becomes a valid log writer. Log messages are written to the file handle ++// with a newline appended. ++@interface NSFileHandle (GTMFileHandleLogWriter) ++// Opens the file at |path| in append mode, and creates the file with |mode| ++// if it didn't previously exist. +++ (id)fileHandleForLoggingAtPath:(NSString *)path mode:(mode_t)mode; ++@end // NSFileHandle ++ ++ ++// This category makes NSArray a GTMLogWriter that can be composed of other ++// GTMLogWriters. This is the classic Composite GoF design pattern. When the ++// GTMLogWriter -logMessage:level: message is sent to the array, the array ++// forwards the message to all of its elements that implement the GTMLogWriter ++// protocol. ++// ++// This is useful in situations where you would like to send log output to ++// multiple log writers at the same time. Simply create an NSArray of the log ++// writers you wish to use, then set the array as the "writer" for your ++// GTMLogger instance. ++@interface NSArray (GTMArrayCompositeLogWriter) ++@end // GTMArrayCompositeLogWriter ++ ++ ++// This category adapts the GTMLogger interface so that it can be used as a log ++// writer; it's an "adapter" in the GoF Adapter pattern sense. ++// ++// This is useful when you want to configure a logger to log to a specific ++// writer with a specific formatter and/or filter. But you want to also compose ++// that with a different log writer that may have its own formatter and/or ++// filter. ++@interface GTMLogger (GTMLoggerLogWriter) ++@end // GTMLoggerLogWriter ++ ++ ++// ++// Log Formatters ++// ++ ++// Protocol to be implemented by a GTMLogFormatter instance. ++@protocol GTMLogFormatter ++// Returns a formatted string using the format specified in |fmt| and the va ++// args specified in |args|. ++- (NSString *)stringForFunc:(NSString *)func ++ withFormat:(NSString *)fmt ++ valist:(va_list)args ++ level:(GTMLoggerLevel)level; ++@end // GTMLogFormatter ++ ++ ++// A basic log formatter that formats a string the same way that NSLog (or ++// printf) would. It does not do anything fancy, nor does it add any data of its ++// own. ++@interface GTMLogBasicFormatter : NSObject ++@end // GTMLogBasicFormatter ++ ++ ++// A log formatter that formats the log string like the basic formatter, but ++// also prepends a timestamp and some basic process info to the message, as ++// shown in the following sample output. ++// 2007-12-30 10:29:24.177 myapp[4588/0xa07d0f60] [lvl=1] log mesage here ++@interface GTMLogStandardFormatter : GTMLogBasicFormatter { ++ @private ++ NSDateFormatter *dateFormatter_; // yyyy-MM-dd HH:mm:ss.SSS ++ NSString *pname_; ++ pid_t pid_; ++} ++@end // GTMLogStandardFormatter ++ ++ ++// ++// Log Filters ++// ++ ++// Protocol to be imlemented by a GTMLogFilter instance. ++@protocol GTMLogFilter ++// Returns YES if |msg| at |level| should be filtered out; NO otherwise. ++- (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level; ++@end // GTMLogFilter ++ ++ ++// A log filter that filters messages at the kGTMLoggerLevelDebug level out of ++// non-debug builds. Messages at the kGTMLoggerLevelInfo level are also filtered ++// out of non-debug builds unless GTMVerboseLogging is set in the environment or ++// the processes's defaults. Messages at the kGTMLoggerLevelError level are ++// never filtered. ++@interface GTMLogLevelFilter : NSObject ++@end // GTMLogLevelFilter ++ ++ ++// A simple log filter that does NOT filter anything out; ++// -filterAllowsMessage:level will always return YES. This can be a convenient ++// way to enable debug-level logging in release builds (if you so desire). ++@interface GTMLogNoFilter : NSObject ++@end // GTMLogNoFilter +diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/GTMLogger.m b/toolkit/crashreporter/google-breakpad/src/common/mac/GTMLogger.m +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/mac/GTMLogger.m +@@ -0,0 +1,445 @@ ++// ++// GTMLogger.m ++// ++// Copyright 2007-2008 Google Inc. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); you may not ++// use this file except in compliance with the License. You may obtain a copy ++// of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT ++// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the ++// License for the specific language governing permissions and limitations under ++// the License. ++// ++ ++#import "GTMLogger.h" ++#import "GTMGarbageCollection.h" ++#import ++#import ++#import ++#import ++ ++ ++// Define a trivial assertion macro to avoid dependencies ++#ifdef DEBUG ++ #define GTMLOGGER_ASSERT(expr) assert(expr) ++#else ++ #define GTMLOGGER_ASSERT(expr) ++#endif ++ ++ ++@interface GTMLogger (PrivateMethods) ++ ++- (void)logInternalFunc:(const char *)func ++ format:(NSString *)fmt ++ valist:(va_list)args ++ level:(GTMLoggerLevel)level; ++ ++@end ++ ++ ++// Reference to the shared GTMLogger instance. This is not a singleton, it's ++// just an easy reference to one shared instance. ++static GTMLogger *gSharedLogger = nil; ++ ++ ++@implementation GTMLogger ++ ++// Returns a pointer to the shared logger instance. If none exists, a standard ++// logger is created and returned. +++ (id)sharedLogger { ++ @synchronized(self) { ++ if (gSharedLogger == nil) { ++ gSharedLogger = [[self standardLogger] retain]; ++ } ++ GTMLOGGER_ASSERT(gSharedLogger != nil); ++ } ++ return [[gSharedLogger retain] autorelease]; ++} ++ +++ (void)setSharedLogger:(GTMLogger *)logger { ++ @synchronized(self) { ++ [gSharedLogger autorelease]; ++ gSharedLogger = [logger retain]; ++ } ++} ++ +++ (id)standardLogger { ++ id writer = [NSFileHandle fileHandleWithStandardOutput]; ++ id fr = [[[GTMLogStandardFormatter alloc] init] autorelease]; ++ id filter = [[[GTMLogLevelFilter alloc] init] autorelease]; ++ return [self loggerWithWriter:writer formatter:fr filter:filter]; ++} ++ +++ (id)standardLoggerWithStderr { ++ id me = [self standardLogger]; ++ [me setWriter:[NSFileHandle fileHandleWithStandardError]]; ++ return me; ++} ++ +++ (id)standardLoggerWithPath:(NSString *)path { ++ NSFileHandle *fh = [NSFileHandle fileHandleForLoggingAtPath:path mode:0644]; ++ if (fh == nil) return nil; ++ id me = [self standardLogger]; ++ [me setWriter:fh]; ++ return me; ++} ++ +++ (id)loggerWithWriter:(id)writer ++ formatter:(id)formatter ++ filter:(id)filter { ++ return [[[self alloc] initWithWriter:writer ++ formatter:formatter ++ filter:filter] autorelease]; ++} ++ +++ (id)logger { ++ return [[[self alloc] init] autorelease]; ++} ++ ++- (id)init { ++ return [self initWithWriter:nil formatter:nil filter:nil]; ++} ++ ++- (id)initWithWriter:(id)writer ++ formatter:(id)formatter ++ filter:(id)filter { ++ if ((self = [super init])) { ++ [self setWriter:writer]; ++ [self setFormatter:formatter]; ++ [self setFilter:filter]; ++ GTMLOGGER_ASSERT(formatter_ != nil); ++ GTMLOGGER_ASSERT(filter_ != nil); ++ GTMLOGGER_ASSERT(writer_ != nil); ++ } ++ return self; ++} ++ ++- (void)dealloc { ++ GTMLOGGER_ASSERT(writer_ != nil); ++ GTMLOGGER_ASSERT(formatter_ != nil); ++ GTMLOGGER_ASSERT(filter_ != nil); ++ [writer_ release]; ++ [formatter_ release]; ++ [filter_ release]; ++ [super dealloc]; ++} ++ ++- (id)writer { ++ GTMLOGGER_ASSERT(writer_ != nil); ++ return [[writer_ retain] autorelease]; ++} ++ ++- (void)setWriter:(id)writer { ++ @synchronized(self) { ++ [writer_ autorelease]; ++ if (writer == nil) ++ writer_ = [[NSFileHandle fileHandleWithStandardOutput] retain]; ++ else ++ writer_ = [writer retain]; ++ } ++ GTMLOGGER_ASSERT(writer_ != nil); ++} ++ ++- (id)formatter { ++ GTMLOGGER_ASSERT(formatter_ != nil); ++ return [[formatter_ retain] autorelease]; ++} ++ ++- (void)setFormatter:(id)formatter { ++ @synchronized(self) { ++ [formatter_ autorelease]; ++ if (formatter == nil) ++ formatter_ = [[GTMLogBasicFormatter alloc] init]; ++ else ++ formatter_ = [formatter retain]; ++ } ++ GTMLOGGER_ASSERT(formatter_ != nil); ++} ++ ++- (id)filter { ++ GTMLOGGER_ASSERT(filter_ != nil); ++ return [[filter_ retain] autorelease]; ++} ++ ++- (void)setFilter:(id)filter { ++ @synchronized(self) { ++ [filter_ autorelease]; ++ if (filter == nil) ++ filter_ = [[GTMLogNoFilter alloc] init]; ++ else ++ filter_ = [filter retain]; ++ } ++ GTMLOGGER_ASSERT(filter_ != nil); ++} ++ ++- (void)logDebug:(NSString *)fmt, ... { ++ va_list args; ++ va_start(args, fmt); ++ [self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelDebug]; ++ va_end(args); ++} ++ ++- (void)logInfo:(NSString *)fmt, ... { ++ va_list args; ++ va_start(args, fmt); ++ [self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelInfo]; ++ va_end(args); ++} ++ ++- (void)logError:(NSString *)fmt, ... { ++ va_list args; ++ va_start(args, fmt); ++ [self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelError]; ++ va_end(args); ++} ++ ++- (void)logAssert:(NSString *)fmt, ... { ++ va_list args; ++ va_start(args, fmt); ++ [self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelAssert]; ++ va_end(args); ++} ++ ++@end // GTMLogger ++ ++ ++@implementation GTMLogger (GTMLoggerMacroHelpers) ++ ++- (void)logFuncDebug:(const char *)func msg:(NSString *)fmt, ... { ++ va_list args; ++ va_start(args, fmt); ++ [self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelDebug]; ++ va_end(args); ++} ++ ++- (void)logFuncInfo:(const char *)func msg:(NSString *)fmt, ... { ++ va_list args; ++ va_start(args, fmt); ++ [self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelInfo]; ++ va_end(args); ++} ++ ++- (void)logFuncError:(const char *)func msg:(NSString *)fmt, ... { ++ va_list args; ++ va_start(args, fmt); ++ [self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelError]; ++ va_end(args); ++} ++ ++- (void)logFuncAssert:(const char *)func msg:(NSString *)fmt, ... { ++ va_list args; ++ va_start(args, fmt); ++ [self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelAssert]; ++ va_end(args); ++} ++ ++@end // GTMLoggerMacroHelpers ++ ++ ++@implementation GTMLogger (PrivateMethods) ++ ++- (void)logInternalFunc:(const char *)func ++ format:(NSString *)fmt ++ valist:(va_list)args ++ level:(GTMLoggerLevel)level { ++ GTMLOGGER_ASSERT(formatter_ != nil); ++ GTMLOGGER_ASSERT(filter_ != nil); ++ GTMLOGGER_ASSERT(writer_ != nil); ++ ++ NSString *fname = func ? [NSString stringWithUTF8String:func] : nil; ++ NSString *msg = [formatter_ stringForFunc:fname ++ withFormat:fmt ++ valist:args ++ level:level]; ++ if (msg && [filter_ filterAllowsMessage:msg level:level]) ++ [writer_ logMessage:msg level:level]; ++} ++ ++@end // PrivateMethods ++ ++ ++@implementation NSFileHandle (GTMFileHandleLogWriter) ++ +++ (id)fileHandleForLoggingAtPath:(NSString *)path mode:(mode_t)mode { ++ int fd = -1; ++ if (path) { ++ int flags = O_WRONLY | O_APPEND | O_CREAT; ++ fd = open([path fileSystemRepresentation], flags, mode); ++ } ++ if (fd == -1) return nil; ++ return [[[self alloc] initWithFileDescriptor:fd ++ closeOnDealloc:YES] autorelease]; ++} ++ ++- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level { ++ @synchronized(self) { ++ NSString *line = [NSString stringWithFormat:@"%@\n", msg]; ++ [self writeData:[line dataUsingEncoding:NSUTF8StringEncoding]]; ++ } ++} ++ ++@end // GTMFileHandleLogWriter ++ ++ ++@implementation NSArray (GTMArrayCompositeLogWriter) ++ ++- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level { ++ @synchronized(self) { ++ id child = nil; ++ GTM_FOREACH_OBJECT(child, self) { ++ if ([child conformsToProtocol:@protocol(GTMLogWriter)]) ++ [child logMessage:msg level:level]; ++ } ++ } ++} ++ ++@end // GTMArrayCompositeLogWriter ++ ++ ++@implementation GTMLogger (GTMLoggerLogWriter) ++ ++- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level { ++ switch (level) { ++ case kGTMLoggerLevelDebug: ++ [self logDebug:@"%@", msg]; ++ break; ++ case kGTMLoggerLevelInfo: ++ [self logInfo:@"%@", msg]; ++ break; ++ case kGTMLoggerLevelError: ++ [self logError:@"%@", msg]; ++ break; ++ case kGTMLoggerLevelAssert: ++ [self logAssert:@"%@", msg]; ++ break; ++ default: ++ // Ignore the message. ++ break; ++ } ++} ++ ++@end // GTMLoggerLogWriter ++ ++ ++@implementation GTMLogBasicFormatter ++ ++- (NSString *)stringForFunc:(NSString *)func ++ withFormat:(NSString *)fmt ++ valist:(va_list)args ++ level:(GTMLoggerLevel)level { ++ // Performance note: since we always have to create a new NSString from the ++ // returned CFStringRef, we may want to do a quick check here to see if |fmt| ++ // contains a '%', and if not, simply return 'fmt'. ++ CFStringRef cfmsg = NULL; ++ cfmsg = CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, ++ NULL, // format options ++ (CFStringRef)fmt, ++ args); ++ return GTMCFAutorelease(cfmsg); ++} ++ ++@end // GTMLogBasicFormatter ++ ++ ++@implementation GTMLogStandardFormatter ++ ++- (id)init { ++ if ((self = [super init])) { ++ dateFormatter_ = [[NSDateFormatter alloc] init]; ++ [dateFormatter_ setFormatterBehavior:NSDateFormatterBehavior10_4]; ++ [dateFormatter_ setDateFormat:@"yyyy-MM-dd HH:mm:ss.SSS"]; ++ pname_ = [[[NSProcessInfo processInfo] processName] copy]; ++ pid_ = [[NSProcessInfo processInfo] processIdentifier]; ++ } ++ return self; ++} ++ ++- (void)dealloc { ++ [dateFormatter_ release]; ++ [pname_ release]; ++ [super dealloc]; ++} ++ ++- (NSString *)stringForFunc:(NSString *)func ++ withFormat:(NSString *)fmt ++ valist:(va_list)args ++ level:(GTMLoggerLevel)level { ++ GTMLOGGER_ASSERT(dateFormatter_ != nil); ++ NSString *tstamp = nil; ++ @synchronized (dateFormatter_) { ++ tstamp = [dateFormatter_ stringFromDate:[NSDate date]]; ++ } ++ return [NSString stringWithFormat:@"%@ %@[%d/%p] [lvl=%d] %@ %@", ++ tstamp, pname_, pid_, pthread_self(), ++ level, (func ? func : @"(no func)"), ++ [super stringForFunc:func withFormat:fmt valist:args level:level]]; ++} ++ ++@end // GTMLogStandardFormatter ++ ++ ++@implementation GTMLogLevelFilter ++ ++// Check the environment and the user preferences for the GTMVerboseLogging key ++// to see if verbose logging has been enabled. The environment variable will ++// override the defaults setting, so check the environment first. ++// COV_NF_START ++static BOOL IsVerboseLoggingEnabled(void) { ++ static NSString *const kVerboseLoggingKey = @"GTMVerboseLogging"; ++ static char *env = NULL; ++ if (env == NULL) ++ env = getenv([kVerboseLoggingKey UTF8String]); ++ ++ if (env && env[0]) { ++ return (strtol(env, NULL, 10) != 0); ++ } ++ ++ return [[NSUserDefaults standardUserDefaults] boolForKey:kVerboseLoggingKey]; ++} ++// COV_NF_END ++ ++// In DEBUG builds, log everything. If we're not in a debug build we'll assume ++// that we're in a Release build. ++- (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level { ++#if DEBUG ++ return YES; ++#endif ++ ++ BOOL allow = YES; ++ ++ switch (level) { ++ case kGTMLoggerLevelDebug: ++ allow = NO; ++ break; ++ case kGTMLoggerLevelInfo: ++ allow = (IsVerboseLoggingEnabled() == YES); ++ break; ++ case kGTMLoggerLevelError: ++ allow = YES; ++ break; ++ case kGTMLoggerLevelAssert: ++ allow = YES; ++ break; ++ default: ++ allow = YES; ++ break; ++ } ++ ++ return allow; ++} ++ ++@end // GTMLogLevelFilter ++ ++ ++@implementation GTMLogNoFilter ++ ++- (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level { ++ return YES; // Allow everything through ++} ++ ++@end // GTMLogNoFilter +diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.h b/toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.h +@@ -0,0 +1,304 @@ ++// Copyright (c) 2007, 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. ++// ++// MachIPC.h ++// ++// Some helpful wrappers for using Mach IPC calls ++ ++#ifndef MACH_IPC_H__ ++#define MACH_IPC_H__ ++ ++#import ++#import ++#import ++#import ++ ++#import ++ ++//============================================================================== ++// DISCUSSION: ++// ++// The three main classes of interest are ++// ++// MachMessage: a wrapper for a mach message of the following form ++// mach_msg_header_t ++// mach_msg_body_t ++// optional descriptors ++// optional extra message data ++// ++// MachReceiveMessage and MachSendMessage subclass MachMessage ++// and are used instead of MachMessage which is an abstract base class ++// ++// ReceivePort: ++// Represents a mach port for which we have receive rights ++// ++// MachPortSender: ++// Represents a mach port for which we have send rights ++// ++// Here's an example to receive a message on a server port: ++// ++// // This creates our named server port ++// ReceivePort receivePort("com.Google.MyService"); ++// ++// MachReceiveMessage message; ++// kern_return_t result = receivePort.WaitForMessage(&message, 0); ++// ++// if (result == KERN_SUCCESS && message.GetMessageID() == 57) { ++// mach_port_t task = message.GetTranslatedPort(0); ++// mach_port_t thread = message.GetTranslatedPort(1); ++// ++// char *messageString = message.GetData(); ++// ++// printf("message string = %s\n", messageString); ++// } ++// ++// Here is an example of using these classes to send a message to this port: ++// ++// // send to already named port ++// MachPortSender sender("com.Google.MyService"); ++// MachSendMessage message(57); // our message ID is 57 ++// ++// // add some ports to be translated for us ++// message.AddDescriptor(mach_task_self()); // our task ++// message.AddDescriptor(mach_thread_self()); // this thread ++// ++// char messageString[] = "Hello server!\n"; ++// message.SetData(messageString, strlen(messageString)+1); ++// ++// kern_return_t result = sender.SendMessage(message, 1000); // timeout 1000ms ++// ++ ++#define PRINT_MACH_RESULT(result_, message_) \ ++ printf(message_" %s (%d)\n", mach_error_string(result_), result_ ); ++ ++//============================================================================== ++// A wrapper class for mach_msg_port_descriptor_t (with same memory layout) ++// with convenient constructors and accessors ++class MachMsgPortDescriptor : public mach_msg_port_descriptor_t { ++ public: ++ // General-purpose constructor ++ MachMsgPortDescriptor(mach_port_t in_name, ++ mach_msg_type_name_t in_disposition) { ++ name = in_name; ++ pad1 = 0; ++ pad2 = 0; ++ disposition = in_disposition; ++ type = MACH_MSG_PORT_DESCRIPTOR; ++ } ++ ++ // For passing send rights to a port ++ MachMsgPortDescriptor(mach_port_t in_name) { ++ name = in_name; ++ pad1 = 0; ++ pad2 = 0; ++ disposition = MACH_MSG_TYPE_COPY_SEND; ++ type = MACH_MSG_PORT_DESCRIPTOR; ++ } ++ ++ // Copy constructor ++ MachMsgPortDescriptor(const MachMsgPortDescriptor& desc) { ++ name = desc.name; ++ pad1 = desc.pad1; ++ pad2 = desc.pad2; ++ disposition = desc.disposition; ++ type = desc.type; ++ } ++ ++ mach_port_t GetMachPort() const { ++ return name; ++ } ++ ++ mach_msg_type_name_t GetDisposition() const { ++ return disposition; ++ } ++ ++ // We're just a simple wrapper for mach_msg_port_descriptor_t ++ // and have the same memory layout ++ operator mach_msg_port_descriptor_t&() { ++ return *this; ++ } ++ ++ // For convenience ++ operator mach_port_t() const { ++ return GetMachPort(); ++ } ++}; ++ ++//============================================================================== ++// MachMessage: a wrapper for a mach message ++// (mach_msg_header_t, mach_msg_body_t, extra data) ++// ++// This considerably simplifies the construction of a message for sending ++// and the getting at relevant data and descriptors for the receiver. ++// ++// Currently the combined size of the descriptors plus data must be ++// less than 1024. But as a benefit no memory allocation is necessary. ++// ++// TODO: could consider adding malloc() support for very large messages ++// ++// A MachMessage object is used by ReceivePort::WaitForMessage ++// and MachPortSender::SendMessage ++// ++class MachMessage { ++ public: ++ ++ // The receiver of the message can retrieve the raw data this way ++ u_int8_t *GetData() { ++ return GetDataLength() > 0 ? GetDataPacket()->data : NULL; ++ } ++ ++ u_int32_t GetDataLength() { ++ return EndianU32_LtoN(GetDataPacket()->data_length); ++ } ++ ++ // The message ID may be used as a code identifying the type of message ++ void SetMessageID(int32_t message_id) { ++ GetDataPacket()->id = EndianU32_NtoL(message_id); ++ } ++ ++ int32_t GetMessageID() { return EndianU32_LtoN(GetDataPacket()->id); } ++ ++ // Adds a descriptor (typically a mach port) to be translated ++ // returns true if successful, otherwise not enough space ++ bool AddDescriptor(const MachMsgPortDescriptor &desc); ++ ++ int GetDescriptorCount() const { return body.msgh_descriptor_count; } ++ MachMsgPortDescriptor *GetDescriptor(int n); ++ ++ // Convenience method which gets the mach port described by the descriptor ++ mach_port_t GetTranslatedPort(int n); ++ ++ // A simple message is one with no descriptors ++ bool IsSimpleMessage() const { return GetDescriptorCount() == 0; } ++ ++ // Sets raw data for the message (returns false if not enough space) ++ bool SetData(void *data, int32_t data_length); ++ ++ protected: ++ // Consider this an abstract base class - must create an actual instance ++ // of MachReceiveMessage or MachSendMessage ++ ++ MachMessage() { ++ memset(this, 0, sizeof(MachMessage)); ++ } ++ ++ friend class ReceivePort; ++ friend class MachPortSender; ++ ++ // Represents raw data in our message ++ struct MessageDataPacket { ++ int32_t id; // little-endian ++ int32_t data_length; // little-endian ++ u_int8_t data[1]; // actual size limited by sizeof(MachMessage) ++ }; ++ ++ MessageDataPacket* GetDataPacket(); ++ ++ void SetDescriptorCount(int n); ++ void SetDescriptor(int n, const MachMsgPortDescriptor &desc); ++ ++ // Returns total message size setting msgh_size in the header to this value ++ int CalculateSize(); ++ ++ mach_msg_header_t head; ++ mach_msg_body_t body; ++ u_int8_t padding[1024]; // descriptors and data may be embedded here ++}; ++ ++//============================================================================== ++// MachReceiveMessage and MachSendMessage are useful to separate the idea ++// of a mach message being sent and being received, and adds increased type ++// safety: ++// ReceivePort::WaitForMessage() only accepts a MachReceiveMessage ++// MachPortSender::SendMessage() only accepts a MachSendMessage ++ ++//============================================================================== ++class MachReceiveMessage : public MachMessage { ++ public: ++ MachReceiveMessage() : MachMessage() {}; ++}; ++ ++//============================================================================== ++class MachSendMessage : public MachMessage { ++ public: ++ MachSendMessage(int32_t message_id); ++}; ++ ++//============================================================================== ++// Represents a mach port for which we have receive rights ++class ReceivePort { ++ public: ++ // Creates a new mach port for receiving messages and registers a name for it ++ ReceivePort(const char *receive_port_name); ++ ++ // Given an already existing mach port, use it. We take ownership of the ++ // port and deallocate it in our destructor. ++ ReceivePort(mach_port_t receive_port); ++ ++ // Create a new mach port for receiving messages ++ ReceivePort(); ++ ++ ~ReceivePort(); ++ ++ // Waits on the mach port until message received or timeout ++ kern_return_t WaitForMessage(MachReceiveMessage *out_message, ++ mach_msg_timeout_t timeout); ++ ++ // The underlying mach port that we wrap ++ mach_port_t GetPort() const { return port_; } ++ ++ private: ++ ReceivePort(const ReceivePort&); // disable copy c-tor ++ ++ mach_port_t port_; ++ kern_return_t init_result_; ++}; ++ ++//============================================================================== ++// Represents a mach port for which we have send rights ++class MachPortSender { ++ public: ++ // get a port with send rights corresponding to a named registered service ++ MachPortSender(const char *receive_port_name); ++ ++ ++ // Given an already existing mach port, use it. ++ MachPortSender(mach_port_t send_port); ++ ++ kern_return_t SendMessage(MachSendMessage &message, ++ mach_msg_timeout_t timeout); ++ ++ private: ++ MachPortSender(const MachPortSender&); // disable copy c-tor ++ ++ mach_port_t send_port_; ++ kern_return_t init_result_; ++}; ++ ++#endif // MACH_IPC_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.mm b/toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.mm +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.mm +@@ -0,0 +1,297 @@ ++// Copyright (c) 2007, 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. ++// ++// MachIPC.mm ++// Wrapper for mach IPC calls ++ ++#import ++#import "MachIPC.h" ++ ++//============================================================================== ++MachSendMessage::MachSendMessage(int32_t message_id) : MachMessage() { ++ head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0); ++ ++ // head.msgh_remote_port = ...; // filled out in MachPortSender::SendMessage() ++ head.msgh_local_port = MACH_PORT_NULL; ++ head.msgh_reserved = 0; ++ head.msgh_id = 0; ++ ++ SetDescriptorCount(0); // start out with no descriptors ++ ++ SetMessageID(message_id); ++ SetData(NULL, 0); // client may add data later ++} ++ ++//============================================================================== ++// returns true if successful ++bool MachMessage::SetData(void *data, ++ int32_t data_length) { ++ // first check to make sure we have enough space ++ int size = CalculateSize(); ++ int new_size = size + data_length; ++ ++ if ((unsigned)new_size > sizeof(MachMessage)) { ++ return false; // not enough space ++ } ++ ++ GetDataPacket()->data_length = EndianU32_NtoL(data_length); ++ if (data) memcpy(GetDataPacket()->data, data, data_length); ++ ++ CalculateSize(); ++ ++ return true; ++} ++ ++//============================================================================== ++// calculates and returns the total size of the message ++// Currently, the entire message MUST fit inside of the MachMessage ++// messsage size <= sizeof(MachMessage) ++int MachMessage::CalculateSize() { ++ int size = sizeof(mach_msg_header_t) + sizeof(mach_msg_body_t); ++ ++ // add space for MessageDataPacket ++ int32_t alignedDataLength = (GetDataLength() + 3) & ~0x3; ++ size += 2*sizeof(int32_t) + alignedDataLength; ++ ++ // add space for descriptors ++ size += GetDescriptorCount() * sizeof(MachMsgPortDescriptor); ++ ++ head.msgh_size = size; ++ ++ return size; ++} ++ ++//============================================================================== ++MachMessage::MessageDataPacket *MachMessage::GetDataPacket() { ++ int desc_size = sizeof(MachMsgPortDescriptor)*GetDescriptorCount(); ++ MessageDataPacket *packet = ++ reinterpret_cast(padding + desc_size); ++ ++ return packet; ++} ++ ++//============================================================================== ++void MachMessage::SetDescriptor(int n, ++ const MachMsgPortDescriptor &desc) { ++ MachMsgPortDescriptor *desc_array = ++ reinterpret_cast(padding); ++ desc_array[n] = desc; ++} ++ ++//============================================================================== ++// returns true if successful otherwise there was not enough space ++bool MachMessage::AddDescriptor(const MachMsgPortDescriptor &desc) { ++ // first check to make sure we have enough space ++ int size = CalculateSize(); ++ int new_size = size + sizeof(MachMsgPortDescriptor); ++ ++ if ((unsigned)new_size > sizeof(MachMessage)) { ++ return false; // not enough space ++ } ++ ++ // unfortunately, we need to move the data to allow space for the ++ // new descriptor ++ u_int8_t *p = reinterpret_cast(GetDataPacket()); ++ bcopy(p, p+sizeof(MachMsgPortDescriptor), GetDataLength()+2*sizeof(int32_t)); ++ ++ SetDescriptor(GetDescriptorCount(), desc); ++ SetDescriptorCount(GetDescriptorCount() + 1); ++ ++ CalculateSize(); ++ ++ return true; ++} ++ ++//============================================================================== ++void MachMessage::SetDescriptorCount(int n) { ++ body.msgh_descriptor_count = n; ++ ++ if (n > 0) { ++ head.msgh_bits |= MACH_MSGH_BITS_COMPLEX; ++ } else { ++ head.msgh_bits &= ~MACH_MSGH_BITS_COMPLEX; ++ } ++} ++ ++//============================================================================== ++MachMsgPortDescriptor *MachMessage::GetDescriptor(int n) { ++ if (n < GetDescriptorCount()) { ++ MachMsgPortDescriptor *desc = ++ reinterpret_cast(padding); ++ return desc + n; ++ } ++ ++ return nil; ++} ++ ++//============================================================================== ++mach_port_t MachMessage::GetTranslatedPort(int n) { ++ if (n < GetDescriptorCount()) { ++ return GetDescriptor(n)->GetMachPort(); ++ } ++ return MACH_PORT_NULL; ++} ++ ++#pragma mark - ++ ++//============================================================================== ++// create a new mach port for receiving messages and register a name for it ++ReceivePort::ReceivePort(const char *receive_port_name) { ++ mach_port_t current_task = mach_task_self(); ++ ++ init_result_ = mach_port_allocate(current_task, ++ MACH_PORT_RIGHT_RECEIVE, ++ &port_); ++ ++ if (init_result_ != KERN_SUCCESS) ++ return; ++ ++ init_result_ = mach_port_insert_right(current_task, ++ port_, ++ port_, ++ MACH_MSG_TYPE_MAKE_SEND); ++ ++ if (init_result_ != KERN_SUCCESS) ++ return; ++ ++ mach_port_t bootstrap_port = 0; ++ init_result_ = task_get_bootstrap_port(current_task, &bootstrap_port); ++ ++ if (init_result_ != KERN_SUCCESS) ++ return; ++ ++ init_result_ = bootstrap_register(bootstrap_port, ++ const_cast(receive_port_name), ++ port_); ++} ++ ++//============================================================================== ++// create a new mach port for receiving messages ++ReceivePort::ReceivePort() { ++ mach_port_t current_task = mach_task_self(); ++ ++ init_result_ = mach_port_allocate(current_task, ++ MACH_PORT_RIGHT_RECEIVE, ++ &port_); ++ ++ if (init_result_ != KERN_SUCCESS) ++ return; ++ ++ init_result_ = mach_port_insert_right(current_task, ++ port_, ++ port_, ++ MACH_MSG_TYPE_MAKE_SEND); ++} ++ ++//============================================================================== ++// Given an already existing mach port, use it. We take ownership of the ++// port and deallocate it in our destructor. ++ReceivePort::ReceivePort(mach_port_t receive_port) ++ : port_(receive_port), ++ init_result_(KERN_SUCCESS) { ++} ++ ++//============================================================================== ++ReceivePort::~ReceivePort() { ++ if (init_result_ == KERN_SUCCESS) ++ mach_port_deallocate(mach_task_self(), port_); ++} ++ ++//============================================================================== ++kern_return_t ReceivePort::WaitForMessage(MachReceiveMessage *out_message, ++ mach_msg_timeout_t timeout) { ++ if (!out_message) { ++ return KERN_INVALID_ARGUMENT; ++ } ++ ++ // return any error condition encountered in constructor ++ if (init_result_ != KERN_SUCCESS) ++ return init_result_; ++ ++ out_message->head.msgh_bits = 0; ++ out_message->head.msgh_local_port = port_; ++ out_message->head.msgh_remote_port = MACH_PORT_NULL; ++ out_message->head.msgh_reserved = 0; ++ out_message->head.msgh_id = 0; ++ ++ kern_return_t result = mach_msg(&out_message->head, ++ MACH_RCV_MSG | MACH_RCV_TIMEOUT, ++ 0, ++ sizeof(MachMessage), ++ port_, ++ timeout, // timeout in ms ++ MACH_PORT_NULL); ++ ++ return result; ++} ++ ++#pragma mark - ++ ++//============================================================================== ++// get a port with send rights corresponding to a named registered service ++MachPortSender::MachPortSender(const char *receive_port_name) { ++ mach_port_t bootstrap_port = 0; ++ init_result_ = task_get_bootstrap_port(mach_task_self(), &bootstrap_port); ++ ++ if (init_result_ != KERN_SUCCESS) ++ return; ++ ++ init_result_ = bootstrap_look_up(bootstrap_port, ++ const_cast(receive_port_name), ++ &send_port_); ++} ++ ++//============================================================================== ++MachPortSender::MachPortSender(mach_port_t send_port) ++ : send_port_(send_port), ++ init_result_(KERN_SUCCESS) { ++} ++ ++//============================================================================== ++kern_return_t MachPortSender::SendMessage(MachSendMessage &message, ++ mach_msg_timeout_t timeout) { ++ if (message.head.msgh_size == 0) { ++ return KERN_INVALID_VALUE; // just for safety -- never should occur ++ }; ++ ++ if (init_result_ != KERN_SUCCESS) ++ return init_result_; ++ ++ message.head.msgh_remote_port = send_port_; ++ ++ kern_return_t result = mach_msg(&message.head, ++ MACH_SEND_MSG | MACH_SEND_TIMEOUT, ++ message.head.msgh_size, ++ 0, ++ MACH_PORT_NULL, ++ timeout, // timeout in ms ++ MACH_PORT_NULL); ++ ++ return result; ++} +diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/Makefile.in b/toolkit/crashreporter/google-breakpad/src/common/mac/Makefile.in +--- a/toolkit/crashreporter/google-breakpad/src/common/mac/Makefile.in ++++ b/toolkit/crashreporter/google-breakpad/src/common/mac/Makefile.in +@@ -42,18 +42,16 @@ VPATH = @srcdir@ + include $(DEPTH)/config/autoconf.mk + + MODULE = breakpad_mac_common + LIBRARY_NAME = breakpad_mac_common_s + HOST_LIBRARY_NAME = host_breakpad_mac_common_s + + LOCAL_INCLUDES = -I$(srcdir)/../.. + +-DIRS = dwarf +- + # This is a little weird, but we're building a host and a target lib here. + # The host lib is used for dump_syms, and the target lib for the + # crash reporter client. Therefore, we don't need all the srcs in both. + CPPSRCS = \ + file_id.cc \ + macho_id.cc \ + macho_walker.cc \ + string_utilities.cc \ +diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/SimpleStringDictionary.h b/toolkit/crashreporter/google-breakpad/src/common/mac/SimpleStringDictionary.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/mac/SimpleStringDictionary.h +@@ -0,0 +1,195 @@ ++// Copyright (c) 2007, 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. ++// ++// SimpleStringDictionary.h ++// ++ ++#ifndef SimpleStringDictionary_H__ ++#define SimpleStringDictionary_H__ ++ ++#import ++#import ++ ++namespace google_breakpad { ++ ++//============================================================================== ++// SimpleStringDictionary (and associated class KeyValueEntry) implement a very ++// basic dictionary container class. It has the property of not making any ++// memory allocations when getting and setting values. But it is not very ++// efficient, with calls to get and set values operating in linear time. ++// It has the additional limitation of having a fairly small fixed capacity of ++// SimpleStringDictionary::MAX_NUM_ENTRIES entries. An assert() will fire if ++// the client attempts to set more than this number of key/value pairs. ++// Ordinarilly a C++ programmer would use something like the std::map template ++// class, or on the Macintosh would often choose CFDictionary or NSDictionary. ++// But these dictionary classes may call malloc() during get and set operations. ++// Google Breakpad requires that no memory allocations be made in code running ++// in its exception handling thread, so it uses SimpleStringDictionary as the ++// underlying implementation for the GoogleBreakpad.framework APIs: ++// GoogleBreakpadSetKeyValue(), GoogleBreakpadKeyValue(), and ++// GoogleBreakpadRemoveKeyValue() ++// ++ ++//============================================================================== ++// KeyValueEntry ++// ++// A helper class used by SimpleStringDictionary representing a single ++// storage cell for a key/value pair. Each key and value string are ++// limited to MAX_STRING_STORAGE_SIZE-1 bytes (not glyphs). This class ++// performs no memory allocations. It has methods for setting and getting ++// key and value strings. ++// ++class KeyValueEntry { ++ public: ++ KeyValueEntry() { ++ Clear(); ++ } ++ ++ KeyValueEntry(const char *key, const char *value) { ++ SetKeyValue(key, value); ++ } ++ ++ void SetKeyValue(const char *key, const char *value) { ++ if (!key) { ++ key = ""; ++ } ++ if (!value) { ++ value = ""; ++ } ++ ++ strlcpy(key_, key, sizeof(key_)); ++ strlcpy(value_, value, sizeof(value_)); ++ } ++ ++ void SetValue(const char *value) { ++ if (!value) { ++ value = ""; ++ } ++ strlcpy(value_, value, sizeof(value_)); ++ }; ++ ++ // Removes the key/value ++ void Clear() { ++ memset(key_, 0, sizeof(key_)); ++ memset(value_, 0, sizeof(value_)); ++ } ++ ++ bool IsActive() const { return key_[0] != '\0'; } ++ const char *GetKey() const { return key_; } ++ const char *GetValue() const { return value_; } ++ ++ // Don't change this without considering the fixed size ++ // of MachMessage (in MachIPC.h) ++ // (see also struct KeyValueMessageData in Inspector.h) ++ enum {MAX_STRING_STORAGE_SIZE = 256}; ++ ++ private: ++ char key_[MAX_STRING_STORAGE_SIZE]; ++ char value_[MAX_STRING_STORAGE_SIZE]; ++}; ++ ++//============================================================================== ++// This class is not an efficient dictionary, but for the purposes of breakpad ++// will be just fine. We're just dealing with ten or so distinct ++// key/value pairs. The idea is to avoid any malloc() or free() calls ++// in certain important methods to be called when a process is in a ++// crashed state. Each key and value string are limited to ++// KeyValueEntry::MAX_STRING_STORAGE_SIZE-1 bytes (not glyphs). Strings passed ++// in exceeding this length will be truncated. ++// ++class SimpleStringDictionary { ++ public: ++ SimpleStringDictionary() {}; // entries will all be cleared ++ ++ // Returns the number of active key/value pairs. The upper limit for this ++ // is MAX_NUM_ENTRIES. ++ int GetCount() const; ++ ++ // Given |key|, returns its corresponding |value|. ++ // If |key| is NULL, an assert will fire or NULL will be returned. If |key| ++ // is not found or is an empty string, NULL is returned. ++ const char *GetValueForKey(const char *key); ++ ++ // Stores a string |value| represented by |key|. If |key| is NULL or an empty ++ // string, this will assert (or do nothing). If |value| is NULL then ++ // the |key| will be removed. An empty string is OK for |value|. ++ void SetKeyValue(const char *key, const char *value); ++ ++ // Given |key|, removes any associated value. It will assert (or do nothing) ++ // if NULL is passed in. It will do nothing if |key| is not found. ++ void RemoveKey(const char *key); ++ ++ // This is the maximum number of key/value pairs which may be set in the ++ // dictionary. An assert may fire if more values than this are set. ++ // Don't change this without also changing comment in GoogleBreakpad.h ++ enum {MAX_NUM_ENTRIES = 64}; ++ ++ private: ++ friend class SimpleStringDictionaryIterator; ++ ++ const KeyValueEntry *GetEntry(int i) const; ++ ++ KeyValueEntry entries_[MAX_NUM_ENTRIES]; ++}; ++ ++//============================================================================== ++class SimpleStringDictionaryIterator { ++ public: ++ SimpleStringDictionaryIterator(const SimpleStringDictionary &dict) ++ : dict_(dict), i_(0) { ++ } ++ ++ // Initializes iterator to the beginning (may later call Next() ) ++ void Start() { ++ i_ = 0; ++ } ++ ++ // like the nextObject method of NSEnumerator (in Cocoa) ++ // returns NULL when there are no more entries ++ // ++ const KeyValueEntry* Next() { ++ for (; i_ < SimpleStringDictionary::MAX_NUM_ENTRIES; ++i_) { ++ const KeyValueEntry *entry = dict_.GetEntry(i_); ++ if (entry->IsActive()) { ++ i_++; // move to next entry for next time ++ return entry; ++ } ++ } ++ ++ return NULL; // reached end of array ++ } ++ ++ private: ++ const SimpleStringDictionary& dict_; ++ int i_; ++}; ++ ++} // namespace google_breakpad ++ ++#endif // SimpleStringDictionary_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/SimpleStringDictionary.mm b/toolkit/crashreporter/google-breakpad/src/common/mac/SimpleStringDictionary.mm +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/mac/SimpleStringDictionary.mm +@@ -0,0 +1,133 @@ ++// Copyright (c) 2007, 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. ++// ++// SimpleStringDictionary.mm ++// Simple string dictionary that does not allocate memory ++// ++ ++#include ++ ++#import "SimpleStringDictionary.h" ++ ++namespace google_breakpad { ++ ++//============================================================================== ++const KeyValueEntry *SimpleStringDictionary::GetEntry(int i) const { ++ return (i >= 0 && i < MAX_NUM_ENTRIES) ? &entries_[i] : NULL; ++} ++ ++//============================================================================== ++int SimpleStringDictionary::GetCount() const { ++ int count = 0; ++ for (int i = 0; i < MAX_NUM_ENTRIES; ++i) { ++ if (entries_[i].IsActive() ) { ++ ++count; ++ } ++ } ++ ++ return count; ++} ++ ++//============================================================================== ++const char *SimpleStringDictionary::GetValueForKey(const char *key) { ++ assert(key); ++ if (!key) ++ return NULL; ++ ++ for (int i = 0; i < MAX_NUM_ENTRIES; ++i) { ++ KeyValueEntry &entry = entries_[i]; ++ if (entry.IsActive() && !strcmp(entry.GetKey(), key)) { ++ return entry.GetValue(); ++ } ++ } ++ ++ return NULL; ++} ++ ++//============================================================================== ++void SimpleStringDictionary::SetKeyValue(const char *key, ++ const char *value) { ++ if (!value) { ++ RemoveKey(key); ++ return; ++ } ++ ++ // key must not be NULL ++ assert(key); ++ if (!key) ++ return; ++ ++ // key must not be empty string ++ assert(key[0] != '\0'); ++ if (key[0] == '\0') ++ return; ++ ++ int free_index = -1; ++ ++ // check if key already exists ++ for (int i = 0; i < MAX_NUM_ENTRIES; ++i) { ++ KeyValueEntry &entry = entries_[i]; ++ ++ if (entry.IsActive()) { ++ if (!strcmp(entry.GetKey(), key)) { ++ entry.SetValue(value); ++ return; ++ } ++ } else { ++ // Make a note of an empty slot ++ if (free_index == -1) { ++ free_index = i; ++ } ++ } ++ } ++ ++ // check if we've run out of space ++ assert(free_index != -1); ++ ++ // Put new key into an empty slot (if found) ++ if (free_index != -1) { ++ entries_[free_index].SetKeyValue(key, value); ++ } ++} ++ ++//============================================================================== ++void SimpleStringDictionary::RemoveKey(const char *key) { ++ assert(key); ++ if (!key) ++ return; ++ ++ for (int i = 0; i < MAX_NUM_ENTRIES; ++i) { ++ if (!strcmp(entries_[i].GetKey(), key)) { ++ entries_[i].Clear(); ++ return; ++ } ++ } ++} ++ ++} // namespace google_breakpad +diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.h b/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.h +--- a/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.h ++++ b/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.h +@@ -28,21 +28,21 @@ + // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + // dump_syms.h: Interface for DumpSymbols. This class will take a mach-o file + // and extract the symbol information and write it to a file using the + // breakpad symbol file format. + + #import + #include +-#include "common/mac/dwarf/dwarf2reader.h" ++#include "common/dwarf/dwarf2reader.h" + + // This will map from an architecture string to a SectionMap, which + // will contain the offsets for all the sections in the dictionary +-typedef hash_map ArchSectionMap; ++typedef map ArchSectionMap; + + @interface DumpSymbols : NSObject { + @protected + NSString *sourcePath_; // Source of symbols (STRONG) + NSString *architecture_; // Architecture to extract (STRONG) + NSMutableDictionary *addresses_; // Addresses and symbols (STRONG) + NSMutableSet *functionAddresses_; // Function addresses (STRONG) + NSMutableDictionary *sources_; // Address and Source file paths (STRONG) +diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.mm b/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.mm +--- a/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.mm ++++ b/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.mm +@@ -42,19 +42,19 @@ + #include + #include + + #import + + #import "dump_syms.h" + #import "common/mac/file_id.h" + #import "common/mac/macho_utilities.h" +-#import "common/mac/dwarf/dwarf2reader.h" +-#import "common/mac/dwarf/functioninfo.h" +-#import "common/mac/dwarf/bytereader.h" ++#import "common/dwarf/dwarf2reader.h" ++#import "common/dwarf/functioninfo.h" ++#import "common/dwarf/bytereader.h" + + using google_breakpad::FileID; + + static NSString *kAddressSymbolKey = @"symbol"; + static NSString *kAddressConvertedSymbolKey = @"converted_symbol"; + static NSString *kAddressSourceLineKey = @"line"; + static NSString *kFunctionSizeKey = @"size"; + static NSString *kFunctionFileKey = @"source_file"; +@@ -63,25 +63,16 @@ static NSString *kHeaderSizeKey = @"size + static NSString *kHeaderOffsetKey = @"offset"; // Offset to the header + static NSString *kHeaderIs64BitKey = @"is64"; + static NSString *kHeaderCPUTypeKey = @"cpuType"; + + // The section for __TEXT, __text seems to be always 1. This is useful + // for pruning out extraneous non-function symbols. + static const int kTextSection = 1; + +-namespace __gnu_cxx { +-template<> +- struct hash { +- size_t operator()(const std::string& k) const { +- return hash< const char* >()( k.c_str() ); +- } +-}; +-} +- + // Dump FunctionMap to stdout. Print address, function name, file + // name, line number, lowpc, and highpc if available. + void DumpFunctionMap(const dwarf2reader::FunctionMap function_map) { + for (dwarf2reader::FunctionMap::const_iterator iter = function_map.begin(); + iter != function_map.end(); ++iter) { + if (iter->second->name.empty()) { + continue; + } +@@ -316,42 +307,49 @@ void DumpFunctionMap(const dwarf2reader: + + #define SwapLongLongIfNeeded(a) (swap ? NXSwapLongLong(a) : (a)) + #define SwapLongIfNeeded(a) (swap ? NXSwapLong(a) : (a)) + #define SwapIntIfNeeded(a) (swap ? NXSwapInt(a) : (a)) + #define SwapShortIfNeeded(a) (swap ? NXSwapShort(a) : (a)) + + //============================================================================= + - (BOOL)loadSymbolInfo:(void *)base offset:(uint32_t)offset { ++ BOOL loadedStabs = [self loadSTABSSymbolInfo:base offset:offset]; ++ + NSMutableDictionary *archSections = [sectionData_ objectForKey:architecture_]; ++ BOOL loadedDWARF = NO; + if ([archSections objectForKey:@"__DWARF__debug_info"]) { + // Treat this this as debug information +- return [self loadDWARFSymbolInfo:base offset:offset]; ++ loadedDWARF = [self loadDWARFSymbolInfo:base offset:offset]; + } + +- return [self loadSTABSSymbolInfo:base offset:offset]; ++ return loadedDWARF || loadedStabs; + } + + //============================================================================= + - (BOOL)loadDWARFSymbolInfo:(void *)base offset:(uint32_t)offset { + + struct mach_header *header = (struct mach_header *) + ((uint32_t)base + offset); + BOOL swap = (header->magic == MH_CIGAM); + + NSMutableDictionary *archSections = [sectionData_ objectForKey:architecture_]; + assert (archSections != nil); + section *dbgInfoSection = [[archSections objectForKey:@"__DWARF__debug_info"] sectionPointer]; + uint32_t debugInfoSize = SwapLongIfNeeded(dbgInfoSection->size); + +- // i think this will break if run on a big-endian machine ++#if __BIG_ENDIAN__ ++ dwarf2reader::ByteReader byte_reader(swap ? ++ dwarf2reader::ENDIANNESS_LITTLE : ++ dwarf2reader::ENDIANNESS_BIG); ++#elif __LITTLE_ENDIAN__ + dwarf2reader::ByteReader byte_reader(swap ? + dwarf2reader::ENDIANNESS_BIG : + dwarf2reader::ENDIANNESS_LITTLE); +- ++#endif + uint64_t dbgOffset = 0; + + dwarf2reader::SectionMap* oneArchitectureSectionMap = [self getSectionMapForArchitecture:architecture_]; + + while (dbgOffset < debugInfoSize) { + // Prepare necessary objects. + dwarf2reader::FunctionMap off_to_funcinfo; + dwarf2reader::FunctionMap address_to_funcinfo; +diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/Makefile.in b/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/Makefile.in +deleted file mode 100644 +--- a/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/Makefile.in ++++ /dev/null +@@ -1,61 +0,0 @@ +-# ***** BEGIN LICENSE BLOCK ***** +-# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +-# +-# The contents of this file are subject to the Mozilla Public License Version +-# 1.1 (the "License"); you may not use this file except in compliance with +-# the License. You may obtain a copy of the License at +-# http://www.mozilla.org/MPL/ +-# +-# Software distributed under the License is distributed on an "AS IS" basis, +-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +-# for the specific language governing rights and limitations under the +-# License. +-# +-# The Original Code is Mozilla Breakpad integration +-# +-# The Initial Developer of the Original Code is +-# The Mozilla Foundation +-# Portions created by the Initial Developer are Copyright (C) 2008 +-# the Initial Developer. All Rights Reserved. +-# +-# Contributor(s): +-# Ted Mielczarek +-# +-# Alternatively, the contents of this file may be used under the terms of +-# either the GNU General Public License Version 2 or later (the "GPL"), or +-# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +-# in which case the provisions of the GPL or the LGPL are applicable instead +-# of those above. If you wish to allow use of your version of this file only +-# under the terms of either the GPL or the LGPL, and not to allow others to +-# use your version of this file under the terms of the MPL, indicate your +-# decision by deleting the provisions above and replace them with the notice +-# and other provisions required by the GPL or the LGPL. If you do not delete +-# the provisions above, a recipient may use your version of this file under +-# the terms of any one of the MPL, the GPL or the LGPL. +-# +-# ***** END LICENSE BLOCK ***** +- +-DEPTH = ../../../../../../.. +-topsrcdir = @top_srcdir@ +-srcdir = @srcdir@ +-VPATH = @srcdir@ +- +-include $(DEPTH)/config/autoconf.mk +- +-MODULE = breakpad_mac_dwarf +-HOST_LIBRARY_NAME = host_breakpad_mac_dwarf_s +- +-LOCAL_INCLUDES = -I$(srcdir)/../../.. +- +-HOST_CPPSRCS = \ +- bytereader.cc \ +- dwarf2reader.cc \ +- functioninfo.cc \ +- $(NULL) +- +-HOST_CXXFLAGS += -funsigned-char +- +-# need static lib +-FORCE_STATIC_LIB = 1 +- +-include $(topsrcdir)/config/rules.mk +diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/bytereader-inl.h b/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/bytereader-inl.h +deleted file mode 100644 +--- a/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/bytereader-inl.h ++++ /dev/null +@@ -1,141 +0,0 @@ +-// Copyright 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. +- +-#ifndef UTIL_DEBUGINFO_BYTEREADER_INL_H__ +-#define UTIL_DEBUGINFO_BYTEREADER_INL_H__ +- +-#include "common/mac/dwarf/bytereader.h" +- +-namespace dwarf2reader { +- +-inline uint8 ByteReader::ReadOneByte(const char* buffer) const { +- return buffer[0]; +-} +- +-inline uint16 ByteReader::ReadTwoBytes(const char* buffer) const { +- const uint16 buffer0 = static_cast(buffer[0]); +- const uint16 buffer1 = static_cast(buffer[1]); +- if (endian_ == ENDIANNESS_LITTLE) { +- return buffer0 | buffer1 << 8; +- } else { +- return buffer1 | buffer0 << 8; +- } +-} +- +-inline uint64 ByteReader::ReadFourBytes(const char* buffer) const { +- const uint32 buffer0 = static_cast(buffer[0]); +- const uint32 buffer1 = static_cast(buffer[1]); +- const uint32 buffer2 = static_cast(buffer[2]); +- const uint32 buffer3 = static_cast(buffer[3]); +- if (endian_ == ENDIANNESS_LITTLE) { +- return buffer0 | buffer1 << 8 | buffer2 << 16 | buffer3 << 24; +- } else { +- return buffer3 | buffer2 << 8 | buffer1 << 16 | buffer0 << 24; +- } +-} +- +-inline uint64 ByteReader::ReadEightBytes(const char* buffer) const { +- const uint64 buffer0 = static_cast(buffer[0]); +- const uint64 buffer1 = static_cast(buffer[1]); +- const uint64 buffer2 = static_cast(buffer[2]); +- const uint64 buffer3 = static_cast(buffer[3]); +- const uint64 buffer4 = static_cast(buffer[4]); +- const uint64 buffer5 = static_cast(buffer[5]); +- const uint64 buffer6 = static_cast(buffer[6]); +- const uint64 buffer7 = static_cast(buffer[7]); +- if (endian_ == ENDIANNESS_LITTLE) { +- return buffer0 | buffer1 << 8 | buffer2 << 16 | buffer3 << 24 | +- buffer4 << 32 | buffer5 << 40 | buffer6 << 48 | buffer7 << 56; +- } else { +- return buffer7 | buffer6 << 8 | buffer5 << 16 | buffer4 << 24 | +- buffer3 << 32 | buffer2 << 40 | buffer1 << 48 | buffer0 << 56; +- } +-} +- +-// Read an unsigned LEB128 number. Each byte contains 7 bits of +-// information, plus one bit saying whether the number continues or +-// not. +- +-inline uint64 ByteReader::ReadUnsignedLEB128(const char* buffer, +- size_t* len) const { +- uint64 result = 0; +- size_t num_read = 0; +- unsigned int shift = 0; +- unsigned char byte; +- +- do { +- byte = *buffer++; +- num_read++; +- +- result |= (static_cast(byte & 0x7f)) << shift; +- +- shift += 7; +- +- } while (byte & 0x80); +- +- *len = num_read; +- +- return result; +-} +- +-// Read a signed LEB128 number. These are like regular LEB128 +-// numbers, except the last byte may have a sign bit set. +- +-inline int64 ByteReader::ReadSignedLEB128(const char* buffer, +- size_t* len) const { +- int64 result = 0; +- unsigned int shift = 0; +- size_t num_read = 0; +- unsigned char byte; +- +- do { +- byte = *buffer++; +- num_read++; +- result |= (static_cast(byte & 0x7f) << shift); +- shift += 7; +- } while (byte & 0x80); +- +- if ((shift < 8 * sizeof (result)) && (byte & 0x40)) +- result |= -((static_cast(1)) << shift); +- *len = num_read; +- return result; +-} +- +-inline uint64 ByteReader::ReadOffset(const char* buffer) const { +- assert(this->offset_reader_); +- return (this->*offset_reader_)(buffer); +-} +- +-inline uint64 ByteReader::ReadAddress(const char* buffer) const { +- assert(this->address_reader_); +- return (this->*address_reader_)(buffer); +-} +- +-} // namespace dwarf2reader +- +-#endif // UTIL_DEBUGINFO_BYTEREADER_INL_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/bytereader.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/bytereader.cc +deleted file mode 100644 +--- a/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/bytereader.cc ++++ /dev/null +@@ -1,62 +0,0 @@ +-// Copyright 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. +- +-#include "common/mac/dwarf/bytereader-inl.h" +- +-#include "common/mac/dwarf/bytereader.h" +- +-namespace dwarf2reader { +- +-ByteReader::ByteReader(enum Endianness endian) +- :offset_reader_(NULL), address_reader_(NULL), endian_(endian), +- address_size_(0), offset_size_(0) +-{ } +- +-ByteReader::~ByteReader() { } +- +-void ByteReader::SetOffsetSize(uint8 size) { +- offset_size_ = size; +- assert(size == 4 || size == 8); +- if (size == 4) { +- this->offset_reader_ = &ByteReader::ReadFourBytes; +- } else { +- this->offset_reader_ = &ByteReader::ReadEightBytes; +- } +-} +- +-void ByteReader::SetAddressSize(uint8 size) { +- address_size_ = size; +- assert(size == 4 || size == 8); +- if (size == 4) { +- this->address_reader_ = &ByteReader::ReadFourBytes; +- } else { +- this->address_reader_ = &ByteReader::ReadEightBytes; +- } +-} +- +-} // namespace dwarf2reader +diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/bytereader.h b/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/bytereader.h +deleted file mode 100644 +--- a/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/bytereader.h ++++ /dev/null +@@ -1,132 +0,0 @@ +-// Copyright 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. +- +-#ifndef COMMON_MAC_DWARF_BYTEREADER_H__ +-#define COMMON_MAC_DWARF_BYTEREADER_H__ +- +-#include +-#include "common/mac/dwarf/types.h" +- +-namespace dwarf2reader { +- +-// We can't use the obvious name of LITTLE_ENDIAN and BIG_ENDIAN +-// because it conflicts with a macro +-enum Endianness { +- ENDIANNESS_BIG, +- ENDIANNESS_LITTLE +-}; +- +-// Class that knows how to read both big endian and little endian +-// numbers, for use in DWARF2/3 reader. +-// Takes an endianness argument. +-// To read addresses and offsets, SetAddressSize and SetOffsetSize +-// must be called first. +-class ByteReader { +- public: +- explicit ByteReader(enum Endianness endian); +- virtual ~ByteReader(); +- +- // Set the address size to SIZE, which sets up the ReadAddress member +- // so that it works. +- void SetAddressSize(uint8 size); +- +- // Set the offset size to SIZE, which sets up the ReadOffset member +- // so that it works. +- void SetOffsetSize(uint8 size); +- +- // Return the current offset size +- uint8 OffsetSize() const { return offset_size_; } +- +- // Return the current address size +- uint8 AddressSize() const { return address_size_; } +- +- // Read a single byte from BUFFER and return it as an unsigned 8 bit +- // number. +- uint8 ReadOneByte(const char* buffer) const; +- +- // Read two bytes from BUFFER and return it as an unsigned 16 bit +- // number. +- uint16 ReadTwoBytes(const char* buffer) const; +- +- // Read four bytes from BUFFER and return it as an unsigned 32 bit +- // number. This function returns a uint64 so that it is compatible +- // with ReadAddress and ReadOffset. The number it returns will +- // never be outside the range of an unsigned 32 bit integer. +- uint64 ReadFourBytes(const char* buffer) const; +- +- // Read eight bytes from BUFFER and return it as an unsigned 64 bit +- // number +- uint64 ReadEightBytes(const char* buffer) const; +- +- // Read an unsigned LEB128 (Little Endian Base 128) number from +- // BUFFER and return it as an unsigned 64 bit integer. LEN is set +- // to the length read. Everybody seems to reinvent LEB128 as a +- // variable size integer encoding, DWARF has had it for a long time. +- uint64 ReadUnsignedLEB128(const char* buffer, size_t* len) const; +- +- // Read a signed LEB128 number from BUFFER and return it as an +- // signed 64 bit integer. LEN is set to the length read. +- int64 ReadSignedLEB128(const char* buffer, size_t* len) const; +- +- // Read an offset from BUFFER and return it as an unsigned 64 bit +- // integer. DWARF2/3 define offsets as either 4 or 8 bytes, +- // generally depending on the amount of DWARF2/3 info present. +- uint64 ReadOffset(const char* buffer) const; +- +- // Read an address from BUFFER and return it as an unsigned 64 bit +- // integer. DWARF2/3 allow addresses to be any size from 0-255 +- // bytes currently. Internally we support 4 and 8 byte addresses, +- // and will CHECK on anything else. +- uint64 ReadAddress(const char* buffer) const; +- +- private: +- +- // Function pointer type for our address and offset readers. +- typedef uint64 (ByteReader::*AddressReader)(const char*) const; +- +- // Read an offset from BUFFER and return it as an unsigned 64 bit +- // integer. DWARF2/3 define offsets as either 4 or 8 bytes, +- // generally depending on the amount of DWARF2/3 info present. +- // This function pointer gets set by SetOffsetSize. +- AddressReader offset_reader_; +- +- // Read an address from BUFFER and return it as an unsigned 64 bit +- // integer. DWARF2/3 allow addresses to be any size from 0-255 +- // bytes currently. Internally we support 4 and 8 byte addresses, +- // and will CHECK on anything else. +- // This function pointer gets set by SetAddressSize. +- AddressReader address_reader_; +- +- Endianness endian_; +- uint8 address_size_; +- uint8 offset_size_; +-}; +- +-} // namespace dwarf2reader +- +-#endif // COMMON_MAC_DWARF_BYTEREADER_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/dwarf2enums.h b/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/dwarf2enums.h +deleted file mode 100644 +--- a/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/dwarf2enums.h ++++ /dev/null +@@ -1,490 +0,0 @@ +-// Copyright 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. +- +-#ifndef COMMON_MAC_DWARF_DWARF2ENUMS_H__ +-#define COMMON_MAC_DWARF_DWARF2ENUMS_H__ +- +-namespace dwarf2reader { +- +-// These enums do not follow the google3 style only because they are +-// known universally (specs, other implementations) by the names in +-// exactly this capitalization. +-// Tag names and codes. +-enum DwarfTag { +- DW_TAG_padding = 0x00, +- DW_TAG_array_type = 0x01, +- DW_TAG_class_type = 0x02, +- DW_TAG_entry_point = 0x03, +- DW_TAG_enumeration_type = 0x04, +- DW_TAG_formal_parameter = 0x05, +- DW_TAG_imported_declaration = 0x08, +- DW_TAG_label = 0x0a, +- DW_TAG_lexical_block = 0x0b, +- DW_TAG_member = 0x0d, +- DW_TAG_pointer_type = 0x0f, +- DW_TAG_reference_type = 0x10, +- DW_TAG_compile_unit = 0x11, +- DW_TAG_string_type = 0x12, +- DW_TAG_structure_type = 0x13, +- DW_TAG_subroutine_type = 0x15, +- DW_TAG_typedef = 0x16, +- DW_TAG_union_type = 0x17, +- DW_TAG_unspecified_parameters = 0x18, +- DW_TAG_variant = 0x19, +- DW_TAG_common_block = 0x1a, +- DW_TAG_common_inclusion = 0x1b, +- DW_TAG_inheritance = 0x1c, +- DW_TAG_inlined_subroutine = 0x1d, +- DW_TAG_module = 0x1e, +- DW_TAG_ptr_to_member_type = 0x1f, +- DW_TAG_set_type = 0x20, +- DW_TAG_subrange_type = 0x21, +- DW_TAG_with_stmt = 0x22, +- DW_TAG_access_declaration = 0x23, +- DW_TAG_base_type = 0x24, +- DW_TAG_catch_block = 0x25, +- DW_TAG_const_type = 0x26, +- DW_TAG_constant = 0x27, +- DW_TAG_enumerator = 0x28, +- DW_TAG_file_type = 0x29, +- DW_TAG_friend = 0x2a, +- DW_TAG_namelist = 0x2b, +- DW_TAG_namelist_item = 0x2c, +- DW_TAG_packed_type = 0x2d, +- DW_TAG_subprogram = 0x2e, +- DW_TAG_template_type_param = 0x2f, +- DW_TAG_template_value_param = 0x30, +- DW_TAG_thrown_type = 0x31, +- DW_TAG_try_block = 0x32, +- DW_TAG_variant_part = 0x33, +- DW_TAG_variable = 0x34, +- DW_TAG_volatile_type = 0x35, +- // DWARF 3. +- DW_TAG_dwarf_procedure = 0x36, +- DW_TAG_restrict_type = 0x37, +- DW_TAG_interface_type = 0x38, +- DW_TAG_namespace = 0x39, +- DW_TAG_imported_module = 0x3a, +- DW_TAG_unspecified_type = 0x3b, +- DW_TAG_partial_unit = 0x3c, +- DW_TAG_imported_unit = 0x3d, +- // SGI/MIPS Extensions. +- DW_TAG_MIPS_loop = 0x4081, +- // HP extensions. See: +- // ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz +- DW_TAG_HP_array_descriptor = 0x4090, +- // GNU extensions. +- DW_TAG_format_label = 0x4101, // For FORTRAN 77 and Fortran 90. +- DW_TAG_function_template = 0x4102, // For C++. +- DW_TAG_class_template = 0x4103, // For C++. +- DW_TAG_GNU_BINCL = 0x4104, +- DW_TAG_GNU_EINCL = 0x4105, +- // Extensions for UPC. See: http://upc.gwu.edu/~upc. +- DW_TAG_upc_shared_type = 0x8765, +- DW_TAG_upc_strict_type = 0x8766, +- DW_TAG_upc_relaxed_type = 0x8767, +- // PGI (STMicroelectronics) extensions. No documentation available. +- DW_TAG_PGI_kanji_type = 0xA000, +- DW_TAG_PGI_interface_block = 0xA020 +-}; +- +- +-enum DwarfHasChild { +- DW_children_no = 0, +- DW_children_yes = 1 +-}; +- +-// Form names and codes. +-enum DwarfForm { +- DW_FORM_addr = 0x01, +- DW_FORM_block2 = 0x03, +- DW_FORM_block4 = 0x04, +- DW_FORM_data2 = 0x05, +- DW_FORM_data4 = 0x06, +- DW_FORM_data8 = 0x07, +- DW_FORM_string = 0x08, +- DW_FORM_block = 0x09, +- DW_FORM_block1 = 0x0a, +- DW_FORM_data1 = 0x0b, +- DW_FORM_flag = 0x0c, +- DW_FORM_sdata = 0x0d, +- DW_FORM_strp = 0x0e, +- DW_FORM_udata = 0x0f, +- DW_FORM_ref_addr = 0x10, +- DW_FORM_ref1 = 0x11, +- DW_FORM_ref2 = 0x12, +- DW_FORM_ref4 = 0x13, +- DW_FORM_ref8 = 0x14, +- DW_FORM_ref_udata = 0x15, +- DW_FORM_indirect = 0x16 +-}; +- +-// Attribute names and codes +-enum DwarfAttribute { +- DW_AT_sibling = 0x01, +- DW_AT_location = 0x02, +- DW_AT_name = 0x03, +- DW_AT_ordering = 0x09, +- DW_AT_subscr_data = 0x0a, +- DW_AT_byte_size = 0x0b, +- DW_AT_bit_offset = 0x0c, +- DW_AT_bit_size = 0x0d, +- DW_AT_element_list = 0x0f, +- DW_AT_stmt_list = 0x10, +- DW_AT_low_pc = 0x11, +- DW_AT_high_pc = 0x12, +- DW_AT_language = 0x13, +- DW_AT_member = 0x14, +- DW_AT_discr = 0x15, +- DW_AT_discr_value = 0x16, +- DW_AT_visibility = 0x17, +- DW_AT_import = 0x18, +- DW_AT_string_length = 0x19, +- DW_AT_common_reference = 0x1a, +- DW_AT_comp_dir = 0x1b, +- DW_AT_const_value = 0x1c, +- DW_AT_containing_type = 0x1d, +- DW_AT_default_value = 0x1e, +- DW_AT_inline = 0x20, +- DW_AT_is_optional = 0x21, +- DW_AT_lower_bound = 0x22, +- DW_AT_producer = 0x25, +- DW_AT_prototyped = 0x27, +- DW_AT_return_addr = 0x2a, +- DW_AT_start_scope = 0x2c, +- DW_AT_stride_size = 0x2e, +- DW_AT_upper_bound = 0x2f, +- DW_AT_abstract_origin = 0x31, +- DW_AT_accessibility = 0x32, +- DW_AT_address_class = 0x33, +- DW_AT_artificial = 0x34, +- DW_AT_base_types = 0x35, +- DW_AT_calling_convention = 0x36, +- DW_AT_count = 0x37, +- DW_AT_data_member_location = 0x38, +- DW_AT_decl_column = 0x39, +- DW_AT_decl_file = 0x3a, +- DW_AT_decl_line = 0x3b, +- DW_AT_declaration = 0x3c, +- DW_AT_discr_list = 0x3d, +- DW_AT_encoding = 0x3e, +- DW_AT_external = 0x3f, +- DW_AT_frame_base = 0x40, +- DW_AT_friend = 0x41, +- DW_AT_identifier_case = 0x42, +- DW_AT_macro_info = 0x43, +- DW_AT_namelist_items = 0x44, +- DW_AT_priority = 0x45, +- DW_AT_segment = 0x46, +- DW_AT_specification = 0x47, +- DW_AT_static_link = 0x48, +- DW_AT_type = 0x49, +- DW_AT_use_location = 0x4a, +- DW_AT_variable_parameter = 0x4b, +- DW_AT_virtuality = 0x4c, +- DW_AT_vtable_elem_location = 0x4d, +- // DWARF 3 values. +- DW_AT_allocated = 0x4e, +- DW_AT_associated = 0x4f, +- DW_AT_data_location = 0x50, +- DW_AT_stride = 0x51, +- DW_AT_entry_pc = 0x52, +- DW_AT_use_UTF8 = 0x53, +- DW_AT_extension = 0x54, +- DW_AT_ranges = 0x55, +- DW_AT_trampoline = 0x56, +- DW_AT_call_column = 0x57, +- DW_AT_call_file = 0x58, +- DW_AT_call_line = 0x59, +- // SGI/MIPS extensions. +- DW_AT_MIPS_fde = 0x2001, +- DW_AT_MIPS_loop_begin = 0x2002, +- DW_AT_MIPS_tail_loop_begin = 0x2003, +- DW_AT_MIPS_epilog_begin = 0x2004, +- DW_AT_MIPS_loop_unroll_factor = 0x2005, +- DW_AT_MIPS_software_pipeline_depth = 0x2006, +- DW_AT_MIPS_linkage_name = 0x2007, +- DW_AT_MIPS_stride = 0x2008, +- DW_AT_MIPS_abstract_name = 0x2009, +- DW_AT_MIPS_clone_origin = 0x200a, +- DW_AT_MIPS_has_inlines = 0x200b, +- // HP extensions. +- DW_AT_HP_block_index = 0x2000, +- DW_AT_HP_unmodifiable = 0x2001, // Same as DW_AT_MIPS_fde. +- DW_AT_HP_actuals_stmt_list = 0x2010, +- DW_AT_HP_proc_per_section = 0x2011, +- DW_AT_HP_raw_data_ptr = 0x2012, +- DW_AT_HP_pass_by_reference = 0x2013, +- DW_AT_HP_opt_level = 0x2014, +- DW_AT_HP_prof_version_id = 0x2015, +- DW_AT_HP_opt_flags = 0x2016, +- DW_AT_HP_cold_region_low_pc = 0x2017, +- DW_AT_HP_cold_region_high_pc = 0x2018, +- DW_AT_HP_all_variables_modifiable = 0x2019, +- DW_AT_HP_linkage_name = 0x201a, +- DW_AT_HP_prof_flags = 0x201b, // In comp unit of procs_info for -g. +- // GNU extensions. +- DW_AT_sf_names = 0x2101, +- DW_AT_src_info = 0x2102, +- DW_AT_mac_info = 0x2103, +- DW_AT_src_coords = 0x2104, +- DW_AT_body_begin = 0x2105, +- DW_AT_body_end = 0x2106, +- DW_AT_GNU_vector = 0x2107, +- // VMS extensions. +- DW_AT_VMS_rtnbeg_pd_address = 0x2201, +- // UPC extension. +- DW_AT_upc_threads_scaled = 0x3210, +- // PGI (STMicroelectronics) extensions. +- DW_AT_PGI_lbase = 0x3a00, +- DW_AT_PGI_soffset = 0x3a01, +- DW_AT_PGI_lstride = 0x3a02 +-}; +- +- +-// Line number opcodes. +-enum DwarfLineNumberOps { +- DW_LNS_extended_op = 0, +- DW_LNS_copy = 1, +- DW_LNS_advance_pc = 2, +- DW_LNS_advance_line = 3, +- DW_LNS_set_file = 4, +- DW_LNS_set_column = 5, +- DW_LNS_negate_stmt = 6, +- DW_LNS_set_basic_block = 7, +- DW_LNS_const_add_pc = 8, +- DW_LNS_fixed_advance_pc = 9, +- // DWARF 3. +- DW_LNS_set_prologue_end = 10, +- DW_LNS_set_epilogue_begin = 11, +- DW_LNS_set_isa = 12 +-}; +- +-// Line number extended opcodes. +-enum DwarfLineNumberExtendedOps { +- DW_LNE_end_sequence = 1, +- DW_LNE_set_address = 2, +- DW_LNE_define_file = 3, +- // HP extensions. +- DW_LNE_HP_negate_is_UV_update = 0x11, +- DW_LNE_HP_push_context = 0x12, +- DW_LNE_HP_pop_context = 0x13, +- DW_LNE_HP_set_file_line_column = 0x14, +- DW_LNE_HP_set_routine_name = 0x15, +- DW_LNE_HP_set_sequence = 0x16, +- DW_LNE_HP_negate_post_semantics = 0x17, +- DW_LNE_HP_negate_function_exit = 0x18, +- DW_LNE_HP_negate_front_end_logical = 0x19, +- DW_LNE_HP_define_proc = 0x20 +-}; +- +-// Type encoding names and codes +-enum DwarfEncoding { +- DW_ATE_address =0x1, +- DW_ATE_boolean =0x2, +- DW_ATE_complex_float =0x3, +- DW_ATE_float =0x4, +- DW_ATE_signed =0x5, +- DW_ATE_signed_char =0x6, +- DW_ATE_unsigned =0x7, +- DW_ATE_unsigned_char =0x8, +- // DWARF3/DWARF3f +- DW_ATE_imaginary_float =0x9, +- DW_ATE_packed_decimal =0xa, +- DW_ATE_numeric_string =0xb, +- DW_ATE_edited =0xc, +- DW_ATE_signed_fixed =0xd, +- DW_ATE_unsigned_fixed =0xe, +- DW_ATE_decimal_float =0xf, +- DW_ATE_lo_user =0x80, +- DW_ATE_hi_user =0xff +-}; +- +-// Location virtual machine opcodes +-enum DwarfOpcode { +- DW_OP_addr =0x03, +- DW_OP_deref =0x06, +- DW_OP_const1u =0x08, +- DW_OP_const1s =0x09, +- DW_OP_const2u =0x0a, +- DW_OP_const2s =0x0b, +- DW_OP_const4u =0x0c, +- DW_OP_const4s =0x0d, +- DW_OP_const8u =0x0e, +- DW_OP_const8s =0x0f, +- DW_OP_constu =0x10, +- DW_OP_consts =0x11, +- DW_OP_dup =0x12, +- DW_OP_drop =0x13, +- DW_OP_over =0x14, +- DW_OP_pick =0x15, +- DW_OP_swap =0x16, +- DW_OP_rot =0x17, +- DW_OP_xderef =0x18, +- DW_OP_abs =0x19, +- DW_OP_and =0x1a, +- DW_OP_div =0x1b, +- DW_OP_minus =0x1c, +- DW_OP_mod =0x1d, +- DW_OP_mul =0x1e, +- DW_OP_neg =0x1f, +- DW_OP_not =0x20, +- DW_OP_or =0x21, +- DW_OP_plus =0x22, +- DW_OP_plus_uconst =0x23, +- DW_OP_shl =0x24, +- DW_OP_shr =0x25, +- DW_OP_shra =0x26, +- DW_OP_xor =0x27, +- DW_OP_bra =0x28, +- DW_OP_eq =0x29, +- DW_OP_ge =0x2a, +- DW_OP_gt =0x2b, +- DW_OP_le =0x2c, +- DW_OP_lt =0x2d, +- DW_OP_ne =0x2e, +- DW_OP_skip =0x2f, +- DW_OP_lit0 =0x30, +- DW_OP_lit1 =0x31, +- DW_OP_lit2 =0x32, +- DW_OP_lit3 =0x33, +- DW_OP_lit4 =0x34, +- DW_OP_lit5 =0x35, +- DW_OP_lit6 =0x36, +- DW_OP_lit7 =0x37, +- DW_OP_lit8 =0x38, +- DW_OP_lit9 =0x39, +- DW_OP_lit10 =0x3a, +- DW_OP_lit11 =0x3b, +- DW_OP_lit12 =0x3c, +- DW_OP_lit13 =0x3d, +- DW_OP_lit14 =0x3e, +- DW_OP_lit15 =0x3f, +- DW_OP_lit16 =0x40, +- DW_OP_lit17 =0x41, +- DW_OP_lit18 =0x42, +- DW_OP_lit19 =0x43, +- DW_OP_lit20 =0x44, +- DW_OP_lit21 =0x45, +- DW_OP_lit22 =0x46, +- DW_OP_lit23 =0x47, +- DW_OP_lit24 =0x48, +- DW_OP_lit25 =0x49, +- DW_OP_lit26 =0x4a, +- DW_OP_lit27 =0x4b, +- DW_OP_lit28 =0x4c, +- DW_OP_lit29 =0x4d, +- DW_OP_lit30 =0x4e, +- DW_OP_lit31 =0x4f, +- DW_OP_reg0 =0x50, +- DW_OP_reg1 =0x51, +- DW_OP_reg2 =0x52, +- DW_OP_reg3 =0x53, +- DW_OP_reg4 =0x54, +- DW_OP_reg5 =0x55, +- DW_OP_reg6 =0x56, +- DW_OP_reg7 =0x57, +- DW_OP_reg8 =0x58, +- DW_OP_reg9 =0x59, +- DW_OP_reg10 =0x5a, +- DW_OP_reg11 =0x5b, +- DW_OP_reg12 =0x5c, +- DW_OP_reg13 =0x5d, +- DW_OP_reg14 =0x5e, +- DW_OP_reg15 =0x5f, +- DW_OP_reg16 =0x60, +- DW_OP_reg17 =0x61, +- DW_OP_reg18 =0x62, +- DW_OP_reg19 =0x63, +- DW_OP_reg20 =0x64, +- DW_OP_reg21 =0x65, +- DW_OP_reg22 =0x66, +- DW_OP_reg23 =0x67, +- DW_OP_reg24 =0x68, +- DW_OP_reg25 =0x69, +- DW_OP_reg26 =0x6a, +- DW_OP_reg27 =0x6b, +- DW_OP_reg28 =0x6c, +- DW_OP_reg29 =0x6d, +- DW_OP_reg30 =0x6e, +- DW_OP_reg31 =0x6f, +- DW_OP_breg0 =0x70, +- DW_OP_breg1 =0x71, +- DW_OP_breg2 =0x72, +- DW_OP_breg3 =0x73, +- DW_OP_breg4 =0x74, +- DW_OP_breg5 =0x75, +- DW_OP_breg6 =0x76, +- DW_OP_breg7 =0x77, +- DW_OP_breg8 =0x78, +- DW_OP_breg9 =0x79, +- DW_OP_breg10 =0x7a, +- DW_OP_breg11 =0x7b, +- DW_OP_breg12 =0x7c, +- DW_OP_breg13 =0x7d, +- DW_OP_breg14 =0x7e, +- DW_OP_breg15 =0x7f, +- DW_OP_breg16 =0x80, +- DW_OP_breg17 =0x81, +- DW_OP_breg18 =0x82, +- DW_OP_breg19 =0x83, +- DW_OP_breg20 =0x84, +- DW_OP_breg21 =0x85, +- DW_OP_breg22 =0x86, +- DW_OP_breg23 =0x87, +- DW_OP_breg24 =0x88, +- DW_OP_breg25 =0x89, +- DW_OP_breg26 =0x8a, +- DW_OP_breg27 =0x8b, +- DW_OP_breg28 =0x8c, +- DW_OP_breg29 =0x8d, +- DW_OP_breg30 =0x8e, +- DW_OP_breg31 =0x8f, +- DW_OP_regX =0x90, +- DW_OP_fbreg =0x91, +- DW_OP_bregX =0x92, +- DW_OP_piece =0x93, +- DW_OP_deref_size =0x94, +- DW_OP_xderef_size =0x95, +- DW_OP_nop =0x96, +- // DWARF3/DWARF3f +- DW_OP_push_object_address =0x97, +- DW_OP_call2 =0x98, +- DW_OP_call4 =0x99, +- DW_OP_call_ref =0x9a, +- DW_OP_form_tls_address =0x9b, +- DW_OP_call_frame_cfa =0x9c, +- DW_OP_bit_piece =0x9d, +- DW_OP_lo_user =0xe0, +- DW_OP_hi_user =0xff, +- // GNU extensions +- DW_OP_GNU_push_tls_address =0xe0 +-}; +- +-} // namespace dwarf2reader +-#endif // COMMON_MAC_DWARF_DWARF2ENUMS_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/dwarf2reader.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/dwarf2reader.cc +deleted file mode 100644 +--- a/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/dwarf2reader.cc ++++ /dev/null +@@ -1,830 +0,0 @@ +-// Copyright 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. +- +-#include +-#include +-#include +- +-#include "common/mac/dwarf/bytereader-inl.h" +-#include "common/mac/dwarf/dwarf2reader.h" +-#include "common/mac/dwarf/bytereader.h" +-#include "common/mac/dwarf/line_state_machine.h" +- +-namespace __gnu_cxx +-{ +- template<> struct hash< std::string > +- { +- size_t operator()( const std::string& x ) const +- { +- return hash< const char* >()( x.c_str() ); +- } +- }; +-} +- +-namespace dwarf2reader { +- +-// Read a DWARF2/3 initial length field from START, using READER, and +-// report the length in LEN. Return the actual initial length. +- +-static uint64 ReadInitialLength(const char* start, +- ByteReader* reader, size_t* len) { +- const uint64 initial_length = reader->ReadFourBytes(start); +- start += 4; +- +- // In DWARF2/3, if the initial length is all 1 bits, then the offset +- // size is 8 and we need to read the next 8 bytes for the real length. +- if (initial_length == 0xffffffff) { +- reader->SetOffsetSize(8); +- *len = 12; +- return reader->ReadOffset(start); +- } else { +- reader->SetOffsetSize(4); +- *len = 4; +- } +- return initial_length; +-} +- +-CompilationUnit::CompilationUnit(const SectionMap& sections, uint64 offset, +- ByteReader* reader, Dwarf2Handler* handler) +- : offset_from_section_start_(offset), reader_(reader), +- sections_(sections), handler_(handler), abbrevs_(NULL), +- string_buffer_(NULL), string_buffer_length_(0) {} +- +-// Read a DWARF2/3 abbreviation section. +-// Each abbrev consists of a abbreviation number, a tag, a byte +-// specifying whether the tag has children, and a list of +-// attribute/form pairs. +-// The list of forms is terminated by a 0 for the attribute, and a +-// zero for the form. The entire abbreviation section is terminated +-// by a zero for the code. +- +-void CompilationUnit::ReadAbbrevs() { +- if (abbrevs_) +- return; +- +- // First get the debug_abbrev section +- SectionMap::const_iterator iter = sections_.find("__debug_abbrev"); +- assert(iter != sections_.end()); +- +- abbrevs_ = new vector; +- abbrevs_->resize(1); +- +- // The only way to check whether we are reading over the end of the +- // buffer would be to first compute the size of the leb128 data by +- // reading it, then go back and read it again. +- const char* abbrev_start = iter->second.first + +- header_.abbrev_offset; +- const char* abbrevptr = abbrev_start; +- const uint64 abbrev_length = iter->second.second - header_.abbrev_offset; +- +- while (1) { +- CompilationUnit::Abbrev abbrev; +- size_t len; +- const uint32 number = reader_->ReadUnsignedLEB128(abbrevptr, &len); +- +- if (number == 0) +- break; +- abbrev.number = number; +- abbrevptr += len; +- +- assert(abbrevptr < abbrev_start + abbrev_length); +- const uint32 tag = reader_->ReadUnsignedLEB128(abbrevptr, &len); +- abbrevptr += len; +- abbrev.tag = static_cast(tag); +- +- assert(abbrevptr < abbrev_start + abbrev_length); +- abbrev.has_children = reader_->ReadOneByte(abbrevptr); +- abbrevptr += 1; +- +- assert(abbrevptr < abbrev_start + abbrev_length); +- +- while (1) { +- const uint32 nametemp = reader_->ReadUnsignedLEB128(abbrevptr, &len); +- abbrevptr += len; +- +- assert(abbrevptr < abbrev_start + abbrev_length); +- const uint32 formtemp = reader_->ReadUnsignedLEB128(abbrevptr, &len); +- abbrevptr += len; +- if (nametemp == 0 && formtemp == 0) +- break; +- +- const enum DwarfAttribute name = +- static_cast(nametemp); +- const enum DwarfForm form = static_cast(formtemp); +- abbrev.attributes.push_back(make_pair(name, form)); +- } +- assert(abbrev.number == abbrevs_->size()); +- abbrevs_->push_back(abbrev); +- } +-} +- +-// Skips a single DIE's attributes. +-const char* CompilationUnit::SkipDIE(const char* start, +- const Abbrev& abbrev) { +- for (AttributeList::const_iterator i = abbrev.attributes.begin(); +- i != abbrev.attributes.end(); +- i++) { +- start = SkipAttribute(start, i->second); +- } +- return start; +-} +- +-// Skips a single attribute form's data. +-const char* CompilationUnit::SkipAttribute(const char* start, +- enum DwarfForm form) { +- size_t len; +- +- switch (form) { +- case DW_FORM_indirect: +- form = static_cast(reader_->ReadUnsignedLEB128(start, +- &len)); +- start += len; +- return SkipAttribute(start, form); +- break; +- +- case DW_FORM_data1: +- case DW_FORM_flag: +- case DW_FORM_ref1: +- return start + 1; +- break; +- case DW_FORM_ref2: +- case DW_FORM_data2: +- return start + 2; +- break; +- case DW_FORM_ref4: +- case DW_FORM_data4: +- return start + 4; +- break; +- case DW_FORM_ref8: +- case DW_FORM_data8: +- return start + 8; +- break; +- case DW_FORM_string: +- return start + strlen(start) + 1; +- break; +- case DW_FORM_udata: +- case DW_FORM_ref_udata: +- reader_->ReadUnsignedLEB128(start, &len); +- return start + len; +- break; +- +- case DW_FORM_sdata: +- reader_->ReadSignedLEB128(start, &len); +- return start + len; +- break; +- case DW_FORM_addr: +- return start + reader_->AddressSize(); +- break; +- case DW_FORM_ref_addr: +- // DWARF2 and 3 differ on whether ref_addr is address size or +- // offset size. +- assert(header_.version == 2 || header_.version == 3); +- if (header_.version == 2) { +- return start + reader_->AddressSize(); +- } else if (header_.version == 3) { +- return start + reader_->OffsetSize(); +- } +- break; +- +- case DW_FORM_block1: +- return start + 1 + reader_->ReadOneByte(start); +- break; +- case DW_FORM_block2: +- return start + 2 + reader_->ReadTwoBytes(start); +- break; +- case DW_FORM_block4: +- return start + 4 + reader_->ReadFourBytes(start); +- break; +- case DW_FORM_block: { +- uint64 size = reader_->ReadUnsignedLEB128(start, &len); +- return start + size + len; +- } +- break; +- case DW_FORM_strp: +- return start + reader_->OffsetSize(); +- break; +- default: +- fprintf(stderr,"Unhandled form type"); +- } +- fprintf(stderr,"Unhandled form type"); +- return NULL; +-} +- +-// Read a DWARF2/3 header. +-// The header is variable length in DWARF3 (and DWARF2 as extended by +-// most compilers), and consists of an length field, a version number, +-// the offset in the .debug_abbrev section for our abbrevs, and an +-// address size. +-void CompilationUnit::ReadHeader() { +- const char* headerptr = buffer_; +- size_t initial_length_size; +- +- assert(headerptr + 4 < buffer_ + buffer_length_); +- const uint64 initial_length = ReadInitialLength(headerptr, reader_, +- &initial_length_size); +- headerptr += initial_length_size; +- header_.length = initial_length; +- +- assert(headerptr + 2 < buffer_ + buffer_length_); +- header_.version = reader_->ReadTwoBytes(headerptr); +- headerptr += 2; +- +- assert(headerptr + reader_->OffsetSize() < buffer_ + buffer_length_); +- header_.abbrev_offset = reader_->ReadOffset(headerptr); +- headerptr += reader_->OffsetSize(); +- +- assert(headerptr + 1 < buffer_ + buffer_length_); +- header_.address_size = reader_->ReadOneByte(headerptr); +- reader_->SetAddressSize(header_.address_size); +- headerptr += 1; +- +- after_header_ = headerptr; +- +- // This check ensures that we don't have to do checking during the +- // reading of DIEs. header_.length does not include the size of the +- // initial length. +- assert(buffer_ + initial_length_size + header_.length <= +- buffer_ + buffer_length_); +-} +- +-uint64 CompilationUnit::Start() { +- // First get the debug_info section +- SectionMap::const_iterator iter = sections_.find("__debug_info"); +- assert(iter != sections_.end()); +- +- // Set up our buffer +- buffer_ = iter->second.first + offset_from_section_start_; +- buffer_length_ = iter->second.second - offset_from_section_start_; +- +- // Read the header +- ReadHeader(); +- +- // Figure out the real length from the end of the initial length to +- // the end of the compilation unit, since that is the value we +- // return. +- uint64 ourlength = header_.length; +- if (reader_->OffsetSize() == 8) +- ourlength += 12; +- else +- ourlength += 4; +- +- // See if the user wants this compilation unit, and if not, just return. +- if (!handler_->StartCompilationUnit(offset_from_section_start_, +- reader_->AddressSize(), +- reader_->OffsetSize(), +- header_.length, +- header_.version)) +- return ourlength; +- +- // Otherwise, continue by reading our abbreviation entries. +- ReadAbbrevs(); +- +- // Set the string section if we have one. +- iter = sections_.find("__debug_str"); +- if (iter != sections_.end()) { +- string_buffer_ = iter->second.first; +- string_buffer_length_ = iter->second.second; +- } +- +- // Now that we have our abbreviations, start processing DIE's. +- ProcessDIEs(); +- +- return ourlength; +-} +- +-// If one really wanted, you could merge SkipAttribute and +-// ProcessAttribute +-// This is all boring data manipulation and calling of the handler. +-const char* CompilationUnit::ProcessAttribute( +- uint64 dieoffset, const char* start, enum DwarfAttribute attr, +- enum DwarfForm form) { +- size_t len; +- +- switch (form) { +- // DW_FORM_indirect is never used because it is such a space +- // waster. +- case DW_FORM_indirect: +- form = static_cast(reader_->ReadUnsignedLEB128(start, +- &len)); +- start += len; +- return ProcessAttribute(dieoffset, start, attr, form); +- break; +- +- case DW_FORM_data1: +- case DW_FORM_flag: +- case DW_FORM_ref1: +- handler_->ProcessAttributeUnsigned(dieoffset, attr, form, +- reader_->ReadOneByte(start)); +- return start + 1; +- break; +- case DW_FORM_ref2: +- case DW_FORM_data2: +- handler_->ProcessAttributeUnsigned(dieoffset, attr, form, +- reader_->ReadTwoBytes(start)); +- return start + 2; +- break; +- case DW_FORM_ref4: +- case DW_FORM_data4: +- handler_->ProcessAttributeUnsigned(dieoffset, attr, form, +- reader_->ReadFourBytes(start)); +- return start + 4; +- break; +- case DW_FORM_ref8: +- case DW_FORM_data8: +- handler_->ProcessAttributeUnsigned(dieoffset, attr, form, +- reader_->ReadEightBytes(start)); +- return start + 8; +- break; +- case DW_FORM_string: { +- const char* str = start; +- handler_->ProcessAttributeString(dieoffset, attr, form, +- str); +- return start + strlen(str) + 1; +- } +- break; +- case DW_FORM_udata: +- case DW_FORM_ref_udata: +- handler_->ProcessAttributeUnsigned(dieoffset, attr, form, +- reader_->ReadUnsignedLEB128(start, +- &len)); +- return start + len; +- break; +- +- case DW_FORM_sdata: +- handler_->ProcessAttributeSigned(dieoffset, attr, form, +- reader_->ReadSignedLEB128(start, &len)); +- return start + len; +- break; +- case DW_FORM_addr: +- handler_->ProcessAttributeUnsigned(dieoffset, attr, form, +- reader_->ReadAddress(start)); +- return start + reader_->AddressSize(); +- break; +- case DW_FORM_ref_addr: +- // DWARF2 and 3 differ on whether ref_addr is address size or +- // offset size. +- assert(header_.version == 2 || header_.version == 3); +- if (header_.version == 2) { +- handler_->ProcessAttributeUnsigned(dieoffset, attr, form, +- reader_->ReadAddress(start)); +- return start + reader_->AddressSize(); +- } else if (header_.version == 3) { +- handler_->ProcessAttributeUnsigned(dieoffset, attr, form, +- reader_->ReadOffset(start)); +- return start + reader_->OffsetSize(); +- } +- break; +- +- case DW_FORM_block1: { +- uint64 datalen = reader_->ReadOneByte(start); +- handler_->ProcessAttributeBuffer(dieoffset, attr, form, start + 1, +- datalen); +- return start + 1 + datalen; +- } +- break; +- case DW_FORM_block2: { +- uint64 datalen = reader_->ReadTwoBytes(start); +- handler_->ProcessAttributeBuffer(dieoffset, attr, form, start + 2, +- datalen); +- return start + 2 + datalen; +- } +- break; +- case DW_FORM_block4: { +- uint64 datalen = reader_->ReadFourBytes(start); +- handler_->ProcessAttributeBuffer(dieoffset, attr, form, start + 4, +- datalen); +- return start + 4 + datalen; +- } +- break; +- case DW_FORM_block: { +- uint64 datalen = reader_->ReadUnsignedLEB128(start, &len); +- handler_->ProcessAttributeBuffer(dieoffset, attr, form, start + len, +- datalen); +- return start + datalen + len; +- } +- break; +- case DW_FORM_strp: { +- assert(string_buffer_ != NULL); +- +- const uint64 offset = reader_->ReadOffset(start); +- assert(string_buffer_ + offset < string_buffer_ + string_buffer_length_); +- +- const char* str = string_buffer_ + offset; +- handler_->ProcessAttributeString(dieoffset, attr, form, +- str); +- return start + reader_->OffsetSize(); +- } +- break; +- default: +- fprintf(stderr, "Unhandled form type"); +- } +- fprintf(stderr, "Unhandled form type"); +- return NULL; +-} +- +-const char* CompilationUnit::ProcessDIE(uint64 dieoffset, +- const char* start, +- const Abbrev& abbrev) { +- for (AttributeList::const_iterator i = abbrev.attributes.begin(); +- i != abbrev.attributes.end(); +- i++) { +- start = ProcessAttribute(dieoffset, start, i->first, i->second); +- } +- return start; +-} +- +-void CompilationUnit::ProcessDIEs() { +- const char* dieptr = after_header_; +- size_t len; +- +- // lengthstart is the place the length field is based on. +- // It is the point in the header after the initial length field +- const char* lengthstart = buffer_; +- +- // In 64 bit dwarf, the initial length is 12 bytes, because of the +- // 0xffffffff at the start. +- if (reader_->OffsetSize() == 8) +- lengthstart += 12; +- else +- lengthstart += 4; +- +- // we need semantics of boost scoped_ptr here - no intention of trasnferring +- // ownership of the stack. use const, but then we limit ourselves to not +- // ever being able to call .reset() on the smart pointer. +- auto_ptr > const die_stack(new stack); +- +- while (dieptr < (lengthstart + header_.length)) { +- // We give the user the absolute offset from the beginning of +- // debug_info, since they need it to deal with ref_addr forms. +- uint64 absolute_offset = (dieptr - buffer_) + offset_from_section_start_; +- +- uint64 abbrev_num = reader_->ReadUnsignedLEB128(dieptr, &len); +- +- dieptr += len; +- +- // Abbrev == 0 represents the end of a list of children. +- if (abbrev_num == 0) { +- const uint64 offset = die_stack->top(); +- die_stack->pop(); +- handler_->EndDIE(offset); +- continue; +- } +- +- const Abbrev& abbrev = abbrevs_->at(abbrev_num); +- const enum DwarfTag tag = abbrev.tag; +- if (!handler_->StartDIE(absolute_offset, tag, abbrev.attributes)) { +- dieptr = SkipDIE(dieptr, abbrev); +- } else { +- dieptr = ProcessDIE(absolute_offset, dieptr, abbrev); +- } +- +- if (abbrev.has_children) { +- die_stack->push(absolute_offset); +- } else { +- handler_->EndDIE(absolute_offset); +- } +- } +-} +- +-LineInfo::LineInfo(const char* buffer, uint64 buffer_length, +- ByteReader* reader, LineInfoHandler* handler): +- handler_(handler), reader_(reader), buffer_(buffer), +- buffer_length_(buffer_length) { +- header_.std_opcode_lengths = NULL; +-} +- +-uint64 LineInfo::Start() { +- ReadHeader(); +- ReadLines(); +- return after_header_ - buffer_; +-} +- +-// The header for a debug_line section is mildly complicated, because +-// the line info is very tightly encoded. +-void LineInfo::ReadHeader() { +- const char* lineptr = buffer_; +- size_t initial_length_size; +- +- const uint64 initial_length = ReadInitialLength(lineptr, reader_, +- &initial_length_size); +- +- lineptr += initial_length_size; +- header_.total_length = initial_length; +- assert(buffer_ + initial_length_size + header_.total_length <= +- buffer_ + buffer_length_); +- +- // Address size *must* be set by CU ahead of time. +- assert(reader_->AddressSize() != 0); +- +- header_.version = reader_->ReadTwoBytes(lineptr); +- lineptr += 2; +- +- header_.prologue_length = reader_->ReadOffset(lineptr); +- lineptr += reader_->OffsetSize(); +- +- header_.min_insn_length = reader_->ReadOneByte(lineptr); +- lineptr += 1; +- +- header_.default_is_stmt = reader_->ReadOneByte(lineptr); +- lineptr += 1; +- +- header_.line_base = *reinterpret_cast(lineptr); +- lineptr += 1; +- +- header_.line_range = reader_->ReadOneByte(lineptr); +- lineptr += 1; +- +- header_.opcode_base = reader_->ReadOneByte(lineptr); +- lineptr += 1; +- +- header_.std_opcode_lengths = new vector; +- header_.std_opcode_lengths->resize(header_.opcode_base + 1); +- (*header_.std_opcode_lengths)[0] = 0; +- for (int i = 1; i < header_.opcode_base; i++) { +- (*header_.std_opcode_lengths)[i] = reader_->ReadOneByte(lineptr); +- lineptr += 1; +- } +- +- // It is legal for the directory entry table to be empty. +- if (*lineptr) { +- uint32 dirindex = 1; +- while (*lineptr) { +- const char* dirname = lineptr; +- handler_->DefineDir(dirname, dirindex); +- lineptr += strlen(dirname) + 1; +- dirindex++; +- } +- } +- lineptr++; +- +- // It is also legal for the file entry table to be empty. +- if (*lineptr) { +- uint32 fileindex = 1; +- size_t len; +- while (*lineptr) { +- const char* filename = lineptr; +- lineptr += strlen(filename) + 1; +- +- uint64 dirindex = reader_->ReadUnsignedLEB128(lineptr, &len); +- lineptr += len; +- +- uint64 mod_time = reader_->ReadUnsignedLEB128(lineptr, &len); +- lineptr += len; +- +- uint64 filelength = reader_->ReadUnsignedLEB128(lineptr, &len); +- lineptr += len; +- handler_->DefineFile(filename, fileindex, dirindex, mod_time, +- filelength); +- fileindex++; +- } +- } +- lineptr++; +- +- after_header_ = lineptr; +-} +- +-/* static */ +-bool LineInfo::ProcessOneOpcode(ByteReader* reader, +- LineInfoHandler* handler, +- const struct LineInfoHeader &header, +- const char* start, +- struct LineStateMachine* lsm, +- size_t* len, +- uintptr_t pc, +- bool *lsm_passes_pc) { +- size_t oplen = 0; +- size_t templen; +- uint8 opcode = reader->ReadOneByte(start); +- oplen++; +- start++; +- +- // If the opcode is great than the opcode_base, it is a special +- // opcode. Most line programs consist mainly of special opcodes. +- if (opcode >= header.opcode_base) { +- opcode -= header.opcode_base; +- const int64 advance_address = (opcode / header.line_range) +- * header.min_insn_length; +- const int64 advance_line = (opcode % header.line_range) +- + header.line_base; +- +- // Check if the lsm passes "pc". If so, mark it as passed. +- if (lsm_passes_pc && +- lsm->address <= pc && pc < lsm->address + advance_address) { +- *lsm_passes_pc = true; +- } +- +- lsm->address += advance_address; +- lsm->line_num += advance_line; +- lsm->basic_block = true; +- *len = oplen; +- return true; +- } +- +- // Otherwise, we have the regular opcodes +- switch (opcode) { +- case DW_LNS_copy: { +- lsm->basic_block = false; +- *len = oplen; +- return true; +- } +- +- case DW_LNS_advance_pc: { +- uint64 advance_address = reader->ReadUnsignedLEB128(start, &templen); +- oplen += templen; +- +- // Check if the lsm passes "pc". If so, mark it as passed. +- if (lsm_passes_pc && lsm->address <= pc && +- pc < lsm->address + header.min_insn_length * advance_address) { +- *lsm_passes_pc = true; +- } +- +- lsm->address += header.min_insn_length * advance_address; +- } +- break; +- case DW_LNS_advance_line: { +- const int64 advance_line = reader->ReadSignedLEB128(start, &templen); +- oplen += templen; +- lsm->line_num += advance_line; +- +- // With gcc 4.2.1, we can get the line_no here for the first time +- // since DW_LNS_advance_line is called after DW_LNE_set_address is +- // called. So we check if the lsm passes "pc" here, not in +- // DW_LNE_set_address. +- if (lsm_passes_pc && lsm->address == pc) { +- *lsm_passes_pc = true; +- } +- } +- break; +- case DW_LNS_set_file: { +- const uint64 fileno = reader->ReadUnsignedLEB128(start, &templen); +- oplen += templen; +- lsm->file_num = fileno; +- } +- break; +- case DW_LNS_set_column: { +- const uint64 colno = reader->ReadUnsignedLEB128(start, &templen); +- oplen += templen; +- lsm->column_num = colno; +- } +- break; +- case DW_LNS_negate_stmt: { +- lsm->is_stmt = !lsm->is_stmt; +- } +- break; +- case DW_LNS_set_basic_block: { +- lsm->basic_block = true; +- } +- break; +- case DW_LNS_fixed_advance_pc: { +- const uint16 advance_address = reader->ReadTwoBytes(start); +- oplen += 2; +- +- // Check if the lsm passes "pc". If so, mark it as passed. +- if (lsm_passes_pc && +- lsm->address <= pc && pc < lsm->address + advance_address) { +- *lsm_passes_pc = true; +- } +- +- lsm->address += advance_address; +- } +- break; +- case DW_LNS_const_add_pc: { +- const int64 advance_address = header.min_insn_length +- * ((255 - header.opcode_base) +- / header.line_range); +- +- // Check if the lsm passes "pc". If so, mark it as passed. +- if (lsm_passes_pc && +- lsm->address <= pc && pc < lsm->address + advance_address) { +- *lsm_passes_pc = true; +- } +- +- lsm->address += advance_address; +- } +- break; +- case DW_LNS_extended_op: { +- const size_t extended_op_len = reader->ReadUnsignedLEB128(start, +- &templen); +- start += templen; +- oplen += templen + extended_op_len; +- +- const uint64 extended_op = reader->ReadOneByte(start); +- start++; +- +- switch (extended_op) { +- case DW_LNE_end_sequence: { +- lsm->end_sequence = true; +- *len = oplen; +- return true; +- } +- break; +- case DW_LNE_set_address: { +- // With gcc 4.2.1, we cannot tell the line_no here since +- // DW_LNE_set_address is called before DW_LNS_advance_line is +- // called. So we do not check if the lsm passes "pc" here. See +- // also the comment in DW_LNS_advance_line. +- uint64 address = reader->ReadAddress(start); +- lsm->address = address; +- } +- break; +- case DW_LNE_define_file: { +- const char* filename = start; +- +- templen = strlen(filename) + 1; +- start += templen; +- +- uint64 dirindex = reader->ReadUnsignedLEB128(start, &templen); +- oplen += templen; +- +- const uint64 mod_time = reader->ReadUnsignedLEB128(start, +- &templen); +- oplen += templen; +- +- const uint64 filelength = reader->ReadUnsignedLEB128(start, +- &templen); +- oplen += templen; +- +- if (handler) { +- handler->DefineFile(filename, -1, dirindex, mod_time, +- filelength); +- } +- } +- break; +- } +- } +- break; +- +- default: { +- // Ignore unknown opcode silently +- if (header.std_opcode_lengths) { +- for (int i = 0; i < (*header.std_opcode_lengths)[opcode]; i++) { +- size_t templen; +- reader->ReadUnsignedLEB128(start, &templen); +- start += templen; +- oplen += templen; +- } +- } +- } +- break; +- } +- *len = oplen; +- return false; +-} +- +-void LineInfo::ReadLines() { +- struct LineStateMachine lsm; +- +- // lengthstart is the place the length field is based on. +- // It is the point in the header after the initial length field +- const char* lengthstart = buffer_; +- +- // In 64 bit dwarf, the initial length is 12 bytes, because of the +- // 0xffffffff at the start. +- if (reader_->OffsetSize() == 8) +- lengthstart += 12; +- else +- lengthstart += 4; +- +- const char* lineptr = after_header_; +- while (lineptr < lengthstart + header_.total_length) { +- lsm.Reset(header_.default_is_stmt); +- while (!lsm.end_sequence) { +- size_t oplength; +- bool add_line = ProcessOneOpcode(reader_, handler_, header_, +- lineptr, &lsm, &oplength, (uintptr_t)-1, NULL); +- if (add_line) +- handler_->AddLine(lsm.address, lsm.file_num, lsm.line_num, +- lsm.column_num); +- lineptr += oplength; +- } +- } +- +- after_header_ = lengthstart + header_.total_length; +-} +- +-} // namespace dwarf2reader +diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/dwarf2reader.h b/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/dwarf2reader.h +deleted file mode 100644 +--- a/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/dwarf2reader.h ++++ /dev/null +@@ -1,393 +0,0 @@ +-// Copyright 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. +- +-// This file contains definitions related to the DWARF2/3 reader and +-// it's handler interfaces. +-// The DWARF2/3 specification can be found at +-// http://dwarf.freestandards.org and should be considered required +-// reading if you wish to modify the implementation. +-// Only a cursory attempt is made to explain terminology that is +-// used here, as it is much better explained in the standard documents +-#ifndef COMMON_MAC_DWARF_DWARF2READER_H__ +-#define COMMON_MAC_DWARF_DWARF2READER_H__ +- +-#include +-#include +-#include +-#include +-#include +- +-#include "common/mac/dwarf/dwarf2enums.h" +-#include "common/mac/dwarf/types.h" +- +-using namespace std; +-using namespace __gnu_cxx; +- +-namespace dwarf2reader { +-struct LineStateMachine; +-class ByteReader; +-class Dwarf2Handler; +-class LineInfoHandler; +- +-// This maps from a string naming a section to a pair containing a +-// the data for the section, and the size of the section. +-typedef hash_map > SectionMap; +-typedef list > AttributeList; +-typedef AttributeList::iterator AttributeIterator; +-typedef AttributeList::const_iterator ConstAttributeIterator; +- +-struct LineInfoHeader { +- uint64 total_length; +- uint16 version; +- uint64 prologue_length; +- uint8 min_insn_length; // insn stands for instructin +- bool default_is_stmt; // stmt stands for statement +- int8 line_base; +- uint8 line_range; +- uint8 opcode_base; +- // Use a pointer so that signalsafe_addr2line is able to use this structure +- // without heap allocation problem. +- vector *std_opcode_lengths; +-}; +- +-class LineInfo { +- public: +- +- // Initializes a .debug_line reader. Buffer and buffer length point +- // to the beginning and length of the line information to read. +- // Reader is a ByteReader class that has the endianness set +- // properly. +- LineInfo(const char* buffer_, uint64 buffer_length, +- ByteReader* reader, LineInfoHandler* handler); +- +- virtual ~LineInfo() { +- if (header_.std_opcode_lengths) { +- delete header_.std_opcode_lengths; +- } +- } +- +- // Start processing line info, and calling callbacks in the handler. +- // Consumes the line number information for a single compilation unit. +- // Returns the number of bytes processed. +- uint64 Start(); +- +- // Process a single line info opcode at START using the state +- // machine at LSM. Return true if we should define a line using the +- // current state of the line state machine. Place the length of the +- // opcode in LEN. +- // If LSM_PASSES_PC is non-NULL, this function also checks if the lsm +- // passes the address of PC. In other words, LSM_PASSES_PC will be +- // set to true, if the following condition is met. +- // +- // lsm's old address < PC <= lsm's new address +- static bool ProcessOneOpcode(ByteReader* reader, +- LineInfoHandler* handler, +- const struct LineInfoHeader &header, +- const char* start, +- struct LineStateMachine* lsm, +- size_t* len, +- uintptr_t pc, +- bool *lsm_passes_pc); +- +- private: +- // Reads the DWARF2/3 header for this line info. +- void ReadHeader(); +- +- // Reads the DWARF2/3 line information +- void ReadLines(); +- +- // The associated handler to call processing functions in +- LineInfoHandler* handler_; +- +- // The associated ByteReader that handles endianness issues for us +- ByteReader* reader_; +- +- // A DWARF2/3 line info header. This is not the same size as +- // in the actual file, as the one in the file may have a 32 bit or +- // 64 bit lengths +- +- struct LineInfoHeader header_; +- +- // buffer is the buffer for our line info, starting at exactly where +- // the line info to read is. after_header is the place right after +- // the end of the line information header. +- const char* buffer_; +- uint64 buffer_length_; +- const char* after_header_; +-}; +- +-// This class is the main interface between the line info reader and +-// the client. The virtual functions inside this get called for +-// interesting events that happen during line info reading. The +-// default implementation does nothing +- +-class LineInfoHandler { +- public: +- LineInfoHandler() { } +- +- virtual ~LineInfoHandler() { } +- +- // Called when we define a directory. NAME is the directory name, +- // DIR_NUM is the directory number +- virtual void DefineDir(const string& name, uint32 dir_num) { } +- +- // Called when we define a filename. NAME is the filename, FILE_NUM +- // is the file number which is -1 if the file index is the next +- // index after the last numbered index (this happens when files are +- // dynamically defined by the line program), DIR_NUM is the +- // directory index for the directory name of this file, MOD_TIME is +- // the modification time of the file, and LENGTH is the length of +- // the file +- virtual void DefineFile(const string& name, int32 file_num, +- uint32 dir_num, uint64 mod_time, +- uint64 length) { } +- +- // Called when the line info reader has a new line, address pair +- // ready for us. ADDRESS is the address of the code, FILE_NUM is +- // the file number containing the code, LINE_NUM is the line number in +- // that file for the code, and COLUMN_NUM is the column number the code +- // starts at, if we know it (0 otherwise). +- virtual void AddLine(uint64 address, uint32 file_num, uint32 line_num, +- uint32 column_num) { } +-}; +- +-// The base of DWARF2/3 debug info is a DIE (Debugging Information +-// Entry. +-// DWARF groups DIE's into a tree and calls the root of this tree a +-// "compilation unit". Most of the time, their is one compilation +-// unit in the .debug_info section for each file that had debug info +-// generated. +-// Each DIE consists of +- +-// 1. a tag specifying a thing that is being described (ie +-// DW_TAG_subprogram for functions, DW_TAG_variable for variables, etc +-// 2. attributes (such as DW_AT_location for location in memory, +-// DW_AT_name for name), and data for each attribute. +-// 3. A flag saying whether the DIE has children or not +- +-// In order to gain some amount of compression, the format of +-// each DIE (tag name, attributes and data forms for the attributes) +-// are stored in a separate table called the "abbreviation table". +-// This is done because a large number of DIEs have the exact same tag +-// and list of attributes, but different data for those attributes. +-// As a result, the .debug_info section is just a stream of data, and +-// requires reading of the .debug_abbrev section to say what the data +-// means. +- +-// As a warning to the user, it should be noted that the reason for +-// using absolute offsets from the beginning of .debug_info is that +-// DWARF2/3 support referencing DIE's from other DIE's by their offset +-// from either the current compilation unit start, *or* the beginning +-// of the .debug_info section. This means it is possible to reference +-// a DIE in one compilation unit from a DIE in another compilation +-// unit. This style of reference is usually used to eliminate +-// duplicated information that occurs across compilation +-// units, such as base types, etc. GCC 3.4+ support this with +-// -feliminate-dwarf2-dups. Other toolchains will sometimes do +-// duplicate elimination in the linker. +- +-class CompilationUnit { +- public: +- +- // Initialize a compilation unit. This requires a map of sections, +- // the offset of this compilation unit in the debug_info section, a +- // ByteReader, and a Dwarf2Handler class to call callbacks in. +- CompilationUnit(const SectionMap& sections, uint64 offset, +- ByteReader* reader, Dwarf2Handler* handler); +- virtual ~CompilationUnit() { +- if (abbrevs_) delete abbrevs_; +- } +- +- // Begin reading a Dwarf2 compilation unit, and calling the +- // callbacks in the Dwarf2Handler +- // Return the offset of the end of the compilation unit - the passed +- // in offset. +- uint64 Start(); +- +- private: +- +- // This struct represents a single DWARF2/3 abbreviation +- // The abbreviation tells how to read a DWARF2/3 DIE, and consist of a +- // tag and a list of attributes, as well as the data form of each attribute. +- struct Abbrev { +- uint32 number; +- enum DwarfTag tag; +- bool has_children; +- AttributeList attributes; +- }; +- +- // A DWARF2/3 compilation unit header. This is not the same size as +- // in the actual file, as the one in the file may have a 32 bit or +- // 64 bit length. +- struct CompilationUnitHeader { +- uint64 length; +- uint16 version; +- uint64 abbrev_offset; +- uint8 address_size; +- } header_; +- +- // Reads the DWARF2/3 header for this compilation unit. +- void ReadHeader(); +- +- // Reads the DWARF2/3 abbreviations for this compilation unit +- void ReadAbbrevs(); +- +- // Processes a single DIE for this compilation unit and return a new +- // pointer just past the end of it +- const char* ProcessDIE(uint64 dieoffset, +- const char* start, +- const Abbrev& abbrev); +- +- // Processes a single attribute and return a new pointer just past the +- // end of it +- const char* ProcessAttribute(uint64 dieoffset, +- const char* start, +- enum DwarfAttribute attr, +- enum DwarfForm form); +- +- // Processes all DIEs for this compilation unit +- void ProcessDIEs(); +- +- // Skips the die with attributes specified in ABBREV starting at +- // START, and return the new place to position the stream to. +- const char* SkipDIE(const char* start, +- const Abbrev& abbrev); +- +- // Skips the attribute starting at START, with FORM, and return the +- // new place to position the stream to. +- const char* SkipAttribute(const char* start, +- enum DwarfForm form); +- +- // Offset from section start is the offset of this compilation unit +- // from the beginning of the .debug_info section. +- uint64 offset_from_section_start_; +- +- // buffer is the buffer for our CU, starting at .debug_info + offset +- // passed in from constructor. +- // after_header points to right after the compilation unit header. +- const char* buffer_; +- uint64 buffer_length_; +- const char* after_header_; +- +- // The associated ByteReader that handles endianness issues for us +- ByteReader* reader_; +- +- // The map of sections in our file to buffers containing their data +- const SectionMap& sections_; +- +- // The associated handler to call processing functions in +- Dwarf2Handler* handler_; +- +- // Set of DWARF2/3 abbreviations for this compilation unit. Indexed +- // by abbreviation number, which means that abbrevs_[0] is not +- // valid. +- vector* abbrevs_; +- +- // String section buffer and length, if we have a string section. +- // This is here to avoid doing a section lookup for strings in +- // ProcessAttribute, which is in the hot path for DWARF2 reading. +- const char* string_buffer_; +- uint64 string_buffer_length_; +-}; +- +-// This class is the main interface between the reader and the +-// client. The virtual functions inside this get called for +-// interesting events that happen during DWARF2 reading. +-// The default implementation skips everything. +- +-class Dwarf2Handler { +- public: +- Dwarf2Handler() { } +- +- virtual ~Dwarf2Handler() { } +- +- // Start to process a compilation unit at OFFSET from the beginning of the +- // debug_info section. Return false if you would like +- // to skip this compilation unit. +- virtual bool StartCompilationUnit(uint64 offset, uint8 address_size, +- uint8 offset_size, uint64 cu_length, +- uint8 dwarf_version) { return false; } +- +- // Start to process a DIE at OFFSET from the beginning of the +- // debug_info section. Return false if you would like to skip this +- // DIE. +- virtual bool StartDIE(uint64 offset, enum DwarfTag tag, +- const AttributeList& attrs) { return false; } +- +- // Called when we have an attribute with unsigned data to give to +- // our handler. The attribute is for the DIE at OFFSET from the +- // beginning of compilation unit, has a name of ATTR, a form of +- // FORM, and the actual data of the attribute is in DATA. +- virtual void ProcessAttributeUnsigned(uint64 offset, +- enum DwarfAttribute attr, +- enum DwarfForm form, +- uint64 data) { } +- +- // Called when we have an attribute with signed data to give to +- // our handler. The attribute is for the DIE at OFFSET from the +- // beginning of compilation unit, has a name of ATTR, a form of +- // FORM, and the actual data of the attribute is in DATA. +- virtual void ProcessAttributeSigned(uint64 offset, +- enum DwarfAttribute attr, +- enum DwarfForm form, +- int64 data) { } +- +- // Called when we have an attribute with a buffer of data to give to +- // our handler. The attribute is for the DIE at OFFSET from the +- // beginning of compilation unit, has a name of ATTR, a form of +- // FORM, and the actual data of the attribute is in DATA, and the +- // length of the buffer is LENGTH. The buffer is owned by the +- // caller, not the callee, and may not persist for very long. If +- // you want the data to be available later, it needs to be copied. +- virtual void ProcessAttributeBuffer(uint64 offset, +- enum DwarfAttribute attr, +- enum DwarfForm form, +- const char* data, +- uint64 len) { } +- +- // Called when we have an attribute with string data to give to +- // our handler. The attribute is for the DIE at OFFSET from the +- // beginning of compilation unit, has a name of ATTR, a form of +- // FORM, and the actual data of the attribute is in DATA. +- virtual void ProcessAttributeString(uint64 offset, +- enum DwarfAttribute attr, +- enum DwarfForm form, +- const string& data) { } +- +- // Called when finished processing the DIE at OFFSET. +- // Because DWARF2/3 specifies a tree of DIEs, you may get starts +- // before ends of the previous DIE, as we process children before +- // ending the parent. +- virtual void EndDIE(uint64 offset) { } +- +-}; +- +- +-} // namespace dwarf2reader +- +-#endif // UTIL_DEBUGINFO_DWARF2READER_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/functioninfo.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/functioninfo.cc +deleted file mode 100644 +--- a/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/functioninfo.cc ++++ /dev/null +@@ -1,240 +0,0 @@ +-// Copyright 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. +- +-// This is a client for the dwarf2reader to extract function and line +-// information from the debug info. +- +-#include +-#include +-#include +- +- +-#include "common/mac/dwarf/functioninfo.h" +- +-#include "common/mac/dwarf/bytereader.h" +- +- +-namespace __gnu_cxx +-{ +- template<> +- struct hash +- { +- size_t operator()(const std::string& k) const; +- }; +-} +- +- +-namespace dwarf2reader { +- +-// Given an offset value, its form, and the base offset of the +-// compilation unit containing this value, return an absolute offset +-// within the .debug_info section. +-uint64 GetAbsoluteOffset(uint64 offset, +- enum DwarfForm form, +- uint64 compilation_unit_base) { +- switch (form) { +- case DW_FORM_ref1: +- case DW_FORM_ref2: +- case DW_FORM_ref4: +- case DW_FORM_ref8: +- case DW_FORM_ref_udata: +- return offset + compilation_unit_base; +- case DW_FORM_ref_addr: +- default: +- return offset; +- } +-} +- +-CULineInfoHandler::CULineInfoHandler(vector* files, +- vector* dirs, +- LineMap* linemap):linemap_(linemap), +- files_(files), +- dirs_(dirs) { +- // The dirs and files are 1 indexed, so just make sure we put +- // nothing in the 0 vector. +- assert(dirs->size() == 0); +- assert(files->size() == 0); +- dirs->push_back(""); +- SourceFileInfo s; +- s.name = ""; +- s.lowpc = ULLONG_MAX; +- files->push_back(s); +-} +- +-void CULineInfoHandler::DefineDir(const string& name, uint32 dir_num) { +- // These should never come out of order, actually +- assert(dir_num == dirs_->size()); +- dirs_->push_back(name); +-} +- +-void CULineInfoHandler::DefineFile(const string& name, +- int32 file_num, uint32 dir_num, +- uint64 mod_time, uint64 length) { +- assert(dir_num >= 0); +- assert(dir_num < dirs_->size()); +- +- // These should never come out of order, actually. +- if (file_num == (int32)files_->size() || file_num == -1) { +- string dir = dirs_->at(dir_num); +- +- SourceFileInfo s; +- s.lowpc = ULLONG_MAX; +- +- if (dir == "") { +- s.name = name; +- } else { +- s.name = dir + "/" + name; +- } +- +- files_->push_back(s); +- } else { +- fprintf(stderr, "error in DefineFile"); +- } +-} +- +-void CULineInfoHandler::AddLine(uint64 address, uint32 file_num, +- uint32 line_num, uint32 column_num) { +- if (file_num < files_->size()) { +- linemap_->insert(make_pair(address, make_pair(files_->at(file_num).name.c_str(), +- line_num))); +- +- if(address < files_->at(file_num).lowpc) { +- files_->at(file_num).lowpc = address; +- } +- } else { +- fprintf(stderr,"error in AddLine"); +- } +-} +- +-bool CUFunctionInfoHandler::StartCompilationUnit(uint64 offset, +- uint8 address_size, +- uint8 offset_size, +- uint64 cu_length, +- uint8 dwarf_version) { +- current_compilation_unit_offset_ = offset; +- return true; +-} +- +- +-// For function info, we only care about subprograms and inlined +-// subroutines. For line info, the DW_AT_stmt_list lives in the +-// compile unit tag. +- +-bool CUFunctionInfoHandler::StartDIE(uint64 offset, enum DwarfTag tag, +- const AttributeList& attrs) { +- switch (tag) { +- case DW_TAG_subprogram: +- case DW_TAG_inlined_subroutine: { +- current_function_info_ = new FunctionInfo; +- current_function_info_->lowpc = current_function_info_->highpc = 0; +- current_function_info_->name = ""; +- current_function_info_->line = 0; +- current_function_info_->file = ""; +- offset_to_funcinfo_->insert(make_pair(offset, current_function_info_)); +- }; +- // FALLTHROUGH +- case DW_TAG_compile_unit: +- return true; +- default: +- return false; +- } +- return false; +-} +- +-// Only care about the name attribute for functions +- +-void CUFunctionInfoHandler::ProcessAttributeString(uint64 offset, +- enum DwarfAttribute attr, +- enum DwarfForm form, +- const string &data) { +- if (current_function_info_) { +- if (attr == DW_AT_name) +- current_function_info_->name = data; +- else if(attr == DW_AT_MIPS_linkage_name) +- current_function_info_->mangled_name = data; +- } +-} +- +-void CUFunctionInfoHandler::ProcessAttributeUnsigned(uint64 offset, +- enum DwarfAttribute attr, +- enum DwarfForm form, +- uint64 data) { +- if (attr == DW_AT_stmt_list) { +- SectionMap::const_iterator iter = sections_.find("__debug_line"); +- assert(iter != sections_.end()); +- +- // this should be a scoped_ptr but we dont' use boost :-( +- auto_ptr lireader(new LineInfo(iter->second.first + data, +- iter->second.second - data, +- reader_, linehandler_)); +- lireader->Start(); +- } else if (current_function_info_) { +- switch (attr) { +- case DW_AT_low_pc: +- current_function_info_->lowpc = data; +- break; +- case DW_AT_high_pc: +- current_function_info_->highpc = data; +- break; +- case DW_AT_decl_line: +- current_function_info_->line = data; +- break; +- case DW_AT_decl_file: +- current_function_info_->file = files_->at(data).name; +- break; +- case DW_AT_specification: { +- // Some functions have a "specification" attribute +- // which means they were defined elsewhere. The name +- // attribute is not repeated, and must be taken from +- // the specification DIE. Here we'll assume that +- // any DIE referenced in this manner will already have +- // been seen, but that's not really required by the spec. +- uint64 abs_offset = GetAbsoluteOffset(data, form, current_compilation_unit_offset_); +- FunctionMap::iterator iter = offset_to_funcinfo_->find(abs_offset); +- if (iter != offset_to_funcinfo_->end()) { +- current_function_info_->name = iter->second->name; +- current_function_info_->mangled_name = iter->second->mangled_name; +- } else { +- // If you hit this, this code probably needs to be rewritten. +- fprintf(stderr, "Error: DW_AT_specification was seen before the referenced DIE! (Looking for DIE at offset %08llx, in DIE at offset %08llx)\n", abs_offset, offset); +- } +- break; +- } +- default: +- break; +- } +- } +-} +- +-void CUFunctionInfoHandler::EndDIE(uint64 offset) { +- if (current_function_info_ && current_function_info_->lowpc) +- address_to_funcinfo_->insert(make_pair(current_function_info_->lowpc, +- current_function_info_)); +-} +- +-} // namespace dwarf2reader +diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/functioninfo.h b/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/functioninfo.h +deleted file mode 100644 +--- a/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/functioninfo.h ++++ /dev/null +@@ -1,178 +0,0 @@ +-// Copyright 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. +- +- +-// This file contains the definitions for a DWARF2/3 information +-// collector that uses the DWARF2/3 reader interface to build a mapping +-// of addresses to files, lines, and functions. +- +-#ifndef COMMON_MAC_DWARF_FUNCTIONINFO_H__ +-#define COMMON_MAC_DWARF_FUNCTIONINFO_H__ +- +-#include +-#include +-#include +-#include +- +-#include "common/mac/dwarf/dwarf2reader.h" +- +- +-namespace dwarf2reader { +- +-struct FunctionInfo { +- // Name of the function +- string name; +- // Mangled name of the function +- string mangled_name; +- // File containing this function +- string file; +- // Line number for start of function. +- uint32 line; +- // Beginning address for this function +- uint64 lowpc; +- // End address for this function. +- uint64 highpc; +-}; +- +-struct SourceFileInfo { +- // Name of the source file name +- string name; +- // Low address of source file name +- uint64 lowpc; +-}; +- +-typedef map FunctionMap; +-typedef map > LineMap; +- +-// This class is a basic line info handler that fills in the dirs, +-// file, and linemap passed into it with the data produced from the +-// LineInfoHandler. +-class CULineInfoHandler: public LineInfoHandler { +- public: +- +- // +- CULineInfoHandler(vector* files, +- vector* dirs, +- LineMap* linemap); +- virtual ~CULineInfoHandler() { } +- +- // Called when we define a directory. We just place NAME into dirs_ +- // at position DIR_NUM. +- virtual void DefineDir(const string& name, uint32 dir_num); +- +- // Called when we define a filename. We just place +- // concat(dirs_[DIR_NUM], NAME) into files_ at position FILE_NUM. +- virtual void DefineFile(const string& name, int32 file_num, +- uint32 dir_num, uint64 mod_time, uint64 length); +- +- +- // Called when the line info reader has a new line, address pair +- // ready for us. ADDRESS is the address of the code, FILE_NUM is +- // the file number containing the code, LINE_NUM is the line number +- // in that file for the code, and COLUMN_NUM is the column number +- // the code starts at, if we know it (0 otherwise). +- virtual void AddLine(uint64 address, uint32 file_num, uint32 line_num, +- uint32 column_num); +- +- +- private: +- LineMap* linemap_; +- vector* files_; +- vector* dirs_; +-}; +- +-class CUFunctionInfoHandler: public Dwarf2Handler { +- public: +- CUFunctionInfoHandler(vector* files, +- vector* dirs, +- LineMap* linemap, +- FunctionMap* offset_to_funcinfo, +- FunctionMap* address_to_funcinfo, +- CULineInfoHandler* linehandler, +- const SectionMap& sections, +- ByteReader* reader) +- : files_(files), dirs_(dirs), linemap_(linemap), +- offset_to_funcinfo_(offset_to_funcinfo), +- address_to_funcinfo_(address_to_funcinfo), +- linehandler_(linehandler), sections_(sections), +- reader_(reader), current_function_info_(NULL) { } +- +- virtual ~CUFunctionInfoHandler() { } +- +- // Start to process a compilation unit at OFFSET from the beginning of the +- // debug_info section. We want to see all compilation units, so we +- // always return true. +- +- virtual bool StartCompilationUnit(uint64 offset, uint8 address_size, +- uint8 offset_size, uint64 cu_length, +- uint8 dwarf_version); +- +- // Start to process a DIE at OFFSET from the beginning of the +- // debug_info section. We only care about function related DIE's. +- virtual bool StartDIE(uint64 offset, enum DwarfTag tag, +- const AttributeList& attrs); +- +- // Called when we have an attribute with unsigned data to give to +- // our handler. The attribute is for the DIE at OFFSET from the +- // beginning of compilation unit, has a name of ATTR, a form of +- // FORM, and the actual data of the attribute is in DATA. +- virtual void ProcessAttributeUnsigned(uint64 offset, +- enum DwarfAttribute attr, +- enum DwarfForm form, +- uint64 data); +- +- // Called when we have an attribute with string data to give to +- // our handler. The attribute is for the DIE at OFFSET from the +- // beginning of compilation unit, has a name of ATTR, a form of +- // FORM, and the actual data of the attribute is in DATA. +- virtual void ProcessAttributeString(uint64 offset, +- enum DwarfAttribute attr, +- enum DwarfForm form, +- const string& data); +- +- // Called when finished processing the DIE at OFFSET. +- // Because DWARF2/3 specifies a tree of DIEs, you may get starts +- // before ends of the previous DIE, as we process children before +- // ending the parent. +- virtual void EndDIE(uint64 offset); +- +- private: +- vector* files_; +- vector* dirs_; +- LineMap* linemap_; +- FunctionMap* offset_to_funcinfo_; +- FunctionMap* address_to_funcinfo_; +- CULineInfoHandler* linehandler_; +- const SectionMap& sections_; +- ByteReader* reader_; +- FunctionInfo* current_function_info_; +- uint64 current_compilation_unit_offset_; +-}; +- +-} // namespace dwarf2reader +-#endif // COMMON_MAC_DWARF_FUNCTIONINFO_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/line_state_machine.h b/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/line_state_machine.h +deleted file mode 100644 +--- a/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/line_state_machine.h ++++ /dev/null +@@ -1,61 +0,0 @@ +-// Copyright 2008 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 COMMON_MAC_DWARF_LINE_STATE_MACHINE_H__ +-#define COMMON_MAC_DWARF_LINE_STATE_MACHINE_H__ +- +-namespace dwarf2reader { +- +-// This is the format of a DWARF2/3 line state machine that we process +-// opcodes using. There is no need for anything outside the lineinfo +-// processor to know how this works. +-struct LineStateMachine { +- void Reset(bool default_is_stmt) { +- file_num = 1; +- address = 0; +- line_num = 1; +- column_num = 0; +- is_stmt = default_is_stmt; +- basic_block = false; +- end_sequence = false; +- } +- +- uint32 file_num; +- uint64 address; +- uint64 line_num; +- uint32 column_num; +- bool is_stmt; // stmt means statement. +- bool basic_block; +- bool end_sequence; +-}; +- +-} // namespace dwarf2reader +- +- +-#endif // COMMON_MAC_DWARF_LINE_STATE_MACHINE_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/types.h b/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/types.h +deleted file mode 100644 +--- a/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/types.h ++++ /dev/null +@@ -1,46 +0,0 @@ +-// Copyright 2008 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. +- +- +-// This file contains some typedefs for basic types +- +- +-#ifndef _COMMON_MAC_DWARF_TYPES_H__ +-#define _COMMON_MAC_DWARF_TYPES_H__ +- +-typedef signed char int8; +-typedef short int16; +-typedef int int32; +-typedef long long int64; +- +-typedef unsigned char uint8; +-typedef unsigned short uint16; +-typedef unsigned int uint32; +-typedef unsigned long long uint64; +- +-#endif // _COMMON_MAC_DWARF_TYPES_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/testing/GTMSenTestCase.h b/toolkit/crashreporter/google-breakpad/src/common/mac/testing/GTMSenTestCase.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/mac/testing/GTMSenTestCase.h +@@ -0,0 +1,1004 @@ ++// ++// GTMSenTestCase.h ++// ++// Copyright 2007-2008 Google Inc. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); you may not ++// use this file except in compliance with the License. You may obtain a copy ++// of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT ++// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the ++// License for the specific language governing permissions and limitations under ++// the License. ++// ++ ++// Portions of this file fall under the following license, marked with ++// SENTE_BEGIN - SENTE_END ++// ++// Copyright (c) 1997-2005, Sen:te (Sente SA). All rights reserved. ++// ++// Use of this source code is governed by the following license: ++// ++// Redistribution and use in source and binary forms, with or without modification, ++// are permitted provided that the following conditions are met: ++// ++// (1) Redistributions of source code must retain the above copyright notice, ++// this list of conditions and the following disclaimer. ++// ++// (2) 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. ++// ++// 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 Sente SA 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. ++// ++// Note: this license is equivalent to the FreeBSD license. ++// ++// This notice may not be removed from this file. ++ ++// Some extra test case macros that would have been convenient for SenTestingKit ++// to provide. I didn't stick GTM in front of the Macro names, so that they would ++// be easy to remember. ++ ++#import "GTMDefines.h" ++ ++#if (!GTM_IPHONE_SDK) ++#import ++#else ++#import ++NSString *STComposeString(NSString *, ...); ++#endif ++ ++// Generates a failure when a1 != noErr ++// Args: ++// a1: should be either an OSErr or an OSStatus ++// description: A format string as in the printf() function. Can be nil or ++// an empty string but must be present. ++// ...: A variable number of arguments to the format string. Can be absent. ++#define STAssertNoErr(a1, description, ...) \ ++do { \ ++ @try {\ ++ OSStatus a1value = (a1); \ ++ if (a1value != noErr) { \ ++ NSString *_expression = [NSString stringWithFormat:@"Expected noErr, got %ld for (%s)", a1value, #a1]; \ ++ if (description) { \ ++ _expression = [NSString stringWithFormat:@"%@: %@", _expression, STComposeString(description, ##__VA_ARGS__)]; \ ++ } \ ++ [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:_expression]]; \ ++ } \ ++ }\ ++ @catch (id anException) {\ ++ [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == noErr fails", #a1] \ ++ exception:anException \ ++ inFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ ++ }\ ++} while(0) ++ ++// Generates a failure when a1 != a2 ++// Args: ++// a1: received value. Should be either an OSErr or an OSStatus ++// a2: expected value. Should be either an OSErr or an OSStatus ++// description: A format string as in the printf() function. Can be nil or ++// an empty string but must be present. ++// ...: A variable number of arguments to the format string. Can be absent. ++#define STAssertErr(a1, a2, description, ...) \ ++do { \ ++ @try {\ ++ OSStatus a1value = (a1); \ ++ OSStatus a2value = (a2); \ ++ if (a1value != a2value) { \ ++ NSString *_expression = [NSString stringWithFormat:@"Expected %s(%ld) but got %ld for (%s)", #a2, a2value, a1value, #a1]; \ ++ if (description) { \ ++ _expression = [NSString stringWithFormat:@"%@: %@", _expression, STComposeString(description, ##__VA_ARGS__)]; \ ++ } \ ++ [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:_expression]]; \ ++ } \ ++ }\ ++ @catch (id anException) {\ ++ [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s) fails", #a1, #a2] \ ++ exception:anException \ ++ inFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ ++ }\ ++} while(0) ++ ++ ++// Generates a failure when a1 is NULL ++// Args: ++// a1: should be a pointer (use STAssertNotNil for an object) ++// description: A format string as in the printf() function. Can be nil or ++// an empty string but must be present. ++// ...: A variable number of arguments to the format string. Can be absent. ++#define STAssertNotNULL(a1, description, ...) \ ++do { \ ++ @try {\ ++ const void* a1value = (a1); \ ++ if (a1value == NULL) { \ ++ NSString *_expression = [NSString stringWithFormat:@"(%s) != NULL", #a1]; \ ++ if (description) { \ ++ _expression = [NSString stringWithFormat:@"%@: %@", _expression, STComposeString(description, ##__VA_ARGS__)]; \ ++ } \ ++ [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:_expression]]; \ ++ } \ ++ }\ ++ @catch (id anException) {\ ++ [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != NULL fails", #a1] \ ++ exception:anException \ ++ inFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ ++ }\ ++} while(0) ++ ++// Generates a failure when a1 is not NULL ++// Args: ++// a1: should be a pointer (use STAssertNil for an object) ++// description: A format string as in the printf() function. Can be nil or ++// an empty string but must be present. ++// ...: A variable number of arguments to the format string. Can be absent. ++#define STAssertNULL(a1, description, ...) \ ++do { \ ++ @try {\ ++ const void* a1value = (a1); \ ++ if (a1value != NULL) { \ ++ NSString *_expression = [NSString stringWithFormat:@"(%s) == NULL", #a1]; \ ++ if (description) { \ ++ _expression = [NSString stringWithFormat:@"%@: %@", _expression, STComposeString(description, ##__VA_ARGS__)]; \ ++ } \ ++ [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:_expression]]; \ ++ } \ ++ }\ ++ @catch (id anException) {\ ++ [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == NULL fails", #a1] \ ++ exception:anException \ ++ inFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ ++ }\ ++} while(0) ++ ++// Generates a failure when a1 is equal to a2. This test is for C scalars, ++// structs and unions. ++// Args: ++// a1: argument 1 ++// a2: argument 2 ++// description: A format string as in the printf() function. Can be nil or ++// an empty string but must be present. ++// ...: A variable number of arguments to the format string. Can be absent. ++#define STAssertNotEquals(a1, a2, description, ...) \ ++do { \ ++ @try {\ ++ if (@encode(__typeof__(a1)) != @encode(__typeof__(a2))) { \ ++ [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:[[[NSString stringWithFormat:@"Type mismatch (%@/%@) -- ",@encode(__typeof__(a1)),@encode(__typeof__(a2))] stringByAppendingString:STComposeString(description, ##__VA_ARGS__)]]]; \ ++ } else { \ ++ __typeof__(a1) a1value = (a1); \ ++ __typeof__(a2) a2value = (a2); \ ++ NSValue *a1encoded = [NSValue value:&a1value withObjCType:@encode(__typeof__(a1))]; \ ++ NSValue *a2encoded = [NSValue value:&a2value withObjCType:@encode(__typeof__(a2))]; \ ++ if ([a1encoded isEqualToValue:a2encoded]) { \ ++ NSString *_expression = [NSString stringWithFormat:@"(%s) != (%s)", #a1, #a2]; \ ++ if (description) { \ ++ _expression = [NSString stringWithFormat:@"%@: %@", _expression, STComposeString(description, ##__VA_ARGS__)]; \ ++ } \ ++ [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:_expression]]; \ ++ } \ ++ } \ ++ } \ ++ @catch (id anException) {\ ++ [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != (%s)", #a1, #a2] \ ++ exception:anException \ ++ inFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ ++ }\ ++} while(0) ++ ++// Generates a failure when a1 is equal to a2. This test is for objects. ++// Args: ++// a1: argument 1. object. ++// a2: argument 2. object. ++// description: A format string as in the printf() function. Can be nil or ++// an empty string but must be present. ++// ...: A variable number of arguments to the format string. Can be absent. ++#define STAssertNotEqualObjects(a1, a2, desc, ...) \ ++do { \ ++ @try {\ ++ id a1value = (a1); \ ++ id a2value = (a2); \ ++ if ( (@encode(__typeof__(a1value)) == @encode(id)) && \ ++ (@encode(__typeof__(a2value)) == @encode(id)) && \ ++ ![(id)a1value isEqual:(id)a2value] ) continue; \ ++ NSString *_expression = [NSString stringWithFormat:@"%s('%@') != %s('%@')", #a1, [a1 description], #a2, [a2 description]]; \ ++ if (desc) { \ ++ _expression = [NSString stringWithFormat:@"%@: %@", _expression, STComposeString(desc, ##__VA_ARGS__)]; \ ++ } \ ++ [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:_expression]]; \ ++ }\ ++ @catch (id anException) {\ ++ [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) != (%s)", #a1, #a2] \ ++ exception:anException \ ++ inFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:STComposeString(desc, ##__VA_ARGS__)]]; \ ++ }\ ++} while(0) ++ ++// Generates a failure when a1 is not 'op' to a2. This test is for C scalars. ++// Args: ++// a1: argument 1 ++// a2: argument 2 ++// op: operation ++// description: A format string as in the printf() function. Can be nil or ++// an empty string but must be present. ++// ...: A variable number of arguments to the format string. Can be absent. ++#define STAssertOperation(a1, a2, op, description, ...) \ ++do { \ ++ @try {\ ++ if (@encode(__typeof__(a1)) != @encode(__typeof__(a2))) { \ ++ [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:[[[NSString stringWithFormat:@"Type mismatch (%@/%@) -- ",@encode(__typeof__(a1)),@encode(__typeof__(a2))] stringByAppendingString:STComposeString(description, ##__VA_ARGS__)]]]; \ ++ } else { \ ++ __typeof__(a1) a1value = (a1); \ ++ __typeof__(a2) a2value = (a2); \ ++ if (!(a1value op a2value)) { \ ++ double a1DoubleValue = a1value; \ ++ double a2DoubleValue = a2value; \ ++ NSString *_expression = [NSString stringWithFormat:@"%s (%lg) %s %s (%lg)", #a1, a1DoubleValue, #op, #a2, a2DoubleValue]; \ ++ if (description) { \ ++ _expression = [NSString stringWithFormat:@"%@: %@", _expression, STComposeString(description, ##__VA_ARGS__)]; \ ++ } \ ++ [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:_expression]]; \ ++ } \ ++ } \ ++ } \ ++ @catch (id anException) {\ ++ [self failWithException:[NSException \ ++ failureInRaise:[NSString stringWithFormat:@"(%s) %s (%s)", #a1, #op, #a2] \ ++ exception:anException \ ++ inFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ ++ }\ ++} while(0) ++ ++// Generates a failure when a1 is not > a2. This test is for C scalars. ++// Args: ++// a1: argument 1 ++// a2: argument 2 ++// op: operation ++// description: A format string as in the printf() function. Can be nil or ++// an empty string but must be present. ++// ...: A variable number of arguments to the format string. Can be absent. ++#define STAssertGreaterThan(a1, a2, description, ...) \ ++ STAssertOperation(a1, a2, >, description, ##__VA_ARGS__) ++ ++// Generates a failure when a1 is not >= a2. This test is for C scalars. ++// Args: ++// a1: argument 1 ++// a2: argument 2 ++// op: operation ++// description: A format string as in the printf() function. Can be nil or ++// an empty string but must be present. ++// ...: A variable number of arguments to the format string. Can be absent. ++#define STAssertGreaterThanOrEqual(a1, a2, description, ...) \ ++ STAssertOperation(a1, a2, >=, description, ##__VA_ARGS__) ++ ++// Generates a failure when a1 is not < a2. This test is for C scalars. ++// Args: ++// a1: argument 1 ++// a2: argument 2 ++// op: operation ++// description: A format string as in the printf() function. Can be nil or ++// an empty string but must be present. ++// ...: A variable number of arguments to the format string. Can be absent. ++#define STAssertLessThan(a1, a2, description, ...) \ ++ STAssertOperation(a1, a2, <, description, ##__VA_ARGS__) ++ ++// Generates a failure when a1 is not <= a2. This test is for C scalars. ++// Args: ++// a1: argument 1 ++// a2: argument 2 ++// op: operation ++// description: A format string as in the printf() function. Can be nil or ++// an empty string but must be present. ++// ...: A variable number of arguments to the format string. Can be absent. ++#define STAssertLessThanOrEqual(a1, a2, description, ...) \ ++ STAssertOperation(a1, a2, <=, description, ##__VA_ARGS__) ++ ++// Generates a failure when string a1 is not equal to string a2. This call ++// differs from STAssertEqualObjects in that strings that are different in ++// composition (precomposed vs decomposed) will compare equal if their final ++// representation is equal. ++// ex O + umlaut decomposed is the same as O + umlaut composed. ++// Args: ++// a1: string 1 ++// a2: string 2 ++// description: A format string as in the printf() function. Can be nil or ++// an empty string but must be present. ++// ...: A variable number of arguments to the format string. Can be absent. ++#define STAssertEqualStrings(a1, a2, description, ...) \ ++do { \ ++ @try {\ ++ id a1value = (a1); \ ++ id a2value = (a2); \ ++ if (a1value == a2value) continue; \ ++ if ([a1value isKindOfClass:[NSString class]] && \ ++ [a2value isKindOfClass:[NSString class]] && \ ++ [a1value compare:a2value options:0] == NSOrderedSame) continue; \ ++ [self failWithException:[NSException failureInEqualityBetweenObject: a1value \ ++ andObject: a2value \ ++ inFile: [NSString stringWithUTF8String:__FILE__] \ ++ atLine: __LINE__ \ ++ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ ++ }\ ++ @catch (id anException) {\ ++ [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) == (%s)", #a1, #a2] \ ++ exception:anException \ ++ inFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ ++ }\ ++} while(0) ++ ++// Generates a failure when string a1 is equal to string a2. This call ++// differs from STAssertEqualObjects in that strings that are different in ++// composition (precomposed vs decomposed) will compare equal if their final ++// representation is equal. ++// ex O + umlaut decomposed is the same as O + umlaut composed. ++// Args: ++// a1: string 1 ++// a2: string 2 ++// description: A format string as in the printf() function. Can be nil or ++// an empty string but must be present. ++// ...: A variable number of arguments to the format string. Can be absent. ++#define STAssertNotEqualStrings(a1, a2, description, ...) \ ++do { \ ++ @try {\ ++ id a1value = (a1); \ ++ id a2value = (a2); \ ++ if ([a1value isKindOfClass:[NSString class]] && \ ++ [a2value isKindOfClass:[NSString class]] && \ ++ [a1value compare:a2value options:0] != NSOrderedSame) continue; \ ++ [self failWithException:[NSException failureInEqualityBetweenObject: a1value \ ++ andObject: a2value \ ++ inFile: [NSString stringWithUTF8String:__FILE__] \ ++ atLine: __LINE__ \ ++ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ ++ }\ ++ @catch (id anException) {\ ++ [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) != (%s)", #a1, #a2] \ ++ exception:anException \ ++ inFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ ++ }\ ++} while(0) ++ ++// Generates a failure when c-string a1 is not equal to c-string a2. ++// Args: ++// a1: string 1 ++// a2: string 2 ++// description: A format string as in the printf() function. Can be nil or ++// an empty string but must be present. ++// ...: A variable number of arguments to the format string. Can be absent. ++#define STAssertEqualCStrings(a1, a2, description, ...) \ ++do { \ ++ @try {\ ++ const char* a1value = (a1); \ ++ const char* a2value = (a2); \ ++ if (a1value == a2value) continue; \ ++ if (strcmp(a1value, a2value) == 0) continue; \ ++ [self failWithException:[NSException failureInEqualityBetweenObject: [NSString stringWithUTF8String:a1value] \ ++ andObject: [NSString stringWithUTF8String:a2value] \ ++ inFile: [NSString stringWithUTF8String:__FILE__] \ ++ atLine: __LINE__ \ ++ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ ++ }\ ++ @catch (id anException) {\ ++ [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) == (%s)", #a1, #a2] \ ++ exception:anException \ ++ inFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ ++ }\ ++} while(0) ++ ++// Generates a failure when c-string a1 is equal to c-string a2. ++// Args: ++// a1: string 1 ++// a2: string 2 ++// description: A format string as in the printf() function. Can be nil or ++// an empty string but must be present. ++// ...: A variable number of arguments to the format string. Can be absent. ++#define STAssertNotEqualCStrings(a1, a2, description, ...) \ ++do { \ ++ @try {\ ++ const char* a1value = (a1); \ ++ const char* a2value = (a2); \ ++ if (strcmp(a1value, a2value) != 0) continue; \ ++ [self failWithException:[NSException failureInEqualityBetweenObject: [NSString stringWithUTF8String:a1value] \ ++ andObject: [NSString stringWithUTF8String:a2value] \ ++ inFile: [NSString stringWithUTF8String:__FILE__] \ ++ atLine: __LINE__ \ ++ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ ++ }\ ++ @catch (id anException) {\ ++ [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) != (%s)", #a1, #a2] \ ++ exception:anException \ ++ inFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ ++ }\ ++} while(0) ++ ++#if GTM_IPHONE_SDK ++ ++// SENTE_BEGIN ++/*" Generates a failure when !{ [a1 isEqualTo:a2] } is false ++ (or one is nil and the other is not). ++ _{a1 The object on the left.} ++ _{a2 The object on the right.} ++ _{description A format string as in the printf() function. Can be nil or ++ an empty string but must be present.} ++ _{... A variable number of arguments to the format string. Can be absent.} ++"*/ ++#define STAssertEqualObjects(a1, a2, description, ...) \ ++do { \ ++ @try {\ ++ id a1value = (a1); \ ++ id a2value = (a2); \ ++ if (a1value == a2value) continue; \ ++ if ( (@encode(__typeof__(a1value)) == @encode(id)) && \ ++ (@encode(__typeof__(a2value)) == @encode(id)) && \ ++ [(id)a1value isEqual: (id)a2value] ) continue; \ ++ [self failWithException:[NSException failureInEqualityBetweenObject: a1value \ ++ andObject: a2value \ ++ inFile: [NSString stringWithUTF8String:__FILE__] \ ++ atLine: __LINE__ \ ++ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ ++ }\ ++ @catch (id anException) {\ ++ [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) == (%s)", #a1, #a2] \ ++ exception:anException \ ++ inFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ ++ }\ ++} while(0) ++ ++ ++/*" Generates a failure when a1 is not equal to a2. This test is for ++ C scalars, structs and unions. ++ _{a1 The argument on the left.} ++ _{a2 The argument on the right.} ++ _{description A format string as in the printf() function. Can be nil or ++ an empty string but must be present.} ++ _{... A variable number of arguments to the format string. Can be absent.} ++"*/ ++#define STAssertEquals(a1, a2, description, ...) \ ++do { \ ++ @try {\ ++ if (@encode(__typeof__(a1)) != @encode(__typeof__(a2))) { \ ++ [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:[[NSString stringWithFormat:@"Type mismatch (%@/%@) -- ",@encode(__typeof__(a1)),@encode(__typeof__(a2))] stringByAppendingString:STComposeString(description, ##__VA_ARGS__)]]]; \ ++ } else { \ ++ __typeof__(a1) a1value = (a1); \ ++ __typeof__(a2) a2value = (a2); \ ++ NSValue *a1encoded = [NSValue value:&a1value withObjCType: @encode(__typeof__(a1))]; \ ++ NSValue *a2encoded = [NSValue value:&a2value withObjCType: @encode(__typeof__(a2))]; \ ++ if (![a1encoded isEqualToValue:a2encoded]) { \ ++ [self failWithException:[NSException failureInEqualityBetweenValue: a1encoded \ ++ andValue: a2encoded \ ++ withAccuracy: nil \ ++ inFile: [NSString stringWithUTF8String:__FILE__] \ ++ atLine: __LINE__ \ ++ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ ++ } \ ++ } \ ++ } \ ++ @catch (id anException) {\ ++ [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) == (%s)", #a1, #a2] \ ++ exception:anException \ ++ inFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ ++ }\ ++} while(0) ++ ++#define STAbsoluteDifference(left,right) (MAX(left,right)-MIN(left,right)) ++ ++ ++/*" Generates a failure when a1 is not equal to a2 within + or - accuracy is false. ++ This test is for scalars such as floats and doubles where small differences ++ could make these items not exactly equal, but also works for all scalars. ++ _{a1 The scalar on the left.} ++ _{a2 The scalar on the right.} ++ _{accuracy The maximum difference between a1 and a2 for these values to be ++ considered equal.} ++ _{description A format string as in the printf() function. Can be nil or ++ an empty string but must be present.} ++ _{... A variable number of arguments to the format string. Can be absent.} ++"*/ ++ ++#define STAssertEqualsWithAccuracy(a1, a2, accuracy, description, ...) \ ++do { \ ++ @try {\ ++ if (@encode(__typeof__(a1)) != @encode(__typeof__(a2))) { \ ++ [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:[[[NSString stringWithFormat:@"Type mismatch (%@/%@) -- ",@encode(__typeof__(a1)),@encode(__typeof__(a2))] stringByAppendingString:STComposeString(description, ##__VA_ARGS__)]]]; \ ++ } else { \ ++ __typeof__(a1) a1value = (a1); \ ++ __typeof__(a2) a2value = (a2); \ ++ __typeof__(accuracy) accuracyvalue = (accuracy); \ ++ if (STAbsoluteDifference(a1value, a2value) > accuracyvalue) { \ ++ NSValue *a1encoded = [NSValue value:&a1value withObjCType:@encode(__typeof__(a1))]; \ ++ NSValue *a2encoded = [NSValue value:&a2value withObjCType:@encode(__typeof__(a2))]; \ ++ NSValue *accuracyencoded = [NSValue value:&accuracyvalue withObjCType:@encode(__typeof__(accuracy))]; \ ++ [self failWithException:[NSException failureInEqualityBetweenValue: a1encoded \ ++ andValue: a2encoded \ ++ withAccuracy: accuracyencoded \ ++ inFile: [NSString stringWithUTF8String:__FILE__] \ ++ atLine: __LINE__ \ ++ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ ++ } \ ++ } \ ++ } \ ++ @catch (id anException) {\ ++ [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) == (%s)", #a1, #a2] \ ++ exception:anException \ ++ inFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ ++ }\ ++} while(0) ++ ++ ++ ++/*" Generates a failure unconditionally. ++ _{description A format string as in the printf() function. Can be nil or ++ an empty string but must be present.} ++ _{... A variable number of arguments to the format string. Can be absent.} ++"*/ ++#define STFail(description, ...) \ ++[self failWithException:[NSException failureInFile: [NSString stringWithUTF8String:__FILE__] \ ++ atLine: __LINE__ \ ++ withDescription: STComposeString(description, ##__VA_ARGS__)]] ++ ++ ++ ++/*" Generates a failure when a1 is not nil. ++ _{a1 An object.} ++ _{description A format string as in the printf() function. Can be nil or ++ an empty string but must be present.} ++ _{... A variable number of arguments to the format string. Can be absent.} ++"*/ ++#define STAssertNil(a1, description, ...) \ ++do { \ ++ @try {\ ++ id a1value = (a1); \ ++ if (a1value != nil) { \ ++ NSString *_a1 = [NSString stringWithUTF8String: #a1]; \ ++ NSString *_expression = [NSString stringWithFormat:@"((%@) == nil)", _a1]; \ ++ [self failWithException:[NSException failureInCondition: _expression \ ++ isTrue: NO \ ++ inFile: [NSString stringWithUTF8String:__FILE__] \ ++ atLine: __LINE__ \ ++ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ ++ } \ ++ }\ ++ @catch (id anException) {\ ++ [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) == nil fails", #a1] \ ++ exception:anException \ ++ inFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ ++ }\ ++} while(0) ++ ++ ++/*" Generates a failure when a1 is nil. ++ _{a1 An object.} ++ _{description A format string as in the printf() function. Can be nil or ++ an empty string but must be present.} ++ _{... A variable number of arguments to the format string. Can be absent.} ++"*/ ++#define STAssertNotNil(a1, description, ...) \ ++do { \ ++ @try {\ ++ id a1value = (a1); \ ++ if (a1value == nil) { \ ++ NSString *_a1 = [NSString stringWithUTF8String: #a1]; \ ++ NSString *_expression = [NSString stringWithFormat:@"((%@) != nil)", _a1]; \ ++ [self failWithException:[NSException failureInCondition: _expression \ ++ isTrue: NO \ ++ inFile: [NSString stringWithUTF8String:__FILE__] \ ++ atLine: __LINE__ \ ++ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ ++ } \ ++ }\ ++ @catch (id anException) {\ ++ [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) != nil fails", #a1] \ ++ exception:anException \ ++ inFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ ++ }\ ++} while(0) ++ ++ ++/*" Generates a failure when expression evaluates to false. ++ _{expr The expression that is tested.} ++ _{description A format string as in the printf() function. Can be nil or ++ an empty string but must be present.} ++ _{... A variable number of arguments to the format string. Can be absent.} ++"*/ ++#define STAssertTrue(expr, description, ...) \ ++do { \ ++ BOOL _evaluatedExpression = (expr);\ ++ if (!_evaluatedExpression) {\ ++ NSString *_expression = [NSString stringWithUTF8String: #expr];\ ++ [self failWithException:[NSException failureInCondition: _expression \ ++ isTrue: NO \ ++ inFile: [NSString stringWithUTF8String:__FILE__] \ ++ atLine: __LINE__ \ ++ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ ++ } \ ++} while (0) ++ ++ ++/*" Generates a failure when expression evaluates to false and in addition will ++ generate error messages if an exception is encountered. ++ _{expr The expression that is tested.} ++ _{description A format string as in the printf() function. Can be nil or ++ an empty string but must be present.} ++ _{... A variable number of arguments to the format string. Can be absent.} ++"*/ ++#define STAssertTrueNoThrow(expr, description, ...) \ ++do { \ ++ @try {\ ++ BOOL _evaluatedExpression = (expr);\ ++ if (!_evaluatedExpression) {\ ++ NSString *_expression = [NSString stringWithUTF8String: #expr];\ ++ [self failWithException:[NSException failureInCondition: _expression \ ++ isTrue: NO \ ++ inFile: [NSString stringWithUTF8String:__FILE__] \ ++ atLine: __LINE__ \ ++ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ ++ } \ ++ } \ ++ @catch (id anException) {\ ++ [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"(%s) ", #expr] \ ++ exception:anException \ ++ inFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ ++ }\ ++} while (0) ++ ++ ++/*" Generates a failure when the expression evaluates to true. ++ _{expr The expression that is tested.} ++ _{description A format string as in the printf() function. Can be nil or ++ an empty string but must be present.} ++ _{... A variable number of arguments to the format string. Can be absent.} ++"*/ ++#define STAssertFalse(expr, description, ...) \ ++do { \ ++ BOOL _evaluatedExpression = (expr);\ ++ if (_evaluatedExpression) {\ ++ NSString *_expression = [NSString stringWithUTF8String: #expr];\ ++ [self failWithException:[NSException failureInCondition: _expression \ ++ isTrue: YES \ ++ inFile: [NSString stringWithUTF8String:__FILE__] \ ++ atLine: __LINE__ \ ++ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ ++ } \ ++} while (0) ++ ++ ++/*" Generates a failure when the expression evaluates to true and in addition ++ will generate error messages if an exception is encountered. ++ _{expr The expression that is tested.} ++ _{description A format string as in the printf() function. Can be nil or ++ an empty string but must be present.} ++ _{... A variable number of arguments to the format string. Can be absent.} ++"*/ ++#define STAssertFalseNoThrow(expr, description, ...) \ ++do { \ ++ @try {\ ++ BOOL _evaluatedExpression = (expr);\ ++ if (_evaluatedExpression) {\ ++ NSString *_expression = [NSString stringWithUTF8String: #expr];\ ++ [self failWithException:[NSException failureInCondition: _expression \ ++ isTrue: YES \ ++ inFile: [NSString stringWithUTF8String:__FILE__] \ ++ atLine: __LINE__ \ ++ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ ++ } \ ++ } \ ++ @catch (id anException) {\ ++ [self failWithException:[NSException failureInRaise:[NSString stringWithFormat: @"!(%s) ", #expr] \ ++ exception:anException \ ++ inFile:[NSString stringWithUTF8String:__FILE__] \ ++ atLine:__LINE__ \ ++ withDescription:STComposeString(description, ##__VA_ARGS__)]]; \ ++ }\ ++} while (0) ++ ++ ++/*" Generates a failure when expression does not throw an exception. ++ _{expression The expression that is evaluated.} ++ _{description A format string as in the printf() function. Can be nil or ++ an empty string but must be present.} ++ _{... A variable number of arguments to the format string. Can be absent. ++"*/ ++#define STAssertThrows(expr, description, ...) \ ++do { \ ++ @try { \ ++ (expr);\ ++ } \ ++ @catch (id anException) { \ ++ continue; \ ++ }\ ++ [self failWithException:[NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ ++ exception: nil \ ++ inFile: [NSString stringWithUTF8String:__FILE__] \ ++ atLine: __LINE__ \ ++ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ ++} while (0) ++ ++ ++/*" Generates a failure when expression does not throw an exception of a ++ specific class. ++ _{expression The expression that is evaluated.} ++ _{specificException The specified class of the exception.} ++ _{description A format string as in the printf() function. Can be nil or ++ an empty string but must be present.} ++ _{... A variable number of arguments to the format string. Can be absent.} ++"*/ ++#define STAssertThrowsSpecific(expr, specificException, description, ...) \ ++do { \ ++ @try { \ ++ (expr);\ ++ } \ ++ @catch (specificException *anException) { \ ++ continue; \ ++ }\ ++ @catch (id anException) {\ ++ NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description);\ ++ [self failWithException:[NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ ++ exception: anException \ ++ inFile: [NSString stringWithUTF8String:__FILE__] \ ++ atLine: __LINE__ \ ++ withDescription: STComposeString(_descrip, ##__VA_ARGS__)]]; \ ++ continue; \ ++ }\ ++ NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description);\ ++ [self failWithException:[NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ ++ exception: nil \ ++ inFile: [NSString stringWithUTF8String:__FILE__] \ ++ atLine: __LINE__ \ ++ withDescription: STComposeString(_descrip, ##__VA_ARGS__)]]; \ ++} while (0) ++ ++ ++/*" Generates a failure when expression does not throw an exception of a ++ specific class with a specific name. Useful for those frameworks like ++ AppKit or Foundation that throw generic NSException w/specific names ++ (NSInvalidArgumentException, etc). ++ _{expression The expression that is evaluated.} ++ _{specificException The specified class of the exception.} ++ _{aName The name of the specified exception.} ++ _{description A format string as in the printf() function. Can be nil or ++ an empty string but must be present.} ++ _{... A variable number of arguments to the format string. Can be absent.} ++ ++"*/ ++#define STAssertThrowsSpecificNamed(expr, specificException, aName, description, ...) \ ++do { \ ++ @try { \ ++ (expr);\ ++ } \ ++ @catch (specificException *anException) { \ ++ if ([aName isEqualToString: [anException name]]) continue; \ ++ NSString *_descrip = STComposeString(@"(Expected exception: %@ (name: %@)) %@", NSStringFromClass([specificException class]), aName, description);\ ++ [self failWithException: \ ++ [NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ ++ exception: anException \ ++ inFile: [NSString stringWithUTF8String:__FILE__] \ ++ atLine: __LINE__ \ ++ withDescription: STComposeString(_descrip, ##__VA_ARGS__)]]; \ ++ continue; \ ++ }\ ++ @catch (id anException) {\ ++ NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description);\ ++ [self failWithException: \ ++ [NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ ++ exception: anException \ ++ inFile: [NSString stringWithUTF8String:__FILE__] \ ++ atLine: __LINE__ \ ++ withDescription: STComposeString(_descrip, ##__VA_ARGS__)]]; \ ++ continue; \ ++ }\ ++ NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description);\ ++ [self failWithException: \ ++ [NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ ++ exception: nil \ ++ inFile: [NSString stringWithUTF8String:__FILE__] \ ++ atLine: __LINE__ \ ++ withDescription: STComposeString(_descrip, ##__VA_ARGS__)]]; \ ++} while (0) ++ ++ ++/*" Generates a failure when expression does throw an exception. ++ _{expression The expression that is evaluated.} ++ _{description A format string as in the printf() function. Can be nil or ++ an empty string but must be present.} ++ _{... A variable number of arguments to the format string. Can be absent.} ++"*/ ++#define STAssertNoThrow(expr, description, ...) \ ++do { \ ++ @try { \ ++ (expr);\ ++ } \ ++ @catch (id anException) { \ ++ [self failWithException:[NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ ++ exception: anException \ ++ inFile: [NSString stringWithUTF8String:__FILE__] \ ++ atLine: __LINE__ \ ++ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ ++ }\ ++} while (0) ++ ++ ++/*" Generates a failure when expression does throw an exception of the specitied ++ class. Any other exception is okay (i.e. does not generate a failure). ++ _{expression The expression that is evaluated.} ++ _{specificException The specified class of the exception.} ++ _{description A format string as in the printf() function. Can be nil or ++ an empty string but must be present.} ++ _{... A variable number of arguments to the format string. Can be absent.} ++"*/ ++#define STAssertNoThrowSpecific(expr, specificException, description, ...) \ ++do { \ ++ @try { \ ++ (expr);\ ++ } \ ++ @catch (specificException *anException) { \ ++ [self failWithException:[NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ ++ exception: anException \ ++ inFile: [NSString stringWithUTF8String:__FILE__] \ ++ atLine: __LINE__ \ ++ withDescription: STComposeString(description, ##__VA_ARGS__)]]; \ ++ }\ ++ @catch (id anythingElse) {\ ++ ; \ ++ }\ ++} while (0) ++ ++ ++/*" Generates a failure when expression does throw an exception of a ++ specific class with a specific name. Useful for those frameworks like ++ AppKit or Foundation that throw generic NSException w/specific names ++ (NSInvalidArgumentException, etc). ++ _{expression The expression that is evaluated.} ++ _{specificException The specified class of the exception.} ++ _{aName The name of the specified exception.} ++ _{description A format string as in the printf() function. Can be nil or ++ an empty string but must be present.} ++ _{... A variable number of arguments to the format string. Can be absent.} ++ ++"*/ ++#define STAssertNoThrowSpecificNamed(expr, specificException, aName, description, ...) \ ++do { \ ++ @try { \ ++ (expr);\ ++ } \ ++ @catch (specificException *anException) { \ ++ if ([aName isEqualToString: [anException name]]) { \ ++ NSString *_descrip = STComposeString(@"(Expected exception: %@ (name: %@)) %@", NSStringFromClass([specificException class]), aName, description);\ ++ [self failWithException: \ ++ [NSException failureInRaise: [NSString stringWithUTF8String:#expr] \ ++ exception: anException \ ++ inFile: [NSString stringWithUTF8String:__FILE__] \ ++ atLine: __LINE__ \ ++ withDescription: STComposeString(_descrip, ##__VA_ARGS__)]]; \ ++ } \ ++ continue; \ ++ }\ ++ @catch (id anythingElse) {\ ++ ; \ ++ }\ ++} while (0) ++ ++ ++ ++@interface NSException (GTMSenTestAdditions) +++ (NSException *)failureInFile:(NSString *)filename ++ atLine:(int)lineNumber ++ withDescription:(NSString *)formatString, ...; +++ (NSException *)failureInCondition:(NSString *)condition ++ isTrue:(BOOL)isTrue ++ inFile:(NSString *)filename ++ atLine:(int)lineNumber ++ withDescription:(NSString *)formatString, ...; +++ (NSException *)failureInEqualityBetweenObject:(id)left ++ andObject:(id)right ++ inFile:(NSString *)filename ++ atLine:(int)lineNumber ++ withDescription:(NSString *)formatString, ...; +++ (NSException *)failureInEqualityBetweenValue:(NSValue *)left ++ andValue:(NSValue *)right ++ withAccuracy:(NSValue *)accuracy ++ inFile:(NSString *)filename ++ atLine:(int) ineNumber ++ withDescription:(NSString *)formatString, ...; +++ (NSException *)failureInRaise:(NSString *)expression ++ inFile:(NSString *)filename ++ atLine:(int)lineNumber ++ withDescription:(NSString *)formatString, ...; +++ (NSException *)failureInRaise:(NSString *)expression ++ exception:(NSException *)exception ++ inFile:(NSString *)filename ++ atLine:(int)lineNumber ++ withDescription:(NSString *)formatString, ...; ++@end ++ ++// SENTE_END ++ ++@interface SenTestCase : NSObject { ++ SEL currentSelector_; ++} ++ ++- (void)setUp; ++- (void)invokeTest; ++- (void)tearDown; ++- (void)performTest:(SEL)sel; ++- (void)failWithException:(NSException*)exception; ++@end ++ ++GTM_EXTERN NSString *const SenTestFailureException; ++ ++GTM_EXTERN NSString *const SenTestFilenameKey; ++GTM_EXTERN NSString *const SenTestLineNumberKey; ++ ++#endif // GTM_IPHONE_SDK ++ ++// All unittest cases in GTM should inherit from GTMTestCase. It makes sure ++// to set up our logging system correctly to verify logging calls. ++// See GTMUnitTestDevLog.h for details ++@interface GTMTestCase : SenTestCase ++@end +diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/testing/GTMSenTestCase.m b/toolkit/crashreporter/google-breakpad/src/common/mac/testing/GTMSenTestCase.m +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/common/mac/testing/GTMSenTestCase.m +@@ -0,0 +1,366 @@ ++// ++// GTMSenTestCase.m ++// ++// Copyright 2007-2008 Google Inc. ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); you may not ++// use this file except in compliance with the License. You may obtain a copy ++// of the License at ++// ++// http://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT ++// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the ++// License for the specific language governing permissions and limitations under ++// the License. ++// ++ ++#import "GTMSenTestCase.h" ++#import ++ ++#if !GTM_IPHONE_SDK ++#import "GTMGarbageCollection.h" ++#endif // !GTM_IPHONE_SDK ++ ++#if GTM_IPHONE_SDK ++#import ++ ++@interface NSException (GTMSenTestPrivateAdditions) +++ (NSException *)failureInFile:(NSString *)filename ++ atLine:(int)lineNumber ++ reason:(NSString *)reason; ++@end ++ ++@implementation NSException (GTMSenTestPrivateAdditions) +++ (NSException *)failureInFile:(NSString *)filename ++ atLine:(int)lineNumber ++ reason:(NSString *)reason { ++ NSDictionary *userInfo = ++ [NSDictionary dictionaryWithObjectsAndKeys: ++ [NSNumber numberWithInteger:lineNumber], SenTestLineNumberKey, ++ filename, SenTestFilenameKey, ++ nil]; ++ ++ return [self exceptionWithName:SenTestFailureException ++ reason:reason ++ userInfo:userInfo]; ++} ++@end ++ ++@implementation NSException (GTMSenTestAdditions) ++ +++ (NSException *)failureInFile:(NSString *)filename ++ atLine:(int)lineNumber ++ withDescription:(NSString *)formatString, ... { ++ ++ NSString *testDescription = @""; ++ if (formatString) { ++ va_list vl; ++ va_start(vl, formatString); ++ testDescription = ++ [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; ++ va_end(vl); ++ } ++ ++ NSString *reason = testDescription; ++ ++ return [self failureInFile:filename atLine:lineNumber reason:reason]; ++} ++ +++ (NSException *)failureInCondition:(NSString *)condition ++ isTrue:(BOOL)isTrue ++ inFile:(NSString *)filename ++ atLine:(int)lineNumber ++ withDescription:(NSString *)formatString, ... { ++ ++ NSString *testDescription = @""; ++ if (formatString) { ++ va_list vl; ++ va_start(vl, formatString); ++ testDescription = ++ [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; ++ va_end(vl); ++ } ++ ++ NSString *reason = [NSString stringWithFormat:@"'%@' should be %s. %@", ++ condition, isTrue ? "TRUE" : "FALSE", testDescription]; ++ ++ return [self failureInFile:filename atLine:lineNumber reason:reason]; ++} ++ +++ (NSException *)failureInEqualityBetweenObject:(id)left ++ andObject:(id)right ++ inFile:(NSString *)filename ++ atLine:(int)lineNumber ++ withDescription:(NSString *)formatString, ... { ++ ++ NSString *testDescription = @""; ++ if (formatString) { ++ va_list vl; ++ va_start(vl, formatString); ++ testDescription = ++ [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; ++ va_end(vl); ++ } ++ ++ NSString *reason = ++ [NSString stringWithFormat:@"'%@' should be equal to '%@'. %@", ++ [left description], [right description], testDescription]; ++ ++ return [self failureInFile:filename atLine:lineNumber reason:reason]; ++} ++ +++ (NSException *)failureInEqualityBetweenValue:(NSValue *)left ++ andValue:(NSValue *)right ++ withAccuracy:(NSValue *)accuracy ++ inFile:(NSString *)filename ++ atLine:(int)lineNumber ++ withDescription:(NSString *)formatString, ... { ++ ++ NSString *testDescription = @""; ++ if (formatString) { ++ va_list vl; ++ va_start(vl, formatString); ++ testDescription = ++ [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; ++ va_end(vl); ++ } ++ ++ NSString *reason; ++ if (accuracy) { ++ reason = ++ [NSString stringWithFormat:@"'%@' should be equal to '%@'. %@", ++ left, right, testDescription]; ++ } else { ++ reason = ++ [NSString stringWithFormat:@"'%@' should be equal to '%@' +/-'%@'. %@", ++ left, right, accuracy, testDescription]; ++ } ++ ++ return [self failureInFile:filename atLine:lineNumber reason:reason]; ++} ++ +++ (NSException *)failureInRaise:(NSString *)expression ++ inFile:(NSString *)filename ++ atLine:(int)lineNumber ++ withDescription:(NSString *)formatString, ... { ++ ++ NSString *testDescription = @""; ++ if (formatString) { ++ va_list vl; ++ va_start(vl, formatString); ++ testDescription = ++ [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; ++ va_end(vl); ++ } ++ ++ NSString *reason = [NSString stringWithFormat:@"'%@' should raise. %@", ++ expression, testDescription]; ++ ++ return [self failureInFile:filename atLine:lineNumber reason:reason]; ++} ++ +++ (NSException *)failureInRaise:(NSString *)expression ++ exception:(NSException *)exception ++ inFile:(NSString *)filename ++ atLine:(int)lineNumber ++ withDescription:(NSString *)formatString, ... { ++ ++ NSString *testDescription = @""; ++ if (formatString) { ++ va_list vl; ++ va_start(vl, formatString); ++ testDescription = ++ [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; ++ va_end(vl); ++ } ++ ++ NSString *reason; ++ if ([[exception name] isEqualToString:SenTestFailureException]) { ++ // it's our exception, assume it has the right description on it. ++ reason = [exception reason]; ++ } else { ++ // not one of our exception, use the exceptions reason and our description ++ reason = [NSString stringWithFormat:@"'%@' raised '%@'. %@", ++ expression, [exception reason], testDescription]; ++ } ++ ++ return [self failureInFile:filename atLine:lineNumber reason:reason]; ++} ++ ++@end ++ ++NSString *STComposeString(NSString *formatString, ...) { ++ NSString *reason = @""; ++ if (formatString) { ++ va_list vl; ++ va_start(vl, formatString); ++ reason = ++ [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease]; ++ va_end(vl); ++ } ++ return reason; ++} ++ ++NSString *const SenTestFailureException = @"SenTestFailureException"; ++NSString *const SenTestFilenameKey = @"SenTestFilenameKey"; ++NSString *const SenTestLineNumberKey = @"SenTestLineNumberKey"; ++ ++@interface SenTestCase (SenTestCasePrivate) ++// our method of logging errors +++ (void)printException:(NSException *)exception fromTestName:(NSString *)name; ++@end ++ ++@implementation SenTestCase ++- (void)failWithException:(NSException*)exception { ++ [exception raise]; ++} ++ ++- (void)setUp { ++} ++ ++- (void)performTest:(SEL)sel { ++ currentSelector_ = sel; ++ @try { ++ [self invokeTest]; ++ } @catch (NSException *exception) { ++ [[self class] printException:exception ++ fromTestName:NSStringFromSelector(sel)]; ++ [exception raise]; ++ } ++} ++ +++ (void)printException:(NSException *)exception fromTestName:(NSString *)name { ++ NSDictionary *userInfo = [exception userInfo]; ++ NSString *filename = [userInfo objectForKey:SenTestFilenameKey]; ++ NSNumber *lineNumber = [userInfo objectForKey:SenTestLineNumberKey]; ++ NSString *className = NSStringFromClass([self class]); ++ if ([filename length] == 0) { ++ filename = @"Unknown.m"; ++ } ++ fprintf(stderr, "%s:%ld: error: -[%s %s] : %s\n", ++ [filename UTF8String], ++ (long)[lineNumber integerValue], ++ [className UTF8String], ++ [name UTF8String], ++ [[exception reason] UTF8String]); ++ fflush(stderr); ++} ++ ++- (void)invokeTest { ++ NSException *e = nil; ++ @try { ++ // Wrap things in autorelease pools because they may ++ // have an STMacro in their dealloc which may get called ++ // when the pool is cleaned up ++ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; ++ // We don't log exceptions here, instead we let the person that called ++ // this log the exception. This ensures they are only logged once but the ++ // outer layers get the exceptions to report counts, etc. ++ @try { ++ [self setUp]; ++ @try { ++ [self performSelector:currentSelector_]; ++ } @catch (NSException *exception) { ++ e = [exception retain]; ++ } ++ [self tearDown]; ++ } @catch (NSException *exception) { ++ e = [exception retain]; ++ } ++ [pool release]; ++ } @catch (NSException *exception) { ++ e = [exception retain]; ++ } ++ if (e) { ++ [e autorelease]; ++ [e raise]; ++ } ++} ++ ++- (void)tearDown { ++} ++ ++- (NSString *)description { ++ // This matches the description OCUnit would return to you ++ return [NSString stringWithFormat:@"-[%@ %@]", [self class], ++ NSStringFromSelector(currentSelector_)]; ++} ++@end ++ ++#endif // GTM_IPHONE_SDK ++ ++@implementation GTMTestCase : SenTestCase ++- (void)invokeTest { ++ Class devLogClass = NSClassFromString(@"GTMUnitTestDevLog"); ++ if (devLogClass) { ++ [devLogClass performSelector:@selector(enableTracking)]; ++ [devLogClass performSelector:@selector(verifyNoMoreLogsExpected)]; ++ ++ } ++ [super invokeTest]; ++ if (devLogClass) { ++ [devLogClass performSelector:@selector(verifyNoMoreLogsExpected)]; ++ [devLogClass performSelector:@selector(disableTracking)]; ++ } ++} ++@end ++ ++// Leak detection ++#if !GTM_IPHONE_DEVICE ++// Don't want to get leaks on the iPhone Device as the device doesn't ++// have 'leaks'. The simulator does though. ++ ++// COV_NF_START ++// We don't have leak checking on by default, so this won't be hit. ++static void _GTMRunLeaks(void) { ++ // This is an atexit handler. It runs leaks for us to check if we are ++ // leaking anything in our tests. ++ const char* cExclusionsEnv = getenv("GTM_LEAKS_SYMBOLS_TO_IGNORE"); ++ NSMutableString *exclusions = [NSMutableString string]; ++ if (cExclusionsEnv) { ++ NSString *exclusionsEnv = [NSString stringWithUTF8String:cExclusionsEnv]; ++ NSArray *exclusionsArray = [exclusionsEnv componentsSeparatedByString:@","]; ++ NSString *exclusion; ++ NSCharacterSet *wcSet = [NSCharacterSet whitespaceCharacterSet]; ++ GTM_FOREACH_OBJECT(exclusion, exclusionsArray) { ++ exclusion = [exclusion stringByTrimmingCharactersInSet:wcSet]; ++ [exclusions appendFormat:@"-exclude \"%@\" ", exclusion]; ++ } ++ } ++ NSString *string ++ = [NSString stringWithFormat:@"/usr/bin/leaks %@%d" ++ @"| /usr/bin/sed -e 's/Leak: /Leaks:0: warning: Leak /'", ++ exclusions, getpid()]; ++ int ret = system([string UTF8String]); ++ if (ret) { ++ fprintf(stderr, "%s:%d: Error: Unable to run leaks. 'system' returned: %d", ++ __FILE__, __LINE__, ret); ++ fflush(stderr); ++ } ++} ++// COV_NF_END ++ ++static __attribute__((constructor)) void _GTMInstallLeaks(void) { ++ BOOL checkLeaks = YES; ++#if !GTM_IPHONE_SDK ++ checkLeaks = GTMIsGarbageCollectionEnabled() ? NO : YES; ++#endif // !GTM_IPHONE_SDK ++ if (checkLeaks) { ++ checkLeaks = getenv("GTM_ENABLE_LEAKS") ? YES : NO; ++ if (checkLeaks) { ++ // COV_NF_START ++ // We don't have leak checking on by default, so this won't be hit. ++ fprintf(stderr, "Leak Checking Enabled\n"); ++ fflush(stderr); ++ int ret = atexit(&_GTMRunLeaks); ++ _GTMDevAssert(ret == 0, ++ @"Unable to install _GTMRunLeaks as an atexit handler (%d)", ++ errno); ++ // COV_NF_END ++ } ++ } ++} ++ ++#endif // !GTM_IPHONE_DEVICE +diff --git a/toolkit/crashreporter/google-breakpad/src/common/solaris/dump_symbols.cc b/toolkit/crashreporter/google-breakpad/src/common/solaris/dump_symbols.cc +--- a/toolkit/crashreporter/google-breakpad/src/common/solaris/dump_symbols.cc ++++ b/toolkit/crashreporter/google-breakpad/src/common/solaris/dump_symbols.cc +@@ -171,34 +171,35 @@ inline void RecalculateOffset(struct sli + } + // Skip the extra '\0' + ++stringOffset; + } + + // Demangle using demangle library on Solaris. + std::string Demangle(const char *mangled) { + int status = 0; ++ std::string str(mangled); + char *demangled = (char *)malloc(demangleLen); ++ + if (!demangled) { + fprintf(stderr, "no enough memory.\n"); + goto out; + } + + if ((status = cplus_demangle(mangled, demangled, demangleLen)) == + DEMANGLE_ESPACE) { + fprintf(stderr, "incorrect demangle.\n"); + goto out; + } + +- std::string str(demangled); ++ str = demangled; + free(demangled); +- return str; + + out: +- return std::string(mangled); ++ return str; + } + + bool WriteFormat(int fd, const char *fmt, ...) { + va_list list; + char buffer[4096]; + ssize_t expected, written; + va_start(list, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, list); +@@ -645,17 +646,17 @@ bool DumpSymbols::WriteSymbolFile(const + if (obj_fd < 0) + return false; + FDWrapper obj_fd_wrapper(obj_fd); + struct stat st; + if (fstat(obj_fd, &st) != 0 && st.st_size <= 0) + return false; + void *obj_base = mmap(NULL, st.st_size, + PROT_READ, MAP_PRIVATE, obj_fd, 0); +- if (!obj_base) ++ if (obj_base == MAP_FAILED)) + return false; + MmapWrapper map_wrapper(obj_base, st.st_size); + GElf_Ehdr elf_header; + Elf *elf = elf_begin(obj_fd, ELF_C_READ, NULL); + AutoElfEnder elfEnder(elf); + + if (gelf_getehdr(elf, &elf_header) == (GElf_Ehdr *)NULL) { + fprintf(stderr, "failed to read elf header: %s\n", elf_errmsg(-1)); +diff --git a/toolkit/crashreporter/google-breakpad/src/common/solaris/file_id.cc b/toolkit/crashreporter/google-breakpad/src/common/solaris/file_id.cc +--- a/toolkit/crashreporter/google-breakpad/src/common/solaris/file_id.cc ++++ b/toolkit/crashreporter/google-breakpad/src/common/solaris/file_id.cc +@@ -146,17 +146,17 @@ bool FileID::ElfFileIdentifier(unsigned + return false; + + AutoCloser autocloser(fd); + struct stat st; + if (fstat(fd, &st) != 0 || st.st_size <= 0) + return false; + + void *base = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); +- if (!base) ++ if (base == MAP_FAILED) + return false; + + bool success = false; + const void *text_section = NULL; + int text_size = 0; + + if (FindElfTextSection(fd, base, &text_section, &text_size)) { + MD5Context md5; +diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.cc b/toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.cc +--- a/toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.cc ++++ b/toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.cc +@@ -25,17 +25,17 @@ + // 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 + + // Disable exception handler warnings. +-#pragma warning( disable : 4530 ) ++#pragma warning( disable : 4530 ) + + #include + + #include "common/windows/string_utils-inl.h" + + #include "common/windows/http_upload.h" + + namespace google_breakpad { +@@ -61,22 +61,23 @@ class HTTPUpload::AutoInternetHandle { + HINTERNET handle_; + }; + + // static + bool HTTPUpload::SendRequest(const wstring &url, + const map ¶meters, + const wstring &upload_file, + const wstring &file_part_name, ++ int *timeout, + wstring *response_body, + int *response_code) { + if (response_code) { + *response_code = 0; + } +- ++ + // TODO(bryner): support non-ASCII parameter names + if (!CheckParameters(parameters)) { + return false; + } + + // Break up the URL and make sure we can handle it + wchar_t scheme[16], host[256], path[256]; + URL_COMPONENTS components; +@@ -141,16 +142,32 @@ bool HTTPUpload::SendRequest(const wstri + HTTP_ADDREQ_FLAG_ADD); + + string request_body; + if (!GenerateRequestBody(parameters, upload_file, + file_part_name, boundary, &request_body)) { + return false; + } + ++ if (timeout) { ++ if (!InternetSetOption(request.get(), ++ INTERNET_OPTION_SEND_TIMEOUT, ++ timeout, ++ sizeof(timeout))) { ++ fwprintf(stderr, L"Could not unset send timeout, continuing...\n"); ++ } ++ ++ if (!InternetSetOption(request.get(), ++ INTERNET_OPTION_RECEIVE_TIMEOUT, ++ timeout, ++ sizeof(timeout))) { ++ fwprintf(stderr, L"Could not unset receive timeout, continuing...\n"); ++ } ++ } ++ + if (!HttpSendRequest(request.get(), NULL, 0, + const_cast(request_body.data()), + static_cast(request_body.size()))) { + return false; + } + + // The server indicates a successful upload with HTTP status 200. + wchar_t http_status[4]; +@@ -189,27 +206,29 @@ bool HTTPUpload::ReadResponse(HINTERNET + has_content_length_header = true; + claimed_size = wcstol(content_length, NULL, 10); + response_body.reserve(claimed_size); + } + + + DWORD bytes_available; + DWORD total_read = 0; +- bool return_code; ++ BOOL return_code; + +- while ((return_code = InternetQueryDataAvailable(request, &bytes_available, +- 0, 0) != 0) && +- bytes_available > 0) { ++ while (((return_code = InternetQueryDataAvailable(request, &bytes_available, ++ 0, 0)) != 0) && bytes_available > 0) { ++ + vector response_buffer(bytes_available); + DWORD size_read; + +- if ((return_code = InternetReadFile(request, &response_buffer[0], +- bytes_available, &size_read) != 0) && +- size_read > 0) { ++ return_code = InternetReadFile(request, ++ &response_buffer[0], ++ bytes_available, &size_read); ++ ++ if (return_code && size_read > 0) { + total_read += size_read; + response_body.append(&response_buffer[0], size_read); + } else { + break; + } + } + + bool succeeded = return_code && (!has_content_length_header || +@@ -311,17 +330,17 @@ void HTTPUpload::GetFileContents(const w + #if _MSC_VER >= 1400 // MSVC 2005/8 + ifstream file; + file.open(filename.c_str(), ios::binary); + #else // _MSC_VER >= 1400 + ifstream file(_wfopen(filename.c_str(), L"rb")); + #endif // _MSC_VER >= 1400 + if (file.is_open()) { + file.seekg(0, ios::end); +- int length = file.tellg(); ++ std::streamoff length = file.tellg(); + contents->resize(length); + if (length != 0) { + file.seekg(0, ios::beg); + file.read(&((*contents)[0]), length); + } + file.close(); + } else { + contents->clear(); +diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.h b/toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.h +--- a/toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.h ++++ b/toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.h +@@ -64,16 +64,17 @@ class HTTPUpload { + // If the request is successful and response_body is non-NULL, + // the response body will be returned in response_body. + // If response_code is non-NULL, it will be set to the HTTP response code + // received (or 0 if the request failed before getting an HTTP response). + static bool SendRequest(const wstring &url, + const map ¶meters, + const wstring &upload_file, + const wstring &file_part_name, ++ int *timeout, + wstring *response_body, + int *response_code); + + private: + class AutoInternetHandle; + + // Retrieves the HTTP response. If NULL is passed in for response, + // this merely checks (via the return value) that we were successfully +diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.cc b/toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.cc +--- a/toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.cc ++++ b/toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.cc +@@ -113,45 +113,48 @@ bool PDBSourceLineWriter::PrintLines(IDi + } + + DWORD length; + if (FAILED(line->get_length(&length))) { + fprintf(stderr, "failed to get line code length\n"); + return false; + } + +- DWORD source_id; +- if (FAILED(line->get_sourceFileId(&source_id))) { ++ DWORD dia_source_id; ++ if (FAILED(line->get_sourceFileId(&dia_source_id))) { + fprintf(stderr, "failed to get line source file id\n"); + return false; + } ++ // duplicate file names are coalesced to share one ID ++ DWORD source_id = GetRealFileID(dia_source_id); + + DWORD line_num; + if (FAILED(line->get_lineNumber(&line_num))) { + fprintf(stderr, "failed to get line number\n"); + return false; + } + + fprintf(output_, "%x %x %d %d\n", rva, length, line_num, source_id); + line.Release(); + } + return true; + } + +-bool PDBSourceLineWriter::PrintFunction(IDiaSymbol *function) { ++bool PDBSourceLineWriter::PrintFunction(IDiaSymbol *function, ++ IDiaSymbol *block) { + // The function format is: + // FUNC
+ DWORD rva; +- if (FAILED(function->get_relativeVirtualAddress(&rva))) { ++ if (FAILED(block->get_relativeVirtualAddress(&rva))) { + fprintf(stderr, "couldn't get rva\n"); + return false; + } + + ULONGLONG length; +- if (FAILED(function->get_length(&length))) { ++ if (FAILED(block->get_length(&length))) { + fprintf(stderr, "failed to get function length\n"); + return false; + } + + if (length == 0) { + // Silently ignore zero-length functions, which can infrequently pop up. + return true; + } +@@ -210,17 +213,26 @@ bool PDBSourceLineWriter::PrintSourceFil + return false; + } + + CComBSTR file_name; + if (FAILED(file->get_fileName(&file_name))) { + return false; + } + +- fwprintf(output_, L"FILE %d %s\n", file_id, file_name); ++ wstring file_name_string(file_name); ++ if (!FileIDIsCached(file_name_string)) { ++ // this is a new file name, cache it and output a FILE line. ++ CacheFileID(file_name_string, file_id); ++ fwprintf(output_, L"FILE %d %s\n", file_id, file_name); ++ } else { ++ // this file name has already been seen, just save this ++ // ID for later lookup. ++ StoreDuplicateFileID(file_name_string, file_id); ++ } + file.Release(); + } + compiland.Release(); + } + return true; + } + + bool PDBSourceLineWriter::PrintFunctions() { +@@ -250,27 +262,85 @@ bool PDBSourceLineWriter::PrintFunctions + return false; + } + + // For a given function, DIA seems to give either a symbol with + // SymTagFunction or SymTagPublicSymbol, but not both. This means + // that PDBSourceLineWriter will output either a FUNC or PUBLIC line, + // but not both. + if (tag == SymTagFunction) { +- if (!PrintFunction(symbol)) { ++ if (!PrintFunction(symbol, symbol)) { + return false; + } + } else if (tag == SymTagPublicSymbol) { + if (!PrintCodePublicSymbol(symbol)) { + return false; + } + } + symbol.Release(); + } while (SUCCEEDED(symbols->Next(1, &symbol, &count)) && count == 1); + ++ // When building with PGO, the compiler can split functions into ++ // "hot" and "cold" blocks, and move the "cold" blocks out to separate ++ // pages, so the function can be noncontiguous. To find these blocks, ++ // we have to iterate over all the compilands, and then find blocks ++ // that are children of them. We can then find the lexical parents ++ // of those blocks and print out an extra FUNC line for blocks ++ // that are not contained in their parent functions. ++ CComPtr global; ++ if (FAILED(session_->get_globalScope(&global))) { ++ fprintf(stderr, "get_globalScope failed\n"); ++ return false; ++ } ++ ++ CComPtr compilands; ++ if (FAILED(global->findChildren(SymTagCompiland, NULL, ++ nsNone, &compilands))) { ++ fprintf(stderr, "findChildren failed on the global\n"); ++ return false; ++ } ++ ++ CComPtr compiland; ++ while (SUCCEEDED(compilands->Next(1, &compiland, &count)) && count == 1) { ++ CComPtr blocks; ++ if (FAILED(compiland->findChildren(SymTagBlock, NULL, ++ nsNone, &blocks))) { ++ fprintf(stderr, "findChildren failed on a compiland\n"); ++ return false; ++ } ++ ++ CComPtr block; ++ while (SUCCEEDED(blocks->Next(1, &block, &count)) && count == 1) { ++ // find this block's lexical parent function ++ CComPtr parent; ++ DWORD tag; ++ if (SUCCEEDED(block->get_lexicalParent(&parent)) && ++ SUCCEEDED(parent->get_symTag(&tag)) && ++ tag == SymTagFunction) { ++ // now get the block's offset and the function's offset and size, ++ // and determine if the block is outside of the function ++ DWORD func_rva, block_rva; ++ ULONGLONG func_length; ++ if (SUCCEEDED(block->get_relativeVirtualAddress(&block_rva)) && ++ SUCCEEDED(parent->get_relativeVirtualAddress(&func_rva)) && ++ SUCCEEDED(parent->get_length(&func_length))) { ++ if (block_rva < func_rva || block_rva > (func_rva + func_length)) { ++ if (!PrintFunction(parent, block)) { ++ return false; ++ } ++ } ++ } ++ } ++ parent.Release(); ++ block.Release(); ++ } ++ blocks.Release(); ++ compiland.Release(); ++ } ++ + return true; + } + + bool PDBSourceLineWriter::PrintFrameData() { + // It would be nice if it were possible to output frame data alongside the + // associated function, as is done with line numbers, but the DIA API + // doesn't make it possible to get the frame data in that way. + +diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.h b/toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.h +--- a/toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.h ++++ b/toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.h +@@ -30,25 +30,27 @@ + // PDBSourceLineWriter uses a pdb file produced by Visual C++ to output + // a line/address map for use with BasicSourceLineResolver. + + #ifndef _PDB_SOURCE_LINE_WRITER_H__ + #define _PDB_SOURCE_LINE_WRITER_H__ + + #include + ++#include + #include + + struct IDiaEnumLineNumbers; + struct IDiaSession; + struct IDiaSymbol; + + namespace google_breakpad { + + using std::wstring; ++using stdext::hash_map; + + // A structure that carries information that identifies a pdb file. + struct PDBModuleInfo { + public: + // The basename of the pdb file from which information was loaded. + wstring debug_file; + + // The pdb's identifier. For recent pdb files, the identifier consists +@@ -106,18 +108,21 @@ class PDBSourceLineWriter { + bool UsesGUID(bool *uses_guid); + + private: + // Outputs the line/address pairs for each line in the enumerator. + // Returns true on success. + bool PrintLines(IDiaEnumLineNumbers *lines); + + // Outputs a function address and name, followed by its source line list. ++ // block can be the same object as function, or it can be a reference ++ // to a code block that is lexically part of this function, but ++ // resides at a separate address. + // Returns true on success. +- bool PrintFunction(IDiaSymbol *function); ++ bool PrintFunction(IDiaSymbol *function, IDiaSymbol *block); + + // Outputs all functions as described above. Returns true on success. + bool PrintFunctions(); + + // Outputs all of the source files in the session's pdb file. + // Returns true on success. + bool PrintSourceFiles(); + +@@ -129,16 +134,47 @@ class PDBSourceLineWriter { + // to a code address. Returns true on success. If symbol is does not + // correspond to code, returns true without outputting anything. + bool PrintCodePublicSymbol(IDiaSymbol *symbol); + + // Outputs a line identifying the PDB file that is being dumped, along with + // its uuid and age. + bool PrintPDBInfo(); + ++ // Returns true if this filename has already been seen, ++ // and an ID is stored for it, or false if it has not. ++ bool FileIDIsCached(const wstring &file) { ++ return unique_files_.find(file) != unique_files_.end(); ++ }; ++ ++ // Cache this filename and ID for later reuse. ++ void CacheFileID(const wstring &file, DWORD id) { ++ unique_files_[file] = id; ++ }; ++ ++ // Store this ID in the cache as a duplicate for this filename. ++ void StoreDuplicateFileID(const wstring &file, DWORD id) { ++ hash_map::iterator iter = unique_files_.find(file); ++ if (iter != unique_files_.end()) { ++ // map this id to the previously seen one ++ file_ids_[id] = iter->second; ++ } ++ }; ++ ++ // Given a file's unique ID, return the ID that should be used to ++ // reference it. There may be multiple files with identical filenames ++ // but different unique IDs. The cache attempts to coalesce these into ++ // one ID per unique filename. ++ DWORD GetRealFileID(DWORD id) { ++ hash_map::iterator iter = file_ids_.find(id); ++ if (iter == file_ids_.end()) ++ return id; ++ return iter->second; ++ }; ++ + // Returns the function name for a symbol. If possible, the name is + // undecorated. If the symbol's decorated form indicates the size of + // parameters on the stack, this information is returned in stack_param_size. + // Returns true on success. If the symbol doesn't encode parameter size + // information, stack_param_size is set to -1. + static bool GetSymbolFunctionName(IDiaSymbol *function, BSTR *name, + int *stack_param_size); + +@@ -148,16 +184,23 @@ class PDBSourceLineWriter { + static int GetFunctionStackParamSize(IDiaSymbol *function); + + // The session for the currently-open pdb file. + CComPtr session_; + + // The current output file for this WriteMap invocation. + FILE *output_; + ++ // There may be many duplicate filenames with different IDs. ++ // This maps from the DIA "unique ID" to a single ID per unique ++ // filename. ++ hash_map file_ids_; ++ // This maps unique filenames to file IDs. ++ hash_map unique_files_; ++ + // Disallow copy ctor and operator= + PDBSourceLineWriter(const PDBSourceLineWriter&); + void operator=(const PDBSourceLineWriter&); + }; + + } // namespace google_breakpad + + #endif // _PDB_SOURCE_LINE_WRITER_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_arm.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_arm.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_arm.h +@@ -0,0 +1,130 @@ ++/* Copyright (c) 2009, 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_format.h: A cross-platform reimplementation of minidump-related ++ * portions of DbgHelp.h from the Windows Platform SDK. ++ * ++ * (This is C99 source, please don't corrupt it with C++.) ++ * ++ * This file contains the necessary definitions to read minidump files ++ * produced on ARM. These files may be read on any platform provided ++ * that the alignments of these structures on the processing system are ++ * identical to the alignments of these structures on the producing system. ++ * For this reason, precise-sized types are used. The structures defined ++ * by this file have been laid out to minimize alignment problems by ++ * ensuring that all members are aligned on their natural boundaries. ++ * In some cases, tail-padding may be significant when different ABIs specify ++ * different tail-padding behaviors. To avoid problems when reading or ++ * writing affected structures, MD_*_SIZE macros are provided where needed, ++ * containing the useful size of the structures without padding. ++ * ++ * Structures that are defined by Microsoft to contain a zero-length array ++ * are instead defined here to contain an array with one element, as ++ * zero-length arrays are forbidden by standard C and C++. In these cases, ++ * *_minsize constants are provided to be used in place of sizeof. For a ++ * cleaner interface to these sizes when using C++, see minidump_size.h. ++ * ++ * These structures are also sufficient to populate minidump files. ++ * ++ * Because precise data type sizes are crucial for this implementation to ++ * function properly and portably, a set of primitive types with known sizes ++ * are used as the basis of each structure defined by this file. ++ * ++ * Author: Julian Seward ++ */ ++ ++/* ++ * ARM support ++ */ ++ ++#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM_H__ ++#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM_H__ ++ ++#define MD_FLOATINGSAVEAREA_ARM_FPR_COUNT 32 ++#define MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT 8 ++ ++/* ++ * Note that these structures *do not* map directly to the CONTEXT ++ * structure defined in WinNT.h in the Windows Mobile SDK. That structure ++ * does not accomodate VFPv3, and I'm unsure if it was ever used in the ++ * wild anyway, as Windows CE only seems to produce "cedumps" which ++ * are not exactly minidumps. ++ */ ++typedef struct { ++ u_int64_t fpscr; /* FPU status register */ ++ ++ /* 32 64-bit floating point registers, d0 .. d31. */ ++ u_int64_t regs[MD_FLOATINGSAVEAREA_ARM_FPR_COUNT]; ++ ++ /* Miscellaneous control words */ ++ u_int32_t extra[MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT]; ++} MDFloatingSaveAreaARM; ++ ++#define MD_CONTEXT_ARM_GPR_COUNT 16 ++ ++typedef struct { ++ /* The next field determines the layout of the structure, and which parts ++ * of it are populated ++ */ ++ u_int32_t context_flags; ++ ++ /* 16 32-bit integer registers, r0 .. r15 ++ * Note the following fixed uses: ++ * r13 is the stack pointer ++ * r14 is the link register ++ * r15 is the program counter ++ */ ++ u_int32_t iregs[MD_CONTEXT_ARM_GPR_COUNT]; ++ ++ /* CPSR (flags, basically): 32 bits: ++ bit 31 - N (negative) ++ bit 30 - Z (zero) ++ bit 29 - C (carry) ++ bit 28 - V (overflow) ++ bit 27 - Q (saturation flag, sticky) ++ All other fields -- ignore */ ++ u_int32_t cpsr; ++ ++ /* The next field is included with MD_CONTEXT_ARM_FLOATING_POINT */ ++ MDFloatingSaveAreaARM float_save; ++ ++} MDRawContextARM; ++ ++/* For (MDRawContextARM).context_flags. These values indicate the type of ++ * context stored in the structure. */ ++#define MD_CONTEXT_ARM_INTEGER (MD_CONTEXT_ARM | 0x00000002) ++#define MD_CONTEXT_ARM_FLOATING_POINT (MD_CONTEXT_ARM | 0x00000004) ++ ++#define MD_CONTEXT_ARM_FULL (MD_CONTEXT_ARM_INTEGER | \ ++ MD_CONTEXT_ARM_FLOATING_POINT) ++ ++#define MD_CONTEXT_ARM_ALL (MD_CONTEXT_ARM_INTEGER | \ ++ MD_CONTEXT_ARM_FLOATING_POINT) ++ ++#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM_H__ */ +diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_ppc.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_ppc.h +--- a/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_ppc.h ++++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_cpu_ppc.h +@@ -102,17 +102,21 @@ typedef struct { + } MDVectorSaveAreaPPC; /* ppc_vector_state */ + + + #define MD_CONTEXT_PPC_GPR_COUNT 32 + + /* Use the same 32-bit alignment when accessing this structure from 64-bit code + * as is used natively in 32-bit code. #pragma pack is a MSVC extension + * supported by gcc. */ ++#if defined(__SUNPRO_C) || defined(__SUNPRO_CC) ++#pragma pack(4) ++#else + #pragma pack(push, 4) ++#endif + + typedef struct { + /* context_flags is not present in ppc_thread_state, but it aids + * identification of MDRawContextPPC among other raw context types, + * and it guarantees alignment when we get to float_save. */ + u_int32_t context_flags; + + u_int32_t srr0; /* Machine status save/restore: stores pc +@@ -131,17 +135,21 @@ typedef struct { + + /* float_save and vector_save aren't present in ppc_thread_state, but + * are represented in separate structures that still define a thread's + * context. */ + MDFloatingSaveAreaPPC float_save; + MDVectorSaveAreaPPC vector_save; + } MDRawContextPPC; /* Based on ppc_thread_state */ + ++#if defined(__SUNPRO_C) || defined(__SUNPRO_CC) ++#pragma pack(0) ++#else + #pragma pack(pop) ++#endif + + /* For (MDRawContextPPC).context_flags. These values indicate the type of + * context stored in the structure. MD_CONTEXT_PPC is Breakpad-defined. Its + * value was chosen to avoid likely conflicts with MD_CONTEXT_* for other + * CPUs. */ + #define MD_CONTEXT_PPC 0x20000000 + #define MD_CONTEXT_PPC_BASE (MD_CONTEXT_PPC | 0x00000001) + #define MD_CONTEXT_PPC_FLOATING_POINT (MD_CONTEXT_PPC | 0x00000008) +diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_win32.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_win32.h +--- a/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_win32.h ++++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_exception_win32.h +@@ -89,14 +89,17 @@ typedef enum { + MD_EXCEPTION_CODE_WIN_INTEGER_DIVIDE_BY_ZERO = 0xc0000094, + /* EXCEPTION_INT_DIVIDE_BY_ZERO */ + MD_EXCEPTION_CODE_WIN_INTEGER_OVERFLOW = 0xc0000095, + /* EXCEPTION_INT_OVERFLOW */ + MD_EXCEPTION_CODE_WIN_PRIVILEGED_INSTRUCTION = 0xc0000096, + /* EXCEPTION_PRIV_INSTRUCTION */ + MD_EXCEPTION_CODE_WIN_STACK_OVERFLOW = 0xc00000fd, + /* EXCEPTION_STACK_OVERFLOW */ +- MD_EXCEPTION_CODE_WIN_POSSIBLE_DEADLOCK = 0xc0000194 ++ MD_EXCEPTION_CODE_WIN_POSSIBLE_DEADLOCK = 0xc0000194, + /* EXCEPTION_POSSIBLE_DEADLOCK */ ++ MD_EXCEPTION_CODE_WIN_UNHANDLED_CPP_EXCEPTION = 0xe06d7363 ++ /* Per http://support.microsoft.com/kb/185294, ++ generated by Visual C++ compiler */ + } MDExceptionCodeWin; + + + #endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_EXCEPTION_WIN32_H__ */ +diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_format.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_format.h +--- a/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_format.h ++++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/common/minidump_format.h +@@ -107,22 +107,22 @@ typedef struct { + + /* This is a base type for MDRawContextX86 and MDRawContextPPC. This + * structure should never be allocated directly. The actual structure type + * can be determined by examining the context_flags field. */ + typedef struct { + u_int32_t context_flags; + } MDRawContextBase; + ++#include "minidump_cpu_amd64.h" ++#include "minidump_cpu_arm.h" ++#include "minidump_cpu_ppc.h" ++#include "minidump_cpu_ppc64.h" + #include "minidump_cpu_sparc.h" + #include "minidump_cpu_x86.h" +-#include "minidump_cpu_ppc.h" +-#include "minidump_cpu_ppc64.h" +-#include "minidump_cpu_amd64.h" +- + + /* + * WinVer.h + */ + + + typedef struct { + u_int32_t signature; +diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/basic_source_line_resolver.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/basic_source_line_resolver.h +--- a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/basic_source_line_resolver.h ++++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/basic_source_line_resolver.h +@@ -28,79 +28,61 @@ + // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + // BasicSourceLineResolver implements SourceLineResolverInterface, using + // address map files produced by a compatible writer, e.g. PDBSourceLineWriter. + + #ifndef GOOGLE_BREAKPAD_PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_H__ + #define GOOGLE_BREAKPAD_PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_H__ + +-// TODO: Platforms that have no hash_map can use map, at the likely cost of +-// performance. +-#ifdef __SUNPRO_CC +-#define BSLR_NO_HASH_MAP +-#endif // __SUNPRO_CC +- +-#ifdef BSLR_NO_HASH_MAP + #include +-#else // BSLR_NO_HASH_MAP +-#include +-#endif // BSLR_NO_HASH_MAP + + #include "google_breakpad/processor/source_line_resolver_interface.h" + + namespace google_breakpad { + + using std::string; +-#ifdef BSLR_NO_HASH_MAP + using std::map; +-#else // BSLR_NO_HASH_MAP +-using __gnu_cxx::hash_map; +-#endif // BSLR_NO_HASH_MAP + + class BasicSourceLineResolver : public SourceLineResolverInterface { + public: + BasicSourceLineResolver(); + virtual ~BasicSourceLineResolver(); + + // SourceLineResolverInterface methods, see source_line_resolver_interface.h + // for more details. + + // Adds a module to this resolver, returning true on success. + // The given map_file is read into memory, and its symbols will be + // retained until the BasicSourceLineResolver is destroyed. + virtual bool LoadModule(const string &module_name, const string &map_file); + ++ // Exactly the same as above, except the given map_buffer is used ++ // for symbols. ++ virtual bool LoadModuleUsingMapBuffer(const string &module_name, ++ const string &map_buffer); ++ ++ + virtual bool HasModule(const string &module_name) const; + + virtual StackFrameInfo* FillSourceLineInfo(StackFrame *frame) const; + + private: + template class MemAddrMap; + struct Line; + struct Function; + struct PublicSymbol; + struct File; +-#ifdef BSLR_NO_HASH_MAP + struct CompareString { + bool operator()(const string &s1, const string &s2) const; + }; +-#else // BSLR_NO_HASH_MAP +- struct HashString { +- size_t operator()(const string &s) const; +- }; +-#endif // BSLR_NO_HASH_MAP + class Module; + + // All of the modules we've loaded +-#ifdef BSLR_NO_HASH_MAP + typedef map ModuleMap; +-#else // BSLR_NO_HASH_MAP +- typedef hash_map ModuleMap; +-#endif // BSLR_NO_HASH_MAP + ModuleMap *modules_; + + // Disallow unwanted copy ctor and assignment operator + BasicSourceLineResolver(const BasicSourceLineResolver&); + void operator=(const BasicSourceLineResolver&); + }; + + } // namespace google_breakpad +diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump.h +--- a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump.h ++++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump.h +@@ -76,16 +76,17 @@ + // + // Author: Mark Mentovai + + #ifndef GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_H__ + #define GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_H__ + + #include + ++#include + #include + #include + #include + + #include "google_breakpad/common/minidump_format.h" + #include "google_breakpad/processor/code_module.h" + #include "google_breakpad/processor/code_modules.h" + #include "google_breakpad/processor/memory_region.h" +@@ -173,20 +174,21 @@ class MinidumpContext : public MinidumpS + // identifying the CPU type that the context was collected from. The + // returned value will identify the CPU only, and will have any other + // MD_CONTEXT_* bits masked out. Returns 0 on failure. + u_int32_t GetContextCPU() const; + + // Returns raw CPU-specific context data for the named CPU type. If the + // context data does not match the CPU type or does not exist, returns + // NULL. ++ const MDRawContextAMD64* GetContextAMD64() const; ++ const MDRawContextARM* GetContextARM() const; ++ const MDRawContextPPC* GetContextPPC() const; ++ const MDRawContextSPARC* GetContextSPARC() const; + const MDRawContextX86* GetContextX86() const; +- const MDRawContextPPC* GetContextPPC() const; +- const MDRawContextAMD64* GetContextAMD64() const; +- const MDRawContextSPARC* GetContextSPARC() const; + + // Print a human-readable representation of the object to stdout. + void Print(); + + private: + friend class MinidumpThread; + friend class MinidumpException; + +@@ -210,17 +212,18 @@ class MinidumpContext : public MinidumpS + // The CPU-specific context structure. + union { + MDRawContextBase* base; + MDRawContextX86* x86; + MDRawContextPPC* ppc; + MDRawContextAMD64* amd64; + // on Solaris SPARC, sparc is defined as a numeric constant, + // so variables can NOT be named as sparc +- MDRawContextSPARC* ctx_sparc; ++ MDRawContextSPARC* ctx_sparc; ++ MDRawContextARM* arm; + } context_; + }; + + + // MinidumpMemoryRegion does not wrap any MDRaw structure, and only contains + // a reference to an MDMemoryDescriptor. This object is intended to wrap + // portions of a minidump file that contain memory dumps. In normal + // minidumps, each MinidumpThread owns a MinidumpMemoryRegion corresponding +@@ -331,17 +334,19 @@ class MinidumpThreadList : public Minidu + public: + virtual ~MinidumpThreadList(); + + static void set_max_threads(u_int32_t max_threads) { + max_threads_ = max_threads; + } + static u_int32_t max_threads() { return max_threads_; } + +- unsigned int thread_count() const { return valid_ ? thread_count_ : 0; } ++ unsigned int thread_count() const { ++ return valid_ ? thread_count_ : 0; ++ } + + // Sequential access to threads. + MinidumpThread* GetThreadAtIndex(unsigned int index) const; + + // Random access to threads. + MinidumpThread* GetThreadByID(u_int32_t thread_id); + + // Print a human-readable representation of the object to stdout. +@@ -632,16 +637,56 @@ class MinidumpException : public Minidum + explicit MinidumpException(Minidump* minidump); + + bool Read(u_int32_t expected_size); + + MDRawExceptionStream exception_; + MinidumpContext* context_; + }; + ++// MinidumpAssertion wraps MDRawAssertionInfo, which contains information ++// about an assertion that caused the minidump to be generated. ++class MinidumpAssertion : public MinidumpStream { ++ public: ++ virtual ~MinidumpAssertion(); ++ ++ const MDRawAssertionInfo* assertion() const { ++ return valid_ ? &assertion_ : NULL; ++ } ++ ++ string expression() const { ++ return valid_ ? expression_ : ""; ++ } ++ ++ string function() const { ++ return valid_ ? function_ : ""; ++ } ++ ++ string file() const { ++ return valid_ ? file_ : ""; ++ } ++ ++ // Print a human-readable representation of the object to stdout. ++ void Print(); ++ ++ private: ++ friend class Minidump; ++ ++ static const u_int32_t kStreamType = MD_ASSERTION_INFO_STREAM; ++ ++ explicit MinidumpAssertion(Minidump* minidump); ++ ++ bool Read(u_int32_t expected_size); ++ ++ MDRawAssertionInfo assertion_; ++ string expression_; ++ string function_; ++ string file_; ++}; ++ + + // MinidumpSystemInfo wraps MDRawSystemInfo and provides information about + // the system on which the minidump was generated. See also MinidumpMiscInfo. + class MinidumpSystemInfo : public MinidumpStream { + public: + virtual ~MinidumpSystemInfo(); + + const MDRawSystemInfo* system_info() const { +@@ -749,45 +794,54 @@ class MinidumpBreakpadInfo : public Mini + + + // Minidump is the user's interface to a minidump file. It wraps MDRawHeader + // and provides access to the minidump's top-level stream directory. + class Minidump { + public: + // path is the pathname of a file containing the minidump. + explicit Minidump(const string& path); ++ // input is an istream wrapping minidump data. Minidump holds a ++ // weak pointer to input, and the caller must ensure that the stream ++ // is valid as long as the Minidump object is. ++ explicit Minidump(std::istream& input); + +- ~Minidump(); ++ virtual ~Minidump(); + ++ // path may be empty if the minidump was not opened from a file ++ virtual string path() const { ++ return path_; ++ } + static void set_max_streams(u_int32_t max_streams) { + max_streams_ = max_streams; + } + static u_int32_t max_streams() { return max_streams_; } + + static void set_max_string_length(u_int32_t max_string_length) { + max_string_length_ = max_string_length; + } + static u_int32_t max_string_length() { return max_string_length_; } + +- const MDRawHeader* header() const { return valid_ ? &header_ : NULL; } ++ virtual const MDRawHeader* header() const { return valid_ ? &header_ : NULL; } + + // Reads the minidump file's header and top-level stream directory. + // The minidump is expected to be positioned at the beginning of the + // header. Read() sets up the stream list and map, and validates the + // Minidump object. +- bool Read(); ++ virtual bool Read(); + + // The next set of methods are stubs that call GetStream. They exist to + // force code generation of the templatized API within the module, and + // to avoid exposing an ugly API (GetStream needs to accept a garbage + // parameter). +- MinidumpThreadList* GetThreadList(); ++ virtual MinidumpThreadList* GetThreadList(); + MinidumpModuleList* GetModuleList(); + MinidumpMemoryList* GetMemoryList(); + MinidumpException* GetException(); ++ MinidumpAssertion* GetAssertion(); + MinidumpSystemInfo* GetSystemInfo(); + MinidumpMiscInfo* GetMiscInfo(); + MinidumpBreakpadInfo* GetBreakpadInfo(); + + // The next set of methods are provided for users who wish to access + // data in minidump files directly, while leveraging the rest of + // this class and related classes to handle the basic minidump + // structure and known stream types. +@@ -803,17 +857,17 @@ class Minidump { + // the storage area pointed to by bytes. bytes must be of sufficient + // size. After the read, the file position is advanced by count. + bool ReadBytes(void* bytes, size_t count); + + // Sets the position of the minidump file to offset. + bool SeekSet(off_t offset); + + // Returns the current position of the minidump file. +- off_t Tell() { return valid_ ? lseek(fd_, 0, SEEK_CUR) : (off_t)-1; } ++ off_t Tell(); + + // The next 2 methods are medium-level I/O routines. + + // ReadString returns a string which is owned by the caller! offset + // specifies the offset that a length-encoded string is stored at in the + // minidump file. + string* ReadString(off_t offset); + +@@ -874,21 +928,22 @@ class Minidump { + + // The list of streams. + MinidumpDirectoryEntries* directory_; + + // Access to streams using the stream type as the key. + MinidumpStreamMap* stream_map_; + + // The pathname of the minidump file to process, set in the constructor. ++ // This may be empty if the minidump was opened directly from a stream. + const string path_; + +- // The file descriptor for all file I/O. Used by ReadBytes and SeekSet. +- // Set based on the |path_| member by Open, which is called by Read. +- int fd_; ++ // The stream for all file I/O. Used by ReadBytes and SeekSet. ++ // Set based on the path in Open, or directly in the constructor. ++ std::istream* stream_; + + // swap_ is true if the minidump file should be byte-swapped. If the + // minidump was produced by a CPU that is other-endian than the CPU + // processing the minidump, this will be true. If the two CPUs are + // same-endian, this will be false. + bool swap_; + + // Validity of the Minidump structure, false immediately after +diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump_processor.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump_processor.h +--- a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump_processor.h ++++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump_processor.h +@@ -25,48 +25,90 @@ + // 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 GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_PROCESSOR_H__ + #define GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_PROCESSOR_H__ + ++#include + #include + #include "google_breakpad/common/breakpad_types.h" + + namespace google_breakpad { + + using std::string; + + class Minidump; + class ProcessState; + class SourceLineResolverInterface; + class SymbolSupplier; + class SystemInfo; ++// Return type for Process() ++enum ProcessResult { ++ PROCESS_OK, // The minidump was ++ // processed ++ // successfully. ++ ++ PROCESS_ERROR_MINIDUMP_NOT_FOUND, // The minidump file ++ // was not found. ++ ++ PROCESS_ERROR_NO_MINIDUMP_HEADER, // The minidump file ++ // had no header ++ ++ PROCESS_ERROR_NO_THREAD_LIST, // The minidump file ++ // had no thread list. ++ ++ PROCESS_ERROR_GETTING_THREAD, // There was an error ++ // getting one ++ // thread's data from ++ // the minidump. ++ ++ PROCESS_ERROR_GETTING_THREAD_ID, // There was an error ++ // getting a thread id ++ // from the thread's ++ // data. ++ ++ PROCESS_ERROR_DUPLICATE_REQUESTING_THREADS, // There was more than ++ // one requesting ++ // thread. ++ ++ PROCESS_ERROR_NO_MEMORY_FOR_THREAD, // A thread had no ++ // memory region. ++ ++ PROCESS_ERROR_NO_STACKWALKER_FOR_THREAD, // We couldn't ++ // determine the ++ // StackWalker to walk ++ // the minidump's ++ // threads. ++ ++ PROCESS_SYMBOL_SUPPLIER_INTERRUPTED // The minidump ++ // processing was ++ // interrupted by the ++ // SymbolSupplier(not ++ // fatal) ++}; + + class MinidumpProcessor { + public: +- // Return type for Process() +- enum ProcessResult { +- PROCESS_OK, // the minidump was processed successfully +- PROCESS_ERROR, // there was an error processing the minidump +- PROCESS_INTERRUPTED // processing was interrupted by the SymbolSupplier +- }; +- + // Initializes this MinidumpProcessor. supplier should be an + // implementation of the SymbolSupplier abstract base class. + MinidumpProcessor(SymbolSupplier *supplier, + SourceLineResolverInterface *resolver); + ~MinidumpProcessor(); + + // Processes the minidump file and fills process_state with the result. + ProcessResult Process(const string &minidump_file, + ProcessState *process_state); + ++ // Processes the minidump structure and fills process_state with the ++ // result. ++ ProcessResult Process(Minidump *minidump, ++ ProcessState *process_state); + // Populates the cpu_* fields of the |info| parameter with textual + // representations of the CPU type that the minidump in |dump| was + // produced on. Returns false if this information is not available in + // the minidump. + static bool GetCPUInfo(Minidump *dump, SystemInfo *info); + + // Populates the os_* fields of the |info| parameter with textual + // representations of the operating system that the minidump in |dump| +@@ -79,16 +121,36 @@ class MinidumpProcessor { + // an empty string if this information cannot be determined. If address + // is non-NULL, it will be set to contain the address that caused the + // exception, if this information is available. This will be a code + // address when the crash was caused by problems such as illegal + // instructions or divisions by zero, or a data address when the crash + // was caused by a memory access violation. + static string GetCrashReason(Minidump *dump, u_int64_t *address); + ++ // This function returns true if the passed-in error code is ++ // something unrecoverable(i.e. retry should not happen). For ++ // instance, if the minidump is corrupt, then it makes no sense to ++ // retry as we won't be able to glean additional information. ++ // However, as an example of the other case, the symbol supplier can ++ // return an error code indicating it was 'interrupted', which can ++ // happen of the symbols are fetched from a remote store, and a ++ // retry might be successful later on. ++ // You should not call this method with PROCESS_OK! Test for ++ // that separately before calling this. ++ static bool IsErrorUnrecoverable(ProcessResult p) { ++ assert(p != PROCESS_OK); ++ return (p != PROCESS_SYMBOL_SUPPLIER_INTERRUPTED); ++ } ++ ++ // Returns a textual representation of an assertion included ++ // in the minidump. Returns an empty string if this information ++ // does not exist or cannot be determined. ++ static string GetAssertion(Minidump *dump); ++ + private: + SymbolSupplier *supplier_; + SourceLineResolverInterface *resolver_; + }; + + } // namespace google_breakpad + + #endif // GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_PROCESSOR_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/process_state.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/process_state.h +--- a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/process_state.h ++++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/process_state.h +@@ -31,18 +31,19 @@ + // + // Author: Mark Mentovai + + #ifndef GOOGLE_BREAKPAD_PROCESSOR_PROCESS_STATE_H__ + #define GOOGLE_BREAKPAD_PROCESSOR_PROCESS_STATE_H__ + + #include + #include ++#include "google_breakpad/common/breakpad_types.h" + #include "google_breakpad/processor/system_info.h" +-#include "google_breakpad/common/breakpad_types.h" ++#include "google_breakpad/processor/minidump.h" + + namespace google_breakpad { + + using std::string; + using std::vector; + + class CallStack; + class CodeModules; +@@ -55,18 +56,22 @@ class ProcessState { + // Resets the ProcessState to its default values + void Clear(); + + // Accessors. See the data declarations below. + u_int32_t time_date_stamp() const { return time_date_stamp_; } + bool crashed() const { return crashed_; } + string crash_reason() const { return crash_reason_; } + u_int64_t crash_address() const { return crash_address_; } ++ string assertion() const { return assertion_; } + int requesting_thread() const { return requesting_thread_; } + const vector* threads() const { return &threads_; } ++ const vector* thread_memory_regions() const { ++ return &thread_memory_regions_; ++ } + const SystemInfo* system_info() const { return &system_info_; } + const CodeModules* modules() const { return modules_; } + + private: + // MinidumpProcessor is responsible for building ProcessState objects. + friend class MinidumpProcessor; + + // The time-date stamp of the minidump (time_t format) +@@ -83,29 +88,35 @@ class ProcessState { + string crash_reason_; + + // If the process crashed, and if crash_reason implicates memory, + // the memory address that caused the crash. For data access errors, + // this will be the data address that caused the fault. For code errors, + // this will be the address of the instruction that caused the fault. + u_int64_t crash_address_; + ++ // If there was an assertion that was hit, a textual representation ++ // of that assertion, possibly including the file and line at which ++ // it occurred. ++ string assertion_; ++ + // The index of the thread that requested a dump be written in the + // threads vector. If a dump was produced as a result of a crash, this + // will point to the thread that crashed. If the dump was produced as + // by user code without crashing, and the dump contains extended Breakpad + // information, this will point to the thread that requested the dump. + // If the dump was not produced as a result of an exception and no + // extended Breakpad information is present, this field will be set to -1, + // indicating that the dump thread is not available. + int requesting_thread_; + + // Stacks for each thread (except possibly the exception handler + // thread) at the time of the crash. + vector threads_; ++ vector thread_memory_regions_; + + // OS and CPU information. + SystemInfo system_info_; + + // The modules that were loaded into the process represented by the + // ProcessState. + const CodeModules *modules_; + }; +diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/source_line_resolver_interface.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/source_line_resolver_interface.h +--- a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/source_line_resolver_interface.h ++++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/source_line_resolver_interface.h +@@ -51,16 +51,19 @@ class SourceLineResolverInterface { + // Adds a module to this resolver, returning true on success. + // + // module_name may be an arbitrary string. Typically, it will be the + // filename of the module, optionally with version identifiers. + // + // map_file should contain line/address mappings for this module. + virtual bool LoadModule(const string &module_name, + const string &map_file) = 0; ++ // Same as above, but takes the contents of a pre-read map buffer ++ virtual bool LoadModuleUsingMapBuffer(const string &module_name, ++ const string &map_buffer) = 0; + + // Returns true if a module with the given name has been loaded. + virtual bool HasModule(const string &module_name) const = 0; + + // Fills in the function_base, function_name, source_file_name, + // and source_line fields of the StackFrame. The instruction and + // module_name fields must already be filled in. Additional debugging + // information, if available, is returned. If the information is not +diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stack_frame_cpu.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stack_frame_cpu.h +--- a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stack_frame_cpu.h ++++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stack_frame_cpu.h +@@ -53,28 +53,48 @@ struct StackFrameX86 : public StackFrame + CONTEXT_VALID_ESP = 1 << 1, + CONTEXT_VALID_EBP = 1 << 2, + CONTEXT_VALID_EBX = 1 << 3, + CONTEXT_VALID_ESI = 1 << 4, + CONTEXT_VALID_EDI = 1 << 5, + CONTEXT_VALID_ALL = -1 + }; + +- StackFrameX86() : context(), context_validity(CONTEXT_VALID_NONE) {} ++ // Indicates how well we trust the instruction pointer we derived ++ // during stack walking. Since the stack walker can resort to ++ // stack scanning, we can wind up with dubious frames. ++ // In rough order of "trust metric". ++ enum FrameTrust { ++ FRAME_TRUST_NONE, // Unknown ++ FRAME_TRUST_SCAN, // Scanned the stack, found this ++ FRAME_TRUST_CFI_SCAN, // Scanned the stack using call frame info, found this ++ FRAME_TRUST_FP, // Derived from frame pointer ++ FRAME_TRUST_CFI, // Derived from call frame info ++ FRAME_TRUST_CONTEXT // Given as instruction pointer in a context ++ }; ++ ++ StackFrameX86() ++ : context(), ++ context_validity(CONTEXT_VALID_NONE), ++ trust(FRAME_TRUST_NONE) {} + + // Register state. This is only fully valid for the topmost frame in a + // stack. In other frames, the values of nonvolatile registers may be + // present, given sufficient debugging information. Refer to + // context_validity. + MDRawContextX86 context; + + // context_validity is actually ContextValidity, but int is used because + // the OR operator doesn't work well with enumerated types. This indicates + // which fields in context are valid. + int context_validity; ++ ++ // Amount of trust the stack walker has in the instruction pointer ++ // of this frame. ++ FrameTrust trust; + }; + + struct StackFramePPC : public StackFrame { + // ContextValidity should eventually contain entries for the validity of + // other nonvolatile (callee-save) registers as in + // StackFrameX86::ContextValidity, but the ppc stackwalker doesn't currently + // locate registers other than the ones listed here. + enum ContextValidity { +@@ -143,11 +163,38 @@ struct StackFrameSPARC : public StackFra + MDRawContextSPARC context; + + // context_validity is actually ContextValidity, but int is used because + // the OR operator doesn't work well with enumerated types. This indicates + // which fields in context are valid. + int context_validity; + }; + ++struct StackFrameARM : public StackFrame { ++ // ContextValidity should eventually contain entries for the validity of ++ // other nonvolatile (callee-save) registers as in ++ // StackFrameX86::ContextValidity. I suspect this list is sufficient ++ // for arm stackwalking. ++ enum ContextValidity { ++ CONTEXT_VALID_NONE = 0, ++ CONTEXT_VALID_R13 = 1 << 0, ++ CONTEXT_VALID_R14 = 1 << 1, ++ CONTEXT_VALID_R15 = 1 << 2, ++ CONTEXT_VALID_ALL = -1 ++ }; ++ ++ StackFrameARM() : context(), context_validity(CONTEXT_VALID_NONE) {} ++ ++ // Register state. This is only fully valid for the topmost frame in a ++ // stack. In other frames, the values of nonvolatile registers may be ++ // present, given sufficient debugging information. Refer to ++ // context_validity. ++ MDRawContextARM context; ++ ++ // context_validity is actually ContextValidity, but int is used because ++ // the OR operator doesn't work well with enumerated types. This indicates ++ // which fields in context are valid. ++ int context_validity; ++}; ++ + } // namespace google_breakpad + + #endif // GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_CPU_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stackwalker.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stackwalker.h +--- a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stackwalker.h ++++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/stackwalker.h +@@ -37,16 +37,17 @@ + // + // Author: Mark Mentovai + + + #ifndef GOOGLE_BREAKPAD_PROCESSOR_STACKWALKER_H__ + #define GOOGLE_BREAKPAD_PROCESSOR_STACKWALKER_H__ + + #include ++#include "google_breakpad/common/breakpad_types.h" + + namespace google_breakpad { + + class CallStack; + class CodeModules; + template class linked_ptr; + class MemoryRegion; + class MinidumpContext; +@@ -90,16 +91,26 @@ class Stackwalker { + // (see source_line_resolver_interface.h and basic_source_line_resolver.h). + // If resolver is NULL, source line info will not be resolved. + Stackwalker(const SystemInfo *system_info, + MemoryRegion *memory, + const CodeModules *modules, + SymbolSupplier *supplier, + SourceLineResolverInterface *resolver); + ++ // This can be used to filter out potential return addresses when ++ // the stack walker resorts to stack scanning. ++ // Returns true if any of: ++ // * This address is within a loaded module, but we don't have symbols ++ // for that module. ++ // * This address is within a loaded module for which we have symbols, ++ // and falls inside a function in that module. ++ // Returns false otherwise. ++ bool InstructionAddressSeemsValid(u_int64_t address); ++ + // Information about the system that produced the minidump. Subclasses + // and the SymbolSupplier may find this information useful. + const SystemInfo *system_info_; + + // The stack memory to walk. Subclasses will require this region to + // get information from the stack. + MemoryRegion *memory_; + +diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/symbol_supplier.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/symbol_supplier.h +--- a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/symbol_supplier.h ++++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/symbol_supplier.h +@@ -54,19 +54,29 @@ class SymbolSupplier { + // stops processing the minidump immediately + INTERRUPT + }; + + virtual ~SymbolSupplier() {} + + // Retrieves the symbol file for the given CodeModule, placing the + // path in symbol_file if successful. system_info contains strings +- // identifying the operating system and CPU; SymbolSupplier may use to help +- // locate the symbol file. system_info may be NULL or its fields may be +- // empty if these values are unknown. ++ // identifying the operating system and CPU; SymbolSupplier may use ++ // to help locate the symbol file. system_info may be NULL or its ++ // fields may be empty if these values are unknown. symbol_file ++ // must be a pointer to a valid string + virtual SymbolResult GetSymbolFile(const CodeModule *module, + const SystemInfo *system_info, + string *symbol_file) = 0; ++ // Same as above, except also places symbol data into symbol_data. ++ // If symbol_data is NULL, the data is not returned. ++ // TODO(nealsid) Once we have symbol data caching behavior implemented ++ // investigate making all symbol suppliers implement all methods, ++ // and make this pure virtual ++ virtual SymbolResult GetSymbolFile(const CodeModule *module, ++ const SystemInfo *system_info, ++ string *symbol_file, ++ string *symbol_data) = 0; + }; + + } // namespace google_breakpad + + #endif // GOOGLE_BREAKPAD_PROCESSOR_SYMBOL_SUPPLIER_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver.cc b/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver.cc +--- a/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver.cc ++++ b/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver.cc +@@ -24,16 +24,19 @@ + // 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 + #include ++#include ++#include ++#include + + #include + #include + #include + + #include "processor/address_map-inl.h" + #include "processor/contained_range_map-inl.h" + #include "processor/range_map-inl.h" +@@ -43,19 +46,16 @@ + #include "google_breakpad/processor/stack_frame.h" + #include "processor/linked_ptr.h" + #include "processor/scoped_ptr.h" + #include "processor/stack_frame_info.h" + + using std::map; + using std::vector; + using std::make_pair; +-#ifndef BSLR_NO_HASH_MAP +-using __gnu_cxx::hash; +-#endif // BSLR_NO_HASH_MAP + + namespace google_breakpad { + + struct BasicSourceLineResolver::Line { + Line(MemAddr addr, MemAddr code_size, int file_id, int source_line) + : address(addr) + , size(code_size) + , source_file_id(file_id) +@@ -101,33 +101,33 @@ struct BasicSourceLineResolver::PublicSy + // stack, if known. + int parameter_size; + }; + + class BasicSourceLineResolver::Module { + public: + Module(const string &name) : name_(name) { } + +- // Loads the given map file, returning true on success. ++ // Loads the given map file, returning true on success. Reads the ++ // map file into memory and calls LoadMapFromBuffer + bool LoadMap(const string &map_file); + ++ // Loads a map from the given buffer, returning true on success ++ bool LoadMapFromBuffer(const string &map_buffer); ++ + // Looks up the given relative address, and fills the StackFrame struct + // with the result. Additional debugging information, if available, is + // returned. If no additional information is available, returns NULL. + // A NULL return value is not an error. The caller takes ownership of + // any returned StackFrameInfo object. + StackFrameInfo* LookupAddress(StackFrame *frame) const; + + private: + friend class BasicSourceLineResolver; +-#ifdef BSLR_NO_HASH_MAP + typedef map FileMap; +-#else // BSLR_NO_HASH_MAP +- typedef hash_map FileMap; +-#endif // BSLR_NO_HASH_MAP + + // The types for stack_info_. This is equivalent to MS DIA's + // StackFrameTypeEnum. Each identifies a different type of frame + // information, although all are represented in the symbol file in the + // same format. These are used as indices to the stack_info_ array. + enum StackInfoTypes { + STACK_INFO_FPO = 0, + STACK_INFO_TRAP, // not used here +@@ -206,16 +206,37 @@ bool BasicSourceLineResolver::LoadModule + delete module; + return false; + } + + modules_->insert(make_pair(module_name, module)); + return true; + } + ++bool BasicSourceLineResolver::LoadModuleUsingMapBuffer( ++ const string &module_name, ++ const string &map_buffer) { ++ // Make sure we don't already have a module with the given name. ++ if (modules_->find(module_name) != modules_->end()) { ++ BPLOG(INFO) << "Symbols for module " << module_name << " already loaded"; ++ return false; ++ } ++ ++ BPLOG(INFO) << "Loading symbols for module " << module_name << " from buffer"; ++ ++ Module *module = new Module(module_name); ++ if (!module->LoadMapFromBuffer(map_buffer)) { ++ delete module; ++ return false; ++ } ++ ++ modules_->insert(make_pair(module_name, module)); ++ return true; ++} ++ + bool BasicSourceLineResolver::HasModule(const string &module_name) const { + return modules_->find(module_name) != modules_->end(); + } + + StackFrameInfo* BasicSourceLineResolver::FillSourceLineInfo( + StackFrame *frame) const { + if (frame->module) { + ModuleMap::const_iterator it = modules_->find(frame->module->code_file()); +@@ -233,96 +254,170 @@ class AutoFileCloser { + if (file_) + fclose(file_); + } + + private: + FILE *file_; + }; + +-bool BasicSourceLineResolver::Module::LoadMap(const string &map_file) { +- FILE *f = fopen(map_file.c_str(), "r"); +- if (!f) { +- string error_string; +- int error_code = ErrnoString(&error_string); +- BPLOG(ERROR) << "Could not open " << map_file << +- ", error " << error_code << ": " << error_string; ++bool BasicSourceLineResolver::Module::LoadMapFromBuffer( ++ const string &map_buffer) { ++ linked_ptr cur_func; ++ int line_number = 0; ++ const char *map_buffer_c_str = map_buffer.c_str(); ++ char *save_ptr; ++ ++ // set up our input buffer as a c-style string so we ++ // can we use strtok() ++ // have to copy because modifying the result of string::c_str is not ++ // permitted ++ size_t map_buffer_length = strlen(map_buffer_c_str); ++ ++ // If the length is 0, we can still pretend we have a symbol file. This is ++ // for scenarios that want to test symbol lookup, but don't necessarily care if ++ // certain modules do not have any information, like system libraries. ++ if (map_buffer_length == 0) { ++ return true; ++ } ++ ++ scoped_array map_buffer_chars(new char[map_buffer_length]); ++ if (map_buffer_chars == NULL) { ++ BPLOG(ERROR) << "Memory allocation of " << map_buffer_length << ++ " bytes failed"; + return false; + } + +- AutoFileCloser closer(f); ++ strncpy(map_buffer_chars.get(), map_buffer_c_str, map_buffer_length); + +- // TODO(mmentovai): this might not be large enough to handle really long +- // lines, which might be present for FUNC lines of highly-templatized +- // code. +- char buffer[8192]; +- linked_ptr cur_func; ++ if (map_buffer_chars[map_buffer_length - 1] == '\n') { ++ map_buffer_chars[map_buffer_length - 1] = '\0'; ++ } ++ char *buffer; ++ buffer = strtok_r(map_buffer_chars.get(), "\r\n", &save_ptr); + +- int line_number = 0; +- while (fgets(buffer, sizeof(buffer), f)) { ++ while (buffer != NULL) { + ++line_number; ++ + if (strncmp(buffer, "FILE ", 5) == 0) { + if (!ParseFile(buffer)) { +- BPLOG(ERROR) << "ParseFile failed at " << +- map_file << ":" << line_number; ++ BPLOG(ERROR) << "ParseFile on buffer failed at " << ++ ":" << line_number; + return false; + } + } else if (strncmp(buffer, "STACK ", 6) == 0) { + if (!ParseStackInfo(buffer)) { + BPLOG(ERROR) << "ParseStackInfo failed at " << +- map_file << ":" << line_number; ++ ":" << line_number; + return false; + } + } else if (strncmp(buffer, "FUNC ", 5) == 0) { + cur_func.reset(ParseFunction(buffer)); + if (!cur_func.get()) { + BPLOG(ERROR) << "ParseFunction failed at " << +- map_file << ":" << line_number; ++ ":" << line_number; + return false; + } + // StoreRange will fail if the function has an invalid address or size. + // We'll silently ignore this, the function and any corresponding lines + // will be destroyed when cur_func is released. + functions_.StoreRange(cur_func->address, cur_func->size, cur_func); + } else if (strncmp(buffer, "PUBLIC ", 7) == 0) { + // Clear cur_func: public symbols don't contain line number information. + cur_func.reset(); + + if (!ParsePublicSymbol(buffer)) { + BPLOG(ERROR) << "ParsePublicSymbol failed at " << +- map_file << ":" << line_number; ++ ":" << line_number; + return false; + } + } else if (strncmp(buffer, "MODULE ", 7) == 0) { + // Ignore these. They're not of any use to BasicSourceLineResolver, + // which is fed modules by a SymbolSupplier. These lines are present to + // aid other tools in properly placing symbol files so that they can + // be accessed by a SymbolSupplier. + // + // MODULE + } else { + if (!cur_func.get()) { + BPLOG(ERROR) << "Found source line data without a function at " << +- map_file << ":" << line_number; ++ ":" << line_number; + return false; + } + Line *line = ParseLine(buffer); + if (!line) { +- BPLOG(ERROR) << "ParseLine failed at " << +- map_file << ":" << line_number; ++ BPLOG(ERROR) << "ParseLine failed at " << line_number << " for " << ++ buffer; + return false; + } + cur_func->lines.StoreRange(line->address, line->size, + linked_ptr(line)); + } ++ ++ buffer = strtok_r(NULL, "\r\n", &save_ptr); + } + + return true; + } + ++bool BasicSourceLineResolver::Module::LoadMap(const string &map_file) { ++ struct stat buf; ++ int error_code = stat(map_file.c_str(), &buf); ++ if (error_code == -1) { ++ string error_string; ++ int error_code = ErrnoString(&error_string); ++ BPLOG(ERROR) << "Could not open " << map_file << ++ ", error " << error_code << ": " << error_string; ++ return false; ++ } ++ ++ off_t file_size = buf.st_size; ++ ++ // Allocate memory for file contents, plus a null terminator ++ // since we'll use strtok() on the contents. ++ char *file_buffer = new char[sizeof(char)*file_size + 1]; ++ ++ if (file_buffer == NULL) { ++ BPLOG(ERROR) << "Could not allocate memory for " << map_file; ++ return false; ++ } ++ ++ BPLOG(ERROR) << "Opening " << map_file; ++ ++ FILE *f = fopen(map_file.c_str(), "rt"); ++ if (!f) { ++ string error_string; ++ int error_code = ErrnoString(&error_string); ++ BPLOG(ERROR) << "Could not open " << map_file << ++ ", error " << error_code << ": " << error_string; ++ delete [] file_buffer; ++ return false; ++ } ++ ++ AutoFileCloser closer(f); ++ ++ int items_read = 0; ++ ++ items_read = fread(file_buffer, 1, file_size, f); ++ ++ if (items_read != file_size) { ++ string error_string; ++ int error_code = ErrnoString(&error_string); ++ BPLOG(ERROR) << "Could not slurp " << map_file << ++ ", error " << error_code << ": " << error_string; ++ delete [] file_buffer; ++ return false; ++ } ++ file_buffer[file_size] = '\0'; ++ string map_buffer(file_buffer); ++ delete [] file_buffer; ++ ++ return LoadMapFromBuffer(map_buffer); ++} ++ + StackFrameInfo* BasicSourceLineResolver::Module::LookupAddress( + StackFrame *frame) const { + MemAddr address = frame->instruction - frame->module->base_address(); + + linked_ptr retrieved_info; + // Check for debugging info first, before any possible early returns. + // + // We only know about STACK_INFO_FRAME_DATA and STACK_INFO_FPO. Prefer +@@ -595,20 +690,14 @@ bool BasicSourceLineResolver::Module::Pa + max_stack_size, + allocates_base_pointer, + program_string)); + stack_info_[type].StoreRange(rva, code_size, stack_frame_info); + + return true; + } + +-#ifdef BSLR_NO_HASH_MAP + bool BasicSourceLineResolver::CompareString::operator()( + const string &s1, const string &s2) const { + return strcmp(s1.c_str(), s2.c_str()) < 0; + } +-#else // BSLR_NO_HASH_MAP +-size_t BasicSourceLineResolver::HashString::operator()(const string &s) const { +- return hash()(s.c_str()); +-} +-#endif // BSLR_NO_HASH_MAP + + } // namespace google_breakpad +diff --git a/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver_unittest.cc +--- a/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver_unittest.cc ++++ b/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver_unittest.cc +@@ -168,30 +168,34 @@ static bool RunTests() { + ASSERT_EQ(frame.module->code_file(), "module2"); + ASSERT_EQ(frame.source_file_name, "file2_2.cc"); + ASSERT_EQ(frame.source_line, 21); + ASSERT_EQ(frame.source_line_base, 0x2180); + ASSERT_TRUE(frame_info.get()); + ASSERT_EQ(frame_info->prolog_size, 1); + + frame.instruction = 0x216f; +- resolver.FillSourceLineInfo(&frame); ++ StackFrameInfo *s; ++ s = resolver.FillSourceLineInfo(&frame); + ASSERT_EQ(frame.function_name, "Public2_1"); ++ delete s; + + ClearSourceLineInfo(&frame); + frame.instruction = 0x219f; + frame.module = &module2; + resolver.FillSourceLineInfo(&frame); + ASSERT_TRUE(frame.function_name.empty()); + + frame.instruction = 0x21a0; + frame.module = &module2; +- resolver.FillSourceLineInfo(&frame); ++ s = resolver.FillSourceLineInfo(&frame); + ASSERT_EQ(frame.function_name, "Public2_2"); + ++ delete s; ++ + ASSERT_FALSE(resolver.LoadModule("module3", + testdata_dir + "/module3_bad.out")); + ASSERT_FALSE(resolver.HasModule("module3")); + ASSERT_FALSE(resolver.LoadModule("module4", + testdata_dir + "/module4_bad.out")); + ASSERT_FALSE(resolver.HasModule("module4")); + ASSERT_FALSE(resolver.LoadModule("module5", + testdata_dir + "/invalid-filename")); +diff --git a/toolkit/crashreporter/google-breakpad/src/processor/contained_range_map-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/contained_range_map-inl.h +--- a/toolkit/crashreporter/google-breakpad/src/processor/contained_range_map-inl.h ++++ b/toolkit/crashreporter/google-breakpad/src/processor/contained_range_map-inl.h +@@ -55,18 +55,22 @@ ContainedRangeMap + bool ContainedRangeMap::StoreRange( + const AddressType &base, const AddressType &size, const EntryType &entry) { + AddressType high = base + size - 1; + + // Check for undersize or overflow. + if (size <= 0 || high < base) { +- BPLOG(INFO) << "StoreRange failed, " << HexString(base) << "+" << +- HexString(size) << ", " << HexString(high); ++ //TODO(nealsid) We are commenting this out in order to prevent ++ // excessive logging. We plan to move to better logging as this ++ // failure happens quite often and is expected(see comment in ++ // basic_source_line_resolver.cc:671). ++ // BPLOG(INFO) << "StoreRange failed, " << HexString(base) << "+" ++ // << HexString(size) << ", " << HexString(high); + return false; + } + + if (!map_) + map_ = new AddressToRangeMap(); + + MapIterator iterator_base = map_->lower_bound(base); + MapIterator iterator_high = map_->lower_bound(high); +@@ -76,18 +80,19 @@ bool ContainedRangeMap= iterator_base->second->base_) { + // The new range is entirely within an existing child range. + + // If the new range's geometry is exactly equal to an existing child + // range's, it violates the containment rules, and an attempt to store + // it must fail. iterator_base->first contains the key, which was the + // containing child's high address. + if (iterator_base->second->base_ == base && iterator_base->first == high) { +- BPLOG(INFO) << "StoreRange failed, identical range is already " +- "present: " << HexString(base) << "+" << HexString(size); ++ // TODO(nealsid): See the TODO above on why this is commented out. ++// BPLOG(INFO) << "StoreRange failed, identical range is already " ++// "present: " << HexString(base) << "+" << HexString(size); + return false; + } + + // Pass the new range on to the child to attempt to store. + return iterator_base->second->StoreRange(base, size, entry); + } + + // iterator_high might refer to an irrelevant range: one whose base address +diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump.cc b/toolkit/crashreporter/google-breakpad/src/processor/minidump.cc +--- a/toolkit/crashreporter/google-breakpad/src/processor/minidump.cc ++++ b/toolkit/crashreporter/google-breakpad/src/processor/minidump.cc +@@ -45,32 +45,36 @@ typedef SSIZE_T ssize_t; + #define open _open + #define read _read + #define lseek _lseek + #else // _WIN32 + #define O_BINARY 0 + #endif // _WIN32 + + #include ++#include ++#include + #include + #include + #include + + #include "processor/range_map-inl.h" + + #include "google_breakpad/processor/minidump.h" + #include "processor/basic_code_module.h" + #include "processor/basic_code_modules.h" + #include "processor/logging.h" + #include "processor/scoped_ptr.h" + + + namespace google_breakpad { + + ++using std::istream; ++using std::ifstream; + using std::numeric_limits; + using std::vector; + + + // + // Swapping routines + // + // Inlining these doesn't increase code size significantly, and it saves +@@ -238,16 +242,25 @@ static string* UTF16ToUTF8(const vector< + HexString(unichar) << " in UTF-8"; + return NULL; + } + } + + return out.release(); + } + ++// Return the smaller of the number of code units in the UTF-16 string, ++// not including the terminating null word, or maxlen. ++static size_t UTF16codeunits(const u_int16_t *string, size_t maxlen) { ++ size_t count = 0; ++ while (count < maxlen && string[count] != 0) ++ count++; ++ return count; ++} ++ + + // + // MinidumpObject + // + + + MinidumpObject::MinidumpObject(Minidump* minidump) + : minidump_(minidump), +@@ -602,19 +615,75 @@ bool MinidumpContext::Read(u_int32_t exp + Swap(&context_sparc->float_save.filler); + Swap(&context_sparc->float_save.fsr); + } + context_.ctx_sparc = context_sparc.release(); + + break; + } + ++ case MD_CONTEXT_ARM: { ++ if (expected_size != sizeof(MDRawContextARM)) { ++ BPLOG(ERROR) << "MinidumpContext arm size mismatch, " << ++ expected_size << " != " << sizeof(MDRawContextARM); ++ return false; ++ } ++ ++ scoped_ptr context_arm(new MDRawContextARM()); ++ ++ // Set the context_flags member, which has already been read, and ++ // read the rest of the structure beginning with the first member ++ // after context_flags. ++ context_arm->context_flags = context_flags; ++ ++ size_t flags_size = sizeof(context_arm->context_flags); ++ u_int8_t* context_after_flags = ++ reinterpret_cast(context_arm.get()) + flags_size; ++ if (!minidump_->ReadBytes(context_after_flags, ++ sizeof(MDRawContextARM) - flags_size)) { ++ BPLOG(ERROR) << "MinidumpContext could not read arm context"; ++ return false; ++ } ++ ++ // Do this after reading the entire MDRawContext structure because ++ // GetSystemInfo may seek minidump to a new position. ++ if (!CheckAgainstSystemInfo(cpu_type)) { ++ BPLOG(ERROR) << "MinidumpContext arm does not match system info"; ++ return false; ++ } ++ ++ if (minidump_->swap()) { ++ // context_arm->context_flags was already swapped. ++ for (unsigned int ireg_index = 0; ++ ireg_index < MD_CONTEXT_ARM_GPR_COUNT; ++ ++ireg_index) { ++ Swap(&context_arm->iregs[ireg_index]); ++ } ++ Swap(&context_arm->cpsr); ++ Swap(&context_arm->float_save.fpscr); ++ for (unsigned int fpr_index = 0; ++ fpr_index < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT; ++ ++fpr_index) { ++ Swap(&context_arm->float_save.regs[fpr_index]); ++ } ++ for (unsigned int fpe_index = 0; ++ fpe_index < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT; ++ ++fpe_index) { ++ Swap(&context_arm->float_save.extra[fpe_index]); ++ } ++ } ++ context_.arm = context_arm.release(); ++ ++ break; ++ } ++ + default: { +- // Unknown context type +- BPLOG(ERROR) << "MinidumpContext unknown context type " << ++ // Unknown context type - Don't log as an error yet. Let the ++ // caller work that out. ++ BPLOG(INFO) << "MinidumpContext unknown context type " << + HexString(cpu_type); + return false; + break; + } + } + context_flags_ = context_flags; + } + +@@ -666,16 +735,25 @@ const MDRawContextSPARC* MinidumpContext + if (GetContextCPU() != MD_CONTEXT_SPARC) { + BPLOG(ERROR) << "MinidumpContext cannot get sparc context"; + return NULL; + } + + return context_.ctx_sparc; + } + ++const MDRawContextARM* MinidumpContext::GetContextARM() const { ++ if (GetContextCPU() != MD_CONTEXT_ARM) { ++ BPLOG(ERROR) << "MinidumpContext cannot get arm context"; ++ return NULL; ++ } ++ ++ return context_.arm; ++} ++ + void MinidumpContext::FreeContext() { + switch (GetContextCPU()) { + case MD_CONTEXT_X86: + delete context_.x86; + break; + + case MD_CONTEXT_PPC: + delete context_.ppc; +@@ -684,16 +762,20 @@ void MinidumpContext::FreeContext() { + case MD_CONTEXT_AMD64: + delete context_.amd64; + break; + + case MD_CONTEXT_SPARC: + delete context_.ctx_sparc; + break; + ++ case MD_CONTEXT_ARM: ++ delete context_.arm; ++ break; ++ + default: + // There is no context record (valid_ is false) or there's a + // context record for an unknown CPU (shouldn't happen, only known + // records are stored by Read). + break; + } + + context_flags_ = 0; +@@ -743,16 +825,21 @@ bool MinidumpContext::CheckAgainstSystem + if (system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64) + return_value = true; + break; + + case MD_CONTEXT_SPARC: + if (system_info_cpu_type == MD_CPU_ARCHITECTURE_SPARC) + return_value = true; + break; ++ ++ case MD_CONTEXT_ARM: ++ if (system_info_cpu_type == MD_CPU_ARCHITECTURE_ARM) ++ return_value = true; ++ break; + } + + BPLOG_IF(ERROR, !return_value) << "MinidumpContext CPU " << + HexString(context_cpu_type) << + " wrong for MinidumpSysmtemInfo CPU " << + HexString(system_info_cpu_type); + + return return_value; +@@ -948,16 +1035,46 @@ void MinidumpContext::Print() { + } + printf(" float_save.filler = 0x%" PRIx64 "\n", + context_sparc->float_save.filler); + printf(" float_save.fsr = 0x%" PRIx64 "\n", + context_sparc->float_save.fsr); + break; + } + ++ case MD_CONTEXT_ARM: { ++ const MDRawContextARM* context_arm = GetContextARM(); ++ printf("MDRawContextARM\n"); ++ printf(" context_flags = 0x%x\n", ++ context_arm->context_flags); ++ for (unsigned int ireg_index = 0; ++ ireg_index < MD_CONTEXT_ARM_GPR_COUNT; ++ ++ireg_index) { ++ printf(" iregs[%2d] = 0x%x\n", ++ ireg_index, context_arm->iregs[ireg_index]); ++ } ++ printf(" cpsr = 0x%x\n", context_arm->cpsr); ++ printf(" float_save.fpscr = 0x%" PRIx64 "\n", ++ context_arm->float_save.fpscr); ++ for (unsigned int fpr_index = 0; ++ fpr_index < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT; ++ ++fpr_index) { ++ printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n", ++ fpr_index, context_arm->float_save.regs[fpr_index]); ++ } ++ for (unsigned int fpe_index = 0; ++ fpe_index < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT; ++ ++fpe_index) { ++ printf(" float_save.extra[%2d] = 0x%" PRIx64 "\n", ++ fpe_index, context_arm->float_save.extra[fpe_index]); ++ } ++ ++ break; ++ } ++ + default: { + break; + } + } + } + + + // +@@ -1297,17 +1414,17 @@ void MinidumpThread::Print() { + } + + + // + // MinidumpThreadList + // + + +-u_int32_t MinidumpThreadList::max_threads_ = 256; ++u_int32_t MinidumpThreadList::max_threads_ = 4096; + + + MinidumpThreadList::MinidumpThreadList(Minidump* minidump) + : MinidumpStream(minidump), + id_to_thread_map_(), + threads_(NULL), + thread_count_(0) { + } +@@ -1459,18 +1576,18 @@ void MinidumpThreadList::Print() { + } + + + // + // MinidumpModule + // + + +-u_int32_t MinidumpModule::max_cv_bytes_ = 1024; +-u_int32_t MinidumpModule::max_misc_bytes_ = 1024; ++u_int32_t MinidumpModule::max_cv_bytes_ = 32768; ++u_int32_t MinidumpModule::max_misc_bytes_ = 32768; + + + MinidumpModule::MinidumpModule(Minidump* minidump) + : MinidumpObject(minidump), + module_valid_(false), + has_debug_info_(false), + module_(), + name_(NULL), +@@ -2419,17 +2536,17 @@ void MinidumpModuleList::Print() { + } + + + // + // MinidumpMemoryList + // + + +-u_int32_t MinidumpMemoryList::max_regions_ = 256; ++u_int32_t MinidumpMemoryList::max_regions_ = 4096; + + + MinidumpMemoryList::MinidumpMemoryList(Minidump* minidump) + : MinidumpStream(minidump), + range_map_(new RangeMap()), + descriptors_(NULL), + regions_(NULL), + region_count_(0) { +@@ -2708,18 +2825,20 @@ MinidumpContext* MinidumpException::GetC + if (!context_) { + if (!minidump_->SeekSet(exception_.thread_context.rva)) { + BPLOG(ERROR) << "MinidumpException cannot seek to context"; + return NULL; + } + + scoped_ptr context(new MinidumpContext(minidump_)); + ++ // Don't log as an error if we can still fall back on the thread's context ++ // (which must be possible if we got this far.) + if (!context->Read(exception_.thread_context.data_size)) { +- BPLOG(ERROR) << "MinidumpException cannot read context"; ++ BPLOG(INFO) << "MinidumpException cannot read context"; + return NULL; + } + + context_ = context.release(); + } + + return context_; + } +@@ -2760,16 +2879,119 @@ void MinidumpException::Print() { + printf("\n"); + context->Print(); + } else { + printf(" (no context)\n"); + printf("\n"); + } + } + ++// ++// MinidumpAssertion ++// ++ ++ ++MinidumpAssertion::MinidumpAssertion(Minidump* minidump) ++ : MinidumpStream(minidump), ++ assertion_(), ++ expression_(), ++ function_(), ++ file_() { ++} ++ ++ ++MinidumpAssertion::~MinidumpAssertion() { ++} ++ ++ ++bool MinidumpAssertion::Read(u_int32_t expected_size) { ++ // Invalidate cached data. ++ valid_ = false; ++ ++ if (expected_size != sizeof(assertion_)) { ++ BPLOG(ERROR) << "MinidumpAssertion size mismatch, " << expected_size << ++ " != " << sizeof(assertion_); ++ return false; ++ } ++ ++ if (!minidump_->ReadBytes(&assertion_, sizeof(assertion_))) { ++ BPLOG(ERROR) << "MinidumpAssertion cannot read assertion"; ++ return false; ++ } ++ ++ // Each of {expression, function, file} is a UTF-16 string, ++ // we'll convert them to UTF-8 for ease of use. ++ // expression ++ // Since we don't have an explicit byte length for each string, ++ // we use UTF16codeunits to calculate word length, then derive byte ++ // length from that. ++ u_int32_t word_length = UTF16codeunits(assertion_.expression, ++ sizeof(assertion_.expression)); ++ if (word_length > 0) { ++ u_int32_t byte_length = word_length * 2; ++ vector expression_utf16(word_length); ++ memcpy(&expression_utf16[0], &assertion_.expression[0], byte_length); ++ ++ scoped_ptr new_expression(UTF16ToUTF8(expression_utf16, ++ minidump_->swap())); ++ expression_ = *new_expression; ++ } ++ ++ // assertion ++ word_length = UTF16codeunits(assertion_.function, ++ sizeof(assertion_.function)); ++ if (word_length) { ++ u_int32_t byte_length = word_length * 2; ++ vector function_utf16(word_length); ++ memcpy(&function_utf16[0], &assertion_.function[0], byte_length); ++ scoped_ptr new_function(UTF16ToUTF8(function_utf16, ++ minidump_->swap())); ++ function_ = *new_function; ++ } ++ ++ // file ++ word_length = UTF16codeunits(assertion_.file, ++ sizeof(assertion_.file)); ++ if (word_length > 0) { ++ u_int32_t byte_length = word_length * 2; ++ vector file_utf16(word_length); ++ memcpy(&file_utf16[0], &assertion_.file[0], byte_length); ++ scoped_ptr new_file(UTF16ToUTF8(file_utf16, ++ minidump_->swap())); ++ file_ = *new_file; ++ } ++ ++ if (minidump_->swap()) { ++ Swap(&assertion_.line); ++ Swap(&assertion_.type); ++ } ++ ++ valid_ = true; ++ return true; ++} ++ ++void MinidumpAssertion::Print() { ++ if (!valid_) { ++ BPLOG(ERROR) << "MinidumpAssertion cannot print invalid data"; ++ return; ++ } ++ ++ printf("MDAssertion\n"); ++ printf(" expression = %s\n", ++ expression_.c_str()); ++ printf(" function = %s\n", ++ function_.c_str()); ++ printf(" file = %s\n", ++ file_.c_str()); ++ printf(" line = %u\n", ++ assertion_.line); ++ printf(" type = %u\n", ++ assertion_.type); ++ printf("\n"); ++} + + // + // MinidumpSystemInfo + // + + + MinidumpSystemInfo::MinidumpSystemInfo(Minidump* minidump) + : MinidumpStream(minidump), +@@ -2882,24 +3104,32 @@ string MinidumpSystemInfo::GetCPU() { + string cpu; + + switch (system_info_.processor_architecture) { + case MD_CPU_ARCHITECTURE_X86: + case MD_CPU_ARCHITECTURE_X86_WIN64: + cpu = "x86"; + break; + ++ case MD_CPU_ARCHITECTURE_AMD64: ++ cpu = "x86-64"; ++ break; ++ + case MD_CPU_ARCHITECTURE_PPC: + cpu = "ppc"; + break; + + case MD_CPU_ARCHITECTURE_SPARC: + cpu = "sparc"; + break; + ++ case MD_CPU_ARCHITECTURE_ARM: ++ cpu = "arm"; ++ break; ++ + default: + BPLOG(ERROR) << "MinidumpSystemInfo unknown CPU for architecture " << + HexString(system_info_.processor_architecture); + break; + } + + return cpu; + } +@@ -3211,53 +3441,62 @@ u_int32_t Minidump::max_streams_ = 128; + unsigned int Minidump::max_string_length_ = 1024; + + + Minidump::Minidump(const string& path) + : header_(), + directory_(NULL), + stream_map_(new MinidumpStreamMap()), + path_(path), +- fd_(-1), ++ stream_(NULL), + swap_(false), + valid_(false) { + } + ++Minidump::Minidump(istream& stream) ++ : header_(), ++ directory_(NULL), ++ stream_map_(new MinidumpStreamMap()), ++ path_(), ++ stream_(&stream), ++ swap_(false), ++ valid_(false) { ++} + + Minidump::~Minidump() { ++ if (stream_) { ++ BPLOG(INFO) << "Minidump closing minidump"; ++ } ++ if (!path_.empty()) { ++ delete stream_; ++ } + delete directory_; + delete stream_map_; +- if (fd_ != -1) { +- BPLOG(INFO) << "Minidump closing minidump on fd " << fd_; +- close(fd_); +- } + } + + + bool Minidump::Open() { +- if (fd_ != -1) { +- BPLOG(INFO) << "Minidump reopening minidump " << path_ << " on fd " << fd_; ++ if (stream_ != NULL) { ++ BPLOG(INFO) << "Minidump reopening minidump " << path_; + + // The file is already open. Seek to the beginning, which is the position + // the file would be at if it were opened anew. + return SeekSet(0); + } + +- // O_BINARY is useful (and defined) on Windows. On other platforms, it's +- // useless, and because it's defined as 0 above, harmless. +- fd_ = open(path_.c_str(), O_RDONLY | O_BINARY); +- if (fd_ == -1) { ++ stream_ = new ifstream(path_.c_str(), std::ios::in | std::ios::binary); ++ if (!stream_ || !stream_->good()) { + string error_string; + int error_code = ErrnoString(&error_string); + BPLOG(ERROR) << "Minidump could not open minidump " << path_ << + ", error " << error_code << ": " << error_string; + return false; + } + +- BPLOG(INFO) << "Minidump opened minidump " << path_ << " on fd " << fd_; ++ BPLOG(INFO) << "Minidump opened minidump " << path_; + return true; + } + + + bool Minidump::Read() { + // Invalidate cached data. + delete directory_; + directory_ = NULL; +@@ -3407,16 +3646,21 @@ MinidumpMemoryList* Minidump::GetMemoryL + } + + + MinidumpException* Minidump::GetException() { + MinidumpException* exception; + return GetStream(&exception); + } + ++MinidumpAssertion* Minidump::GetAssertion() { ++ MinidumpAssertion* assertion; ++ return GetStream(&assertion); ++} ++ + + MinidumpSystemInfo* Minidump::GetSystemInfo() { + MinidumpSystemInfo* system_info; + return GetStream(&system_info); + } + + + MinidumpMiscInfo* Minidump::GetMiscInfo() { +@@ -3492,53 +3736,60 @@ const MDRawDirectory* Minidump::GetDirec + } + + return &(*directory_)[index]; + } + + + bool Minidump::ReadBytes(void* bytes, size_t count) { + // Can't check valid_ because Read needs to call this method before +- // validity can be determined. The only member that this method +- // depends on is mFD, and an unset or invalid fd may generate an +- // error but should not cause a crash. +- ssize_t bytes_read = read(fd_, bytes, count); ++ // validity can be determined. ++ if (!stream_) { ++ return false; ++ } ++ stream_->read(static_cast(bytes), count); ++ size_t bytes_read = stream_->gcount(); + if (static_cast(bytes_read) != count) { + if (bytes_read == -1) { + string error_string; + int error_code = ErrnoString(&error_string); + BPLOG(ERROR) << "ReadBytes: error " << error_code << ": " << error_string; + } else { + BPLOG(ERROR) << "ReadBytes: read " << bytes_read << "/" << count; + } + return false; + } + return true; + } + + + bool Minidump::SeekSet(off_t offset) { + // Can't check valid_ because Read needs to call this method before +- // validity can be determined. The only member that this method +- // depends on is mFD, and an unset or invalid fd may generate an +- // error but should not cause a crash. +- off_t sought = lseek(fd_, offset, SEEK_SET); +- if (sought != offset) { +- if (sought == -1) { +- string error_string; +- int error_code = ErrnoString(&error_string); +- BPLOG(ERROR) << "SeekSet: error " << error_code << ": " << error_string; +- } else { +- BPLOG(ERROR) << "SeekSet: sought " << sought << "/" << offset; +- } ++ // validity can be determined. ++ if (!stream_) { ++ return false; ++ } ++ stream_->seekg(offset, std::ios_base::beg); ++ if (!stream_->good()) { ++ string error_string; ++ int error_code = ErrnoString(&error_string); ++ BPLOG(ERROR) << "SeekSet: error " << error_code << ": " << error_string; + return false; + } + return true; + } + ++off_t Minidump::Tell() { ++ if (!valid_ || !stream_) { ++ return (off_t)-1; ++ } ++ ++ return stream_->tellg(); ++} ++ + + string* Minidump::ReadString(off_t offset) { + if (!valid_) { + BPLOG(ERROR) << "Invalid Minidump for ReadString"; + return NULL; + } + if (!SeekSet(offset)) { + BPLOG(ERROR) << "ReadString could not seek to string at offset " << offset; +diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump_dump.cc b/toolkit/crashreporter/google-breakpad/src/processor/minidump_dump.cc +--- a/toolkit/crashreporter/google-breakpad/src/processor/minidump_dump.cc ++++ b/toolkit/crashreporter/google-breakpad/src/processor/minidump_dump.cc +@@ -39,16 +39,17 @@ + + namespace { + + using google_breakpad::Minidump; + using google_breakpad::MinidumpThreadList; + using google_breakpad::MinidumpModuleList; + using google_breakpad::MinidumpMemoryList; + using google_breakpad::MinidumpException; ++using google_breakpad::MinidumpAssertion; + using google_breakpad::MinidumpSystemInfo; + using google_breakpad::MinidumpMiscInfo; + using google_breakpad::MinidumpBreakpadInfo; + + static bool PrintMinidumpDump(const char *minidump_file) { + Minidump minidump(minidump_file); + if (!minidump.Read()) { + BPLOG(ERROR) << "minidump.Read() failed"; +@@ -84,16 +85,23 @@ static bool PrintMinidumpDump(const char + + MinidumpException *exception = minidump.GetException(); + if (!exception) { + BPLOG(INFO) << "minidump.GetException() failed"; + } else { + exception->Print(); + } + ++ MinidumpAssertion *assertion = minidump.GetAssertion(); ++ if (!assertion) { ++ BPLOG(INFO) << "minidump.GetAssertion() failed"; ++ } else { ++ assertion->Print(); ++ } ++ + MinidumpSystemInfo *system_info = minidump.GetSystemInfo(); + if (!system_info) { + ++errors; + BPLOG(ERROR) << "minidump.GetSystemInfo() failed"; + } else { + system_info->Print(); + } + +diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump_processor.cc b/toolkit/crashreporter/google-breakpad/src/processor/minidump_processor.cc +--- a/toolkit/crashreporter/google-breakpad/src/processor/minidump_processor.cc ++++ b/toolkit/crashreporter/google-breakpad/src/processor/minidump_processor.cc +@@ -23,16 +23,17 @@ + // 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 ++#include + + #include "google_breakpad/processor/minidump_processor.h" + #include "google_breakpad/processor/call_stack.h" + #include "google_breakpad/processor/minidump.h" + #include "google_breakpad/processor/process_state.h" + #include "processor/logging.h" + #include "processor/scoped_ptr.h" + #include "processor/stackwalker_x86.h" +@@ -42,102 +43,102 @@ namespace google_breakpad { + MinidumpProcessor::MinidumpProcessor(SymbolSupplier *supplier, + SourceLineResolverInterface *resolver) + : supplier_(supplier), resolver_(resolver) { + } + + MinidumpProcessor::~MinidumpProcessor() { + } + +-MinidumpProcessor::ProcessResult MinidumpProcessor::Process( +- const string &minidump_file, ProcessState *process_state) { +- BPLOG(INFO) << "Processing minidump in file " << minidump_file; +- +- Minidump dump(minidump_file); +- if (!dump.Read()) { +- BPLOG(ERROR) << "Minidump " << minidump_file << " could not be read"; +- return PROCESS_ERROR; +- } ++ProcessResult MinidumpProcessor::Process( ++ Minidump *dump, ProcessState *process_state) { ++ assert(dump); ++ assert(process_state); + + process_state->Clear(); + +- const MDRawHeader *header = dump.header(); +- BPLOG_IF(ERROR, !header) << "Minidump " << minidump_file << " has no header"; +- assert(header); ++ const MDRawHeader *header = dump->header(); ++ if (!header) { ++ BPLOG(ERROR) << "Minidump " << dump->path() << " has no header"; ++ return PROCESS_ERROR_NO_MINIDUMP_HEADER; ++ } + process_state->time_date_stamp_ = header->time_date_stamp; + +- bool has_cpu_info = GetCPUInfo(&dump, &process_state->system_info_); +- bool has_os_info = GetOSInfo(&dump, &process_state->system_info_); ++ bool has_cpu_info = GetCPUInfo(dump, &process_state->system_info_); ++ bool has_os_info = GetOSInfo(dump, &process_state->system_info_); + + u_int32_t dump_thread_id = 0; + bool has_dump_thread = false; + u_int32_t requesting_thread_id = 0; + bool has_requesting_thread = false; + +- MinidumpBreakpadInfo *breakpad_info = dump.GetBreakpadInfo(); ++ MinidumpBreakpadInfo *breakpad_info = dump->GetBreakpadInfo(); + if (breakpad_info) { + has_dump_thread = breakpad_info->GetDumpThreadID(&dump_thread_id); + has_requesting_thread = + breakpad_info->GetRequestingThreadID(&requesting_thread_id); + } + +- MinidumpException *exception = dump.GetException(); ++ MinidumpException *exception = dump->GetException(); + if (exception) { + process_state->crashed_ = true; + has_requesting_thread = exception->GetThreadID(&requesting_thread_id); + + process_state->crash_reason_ = GetCrashReason( +- &dump, &process_state->crash_address_); ++ dump, &process_state->crash_address_); + } + +- MinidumpModuleList *module_list = dump.GetModuleList(); ++ // This will just return an empty string if it doesn't exist. ++ process_state->assertion_ = GetAssertion(dump); ++ ++ MinidumpModuleList *module_list = dump->GetModuleList(); + + // Put a copy of the module list into ProcessState object. This is not + // necessarily a MinidumpModuleList, but it adheres to the CodeModules + // interface, which is all that ProcessState needs to expose. + if (module_list) + process_state->modules_ = module_list->Copy(); + +- MinidumpThreadList *threads = dump.GetThreadList(); ++ MinidumpThreadList *threads = dump->GetThreadList(); + if (!threads) { +- BPLOG(ERROR) << "Minidump " << minidump_file << " has no thread list"; +- return PROCESS_ERROR; ++ BPLOG(ERROR) << "Minidump " << dump->path() << " has no thread list"; ++ return PROCESS_ERROR_NO_THREAD_LIST; + } + +- BPLOG(INFO) << "Minidump " << minidump_file << " has " << +- (has_cpu_info ? "" : "no ") << "CPU info, " << +- (has_os_info ? "" : "no ") << "OS info, " << +- (breakpad_info != NULL ? "" : "no ") << "Breakpad info, " << +- (exception != NULL ? "" : "no ") << "exception, " << +- (module_list != NULL ? "" : "no ") << "module list, " << +- (threads != NULL ? "" : "no ") << "thread list, " << +- (has_dump_thread ? "" : "no ") << "dump thread, and " << +- (has_requesting_thread ? "" : "no ") << "requesting thread"; ++ BPLOG(INFO) << "Minidump " << dump->path() << " has " << ++ (has_cpu_info ? "" : "no ") << "CPU info, " << ++ (has_os_info ? "" : "no ") << "OS info, " << ++ (breakpad_info != NULL ? "" : "no ") << "Breakpad info, " << ++ (exception != NULL ? "" : "no ") << "exception, " << ++ (module_list != NULL ? "" : "no ") << "module list, " << ++ (threads != NULL ? "" : "no ") << "thread list, " << ++ (has_dump_thread ? "" : "no ") << "dump thread, and " << ++ (has_requesting_thread ? "" : "no ") << "requesting thread"; + + bool interrupted = false; + bool found_requesting_thread = false; + unsigned int thread_count = threads->thread_count(); + for (unsigned int thread_index = 0; + thread_index < thread_count; + ++thread_index) { + char thread_string_buffer[64]; + snprintf(thread_string_buffer, sizeof(thread_string_buffer), "%d/%d", + thread_index, thread_count); +- string thread_string = minidump_file + ":" + thread_string_buffer; ++ string thread_string = dump->path() + ":" + thread_string_buffer; + + MinidumpThread *thread = threads->GetThreadAtIndex(thread_index); + if (!thread) { + BPLOG(ERROR) << "Could not get thread for " << thread_string; +- return PROCESS_ERROR; ++ return PROCESS_ERROR_GETTING_THREAD; + } + + u_int32_t thread_id; + if (!thread->GetThreadID(&thread_id)) { + BPLOG(ERROR) << "Could not get thread ID for " << thread_string; +- return PROCESS_ERROR; ++ return PROCESS_ERROR_GETTING_THREAD_ID; + } + + thread_string += " id " + HexString(thread_id); + BPLOG(INFO) << "Looking at thread " << thread_string; + + // If this thread is the thread that produced the minidump, don't process + // it. Because of the problems associated with a thread producing a + // dump of itself (when both its context and its stack are in flux), +@@ -147,17 +148,17 @@ MinidumpProcessor::ProcessResult Minidum + } + + MinidumpContext *context = thread->GetContext(); + + if (has_requesting_thread && thread_id == requesting_thread_id) { + if (found_requesting_thread) { + // There can't be more than one requesting thread. + BPLOG(ERROR) << "Duplicate requesting thread: " << thread_string; +- return PROCESS_ERROR; ++ return PROCESS_ERROR_DUPLICATE_REQUESTING_THREADS; + } + + // Use processed_state->threads_.size() instead of thread_index. + // thread_index points to the thread index in the minidump, which + // might be greater than the thread index in the threads vector if + // any of the minidump's threads are skipped and not placed into the + // processed threads vector. The thread vector's current size will + // be the index of the current thread when it's pushed into the +@@ -166,25 +167,27 @@ MinidumpProcessor::ProcessResult Minidum + + found_requesting_thread = true; + + if (process_state->crashed_) { + // 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. +- context = exception->GetContext(); ++ // crash. If the exception context is invalid, however, we fall back ++ // on the thread context. ++ MinidumpContext *ctx = exception->GetContext(); ++ context = ctx ? ctx : thread->GetContext(); + } + } + + MinidumpMemoryRegion *thread_memory = thread->GetMemory(); + if (!thread_memory) { + BPLOG(ERROR) << "No memory region for " << thread_string; +- return PROCESS_ERROR; ++ return PROCESS_ERROR_NO_MEMORY_FOR_THREAD; + } + + // Use process_state->modules_ instead of module_list, because the + // |modules| argument will be used to populate the |module| fields in + // the returned StackFrame objects, which will be placed into the + // returned ProcessState object. module_list's lifetime is only as + // long as the Minidump object: it will be deleted when this function + // returns. process_state->modules_ is owned by the ProcessState object +@@ -194,46 +197,60 @@ MinidumpProcessor::ProcessResult Minidum + Stackwalker::StackwalkerForCPU(process_state->system_info(), + context, + thread_memory, + process_state->modules_, + supplier_, + resolver_)); + if (!stackwalker.get()) { + BPLOG(ERROR) << "No stackwalker for " << thread_string; +- return PROCESS_ERROR; ++ return PROCESS_ERROR_NO_STACKWALKER_FOR_THREAD; + } + + scoped_ptr stack(new CallStack()); + if (!stackwalker->Walk(stack.get())) { + BPLOG(INFO) << "Stackwalker interrupt (missing symbols?) at " << +- thread_string; ++ thread_string; + interrupted = true; + } + process_state->threads_.push_back(stack.release()); ++ process_state->thread_memory_regions_.push_back(thread_memory); + } + + if (interrupted) { +- BPLOG(INFO) << "Processing interrupted for " << minidump_file; +- return PROCESS_INTERRUPTED; ++ BPLOG(INFO) << "Processing interrupted for " << dump->path(); ++ return PROCESS_SYMBOL_SUPPLIER_INTERRUPTED; + } + + // If a requesting thread was indicated, it must be present. + if (has_requesting_thread && !found_requesting_thread) { + // Don't mark as an error, but invalidate the requesting thread + BPLOG(ERROR) << "Minidump indicated requesting thread " << +- HexString(requesting_thread_id) << ", not found in " << +- minidump_file; ++ HexString(requesting_thread_id) << ", not found in " << ++ dump->path(); + process_state->requesting_thread_ = -1; + } + +- BPLOG(INFO) << "Processed " << minidump_file; ++ BPLOG(INFO) << "Processed " << dump->path(); + return PROCESS_OK; + } + ++ProcessResult MinidumpProcessor::Process( ++ const string &minidump_file, ProcessState *process_state) { ++ BPLOG(INFO) << "Processing minidump in file " << minidump_file; ++ ++ Minidump dump(minidump_file); ++ if (!dump.Read()) { ++ BPLOG(ERROR) << "Minidump " << dump.path() << " could not be read"; ++ return PROCESS_ERROR_MINIDUMP_NOT_FOUND; ++ } ++ ++ return Process(&dump, process_state); ++} ++ + // Returns the MDRawSystemInfo from a minidump, or NULL if system info is + // not available from the minidump. If system_info is non-NULL, it is used + // to pass back the MinidumpSystemInfo object. + static const MDRawSystemInfo* GetSystemInfo(Minidump *dump, + MinidumpSystemInfo **system_info) { + MinidumpSystemInfo *minidump_system_info = dump->GetSystemInfo(); + if (!minidump_system_info) + return NULL; +@@ -255,17 +272,17 @@ bool MinidumpProcessor::GetCPUInfo(Minid + MinidumpSystemInfo *system_info; + const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, &system_info); + if (!raw_system_info) + return false; + + switch (raw_system_info->processor_architecture) { + case MD_CPU_ARCHITECTURE_X86: + case MD_CPU_ARCHITECTURE_AMD64: { +- if (raw_system_info->processor_architecture == ++ if (raw_system_info->processor_architecture == + MD_CPU_ARCHITECTURE_X86) + info->cpu = "x86"; + else + info->cpu = "amd64"; + + const string *cpu_vendor = system_info->GetCPUVendor(); + if (cpu_vendor) { + info->cpu_info = *cpu_vendor; +@@ -286,16 +303,21 @@ bool MinidumpProcessor::GetCPUInfo(Minid + break; + } + + case MD_CPU_ARCHITECTURE_SPARC: { + info->cpu = "sparc"; + break; + } + ++ case MD_CPU_ARCHITECTURE_ARM: { ++ info->cpu = "arm"; ++ break; ++ } ++ + default: { + // Assign the numeric architecture ID into the CPU string. + char cpu_string[7]; + snprintf(cpu_string, sizeof(cpu_string), "0x%04x", + raw_system_info->processor_architecture); + info->cpu = cpu_string; + break; + } +@@ -737,16 +759,19 @@ string MinidumpProcessor::GetCrashReason + reason = "EXCEPTION_PRIV_INSTRUCTION"; + break; + case MD_EXCEPTION_CODE_WIN_STACK_OVERFLOW: + reason = "EXCEPTION_STACK_OVERFLOW"; + break; + case MD_EXCEPTION_CODE_WIN_POSSIBLE_DEADLOCK: + reason = "EXCEPTION_POSSIBLE_DEADLOCK"; + break; ++ case MD_EXCEPTION_CODE_WIN_UNHANDLED_CPP_EXCEPTION: ++ reason = "Unhandled C++ Exception"; ++ break; + default: + BPLOG(INFO) << "Unknown exception reason " << reason; + break; + } + break; + } + + case MD_OS_LINUX: { +@@ -856,137 +881,190 @@ string MinidumpProcessor::GetCrashReason + case MD_EXCEPTION_CODE_SOL_SIGHUP: + reason = "SIGHUP"; + break; + case MD_EXCEPTION_CODE_SOL_SIGINT: + reason = "SIGINT"; + break; + case MD_EXCEPTION_CODE_SOL_SIGQUIT: + reason = "SIGQUIT"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGILL: + reason = "SIGILL"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGTRAP: + reason = "SIGTRAP"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGIOT: + reason = "SIGIOT | SIGABRT"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGEMT: + reason = "SIGEMT"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGFPE: + reason = "SIGFPE"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGKILL: + reason = "SIGKILL"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGBUS: + reason = "SIGBUS"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGSEGV: + reason = "SIGSEGV"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGSYS: + reason = "SIGSYS"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGPIPE: + reason = "SIGPIPE"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGALRM: + reason = "SIGALRM"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGTERM: + reason = "SIGTERM"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGUSR1: + reason = "SIGUSR1"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGUSR2: + reason = "SIGUSR2"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGCLD: + reason = "SIGCLD | SIGCHLD"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGPWR: + reason = "SIGPWR"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGWINCH: + reason = "SIGWINCH"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGURG: + reason = "SIGURG"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGPOLL: + reason = "SIGPOLL | SIGIO"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGSTOP: + reason = "SIGSTOP"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGTSTP: + reason = "SIGTSTP"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGCONT: + reason = "SIGCONT"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGTTIN: + reason = "SIGTTIN"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGTTOU: + reason = "SIGTTOU"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGVTALRM: + reason = "SIGVTALRM"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGPROF: + reason = "SIGPROF"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGXCPU: + reason = "SIGXCPU"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGXFSZ: + reason = "SIGXFSZ"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGWAITING: + reason = "SIGWAITING"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGLWP: + reason = "SIGLWP"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGFREEZE: + reason = "SIGFREEZE"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGTHAW: + reason = "SIGTHAW"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGCANCEL: + reason = "SIGCANCEL"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGLOST: + reason = "SIGLOST"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGXRES: + reason = "SIGXRES"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGJVM1: + reason = "SIGJVM1"; +- break; ++ break; + case MD_EXCEPTION_CODE_SOL_SIGJVM2: + reason = "SIGJVM2"; +- break; ++ break; + default: + BPLOG(INFO) << "Unknown exception reason " << reason; + break; + } + break; + } + + default: { + BPLOG(INFO) << "Unknown exception reason " << reason; + break; + } + } + + return reason; + } + ++// static ++string MinidumpProcessor::GetAssertion(Minidump *dump) ++{ ++ MinidumpAssertion *assertion = dump->GetAssertion(); ++ if (!assertion) ++ return ""; ++ ++ const MDRawAssertionInfo *raw_assertion = assertion->assertion(); ++ if (!raw_assertion) ++ return ""; ++ ++ string assertion_string; ++ switch (raw_assertion->type) { ++ case MD_ASSERTION_INFO_TYPE_INVALID_PARAMETER: ++ assertion_string = "Invalid parameter passed to library function"; ++ break; ++ case MD_ASSERTION_INFO_TYPE_PURE_VIRTUAL_CALL: ++ assertion_string = "Pure virtual function called"; ++ break; ++ default: { ++ char assertion_type[32]; ++ sprintf(assertion_type, "0x%08x", raw_assertion->type); ++ assertion_string = "Unknown assertion type "; ++ assertion_string += assertion_type; ++ break; ++ } ++ } ++ ++ string expression = assertion->expression(); ++ if (!expression.empty()) { ++ assertion_string.append(" " + expression); ++ } ++ ++ string function = assertion->function(); ++ if (!function.empty()) { ++ assertion_string.append(" in function " + function); ++ } ++ ++ string file = assertion->file(); ++ if (!file.empty()) { ++ assertion_string.append(", in file " + file); ++ } ++ ++ if (raw_assertion->line != 0) { ++ char assertion_line[32]; ++ sprintf(assertion_line, "%u", raw_assertion->line); ++ assertion_string.append(" at line "); ++ assertion_string.append(assertion_line); ++ } ++ ++ return assertion_string; ++} ++ + } // namespace google_breakpad +diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump_processor_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/minidump_processor_unittest.cc +--- a/toolkit/crashreporter/google-breakpad/src/processor/minidump_processor_unittest.cc ++++ b/toolkit/crashreporter/google-breakpad/src/processor/minidump_processor_unittest.cc +@@ -27,73 +27,88 @@ + // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + // Unit test for MinidumpProcessor. Uses a pre-generated minidump and + // corresponding symbol file, and checks the stack frames for correctness. + + #include + #include ++#include ++#include ++#include "breakpad_googletest_includes.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/code_modules.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.h" + #include "google_breakpad/processor/symbol_supplier.h" + #include "processor/logging.h" + #include "processor/scoped_ptr.h" + ++namespace google_breakpad { ++class MockMinidump : public Minidump { ++ public: ++ MockMinidump() : Minidump("") { ++ } ++ ++ MOCK_METHOD0(Read,bool()); ++ MOCK_CONST_METHOD0(path, string()); ++ MOCK_CONST_METHOD0(header,const MDRawHeader*()); ++ MOCK_METHOD0(GetThreadList,MinidumpThreadList*()); ++}; ++} ++ + namespace { + +-using std::string; + using google_breakpad::BasicSourceLineResolver; + using google_breakpad::CallStack; + using google_breakpad::CodeModule; + using google_breakpad::MinidumpProcessor; ++using google_breakpad::MinidumpThreadList; ++using google_breakpad::MinidumpThread; ++using google_breakpad::MockMinidump; + using google_breakpad::ProcessState; + using google_breakpad::scoped_ptr; + using google_breakpad::SymbolSupplier; + using google_breakpad::SystemInfo; ++using std::string; ++using ::testing::Return; + + static const char *kSystemInfoOS = "Windows NT"; + static const char *kSystemInfoOSShort = "windows"; + static const char *kSystemInfoOSVersion = "5.1.2600 Service Pack 2"; + static const char *kSystemInfoCPU = "x86"; + static const char *kSystemInfoCPUInfo = + "GenuineIntel family 6 model 13 stepping 8"; + +-#define ASSERT_TRUE(cond) \ +- if (!(cond)) { \ +- fprintf(stderr, "FAILED: %s at %s:%d\n", #cond, __FILE__, __LINE__); \ +- return false; \ +- } +- +-#define ASSERT_FALSE(cond) ASSERT_TRUE(!(cond)) +- +-#define ASSERT_EQ(e1, e2) ASSERT_TRUE((e1) == (e2)) +- +-// Use ASSERT_*_ABORT in functions that can't return a boolean. + #define ASSERT_TRUE_ABORT(cond) \ + if (!(cond)) { \ + fprintf(stderr, "FAILED: %s at %s:%d\n", #cond, __FILE__, __LINE__); \ + abort(); \ + } + + #define ASSERT_EQ_ABORT(e1, e2) ASSERT_TRUE_ABORT((e1) == (e2)) + + class TestSymbolSupplier : public SymbolSupplier { + public: + TestSymbolSupplier() : interrupt_(false) {} + + virtual SymbolResult GetSymbolFile(const CodeModule *module, + const SystemInfo *system_info, + string *symbol_file); + ++ virtual SymbolResult GetSymbolFile(const CodeModule *module, ++ const SystemInfo *system_info, ++ string *symbol_file, ++ string *symbol_data); ++ + // When set to true, causes the SymbolSupplier to return INTERRUPT + void set_interrupt(bool interrupt) { interrupt_ = interrupt; } + + private: + bool interrupt_; + }; + + SymbolSupplier::SymbolResult TestSymbolSupplier::GetSymbolFile( +@@ -118,27 +133,75 @@ SymbolSupplier::SymbolResult TestSymbolS + module->debug_identifier() + + "/test_app.sym"; + return FOUND; + } + + return NOT_FOUND; + } + +-static bool RunTests() { ++SymbolSupplier::SymbolResult TestSymbolSupplier::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()); ++ std::getline(in, *symbol_data, std::string::traits_type::to_char_type( ++ std::string::traits_type::eof())); ++ in.close(); ++ } ++ ++ return s; ++} ++ ++ ++class MinidumpProcessorTest : public ::testing::Test { ++ ++}; ++ ++TEST_F(MinidumpProcessorTest, TestCorruptMinidumps) { ++ MockMinidump dump; ++ TestSymbolSupplier supplier; ++ BasicSourceLineResolver resolver; ++ MinidumpProcessor processor(&supplier, &resolver); ++ ProcessState state; ++ ++ EXPECT_EQ(processor.Process("nonexistant minidump", &state), ++ google_breakpad::PROCESS_ERROR_MINIDUMP_NOT_FOUND); ++ ++ EXPECT_CALL(dump, path()).WillRepeatedly(Return("mock minidump")); ++ EXPECT_CALL(dump, Read()).WillRepeatedly(Return(true)); ++ ++ MDRawHeader fakeHeader; ++ fakeHeader.time_date_stamp = 0; ++ EXPECT_CALL(dump, header()).WillOnce(Return((MDRawHeader*)NULL)). ++ WillRepeatedly(Return(&fakeHeader)); ++ EXPECT_EQ(processor.Process(&dump, &state), ++ google_breakpad::PROCESS_ERROR_NO_MINIDUMP_HEADER); ++ ++ EXPECT_CALL(dump, GetThreadList()). ++ WillOnce(Return((MinidumpThreadList*)NULL)); ++ EXPECT_EQ(processor.Process(&dump, &state), ++ google_breakpad::PROCESS_ERROR_NO_THREAD_LIST); ++} ++ ++TEST_F(MinidumpProcessorTest, TestBasicProcessing) { + TestSymbolSupplier supplier; + BasicSourceLineResolver resolver; + MinidumpProcessor processor(&supplier, &resolver); + + string minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") + + "/src/processor/testdata/minidump2.dmp"; + + ProcessState state; + ASSERT_EQ(processor.Process(minidump_file, &state), +- MinidumpProcessor::PROCESS_OK); ++ google_breakpad::PROCESS_OK); + ASSERT_EQ(state.system_info()->os, kSystemInfoOS); + ASSERT_EQ(state.system_info()->os_short, kSystemInfoOSShort); + ASSERT_EQ(state.system_info()->os_version, kSystemInfoOSVersion); + ASSERT_EQ(state.system_info()->cpu, kSystemInfoCPU); + ASSERT_EQ(state.system_info()->cpu_info, kSystemInfoCPUInfo); + ASSERT_TRUE(state.crashed()); + ASSERT_EQ(state.crash_reason(), "EXCEPTION_ACCESS_VIOLATION"); + ASSERT_EQ(state.crash_address(), 0x45); +@@ -192,24 +255,17 @@ static bool RunTests() { + "kernel32.pdb"); + ASSERT_EQ(state.modules()->GetModuleForAddress(0x77d43210)->version(), + "5.1.2600.2622"); + + // Test that the symbol supplier can interrupt processing + state.Clear(); + supplier.set_interrupt(true); + ASSERT_EQ(processor.Process(minidump_file, &state), +- MinidumpProcessor::PROCESS_INTERRUPTED); +- +- return true; ++ google_breakpad::PROCESS_SYMBOL_SUPPLIER_INTERRUPTED ++ ); + } +- + } // namespace + + int main(int argc, char *argv[]) { +- BPLOG_INIT(&argc, &argv); +- +- if (!RunTests()) { +- return 1; +- } +- +- return 0; ++ ::testing::InitGoogleTest(&argc, argv); ++ return RUN_ALL_TESTS(); + } +diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk.cc b/toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk.cc +--- a/toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk.cc ++++ b/toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk.cc +@@ -29,16 +29,17 @@ + + // minidump_stackwalk.cc: Process a minidump with MinidumpProcessor, printing + // the results, including stack traces. + // + // Author: Mark Mentovai + + #include + #include ++#include + #include + #include + + #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/code_modules.h" + #include "google_breakpad/processor/minidump.h" +@@ -154,16 +155,38 @@ static void PrintStack(const CallStack * + 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); + } ++ const char *trust_name; ++ switch (frame_x86->trust) { ++ case StackFrameX86::FRAME_TRUST_NONE: ++ trust_name = "unknown"; ++ break; ++ case StackFrameX86::FRAME_TRUST_CONTEXT: ++ trust_name = "given as instruction pointer in context"; ++ break; ++ case StackFrameX86::FRAME_TRUST_CFI: ++ trust_name = "call frame info"; ++ break; ++ case StackFrameX86::FRAME_TRUST_CFI_SCAN: ++ trust_name = "call frame info with scanning"; ++ break; ++ case StackFrameX86::FRAME_TRUST_FP: ++ trust_name = "previous frame's frame pointer"; ++ break; ++ case StackFrameX86::FRAME_TRUST_SCAN: ++ trust_name = "stack scanning"; ++ break; ++ } ++ printf("\n Found by: %s", trust_name); + } else if (cpu == "ppc") { + const StackFramePPC *frame_ppc = + reinterpret_cast(frame); + + 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); +@@ -333,16 +356,21 @@ static void PrintProcessState(const Proc + // Print crash information. + if (process_state.crashed()) { + printf("Crash reason: %s\n", process_state.crash_reason().c_str()); + printf("Crash address: 0x%" PRIx64 "\n", process_state.crash_address()); + } else { + printf("No crash\n"); + } + ++ string assertion = process_state.assertion(); ++ if (!assertion.empty()) { ++ printf("Assertion: %s\n", assertion.c_str()); ++ } ++ + // If the thread that requested the dump is known, print it first. + 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"); +@@ -385,17 +413,25 @@ static void PrintProcessStateMachineRead + // Print crash information. + // Crash|{Crash Reason}|{Crash Address}|{Crashed Thread} + printf("Crash%c", kOutputSeparator); + if (process_state.crashed()) { + printf("%s%c0x%" PRIx64 "%c", + StripSeparator(process_state.crash_reason()).c_str(), + kOutputSeparator, process_state.crash_address(), kOutputSeparator); + } else { +- printf("No crash%c%c", kOutputSeparator, kOutputSeparator); ++ // print assertion info, if available, in place of crash reason, ++ // instead of the unhelpful "No crash" ++ string assertion = process_state.assertion(); ++ if (!assertion.empty()) { ++ printf("%s%c%c", StripSeparator(assertion).c_str(), ++ kOutputSeparator, kOutputSeparator); ++ } else { ++ printf("No crash%c%c", kOutputSeparator, kOutputSeparator); ++ } + } + + if (requesting_thread != -1) { + printf("%d\n", requesting_thread); + } else { + printf("\n"); + } + +@@ -441,17 +477,17 @@ static bool PrintMinidumpProcess(const s + } + + BasicSourceLineResolver resolver; + MinidumpProcessor minidump_processor(symbol_supplier.get(), &resolver); + + // Process the minidump. + ProcessState process_state; + if (minidump_processor.Process(minidump_file, &process_state) != +- MinidumpProcessor::PROCESS_OK) { ++ google_breakpad::PROCESS_OK) { + BPLOG(ERROR) << "MinidumpProcessor::Process failed"; + return false; + } + + if (machine_readable) { + PrintProcessStateMachineReadable(process_state); + } else { + PrintProcessState(process_state); +diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/minidump_unittest.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/processor/minidump_unittest.cc +@@ -0,0 +1,103 @@ ++// Copyright (c) 2009, 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. ++ ++// Unit test for Minidump. Uses a pre-generated minidump and ++// verifies that certain streams are correct. ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "breakpad_googletest_includes.h" ++#include "google_breakpad/common/minidump_format.h" ++#include "google_breakpad/processor/minidump.h" ++#include "processor/logging.h" ++ ++namespace { ++ ++using google_breakpad::Minidump; ++using std::ifstream; ++using std::istringstream; ++using std::string; ++using std::vector; ++using ::testing::Return; ++ ++class MinidumpTest : public ::testing::Test { ++public: ++ void SetUp() { ++ minidump_file_ = string(getenv("srcdir") ? getenv("srcdir") : ".") + ++ "/src/processor/testdata/minidump2.dmp"; ++ } ++ string minidump_file_; ++}; ++ ++TEST_F(MinidumpTest, TestMinidumpFromFile) { ++ Minidump minidump(minidump_file_); ++ ASSERT_EQ(minidump.path(), minidump_file_); ++ ASSERT_TRUE(minidump.Read()); ++ const MDRawHeader* header = minidump.header(); ++ ASSERT_NE(header, (MDRawHeader*)NULL); ++ ASSERT_EQ(header->signature, MD_HEADER_SIGNATURE); ++ //TODO: add more checks here ++} ++ ++TEST_F(MinidumpTest, TestMinidumpFromStream) { ++ // read minidump contents into memory, construct a stringstream around them ++ ifstream file_stream(minidump_file_.c_str(), std::ios::in); ++ ASSERT_TRUE(file_stream.good()); ++ vector bytes; ++ file_stream.seekg(0, std::ios_base::end); ++ ASSERT_TRUE(file_stream.good()); ++ bytes.resize(file_stream.tellg()); ++ file_stream.seekg(0, std::ios_base::beg); ++ ASSERT_TRUE(file_stream.good()); ++ file_stream.read(&bytes[0], bytes.size()); ++ ASSERT_TRUE(file_stream.good()); ++ string str(&bytes[0], bytes.size()); ++ istringstream stream(str); ++ ASSERT_TRUE(stream.good()); ++ ++ // now read minidump from stringstream ++ Minidump minidump(stream); ++ ASSERT_EQ(minidump.path(), ""); ++ ASSERT_TRUE(minidump.Read()); ++ const MDRawHeader* header = minidump.header(); ++ ASSERT_NE(header, (MDRawHeader*)NULL); ++ ASSERT_EQ(header->signature, MD_HEADER_SIGNATURE); ++ //TODO: add more checks here ++} ++ ++} // namespace ++ ++int main(int argc, char* argv[]) { ++ ::testing::InitGoogleTest(&argc, argv); ++ return RUN_ALL_TESTS(); ++} +diff --git a/toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper_unittest.cc +--- a/toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper_unittest.cc ++++ b/toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper_unittest.cc +@@ -22,16 +22,18 @@ + // 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 ++ + #include "processor/pathname_stripper.h" + #include "processor/logging.h" + + #define ASSERT_TRUE(condition) \ + if (!(condition)) { \ + fprintf(stderr, "FAIL: %s @ %s:%d\n", #condition, __FILE__, __LINE__); \ + return false; \ + } +diff --git a/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator-inl.h +--- a/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator-inl.h ++++ b/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator-inl.h +@@ -33,16 +33,17 @@ + // Documentation in postfix_evaluator.h. + // + // Author: Mark Mentovai + + #ifndef PROCESSOR_POSTFIX_EVALUATOR_INL_H__ + #define PROCESSOR_POSTFIX_EVALUATOR_INL_H__ + + ++#include + #include + + #include "processor/postfix_evaluator.h" + #include "google_breakpad/processor/memory_region.h" + #include "processor/logging.h" + + namespace google_breakpad { + +diff --git a/toolkit/crashreporter/google-breakpad/src/processor/process_state.cc b/toolkit/crashreporter/google-breakpad/src/processor/process_state.cc +--- a/toolkit/crashreporter/google-breakpad/src/processor/process_state.cc ++++ b/toolkit/crashreporter/google-breakpad/src/processor/process_state.cc +@@ -43,16 +43,17 @@ ProcessState::~ProcessState() { + Clear(); + } + + void ProcessState::Clear() { + time_date_stamp_ = 0; + crashed_ = false; + crash_reason_.clear(); + crash_address_ = 0; ++ assertion_.clear(); + requesting_thread_ = -1; + for (vector::const_iterator iterator = threads_.begin(); + iterator != threads_.end(); + ++iterator) { + delete *iterator; + } + threads_.clear(); + system_info_.Clear(); +diff --git a/toolkit/crashreporter/google-breakpad/src/processor/simple_symbol_supplier.cc b/toolkit/crashreporter/google-breakpad/src/processor/simple_symbol_supplier.cc +--- a/toolkit/crashreporter/google-breakpad/src/processor/simple_symbol_supplier.cc ++++ b/toolkit/crashreporter/google-breakpad/src/processor/simple_symbol_supplier.cc +@@ -33,16 +33,18 @@ + // + // Author: Mark Mentovai + + #include + #include + + #include + #include ++#include ++#include + + #include "processor/simple_symbol_supplier.h" + #include "google_breakpad/processor/code_module.h" + #include "google_breakpad/processor/system_info.h" + #include "processor/logging.h" + #include "processor/pathname_stripper.h" + + namespace google_breakpad { +@@ -57,25 +59,45 @@ SymbolSupplier::SymbolResult SimpleSymbo + string *symbol_file) { + BPLOG_IF(ERROR, !symbol_file) << "SimpleSymbolSupplier::GetSymbolFile " + "requires |symbol_file|"; + assert(symbol_file); + symbol_file->clear(); + + for (unsigned int path_index = 0; path_index < paths_.size(); ++path_index) { + SymbolResult result; +- if ((result = GetSymbolFileAtPath(module, system_info, paths_[path_index], +- symbol_file)) != NOT_FOUND) { ++ if ((result = GetSymbolFileAtPathFromRoot(module, system_info, ++ paths_[path_index], ++ symbol_file)) != NOT_FOUND) { + return result; + } + } + return NOT_FOUND; + } + +-SymbolSupplier::SymbolResult SimpleSymbolSupplier::GetSymbolFileAtPath( ++SymbolSupplier::SymbolResult SimpleSymbolSupplier::GetSymbolFile( ++ const CodeModule *module, ++ const SystemInfo *system_info, ++ string *symbol_file, ++ string *symbol_data) { ++ assert(symbol_data); ++ symbol_data->clear(); ++ ++ SymbolSupplier::SymbolResult s = GetSymbolFile(module, system_info, symbol_file); ++ ++ if (s == FOUND) { ++ std::ifstream in(symbol_file->c_str()); ++ std::getline(in, *symbol_data, std::string::traits_type::to_char_type( ++ std::string::traits_type::eof())); ++ in.close(); ++ } ++ return s; ++} ++ ++SymbolSupplier::SymbolResult SimpleSymbolSupplier::GetSymbolFileAtPathFromRoot( + const CodeModule *module, const SystemInfo *system_info, + const string &root_path, string *symbol_file) { + BPLOG_IF(ERROR, !symbol_file) << "SimpleSymbolSupplier::GetSymbolFileAtPath " + "requires |symbol_file|"; + assert(symbol_file); + symbol_file->clear(); + + if (!module) +diff --git a/toolkit/crashreporter/google-breakpad/src/processor/simple_symbol_supplier.h b/toolkit/crashreporter/google-breakpad/src/processor/simple_symbol_supplier.h +--- a/toolkit/crashreporter/google-breakpad/src/processor/simple_symbol_supplier.h ++++ b/toolkit/crashreporter/google-breakpad/src/processor/simple_symbol_supplier.h +@@ -97,25 +97,29 @@ class SimpleSymbolSupplier : public Symb + // Creates a new SimpleSymbolSupplier, using paths as a list of root + // paths where symbols may be stored. + explicit SimpleSymbolSupplier(const vector &paths) : paths_(paths) {} + + virtual ~SimpleSymbolSupplier() {} + + // Returns the path to the symbol file for the given module. See the + // description above. +- SymbolResult GetSymbolFile(const CodeModule *module, +- const SystemInfo *system_info, +- string *symbol_file); ++ virtual SymbolResult GetSymbolFile(const CodeModule *module, ++ const SystemInfo *system_info, ++ string *symbol_file); + ++ virtual SymbolResult GetSymbolFile(const CodeModule *module, ++ const SystemInfo *system_info, ++ string *symbol_file, ++ string *symbol_data); + protected: +- SymbolResult GetSymbolFileAtPath(const CodeModule *module, +- const SystemInfo *system_info, +- const string &root_path, +- string *symbol_file); ++ SymbolResult GetSymbolFileAtPathFromRoot(const CodeModule *module, ++ const SystemInfo *system_info, ++ const string &root_path, ++ string *symbol_file); + + private: + vector paths_; + }; + + } // namespace google_breakpad + + #endif // PROCESSOR_SIMPLE_SYMBOL_SUPPLIER_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker.cc +--- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker.cc ++++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker.cc +@@ -47,16 +47,17 @@ + #include "processor/linked_ptr.h" + #include "processor/logging.h" + #include "processor/scoped_ptr.h" + #include "processor/stack_frame_info.h" + #include "processor/stackwalker_ppc.h" + #include "processor/stackwalker_sparc.h" + #include "processor/stackwalker_x86.h" + #include "processor/stackwalker_amd64.h" ++#include "processor/stackwalker_arm.h" + + namespace google_breakpad { + + + Stackwalker::Stackwalker(const SystemInfo *system_info, + MemoryRegion *memory, + const CodeModules *modules, + SymbolSupplier *supplier, +@@ -96,23 +97,25 @@ bool Stackwalker::Walk(CallStack *stack) + if (modules_) { + const CodeModule *module = + modules_->GetModuleForAddress(frame->instruction); + if (module) { + frame->module = module; + if (resolver_ && + !resolver_->HasModule(frame->module->code_file()) && + supplier_) { +- string symbol_file; ++ string symbol_data, symbol_file; + SymbolSupplier::SymbolResult symbol_result = +- supplier_->GetSymbolFile(module, system_info_, &symbol_file); ++ supplier_->GetSymbolFile(module, system_info_, ++ &symbol_file, &symbol_data); + + switch (symbol_result) { + case SymbolSupplier::FOUND: +- resolver_->LoadModule(frame->module->code_file(), symbol_file); ++ resolver_->LoadModuleUsingMapBuffer(frame->module->code_file(), ++ symbol_data); + break; + case SymbolSupplier::NOT_FOUND: + break; // nothing to do + case SymbolSupplier::INTERRUPT: + return false; + } + } + frame_info.reset(resolver_->FillSourceLineInfo(frame.get())); +@@ -174,18 +177,59 @@ Stackwalker* Stackwalker::StackwalkerFor + break; + + case MD_CONTEXT_SPARC: + cpu_stackwalker = new StackwalkerSPARC(system_info, + context->GetContextSPARC(), + memory, modules, supplier, + resolver); + break; ++ ++ case MD_CONTEXT_ARM: ++ cpu_stackwalker = new StackwalkerARM(system_info, ++ context->GetContextARM(), ++ memory, modules, supplier, ++ resolver); ++ break; + } + + BPLOG_IF(ERROR, !cpu_stackwalker) << "Unknown CPU type " << HexString(cpu) << + ", can't choose a stackwalker " + "implementation"; + return cpu_stackwalker; + } + ++bool Stackwalker::InstructionAddressSeemsValid(u_int64_t address) { ++ const CodeModule *module = modules_->GetModuleForAddress(address); ++ if (!module) { ++ // not inside any loaded module ++ return false; ++ } ++ ++ if (!resolver_ || !supplier_) { ++ // we don't have a resolver and or symbol supplier, ++ // but we're inside a known module ++ return true; ++ } ++ ++ if (!resolver_->HasModule(module->code_file())) { ++ string symbol_data, symbol_file; ++ SymbolSupplier::SymbolResult symbol_result = ++ supplier_->GetSymbolFile(module, system_info_, ++ &symbol_file, &symbol_data); ++ ++ if (symbol_result != SymbolSupplier::FOUND || ++ !resolver_->LoadModuleUsingMapBuffer(module->code_file(), ++ symbol_data)) { ++ // we don't have symbols, but we're inside a loaded module ++ return true; ++ } ++ } ++ ++ StackFrame frame; ++ frame.module = module; ++ frame.instruction = address; ++ resolver_->FillSourceLineInfo(&frame); ++ // we have symbols, so return true if inside a function ++ return !frame.function_name.empty(); ++} + + } // namespace google_breakpad +diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm.cc +@@ -0,0 +1,92 @@ ++// Copyright (c) 2009, 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. ++ ++// stackwalker_arm.cc: arm-specific stackwalker. ++// ++// See stackwalker_arm.h for documentation. ++// ++// Author: Mark Mentovai, Ted Mielczarek ++ ++ ++#include "processor/stackwalker_arm.h" ++#include "google_breakpad/processor/call_stack.h" ++#include "google_breakpad/processor/memory_region.h" ++#include "google_breakpad/processor/stack_frame_cpu.h" ++#include "processor/logging.h" ++ ++namespace google_breakpad { ++ ++ ++StackwalkerARM::StackwalkerARM(const SystemInfo *system_info, ++ const MDRawContextARM *context, ++ MemoryRegion *memory, ++ const CodeModules *modules, ++ SymbolSupplier *supplier, ++ SourceLineResolverInterface *resolver) ++ : Stackwalker(system_info, memory, modules, supplier, resolver), ++ context_(context) { ++} ++ ++ ++StackFrame* StackwalkerARM::GetContextFrame() { ++ if (!context_ || !memory_) { ++ BPLOG(ERROR) << "Can't get context frame without context or memory"; ++ return NULL; ++ } ++ ++ StackFrameARM *frame = new StackFrameARM(); ++ ++ // The instruction pointer is stored directly in a register (r15), so pull it ++ // straight out of the CPU context structure. ++ frame->context = *context_; ++ frame->context_validity = StackFrameARM::CONTEXT_VALID_ALL; ++ frame->instruction = frame->context.iregs[15]; ++ ++ return frame; ++} ++ ++ ++StackFrame* StackwalkerARM::GetCallerFrame( ++ const CallStack *stack, ++ const vector< linked_ptr > &stack_frame_info) { ++ if (!memory_ || !stack) { ++ BPLOG(ERROR) << "Can't get caller frame without memory or stack"; ++ return NULL; ++ } ++ ++ StackFrameARM *last_frame = static_cast( ++ stack->frames()->back()); ++ ++ // TODO: Can't actually walk the stack on ARM without the CFI data. ++ // Implement this when the CFI symbol dumper changes have landed. ++ return NULL; ++} ++ ++ ++} // namespace google_breakpad +diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm.h b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm.h +@@ -0,0 +1,80 @@ ++// Copyright (c) 2009, 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. ++ ++// stackwalker_arm.h: arm-specific stackwalker. ++// ++// Provides stack frames given arm register context and a memory region ++// corresponding to an arm stack. ++// ++// Author: Mark Mentovai, Ted Mielczarek ++ ++ ++#ifndef PROCESSOR_STACKWALKER_ARM_H__ ++#define PROCESSOR_STACKWALKER_ARM_H__ ++ ++ ++#include "google_breakpad/common/breakpad_types.h" ++#include "google_breakpad/common/minidump_format.h" ++#include "google_breakpad/processor/stackwalker.h" ++ ++namespace google_breakpad { ++ ++class CodeModules; ++ ++class StackwalkerARM : public Stackwalker { ++ public: ++ // context is an arm context object that gives access to arm-specific ++ // register state corresponding to the innermost called frame to be ++ // included in the stack. The other arguments are passed directly through ++ // to the base Stackwalker constructor. ++ StackwalkerARM(const SystemInfo *system_info, ++ const MDRawContextARM *context, ++ MemoryRegion *memory, ++ const CodeModules *modules, ++ SymbolSupplier *supplier, ++ SourceLineResolverInterface *resolver); ++ ++ private: ++ // Implementation of Stackwalker, using arm context and stack conventions. ++ // TODO: currently stubbed out, needs CFI symbol dumper support ++ virtual StackFrame* GetContextFrame(); ++ virtual StackFrame* GetCallerFrame( ++ const CallStack *stack, ++ const vector< linked_ptr > &stack_frame_info); ++ ++ // Stores the CPU context corresponding to the innermost stack frame to ++ // be returned by GetContextFrame. ++ const MDRawContextARM *context_; ++}; ++ ++ ++} // namespace google_breakpad ++ ++ ++#endif // PROCESSOR_STACKWALKER_ARM_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.cc +--- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.cc ++++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.cc +@@ -74,30 +74,31 @@ StackFrame* StackwalkerX86::GetContextFr + } + + StackFrameX86 *frame = new StackFrameX86(); + + // The instruction pointer is stored directly in a register, so pull it + // straight out of the CPU context structure. + frame->context = *context_; + frame->context_validity = StackFrameX86::CONTEXT_VALID_ALL; ++ frame->trust = StackFrameX86::FRAME_TRUST_CONTEXT; + frame->instruction = frame->context.eip; + + return frame; + } + + + StackFrame* StackwalkerX86::GetCallerFrame( + const CallStack *stack, + const vector< linked_ptr > &stack_frame_info) { + if (!memory_ || !stack) { + BPLOG(ERROR) << "Can't get caller frame without memory or stack"; + return NULL; + } +- ++ StackFrameX86::FrameTrust trust = StackFrameX86::FRAME_TRUST_NONE; + StackFrameX86 *last_frame = static_cast( + stack->frames()->back()); + StackFrameInfo *last_frame_info = stack_frame_info.back().get(); + + // This stackwalker sets each frame's %esp to its value immediately prior + // to the CALL into the callee. This means that %esp points to the last + // callee argument pushed onto the stack, which may not be where %esp points + // after the callee returns. Specifically, the value is correct for the +@@ -178,16 +179,17 @@ StackFrame* StackwalkerX86::GetCallerFra + // without any need for scanning. The results of program string evaluation + // will be used to determine whether to scan for better values. + string program_string; + bool traditional_frame = true; + bool recover_ebp = true; + if (last_frame_info && last_frame_info->valid == StackFrameInfo::VALID_ALL) { + // FPO data available. + traditional_frame = false; ++ trust = StackFrameX86::FRAME_TRUST_CFI; + if (!last_frame_info->program_string.empty()) { + // The FPO data has its own program string, which will tell us how to + // get to the caller frame, and may even fill in the values of + // nonvolatile registers and provide pointers to local variables and + // parameters. In some cases, particularly with program strings that use + // .raSearchStart, the stack may need to be scanned afterward. + program_string = last_frame_info->program_string; + } else if (last_frame_info->allocates_base_pointer) { +@@ -275,30 +277,50 @@ StackFrame* StackwalkerX86::GetCallerFra + // + // Instruction and frame pointer recovery for these traditional frames is + // entirely deterministic, and the stack will not be scanned after + // recovering these values. + // + // %eip_new = *(%ebp_old + 4) + // %esp_new = %ebp_old + 8 + // %ebp_new = *(%ebp_old) ++ trust = StackFrameX86::FRAME_TRUST_FP; + program_string = "$eip $ebp 4 + ^ = " + "$esp $ebp 8 + = " + "$ebp $ebp ^ ="; + } + + // Now crank it out, making sure that the program string set at least the + // two required variables. + PostfixEvaluator evaluator = + PostfixEvaluator(&dictionary, memory_); + PostfixEvaluator::DictionaryValidityType dictionary_validity; + if (!evaluator.Evaluate(program_string, &dictionary_validity) || + dictionary_validity.find("$eip") == dictionary_validity.end() || + dictionary_validity.find("$esp") == dictionary_validity.end()) { +- return NULL; ++ // Program string evaluation failed. It may be that %eip is not somewhere ++ // with stack frame info, and %ebp is pointing to non-stack memory, so ++ // our evaluation couldn't succeed. We'll scan the stack for a return ++ // address. This can happen if the stack is in a module for which ++ // we don't have symbols, and that module is compiled without a ++ // frame pointer. ++ u_int32_t location_start = last_frame->context.esp; ++ u_int32_t location, eip; ++ if (!ScanForReturnAddress(location_start, location, eip)) { ++ // if we can't find an instruction pointer even with stack scanning, ++ // give up. ++ return NULL; ++ } ++ ++ // This seems like a reasonable return address. Since program string ++ // evaluation failed, use it and set %esp to the location above the ++ // one where the return address was found. ++ dictionary["$eip"] = eip; ++ dictionary["$esp"] = location + 4; ++ trust = StackFrameX86::FRAME_TRUST_SCAN; + } + + // If this stack frame did not use %ebp in a traditional way, locating the + // return address isn't entirely deterministic. In that case, the stack + // can be scanned to locate the return address. + // + // Even in nontraditional frames, if program string evaluation resulted in + // both %eip and %ebp values of 0, trust that the end of the stack has been +@@ -316,43 +338,28 @@ StackFrame* StackwalkerX86::GetCallerFra + // require dumps that contain MINIDUMP_MEMORY_INFO, which the Breakpad + // client doesn't currently write (it would need to call MiniDumpWriteDump + // with the MiniDumpWithFullMemoryInfo type bit set). Even given this + // ability, older OSes (pre-XP SP2) and CPUs (pre-P4) don't enforce + // an independent execute privilege on memory pages. + + u_int32_t eip = dictionary["$eip"]; + if (modules_ && !modules_->GetModuleForAddress(eip)) { +- const int kRASearchWords = 15; +- + // The instruction pointer at .raSearchStart was invalid, so start + // looking one 32-bit word above that location. + u_int32_t location_start = dictionary[".raSearchStart"] + 4; +- +- for (u_int32_t location = location_start; +- location <= location_start + kRASearchWords * 4; +- location += 4) { +- if (!memory_->GetMemoryAtAddress(location, &eip)) +- break; +- +- if (modules_->GetModuleForAddress(eip)) { +- // This is a better return address that what program string +- // evaluation found. Use it, and set %esp to the location above the +- // one where the return address was found. +- // +- // TODO(mmentovai): The return-address check can be made even +- // stronger in modules for which debugging data is available. In +- // that case, it's possible to check that the candidate return +- // address is inside a known function. +- +- dictionary["$eip"] = eip; +- dictionary["$esp"] = location + 4; +- offset = location - location_start; +- break; +- } ++ u_int32_t location; ++ if (ScanForReturnAddress(location_start, location, eip)) { ++ // This is a better return address that what program string ++ // evaluation found. Use it, and set %esp to the location above the ++ // one where the return address was found. ++ dictionary["$eip"] = eip; ++ dictionary["$esp"] = location + 4; ++ offset = location - location_start; ++ trust = StackFrameX86::FRAME_TRUST_CFI_SCAN; + } + } + + // When trying to recover the previous value of the frame pointer (%ebp), + // start looking at the lowest possible address in the saved-register + // area, and look at the entire saved register area, increased by the + // size of |offset| to account for additional data that may be on the + // stack. The scan is performed from the highest possible address to +@@ -387,16 +394,17 @@ StackFrame* StackwalkerX86::GetCallerFra + dictionary["$esp"] <= last_frame->context.esp) { + return NULL; + } + + // Create a new stack frame (ownership will be transferred to the caller) + // and fill it in. + StackFrameX86 *frame = new StackFrameX86(); + ++ frame->trust = trust; + frame->context = last_frame->context; + frame->context.eip = dictionary["$eip"]; + frame->context.esp = dictionary["$esp"]; + frame->context.ebp = dictionary["$ebp"]; + frame->context_validity = StackFrameX86::CONTEXT_VALID_EIP | + StackFrameX86::CONTEXT_VALID_ESP | + StackFrameX86::CONTEXT_VALID_EBP; + +@@ -423,10 +431,32 @@ StackFrame* StackwalkerX86::GetCallerFra + // with the line that contains a function call. Callers that require the + // exact return address value may access the context.eip field of + // StackFrameX86. + frame->instruction = frame->context.eip - 1; + + return frame; + } + ++bool StackwalkerX86::ScanForReturnAddress(u_int32_t location_start, ++ u_int32_t &location_found, ++ u_int32_t &eip_found) { ++ const int kRASearchWords = 15; ++ for (u_int32_t location = location_start; ++ location <= location_start + kRASearchWords * 4; ++ location += 4) { ++ u_int32_t eip; ++ if (!memory_->GetMemoryAtAddress(location, &eip)) ++ break; ++ ++ if (modules_ && modules_->GetModuleForAddress(eip) && ++ InstructionAddressSeemsValid(eip)) { ++ ++ eip_found = eip; ++ location_found = location; ++ return true; ++ } ++ } ++ // nothing found ++ return false; ++} + + } // namespace google_breakpad +diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.h b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.h +--- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.h ++++ b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.h +@@ -65,16 +65,29 @@ class StackwalkerX86 : public Stackwalke + // Implementation of Stackwalker, using x86 context (%ebp, %esp, %eip) and + // stack conventions (saved %ebp at [%ebp], saved %eip at 4[%ebp], or + // alternate conventions as guided by stack_frame_info_). + virtual StackFrame* GetContextFrame(); + virtual StackFrame* GetCallerFrame( + const CallStack *stack, + const vector< linked_ptr > &stack_frame_info); + ++ // Scan the stack starting at location_start, looking for an address ++ // that looks like a valid instruction pointer. Addresses must ++ // 1) be contained in the current stack memory ++ // 2) pass the checks in Stackwalker::InstructionAddressSeemsValid ++ // ++ // Returns true if a valid-looking instruction pointer was found. ++ // When returning true, sets location_found to the address at which ++ // the value was found, and eip_found to the value contained at that ++ // location in memory. ++ bool ScanForReturnAddress(u_int32_t location_start, ++ u_int32_t &location_found, ++ u_int32_t &eip_found); ++ + // Stores the CPU context corresponding to the innermost stack frame to + // be returned by GetContextFrame. + const MDRawContextX86 *context_; + }; + + + } // namespace google_breakpad + +diff --git a/toolkit/crashreporter/google-breakpad/src/processor/testdata/linux_test_app.cc b/toolkit/crashreporter/google-breakpad/src/processor/testdata/linux_test_app.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/processor/testdata/linux_test_app.cc +@@ -0,0 +1,81 @@ ++// Copyright (c) 2009, 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. ++ ++// Breakpad test application for Linux. When run, it generates one on-demand ++// minidump and then crashes, which should generate an on-crash minidump. ++// dump_syms can be used to extract symbol information for use in processing. ++ ++// To build: ++// g++ -g -o linux_test_app -I ../../ -L../../client/linux linux_test_app.cc \ ++// -lbreakpad ++// Add -m32 to build a 32-bit executable, or -m64 for a 64-bit one ++// (assuming your environment supports it). Replace -g with -gstabs+ to ++// generate an executable with STABS symbols (needs -m32), or -gdwarf-2 for one ++// with DWARF symbols (32- or 64-bit) ++ ++#include ++#include ++#include ++#include ++ ++#include "common/linux/linux_syscall_support.h" ++#include "client/linux/handler/exception_handler.h" ++ ++namespace { ++ ++// google_breakpad::MinidumpCallback to invoke after minidump generation. ++static bool callback(const char *dump_path, const char *id, ++ void *context, ++ bool succeeded) { ++ if (succeeded) { ++ printf("dump guid is %s\n", id); ++ } else { ++ printf("dump failed\n"); ++ } ++ fflush(stdout); ++ ++ return succeeded; ++} ++ ++static void CrashFunction() { ++ int *i = reinterpret_cast(0x45); ++ *i = 5; // crash! ++} ++ ++} // namespace ++ ++int main(int argc, char **argv) { ++ google_breakpad::ExceptionHandler eh(".", NULL, callback, NULL, true); ++ if (!eh.WriteMinidump()) { ++ printf("Failed to generate on-demand minidump\n"); ++ } ++ CrashFunction(); ++ printf("did not crash?\n"); ++ return 0; ++} +diff --git a/toolkit/crashreporter/google-breakpad/src/processor/testdata/minidump2.stackwalk.out b/toolkit/crashreporter/google-breakpad/src/processor/testdata/minidump2.stackwalk.out +--- a/toolkit/crashreporter/google-breakpad/src/processor/testdata/minidump2.stackwalk.out ++++ b/toolkit/crashreporter/google-breakpad/src/processor/testdata/minidump2.stackwalk.out +@@ -7,22 +7,26 @@ CPU: x86 + Crash reason: EXCEPTION_ACCESS_VIOLATION + Crash address: 0x45 + + Thread 0 (crashed) + 0 test_app.exe!`anonymous namespace'::CrashFunction [test_app.cc : 58 + 0x3] + eip = 0x0040429e esp = 0x0012fe84 ebp = 0x0012fe88 ebx = 0x7c80abc1 + esi = 0x00000002 edi = 0x00000a28 eax = 0x00000045 ecx = 0x0012fe94 + edx = 0x0042bc58 efl = 0x00010246 ++ Found by: given as instruction pointer in context + 1 test_app.exe!main [test_app.cc : 65 + 0x4] + eip = 0x00404200 esp = 0x0012fe90 ebp = 0x0012ff70 ++ Found by: call frame info + 2 test_app.exe!__tmainCRTStartup [crt0.c : 327 + 0x11] + eip = 0x004053ec esp = 0x0012ff78 ebp = 0x0012ffc0 ++ Found by: call frame info + 3 kernel32.dll!BaseProcessStart + 0x22 + eip = 0x7c816fd7 esp = 0x0012ffc8 ebp = 0x0012fff0 ++ Found by: call frame info + + Loaded modules: + 0x00400000 - 0x0042cfff test_app.exe ??? (main) + 0x59a60000 - 0x59b00fff dbghelp.dll 5.1.2600.2180 + 0x76390000 - 0x763acfff imm32.dll 5.1.2600.2180 + 0x76bf0000 - 0x76bfafff psapi.dll 5.1.2600.2180 + 0x774e0000 - 0x7761cfff ole32.dll 5.1.2600.2726 + 0x77c00000 - 0x77c07fff version.dll 5.1.2600.2180 +diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/linux/include/gflags/gflags.h b/toolkit/crashreporter/google-breakpad/src/third_party/linux/include/gflags/gflags.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/third_party/linux/include/gflags/gflags.h +@@ -0,0 +1,533 @@ ++// 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. ++ ++// --- ++// Author: Ray Sidney ++// Revamped and reorganized by Craig Silverstein ++// ++// This is the file that should be included by any file which declares ++// or defines a command line flag or wants to parse command line flags ++// or print a program usage message (which will include information about ++// flags). Executive summary, in the form of an example foo.cc file: ++// ++// #include "foo.h" // foo.h has a line "DECLARE_int32(start);" ++// ++// DEFINE_int32(end, 1000, "The last record to read"); ++// DECLARE_bool(verbose); // some other file has a DEFINE_bool(verbose, ...) ++// ++// void MyFunc() { ++// if (FLAGS_verbose) printf("Records %d-%d\n", FLAGS_start, FLAGS_end); ++// } ++// ++// Then, at the command-line: ++// ./foo --noverbose --start=5 --end=100 ++// ++// For more details, see ++// doc/gflags.html ++// ++// --- A note about thread-safety: ++// ++// We describe many functions in this routine as being thread-hostile, ++// thread-compatible, or thread-safe. Here are the meanings we use: ++// ++// thread-safe: it is safe for multiple threads to call this routine ++// (or, when referring to a class, methods of this class) ++// concurrently. ++// thread-hostile: it is not safe for multiple threads to call this ++// routine (or methods of this class) concurrently. In gflags, ++// most thread-hostile routines are intended to be called early in, ++// or even before, main() -- that is, before threads are spawned. ++// thread-compatible: it is safe for multiple threads to read from ++// this variable (when applied to variables), or to call const ++// methods of this class (when applied to classes), as long as no ++// other thread is writing to the variable or calling non-const ++// methods of this class. ++ ++#ifndef GOOGLE_GFLAGS_H_ ++#define GOOGLE_GFLAGS_H_ ++ ++#include ++#include ++ ++// We care a lot about number of bits things take up. Unfortunately, ++// systems define their bit-specific ints in a lot of different ways. ++// We use our own way, and have a typedef to get there. ++// Note: these commands below may look like "#if 1" or "#if 0", but ++// that's because they were constructed that way at ./configure time. ++// Look at gflags.h.in to see how they're calculated (based on your config). ++#if 1 ++#include // the normal place uint16_t is defined ++#endif ++#if 1 ++#include // the normal place u_int16_t is defined ++#endif ++#if 1 ++#include // a third place for uint16_t or u_int16_t ++#endif ++ ++namespace google { ++ ++#if 1 // the C99 format ++typedef int32_t int32; ++typedef uint32_t uint32; ++typedef int64_t int64; ++typedef uint64_t uint64; ++#elif 1 // the BSD format ++typedef int32_t int32; ++typedef u_int32_t uint32; ++typedef int64_t int64; ++typedef u_int64_t uint64; ++#elif 0 // the windows (vc7) format ++typedef __int32 int32; ++typedef unsigned __int32 uint32; ++typedef __int64 int64; ++typedef unsigned __int64 uint64; ++#else ++#error Do not know how to define a 32-bit integer quantity on your system ++#endif ++ ++// -------------------------------------------------------------------- ++// To actually define a flag in a file, use DEFINE_bool, ++// DEFINE_string, etc. at the bottom of this file. You may also find ++// it useful to register a validator with the flag. This ensures that ++// when the flag is parsed from the commandline, or is later set via ++// SetCommandLineOption, we call the validation function. ++// ++// The validation function should return true if the flag value is valid, and ++// false otherwise. If the function returns false for the new setting of the ++// flag, the flag will retain its current value. If it returns false for the ++// default value, InitGoogle will die. ++// ++// This function is safe to call at global construct time (as in the ++// example below). ++// ++// Example use: ++// static bool ValidatePort(const char* flagname, int32 value) { ++// if (value > 0 && value < 32768) // value is ok ++// return true; ++// printf("Invalid value for --%s: %d\n", flagname, (int)value); ++// return false; ++// } ++// DEFINE_int32(port, 0, "What port to listen on"); ++// static bool dummy = RegisterFlagValidator(&FLAGS_port, &ValidatePort); ++ ++// Returns true if successfully registered, false if not (because the ++// first argument doesn't point to a command-line flag, or because a ++// validator is already registered for this flag). ++bool RegisterFlagValidator(const bool* flag, ++ bool (*validate_fn)(const char*, bool)); ++bool RegisterFlagValidator(const int32* flag, ++ bool (*validate_fn)(const char*, int32)); ++bool RegisterFlagValidator(const int64* flag, ++ bool (*validate_fn)(const char*, int64)); ++bool RegisterFlagValidator(const uint64* flag, ++ bool (*validate_fn)(const char*, uint64)); ++bool RegisterFlagValidator(const double* flag, ++ bool (*validate_fn)(const char*, double)); ++bool RegisterFlagValidator(const std::string* flag, ++ bool (*validate_fn)(const char*, const std::string&)); ++ ++ ++// -------------------------------------------------------------------- ++// These methods are the best way to get access to info about the ++// list of commandline flags. Note that these routines are pretty slow. ++// GetAllFlags: mostly-complete info about the list, sorted by file. ++// ShowUsageWithFlags: pretty-prints the list to stdout (what --help does) ++// ShowUsageWithFlagsRestrict: limit to filenames with restrict as a substr ++// ++// In addition to accessing flags, you can also access argv[0] (the program ++// name) and argv (the entire commandline), which we sock away a copy of. ++// These variables are static, so you should only set them once. ++ ++struct CommandLineFlagInfo { ++ std::string name; // the name of the flag ++ std::string type; // the type of the flag: int32, etc ++ std::string description; // the "help text" associated with the flag ++ std::string current_value; // the current value, as a string ++ std::string default_value; // the default value, as a string ++ std::string filename; // 'cleaned' version of filename holding the flag ++ bool has_validator_fn; // true if RegisterFlagValidator called on flag ++ bool is_default; // true if the flag has default value ++}; ++ ++extern void GetAllFlags(std::vector* OUTPUT); ++// These two are actually defined in commandlineflags_reporting.cc. ++extern void ShowUsageWithFlags(const char *argv0); // what --help does ++extern void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict); ++ ++// Create a descriptive string for a flag. ++// Goes to some trouble to make pretty line breaks. ++extern std::string DescribeOneFlag(const CommandLineFlagInfo& flag); ++ ++// Thread-hostile; meant to be called before any threads are spawned. ++extern void SetArgv(int argc, const char** argv); ++// The following functions are thread-safe as long as SetArgv() is ++// only called before any threads start. ++extern const std::vector& GetArgvs(); // all of argv as a vector ++extern const char* GetArgv(); // all of argv as a string ++extern const char* GetArgv0(); // only argv0 ++extern uint32 GetArgvSum(); // simple checksum of argv ++extern const char* ProgramInvocationName(); // argv0, or "UNKNOWN" if not set ++extern const char* ProgramInvocationShortName(); // basename(argv0) ++// ProgramUsage() is thread-safe as long as SetUsageMessage() is only ++// called before any threads start. ++extern const char* ProgramUsage(); // string set by SetUsageMessage() ++ ++ ++// -------------------------------------------------------------------- ++// Normally you access commandline flags by just saying "if (FLAGS_foo)" ++// or whatever, and set them by calling "FLAGS_foo = bar" (or, more ++// commonly, via the DEFINE_foo macro). But if you need a bit more ++// control, we have programmatic ways to get/set the flags as well. ++// These programmatic ways to access flags are thread-safe, but direct ++// access is only thread-compatible. ++ ++// Return true iff the flagname was found. ++// OUTPUT is set to the flag's value, or unchanged if we return false. ++extern bool GetCommandLineOption(const char* name, std::string* OUTPUT); ++ ++// Return true iff the flagname was found. OUTPUT is set to the flag's ++// CommandLineFlagInfo or unchanged if we return false. ++extern bool GetCommandLineFlagInfo(const char* name, ++ CommandLineFlagInfo* OUTPUT); ++ ++// Return the CommandLineFlagInfo of the flagname. exit() if name not found. ++// Example usage, to check if a flag's value is currently the default value: ++// if (GetCommandLineFlagInfoOrDie("foo").is_default) ... ++extern CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name); ++ ++enum FlagSettingMode { ++ // update the flag's value (can call this multiple times). ++ SET_FLAGS_VALUE, ++ // update the flag's value, but *only if* it has not yet been updated ++ // with SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef". ++ SET_FLAG_IF_DEFAULT, ++ // set the flag's default value to this. If the flag has not yet updated ++ // yet (via SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef") ++ // change the flag's current value to the new default value as well. ++ SET_FLAGS_DEFAULT ++}; ++ ++// Set a particular flag ("command line option"). Returns a string ++// describing the new value that the option has been set to. The ++// return value API is not well-specified, so basically just depend on ++// it to be empty if the setting failed for some reason -- the name is ++// not a valid flag name, or the value is not a valid value -- and ++// non-empty else. ++ ++// SetCommandLineOption uses set_mode == SET_FLAGS_VALUE (the common case) ++extern std::string SetCommandLineOption(const char* name, const char* value); ++extern std::string SetCommandLineOptionWithMode(const char* name, const char* value, ++ FlagSettingMode set_mode); ++ ++ ++// -------------------------------------------------------------------- ++// Saves the states (value, default value, whether the user has set ++// the flag, registered validators, etc) of all flags, and restores ++// them when the FlagSaver is destroyed. This is very useful in ++// tests, say, when you want to let your tests change the flags, but ++// make sure that they get reverted to the original states when your ++// test is complete. ++// ++// Example usage: ++// void TestFoo() { ++// FlagSaver s1; ++// FLAG_foo = false; ++// FLAG_bar = "some value"; ++// ++// // test happens here. You can return at any time ++// // without worrying about restoring the FLAG values. ++// } ++// ++// Note: This class is marked with __attribute__((unused)) because all the ++// work is done in the constructor and destructor, so in the standard ++// usage example above, the compiler would complain that it's an ++// unused variable. ++// ++// This class is thread-safe. ++ ++class FlagSaver { ++ public: ++ FlagSaver(); ++ ~FlagSaver(); ++ ++ private: ++ class FlagSaverImpl* impl_; // we use pimpl here to keep API steady ++ ++ FlagSaver(const FlagSaver&); // no copying! ++ void operator=(const FlagSaver&); ++} __attribute__ ((unused)); ++ ++// -------------------------------------------------------------------- ++// Some deprecated or hopefully-soon-to-be-deprecated functions. ++ ++// This is often used for logging. TODO(csilvers): figure out a better way ++extern std::string CommandlineFlagsIntoString(); ++// Usually where this is used, a FlagSaver should be used instead. ++extern bool ReadFlagsFromString(const std::string& flagfilecontents, ++ const char* prog_name, ++ bool errors_are_fatal); // uses SET_FLAGS_VALUE ++ ++// These let you manually implement --flagfile functionality. ++// DEPRECATED. ++extern bool AppendFlagsIntoFile(const std::string& filename, const char* prog_name); ++extern bool SaveCommandFlags(); // actually defined in google.cc ! ++extern bool ReadFromFlagsFile(const std::string& filename, const char* prog_name, ++ bool errors_are_fatal); // uses SET_FLAGS_VALUE ++ ++ ++// -------------------------------------------------------------------- ++// Useful routines for initializing flags from the environment. ++// In each case, if 'varname' does not exist in the environment ++// return defval. If 'varname' does exist but is not valid ++// (e.g., not a number for an int32 flag), abort with an error. ++// Otherwise, return the value. NOTE: for booleans, for true use ++// 't' or 'T' or 'true' or '1', for false 'f' or 'F' or 'false' or '0'. ++ ++extern bool BoolFromEnv(const char *varname, bool defval); ++extern int32 Int32FromEnv(const char *varname, int32 defval); ++extern int64 Int64FromEnv(const char *varname, int64 defval); ++extern uint64 Uint64FromEnv(const char *varname, uint64 defval); ++extern double DoubleFromEnv(const char *varname, double defval); ++extern const char *StringFromEnv(const char *varname, const char *defval); ++ ++ ++// -------------------------------------------------------------------- ++// The next two functions parse commandlineflags from main(): ++ ++// Set the "usage" message for this program. For example: ++// string usage("This program does nothing. Sample usage:\n"); ++// usage += argv[0] + " "; ++// SetUsageMessage(usage); ++// Do not include commandline flags in the usage: we do that for you! ++// Thread-hostile; meant to be called before any threads are spawned. ++extern void SetUsageMessage(const std::string& usage); ++ ++// Looks for flags in argv and parses them. Rearranges argv to put ++// flags first, or removes them entirely if remove_flags is true. ++// If a flag is defined more than once in the command line or flag ++// file, the last definition is used. ++// See top-of-file for more details on this function. ++#ifndef SWIG // In swig, use ParseCommandLineFlagsScript() instead. ++extern uint32 ParseCommandLineFlags(int *argc, char*** argv, ++ bool remove_flags); ++#endif ++ ++ ++// Calls to ParseCommandLineNonHelpFlags and then to ++// HandleCommandLineHelpFlags can be used instead of a call to ++// ParseCommandLineFlags during initialization, in order to allow for ++// changing default values for some FLAGS (via ++// e.g. SetCommandLineOptionWithMode calls) between the time of ++// command line parsing and the time of dumping help information for ++// the flags as a result of command line parsing. ++// If a flag is defined more than once in the command line or flag ++// file, the last definition is used. ++extern uint32 ParseCommandLineNonHelpFlags(int *argc, char*** argv, ++ bool remove_flags); ++// This is actually defined in commandlineflags_reporting.cc. ++// This function is misnamed (it also handles --version, etc.), but ++// it's too late to change that now. :-( ++extern void HandleCommandLineHelpFlags(); // in commandlineflags_reporting.cc ++ ++// Allow command line reparsing. Disables the error normally ++// generated when an unknown flag is found, since it may be found in a ++// later parse. Thread-hostile; meant to be called before any threads ++// are spawned. ++extern void AllowCommandLineReparsing(); ++ ++// Reparse the flags that have not yet been recognized. ++// Only flags registered since the last parse will be recognized. ++// Any flag value must be provided as part of the argument using "=", ++// not as a separate command line argument that follows the flag argument. ++// Intended for handling flags from dynamically loaded libraries, ++// since their flags are not registered until they are loaded. ++extern uint32 ReparseCommandLineNonHelpFlags(); ++ ++ ++// -------------------------------------------------------------------- ++// Now come the command line flag declaration/definition macros that ++// will actually be used. They're kind of hairy. A major reason ++// for this is initialization: we want people to be able to access ++// variables in global constructors and have that not crash, even if ++// their global constructor runs before the global constructor here. ++// (Obviously, we can't guarantee the flags will have the correct ++// default value in that case, but at least accessing them is safe.) ++// The only way to do that is have flags point to a static buffer. ++// So we make one, using a union to ensure proper alignment, and ++// then use placement-new to actually set up the flag with the ++// correct default value. In the same vein, we have to worry about ++// flag access in global destructors, so FlagRegisterer has to be ++// careful never to destroy the flag-values it constructs. ++// ++// Note that when we define a flag variable FLAGS_, we also ++// preemptively define a junk variable, FLAGS_no. This is to ++// cause a link-time error if someone tries to define 2 flags with ++// names like "logging" and "nologging". We do this because a bool ++// flag FLAG can be set from the command line to true with a "-FLAG" ++// argument, and to false with a "-noFLAG" argument, and so this can ++// potentially avert confusion. ++// ++// We also put flags into their own namespace. It is purposefully ++// named in an opaque way that people should have trouble typing ++// directly. The idea is that DEFINE puts the flag in the weird ++// namespace, and DECLARE imports the flag from there into the current ++// namespace. The net result is to force people to use DECLARE to get ++// access to a flag, rather than saying "extern bool FLAGS_whatever;" ++// or some such instead. We want this so we can put extra ++// functionality (like sanity-checking) in DECLARE if we want, and ++// make sure it is picked up everywhere. ++// ++// We also put the type of the variable in the namespace, so that ++// people can't DECLARE_int32 something that they DEFINE_bool'd ++// elsewhere. ++ ++class FlagRegisterer { ++ public: ++ FlagRegisterer(const char* name, const char* type, ++ const char* help, const char* filename, ++ void* current_storage, void* defvalue_storage); ++}; ++ ++extern bool FlagsTypeWarn(const char *name); ++ ++// If your application #defines STRIP_FLAG_HELP to a non-zero value ++// before #including this file, we remove the help message from the ++// binary file. This can reduce the size of the resulting binary ++// somewhat, and may also be useful for security reasons. ++ ++extern const char kStrippedFlagHelp[]; ++ ++} ++ ++#ifndef SWIG // In swig, ignore the main flag declarations ++ ++#if defined(STRIP_FLAG_HELP) && STRIP_FLAG_HELP > 0 ++// Need this construct to avoid the 'defined but not used' warning. ++#define MAYBE_STRIPPED_HELP(txt) (false ? (txt) : kStrippedFlagHelp) ++#else ++#define MAYBE_STRIPPED_HELP(txt) txt ++#endif ++ ++// Each command-line flag has two variables associated with it: one ++// with the current value, and one with the default value. However, ++// we have a third variable, which is where value is assigned; it's a ++// constant. This guarantees that FLAG_##value is initialized at ++// static initialization time (e.g. before program-start) rather than ++// than global construction time (which is after program-start but ++// before main), at least when 'value' is a compile-time constant. We ++// use a small trick for the "default value" variable, and call it ++// FLAGS_no. This serves the second purpose of assuring a ++// compile error if someone tries to define a flag named no ++// which is illegal (--foo and --nofoo both affect the "foo" flag). ++#define DEFINE_VARIABLE(type, shorttype, name, value, help) \ ++ namespace fL##shorttype { \ ++ static const type FLAGS_nono##name = value; \ ++ type FLAGS_##name = FLAGS_nono##name; \ ++ type FLAGS_no##name = FLAGS_nono##name; \ ++ static ::google::FlagRegisterer o_##name( \ ++ #name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \ ++ &FLAGS_##name, &FLAGS_no##name); \ ++ } \ ++ using fL##shorttype::FLAGS_##name ++ ++#define DECLARE_VARIABLE(type, shorttype, name) \ ++ namespace fL##shorttype { \ ++ extern type FLAGS_##name; \ ++ } \ ++ using fL##shorttype::FLAGS_##name ++ ++// For DEFINE_bool, we want to do the extra check that the passed-in ++// value is actually a bool, and not a string or something that can be ++// coerced to a bool. These declarations (no definition needed!) will ++// help us do that, and never evaluate From, which is important. ++// We'll use 'sizeof(IsBool(val))' to distinguish. This code requires ++// that the compiler have different sizes for bool & double. Since ++// this is not guaranteed by the standard, we check it with a ++// compile-time assert (msg[-1] will give a compile-time error). ++namespace fLB { ++struct CompileAssert {}; ++typedef CompileAssert expected_sizeof_double_neq_sizeof_bool[ ++ (sizeof(double) != sizeof(bool)) ? 1 : -1]; ++template double IsBoolFlag(const From& from); ++bool IsBoolFlag(bool from); ++} // namespace fLB ++ ++#define DECLARE_bool(name) DECLARE_VARIABLE(bool,B, name) ++#define DEFINE_bool(name,val,txt) \ ++ namespace fLB { \ ++ typedef CompileAssert FLAG_##name##_value_is_not_a_bool[ \ ++ (sizeof(::fLB::IsBoolFlag(val)) != sizeof(double)) ? 1 : -1]; \ ++ } \ ++ DEFINE_VARIABLE(bool,B, name, val, txt) ++ ++#define DECLARE_int32(name) DECLARE_VARIABLE(::google::int32,I, name) ++#define DEFINE_int32(name,val,txt) DEFINE_VARIABLE(::google::int32,I, name, val, txt) ++ ++#define DECLARE_int64(name) DECLARE_VARIABLE(::google::int64,I64, name) ++#define DEFINE_int64(name,val,txt) DEFINE_VARIABLE(::google::int64,I64, name, val, txt) ++ ++#define DECLARE_uint64(name) DECLARE_VARIABLE(::google::uint64,U64, name) ++#define DEFINE_uint64(name,val,txt) DEFINE_VARIABLE(::google::uint64,U64, name, val, txt) ++ ++#define DECLARE_double(name) DECLARE_VARIABLE(double,D, name) ++#define DEFINE_double(name,val,txt) DEFINE_VARIABLE(double,D, name, val, txt) ++ ++// Strings are trickier, because they're not a POD, so we can't ++// construct them at static-initialization time (instead they get ++// constructed at global-constructor time, which is much later). To ++// try to avoid crashes in that case, we use a char buffer to store ++// the string, which we can static-initialize, and then placement-new ++// into it later. It's not perfect, but the best we can do. ++#define DECLARE_string(name) namespace fLS { extern std::string& FLAGS_##name; } \ ++ using fLS::FLAGS_##name ++ ++// We need to define a var named FLAGS_no##name so people don't define ++// --string and --nostring. And we need a temporary place to put val ++// so we don't have to evaluate it twice. Two great needs that go ++// great together! ++// The weird 'using' + 'extern' inside the fLS namespace is to work around ++// an unknown compiler bug/issue with the gcc 4.2.1 on SUSE 10. See ++// http://code.google.com/p/google-gflags/issues/detail?id=20 ++#define DEFINE_string(name, val, txt) \ ++ namespace fLS { \ ++ static union { void* align; char s[sizeof(std::string)]; } s_##name[2]; \ ++ const std::string* const FLAGS_no##name = new (s_##name[0].s) std::string(val); \ ++ static ::google::FlagRegisterer o_##name( \ ++ #name, "string", MAYBE_STRIPPED_HELP(txt), __FILE__, \ ++ s_##name[0].s, new (s_##name[1].s) std::string(*FLAGS_no##name)); \ ++ extern std::string& FLAGS_##name; \ ++ using fLS::FLAGS_##name; \ ++ std::string& FLAGS_##name = *(reinterpret_cast(s_##name[0].s)); \ ++ } \ ++ using fLS::FLAGS_##name ++ ++#endif // SWIG ++ ++#endif // GOOGLE_GFLAGS_H_ +diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/linux/include/gflags/gflags_completions.h b/toolkit/crashreporter/google-breakpad/src/third_party/linux/include/gflags/gflags_completions.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/third_party/linux/include/gflags/gflags_completions.h +@@ -0,0 +1,121 @@ ++// Copyright (c) 2008, 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. ++// ++// --- ++// Author: Dave Nicponski ++// ++// Implement helpful bash-style command line flag completions ++// ++// ** Functional API: ++// HandleCommandLineCompletions() should be called early during ++// program startup, but after command line flag code has been ++// initialized, such as the beginning of HandleCommandLineHelpFlags(). ++// It checks the value of the flag --tab_completion_word. If this ++// flag is empty, nothing happens here. If it contains a string, ++// however, then HandleCommandLineCompletions() will hijack the ++// process, attempting to identify the intention behind this ++// completion. Regardless of the outcome of this deduction, the ++// process will be terminated, similar to --helpshort flag ++// handling. ++// ++// ** Overview of Bash completions: ++// Bash can be told to programatically determine completions for the ++// current 'cursor word'. It does this by (in this case) invoking a ++// command with some additional arguments identifying the command ++// being executed, the word being completed, and the previous word ++// (if any). Bash then expects a sequence of output lines to be ++// printed to stdout. If these lines all contain a common prefix ++// longer than the cursor word, bash will replace the cursor word ++// with that common prefix, and display nothing. If there isn't such ++// a common prefix, bash will display the lines in pages using 'more'. ++// ++// ** Strategy taken for command line completions: ++// If we can deduce either the exact flag intended, or a common flag ++// prefix, we'll output exactly that. Otherwise, if information ++// must be displayed to the user, we'll take the opportunity to add ++// some helpful information beyond just the flag name (specifically, ++// we'll include the default flag value and as much of the flag's ++// description as can fit on a single terminal line width, as specified ++// by the flag --tab_completion_columns). Furthermore, we'll try to ++// make bash order the output such that the most useful or relevent ++// flags are the most likely to be shown at the top. ++// ++// ** Additional features: ++// To assist in finding that one really useful flag, substring matching ++// was implemented. Before pressing a to get completion for the ++// current word, you can append one or more '?' to the flag to do ++// substring matching. Here's the semantics: ++// --foo Show me all flags with names prefixed by 'foo' ++// --foo? Show me all flags with 'foo' somewhere in the name ++// --foo?? Same as prior case, but also search in module ++// definition path for 'foo' ++// --foo??? Same as prior case, but also search in flag ++// descriptions for 'foo' ++// Finally, we'll trim the output to a relatively small number of ++// flags to keep bash quiet about the verbosity of output. If one ++// really wanted to see all possible matches, appending a '+' to the ++// search word will force the exhaustive list of matches to be printed. ++// ++// ** How to have bash accept completions from a binary: ++// Bash requires that it be informed about each command that programmatic ++// completion should be enabled for. Example addition to a .bashrc ++// file would be (your path to gflags_completions.sh file may differ): ++ ++/* ++$ complete -o bashdefault -o default -o nospace -C \ ++ '/usr/local/bin/gflags_completions.sh --tab_completion_columns $COLUMNS' \ ++ time env binary_name another_binary [...] ++*/ ++ ++// This would allow the following to work: ++// $ /path/to/binary_name --vmodule ++// Or: ++// $ ./bin/path/another_binary --gfs_u ++// (etc) ++// ++// Sadly, it appears that bash gives no easy way to force this behavior for ++// all commands. That's where the "time" in the above example comes in. ++// If you haven't specifically added a command to the list of completion ++// supported commands, you can still get completions by prefixing the ++// entire command with "env". ++// $ env /some/brand/new/binary --vmod ++// Assuming that "binary" is a newly compiled binary, this should still ++// produce the expected completion output. ++ ++ ++#ifndef GOOGLE_GFLAGS_COMPLETIONS_H_ ++#define GOOGLE_GFLAGS_COMPLETIONS_H_ ++ ++namespace google { ++ ++void HandleCommandLineCompletions(void); ++ ++} ++ ++#endif // GOOGLE_GFLAGS_COMPLETIONS_H_ +diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/log_severity.h b/toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/log_severity.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/log_severity.h +@@ -0,0 +1,84 @@ ++// Copyright (c) 2007, 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 BASE_LOG_SEVERITY_H__ ++#define BASE_LOG_SEVERITY_H__ ++ ++// Annoying stuff for windows -- makes sure clients can import these functions ++#ifndef GOOGLE_GLOG_DLL_DECL ++# if defined(_WIN32) && !defined(__CYGWIN__) ++# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport) ++# else ++# define GOOGLE_GLOG_DLL_DECL ++# endif ++#endif ++ ++// Variables of type LogSeverity are widely taken to lie in the range ++// [0, NUM_SEVERITIES-1]. Be careful to preserve this assumption if ++// you ever need to change their values or add a new severity. ++typedef int LogSeverity; ++ ++const int INFO = 0, WARNING = 1, ERROR = 2, FATAL = 3, NUM_SEVERITIES = 4; ++ ++// DFATAL is FATAL in debug mode, ERROR in normal mode ++#ifdef NDEBUG ++#define DFATAL_LEVEL ERROR ++#else ++#define DFATAL_LEVEL FATAL ++#endif ++ ++extern GOOGLE_GLOG_DLL_DECL const char* const LogSeverityNames[NUM_SEVERITIES]; ++ ++// NDEBUG usage helpers related to (RAW_)DCHECK: ++// ++// DEBUG_MODE is for small !NDEBUG uses like ++// if (DEBUG_MODE) foo.CheckThatFoo(); ++// instead of substantially more verbose ++// #ifndef NDEBUG ++// foo.CheckThatFoo(); ++// #endif ++// ++// IF_DEBUG_MODE is for small !NDEBUG uses like ++// IF_DEBUG_MODE( string error; ) ++// DCHECK(Foo(&error)) << error; ++// instead of substantially more verbose ++// #ifndef NDEBUG ++// string error; ++// DCHECK(Foo(&error)) << error; ++// #endif ++// ++#ifdef NDEBUG ++enum { DEBUG_MODE = 0 }; ++#define IF_DEBUG_MODE(x) ++#else ++enum { DEBUG_MODE = 1 }; ++#define IF_DEBUG_MODE(x) x ++#endif ++ ++#endif // BASE_LOG_SEVERITY_H__ +diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/logging.h b/toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/logging.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/logging.h +@@ -0,0 +1,1499 @@ ++// Copyright (c) 1999, 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. ++// ++// Author: Ray Sidney ++// ++// This file contains #include information about logging-related stuff. ++// Pretty much everybody needs to #include this file so that they can ++// log various happenings. ++// ++#ifndef _LOGGING_H_ ++#define _LOGGING_H_ ++ ++#include ++#include ++#include ++#include ++#if 1 ++# include ++#endif ++#ifdef __DEPRECATED ++// Make GCC quiet. ++# undef __DEPRECATED ++# include ++# define __DEPRECATED ++#else ++# include ++#endif ++#include ++ ++// Annoying stuff for windows -- makes sure clients can import these functions ++#ifndef GOOGLE_GLOG_DLL_DECL ++# if defined(_WIN32) && !defined(__CYGWIN__) ++# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport) ++# else ++# define GOOGLE_GLOG_DLL_DECL ++# endif ++#endif ++ ++// We care a lot about number of bits things take up. Unfortunately, ++// systems define their bit-specific ints in a lot of different ways. ++// We use our own way, and have a typedef to get there. ++// Note: these commands below may look like "#if 1" or "#if 0", but ++// that's because they were constructed that way at ./configure time. ++// Look at logging.h.in to see how they're calculated (based on your config). ++#if 1 ++#include // the normal place uint16_t is defined ++#endif ++#if 1 ++#include // the normal place u_int16_t is defined ++#endif ++#if 1 ++#include // a third place for uint16_t or u_int16_t ++#endif ++ ++#if 0 ++#include ++#endif ++ ++namespace google { ++ ++#if 1 // the C99 format ++typedef int32_t int32; ++typedef uint32_t uint32; ++typedef int64_t int64; ++typedef uint64_t uint64; ++#elif 1 // the BSD format ++typedef int32_t int32; ++typedef u_int32_t uint32; ++typedef int64_t int64; ++typedef u_int64_t uint64; ++#elif 0 // the windows (vc7) format ++typedef __int32 int32; ++typedef unsigned __int32 uint32; ++typedef __int64 int64; ++typedef unsigned __int64 uint64; ++#else ++#error Do not know how to define a 32-bit integer quantity on your system ++#endif ++ ++} ++ ++// The global value of GOOGLE_STRIP_LOG. All the messages logged to ++// LOG(XXX) with severity less than GOOGLE_STRIP_LOG will not be displayed. ++// If it can be determined at compile time that the message will not be ++// printed, the statement will be compiled out. ++// ++// Example: to strip out all INFO and WARNING messages, use the value ++// of 2 below. To make an exception for WARNING messages from a single ++// file, add "#define GOOGLE_STRIP_LOG 1" to that file _before_ including ++// base/logging.h ++#ifndef GOOGLE_STRIP_LOG ++#define GOOGLE_STRIP_LOG 0 ++#endif ++ ++// GCC can be told that a certain branch is not likely to be taken (for ++// instance, a CHECK failure), and use that information in static analysis. ++// Giving it this information can help it optimize for the common case in ++// the absence of better information (ie. -fprofile-arcs). ++// ++#ifndef GOOGLE_PREDICT_BRANCH_NOT_TAKEN ++#if 1 ++#define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) (__builtin_expect(x, 0)) ++#else ++#define GOOGLE_PREDICT_BRANCH_NOT_TAKEN(x) x ++#endif ++#endif ++ ++// Make a bunch of macros for logging. The way to log things is to stream ++// things to LOG(). E.g., ++// ++// LOG(INFO) << "Found " << num_cookies << " cookies"; ++// ++// You can capture log messages in a string, rather than reporting them ++// immediately: ++// ++// vector errors; ++// LOG_STRING(ERROR, &errors) << "Couldn't parse cookie #" << cookie_num; ++// ++// This pushes back the new error onto 'errors'; if given a NULL pointer, ++// it reports the error via LOG(ERROR). ++// ++// You can also do conditional logging: ++// ++// LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies"; ++// ++// You can also do occasional logging (log every n'th occurrence of an ++// event): ++// ++// LOG_EVERY_N(INFO, 10) << "Got the " << COUNTER << "th cookie"; ++// ++// The above will cause log messages to be output on the 1st, 11th, 21st, ... ++// times it is executed. Note that the special COUNTER value is used to ++// identify which repetition is happening. ++// ++// You can also do occasional conditional logging (log every n'th ++// occurrence of an event, when condition is satisfied): ++// ++// LOG_IF_EVERY_N(INFO, (size > 1024), 10) << "Got the " << COUNTER ++// << "th big cookie"; ++// ++// You can log messages the first N times your code executes a line. E.g. ++// ++// LOG_FIRST_N(INFO, 20) << "Got the " << COUNTER << "th cookie"; ++// ++// Outputs log messages for the first 20 times it is executed. ++// ++// Analogous SYSLOG, SYSLOG_IF, and SYSLOG_EVERY_N macros are available. ++// These log to syslog as well as to the normal logs. If you use these at ++// all, you need to be aware that syslog can drastically reduce performance, ++// especially if it is configured for remote logging! Don't use these ++// unless you fully understand this and have a concrete need to use them. ++// Even then, try to minimize your use of them. ++// ++// There are also "debug mode" logging macros like the ones above: ++// ++// DLOG(INFO) << "Found cookies"; ++// ++// DLOG_IF(INFO, num_cookies > 10) << "Got lots of cookies"; ++// ++// DLOG_EVERY_N(INFO, 10) << "Got the " << COUNTER << "th cookie"; ++// ++// All "debug mode" logging is compiled away to nothing for non-debug mode ++// compiles. ++// ++// We also have ++// ++// LOG_ASSERT(assertion); ++// DLOG_ASSERT(assertion); ++// ++// which is syntactic sugar for {,D}LOG_IF(FATAL, assert fails) << assertion; ++// ++// There are "verbose level" logging macros. They look like ++// ++// VLOG(1) << "I'm printed when you run the program with --v=1 or more"; ++// VLOG(2) << "I'm printed when you run the program with --v=2 or more"; ++// ++// These always log at the INFO log level (when they log at all). ++// The verbose logging can also be turned on module-by-module. For instance, ++// --vmodule=mapreduce=2,file=1,gfs*=3 --v=0 ++// will cause: ++// a. VLOG(2) and lower messages to be printed from mapreduce.{h,cc} ++// b. VLOG(1) and lower messages to be printed from file.{h,cc} ++// c. VLOG(3) and lower messages to be printed from files prefixed with "gfs" ++// d. VLOG(0) and lower messages to be printed from elsewhere ++// ++// The wildcarding functionality shown by (c) supports both '*' (match ++// 0 or more characters) and '?' (match any single character) wildcards. ++// ++// There's also VLOG_IS_ON(n) "verbose level" condition macro. To be used as ++// ++// if (VLOG_IS_ON(2)) { ++// // do some logging preparation and logging ++// // that can't be accomplished with just VLOG(2) << ...; ++// } ++// ++// There are also VLOG_IF, VLOG_EVERY_N and VLOG_IF_EVERY_N "verbose level" ++// condition macros for sample cases, when some extra computation and ++// preparation for logs is not needed. ++// VLOG_IF(1, (size > 1024)) ++// << "I'm printed when size is more than 1024 and when you run the " ++// "program with --v=1 or more"; ++// VLOG_EVERY_N(1, 10) ++// << "I'm printed every 10th occurrence, and when you run the program " ++// "with --v=1 or more. Present occurence is " << COUNTER; ++// VLOG_IF_EVERY_N(1, (size > 1024), 10) ++// << "I'm printed on every 10th occurence of case when size is more " ++// " than 1024, when you run the program with --v=1 or more. "; ++// "Present occurence is " << COUNTER; ++// ++// The supported severity levels for macros that allow you to specify one ++// are (in increasing order of severity) INFO, WARNING, ERROR, and FATAL. ++// Note that messages of a given severity are logged not only in the ++// logfile for that severity, but also in all logfiles of lower severity. ++// E.g., a message of severity FATAL will be logged to the logfiles of ++// severity FATAL, ERROR, WARNING, and INFO. ++// ++// There is also the special severity of DFATAL, which logs FATAL in ++// debug mode, ERROR in normal mode. ++// ++// Very important: logging a message at the FATAL severity level causes ++// the program to terminate (after the message is logged). ++// ++// Unless otherwise specified, logs will be written to the filename ++// "...log..", followed ++// by the date, time, and pid (you can't prevent the date, time, and pid ++// from being in the filename). ++// ++// The logging code takes two flags: ++// --v=# set the verbose level ++// --logtostderr log all the messages to stderr instead of to logfiles ++ ++// LOG LINE PREFIX FORMAT ++// ++// Log lines have this form: ++// ++// Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg... ++// ++// where the fields are defined as follows: ++// ++// L A single character, representing the log level ++// (eg 'I' for INFO) ++// mm The month (zero padded; ie May is '05') ++// dd The day (zero padded) ++// hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds ++// threadid The space-padded thread ID as returned by GetTID() ++// (this matches the PID on Linux) ++// file The file name ++// line The line number ++// msg The user-supplied message ++// ++// Example: ++// ++// I1103 11:57:31.739339 24395 google.cc:2341] Command line: ./some_prog ++// I1103 11:57:31.739403 24395 google.cc:2342] Process id 24395 ++// ++// NOTE: although the microseconds are useful for comparing events on ++// a single machine, clocks on different machines may not be well ++// synchronized. Hence, use caution when comparing the low bits of ++// timestamps from different machines. ++ ++#ifndef DECLARE_VARIABLE ++#define MUST_UNDEF_GFLAGS_DECLARE_MACROS ++#define DECLARE_VARIABLE(type, name, tn) \ ++ namespace FLAG__namespace_do_not_use_directly_use_DECLARE_##tn##_instead { \ ++ extern GOOGLE_GLOG_DLL_DECL type FLAGS_##name; \ ++ } \ ++ using FLAG__namespace_do_not_use_directly_use_DECLARE_##tn##_instead::FLAGS_##name ++ ++// bool specialization ++#define DECLARE_bool(name) \ ++ DECLARE_VARIABLE(bool, name, bool) ++ ++// int32 specialization ++#define DECLARE_int32(name) \ ++ DECLARE_VARIABLE(google::int32, name, int32) ++ ++// Special case for string, because we have to specify the namespace ++// std::string, which doesn't play nicely with our FLAG__namespace hackery. ++#define DECLARE_string(name) \ ++ namespace FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead { \ ++ extern GOOGLE_GLOG_DLL_DECL std::string FLAGS_##name; \ ++ } \ ++ using FLAG__namespace_do_not_use_directly_use_DECLARE_string_instead::FLAGS_##name ++#endif ++ ++// Set whether log messages go to stderr instead of logfiles ++DECLARE_bool(logtostderr); ++ ++// Set whether log messages go to stderr in addition to logfiles. ++DECLARE_bool(alsologtostderr); ++ ++// Log messages at a level >= this flag are automatically sent to ++// stderr in addition to log files. ++DECLARE_int32(stderrthreshold); ++ ++// Set whether the log prefix should be prepended to each line of output. ++DECLARE_bool(log_prefix); ++ ++// Log messages at a level <= this flag are buffered. ++// Log messages at a higher level are flushed immediately. ++DECLARE_int32(logbuflevel); ++ ++// Sets the maximum number of seconds which logs may be buffered for. ++DECLARE_int32(logbufsecs); ++ ++// Log suppression level: messages logged at a lower level than this ++// are suppressed. ++DECLARE_int32(minloglevel); ++ ++// If specified, logfiles are written into this directory instead of the ++// default logging directory. ++DECLARE_string(log_dir); ++ ++// Sets the path of the directory into which to put additional links ++// to the log files. ++DECLARE_string(log_link); ++ ++DECLARE_int32(v); // in vlog_is_on.cc ++ ++// Sets the maximum log file size (in MB). ++DECLARE_int32(max_log_size); ++ ++// Sets whether to avoid logging to the disk if the disk is full. ++DECLARE_bool(stop_logging_if_full_disk); ++ ++#ifdef MUST_UNDEF_GFLAGS_DECLARE_MACROS ++#undef MUST_UNDEF_GFLAGS_DECLARE_MACROS ++#undef DECLARE_VARIABLE ++#undef DECLARE_bool ++#undef DECLARE_int32 ++#undef DECLARE_string ++#endif ++ ++// Log messages below the GOOGLE_STRIP_LOG level will be compiled away for ++// security reasons. See LOG(severtiy) below. ++ ++// A few definitions of macros that don't generate much code. Since ++// LOG(INFO) and its ilk are used all over our code, it's ++// better to have compact code for these operations. ++ ++#if GOOGLE_STRIP_LOG == 0 ++#define COMPACT_GOOGLE_LOG_INFO google::LogMessage( \ ++ __FILE__, __LINE__) ++#define LOG_TO_STRING_INFO(message) google::LogMessage( \ ++ __FILE__, __LINE__, google::INFO, message) ++#else ++#define COMPACT_GOOGLE_LOG_INFO google::NullStream() ++#define LOG_TO_STRING_INFO(message) google::NullStream() ++#endif ++ ++#if GOOGLE_STRIP_LOG <= 1 ++#define COMPACT_GOOGLE_LOG_WARNING google::LogMessage( \ ++ __FILE__, __LINE__, google::WARNING) ++#define LOG_TO_STRING_WARNING(message) google::LogMessage( \ ++ __FILE__, __LINE__, google::WARNING, message) ++#else ++#define COMPACT_GOOGLE_LOG_WARNING google::NullStream() ++#define LOG_TO_STRING_WARNING(message) google::NullStream() ++#endif ++ ++#if GOOGLE_STRIP_LOG <= 2 ++#define COMPACT_GOOGLE_LOG_ERROR google::LogMessage( \ ++ __FILE__, __LINE__, google::ERROR) ++#define LOG_TO_STRING_ERROR(message) google::LogMessage( \ ++ __FILE__, __LINE__, google::ERROR, message) ++#else ++#define COMPACT_GOOGLE_LOG_ERROR google::NullStream() ++#define LOG_TO_STRING_ERROR(message) google::NullStream() ++#endif ++ ++#if GOOGLE_STRIP_LOG <= 3 ++#define COMPACT_GOOGLE_LOG_FATAL google::LogMessageFatal( \ ++ __FILE__, __LINE__) ++#define LOG_TO_STRING_FATAL(message) google::LogMessage( \ ++ __FILE__, __LINE__, google::FATAL, message) ++#else ++#define COMPACT_GOOGLE_LOG_FATAL google::NullStreamFatal() ++#define LOG_TO_STRING_FATAL(message) google::NullStreamFatal() ++#endif ++ ++// For DFATAL, we want to use LogMessage (as opposed to ++// LogMessageFatal), to be consistent with the original behavior. ++#ifdef NDEBUG ++#define COMPACT_GOOGLE_LOG_DFATAL COMPACT_GOOGLE_LOG_ERROR ++#elif GOOGLE_STRIP_LOG <= 3 ++#define COMPACT_GOOGLE_LOG_DFATAL LogMessage( \ ++ __FILE__, __LINE__, google::FATAL) ++#else ++#define COMPACT_GOOGLE_LOG_DFATAL google::NullStreamFatal() ++#endif ++ ++#define GOOGLE_LOG_INFO(counter) google::LogMessage(__FILE__, __LINE__, google::INFO, counter, &google::LogMessage::SendToLog) ++#define SYSLOG_INFO(counter) \ ++ google::LogMessage(__FILE__, __LINE__, google::INFO, counter, \ ++ &google::LogMessage::SendToSyslogAndLog) ++#define GOOGLE_LOG_WARNING(counter) \ ++ google::LogMessage(__FILE__, __LINE__, google::WARNING, counter, \ ++ &google::LogMessage::SendToLog) ++#define SYSLOG_WARNING(counter) \ ++ google::LogMessage(__FILE__, __LINE__, google::WARNING, counter, \ ++ &google::LogMessage::SendToSyslogAndLog) ++#define GOOGLE_LOG_ERROR(counter) \ ++ google::LogMessage(__FILE__, __LINE__, google::ERROR, counter, \ ++ &google::LogMessage::SendToLog) ++#define SYSLOG_ERROR(counter) \ ++ google::LogMessage(__FILE__, __LINE__, google::ERROR, counter, \ ++ &google::LogMessage::SendToSyslogAndLog) ++#define GOOGLE_LOG_FATAL(counter) \ ++ google::LogMessage(__FILE__, __LINE__, google::FATAL, counter, \ ++ &google::LogMessage::SendToLog) ++#define SYSLOG_FATAL(counter) \ ++ google::LogMessage(__FILE__, __LINE__, google::FATAL, counter, \ ++ &google::LogMessage::SendToSyslogAndLog) ++#define GOOGLE_LOG_DFATAL(counter) \ ++ google::LogMessage(__FILE__, __LINE__, google::DFATAL_LEVEL, counter, \ ++ &google::LogMessage::SendToLog) ++#define SYSLOG_DFATAL(counter) \ ++ google::LogMessage(__FILE__, __LINE__, google::DFATAL_LEVEL, counter, \ ++ &google::LogMessage::SendToSyslogAndLog) ++ ++#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) || defined(__CYGWIN32__) ++// A very useful logging macro to log windows errors: ++#define LOG_SYSRESULT(result) \ ++ if (FAILED(result)) { \ ++ LPTSTR message = NULL; \ ++ LPTSTR msg = reinterpret_cast(&message); \ ++ DWORD message_length = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | \ ++ FORMAT_MESSAGE_FROM_SYSTEM, \ ++ 0, result, 0, msg, 100, NULL); \ ++ if (message_length > 0) { \ ++ google::LogMessage(__FILE__, __LINE__, ERROR, 0, \ ++ &google::LogMessage::SendToLog).stream() << message; \ ++ LocalFree(message); \ ++ } \ ++ } ++#endif ++ ++// We use the preprocessor's merging operator, "##", so that, e.g., ++// LOG(INFO) becomes the token GOOGLE_LOG_INFO. There's some funny ++// subtle difference between ostream member streaming functions (e.g., ++// ostream::operator<<(int) and ostream non-member streaming functions ++// (e.g., ::operator<<(ostream&, string&): it turns out that it's ++// impossible to stream something like a string directly to an unnamed ++// ostream. We employ a neat hack by calling the stream() member ++// function of LogMessage which seems to avoid the problem. ++#define LOG(severity) COMPACT_GOOGLE_LOG_ ## severity.stream() ++#define SYSLOG(severity) SYSLOG_ ## severity(0).stream() ++ ++namespace google { ++ ++// They need the definitions of integer types. ++#include "glog/log_severity.h" ++#include "glog/vlog_is_on.h" ++ ++// Initialize google's logging library. You will see the program name ++// specified by argv0 in log outputs. ++GOOGLE_GLOG_DLL_DECL void InitGoogleLogging(const char* argv0); ++ ++// Install a function which will be called after LOG(FATAL). ++GOOGLE_GLOG_DLL_DECL void InstallFailureFunction(void (*fail_func)()); ++ ++class LogSink; // defined below ++ ++// If a non-NULL sink pointer is given, we push this message to that sink. ++// For LOG_TO_SINK we then do normal LOG(severity) logging as well. ++// This is useful for capturing messages and passing/storing them ++// somewhere more specific than the global log of the process. ++// Argument types: ++// LogSink* sink; ++// LogSeverity severity; ++// The cast is to disambiguate NULL arguments. ++#define LOG_TO_SINK(sink, severity) \ ++ google::LogMessage( \ ++ __FILE__, __LINE__, \ ++ google::severity, \ ++ static_cast(sink), true).stream() ++#define LOG_TO_SINK_BUT_NOT_TO_LOGFILE(sink, severity) \ ++ google::LogMessage( \ ++ __FILE__, __LINE__, \ ++ google::severity, \ ++ static_cast(sink), false).stream() ++ ++// If a non-NULL string pointer is given, we write this message to that string. ++// We then do normal LOG(severity) logging as well. ++// This is useful for capturing messages and storing them somewhere more ++// specific than the global log of the process. ++// Argument types: ++// string* message; ++// LogSeverity severity; ++// The cast is to disambiguate NULL arguments. ++// NOTE: LOG(severity) expands to LogMessage().stream() for the specified ++// severity. ++#define LOG_TO_STRING(severity, message) \ ++ LOG_TO_STRING_##severity(static_cast(message)).stream() ++ ++// If a non-NULL pointer is given, we push the message onto the end ++// of a vector of strings; otherwise, we report it with LOG(severity). ++// This is handy for capturing messages and perhaps passing them back ++// to the caller, rather than reporting them immediately. ++// Argument types: ++// LogSeverity severity; ++// vector *outvec; ++// The cast is to disambiguate NULL arguments. ++#define LOG_STRING(severity, outvec) \ ++ LOG_TO_STRING_##severity(static_cast*>(outvec)).stream() ++ ++#define LOG_IF(severity, condition) \ ++ !(condition) ? (void) 0 : google::LogMessageVoidify() & LOG(severity) ++#define SYSLOG_IF(severity, condition) \ ++ !(condition) ? (void) 0 : google::LogMessageVoidify() & SYSLOG(severity) ++ ++#define LOG_ASSERT(condition) \ ++ LOG_IF(FATAL, !(condition)) << "Assert failed: " #condition ++#define SYSLOG_ASSERT(condition) \ ++ SYSLOG_IF(FATAL, !(condition)) << "Assert failed: " #condition ++ ++// CHECK dies with a fatal error if condition is not true. It is *not* ++// controlled by NDEBUG, so the check will be executed regardless of ++// compilation mode. Therefore, it is safe to do things like: ++// CHECK(fp->Write(x) == 4) ++#define CHECK(condition) \ ++ LOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN(!(condition))) \ ++ << "Check failed: " #condition " " ++ ++// A container for a string pointer which can be evaluated to a bool - ++// true iff the pointer is NULL. ++struct CheckOpString { ++ CheckOpString(std::string* str) : str_(str) { } ++ // No destructor: if str_ is non-NULL, we're about to LOG(FATAL), ++ // so there's no point in cleaning up str_. ++ operator bool() const { ++ return GOOGLE_PREDICT_BRANCH_NOT_TAKEN(str_ != NULL); ++ } ++ std::string* str_; ++}; ++ ++// Function is overloaded for integral types to allow static const ++// integrals declared in classes and not defined to be used as arguments to ++// CHECK* macros. It's not encouraged though. ++template ++inline const T& GetReferenceableValue(const T& t) { return t; } ++inline char GetReferenceableValue(char t) { return t; } ++inline unsigned char GetReferenceableValue(unsigned char t) { return t; } ++inline signed char GetReferenceableValue(signed char t) { return t; } ++inline short GetReferenceableValue(short t) { return t; } ++inline unsigned short GetReferenceableValue(unsigned short t) { return t; } ++inline int GetReferenceableValue(int t) { return t; } ++inline unsigned int GetReferenceableValue(unsigned int t) { return t; } ++inline long GetReferenceableValue(long t) { return t; } ++inline unsigned long GetReferenceableValue(unsigned long t) { return t; } ++inline long long GetReferenceableValue(long long t) { return t; } ++inline unsigned long long GetReferenceableValue(unsigned long long t) { ++ return t; ++} ++ ++// This is a dummy class to define the following operator. ++struct DummyClassToDefineOperator {}; ++ ++} ++ ++// Define global operator<< to declare using ::operator<<. ++// This declaration will allow use to use CHECK macros for user ++// defined classes which have operator<< (e.g., stl_logging.h). ++inline std::ostream& operator<<( ++ std::ostream& out, const google::DummyClassToDefineOperator&) { ++ return out; ++} ++ ++namespace google { ++ ++// Build the error message string. ++template ++std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) { ++ // It means that we cannot use stl_logging if compiler doesn't ++ // support using expression for operator. ++ // TODO(hamaji): Figure out a way to fix. ++#if 1 ++ using ::operator<<; ++#endif ++ std::strstream ss; ++ ss << names << " (" << v1 << " vs. " << v2 << ")"; ++ return new std::string(ss.str(), ss.pcount()); ++} ++ ++// Helper functions for CHECK_OP macro. ++// The (int, int) specialization works around the issue that the compiler ++// will not instantiate the template version of the function on values of ++// unnamed enum type - see comment below. ++#define DEFINE_CHECK_OP_IMPL(name, op) \ ++ template \ ++ inline std::string* Check##name##Impl(const t1& v1, const t2& v2, \ ++ const char* names) { \ ++ if (v1 op v2) return NULL; \ ++ else return MakeCheckOpString(v1, v2, names); \ ++ } \ ++ inline std::string* Check##name##Impl(int v1, int v2, const char* names) { \ ++ return Check##name##Impl(v1, v2, names); \ ++ } ++ ++// Use _EQ, _NE, _LE, etc. in case the file including base/logging.h ++// provides its own #defines for the simpler names EQ, NE, LE, etc. ++// This happens if, for example, those are used as token names in a ++// yacc grammar. ++DEFINE_CHECK_OP_IMPL(_EQ, ==) ++DEFINE_CHECK_OP_IMPL(_NE, !=) ++DEFINE_CHECK_OP_IMPL(_LE, <=) ++DEFINE_CHECK_OP_IMPL(_LT, < ) ++DEFINE_CHECK_OP_IMPL(_GE, >=) ++DEFINE_CHECK_OP_IMPL(_GT, > ) ++#undef DEFINE_CHECK_OP_IMPL ++ ++// Helper macro for binary operators. ++// Don't use this macro directly in your code, use CHECK_EQ et al below. ++ ++#if defined(STATIC_ANALYSIS) ++// Only for static analysis tool to know that it is equivalent to assert ++#define CHECK_OP_LOG(name, op, val1, val2, log) CHECK((val1) op (val2)) ++#elif !defined(NDEBUG) ++// In debug mode, avoid constructing CheckOpStrings if possible, ++// to reduce the overhead of CHECK statments by 2x. ++// Real DCHECK-heavy tests have seen 1.5x speedups. ++ ++// The meaning of "string" might be different between now and ++// when this macro gets invoked (e.g., if someone is experimenting ++// with other string implementations that get defined after this ++// file is included). Save the current meaning now and use it ++// in the macro. ++typedef std::string _Check_string; ++#define CHECK_OP_LOG(name, op, val1, val2, log) \ ++ while (google::_Check_string* _result = \ ++ google::Check##name##Impl( \ ++ google::GetReferenceableValue(val1), \ ++ google::GetReferenceableValue(val2), \ ++ #val1 " " #op " " #val2)) \ ++ log(__FILE__, __LINE__, \ ++ google::CheckOpString(_result)).stream() ++#else ++// In optimized mode, use CheckOpString to hint to compiler that ++// the while condition is unlikely. ++#define CHECK_OP_LOG(name, op, val1, val2, log) \ ++ while (google::CheckOpString _result = \ ++ google::Check##name##Impl(GetReferenceableValue(val1), \ ++ GetReferenceableValue(val2), \ ++ #val1 " " #op " " #val2)) \ ++ log(__FILE__, __LINE__, _result).stream() ++#endif // STATIC_ANALYSIS, !NDEBUG ++ ++#if GOOGLE_STRIP_LOG <= 3 ++#define CHECK_OP(name, op, val1, val2) \ ++ CHECK_OP_LOG(name, op, val1, val2, google::LogMessageFatal) ++#else ++#define CHECK_OP(name, op, val1, val2) \ ++ CHECK_OP_LOG(name, op, val1, val2, google::NullStreamFatal) ++#endif // STRIP_LOG <= 3 ++ ++// Equality/Inequality checks - compare two values, and log a FATAL message ++// including the two values when the result is not as expected. The values ++// must have operator<<(ostream, ...) defined. ++// ++// You may append to the error message like so: ++// CHECK_NE(1, 2) << ": The world must be ending!"; ++// ++// We are very careful to ensure that each argument is evaluated exactly ++// once, and that anything which is legal to pass as a function argument is ++// legal here. In particular, the arguments may be temporary expressions ++// which will end up being destroyed at the end of the apparent statement, ++// for example: ++// CHECK_EQ(string("abc")[1], 'b'); ++// ++// WARNING: These don't compile correctly if one of the arguments is a pointer ++// and the other is NULL. To work around this, simply static_cast NULL to the ++// type of the desired pointer. ++ ++#define CHECK_EQ(val1, val2) CHECK_OP(_EQ, ==, val1, val2) ++#define CHECK_NE(val1, val2) CHECK_OP(_NE, !=, val1, val2) ++#define CHECK_LE(val1, val2) CHECK_OP(_LE, <=, val1, val2) ++#define CHECK_LT(val1, val2) CHECK_OP(_LT, < , val1, val2) ++#define CHECK_GE(val1, val2) CHECK_OP(_GE, >=, val1, val2) ++#define CHECK_GT(val1, val2) CHECK_OP(_GT, > , val1, val2) ++ ++// Check that the input is non NULL. This very useful in constructor ++// initializer lists. ++ ++#define CHECK_NOTNULL(val) \ ++ google::CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non NULL", (val)) ++ ++// Helper functions for string comparisons. ++// To avoid bloat, the definitions are in logging.cc. ++#define DECLARE_CHECK_STROP_IMPL(func, expected) \ ++ GOOGLE_GLOG_DLL_DECL std::string* Check##func##expected##Impl( \ ++ const char* s1, const char* s2, const char* names); ++DECLARE_CHECK_STROP_IMPL(strcmp, true) ++DECLARE_CHECK_STROP_IMPL(strcmp, false) ++DECLARE_CHECK_STROP_IMPL(strcasecmp, true) ++DECLARE_CHECK_STROP_IMPL(strcasecmp, false) ++#undef DECLARE_CHECK_STROP_IMPL ++ ++// Helper macro for string comparisons. ++// Don't use this macro directly in your code, use CHECK_STREQ et al below. ++#define CHECK_STROP(func, op, expected, s1, s2) \ ++ while (google::CheckOpString _result = \ ++ google::Check##func##expected##Impl((s1), (s2), \ ++ #s1 " " #op " " #s2)) \ ++ LOG(FATAL) << *_result.str_ ++ ++ ++// String (char*) equality/inequality checks. ++// CASE versions are case-insensitive. ++// ++// Note that "s1" and "s2" may be temporary strings which are destroyed ++// by the compiler at the end of the current "full expression" ++// (e.g. CHECK_STREQ(Foo().c_str(), Bar().c_str())). ++ ++#define CHECK_STREQ(s1, s2) CHECK_STROP(strcmp, ==, true, s1, s2) ++#define CHECK_STRNE(s1, s2) CHECK_STROP(strcmp, !=, false, s1, s2) ++#define CHECK_STRCASEEQ(s1, s2) CHECK_STROP(strcasecmp, ==, true, s1, s2) ++#define CHECK_STRCASENE(s1, s2) CHECK_STROP(strcasecmp, !=, false, s1, s2) ++ ++#define CHECK_INDEX(I,A) CHECK(I < (sizeof(A)/sizeof(A[0]))) ++#define CHECK_BOUND(B,A) CHECK(B <= (sizeof(A)/sizeof(A[0]))) ++ ++#define CHECK_DOUBLE_EQ(val1, val2) \ ++ do { \ ++ CHECK_LE((val1), (val2)+0.000000000000001L); \ ++ CHECK_GE((val1), (val2)-0.000000000000001L); \ ++ } while (0) ++ ++#define CHECK_NEAR(val1, val2, margin) \ ++ do { \ ++ CHECK_LE((val1), (val2)+(margin)); \ ++ CHECK_GE((val1), (val2)-(margin)); \ ++ } while (0) ++ ++// perror()..googly style! ++// ++// PLOG() and PLOG_IF() and PCHECK() behave exactly like their LOG* and ++// CHECK equivalents with the addition that they postpend a description ++// of the current state of errno to their output lines. ++ ++#define PLOG(severity) GOOGLE_PLOG(severity, 0).stream() ++ ++#define GOOGLE_PLOG(severity, counter) \ ++ google::ErrnoLogMessage( \ ++ __FILE__, __LINE__, google::severity, counter, \ ++ &google::LogMessage::SendToLog) ++ ++#define PLOG_IF(severity, condition) \ ++ !(condition) ? (void) 0 : google::LogMessageVoidify() & PLOG(severity) ++ ++// A CHECK() macro that postpends errno if the condition is false. E.g. ++// ++// if (poll(fds, nfds, timeout) == -1) { PCHECK(errno == EINTR); ... } ++#define PCHECK(condition) \ ++ PLOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN(!(condition))) \ ++ << "Check failed: " #condition " " ++ ++// A CHECK() macro that lets you assert the success of a function that ++// returns -1 and sets errno in case of an error. E.g. ++// ++// CHECK_ERR(mkdir(path, 0700)); ++// ++// or ++// ++// int fd = open(filename, flags); CHECK_ERR(fd) << ": open " << filename; ++#define CHECK_ERR(invocation) \ ++PLOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN((invocation) == -1)) \ ++ << #invocation ++ ++// Use macro expansion to create, for each use of LOG_EVERY_N(), static ++// variables with the __LINE__ expansion as part of the variable name. ++#define LOG_EVERY_N_VARNAME(base, line) LOG_EVERY_N_VARNAME_CONCAT(base, line) ++#define LOG_EVERY_N_VARNAME_CONCAT(base, line) base ## line ++ ++#define LOG_OCCURRENCES LOG_EVERY_N_VARNAME(occurrences_, __LINE__) ++#define LOG_OCCURRENCES_MOD_N LOG_EVERY_N_VARNAME(occurrences_mod_n_, __LINE__) ++ ++#define SOME_KIND_OF_LOG_EVERY_N(severity, n, what_to_do) \ ++ static int LOG_OCCURRENCES = 0, LOG_OCCURRENCES_MOD_N = 0; \ ++ ++LOG_OCCURRENCES; \ ++ if (++LOG_OCCURRENCES_MOD_N > n) LOG_OCCURRENCES_MOD_N -= n; \ ++ if (LOG_OCCURRENCES_MOD_N == 1) \ ++ google::LogMessage( \ ++ __FILE__, __LINE__, google::severity, LOG_OCCURRENCES, \ ++ &what_to_do).stream() ++ ++#define SOME_KIND_OF_LOG_IF_EVERY_N(severity, condition, n, what_to_do) \ ++ static int LOG_OCCURRENCES = 0, LOG_OCCURRENCES_MOD_N = 0; \ ++ ++LOG_OCCURRENCES; \ ++ if (condition && \ ++ ((LOG_OCCURRENCES_MOD_N=(LOG_OCCURRENCES_MOD_N + 1) % n) == (1 % n))) \ ++ google::LogMessage( \ ++ __FILE__, __LINE__, google::severity, LOG_OCCURRENCES, \ ++ &what_to_do).stream() ++ ++#define SOME_KIND_OF_PLOG_EVERY_N(severity, n, what_to_do) \ ++ static int LOG_OCCURRENCES = 0, LOG_OCCURRENCES_MOD_N = 0; \ ++ ++LOG_OCCURRENCES; \ ++ if (++LOG_OCCURRENCES_MOD_N > n) LOG_OCCURRENCES_MOD_N -= n; \ ++ if (LOG_OCCURRENCES_MOD_N == 1) \ ++ google::ErrnoLogMessage( \ ++ __FILE__, __LINE__, google::severity, LOG_OCCURRENCES, \ ++ &what_to_do).stream() ++ ++#define SOME_KIND_OF_LOG_FIRST_N(severity, n, what_to_do) \ ++ static int LOG_OCCURRENCES = 0; \ ++ if (LOG_OCCURRENCES <= n) \ ++ ++LOG_OCCURRENCES; \ ++ if (LOG_OCCURRENCES <= n) \ ++ google::LogMessage( \ ++ __FILE__, __LINE__, google::severity, LOG_OCCURRENCES, \ ++ &what_to_do).stream() ++ ++namespace glog_internal_namespace_ { ++template ++struct CompileAssert { ++}; ++struct CrashReason; ++} // namespace glog_internal_namespace_ ++ ++#define GOOGLE_GLOG_COMPILE_ASSERT(expr, msg) \ ++ typedef google::glog_internal_namespace_::CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1] ++ ++#define LOG_EVERY_N(severity, n) \ ++ GOOGLE_GLOG_COMPILE_ASSERT(google::severity < \ ++ google::NUM_SEVERITIES, \ ++ INVALID_REQUESTED_LOG_SEVERITY); \ ++ SOME_KIND_OF_LOG_EVERY_N(severity, (n), google::LogMessage::SendToLog) ++ ++#define SYSLOG_EVERY_N(severity, n) \ ++ SOME_KIND_OF_LOG_EVERY_N(severity, (n), google::LogMessage::SendToSyslogAndLog) ++ ++#define PLOG_EVERY_N(severity, n) \ ++ SOME_KIND_OF_PLOG_EVERY_N(severity, (n), google::LogMessage::SendToLog) ++ ++#define LOG_FIRST_N(severity, n) \ ++ SOME_KIND_OF_LOG_FIRST_N(severity, (n), google::LogMessage::SendToLog) ++ ++#define LOG_IF_EVERY_N(severity, condition, n) \ ++ SOME_KIND_OF_LOG_IF_EVERY_N(severity, (condition), (n), google::LogMessage::SendToLog) ++ ++// We want the special COUNTER value available for LOG_EVERY_X()'ed messages ++enum PRIVATE_Counter {COUNTER}; ++ ++ ++// Plus some debug-logging macros that get compiled to nothing for production ++ ++#ifndef NDEBUG ++ ++#define DLOG(severity) LOG(severity) ++#define DVLOG(verboselevel) VLOG(verboselevel) ++#define DLOG_IF(severity, condition) LOG_IF(severity, condition) ++#define DLOG_EVERY_N(severity, n) LOG_EVERY_N(severity, n) ++#define DLOG_IF_EVERY_N(severity, condition, n) \ ++ LOG_IF_EVERY_N(severity, condition, n) ++#define DLOG_ASSERT(condition) LOG_ASSERT(condition) ++ ++// debug-only checking. not executed in NDEBUG mode. ++#define DCHECK(condition) CHECK(condition) ++#define DCHECK_EQ(val1, val2) CHECK_EQ(val1, val2) ++#define DCHECK_NE(val1, val2) CHECK_NE(val1, val2) ++#define DCHECK_LE(val1, val2) CHECK_LE(val1, val2) ++#define DCHECK_LT(val1, val2) CHECK_LT(val1, val2) ++#define DCHECK_GE(val1, val2) CHECK_GE(val1, val2) ++#define DCHECK_GT(val1, val2) CHECK_GT(val1, val2) ++#define DCHECK_STREQ(str1, str2) CHECK_STREQ(str1, str2) ++#define DCHECK_STRCASEEQ(str1, str2) CHECK_STRCASEEQ(str1, str2) ++#define DCHECK_STRNE(str1, str2) CHECK_STRNE(str1, str2) ++#define DCHECK_STRCASENE(str1, str2) CHECK_STRCASENE(str1, str2) ++ ++#else // NDEBUG ++ ++#define DLOG(severity) \ ++ true ? (void) 0 : google::LogMessageVoidify() & LOG(severity) ++ ++#define DVLOG(verboselevel) \ ++ (true || !VLOG_IS_ON(verboselevel)) ?\ ++ (void) 0 : google::LogMessageVoidify() & LOG(INFO) ++ ++#define DLOG_IF(severity, condition) \ ++ (true || !(condition)) ? (void) 0 : google::LogMessageVoidify() & LOG(severity) ++ ++#define DLOG_EVERY_N(severity, n) \ ++ true ? (void) 0 : google::LogMessageVoidify() & LOG(severity) ++ ++#define DLOG_IF_EVERY_N(severity, condition, n) \ ++ (true || !(condition))? (void) 0 : google::LogMessageVoidify() & LOG(severity) ++ ++#define DLOG_ASSERT(condition) \ ++ true ? (void) 0 : LOG_ASSERT(condition) ++ ++#define DCHECK(condition) \ ++ while (false) \ ++ CHECK(condition) ++ ++#define DCHECK_EQ(val1, val2) \ ++ while (false) \ ++ CHECK_EQ(val1, val2) ++ ++#define DCHECK_NE(val1, val2) \ ++ while (false) \ ++ CHECK_NE(val1, val2) ++ ++#define DCHECK_LE(val1, val2) \ ++ while (false) \ ++ CHECK_LE(val1, val2) ++ ++#define DCHECK_LT(val1, val2) \ ++ while (false) \ ++ CHECK_LT(val1, val2) ++ ++#define DCHECK_GE(val1, val2) \ ++ while (false) \ ++ CHECK_GE(val1, val2) ++ ++#define DCHECK_GT(val1, val2) \ ++ while (false) \ ++ CHECK_GT(val1, val2) ++ ++#define DCHECK_STREQ(str1, str2) \ ++ while (false) \ ++ CHECK_STREQ(str1, str2) ++ ++#define DCHECK_STRCASEEQ(str1, str2) \ ++ while (false) \ ++ CHECK_STRCASEEQ(str1, str2) ++ ++#define DCHECK_STRNE(str1, str2) \ ++ while (false) \ ++ CHECK_STRNE(str1, str2) ++ ++#define DCHECK_STRCASENE(str1, str2) \ ++ while (false) \ ++ CHECK_STRCASENE(str1, str2) ++ ++ ++#endif // NDEBUG ++ ++// Log only in verbose mode. ++ ++#define VLOG(verboselevel) LOG_IF(INFO, VLOG_IS_ON(verboselevel)) ++ ++#define VLOG_IF(verboselevel, condition) \ ++ LOG_IF(INFO, (condition) && VLOG_IS_ON(verboselevel)) ++ ++#define VLOG_EVERY_N(verboselevel, n) \ ++ LOG_IF_EVERY_N(INFO, VLOG_IS_ON(verboselevel), n) ++ ++#define VLOG_IF_EVERY_N(verboselevel, condition, n) \ ++ LOG_IF_EVERY_N(INFO, (condition) && VLOG_IS_ON(verboselevel), n) ++ ++// ++// This class more or less represents a particular log message. You ++// create an instance of LogMessage and then stream stuff to it. ++// When you finish streaming to it, ~LogMessage is called and the ++// full message gets streamed to the appropriate destination. ++// ++// You shouldn't actually use LogMessage's constructor to log things, ++// though. You should use the LOG() macro (and variants thereof) ++// above. ++class GOOGLE_GLOG_DLL_DECL LogMessage { ++public: ++ enum { ++ // Passing kNoLogPrefix for the line number disables the ++ // log-message prefix. Useful for using the LogMessage ++ // infrastructure as a printing utility. See also the --log_prefix ++ // flag for controlling the log-message prefix on an ++ // application-wide basis. ++ kNoLogPrefix = -1 ++ }; ++ ++ // LogStream inherit from non-DLL-exported class (std::ostrstream) ++ // and VC++ produces a warning for this situation. ++ // However, MSDN says "C4275 can be ignored in Microsoft Visual C++ ++ // 2005 if you are deriving from a type in the Standard C++ Library" ++ // http://msdn.microsoft.com/en-us/library/3tdb471s(VS.80).aspx ++ // Let's just ignore the warning. ++#ifdef _MSC_VER ++# pragma warning(disable: 4275) ++#endif ++ class GOOGLE_GLOG_DLL_DECL LogStream : public std::ostrstream { ++#ifdef _MSC_VER ++# pragma warning(default: 4275) ++#endif ++ public: ++ LogStream(char *buf, int len, int ctr) ++ : ostrstream(buf, len), ++ ctr_(ctr) { ++ self_ = this; ++ } ++ ++ int ctr() const { return ctr_; } ++ void set_ctr(int ctr) { ctr_ = ctr; } ++ LogStream* self() const { return self_; } ++ ++ private: ++ int ctr_; // Counter hack (for the LOG_EVERY_X() macro) ++ LogStream *self_; // Consistency check hack ++ }; ++ ++public: ++ // icc 8 requires this typedef to avoid an internal compiler error. ++ typedef void (LogMessage::*SendMethod)(); ++ ++ LogMessage(const char* file, int line, LogSeverity severity, int ctr, ++ SendMethod send_method); ++ ++ // Two special constructors that generate reduced amounts of code at ++ // LOG call sites for common cases. ++ ++ // Used for LOG(INFO): Implied are: ++ // severity = INFO, ctr = 0, send_method = &LogMessage::SendToLog. ++ // ++ // Using this constructor instead of the more complex constructor above ++ // saves 19 bytes per call site. ++ LogMessage(const char* file, int line); ++ ++ // Used for LOG(severity) where severity != INFO. Implied ++ // are: ctr = 0, send_method = &LogMessage::SendToLog ++ // ++ // Using this constructor instead of the more complex constructor above ++ // saves 17 bytes per call site. ++ LogMessage(const char* file, int line, LogSeverity severity); ++ ++ // Constructor to log this message to a specified sink (if not NULL). ++ // Implied are: ctr = 0, send_method = &LogMessage::SendToSinkAndLog if ++ // also_send_to_log is true, send_method = &LogMessage::SendToSink otherwise. ++ LogMessage(const char* file, int line, LogSeverity severity, LogSink* sink, ++ bool also_send_to_log); ++ ++ // Constructor where we also give a vector pointer ++ // for storing the messages (if the pointer is not NULL). ++ // Implied are: ctr = 0, send_method = &LogMessage::SaveOrSendToLog. ++ LogMessage(const char* file, int line, LogSeverity severity, ++ std::vector* outvec); ++ ++ // Constructor where we also give a string pointer for storing the ++ // message (if the pointer is not NULL). Implied are: ctr = 0, ++ // send_method = &LogMessage::WriteToStringAndLog. ++ LogMessage(const char* file, int line, LogSeverity severity, ++ std::string* message); ++ ++ // A special constructor used for check failures ++ LogMessage(const char* file, int line, const CheckOpString& result); ++ ++ ~LogMessage(); ++ ++ // Flush a buffered message to the sink set in the constructor. Always ++ // called by the destructor, it may also be called from elsewhere if ++ // needed. Only the first call is actioned; any later ones are ignored. ++ void Flush(); ++ ++ // An arbitrary limit on the length of a single log message. This ++ // is so that streaming can be done more efficiently. ++ static const size_t kMaxLogMessageLen; ++ ++ // Theses should not be called directly outside of logging.*, ++ // only passed as SendMethod arguments to other LogMessage methods: ++ void SendToLog(); // Actually dispatch to the logs ++ void SendToSyslogAndLog(); // Actually dispatch to syslog and the logs ++ ++ // Call abort() or similar to perform LOG(FATAL) crash. ++ static void Fail() __attribute__ ((noreturn)); ++ ++ std::ostream& stream() { return *(data_->stream_); } ++ ++ int preserved_errno() const { return data_->preserved_errno_; } ++ ++ // Must be called without the log_mutex held. (L < log_mutex) ++ static int64 num_messages(int severity); ++ ++private: ++ // Fully internal SendMethod cases: ++ void SendToSinkAndLog(); // Send to sink if provided and dispatch to the logs ++ void SendToSink(); // Send to sink if provided, do nothing otherwise. ++ ++ // Write to string if provided and dispatch to the logs. ++ void WriteToStringAndLog(); ++ ++ void SaveOrSendToLog(); // Save to stringvec if provided, else to logs ++ ++ void Init(const char* file, int line, LogSeverity severity, ++ void (LogMessage::*send_method)()); ++ ++ // Used to fill in crash information during LOG(FATAL) failures. ++ void RecordCrashReason(glog_internal_namespace_::CrashReason* reason); ++ ++ // Counts of messages sent at each priority: ++ static int64 num_messages_[NUM_SEVERITIES]; // under log_mutex ++ ++ // We keep the data in a separate struct so that each instance of ++ // LogMessage uses less stack space. ++ struct GOOGLE_GLOG_DLL_DECL LogMessageData { ++ LogMessageData() {}; ++ ++ int preserved_errno_; // preserved errno ++ char* buf_; ++ char* message_text_; // Complete message text (points to selected buffer) ++ LogStream* stream_alloc_; ++ LogStream* stream_; ++ char severity_; // What level is this LogMessage logged at? ++ int line_; // line number where logging call is. ++ void (LogMessage::*send_method_)(); // Call this in destructor to send ++ union { // At most one of these is used: union to keep the size low. ++ LogSink* sink_; // NULL or sink to send message to ++ std::vector* outvec_; // NULL or vector to push message onto ++ std::string* message_; // NULL or string to write message into ++ }; ++ time_t timestamp_; // Time of creation of LogMessage ++ struct ::tm tm_time_; // Time of creation of LogMessage ++ size_t num_prefix_chars_; // # of chars of prefix in this message ++ size_t num_chars_to_log_; // # of chars of msg to send to log ++ size_t num_chars_to_syslog_; // # of chars of msg to send to syslog ++ const char* basename_; // basename of file that called LOG ++ const char* fullname_; // fullname of file that called LOG ++ bool has_been_flushed_; // false => data has not been flushed ++ bool first_fatal_; // true => this was first fatal msg ++ ++ ~LogMessageData(); ++ private: ++ LogMessageData(const LogMessageData&); ++ void operator=(const LogMessageData&); ++ }; ++ ++ static LogMessageData fatal_msg_data_exclusive_; ++ static LogMessageData fatal_msg_data_shared_; ++ ++ LogMessageData* allocated_; ++ LogMessageData* data_; ++ ++ friend class LogDestination; ++ ++ LogMessage(const LogMessage&); ++ void operator=(const LogMessage&); ++}; ++ ++// This class happens to be thread-hostile because all instances share ++// a single data buffer, but since it can only be created just before ++// the process dies, we don't worry so much. ++class GOOGLE_GLOG_DLL_DECL LogMessageFatal : public LogMessage { ++ public: ++ LogMessageFatal(const char* file, int line); ++ LogMessageFatal(const char* file, int line, const CheckOpString& result); ++ ~LogMessageFatal() __attribute__ ((noreturn)); ++}; ++ ++// A non-macro interface to the log facility; (useful ++// when the logging level is not a compile-time constant). ++inline void LogAtLevel(int const severity, std::string const &msg) { ++ LogMessage(__FILE__, __LINE__, severity).stream() << msg; ++} ++ ++// A macro alternative of LogAtLevel. New code may want to use this ++// version since there are two advantages: 1. this version outputs the ++// file name and the line number where this macro is put like other ++// LOG macros, 2. this macro can be used as C++ stream. ++#define LOG_AT_LEVEL(severity) LogMessage(__FILE__, __LINE__, severity).stream() ++ ++// A small helper for CHECK_NOTNULL(). ++template ++T* CheckNotNull(const char *file, int line, const char *names, T* t) { ++ if (t == NULL) { ++ LogMessageFatal(file, line, new std::string(names)); ++ } ++ return t; ++} ++ ++// Allow folks to put a counter in the LOG_EVERY_X()'ed messages. This ++// only works if ostream is a LogStream. If the ostream is not a ++// LogStream you'll get an assert saying as much at runtime. ++GOOGLE_GLOG_DLL_DECL std::ostream& operator<<(std::ostream &os, ++ const PRIVATE_Counter&); ++ ++ ++// Derived class for PLOG*() above. ++class GOOGLE_GLOG_DLL_DECL ErrnoLogMessage : public LogMessage { ++ public: ++ ++ ErrnoLogMessage(const char* file, int line, LogSeverity severity, int ctr, ++ void (LogMessage::*send_method)()); ++ ++ // Postpends ": strerror(errno) [errno]". ++ ~ErrnoLogMessage(); ++ ++ private: ++ ErrnoLogMessage(const ErrnoLogMessage&); ++ void operator=(const ErrnoLogMessage&); ++}; ++ ++ ++// This class is used to explicitly ignore values in the conditional ++// logging macros. This avoids compiler warnings like "value computed ++// is not used" and "statement has no effect". ++ ++class GOOGLE_GLOG_DLL_DECL LogMessageVoidify { ++ public: ++ LogMessageVoidify() { } ++ // This has to be an operator with a precedence lower than << but ++ // higher than ?: ++ void operator&(std::ostream&) { } ++}; ++ ++ ++// Flushes all log files that contains messages that are at least of ++// the specified severity level. Thread-safe. ++GOOGLE_GLOG_DLL_DECL void FlushLogFiles(LogSeverity min_severity); ++ ++// Flushes all log files that contains messages that are at least of ++// the specified severity level. Thread-hostile because it ignores ++// locking -- used for catastrophic failures. ++GOOGLE_GLOG_DLL_DECL void FlushLogFilesUnsafe(LogSeverity min_severity); ++ ++// ++// Set the destination to which a particular severity level of log ++// messages is sent. If base_filename is "", it means "don't log this ++// severity". Thread-safe. ++// ++GOOGLE_GLOG_DLL_DECL void SetLogDestination(LogSeverity severity, ++ const char* base_filename); ++ ++// ++// Set the basename of the symlink to the latest log file at a given ++// severity. If symlink_basename is empty, do not make a symlink. If ++// you don't call this function, the symlink basename is the ++// invocation name of the program. Thread-safe. ++// ++GOOGLE_GLOG_DLL_DECL void SetLogSymlink(LogSeverity severity, ++ const char* symlink_basename); ++ ++// ++// Used to send logs to some other kind of destination ++// Users should subclass LogSink and override send to do whatever they want. ++// Implementations must be thread-safe because a shared instance will ++// be called from whichever thread ran the LOG(XXX) line. ++class GOOGLE_GLOG_DLL_DECL LogSink { ++ public: ++ virtual ~LogSink(); ++ ++ // Sink's logging logic (message_len is such as to exclude '\n' at the end). ++ // This method can't use LOG() or CHECK() as logging system mutex(s) are held ++ // during this call. ++ virtual void send(LogSeverity severity, const char* full_filename, ++ const char* base_filename, int line, ++ const struct ::tm* tm_time, ++ const char* message, size_t message_len) = 0; ++ ++ // Redefine this to implement waiting for ++ // the sink's logging logic to complete. ++ // It will be called after each send() returns, ++ // but before that LogMessage exits or crashes. ++ // By default this function does nothing. ++ // Using this function one can implement complex logic for send() ++ // that itself involves logging; and do all this w/o causing deadlocks and ++ // inconsistent rearrangement of log messages. ++ // E.g. if a LogSink has thread-specific actions, the send() method ++ // can simply add the message to a queue and wake up another thread that ++ // handles real logging while itself making some LOG() calls; ++ // WaitTillSent() can be implemented to wait for that logic to complete. ++ // See our unittest for an example. ++ virtual void WaitTillSent(); ++ ++ // Returns the normal text output of the log message. ++ // Can be useful to implement send(). ++ static std::string ToString(LogSeverity severity, const char* file, int line, ++ const struct ::tm* tm_time, ++ const char* message, size_t message_len); ++}; ++ ++// Add or remove a LogSink as a consumer of logging data. Thread-safe. ++GOOGLE_GLOG_DLL_DECL void AddLogSink(LogSink *destination); ++GOOGLE_GLOG_DLL_DECL void RemoveLogSink(LogSink *destination); ++ ++// ++// Specify an "extension" added to the filename specified via ++// SetLogDestination. This applies to all severity levels. It's ++// often used to append the port we're listening on to the logfile ++// name. Thread-safe. ++// ++GOOGLE_GLOG_DLL_DECL void SetLogFilenameExtension( ++ const char* filename_extension); ++ ++// ++// Make it so that all log messages of at least a particular severity ++// are logged to stderr (in addition to logging to the usual log ++// file(s)). Thread-safe. ++// ++GOOGLE_GLOG_DLL_DECL void SetStderrLogging(LogSeverity min_severity); ++ ++// ++// Make it so that all log messages go only to stderr. Thread-safe. ++// ++GOOGLE_GLOG_DLL_DECL void LogToStderr(); ++ ++// ++// Make it so that all log messages of at least a particular severity are ++// logged via email to a list of addresses (in addition to logging to the ++// usual log file(s)). The list of addresses is just a string containing ++// the email addresses to send to (separated by spaces, say). Thread-safe. ++// ++GOOGLE_GLOG_DLL_DECL void SetEmailLogging(LogSeverity min_severity, ++ const char* addresses); ++ ++// A simple function that sends email. dest is a commma-separated ++// list of addressess. Thread-safe. ++GOOGLE_GLOG_DLL_DECL bool SendEmail(const char *dest, ++ const char *subject, const char *body); ++ ++GOOGLE_GLOG_DLL_DECL const std::vector& GetLoggingDirectories(); ++ ++// For tests only: Clear the internal [cached] list of logging directories to ++// force a refresh the next time GetLoggingDirectories is called. ++// Thread-hostile. ++void TestOnly_ClearLoggingDirectoriesList(); ++ ++// Returns a set of existing temporary directories, which will be a ++// subset of the directories returned by GetLogginDirectories(). ++// Thread-safe. ++GOOGLE_GLOG_DLL_DECL void GetExistingTempDirectories( ++ std::vector* list); ++ ++// Print any fatal message again -- useful to call from signal handler ++// so that the last thing in the output is the fatal message. ++// Thread-hostile, but a race is unlikely. ++GOOGLE_GLOG_DLL_DECL void ReprintFatalMessage(); ++ ++// Truncate a log file that may be the append-only output of multiple ++// processes and hence can't simply be renamed/reopened (typically a ++// stdout/stderr). If the file "path" is > "limit" bytes, copy the ++// last "keep" bytes to offset 0 and truncate the rest. Since we could ++// be racing with other writers, this approach has the potential to ++// lose very small amounts of data. For security, only follow symlinks ++// if the path is /proc/self/fd/* ++GOOGLE_GLOG_DLL_DECL void TruncateLogFile(const char *path, ++ int64 limit, int64 keep); ++ ++// Truncate stdout and stderr if they are over the value specified by ++// --max_log_size; keep the final 1MB. This function has the same ++// race condition as TruncateLogFile. ++GOOGLE_GLOG_DLL_DECL void TruncateStdoutStderr(); ++ ++// Return the string representation of the provided LogSeverity level. ++// Thread-safe. ++GOOGLE_GLOG_DLL_DECL const char* GetLogSeverityName(LogSeverity severity); ++ ++// --------------------------------------------------------------------- ++// Implementation details that are not useful to most clients ++// --------------------------------------------------------------------- ++ ++// A Logger is the interface used by logging modules to emit entries ++// to a log. A typical implementation will dump formatted data to a ++// sequence of files. We also provide interfaces that will forward ++// the data to another thread so that the invoker never blocks. ++// Implementations should be thread-safe since the logging system ++// will write to them from multiple threads. ++ ++namespace base { ++ ++class GOOGLE_GLOG_DLL_DECL Logger { ++ public: ++ virtual ~Logger(); ++ ++ // Writes "message[0,message_len-1]" corresponding to an event that ++ // occurred at "timestamp". If "force_flush" is true, the log file ++ // is flushed immediately. ++ // ++ // The input message has already been formatted as deemed ++ // appropriate by the higher level logging facility. For example, ++ // textual log messages already contain timestamps, and the ++ // file:linenumber header. ++ virtual void Write(bool force_flush, ++ time_t timestamp, ++ const char* message, ++ int message_len) = 0; ++ ++ // Flush any buffered messages ++ virtual void Flush() = 0; ++ ++ // Get the current LOG file size. ++ // The returned value is approximate since some ++ // logged data may not have been flushed to disk yet. ++ virtual uint32 LogSize() = 0; ++}; ++ ++// Get the logger for the specified severity level. The logger ++// remains the property of the logging module and should not be ++// deleted by the caller. Thread-safe. ++extern GOOGLE_GLOG_DLL_DECL Logger* GetLogger(LogSeverity level); ++ ++// Set the logger for the specified severity level. The logger ++// becomes the property of the logging module and should not ++// be deleted by the caller. Thread-safe. ++extern GOOGLE_GLOG_DLL_DECL void SetLogger(LogSeverity level, Logger* logger); ++ ++} ++ ++// glibc has traditionally implemented two incompatible versions of ++// strerror_r(). There is a poorly defined convention for picking the ++// version that we want, but it is not clear whether it even works with ++// all versions of glibc. ++// So, instead, we provide this wrapper that automatically detects the ++// version that is in use, and then implements POSIX semantics. ++// N.B. In addition to what POSIX says, we also guarantee that "buf" will ++// be set to an empty string, if this function failed. This means, in most ++// cases, you do not need to check the error code and you can directly ++// use the value of "buf". It will never have an undefined value. ++GOOGLE_GLOG_DLL_DECL int posix_strerror_r(int err, char *buf, size_t len); ++ ++ ++// A class for which we define operator<<, which does nothing. ++class GOOGLE_GLOG_DLL_DECL NullStream : public LogMessage::LogStream { ++ public: ++ // Initialize the LogStream so the messages can be written somewhere ++ // (they'll never be actually displayed). This will be needed if a ++ // NullStream& is implicitly converted to LogStream&, in which case ++ // the overloaded NullStream::operator<< will not be invoked. ++ NullStream() : LogMessage::LogStream(message_buffer_, 1, 0) { } ++ NullStream(const char* /*file*/, int /*line*/, ++ const CheckOpString& /*result*/) : ++ LogMessage::LogStream(message_buffer_, 1, 0) { } ++ NullStream &stream() { return *this; } ++ private: ++ // A very short buffer for messages (which we discard anyway). This ++ // will be needed if NullStream& converted to LogStream& (e.g. as a ++ // result of a conditional expression). ++ char message_buffer_[2]; ++}; ++ ++// Do nothing. This operator is inline, allowing the message to be ++// compiled away. The message will not be compiled away if we do ++// something like (flag ? LOG(INFO) : LOG(ERROR)) << message; when ++// SKIP_LOG=WARNING. In those cases, NullStream will be implicitly ++// converted to LogStream and the message will be computed and then ++// quietly discarded. ++template ++inline NullStream& operator<<(NullStream &str, const T &value) { return str; } ++ ++// Similar to NullStream, but aborts the program (without stack ++// trace), like LogMessageFatal. ++class GOOGLE_GLOG_DLL_DECL NullStreamFatal : public NullStream { ++ public: ++ NullStreamFatal() { } ++ NullStreamFatal(const char* file, int line, const CheckOpString& result) : ++ NullStream(file, line, result) { } ++ __attribute__ ((noreturn)) ~NullStreamFatal() { _exit(1); } ++}; ++ ++// Install a signal handler that will dump signal information and a stack ++// trace when the program crashes on certain signals. We'll install the ++// signal handler for the following signals. ++// ++// SIGSEGV, SIGILL, SIGFPE, SIGABRT, SIGBUS, and SIGTERM. ++// ++// By default, the signal handler will write the failure dump to the ++// standard error. You can customize the destination by installing your ++// own writer function by InstallFailureWriter() below. ++// ++// Note on threading: ++// ++// The function should be called before threads are created, if you want ++// to use the failure signal handler for all threads. The stack trace ++// will be shown only for the thread that receives the signal. In other ++// words, stack traces of other threads won't be shown. ++GOOGLE_GLOG_DLL_DECL void InstallFailureSignalHandler(); ++ ++// Installs a function that is used for writing the failure dump. "data" ++// is the pointer to the beginning of a message to be written, and "size" ++// is the size of the message. You should not expect the data is ++// terminated with '\0'. ++GOOGLE_GLOG_DLL_DECL void InstallFailureWriter( ++ void (*writer)(const char* data, int size)); ++ ++} ++ ++#endif // _LOGGING_H_ +diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/raw_logging.h b/toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/raw_logging.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/raw_logging.h +@@ -0,0 +1,185 @@ ++// 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. ++// ++// Author: Maxim Lifantsev ++// ++// Thread-safe logging routines that do not allocate any memory or ++// acquire any locks, and can therefore be used by low-level memory ++// allocation and synchronization code. ++ ++#ifndef BASE_RAW_LOGGING_H_ ++#define BASE_RAW_LOGGING_H_ ++ ++#include ++ ++namespace google { ++ ++#include "glog/log_severity.h" ++#include "glog/vlog_is_on.h" ++ ++// Annoying stuff for windows -- makes sure clients can import these functions ++#ifndef GOOGLE_GLOG_DLL_DECL ++# if defined(_WIN32) && !defined(__CYGWIN__) ++# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport) ++# else ++# define GOOGLE_GLOG_DLL_DECL ++# endif ++#endif ++ ++// This is similar to LOG(severity) << format... and VLOG(level) << format.., ++// but ++// * it is to be used ONLY by low-level modules that can't use normal LOG() ++// * it is desiged to be a low-level logger that does not allocate any ++// memory and does not need any locks, hence: ++// * it logs straight and ONLY to STDERR w/o buffering ++// * it uses an explicit format and arguments list ++// * it will silently chop off really long message strings ++// Usage example: ++// RAW_LOG(ERROR, "Failed foo with %i: %s", status, error); ++// RAW_VLOG(3, "status is %i", status); ++// These will print an almost standard log lines like this to stderr only: ++// E0821 211317 file.cc:123] RAW: Failed foo with 22: bad_file ++// I0821 211317 file.cc:142] RAW: status is 20 ++#define RAW_LOG(severity, ...) \ ++ do { \ ++ switch (google::severity) { \ ++ case 0: \ ++ RAW_LOG_INFO(__VA_ARGS__); \ ++ break; \ ++ case 1: \ ++ RAW_LOG_WARNING(__VA_ARGS__); \ ++ break; \ ++ case 2: \ ++ RAW_LOG_ERROR(__VA_ARGS__); \ ++ break; \ ++ case 3: \ ++ RAW_LOG_FATAL(__VA_ARGS__); \ ++ break; \ ++ default: \ ++ break; \ ++ } \ ++ } while (0) ++ ++// The following STRIP_LOG testing is performed in the header file so that it's ++// possible to completely compile out the logging code and the log messages. ++#if STRIP_LOG == 0 ++#define RAW_VLOG(verboselevel, ...) \ ++ do { \ ++ if (VLOG_IS_ON(verboselevel)) { \ ++ RAW_LOG_INFO(__VA_ARGS__); \ ++ } \ ++ } while (0) ++#else ++#define RAW_VLOG(verboselevel, ...) RawLogStub__(0, __VA_ARGS__) ++#endif // STRIP_LOG == 0 ++ ++#if STRIP_LOG == 0 ++#define RAW_LOG_INFO(...) google::RawLog__(google::INFO, \ ++ __FILE__, __LINE__, __VA_ARGS__) ++#else ++#define RAW_LOG_INFO(...) google::RawLogStub__(0, __VA_ARGS__) ++#endif // STRIP_LOG == 0 ++ ++#if STRIP_LOG <= 1 ++#define RAW_LOG_WARNING(...) google::RawLog__(google::WARNING, \ ++ __FILE__, __LINE__, __VA_ARGS__) ++#else ++#define RAW_LOG_WARNING(...) google::RawLogStub__(0, __VA_ARGS__) ++#endif // STRIP_LOG <= 1 ++ ++#if STRIP_LOG <= 2 ++#define RAW_LOG_ERROR(...) google::RawLog__(google::ERROR, \ ++ __FILE__, __LINE__, __VA_ARGS__) ++#else ++#define RAW_LOG_ERROR(...) google::RawLogStub__(0, __VA_ARGS__) ++#endif // STRIP_LOG <= 2 ++ ++#if STRIP_LOG <= 3 ++#define RAW_LOG_FATAL(...) google::RawLog__(google::FATAL, \ ++ __FILE__, __LINE__, __VA_ARGS__) ++#else ++#define RAW_LOG_FATAL(...) \ ++ do { \ ++ google::RawLogStub__(0, __VA_ARGS__); \ ++ exit(1); \ ++ } while (0) ++#endif // STRIP_LOG <= 3 ++ ++// Similar to CHECK(condition) << message, ++// but for low-level modules: we use only RAW_LOG that does not allocate memory. ++// We do not want to provide args list here to encourage this usage: ++// if (!cond) RAW_LOG(FATAL, "foo ...", hard_to_compute_args); ++// so that the args are not computed when not needed. ++#define RAW_CHECK(condition, message) \ ++ do { \ ++ if (!(condition)) { \ ++ RAW_LOG(FATAL, "Check %s failed: %s", #condition, message); \ ++ } \ ++ } while (0) ++ ++// Debug versions of RAW_LOG and RAW_CHECK ++#ifndef NDEBUG ++ ++#define RAW_DLOG(severity, ...) RAW_LOG(severity, __VA_ARGS__) ++#define RAW_DCHECK(condition, message) RAW_CHECK(condition, message) ++ ++#else // NDEBUG ++ ++#define RAW_DLOG(severity, ...) \ ++ while (false) \ ++ RAW_LOG(severity, __VA_ARGS__) ++#define RAW_DCHECK(condition, message) \ ++ while (false) \ ++ RAW_CHECK(condition, message) ++ ++#endif // NDEBUG ++ ++// Stub log function used to work around for unused variable warnings when ++// building with STRIP_LOG > 0. ++static inline void RawLogStub__(int ignored, ...) { ++} ++ ++// Helper function to implement RAW_LOG and RAW_VLOG ++// Logs format... at "severity" level, reporting it ++// as called from file:line. ++// This does not allocate memory or acquire locks. ++GOOGLE_GLOG_DLL_DECL void RawLog__(LogSeverity severity, ++ const char* file, ++ int line, ++ const char* format, ...) ++ __attribute__((__format__ (__printf__, 4, 5))); ++ ++// Hack to propagate time information into this module so that ++// this module does not have to directly call localtime_r(), ++// which could allocate memory. ++GOOGLE_GLOG_DLL_DECL void RawLog__SetLastTime(const struct tm& t, int usecs); ++ ++} ++ ++#endif // BASE_RAW_LOGGING_H_ +diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/stl_logging.h b/toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/stl_logging.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/stl_logging.h +@@ -0,0 +1,154 @@ ++// Copyright (c) 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. ++// ++// Stream output operators for STL containers; to be used for logging *only*. ++// Inclusion of this file lets you do: ++// ++// list x; ++// LOG(INFO) << "data: " << x; ++// vector v1, v2; ++// CHECK_EQ(v1, v2); ++// ++// Note that if you want to use these operators from the non-global namespace, ++// you may get an error since they are not in namespace std (and they are not ++// in namespace std since that would result in undefined behavior). You may ++// need to write ++// ++// using ::operator<<; ++// ++// to fix these errors. ++ ++#ifndef UTIL_GTL_STL_LOGGING_INL_H_ ++#define UTIL_GTL_STL_LOGGING_INL_H_ ++ ++#if !1 ++# error We do not support stl_logging for this compiler ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef __GNUC__ ++# include ++# include ++# include ++#endif ++ ++template ++inline std::ostream& operator<<(std::ostream& out, ++ const std::pair& p) { ++ out << '(' << p.first << ", " << p.second << ')'; ++ return out; ++} ++ ++namespace google { ++ ++template ++inline void PrintSequence(std::ostream& out, Iter begin, Iter end) { ++ using ::operator<<; ++ // Output at most 100 elements -- appropriate if used for logging. ++ for (int i = 0; begin != end && i < 100; ++i, ++begin) { ++ if (i > 0) out << ' '; ++ out << *begin; ++ } ++ if (begin != end) { ++ out << " ..."; ++ } ++} ++ ++} ++ ++#define OUTPUT_TWO_ARG_CONTAINER(Sequence) \ ++template \ ++inline std::ostream& operator<<(std::ostream& out, \ ++ const Sequence& seq) { \ ++ google::PrintSequence(out, seq.begin(), seq.end()); \ ++ return out; \ ++} ++ ++OUTPUT_TWO_ARG_CONTAINER(std::vector) ++OUTPUT_TWO_ARG_CONTAINER(std::deque) ++OUTPUT_TWO_ARG_CONTAINER(std::list) ++#ifdef __GNUC__ ++OUTPUT_TWO_ARG_CONTAINER(__gnu_cxx::slist) ++#endif ++ ++#undef OUTPUT_TWO_ARG_CONTAINER ++ ++#define OUTPUT_THREE_ARG_CONTAINER(Sequence) \ ++template \ ++inline std::ostream& operator<<(std::ostream& out, \ ++ const Sequence& seq) { \ ++ google::PrintSequence(out, seq.begin(), seq.end()); \ ++ return out; \ ++} ++ ++OUTPUT_THREE_ARG_CONTAINER(std::set) ++OUTPUT_THREE_ARG_CONTAINER(std::multiset) ++ ++#undef OUTPUT_THREE_ARG_CONTAINER ++ ++#define OUTPUT_FOUR_ARG_CONTAINER(Sequence) \ ++template \ ++inline std::ostream& operator<<(std::ostream& out, \ ++ const Sequence& seq) { \ ++ google::PrintSequence(out, seq.begin(), seq.end()); \ ++ return out; \ ++} ++ ++OUTPUT_FOUR_ARG_CONTAINER(std::map) ++OUTPUT_FOUR_ARG_CONTAINER(std::multimap) ++#ifdef __GNUC__ ++OUTPUT_FOUR_ARG_CONTAINER(__gnu_cxx::hash_set) ++OUTPUT_FOUR_ARG_CONTAINER(__gnu_cxx::hash_multiset) ++#endif ++ ++#undef OUTPUT_FOUR_ARG_CONTAINER ++ ++#define OUTPUT_FIVE_ARG_CONTAINER(Sequence) \ ++template \ ++inline std::ostream& operator<<(std::ostream& out, \ ++ const Sequence& seq) { \ ++ google::PrintSequence(out, seq.begin(), seq.end()); \ ++ return out; \ ++} ++ ++#ifdef __GNUC__ ++OUTPUT_FIVE_ARG_CONTAINER(__gnu_cxx::hash_map) ++OUTPUT_FIVE_ARG_CONTAINER(__gnu_cxx::hash_multimap) ++#endif ++ ++#undef OUTPUT_FIVE_ARG_CONTAINER ++ ++#endif // UTIL_GTL_STL_LOGGING_INL_H_ +diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/vlog_is_on.h b/toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/vlog_is_on.h +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/third_party/linux/include/glog/vlog_is_on.h +@@ -0,0 +1,128 @@ ++// Copyright (c) 1999, 2007, 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. ++// ++// Author: Ray Sidney and many others ++// ++// Defines the VLOG_IS_ON macro that controls the variable-verbosity ++// conditional logging. ++// ++// It's used by VLOG and VLOG_IF in logging.h ++// and by RAW_VLOG in raw_logging.h to trigger the logging. ++// ++// It can also be used directly e.g. like this: ++// if (VLOG_IS_ON(2)) { ++// // do some logging preparation and logging ++// // that can't be accomplished e.g. via just VLOG(2) << ...; ++// } ++// ++// The truth value that VLOG_IS_ON(level) returns is determined by ++// the three verbosity level flags: ++// --v= Gives the default maximal active V-logging level; ++// 0 is the default. ++// Normally positive values are used for V-logging levels. ++// --vmodule= Gives the per-module maximal V-logging levels to override ++// the value given by --v. ++// E.g. "my_module=2,foo*=3" would change the logging level ++// for all code in source files "my_module.*" and "foo*.*" ++// ("-inl" suffixes are also disregarded for this matching). ++// ++// SetVLOGLevel helper function is provided to do limited dynamic control over ++// V-logging by overriding the per-module settings given via --vmodule flag. ++// ++// CAVEAT: --vmodule functionality is not available in non gcc compilers. ++// ++ ++#ifndef BASE_VLOG_IS_ON_H_ ++#define BASE_VLOG_IS_ON_H_ ++ ++#include "glog/log_severity.h" ++ ++// Annoying stuff for windows -- makes sure clients can import these functions ++#ifndef GOOGLE_GLOG_DLL_DECL ++# if defined(_WIN32) && !defined(__CYGWIN__) ++# define GOOGLE_GLOG_DLL_DECL __declspec(dllimport) ++# else ++# define GOOGLE_GLOG_DLL_DECL ++# endif ++#endif ++ ++#if defined(__GNUC__) ++// We emit an anonymous static int* variable at every VLOG_IS_ON(n) site. ++// (Normally) the first time every VLOG_IS_ON(n) site is hit, ++// we determine what variable will dynamically control logging at this site: ++// it's either FLAGS_v or an appropriate internal variable ++// matching the current source file that represents results of ++// parsing of --vmodule flag and/or SetVLOGLevel calls. ++#define VLOG_IS_ON(verboselevel) \ ++ ({ static google::int32* vlocal__ = &google::kLogSiteUninitialized; \ ++ google::int32 verbose_level__ = (verboselevel); \ ++ (*vlocal__ >= verbose_level__) && \ ++ ((vlocal__ != &google::kLogSiteUninitialized) || \ ++ (google::InitVLOG3__(&vlocal__, &FLAGS_v, \ ++ __FILE__, verbose_level__))); }) ++#else ++// GNU extensions not available, so we do not support --vmodule. ++// Dynamic value of FLAGS_v always controls the logging level. ++#define VLOG_IS_ON(verboselevel) (FLAGS_v >= (verboselevel)) ++#endif ++ ++// Set VLOG(_IS_ON) level for module_pattern to log_level. ++// This lets us dynamically control what is normally set by the --vmodule flag. ++// Returns the level that previously applied to module_pattern. ++// NOTE: To change the log level for VLOG(_IS_ON) sites ++// that have already executed after/during InitGoogleLogging, ++// one needs to supply the exact --vmodule pattern that applied to them. ++// (If no --vmodule pattern applied to them ++// the value of FLAGS_v will continue to control them.) ++extern GOOGLE_GLOG_DLL_DECL int SetVLOGLevel(const char* module_pattern, ++ int log_level); ++ ++// Various declarations needed for VLOG_IS_ON above: ========================= ++ ++// Special value used to indicate that a VLOG_IS_ON site has not been ++// initialized. We make this a large value, so the common-case check ++// of "*vlocal__ >= verbose_level__" in VLOG_IS_ON definition ++// passes in such cases and InitVLOG3__ is then triggered. ++extern google::int32 kLogSiteUninitialized; ++ ++// Helper routine which determines the logging info for a particalur VLOG site. ++// site_flag is the address of the site-local pointer to the controlling ++// verbosity level ++// site_default is the default to use for *site_flag ++// fname is the current source file name ++// verbose_level is the argument to VLOG_IS_ON ++// We will return the return value for VLOG_IS_ON ++// and if possible set *site_flag appropriately. ++extern GOOGLE_GLOG_DLL_DECL bool InitVLOG3__( ++ google::int32** site_flag, ++ google::int32* site_default, ++ const char* fname, ++ google::int32 verbose_level); ++ ++#endif // BASE_VLOG_IS_ON_H_ +diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/linux/lib/gflags/libgflags.a b/toolkit/crashreporter/google-breakpad/src/third_party/linux/lib/gflags/libgflags.a +new file mode 100644 +index 0000000000000000000000000000000000000000..c0de874c969cb05c58fa24af1293f65642b26dc0 +GIT binary patch +literal 390804 +zc%1A#4}28G)pM8IaKwY08Zm0r)S_Z7n1m2Otwm(5RHCU6MN2$GazHfynp_ZCQ>_Oz +z*E6kJs8q4VPpW9GQj3&U)Bq`nqoJmusOwG>Dp)um$?CgnC^7Gj9 +zb!mh+3kdl|^vmCuzb}7Z{)X(Aa`&n)fB(fl*A3@?`TO$s-~97kQ+?z0MT?2=n)1q` +z#j}0za9Lj7!UdJ33+sJV4FUfWUv+7fzrMD#%s;6R->1&@2WHmKE?wZ4G23MY3u|f? +zR{E!W%OAL~ZsFp3L+oT8YYUoVh|SI6(X$(>3<-I;MRhd`>q@I;Rxhq8D-BfCR9^-t +z88hc`nBw}*Xsh +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 +z$|ngn@Nh16{J(b3 +z_H(;B|2aEaNZ@dA*!?hk{`ZSN_q#m*A8&KOa(;Sl9$U^=*DT@-K^C3EqK%OSBJ6^O +z%1S*cUxzm)OcwLhqlrpSo1|wlrA!rb)j~7So?$N2Hf@rab4ite$wWPuAzsU|*k4zV +zh6ZyEF@ET;4;=2H+9Zzf|GzsGe|RQUD||tvzj|R{5jRIBUuqG%oyc#KetC}6?i}eC +z{V@1{$+^>EJ$v~%ZC?&*olvA*N*II}*`mX{$zT$>lR!k3)m6;*U(WbE-r+aH4#Vt4 +zH8)ZdJzB)6`4@Kx>nd=dyR>T=6=65Z?8vCQqql0+E)Li74}Oj?4Yf%;>qlU +z0}EBvslJ)z{^~$QU@1M;qaA_9XMWPh>Ii)3>ktfN)OBIKKahlANLbF{`-B@-1Nj%$ +zh?i?N;^lp|M!ey*?i}Hc+#ojO2Dhb14K#zZ*H6XunqaS=G-!MM;I|iJ5Fj~|`($Qv +zpK39=f9bk?*tSWI&~^I}=|k~8&@xdqGpfFhj-VdZ5z-{h5z=9OM`P$`G~;A)*b|zu +zm?Iz*`_@MO&?zxrpuLjV(_CUc)o0OUcsjwXny`o&gQ)IsF61XHG`?f=B(leIbv}sN +zhhfB79NtZi?GAnDbmKufNFS<-lX02;U$%vqdl+~#zK7hQ4>#FTery*ZMQ@N%zvjF#X4=d1w{5 +zxK8ww$eue>y|t!!vpoWZR`749t-L?~BQ(R-*>N1w591sX*G2s>);oCb@WayLSYHGh +zmSy__>I+`bPY!>ADXVFy4kY!3%fk}`x?kVcQT?qFLlC$j2F5f3wy8*jv6wIK +zY*-H*9NukoO%?qDUCBADy8=hHU8MUDKCHbf^;3hxF?^En#XQ|Nypq+{JM+XNHBzar +zkhQY#N<`iy+r{aPHFZYEW>YNJE-uob@!|zJ=bY?8{hOMnK3$hqSuvkGa;q#I&z>gK +zoMRX5tMk{^)S-K%SO9t>Xc=keJ5dDpiMOU%6eEN4BS?;{mi81d}SVBJFVU&j-^RSnP +zpYU)m5BKq~kB9qtcz}lodDzdxPkDHVhXXvsKNvcAn8HIB4<#O^@^AzX-8@X=;ZZys +z#lv(SdU<#Z4>Nc;hKI-V@B|*7$iplip2EXZd6><^(|9@NFI{JbagjJv@A$hfyAW#KT@5?&V=04-fFLpNEHdNSrKm^3cV@ +zR35r{n8rg74@dLR%fn-Mn8Cv_Jj~?bi9F2W;VC@K=HY2P9LvKqcsP!SU*qA|c{qWG +zIXukcVLlHFcsPZJ=koA;9$vu1X*`_H!x=ohn1`3}@Y_6`#ly>ZSj59CcsPfLSMqQ! +z53k|jJRV-l!|QlBpNHi{^LjG0+(<_96sH-w6L(LNms?!m=mi8awbRzRLaG +zkJ1bbC`@bs!U#~v0g7A0lHAF>J9S7Jabi%ud1n5G$JE*$T)eE +zu-yOLwmWFs-G;W`IGwe78f`Z~XTn1yA0AG|hqK|~tN3slJe-9OC%{7vK6v3_GCp7( +z7Z~e+()-~xOrG0jc%SAnLrimPc&Ra7Xn^vafq?-FY$l5d7gGW`Y3L12chQH8&~$9t +z_GunM-?Ku~z4Re7G(7_nc1**jk&f?ymc5A$oaBAdNn#oHAGJ#qClhygEvF>++FMP&bwm +zR2(6>7f`1UJkqu!m`4ep%sJBD-Oz +zP1y=`YmyHJs}x62?s7oFd2+Nq@0P}cq@gwPwHUdhHn|%W5=f=_p4R}Dwft~W`o@xj +zJD?0UCSsNIs}`W{S2~~{S7M3j8==(Je7#T95!4@S><8&V$9i!;jG|kZ^q_-rE6|5Z +zkS1rOQjCHJXXF|dvxUXbvF`|d#}%0#BmQe*2_ObejAYVBjKPFCAUJqq_?Ytmexc&N +zP$6_wU)YPR1AltiQ;~~9xfzrQ(udWGFxqGiws^(SYRG3UuRlzSB2%$jD6@XHWeIs! +zTJ!8c1~5w}(##s}jVZ~lx)Mf07E&A`J-`H0w+1{r +z9cf4&^xJ%9;heR*`=6b^!qj`Wex;p*oEeMNc=`xVfw0^YY|Z-awZ0Nzu1Vime}uYz>T}j~L@_qVeIP3`(;MwcM2;9fMH^$j?l>DXok_q;8i791$1%g&vg$0D}>1 +z7IBzoKX>feFIip|`9HZ4jwPFFQT}6^T@$5a+{;27$ILWNDXPlrRydxr#irC>TH|6# +zCUu^5g|@LWgIisp4vJT(BiQQV@>zs{|vSKuw0{4ZAk=n`|2n@{9 +zt2{*KyQ$llmUNFWV+3}r;fIhY<9>K;|&UboY`Jn{MV +zGr%<=4iFP;aal%ApDia^cnNf_7FTF%Vs6@Q5dz8~jq`#?1(5QiTs)v`24IZMIH+kzu~#WL)j@pdm9w^lc5dmj9ho{VO6P!~Oe+^A +zggA^cXb)|Yq-#Z>iY~>MB$X|;p-AQ{~wDyEK{PsaF7-fISOAM +zWiOz!lZGcLtGks$Of7hBtBY`c&Y=8^qYWW?wJNg4Dn6_N+S3s(G0Ut3t$X^Asdanz +zX|1d17h1RH&>&j(-T|R?FC8$p4pw7Ic0clbG+gXa&c?^$D8{aVx&NLV%&cUnf8@U{sOziCWWUV%7ex1K9m{YaGURHU^HFcE2%jP%K)J$bdK +zj99W17NnpbQBBYzJgaM~EG92Qgip^y@_o27dogzQRR7U2D!GxD0TjuXqkP$j+U8L +zTK;9P9W7tpn*=R?xc4wpIWwGwK7$Yb!^B2_J`# +zJn~4II4*^EHm%eNr+%K^fKs`UhPT1Y5`ID}l&F6!l*N2xh@@BLe@T4C+x%|Ab8jOxlJR +z+lFLMu+c*rcGy$wi1Aaka24HyyCOppS0+;Xg}G--+$cOla`gDsiLt^NEl$3(q&l-1LM +zjeR6A8c9s&3Bzhuvt7H*nj>2BsA3QL2P2Hq9~Dcdy27VXT~~NG%7h16n0mqlqLnN6 +zGr=&IB`Hl7{LuUexI39zubE--Ez8g%y&r@WuHjQ!t8tNWS|?c2?7E^@wVnuj3qN3c +z3+n}|s9O4U#@Fu{U#A;iCmLVJvR9_;1jdA!QJglUxL?&@o)a<3U>H$g+QXM|rqc*O +zZAGRM&*GfyN~XmALrIkQk3+FbG*fNo=SVe_pEFGI6XUYYaq0?6<3s=C@01qmk#L?^vwL4lI?OQriY~&y0{u55tf2QK^erunT?1(B?v6ryi!6)s8-@qEY87Tb#5RhgnYnHok34*$0 +zGb%`ma&m+c2$``IS^Cj +z!Q>?av|>)U1UEXAMehv^Ox;GeOw*Tbpo+Igx$gtqM-7}GF3v#gZ~B0BtVg*H$0bqj +zjN10EW|4n^4zw3=puGU?m`wGo514^BL+$Y$Gsf~2fk#kly#2J}yW5<=U)aqVYHxcdPo-Aq(IWk@2%2bAaEkHLWH%kY>P@*U2vlmc7d=O$#jZTt<4di;H6 +zU-l@!d0)hO9`NZL4I7T}wFeo-c+P}YzhAi&$K^I$LC-!w2}bE=J0NOt9RKWHecw7K +zj5Y(@?7*>Mp%SziGQWF()rn`7@Bl)gNLXPgaTK58;CPga4q`J=FFDAG+R2D|nS-~b +zPr3O$*7;uL-q=JPV)bl|>>1NUW!$>r9b=E9yZ*4m{wptRkLgZ6=Yqnu=>D?wzKK8y%tBG8Iot=rRthc*$ +zBo7=CtcPq()u){OHnTe(g)biVf*NhZ<}fq8wZ4rV+k;d0%lL@XdQ`dO9on%cq0rcX +zbx{7IBkt#i3}(Z7-ezXQsLFlxTuV}x*5hN?4!PlQvu-%7`6o3TVy9pBwq`ZF`k$KB +zaKS%qtcKtFr`c+#>PwgYTho`;yrt_)m+AUav%*+`>PtU;OQ-URPfd!_b6tX>^hlRk +zQF@dsO7q_0iqdslQF`DlO;OtYma4NPr6^7Q)TAi=8S+OOv83u=O-p*Mi_I;H^0C0l +zf9oHVdeqi$Qjacw%c>rs6wt*^;(o6`WbJpidRPn3?PMCy?JRF;NT&z0sKKrq7n%rl +zax5rRrMiE@p}uN?@-QeT^2tI3IV%=O3WCf)kepZ`h*IP$2r}6MlEy$JbRca!H_*d*K|ACq +zo7JPi)@;Fg{r`Y_@pK?tk%S66nFUd|e^Fagvu8OY4qZpUN}w~e?X16sb~Blxh#Hgt +zb5^@}>TaB7WykY2VKlZYXbk&-V22ZCd2KW2Ss~p}2H7qjB6>Mb*_Xq%#MR~?YE<3o +zXF7z=M;5pgxtFhnVqt#g@M5l&qo-5pOV6-`3aOe&53{6iEcu`bhRajbn3rLu=MLdtFFzqlqv!VXhgz7@J<64P +z=mFB#LLVvLqDFR)QrO8BkWp9|1gN6#R%Uk6=@}nuyHHi@Vd}OA#&e%Kos#IaX7gC{Y=wA*Bu +zc2o3~W4oyig{@^LqC4?Kw5-r^n1bUOIt{e9929FJH|l0;+WV*J?}du8e>byZ^M3Dv +zevgc8Mr%QjGLfb!hN0AhLuu`&2CJxMJm6MK3N80UQcjf33M&21()M} +zqwVy~!A>snVjghO6AT+|LDorzM +z6oc*IyIk77l#m)3gQ{UkhY%Gi>4;SlVi**Lw? +z!{NZ;krRRNc(37^c6v6v+2woy!=S7d0-_J69!YWDwp@w|_Di^X)p +zNZY3f6LFtCeoh81?%BHy#_iaqZPD0%WI2(?kUeHl9?}+%_uoYDBz?n4(6zI4RRjb< +z0M`#EV{(}O6*7V9fMmrTIYTU!I2r;Lv$y>EnEt?_f4wX1RHxv +z1FUuwy4snGyJvrV3B{vFyOf~NO9|h=?YY1)2=I%SsId(eu^-Sy><74r{eT10a=dh= +z@Pwvk^6ZF13B^HCd(dd4xOhOgqhLuL7dJI6Zfeh=c&RVNOSn^8!P|xMER+e6vZ^k@(ukeyKV(Jq1^uuZB2fC +z`@lf=eNJYrTG>w5w#w5l@c0Nb! +z#1|OJ4(KG?V; +zTO?{-?9-VpYAqhx!L$So45rhc3#trNuzHQ$(1Dg@;aY``<_~bG1+d83IzRLYg&EgQ +z6!=PeU}%v&{9Jo@YQwR%PqDNwefgDKPuLYM*(IuN_@=RxX`gHyy`+ZqpF{Ne)v5R> +zstn-mvWS}k8f|p}%=Zm$Mc1-2yV}W`$oJ}1XE38fWI~wr8dZY@%ei>F4K%HAaRyy& +z2+`bbpwA@>=+-J)Ye@R?eJ;eM7u2Wos~e8SjkXpCzSN{IyWC-tz6Xs`OwkG6g~I3> +z2a7cm9&e@M-VcD8n5DUR4`y6UGj>`s?qNu0>KGWr&+2f=YJ>P$jl;Ur3esr;>9T@! +znLrdPh$4cVC=h0cyoPGyAEjV#GhktcSRIyE>-`Dzbqam4yIbfBMsPuX9*93}Tw_0N +z$n6@zcUcJDrW4#cZM0bk-e#pkn~7BIR*-fR$Sy0$E)z(H6{N#N@B?Oo|H!Em{D4UC +z!qxiTM2~W1D`eqTEZrJJ_leV&y+&8%JxXpXcEs9vv-VD%{H;jEr4ANrrecdm{#Fb5 +zH)F;S&Ddg@(l>?WwQRcIY)RXI8SkMPH(6@jVClCFR&s7IQGAmXWRnSGvlV2s38cje +z(qaN>wSu&oKz3R|cA9#Bzq$8=MDP9mv3g%0Zbq5<8143qFs^`3qy4|tj!AGw{7q2)6=>Bd-S`6ck+4lk!CUZY{7V|@jfwXYW?RN}%|LskI81>}EFQ>;mx*07kqKQ@WH|KF@&ZEQ%@qC2Vjlzd_Hh_V0wy@@ZJ(ee|z^ +z0wEqZO^D<875DikQWElm9Y1PCLThJ+e$=y!FuKdDsD)*nNb#_|j_yya4mPfq(r*jV +z!v?Fvu9av~!;@;Opc|XzKk5v!j^1%)>&Ug}oCFPUYyU(?-yiAZTf7!&1bwd$IW2$p +z5-OKggiBTkv7wR`;o=p#2D6SkV4!4u*1^a+jj#c(sfnwa<&An38<}+2r0!*@v1-Kw +z4!z=yV#V?bL*rDR4XC_%vHq=b>VHzN|4G~WHGuA$h5Db2*Kl+FJL1&8L9c&Iau&r1F=>D-#@gHI|ym%F@TNK`r@6d{#&?|aEopR7I +zg8=O2DGDmE$)w2aOM*$UE8`-%KxY4UrJk8d}m9#Z|%F*5XPIVaZC(!7%7ssoX(_X4LF^qR>Mp(Bq4C +zyBch%>JnE>VxkbMT?S|_-f3M*q4`aYMv4VE5#^Jeh6M#RQ=ig|rz@jO|L-vA|B(Vi +zjXidYH|~-~16$V8a0|6FX`rp|aZr8Hy47NuF|2W!Axc=|wnR<~i`z-9%rveq!cMib +znu!K1xmA>!cC_!YrG1aie{SAbL^|4|HD5r1NgiPy5G9ZCd`_@u3EPZ?j#$10hpW69 +zmGm8Q3wkAkCT^f_JIB$twy)7(-D5QJ(Fycz{h#RDh8+5~DUSx!4HaHs=nv0WzS$%^ +zV1+>4e30$Lu|r-(4?6svvL!;Viw#Xw=yguq!s>Sf8~a_0?}1p#?{_&>k1WAH2^T1; +z4;`_S)gt^9*u!?fJZce_Q|x=wh?;nQPQzE|aXxC_SwcOU@Rzv_px^dtR(|!OyIWJ6 +zo$1SdPxl&EJ8wP;{yGAubiYH#;3U8iHlB0sCZ98bVl;RxSJfr +zr6XLtN5my^jkWYQO4^ez`b1jv8*=*_nQDNTJHEv_{3P($>@7FeQ +z-a-y<%pmE@e#f|4x$_CkaSJ`?M<18PGc$?;6IJ#}Y`?{7-_^`6Jr=VIwNJ`UTl*wV +zYs*--bXn4#_wX3%Fx@qOAvd@Z^FL1?O~J+{y2ajv(J$`6=q7#Yyq%8jH(cuIR`s$q>$MT^oHhdP}D%$ODxzHE9}l#usf}=ZLwh6tg!8|VB1Zw +zrx@5mH>plHW;}kjqyD8&^;+rOVRt;JE33@?h +zouH%4S9QAmdQEO+#iMLvdB463yJBe6 +zL@$tN4q|v2kL*)d;h-#aP)2jJTSF9+i_PUY6Xd! +zKzgkpy&}jd_KPp-l~K(g>{YUe9x+0fM5=qj7-av?Co0)Tad@CoK}uqCR!Qa?cy& +z4ejh?;931B0*@+v)_fG<4Y@8--;n#>n8#|$;hQ0lDRn^ipOC2SNAr~p +zU5j-8G6@P~ylAFCT{KAwoO6hsvh{{9afOOILWO&H36;-S=y3Hjj1Gmn^o>1S_b^i2 +zVWkDyd5ilwvL5|P0d4XJhlG=nLr)XZW~RxtA0$bWlRk|>lete@Xd*v-#5DP844UK{ +z=)msQ9YqUK)N$d8K>;eB4n0qehJqby-unUt`r=UFgnoJ?8BewIP14q5?6J3;tft1u7=vm6 +zdXihWNeXkOVK)RDKboDVLi;&-OgHS11n9J+fwT2tsri^Ix1eqiWB8*XKPoC4)T!^g +zhqMEP-OuZay11mm^DTCZ%RHya(9))zM6udg3|a|0ej#Wjt0Pwmb>L1&OICBS+2~@$ +zjUGVFYA)+ +zYuTWsjkQ>=m@P}hY>M!bn2sVaufu8p>tJ>4(lhNc)w-;up=rCkU$lA9;?THZDQ>43 +z+S`kLS+d`7%5II`{o>g>!^y)nruCawVAna}61Tk#)_4v}l0sSv#vd+7OJZD*-` +zx4uz{Tj8E&_5PN&Xt+v(rW!OeztrfP>c3O^#G7v=s`6iyr6)-&yCVe)9 +z3kLW$nE6<>wZslnrG{Hh45Zh-7YwJD*?Dsf5-m3YbPE;c2M+Yr9rw%$Zl_PNNuI_f@(cA7ll)V|?0TJ*a=B`C~@t3jpfJ@oZ6kUHXatfYraN=0nZ`|t@ +z_)TA-pDAF_BVxe4@FveXWfKaNOl3^FvjL>@TaI)?Pck}xX7g|zX!jM2|SK+si{ +zr*^X4E#{x2dj~t!sc&?huz5f`z`g7)Y#u^xP>z3`Uqr}Y!^+EsRS(muG^K4(zp7%G +zcBV{nWnH*roq_u6BH}$$tnnX@p;=J{-JtAvjKPhfH?08iNS>M)Rj%2=5>r@|;V28d +zt&1f+GGLH}cAHE%*4q~BOqG^Pq^RL$LKK~pY?luZ=BA|ky%gL?jXK!E2-xR1zC?Pa +zMQ5yrH;~!V_%xu)eR^klRG6MK!L?RkD(M< +z8!lOEIC;Fb`x}7%Esc+nh7;9q^$6K;S@TsCoxh`^^LHpZe<$n^#mF+AI~YTc7Dy@j +zQ6H+uNZpS(4dC?N39b{_3d$9fI~~GKpRf(UMLwz~UN+5onBu3N*}=a2_KQfhUDS}f +zAS`#lqS1%0iwfHXFHg)Jk~orA?$=qm-N@30s{)LEg1WNSa#);!w2C0&o@V!5R7NtW +zJz_`ThZKQO2NwTlCS*U!6yq21> +zv*3ZAq&Qa9($_2F9%d`NQ}E@ahmA->t7So_7jGxU*6F!T3l;~WU8}iRJ9K*W%S<@W +z)5fd7S?L=)j90pKE0hpxvO)!v3!XEG{$0sL2*i@zemrUvhzhF*$E^|QTj;jqVhDXpC3utK#v#&8#{r! +z&rUJip=UB7&b6+>lo+>xF>xVHv|I<4+rspAog2U`d!zAA1F)-1l_~aDnar1=!m4^E +zTpae;UmR{VihjdE6tQFX7(3Rq*{RE*0%NxQCVt@2t)|kX4NSF9d=$G%Kjv_nvAjNGdEHx5QG4~Et;=}$!)oGbiG^c} +z3CA%4V%?dk=25-Rgu(@MKzyQC^ogM-BtWlsN13l(o&pn;D7L*`KLcnPPvYLRg^n8ahck>7a^+N6n&PjZri_ +z8mlKBwf2Ni>zY_S(QDrmYfPn?Pj-l~Ypt;BV!^Jn!fKQ^cj(8a4*fR>y$irh)+s@f0@3M!T5AL_LD(AdA);f?0v71)RCQ&_B7_TNG8UeUxAmJYr>T)duf +z#vK;UXwpx6-EPVFk&f3#2F_S*=8V;5&S)}n#_Cu!Uv1?Kq1L8Yobi!8XEa%R@b*|W +z-)@DyBNpr(R@fD>U{_dSSH*%|Wr7_e@Iv=GVivL=n!szDiPc-}DUsvX+KQu7%R261ytD=rzRga^4I>k@XtPH9HF5??uG+JBdb)O;` +zOckOA$@~QEVYY})W{c=z{HU44p4p5b`IewVBUA~)|IPOLh$K7a7dy}0kQ;xe88EcjO#=(IUb`V6d*U@nuaQ4ug-j-*t-s*{OndGYmbSrRNXx>s-|@6R8Pd>o+plTQ{2F`a +z*UMT0XNA$o(4ka927bg3za7AP#Ou;;WddTL*sI$LY#!@iazne3=zhzr?n8^Ir&*1* +zdqmn!7T$x6Ye>Kie;t9NBFCt14C0;%xV5l|^j +zh0JJn@&)FBhaSg$;B_Q0lM9`wAcWam;Ml4ex2YYMQL*Q?7apg@C+{v4=-s556}08vS0Uatrp1BrftM{a$;V +zwujoWOol#s5NLzqTgi6dv$O*k%B+>KOm*scEiXT>CAP)r@$bq*!f7?GRP+hX|Cw7S +zn5Bd-oWMk@x{EJhgP1y>ZO(Fr)$>nQ=V5A?!Wgo5s@!waR-9niW<=Dq9|yGBA$Kve +zCTR9r9aLIq%3K#Ksq3aakOt%YC}AhYa6j8Z4Tmi?E>ZofqG!Tsc#mMlqwK);jGHJe +znhQPDhkmE>$D2`7cQ%6zdG%(lI4aGB9ZJFfP*&*SdoJu8fk!zV3)qGipm!knG?#KL +z#>^9q5iRpz4jmmP{B>%1QSP@Y9L-wF0I5w|MAmn&68uA2<5( +zj%UUNgs(M;$vJl51e<88yLpYi%C$YeEIRPA#ww%lM{e(n0hX^{ +zGG?n4tL&}rxj|a~Nt%0GgJvhM7Jvk2>}%-sFfB|Mv6?Yk@CbvC^4iE)^hr~)N-abH +z2$iggOkq%AdF=yZjVCBDgUeFux**IA4W~qW)NzQQ_N)@FY}`MVjUks|BX?a$el#*( +z$HqmmS!Z7a0}oT%O(sBRaB6wamY4vZ%0lXLUOfi^sE#8V6%7iNydHtvmiBB2Hg2F) +zTyLbJesB*SA@90I~^ +zN|B0Q)7~bdB0`1bwg>Vl759r&%&^qj9&BvasklD|74tPJ3J3Yx(W$vW#SDr~dn_s< +zINNBZRP>stc!!CK(-{?~=u|XpzQ`Tw329?{_5>UEP%3s9sVJ;e_kcbuQZdsAz^S;0 +zY0VFuPYfGBm?6tjYge$bOQ&LA3@V_WHL0u{3;HeIo(*u`uJDit$LRNQQ$ +z;=QR9)oFsvRK?&75?hXD>vGhzC1G+RzE7ZwxscA|IGF0XNcDS+FeuX1(~zkL1TAS; +zXSs3rBsI%9?m7Hf?xX;l<-WDnG|Rd6sk0oR|8_#xTtL+`f+uXC2s-~kGJSJzpO)!B +z*wX>z+wi*qes{p{N%;L0e)DT;DoI6kU}7HrEyyPgEGVyOm|y89^?|yI>V*JzGSK)8 +z_?-j4De$`xe&2@QRi$;+0C8^iY=5A*zI36#&|iM_2Y$zlAY>B!mYx8x@Vgs+55n(B__f0C@e>Jo27WKX +zZ_kP7q=1kE@cR=?H@)!7JByGT;kOxnpTKXizbsHwcka2qLSIF7y}vHtD{WXpvdQ@I +zgk)DW)CaQX`?Kr)f$W;;ux@=<2m_~9)E~z7dx&}X4P+D2|Kp9XUJgxty4Cs$uc$V>41 +z)^y-;_2RFmo&QUP7Ju(Xon4$ZOP&f7@{5(i>+>SWg}01mj3 +z=OvgKv+xX*?`dj2E7vi8 +z%MRRFQRdgc{8hDqrL^u!Xf~7|s9UNfQj|_R{cH870WT~BE@8EuIUcGx9cWQkQw0b? +zZ!A?GV|F>Aw8$Q}xS}+B{CEzY4J{i#Ue6AEbMdSTzct%Ova4$XK$Qk4qM{mGT~Sw4 +z4It1l71awWsw)Ei>^gs015gDCTAfV<7?qSNMJwvFt19X#{VD?W*`;+08xV|~#{kRy +z^<{Mxwb(W1g7Q0~qC9(PO#>7U^jex-g)9pFf!)FiM5;psjtQOa-^8PK2D-7{DXoX{ +z0bw9~RZX2Aa+M;!Wx(*zFl4QI28q(sT7hq`-VXmIM891E4a$1`4VV06Uh^Mq=gVOJOYVcaU`0K*;7_ +z0#ptly8&MHb!F!)#QN(el$DXnn$mKLO?@`@AFU2(pc0D5BALX#`EEl!Amv|DTT>Uv +zX1$Hjx!<6)JhLQG{)z?JwRQe_>_0*%n~ksc!|*5#_>tX!hhcbWL%SXc4w(W-f|?sj +zm(s4JLv^W1urXc*$y|+fU_xzO&BD6UDk>Q$L$aRCE@kD@-k`-}P0#@|3yUtlV$Ow^ +z%{iAhprV=)k)lN*7nLsdYYbSQU06JOPBsz*tHV6s-~zR#uBtQuqX}xPxq;1RIHRIc +zhboD~nc~VG#|PV4*{&3)gA`wO>1CH+b(zXL%n!GV8@$|MGIeV`ok!(<{K5+VIKp%4 +zY=~ZrOdpZaW=guz!R%It^!P|TSUou6r1b5Ry82L1>+ +z)bznYTd=o$H-eilRBC%RWD{E(9_r}jc&A%G<+QmiT +z3WbjqaZq9Dm*8Up3w<-24qp94c&2bIlYaS@j;CO&>%0FAoOZaaGQ$&U4-{T^pS3mA +z4#KLU<&RabZ)6#b6sMmsCCwRhm$%vVHw?~dZ+1Bn_1fW3ba1qeL9y^OkFC7XC0@xk +zdyY(k)3F@GO$F2F5icghl$P|Px>_ptX{L1x6{BiuvH9kMCcwkm*AeLxUEapYr}3D5 +z3cFj#X+^(LJ2<)|M-3ecI_U_@GR{)g`IoV@McUZ&bLe>-2nl4%XW1XIM}o@9n;_#{f4(b{4B8cl`!a=LeZUzcD0$_ +zouHoQ4UdLZ$AhA`T{CwT8>+HlpZ}`18l3}K??G9&&z7|`oNoC1 +zCf|}Y=n;U+@m9%%H{spPu>#%bG2Y5bma>dLXWlh-WHS7T8fceM15G&3-4%bHv%s&2 +zIorpai)}}`d4SU=kM`u%o-$&I1g04xvPB-@*{k!J*TjJuCT@&0ob<48sWBUahu~1m +zY!-diByH$d+VDc&n0vZmy@h^FolbzpnFPn_DPh&Ox9~+IcUDmL +zW(BLLgI#hneivNDd>np|)_8-_LV>H0#9846=qAm1TzE>e@G+6hW`oXl6AV9L=Qt!s +z)jQ5=mqdfDS>L_ZXVRbfJxB+?qi(ub8B>2TQ-jhWSmkjAtGq6)Q93;imkw-~K0d@a +z?E}Aw%Zk~DfIIY-H|q}uS*k2p-szZerY`U +z7JDCgF5vc4j+;A6$|aZa=dVje$WC +z4)QU5{smI)kDPR4mN|azB;?O2QdI>;uBdX2{)cMcv63_GPAPV!6V8HD_c +zBjg2|+UrW`aY@TYke!mWS0W!u +z((S2aO={4glXH+|-EA)G7lyJ19A{60{MVfNFDF^!ka`^C4-V-s4)P3rUg4A=em6Gk +zAa7mTO~~#$RL=XFG>264lp7joYX}5#i=@|8x1N#r2A9PAjNTkIn +z{Y)ZzoKlaA>~~7fxya)w(n=R;O&Rk}3hAWJKXqaJRu{s&?F@PrFJKIjz0I$ +z_@AX9%o8aHe~XJA;F123O8(`N9!Vviy0H3tB&kaxk4w@PiTs&9zd_NuB^6;FNJaP$ +z5ykBzq`#$+&JohOG}1ppTAoIJ>6ZRIl04~_o*hYEbxW&9l6TzFemD7uKCc{!@tZ~> +z%WrJKjGv&{saiGlz!^EXEegRG#cTTr$hed(z7U8rjFVM +z!+S5xbt&Wyr}WDd@~BhVOJx*Dsy6!k0gb;a1z}o{yq~08Pct8jr>n{)Jm?_5#%^!n +zeSa*9&WZ_7IFQDKv?Yih58+i4?s1TxW6TCMIv>JoC;Z02B=xgA`lR`}1Q<#Bv6H;u +zklt|MK!xWuoU3MF+b$pTFBf?bI@XEVb~(t4^!X3Ye>v`Vk$YScB=1JXKIp;^dJUw$ +z=;(Blzq=vkfSZ*w4Y{#Ex|H~VdmnIo=P_u%Q`+Ms4*_>Lk%{5?Z%zr~SEu0Lhf<_h +zQpod2oe1Z^`B=vJ(t8rQ%^}_9B&!``*kl6Fw>YKsPSTWusrRKwPo$7_^!Y9q{(Z%f&Sg>kUAZt +znG>i4!84^t-AKgO9OPxk(~i9(uyg~kdB4F +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 +z-Ho5}^VtGVBH$zI=_Y +z#Tha73B>4roZu%KJ6#rR_KMvz*JZ$o*_YMtOo&@76rH_x^fj7+47=0;JhRCM$SRF_!uzqWZo9ny81U0wXIqtC0tvYWCtN#;A{Uz-hFBP`yJKToG*_{2@Lf=vI +znPs#cQarjsP8xQGrlWzHI$};KrhDK;Zr#Y#YtPBtL9lwSSsbTF-(8A?ISJvUlhc2sp=o&itz|a-sLko`2SREKcK6EjDR>TBRKJXQez1rh17Zh@dO~t?{-H}ZT5ME-CePr +z3}!3+ytGGEU6l)<<=sybh8f-wq<+Crg<*}vuf=vLmGrR>w5HGHT)r2^Xfvt(uEFmGjSG +z$hz`{HuWguJbc}w&^B?B{#_#UL${}}<%LF8W>8hhDq2&6t#b@#_2TZI5B=HHOm;n- +zIKE#ri#Tp_r?OX%%hlvSKk?Z-{UH3P`IR1}8SP%~bm7-c@YWeYukM$?Zw|y1$AY5{ +z<%20$Ci<_$Z&QCYL7BJ{mzP4wQI5oA?u6e3@cLk!G7&Dy+jCkRIP~nE3DM^QF~-NN +z8z~i(e(bu9)_(~kF9N>#eS-RHA^Jo&&?*7kDt>SO@dR)!9PZ= +z;c#D1qQA>IEQv)+UgqtCD035sJvKpmIyu}|62Q4r7+gHQK)4(ZcVYs#xg2h00=Qc^ +z-05-PkRIzeTxm?&==_MZ?BMX{B|%I22>&ihfa}*?iE%}^Ij-breiMf~D*@bES8}v$ +zOA^1{B=O6V661$`Gea6&-vp%O`UYXwaM-dWVB17kPkh)u4m%scGGoIc9meuWA>LTS +zGG}qPGjW`ci(lrFB+5j%H5~5W3E*}nSza_XxxUXF!Qc|fgJ~Qto;*NOEaGsud_MhJa=Pkh)O5%$6Ou$gWKTZ3Rv#D|^1VRK{AK@N|_>4>lY04#pOA|nnB5N&!1yX2(AvT+{3U7rNpG7oF> +zsR?NFD2KZRL9UBWn+^_}NVg!P7+k#h0P7w%N~n8D{JQ6iO0MpklBk>NKLB?-&~Zir +zxHf=mKPkSBk8SA%xc33>Te0ATv5-BQkOEj&Kb8dSEP(9-*dh_4mUOd+zJjSCxF|W +zWO-d2E>U|uUIv$FU7pY3)+5Lr@nz|C9QL^+_~&*G+mQtSYy#N%r^c5pSY{`{EjyL1 +zvl7+sIU16o@dZiXIt5_Q1=vjqU=i2yqglHW$+z1%+-phTx{1S1Oaj*~4tqJ$b$$H) +z@*V?oKOp^366Kx`uo-6%vM@n^QT-QSZ#t8ZbCM``#W4)usw7}rIBZT5IP`E>JhR~X +zTYNfX9?M{<+V??x*clx5VT2vwj0;=KVS5qwUZAzYNh +zCDJJ~GZ@_S3E-x2xNULZaE-i(!!;u*3+>v1kU`gvQ@H-m;eU|?543Vvy8KxXpQcd` +zdne-Y{rEJ^I*!5qIROo3aJaezG^hl)y8wxQVBPn{rvbvR=H)(u@?b-Jcsl=c_=W^{ +z^m4eTshmkkSnk*{$(1_`;4U6d$bpz+(OB+H06z@`LV28WvCq~5+^YchV=Q-;9lm=1 +zwsTxx#o~St8y4&D2iUE!Xq}p%f5*Z)s6PQ5)qeo4AP?GwAffnmF9Fym0QP?p)V&7a +z=1fd%x7~?OR+E5>0^A)*z-7W(>9Hi>rU6`A5^#$E?%gEd?f^J2hGid+-o!)C#nam_bXeO|JG9ihQq0@I-)1$t~n96pH+ +zi~LAny_R(;%uTU$PR@_x0IumWLI$84T~cb?{+)xcR}!)mr>v|IaqGVYV4YXTUz^bO +z1Kc!#dx`Qv{4#d|?C5KN7Za4(4{+xL+#3i|8^6qPAh=HaE+LZ=lvxCDMc?IR-WI>i +zn*esg|5EoQ@KIFB|J{>_+#zBn3;rtC +zj_!FqyLQekpjQlfFAJ4T_MC5nZl5`|$IqWZZvyDODO8@c=j;s&;EosCJeN~2c25Sq +zv7mQOEw;m;w;c3FiMISkblZCW2i+GnMY&vrs;}*J-vHeS#Wep&Zff8Eg|8)wa;9ka +zi|loKL$EIPLO&6_pW5r@inZqa*w&CsLH8-pohI_uvYCDV2i=x_MbWoy%j|XE1Kn-` +zMY%+nzsg=$=>hX*(EYl(7`v==jeb24bXQ*lbA8eMk2bf}Js)%@LJ(Xk{Jo@wZTngU +zy05N;HC!$2W-I6&T}ge*rfdc0hoJl3Dtk`Rp2g-{A_Pij40BfDLlWqxt%kWw4D~x3 +zbbDN`D4&ZEe4|wvoLuei8qgKrYwlJ{89WMl-L9Db6AhQkH~8yxmjh4HUqci62AE)0bbijOG6 +zpW^;tZC3fB`MH(VsMwcVnXgsDsV*0OJyk2KfJ>VGfzp7x$dfun;Ea4vI46|vF7aen +zB6rY_#wdM$IJwMQo-;o?Z&HDl?-KtS+>`RdY4}O!oO~dG|7B;VguF|1vWSv}j<+g% +zzKO*-RLd*W!aN3C3Ziq&T%&7Cwgt<>)?^?95bnfT?{ +z$=-6$IH=d0@)CcxRK!q2Zaq(WrW@HpARt?q)F>wEQcR6rN{wGg4KE|BPKg~Z5>xbU +z?OB*p1Ug=se2mF +zLf(<3N=h#GEYjRQpT7u`hO#qVkyu%sW4)B4wxpUASy3pmoKdd3Vx|V~^eVCRP`_t= +z%V~8h>~v|<^|quHx^>TQ`?G^1tS +zdK$I0=u9p4mXvscp7J7(7G50Cmkwhzz1N$|98YZpx@0PU2~7C>Zm3N@B28TelGQYb<(<@X|0E^OB-o6w#u84b2*}oH$hJ0?%Tt +z$X^z)n1UsjxdVbW#L}@A9gQMC>fSuTdce +zas1kS8Vt3po?}|4f-kui;YZ)Vif_1yG($6MjIG5waYJ2-ww{X7snnYL35_t+*4TZh +z+Zv~O@3gU}1Z7^F62yHjiruBwUK|@WcG8+;bt_cErFcvwqRfeEP3FXs2T$A(63si# +zb>1$qY8o|ng3`;}RhngsvWRmgofw{zRKwu9W8tRS3vxx?0 +z&cJ8EO6ZX@XTiKS;WU8s?b2K$0G(=_9erO6iS>J6_=;i+Y8iqJ(_&}k933#%V9CZ5BJh^v*jeIeXsj7n@Iu~RX4p&XNVK{igb +ztFbCc)3hRgU~!JmtOz6 +zJuKN;sK9AtO3^GH7>at*sjzGy2hMEqA519ddQRL5F;y?bR6Ww>kEzaKrj|dJ=MYON +zZkCgE%gJatJyIZJwET>k1(He`FLW0zSmX{C$5N@0!Yb5TWO8-ZQZ*i@!9WHx5a}QJ +zNfF0fH5$Emk;uiXiuq~UP?`-u$?(Q(SM7DNSj)mn@}Qynb*a!~L!Rtf +zAGA0%y_H6tztrM!Ec2?`C<=rNvCp|;qN{ImQFi2z)nv^sZOxWhi?+q1lX|xtQ@?g; +zH8*@&KaQakEIT=Lnb0Cw+tgMGc{OW6jLuF?Z+n`~p$`EW25!6opi*BOvy3!`Wghk| +z46}G8+5t2Ji~i2FYCidlIkK5rhgd7s>>;q4j`|2ve*UPhd2?&N^J6>eIFpJ!bipIW +zo%uByMzp>AWLVGEGp*GN1T{A7>o#1}HYT%trfM~ujmt)Ppdzf>KUU8%VNyM%I;0;< +z!{QBQ9LJ84L5p`)V%^J$<1~OZBUjC4RKFeJ8lA}*CuX~@79&H{!82Lt=DRCl%2@rD +zUhLCFs|tDC{Yk^`op9*}YZtIM?*-q`F&< +z^ZGnu#1ef{$jq{U{>p}U#An@SYwnT4nkrBcny1b4G}cPS3vw!yu%*9|)m8pju|6oM +zx$I2VGDnpWm1_PWb!nY!pZ$=2-p +zFYHt4-le0+X?V@1wb+D}dQ +zT&Z#~`oNGoNW=AUidWWdrpa!ie^A@Uv)x;CN4=^~NY})wtHfI_Y@e78rkp_DSnV(B +zdoDDMg;jR#&tpRRk_;cr)xw>jPy58POI!UqY!21MQF?G>`-7a=Oq=t;+3fdsQYQN$ +zS&Umk8F~_tLi`2<=Ge$lr{|Ap)5?7oCarg?oI~?GAt(q>fj`ev>J5d1i|g)dtXpHw +zH1X%Spua4dt-746Qu9Yjb$UWj{WB%cJgp=MnNkK9K@;$lhn2zQ{;+58_^Hzdg~Cwh +z%HYzVzapU2;hz`BE6S-7PJ#c#XAxF96lJdi&lO6v&>JD??X%I#lJvf?(VHykePg3n +zAnAQ?qc>a9J8Yv@Eb0AVqvwXrp&f(mTmU?}((=#76HoN$+GEJ#nO1M6aohUQ0=@nT=k1Nw2w$UN=dv +zg^gZsNw1}i-atvOm5pACq}SR;Z-k_Gij7{Dq}RqqZ?dF!s*PTOq}SF)Z?>e@&PK0T +z(ra&{=ack0*yx2Ny^c0|OC`NdHhQZhz0Njz>m|L@Z1k>|^t#ySZItx7+URYO^t##T +zZI$#+x6#`s>2ACFUpQM*;7yl%^6ubB*>80AmKS?jmF8)b+L+#?9q?c|N +z|0KN(yZ9&R4YP}XlHPE;_$TR&u#10^-Z^&hPtqG{7yl%^QFif9(i?3T|0KOJcJWWr +z8*3N;B)v?#_$TRQ*~LFeFWWBuNqXb#;-929-Y)(n7>?y(wk!!|0KN& +z?c$%Lr`g3nNpG%Q{FC(DcJWWrE3}J$l3tNr{FC&G?c$%L=dp`_l3s~j{FC%b?c!ge +zq35-Wf0EvOyZ9&REwGD!lAg~-ueYREW*7e?y>h$wC+Yd^;-91!u#10^-a@0NCX|0KO@?BbuKcdcFglk~2$ +zi+_^d^>*=3(!0Sf{z-Z_+QmOf?D^%$|0KOT?c$%Lcb8rKlk~RO#Xm{!ZoBv=>D^-&|0KP8?c$%L +zcb{GSll1Pli+_^d19tIG(tFr0{z-a|*u_6d?+Ls3C+Tgoi+_^dlXmg1iJ|wDUHp^u +z{?9J{NqW!O#Xm`JyIuT~^q#kif0Et{cJWWr`>S32lk{G+i+_^dOLp;3(tFu1{z-bT +z*u_6d?{9YTPttqUF8)b+f47T&lHN|c_$TS@vWtI`-WzuDPttqSF8)b+Z`s8^N$($a +z@lVow+b;e|djGVGf0EuicJWWrd)F@hNqX( +zN$(rG_$TRoXBYn@y~B3#PtyC@xvpX5=R<{Gm?x;w)I8blt4R}5B4_#KKFuhfvcanwPY^JxCl}kkLdeV#F +zn?dixCWc-lA6K({6hJ;UtC)}PrF?8;b^~zXYzwoM}Zzt1hdYhuOve0ul%z7O`ueF6t#i;yO!zYMX~!e)0-E??vzBcUhp>SdJ8eV)wkjILb;wl(cJ!y{M+b9 +zs%o^qt&H!!+pO#DEvEM(=(VuWJL@E~-WyTscP7*OIEvkCnBL*rto!eaOz-C?ZP>?V=jPLkc>jBoVq*70-;)5`_DUKV9won9ncf?qH^4&gzNTjX +ze3E}XB>#S3d_Uh#-;8B^-!ZvO7w$`x@ih8O3hmDQ3O5qSzI|ShjmmvO89?+ne$2jbb;*^uCN@x18BMBH7KB +z?B37#ev4LqjPEyzZ@k2}hw-(!)0%HL<4gRH!IvZPO=!c$g*&b1#ZNN5q$ql4o@&+` +zai?{Eo5%FB?zCQ4Y-M^=@3bC&e`0zU-f2BQ_~BGG@07|VS1Ok-ZP~gzihq?%Z^NCq +z_rUdnZP~n2vYRj2eTMOE1HRKO_?~2Z-6Xzg65mnA_f8bP!;G)D#5Y4Omv(HO417Z^ +z_&T;@^GS(sro?wX&A1LUgcfZ?Q~LmvwvBVe{RXYyBXicyR6&a9gJ_X#8)Ko?PYu~NAd47##bQm +zdF1&^2NqAG_?Om!tpg;!Qi-pE@wMJ!-7i02dY!je&+kv~$kvyjH_k%uw2o|DA^EpJ +z^6xUnw|t9r|G1R#`6RwFIo>nAr?*(Q=iQ7iEb;jzzCoQ>Jcz>AuM?Z!OMD9@K0o6- +zxW#&0eV*wZ-eNs&J;Us-lI(^hyT38MCU;wpGwGdKd%4@Xz4)14=ew=P>yQ5! +z^R+5@z0dek?zWB_N0{E|DET<+G_&4>D13{VUO^PS_n6+?D0<_%nDu;jTkqG6?ZVbG +zQn@UX%H=7>w*mOBvEX~0@ofdZbmF^I;_KYi%-7={>veMbu55lPwX2m9-yFs_`5xvFk)@y*_6 +zl*?L)?|sI1&%M^|bjay!U2(5BjBl01cb&x7?hG^E#QUt{sfX$1-e(=h-Dj|U +z3#oo@l(Yz;%S5iKv&qk +z_YJbKW&{Ibqs45QvY~W;&b(7^ZSRa`^VtEY!-5p@J +z2ibjHvOAjiBI%9*-%)7-9eKZGI^IhpyCuGf1K2*z^Va^28^Gopl7F8`e5)DX_0LK=y^L?=^&8`x_>!VHE%-JvzR6!2@#>H~zaPw=i@#*uUiuGa^OrA;_HtO_ +zyO;6Z2z=8l`0iqSzAugPJ0kJD$@mTe-}x4NuQ9&$65mmY?|a6V^|E#Se#7{-N_;;{ +zd?SXK`R)V085Vr$L)i0QiSJj5?_$QMykZ@%7BjwsQhod;@jb)%+P`8wA9|AU9g+C{ +zkobONd?R16o{xXe_S4MslCB8cuUlQ>3w&2^u_zEPxCK6vKC)>B(foJ=1zIIMF{(fb|gQgPS)r@Z^ +z@a07+=-jtn1@E7u#2n%CEJY +zU&gmS3g3Fhw_Dp-^K$* +ze!EC~eNxPPkN+KiTfq5xrm*&RKzjdA;+w)c3QWW +zyBXg;$-f>F-{*{P=}znUa@#d|5gy(PZ2jIaA^*7;q{ +z_4;kM;iLbB3HzJL-zt^naze-PI>#eVi`A~m}uY&R2`I>dS +zU�-Oa2X%__i{>SAj3vg6}@YS0MQ}SdPy_&3r9)S^M`p7*-UDodd-_Q8gOa7%ud@a+>eAfcsqZWKk)7kzD@Z}O;n#31md}CjS +zxuXSNIpf>+wXwcTm-r4czLsy``k3>5$@sb*bSO6y-!O@fE@yn(fls_AD)>f9e65DD{my?{?~gYd#^TjChJT|az6Ff0?K_Hc +zu0{EkGQK0gS4Dhd<@n6_3g1Zyox5PJD;+uC4o3DL{X9;t@;&a&eambi&OqKW&MzZ~!j}+xU7JPp)zEy_| +z|8nK}V0^_N!<@l_@0yWp{dUNRe|ZvL-%)11mp`^%AN3x^;>#gpK2#v_z0CNUd;)c3 +z!S@2=J95aFk58BQdXHx9`4fGKS%a^~Xcn)&H{$8}65kt)@A}<}a-~Ik-pTlU-y8jR +zmK+bpnE85srYJXB_*XiHmEZS9{mz#7+Ky$9*rL*65pqc@7XV4&Sl}>M~rXB5u?A&lgFcMHhFF`+_&bIVRlh6rKg;yr +z>)-hh-&!c5`!9o>t6~`lEPksSP_cXk7U%n~kg#~SNSs-J8sYC$e9t6uU(8v>bNaD_ +z?{VNhYXpmLK!|yA#GW`CRm@wa5f*0}J>bB#pY9J-&|C%2Do~-kPEW-4l&Isc6lWs- +z9l@E2xG$PW`sc$R0SSxWm-`f~H?>Cj|De2_i062VauD|S0v-wf-9!EiI0?_l>qB@A +z;N~acT3Rm;_pPMN^Z1Mc6%s9$sX +zUm5-%!@n{7JHvl4{3pZaZknK|>Impi!qCo+FeVz>#zCo|lX;pPmt +zV7L{-r!d@x;kFF7XSgH7oftli;Vuk!W4ODz4$A9bQ+%gdl-IX_f0oL7*eMVTni=R}$H%jTxXbWR-GoycQ +z2E4r)?nMgx8{p3XcPBgxh<=mOe*(C9bDVn#d>?eAzRivM{b7=l)*RpY6nH1#lIHj> +zYt8m^1}ncF4EJQXH^XN!d^W><8Sc;U0EP!KJcQvShFuJ&Fr3ElP=?bP9>(wpb$CaZ +z8#FiC%Y%R)Xl~SRVkelpO83KncS-l(1pJwFKNl+gfOLO5;6EhX7aCIA76yI`aGw@N +z{8-#YQPL&c3j*iF76$)yfTv684+5Sq-JcB;gG%ZClYrMs_tT+a-6-AP0{8*R-ehQ) +z+a>%1;I|~a8YZE8Bzy?)VZa>;2YbNy+tL`H9nkOxwlv!N62KFs`z?DyJeBT?_i5L+ +zG~(k=fVZ~9Gl2y5L&Eo38u@X+z`93De=*=cS{nYfIt#{{R)&990q)bvu-^>=@5EL{ +zdUN|2$=b^(hQ}~Gmf?Bffh9KP}H}IMg3s@+uCTa;(fkZ()|grC@PWe +zzXW)xbU$l=qO6hbZwI_dx_|0G=(nYJ|Ibb}>Te(5 +zL#G<^pW!gEY2DUX?`{O#zpXJJIyD{oPg|ouE(JWHtug=l4Deh@-;)93OpH!*xW!*?)z7sFc^zK7xa7=D1^tqecR +z@S_Yr&hR#MRwmSM2ctaA_n%_=Pc!^1!`m5tf#DY!ewpDN48O|oPW5B(_r(rI|L|lf +z%G({Ht-p7%^sh7gCc|$r{5HeyF#I0F?=$=%!yhxeo8iwG-ox--hW9bNpW!bVKEUun +zhQDR_5W|NVKEm)(hJR-GSB8IM_z#8^hZ#E@hoHXqbTIZ~eg=G`gAq@!$cDDi(U||H +zj#HGufX5IP`_+Mt_^eUjE5|F!wvI;n?h~LrN$KAN{H>IJd5)qabu!Wqn5gJ$sF{SH +z0sK}cV?8otlA`SGgugWwcp>1{oeg_?0r&5WzYP+&V6vjGxzY(g33yFsV?WVc9*L}c +znlRjy;pPmtWVp5Clqs+t>}oqKxQb++PlOLl+~xS-*?p1-Rd%tISU7UeDWKf9d^ +zQ|Z17@Pw}T+X8Wa6X5w0HrwmQ^4Fc=9t`(nxHrRn81Cz6o(t>8u9yd5|0ck1cQxh{ +zgU*BY*%jX<6nGclG|243gfD`E+t&@xV$jFqe5lLr2H(AaH+MJqMi(f`3*8OAJ%F2> +zf$usAJY^cBJtNxsvOn{GAj5+hPGZ=_a0GC5&$# +z!}A&TIr>9j%pG7nU-~QHZ3B$?X#Y8i^5Fnu{q`u}p9dK8(+(Fx{DHw?D&dWQ%Lf|i +z{{VdLKqGyXrYMgOG}6Bd_+#mQ-dsibbs(O#sjrs-_Zei|PjM^CxIy?^3VlBS@MvgE +z#dLpAA)a#(iHGL=mOEy`{qvp1e18+*pflR@mH;cSpyMadzg9{=5(;js6Q5PrOdn?H +zD;=vqKMe+_rKJB}5&j){-gOpao0Ls!2NfI;%~WY@-21z1Ma^FYp^{h;r%37h;JTc#NR5woyXv}eFc62@Hhy@ +z{mH*mOCf*R1}+9X7w|ch{v*KMCgC^f^!3v`m>)pn`SWDNR|^a=Zm|P#8!yP2M*Q{y +z9u4>{!rK6kn1$zz3;ZYG+zSjmaXz#SXwxqfz5(zAXv1$3-UE2~g?Of+zCW@6@(*qD +z@w4n +zkC(9iaVf*g88%I?#eACK1cnnCK8fKb44=$!Q-+%{+??SS47X&s6~nC=K84{n44=wy +zTZY>)+@9eM40mL>6T_VuK8@in40mO?8^fnF+@0Yw81BLFnGE-2xEI5{89s~QJ`A7D +za9@V|G2EZw0Spghco4&b86LuL62nf0T?{8PoWgJ_!)Xi;WjLMT42Fj>Je=VX44=dB +zNQOr-JeuJ#43A|vli@6evl$-8@OXwNFr35iM206ZJelDs3{PeFT!wQQK9Au%hVvON +zV0aqC(;1$@@c9hSWOx?C7ce}V;W-Rn$gsxnT!!5Y7cyMLa52LkhD#VOWq2OLUWVs0 +zyntaJ!(|MYGwf$L!0FualB+Zf)&@a+t5X7~<J64>0^7 +z!&@1Ch~bABeuUvi8Gel6#~FTt;cW~*$?#JQ{~yCoGyDw0&ocZR!`m5tp5Yf5{wu>T +zGW-(5FEjiK!#f!M8^fezo}Nf +zRr*Lnu2_8yCw!8A|2rj%a7!H@Qi6cra^P89ZDD=B2JnXxzAb?7tw-<^fDcOe4Zuew +zd?=thrms{4ZUIAnp9Higa57B+&erY!pyVtx`#Xc-LWcc>yXxtWC>sd3)A5hW{e(N| +z_^9#;;Zt<{lhQ9J-~U;06KnmjcPg0*X={Hdi +z62|&JSv|E`!lX22Bx%==d!4mBn&?&sGzc$oc834qhVP@2~nz_XnuAnD8L=6_frD +zwdqB2c_pc7ChSs+FOt)zsE=JF`ZnWP`&sHr)BSAqQ4=1oerm!w>L{8rV|$*Y-eba( +z)t1ZU{7q4(5XSyARb59I>-${w4Z_$ya@DU)`g!Vbnu4FD<9szt_;ejlQ|~q58R|=f +zhw6By`Xgbip9|EkD`Y%J9kxRDUsJCjjQw-2`o;>`KeyU>rR-0UI%%bR-=p4Qx?ifk +zwNlQHSM5(r1Z@BF)e^$vbi6>_u}b#8Ozm))?5|%v--H*c*AvG245=Ry#`+4Yr_z!G +z>!VT~zgqTZks2n9@wrO9X|-G)OVn>n=`T_{UoPKYs+O4W#p-h=e2LnNmNXbIm#J3} +zzDCEFs{ba8{d=X_;|e+bW$KzMbUa!dQQ|tG8~D?cbpu-XQybmpb4oS$~T-;X2-?K0z4c*HdbX +zYvuG$tLfLu{ynQMC)`iR+tquomF>TvcD+tc|Dsxaot*wt+95RqwuD +z_HU=!otCKBK6a_|r6sE{j +zG{X5heotLM80+_a^=`sv>+SzT^)=J|kJWaxq~5FJ-D>4c^8L@$`)-oUYmfQ^VQde3 +z)xNX@$M&#KEhW5P$NSZF(h^U( +zxQ6hfI!<$ZL-;ivr#t4*meGfL{~6|ZPTE2e{(Vgt%X@^QGi@n}vvy$q=eU|M#_Q3J +zeT2`|`Nldr-(%)GgK(LypXG3~`vJm9dirsWCbUI$NXHW#n+PA)(@%7qOv*!` +zIl@PDJk>Fowy^%A<6Oskgy-lu&oPI#w6K2_IKCmgOUKh4*|f#=ijL2B{D<(Bx<9iV +zRkY=Gqkez3qXTVu-KygY9gh;eM%SO~7(-iN&+7LJ9Ul@7>bTf3o3_Lr(95^P@vyW- +zCd%gx!WFvyJjY?e&+Gd09Yv4I_kE6gA2p|c1n?FZ%*B&AvA%wr-TwgaJ45i>F8cbM +z-T#TvDu^_biB^=_Yi(ZzaMs-^0=bB48c5u +z^4AyeZxS9uTZlN{s&p&>T#$_R^!*FKK?%PO_-YCN0{CGGpZx^XiG-&CJ|N+hPniAP +zMtF?g9;zIB0ryW)^e2Hr|9^nzOSt_ubNXI{u|F-|BqqElV;qG;jhHn8J$Wrv3 +zP?5iv*!?#FZ-T|p4RpWtQ;L!TgVhSc!=5thk6}0m@KfXQTh~H=1K?c~pp6iIis^3$ +zeB(q#e^Mjvf5Gk_Vp#n@Gj7Ik8-`C~xCg`i0Jol{=uhT_{Rx1(T%hPr&IK+7Jb1Q& +zF9Y0X4$jvEz6)^23vvA;@QZ-QUWmU>5cuEB-j9GEZ4#;P@0C_ho9}l8yhXa70{A`& +zPX@eI!li(Vz4&cxVQ(wo<@51?p{wLFahv5$x{tWPYs|>!TFmR;7n)m?Wq0gH2&t-Tv +z!(PDMt~Ao$40u};e7{26o@` +zHi)cXalkXxUFONItTT%@D{Q#+34S5zX`X0`VY97nkGZRYn-fN{bhp +zb7&>iqgGN;UKIBF%aOK0teGy+D)N&x_&0ZIev)QXb#{KL)^L7jt^5rvmgG#I$6Y=S +zZpN!w8XYEY5_35Y{-#FQGb@5YPkGo>iK*^jX=Nx|x-zt=tk?%>v$n&bhppvU!)ab4m9D07W4$%!H~DSRM6#zokKOP(i8NS +zEY?bc{)zzHfcl=FHz_|C +z$odd~LrZG*!V0&~7*`rLQK&giHE@bIEg)tFQ~br=60fItthYLUJ7y+vrG#G7g +zgN6{2q~&{jP}I&)SdSf3VO-3}4+mi|&nydMi?WBS+3DI8tkL%)#zD=nlk3Z@u@A~OO79(OX3SVUD|Yge9#KrAy0$ZMNCPCm}1a+ +z%L2aY8f-Lk84$xtJz=dNU{qyH<9nk`E~Ir)L?d3gP4<)*M+!9F+^OPMfsoH(uy1y_BZ5?fDW +z3J>wvO|uLS@!6(}JyW4Q=(6uVlSOcv5!Mh2{!3Mr$FqBY)sIM!>ySSvCvw(Kji;U?-- +zk#WdTjfy-m=EGv4i_ai(C!OePm^APeCRG0)c*;uk1Yej-rF!D-bikBl3U0}i`9tAa +zw-MsdW94mx6JZ@AjpiqSH%=$ihuC^Ds^bLksy^ZDIIY9#8q1DTE&Ke7Jg`jgSHOZL +zulhxhW42J@4p@zyCqhd*aRcZ7C-FU{#Cv>NSj2Ef-Crg(Eg@Y=lYZH8+?^9omAvH; +zrK0}+CV#wkB020#tM*u{DEBU`kjnFTE}xD5fR9U0khxc_UE;Vo7PVJ2=F?1zT57DR +zmMD0`+_4&l0w>PzG%R{*^n>T55Od7-%hM?EMe%BkCO;fGW?p%#s^8?O+i7LheXPhw +zr>CAcy*-9uW?Zyk=6LxW<#nE8vUrWyPH*5FJ#d@e=&62}r|85fVY{*X*p_!B6jX1; +z*Kd&{7Lt`z#PvLCFnOwHQA5^Q;%Mf|>RNWDYFd#$uo${n(Sk+pU~$gmLMPOaD=i2` +z7Ka+4hE^U2C&U51=ta5)*{1jA%vI1hSxv)y#8Sa2x?^5}!w8#e& +z#`t{Va;WaqX$!K0K`0D4owHz`C*&cMJ~A1~DG&Q`hN+*f9_iTPNWcu{UQT(5U+=L_ +zItH)-RiBX`@OeeIt|;@Ahm9G2ZhlCQHz{>rJ*4M(+{NSIPbo_co6x2gM0n!yIg{if +z{Qd>~a3wC3#hwy(h0jFUAVya*6rj(l-gBe2i26_XGxP?ppC?WgRVU|D3WAGuhU(^{ +z$KM*glYfQh7t_$Aa(~TR +zN&cGp8Nh*+Zs?^}Q?NT3{+i0J5KNI5*SMS>;jp^t@>`_=S1QV3R^ne^;R?S4u1J^4 +z7tPNV?^%>qRcQfFFyx0i^oAE}mEyICVqb1$z8+&;F8q$5R#p-AROw%v3kBRop42G< +zXFwCrf!JAMo(-js$2Fum@(rb{ma0jnt9sxUm-8#iOgHohD84zCQ(h?^m_hv-pJj_A +zc9G6B{j+4IO$`P +z?8wK+CRvOprgIEx+>OxGc0?W|2t~dO6xkDqVX1}5>^|h=s>_F*YI;$ZbdgUf)ppi< +zbuC)2hm1mW>BmaB>hi^+`f$hmJ)(M%$5tqfSSF2GBn>GMtIkB-B|q$0m{TNnCyVB} +zgV6Te-f$?VNUW8M^aJ+u3-POXVo$I7Oq0;iB7Yh5b&uR%@d<10q)Ivf#i?1mqXhO% +zO_@Koa!F6ML)np>)bZOv*hymj_z!C1p_j?Ez0ndf9cC4Z<;due=`7@s=~VVm44;ZY +zo5t4_-NqHo8S&HghWNuWYM3XR^y +z?9IwuzBbKT!$BQ?U_Z=W*3*0VkVp$etNIUg6x0|RShJGa3eL^+?fp4qWKUbg;o +z51Z3r;}%wJ4|k256@D~oWKs}g9F2CgYn%(Y(PnscJ=e6JjhcQ-P{+bG|NNn5jEUcGaJck8Q*=eUYWHR);o6%+YY0 +z7AFtTQkwX+)6ly0NXzrx>gPnv$FoHy@m2-nv^`&~zV%~qJX-DNfuWm))f@77pqG5! +zFWj%pEx-Z~(O!VXk;X!;Kod`lM7+~V+`f?Ysl?TaHE$Rk#=*di6JuyDZT$2jsg6JW +zh+;3b`qvLbHEj6&mmRebxFRp&>o4Wg1ii-ZHk{ewKk0WHaVsYM<$wHXSGM>eCwY^p +z;X$>L-*UvwUa}T>2|rt`|H<4Kt@?aDs~=+3T3ON$v7l8YS7#%Yo@Yk=Efr`dMVxSH +z)gymhe+{MYSY)%BwD>(!6mt#DbA1}Ab$QgIwbr$)YB7;g?X2-zm>T66UpJ|DncO^f +z9gJu0Sar4f9b6dM^^+%t)5;gY3|PzageuBv`>J%ve5PY4@-jkx2uGw)B!p&0v~qBq +zfFUVwQbAG-FJ%Fd{?^=3D3}GFV2<$G +zDJ(hZ(@@E#uiIJGX6@{?%>N~8_1n5h#go%&-M@C~KPk&*LwqgX(KN$ia#35t0%5MU +ziAPK%bxS15gp3Q?8b{^imlyFRQ_#gI>_$3Y_wErO|c +zZAF?_AkAW&n%+V*J*6IDGYs5#@wHN4g6U2-hCLottIe^%`EiTBn98kwDIk>Q4g|yoKm8cSHfXcs_d?=5H1U#bEl+7`oT3-9 +zK18oNMa@(2j9YPdEX%TyTJt2(2JB$kp5ht5oxqq*;EbC&`_nVyW`>=7S^E;d!9yc! +z3a%)}JI1(qSEHdj8^l+$8^oB74Kn6W=0@(?PjqxG^E`=~8&$Q}AJX%ZB4$>`27$3H +zTkI(cdc+ScZJ+wb@JN(42kn3LUt>*Gb6x<=!;LSaYEV5z^XN*@1G)4sA_So@ayRM^ +z{jJt-c0bkE^&uy+ch$eOx6f9cmN=GEA?qyEb?Ic6y;`|MqmcX^SgFxufrNm^ch?Joq!aJ-o@h}Arwtp5A)wcCv` +z;MB#b7?yLkhw?RGOpJb@UOh=I4#SJguo}u8!_iw~v^d(cKGZ2PSx=YRf1JXp)sc5` +zb3OVmY@{NKad5BYytx!je$Wvkr+!)-L^K%5ipm1|21s>J6F=h@qoC+!LgLYI_>9N8 +z8%Cb>g;I+&V2q4`u;kH?7MbU1tR;sR9T5h;6wsv{0+AG~tgH();3ZDj}(m(i^vgVy>)= +zkU!X%4LSB!;|jQgVoIb5k4}IJ(zG&9vDaN*%M?Q28@1-tfAyJ4|3-LSPBHx}t#Aj6 +zVd|&nS^Vtucytu2ev+oaKm@B3y;=DD{>F-Lv9ybbQ?69G$i(3{?jQ}9$0@$Z&ZWuD +zp;zK(;>WQSS9dABGEX3f#L}n4TP`e~NN%MZcOR@a=<0mXTS#BZR6q1_B}G<*V7xRu +zPxFY=L#j{ctYOc5id(2Y`z3XDnVxf4yp|uEL9@@mQRXQt^H+LIn>Ki~2%Y<)pHK{n +zu#)nWn~oDO9aJagwZ#;jt}Lck6EO_ZYS>ie`INZ)Q0}-wQTF-fr$*6J6k~$o*t8d;_Tt#It5CZtHf=9zdt=isMD4=t=<8UU +zw>YEJX`1*`^oUxjG&5S2M&2D4OEyngAiOxT6psA>hw7ikgwilTMS9iHpa&vIW#sUB +z(fz7}TAd!wL{4^Ew +zDo6hky8?-}uimL`6~*29%!`=p!lDN4>%80qx0Y^HcZ`jIxKmqtX}lSVZC44`B@ +z14uprNSt8BM +z0N#*3{9xAg(?Ckf%jl7X(Z2M9DMeE;jwy?@uR>GPnjqShe4y0?k1v3Y+w>G^sLlvv +z$SSqhLeZMwUsEygW3s0D%MD_SL%Ndi45Fw>^v42jJ-&#n7rS%WiAYw*a#lYV1)_E!8tBy} +zGMugGlxHZ4qP9?!PAbYCB>RzcksMAki{uoN(@DPL0GX&LyM;_pl>H`XK)dpqnQ&D#8fcH0({Hg=m|5o5l2}<*hApeq}>>~L}Cy+}Ml%}0Q +zt^}UWc>PNu3lo&1B-@+@atquiIhy3u(=dJLH1u=DX_)>RlAB3BLh=QY9|<`xLD@(6 +z)GjE~NEVS?L-PJE$p19qzmt5Qs( +zK9ry=CHa()PeVBg`AmWm?uO<2oRH5ZD9+On|4MRochtYNJL)H$fq3K@lwQak3ChQ3 +zp#DWYP_{S|<=Z4@^+b7NFO;YB1__Pi#@=Z6g|o37UOOAF?<4#j;pTl2cj$|F5aD#f +zxr8qu93p%P;U@^c)EE7JhvaU${u|*o{ZMx4hu4P@o<>rm>&pn=N^%Qb-$D3&l6&a- +z?}S_Q2e|?G`y=k%AMcOrkM&v5AKTqhx_)_o^#4x64-wu;_+7$Z6Fy3~^#H`D4M6N9 +zJc95>A^)AAt7@&zYoE9(KHG3(=!Rv +z4-$BPf-;_Do{;~A`VjKV1m)5scsL~Amo7rzTBp*&gyU!4QgYc(>zagm%McIaAFOtb5 +z$B~>q6w`Z2zBUxgZ;y~aIh0?7Y!7iHU6iLo=_KTzP;Z2X5FRJw&kp5$Av+`}WkPm> +z{*{jHc7u>gqOv(1`JPJ0a(E#f+wW_{_o0wbvHzj_U(@}gbiZi^-fx$I_q%4`{XQ9J +zKRpBOPsu?0^D;1>l^K|?bs5;6|03{7iOM#@?+e@{QTblTlM|Kh!$3AoR8ogwzqoi9 +z*3=lB-GH +zI2`Ng36d`j$9#P|9R2%!INEJG0{v?@0&&j~=*P$r=-*_zegRz%j6nY`8i95;klaM_ +zF_JHle2?Tll0T6=`5g4CH%Zqy=-=3L(B4FWAug7kgZ?h1>zAK{{$5M?j&snj=g&cZ +zU#III)Agey6G!6pb|Vq@9f|o!9!c$-S)y{vXpqelmG+~>^+aWmz%3J% +zEV`aU*TVw0N>nxq**Z~qS;$iomCr__e}_k-Kh4H~Y?G+uk3l;nW3b#86J9~`FJrL$ +z?-_&n*-moT807hs^bQFOlg&Sfr~Oz=cg9%MPbHZ-7Sqici|GPmG2JC&G2Qi)?sn3D +zlH@Ct?oh|>K*>Dp(Ky-c!4GBXp?P0z%1-b_rlC==6NN$GAT{f9|zr*v-%c?rZl +z(*KTlexh`aEY$BnvR4+S8=8gX`%xCQyM0;IA4r~=je1LjY?r89Px4`sZ)Ib;kFrt! +z7s4&aA?`8`)1O6n>^Mw!8R6^be)sXz&xE`Z<~KsNPgL9>)sBfuU_9ohN?h-hs9ZcA +z+tDoouTD_zrSu0Wedh@v_dq@;;Qf&#Cr?1VtAsoi<`Y7~qU9waKS@wN6cXa)o(X90 +z%L&-7+vXrXJqPXg74ozMWtfoTpx+4D72=hjLKVBj4gSbR;?L^G) +zmWk-^QxnnOmnNdWZ%jmg50d_$BwJ0wbjg!weoJx;$q6LSB{`ks9FoN(7my5+yhiYL +zOH}?!vh`$a52Zq$o~XPcWOry+gg+PZj6`MP6udrd3SKXng4aJ1vPYt_kFNhn*N098 +zd1j(AYARmOor>4@O~wB4!&LO=kEz%{nw^WdGe{AKQ%H`b>*oBUrYENlH2I| +zD}+B3Qp^X=#d`XUk)kBe|92UrByQ@@tZb=b`LGGKpm7dD!n~ +zlMI}P^?R+5FmF9{9+u0W=b``2^RQex4!*og_aYd4%N21(@%)1;kHyEaB+| +zSRPdcSROAHV0r8*z;gJy0Q2!{0p_FQG|YGJX?Q((8eX3;4fB^j4S9Vemyx`g%L{pLR1bUiSg%=$WWEXJVY5B`~ZLmk0^# +zmzQRuf9fnuH((aUky)s>bQbEpLf4yJfO;b@Ks^5f)Vulu)cb(0pFSJ)@@7-qnT>ka +z&PKhD==y1MP;clQ#Ixt1-o0qG}bD7$D_U&Dm#2lH7WVVyfe!}6R@a*2lJd>zRJye%-S +z^Y#mQ64axR!=U}l1$lCU(sVBBwV8{4juP^)Lzyxc?a!V|^Srs(ZkEr*cCukE+P{P3 +zV{_5|t3r;1{zW`Tgq)F}Gkj{$wFxJy_tTauyikeaMYG*SazNy_D`n +z(%(t?ZtU|IqhZ}E939JGuz#BaiSLA-{Df +z3kX*VIUrG4FC@%=|5AkZ9xXz9e|Tob8(50zhL>VFWR_z3>2%*qav8~+Nbh!mVLtY-zylMNJ*Ak>uZdrs +zhw`*}sDI`>)K3z4P@*z_9_m++-a3+Zk^Y0E|E$1+6O|*R|0n6S^`h+O#qt_Kc%m1} +zWg6k27t7~sFP6hmy54L)`8OZiLowmtd`y3jkV6uc9rH2$Kjve7CN2Q!OjNoG32|$L +zkPx?W7hpLCgoHSC(E=>5)eDe+BjM+TbR{Z>NS@(C-jP1ElSA?aALjQpANsYMU!Mtiz@Z$ZbdGYo-do6ISf2`+ +zn5Yad$NPD7eNj2uT}$#AlCP2cj^yvH&l{Z|0n)u#b$-(LnWe~AlGc3z0- +zdM(8AAG{FzdFDdw=TjGAKcBe}?Qd9!{rpD4e_M!l-dl)vK3|A-4iNrDV6i_KMBFim +z*hO+QT|bxb9Kt@rOM=LMT@ZQi3u6C%CW!5NM-cP>Dak`Y%-8=2w+|s65JEhXkiamGTubR6B>4jA +ze@yZa@inVJzV;P}dsQIMV7fkDNEnZ&RUl6}$xADcXFcJ&32!I-55gZ;U_JgqxNW7P +z&vS-WqP=mIw7#iCd-E&NUKL%xyb|l_2GW0+^j@jNe7{$T_4Iiq+Wnbii$!R!<08aE +z2#+H?lVp(OWh6I|e2nyWk=(lo{rN^A8#x}p3g~sN7AvJ+RJi^CnU!% +z$Mh4IBY&R2`xBI_2;a0E+xLTnpAdLxqVjjb{~&yHIj*~!T#DCQgB1HzS(l>S3rUuf +zypQBlmtuXtM0mssoHs87>DZT`T(bh_LC>$i`!BD+dCpP7|676cm?0|>mk0^t-eoIs +z+^euvU>6}HD7LJost! +zJbfAF^C-!2t5MDbDdq)%)!2Sl2np-C`$@h{GV5~8XAVfms6^#Ffk!7QbA@y$ibq@@ +z13Z^w{a-@*YX#oxQ0}}O?LBlkwue{f{#yd?b145NeDHFt=OcubHJJXiHF*8(HCR3a +z*Wmr(Yp|c5M|k!clJIQ-U??I7nWTNua8qCKIy8br#@g?d1 +zum!=wdlv-wWy!57V~i~-Ji7J>1uETtcU5EL|rR%fT +zp&wz=U$zeOaRc4oybkR?LHLDr=kzM*u7Dc!&;(e9`#v0qQW68rVME3qG6Me-?<;vY3DQAwotpPG`?uR9Ex +zNU|x(mL%JdY)^7D$t;o+NKPi1OR|9Ea+0e^t|7Ue?r%7%n`69_3BzKa0gXG&J-y``U$=xLPklaV|OOgjk9wK=p!lM!o$=xLPklaV| +zOOjifVEx}max2M4Ns4lJ{0Z|FArli&HZi1rznLNR>rDy6d|)8SERwTHhDoj`*+Ixt +zV0}dLbRpX%DBVf67P2GEmq_Y%I+N^TNZsz~hSaZjqx3x~eNO|QPBNA3>iT_1_9fY$ +z$${jjD*^pZNvJL-U8WIkPBNWj2BjN8>CRzz6wIf{4_&`I$t;rDWPd!#97;Ela4yUP +zg`7fIrTh+u^_Y<7!8%jOp$W^wL0L_H=;`w)eL=(dZl-)bBxFK@-Y*=} +z5|no+-IsJjSTC0gNoph~Bq)P~oJ-|7fOyY_^@xz}1jQ+2Kcl|& +zbVUhD4>(Nt5|2=zb;LUsQ{|N@i~{tp9|BaY@fVj6aivgmGu4kV|X7 +zujl^@2lkgs6ZClNSP}jDsZ@?VNe(BOLwtHUuQK$`A~}ZSERvNZuOj&%$sHv3kUScx +zHx=dSs$^$1`FU!Bc%4acoRy%D8{&CxAziE%pJY18aU=^!mXV*UN#0KKX_9Y|+)d@wf$C!r$!wByNLG-%lH`k&{v(oyNw%PJ +zIg{iN)uP_7s-<06-0wiw&!+a8K{AWVZ3amX>Feb+hT8KON_Q=l=XFMY`;$C}{GSx1 +zJVw*~saF2p7{%X9$nGsLkEZk!SwnmC@vv4k{>O}|5h}9w4ipqfa>{V%I|Fn +z%6!6?626M@>*L$)R1O}>&t=qZAU;hLax>L)KZ>tQsT~fc^misG{e*=0J5tCy$Ul|* +zyOZM7paf++$!W45cd`85P4@4h_}+u~&LqAwD8K6|zg;Q6_fmelQhx6>@++o%4w!G8 +zMzS}_6p|B3P9s0&5MDsClH@v)TSz`m{CZq}kmAM)DxZhQ-({4KM=9U)DXu(5?eXyh +zB}6=W{vV{wXR~7@zh0K27cD8LGGE=>AOO{wVqW^K}0r<9<5b +z*Zuk{)ys=i|ImKM3VBn4GKJbp3CS?|zna?9I`aQU@_!5YulK*J!p0q;`5Kwck4_{R=|E{O4UEVV>X+ap`3! +z2O&$K{R;Uo^m7&Y#P1@6e{)sjy^8c7B>i0^^>(m>#+Tt#PXCX)cY%+p#^T3wXXdt3 +z7-)q81quvU5EQV5@)Q-2tFTgJg(?blD5XHLw6&cgKC0*xWgM#LqT=eRtf;KIF7C33 +zh+3e_LvcmLwQAL>b)DL(MGKUN^p}&IJ2y9TXUfC<|9}5KAMN*^p|~FfIIDMy$w7EmZKZyKOFEXIkr6(8td@_ +zmj4Y*zfa-z_!aqsZ5%UfJl{eaPk+0Or+dK0)4gcp<=l=K#B|32|79nto%6ffdHTV2 +zp6(($&oAH3`D+n3+j)MhAMe8UoPq15OK`l~aU9stUL)+}ZnWF;fcNA4^DxfKyX|a$ +z0`q*V!m%69Kj$Nk#(C&6h3jSQ^$wk<5Sd@xi{twp^z-lFINXctsQ&2x=zMY=$_r6u +zhmlLjst!Lh~ +zlYbDN{$0e+aNJwY$ND_3&-W>4N2=!zO#dL_Q>cgerGL}$fO^Iw&OkfOL-{7u%lycD +z=zpl5R}ue(`e1(y@82;y&cS|p8TLnAKh-lA!+nS^qu$q0-#)}oQ7`ka`PjbiqrXf+ +z{rhpA{{ZdrHu}N0(T`EQ5Akn^@mS6tSgv6h&idZ0PCB|Qa;rUpP+fZJGysjws$8s=#`!UW3_n`lv^<0GVQfwEvKLhJ= +z)~~a$9s1*bg6i|2zQtnyejED_$?c+dpr8ugEsDOuC$X@!tb}S`Ra2!NmqC{o2RzX +z{tVaw{SRHo-mLI^*8*;$`2o`P>vn~g?*PgTnC=*+Yj5M}&a?4!BW#>E-o|-X**I?r +zAYCW>F#Zuhx-MCVyp71)i@XEK`vH)yzkdd#>lVA6hj#{~>zBTEUjM-uKF7}a52E}O +z#;2m4nLiqi +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 +z%yHbaYIGsOVIHs3l<^5s!O-9wu<-2 +z4G@>!09kE_WVH?97Ty?%yD^-*DH3;+#O-aWdB`vgBhAT5LO +z;RakEiMu|Wdngk3ki;E;L%W?Yw8eGi@5JQdvYaQ6F>7y<+N6TbM6S@<7?u&nJ(!uC +zs&B@Q{t{X*%}H_TcK*@&_C;uwzh4XqT?(P0)$cCtn6gVd3j1K*A{P5!p$heGn`x^< +zcYA$>=!)ry!rrR%AX^vGec2ASFWUk8vK=t|-%~;h%23*{1!eq-4U|R;rZ0sP!%g_~xxF&s7umMRe(G +zv2HddXwfqYF-Bc$#Ja9Gw}uxl$t6NeisNTb1a;4Or-QP-+=NTH*YulSlxgU?k@SN(r0JwG2~1WA67x +z+UM>3Niq@o7dQ`iBc6rRy^?t2(zJ_eG;TdMS=>7k#>bXG))vzph%NOO+fCa&p^D+f +z6nOQApcJUEQB>Gyv#N^sLQ`1OZ0aAg36_j6zuabeFva_&xGFbA3ZcR#woY2MGuzZj +z-MD^;!nd)aLl14@CpPHKvf>yq@tFG#-BeiCi0x7X?ZR&}SBK?Y9o{b0q8WQCyj@rc +zLmrJ9a<=H;%w`m7%#GfQdu8EKPpVyX%r)|jA+tN>#i|jDRc@|1o7ln)TPqnBY_|TS +zseqQHn=6zqV%G!r5#H~>!x%fU>vc+{NSSGj$)0GoB@J>;4ZRIk=ir0i8Sw;5V!8{% +zvk~sX&|Ok!YomK*e4h8Y`A+HHom76(!QMxpUY0%i%Yv|W{IwtACMCr=7vgU=7Uvcf +z7Q=6B4b6e?oJtlI-t1nKn_uKEEO2M%=errpJ=>dCG**yvvJ2dcvX|z%y*C%S=VzBJ +z$}Pzv^9l>|38amzXUGtDN%oRlcQ(CbO!%_^es4`qQ&^CHi`%;>*S#b=ufV;eaDHii +zu6sdYF%8QraToC)_+!aS;J5w4(zB#2Rf!vZk#fF!-Yq;Wl*GL>JHIp+ewK^YoN0ld +zf)ms0X>VRsSdz;$xN`~%ytFVSOm|69Zcg5UJgT>(bRPV+7bN7rG8R^MT~}U#QKO>l +zoEx(j=CWk^HT_2`Hor878mPd%Y)QU*X>M^z9#~_6J7g{zj&;>zvkPeLO7rsP(;OBQ +zGLij27RHkS*-MHpA_K^PeD6hM92s{Z83#tVguw5)5vUtklAB!srkJ0*AiFf*OL9t! +zi*pOS#CuCoE=|Dc{Y%;r{#$-y$C`c-mRv}Nk|9v9p~S;s+@(VKFYcE%G_~KQm$W0} +z^dAOgT}s=Ubxha?T|43GX;Y?MG1i?yHRcu3{)Y`! +zqIU&%wi`@%G2|ogGYhikQMR{`#?rRP*3+^6Yb1ahvhXmUjZ-JQ<--;!@Rko9uX-pO +zztUC3^yE`vx&rKtp#;uhPx!N7;T0I~@M|sjuv)*#=dTu?g9=;{jf#0^;TlnV$`?oy +zUsEDucE&$k8Na#GSLK+^%ftUtA7=JlQDfR*<5T0%tf70!XfcvDy*3usOXL=jEs+?q +zgu#JZN0u}p2VSm_g?MIrcbp;6`3dSr83jnuf-xzJHe;l(2Xyu%hW29 +zOmC*KXQ+(we|=j+T-d8Ga6^Rfg@kkWct_}pJ;F3f7?y5tM2(SS{zrKkeOdGlbnx$B +zA^eW__7;}!pPQgwKvLAXGZ!2V{qMlI5A%!xY +zuyI;PNOsxMy$bn8;US&6j3XpleNiF#7ZdU?4DEiNdJVZsU27vnG~hmEl|nE7ZnMt2 +zLr;(=E+*xeI&Q3*1!a&0(nWD4t7DXz?QS5&D$!pyZzWTdOU4YK>v^T`R)uT??g8Z% +zLLRlNyY2Q$yShqMo^z;&9ri|tS{_UGFdH3I)m1U%=@=h>UAK(uYE`D5r(Q`WsZBPL +zOBLM-7i$#tIfXo>!1V$4w_Z_?E2NoSKWBr#uiMmjZDbd_u7{f5XXh2j8FAH~81h#| +z{lG@vQq(7Gu4#kP@IAJ1uRF+tcJ)X2gtpH+c2dQzzq6|}{71*RRKp+D +zKD$)%ma5Y0%`xzIdkoFt>ln0Z4~iqyapW2IvaUZQ4c9(lcLhr +z+rh4XR3QA1dci6CSDU&ffoz15(*n@TM!UMgLHk#wawwj>8>2oKOTLUz55|!1+4V}N +zO2hX!)s{H&l~a8^j{NFWABZC>aGst{`Ttf4&?dv>RuPw*@!dOi$c8WJqqm&^lG1?exZ<$p_{c}CoPEWK**G5l^>nt +z9-I0&?J+i$UT?MaYqXKC*>#0|B>lU>k#Mh*eBu~V7Yo_`LnSY%D!u+ho&Re5(#)u3^>sxGdJ6Mvvn{@|7UCU?FCqqvskvc*UuzCz +zHHZ9*@akZ*u(fCFIAe9lC-De*$eN5ioTrmV_~Zv631Z0UytIdU(;-N>Z46QZzUnJ% +ztLp+;byjiyth$EoEW*X#D6&i>#Tkj5eyu4W+!GTMNpVIZ2bj9rQqo3^0|-cBRT3q)8AWwx+K +z^O-L3Il$Q!G;EC@vM1akhkHd%Sc!=X0b}`Qd`%J<@01s8d6lm&`E0WuO3N+T-pV%V +zVv*TGUbsQ+46watK!0JF8NsFBy%UMjm>S8upy>_PP@j}WSmZwW+gs@W7q;Ogqpqr@ +zp+~rvg>|w|Yth%rUqF-=Y`6q+6+e(@kruc(I-n#Lxzl3t0+>d=>o-{YiX)a5IQ}8n +z9qMn|s+hTJd#x>O{SLiAdU@2e&w)38#~Teb-Z^GReEA!E6GgW>71Lpl8<@-r1s!6l +zFv5|+;-))rw2QA{a>A?=cu~|+A#SSubErPA_~g)VKs%%dC*nipdiI=Se;{kW>A}f< +z(+5Jr%dd?l<2AB(O1v&QQ)~J&R9{&m@wTJWlTr!a6~*q>;9L_D$T;B7fX+r!m2@=e +z3^Mm-db#zjCwc; +z%BR&j!b)>kY@S&TQNQ^Zh2KwTaIBHBzDE>_rsy}XGpDzjP1>NUcdV98BNN4MXB)-KZ +z%B|C<66JPh3>RGv$4UjB61g!R&e>u2h*(Y?ohxh(c(I}bJYE9cWaRa0gI9#S&Ta74 +zBCl^7yvkF|H;B9*ZSWFs&wp7PywS+(-v)24a%%NhiM&Bkc4&Ezd?6A5}gZYBHcj;9-Lk0cqzJ#Hd1b7 +zEMezCMJsEyU1+1d(er1Qgr6Va_#`?v6}fPxfaCk<+&LomNObN>|9ql@=M!j)0gN)khc9A +zP`N0&jjB;+TYaCzw9SJ$!TDIX#}RhUoweUF*J&2zf7*_pxe={S%Rw*vZXMWaOXNDS +z`eRw)Tn|SdTU2f}vaoJ^K-2<A9bA7?h +zi>EIQN%QlkFP-7xyy8Nh5TmAz@pu*%lzMWOElV5a@e~vmFUijLptu$#78twG5o^%FTPf9z3G{b(A;!;b|ZZ_O=+SX#} +z(oR2Jnq@j~+Az;GthacebG4xbx>FkMEJmWdB}Ms@ObvLZD#v&-JPUKZo|#345l>?@ +zpNYHRHVJEk5ckwdZVd0U(V{z(Q*{w%Qr|ZG$8YC{FH4&;on3*~N%c@41I{PSO +zfO+y3Oqo?uOnXYI$CF*0>w%Xar%(?xV}eJcgYUyv{~d{*PylQ*o`) +z^+JWMbw_u;X=tV~)J&-!Y6PgObt!UhI$HZnOV*i5PpjD0i{~{dmmNBmd@JGhT^QF +z(yXFnml(45X*p6ORU}{eo4a=F#n2h5=4K05c6yHT6pIwW#5{HCDW~RT4(ErB97FM` +z`l&Y7cxR`^yb`t=>ggqUx1P>&IofJDd|453u`Cqnw7a*JNy10&=q1_9JbLBYa(I!* +zGrXfclXB^XwD1<-EuB8oBgLl;_ju-W2E6MH2GW+!^iW%{nt2vv=a=NN*(;)ABS|!h +zp*I_52raDZj_`PL3X5)`R?NBa=IrA6Q>M;KrPJK7k;QZj6)y2)=j7y;l!Thnn!9EQ_z1^(MJV}xf$dRR@zNEzt$rQIEq4GXITE!ePOays6rSoz?84d#E&@DwnG +z!$Ji~_s9z~FuA#&Rz+BtljF%jNZ~_y +zSh~kkT98+e=grH`r}NT$?jWr_ZX2U8ZFIP%w){4C+g2sOl(gJp3Fxp(ljo%9({sq2 +zi>F`N)|%C5iZt33M#?rV%bL#k5=%RU)eYZ>NlxEN_n4y6l0|G53g@5JUMbx1&+yVc +z-q|ESJ%^_!&t2qMPz>L@4b7p$4nA-jT2ScC9eTyI%poOST2VT$78jQ4PsZE+_qT3@ +z{jQ$=56(Y__mny+{CCD3_`l2>C-A3Z +z@ZzKJRtda>D7-ZS@0=*SCj?%nD7^IouX7aMO9C%33U8CZ>k@^xP2hEn!mAQ^-Jm7v$Z%pVscNCsW;Ps8d +zOB8thqWM38cWyNQC-C}5^M3+wKs5g+@Xm|o{{-IHX#P*&T@=m#3A}O9{GY(PB%1#d +zc$Y@=e*$lOH2){?CPedp0&ik8|0nRKMDu?F@5*TYPvB)l^M3;G>S+E?;LVKY{{&uU +zH2){?u8HRV1m3mL{GY&^70v$%yz8R*KY@3BH2){?W=HdX0?!l8{|UUg(fpsl%Z}#% +z1m65;{!ifLM)QAmgSRl6{}XtNqWM38w>X;r6L>cZJot@OD(bHqk`y=^$t{!@5#D`^ +z6ZCDQ8wO`Qwg>V+e}B|x*Lmj>(?4C`1;`h9sTRC+3w;g?UaC~SE$^U*mbaPs;kfczRQGs;~i#wizDQFy~Hbu +zknc4PbG|J?zPAba-Y@AZkD%{9Ngv#h(DjuG`refEt&LER4yu{=Ig +zLcYs|d^JhmmI(SLNcs{4eRm7`$|QXsM6k;(lD;HCU%8-fzohTK5&ARxZDxV@<3Q{2 +z`=G=-NqOg5@G4@=<#P+=TPc+9V@Y4XLHu{hWqlt?`UVR6?i2KNi#6+;JjlAf%O&3Q +zLDubdd#pL%R3YCAA>TBoG>#(V`?$m_9%St|9(9`Y9lg)+8>@wU`^K5|{W*fZUU6o9 +zlLdVb3Hol4^nF0}U16cGRMIzVAOD?s(6>g=_l%^k$NBs_2wC4#lD;Cr&W{NCY9xK* +z&bJ=t?c14o6VJCEN3re9`7RUkeN4!=kEHLK2>DKvcyl7;`#UM$C9M^c6+W +zH&4>HQqcFLpzl^mUwMRj{8i%JcfR%b_=}Y9Y9ZfsLcV(>ed{CWtCIAs74$tL==(;} +z_htmUd@1RBTG02bps#y-so$S(J$`3NyiX}_lm%~Qdvm@UgnTy$`Tj%F*XaUlyZlYk +zw^7jdf}jr$9~AWsj-c;^q;HF$?-4UUD%O!n# +z1brI?eVZhGYa{5}DCyfT==-~%?-NPi-!HK42ks7L-qs7O*TwTCUeyJB4<_^c60i0G +z>-qP9#A~|1dcNG>L0az$_1z-W_lTsg>tO5p4)18@^&V_p-^CJd;9%?eF6bz&i-q}U +zn^3+-C4G|yTaWWUNcx(D`o1aXdsWgmYcT(IQP%elNneYguTs$0B3e_X=cv +zf0Fbi3HtU3`l=;;?jhFgaX`}N7WBO>=sQ0_n)iqBZ&+o00}`b5q@Zt~pzqoQ^L>GQ +zs;{GP<3hh&BISE)8oys5=bI`zRM(iJBC}2^GhXtO+veU +zEaNneYg?-N1a0ZCuWaO-itU(!eZZRq<<(AT+>v@TAMFwQ$k<6O}9 +zxu9>3q%S?)x_xI!`V#(awC|UKzQ-kftJ1C8<55Xps!+bK1bw?CeNU(JeS)lShoo;b +z)i)mXeIw|L?JU)IgmwAsou&1?P`+;keRCy!lSf$ljX9FO<$}KN1btg2eZ?dAy+~Q# +zW=Y@5e;e~)y`ayYDBZ^#!S^S!zE(-!TETw$`#J2sg{1GAk=FK`kSMJqg!=v<=(|hO +zw|Jzr{mLYLwSvB%1buHv`qqrJp0{3;^aTa`9TfD{OZuuuTHEhiNneX#KmGk2R^BdB +z`;OxGg=Bs0x=8)`J${cH^y%;CfWGS`eLs(~w%;|9zD4gD_B$fzTP^8J9&PRaR!RDb +z1bs&ZeIH8tE*Z_wa**}CC+S=Eo^fB`xS-F~)vRynXgn)H(g(lXYMMWU^8G64yG+ve +z$I<+32wC5ylD@U?@#iw2uT{|Zl%#LcIDWrY*7vxi4<=o`zWVz)pzl3N-_~)~^T#`q +zzNGh!`q~A39lM$J)kM(OuA8)O67;Epz6?p<$#MJ)2wC40N#DTtjrk*1(6_3adEGSs +zV!E%4HPY$prj?Su$)L~1^~DML9_bc3DwzFC(CAuEkoCByB;Ht!nEvT;@J!7v@iuo0 +z=ZSTIe?|Aw|C9JTH?>#~@HcUizS^hg)Sn!#PyQ!{JIKLSG0x7O$cb{cB+rxN9QLdS +zej_BAm0M1qE6EEac_A5r*DEa3=SlKnNxo5%^CfwSBo|0>p(GbcaJ4`7_Gxn7o*LWs+|sZimRvC$~Gq +z_$A~MlUzVX;*=84u`Om$aaKA(KnVvT_Wlk08^GlI$m}>V{VK9GPRy@@)0F;M@~um(@AISwE(u04c>}qzgP8sW^0G;OiF|M3zf5{}6yrCNNhbO4B&Va8 +z-zKsiW!``PNxnw8CzCf51(zVaeP1OLQReNrg?QpceOt-H@uI%h$&PqY-!}4XyjcG? +z$#G$c1MQ>Y5~nYVuO#Ux^Y+|9G7`l4RFOiIFJtm9vOB@7?*PjES^OTNoFnRgn@mA@ +z5R>p|2cHO^a#f5@{1Dx({l)0b?Whl&f)jRbh%?E-dA+_{7(8_j?0re +znf3i%lIKhEO_F>Em16~cPjuq%yzBB7e14?MA9T|9mR$ax%IyW&(V4fUE+^xXGKbmg +zJ#v*vexDSgd@YkdB+m&;P$=K4D8sYRessV18Opprd`vnditY0WnT0ZM|IbJT%DnwQ +zC;NmYE$FY65{|)&>ivLEE +z4@$Dq)hu`JD(3esnJ2~Pq0Ia9cjPscr!cvmw4nSLlN(5CH&NdYWL`Hh{ZC{K%6xns +z4BZ3f>3<>bqr9BShe&5(ivZ>6FUi9t`LZN2zayj&W#0Zr$p(~1Gx<3ASW4d{$%j!+ +zVf%|ng0irOBr8LUPGDpH@otq#8-NV@v1VihdEx8_%9|KXIz7RV)b+2 +zo-3waHF3gJk7tUUo|#0DdOi2u$OF?8m?L +z&>5pkJp8x3Lm_GDyuby8QpD)OFlri4&3+8p2puIVkm9fqrqGFL!+9wF=yNE13=dwm +zBwq}|U&t1XIciqM)S0=FnVHkNiK^pXO)%?#i!N1Y61JHZ@DBRAvzO& +zPW;+D?;=KF<%05XOIj9(pS?%ahs9@=W&sVqqD|;^ApB@gLB2t<}~p$IYa!^P7ZJ5yzsL=Dg5lt2yf$b +z@UuP_JnCuSXLb(wX`KLm3g>=XpZ3l6C^$Y&>$LBPXMDGPviJY$Ja1N)>>0XuJB=f~ +zf2)JMPx1I}PiDc*c?I)5SLc?LF3AnuIv6J2Y!L2%Sl@L?ONU{8HC>^UP!r`A)4oVI +zosa|jkM2(SqKD}iDXKQ#OG!7>n%r5*aaU_R;5w86~_xv@sw!6hBFf +z*XJRobBvgueE&o*jb+>jF{OBmC2hEo$`l?-A>M%zQ;6ZGdz^Y(hp3<7(do=+BeU7< +z82JWB#1qs{|J?N7@U-+ZIwSooPex}}8daQIl%JiGt1VuPhNA6~z95eqZgJ?&jQK7R +z+~X?FUNWU%DKsx_{Ta};r@{TErKH3=zp&Ix78Did6?hk%ejDN{%xFQq??*p=omzoP +zr_PRdKmg*)jrVD1IlHB5@aL%;cwHBY%X4c}Yc7DI?Y?f1&2eqH&@$6@MDEsLj +z#eVt+u(y5edX&S~&;E#YI?*l5_OSi0CkO78Vn}hWcTsWS%_!0CqQ{=bLF{LI{Q7Ag +zy3Wc(7jvw{)PnOldnv!Q+eVv6C$azb=dUv>r0S*PL*A2HTwGYJ-#c#mO!hN6iCx+Y +z^4!kgNOrDgM2?60DCQuG>3@2tu~!8#Zy7ZqjV;JoQlvAAnLFmL25zC3utx;cV*{}` +zXHl^@zolJ~>z$CFk9YTlK^y7ehCW`&f}4w}{Y72F(9g360;Y!@X`^n0=Nr@w&Id)4 +zam958=gpfO>SEJWJwkd;6ZH`dH3e8AucU-7dUC~e)na{N1r%!41x2M^)AJyUhaOkM +zq?!jS6}nL5%ia)sGR-?bS11J3p4;2>JZN+nkzN+%=fZp`QAgx(Qa&Z|2aLJP^1KU5 +z3v!HyXv2&Jn)ozMSYP7vH9G&&!66!Qba(|>XC~~8V%s&d9XUL`yLI7LaQR +zc@X(<9 +zwe#{0LV1Lpr=N!5bL_l)*%)7B=k>S;$cppM~k?f=oNl +zBET^UDMH>d#N~)95g)+xYcTzL4sMt4G5#dTmnkGc<#G~5+a!gZR|j&Y%HtQJT!`_j +z0sAQANtN5P3Q$wXe^fsH>QPRJ;p4Dp4CkL4!}Sb};k@yPGh#S@0rI>tT<@wF-fy17 +zbkD``egf}>Lc8z6@UKw*3DYUDJiIsJMToNyOA%Khu8!s9cqW$T|4J;^vm5Yog}e*A +zD-`kx^1p&`I%p5a^75%pY4VH}U2hFV91OKN9jR;CF=l74Sxd +zy}t^$3ou_H|Hb$p0jX26x1$)Oeh;ufA^qF&_#y3hy3v4B6{2By28Pc@yb-WaArAxo +zmyqWHf1u+Mu!)c(fJF)!*`DG})NX*q3b_yPXX^g|J1OLOKn +zm8kb$fTarg48u=gKFJ+;KK(lIe1>-5`Hbwq^O?|r>zj!j}9D +z@K@^h0TqRvzXa)D#`JK064>=kz-wqZ5Wnom`&-9&ZkJy1oIfz0+hY>o6xvTQJUgEE +z=j9j<=L*?wR>+I-ygXHiA0sv)+7mb?BVLF&8F6+3x6gtEUjG#+KbFAD_g6r=&UiC{ +zm-F2OUY?H*CAGQ;(F>k@p2sO#PxOS%=HcEjP2GL`)_A%ubVn^efJ^$32`&x-p*YA +z$DO$yenB}Vk?T8$qOFYDFOlbS35HKeTjNz*jdHydUewfJfYeZ~COzOh% +z0>nv(*LLCMn1}LhC_jYqvnX#z{BIXtjze8=KJLoP(Y-6re|%S-?mEPL#1)8ZyK+6R +zAnpUC^U=o`--H<7jpMo9ct082jgM<~egf_PS>1U4x!w5qDeA`k)ZN{$iZ%W-1bZ2<9J9Cm&XAvR>%yLa{=jMv;yT#DDOz( +z<^2fpTf`Q`uHAXL)4HSI>CVTk)}8B_-ktZ0Ymhe&d5gRA`jsN@UceMOUnB32-MN4H +z3m{#zzKVKw0p3CVL3f^i9paJh+^@v-;C`id5AIhk?ZNFZw+GjITMu04^x)+T^x)~A +zM0~ji_cPlO-|NBK>A!%nwBCSSsDJ25F^>A(p1j{&)RXs@3_v<>&g#ka-H3QwPu?%? +zN8AW_y+U>(zTcDQQwK=b3ypwx(R%gd`Nk#ld=ry-zC)7veqb`--L&5%^Zm)9WWLYv +zCi8mU3H&=1QjWYw0euR23c~69`!|%|ME))a&rrw#l)nL)`p<*OydI8T9J}@6?J=Mi +z*MC7TuK!Yu&qSOD;pGZh+>7V86y-ZGeFdg}2-82`i?55f_Tv41UoYP8Kkmi*{nx#C +zzyF~Z@As{}c)w5V&HH^yZ{DA#BIftz^|-A!uZO=kFV_=@n|t$q{;%G=JO_I7@_gBw +zm$wnpuTaQw)MM|%`)!v#yuZ5pa6Q8jFYm+q;jBKqA1>*``{D9FT;F|txW32waDD4g +z-*bI<{kNi?cM(7D!~0Fv0c7DP +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 +z{!kv%ICn_>)LGv`lYEfa7`IuPdJ$6|7)C4k~ +z@J~%~R?vAsT8m`Dir(pAOZ}R#NV*DM3r4D73wv|ien^ +zZWyPR^{7zRfVRr7ZJ^7uXV{vJEdfHB1DPBAnXBr{m9T!_WHb7`U)xjv59T;pjG@({ +z53QS62dNTvQC&KXV%kxIo+H*R}-cf0^JK6UD7v5^nAI +zx~bCSR-@+UE30fRT_w2ah7o#AnnY9Bd8n}Q!X`D$0}JLI4#H>8`E%hB2yW +zWJ6aWXnEP2rbK%n01^rJdGS`GxE&!ZfrL!`+J30czChMKQ&-*>Fy?K()MGtk2=jmYc_TI%ghp7qQqu-9U16qe +z3@ejqEb^>{vA8d6EOJVdL^&?D2d5m5PyxPWGaIY^RT467D>H3CbAzBz^d~GYt0vxo +z;-I9fuUg6O1DmUg^ZO+BhKo>g*16@5 +zG}U)(QDSU8Gfnx^Mc9h+FothOl9^PRBNI|3!bF)cSt9h633JVa@TZuiDMAw5;DvAg +zOq`a8w`BzyyI&f*XM9)V`q0B$J6rp$xSf(NofuCV+VN}nfvNzzqFY@37`*4})>Z{v$41C~(~s3Pn@JU7>hdDb;TZ(3{2 +zIV}6d6?_|tV*qDFa>B&rZs^iT`QKs-1wta8`505?3mYNFCchTMhY=9C<4gXygswB` +zQYmv=Fy|}i`!$gKIeJ +zfEy=H-EYJnHT*}d#nw<*uz;=^EMF)0yUEq +z1TVZ|8RYw?Wv!+NKMQE+EtE~%q>nTwJ8Dj*2k#HpCKzR3ByBC$+V)A>&J~&iJQJ8E +z`3u^bOKO#derAieqXk8Ft*K&`V$$QQO!Uv;jd-DH$KGh7 +zL4Pofa8p6kQwf{h+MA;rcdo!xHEnru!Yx{SMWA +zo~(OrMaDi0-J;8YT~7EasF|;VLNpk`Rlni_(s<4sD&Q{dxMHcQelgp`8XKM+;hU=hv}A3{AMzGC-j@o +zSaCjs;(SKSeIJZQK5k`=;@%VP357Rj6K~FDu{jr>H1-3~n%0jTHrPyUB9O3+g2vN# +zVN+OVdUGTwWshxd(%T&NI>f0z-{%j0cs*vCUVBKeC^)a3d9h%6Yvu)3XBJy~k_WwH +z1igzv|1g5KV$fD2=y?p-ZZ72S$sDXXX7ejYIE@55#PN)WvysBvx|rK6a#AE=vkGHa0on$u{7ymkWrX$L8lJ`|! +zAmLFVZdmPEQh40OSIGXL_0&A45@ +zo82XW*n0TpODH5&5ii6ZGCv0u?)z5oM+OzzCNYwgJt#!He;gu099Y>lgFF0F^GQ>L +zp9R#zmsk}mlECTBrn?`0$?a3e?GrS$2P=2lVT(tnG;)I&61v>L^yrEWQ!`a}{{-`b +z_8|<;hgioJHV{X3Q+{LP_v}M4wP6_=x9|IyYg}utF|3h~MzYRP$vRI#iD0q6A#9XX +z^AZ@tb+kB8Ejz@wLWdB@6`2RDGB_Y*KqtyS2{o3hxgo5Yyj4H^B8R@23VxUBqh87=j2}2 +z=q~33Z#~8y4u>89@7+n*uhzox-JPi8w~i`gIJe2g_njlh1P<1!^Kjigi0lF +zY4b%P|Ayr=WV#%T-wc;4r#r;ps +zK2?dBF4T{#W6q?HpI+~eRP*sJVdOghpRc*uD~5Z7Q0eG!60TjswNtn@dW<+a6Ik0m +zBzW3Pm*tqH=7>0EBlVMLz4J`+vGxt{?NK#8^*&oaBkPhpxM*p!XGg2I)hG3FzlDZh +znicLr!+K$;-F%HnB9E=|1o~;S+1HyPU&CIo6{MDiX~GM)wC82G@HUm{&KbK++7*~u +zi^$hbG;}n}>|@ZE0{YWL^KLTynQr)Qvb4YOnk#<{D?iSpW$6~~@!-}WWj4d~WuxKv +zCKLa9wIcI`lsCLun9;)3gx@AS5q298J{DzvOjFwN3`b4NCP6!kVWYKTT$vB_F$%x6q=4@$fz&8#FbTInA +z5IZ4gOE*St!t5LLnRd&Rhf?AqYNKHd@nQ$ioKXFXG*@Z8&PbxW$JUj`U00KmNOPzD +zK0C&kzawKk9KLm+9yLIFl`X{Pj!yU5FgAMombe_gB?*pD9>(2z{d2?`8mO0cAo~o_ +zbeq_s)=6zL28KRGjLzJ$Z{I$bzCKB@tZobYVr6XTVXE);!0M> +zC^OsLK#EoV;W}Z|#LhPoa=)TJuaL(;({_dH?w^IEc4olCA$A66jqw-vIJ +z)!-1QegcxPGIvN(uTgGlcN=*?2^AW24WMan1zlu{a>3ZYFs##DRo=LKrPG<7! +zUY*sUsl^`J_=XV(=m5WX=6I3LCU|8NYXeJmFAJmggO +zImwf8aQ#l4`c^yA7^j|$BS+ZvKij>j(1^QTP}tX8y!^}H$mom5@3oV))CzX8Nl{nY +z$@_}>t&RMks5@-rKAZZKjjXl7_3JhW|H1~GyX?SUZ&zvBpWwjO3P%sxQd=GBS25&A +z$K3y@jiK2+8O!s&VZbCpyTh{zSpn93Tv7jPBX7ZFExSCb +zs5@=sew+HVjXY+9>uoj&Uv9sTw*DU->Z=a&tb^wKz5@=iXjavGVo0k>(?1=t++j0HV4u`1R152s2qSRSWt +zh$HXDL6(1P2e}_;2UBjy8#<$SL)qsU-q3j}-jMz)DbBeNf6qL}_+xzzsin;D$oDjWW3Df8IrTC2scfm_rHwL2Tm9o+lL4b8}%a9EV4y +zl`ff=TkI}eKsDr-E-5I1%t}jg-FZ||ski9=RCgWlQB_(0zLx+20tASN5H<87giLy9 +z0?7z50b>%R2tFpsq(Cx>GZTtyLqKJLRaY##i@Vl!)nzSe_>TraK6YD+x%nT|H +zQcRtmF>#{l^b$6nrHZp(CbHCOca5v1!O#CHbo*WP4L%vysPW_3sEIw8_`xa8;90Dm +zn96#vQHe%s!7WU5+4o>@ORX`b1 +z)M%5ZVU;MY>Q)3}rs#YvmE*&re^-{^_uka>3|OTGYjSiHkRd!v{mu5lg?%oE>}AJ%>LeXvJ$Opzd+=aO6Te@Cn7UK)Nc6euCm=cVEILV@DR +z7p6E+eAq{(;+xb2^%-q2MDUwba>MG?1e?7$x^_!x>)H+V^f8;vn;;wTtAQwz!zr5r +zZ(yMBBwBWKvKwHX><8>tskm%;@mc<+fip4u*9_#o(G#IJ-K=*kqifGiTra*_CqI}F +z+MB{(u4(8Al+~VW~Nra9r +ze<#Ddd-}aa4%N?3B&c_@6E`@+UdNO#e1DHK6skwlw}j#=Q&kw>qr&+7PM(1^&VBJ= +zsre39kNo9|P@2?R!ig$|1o=i&GD^;OR^>}yM+-D1_>$6;DVeH3a=$~#72|NE3X~Ci +z8!E$ZQ6b>pz6o)Hm6M@ii-c+u=p463AUx#dqQ8%n=%*vdmQSQIK;-O_~JZl +z>bW0&lw+U#A(YSH=Q#F<`ngKYA?udBX4kaP?{%2_seeKcizI~YI+OnSWt!z@N)Ryk +z10Gf*iDj+$<=c`lk07(6$n%JB-x>7$7C)f$ +z>`pWn4Eh5x&0DiGY17=F!b@0QOr#ykl(9qdt%}f-;KYbpJk%oWGLZ-!c7mEbM_*1O +z+vBGCqR(>Z{Uhu7{GE>{Ee~4eKD_$FW_N*UFqz$1&w{OHcWT{Y7iZwkP7LA@2tH_y +zOoitnYH+oC=G*S^He!ELFKM)`R}IHiw-Z1ApPL{@SM$>$n+`Zoz9wt=RebmpHu+(# +z(BBYv)A%5ccm@{#GF`2;O?}jU@r~Z2{=expVzti@q1~Hm*?HL1CW6a|IDUh!=@T}{ +zZ^r5O%^gcjdYQ`n$1%3Qn>x=Teo>VC +zbMAu)OrFmi?~juII2FG*2O<8tDEW^=b+F5xyA8PF9EbQl_GPsXxY7DiLVWbH61;Ta +z+4Uol#`(aL**CW3%A3nF?Z6^LB +zD{i-78O-XgbffvjW^pF{0LHe8_Ii_UTdrF`^Ta5cyEyN@;}{z&G*67P)jZfr&4KXL +z``IYOZ;9xK +zQ2ld%HFOkXFSa6IvpDx4|3iEv8~=9XIuKkx=WgeN-F+erKiG4x=UfkWboE`td@J6z +z4L;AgZ}EB7Sev?KGYbkPrjDLDXYQEPth9`@tkltSD_cDN7KO$;S|rNi$xHLCYV^A* +zx%GRMtqc6+bvLB>-7Ebpt=i>xv9wB`PhAx6y6`{6y)4P`bR_2*Nq} +zhEeNjF{)OsbmSU_r^(ysYB1{kZm)}r6qOd2`^x<}>h+l-{od +z_qyFiRg=f(Z+!$#kK0*RT%KigmR=jPZ`}~gB1j|C<6dF78XB6aWcVm)Daa5qfnFh` +zcm&bHI65Wj!gfSm=x9fnjLs@4-U>2}HkXzR=V*I4hh;dwBf~gDHU^{8<#R_-5v|3+ +z`$H&DePeS&p{WAfE17T1Hfr5|qoO%fh-TfqKo^PLi8GCIf4)&v?e_TV{i}*N<{dk$ +z!R_;@zg^Ne^LU(D`?lQ?`5ol(se=Ri@AFZ-rB`Q$%Wkj@`O4&+^ru<0cBR +zsl3SDgnJ)Lry;Jl(lKzVW#<>ytvYy+-`dn!cQ})trXCdv)rNAn +z8Vsz*f=I3+jG5{7REL#sI4wK8i?u6VSt9c^zV;1w1r8C3ljn0zdAd9 +zdt8+bZlk`YXui+O%RSvNTwb@~b2ai(&o|2R3@498zD(^b&o-Pnh9O>G=87F2furQk +zA(=okjp+=r +zHPzQ1UHh6%=alk71N({&%p_H{`FUIcgjV&WrqxP^0oRRY&g; +z5mMAHAFt*4Nhgou#~Z@=V1edsl3u&*jlK +zxNB@;Z_fl)b<*@!Pk)tb2-?hQL+~5>WBAI&684X%c2Ng=)>PQX1|d +z)yyl_{?B5K*3MjnW+UOV#dZmjd17bHbW4j{Q`WKB42ra_Y5!(WB*o58yw#$=BS{Zi +zo&Epb=sQXtJv3|={~EIfG--(%f9Fn6tv3tXBjiw7;hx3CSCiH|B5j?}=T^IYes9w% +z?#Rglo_25H72EDk<~6!j8WGl~VN)6tIo8cXZIZRl%f_Z7mK)35t87wm6ic8L6YCh4 +zK-3h(X6vM;p8GvT86^>Zz@_S-F%9k#kTddpZfgR)9}zz2q9 +zH3q3uso-JAM2`Emu~ZK?9hq2GExHrwC}mF894`Bp7k;qq1&iN49#F*#nY*VJgZ +zs>HAT1eY;}-&M;85(p!cFX~S0dmG%F&=`0G`6PlsVV3i(s$dymB_tM788n>QMUm-~ +z{zE(nQw+l+1v7#P$ug*O7xih*r&SVKGrwtvuZ=h%vYkems?W!3&&SegtEvq5$|`rW +zpI1a>18sV|ND2ahid4(u4ZEzkBCw0)ZBp-qnL=@&9Pz;heyYKfkYkjFjhno#vJCOt +zJf3=gy{my|vs%@Qbwx+%J&wF^rD)AXwHB)sKuBH?I0d|)IcPt#t3u12LsHsNd?1gH +zR7Gnd4%@KCt|LmTYmG~bCQ)HX=iOR&*DATzx1G*=44i2M1{o*sOPPU|RA7|PXjgkY +zIw@;y8;@OTXi-^ooHjH7*$GsWYTHOB)|7zU&ZVWrVb5M7E@Z_VDHO8R@wLat+a@qZ +z+vj4!B+}RVaV6SxsV&9a%7?dhbExtNAk+I}Q%7@iM%P{TmN2HzGO-L=|7-2;jqps52 +z0$t@-dz|6O;>oD;x_Qo3O03?sjYYiKvi+)I|JN-7vE|KMyzf^`g2g)k?O*0wiN)a2 +zOjU#16~3_V$Yzz5V7mtm(x)@R`*iyTjxfLL=pS?pNR +zkU0%*Pp!YsSz27x&Y0waPe#}N_u;}9jU9Vbsy^T$Id9K%+{VVE(Sh@WbAd>2wD8IG +z(HaeMLK73dnmD^9!Z_4!=aK_CMXK&PqsHrMQUZ +z0mR#F!#jj{&)e{hAl?f$Jn?yLfcK&eFA?!xvf(8o-X0rX3gW$N!yArxuh{U$A>OMt +zye!0f&CdTJ-s^V$5Aoix^M8o|3kdJcK#3X +z-nH|8i1(hI|3kd@?ff6&?X&ZLi1&e=|3kbF?ff6&ePrkV5O2So|3kcw?ff6&eQM|b +z5brZP|A%;=+xb7l`@+uuA>NmE{txjE*!e%i`^wJ$A>P+^{!b6_{%z;~5bvO!|3ke0 +z*!e%i`^L`yA>M!O{2$^Svh#n4_pP1(L%i?o{2$_dZ|DCI@35W!L%bjC{2$`|Xy^YB +z?Tq{2$`|kDdQRyr1p-AL9LD=l>9o={Eik@iZIW7R1wScsCAzWIO+dc+>3s +zAL2Rf{2$_-V(0%5Z>F99L%dmb{txkr?ED|%ooeU*5U<$I{~=z9o&Q6;*>?U9@#fh1 +zKg2uT&i^4^nVtVbymCALhjKSY|A%-B?ff6&ooVO)5O0y4 +z|3kdRcK#3X&a(4=h-cXOKg3&N=l>ATW#|78uhP!{Azqc8|LYRsRonSL#BATW9R=6ui4K3A)eRH +z{~_LLJO77x>+Jj=;$33r{}6Azo&Q6;4R-zy@iro!_^nW}bcUbKmA^}@XN1DVgB{HO +z>yGsHdNh{WN9p|octU>!=)q4@v+Hx!b*gs~@B_TRab61I1;S(zJ;94dyujb-Bz;HD +z(}MZE2c>UPAiuie{hg!_F0&%S+s1iaEO_$???KKx#)7wn@b++C4-4K0g!fJay#me5 +zI~YOluY~tw1fE#aV_tk7U$DS-9mU{^Q`0jg7C8Ptjjq&&di&br+$-| +z@*HvIb`XDls2x1ULhZm!^yWl}_b$S#h!F4JNxX?D-X~DJ`-xs%1igJkFB$3WLV99e +zjrGorkdG?DyC_fnhC1aL@#c6_P`pp0c>hH7wnWgohUg7Pde0)gSBc(z5z6HyqBjod +z?M8YdyO{N!%d_t1=M&y5oY&KW_bK7M7a@IRUCq32IB$RjZ%$WpKC)0g_Mm)RPxKP< +z)of_ajMP +z14`e=D19TkoAtU*RA(wsy&>JrdVZw$DbhQY=#8Cdo!_enFJq#0yd(OWywy56SsH1jr3RC7Jbo7~eJ?`D+W +zgDBohh~DE9)!7hKZw=Agg7m&Yde0EO0};wEBhkz|6rudm63y}6jLPp@6z|PMZ}=qZ +z^6Sxy%!ekaxi{r4CA`u}>U;vqtLbG<-!@b(KcMv8MD)CqtjED#z0JJyCt3TA?!C?N +zK8)f$g5q6B^nO3ddfxdD!n>XGaxHkblX!Qbcz;3hcJE`>`*4zVzwFY-toJ<9)3lJ@ +z8AR_$1idn%_ZrfRLweT|y#bT0$C-}_FJ-cIeSART-HYPwisC&s$*h+iA>L}j%ZU*0 +zk|cAy`%%2zQM^|Zy;CE^`yJtxMu_(t67K;NZz78KIiz1`kM6)A-?^2?- +zGJ@V(qIU%8B_Tb%pIL9?Wb1ypn((fTz>Di|=G{Emx*z@0kF29E2&FF>rEfaX+dJ91 +z-B0OH)<;Nh0Ma{~=zSMKuaW2_BfWvRT@k&cDc0-IcL;CL6l=fx3*qHVu`cJDWHWC@ +z1m3HJHzxvb(lKVE!seOrlM7SbDs^adSA+ChZ$4LFXh^N?N|(yJkQo2Od0(>;WD +zeFR?KAhKTKtNko8f7c;}x$){Q9MX(--k*uyo@v(YN>4TO-k4@RuKrBoJ%rlxOcd{FMDHNi +zTWO(JoJ!_7NUsR#eMR)@rZYCxLho~;7k^=>T#Aw2q9JCzzfQNF=gc2M#v`OR8|mFb +z^xm6p-7kj>HS<21ZtXXYA4>f5g`sjOMe!~tdOuFLUWa;#-sB5I?YRu;eM0oc&an0y +z`NPOMbcS_4vWF4Bf$}jI#k+v$&6;7ok2#m3#61@hbw;1V79d6cpZH79ZnCeX&PWG>mo`LkP +zCwc=5tjGN=MDJXr=R$gK61}Mf*7f@;(OZl3s*v885oWz51?mi0syAYUS#KlKb0fVo +zh~94ttlRyggtxgso!d)!50ZE{^LSGs-Z~WT_n;RDcbMzlh8|!B{_Hi<9Pf>@tmExI +zlI-W8c$cAgb4QxvO(^2NT@Qr|#G6U9*AAkjN`n)Uc`fas-M6e_>-klwh_X1(}Q>-rcynykx^-UUc+HPIVcYCV3ONA$)a +zz12wXaiTY?RGp7a^&TdASzK=x=&eC|OU96SM5%RqUNnaIXOzBmNbd`xmvp*y`F%q4 +z)*`)2klsaO$#adiqbnE9)HxRw&QTnbxdIQFp +z^%Bd}S>RN!-#Fs$QTnb#ddrAjS($bD)e^k}D1BEUy~l{&@-lU{IMsWI=pDK!eZn=N^!)+*XQG!>Zr$IUL@x#D{R!!bE@|)(c8E-RKI^gdVSN#e&Rgq`DCv&@_cJ;XkBpw(wjo`{ya~e +z?@jgciQYD@Hx2Y|LVA@%FK@ne{hmei4y_H<$1Qk%K=exHTes)uiQW;UcPrAHH^Hpe +zJYSs=PxZAghsp5uDu7J9ph-f*OM2hv-ZPWE3GsB`J5-Wlm+{|f1C +zMSAZNJe9i%<43)RQnNbho@_u&F{zCG33 +zNc1*yy*$wSC(`?o=*?efoxbmg-t#DZ_aeRG46|NC1ihIV#6Kgw`;p$wMDN0d*8b{x +zqPG|6J%IFnCVICoRPR7iy&s9*{&gXL@DS3QnMt0XbG>~QdIg!J|E>$oCm%t2n~2_P +zXIlH0^+d1Y;*fuN4C%c@^gN5K*E73`-sX!#{bL8x>z!rRduow&{r1Qr{_o;Yee6Vf +z`9$xXMd~+9s9rYFdl=>SNu+lU(eo^}p6@OvdPh+Do<@2P5WUM6t9Oa1-n~RG{u1>5 +zAJR+6HtXFLK`%a=JV!)&yOG}ML~qYx^}Zq1n@#kRFA4dB7m(h&MDLGhDGt?po9LBr +zy=y`5C8Rem$E@dF!hN0<8tOy70Jx+L^G%(Y@z&-IUdK}@snG?>#c@Y2he8t<=81-8o0e>(2 +zO?RTV@Y@K!mz@HC +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 +zuzXy(4tRe%N#*MyuzQ5PS7RRv`Cgs +zid*eUon0z0AD6EbmXB{w2>Y1EUK92JuQy?LXzUANxqtaq*v-73j92`O@v1!(fIU-K +zKJK}=)vnT6<9P5t;`-IRT?@EZY$NyIY08$Rsd}qUQ}x!Art0ms +zG}Vr_rz!oNX{sH)o~GKxzBE-{KY&e~pxV<2urns8dYd;v)myc&_i3zQf=a)4f=d7S +z6O{hN6IA-In4rr4rU|P2w@*;z|MUb^uKU2An6Bc@16vHX8ti3YZv?wnSnj|64OX08 +zDDpoU>~e?Vtp|H2*qshluP*|A-=XUDQ-|uuM})mrmuJ+7`KUO{Pk&TX_VJJvr`hW} +zLsnjY0_?M3UjX}3$V&bzAuF%HtjW{u^*1$nR;sY_`a7ChpYPS=nR^0@Q|tBjGX>N_RJcyX#7) +z57>Tiy+7b%_&iKl2KZQld+I7*iMl+)Qy-wqv%Pd)G2(P@y_YUexz>B@^7Ld8@3j!` +zR$)Ka*u%mOL>7dq_77=uC4Ic}`;eatz!TN6hLIbv6;wHw$>Oon=6IPuAsW +z?INAx>?wVUE>ADlr|R;QZ^4)8n*`}SSr6)u2kQj87;FpJO<*5~_}>Qm4cMNVvO~a5 +z&@A%l49{m@2tNYsbg&D-E(d!V*gL@P0=p0FcY%6?_>YJ9Wqr=nRejEa`YeKUZHIVI +zf%e768F3V#7+;n^d5Y80^;30u%DE`di=aF&$K_cJDhx=)v`}uHR)@M1~9~QcQG7di%>W%ve*)Gn|++Ou{YOonZY|pN-B6xSgMA%zWqJR^=NrN%>+Bb%#*uhY-V6AA +zRa4iCge~LkNZ2>{_#^DA8e5^Mc&`<98lS%k%g4PPno8emfWL%rKSH>kx(YW+SK+dC +z#ha!p-f6nxH44i~YvBIXx~j(;fOi-0o(0}(!23$rGj;ZjuIf21PF?RGr|Nr1oXY<= +zxV|V(@vi{<7r37ery?FTXF&M%54TbvW3$I9={=zBsa4{~wKsqkHuuno8f#nkuJXpuZgf +zzg$b&Z#|@UDfqdkp!}YPeC^g$dgehtdK&!WlbSs9QOp~~X1bWyiZc`S*}6Q{UCjTs +zgB54{>C1GrpFRQ7|1_lkNvNMWP(M4MewIP~?11`N7OEeU-);)`+cJM=Lp;skmwdpV +z0r~Lrd7`i_I;#eq6`->Ybfmwz2J-|}{FAnRD`?&sl! +z{g|<4VLxYVRf4*|Mc6O64&Y~m{gSbl0Ur|fE5`l@aB6p@Kc>6FCBpJaj~}j|2iLC` +z_7K;D>o3FgL&EaONlFiHzvt-^_An1G><>I#55<25?8`kM9N^TR(5}JG?Wyjs1iTvX +M&49N8-UIl50Z6-5d;kCd + +diff --git a/toolkit/crashreporter/google-breakpad/src/third_party/linux/lib/glog/libglog.a b/toolkit/crashreporter/google-breakpad/src/third_party/linux/lib/glog/libglog.a +new file mode 100644 +index 0000000000000000000000000000000000000000..8d2afaef645de7ae6ba30a1b855f75343f689383 +GIT binary patch +literal 226928 +zc%1CL4}4U`xjue2*@Xpyi5eA^)j$EG?!-ONUF6rAd-1bN>DJ@4tWl{rm6#$-j(y7AO8S?7eV*->mq@{q5f>WnO(! +z|5w&?A^u#Sn^#b@+#g)-@&zK^P{8eX1>E)CaD%(f>zX*XG2(4@=1&WUy`ji#uiqm# +zNom9=t@1|7!&UBOUWyN_T3HF9$6wi0qfV}-Zw-uVqxk&rL2e1=o5 +ztO}$11{^SW#O-i2;|qgVC;W{yIVUlCkB*BcJImwQXeA>s16>kI25 +zA(mNF*rc#G;sR(Iltp2$e_2w_;xGlV`$k00i47qykz1d(Eh%XqBD`z$}=`vTk95TI}Xsc@(!Mc_aq@1K4i-0Y8E$3Hx1D@(& +zl`n9w4g{447o7!nyM2*rpWjb_5nc_2^}ay)N_oMYYFAYO{HN+x6)A2aVh@JOD@7K$ +z%3V%ivRp(3O%qB7?rWA;0=CrUS{`V0)ipOeCy_c2hU$s3_=wWDY5X}=VU3L(lh|Qd +zmKz#)LpZnS9xpF0w9jQk0_AmbRiwmK#m}l;a+TAi3B)G~Bt^1GGR=gXs>tRgMv)5x +z-c>H5RKYs8v8-jTpz{cc(Ou^`P?niemYoYF$>oAMRYfk7oKi%A8N#U{29gsxDd`Zz9ffZVc&Wipj1hZCRghgHVKEWSwWj{ZK +z4PpwFpUehek~tTqcIFJKLoEUCT`PQA4rpSWbFio;*(5QOXG`VQLr5M9T`q1tT<*qZ +zBR!Oxh;LcsB3P%(MO+cDE7H>7rLjv~Wh|~qywpGt4^P8g4n|XmLh{{IS?w~;FWe+? +zoh~X*GAi+hjWehM6K`l7YWhZM=bT9Dg|rrufIH%XcBR_e#BQq2?{$aNZp!7V3pTWr +zSJdW{W?fJmatA!YdY8Mdjtqv>Cg_T|m&-*I2$_QBPI5ysHc^$MGoLXjWhae*V+veq +zp9wOeAlAf5s!kdHq)bf|(u9I!lphIt>tO_cA*h`b88x8=PG$Pxd|3-sR)Aj^ +z&LWM|57y~|NVY&Dg-VQsfWsZpO`X8B7Z@d9zzvfx&V0AW6CxVw4ZF;6r7MEr2xN?* +zQcX^Zb7h8eeJ~YS=L5&Hy4oBm>n50zW9Aj-4_1V=!JuEQl}V}qBc!+65($O@t&D}sK{g%EPFrlk!b?=oNWg~+c`b@jf0 +zA9SS2>%Wk+gtNAB*@dGm#+oPR#n2xt2Bh{Umny +zUQ+|(3={k2st2p!N;ZjGFmahXLd-~gn3z~{Z2?Dv$?va +zT76>04Z*Ol8M=95gh@SzWM5?+uDOCDNn +z4g;;^=zJBOir86-pr)kGNps!zdUeGv_xWUKR`7U%{N=kyJRGBdqFu9OARQD~_W6u& +zS5yyzi-8lk3X7|WnVTOVmU9LS!z!3%ETiT$81i|;6~1ud(~d-gq?>&wnW4iyItrVi +z+$d+m$4Z`0dY|OK4u;Eh#PE?3v)dO5!xJ1g`H`z?+00-y8L1G$Vp1~2%P%N$xf%n$ +zfG^^6`^ga9V>Z+?9PT5c(;T^TW!HZ+D;uqPV|YH*W3smo|$@DmHIwCUnm-iX}ngZ_DW +zwYR+^zRPBUqaoLtU}p(foe>uuqGG~aMcryHOX0!0`E8Mn<`cX<6)hMsAwoeR +z^$k@&F3g|t>m9AZvN{VFkfBGDS5ZW$J0s^oj8_cKp)m4HmkK}TF9Q{)`POi`kVkV$t?3C6vul+S71ksuN3-TqJA86H94kN1M=0DJVXnnWm6*^P6dACUL%#i$t66OjjN}v*{#k +z-e0F=Fq%#`?!ME^Ow#V$Fg|ofI5%4Vp3bw3L3hdpkcf;{Nu-g8zMn2|nHjnKX&z5% +zvy=u%xmHpgWG*nZujH>FQZJ0n#7vNmF_kTzNM|aw3+5fjBmr$c59lnMNe1RC$i%054lj;R0(5(J35 +zh)D~)b-|DatnmAlD1Kg7h7Uh-*^tNFopvo;lfT42tcY$_-H;^^FD?KW+FJQY(& +zK>{Q(o90tizk2JsS55vlLR<9E)7nCoY +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 +zr`KZaT0&lwGrFv8O!w_ZLqeT>F%U;vv-3y7| +zKbqBMEIOX@XR!%1@3(U4(6h(c5vO<9W4zWixtWcZ@BtWAyzF(Cu?0vC+UQ#ucC(nV +zQ7j|^X6Kbweqj+PqO(znH$%Cu0-%J}*mS#k$~*-Ut3#Xbv#Kdkyj^^{O~-u9FVlHx +z+^eX}GD?+Lqa5}0(A0YA^j|<8(SGQ-w$Wdju;!@HYwhr>bM#>79W6shBD|3jZO=0f +z(Ibfqc&b%9A&DNIYNv)pJI|5uImwizdvfx)EkfKDeO!E#ic6nMUR9dql3Kg6;u6s| +zaZsh!B|DR1nVLN1+zr!n(P>U>x}prT>9D0{bZpw_*j)~knLME++BC}_wv}k+TjhB5xV2*}cG{65jII2= +zHLuN+$CG>OkAJW=lkWMgSIiUkpoDRHa9uZG&}_X6R#82(jRr +z*hGwm;Z)s(kvP>&^Em(-b)^tBfq%70NhA7ucodGBs;Vx?FhJMBlHS(_a6R6_%fQ!&*chGnjQXAe@qQ1>eY7u^``K8aFJ9BnMU=~CMY57E +zEdq}RdYw_R>3NDb{r@w*lDIs2gWR)rO^+10T+a<-SmNL2^666ke6DS7Z)|Q?ocy=M +z@3Q_sneutb@B(s-g7GTBWdcDB#I(b71u{oy6qqK`G+&D2Ym%`G$3o|3bQKtvd*d}{ +zFioZz4Rn*E@B?RZdo{K_i}j{9j_$EZoPU{IC^J0%p6vO2h7c5KAz4MCA$Gv2Ldy#(pOwY2&^-=5yUdglaAw4Ym9C&T8 +z?_~)BNwuOveU5gDHsV}5q+T?@ht$>dASXuMqz&!h_9!FlK4(YkivX0e*Zs@}{s5fN +zSGcm*?Isu2zF5KT!ds??Wq7w#`W9U(EZrt=Ts?&z-wye2yfH3sROWixGIWcr?MnH` +zz;oE4=;Q&uB4P3XTaf_aq3CUJ1_{F(>%elr##q|uIJN=x<_v7nUj*pZ40C@HFh9sJ +z_Z|WBlMHijHg=#*{wi*#=ydIiv?PtQPk#x794(^mApFMK%e4EEi}cx#Gk*ocmDx=l +zuDd9H85^DPOy#IW$WjYTAH8=#A=DYtbs*BysABL)sb;Mfm9Hzo3nbcCGr8E`qfhhK +ziudIW@%BZ`-?cL^?m*~JY&9;zwY-?yifHlhy%@a)D-qVBd36leZg6ZK^<@$+&BNU1vR~+O6!T|P{*8lF`EUA&C1}7=5<}8S%DJLp8@7? +zDYP6gBQtd_xjtb%W%o*bwc>kB+NW={q$&$jZgw$C%@UPlPNt^MAgow)DrAz5y&%$Q +zSXQQr?I9)*RWK)Yf?28)%u+!x&P;Q`=wozG*Oz-~LbgdQ;y2RN}(*k!V0@V +zP*}Zb&~CTBNaYY2ewd1dB?m|Gnm+w72cBRm-XBQFlFUi@?nfZ#j`Qo4T6=O)L{<{w +z^eySrJ^kp5Ymc=|SIofE0=kNH7+)UPeFL6!Do2#N{zR47suoiuueekf(wxmhz%ZQ +zv74$9L-(}V_ykW$TjO+YQYIe5W-cdr1M&&tNa^+`Yo`b!uSI7mjRpXoLx6bAT5+o8 +zd3>8t%j@Db>y-H2&KT`6;@egm-Hx%#x=tmb2|RcZ3a+k}uO7pnL*%{9ou*N5bEj!E +zJ;;qkbLhdSSTy%-&4D`O>^L0lB^M+I(VJ)wIimI^+C`3jNM}6Z2vwmyP7|S(sk=us +zaQK65z#vH(Bwmk-%EJuNQ*T3Chu?whXfQ*4=c%>t>g*_N>Y=K?E+TX@Y+B|On!(Pu +zn2k6bJ@%GjE#O+b9nKa1m~iDtf+2+`#F`=PcpDp1d+C6#oOW6sOziMWo)l5V|#^+y`Catfcax4o@v4ir@t~(%;?_4jMDpRqS523 +z#80RaKTZpDB89}gx`OS}6>OJKu)n92IF51p$Plq0yHZHJEjm`!%u|L6_9I%zlWK8K +zsl`1>*-oV>?!CI=?$i}`r%+s*71t5Id-`pgShSrfiWZNS5CmU7y%x5Nc$5x`sv%yq +z3y`q+L9D%pRxkYCMh!&v#t;DM_1oIv$^)0gX@uLTCCOgD01@?SL}w_`84Ap$MB^wC +zz0#h`iF)b%97;5dbx`&uoshQcgtT1{(iPU!%B~ynyc}odj^=e+mtKKqveyI^k~-gnv^C;p=0ZhHa$ua@dkm4p6Gwq9BLt +zbuS26{h}_bn{-*-BxLmtA*&}1^yDr9b0VQQm=&hvaalGcmPKbJd77X-7OF89Q;p%t +zu**m2<)id+C$D?z`Z=J4$?E?kt$+BHvL6RC72Ws0$`zs!ho~M%s$N>(Ry0DQN@jiA +zTqC}u6Y~b0nDH54K9^D>HkgQTL!t-`nuVEtW@WXjWzAB{YNut*N>SD}U0K)a%DPr4 +zYib8ztw~werYtKiA@P;Hg*Kg+2acUGPdc{Cy?bEb<&(M0_7YFHrk~E=<|NGDf-T8W +zr>3d(J8aDhS`}x@9QS}#ozC0zZ!cSw|M||Jk}*zM!t%tjgm(|7mZ(f6=sI8Srw7AI +zLHRhW#a0wBKPDfGFFB@LWC<6Hz~oN%m3;l5Zu|yIHPuMMJuT9BJ}5PcB;12YH}Mk7 +z!kR3$2bRimCt?x6YDx4_;Ie#7IWyWyqV-^zHqQKa9sJ|#K>Bwb{L9yYhlzr(b)E}v +zZ?GK?xtmO<)z9!Xw!#ZwW#Pf_YAe6>pvPb3Ia +z)43}Z@gY^)dHNPQpQoy9>zY$i_PWiI?zOXc%_+#@ugAR{I|56s_Vf49=reI;OUh$f +ztsP@mj^iszE-qJcaSY`GUSs??F{2;jj83PkhEFC?Ypo3x0krcJWL4hVJtRK2CpLF) +zT;3a#J29S48>;Wp7_0>PPb!9^AotHDc|If`A>yY4teT_ZqaFE3LS~O7%HfD0hogy* +zqZo3#L6H+m)njl+<2x=Sc`^}l5<{T9&>48O1)`PEJL7YADotCrl6n`NPFLRBG_|}_ +zL9FaOdT>E~uTGtwE!}%uvb_0IIQsA%%dcav#z?y-&L#b2X&;Ea&OJ_R9tfXawH&|r +z{rFsaY+6O^u1fyuXVNz;P2San!#f8q{9B-47K?-h2E?3BQw4NwvaTtvy>wwjGWd+1 +zgH#Sp9cy8h{X!H$Bsn)(D?6N~dZ+loo}J3FdjBWdRCT|zqb=HmmcJ?Q&<{Nn{V};L +zvAeAu)7aS2k5|gc{rZuWng?u72v@#x9uZ6pxd#hktY5LRt=^RDw3}sY^o@Xx%1CLG +zlJ8z;2i_(udymc9OV|IicjqrtEEzi;a!6iJxBgoXTmP*m$xdpU``imhNwRyVvra|V +zOGBQfQTz8C6!x8?0|SR>0v2@6CC7n?^ZcRgeXsYF@94%qu29kGhMQL)8j&>qRl +ziLK7diqG9ZF4?iMK0U^w=5*0wG3D7~^?Zw2$45xeKuuqc*>-)D3kyFlDQ!$wN*hHf +zY4|Cb*-_X9p1*PebzP}SkO1o8%7fgeT1q{jO{kmIwoH__4`@0vb#YAI(I#(aMrVhb +ztOT7-%}%U9%6nPri&w-8JhYa6i9mskeG+D?b#G%WKPYG?7O +z)ok1F9NjfM*Tc8uQJ<$;m_sn|TC2R((z<4A=KW9LR>`uXd4*ecQh#y_>aOi@TBd*h +zi^uI1r)|Irpq03zNcsBSQ_80{T)UlTZUpjH4pF281w5K1>I>RlZ +z3}aa*GDg9w?{Ko~!wyAfoaJlR-~iUHK}eL+cKUEO%%DQN_|&qOyK-X(y8in3z(DDN +z>}}A?-mTmN$Khi2M4tu4ec&fkwUc<|RCW-nEK_bX2ScOHj(#^wyD+=0(xOC}tzK;H +zbFg0DcKY&cEv4CXP9R#{&phikZ6|v$204l`p!;*3`GkX_TR+xM_Oksm;3^sjvZ{`j +zLHg}9f%e&FVRH9)zws+9ZHoZZRzX20l7OO%0TivIpp!{J?MrEL)f99p8Iz|U@@t7j +z7g1bSGTaJsWb+SY15FDcs~MUNqX9^Mx1L}%UC$D&g}FSkuODXB2&==^WKD<1-?L%b^^VHi(YzC@oQ)`G_utwA+s`wWBj1yad7=NAzGn +z06Te6Srlar#wtzw_ub{ji?;{eBn$w(o>0rI&_U*iGVb&<2R<}|u +zJEm&c_Czg#`d30WNQuy +zeFA+(75b^OMh?lTvqlcd(zA523dD_iXvQ}5CvhXFL(;y2f;J`rwNZzp%}+s_l7OPr +zA&E9n(B@Kds +zVa?E}LF+tW)}SBBP(}h;gFeC=wCyy!r9+1FwqA7~k1fiK0N=4+Eq=|Y#CIu0Do(!)6^rho +zx!ny&`diu#u+_nM8$D}#hUJRlN-0sON@IQ*aea7v%n?!t&@{HK#SH|HQ=wVGhv&o= +z2Fr@D!s4+%Q`mSr{A$jJZgybq8E@f8@%;(u@%0udl1bH7LZ54uULQff0l4IV#J=oz +zXsW}qgnjidi-!CT+jlBM#Vt|33^+AkhnSwP-6>Mh>4y%roU-XQ +ziOoN~+^3Zp2(n&2nbBrN*QB;etFp8KUFFYl;5CPMP1c5*p6op}JsWZ$g9bTTW0oUH +zm0Mz3O8NB9i_*T6MMQ@?9PQniBzO2OTvpva;{3&$;c+=9F2Ulmj8_f_IiQ=m(Cw3H +z3F53Ay4SXu&QXyl^+sn9m(bk6A~e49vAR_;+o_dH6k$mfnt+l1R?%wEChSI`&z_KK +zIlx}HX+3DY=iH@zp=%(KO>2z_(#vHM5e1QprN%LQsxc9E9`ZtUl0%h)HJ%i;!=Du< +zNU=tI1KiY9n8Z^hX?zD;H?{4hkZ=m=p*Eb%zWg&vxR+eG)8L7-v3{k8R!TD}dyfp8 +z$C&OVoz^bXyp-M9c+Oq6Lp=DF(dk#tJ4ODaLM>34?v*%ZulW9uV6%{R>K;t64$!JS +zBv10}fITpfB;w83OKeqAy^S7^yo7{z+QQN!7ItCE_3%!+)%KEAIu6@Nt+(5LWtUFd +z$>G*vw*ML?4Z!Oa&kwi#&u}R=f*ih`WqUqHdST?(GHLu_lWj|+hdJ4>Lfb6qAND-T9kO4l}o}K +zY_~|Wzy%zTF0*8fwv}3{hkssz*Iu~qGa!{)?kFV!h*`$GV3Br#l#W?iNH#NVhch!f +zGHn}emhV_?A6PScthRMSr6V@m2R7-iHrvJ_()J;(>=Vjs7}tQskwZ&vJ8Y3&u-Lwu +zDg8GPMl*`Z;ZHJiD5iM4?Oy3~`S8u^tI5dZu*LSKMS9I*Bgfy!xI~hEo?&axlul;Y +z-p`P_>GAiqqE43<^W*WhJCvek-)8fW0@xn4NI&A$JU!pG!y?VKxd?_FY_r%N945UA +zH+w9BHf0<)2{dOq1u)+Rwa-nC~-EAYJqr=ICJtJUa +zfYVu5wvUwJBguuAM&2$-n=iWkj~7Y5gJ;PPWy5ghq## +z#h`iqecvMOwAe`TNh5wbLpqgl{&%ykBH={a6lozlZyH0w+igpw +zIV4g~KJ!rKZu}WXH+P-a-9;3(aSs%1) +zA1bXMV(T0tJvzkp>=5ZY^!Sw_HgdgZ$SCsrjiC^E-%udxAIj_aT3eAckJsn;&$QCU +z#_o)}e4*69?-YLKAq!Xr-YPDiAuVCYHMfwkwEQEh^aG3Sp-k!L7TenyQkTWHFGE_F +zVf#jg^hgFA|0n~lAI|{H+RTZsTcrb;bw9L9&sc5b_*YgNVR#>u;Hx&?+#2rM@XmX@uOLA{TEq) +z8OQ?s^CKbdJ0pRo{URITeEFi!k>8(Y+qUOOZ)V%x%a-1y$KS|-yT^0dEhN}=iH&5U +z^-{>to0rZaS=^oby6u-&Nr$hpk&~yd{#ho;{p${!ghm#UabG`*KWA6GEErvVI?gr^ +z#@})$jzp`RV{NVPx4E81McwTAgW)9p`(#voe&>&(`RC +zKms}}_tBZTnlt<(yKVZ7_3294e&z_Nt4G&$MDA&WjeHZ?dKp^}D~b^ttX9rp8Si2l +z?-3wu=thT$S#+3~MTd!5`sGeA+NWFezM_m43~RczK8w_8j#aHTt;Wx_rs?Q61%mP% +zl0Px!f`7B-&!1HxyDH|-a+Q@YkgDaXYFG8#N;sAx)h(ZO5(wP%2bV{J;fTi@3ZXdF +z^Q)@M(&robu@*aK#&vZmsnNZq=ve@rAS#zb|kv +zPuSf|uY`T~d6hD-f-Uz2mb-k*T+15$eiA!;uNJ-5U3YIJJ1!Gy@-+3-f(1oz~ADU;rF^j6)b;c +zzL2*r5)Apg;R;_k;viCQ^m`mZf^*b*9d&LZ9*<*LC|K`^kob+%J{-cZElZfurrjnp?tTy;nw-6~DERa)YZCP>$ZCtvR&Tcztn^0FLRfk&0ks}gxguMZeqq@AhLY^!+rq3_?ED6YEqQ8b1$Ms=`f&+5v +z`tWecaZC7G=~{=hN~#P6YyIB(FpU9`p{6Mv$wbndq!5&+Cg3IjH9<9QlIsv9Omr;d +zi?lfIxZRPjolSAftC{Pnk{8Mg%B#!eDnTAZ5RTh#hv1ew!e0Nfu|#5yd!!}Otqq}I +z-K}ux)@7bsQNoc>W1!9*@sir+M;;Qz(@1a1GpCo&a**Z~4528&25$i8eHp2v$k=fT +z0SG{H)V7e?N1#P>WbS&$&h +z1HQrWuZq;*%UQ%QRfNe!@**X$EZsfgsU$l5!$5`+)H#6)==r1bRwyr=wbdFGP( +zdXLAkV#Vb8`pMz&ghu+$A%V4Zdwd>BKN+Geany&GOXc%s&Q~NV5#h{VAkCasJq=h03LYb2O-|yxTcX+NOt#C=wriEmLFj~8}cHM+&N`Hn| +zD`xMR>R^wiJ{6Y}9!sz<)eq3+;kWqUYX}MN +z4B{6H*?vstDVsPH+MYR$F2n7%@SQ77YLaRMyfLkx-99Y$z>0y^H9b<}XS#hn-*P{? +z9vMUY%o0l63l+|`$C7b%!;)lOiBrZf{ucfJ^QDrEN~MmOw1$2e0+=>%WgeTphLgRg +zLkaO0ob{h-WlwGB&ho5@(4FJ?2fPx#n+w(ke+xBfbgwYo5=k}po-M9RbeJHm* +zkEMq{l&fw*FMKF>+gO3u;48N9q1-GAroZi!K;5tauECdZHH7YCeg?ONBDR0HucH?)5Z>#qSLug)p=wl4}72(TX{HcuDCgACguJLmr +zlHu$}R7<2Y3?!DZeH#pvBDSWIJ>BZ>OOA9 +zbw}2HE{qD~LxU2s6%cl~Nmb;O==cyK6jSeu=)QajFQ_wNe29c``uot$$|tP}x%mKB +z&myZXPjHuJ=OoR}VqChD`lxzR-6yM5Z|;m(D4HuJyC0zJc4xv>;|in+{9Tjb-;oe> +zA6`~5YUS94uiEjVu=M|)kp7ZRRhQ;=8oott=n20}&%pz#$g?Myu~XcMKN*`&vfBlX +zbbn?I^-(MBVAfb}&KPTQ>%pn~Yr*_oHm#jTZq*i)ylgP45ZY(=1jFxmt6!Jv|39}q +z=i`%U&-gP~Z5ZVG+?kCSVUI2GyVL~uBpvAC?R0C*zDoHd5{B;k;DdhGTtexvJg9KG +zcLBV32rI_Eg~zh=t->?i|3UglA$7%k3Snv-MhR_M>>XOUkG4Xvrw7LUCiXjMw?fN6m~ovbuQ1PT`M;Vk +zH=N~%Y-yi^M9xVfE>l0x|9_qDl!y!FAsKivkq6GjgMsCCz31b%!1tjuPXEp#Y-@e) +zK8Spb4T1lqeUN`SN8=ybY5%kPWaX>G%<8KJVv^#E{zZA_Qsd=>IR#=@tR(=mXIgas{1C8VgC%hV?N%^UG8mN(<{L~LA`uG +z2D%gyPGW4M1=_h~-v8=3?RW#0E1!Kgmvn-UcWjV9)HU*6EnRy&KVFlYy=U%+aBWdF +z+tgAwr(8j+b>Q{ZgZY|k@_-B2TPGkEGM0y3Z(EZ(cNj~|bIyTDV&b--Xz)TY_0FHK)2QM8*0`@ +zvkweiPc5M1uzVa&56dT58$Lmd;}nJ?X%^rZH!CqtvKXgWj8i1Wa3u!p81x3M$2XuJ +z-yrQ|?V1lIzPD4Jx|3I)+Ct%kwop`LZMccH|bg5dFu=OT%3*;YJ48LAse5jjx6LS$dk6i50kT9=^+@Et`u)oPb@a@ociy)94R<_fns!!NIKsWF%jq)*UVddlc+F{?0tU1O$VtHKgCqpH=gtRi9 +z6pG!O2RL16>!&k!ws+|%M)}3f)Q6^*b9rkymb+O3q2{5XH-mEAiHXVK|ic}ig?`~=Ol<- +zg;&SP&cce|@|ixrcYf_k5?hueyFosRYTaRPF|0@Nh6qH(DEB9kTUEZmz4#vd%R+w+ +z^jBg~<|9O&@RyE!{;%TO4RG*JDYrA96nw5X9Ck1FmVyi-A+Nh$mPT=$<-W=a$+Fr$ +zgq>ztts5+0mmK8p4)QlrV(U;O+9zFPk7m#v0AOXgG@ksymQApRGoNGtOejvbvM?GBEckpkDnao4A)$D9m?bEjF4Q#t;&G|J@X*gvJn>*kE~%Cs*d +zb(sKnisMq%cNSk{H7*6Nh~OrWE4e9fiwSOe8n|@?w=fOdGX%FX4csw;yFU$FKfyhc +z1`hm;@1($iE>u{V{I&rkE4ePv_D>GiLb-|IvVO{3Z=h?2_t?$a0&pJX>3;(tOUya@ +ztnj4`NrG*6tSgh39o|JyajTN!W|M>0vr@|vUK{yK8n`XwVDiY+GVdS<6E2dZo5@w{ +zI-@cVRb}2ou%9D^xdE_GnPW$hX1?|k&ihMqY#G5mlgoMkW{z#(9n4R_?vJu0#exjB +za_k)`WOb0^Qnl}%H2HFerpGsh;9k32lI}@SM;^{s2awy0%B;1EO&B}N9J`NW?*?p@ +zIkt;q*8S}fPk$-FuD?!_Zc35< +zh7qhxUj)eW$vJ8HITpStY<)RJ`3ZK{b!n8J^hpN^j&_^BFi*dTV6P?QO9A_)xehGN +zVtHMfEPX)-HWB<6^HR%eFTp*N$Lrv~%w=$jU_Wz%Bz@L|leT}--|n~}wZC69l9eeH +z-(rrtH3e=R!5t#$u1HblXE-0V_XFm2bev;hPiAX&rYY8X5yKXNEI)0I%_rCiH^MvF +z1a?buEN%Y;n@2j4$HB*&YJ>#?#l{k}{S*8_rzBOTkk@X4%PmNaJ3(-sG;r2z!kGqc +zJi%EDCF#BtxN3sCKMmY!g6ku=vJ|)-1UIE9HSQ?Etu0F3Z=WH!r_;cVCcfe^f|FC= +z$_VbNiRL&u{w27j1h+mJ4(Ztzg8g$ESnB@~tiPD0Ve0=8+~zcJxfc`Pis0s@z)c~z +z;geG1JOsCB5`4uqh5tivUrPhGo8XQS-1HQ<69jj8N$RnNmH7ELrGXnyaCZ>gq!jgB +zO>j*F=Oq5N)nnA|HNOYO7(4G^ew|s`I|=UC9jVjqB)F_QC8-!7Z{%V2^P33uoPY0V|cM|MQf*k_97aL(U|Ku3K +zJ~xfDA7WnVQ#BL$L#1z?BS|eO$~BhYE~?<^A2jEzCfMA$=K4v?pUd81gUwc~Z=@)H +zE_>&VV*hTAJw~vfujE+R$-)FHUB+}^8D!IGjvY_1f4Ym54U(Uh91FU$ubFK20+`8~A!1os!hxf39V&1JQS +zbAAD^zco*P9l<_wcj_`dLvY_AI9Oe6{iAvM$9ekHr~021<-dYqC#R78c!FEFNHU!Z +zr}|HDo<-)ig7*IecR#`TQs8zFTo=L3O(CD7yd2xWHT>9IKl=!_m?#H)jN4d0^}gBI +zQKX+EgM-Z}@>)r7e_E1y4A)F>i#{(&e+5YO5YzhEL9m~3Nz$iNm46g_ANB##&szgV +zoXkc^vu4bg>=-+1Ud=d1(S(8tMUJsGwT*#DBRjjr*+|cdh<`L8+)^KL*OD+2V&Mwq +zDCG4|huvZ>0YQ7X@a3h7(l^BbxnAzxtm +z45wUK6;41EIA?hy3%tv`A#b403-6sTbo(2!l2LNTh@{; +z&K-~!R0R`jB&kL?oijr2@QMXqcQ_c(rBW3ka*C|-X*!Dt@dMKt1-e*;^}ay)N_oMY +zYFAYO{6`Y3iWIZ$D#|Mp9<5fn%L!PPi(vN-T-tOZ`I_aGT8vVcYk8p2RoC3?oaAx^ +z;Jtgl%SX!YrYv)+!Wt(zCLCc|mKz#$wS8_R96-4k~MppFVu1@?gs#waj-{OB@e-zB3ndb=pGM0o +zX$UsZJ#+@4Z%NvYv0UaDKquCEm-_;u0vI6+y#db!Xx7x;iRo!n0dLZna_xdS^Qv4% +ziB-F*^N9qjrl(bPgw3#7!SytCoInkm4P197xn7VqHEROS#3sOUNbVWmDlobgaTd51 +zQdzn{^qN4m>%RI1zrJ;w#42^obuA~3LUn_d>GQUbtW*glPFG(qfV!Tuww|-HP7|Bw +zx%Dl6A~|2W29QKSRw|rARg&8(z3#BuOSE}u(=p9G7o({qovs)SxHPdAx`4RQg{%HT +z6MMX-EzLye=h^hq%^;I$LT{Z$ZCsc}rx%b>U!;1r=VIwt@$%EQlT0}i@d>%oh*91z +zT>DB4dIg +z7r{DRF5>ceU6GasuP#9tT9h#s6NbS=0dewl-Q{5TlSU?GYpSdk$rH*2Fv90_(b{k= +zbNj=o3Zh0agJ`@4`7}~@=R{KHq$P)8zeg9eeA=Tdud8!;o9ny{5my9eEK+yrb+C1# +zL6`1w)dd?`$}4K~iJ>Ye4!HxKV7<#-S4Rfwsu3ZHESHNY5DEbXjO3maWTHV$IrAB( +zB1zI%Il3T0JoA|BDV!NDk`t#4e{zX(z5LwV9l5GR&F3^%RjHUyR-SX^E>;RfhRKuC +zaH(h=%4wwLB$-Z-(L^o_7`d!+hdk-jmmsnZ@zS9BIiX;Mu2i`*>46i9S|GBS)=F9apeix3;Hk7kKSon$QT0>F +zbxpO&vN36{`(CdOT<-J9P^BKh;}+0(u32(9aiPvJn(XtX0#;O?6F-Y) +z#BbUvbdx_MHDN?VJB%3$q@4AUl{`xVl4QCLJd3&&Zers?ZeJt}Qg7 +zpd^uEQk+EdQc&b_H3obEU&QD36Ys`j)>EbE`<*3;OsPyJvzSIX;4w+zaSn)=;1sL>ZW>W9XK&1;^Nu9uR@a7B>n5cSplUyXbsl2;E +zXHgrkq!cJ0uMAq4y5Y;9GnhD>;iA)qGlQ2KFUsIDW8T}Pfj0!U6ad}NkJa{3-kWJqS~@~3$`X&AbsR+fHvLc5TzbuOIgC%NTs +zA&1kAMV#K2TCmI2LGlB;!OK2BG3!Y@`-HxP#+>H&^T^@B#nuvM9TM$PRtmZ{DBqEc +z>Id1Mvqab9q{GXbYM2UzpGtO*k$tJCx@|1|`RGTOytM4@NGg9F5!Qsd!QVX%AZ08U^ +zn6%W%^Oz_@)AD#%xR!;8Zb%dAg7x*@Kt!5Aw8J}L*1Vcq=r?7g3Clyl#s(?vfAhvk +z(#7b!NMie3{M8~!Pg&SnP^$rM3c`KQ1XqS|&zRsU5bjwMTs6WyXM$UdaNjqqncy}f+#VC$R)qVp32q0%?KQzYgK$4F +z!Rc5bmG}?jXV)Ho+Z5xFaUGV+i+(3GM{Ky=sCxg>XMN!Sx{AQ4`!5g!_dF +zt{>rkX@Z00-3snkCb%qw>omdTBHXV{aHA3KH4|JO!u`esHy+`Rnc#{L?zd+458+-n +zvwsNphME0CxZ`H_58>W4vwsNpJ2U%-aKAURe+YNN%>E(VAI$6@!o6i?{}AqNGy8{d +zC(Z01!u`?A{vq6-%3cg>>t8)o7q2v>oK!`2>0J+_7CCSGqZmg8m`yO{vq67&Fmk-y>Dj!5bkeg_7CCC +znAtys`@5O_L%0vj>>t8?XlDNquFuT=A>2o1_7CCCn%O^u``FC>AzZ(i{X@9_HM4&R +z_lcSPL%0Dm`-gB+hKc<{IEx8xGs0z<;I<-MrU`Bb!dXpl&mf%51h*UEhM3^?A>2?C +z+(Cr1o8XQj+%OZ|F@zgof;)k5Sthts2shFM*Mo4`Cb%;Qmt%tKN4SekaMnx>cZmru +z3*jy`!Q~=ct_f~5!d+&9%R{)!O>pB8&S8QpLb&Tpa8nTOP7_=i!c8;5RUq7S6I?aI +z%`m|&Mz}H)oCo1#6PzF6=9%Ck2zQqWZZ*O!Fu|=uxN0-|hj7cy>>tAU%L) +z>>t8?!_596++$|;58)m+vwsM;-OTE(V +zcg^e{!tFG(e+c)Knf*h!r_Jmi!hO%o{vq5mX7&%^o;9<72=|kw{%32r08Ei%DvMz~57+*TXgtBcmJiTrjUKAQ>OUWBVdxNFEC +z4DI>0xpc4LcY|6yD-Ypw7{d_XmRBuO$xV#!d5#1Aah#8Dvn}mxl%$JLJcaLifv@w7 +zh3>%&d_P2dxAIWo>mYnXdbM~C9+n8{0?w+z)Z-!{-IF9;MJ{_#x_2sa$zZsHgwKZJ +z@ypUG0rzSn`@VpPdse``-pJAsaX%GsZzW0hRRMRZk?mO|;(7(#`$^Kh%A&`eCAbj= +zxY+`3NRz&P61ouS& +zH?N85u84a{z}?@(+PR4PjevWE;Ia*H&?jPj?n3%}MAG#6jKKE<;k(g*FDFyb=O)(n +zMchmQ_va?Ix0i@(7I0^q)a}@GxP1aHhcv9=1~`jVkGqQCt~9`n6L3YVjLRzvxW!4* +zjS0AAtBlKWRKTrXWvnkFY199#r94UalaPQg@*-7y1zr|T88NPI+O7IufS(Vd?yg!Edt+P +z2;T$)zHvkJd^w2kEyUL>@QrFVmP?0#`*btgCsV}j6Ve@p()}Y!_alMtGtI_!LmsNf +zeU9L6Ho#3As!!K}(mjRJ4GMhgla%9Lfp0A0`!nMEs=)VyX5)VAZ2|W}v$5U%y^wDH +z-!*^ZG)lM7F6cp$daD(1z0Jn$=<{}cx>Hekdr-Pf0-v?TINfgxxZy3v>3&N{cQ#7* +ze^9zF3VfeV!uJz_uM+Y774iLA;44T{4%m7S<4RhL+b<-F(_MtpJ%iG{M&MhJgzsvB +zZz7Ea1A5njzW~~`vTwQb?lpgBHw!g-%`Xk5%JBuMCfPMvAIZ*Z~7&IUx)Z6A-;&f_sKf; +zT}6?vLEvj3d}BFZDdKxi;9DAH-(3{>{vz;gLHWB4@s(dH_yf(6gZT0;)AN1jVPiY)xJ=OJ4>kGC +zMSM#Iz84-gu8+k6-*&_|ANN}V->HX<^?8fHxAQ}-|Gf+G9TE7(ewlr%Qsg@*@a-jh +zQ#oH1;`?ubZ~vE#<#$@(>qF(OL41=h7oJ0W*;szXmka%LpT>7L;@cqbNt+0#0pB`- +z&)%n%_p{jl6Z4mZ?}q~4Y{YjD;`_6}_smz=yJI5Xp9H=QeOmo4L43Ja2=?VG#{Kji +z0xshb_TG_*n|y_!_axn&Jl&-z-TMT-eP3nYxD@%C1iq;sY4ui%_?{Q|&VJR{PChH} +z%|?74#P>UaZ}ev4{Jk#lRU*D+i0|T2!u;fBrCHN7DZw1zSfp7I@_I*Q(;s=GTntcd5YFhxj6h@4Euuim&OvtFG`p +zDe%D}ex)C5LVPC$zU^OQ-#!ufP6&LX&T9EGjJ%kOc4Z#&|QMtpk(zW28okE3=Ae7%V8Ylv?^ +z;2ZUrv3>qn;Oj$tTM(c7(|W$ij~VwLOFk{w=l|9CzKQsr5coWgv2Rm~e2)oycEq<8 +z@!77?^F95TvHUF82>Oip9z%RH1isEB^1D;u8-@6`Bff74eD5cbU%SBPKzvUizD|K} +z^y9|)J1X#vMSMFD-^~s^-yM$|=kG>`@EjKLeFyRVhrqWYN&e~uz7oW@6Y>2_;CtwC +z_RVUM?`45+D&gzod{5*4XpG?BKVjVe=8qBdD +z?EBFo-!<0?_FzD>&$|&{t-!Zq2m3Cf$oF}HFK0ljk3EQQyTJF!4&&#NTLr$ch;J|A +z`-8wY;oHXk{hI>c)B&ykeF5=}zD}5b{*dMAE_!=f`zWpikeOut$OZb%b+ll!8An@gXk9~tvm+>Fd|Q!!7~0^*R0eXXUxjDIwhrnVOv6MCk@^)bs5me3zqmN)v4ta2?O- +zpTjEYe&t4Cyqc-Cj}s`}9}9d(2;U_J>Aor8P9#b9w?ewRP`YoUbUzmOx}G!EgAWD1 +z4peV{M0_`o)$_rJbjPB24j$e(Ru~5$zIPDcJp$jH0sE?!gdd53WRvT(j%I6okq9~91iCY&D<&JRoV{MaEG$>WG{ +z{;IT|gx6Zw8m&b9&xP}&!uc0_q?a~_ul(=h3`@LdkTMF;U6meBZco( +z_@@frr|{1e{-whAEBv1dKcMh~3O}Uq!wUaa;om9z-wOXh;YStzqr#6V{AY##qVVGi +z|5f4EVZbIWGtJzl@JNNXQ+RuYcT{*Mg?CnXtit0I-bLZv6dtee?h5az@ZJjVtMGmb +z@2~JP6`r8*0SX_a@I-|VQTR}W4_EjIg(oRIS>Y)PPgQuj!ZQ_~t?)4lAE)pM3ZJC# +zDGGOJuuT+6Iz3~B;~gxo{97m+PP23v)Gz~|X +zXLLH-K!5D9eQb2r+f+VR!ybX}FzFc9f2M{lVgvZkizfek-lt&3HJC4#!jI9NLg~Rf +zReYacH2dS7#XgPhVvysR>JXDWo)LC6aXj-%&_nXLNBuP>&r_O +z`O6f3xz-cf?uLGJw~y(00Qi33=^|YEu28~XrSNMMex1UvSNNY4ext%~R`{(7zg^*X +zD*SGR->dNZ75<>YAJ**9@D2>1yALc6e1FD*C|aLu(o)SV|ER+MqVUJH)JP#7ObqGU +z3jEF?bXL{0ytgXhpVII-L%B@Ss6QM*ex$kn@r)AwIfcKV@NEizNsEr6=a7x|h0h1p +z!FXhkqVyI-(byXy!nMEc+Qr~MZ3i*-_`bjf5ef{{M8pGzGL5pcq#DdQM3oe_H-WbN~aJP#F0K5bnZw~c&q+B +zN_yT?_y-FAP~jgde6PYkRrqHL|6Ji;D*P*jf35I?3O}Uq!wUaS;omCULV@cFw<$bA +z;gJfDQg}OsM=QL&!aFFuqrzhp-bvw|6&|bbIE8mncvppYQ+T|>yDPkh!h0&bm%@81 +zypO{BD!iY<`z!nmg`cVL1ceV!_&|jZQh1`m2P=Gt!p~CpP=yau_;7`vt?&^FAF1#p +zg^yBrvcl~OPf>WP!qXI=PJBF;e`q>Qh2e#=P7)?!WSrf +zp~BBm_#%ZbR`?QyFIBix;mZ_WqVQ6Mmnpnl;Vy+&D15oXD;4fm_zH!uRCtxbs}=51 +zxL4sd3O`rjK85=g9#D9#!s`^iO5v*&zDD8aDg1neuT}Uug|Aom1q$Dw@Cy}wk;3a0 +zzERQ23P!ze?d(EBqRTU#sxz6#hqr +zU$5{R6#gfL|5@QTD*Pse->mRk6n?A1Z&Uc~3co|)cPjiYh2O34dlY`J!tYb~{R)3T +z;SVbOA%#Dz@JAH>sOZm2NL;xN6i +zpA)ZGSN$(yx-~q`>p?Q_*fbK +zRT0liY+RWRfc;bw@MKOehMylxx=H_E#p+mk4#e=kE|$Kv^fvQnW9eHfk<343{b$Me +zUYE~3o9j!Dv+_>N`%3vY#5m^NB;O^UbH+d2C4W=g!@Ps!Z;5|0?=AV;BD#w?{@vn? +zE@t_6#NsYyeea4Jx|qxV@8Yd4=J@xB!xsPd#DK15|M$g&u4exa#cJk#B>zbK$-?)F +z=a?r+{;ANqnZxfB6PS;X{Bz-BPWAVtc%1p!lJ6ILEb{*p-!rH7d_bh}7Kqx@L2*&M +zIle>Uo_KS94vQx&{@;p^EdJk#0~Y>o@uNll2XSV1bAFGCWDEaMOzLh9e@vX)-JIT^ +z#ogV_`Ta$F&3usL$3+xx*@j5|s~FV79A0SUJ-@B^)ma%YR~sF=Pyo+>ut_Y7j1lR +zbNFuBTISS0;k-(TBhkv~(@ +z`zOuA{)Ob@v}tFU^-s`lIm4`PlD6v%bN;4i@w~+!Cb>f!b0($37|*Xelb+i#_+j7^ +zO?+a4kh?O2UkiMJiGQC!&xskl&j9)cTrj-p2m#}rrtsO!=g9QsYITbLr3$}-`At%O +zruLNL|2gwsvJ5`gA_rRilb8>c{$FYZivRfvzgpq9D*Pel8t2zGi0oqwzGRSbmP`D} +zLDujuEBy6Aq4QsqADn3QPf@r-;RT5_*BJ5LlSpM@==(L1=5K=+52ms(_ydD!el~an +z3>3vCeU(G3@%ez?D(Jos{r?PnAN;Oi{uXe&wKDjx9G?2)EG_vgtG-O;)L!RkZsye9 +z=W312Z;-rDyZbD&zGCg5CH#DCBxLUUjx^rkdLf68n5cd1(ar(hD<ldG_=l{Y#@mHj)G*4|4(4Z@jlF3kCOGK2BGGQz5Vm%{(fyiA5)p+$|f`ga>?_OH@X +zna`KpqpeWn&u6|t`qyaBEBjqevOu8IzpHA!<^PP*JejDD`dCHZ!OF+f&-Jz;_IxXGu`sCrbGJ%xV06 +zM(aJ!>VGzKYVXf!OB8=Ua~dCB&>m&}s^r_WgUr+9{PdER1{2K;r;s;ym>wtaq_gN- +zhsf8Dx9a~B@I+{=w?vcwcE$g7g`ZG(#|c)RqVSapuT}VZh5t?AyMb@F)0q;c?|a~1 +zETR5_JYk{`@hKty$-v7^ycYO^rSuM29tH{|@bOup`Q=B&zjuz6yA-}z;a4d9I)&c^{NC|&euVKo2Yk=?Q2g%$kC{N{C&+)| +z@B!H$wrfM6U?)!q%~uZKizm=KE0I_8l_MUj4iE>mD;?JOuUGgzz{v-b3MMDtxfQM=3l*;bRp(RpEKSubC-LAgTU=cg_o?{|~_9 +zXNBtj872IS%<*P!pxB}PsQ5=sv+@{)cT;#Dg%4EtD1~P#e7wSI6@EYSY?azp_7_=e(|^PPc}i%KUukze`&W{Hpn(@OQI+rSyMG`;hr)$#-kETp{Ky2%S&& +z2VTA))E+11D)9k70RFSszl!~DlIw+cwVM_BM-~2q!hcqH&I}j}VEnv>^`AS#>c2+e +z8x($(!k<<6QHB4a@T8emo}=)Y3ST(Wu)U)7!DBP=-X+94<cPk0hZT%i~nBjT;}IX{(*Lc +zIgNK8YTg2C`0JVXkp3TQe^LBDVBS^wf2w`UoX*F-(gqfq`PbTvLTmUX3im7gN`*h7 +z@TV32vcmtN@UNLC$n+f2M3r~>a<^xBQdyaBPRpA!c~YL!nd@|(Gdm-BYTl%2PN%1& +z+U2h)DRVi?y-tre;H>q-Pq)ui7N}YyNsePm-lPJDv()RYa=JbKfUBh3o{6CgouEG8 +z^#{sbKA%IN*5zLB@+y}-c~;5lJn!;C_jxWy9e5N5?3qqyoy+I0SmRvo^VZftqVi{! +zttgmT=oe0Bpsd1aXG~#CWlUpCXUt^G0=@Rs99Kn2ZB+mw%W?ZKD!Y9$By_6JTkY`F +zK@_Ftbfs{4I4errRWfC1cBj)HC<(aBAaCw~yQIo}9x$)RS>h>omb?4`Uu~J>$!@pI +zNtV;;_M$AOBiR%|ChN~$nP0NpC9`kx%?4j*b#1`4+QDHn7_-fZOsgmflvFvZ{mY?z +z%T^k)_GC*=%6ujMN~h0N;`e&Yk)))Cf|u4-I9;pDs%ri2I!j7YGD1R-Lsv<)MULXL +zn*$_UwfZYde6I55;$@XVA<}15tlg+tdzv|Xno&2@`n*23%kQjm`vaDil{L*3C~{TT +z~Yi{e>m)kHZos&9&Mca6%Q9%OqN=BqP`@X8&)xg*_G8=2Ul;YfkA3 +z2yM?QbOj36R9Cq@D<_xuT^NxAn(6PErc85J{oPVA#qMxZK@`pV-4gM;wv8z%MhOI) +zZt8rWJK!qv7E%BlGA-WR=Uje2j5pRHn7jh+YO8y8sGEiz8tj>cE>F3m8V1N*Pr&8# +zK!<^73++z$9|zMmN;ajy=lv&YkhZ%o51egtO +z`M6p%jX=o|d=?FU**F*#dBMR^=SWQ{se*P_zQ(z##OHC9J4;;^UY|=Y@hE6>YH)r= +zJ%wxhkkCnRW1r0^Be`aMGKupbDVkbJ1;3MIW;rocWqa4 +z&Ty1gK>@lgYes*-TjN{>zOc-aV}457a?F#Phi_Aw(r4j1)t)@b?|1nE(_K}vvpAQp +zUhS-L`C!cn3+2EXXI*kz)Ii+?a$#jwK}!tJsulT&!5i;Eqc7osH6_@hv#3Q^m#oHC +z?er_VCb{ItLU-Z*F|Y>50f(hsXDGgYbMUlM7*9}Qxyv_&X2a0>((Gy3%%tQ(;-H65 +zg~d&+&o#ByBR7GL{Hb+y*5wp#(n5PmX9Y+)nyJUMsm87|Y%M4A$OAhAix4f(JuB@g +z^Gn=;B6n342nM(sQmfsb+!c<3nMKaR6#QQ{w?coKKe(U==3ebsK|g~#rF>Pr19wg- +zPKU!3v@PO>?razxJhjfU)vIx@@A3Mop%uYEd7m~lqWvk +zHBv=edq7qVOsl0OWh>j%Dw=7@=6uf#BamL|f>Flk(M|nRaW8f%T}h6GY7RWEX5}5F +z1v6(CI>SX#jgstG0N6h;zCwOwhaVOz{8HJFoZFTc6D +zOgfbzxeCg{-D=gF`nOzI7W$j5w&wf0wce=~Qp2~E=9N$jYx^K$j;6ID3Zo@dWT{S6 +znd-Dw;ptLY?mGG6{LS5>t%;(tOKWpkpK8}AcQrpwTUJ+X8(Ap%$*qh=)S!}^8x71# +zW}cqfnR!xEYZfl>&8yP3%&bkq{D!f$g=9j==93lFZ54quq&l5EjyOwdSBGndjyhOn +zra3{@?sUSU#N`aEsd4fBQ4WP|AzbT%SUem@NiGhbN)SkQU4D@>e0tHd2v2EcdBVn} +z${#*~LBXaTAst5i#hz7ePr0+e<*%)FHPZ_1=}=A3c_6-$fD^l!F%XBDzsjmyCBESN +z<#d*LYu4oEl_os^)F^$;!A#sq-bf?k({UwDC +zx^~2(NhY;Mxj+Zu04dJk%!=hFg{b>O66_BA>&PdF6SX3-3xC +zr$e+FS0joQ$=otd*1nH)w$@5RnsgS}qgJ2aG#sB1N{M5Ck*p*&<+BKK^yfv~ZLp$^O*2rd81LclO4gpmb@K&9Mb5Q%>(=;O74FrJ({YH*RbTDK +zOPVTIovZ3}ss){;wH2pNZH8H`-&N*6En2gKTIEDzO71DuSZc80P&1W>-R=r!MQv3T +zg!a>rE?Z4qOXIKI55qs%KRKH_B2P&VnJ1LPuaJ#G^FdOSAY^t#@+~g??aAdXc5vZ3 +z6pyj-PO6o?St=}Hn+9wlL})y0vJm@C$E-@aQ=Q@CZ(&c@Bnv4{vt5Z1fUPG&vqDf) +zIALq`2c4}J2<96X#W=&_WpCb#=e@dQrw4M}@`R;C(Xx}`pMg<4xgLh%DlCFPv%**!aTFBFi&l!AWBK4q$+vDjl7aYlXP-Wy7|(ek_cWN +znnJXw+nzbAWTnee-MMbJ1IHe`&w{_n!IJS-`K{NZDKeaMngi807c8u>!>!t*v3Fk4 +zN$4WsCc08Hil9x;@xaV81vmP6G_#ltJM+-^vrf>0MO2{Sf~(a*-Es}&=Z!wqym{9@ +z#gNLSql|pcg7k;1g<03iCgUh9rSs|{*cpSu49K)`itEoPsi~1?8Zx7>TTOF1Ydt}` +zVwjX#IBRHn79$tO@(|w%*(DqU-;cE?WMz|j^&|L%&9BM +z#T>U<{8_@Y?k5lvk$8Ot;F1(6WMT +zsQ|;{fIhpBHMYs7DTA#4nnqmfIhlyVtx&Rz5cYIwR_BJ{EoZ8G|d#-2{n +zO&VPIlUVynoWwRAnjA3w<>O>lm@Q9@t6kMta4j9sh8e0-olOqgPx`<%jN0_z0dA%f +zk{JE~w~fgO-6FJFV0??vdSNxaM`&YWn%*mLk%aCQ+FBl**tSI6^0K5=4dJe|!mm2o +zn3!f)Az{PgWN1!JXj#&h`^1x8GNfQ64wKDN8zQl;6H=Tl4R*OgkZ`>1> +z8KJ@@BTO)|H^B}ZNJmS-Rlhxa$kGtob_;r_K$};Vi3V$>x!9!Boko+MdD1l&+6$j_ +zP<8X$Y-Ocn_T7XR- +z5HqhyG7DT~USGM%T3ZemZM5vRuAHXfG7^TcBD`61&A&tJUb+tUQ<=^XjOyHT`W8X3fobXSY2&mQ8WUTMlX*ON$~YO+=a|v*jeT9G1*; +zt#=B|mUl|qf;5xQlMmO%_`+12c_3-2dcw-3JMc;*oKj^Nb+j5XrL7@b7@T>DR$h|d +zTw_xgarTw6fd^d0<}KFgxNYW}ackP`IDXH|n==h|wyeY0C +zS6w4y`3G1;R2b*Qa^_ksYG{R5gUcFG5foFaD<#>81XgU`T0U=VC7mhF4v2!J5Sa@v%*pJUy3dKtENxsHngdOdHn%Q`VGKxu(b^ +zAgwyuwp1zhyUL2ZGB6f>3r#lLvNb98`0+Vf%V6HDL}9?=YQFGF<(4y8e!+_@D2mK7 +zZ*@(HPkms&>2Wai7mQb~gqnGhysdIgcS#g3$GjtKC5YX;m$0EL%-j>+!M^9VvJ~S&KR)`8NhR+StV{yk=%*pyRiUjn>v(}I~{VA4jaaMe+iH+awEUSVgfV?gQbroJ~F*PYbs|viAYcag}Hmqn$D;uz6r*(#JV;C=O +z+|;1zav|AjF&btu(Y&u=gX#_5^Lv}<^ES~DlqqZ_6GDDXT6;#5@8;H?)8sp)wQZVw +z7dK)ueiQu_P0U5yu8H#zcWClkAc&eymrGxC1AxRv=M$ouQ!apo^0uMy%^Eb`^ +z|10~qZ%4dyJK{syk^E?M&(?*b9hGw)%gtrE#mq~XS2Mq;9rd$I+EF=Q)sD*TPwl9j +z?`ucp{BS!e=cif!HV*#^>)XrWzG+A0{R{i!OO(;SS2XqC{?QcA&}foRj;44fL{mID +z(G<^|Xo_cEG`A1d+$fgI +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 +zyPCK_qj)c8`I}h&VU~ZLFPuvb4Y`$J) +zx$V}dJuKt;{GP(2|58Ev&t*KH-R1c45RV^FZ}&28<#vSa9{1&gSnou{XGuT0FGD_2 +z53V;>v%A`U@%bUNmvORwAL9lN*B<3Fc^rL?`3P=*xxcf +z?`k?e%XadX(m&r+%Jc0|c_uQB;C3^Pc`mp6n-Fh-bvok<;riW4=#%s3OI$B6QG3Pv +z`iB_XYZOmE#^F5g$$s^SM(e~!XnewUE!)ouoz`>E7;)a#i*!-R{&F5VqKoy2f7L_- +zqGqFZ0D5j`yr1P|d#KXIE39uf>-(1d|HJy^JOcV+HPY8pqjoS*qjoS-qxv1MalLBP +z4i+=6&`kApF4tFY8{yq+@VF$lk2~$sh!IE6y(EfwC{oOx+`Kf^&foRDT(uyE@&K=?etQe*3*~L{Em7m +zkZ+`Zg>q|S7n7Ul$*-`$6WB8eun$%5w-~24gPc +zLdGh_wY=`S5E1t8e`NlcM)|?#{V<;G8m0Ra#AKT|fOv^6eq@Z$2?y#_t|R$*y@`y* +z^MGZh=Kv8eX1qqHa+mwad@kqdx`;uX3hPJ2xi;Azw3juKD`2^qEH^`u1MJ0!f3#v7 +zg)8K61?)bb-RCKM0rRssT?;wfIW~$9Fpk~hSx)*#vj1F8&urT7p?iYNACDWeSbh=9 +zk7a$Zi0Q}fQhtezKi^l0c)bwkwxe*@Aj05r6La~z-=Bnd +zjrn0jSls;|bNPJVji3(^CcjEVn53>iyhVto5N{RY#b}a0fOs3!4?edBlSvjLEE1Qs +zr}VhnliX#@A7^}?-SPQ1?Ex6Kn8)z*Vrh)yI*|J^MA*b$fe4Gbrx0N>ev$q6vwRFc +zuhqRHxo0t-#JrsOWr!~daV@()g$Rqp7n$#8xtJK%7sL9PPhwt<_%f6;yFbVH3i}^m +z9@mL53vmbJ2N5=Ho7w$Q#Mgy*x)X)li}z$-{zZ&S*nI=@2Idbke}ef3%s*!y5l?&s +zV|qNfFJQibv4PzmWc~#6514<>JOZCDdQXT>-H9i6C;x2bibu% +z?l`-T=*8vDxR!BKFOs{L`EJG!*?m+>N`m>1JtaLgJu^EwBP$^xGbK6Qo{*lLoDA;C +z$r)*Y>1oMXB)P1^1&+L_nx+Zkk0xv)#Gr3R6Q;?3hr(L2tMr$9a`@Yk5$De0hOY|i +z52rOc;u<0n4;(*n;za!ct-*1$(Geqm9NywM+>nzPvBh!J5NH$)jw6l09S3$ee$jS1 +z_G2`Mk{TTcP|~C-c57UtW53N29lKRzy%c-Rw#|-T>Z=cE^^W}-c#Lrz@uzH9_lv0A +zerR|zp^tn$iVrl*+7G#hVtuL6akw#>0>(fA0Yo)P*h?31NGm^GYTd>l(M4mH6)$2HX15C>wKOw&G!8|pl9 +zizB|lajbFHF-R5!eHr3yjBCilnB!#3iy`KCBj%&^>yFBpV=(5U81n%m<`{|@8x6)B +zjWHj^n4>Y~0~GUt`t6Ba%Jb(HUU+zH47$cNY>GRIB@^GUDF%MHZo?HMG%!0k^s2%+fv0Ei>+!niOKJ>tyo01_O +ztdlL9vfx+4rV;S(&P_w%Uz`maWrB>x)9^CEOO2hd<{D+-#$?9T5&UCfbi=0O5Q#w{ +zTjFSl#?^1r8a749j7B#`;2}IDOT@mgtzlENbj1=+h7unE^*t0SA+aHln9#5`v0tOq +z3%jyMxs3pcFQPzzV9zJ9sd-BSO|* +z0&8!S<-q-OpAm9rBo^U5MSlY6k1?d~xQrZv!vgp1Bd*j)Y`lR;>2Tq8Y~hQRI+wgG +ztbg#GGSCa4DeM%Kyy%@1BZ9x8jb9rs;{c#Rju#Qw)no?~*)RE{vG+KRABw_$=74U0 +z{56*Ag>uDln;nNY7axe-I_p4VF${i=!$)Et?XcMa1EK>)D_Db<4Ngue$G-{q&*%vD40_)I-#i2mB6pnNmy0lPY8Iu +z2~}Rt@&PE@%b1_e%NN?(XxU{&Ohm+H$Ul}|0{eHwlE#A-(K&jPE^ED0WCRvSy$#QE +z@r=s{u0QDEC4=2TDo-13tn^l@xHT4u~ZDZmLKs_4~;Y-?%fuUN9ru`lso;aN@{XT9gZSrKB<&ieO}51 +zX24bHtnlHhJCh(>waWup^mqfVBq*?v@|Ef$X}Ql^TO&^5PcNvBE+&rM9UCy7U-l7n +zA081#ZmdbJUkh?MCb=_Ba`HS1{zkDJ?%Q3Fp>Pq5c+S?|r0=P2v}f;T(uMj5vpyTk +zJ#Nxv)^|3`8*c0=!%^BSH@Tg#{4xBnP1zK=Gqt92<~-n^2RqUk3=Zr@dyeBgnDsr^na)g9 +zed-^xdxZG+3A3Ng(n63&DZHJ+qh(rfK9T3+O~Q9jct?59jel^=Z7Lrl@5f@mZxHLd +ziv6yTX>TX*mu`i>BbdY1Q=Y{}F#i#7HH1H(!}o^YN8#_fu<7e0GBrM1at29;a|k;kv?YqJ%}TFAaq9`lBfbYI~6RS<=6wcuDc!t?-YT50~;W;%q!q +z)M(u33i&V4t?~;Mj_1P0T!-=(D*o>)JjG_^mnr;hg-1tNd4|G^6uwB|WeTrX_?rqp +zq;TOYS!KNPGO4Ug1mDJ(>umG4Na*9K_=&}eHBLEWfinJpF@BpP%`QI?62Q-J8E=7> +zubh_ir2J-dZJFfB)(=pml;MQ!^fh_Mb4pqjq{11fcFOOjRN&{IDIXT86e(4UZ+LA^ +z#-2QHQjV9h=g7}5%a>oRNjAUOKdXuVc_!aXnMUJl1^iM=N_S~(g*DM_Uzs?a%U7>< +z*0_A&0L2wp-;TJ0OD)cn@GF0OOr^Y8&PwU#HjqQP7?Ohk<12b7hF#7CUq1}1j +zX?U}7n0J1j#@G3Veb4i$y`Y*khkf<+DZW?zR6Y!JQs2J|HU)eqY9W7L72i$UH|Ksz^6^cS7_HY{Z5g*OYKi{jSdsGw7oh*h(9uZ#+b-=%ENGu +zhDAp?b2stVFEj*Q@DO;3j`ahLGqoS +zFgNi#KV!UEv+2nzQ$a#)am&io)_L?mJRNJ@7s +z^KOj88AqZ2NI~z~1U`mwBDyCD;Xs5!nrlEH?_(`Xs +zV~5v9?Qk5@4n@GfB6h3eP=jOt!N*CH6v2Z$n +z4?0ape|VX0M3i7ot0H%^jr|Ut+2GjMxMZJ6ZNrj%jgEc624g8b<+T5~UxTOp(dHP9 +zlFczY?ug9c*hMJIM|V07Q=gV+=m!^Rmhx&WmTmE!VJ|kk+VB#UN(}UgXmphgcfTQO +z3bh52&j+X7Wj!1T=H{3NO>N`0+Qfrsm)+pl-MD18CGWc%9lK4n6%$J8p2k^wjQfX1 +z$DRhq-p1m+TjbqD@OI!(4^n9o1(k;uH5Nme?rq4As9$$j1UfbrA3!=e8jmdZLO+!M +z9>4^TuqK$V8*u#iKz76t*ztkLQQ%A?1N*~gz~oWC?gJ4Rj4_O(u`m?Fk@|H<1oRiY +z7ufJCib5K@-G+yakWffvqvP-$$fyRj`t3Qvu_ebi7d8zcv0J5_(f#BhbmW0={%f2M +z(+Cp-*~Y-5to<2^K@I^O@ty?6LC0<=qvE)RVwo>0qa+#RfT_>buiGzhRNfB>9tL82 +z4t2H&>}f3C(@?yxe%(G>-7sj~Hc);b0y{TwiT;yc$fAV;5Br-)T5o$#t{B4q9;P8Cu*reSi#As>s-HPlSZlVg{qK6aZK +zWO^6f^F`C3x7!>gDS_Gf4LLi%fwS`)O(RDV&5b8^(`4BUjdZS1J2Ld%2vbLfRJ00M9K70r^g?DomYMw+Gy5^Pq+pDA-z8HS2jOCpDSY(vtmh16Y;9a} +z)KsqxOSWUn!7N!^A%ojOWwE_}dl9r8alm|_*UX=bY;s*jH!_f}9TO9@B`=@U?M$?( +zNt$kKqC*LSS$$#xwSfM35v0tvn`Bv?kY$C}n~oE5s3CpR^5#r))(L`YZ+UH%3+iET +zxftp8R0+SYY*d}x^Z1=!4<5k4J|_XcO_(6R9+Obv^(71(>>rpA@FqZ@6DPEe4{MPd +zb=X|M>Ko|b0f5z!cWYvs2ETS`kzecLBQ5ejX!DJ~FSNx;!H%Pj;)8Kl+bCSG*{^C> +zMu=PV$QN|+q`ni$1Gqy7mPshn-A$#@VrEZ6*kV~xx~w*}R!%ilVKv6klF+0I=4M#F +zz4o%{zAO(f%=q+I-k9M%SOWWJX?&jE!kt+j%XMr;7JJTW)@$5}G?5jwFS%8a-C}$T +zav1lk@OObu``6auKFWQnUn_C<<4xGWR^rY9=f8lyFEH-dmdgljHt~B5x1nrS%d%+C +znE{K|Z19Pg*1YWLzJtVHE#E`7{(bIAe!t5XnC_}7H{C(D8V*i-czqivGI!hq}Cll;Kt|LTJH2|fJ%Fg}lawg}z9s&ZpZawA)i%Q4A~ +zYC$f~B$v{HT#-pGqXoIeCb`Ki$d#Mqa$1n9GRaMCK`vmDo7RHdT9aIE3vwGxax+YF +z>is&JqIgXgx6R$J4;?JTL>uXg5uy9sVZwSJe!M-otNI2j`YMNp(r3OO9wn^z@ChBL +zj*UMFj9E&&C>QP?K23?Y#uRTCQ@j&|_1-)Y^qEZsn!AU`@0G-ak$Xsy!|#}cyRUy! +zk;CtpbPFT*nv##zrhN1;<>LoMpAYoS38U{jMc;;@be4(wdYSYM(5!doXrDgY6wWw9 +z9j3^|b`! +zZbjcWps#-zeYY$6o-)-(f=S;$6@Ae$;nVkpqHmiiea6}d_4U`S`f_6EOj^~~Tes@l +zZAxFFNnfF&@0=KlPt`X^(f5H#-w>0&t8{BSSQ|sn${2r)etEf~Z{JW_ucE%8CVe;R +zR@;h+ox|IU+@;8^u$mM!YcGOw&*@F&RC|#P&?)d+U3gey%x~fBMeu$7J5A;tzs+7G +zMp(IOAEDYqbdk?f8tZMnN%(FGk5_ni`P`nduV@;+hkSn8*dsLc@1^iQ^8E?MUIFFt +zInxAT+=IjkJpQ}c)||e+3h$@zGZdbn@PP_XRQM2Si(>32Fn+86c^t^;!{?~+1SEoa +zx)z#4wI=m3RN-eUe7M3}w_mYx)xIWD;jP;fS$TVfH?=2P%1OkS215I}La~Rri+POn +zj~D-7j%}zbxOU+zk$p{f`ThiR_;iI&WZq56_YjK}{|Y^1H`fJRo>Ba_GoK^F_Y#K{ +zf1%jRL@B(x!uu(F5OX7buj0Q};eSy0jS9a{;ai!HmFe#%K2`kx&*FcENNC31r@!=1 +z5LFRo`GMjFMg9@y-KBq`_?Y=X`FDtji?qrQQh18Orz(7w!V49?OySEF?uiWT;jukk +zsrcWn@cR}1n8Kfm4DIt#-+PMx7tE=CJB!FDtN)-VqwiDwpBqJO-{8V}`lgsaotg;= +z8>ZAbTDOsM2Ffa&$){v1#fOVdxoc&Oc8jG39xJAV>_vQ5Lyk0z&sA<5QaZvbcl+fR +zbWL7`t^g{|lOMZAvmQqllxZ34jit%ZNgjtZWB7D(rz35$C`m!#sk3L51j;IL*Il-v +zFvYpzw;NeCJz~Mn@Aj2d+yXFOcfC9y2L9mfgp@rY*sZGbcsEDj!123YtBCI;m49CE{Ao$wbV};y0W- +zQPa+3V?e_+44l%-ut8dDZG};7et%hs2QB?Pt5%ReNuh(SKg+A~Wm77v^jUff4n#O` +zq&gw)e0O2869*5dXP3|C@!~Kh$2|-x!?INwnip2rSO%viBTz62ie;O9rThwaz*X#V +zo6P3gV4-+w?LXW2@O#~9`H;LlJ*dwZ41}(cZPrwcY_gVXWTSN@qFso$8GGu4vvA*) +zCZzqdo-V{1EMA&ce`x27md$M4i$u@AKk!J`ondRoP+&q?Zvz}Fm*+SgI;T}Xj +z8TN?GU$l{}+)n0ib9(lmdmgRRFh96H(`O0!eQeY_I)c*gKt5Xt7rXl-D8362VeyLJ +z!^Usu+=ZAA>lVbhLi~tW0DJ97DrdB*!*COrFNh@nTDGyPXKY}+g%Q_D`czsUA%6{d +zkq}=a77O{kY1A_Yah?!mQIzhL$mhczJ&M9@j-vJzKV8~u9eI;A)g_{8|^5b58F{Z$J$Xm)1#@p@H@;{ULM4S +zLR=V4Qc^LEl@3{OygVbbZPG_#Ozo5ca3-$v=@X8NX}1 +z2=dXM@>RrG+MeIZOhNBE84nMZk>ZP;Y?6TPK>Cti1VW{hQwW9-U^dr7*% +zzYUk_o3;fy$RBup-)^VlIBJ#m_h?(fBC*%vo$Zp)T`xXLEpPlA;Yaatc?&FUAfybw +zK1BR~%fzOZiH*fEiVceK96j5`n2bfR4O^bWkEc6!X*B=vsQT(S?NDE61268=WeV^ycoJ&R(PS32LQ#zkJWLKd4z +zW=;>TqY)17eL3p&`GaAuBtR +z0T>lpM_DD<-`G4SSj*TuIg{IVIKIS+t-yrXHA)D+PS<2f1R|P=qQn9bGSor7*~A-O +zHXB_o#(o~88`ga(YDXT*Km$u@7KsjljwbEcXUQ{Y=V*z!NoJ)DC1&=h%X#mWza_TjVm>!&ZZcN$)AoOP_>jTe78Q+u_`NA%hVZo3$?Apf%w +ziCfAOqd$qn)8S8FGiolL$7VDeJti$h2R8PP3#NE+$VAZ?zvZBPtbThu#c<)_>$waa +zm&w6=GY)KyjcB><*kHVx;<$ZVqhll5r9r;pI>-|P(r?q(X-(WTLG +z*@@jyZr1k&yhbU&1q-HN)8U`w3qu+<9r%e}5V2|hPyC{ceLsa>lmV&Px#<`R8pGRCm04Av?G7@o32Ptw;WBxIKs +zcVhQz^rnj9*)wO)nLk?;!=75WJ$0~cEguQnLmycc`qxyKdT}R9&o>3|(JB!rTC)(g +zd9?v|6>M}}erahKWO&pm#FR=`*~$cb6v|aTI$=Qb50(ubhHXJC^wuWe6J4(I1oX5> +zgGgYNyUaB}4E9e<7(BeDgBV)tS?Tev@(eSa5)uacI|y7u()w`Azn-}DryY-uKPhX? +zxJG1x%B32=Wc|*m$qWJhjQBmJwrCN6**iV?bln*3(CcVGrq6-g;wOoYV;n%mTUmA +zZ16ca%zjK8$_DSDbf|=jT8aB9aNY=VU$-KM_RUr8$Of_{xoBW9(e(U$OLED;aLT=~ +z6*;^c#bIT53v$29dr!TtFmhu} +zawA%h%Q4A~Y(Xy1B$w2JT#-pGtp&NoCb?{roNAYb>#V(|YwPCh((Z)Lv`;5}?L_nM +zeVJ&z@^1FMFDTbLjGX%37nBQUZ>GNYW#d_){B|^@Pkrx8PJ3aoDlo3EOBA_+_TlZ) +z8Wgz&&B*;#kz3lH#(P!nV_~&{scBE|?=b!tRr95yFTWW(w-buo>JGwU`OI>|1M#+yXhdmw-RmQ*6>~B+Qe9AHBDbP`JIq>Q}{AmqrhJe +z=ciE%t*MY-t%cT3$luXIYb4|s>7lg{^1tX*pBn4Odxbbte3#fl>w~80ix&^rLeG?= +z{6Sl2y@T?dBSPyMlfq|5utTOQ~li)uG($&RQTz)Q)*-pY#9Tg6dzFRQnoQC +zyQ9wH3k#1GQLM6)vPWJlE#s^l__){!V*0{je}?8K2@*v=ZhQQ=o9 +z{APvU#hmO?I*5p9tA9s@cUSm8g^vQh%SL60>8n)yYZQJ#bZ9M)^0z7e+ZBFX;r-fM +z`7nj!{D-zl4o=So#eZ{qdY{A$_WzsWzYF-Sk!16W{u)&L3z4)QLO!O0RX$hY1qv@y +z`1%f^eS(Z%@!z5FcNM-@;a@2Hpu)fFV2l-1-@>vtSIm%3?R7I5{34q$#{}l9?^OG8 +zXN}Lh92Ue7w2rUeo&HL%FCe3C5$g8(%M^FZOd(~)vxrswpy##K&hZbi2&Gn*U9ZafGqeKbtt+n?$=j?Ol +zL6mTN|M>FDo^{sV>#V)@d!N16Ui&m&#V{KqC||6= +z_cDGpH!5UmE8k>lYnGsb=qq@t&q7{kmRj-1uw%k?{E`DhjtT* +z!@%ZNo*<0F>)c^)h(;|bd(;hG-T|g! +z&_IG}hy^`$YJEefnV#LeJV?iw^fxzR&oT%tX|ARNnYbs$O8&3f4ZTS8znJt9uOfT`;l+e2r1!X*^djA)54n!?8|w)MNDuNZ +z#1}IbA^pj(r3wACZxj9l;`{IP-ot4^U+=Xvq2HJ35c+%*9D=UEA@t`;5JIMwlK+hk +zq5pRa;cmix2&Xc($szRV9&iZ#w>=J_5BFQbUv!B0dK^NI4;?~(@Dsvqbbl4DC!n6@ +z7}AHFnlAJT7ZYBZF7m^hF7yh2nlAJ*an~Br^< +zq*u9*{NE(K%BwR3UX&r|RML<92EzGJPclULJV|uN2wsNzigTbGogzJc(u3TJ@K(ki +zateLLM-i@u`iO81V}C(N2ET1~(wUn=`h&v^n~O~ZA0&8?U=P7u(g!RixSk+CmwPE= +z_Y(dT!D9q7?E)4OTupFB(VS1EPgqber>J0n`h+)^2&m~3j$p%SFPM}8yPPeG)7GN& +z+oGfn7k-Ct3!AANf}&s3nG0RbkxYSHq=jVbzH|454oM`MT^QQ0)-Ba=wS_ym4XHGt +zK36V6v(ai9J!GP$2!vPcdpCo#^GQk-^*vtNtTQ0+AI +z3A06di}r^ozKxsp;mNM^nLzs_{IrF*FI${14w0XapvLdcoJ +zAabq=4ZoLA=zGldZ4sB;DWr)OXBX`YUV~3)r;94p4!cYfDR-izT|-52+q#@wkuv-4 +zUkk%Wn?p`tR7B3BPx3vE+FIx*c1V8 +zsZgyl>ubAtk}(Af7KG>XL}d!8AdyqVQ%lSy!Y{Sn4ntMx#nW7)iZ0#(kDItYRCpM1 +zt`5iBbQ-N?AY@jK*0yr#h9t8wC;w?fuX3!OiqHgVuuq=k3Qa;^)AFhv1d(ckXqYHD +z_vEdOn*XA)d +z9QL7Qz+zWR-|)sO`Mp+cN{^<}_SH`$TY0i2+h|q4I&-vDzYa=ZaZvi$L_ID)U1|RUYo;?>X%%r +z3_FwgO5et(IZt>Bxp-OjVOQQ8*_ZW;D&B*ZyR_~jL+&svn$DU&+*;ASfI!#KQ_+^O +z$aLS{*B!z~5~UCI#W~d-n`hF~x-F9u(BCBJX>8-7_iy|biQXT&gp1w}qKhOfN-T6@ +znHzMOr|B|Z9j)raOiZ&KCXMMh(Pt5H@#cB-bnBM9Qc+DD(74AZ#!u=U4To)h0%3UI(D#tmcF5%rzL@gA< +zk&A9qGX`p^#?m;j98+XRL!FBps3^S1iAHW0WunIKqU?wgi!RDR&D=$~c%op@SUh*I +z$c4>o(YS~{ioepYH7HHD@V(Q?%~3*X581>JiP_nKb-ELcL@GzQ1=VAGA`*)%!VBpl +zi*nE?CU&2_(2bxxDv{zrN#h46wGk7+zD&y +z51jm0q<+b{r4v)N-bmFAAL;2OpYQ5r>ayg()gMXeJ;2j@0MmN_6^9Qf2Qj_J@eIm2 +zCK+OFG-7@9L#u=rB$aU6hmwSUMi=+AJ`pFz=|0nwLfqW5Z|_gKy>?Ei>gq9;<*E2ZYm5B1bg +zv3~ZXC{KuDeL_D|BYJC;C1A*M`3Jnyv5A(n$_Pj|1zcwYbic0!;0cqg2c$2zVr%*3d!hl98bXiN6FARkN3YI;c69x_$!bpQpUG=Zf@ZgZVl6T_wD+8sW_QnE +z%pEN?;AFS8zx@7t|B9L7AoM0>()?FX)hzP)q230rCZAuN*87#|DN6kO_7w{ZnP2Ei +z*jI$!G5U(vZF*mE4x?p-)c)VL_7y|lOV(Gs^mg*T!YcGL|1^Z2rp??w`{-&GdimS@ +z7VPbK2MEr4fPYuBX-=ZAq27+KUTeHM;h#93;!H&>UQe{F4rS=!QUia#JMm1WYn3#O +z$!fieUnnuSvk1+`{sSNL6}~KOZgon#X+U1)lU6JFm-i)j%us)4N2+(06H&`p(>tiC +zDc(u;1@*Uc9=#~4k~7wR=#7EQ+t!?0qts?jV|Y4st{KTo;)T=lcl_XtTg|7fY5&cK +z$-iE8DK`&F+WSwLs#aZ=R^-XD+>|+k)py@&v_a25w6uSbe7>RQkH<1pFVtyou(afb +z$E_p4s8iMv;L$#P1ep5P0G11ET2FRP%LP(WH@~TiPd-1xc@sY$?s5---*29ma30Gn>I*e_`)o$o-H7s8huosOg=Zpjq}&a +z*F-(fWqclGd|sCEs4$$t&)w-l5#P=H`qToy}^Fb8|)v%aj?Wl=bt;RW6DOokF)MQ +z{jAekkEYn995}y|D@o=nJFSzeKYyZ6m=^q3GV$O3yH$KVtM)(Hoe$>v@mto!JaA?J +zbCS@Y^eromOjYAD_2M%r`#2#-_n_2?DnpJ7{$_2jk=Lw}Z8|-G8PLjemP}ih`UfAa +zuOswFF^+0I-!?IpPt(@4`B=_1#t?m(nZDM4@=tA~Pc|#M-^hvYzZ=)vr&!+^*D4pV^WWZ=WXUr>l`m}jq$7>w9^odbjSDF2V)E93r0q)dPz&< +z8Vm^;A)n}lxR`t<>eW1-e9HBO>MMlOi`Eb?Jd(2BiTOzHpll6E`d8Bqn_B2*Y5Y4J +zH>SLjvPN3wd7oKAZCR6awOjP;zAUQi{cC|=(*hH$zw0&N8L{n!7T1qIAQEWN#>r}J +z(fqYz1@fjCUqp`>Su^ra(xwp4(*Wn?`1gebH3eb{Qeu|C%XppE#}M?b}?;w^7Wu!RJEEZSCtHxOM$I +zA$tz<>)I_T9`~x0Vp*ddtCiOG2n)q%csGO8mkq7uL6{j|ZxqR>Lz*~uk^w9Z|A +z*`cowjD0~1)V|Cf);|l2%zAwjbUtzG|9|+`d{G!HVp6%j`VXyK&!!D~Zh3yQl>X1NM+BVZEF5_fwB1pGM$1)fsLl{?>~oU +z#;l@~9ol4nE;er-lk9x3iEf|Y*Ie%p2VMH<-bpOKU?$7UFJPP5#7V5OnqA8le2!IA +zvtX!}DQL}wmE8&m3kF#E%Eimrs>;#|R$0TAtzwmn+0xImWh>dT61KjP)ig4HgBoy$ +z`~erToLM+)_MEvzx+kl^M;uIN6@KQ| +z9&4FLdrt9(UFr9ju*CmY7WTvxA(Evxm1(Y&TA7!pCJ`xozSuSieo&X|V-dE4Z(K`!=}yY~oJ%AAtKg +zxJSYLUvQ6s+h-GZnZ5|_Ft|6sy$S9ea6RDcFcrlu_hEFtbriVK;I0IBHQq^M7xrPb +zKi@{?Q^C0r+_r|*dReXNRYNMPb<-30HU!xe23a?axog=q;Lj$r8b53BvU(4zhgTZe +z3>K(oOu@?R0bq< +zDgz3r6<0F1n_Y7a^ZVJ|ce92DHf0K{uV>Syv6^}|l{LWQ=O(j;5CB%=Wu7Jm>H9*M +zp&=3fIu^VuW%s~(An!f^cLLlen2+%Fo(66hxC_8t1a1ttOTk?Z&Xp$aZ5$77BDl$E +z;(qCAM3+Z&GbwyFxFT@#!F?`GoRP=(7lT_0ZaKK?z^wpR4sIpd-v)OxxZA+po+i%E +z*Mh49w;@fOpKkz%TStxHn$yHxkz3NleXXtFcHk;Rnm9}U4RE`_-IpfrjC=sxkJ7|> +z`iH=weZWW4gbhZ#zw}q&o&fh-yxS&C+)wm7aJYy0T$-@mhIbVG3EZE-b%6UjIJ{r- +zD7ZJky#?-VaQ_5{y3#!WKLGa;IMiXoJ+Y6`)SrVO{Ykd5(KNQO#K$dT3%l6p@LV@4 +zf+n(WjNy0yp*D-L*Hh5o_x#dqVRt$i4Vq*B=19h-q@dXY?$wLw{C5(XBj85nihHk< +z(cr1K!ZG6B?PN4#!Ta+-Gb9Bc?61l%f%=?+25n<6AIsRcQpAP%-3c@w+mq8g0^WbQ +z0z4eaX|PW_b~R(|DdfQ~R8+e^lOnEMz;;g*HY$_REC6ihB*rcrlAPuav?nn`-2Ih| +zW;^mJ5H=l?(crq*t3Wd>MY{0*vDi#u$1@oX_CG&?$}=YgpB!vkvr^Z?x!7kx!%~yP +zb)M~hYX-FkX1V%P{8?={V>|QDF~XDCaPGU2v8^`aKGkG4oOesSWPVl~&dKOB8_wDg +z+zxbmBon1Bf>s;OO%>2K974WyNxotWzlMckEU?DAz`}1id=j)X!B4hX{ds1#*L$!y +zu?^x13*Gz0=JaY|RvW}fSCfEFP6Ph!Sj^ai4q;<;8B1=1c;a#xTcm`^G9{9Su|zhA +z&2J^LDXUo(zJ|+bW +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 +zNulgA2lmcq!urrKHlbyFEpq+?k27C +zIjD6$hxo(TNNYQPa79}8V^(dN$S`l8qEb6P1sj4gF^c`;#AxxjNGn#$$l)h3^u(_? +z!o8v*Kpzl~|J^3uT%OI}ABXnZf3dI4A?A13HD~gKI +zeS%x7-5Ya=gthb)!?3dT1Rm9h@%V1x@x|J9A+Nnh9ei-WnE;F+T-pe9(N&#Mk>FjJ +zTAR{wA^0GPlar(=9iyr`Y1Y8sgnGUGBrl6&S&tWwSciBQ$2+1x$s1#YH`yrvoxkf4 +zZ?Fe=o#Z||tFa^4!^02q@SpN!}EXp9I(W+d`P%-S~NICiNDa^^EEt`(A&6h_Nq;eXw)EuMvhBJ*)@0u%~ +zaRlp{+M>i@SdYzDy0dnEk54wbwRuQ?*3L1fv6X9YM){Lg>kjhDlesR^y80Bipw0^l +z)q1lY=U!7_lC+O(`tLoOM)s9k%OPmn)A)-^I*r2)v}(`MUHBBK!VePZJs765c`o#7 +zxzN_S{*+dw#QF7pQKeS&9B3_rpcf7uIuzwkCtd?ivGho5CGWrR7Z|6}Lt5ndN&6zZ +z5NUZDf3ej%(PnT}Jg3(MC#s=1JA1WPuc2L=qE#_NXj^O=E<~Y~{G9OZ5ENaJD~Gn- +zgDHsGBQ`waP~yNd4kb=J<4}@`XBk)pm8%r*Jc +zfnv))l_<6cvAbCji&pJ13Jp6q>ef)_sI9f(jHwRl_Iga5R@pFpD1l3V1N!y$Xw`mr +z$^l7oMZ?XG@{AK@;pAl@@^%+yEJT1p$1*?RlYNQ-%l~*UFNuWd9UhKTRb(DrZxnmQ4?d +zY5^Jj5o9!gPqH3w*T%i=QDwV1!^+GVwlg8mN}PQuTlw>Ja@QS-4W +z(%Qs5n)Kr2{Yaa#L%xyc1df3rY}ilZ?-?AAG`?L`Q62yYmfndN@;m_KoICui=DLyg7la@{gs>IfFS@)WO6*Yeul+otrylrB8v))TAf5(3%Z_62yba9v!pD2G>IgOikT55*+IsvBX833R +z5>aBfB)Az5_SqEtoup((*K|a~oyci7=LGNOL_*`}9;KnkO)tXE0aRJQ1yW0xxOepB>=)vo0*8r&{*kaog?s +z3L{?d)tnwvy2YRzH=@te497D4ek)=9lEFu$lWt}k!k6^=xjjoZqaon0nSr;r&Zu`c +z1X*BO6RS|URtY~J=$bG-IKkx!xwa4Tee +zzwMuPwmprjDNAQ!%J5JO>B938WQ<|h!mm?fcQ +zVvhp#nCHPK^M9O$4$l?719aa^7B>?*%vfh}Pi2xLnT#2_jCc>^!$XBmdaAf_&-XOY +zh3%>7P`5e+UEs4RWJEgLQ<*nHoKH$chdQQ#5n|6Z6&+qfGV(&kt~d)F>WLSO!s&Es +zI;UOe2tS&FZYmS!0lm<*eGk){lPIr|vc>V`G{G15uALW&b8N}@p2zbe=rKLddM<@c5cLuH*;(>)DWQv)=}+TlJ(q%Xjs$dhntXPHZh}Oooy{mCIt{-c=)RbM +zU!{fa;)~7vwEesd7P{h#g-(N&AD*X>^QCyA*aICw{#w3-B;NRkR>TvXU)f}#duI$Y +z{UtlUf^_#LptGJ|aa<Qkb?KJ~QEXepVY_xIAgbI1(>U2EX%J8$aU1o&3D1HfCTr&R?~$ +z0r5EwV+=qX^+2?~9&tSTqV?&BKkYF3WW@jGF#2A^@y=(hkBygSs0Gio;KMDrja^A+ +z#&EzN3H(+{XUMP&>j=j-cNLV+CQEqKf`8kB-*3Smwcw9g@Fy+!GZy@S1^(r3a +zIB4AS$~-=GrRuI#xzy(4CWFR0f99g_x^;LGK&fvCHFNnZLiuy5s~gpTXI*nOAFw^X +zy7KF4Hmtm^B6z-XZ%O|7$-Df5r5;}`;!9Pv_B_QgYq>kP*k9j(<{Z%56it3!Nie7e +zLQCBquPI>mGBvbZ)y^E1H=DF~k#o5k2zr7cm`FkSH*Po|qR&OZMJ`7%3gweOg@rdX +zsJ)vNV2>jTWa7Hz`> +zAP3Q>-roqMRlbc-YSk;%U>N54eyAUuy1pS^o!c8!)jQ8pf?R>!gMCY~BAmO@y|K(+ +zS6$7?JkU_?N~I_cUp8KlNj}@Bd{g8Ixz!vI{%(%QrwOA4d~dXnYb561)rRh5 +zIl(4^4-z~`@Fj%sZZF|uExMClg7*@9ir_JVnWO_*NN}ND@Y8fBXXFk +z!RZ9?yF%R1jhbYk3-z_LXmOclQVu1R^tX~|UiNWgV!f!f)Q6_R%AFP+%VLMn@?%1m +zO1pIxVu@76w41Uo!AsqBeXjmAC6@JTw!7FO^=~zDU*KmQ6iFw+u(^iT1o5$}3$%`QuIS2(rBrtvZZ_jrxxr!4`RD;2a>+1Usqf)AHi2(|^h9%hUrf445DsO!2&>k=*p{zi6H8iAqV5_7ScX`?0{{v37iET6A9!=rQ`90nr% +zr55gG6Cn_9<8y7haPO$C6?Nf$gB@UO(n$?}633lb9aqZYQKIHquTCCYf!bAhM2q(! +z#O9wA_CT=}w0$4_4>-ng)#aDCHsW{tb>3@`emK`f!t_OpGx-*j{#Lf}R*mr%T3+Eh +zc!cBjX6*NXi&9G#@0A9Jjrhj5v^SE*`L2-*Tk#FI5oZhHH+~{Xo;2Q{8C-CkHFl}N +z93&4&RD0x0&gja9s203EG8H%uyc)l_ah_q=o{Pc(Wh>4Pv}Wi`rBY)Cu!-KGD7KV +z+0@5EbNMEBl%W=!R8ja01ZvB0YH>6Ax$L^8M%VlN9&(z=cs}Gi?xZFUbm^F<^H1?{ +z49|-4w(sKU@=9%=H%fWO_`#2HPnu6*yDrE1;dVhUxT3Y3*qf+$qIAR9)D3gAyZ+UX@Lg+8mmOV^&29B&_GJBX +zm>dSAYxX%bDn8ZQpHoprs?u!Q%b71UKRC=m=d%o9e-ja +zfo)*E74NC@xxMS%zFMyuz~y1|_td%hO2NcCaosE&P%Ai9@HWqy={{~-WUA{LpsE&R +zQ(f0rm6c6mlP6DhF+u8Lu8GBYO>7c#1=JeV)2P)U`v2_7|z3`py +zVtft56$-d()OjvoHjDw$#IWy9pMRro5-WyR*)SeU39gO+OLqv_g?*kTSIASZLTsTx +zv+Jr_cSv6LtC|^7ec)%a4C|y>eEL(-J +zw5$xl(sBhs$)c5&2p3gVAgEMUuHgBHI~Q5BkAAUD?9p9r6Z@d!ZDOqhZD`>>8TJw| +zy&C?yZNeTq>$2mhM{PtdK%=oppD8j$nv$*80bw6Kf$E1`Q*zHr!L7DGtDI)3C%?s!$s&&ib)djPH&AyuIM)0ih*Ec|mt%iQ7 +zI=Io@P+DHED3#Ua6*H^FzZ7MDQFXN^B+Oz|*FeLr^9Pzs%WIVDA#9c&0{x076fCW* +zR`Tb>k%PdptQDa`9&3%#xDpbQUu|SLrUdxri#UaFWoz>lrO3d`Yk--eG*(tu=9you +z2${+9s*_MvR|nKa6^$@KLK?XY6`_LJ0mu-4J@mUZPz*+@L+&~YgE?`pTL=o*dAweb +zpnBzXHD?m8^F+10quVHPDnPjIYuhnpx< +zAV)+6N|5z4iQ4B6)VsYPMxKIBnXCD0`7f9hit1ucJeMm;RD-Tb^S!jhdNjD-K93oC +zG*-F=65WCnbW0?LDB)V%;&{axwi&D_7mgp9zpsSVWmZYHbN_0vJx{yS-GzHz= +z65X;CblWAmB80v^1F~3dPtL)Sw9O^Iuhw!jkoY?$}{8}CGnfV%z9joB>Xh{!kQiz(v6Vl +zG|iJ+Ep#I@g0AvCv(fnOJ}9poMN}rpQw(-4!-7-CCdn +zJhjq&(?a*nOtA-IrTd!ATpnAc^1$z2tvp_^@OvZ)zvnFcc1ZlLkobLI;rA@?o11{& +zyB2=;Nc^sp`0>3ciQnl=L1X2Ix}P$?`|^Z-4ANdL@vE}%n|%S<)VJ`v(ZcT`NxtzC +zzXrQmXKpL-Ymhd!Tm-!qetYu79uxALAn|Lm@aq{NzA3anjrG?o=|G}H>G-N8-lI}F +zCQI=iweXvlmAL+OTKL5zep4lWc!z|{?~W`{u2z0S)6D#OB!1H+ek(2fzLX{UCM&<| +zE&Tc-4mM_K)8h6#M+k2_J0}-;K3|Z?tK$qU=_A#xT6=N&9xS$H{+*1;5mS +zkG0^JS@0_?_>~s?Y8HcdKLYn5OBDZj3qFCB+Kul~q(?gnxV0nnoF`c5C-J*nv~Osn +zufV%bpgwF&7~fEfO%p>KPkxHE)l`n6-&1dD#@EDK&t +z_@$iw67~(khjIK;ZhsyB#&diu>m~dWj$g*cXUO;!tc38n9KVt^5k80GSF^86MS$^t +z*Mk3;@FGq>o;_v>|E&doKEqg#!u0oA!sQ}He3%8FX2I($_yZRF84Lcb1%KIsAG6@c +zopSmnvwVv^_9DVXeotkq3BQu#)7f_jpTzMz_8*q_U$o#aTkzK`_*)h{W0)DAWWib7 +zqO+v;C@WV612xrF+Uh*|tDco#SW;M2ICIuAHB`P>DQ`SCHuU@r7m=D$SmAi=ZISw7IcdkSdx6Xgg6>64c`$RcMeuYcI^$mho +zDaa>@dX70UyVTd{zf)bJu5*XIAxnM?b}<&@iDF!?HsLJ<x#LTOC@D>b=#T+Uf>j0s36)$IP3sVOIJp +zLbYlj5O6Q625jr_^FLr|~Q2i1^O2VE+OIp!iZcOs2A&O5I6g!D@px8TUr{YHP?k0}idy9jmSVPx`&vcO +z)hJLqL-{ks4YPD@Y-tUYXvM7RxSLJPG4g{lb!w==Q_C8t{o;A~cm@1BA@A5=ZI|dL +z0M5Qyat>Q0sWwJZ==9^pyPg>;n#X5Buc|hf?AD9(Dm8aj2Kdp8@C!ztn&F;v8h-y`;F#_kv@!oNlE#{~aE +z5Wg$%z06_aJyh1hbS@kw&Oj_ed=X>igu4;H1Iizvo3Y))1fK(luVw5L!Y_tTZhH-5 +zOAywI?+`3^e*fDNf(oraEG2v~U)E#xWsJ>aBH#F#3E)>ou#(_vg0%#_1W_lzek+|T +szD0Z=+iw$V&-T@HmScYWSq@y^vRx|nuMmHT;1PoSJ^(w}@dx<-0NDlQN&o-= + +diff --git a/toolkit/crashreporter/google-breakpad/src/tools/linux/dump_syms/dump_syms.cc b/toolkit/crashreporter/google-breakpad/src/tools/linux/dump_syms/dump_syms.cc +--- a/toolkit/crashreporter/google-breakpad/src/tools/linux/dump_syms/dump_syms.cc ++++ b/toolkit/crashreporter/google-breakpad/src/tools/linux/dump_syms/dump_syms.cc +@@ -38,15 +38,15 @@ int main(int argc, char **argv) { + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + + const char *binary = argv[1]; + + DumpSymbols dumper; +- if (!dumper.WriteSymbolFile(binary, fileno(stdout))) { ++ if (!dumper.WriteSymbolFile(binary, stdout)) { + fprintf(stderr, "Failed to write symbol file.\n"); + return 1; + } + + return 0; + } +diff --git a/toolkit/crashreporter/google-breakpad/src/tools/linux/md2core/minidump-2-core.cc b/toolkit/crashreporter/google-breakpad/src/tools/linux/md2core/minidump-2-core.cc +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/google-breakpad/src/tools/linux/md2core/minidump-2-core.cc +@@ -0,0 +1,603 @@ ++// Copyright (c) 2009, 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. ++ ++// Converts a minidump file to a core file which gdb can read. ++// Large parts lifted from the userspace core dumper: ++// http://code.google.com/p/google-coredumper/ ++// ++// Usage: minidump-2-core 1234.dmp > core ++ ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "google_breakpad/common/minidump_format.h" ++#include "google_breakpad/common/minidump_cpu_x86.h" ++#include "common/linux/linux_syscall_support.h" ++#include "common/linux/minidump_format_linux.h" ++ ++#if __WORDSIZE == 64 ++ #define ELF_CLASS ELFCLASS64 ++ #define Ehdr Elf64_Ehdr ++ #define Phdr Elf64_Phdr ++ #define Shdr Elf64_Shdr ++ #define Nhdr Elf64_Nhdr ++ #define auxv_t Elf64_auxv_t ++#else ++ #define ELF_CLASS ELFCLASS32 ++ #define Ehdr Elf32_Ehdr ++ #define Phdr Elf32_Phdr ++ #define Shdr Elf32_Shdr ++ #define Nhdr Elf32_Nhdr ++ #define auxv_t Elf32_auxv_t ++#endif ++ ++ ++#if defined(__x86_64__) ++ #define ELF_ARCH EM_X86_64 ++#elif defined(__i386__) ++ #define ELF_ARCH EM_386 ++#elif defined(__ARM_ARCH_3__) ++ #define ELF_ARCH EM_ARM ++#elif defined(__mips__) ++ #define ELF_ARCH EM_MIPS ++#endif ++ ++static int usage(const char* argv0) { ++ fprintf(stderr, "Usage: %s \n", argv0); ++ return 1; ++} ++ ++// Write all of the given buffer, handling short writes and EINTR. Return true ++// iff successful. ++static bool ++writea(int fd, const void* idata, size_t length) { ++ const uint8_t* data = (const uint8_t*) idata; ++ ++ size_t done = 0; ++ while (done < length) { ++ ssize_t r; ++ do { ++ r = write(fd, data + done, length - done); ++ } while (r == -1 && errno == EINTR); ++ ++ if (r < 1) ++ return false; ++ done += r; ++ } ++ ++ return true; ++} ++ ++// A range of a mmaped file. ++class MMappedRange { ++ public: ++ MMappedRange(const void* data, size_t length) ++ : data_(reinterpret_cast(data)), ++ length_(length) { ++ } ++ ++ // Get an object of |length| bytes at |offset| and return a pointer to it ++ // unless it's out of bounds. ++ const void* GetObject(size_t offset, size_t length) { ++ if (offset + length < offset) ++ return NULL; ++ if (offset + length > length_) ++ return NULL; ++ return data_ + offset; ++ } ++ ++ // Get element |index| of an array of objects of length |length| starting at ++ // |offset| bytes. Return NULL if out of bounds. ++ const void* GetArrayElement(size_t offset, size_t length, unsigned index) { ++ const size_t element_offset = offset + index * length; ++ return GetObject(element_offset, length); ++ } ++ ++ // Return a new range which is a subset of this range. ++ MMappedRange Subrange(const MDLocationDescriptor& location) const { ++ if (location.rva > length_ || ++ location.rva + location.data_size < location.rva || ++ location.rva + location.data_size > length_) { ++ return MMappedRange(NULL, 0); ++ } ++ ++ return MMappedRange(data_ + location.rva, location.data_size); ++ } ++ ++ const uint8_t* data() const { return data_; } ++ size_t length() const { return length_; } ++ ++ private: ++ const uint8_t* const data_; ++ const size_t length_; ++}; ++ ++/* Dynamically determines the byte sex of the system. Returns non-zero ++ * for big-endian machines. ++ */ ++static inline int sex() { ++ int probe = 1; ++ return !*(char *)&probe; ++} ++ ++typedef struct elf_timeval { /* Time value with microsecond resolution */ ++ long tv_sec; /* Seconds */ ++ long tv_usec; /* Microseconds */ ++} elf_timeval; ++ ++typedef struct elf_siginfo { /* Information about signal (unused) */ ++ int32_t si_signo; /* Signal number */ ++ int32_t si_code; /* Extra code */ ++ int32_t si_errno; /* Errno */ ++} elf_siginfo; ++ ++typedef struct prstatus { /* Information about thread; includes CPU reg*/ ++ elf_siginfo pr_info; /* Info associated with signal */ ++ uint16_t pr_cursig; /* Current signal */ ++ unsigned long pr_sigpend; /* Set of pending signals */ ++ unsigned long pr_sighold; /* Set of held signals */ ++ pid_t pr_pid; /* Process ID */ ++ pid_t pr_ppid; /* Parent's process ID */ ++ pid_t pr_pgrp; /* Group ID */ ++ pid_t pr_sid; /* Session ID */ ++ elf_timeval pr_utime; /* User time */ ++ elf_timeval pr_stime; /* System time */ ++ elf_timeval pr_cutime; /* Cumulative user time */ ++ elf_timeval pr_cstime; /* Cumulative system time */ ++ user_regs_struct pr_reg; /* CPU registers */ ++ uint32_t pr_fpvalid; /* True if math co-processor being used */ ++} prstatus; ++ ++typedef struct prpsinfo { /* Information about process */ ++ unsigned char pr_state; /* Numeric process state */ ++ char pr_sname; /* Char for pr_state */ ++ unsigned char pr_zomb; /* Zombie */ ++ signed char pr_nice; /* Nice val */ ++ unsigned long pr_flag; /* Flags */ ++#if defined(__x86_64__) || defined(__mips__) ++ uint32_t pr_uid; /* User ID */ ++ uint32_t pr_gid; /* Group ID */ ++#else ++ uint16_t pr_uid; /* User ID */ ++ uint16_t pr_gid; /* Group ID */ ++#endif ++ pid_t pr_pid; /* Process ID */ ++ pid_t pr_ppid; /* Parent's process ID */ ++ pid_t pr_pgrp; /* Group ID */ ++ pid_t pr_sid; /* Session ID */ ++ char pr_fname[16]; /* Filename of executable */ ++ char pr_psargs[80]; /* Initial part of arg list */ ++} prpsinfo; ++ ++// We parse the minidump file and keep the parsed information in this structure. ++struct CrashedProcess { ++ CrashedProcess() ++ : crashing_tid(-1), ++ auxv(NULL), ++ auxv_length(0) { ++ memset(&prps, 0, sizeof(prps)); ++ prps.pr_sname = 'R'; ++ } ++ ++ struct Mapping { ++ uint64_t start_address, end_address; ++ }; ++ std::vector mappings; ++ ++ pid_t crashing_tid; ++ int fatal_signal; ++ ++ struct Thread { ++ pid_t tid; ++ user_regs_struct regs; ++ user_fpregs_struct fpregs; ++ user_fpxregs_struct fpxregs; ++ uintptr_t stack_addr; ++ const uint8_t* stack; ++ size_t stack_length; ++ }; ++ std::vector threads; ++ ++ const uint8_t* auxv; ++ size_t auxv_length; ++ ++ prpsinfo prps; ++}; ++ ++static uint32_t ++U32(const uint8_t* data) { ++ uint32_t v; ++ memcpy(&v, data, sizeof(v)); ++ return v; ++} ++ ++static uint16_t ++U16(const uint8_t* data) { ++ uint16_t v; ++ memcpy(&v, data, sizeof(v)); ++ return v; ++} ++ ++#if defined(__i386__) ++static void ++ParseThreadRegisters(CrashedProcess::Thread* thread, MMappedRange range) { ++ const MDRawContextX86* rawregs = ++ (const MDRawContextX86*) range.GetObject(0, sizeof(MDRawContextX86)); ++ ++ thread->regs.ebx = rawregs->ebx; ++ thread->regs.ecx = rawregs->ecx; ++ thread->regs.edx = rawregs->edx; ++ thread->regs.esi = rawregs->esi; ++ thread->regs.edi = rawregs->edi; ++ thread->regs.ebp = rawregs->ebp; ++ thread->regs.eax = rawregs->eax; ++ thread->regs.xds = rawregs->ds; ++ thread->regs.xes = rawregs->es; ++ thread->regs.xfs = rawregs->fs; ++ thread->regs.xgs = rawregs->gs; ++ thread->regs.orig_eax = rawregs->eax; ++ thread->regs.eip = rawregs->eip; ++ thread->regs.xcs = rawregs->cs; ++ thread->regs.eflags = rawregs->eflags; ++ thread->regs.esp = rawregs->esp; ++ thread->regs.xss = rawregs->ss; ++ ++ thread->fpregs.cwd = rawregs->float_save.control_word; ++ thread->fpregs.swd = rawregs->float_save.status_word; ++ thread->fpregs.twd = rawregs->float_save.tag_word; ++ thread->fpregs.fip = rawregs->float_save.error_offset; ++ thread->fpregs.fcs = rawregs->float_save.error_selector; ++ thread->fpregs.foo = rawregs->float_save.data_offset; ++ thread->fpregs.fos = rawregs->float_save.data_selector; ++ memcpy(thread->fpregs.st_space, rawregs->float_save.register_area, ++ 10 * 8); ++ ++ thread->fpxregs.cwd = rawregs->float_save.control_word; ++ thread->fpxregs.swd = rawregs->float_save.status_word; ++ thread->fpxregs.twd = rawregs->float_save.tag_word; ++ thread->fpxregs.fop = U16(rawregs->extended_registers + 6); ++ thread->fpxregs.fip = U16(rawregs->extended_registers + 8); ++ thread->fpxregs.fcs = U16(rawregs->extended_registers + 12); ++ thread->fpxregs.foo = U16(rawregs->extended_registers + 16); ++ thread->fpxregs.fos = U16(rawregs->extended_registers + 20); ++ thread->fpxregs.mxcsr = U32(rawregs->extended_registers + 24); ++ memcpy(thread->fpxregs.st_space, rawregs->extended_registers + 32, 128); ++ memcpy(thread->fpxregs.xmm_space, rawregs->extended_registers + 160, 128); ++} ++#else ++#error "This code has not been ported to your platform yet" ++#endif ++ ++static void ++ParseThreadList(CrashedProcess* crashinfo, MMappedRange range, ++ const MMappedRange& full_file) { ++ const uint32_t num_threads = ++ *(const uint32_t*) range.GetObject(0, sizeof(uint32_t)); ++ for (unsigned i = 0; i < num_threads; ++i) { ++ CrashedProcess::Thread thread; ++ memset(&thread, 0, sizeof(thread)); ++ const MDRawThread* rawthread = ++ (MDRawThread*) range.GetArrayElement(sizeof(uint32_t), ++ sizeof(MDRawThread), i); ++ thread.tid = rawthread->thread_id; ++ thread.stack_addr = rawthread->stack.start_of_memory_range; ++ MMappedRange stack_range = full_file.Subrange(rawthread->stack.memory); ++ thread.stack = stack_range.data(); ++ thread.stack_length = rawthread->stack.memory.data_size; ++ ++ ParseThreadRegisters(&thread, ++ full_file.Subrange(rawthread->thread_context)); ++ ++ crashinfo->threads.push_back(thread); ++ } ++} ++ ++static void ++ParseAuxVector(CrashedProcess* crashinfo, MMappedRange range) { ++ crashinfo->auxv = range.data(); ++ crashinfo->auxv_length = range.length(); ++} ++ ++static void ++ParseCmdLine(CrashedProcess* crashinfo, MMappedRange range) { ++ const char* cmdline = (const char*) range.data(); ++ for (size_t i = 0; i < range.length(); ++i) { ++ if (cmdline[i] == 0) { ++ static const size_t fname_len = sizeof(crashinfo->prps.pr_fname) - 1; ++ static const size_t args_len = sizeof(crashinfo->prps.pr_psargs) - 1; ++ memset(crashinfo->prps.pr_fname, 0, fname_len + 1); ++ memset(crashinfo->prps.pr_psargs, 0, args_len + 1); ++ const char* binary_name = strrchr(cmdline, '/'); ++ if (binary_name) { ++ binary_name++; ++ const unsigned len = strlen(binary_name); ++ memcpy(crashinfo->prps.pr_fname, binary_name, ++ len > fname_len ? fname_len : len); ++ } else { ++ memcpy(crashinfo->prps.pr_fname, cmdline, ++ i > fname_len ? fname_len : i); ++ } ++ ++ const unsigned len = range.length() > args_len ? ++ args_len : range.length(); ++ memcpy(crashinfo->prps.pr_psargs, cmdline, len); ++ for (unsigned i = 0; i < len; ++i) { ++ if (crashinfo->prps.pr_psargs[i] == 0) ++ crashinfo->prps.pr_psargs[i] = ' '; ++ } ++ } ++ } ++} ++ ++static void ++ParseExceptionStream(CrashedProcess* crashinfo, MMappedRange range) { ++ const MDRawExceptionStream* exp = ++ (MDRawExceptionStream*) range.GetObject(0, sizeof(MDRawExceptionStream)); ++ crashinfo->crashing_tid = exp->thread_id; ++ crashinfo->fatal_signal = (int) exp->exception_record.exception_code; ++} ++ ++static bool ++WriteThread(const CrashedProcess::Thread& thread, int fatal_signal) { ++ struct prstatus pr; ++ memset(&pr, 0, sizeof(pr)); ++ ++ pr.pr_info.si_signo = fatal_signal; ++ pr.pr_cursig = fatal_signal; ++ pr.pr_pid = thread.tid; ++ memcpy(&pr.pr_reg, &thread.regs, sizeof(user_regs_struct)); ++ ++ Nhdr nhdr; ++ memset(&nhdr, 0, sizeof(nhdr)); ++ nhdr.n_namesz = 5; ++ nhdr.n_descsz = sizeof(struct prstatus); ++ nhdr.n_type = NT_PRSTATUS; ++ if (!writea(1, &nhdr, sizeof(nhdr)) || ++ !writea(1, "CORE\0\0\0\0", 8) || ++ !writea(1, &pr, sizeof(struct prstatus))) { ++ return false; ++ } ++ ++ nhdr.n_descsz = sizeof(user_fpregs_struct); ++ nhdr.n_type = NT_FPREGSET; ++ if (!writea(1, &nhdr, sizeof(nhdr)) || ++ !writea(1, "CORE\0\0\0\0", 8) || ++ !writea(1, &thread.fpregs, sizeof(user_fpregs_struct))) { ++ return false; ++ } ++ ++ nhdr.n_descsz = sizeof(user_fpxregs_struct); ++ nhdr.n_type = NT_PRXFPREG; ++ if (!writea(1, &nhdr, sizeof(nhdr)) || ++ !writea(1, "LINUX\0\0\0", 8) || ++ !writea(1, &thread.fpxregs, sizeof(user_fpxregs_struct))) { ++ return false; ++ } ++ ++ return true; ++} ++ ++static void ++ParseModuleStream(CrashedProcess* crashinfo, MMappedRange range) { ++ const uint32_t num_mappings = ++ *(const uint32_t*) range.GetObject(0, sizeof(uint32_t)); ++ for (unsigned i = 0; i < num_mappings; ++i) { ++ CrashedProcess::Mapping mapping; ++ const MDRawModule* rawmodule = ++ (MDRawModule*) range.GetArrayElement(sizeof(uint32_t), ++ MD_MODULE_SIZE, i); ++ mapping.start_address = rawmodule->base_of_image; ++ mapping.end_address = rawmodule->size_of_image + rawmodule->base_of_image; ++ ++ crashinfo->mappings.push_back(mapping); ++ } ++} ++ ++int ++main(int argc, char** argv) { ++ if (argc != 2) ++ return usage(argv[0]); ++ ++ const int fd = open(argv[1], O_RDONLY); ++ if (fd < 0) ++ return usage(argv[0]); ++ ++ struct stat st; ++ fstat(fd, &st); ++ ++ const void* bytes = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); ++ close(fd); ++ if (bytes == MAP_FAILED) { ++ perror("Failed to mmap dump file"); ++ return 1; ++ } ++ ++ MMappedRange dump(bytes, st.st_size); ++ ++ const MDRawHeader* header = ++ (const MDRawHeader*) dump.GetObject(0, sizeof(MDRawHeader)); ++ ++ CrashedProcess crashinfo; ++ ++ for (unsigned i = 0; i < header->stream_count; ++i) { ++ const MDRawDirectory* dirent = ++ (const MDRawDirectory*) dump.GetArrayElement( ++ header->stream_directory_rva, sizeof(MDRawDirectory), i); ++ switch (dirent->stream_type) { ++ case MD_THREAD_LIST_STREAM: ++ ParseThreadList(&crashinfo, dump.Subrange(dirent->location), dump); ++ break; ++ case MD_LINUX_AUXV: ++ ParseAuxVector(&crashinfo, dump.Subrange(dirent->location)); ++ break; ++ case MD_LINUX_CMD_LINE: ++ ParseCmdLine(&crashinfo, dump.Subrange(dirent->location)); ++ break; ++ case MD_EXCEPTION_STREAM: ++ ParseExceptionStream(&crashinfo, dump.Subrange(dirent->location)); ++ break; ++ case MD_MODULE_LIST_STREAM: ++ ParseModuleStream(&crashinfo, dump.Subrange(dirent->location)); ++ default: ++ fprintf(stderr, "Skipping %x\n", dirent->stream_type); ++ } ++ } ++ ++ // Write the ELF header. The file will look like: ++ // ELF header ++ // Phdr for the PT_NOTE ++ // Phdr for each of the thread stacks ++ // PT_NOTE ++ // each of the thread stacks ++ Ehdr ehdr; ++ memset(&ehdr, 0, sizeof(Ehdr)); ++ ehdr.e_ident[0] = ELFMAG0; ++ ehdr.e_ident[1] = ELFMAG1; ++ ehdr.e_ident[2] = ELFMAG2; ++ ehdr.e_ident[3] = ELFMAG3; ++ ehdr.e_ident[4] = ELF_CLASS; ++ ehdr.e_ident[5] = sex() ? ELFDATA2MSB : ELFDATA2LSB; ++ ehdr.e_ident[6] = EV_CURRENT; ++ ehdr.e_type = ET_CORE; ++ ehdr.e_machine = ELF_ARCH; ++ ehdr.e_version = EV_CURRENT; ++ ehdr.e_phoff = sizeof(Ehdr); ++ ehdr.e_ehsize = sizeof(Ehdr); ++ ehdr.e_phentsize= sizeof(Phdr); ++ ehdr.e_phnum = 1 + crashinfo.threads.size() + crashinfo.mappings.size(); ++ ehdr.e_shentsize= sizeof(Shdr); ++ if (!writea(1, &ehdr, sizeof(Ehdr))) ++ return 1; ++ ++ size_t offset = sizeof(Ehdr) + ++ (1 + crashinfo.threads.size() + ++ crashinfo.mappings.size()) * sizeof(Phdr); ++ size_t filesz = sizeof(Nhdr) + 8 + sizeof(prpsinfo) + ++ // sizeof(Nhdr) + 8 + sizeof(user) + ++ sizeof(Nhdr) + 8 + crashinfo.auxv_length + ++ crashinfo.threads.size() * ( ++ (sizeof(Nhdr) + 8 + sizeof(prstatus)) + ++ sizeof(Nhdr) + 8 + sizeof(user_fpregs_struct) + ++ sizeof(Nhdr) + 8 + sizeof(user_fpxregs_struct)); ++ ++ Phdr phdr; ++ memset(&phdr, 0, sizeof(Phdr)); ++ phdr.p_type = PT_NOTE; ++ phdr.p_offset = offset; ++ phdr.p_filesz = filesz; ++ if (!writea(1, &phdr, sizeof(phdr))) ++ return 1; ++ ++ phdr.p_type = PT_LOAD; ++ phdr.p_align = getpagesize(); ++ size_t note_align = phdr.p_align - ((offset+filesz) % phdr.p_align); ++ if (note_align == phdr.p_align) ++ note_align = 0; ++ offset += note_align; ++ ++ for (unsigned i = 0; i < crashinfo.threads.size(); ++i) { ++ const CrashedProcess::Thread& thread = crashinfo.threads[i]; ++ offset += filesz; ++ filesz = thread.stack_length; ++ phdr.p_offset = offset; ++ phdr.p_vaddr = thread.stack_addr; ++ phdr.p_filesz = phdr.p_memsz = filesz; ++ phdr.p_flags = PF_R | PF_W; ++ if (!writea(1, &phdr, sizeof(phdr))) ++ return 1; ++ } ++ ++ for (unsigned i = 0; i < crashinfo.mappings.size(); ++i) { ++ const CrashedProcess::Mapping& mapping = crashinfo.mappings[i]; ++ phdr.p_offset = 0; ++ phdr.p_vaddr = mapping.start_address; ++ phdr.p_filesz = 0; ++ phdr.p_flags = PF_R; ++ phdr.p_memsz = mapping.end_address - mapping.start_address; ++ if (!writea(1, &phdr, sizeof(phdr))) ++ return 1; ++ } ++ ++ Nhdr nhdr; ++ memset(&nhdr, 0, sizeof(nhdr)); ++ nhdr.n_namesz = 5; ++ nhdr.n_descsz = sizeof(prpsinfo); ++ nhdr.n_type = NT_PRPSINFO; ++ if (!writea(1, &nhdr, sizeof(nhdr)) || ++ !writea(1, "CORE\0\0\0\0", 8) || ++ !writea(1, &crashinfo.prps, sizeof(prpsinfo))) { ++ return 1; ++ } ++ ++ nhdr.n_descsz = crashinfo.auxv_length; ++ nhdr.n_type = NT_AUXV; ++ if (!writea(1, &nhdr, sizeof(nhdr)) || ++ !writea(1, "CORE\0\0\0\0", 8) || ++ !writea(1, &crashinfo.auxv, crashinfo.auxv_length)) { ++ return 1; ++ } ++ ++ for (unsigned i = 0; i < crashinfo.threads.size(); ++i) { ++ if (crashinfo.threads[i].tid == crashinfo.crashing_tid) { ++ WriteThread(crashinfo.threads[i], crashinfo.fatal_signal); ++ break; ++ } ++ } ++ ++ for (unsigned i = 0; i < crashinfo.threads.size(); ++i) { ++ if (crashinfo.threads[i].tid != crashinfo.crashing_tid) ++ WriteThread(crashinfo.threads[i], 0); ++ } ++ ++ if (note_align) { ++ char scratch[note_align]; ++ memset(scratch, 0, sizeof(scratch)); ++ if (!writea(1, scratch, sizeof(scratch))) ++ return 1; ++ } ++ ++ for (unsigned i = 0; i < crashinfo.threads.size(); ++i) { ++ const CrashedProcess::Thread& thread = crashinfo.threads[i]; ++ if (!writea(1, thread.stack, thread.stack_length)) ++ return 1; ++ } ++ ++ munmap(const_cast(bytes), st.st_size); ++ ++ return 0; ++} +diff --git a/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/crash_report.mm b/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/crash_report.mm +--- a/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/crash_report.mm ++++ b/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/crash_report.mm +@@ -54,30 +54,32 @@ + #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); +@@ -185,32 +187,66 @@ static void PrintRegisters(const CallSta + if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_GPR1) + sequence = PrintRegister("r1", frame_ppc->context.gpr[1], sequence); + } + } + + printf("\n"); + } + +-//============================================================================= +-static void Start(Options *options) { +- string minidump_file([options->minidumpPath fileSystemRepresentation]); ++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 symbol_supplier( + new OnDemandSymbolSupplier(search_dir, symbol_search_dir)); + scoped_ptr + minidump_processor(new MinidumpProcessor(symbol_supplier.get(), &resolver)); + ProcessState process_state; +- if (minidump_processor->Process(minidump_file, &process_state) != +- MinidumpProcessor::PROCESS_OK) { ++ scoped_ptr 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 +@@ -239,68 +275,109 @@ static void Start(Options *options) { + 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 = process_state.threads()->size(); ++ const std::vector ++ *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::MinidumpMemoryRegion *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])) { ++ 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); ++ } ++ } ++ } 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 " + "/.\n"); +- fprintf(stderr, "Usage: %s [-s module-search-dir] [-S symbol-file-search-dir] minidump-file\n", argv[0]); ++ 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-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:h?")) != -1) { ++ 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; + } + } + +diff --git a/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj b/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj +--- a/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj ++++ b/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj +@@ -125,19 +125,19 @@ + 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; }; +- F9C7ECE20E8ABCA600E953AD /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/mac/dwarf/bytereader.cc; sourceTree = SOURCE_ROOT; }; +- F9C7ECE30E8ABCA600E953AD /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/mac/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; }; +- F9C7ECE40E8ABCA600E953AD /* functioninfo.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = functioninfo.cc; path = ../../../common/mac/dwarf/functioninfo.cc; sourceTree = SOURCE_ROOT; }; ++ 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; }; + 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 */ = { +diff --git a/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/on_demand_symbol_supplier.h b/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/on_demand_symbol_supplier.h +--- a/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/on_demand_symbol_supplier.h ++++ b/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/on_demand_symbol_supplier.h +@@ -42,30 +42,35 @@ 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, ++ 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); + 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 module_file_map_; + + // Return the name for |module| This will be the value used as the key + // to the |module_file_map_|. + string GetNameForModule(const CodeModule *module); + +diff --git a/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/on_demand_symbol_supplier.mm b/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/on_demand_symbol_supplier.mm +--- a/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/on_demand_symbol_supplier.mm ++++ b/toolkit/crashreporter/google-breakpad/src/tools/mac/crash_report/on_demand_symbol_supplier.mm +@@ -25,16 +25,18 @@ + // 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 + #include + #include ++#include ++#include + + #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 "dump_syms.h" +@@ -131,16 +133,36 @@ OnDemandSymbolSupplier::GetSymbolFile(co + + 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) { ++ 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; ++} ++ + 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)]; +diff --git a/toolkit/crashreporter/google-breakpad/src/tools/mac/dump_syms/Makefile.in b/toolkit/crashreporter/google-breakpad/src/tools/mac/dump_syms/Makefile.in +--- a/toolkit/crashreporter/google-breakpad/src/tools/mac/dump_syms/Makefile.in ++++ b/toolkit/crashreporter/google-breakpad/src/tools/mac/dump_syms/Makefile.in +@@ -48,18 +48,18 @@ LOCAL_INCLUDES = \ + -I$(srcdir)/../../../common/mac \ + $(NULL) + + HOST_CMMSRCS = \ + dump_syms_tool.mm \ + $(NULL) + + HOST_LIBS += \ ++ $(DEPTH)/toolkit/crashreporter/google-breakpad/src/common/dwarf/$(LIB_PREFIX)host_breakpad_dwarf_s.$(LIB_SUFFIX) \ + $(DEPTH)/toolkit/crashreporter/google-breakpad/src/common/mac/$(LIB_PREFIX)host_breakpad_mac_common_s.$(LIB_SUFFIX) \ +- $(DEPTH)/toolkit/crashreporter/google-breakpad/src/common/mac/dwarf/$(LIB_PREFIX)host_breakpad_mac_dwarf_s.$(LIB_SUFFIX) \ + $(DEPTH)/toolkit/crashreporter/google-breakpad/src/common/$(LIB_PREFIX)host_breakpad_common_s.$(LIB_SUFFIX) \ + $(NULL) + + HOST_LDFLAGS += \ + -framework Foundation \ + -lcrypto \ + $(NULL) + +diff --git a/toolkit/crashreporter/google-breakpad/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj b/toolkit/crashreporter/google-breakpad/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj +--- a/toolkit/crashreporter/google-breakpad/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj ++++ b/toolkit/crashreporter/google-breakpad/src/tools/mac/dump_syms/dump_syms.xcodeproj/project.pbxproj +@@ -40,25 +40,25 @@ + 9BDF186D0B1BB43700F8391B /* dump_syms.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dump_syms.h; path = ../../../common/mac/dump_syms.h; sourceTree = ""; }; + 9BDF186E0B1BB43700F8391B /* dump_syms_tool.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = dump_syms_tool.mm; sourceTree = ""; }; + 9BE650410B52F6D800611104 /* file_id.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = file_id.cc; path = ../../../common/mac/file_id.cc; sourceTree = SOURCE_ROOT; }; + 9BE650420B52F6D800611104 /* file_id.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = file_id.h; path = ../../../common/mac/file_id.h; sourceTree = SOURCE_ROOT; }; + 9BE650430B52F6D800611104 /* macho_id.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_id.cc; path = ../../../common/mac/macho_id.cc; sourceTree = SOURCE_ROOT; }; + 9BE650440B52F6D800611104 /* macho_id.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_id.h; path = ../../../common/mac/macho_id.h; sourceTree = SOURCE_ROOT; }; + 9BE650450B52F6D800611104 /* macho_walker.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_walker.cc; path = ../../../common/mac/macho_walker.cc; sourceTree = SOURCE_ROOT; }; + 9BE650460B52F6D800611104 /* macho_walker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_walker.h; path = ../../../common/mac/macho_walker.h; sourceTree = SOURCE_ROOT; }; +- F95B422B0E0E22D100DBDE83 /* bytereader-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "bytereader-inl.h"; path = "../../../common/mac/dwarf/bytereader-inl.h"; sourceTree = SOURCE_ROOT; }; +- F95B422C0E0E22D100DBDE83 /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/mac/dwarf/bytereader.cc; sourceTree = SOURCE_ROOT; }; +- F95B422D0E0E22D100DBDE83 /* bytereader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bytereader.h; path = ../../../common/mac/dwarf/bytereader.h; sourceTree = SOURCE_ROOT; }; +- F95B422E0E0E22D100DBDE83 /* dwarf2enums.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2enums.h; path = ../../../common/mac/dwarf/dwarf2enums.h; sourceTree = SOURCE_ROOT; }; +- F95B422F0E0E22D100DBDE83 /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/mac/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; }; +- F95B42300E0E22D100DBDE83 /* dwarf2reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2reader.h; path = ../../../common/mac/dwarf/dwarf2reader.h; sourceTree = SOURCE_ROOT; }; +- F95B42310E0E22D100DBDE83 /* line_state_machine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = line_state_machine.h; path = ../../../common/mac/dwarf/line_state_machine.h; sourceTree = SOURCE_ROOT; }; +- F9C7ED420E8AD93000E953AD /* functioninfo.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = functioninfo.cc; path = ../../../common/mac/dwarf/functioninfo.cc; sourceTree = SOURCE_ROOT; }; +- F9F5344D0E7C902C0012363F /* functioninfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = functioninfo.h; path = ../../../common/mac/dwarf/functioninfo.h; sourceTree = SOURCE_ROOT; }; ++ F95B422B0E0E22D100DBDE83 /* bytereader-inl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "bytereader-inl.h"; path = "../../../common/dwarf/bytereader-inl.h"; sourceTree = SOURCE_ROOT; }; ++ F95B422C0E0E22D100DBDE83 /* bytereader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bytereader.cc; path = ../../../common/dwarf/bytereader.cc; sourceTree = SOURCE_ROOT; }; ++ F95B422D0E0E22D100DBDE83 /* bytereader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bytereader.h; path = ../../../common/dwarf/bytereader.h; sourceTree = SOURCE_ROOT; }; ++ F95B422E0E0E22D100DBDE83 /* dwarf2enums.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2enums.h; path = ../../../common/dwarf/dwarf2enums.h; sourceTree = SOURCE_ROOT; }; ++ F95B422F0E0E22D100DBDE83 /* dwarf2reader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dwarf2reader.cc; path = ../../../common/dwarf/dwarf2reader.cc; sourceTree = SOURCE_ROOT; }; ++ F95B42300E0E22D100DBDE83 /* dwarf2reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dwarf2reader.h; path = ../../../common/dwarf/dwarf2reader.h; sourceTree = SOURCE_ROOT; }; ++ F95B42310E0E22D100DBDE83 /* 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 = SOURCE_ROOT; }; ++ F9C7ED420E8AD93000E953AD /* functioninfo.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = functioninfo.cc; path = ../../../common/dwarf/functioninfo.cc; sourceTree = SOURCE_ROOT; }; ++ F9F5344D0E7C902C0012363F /* functioninfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = functioninfo.h; path = ../../../common/dwarf/functioninfo.h; sourceTree = SOURCE_ROOT; }; + /* End PBXFileReference section */ + + /* Begin PBXFrameworksBuildPhase section */ + 8DD76F9B0486AA7600D96B5E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8DD76F9C0486AA7600D96B5E /* Foundation.framework in Frameworks */, +diff --git a/toolkit/crashreporter/google-breakpad/src/tools/windows/symupload/symupload.cc b/toolkit/crashreporter/google-breakpad/src/tools/windows/symupload/symupload.cc +--- a/toolkit/crashreporter/google-breakpad/src/tools/windows/symupload/symupload.cc ++++ b/toolkit/crashreporter/google-breakpad/src/tools/windows/symupload/symupload.cc +@@ -126,43 +126,65 @@ static bool DumpSymbolsToTempFile(const + + wchar_t temp_filename[_MAX_PATH]; + if (GetTempFileName(temp_path, L"sym", 0, temp_filename) == 0) { + return false; + } + + FILE *temp_file = NULL; + #if _MSC_VER >= 1400 // MSVC 2005/8 +- if (_wfopen_s(&temp_file, temp_filename, L"w") != 0) { ++ if (_wfopen_s(&temp_file, temp_filename, L"w") != 0) + #else // _MSC_VER >= 1400 + // _wfopen_s was introduced in MSVC8. Use _wfopen for earlier environments. + // Don't use it with MSVC8 and later, because it's deprecated. +- if (!(temp_file = _wfopen(temp_filename, L"w"))) { ++ if (!(temp_file = _wfopen(temp_filename, L"w"))) + #endif // _MSC_VER >= 1400 ++ { + return false; + } + + bool success = writer.WriteMap(temp_file); + fclose(temp_file); + if (!success) { + _wunlink(temp_filename); + return false; + } + + *temp_file_path = temp_filename; + + return writer.GetModuleInfo(pdb_info); + } + ++void printUsageAndExit() { ++ wprintf(L"Usage: symupload [--timeout NN] \n\n"); ++ wprintf(L"Timeout is in milliseconds, or can be 0 to be unlimited\n\n"); ++ wprintf(L"Example:\n\n\tsymupload.exe --timeout 0 chrome.dll http://no.free.symbol.server.for.you\n"); ++ exit(0); ++} + int wmain(int argc, wchar_t *argv[]) { +- if (argc < 3) { +- wprintf(L"Usage: %s \n", argv[0]); +- return 0; ++ if ((argc != 3) && ++ (argc != 5)) { ++ printUsageAndExit(); + } +- const wchar_t *module = argv[1], *url = argv[2]; ++ ++ const wchar_t *module, *url; ++ int timeout = -1; ++ if (argc == 3) { ++ module = argv[1]; ++ url = argv[2]; ++ } else { ++ // check for timeout flag ++ if (!wcscmp(L"--timeout", argv[1])) { ++ timeout = _wtoi(argv[2]); ++ module = argv[3]; ++ url = argv[4]; ++ } else { ++ printUsageAndExit(); ++ } ++ } + + wstring symbol_file; + PDBModuleInfo pdb_info; + if (!DumpSymbolsToTempFile(module, &symbol_file, &pdb_info)) { + fwprintf(stderr, L"Could not get symbol data from %s\n", module); + return 1; + } + +@@ -181,16 +203,17 @@ int wmain(int argc, wchar_t *argv[]) { + if (GetFileVersionString(module, &file_version)) { + parameters[L"version"] = file_version; + } else { + fwprintf(stderr, L"Warning: Could not get file version for %s\n", module); + } + + bool success = HTTPUpload::SendRequest(url, parameters, + symbol_file, L"symbol_file", ++ timeout == -1 ? NULL : &timeout, + NULL, NULL); + _wunlink(symbol_file.c_str()); + + if (!success) { + fwprintf(stderr, L"Symbol file upload failed\n"); + return 1; + } + +diff --git a/toolkit/crashreporter/test/unit/test_crashreporter_crash_profile_lock.js b/toolkit/crashreporter/test/unit/test_crashreporter_crash_profile_lock.js +new file mode 100644 +--- /dev/null ++++ b/toolkit/crashreporter/test/unit/test_crashreporter_crash_profile_lock.js +@@ -0,0 +1,27 @@ ++function run_test() ++{ ++ if (!("@mozilla.org/toolkit/crash-reporter;1" in Components.classes)) { ++ dump("INFO | test_crashreporter.js | Can't test crashreporter in a non-libxul build.\n"); ++ return; ++ } ++ ++ // lock a profile directory, crash, and ensure that ++ // the profile lock signal handler doesn't interfere with ++ // writing a minidump ++ do_crash(function() { ++ let env = Components.classes["@mozilla.org/process/environment;1"] ++ .getService(Components.interfaces.nsIEnvironment); ++ // the python harness sets this in the environment for us ++ let profd = env.get("XPCSHELL_TEST_PROFILE_DIR"); ++ let dir = Components.classes["@mozilla.org/file/local;1"] ++ .createInstance(Components.interfaces.nsILocalFile); ++ dir.initWithPath(profd); ++ let mycrasher = Components.classes["@mozilla.org/testcrasher;1"].createInstance(Components.interfaces.nsITestCrasher); ++ let lock = mycrasher.lockDir(dir); ++ // when we crash, the lock file should be cleaned up ++ }, ++ function(mdump, extra) { ++ // if we got here, we have a minidump, so that's all we wanted ++ do_check_true(true); ++ }); ++} +diff --git a/toolkit/toolkit-makefiles.sh b/toolkit/toolkit-makefiles.sh +--- a/toolkit/toolkit-makefiles.sh ++++ b/toolkit/toolkit-makefiles.sh +@@ -690,16 +690,17 @@ MAKEFILES_embedding=" + + MAKEFILES_xulapp=" + toolkit/Makefile + toolkit/library/Makefile + toolkit/crashreporter/Makefile + toolkit/crashreporter/client/Makefile + toolkit/crashreporter/google-breakpad/src/client/Makefile + toolkit/crashreporter/google-breakpad/src/client/linux/handler/Makefile ++ toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/Makefile + toolkit/crashreporter/google-breakpad/src/client/mac/handler/Makefile + toolkit/crashreporter/google-breakpad/src/client/solaris/handler/Makefile + toolkit/crashreporter/google-breakpad/src/client/windows/crash_generation/Makefile + toolkit/crashreporter/google-breakpad/src/client/windows/handler/Makefile + toolkit/crashreporter/google-breakpad/src/client/windows/sender/Makefile + toolkit/crashreporter/google-breakpad/src/common/Makefile + toolkit/crashreporter/google-breakpad/src/common/linux/Makefile + toolkit/crashreporter/google-breakpad/src/common/mac/Makefile +diff --git a/toolkit/xre/Makefile.in b/toolkit/xre/Makefile.in +--- a/toolkit/xre/Makefile.in ++++ b/toolkit/xre/Makefile.in +@@ -182,16 +182,17 @@ SHARED_LIBRARY_LIBS += \ + $(DEPTH)/toolkit/crashreporter/google-breakpad/src/client/mac/handler/$(LIB_PREFIX)exception_handler_s.$(LIB_SUFFIX) \ + $(DEPTH)/toolkit/crashreporter/google-breakpad/src/common/$(LIB_PREFIX)breakpad_common_s.$(LIB_SUFFIX) \ + $(DEPTH)/toolkit/crashreporter/google-breakpad/src/common/mac/$(LIB_PREFIX)breakpad_mac_common_s.$(LIB_SUFFIX) + endif + + ifeq ($(OS_ARCH),Linux) + SHARED_LIBRARY_LIBS += \ + $(DEPTH)/toolkit/crashreporter/google-breakpad/src/client/linux/handler/$(LIB_PREFIX)exception_handler_s.$(LIB_SUFFIX) \ ++ $(DEPTH)/toolkit/crashreporter/google-breakpad/src/client/linux/minidump_writer/$(LIB_PREFIX)minidump_writer_s.$(LIB_SUFFIX) \ + $(DEPTH)/toolkit/crashreporter/google-breakpad/src/client/$(LIB_PREFIX)minidump_file_writer_s.$(LIB_SUFFIX) \ + $(DEPTH)/toolkit/crashreporter/google-breakpad/src/common/$(LIB_PREFIX)breakpad_common_s.$(LIB_SUFFIX) \ + $(DEPTH)/toolkit/crashreporter/google-breakpad/src/common/linux/$(LIB_PREFIX)breakpad_linux_common_s.$(LIB_SUFFIX) \ + $(NULL) + endif + + ifeq ($(OS_ARCH),SunOS) + SHARED_LIBRARY_LIBS += \ diff -r 6ee6583389c7 -r 3a1561dda105 mozilla-xulrunner192/mozilla-breakpad-update.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mozilla-xulrunner192/mozilla-breakpad-update.patch Wed Jan 06 13:19:39 2010 +0100 @@ -0,0 +1,1 @@ +../mozilla-breakpad-update.patch \ No newline at end of file diff -r 6ee6583389c7 -r 3a1561dda105 mozilla-xulrunner192/mozilla-xulrunner192.spec --- a/mozilla-xulrunner192/mozilla-xulrunner192.spec Mon Dec 28 19:09:32 2009 +0100 +++ b/mozilla-xulrunner192/mozilla-xulrunner192.spec Wed Jan 06 13:19:39 2010 +0100 @@ -2,7 +2,7 @@ # spec file for package mozilla-xulrunner192 (Version 1.9.2b5) # # Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany. -# 2006-2009 Wolfgang Rosenauer +# 2006-2010 Wolfgang Rosenauer # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -83,6 +83,7 @@ Patch13: toolkit-ui-lockdown.patch # --- Patch14: mozilla-breakpad.patch +Patch15: mozilla-breakpad-update.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build PreReq: update-alternatives coreutils ### build configuration ### @@ -138,7 +139,7 @@ %description devel Software Development Kit to embed XUL or Gecko into other applications. - +%if %localize %package translations-common License: GPLv2+ ; LGPLv2.1+ ; MPLv1.1+ Summary: Common translations for XULRunner 1.9.2 @@ -170,7 +171,7 @@ Thunderbird. This package contains rarely used languages. - +%endif %package gnome License: GPLv2+ ; LGPLv2.1+ ; MPLv1.1+ @@ -215,6 +216,7 @@ %patch12 -p1 %patch13 -p1 %patch14 -p1 +#%patch15 -p1 %build %if %suse_version >= 1110 diff -r 6ee6583389c7 -r 3a1561dda105 series --- a/series Mon Dec 28 19:09:32 2009 +0100 +++ b/series Wed Jan 06 13:19:39 2010 +0100 @@ -13,6 +13,7 @@ gecko-lockdown.patch toolkit-ui-lockdown.patch mozilla-breakpad.patch +mozilla-breakpad-update.patch # Firefox patches firefox-libxul-sdk.patch