Hand-apply 155b4b9f615f42b5cc26e2953860aba34b17bbc0; allow build of Windows debug...
authorCarl Hetherington <cth@carlh.net>
Mon, 15 Dec 2014 10:58:01 +0000 (10:58 +0000)
committerCarl Hetherington <cth@carlh.net>
Mon, 15 Dec 2014 10:58:01 +0000 (10:58 +0000)
TO_PORT
cscript
platform/windows/wscript
src/lib/stack.cpp [deleted file]
src/lib/stack.hpp [deleted file]
src/lib/util.cc
src/lib/util.h
src/lib/wscript
src/tools/dcpomatic_kdm.cc

diff --git a/TO_PORT b/TO_PORT
index e340470c258fa55c921d924f21211d0dc10ee9e6..3a54c0d1ea606971cc0394924fd0b7ad46bea79c 100644 (file)
--- a/TO_PORT
+++ b/TO_PORT
@@ -1,4 +1,3 @@
-e7fe121fedc6d837c5bc8ab31e4b36c50497c4cd
 250ff9430c5e3727e2c5e24f81bc6d05a8700b49
 df4337db7d2f94f430caaf1b89f41dfae777799b
 46db828eab42862bf950b4690d9ad191faf9393e
diff --git a/cscript b/cscript
index 5621ef51f630ed6aeec253216774b4e90c458c98..fffec8035b17bdfb684f2bcb616ef00156e139c1 100644 (file)
--- a/cscript
+++ b/cscript
@@ -161,6 +161,8 @@ def dependencies(target):
 
 def build(target, options):
     cmd = './waf configure --prefix=%s' % target.directory
+    if target.debug:
+        cmd += ' --enable-debug'
     if target.platform == 'windows':
         cmd += ' --target-windows'
     elif target.platform == 'linux':
@@ -185,6 +187,7 @@ def package_windows(target):
     target.command('sed -i "s~%%resources%%~%s/platform/windows~g" build/platform/windows/installer2.%s.nsi' % (os.getcwd(), target.bits))
     target.command('sed -i "s~%%static_deps%%~%s~g" build/platform/windows/installer2.%s.nsi' % (target.windows_prefix, target.bits))
     target.command('sed -i "s~%%cdist_deps%%~%s~g" build/platform/windows/installer2.%s.nsi' % (target.directory, target.bits))
+    target.command('sed -i "s~%%mingw%%~%s~g" build/platform/windows/installer2.%s.nsi' % (target.mingw_path, target.bits))
     target.command('sed -i "s~%%binaries%%~%s/build~g" build/platform/windows/installer2.%s.nsi' % (os.getcwd(), target.bits))
     target.command('sed -i "s~%%bits%%~32~g" build/platform/windows/installer2.%s.nsi' % target.bits)
     target.command('makensis build/platform/windows/installer2.%s.nsi' % target.bits)
index 4e38e4f2d4ba7cb6ee54a2976f5d91a374dcd33c..cdfc249318379dd15775c5c161b61c0eb8f7a7db 100644 (file)
@@ -1,7 +1,7 @@
 from __future__ import print_function
 import os
 
-def write_installer(bits, version):
+def write_installer(bits, version, debug):
     try:
         os.makedirs('build/platform/windows')
     except:
@@ -12,18 +12,31 @@ def write_installer(bits, version):
     if bits == 64:
         print('!include "x64.nsh"', file=f)
 
-    print('Name "DCP-o-matic"', file=f)
+    if debug:
+        print('Name "DCP-o-matic Debug"', file=f)
+    else:
+        print('Name "DCP-o-matic"', file=f)
+
     print('RequestExecutionLevel admin', file=f)
 
-    print('outFile "DCP-o-matic %s %d-bit Installer.exe"' % (version, bits), file=f)
+    if debug:
+        print('outFile "DCP-o-matic Debug %s %d-bit Installer.exe"' % (version, bits), file=f)
+    else:
+        print('outFile "DCP-o-matic %s %d-bit Installer.exe"' % (version, bits), file=f)
+
     print("""
 !define MUI_ICON "%resources%/dcpomatic.ico"
 !define MUI_UNICON "%resources%/dcpomatic.ico"
 !define MUI_SPECIALBITMAP "%resources%/dcpomatic.bmp"
 !include "Sections.nsh"
+    """, file=f)
 
-InstallDir "$PROGRAMFILES\\DCP-o-matic 2"
+    if debug:
+        print('InstallDir "$PROGRAMFILES\\DCP-o-matic 2 Debug"', file=f)
+    else:
+        print('InstallDir "$PROGRAMFILES\\DCP-o-matic 2"', file=f)
 
+    print("""
 !insertmacro MUI_PAGE_WELCOME
 !insertmacro MUI_PAGE_LICENSE "../../../COPYING"
 !insertmacro MUI_PAGE_DIRECTORY
@@ -121,10 +134,18 @@ File "%cdist_deps%/bin/swscale-3.dll"
 File "%cdist_deps%/bin/cxml-0.dll"
 File "%cdist_deps%/bin/sub.dll"
 File "%cdist_deps%/bin/ffprobe.exe"
+    """, file=f)
 
-File "%binaries%/src/wx/dcpomatic2-wx.dll"
-File "%binaries%/src/lib/dcpomatic2.dll"
+    if debug:
+        print('File "%resources%/gdb_script"', file=f)
+        print('File "%resources%/debug.bat"', file=f)
+        print('File "%mingw%/gdb.exe"', file=f)
+        print('File "%mingw%/addr2line.exe"', file=f)
+    else:
+        print('File "%binaries%/src/wx/dcpomatic2-wx.dll"', file=f)
+        print('File "%binaries%/src/lib/dcpomatic2.dll"', file=f)
 
+    print("""
 SetOutPath "$INSTDIR\\lib\\pango\\1.8.0\\modules"
 File "%static_deps%/lib/pango/1.8.0/modules/pango-arabic-lang.dll"
 File "%static_deps%/lib/pango/1.8.0/modules/pango-basic-win32.dll"
@@ -168,9 +189,16 @@ File "%binaries%/src/lib/mo/nl_NL/libdcpomatic2.mo"
 File "%binaries%/src/wx/mo/nl_NL/libdcpomatic2-wx.mo"
 File "%binaries%/src/tools/mo/nl_NL/dcpomatic2.mo"
 File "%static_deps%/share/locale/nl/LC_MESSAGES/wxstd.mo"
+    """, file=f)
+
+    if debug:
+        print('WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\DCP-o-matic 2 Debug" "DisplayName" "DCP-o-matic 2 Debug (remove only)"', file=f)
+        print('WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\DCP-o-matic 2 Debug" "UninstallString" "$INSTDIR\\Uninstall.exe"', file=f)
+    else:
+        print('WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\DCP-o-matic 2" "DisplayName" "DCP-o-matic 2 (remove only)"', file=f)
+        print('WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\DCP-o-matic 2" "UninstallString" "$INSTDIR\\Uninstall.exe"', file=f)
 
-WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\DCP-o-matic2" "DisplayName" "DCP-o-matic 2 (remove only)"
-WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\DCP-o-matic2" "UninstallString" "$INSTDIR\\Uninstall.exe"
+    print("""
 WriteUninstaller "$INSTDIR\\Uninstall.exe"
 
 CreateDirectory "$INSTDIR\etc\pango"
@@ -179,23 +207,48 @@ SetOutPath "$INSTDIR"
 nsExec::ExecToLog '$0 /C bin\pango-querymodules.exe > etc\pango\pango.modules'
 
 SectionEnd
+    """, file=f)
 
-Section "DCP-o-matic" SEC_MASTER
-SetOutPath "$INSTDIR\\bin"
-CreateDirectory "$SMPROGRAMS\\DCP-o-matic 2"
+    if debug:
+        print('Section "DCP-o-matic 2 Debug" SEC_MASTER', file=f)
+    else:
+        print('Section "DCP-o-matic 2" SEC_MASTER', file=f)
+    
+    print('SetOutPath "$INSTDIR\\bin"', file=f)
+
+    if debug:
+        print('CreateDirectory "$SMPROGRAMS\\DCP-o-matic 2 Debug"', file=f)
+    else:
+        print('CreateDirectory "$SMPROGRAMS\\DCP-o-matic 2"', file=f)
+
+    print("""
 File "%binaries%/src/tools/dcpomatic2.exe"
 File "%binaries%/src/tools/dcpomatic2_batch.exe"
 File "%binaries%/src/tools/dcpomatic2_cli.exe"
-CreateShortCut "$DESKTOP\\DCP-o-matic 2.lnk" "$INSTDIR\\bin\\dcpomatic2.exe" ""
-CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2\\DCP-o-matic 2.lnk" "$INSTDIR\\bin\\dcpomatic2.exe" "" "$INSTDIR\\bin\\dcpomatic2.exe" 0
-CreateShortCut "$DESKTOP\\DCP-o-matic 2 batch converter.lnk" "$INSTDIR\\bin\\dcpomatic2_batch.exe" ""
-CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2\\DCP-o-matic 2 batch converter.lnk" "$INSTDIR\\bin\\dcpomatic2.exe" "" "$INSTDIR\\bin\\dcpomatic2_batch.exe" 0
-CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2\\Uninstall DCP-o-matic 2.lnk" "$INSTDIR\\Uninstall.exe" "" "$INSTDIR\\Uninstall.exe" 0
-WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\DCP-o-matic2" "DisplayName" "DCP-o-matic 2 (remove only)"
-WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\DCP-o-matic2" "UninstallString" "$INSTDIR\\Uninstall.exe"
+    """, file=f)
+
+    if debug:
+        print('CreateShortCut "$DESKTOP\\DCP-o-matic 2 Debug.lnk" "$INSTDIR\\bin\\debug.bat" ""', file=f)
+        print('CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2 Debug\\DCP-o-matic 2 Debug.lnk" "$INSTDIR\\bin\\debug.bat"', file=f)
+        print('CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2\\Uninstall DCP-o-matic 2 Debug.lnk" "$INSTDIR\\Uninstall.exe"', file=f)
+        print('WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\DCP-o-matic 2 Debug" "DisplayName" "DCP-o-matic 2 Debug (remove only)"', file=f)
+        print('WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\DCP-o-matic 2 Debug" "UninstallString" "$INSTDIR\\Uninstall.exe"', file=f)
+    else:
+        print('CreateShortCut "$DESKTOP\\DCP-o-matic 2.lnk" "$INSTDIR\\bin\\dcpomatic2.exe" ""', file=f)
+        print('CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2\\DCP-o-matic 2.lnk" "$INSTDIR\\bin\\dcpomatic2.exe"', file=f)
+        print('CreateShortCut "$DESKTOP\\DCP-o-matic 2 batch converter.lnk" "$INSTDIR\\bin\\dcpomatic2_batch.exe"', file=f)
+        print('CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2\\DCP-o-matic 2 batch converter.lnk" "$INSTDIR\\bin\\dcpomatic2.exe"', file=f)
+        print('CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2\\Uninstall DCP-o-matic 2.lnk" "$INSTDIR\\Uninstall.exe"', file=f)
+        print('WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\DCP-o-matic2" "DisplayName" "DCP-o-matic 2 (remove only)"', file=f)
+        print('WriteRegStr HKLM "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\DCP-o-matic2" "UninstallString" "$INSTDIR\\Uninstall.exe"', file=f)
+
+    print("""
 WriteUninstaller "$INSTDIR\\Uninstall.exe"
 SectionEnd
+    """, file=f)
 
+    if not debug:
+        print("""
 Section "Encode server" SEC_SERVER
 SetOutPath "$INSTDIR\\bin"
 CreateDirectory "$SMPROGRAMS\\DCP-o-matic 2"
@@ -205,10 +258,15 @@ CreateShortCut "$DESKTOP\\DCP-o-matic 2 encode server.lnk" "$INSTDIR\\bin\\dcpom
 CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2\\DCP-o-matic 2 encode server.lnk" "$INSTDIR\\bin\\dcpomatic_server.exe" "" "$INSTDIR\\bin\\dcpomatic2_server.exe" 0
 CreateShortCut "$SMPROGRAMS\\DCP-o-matic 2\\Uninstall DCP-o-matic 2.lnk" "$INSTDIR\\Uninstall.exe" "" "$INSTDIR\\Uninstall.exe" 0
 SectionEnd
+    """, file=f)
 
-LangString DESC_SEC_MASTER ${LANG_ENGLISH} "DCP-o-matic"
-LangString DESC_SEC_SERVER ${LANG_ENGLISH} "DCP-o-matic encode server"
+    if debug:
+        print('LangString DESC_SEC_MASTER ${LANG_ENGLISH} "DCP-o-matic 2 Debug"', file=f)
+    else:
+        print('LangString DESC_SEC_MASTER ${LANG_ENGLISH} "DCP-o-matic 2"', file=f)
+        print('LangString DESC_SEC_SERVER ${LANG_ENGLISH} "DCP-o-matic 2 encode server"', file=f)
 
+    printf("""
 !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
   !insertmacro MUI_DESCRIPTION_TEXT ${SEC_MASTER} $(DESC_SEC_MASTER)
   !insertmacro MUI_DESCRIPTION_TEXT ${SEC_SERVER} $(DESC_SEC_SERVER)
@@ -222,7 +280,22 @@ LangString DESC_SEC_SERVER ${LANG_ENGLISH} "DCP-o-matic encode server"
 !insertmacro MUI_UNPAGE_INSTFILES
 !insertmacro MUI_UNPAGE_FINISH
 !insertmacro MUI_LANGUAGE "English"
+    """, file=f)
 
+    if debug:
+        print("""
+Section "Uninstall"
+RMDir /r "$INSTDIR\\*.*"    
+RMDir "$INSTDIR"
+Delete "$DESKTOP\\DCP-o-matic 2 Debug.lnk"
+Delete "$SMPROGRAMS\\DCP-o-matic 2 Debug\\*.*"
+RmDir  "$SMPROGRAMS\\DCP-o-matic 2 Debug"
+DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\\DCP-o-matic 2 Debug"
+DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\DCP-o-matic 2 Debug"
+ SectionEnd
+        """, file=f)
+    else:
+        print("""
 Section "Uninstall"
 RMDir /r "$INSTDIR\\*.*"    
 RMDir "$INSTDIR"
@@ -231,12 +304,12 @@ Delete "$DESKTOP\\DCP-o-matic 2 batch converter.lnk"
 Delete "$DESKTOP\\DCP-o-matic 2 encode server.lnk"
 Delete "$SMPROGRAMS\\DCP-o-matic 2\\*.*"
 RmDir  "$SMPROGRAMS\\DCP-o-matic 2"
-DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\\DCP-o-matic2"
-DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\DCP-o-matic2"
+DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\\DCP-o-matic 2"
+DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\DCP-o-matic 2"
  SectionEnd
     """, file=f)
     
 
 def build(bld):
-    write_installer(32, bld.env.VERSION)
-    write_installer(64, bld.env.VERSION)
+    write_installer(32, bld.env.VERSION, bld.env.DEBUG)
+    write_installer(64, bld.env.VERSION, bld.env.DEBUG)
diff --git a/src/lib/stack.cpp b/src/lib/stack.cpp
deleted file mode 100644 (file)
index 1675240..0000000
+++ /dev/null
@@ -1,460 +0,0 @@
-// Copyright 2007 Edd Dawson.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#include <cassert>
-#include <cstring>
-#include <cstdlib>
-#include <iomanip>
-#include <ostream>
-#include <stdexcept>
-
-#include "stack.hpp"
-
-#if defined(_WIN32)
-#   include <windows.h>
-#   include <imagehlp.h>
-
-#   if defined(__MINGW32__)
-#       define PACKAGE 1
-#       define PACKAGE_VERSION 1
-#       include <bfd.h> // link against libbfd and libiberty
-#       include <psapi.h> // link against psapi
-#       include <cxxabi.h>
-#   endif
-
-#elif defined(__GNUC__)
-#   include <dlfcn.h>
-#   include <cxxabi.h>
-#endif
-
-namespace
-{
-    const char * const unknown_function = "[unknown function]";
-    const char * const unknown_module = "[unknown module]";
-
-#if defined(__GNUC__)
-    std::string demangle(const char *name)
-    {
-        if (!name)
-            return unknown_function;
-
-        int status = 0;
-        char *d = 0;
-        std::string ret = name;
-        try
-        {
-            if ((d = abi::__cxa_demangle(name, 0, 0, &status)))
-                ret = d;
-        }
-        catch (const std::bad_alloc &) {  }
-
-        std::free(d);
-        return ret;
-    }
-#endif
-
-#if defined(_WIN32)
-
-    // Derive from this to disallow copying of your class.
-    // c.f. boost::noncopyable
-    class uncopyable
-    {
-        protected:
-            uncopyable() { }
-
-        private:
-            uncopyable(const uncopyable &);
-            uncopyable &operator= (const uncopyable &);
-    };
-
-#if defined(__MINGW32__)
-
-    // Provides a means to translate a program counter offset in to the name of the corresponding function.
-    class bfd_context : uncopyable
-    {
-        private:
-            struct find_data
-            {
-                std::string func;
-                unsigned int line;
-                asymbol **symbol_table;
-                bfd_vma counter;
-            };
-
-        public:
-            bfd_context() :
-                abfd_(0),
-                sec_(0),
-                symbol_table_(0)
-            {
-                char procname[MAX_PATH];
-                GetModuleFileNameA(NULL, procname, sizeof procname);
-
-                bfd_init();
-                abfd_ = bfd_openr(procname, 0);
-                if (!abfd_)
-                    throw std::runtime_error("Failed to parse object data for the executable");
-
-                char **formats = 0;
-                bool b1 = bfd_check_format(abfd_, bfd_object);
-                bool b2 = bfd_check_format_matches(abfd_, bfd_object, &formats);
-                bool b3 = bfd_get_file_flags(abfd_) & HAS_SYMS;
-
-                if (!(b1 && b2 && b3))
-                {
-                    bfd_close(abfd_);
-                    free(formats);
-                    throw std::runtime_error("Failed to parse object data for the executable");
-                }
-                free(formats);
-
-                // Load symbol table
-                unsigned dummy = 0;
-                if (bfd_read_minisymbols(abfd_, FALSE, reinterpret_cast<void **>(&symbol_table_), &dummy) == 0 &&
-                    bfd_read_minisymbols(abfd_, TRUE, reinterpret_cast<void **>(&symbol_table_), &dummy) < 0)
-                {
-                    free(symbol_table_);
-                    bfd_close(abfd_);
-                    throw std::runtime_error("Failed to parse object data for the executable");
-                }
-            }
-
-            ~bfd_context()
-            {
-                free(symbol_table_);
-                bfd_close(abfd_);
-            }
-
-            std::pair<std::string, unsigned int> get_function_name_and_line(DWORD offset)
-            {
-                find_data data;
-                data.symbol_table = symbol_table_;
-                data.counter = offset;
-
-                bfd_map_over_sections(abfd_, &find_function_name_in_section, &data);
-
-                return std::make_pair(data.func, data.line);
-            }
-
-        private:
-            static void find_function_name_in_section(bfd *abfd, asection *sec, void *opaque_data)
-            {
-                assert(sec);
-                assert(opaque_data);
-                find_data &data = *static_cast<find_data *>(opaque_data);
-
-                if (!data.func.empty()) return; // already found it
-
-                if (!(bfd_get_section_flags(abfd, sec) & SEC_ALLOC)) return;
-
-                bfd_vma vma = bfd_get_section_vma(abfd, sec);
-                if (data.counter < vma || vma + bfd_get_section_size(sec) <= data.counter) return;
-
-                const char *func = 0;
-                const char *file = 0;
-                unsigned line = 0;
-
-                if (bfd_find_nearest_line(abfd, sec, data.symbol_table, data.counter - vma, &file, &func, &line) && func) {
-                    data.func = demangle(func);
-                    data.line = line;
-                }
-            }
-
-        private:
-            bfd *abfd_;
-            asection *sec_;
-            asymbol **symbol_table_;
-    };
-
-#endif // __MINGW32__
-
-    // g++ spouts warnings if you use {0} to initialize PODs. So we use this instead:
-    const struct
-    {
-        template<typename POD>
-        operator POD () const { POD p; std::memset(&p, 0, sizeof p); return p; }
-    }
-    empty_pod = { };
-
-    // Wraps a FARPROC. Implicitly convertible to any kind of pointer-to-function.
-    // Avoids having reinterpret casts all over the place.
-    struct auto_cast_function_ptr
-    {
-        auto_cast_function_ptr(FARPROC f) : fptr_(f) { }
-
-        template<typename FuncPtr>
-        operator FuncPtr() const { return reinterpret_cast<FuncPtr>(fptr_); }
-
-        FARPROC fptr_;
-    };
-
-    // A wrapper around a DLL. Can dynamically get function pointers with the function() function!
-    class windows_dll : uncopyable
-    {
-        public:
-            explicit windows_dll(const std::string &libname) :
-                name_(libname),
-                lib_(LoadLibraryA(name_.c_str()))
-            {
-                if (!lib_) throw std::runtime_error("Failed to load dll " + name_);
-            }
-
-            ~windows_dll() { FreeLibrary(lib_); }
-
-            const std::string &name() const { return name_; }
-
-            auto_cast_function_ptr function(const char *func_name) const
-            {
-                FARPROC proc = GetProcAddress(lib_, func_name);
-                if (!proc) throw std::runtime_error(std::string("failed to load function ") + func_name + " from library " + name_);
-
-                return proc;
-            }
-
-        private:
-            std::string name_;
-            HMODULE lib_;
-    };
-
-    // An object that makes sure debugging symbols are available
-    class symbol_context : uncopyable
-    {
-        public:
-            symbol_context()
-            {
-                if (!SymInitialize(GetCurrentProcess(), 0, TRUE))
-                    throw std::runtime_error("Failed to initialize symbol context");
-            }
-            ~symbol_context() { SymCleanup(GetCurrentProcess()); }
-    };
-
-    // A simple Windows mutex class. Use a lock object to lock the mutex for the duration of a scope.
-    class mutex : uncopyable
-    {
-        public:
-            mutex() { InitializeCriticalSection(&cs_); }
-            ~mutex() { DeleteCriticalSection(&cs_); }
-
-        private:
-            friend class lock;
-            void lock() { EnterCriticalSection(&cs_); }
-            void unlock() { LeaveCriticalSection(&cs_); }
-
-            CRITICAL_SECTION cs_;
-    }
-    g_fill_frames_mtx;
-
-    // A lock for the mutex
-    class lock : uncopyable
-    {
-        public:
-            lock(mutex &m) : m_(m) { m.lock(); }
-            ~lock() { m_.unlock(); }
-        private:
-            mutex &m_;
-    };
-
-
-    void fill_frames(std::list<dbg::stack_frame> &frames, dbg::stack::depth_type limit)
-    {
-        lock lk(g_fill_frames_mtx);
-
-        symbol_context sc;
-#ifdef __MINGW32__
-        bfd_context bfdc;
-#endif
-
-        STACKFRAME frame = empty_pod;
-        CONTEXT context = empty_pod;
-        context.ContextFlags = CONTEXT_FULL;
-
-        windows_dll kernel32("kernel32.dll");
-        void (WINAPI *RtlCaptureContext_)(CONTEXT*) = kernel32.function("RtlCaptureContext");
-
-        RtlCaptureContext_(&context);
-
-#if defined(_M_AMD64)
-        frame.AddrPC.Offset = context.Rip;
-        frame.AddrPC.Mode = AddrModeFlat;
-        frame.AddrStack.Offset = context.Rsp;
-        frame.AddrStack.Mode = AddrModeFlat;
-        frame.AddrFrame.Offset = context.Rbp;
-        frame.AddrFrame.Mode = AddrModeFlat;
-#else
-        frame.AddrPC.Offset = context.Eip;
-        frame.AddrPC.Mode = AddrModeFlat;
-        frame.AddrStack.Offset = context.Esp;
-        frame.AddrStack.Mode = AddrModeFlat;
-        frame.AddrFrame.Offset = context.Ebp;
-        frame.AddrFrame.Mode = AddrModeFlat;
-#endif
-
-        HANDLE process = GetCurrentProcess();
-        HANDLE thread = GetCurrentThread();
-
-        bool skip = true;
-        bool has_limit = limit != 0;
-        char symbol_buffer[sizeof(IMAGEHLP_SYMBOL) + 255];
-        char module_name_raw[MAX_PATH];
-
-#if defined(_M_AMD64)
-        const DWORD machine = IMAGE_FILE_MACHINE_AMD64;
-#else
-        const DWORD machine = IMAGE_FILE_MACHINE_I386;
-#endif
-
-        while(StackWalk(machine, process, thread, &frame, &context, 0, SymFunctionTableAccess, SymGetModuleBase, 0))
-        {
-            if (skip)
-            {
-                skip = false;
-                continue;
-            }
-
-            if (has_limit && limit-- == 0) break;
-
-            IMAGEHLP_SYMBOL *symbol = reinterpret_cast<IMAGEHLP_SYMBOL *>(symbol_buffer);
-            symbol->SizeOfStruct = (sizeof *symbol) + 255;
-            symbol->MaxNameLength = 254;
-
-#if defined(_WIN64)
-            DWORD64 module_base = SymGetModuleBase(process, frame.AddrPC.Offset);
-#else
-            DWORD module_base = SymGetModuleBase(process, frame.AddrPC.Offset);
-#endif
-            std::string module_name = unknown_module;
-            if (module_base && GetModuleFileNameA(reinterpret_cast<HINSTANCE>(module_base), module_name_raw, MAX_PATH))
-                module_name = module_name_raw;
-
-#if defined(__MINGW32__)
-                std::pair<std::string, unsigned int> func_and_line = bfdc.get_function_name_and_line(frame.AddrPC.Offset);
-
-                if (func_and_line.first.empty())
-                {
-#if defined(_WIN64)
-                   DWORD64 dummy = 0;
-#else              
-                    DWORD dummy = 0;
-#endif             
-                    BOOL got_symbol = SymGetSymFromAddr(process, frame.AddrPC.Offset, &dummy, symbol);
-                    func_and_line.first = got_symbol ? symbol->Name : unknown_function;
-                }
-#else
-                DWORD dummy = 0;
-                BOOL got_symbol = SymGetSymFromAddr(process, frame.AddrPC.Offset, &dummy, symbol);
-                std::string func = got_symbol ? symbol->Name : unknown_function;
-#endif
-
-            dbg::stack_frame f(reinterpret_cast<const void *>(frame.AddrPC.Offset), func_and_line.first, func_and_line.second, module_name);
-            frames.push_back(f);
-        }
-    }
-#elif defined(__GNUC__)
-#   if defined(__i386__) || defined(__amd64__)
-
-    void fill_frames(std::list<dbg::stack_frame> &frames, dbg::stack::depth_type limit)
-    {
-        // Based on code found at:
-        // http://www.tlug.org.za/wiki/index.php/Obtaining_a_stack_trace_in_C_upon_SIGSEGV
-
-        Dl_info info;
-        void **frame = static_cast<void **>(__builtin_frame_address(0));
-        void **bp = static_cast<void **>(*frame);
-        void *ip = frame[1];
-
-        bool has_limit = limit != 0;
-        bool skip = true;
-
-        while(bp && ip && dladdr(ip, &info))
-        {
-            if (skip)
-                skip = false;
-            else
-            {
-                if (has_limit && limit-- == 0) break;
-                frames.push_back(dbg::stack_frame(ip, demangle(info.dli_sname), info.dli_fname));
-
-                if(info.dli_sname && !std::strcmp(info.dli_sname, "main")) break;
-            }
-
-            ip = bp[1];
-            bp = static_cast<void**>(bp[0]);
-        }
-    }
-
-#   elif defined(__ppc__)
-
-    void fill_frames(std::list<dbg::stack_frame> &frames, dbg::stack::depth_type limit)
-    {
-        // Based on code found at:
-        // http://www.informit.com/articles/article.aspx?p=606582&seqNum=4&rl=1
-
-        void *ip = __builtin_return_address(0);
-        void **frame = static_cast<void **>(__builtin_frame_address(1));
-        bool has_limit = limit != 0;
-        Dl_info info;
-
-        do
-        {
-            if (has_limit && limit-- == 0) break;
-
-            if (dladdr(ip, &info))
-                frames.push_back(dbg::stack_frame(ip, demangle(info.dli_sname), info.dli_fname));
-
-            if (frame && (frame = static_cast<void**>(*frame))) ip = *(frame + 2);
-        }
-        while (frame && ip);
-    }
-
-#   else
-        // GNU, but not x86, x64 nor PPC
-#       error "Sorry but dbg::stack is not supported on this architecture"
-#   endif
-#else
-    // Unsupported compiler
-#   error "Sorry but dbg::stack is not supported on this compiler"
-#endif
-
-} // close anonymous namespace
-
-
-
-namespace dbg
-{
-    stack_frame::stack_frame(const void *instruction, const std::string &function, unsigned int line, const std::string &module) :
-        instruction(instruction),
-        function(function),
-        line(line),
-        module(module)
-    {
-    }
-
-    std::ostream &operator<< (std::ostream &out, const stack_frame &frame)
-    {
-        return out << frame.instruction << ": " << frame.function << ":" << frame.line << " in " << frame.module;
-    }
-
-    stack::stack(depth_type limit)
-    {
-        fill_frames(frames_, limit);
-    }
-
-    stack::const_iterator stack::begin() const
-    {
-        return frames_.begin();
-    }
-
-    stack::const_iterator stack::end() const
-    {
-        return frames_.end();
-    }
-
-    stack::depth_type stack::depth() const
-    {
-        return frames_.size();
-    }
-
-} // close namespace dbg
-
diff --git a/src/lib/stack.hpp b/src/lib/stack.hpp
deleted file mode 100644 (file)
index 73a13bf..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2007 Edd Dawson.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef STACK_HPP_0022_01092007
-#define STACK_HPP_0022_01092007
-
-#include <string>
-#include <list>
-#include <iosfwd>
-
-namespace dbg
-{
-    //! stack_frame objects are collected by a stack object. They contain information about the instruction pointer,
-    //! the name of the corresponding function and the "module" (executable or library) in which the function resides.
-    struct stack_frame
-    {
-        stack_frame(const void *instruction, const std::string &function, unsigned int line, const std::string &module);
-
-        const void *instruction;
-        std::string function;
-        unsigned int line;
-        std::string module;
-    };
-
-    //! Allows you to write a stack_frame object to an std::ostream
-    std::ostream &operator<< (std::ostream &out, const stack_frame &frame);
-
-    //! Instantiate a dbg::stack object to collect information about the current call stack. Once created, a stack object
-    //! may be freely copied about and will continue to contain the information about the scope in which collection occurred.
-    class stack
-    {
-        public:
-            typedef std::list<stack_frame>::size_type depth_type;
-            typedef std::list<stack_frame>::const_iterator const_iterator;
-
-            //! Collect information about the current call stack. Information on the most recent frames will be collected
-            //! up to the specified limit. 0 means unlimited.
-            //! An std::runtime_error may be thrown on failure.
-            stack(depth_type limit = 0);
-
-            //! Returns an iterator referring to the "top" stack frame
-            const_iterator begin() const;
-
-            //! Returns an iterator referring to one past the "bottom" stack frame
-            const_iterator end() const;
-
-            //! Returns the number of frames collected
-            depth_type depth() const;
-
-        private:
-            std::list<stack_frame> frames_;
-    };
-
-} // close namespace dbg
-
-#endif // STACK_HPP_0022_01092007
index e03b4756870c33969013ae2c89d5dc886de564e8..502393094b1e6b1989ab3d853280faf465de8835 100644 (file)
@@ -37,9 +37,6 @@
 #include "md5_digester.h"
 #include "audio_processor.h"
 #include "safe_stringstream.h"
-#ifdef DCPOMATIC_WINDOWS
-#include "stack.hpp"
-#endif
 #include <dcp/version.h>
 #include <dcp/util.h>
 #include <dcp/signer.h>
@@ -69,6 +66,7 @@ extern "C" {
 #include <boost/filesystem.hpp>
 #ifdef DCPOMATIC_WINDOWS
 #include <boost/locale.hpp>
+#include <dbghelp.h>
 #endif
 #include <signal.h>
 #include <iomanip>
@@ -103,6 +101,10 @@ using boost::optional;
 using dcp::Size;
 using dcp::raw_convert;
 
+/** Path to our executable, required by the stacktrace stuff and filled
+ *  in during App::onInit().
+ */
+string program_name;
 static boost::thread::id ui_thread;
 static boost::filesystem::path backtrace_file;
 
@@ -263,15 +265,69 @@ seconds (struct timeval t)
 }
 
 #ifdef DCPOMATIC_WINDOWS
+
+/** Resolve symbol name and source location given the path to the executable */
+int
+addr2line (void const * const adr)
+{
+       char addr2line_cmd[512] = { 0 };
+       sprintf (addr2line_cmd, "addr2line -f -p -e %.256s %p > %s", program_name.c_str(), addr, backtrace_file.string().c_str()); 
+       return system(addr2line_cmd);
+}
+
+/** This is called when C signals occur on Windows (e.g. SIGSEGV)
+ *  (NOT C++ exceptions!).  We write a backtrace to backtrace_file by dark means.
+ *  Adapted from code here: http://spin.atomicobject.com/2013/01/13/exceptions-stack-traces-c/
+ */
 LONG WINAPI exception_handler(struct _EXCEPTION_POINTERS *)
 {
-       dbg::stack s;
        FILE* f = fopen_boost (backtrace_file, "w");
-       fprintf (f, "Exception thrown:");
-       for (dbg::stack::const_iterator i = s.begin(); i != s.end(); ++i) {
-               fprintf (f, "%p %s %d %s\n", i->instruction, i->function.c_str(), i->line, i->module.c_str());
+       fprintf (f, "C-style exception %d\n", info->ExceptionRecord->ExceptionCode);
+       fclose(f);
+       
+       if (info->ExceptionRecord->ExceptionCode != EXCEPTION_STACK_OVERFLOW) {
+               CONTEXT* context = info->ContextRecord;
+               SymInitialize (GetCurrentProcess (), 0, true);
+               
+               STACKFRAME frame = { 0 };
+               
+               /* setup initial stack frame */
+#if _WIN64
+               frame.AddrPC.Offset    = context->Rip;
+               frame.AddrStack.Offset = context->Rsp;
+               frame.AddrFrame.Offset = context->Rbp;
+#else  
+               frame.AddrPC.Offset    = context->Eip;
+               frame.AddrStack.Offset = context->Esp;
+               frame.AddrFrame.Offset = context->Ebp;
+#endif
+               frame.AddrPC.Mode      = AddrModeFlat;
+               frame.AddrStack.Mode   = AddrModeFlat;
+               frame.AddrFrame.Mode   = AddrModeFlat;
+               
+               while (
+                       StackWalk (
+                               IMAGE_FILE_MACHINE_I386,
+                               GetCurrentProcess (),
+                               GetCurrentThread (),
+                               &frame,
+                               context,
+                               0,
+                               SymFunctionTableAccess,
+                               SymGetModuleBase,
+                               0
+                               )
+                       ) {
+                       addr2line((void *) frame.AddrPC.Offset);
+               }
+       } else {
+#ifdef _WIN64          
+               addr2line ((void *) info->ContextRecord->Rip);
+#else          
+               addr2line ((void *) info->ContextRecord->Eip);
+#endif         
        }
-       fclose (f);
+       
        return EXCEPTION_CONTINUE_SEARCH;
 }
 #endif
@@ -282,7 +338,11 @@ set_backtrace_file (boost::filesystem::path p)
        backtrace_file = p;
 }
 
-/* From http://stackoverflow.com/questions/2443135/how-do-i-find-where-an-exception-was-thrown-in-c */
+/** This is called when there is an unhandled exception.  Any
+ *  backtrace in this function is useless on Windows as the stack has
+ *  already been unwound from the throw; we have the gdb wrap hack to
+ *  cope with that.
+ */
 void
 terminate ()
 {
index 1d04d358bb6136d261697d4b5e5c9a98f661e6f4..f5d0b3acac066cd4ef2e9283e2a360628e9f1e6b 100644 (file)
@@ -48,6 +48,8 @@ extern "C" {
 #define HISTORY_SIZE 10
 #define REPORT_PROBLEM _("Please report this problem by using Help -> Report a problem or via email to carl@dcpomatic.com")
 
+extern std::string program_name;
+
 class Job;
 struct AVSubtitle;
 
index 0a6b7920719fdbe6fe989eff5fe3269c46ebd2e3..7edd5dcdf0d3747c6a2e4efad7fe5499753638fa 100644 (file)
@@ -118,7 +118,6 @@ def build(bld):
 
     if bld.env.TARGET_WINDOWS:
         obj.uselib += ' WINSOCK2 BFD DBGHELP IBERTY SHLWAPI MSWSOCK BOOST_LOCALE'
-        obj.source += ' stack.cpp'
     if bld.env.BUILD_STATIC:
         obj.uselib += ' XMLPP'
 
index 6257d60af3f636e2a25eaf3464eebafa993c5ee3..2398dc74d1e13e859a3c24e3bcaf075ac1a7922d 100644 (file)
@@ -33,8 +33,6 @@ using std::list;
 using std::vector;
 using boost::shared_ptr;
 
-static string program_name;
-
 static void
 help ()
 {