Try to integrate; add line numbers to traces.
authorCarl Hetherington <cth@carlh.net>
Fri, 17 May 2013 12:37:18 +0000 (13:37 +0100)
committerCarl Hetherington <cth@carlh.net>
Fri, 17 May 2013 12:37:18 +0000 (13:37 +0100)
src/lib/stack.cpp
src/lib/stack.hpp
src/lib/util.cc

index 24668dfe7a22c158e693225ba0aada3dc0de8e2f..20a5c5be74011d0898282907b12d53c01fa58bb6 100644 (file)
@@ -1,3 +1,5 @@
+/** -*- c-basic-offset: 4; default-tab-width: 4; indent-tabs-mode: nil; -*- */
+
 // Copyright 2007 Edd Dawson.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
@@ -79,6 +81,7 @@ namespace
             struct find_data
             {
                 std::string func;
+                unsigned int line;
                 asymbol **symbol_table;
                 bfd_vma counter;
             };
@@ -127,7 +130,7 @@ namespace
                 bfd_close(abfd_);
             }
 
-            std::string get_function_name(DWORD offset)
+            std::pair<std::string, unsigned int> get_function_name_and_line(DWORD offset)
             {
                 find_data data;
                 data.symbol_table = symbol_table_;
@@ -135,7 +138,7 @@ namespace
 
                 bfd_map_over_sections(abfd_, &find_function_name_in_section, &data);
 
-                return data.func;
+                return std::make_pair(data.func, data.line);
             }
 
         private:
@@ -156,8 +159,10 @@ namespace
                 const char *file = 0;
                 unsigned line = 0;
 
-                if (bfd_find_nearest_line(abfd, sec, data.symbol_table, data.counter - vma, &file, &func, &line) && func)
+                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:
@@ -327,9 +332,9 @@ namespace
                 module_name = module_name_raw;
 
 #if defined(__MINGW32__)
-                std::string func = bfdc.get_function_name(frame.AddrPC.Offset);
+                std::pair<std::string, unsigned int> func_and_line = bfdc.get_function_name_and_line(frame.AddrPC.Offset);
 
-                if (func.empty())
+                if (func_and_line.first.empty())
                 {
 #if defined(_WIN64)
                    DWORD64 dummy = 0;
@@ -337,7 +342,7 @@ namespace
                     DWORD dummy = 0;
 #endif             
                     BOOL got_symbol = SymGetSymFromAddr(process, frame.AddrPC.Offset, &dummy, symbol);
-                    func = got_symbol ? symbol->Name : unknown_function;
+                    func_and_line.first = got_symbol ? symbol->Name : unknown_function;
                 }
 #else
                 DWORD dummy = 0;
@@ -345,7 +350,7 @@ namespace
                 std::string func = got_symbol ? symbol->Name : unknown_function;
 #endif
 
-            dbg::stack_frame f(reinterpret_cast<const void *>(frame.AddrPC.Offset), func, module_name);
+            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);
         }
     }
@@ -421,16 +426,17 @@ namespace
 
 namespace dbg
 {
-    stack_frame::stack_frame(const void *instruction, const std::string &function, const std::string &module) :
+    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 << " in " << frame.module;
+        return out << frame.instruction << ": " << frame.function << ":" << frame.line << " in " << frame.module;
     }
 
     stack::stack(depth_type limit)
index 0430439e04f634320e63829dbfc9df0bb670617d..2b622d0208b080630e1077f00ba82b73023a5eb1 100644 (file)
@@ -1,3 +1,5 @@
+/** -*- c-basic-offset: 4; default-tab-width: 4; indent-tabs-mode: nil; -*- */
+
 // Copyright 2007 Edd Dawson.
 // Distributed under the Boost Software License, Version 1.0.
 // (See accompanying file LICENSE_1_0.txt or copy at
@@ -16,10 +18,11 @@ namespace dbg
     //! 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, const std::string &module);
+        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;
     };
 
index be078a95f298e6cd286efaf76dd4ee2dc1bf05c0..f5bcdf12cb3129733ab673e6c5ef5e035109bc98 100644 (file)
@@ -39,6 +39,7 @@
 #include <boost/lexical_cast.hpp>
 #include <boost/thread.hpp>
 #include <boost/filesystem.hpp>
+#include <glib.h>
 #include <openjpeg.h>
 #include <openssl/md5.h>
 #include <magick/MagickCore.h>
@@ -60,6 +61,9 @@ extern "C" {
 #include "filter.h"
 #include "sound_processor.h"
 #include "config.h"
+#ifdef DVDOMATIC_WINDOWS
+#include "stack.hpp"
+#endif
 
 #include "i18n.h"
 
@@ -75,12 +79,14 @@ using std::min;
 using std::max;
 using std::multimap;
 using std::pair;
+using std::ofstream;
 using boost::shared_ptr;
 using boost::lexical_cast;
 using boost::optional;
 using libdcp::Size;
 
 boost::thread::id ui_thread;
+boost::filesystem::path backtrace_file;
 
 /** Convert some number of seconds to a string representation
  *  in hours, minutes and seconds.
@@ -242,12 +248,28 @@ seconds (struct timeval t)
        return t.tv_sec + (double (t.tv_usec) / 1e6);
 }
 
+#ifdef DVDOMATIC_WINDOWS
+LONG WINAPI exception_handler(struct _EXCEPTION_POINTERS *)
+{
+       dbg::stack s;
+       ofstream f (backtrace_file.string().c_str());
+       std::copy(s.begin(), s.end(), std::ostream_iterator<dbg::stack_frame>(f, "\n"));
+       return EXCEPTION_CONTINUE_SEARCH;
+}
+#endif
+
 /** Call the required functions to set up DVD-o-matic's static arrays, etc.
  *  Must be called from the UI thread, if there is one.
  */
 void
 dvdomatic_setup ()
 {
+#ifdef DVDOMATIC_WINDOWS
+       backtrace_file /= g_get_user_config_dir ();
+       backtrace_file /= "backtrace.txt";
+       SetUnhandledExceptionFilter(exception_handler);
+#endif 
+       
        avfilter_register_all ();
        
        Format::setup_formats ();