From 48501fb37dd46c2e9f6f016dd987b13e61dd476a Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Fri, 17 May 2013 12:54:59 +0100 Subject: Add verbatim stack.{cpp,hpp} from mr-edd.co.uk hg repo. --- src/lib/stack.hpp | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 src/lib/stack.hpp (limited to 'src/lib/stack.hpp') diff --git a/src/lib/stack.hpp b/src/lib/stack.hpp new file mode 100644 index 000000000..0430439e0 --- /dev/null +++ b/src/lib/stack.hpp @@ -0,0 +1,57 @@ +// 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 +#include +#include + +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, const std::string &module); + + const void *instruction; + std::string function; + 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::size_type depth_type; + typedef std::list::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 frames_; + }; + +} // close namespace dbg + +#endif // STACK_HPP_0022_01092007 -- cgit v1.2.3 From beb7c9406f6c9d3979f527db3248eab66347c846 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Fri, 17 May 2013 13:37:18 +0100 Subject: Try to integrate; add line numbers to traces. --- src/lib/stack.cpp | 24 +++++++++++++++--------- src/lib/stack.hpp | 5 ++++- src/lib/util.cc | 22 ++++++++++++++++++++++ 3 files changed, 41 insertions(+), 10 deletions(-) (limited to 'src/lib/stack.hpp') diff --git a/src/lib/stack.cpp b/src/lib/stack.cpp index 24668dfe7..20a5c5be7 100644 --- a/src/lib/stack.cpp +++ b/src/lib/stack.cpp @@ -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 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 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(frame.AddrPC.Offset), func, module_name); + dbg::stack_frame f(reinterpret_cast(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) diff --git a/src/lib/stack.hpp b/src/lib/stack.hpp index 0430439e0..2b622d020 100644 --- a/src/lib/stack.hpp +++ b/src/lib/stack.hpp @@ -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; }; diff --git a/src/lib/util.cc b/src/lib/util.cc index be078a95f..f5bcdf12c 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -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(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 (); -- cgit v1.2.3