[Libreoffice-commits] core.git: Branch 'feature/breakpad' - 16 commits - bin/symbolstore.py bin/upload_symbols.py configure.ac desktop/Executable_minidump_upload.mk desktop/Library_sofficeapp.mk desktop/Module_desktop.mk desktop/source distro-configs/LibreOfficeLinux.conf external/breakpad include/desktop include/vcl RepositoryExternal.mk Repository.mk sc/source svx/Library_svx.mk svx/source svx/UIConfig_svx.mk svx/util vcl/inc vcl/Library_vcl.mk vcl/opengl vcl/source

Markus Mohrhard markus.mohrhard at googlemail.com
Mon Feb 15 06:10:23 UTC 2016


 Repository.mk                                 |    2 
 RepositoryExternal.mk                         |    5 
 bin/symbolstore.py                            |  644 ++++++++++++++++++++++++++
 bin/upload_symbols.py                         |   24 
 configure.ac                                  |    6 
 desktop/Executable_minidump_upload.mk         |   22 
 desktop/Library_sofficeapp.mk                 |   12 
 desktop/Module_desktop.mk                     |    2 
 desktop/source/app/app.cxx                    |   60 ++
 desktop/source/app/crashreport.cxx            |   45 +
 desktop/source/app/sofficemain.cxx            |   21 
 desktop/source/minidump/minidump_upload.cxx   |  199 ++++++++
 distro-configs/LibreOfficeLinux.conf          |    1 
 external/breakpad/ExternalPackage_breakpad.mk |   20 
 external/breakpad/Module_breakpad.mk          |    1 
 external/breakpad/UnpackedTarball_breakpad.mk |    2 
 external/breakpad/breakpad-wshadow.patch.1    |  232 +++++++++
 external/breakpad/breakpad-wshadow2.patch.1   |  144 +++++
 include/desktop/crashreport.hxx               |    9 
 include/desktop/dllapi.h                      |    6 
 include/vcl/window.hxx                        |   10 
 sc/source/ui/docshell/docsh.cxx               |    7 
 svx/Library_svx.mk                            |    5 
 svx/UIConfig_svx.mk                           |    1 
 svx/source/dialog/crashreportdlg.cxx          |   74 ++
 svx/source/dialog/crashreportdlg.hxx          |   36 +
 svx/source/dialog/crashreportui.cxx           |  104 ++++
 svx/util/svx.component                        |    4 
 vcl/Library_vcl.mk                            |    2 
 vcl/inc/window.h                              |    1 
 vcl/opengl/win/WinDeviceInfo.cxx              |    4 
 vcl/opengl/x11/X11DeviceInfo.cxx              |    9 
 vcl/source/window/builder.cxx                 |    1 
 vcl/source/window/window.cxx                  |   10 
 34 files changed, 1672 insertions(+), 53 deletions(-)

New commits:
commit 07846bf83bda00ed220fc2e26609920b19c5adaf
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Sun Feb 7 22:57:51 2016 +0100

    disable breakpad by default
    
    Includes fixes for disabled breakpad build.
    
    Change-Id: I2112a82cfa8ca548987994ea97cda48a7387842e

diff --git a/configure.ac b/configure.ac
index 3f06009..1a28b34 100644
--- a/configure.ac
+++ b/configure.ac
@@ -9090,14 +9090,14 @@ dnl ==================================================================
 dnl Breakpad
 dnl ==================================================================
 AC_MSG_CHECKING([whether to enable breakpad])
-if test -z "$enable_breakpad" -o "$enable_breakpad" != no; then
+if test "$enable_breakpad" != yes; then
+    AC_MSG_RESULT([no])
+else
     AC_MSG_RESULT([yes])
     ENABLE_BREAKPAD="TRUE"
     AC_DEFINE(ENABLE_BREAKPAD)
     AC_DEFINE(HAVE_FEATURE_BREAKPAD, 1)
     BUILD_TYPE="$BUILD_TYPE BREAKPAD"
-else
-    AC_MSG_RESULT([no])
 fi
 AC_SUBST(ENABLE_BREAKPAD)
 
diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx
index f1c767f..2fae668 100644
--- a/desktop/source/app/app.cxx
+++ b/desktop/source/app/app.cxx
@@ -2344,7 +2344,9 @@ void Desktop::OpenClients()
         }
     }
 
+#if HAVE_FEATURE_BREAKPAD
     CrashReporter::writeCommonInfo();
+#endif
     OfficeIPCThread::EnableRequests();
 
     ProcessDocumentsRequest aRequest(rArgs.getCwdUrl());
diff --git a/distro-configs/LibreOfficeLinux.conf b/distro-configs/LibreOfficeLinux.conf
index d57706c..efa314f 100644
--- a/distro-configs/LibreOfficeLinux.conf
+++ b/distro-configs/LibreOfficeLinux.conf
@@ -34,3 +34,4 @@
 --enable-online-update
 --disable-dconf
 --enable-mergelibs
+--enable-breakpad
diff --git a/svx/Library_svx.mk b/svx/Library_svx.mk
index 32a9ec5..88d4173 100644
--- a/svx/Library_svx.mk
+++ b/svx/Library_svx.mk
@@ -46,7 +46,8 @@ $(eval $(call gb_Library_use_libraries,svx,\
     comphelper \
     cppuhelper \
     cppu \
-    crashreport \
+    $(if $(filter TRUE,$(ENABLE_BREAKPAD)), \
+		crashreport) \
     $(call gb_Helper_optional,DBCONNECTIVITY, \
         dbtools) \
     drawinglayer \
@@ -109,7 +110,8 @@ $(eval $(call gb_Library_add_exception_objects,svx,\
     svx/source/dialog/_contdlg \
     svx/source/dialog/contwnd \
     svx/source/dialog/compressgraphicdialog \
-    svx/source/dialog/crashreportdlg \
+    $(if $(filter TRUE,$(ENABLE_BREAKPAD)), \
+		svx/source/dialog/crashreportdlg) \
     svx/source/dialog/crashreportui \
     svx/source/dialog/ctredlin \
     svx/source/dialog/databaseregistrationui \
diff --git a/svx/source/dialog/crashreportui.cxx b/svx/source/dialog/crashreportui.cxx
index 94b1a68..880a488 100644
--- a/svx/source/dialog/crashreportui.cxx
+++ b/svx/source/dialog/crashreportui.cxx
@@ -11,6 +11,8 @@
 #include <com/sun/star/frame/XSynchronousDispatch.hpp>
 #include <com/sun/star/lang/XServiceInfo.hpp>
 
+#include <config_features.h>
+
 #include <comphelper/processfactory.hxx>
 #include <cppuhelper/supportsservice.hxx>
 
@@ -82,8 +84,10 @@ css::uno::Any SAL_CALL CrashReportUI::dispatchWithReturnValue(const css::util::U
 {
     SolarMutexGuard aGuard;
     css::uno::Any aRet;
+#if HAVE_FEATURE_BREAKPAD
     ScopedVclPtrInstance<CrashReportDialog> xDialog(new CrashReportDialog(nullptr));
     xDialog->Execute();
+#endif
     return aRet;
 }
 
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 323c185..453cdae 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -75,7 +75,8 @@ $(eval $(call gb_Library_use_externals,vcl,\
 ))
 
 $(eval $(call gb_Library_use_libraries,vcl,\
-	crashreport \
+    $(if $(filter TRUE,$(ENABLE_BREAKPAD)), \
+		crashreport) \
     svl \
     tl \
     utl \
diff --git a/vcl/opengl/x11/X11DeviceInfo.cxx b/vcl/opengl/x11/X11DeviceInfo.cxx
index 89af561..1545370 100644
--- a/vcl/opengl/x11/X11DeviceInfo.cxx
+++ b/vcl/opengl/x11/X11DeviceInfo.cxx
@@ -10,6 +10,8 @@
 #include "opengl/x11/X11DeviceInfo.hxx"
 #include "opengl/x11//glxtest.hxx"
 
+#include <config_features.h>
+
 #include <rtl/ustring.hxx>
 
 #include <unistd.h>
@@ -288,8 +290,10 @@ bool X11OpenGLDeviceInfo::isDeviceBlocked()
     if (mnGLMajorVersion == 1)
         return true;
 
+#if HAVE_FEATURE_BREAKPAD
     CrashReporter::AddKeyValue("AdapterVendorId", rtl::OStringToOUString(maVendor, RTL_TEXTENCODING_UTF8));
     CrashReporter::AddKeyValue("AdapterDeviceId", rtl::OStringToOUString(maRenderer, RTL_TEXTENCODING_UTF8));
+#endif
 
     SAL_INFO("vcl.opengl", "Vendor: " << maVendor);
     SAL_INFO("vcl.opengl", "Renderer: " << maRenderer);
commit a5308f47c44884980784861836aad12f93754bb4
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Sun Feb 7 22:54:48 2016 +0100

    add TODO comment for showing the user the generated uuid
    
    Change-Id: I0f54f7e7f3b6b49fda926e7c579bb67c2924a943

diff --git a/svx/source/dialog/crashreportdlg.cxx b/svx/source/dialog/crashreportdlg.cxx
index 74066a8..23f0bbe 100644
--- a/svx/source/dialog/crashreportdlg.cxx
+++ b/svx/source/dialog/crashreportdlg.cxx
@@ -58,6 +58,7 @@ IMPL_LINK_TYPED(CrashReportDialog, BtnHdl, Button*, pBtn, void)
         OString aCommand = getLibDir().copy(7) + "/minidump_upload " + ini_path.c_str();
         int retVal = std::system(aCommand.getStr());
         SAL_WARN_IF(retVal != 0, "crashreport", "Failed to upload minidump. Error Code: " << retVal);
+        // TODO: moggi: return the id for the user to look it up
         Close();
     }
     else if (pBtn == mpBtnCancel.get())
commit ff12e1fc5d9979d4ebe3bdec2c4b5dd1e1e165ef
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Sun Feb 7 19:32:28 2016 +0100

    fix a number of Wshadow warnings in breakpad
    
    Change-Id: I8133e03e4ed21ac1efd9982860276d4776850bba

diff --git a/external/breakpad/UnpackedTarball_breakpad.mk b/external/breakpad/UnpackedTarball_breakpad.mk
index 8424a02..59073eb 100644
--- a/external/breakpad/UnpackedTarball_breakpad.mk
+++ b/external/breakpad/UnpackedTarball_breakpad.mk
@@ -13,6 +13,8 @@ $(eval $(call gb_UnpackedTarball_set_tarball,breakpad,$(BREAKPAD_TARBALL)))
 
 $(eval $(call gb_UnpackedTarball_add_patches,breakpad,\
 	external/breakpad/breakpad-use-correct-http-header.patch.1 \
+	external/breakpad/breakpad-wshadow.patch.1 \
+	external/breakpad/breakpad-wshadow2.patch.1 \
 ))
 
 # vim: set noet sw=4 ts=4:
diff --git a/external/breakpad/breakpad-wshadow.patch.1 b/external/breakpad/breakpad-wshadow.patch.1
new file mode 100644
index 0000000..d696e5b
--- /dev/null
+++ b/external/breakpad/breakpad-wshadow.patch.1
@@ -0,0 +1,232 @@
+Only in breakpad: breakpad-client.pc
+Only in breakpad: breakpad.pc
+Only in breakpad: build.log
+Only in breakpad: config.log
+Only in breakpad: config.status
+Only in breakpad: Makefile
+Only in breakpad/src/client: .deps
+Only in breakpad/src/client: .dirstamp
+Only in breakpad/src/client/linux/crash_generation: crash_generation_client.o
+Only in breakpad/src/client/linux/crash_generation: crash_generation_server.o
+Only in breakpad/src/client/linux/crash_generation: .deps
+Only in breakpad/src/client/linux/crash_generation: .dirstamp
+Only in breakpad/src/client/linux: .dirstamp
+Only in breakpad/src/client/linux/dump_writer_common: .deps
+Only in breakpad/src/client/linux/dump_writer_common: .dirstamp
+Only in breakpad/src/client/linux/dump_writer_common: thread_info.o
+Only in breakpad/src/client/linux/dump_writer_common: ucontext_reader.o
+Only in breakpad/src/client/linux/handler: .deps
+Only in breakpad/src/client/linux/handler: .dirstamp
+Only in breakpad/src/client/linux/handler: exception_handler.o
+diff -ur breakpad.org/src/client/linux/handler/minidump_descriptor.h breakpad/src/client/linux/handler/minidump_descriptor.h
+--- breakpad.org/src/client/linux/handler/minidump_descriptor.h	2016-02-07 19:22:24.329411023 +0100
++++ breakpad/src/client/linux/handler/minidump_descriptor.h	2016-02-07 19:24:28.600438386 +0100
+@@ -55,18 +55,18 @@
+         fd_(-1),
+         size_limit_(-1) {}
+ 
+-  explicit MinidumpDescriptor(const string& directory)
++  explicit MinidumpDescriptor(const string& dir)
+       : mode_(kWriteMinidumpToFile),
+         fd_(-1),
+-        directory_(directory),
++        directory_(dir),
+         c_path_(NULL),
+         size_limit_(-1) {
+     assert(!directory.empty());
+   }
+ 
+-  explicit MinidumpDescriptor(int fd)
++  explicit MinidumpDescriptor(int file_descriptor)
+       : mode_(kWriteMinidumpToFd),
+-        fd_(fd),
++        fd_(file_descriptor),
+         c_path_(NULL),
+         size_limit_(-1) {
+     assert(fd != -1);
+Only in breakpad/src/client/linux/handler: .minidump_descriptor.h.un~
+Only in breakpad/src/client/linux/handler: minidump_descriptor.o
+Only in breakpad/src/client/linux: libbreakpad_client.a
+Only in breakpad/src/client/linux: linux_dumper_unittest_helper
+Only in breakpad/src/client/linux/log: .deps
+Only in breakpad/src/client/linux/log: .dirstamp
+Only in breakpad/src/client/linux/log: log.o
+Only in breakpad/src/client/linux/microdump_writer: .deps
+Only in breakpad/src/client/linux/microdump_writer: .dirstamp
+Only in breakpad/src/client/linux/microdump_writer: microdump_writer.o
+Only in breakpad/src/client/linux/minidump_writer: .deps
+Only in breakpad/src/client/linux/minidump_writer: .dirstamp
+Only in breakpad/src/client/linux/minidump_writer: linux_core_dumper.o
+diff -ur breakpad.org/src/client/linux/minidump_writer/linux_dumper.h breakpad/src/client/linux/minidump_writer/linux_dumper.h
+--- breakpad.org/src/client/linux/minidump_writer/linux_dumper.h	2016-02-07 19:22:24.330410999 +0100
++++ breakpad/src/client/linux/minidump_writer/linux_dumper.h	2016-02-07 19:26:10.870017835 +0100
+@@ -130,15 +130,15 @@
+                                    uint8_t identifier[sizeof(MDGUID)]);
+ 
+   uintptr_t crash_address() const { return crash_address_; }
+-  void set_crash_address(uintptr_t crash_address) {
+-    crash_address_ = crash_address;
++  void set_crash_address(uintptr_t crash_addr) {
++    crash_address_ = crash_addr;
+   }
+ 
+   int crash_signal() const { return crash_signal_; }
+-  void set_crash_signal(int crash_signal) { crash_signal_ = crash_signal; }
++  void set_crash_signal(int crash_sig) { crash_signal_ = crash_sig; }
+ 
+   pid_t crash_thread() const { return crash_thread_; }
+-  void set_crash_thread(pid_t crash_thread) { crash_thread_ = crash_thread; }
++  void set_crash_thread(pid_t thread) { crash_thread_ = thread; }
+ 
+   // Extracts the effective path and file name of from |mapping|. In most cases
+   // the effective name/path are just the mapping's path and basename. In some
+Only in breakpad/src/client/linux/minidump_writer: .linux_dumper.h.un~
+Only in breakpad/src/client/linux/minidump_writer: linux_dumper.o
+Only in breakpad/src/client/linux/minidump_writer: linux_ptrace_dumper.o
+Only in breakpad/src/client/linux/minidump_writer: minidump_writer.o
+Only in breakpad/src/client/linux/minidump_writer: src_client_linux_linux_dumper_unittest_helper-linux_dumper_unittest_helper.o
+Only in breakpad/src/client: minidump_file_writer.o
+Only in breakpad/src/common/android: .deps
+Only in breakpad/src/common: convert_UTF.o
+Only in breakpad/src/common: .deps
+Only in breakpad/src/common: .dirstamp
+Only in breakpad/src/common/dwarf: bytereader.o
+Only in breakpad/src/common/dwarf: .deps
+Only in breakpad/src/common/dwarf: .dirstamp
+Only in breakpad/src/common/dwarf: dwarf2diehandler.o
+Only in breakpad/src/common/dwarf: dwarf2reader.o
+Only in breakpad/src/common/dwarf: src_tools_mac_dump_syms_dump_syms-bytereader.o
+Only in breakpad/src/common/dwarf: src_tools_mac_dump_syms_dump_syms-dwarf2diehandler.o
+Only in breakpad/src/common/dwarf: src_tools_mac_dump_syms_dump_syms-dwarf2reader.o
+Only in breakpad/src/common: dwarf_cfi_to_module.o
+Only in breakpad/src/common: dwarf_cu_to_module.o
+Only in breakpad/src/common: dwarf_line_to_module.o
+Only in breakpad/src/common: language.o
+Only in breakpad/src/common/linux: crc32.o
+Only in breakpad/src/common/linux: .deps
+Only in breakpad/src/common/linux: .dirstamp
+Only in breakpad/src/common/linux: dump_symbols.o
+Only in breakpad/src/common/linux: elf_core_dump.o
+Only in breakpad/src/common/linux: elf_symbols_to_module.o
+Only in breakpad/src/common/linux: elfutils.o
+Only in breakpad/src/common/linux: file_id.o
+Only in breakpad/src/common/linux: guid_creator.o
+Only in breakpad/src/common/linux: http_upload.o
+Only in breakpad/src/common/linux: linux_libc_support.o
+Only in breakpad/src/common/linux: memory_mapped_file.o
+Only in breakpad/src/common/linux: safe_readlink.o
+Only in breakpad/src/common/linux/tests: .deps
+Only in breakpad/src/common/mac: .deps
+Only in breakpad/src/common/mac: .dirstamp
+Only in breakpad/src/common/mac: src_tools_mac_dump_syms_dump_syms-arch_utilities.o
+Only in breakpad/src/common/mac: src_tools_mac_dump_syms_dump_syms-dump_syms.o
+Only in breakpad/src/common/mac: src_tools_mac_dump_syms_dump_syms-file_id.o
+Only in breakpad/src/common/mac: src_tools_mac_dump_syms_dump_syms-macho_id.o
+Only in breakpad/src/common/mac: src_tools_mac_dump_syms_dump_syms-macho_reader.o
+Only in breakpad/src/common/mac: src_tools_mac_dump_syms_dump_syms-macho_utilities.o
+Only in breakpad/src/common/mac: src_tools_mac_dump_syms_dump_syms-macho_walker.o
+Only in breakpad/src/common: md5.o
+Only in breakpad/src/common: module.o
+Only in breakpad/src/common: src_tools_mac_dump_syms_dump_syms-dwarf_cfi_to_module.o
+Only in breakpad/src/common: src_tools_mac_dump_syms_dump_syms-dwarf_cu_to_module.o
+Only in breakpad/src/common: src_tools_mac_dump_syms_dump_syms-dwarf_line_to_module.o
+Only in breakpad/src/common: src_tools_mac_dump_syms_dump_syms-language.o
+Only in breakpad/src/common: src_tools_mac_dump_syms_dump_syms-md5.o
+Only in breakpad/src/common: src_tools_mac_dump_syms_dump_syms-module.o
+Only in breakpad/src/common: src_tools_mac_dump_syms_dump_syms-stabs_reader.o
+Only in breakpad/src/common: src_tools_mac_dump_syms_dump_syms-stabs_to_module.o
+Only in breakpad/src/common: stabs_reader.o
+Only in breakpad/src/common: stabs_to_module.o
+Only in breakpad/src/common: string_conversion.o
+Only in breakpad/src/common/tests: .deps
+Only in breakpad/src: config.h
+Only in breakpad/src: .dirstamp
+Only in breakpad/src: libbreakpad.a
+Only in breakpad/src/processor: basic_code_modules.o
+Only in breakpad/src/processor: basic_source_line_resolver.o
+Only in breakpad/src/processor: call_stack.o
+Only in breakpad/src/processor: cfi_frame_info.o
+Only in breakpad/src/processor: .deps
+Only in breakpad/src/processor: .dirstamp
+Only in breakpad/src/processor: disassembler_x86.o
+Only in breakpad/src/processor: dump_context.o
+Only in breakpad/src/processor: dump_object.o
+Only in breakpad/src/processor: exploitability_linux.o
+Only in breakpad/src/processor: exploitability.o
+Only in breakpad/src/processor: exploitability_win.o
+Only in breakpad/src/processor: fast_source_line_resolver.o
+Only in breakpad/src/processor: logging.o
+Only in breakpad/src/processor: microdump.o
+Only in breakpad/src/processor: microdump_processor.o
+Only in breakpad/src/processor: microdump_stackwalk
+Only in breakpad/src/processor: microdump_stackwalk.o
+Only in breakpad/src/processor: minidump_dump
+Only in breakpad/src/processor: minidump_dump.o
+Only in breakpad/src/processor: minidump.o
+Only in breakpad/src/processor: minidump_processor.o
+Only in breakpad/src/processor: minidump_stackwalk
+Only in breakpad/src/processor: minidump_stackwalk.o
+Only in breakpad/src/processor: module_comparer.o
+Only in breakpad/src/processor: module_serializer.o
+Only in breakpad/src/processor: pathname_stripper.o
+Only in breakpad/src/processor: process_state.o
+Only in breakpad/src/processor: proc_maps_linux.o
+Only in breakpad/src/processor: simple_symbol_supplier.o
+Only in breakpad/src/processor: source_line_resolver_base.o
+Only in breakpad/src/processor: stack_frame_cpu.o
+Only in breakpad/src/processor: stack_frame_symbolizer.o
+Only in breakpad/src/processor: stackwalk_common.o
+Only in breakpad/src/processor: stackwalker_address_list.o
+Only in breakpad/src/processor: stackwalker_amd64.o
+Only in breakpad/src/processor: stackwalker_arm64.o
+Only in breakpad/src/processor: stackwalker_arm.o
+Only in breakpad/src/processor: stackwalker_mips.o
+Only in breakpad/src/processor: stackwalker.o
+Only in breakpad/src/processor: stackwalker_ppc64.o
+Only in breakpad/src/processor: stackwalker_ppc.o
+Only in breakpad/src/processor: stackwalker_sparc.o
+Only in breakpad/src/processor: stackwalker_x86.o
+Only in breakpad/src/processor: symbolic_constants_win.o
+Only in breakpad/src/processor: tokenize.o
+Only in breakpad/src: stamp-h1
+Only in breakpad/src/testing/gtest/src: .deps
+Only in breakpad/src/testing/src: .deps
+Only in breakpad/src/third_party/libdisasm: .deps
+Only in breakpad/src/third_party/libdisasm: .dirstamp
+Only in breakpad/src/third_party/libdisasm: ia32_implicit.o
+Only in breakpad/src/third_party/libdisasm: ia32_insn.o
+Only in breakpad/src/third_party/libdisasm: ia32_invariant.o
+Only in breakpad/src/third_party/libdisasm: ia32_modrm.o
+Only in breakpad/src/third_party/libdisasm: ia32_opcode_tables.o
+Only in breakpad/src/third_party/libdisasm: ia32_operand.o
+Only in breakpad/src/third_party/libdisasm: ia32_reg.o
+Only in breakpad/src/third_party/libdisasm: ia32_settings.o
+Only in breakpad/src/third_party/libdisasm: libdisasm.a
+Only in breakpad/src/third_party/libdisasm: x86_disasm.o
+Only in breakpad/src/third_party/libdisasm: x86_format.o
+Only in breakpad/src/third_party/libdisasm: x86_imm.o
+Only in breakpad/src/third_party/libdisasm: x86_insn.o
+Only in breakpad/src/third_party/libdisasm: x86_misc.o
+Only in breakpad/src/third_party/libdisasm: x86_operand_list.o
+Only in breakpad/src/tools/linux/core2md: core2md
+Only in breakpad/src/tools/linux/core2md: core2md.o
+Only in breakpad/src/tools/linux/core2md: .deps
+Only in breakpad/src/tools/linux/core2md: .dirstamp
+Only in breakpad/src/tools/linux/dump_syms: .deps
+Only in breakpad/src/tools/linux/dump_syms: .dirstamp
+Only in breakpad/src/tools/linux/dump_syms: dump_syms
+Only in breakpad/src/tools/linux/dump_syms: dump_syms.o
+Only in breakpad/src/tools/linux/md2core: .deps
+Only in breakpad/src/tools/linux/md2core: .dirstamp
+Only in breakpad/src/tools/linux/md2core: minidump-2-core
+Only in breakpad/src/tools/linux/md2core: minidump-2-core.o
+Only in breakpad/src/tools/linux/symupload: .deps
+Only in breakpad/src/tools/linux/symupload: .dirstamp
+Only in breakpad/src/tools/linux/symupload: minidump_upload
+Only in breakpad/src/tools/linux/symupload: minidump_upload.o
+Only in breakpad/src/tools/linux/symupload: sym_upload
+Only in breakpad/src/tools/linux/symupload: sym_upload.o
+Only in breakpad/src/tools/mac/dump_syms: .deps
+Only in breakpad/src/tools/mac/dump_syms: .dirstamp
+Only in breakpad/src/tools/mac/dump_syms: dump_syms
+Only in breakpad/src/tools/mac/dump_syms: src_tools_mac_dump_syms_dump_syms-dump_syms_tool.o
diff --git a/external/breakpad/breakpad-wshadow2.patch.1 b/external/breakpad/breakpad-wshadow2.patch.1
new file mode 100644
index 0000000..40267b3
--- /dev/null
+++ b/external/breakpad/breakpad-wshadow2.patch.1
@@ -0,0 +1,144 @@
+Only in breakpad: breakpad-client.pc
+Only in breakpad: breakpad.pc
+Only in breakpad: build.log
+Only in breakpad: config.log
+Only in breakpad: config.status
+Only in breakpad: Makefile
+Only in breakpad/src/client: .deps
+Only in breakpad/src/client: .dirstamp
+Only in breakpad/src/client/linux/crash_generation: crash_generation_client.o
+Only in breakpad/src/client/linux/crash_generation: .deps
+Only in breakpad/src/client/linux/crash_generation: .dirstamp
+Only in breakpad/src/client/linux: .dirstamp
+Only in breakpad/src/client/linux/dump_writer_common: .deps
+Only in breakpad/src/client/linux/dump_writer_common: .dirstamp
+Only in breakpad/src/client/linux/dump_writer_common: thread_info.o
+Only in breakpad/src/client/linux/dump_writer_common: ucontext_reader.o
+Only in breakpad/src/client/linux/handler: .deps
+Only in breakpad/src/client/linux/handler: .dirstamp
+diff -ur breakpad.org/src/client/linux/handler/minidump_descriptor.h breakpad/src/client/linux/handler/minidump_descriptor.h
+--- breakpad.org/src/client/linux/handler/minidump_descriptor.h	2016-02-07 19:28:40.335518286 +0100
++++ breakpad/src/client/linux/handler/minidump_descriptor.h	2016-02-07 19:29:14.706713302 +0100
+@@ -61,7 +61,7 @@
+         directory_(dir),
+         c_path_(NULL),
+         size_limit_(-1) {
+-    assert(!directory.empty());
++    assert(!dir.empty());
+   }
+ 
+   explicit MinidumpDescriptor(int file_descriptor)
+@@ -69,7 +69,7 @@
+         fd_(file_descriptor),
+         c_path_(NULL),
+         size_limit_(-1) {
+-    assert(fd != -1);
++    assert(file_descriptor != -1);
+   }
+ 
+   explicit MinidumpDescriptor(const MicrodumpOnConsole&)
+Only in breakpad/src/client/linux/handler: .minidump_descriptor.h.un~
+Only in breakpad/src/client/linux/log: .deps
+Only in breakpad/src/client/linux/log: .dirstamp
+Only in breakpad/src/client/linux/log: log.o
+Only in breakpad/src/client/linux/microdump_writer: .deps
+Only in breakpad/src/client/linux/microdump_writer: .dirstamp
+Only in breakpad/src/client/linux/minidump_writer: .deps
+Only in breakpad/src/client/linux/minidump_writer: .dirstamp
+Only in breakpad/src/client/linux/minidump_writer: linux_dumper.o
+Only in breakpad/src/client/linux/minidump_writer: linux_ptrace_dumper.o
+Only in breakpad/src/client: minidump_file_writer.o
+Only in breakpad/src/common/android: .deps
+Only in breakpad/src/common: convert_UTF.o
+Only in breakpad/src/common: .deps
+Only in breakpad/src/common: .dirstamp
+Only in breakpad/src/common/dwarf: .deps
+Only in breakpad/src/common/dwarf: .dirstamp
+Only in breakpad/src/common/dwarf: src_tools_mac_dump_syms_dump_syms-bytereader.o
+Only in breakpad/src/common/dwarf: src_tools_mac_dump_syms_dump_syms-dwarf2diehandler.o
+Only in breakpad/src/common/dwarf: src_tools_mac_dump_syms_dump_syms-dwarf2reader.o
+Only in breakpad/src/common: dwarf_cfi_to_module.o
+Only in breakpad/src/common: dwarf_cu_to_module.o
+Only in breakpad/src/common: dwarf_line_to_module.o
+Only in breakpad/src/common: language.o
+Only in breakpad/src/common/linux: crc32.o
+Only in breakpad/src/common/linux: .deps
+Only in breakpad/src/common/linux: .dirstamp
+Only in breakpad/src/common/linux: dump_symbols.o
+Only in breakpad/src/common/linux: elf_symbols_to_module.o
+Only in breakpad/src/common/linux: http_upload.o
+Only in breakpad/src/common/linux/tests: .deps
+Only in breakpad/src/common/mac: .deps
+Only in breakpad/src/common/mac: .dirstamp
+Only in breakpad/src/common: module.o
+Only in breakpad/src/common: src_tools_mac_dump_syms_dump_syms-dwarf_cfi_to_module.o
+Only in breakpad/src/common: src_tools_mac_dump_syms_dump_syms-dwarf_cu_to_module.o
+Only in breakpad/src/common: src_tools_mac_dump_syms_dump_syms-dwarf_line_to_module.o
+Only in breakpad/src/common: src_tools_mac_dump_syms_dump_syms-language.o
+Only in breakpad/src/common: src_tools_mac_dump_syms_dump_syms-md5.o
+Only in breakpad/src/common: src_tools_mac_dump_syms_dump_syms-module.o
+Only in breakpad/src/common: src_tools_mac_dump_syms_dump_syms-stabs_reader.o
+Only in breakpad/src/common: src_tools_mac_dump_syms_dump_syms-stabs_to_module.o
+Only in breakpad/src/common: stabs_reader.o
+Only in breakpad/src/common: stabs_to_module.o
+Only in breakpad/src/common/tests: .deps
+Only in breakpad/src: config.h
+Only in breakpad/src: .dirstamp
+Only in breakpad/src/processor: basic_code_modules.o
+Only in breakpad/src/processor: basic_source_line_resolver.o
+Only in breakpad/src/processor: call_stack.o
+Only in breakpad/src/processor: cfi_frame_info.o
+Only in breakpad/src/processor: .deps
+Only in breakpad/src/processor: .dirstamp
+Only in breakpad/src/processor: disassembler_x86.o
+Only in breakpad/src/processor: dump_context.o
+Only in breakpad/src/processor: dump_object.o
+Only in breakpad/src/processor: exploitability_linux.o
+Only in breakpad/src/processor: exploitability.o
+Only in breakpad/src/processor: exploitability_win.o
+Only in breakpad/src/processor: fast_source_line_resolver.o
+Only in breakpad/src/processor: logging.o
+Only in breakpad/src/processor: microdump.o
+Only in breakpad/src/processor: microdump_processor.o
+Only in breakpad/src/processor: microdump_stackwalk.o
+Only in breakpad/src/processor: minidump_dump.o
+Only in breakpad/src/processor: minidump.o
+Only in breakpad/src/processor: minidump_processor.o
+Only in breakpad/src/processor: minidump_stackwalk.o
+Only in breakpad/src/processor: module_comparer.o
+Only in breakpad/src/processor: module_serializer.o
+Only in breakpad/src/processor: pathname_stripper.o
+Only in breakpad/src/processor: process_state.o
+Only in breakpad/src/processor: proc_maps_linux.o
+Only in breakpad/src/processor: simple_symbol_supplier.o
+Only in breakpad/src/processor: source_line_resolver_base.o
+Only in breakpad/src/processor: stack_frame_cpu.o
+Only in breakpad/src/processor: stack_frame_symbolizer.o
+Only in breakpad/src/processor: stackwalk_common.o
+Only in breakpad/src/processor: stackwalker_address_list.o
+Only in breakpad/src/processor: stackwalker_amd64.o
+Only in breakpad/src/processor: stackwalker_arm64.o
+Only in breakpad/src/processor: stackwalker_arm.o
+Only in breakpad/src/processor: stackwalker_mips.o
+Only in breakpad/src/processor: stackwalker.o
+Only in breakpad/src/processor: stackwalker_ppc64.o
+Only in breakpad/src/processor: stackwalker_ppc.o
+Only in breakpad/src/processor: stackwalker_sparc.o
+Only in breakpad/src/processor: stackwalker_x86.o
+Only in breakpad/src/processor: symbolic_constants_win.o
+Only in breakpad/src/processor: tokenize.o
+Only in breakpad/src: stamp-h1
+Only in breakpad/src/testing/gtest/src: .deps
+Only in breakpad/src/testing/src: .deps
+Only in breakpad/src/third_party/libdisasm: .deps
+Only in breakpad/src/third_party/libdisasm: .dirstamp
+Only in breakpad/src/tools/linux/core2md: .deps
+Only in breakpad/src/tools/linux/core2md: .dirstamp
+Only in breakpad/src/tools/linux/dump_syms: .deps
+Only in breakpad/src/tools/linux/dump_syms: .dirstamp
+Only in breakpad/src/tools/linux/md2core: .deps
+Only in breakpad/src/tools/linux/md2core: .dirstamp
+Only in breakpad/src/tools/linux/symupload: .deps
+Only in breakpad/src/tools/linux/symupload: .dirstamp
+Only in breakpad/src/tools/mac/dump_syms: .deps
+Only in breakpad/src/tools/mac/dump_syms: .dirstamp
commit 7805c4ef9ca9d2ae5891d7ad71c24a357091e8de
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Sun Feb 7 00:19:09 2016 +0100

    work on adding crash report UI
    
    Change-Id: I66f4dca3cd32381ecd52cc36490e7ee1dddf3699

diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx
index d5e5c2c..f1c767f 100644
--- a/desktop/source/app/app.cxx
+++ b/desktop/source/app/app.cxx
@@ -105,6 +105,7 @@
 #include <svl/itemset.hxx>
 #include <svl/eitem.hxx>
 #include <basic/sbstar.hxx>
+#include <desktop/crashreport.hxx>
 
 #include <svtools/fontsubstconfig.hxx>
 #include <svtools/accessibilityoptions.hxx>
@@ -119,6 +120,10 @@
 #include <tubes/manager.hxx>
 #endif
 
+#if HAVE_FEATURE_BREAKPAD
+#include <fstream>
+#endif
+
 #if defined MACOSX
 #include <errno.h>
 #include <sys/wait.h>
@@ -1017,6 +1022,48 @@ bool Desktop::isUIOnSessionShutdownAllowed()
         ::get();
 }
 
+namespace {
+
+bool crashReportInfoExists()
+{
+#if HAVE_FEATURE_BREAKPAD
+    std::string path = CrashReporter::getIniFileName();
+    std::ifstream aFile(path);
+    while (!aFile.eof())
+    {
+        std::string line;
+        std::getline(aFile, line);
+        int sep = line.find('=');
+        if (sep >= 0)
+        {
+            std::string key = line.substr(0, sep);
+            std::string value = line.substr(sep + 1);
+            if (key == "DumpFile")
+                return true;
+        }
+    }
+#endif
+    return false;
+}
+
+void handleCrashReport()
+{
+    static const char SERVICENAME_CRASHREPORT[] = "com.sun.star.comp.svx.CrashReportUI";
+
+    css::uno::Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
+
+    Reference< css::frame::XSynchronousDispatch > xRecoveryUI(
+        xContext->getServiceManager()->createInstanceWithContext(SERVICENAME_CRASHREPORT, xContext),
+        css::uno::UNO_QUERY_THROW);
+
+    Reference< css::util::XURLTransformer > xURLParser =
+        css::util::URLTransformer::create(::comphelper::getProcessComponentContext());
+
+    css::util::URL aURL;
+    css::uno::Any aRet = xRecoveryUI->dispatchWithReturnValue(aURL, css::uno::Sequence< css::beans::PropertyValue >());
+    bool bRet = false;
+    aRet >>= bRet;
+}
 
 /** @short  check if recovery must be started or not.
 
@@ -1038,7 +1085,7 @@ void impl_checkRecoveryState(bool& bCrashed           ,
                              bool& bRecoveryDataExists,
                              bool& bSessionDataExists )
 {
-    bCrashed = officecfg::Office::Recovery::RecoveryInfo::Crashed::get();
+    bCrashed = officecfg::Office::Recovery::RecoveryInfo::Crashed::get() || crashReportInfoExists();
     bool elements = officecfg::Office::Recovery::RecoveryList::get()->
         hasElements();
     bool session
@@ -1085,6 +1132,8 @@ bool impl_callRecoveryUI(bool bEmergencySave     ,
     return !bEmergencySave || bRet;
 }
 
+}
+
 /*
  * Save all open documents so they will be reopened
  * the next time the application is started
@@ -1092,7 +1141,6 @@ bool impl_callRecoveryUI(bool bEmergencySave     ,
  * returns sal_True if at least one document could be saved...
  *
  */
-
 bool Desktop::SaveTasks()
 {
     return impl_callRecoveryUI(
@@ -2216,6 +2264,11 @@ void Desktop::OpenClients()
     // need some time, where the user won't see any results and wait for finishing the office startup...
     bool bAllowRecoveryAndSessionManagement = ( !rArgs.IsNoRestore() ) && ( !rArgs.IsHeadless()  );
 
+#if HAVE_FEATURE_BREAKPAD
+    if (crashReportInfoExists())
+        handleCrashReport();
+#endif
+
     if ( ! bAllowRecoveryAndSessionManagement )
     {
         try
@@ -2291,6 +2344,7 @@ void Desktop::OpenClients()
         }
     }
 
+    CrashReporter::writeCommonInfo();
     OfficeIPCThread::EnableRequests();
 
     ProcessDocumentsRequest aRequest(rArgs.getCwdUrl());
diff --git a/desktop/source/app/crashreport.cxx b/desktop/source/app/crashreport.cxx
index 0b5b98a..967097c 100644
--- a/desktop/source/app/crashreport.cxx
+++ b/desktop/source/app/crashreport.cxx
@@ -9,6 +9,8 @@
 
 #include <desktop/crashreport.hxx>
 
+#include <config_version.h>
+
 #include <string>
 #include <fstream>
 
@@ -23,7 +25,18 @@ void CrashReporter::AddKeyValue(const OUString& rKey, const OUString& rValue)
     ini_file << rtl::OUStringToOString(rValue, RTL_TEXTENCODING_UTF8).getStr() << "\n";
 }
 
-const char* CrashReporter::getIniFileName()
+void CrashReporter::writeCommonInfo()
+{
+    // limit the amount of code that needs to be executed before the crash reporting
+    std::string ini_path = CrashReporter::getIniFileName();
+    std::ofstream minidump_file(ini_path, std::ios_base::trunc);
+    minidump_file << "ProductName=LibreOffice\n";
+    minidump_file << "Version=" << LIBO_VERSION_DOTTED << "\n";
+    minidump_file << "URL=" << "http://127.0.0.1:8000/submit" << "\n";
+    minidump_file.close();
+}
+
+std::string CrashReporter::getIniFileName()
 {
     // TODO: we need a generic solution for the location
     return "/tmp/dump.ini";
diff --git a/desktop/source/app/sofficemain.cxx b/desktop/source/app/sofficemain.cxx
index 3af06c5..84ea2c8 100644
--- a/desktop/source/app/sofficemain.cxx
+++ b/desktop/source/app/sofficemain.cxx
@@ -18,8 +18,8 @@
  */
 
 #include <sal/config.h>
-#include <config_version.h>
 #include <config_folders.h>
+#include <config_features.h>
 
 #include <desktop/dllapi.h>
 
@@ -64,14 +64,6 @@
 
 #if HAVE_FEATURE_BREAKPAD
 
-OString getLibDir()
-{
-    OUString aOriginal = "$BRAND_BASE_DIR/" LIBO_LIBEXEC_FOLDER;
-    rtl::Bootstrap::expandMacros(aOriginal);
-
-    return rtl::OUStringToOString(aOriginal, RTL_TEXTENCODING_UTF8);
-}
-
 #if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
 static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* /*context*/, bool succeeded)
 {
@@ -81,9 +73,6 @@ static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,
     minidump_file.close();
     // send the minidump to the server (not yet implemented)
     SAL_WARN("crashreport", "minidump generated: " << descriptor.path());
-    OString aCommand = getLibDir().copy(7) + "/minidump_upload " + ini_path.c_str();
-    int retVal = std::system(aCommand.getStr());
-    SAL_WARN_IF(retVal != 0, "crashreport", "Failed to upload minidump. Error Code: " << retVal);
     return succeeded;
 }
 #endif
@@ -92,14 +81,6 @@ static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,
 extern "C" int DESKTOP_DLLPUBLIC soffice_main()
 {
 #if HAVE_FEATURE_BREAKPAD
-    //limit the amount of code that needs to be executed before the crash reporting
-
-    std::string ini_path = CrashReporter::getIniFileName();
-    std::ofstream minidump_file(ini_path, std::ios_base::trunc);
-    minidump_file << "ProductName=LibreOffice\n";
-    minidump_file << "Version=" << LIBO_VERSION_DOTTED << "\n";
-    minidump_file << "URL=" << "http://127.0.0.1:8000/submit" << "\n";
-    minidump_file.close();
 
 #if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
     google_breakpad::MinidumpDescriptor descriptor("/tmp");
diff --git a/include/desktop/crashreport.hxx b/include/desktop/crashreport.hxx
index 18aaa2e..cdbcbe2 100644
--- a/include/desktop/crashreport.hxx
+++ b/include/desktop/crashreport.hxx
@@ -16,6 +16,7 @@
 #include <osl/mutex.hxx>
 
 #include <map>
+#include <string>
 
 /**
  * Provides access to the crash reporter service.
@@ -30,7 +31,9 @@ class CRASHREPORT_DLLPUBLIC CrashReporter
 public:
     static void AddKeyValue(const OUString& rKey, const OUString& rValue);
 
-    static const char* getIniFileName();
+    static std::string getIniFileName();
+
+    static void writeCommonInfo();
 
 private:
 
diff --git a/svx/Library_svx.mk b/svx/Library_svx.mk
index c26c036..32a9ec5 100644
--- a/svx/Library_svx.mk
+++ b/svx/Library_svx.mk
@@ -46,6 +46,7 @@ $(eval $(call gb_Library_use_libraries,svx,\
     comphelper \
     cppuhelper \
     cppu \
+    crashreport \
     $(call gb_Helper_optional,DBCONNECTIVITY, \
         dbtools) \
     drawinglayer \
@@ -108,6 +109,8 @@ $(eval $(call gb_Library_add_exception_objects,svx,\
     svx/source/dialog/_contdlg \
     svx/source/dialog/contwnd \
     svx/source/dialog/compressgraphicdialog \
+    svx/source/dialog/crashreportdlg \
+    svx/source/dialog/crashreportui \
     svx/source/dialog/ctredlin \
     svx/source/dialog/databaseregistrationui \
     svx/source/dialog/dialcontrol \
diff --git a/svx/UIConfig_svx.mk b/svx/UIConfig_svx.mk
index 650ecf9..39df1db 100644
--- a/svx/UIConfig_svx.mk
+++ b/svx/UIConfig_svx.mk
@@ -22,6 +22,7 @@ $(eval $(call gb_UIConfig_add_uifiles,svx,\
 	svx/uiconfig/ui/chinesedictionary \
 	svx/uiconfig/ui/colorwindow \
 	svx/uiconfig/ui/compressgraphicdialog \
+	svx/uiconfig/ui/crashreportdlg \
 	svx/uiconfig/ui/datanavigator \
 	svx/uiconfig/ui/deleteheaderdialog \
 	svx/uiconfig/ui/deletefooterdialog \
diff --git a/svx/source/dialog/crashreportdlg.cxx b/svx/source/dialog/crashreportdlg.cxx
new file mode 100644
index 0000000..74066a8
--- /dev/null
+++ b/svx/source/dialog/crashreportdlg.cxx
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "crashreportdlg.hxx"
+
+#include <config_folders.h>
+
+#include <rtl/bootstrap.hxx>
+#include <desktop/crashreport.hxx>
+
+CrashReportDialog::CrashReportDialog(vcl::Window* pParent):
+    Dialog(pParent, "CrashReportDialog",
+            "svx/ui/crashreportdlg.ui")
+{
+    get(mpBtnSend, "btn_send");
+    get(mpBtnCancel, "btn_cancel");
+
+    mpBtnSend->SetClickHdl(LINK(this, CrashReportDialog, BtnHdl));
+    mpBtnCancel->SetClickHdl(LINK(this, CrashReportDialog, BtnHdl));
+}
+
+CrashReportDialog::~CrashReportDialog()
+{
+    disposeOnce();
+}
+
+void CrashReportDialog::dispose()
+{
+    mpBtnSend.clear();
+    mpBtnCancel.clear();
+
+    Dialog::dispose();
+}
+
+namespace {
+
+OString getLibDir()
+{
+    OUString aOriginal = "$BRAND_BASE_DIR/" LIBO_LIBEXEC_FOLDER;
+    rtl::Bootstrap::expandMacros(aOriginal);
+
+    return rtl::OUStringToOString(aOriginal, RTL_TEXTENCODING_UTF8);
+}
+
+}
+
+IMPL_LINK_TYPED(CrashReportDialog, BtnHdl, Button*, pBtn, void)
+{
+    if (pBtn == mpBtnSend.get())
+    {
+        std::string ini_path = CrashReporter::getIniFileName();
+        OString aCommand = getLibDir().copy(7) + "/minidump_upload " + ini_path.c_str();
+        int retVal = std::system(aCommand.getStr());
+        SAL_WARN_IF(retVal != 0, "crashreport", "Failed to upload minidump. Error Code: " << retVal);
+        Close();
+    }
+    else if (pBtn == mpBtnCancel.get())
+    {
+        Close();
+    }
+    else
+    {
+        assert(false);
+    }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/dialog/crashreportdlg.hxx b/svx/source/dialog/crashreportdlg.hxx
new file mode 100644
index 0000000..e6041f8
--- /dev/null
+++ b/svx/source/dialog/crashreportdlg.hxx
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_SVX_SOURCE_DIALOG_CRASHREPORTDLG_HXX
+#define INCLUDED_SVX_SOURCE_DIALOG_CRASHREPORTDLG_HXX
+
+#include <vcl/dialog.hxx>
+#include <vcl/button.hxx>
+
+class CrashReportDialog : public Dialog
+{
+public:
+
+    CrashReportDialog(vcl::Window* pParent);
+
+    ~CrashReportDialog();
+
+    virtual void dispose() override;
+
+private:
+
+    VclPtr<Button> mpBtnSend;
+    VclPtr<Button> mpBtnCancel;
+
+    DECL_LINK_TYPED(BtnHdl, Button*, void);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/dialog/crashreportui.cxx b/svx/source/dialog/crashreportui.cxx
new file mode 100644
index 0000000..94b1a68
--- /dev/null
+++ b/svx/source/dialog/crashreportui.cxx
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/frame/XSynchronousDispatch.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <comphelper/processfactory.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <vcl/svapp.hxx>
+
+#include "crashreportdlg.hxx"
+
+namespace {
+
+class CrashReportUI : public ::cppu::WeakImplHelper< css::lang::XServiceInfo        ,
+                                                   css::frame::XSynchronousDispatch > // => XDispatch!
+{
+public:
+    CrashReportUI(const css::uno::Reference< css::uno::XComponentContext >& xContext);
+    virtual ~CrashReportUI();
+
+    // css.lang.XServiceInfo
+
+    virtual OUString SAL_CALL getImplementationName()
+        throw(css::uno::RuntimeException, std::exception) override;
+
+    virtual sal_Bool SAL_CALL supportsService(const OUString& sServiceName)
+        throw(css::uno::RuntimeException, std::exception) override;
+
+    virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames()
+        throw(css::uno::RuntimeException, std::exception) override;
+
+
+    virtual css::uno::Any SAL_CALL dispatchWithReturnValue(const css::util::URL& aURL,
+                                        const css::uno::Sequence< css::beans::PropertyValue >& lArguments )
+        throw(css::uno::RuntimeException, std::exception) override;
+
+private:
+    css::uno::Reference< css::uno::XComponentContext > mxContext;
+};
+
+CrashReportUI::CrashReportUI(const css::uno::Reference<css::uno::XComponentContext>& xContext):
+    mxContext(xContext)
+{
+
+}
+
+CrashReportUI::~CrashReportUI()
+{
+}
+
+OUString SAL_CALL CrashReportUI::getImplementationName()
+    throw(css::uno::RuntimeException, std::exception)
+{
+    return OUString("com.sun.star.comp.svx.CrashReportUI");
+}
+
+sal_Bool SAL_CALL CrashReportUI::supportsService(const OUString& sServiceName)
+    throw(css::uno::RuntimeException, std::exception)
+{
+    return cppu::supportsService(this, sServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL CrashReportUI::getSupportedServiceNames()
+    throw(css::uno::RuntimeException, std::exception)
+{
+    css::uno::Sequence< OUString > lServiceNames { "com.sun.star.dialog.CrashReportUI" };
+    return lServiceNames;
+}
+
+css::uno::Any SAL_CALL CrashReportUI::dispatchWithReturnValue(const css::util::URL& aURL,
+                                                   const css::uno::Sequence< css::beans::PropertyValue >& )
+    throw(css::uno::RuntimeException, std::exception)
+{
+    SolarMutexGuard aGuard;
+    css::uno::Any aRet;
+    ScopedVclPtrInstance<CrashReportDialog> xDialog(new CrashReportDialog(nullptr));
+    xDialog->Execute();
+    return aRet;
+}
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
+com_sun_star_comp_svx_CrashReportUI_get_implementation(
+    css::uno::XComponentContext *context,
+    css::uno::Sequence<css::uno::Any> const &)
+{
+    return cppu::acquire(new CrashReportUI(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/util/svx.component b/svx/util/svx.component
index 3f0e38e..31c8005 100644
--- a/svx/util/svx.component
+++ b/svx/util/svx.component
@@ -32,6 +32,10 @@
       constructor="com_sun_star_comp_svx_RecoveryUI_get_implementation">
     <service name="com.sun.star.dialog.RecoveryUI"/>
   </implementation>
+  <implementation name="com.sun.star.comp.svx.CrashReportUI"
+      constructor="com_sun_star_comp_svx_CrashReportUI_get_implementation">
+    <service name="com.sun.star.dialog.CrashReportUI"/>
+  </implementation>
   <implementation name="com.sun.star.drawing.EnhancedCustomShapeEngine"
       constructor="com_sun_star_drawing_EnhancedCustomShapeEngine_get_implementation">
     <service name="com.sun.star.drawing.CustomShapeEngine"/>
commit 0328732f70931041cf3c1ee01c2ef91c09734324
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed Jan 6 13:57:52 2016 +0100

    don't push, crash for crash reporting
    
    Change-Id: I3fff25a84a93edaabb64624a19fea4159b68555b

diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx
index 21eb4ed..5b7e9f6 100644
--- a/sc/source/ui/docshell/docsh.cxx
+++ b/sc/source/ui/docshell/docsh.cxx
@@ -426,10 +426,17 @@ void processDataStream( ScDocShell& rShell, const sc::ImportPostProcessData& rDa
     rMgr.setDataStream(pStrm);
 }
 
+void crash()
+{
+    int* a = 0;
+    *a = 3;
+}
+
 }
 
 bool ScDocShell::LoadXML( SfxMedium* pLoadMedium, const css::uno::Reference< css::embed::XStorage >& xStor )
 {
+    crash();
     LoadMediumGuard aLoadGuard(&aDocument);
 
     //  MacroCallMode is no longer needed, state is kept in SfxObjectShell now
commit b6e24a7f261424818d32a189f715639f01087bac
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed Jan 6 13:57:24 2016 +0100

    better error reporting for crash uploader
    
    Change-Id: I6a2b5bd72187de2b646ec0d6fdb5fe20f5d6a2d8

diff --git a/desktop/source/minidump/minidump_upload.cxx b/desktop/source/minidump/minidump_upload.cxx
index e49eab0..9b1160d 100644
--- a/desktop/source/minidump/minidump_upload.cxx
+++ b/desktop/source/minidump/minidump_upload.cxx
@@ -131,11 +131,7 @@ bool uploadContent(std::map<std::string, std::string>& parameters)
                 url.c_str(),
                 curl_easy_strerror(cc));
 #endif
-    /*
-     * TODO
-    if (error_description != NULL)
-        *error_description = curl_easy_strerror(cc);
-    */
+    const char* error_description = curl_easy_strerror(cc);
 
     if (formpost != NULL)
     {
@@ -146,7 +142,7 @@ bool uploadContent(std::map<std::string, std::string>& parameters)
         curl_slist_free_all(headerlist);
     }
 
-    std::cerr << response_body << std::endl;
+    std::cerr << response_body << " " << error_description << std::endl;
 
 
     if( CURLE_OK != cc )
commit 5627aeb0c4c6839c7cc965bedd862fa9dbbf2867
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed Jan 6 13:56:47 2016 +0100

    store the URL in the crash ini file
    
    Change-Id: I1b5f29f864d01c238f2e21de87dde8005236f332

diff --git a/desktop/source/app/sofficemain.cxx b/desktop/source/app/sofficemain.cxx
index 7a3515b..3af06c5 100644
--- a/desktop/source/app/sofficemain.cxx
+++ b/desktop/source/app/sofficemain.cxx
@@ -98,6 +98,7 @@ extern "C" int DESKTOP_DLLPUBLIC soffice_main()
     std::ofstream minidump_file(ini_path, std::ios_base::trunc);
     minidump_file << "ProductName=LibreOffice\n";
     minidump_file << "Version=" << LIBO_VERSION_DOTTED << "\n";
+    minidump_file << "URL=" << "http://127.0.0.1:8000/submit" << "\n";
     minidump_file.close();
 
 #if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
diff --git a/desktop/source/minidump/minidump_upload.cxx b/desktop/source/minidump/minidump_upload.cxx
index 220286a..e49eab0 100644
--- a/desktop/source/minidump/minidump_upload.cxx
+++ b/desktop/source/minidump/minidump_upload.cxx
@@ -68,15 +68,16 @@ bool uploadContent(std::map<std::string, std::string>& parameters)
     if (!curl)
         return false;
 
-    std::string proxy, proxy_user_pwd, ca_certificate_file, file;
-
-    std::string url = "http://libreofficecrash.org/submit";
+    std::string proxy, proxy_user_pwd, ca_certificate_file, file, url;
 
     getProperty("Proxy", proxy, parameters);
     getProperty("ProxyUserPW", proxy_user_pwd, parameters);
     getProperty("CAFile", ca_certificate_file, parameters);
 
     getProperty("DumpFile", file, parameters);
+    getProperty("URL", file, parameters);
+    if (url.empty())
+        return false;
 
     curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
     curl_easy_setopt(curl, CURLOPT_USERAGENT, kUserAgent);
commit fa1373a00faf87884cb54b36be842311ff742d26
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Fri Dec 18 23:08:02 2015 +0100

    add script to upload symbols to crash reporting site
    
    Change-Id: I85f6c0757550192443909f08331d65c21c7f4350

diff --git a/bin/upload_symbols.py b/bin/upload_symbols.py
new file mode 100644
index 0000000..8d99ab9
--- /dev/null
+++ b/bin/upload_symbols.py
@@ -0,0 +1,24 @@
+# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+import requests, sys
+
+def main():
+    if len(sys.argv) != 3:
+        print("Invalid number of parameters")
+        sys.exit(1)
+
+    url = "http://localhost:8000/upload/"
+    files = {'symbols': open(sys.argv[1], 'rb'), 'comment':sys.argv[2]}
+    comment = {'comment': sys.argv[2]}
+    r = requests.post(url, files = files, data = {"comment":"whatever", "tempt":"tempt"})
+    print(r)
+
+if __name__ == "__main__":
+    main()
+
+# vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit bfc430a341d8155cedb3772e32b927b1010d737e
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Tue Dec 15 14:01:27 2015 +0100

    add script to generate symbols
    
    Change-Id: Icae707709307bc86360676692e55780b9ec89639

diff --git a/bin/symbolstore.py b/bin/symbolstore.py
new file mode 100755
index 0000000..941f448
--- /dev/null
+++ b/bin/symbolstore.py
@@ -0,0 +1,644 @@
+#!/usr/bin/env python
+# ***** 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.org code.
+#
+# The Initial Developer of the Original Code is
+# The Mozilla Foundation
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Ted Mielczarek <ted.mielczarek at gmail.com>
+# Ben Turner <mozilla at songbirdnest.com>
+#
+# 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 *****
+#
+# Usage: symbolstore.py <params> <dump_syms path> <symbol store path>
+#                                <debug info files or dirs>
+#   Runs dump_syms on each debug info file specified on the command line,
+#   then places the resulting symbol file in the proper directory
+#   structure in the symbol store path.  Accepts multiple files
+#   on the command line, so can be called as part of a pipe using
+#   find <dir> | xargs symbolstore.pl <dump_syms> <storepath>
+#   But really, you might just want to pass it <dir>.
+#
+#   Parameters accepted:
+#     -c           : Copy debug info files to the same directory structure
+#                    as sym files
+#     -a "<archs>" : Run dump_syms -a <arch> for each space separated
+#                    cpu architecture in <archs> (only on OS X)
+#     -s <srcdir>  : Use <srcdir> as the top source directory to
+#                    generate relative filenames.
+
+import sys
+import os
+import re
+import shutil
+from optparse import OptionParser
+
+# Utility classes
+
+class VCSFileInfo:
+    """ A base class for version-controlled file information. Ensures that the
+        following attributes are generated only once (successfully):
+
+            self.root
+            self.clean_root
+            self.revision
+            self.filename
+
+        The attributes are generated by a single call to the GetRoot,
+        GetRevision, and GetFilename methods. Those methods are explicitly not
+        implemented here and must be implemented in derived classes. """
+
+    def __init__(self, file):
+        if not file:
+            raise ValueError
+        self.file = file
+
+    def __getattr__(self, name):
+        """ __getattr__ is only called for attributes that are not set on self,
+            so setting self.[attr] will prevent future calls to the GetRoot,
+            GetRevision, and GetFilename methods. We don't set the values on
+            failure on the off chance that a future call might succeed. """
+
+        if name == "root":
+            root = self.GetRoot()
+            if root:
+                self.root = root
+            return root
+
+        elif name == "clean_root":
+            clean_root = self.GetCleanRoot()
+            if clean_root:
+                self.clean_root = clean_root
+            return clean_root
+
+        elif name == "revision":
+            revision = self.GetRevision()
+            if revision:
+                self.revision = revision
+            return revision
+
+        elif name == "filename":
+            filename = self.GetFilename()
+            if filename:
+                self.filename = filename
+            return filename
+
+        raise AttributeError
+
+    def GetRoot(self):
+        """ This method should return the unmodified root for the file or 'None'
+            on failure. """
+        raise NotImplementedError
+
+    def GetCleanRoot(self):
+        """ This method should return the repository root for the file or 'None'
+            on failure. """
+        raise NotImplementedErrors
+
+    def GetRevision(self):
+        """ This method should return the revision number for the file or 'None'
+            on failure. """
+        raise NotImplementedError
+
+    def GetFilename(self):
+        """ This method should return the repository-specific filename for the
+            file or 'None' on failure. """
+        raise NotImplementedError
+
+class CVSFileInfo(VCSFileInfo):
+    """ A class to maintiain version information for files in a CVS repository.
+        Derived from VCSFileInfo. """
+
+    def __init__(self, file, srcdir):
+        VCSFileInfo.__init__(self, file)
+        self.srcdir = srcdir
+
+    def GetRoot(self):
+        (path, filename) = os.path.split(self.file)
+        root = os.path.join(path, "CVS", "Root")
+        if not os.path.isfile(root):
+            return None
+        f = open(root, "r")
+        root_name = f.readline().strip()
+        f.close()
+        if root_name:
+            return root_name
+        print >> sys.stderr, "Failed to get CVS Root for %s" % filename
+        return None
+
+    def GetCleanRoot(self):
+        parts = self.root.split('@')
+        if len(parts) > 1:
+            # we don't want the extra colon
+            return parts[1].replace(":","")
+        print >> sys.stderr, "Failed to get CVS Root for %s" % filename
+        return None
+
+    def GetRevision(self):
+        (path, filename) = os.path.split(self.file)
+        entries = os.path.join(path, "CVS", "Entries")
+        if not os.path.isfile(entries):
+            return None
+        f = open(entries, "r")
+        for line in f:
+            parts = line.split("/")
+            if len(parts) > 1 and parts[1] == filename:
+                return parts[2]
+        print >> sys.stderr, "Failed to get CVS Revision for %s" % filename
+        return None
+
+    def GetFilename(self):
+        file = self.file
+        if self.revision and self.clean_root:
+            if self.srcdir:
+                # strip the base path off
+                # but we actually want the last dir in srcdir
+                file = os.path.normpath(file)
+                # the lower() is to handle win32+vc8, where
+                # the source filenames come out all lowercase,
+                # but the srcdir can be mixed case
+                if file.lower().startswith(self.srcdir.lower()):
+                    file = file[len(self.srcdir):]
+                (head, tail) = os.path.split(self.srcdir)
+                if tail == "":
+                    tail = os.path.basename(head)
+                file = tail + file
+            return "cvs:%s:%s:%s" % (self.clean_root, file, self.revision)
+        return file
+
+class SVNFileInfo(VCSFileInfo):
+    url = None
+    repo = None
+    svndata = {}
+
+    # This regex separates protocol and optional username/password from a url.
+    # For instance, all the following urls will be transformed into
+    # 'foo.com/bar':
+    #
+    #   http://foo.com/bar
+    #   svn+ssh://user@foo.com/bar
+    #   svn+ssh://user:pass@foo.com/bar
+    #
+    rootRegex = re.compile(r'^\S+?:/+(?:[^\s/]*@)?(\S+)$')
+
+    def __init__(self, file):
+        """ We only want to run subversion's info tool once so pull all the data
+            here. """
+
+        VCSFileInfo.__init__(self, file)
+
+        if os.path.isfile(file):
+            command = os.popen("svn info %s" % file, "r")
+            for line in command:
+                # The last line of the output is usually '\n'
+                if line.strip() == '':
+                    continue
+                # Split into a key/value pair on the first colon
+                key, value = line.split(':', 1)
+                if key in ["Repository Root", "Revision", "URL"]:
+                    self.svndata[key] = value.strip()
+
+            exitStatus = command.close()
+            if exitStatus:
+              print >> sys.stderr, "Failed to get SVN info for %s" % file
+
+    def GetRoot(self):
+        key = "Repository Root"
+        if key in self.svndata:
+            match = self.rootRegex.match(self.svndata[key])
+            if match:
+                return match.group(1)
+        print >> sys.stderr, "Failed to get SVN Root for %s" % self.file
+        return None
+
+    # File bug to get this teased out from the current GetRoot, this is temporary
+    def GetCleanRoot(self):
+        return self.root
+
+    def GetRevision(self):
+        key = "Revision"
+        if key in self.svndata:
+            return self.svndata[key]
+        print >> sys.stderr, "Failed to get SVN Revision for %s" % self.file
+        return None
+
+    def GetFilename(self):
+        if self.root and self.revision:
+            if "URL" in self.svndata and "Repository Root" in self.svndata:
+                url, repo = self.svndata["URL"], self.svndata["Repository Root"]
+                file = url[len(repo) + 1:]
+            return "svn:%s:%s:%s" % (self.root, file, self.revision)
+        print >> sys.stderr, "Failed to get SVN Filename for %s" % self.file
+        return self.file
+
+# Utility functions
+
+# A cache of files for which VCS info has already been determined. Used to
+# prevent extra filesystem activity or process launching.
+vcsFileInfoCache = {}
+
+def GetVCSFilename(file, srcdir):
+    """Given a full path to a file, and the top source directory,
+    look for version control information about this file, and return
+    a tuple containing
+    1) a specially formatted filename that contains the VCS type,
+    VCS location, relative filename, and revision number, formatted like:
+    vcs:vcs location:filename:revision
+    For example:
+    cvs:cvs.mozilla.org/cvsroot:mozilla/browser/app/nsBrowserApp.cpp:1.36
+    2) the unmodified root information if it exists"""
+    (path, filename) = os.path.split(file)
+    if path == '' or filename == '':
+        return (file, None)
+
+    fileInfo = None
+    root = ''
+    if file in vcsFileInfoCache:
+        # Already cached this info, use it.
+        fileInfo = vcsFileInfoCache[file]
+    else:
+        if os.path.isdir(os.path.join(path, "CVS")):
+            fileInfo = CVSFileInfo(file, srcdir)
+            if fileInfo:
+               root = fileInfo.root
+        elif os.path.isdir(os.path.join(path, ".svn")) or \
+             os.path.isdir(os.path.join(path, "_svn")):
+            fileInfo = SVNFileInfo(file);
+        vcsFileInfoCache[file] = fileInfo
+
+    if fileInfo:
+        file = fileInfo.filename
+
+    # we want forward slashes on win32 paths
+    return (file.replace("\\", "/"), root)
+
+def GetPlatformSpecificDumper(**kwargs):
+    """This function simply returns a instance of a subclass of Dumper
+    that is appropriate for the current platform."""
+    return {'win32': Dumper_Win32,
+            'cygwin': Dumper_Win32,
+            'linux2': Dumper_Linux,
+            'sunos5': Dumper_Solaris,
+            'darwin': Dumper_Mac}[sys.platform](**kwargs)
+
+def SourceIndex(fileStream, outputPath, cvs_root):
+    """Takes a list of files, writes info to a data block in a .stream file"""
+    # Creates a .pdb.stream file in the mozilla\objdir to be used for source indexing
+    # Create the srcsrv data block that indexes the pdb file
+    result = True
+    pdbStreamFile = open(outputPath, "w")
+    pdbStreamFile.write('''SRCSRV: ini ------------------------------------------------\r\nVERSION=1\r\nSRCSRV: variables ------------------------------------------\r\nCVS_EXTRACT_CMD=%fnchdir%(%targ%)cvs.exe -d %fnvar%(%var2%) checkout -r %var4% -d %var4% -N %var3%\r\nMYSERVER=''')
+    pdbStreamFile.write(cvs_root)
+    pdbStreamFile.write('''\r\nSRCSRVTRG=%targ%\%var4%\%fnbksl%(%var3%)\r\nSRCSRVCMD=%CVS_EXTRACT_CMD%\r\nSRCSRV: source files ---------------------------------------\r\n''')
+    pdbStreamFile.write(fileStream) # can't do string interpolation because the source server also uses this and so there are % in the above
+    pdbStreamFile.write("SRCSRV: end ------------------------------------------------\r\n\n")
+    pdbStreamFile.close()
+    return result
+
+class Dumper:
+    """This class can dump symbols from a file with debug info, and
+    store the output in a directory structure that is valid for use as
+    a Breakpad symbol server.  Requires a path to a dump_syms binary--
+    |dump_syms| and a directory to store symbols in--|symbol_path|.
+    Optionally takes a list of processor architectures to process from
+    each debug file--|archs|, the full path to the top source
+    directory--|srcdir|, for generating relative source file names,
+    and an option to copy debug info files alongside the dumped
+    symbol files--|copy_debug|, mostly useful for creating a
+    Microsoft Symbol Server from the resulting output.
+
+    You don't want to use this directly if you intend to call
+    ProcessDir.  Instead, call GetPlatformSpecificDumper to
+    get an instance of a subclass."""
+    def __init__(self, dump_syms, symbol_path,
+                 archs=None, srcdir=None, copy_debug=False, vcsinfo=False, srcsrv=False):
+        # popen likes absolute paths, at least on windows
+        self.dump_syms = os.path.abspath(dump_syms)
+        self.symbol_path = symbol_path
+        if archs is None:
+            # makes the loop logic simpler
+            self.archs = ['']
+        else:
+            self.archs = ['-a %s' % a for a in archs.split()]
+        if srcdir is not None:
+            self.srcdir = os.path.normpath(srcdir)
+        else:
+            self.srcdir = None
+        self.copy_debug = copy_debug
+        self.vcsinfo = vcsinfo
+        self.srcsrv = srcsrv
+
+    # subclasses override this
+    def ShouldProcess(self, file):
+        return False
+
+    def RunFileCommand(self, file):
+        """Utility function, returns the output of file(1)"""
+        try:
+            # we use -L to read the targets of symlinks,
+            # and -b to print just the content, not the filename
+            return os.popen("file -Lb " + file).read()
+        except:
+            return ""
+
+    # This is a no-op except on Win32
+    def FixFilenameCase(self, file):
+        return file
+
+    # This is a no-op except on Win32
+    def SourceServerIndexing(self, debug_file, guid, sourceFileStream, cvs_root):
+        return ""
+
+    # subclasses override this if they want to support this
+    def CopyDebug(self, file, debug_file, guid):
+        pass
+
+    def Process(self, file_or_dir):
+        "Process a file or all the (valid) files in a directory."
+        if os.path.isdir(file_or_dir):
+            return self.ProcessDir(file_or_dir)
+        elif os.path.isfile(file_or_dir):
+            return self.ProcessFile(file_or_dir)
+        # maybe it doesn't exist?
+        return False
+
+    def ProcessDir(self, dir):
+        """Process all the valid files in this directory.  Valid files
+        are determined by calling ShouldProcess."""
+        result = True
+        for root, dirs, files in os.walk(dir):
+            for f in files:
+                fullpath = os.path.join(root, f)
+                if self.ShouldProcess(fullpath):
+                    if not self.ProcessFile(fullpath):
+                        result = False
+        return result
+
+    def ProcessFile(self, file):
+        """Dump symbols from this file into a symbol file, stored
+        in the proper directory structure in  |symbol_path|."""
+        result = False
+        sourceFileStream = ''
+        # tries to get cvsroot from the .mozconfig first - if it's not set
+        # the tinderbox cvs_path will be assigned further down
+        cvs_root = os.environ.get("SRCSRV_ROOT")
+        for arch in self.archs:
+            try:
+                cmd = os.popen("%s %s %s" % (self.dump_syms, arch, file), "r")
+                module_line = cmd.next()
+                if module_line.startswith("MODULE"):
+                    # MODULE os cpu guid debug_file
+                    (guid, debug_file) = (module_line.split())[3:5]
+                    # strip off .pdb extensions, and append .sym
+                    sym_file = re.sub("\.pdb$", "", debug_file) + ".sym"
+                    # we do want forward slashes here
+                    rel_path = os.path.join(debug_file,
+                                            guid,
+                                            sym_file).replace("\\", "/")
+                    full_path = os.path.normpath(os.path.join(self.symbol_path,
+                                                              rel_path))
+                    try:
+                        os.makedirs(os.path.dirname(full_path))
+                    except OSError: # already exists
+                        pass
+                    f = open(full_path, "w")
+                    f.write(module_line)
+                    # now process the rest of the output
+                    for line in cmd:
+                        if line.startswith("FILE"):
+                            # FILE index filename
+                            (x, index, filename) = line.split(None, 2)
+                            if sys.platform == "sunos5":
+                                start = filename.find(self.srcdir)
+                                if start == -1:
+                                    start = 0
+                                filename = filename[start:]
+                            filename = self.FixFilenameCase(filename.rstrip())
+                            sourcepath = filename
+                            if self.vcsinfo:
+                                (filename, rootname) = GetVCSFilename(filename, self.srcdir)
+                                # sets cvs_root in case the loop through files were to end on an empty rootname
+                                if cvs_root is None:
+                                  if rootname:
+                                     cvs_root = rootname
+                            # gather up files with cvs for indexing   
+                            if filename.startswith("cvs"):
+                                (ver, checkout, source_file, revision) = filename.split(":", 3)
+                                sourceFileStream += sourcepath + "*MYSERVER*" + source_file + '*' + revision + "\r\n"
+                            f.write("FILE %s %s\n" % (index, filename))
+                        else:
+                            # pass through all other lines unchanged
+                            f.write(line)
+                    f.close()
+                    cmd.close()
+                    # we output relative paths so callers can get a list of what
+                    # was generated
+                    print rel_path
+                    if self.copy_debug:
+                        self.CopyDebug(file, debug_file, guid)
+                    if self.srcsrv:
+                        # Call on SourceServerIndexing
+                        result = self.SourceServerIndexing(debug_file, guid, sourceFileStream, cvs_root)
+                    result = True
+            except StopIteration:
+                pass
+            except:
+                print >> sys.stderr, "Unexpected error: ", sys.exc_info()[0]
+                raise
+        return result
+
+# Platform-specific subclasses.  For the most part, these just have
+# logic to determine what files to extract symbols from.
+
+class Dumper_Win32(Dumper):
+    fixedFilenameCaseCache = {}
+
+    def ShouldProcess(self, file):
+        """This function will allow processing of pdb files that have dll
+        or exe files with the same base name next to them."""
+        if file.endswith(".pdb"):
+            (path,ext) = os.path.splitext(file)
+            if os.path.isfile(path + ".exe") or os.path.isfile(path + ".dll"):
+                return True
+        return False
+
+    def FixFilenameCase(self, file):
+        """Recent versions of Visual C++ put filenames into
+        PDB files as all lowercase.  If the file exists
+        on the local filesystem, fix it."""
+
+        # Use a cached version if we have one.
+        if file in self.fixedFilenameCaseCache:
+            return self.fixedFilenameCaseCache[file]
+
+        result = file
+
+        (path, filename) = os.path.split(file)
+        if os.path.isdir(path):
+            lc_filename = filename.lower()
+            for f in os.listdir(path):
+                if f.lower() == lc_filename:
+                    result = os.path.join(path, f)
+                    break
+
+        # Cache the corrected version to avoid future filesystem hits.
+        self.fixedFilenameCaseCache[file] = result
+        return result
+
+    def CopyDebug(self, file, debug_file, guid):
+        rel_path = os.path.join(debug_file,
+                                guid,
+                                debug_file).replace("\\", "/")
+        print rel_path
+        full_path = os.path.normpath(os.path.join(self.symbol_path,
+                                                  rel_path))
+        shutil.copyfile(file, full_path)
+        pass
+        
+    def SourceServerIndexing(self, debug_file, guid, sourceFileStream, cvs_root):
+        # Creates a .pdb.stream file in the mozilla\objdir to be used for source indexing
+        cwd = os.getcwd()
+        streamFilename = debug_file + ".stream"
+        stream_output_path = os.path.join(cwd, streamFilename)
+        # Call SourceIndex to create the .stream file
+        result = SourceIndex(sourceFileStream, stream_output_path, cvs_root)
+        
+        if self.copy_debug:
+            pdbstr_path = os.environ.get("PDBSTR_PATH")
+            pdbstr = os.path.normpath(pdbstr_path)
+            pdb_rel_path = os.path.join(debug_file, guid, debug_file)
+            pdb_filename = os.path.normpath(os.path.join(self.symbol_path, pdb_rel_path))
+            # move to the dir with the stream files to call pdbstr
+            os.chdir(os.path.dirname(stream_output_path))
+            os.spawnv(os.P_WAIT, pdbstr, [pdbstr, "-w", "-p:" + pdb_filename, "-i:" + streamFilename, "-s:srcsrv"])
+            # clean up all the .stream files when done
+            os.remove(stream_output_path)
+        return result
+
+class Dumper_Linux(Dumper):
+    def ShouldProcess(self, file):
+        """This function will allow processing of files that are
+        executable, or end with the .so extension, and additionally
+        file(1) reports as being ELF files.  It expects to find the file
+        command in PATH."""
+        if file.endswith(".so") or file.endswith(".bin") or os.access(file, os.X_OK):
+            return self.RunFileCommand(file).startswith("ELF")
+        return False
+
+    def CopyDebug(self, file, debug_file, guid):
+        # We want to strip out the debug info, and add a
+        # .gnu_debuglink section to the object, so the debugger can
+        # actually load our debug info later.
+        file_dbg = file + ".dbg"
+        os.system("objcopy --only-keep-debug %s %s" % (file, file_dbg))
+        os.system("objcopy --add-gnu-debuglink=%s %s" % (file_dbg, file))
+        
+        rel_path = os.path.join(debug_file,
+                                guid,
+                                debug_file + ".dbg")
+        full_path = os.path.normpath(os.path.join(self.symbol_path,
+                                                  rel_path))
+        shutil.copyfile(file_dbg, full_path)
+        # gzip the shipped debug files
+        os.system("gzip %s" % full_path)
+        print rel_path + ".gz"
+
+class Dumper_Solaris(Dumper):
+    def RunFileCommand(self, file):
+        """Utility function, returns the output of file(1)"""
+        try:
+            output = os.popen("file " + file).read()
+            return output.split('\t')[1];
+        except:
+            return ""
+
+    def ShouldProcess(self, file):
+        """This function will allow processing of files that are
+        executable, or end with the .so extension, and additionally
+        file(1) reports as being ELF files.  It expects to find the file
+        command in PATH."""
+        if file.endswith(".so") or os.access(file, os.X_OK):
+            return self.RunFileCommand(file).startswith("ELF")
+        return False
+
+class Dumper_Mac(Dumper):
+    def ShouldProcess(self, file):
+        """This function will allow processing of files that are
+        executable, or end with the .dylib extension, and additionally
+        file(1) reports as being Mach-O files.  It expects to find the file
+        command in PATH."""
+        if file.endswith(".dylib") or os.access(file, os.X_OK):
+            return self.RunFileCommand(file).startswith("Mach-O")
+        return False
+
+# Entry point if called as a standalone program
+def main():
+    parser = OptionParser(usage="usage: %prog [options] <dump_syms binary> <symbol store path> <debug info files>")
+    parser.add_option("-c", "--copy",
+                      action="store_true", dest="copy_debug", default=False,
+                      help="Copy debug info files into the same directory structure as symbol files")
+    parser.add_option("-a", "--archs",
+                      action="store", dest="archs",
+                      help="Run dump_syms -a <arch> for each space separated cpu architecture in ARCHS (only on OS X)")
+    parser.add_option("-s", "--srcdir",
+                      action="store", dest="srcdir",
+                      help="Use SRCDIR to determine relative paths to source files")
+    parser.add_option("-v", "--vcs-info",
+                      action="store_true", dest="vcsinfo",
+                      help="Try to retrieve VCS info for each FILE listed in the output")
+    parser.add_option("-i", "--source-index",
+                      action="store_true", dest="srcsrv", default=False,
+                      help="Add source index information to debug files, making them suitable for use in a source server.")
+    (options, args) = parser.parse_args()
+    
+    #check to see if the pdbstr.exe exists
+    if options.srcsrv:
+        pdbstr = os.environ.get("PDBSTR_PATH")
+        if not os.path.exists(pdbstr):
+            print >> sys.stderr, "Invalid path to pdbstr.exe - please set/check PDBSTR_PATH.\n"
+            sys.exit(1)
+            
+    if len(args) < 3:
+        parser.error("not enough arguments")
+        exit(1)
+
+    dumper = GetPlatformSpecificDumper(dump_syms=args[0],
+                                       symbol_path=args[1],
+                                       copy_debug=options.copy_debug,
+                                       archs=options.archs,
+                                       srcdir=options.srcdir,
+                                       vcsinfo=options.vcsinfo,
+                                       srcsrv=options.srcsrv)
+    for arg in args[2:]:
+        dumper.Process(arg)
+
+# run main if run directly
+if __name__ == "__main__":
+    main()
commit 852c93e0a310086539b01cbf3672702b301cfac5
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed Dec 9 07:39:58 2015 +0100

    store the id of each vcl::Window
    
    We will use the ID in the UI testing to identify the widget.
    
    Change-Id: I4dd79a02355e1de40f3c2ddc6a61a805b4e30778

diff --git a/include/vcl/window.hxx b/include/vcl/window.hxx
index c9a6d0b..dda799e 100644
--- a/include/vcl/window.hxx
+++ b/include/vcl/window.hxx
@@ -1527,6 +1527,16 @@ public:
      */
     void reorderWithinParent(sal_uInt16 nNewPosition);
 
+    /**
+     * Sets an ID.
+     */
+    void set_id(const OUString& rID);
+
+    /**
+     * Get the ID of the window.
+     */
+    const OUString& get_id() const;
+
 
     //  Native Widget Rendering functions
 
diff --git a/vcl/inc/window.h b/vcl/inc/window.h
index db8bdfb..a1df543 100644
--- a/vcl/inc/window.h
+++ b/vcl/inc/window.h
@@ -231,6 +231,7 @@ public:
     OString             maUniqId;
     OUString            maHelpText;
     OUString            maQuickHelpText;
+    OUString            maID;
     InputContext        maInputContext;
     css::uno::Reference< css::awt::XWindowPeer > mxWindowPeer;
     css::uno::Reference< css::accessibility::XAccessible > mxAccessible;
diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx
index cc11c28..a48f3fd 100644
--- a/vcl/source/window/builder.cxx
+++ b/vcl/source/window/builder.cxx
@@ -1845,6 +1845,7 @@ VclPtr<vcl::Window> VclBuilder::insertObject(vcl::Window *pParent, const OString
 
     if (pCurrentChild)
     {
+        pCurrentChild->set_id(OStringToOUString(rID, RTL_TEXTENCODING_UTF8));
         if (pCurrentChild == m_pParent.get() && m_bToplevelHasDeferredProperties)
             m_aDeferredProperties = rProps;
         else
diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
index 599514d..1998b6d 100644
--- a/vcl/source/window/window.cxx
+++ b/vcl/source/window/window.cxx
@@ -3847,6 +3847,16 @@ bool Window::CompatNotify( NotifyEvent& rNEvt )
         return Notify( rNEvt );
 }
 
+void Window::set_id(const OUString& rID)
+{
+    mpWindowImpl->maID = rID;
+}
+
+const OUString& Window::get_id() const
+{
+    return mpWindowImpl->maID;
+}
+
 } /* namespace vcl */
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 1cc8f7fd3b14820d851b926fb947c6d0b7498de6
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Tue Dec 1 15:01:23 2015 +0100

    fix crashreport build
    
    There was a circular dependency between vcl and sofficeapp
    
    Change-Id: I7f7c10ddcb2966b324469ce9cb9693da628c3781

diff --git a/Repository.mk b/Repository.mk
index 2b6f10a..ea242bd 100644
--- a/Repository.mk
+++ b/Repository.mk
@@ -543,6 +543,7 @@ $(eval $(call gb_Helper_register_libraries_for_install,PLAINLIBS_OOO,ooo, \
 	collator_data \
 	comphelper \
 	$(call gb_Helper_optional,DBCONNECTIVITY,dbpool2) \
+	$(call gb_Helper_optional,BREAKPAD,crashreport) \
 	deployment \
 	deploymentgui \
 	dict_ja \
diff --git a/desktop/Library_sofficeapp.mk b/desktop/Library_sofficeapp.mk
index 99fa979..d24f615 100644
--- a/desktop/Library_sofficeapp.mk
+++ b/desktop/Library_sofficeapp.mk
@@ -25,6 +25,10 @@ $(eval $(call gb_Library_add_libs,sofficeapp,\
 
 $(eval $(call gb_Library_use_external,sofficeapp,boost_headers))
 
+ifeq ($(ENABLE_BREAKPAD),TRUE)
+$(eval $(call gb_Library_use_external,sofficeapp,breakpad))
+endif
+
 $(eval $(call gb_Library_use_custom_headers,sofficeapp,\
 	officecfg/registry \
 ))
@@ -44,6 +48,9 @@ $(eval $(call gb_Library_use_libraries,sofficeapp,\
     comphelper \
     cppu \
     cppuhelper \
+    $(if $(filter TRUE,$(ENABLE_BREAKPAD)), \
+        crashreport \
+    ) \
     deploymentmisc \
     editeng \
     i18nlangtag \
@@ -86,7 +93,6 @@ $(eval $(call gb_Library_add_exception_objects,sofficeapp,\
     desktop/source/app/check_ext_deps \
     desktop/source/app/cmdlineargs \
     desktop/source/app/cmdlinehelp \
-    desktop/source/app/crashreport \
     desktop/source/app/desktopcontext \
     desktop/source/app/desktopresid \
     desktop/source/app/dispatchwatcher \
@@ -117,10 +123,6 @@ $(eval $(call gb_Library_add_libs,sofficeapp,\
 endif
 endif
 
-ifeq ($(ENABLE_BREAKPAD),TRUE)
-$(eval $(call gb_Library_use_external,sofficeapp,breakpad))
-endif
-
 # LibreOfficeKit bits
 ifneq ($(filter $(OS),ANDROID IOS MACOSX WNT),)
 $(eval $(call gb_Library_add_exception_objects,sofficeapp,\
diff --git a/desktop/Module_desktop.mk b/desktop/Module_desktop.mk
index c87a777..619c060 100644
--- a/desktop/Module_desktop.mk
+++ b/desktop/Module_desktop.mk
@@ -17,6 +17,7 @@ $(eval $(call gb_Module_add_targets,desktop,\
     Library_deploymentmisc \
     Library_offacc \
     Library_sofficeapp \
+    $(if $(ENABLE_BREAKPAD),Library_crashreport) \
     $(if $(ENABLE_HEADLESS),,Library_spl) \
     Package_branding \
     $(if $(CUSTOM_BRAND_DIR),Package_branding_custom) \
diff --git a/include/desktop/crashreport.hxx b/include/desktop/crashreport.hxx
index 5a5f694..18aaa2e 100644
--- a/include/desktop/crashreport.hxx
+++ b/include/desktop/crashreport.hxx
@@ -25,7 +25,7 @@
  *      * AdapterDeviceId
  *
  */
-class DESKTOP_DLLPUBLIC CrashReporter
+class CRASHREPORT_DLLPUBLIC CrashReporter
 {
 public:
     static void AddKeyValue(const OUString& rKey, const OUString& rValue);
diff --git a/include/desktop/dllapi.h b/include/desktop/dllapi.h
index ebc75f1..fd23aeb 100644
--- a/include/desktop/dllapi.h
+++ b/include/desktop/dllapi.h
@@ -19,6 +19,12 @@
 #   define DESKTOP_DLLPUBLIC SAL_DLLPUBLIC_IMPORT
 #endif
 
+#if defined(CRASHREPORT_DLLIMPLEMENTATION)
+#   define CRASHREPORT_DLLPUBLIC SAL_DLLPUBLIC_EXPORT
+#else
+#   define CRASHREPORT_DLLPUBLIC SAL_DLLPUBLIC_IMPORT
+#endif
+
 #endif
 
 /* vim: set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 42304f8..323c185 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -75,6 +75,7 @@ $(eval $(call gb_Library_use_externals,vcl,\
 ))
 
 $(eval $(call gb_Library_use_libraries,vcl,\
+	crashreport \
     svl \
     tl \
     utl \
@@ -88,7 +89,6 @@ $(eval $(call gb_Library_use_libraries,vcl,\
     cppu \
     sal \
     salhelper \
-    sofficeapp \
     xmlreader \
 	$(gb_UWINAPI) \
 ))
commit f5749b1af2c16fce9186cdc9804a76150610aaa1
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Thu Nov 26 00:35:55 2015 +0100

    add TODO for location of dump.ini file
    
    Change-Id: Idbe473c9fdfe8856380b16c48ce868ca10045410

diff --git a/desktop/source/app/crashreport.cxx b/desktop/source/app/crashreport.cxx
index 063b15e..0b5b98a 100644
--- a/desktop/source/app/crashreport.cxx
+++ b/desktop/source/app/crashreport.cxx
@@ -25,6 +25,7 @@ void CrashReporter::AddKeyValue(const OUString& rKey, const OUString& rValue)
 
 const char* CrashReporter::getIniFileName()
 {
+    // TODO: we need a generic solution for the location
     return "/tmp/dump.ini";
 }
 
commit 566cec793ae42c15f117dd75ad3f28525b095d42
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Thu Nov 26 00:15:27 2015 +0100

    use the new ini file based minidump uploader
    
    Change-Id: Iaf85fb53e6eff34e268b6948d62ca84b7f8e6dd2

diff --git a/desktop/source/app/crashreport.cxx b/desktop/source/app/crashreport.cxx
new file mode 100644
index 0000000..063b15e
--- /dev/null
+++ b/desktop/source/app/crashreport.cxx
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <desktop/crashreport.hxx>
+
+#include <string>
+#include <fstream>
+
+osl::Mutex CrashReporter::maMutex;
+
+void CrashReporter::AddKeyValue(const OUString& rKey, const OUString& rValue)
+{
+    osl::MutexGuard aGuard(maMutex);
+    std::string ini_path = getIniFileName();
+    std::ofstream ini_file(ini_path, std::ios_base::app);
+    ini_file << rtl::OUStringToOString(rKey, RTL_TEXTENCODING_UTF8).getStr() << "=";
+    ini_file << rtl::OUStringToOString(rValue, RTL_TEXTENCODING_UTF8).getStr() << "\n";
+}
+
+const char* CrashReporter::getIniFileName()
+{
+    return "/tmp/dump.ini";
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/desktop/source/app/sofficemain.cxx b/desktop/source/app/sofficemain.cxx
index 921de86..7a3515b 100644
--- a/desktop/source/app/sofficemain.cxx
+++ b/desktop/source/app/sofficemain.cxx
@@ -43,6 +43,8 @@
 #include <unotools/mediadescriptor.hxx>
 
 #if HAVE_FEATURE_BREAKPAD
+#include <fstream>
+#include <desktop/crashreport.hxx>
 
 #if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
 #include <client/linux/handler/exception_handler.h>
@@ -73,10 +75,13 @@ OString getLibDir()
 #if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
 static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* /*context*/, bool succeeded)
 {
+    std::string ini_path = CrashReporter::getIniFileName();
+    std::ofstream minidump_file(ini_path, std::ios_base::app);
+    minidump_file << "DumpFile=" << descriptor.path() << "\n";;
+    minidump_file.close();
     // send the minidump to the server (not yet implemented)
     SAL_WARN("crashreport", "minidump generated: " << descriptor.path());
-    OString aCommand = getLibDir().copy(7) + "/minidump_upload -p LibreOffice -v \"" + LIBO_VERSION_DOTTED + "\" ";
-    aCommand = aCommand + descriptor.path() + " " + "http://libreofficecrash.org/submit";
+    OString aCommand = getLibDir().copy(7) + "/minidump_upload " + ini_path.c_str();
     int retVal = std::system(aCommand.getStr());
     SAL_WARN_IF(retVal != 0, "crashreport", "Failed to upload minidump. Error Code: " << retVal);
     return succeeded;
@@ -89,6 +94,12 @@ extern "C" int DESKTOP_DLLPUBLIC soffice_main()
 #if HAVE_FEATURE_BREAKPAD
     //limit the amount of code that needs to be executed before the crash reporting
 
+    std::string ini_path = CrashReporter::getIniFileName();
+    std::ofstream minidump_file(ini_path, std::ios_base::trunc);
+    minidump_file << "ProductName=LibreOffice\n";
+    minidump_file << "Version=" << LIBO_VERSION_DOTTED << "\n";
+    minidump_file.close();
+
 #if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
     google_breakpad::MinidumpDescriptor descriptor("/tmp");
     google_breakpad::ExceptionHandler eh(descriptor, NULL, dumpCallback, NULL, true, -1);
diff --git a/include/desktop/crashreport.hxx b/include/desktop/crashreport.hxx
index 8053afb..5a5f694 100644
--- a/include/desktop/crashreport.hxx
+++ b/include/desktop/crashreport.hxx
@@ -30,9 +30,9 @@ class DESKTOP_DLLPUBLIC CrashReporter
 public:
     static void AddKeyValue(const OUString& rKey, const OUString& rValue);
 
-private:
+    static const char* getIniFileName();
 
-    static std::map<OUString, OUString> maValueMap;
+private:
 
     static osl::Mutex maMutex;
 };
commit e03e8ee6ea23b10d7918fb329a8db46d9803dacd
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed Nov 25 23:48:20 2015 +0100

    write an own minidump uploader
    
    This one is platform independent and uses a key-value file.
    
    Change-Id: I28a4483763666a5a8520874bf8e984eaaf24e9c0

diff --git a/Repository.mk b/Repository.mk
index a99e8f5..2b6f10a 100644
--- a/Repository.mk
+++ b/Repository.mk
@@ -88,6 +88,7 @@ $(eval $(call gb_Helper_register_executables_for_install,SDK,sdk, \
 ))
 
 $(eval $(call gb_Helper_register_executables_for_install,OOO,brand, \
+	minidump_upload \
 	$(if $(filter-out ANDROID IOS MACOSX WNT,$(OS)),oosplash) \
 	soffice_bin \
 	$(if $(filter DESKTOP,$(BUILD_TYPE)),unopkg_bin) \
diff --git a/desktop/Executable_minidump_upload.mk b/desktop/Executable_minidump_upload.mk
new file mode 100644
index 0000000..7fe9546
--- /dev/null
+++ b/desktop/Executable_minidump_upload.mk
@@ -0,0 +1,22 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Executable_Executable,minidump_upload))
+
+$(eval $(call gb_Executable_use_libraries,minidump_upload,\
+    sal \
+))
+
+$(eval $(call gb_Executable_use_external,minidump_upload,curl))
+
+$(eval $(call gb_Executable_add_exception_objects,minidump_upload,\
+    desktop/source/minidump/minidump_upload \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/desktop/Module_desktop.mk b/desktop/Module_desktop.mk
index d74d406..c87a777 100644
--- a/desktop/Module_desktop.mk
+++ b/desktop/Module_desktop.mk
@@ -33,6 +33,7 @@ ifneq (,$(filter DESKTOP,$(BUILD_TYPE)))
 $(eval $(call gb_Module_add_targets,desktop,\
     Executable_soffice_bin \
     Executable_unopkg_bin \
+    Executable_minidump_upload \
     Library_migrationoo2 \
     Library_migrationoo3 \
     Library_unopkgapp \
diff --git a/desktop/source/minidump/minidump_upload.cxx b/desktop/source/minidump/minidump_upload.cxx
new file mode 100644
index 0000000..220286a
--- /dev/null
+++ b/desktop/source/minidump/minidump_upload.cxx
@@ -0,0 +1,202 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <string>
+#include <map>
+#include <memory>
+#include <iostream>
+#include <fstream>
+
+#include <curl/curl.h>
+
+static const char kUserAgent[] = "Breakpad/1.0 (Linux)";
+
+std::map<std::string, std::string> readStrings(std::istream& file)
+{
+    std::map<std::string, std::string> parameters;
+
+
+    while (!file.eof())
+    {
+        std::string line;
+        std::getline(file, line);
+        int sep = line.find('=');
+        if (sep >= 0)
+        {
+            std::string key = line.substr(0, sep);
+            std::string value = line.substr(sep + 1);
+            parameters[key] = value;
+        }
+    }
+
+    return parameters;
+}
+
+// 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<std::string *>(userp);
+  size_t real_size = size * nmemb;
+  response->append(reinterpret_cast<char *>(ptr), real_size);
+  return real_size;
+}
+
+void getProperty(const std::string& key, std::string& value,
+        std::map<std::string, std::string>& parameters)
+{
+    auto itr = parameters.find(key);
+    if (itr != parameters.end())
+    {
+        value = itr->second;
+        parameters.erase(itr);
+    }
+}
+
+bool uploadContent(std::map<std::string, std::string>& parameters)
+{
+    CURL* curl = curl_easy_init();
+    if (!curl)
+        return false;
+
+    std::string proxy, proxy_user_pwd, ca_certificate_file, file;
+
+    std::string url = "http://libreofficecrash.org/submit";
+
+    getProperty("Proxy", proxy, parameters);
+    getProperty("ProxyUserPW", proxy_user_pwd, parameters);
+    getProperty("CAFile", ca_certificate_file, parameters);
+
+    getProperty("DumpFile", file, parameters);
+
+    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
+    curl_easy_setopt(curl, CURLOPT_USERAGENT, kUserAgent);
+    // Set proxy information if necessary.
+    if (!proxy.empty())
+        curl_easy_setopt(curl, CURLOPT_PROXY, proxy.c_str());
+    if (!proxy_user_pwd.empty())
+        curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, proxy_user_pwd.c_str());
+
+    if (!ca_certificate_file.empty())
+        curl_easy_setopt(curl, CURLOPT_CAINFO, ca_certificate_file.c_str());
+
+    curl_httppost* formpost = nullptr;
+    curl_httppost* lastptr = nullptr;
+    for (auto itr = parameters.begin(), itEnd = parameters.end(); itr != itEnd; ++itr)
+    {
+        curl_formadd(&formpost, &lastptr,
+                CURLFORM_COPYNAME, itr->first.c_str(),
+                CURLFORM_COPYCONTENTS, itr->second.c_str(),
+                CURLFORM_END);
+    }
+
+    std::string response_body;
+    long response_code;
+    curl_formadd(&formpost, &lastptr,
+            CURLFORM_COPYNAME, "upload_file_minidump",
+            CURLFORM_FILE, file.c_str(),
+            CURLFORM_END);
+
+    curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
+
+
+    // Disable 100-continue header.
+    char buf[] = "Expect:";
+    curl_slist* headerlist = NULL;
+    headerlist = curl_slist_append(headerlist, buf);
+    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
+
+    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
+    curl_easy_setopt(curl, CURLOPT_WRITEDATA,
+            reinterpret_cast<void *>(&response_body));
+
+    // Fail if 400+ is returned from the web server.
+    curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
+
+    CURLcode cc = curl_easy_perform(curl);
+    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
+#ifndef NDEBUG
+    if (cc != CURLE_OK)
+        fprintf(stderr, "Failed to send http request to %s, error: %s\n",
+                url.c_str(),
+                curl_easy_strerror(cc));
+#endif
+    /*
+     * TODO
+    if (error_description != NULL)
+        *error_description = curl_easy_strerror(cc);
+    */
+
+    if (formpost != NULL)
+    {
+        curl_formfree(formpost);
+    }
+    if (headerlist != NULL)
+    {
+        curl_slist_free_all(headerlist);
+    }
+
+    std::cerr << response_body << std::endl;
+
+
+    if( CURLE_OK != cc )
+        return false;
+
+    return true;
+}
+
+bool readConfig(char** argv)
+{
+    std::string iniPath = argv[1];
+
+    std::ifstream file(iniPath);
+    std::map<std::string, std::string> parameters = readStrings(file);
+
+    // make sure that at least the mandatory parameters are in there
+    if (parameters.find("DumpFile") == parameters.end())
+    {
+        std::cerr << "ini file needs to contain a key DumpFile!";
+        return false;
+    }
+
+    if (parameters.find("Version") == parameters.end())
+    {
+        std::cerr << "ini file needs to contain a key Version!";
+        return false;
+    }
+
+    if (parameters.find("ProductName") == parameters.end())
+    {
+        std::cerr << "ini file needs to contain a ket ProductName!";
+        return false;
+    }
+
+    uploadContent(parameters);
+
+    return true;
+}
+
+int main(int argc, char* argv[])
+{
+    if (argc < 2)
+    {
+        std::cerr << "minidump_upload path_to_ini_file" << std::endl;
+        return EXIT_FAILURE;
+    }
+
+    if (!readConfig(argv))
+        return EXIT_FAILURE;
+
+    return EXIT_SUCCESS;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 5a20bc5037a986e634ef970b99bb4586b02c0d55
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed Nov 25 23:47:47 2015 +0100

    Revert "package minidump_upload tool"
    
    This reverts commit 0fb1b359c5b80adf6179c4c0bf5ad999b06b9902.

diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk
index ffa7a15..8079c1b 100644
--- a/RepositoryExternal.mk
+++ b/RepositoryExternal.mk
@@ -3382,11 +3382,6 @@ endif
 
 $(call gb_LinkTarget_use_external_project,$(1),breakpad)
 
-$(eval $(call gb_Helper_register_packages_for_install,ooo,\
-	breakpad \
-))
-
-
 endef
 
 # else # SYSTEM_LIBBREAKPAD
diff --git a/external/breakpad/ExternalPackage_breakpad.mk b/external/breakpad/ExternalPackage_breakpad.mk
deleted file mode 100644
index 6c0d0bf..0000000
--- a/external/breakpad/ExternalPackage_breakpad.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
-#
-# This file is part of the LibreOffice project.
-#
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#
-
-$(eval $(call gb_ExternalPackage_ExternalPackage,breakpad,breakpad))
-
-$(eval $(call gb_ExternalPackage_use_external_project,breakpad,breakpad))
-
-ifeq ($(OS),LINUX)
-$(eval $(call gb_ExternalPackage_add_file,breakpad,$(LIBO_LIB_FOLDER)/minidump_upload,src/tools/linux/symupload/minidump_upload))
-else ifeq ($(OS)),WNT)
-$(eval $(call gb_ExternalPackage_add_file,breakpad,$(LIBO_LIB_FOLDER)/minidump_upload,src/tools/linux/symupload/minidump_upload))
-endif
-
-# vim: set noet sw=4 ts=4:
diff --git a/external/breakpad/Module_breakpad.mk b/external/breakpad/Module_breakpad.mk
index 3902c8e..9750c31 100644
--- a/external/breakpad/Module_breakpad.mk
+++ b/external/breakpad/Module_breakpad.mk
@@ -12,7 +12,6 @@ $(eval $(call gb_Module_Module,breakpad))
 $(eval $(call gb_Module_add_targets,breakpad,\
 	ExternalProject_breakpad \
 	UnpackedTarball_breakpad \
-	ExternalPackage_breakpad \
 ))
 
 # vim: set noet sw=4 ts=4:
commit 36bf5f9b18df26195ddb5311baf582f7dd062029
Author: Markus Mohrhard <markus.mohrhard at googlemail.com>
Date:   Wed Nov 25 17:10:39 2015 +0100

    log some information about used OpenGL device
    
    Change-Id: I0c050396e6b1efa7dd2f003a79a9dc506135197a

diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 22e026e..42304f8 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -88,6 +88,7 @@ $(eval $(call gb_Library_use_libraries,vcl,\
     cppu \
     sal \
     salhelper \
+    sofficeapp \
     xmlreader \
 	$(gb_UWINAPI) \
 ))
diff --git a/vcl/opengl/win/WinDeviceInfo.cxx b/vcl/opengl/win/WinDeviceInfo.cxx
index 798dc58..d04c692 100644
--- a/vcl/opengl/win/WinDeviceInfo.cxx
+++ b/vcl/opengl/win/WinDeviceInfo.cxx
@@ -22,6 +22,8 @@
 #include <rtl/ustrbuf.hxx>
 #include <tools/stream.hxx>
 
+#include <desktop/crashreport.hxx>
+
 OUString* WinOpenGLDeviceInfo::mpDeviceVendors[wgl::DeviceVendorMax];
 std::vector<wgl::DriverInfo> WinOpenGLDeviceInfo::maDriverInfo;
 
@@ -555,6 +557,8 @@ void writeToLog(SvStream& rStrm, const char* pKey, const OUString rVal)
 
 bool WinOpenGLDeviceInfo::isDeviceBlocked()
 {
+    CrashReporter::AddKeyAndValue("AdapterVendorId", maAdapterVendorID);
+    CrashReporter::AddKeyAndValue("AdapterDeviceId", maAdapterDeviceID);
     SAL_INFO("vcl.opengl", maDriverVersion);
     SAL_INFO("vcl.opengl", maDriverDate);
     SAL_INFO("vcl.opengl", maDeviceID);
diff --git a/vcl/opengl/x11/X11DeviceInfo.cxx b/vcl/opengl/x11/X11DeviceInfo.cxx
index 49593c7..89af561 100644
--- a/vcl/opengl/x11/X11DeviceInfo.cxx
+++ b/vcl/opengl/x11/X11DeviceInfo.cxx
@@ -18,6 +18,8 @@
 #include <errno.h>
 #include <sys/utsname.h>
 
+#include <desktop/crashreport.hxx>
+
 namespace glx {
 
 static int glxtest_pipe = 0;
@@ -286,6 +288,9 @@ bool X11OpenGLDeviceInfo::isDeviceBlocked()
     if (mnGLMajorVersion == 1)
         return true;
 
+    CrashReporter::AddKeyValue("AdapterVendorId", rtl::OStringToOUString(maVendor, RTL_TEXTENCODING_UTF8));
+    CrashReporter::AddKeyValue("AdapterDeviceId", rtl::OStringToOUString(maRenderer, RTL_TEXTENCODING_UTF8));
+
     SAL_INFO("vcl.opengl", "Vendor: " << maVendor);
     SAL_INFO("vcl.opengl", "Renderer: " << maRenderer);
     SAL_INFO("vcl.opengl", "Version: " << maVersion);


More information about the Libreoffice-commits mailing list