mirror of
https://github.com/QuasarApp/backward-cpp.git
synced 2025-05-07 15:29:34 +00:00
functional mac port (#70)
* functional mac port * combine common parts of Linux and Darwin implementations * add unwind support for apple * insure BACKWARD_HAS_BACKTRACE_SYMBOL is set for BACKWARD_SYSTEM_DARWIN * fix indentation * use pthread_self and pthread_main_np
This commit is contained in:
parent
edc1c3efcd
commit
44ae9609e8
259
backward.hpp
259
backward.hpp
@ -46,14 +46,20 @@
|
|||||||
// #define BACKWARD_SYSTEM_LINUX
|
// #define BACKWARD_SYSTEM_LINUX
|
||||||
// - specialization for linux
|
// - specialization for linux
|
||||||
//
|
//
|
||||||
|
// #define BACKWARD_SYSTEM_DARWIN
|
||||||
|
// - specialization for Mac OS X 10.5 and later.
|
||||||
|
//
|
||||||
// #define BACKWARD_SYSTEM_UNKNOWN
|
// #define BACKWARD_SYSTEM_UNKNOWN
|
||||||
// - placebo implementation, does nothing.
|
// - placebo implementation, does nothing.
|
||||||
//
|
//
|
||||||
#if defined(BACKWARD_SYSTEM_LINUX)
|
#if defined(BACKWARD_SYSTEM_LINUX)
|
||||||
|
#elif defined(BACKWARD_SYSTEM_DARWIN)
|
||||||
#elif defined(BACKWARD_SYSTEM_UNKNOWN)
|
#elif defined(BACKWARD_SYSTEM_UNKNOWN)
|
||||||
#else
|
#else
|
||||||
# if defined(__linux)
|
# if defined(__linux)
|
||||||
# define BACKWARD_SYSTEM_LINUX
|
# define BACKWARD_SYSTEM_LINUX
|
||||||
|
# elif defined(__APPLE__)
|
||||||
|
# define BACKWARD_SYSTEM_DARWIN
|
||||||
# else
|
# else
|
||||||
# define BACKWARD_SYSTEM_UNKNOWN
|
# define BACKWARD_SYSTEM_UNKNOWN
|
||||||
# endif
|
# endif
|
||||||
@ -155,31 +161,6 @@
|
|||||||
# define BACKWARD_HAS_BACKTRACE_SYMBOL 1
|
# define BACKWARD_HAS_BACKTRACE_SYMBOL 1
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
|
||||||
# if BACKWARD_HAS_UNWIND == 1
|
|
||||||
|
|
||||||
# include <unwind.h>
|
|
||||||
// while gcc's unwind.h defines something like that:
|
|
||||||
// extern _Unwind_Ptr _Unwind_GetIP (struct _Unwind_Context *);
|
|
||||||
// extern _Unwind_Ptr _Unwind_GetIPInfo (struct _Unwind_Context *, int *);
|
|
||||||
//
|
|
||||||
// clang's unwind.h defines something like this:
|
|
||||||
// uintptr_t _Unwind_GetIP(struct _Unwind_Context* __context);
|
|
||||||
//
|
|
||||||
// Even if the _Unwind_GetIPInfo can be linked to, it is not declared, worse we
|
|
||||||
// cannot just redeclare it because clang's unwind.h doesn't define _Unwind_Ptr
|
|
||||||
// anyway.
|
|
||||||
//
|
|
||||||
// Luckily we can play on the fact that the guard macros have a different name:
|
|
||||||
#ifdef __CLANG_UNWIND_H
|
|
||||||
// In fact, this function still comes from libgcc (on my different linux boxes,
|
|
||||||
// clang links against libgcc).
|
|
||||||
# include <inttypes.h>
|
|
||||||
extern "C" uintptr_t _Unwind_GetIPInfo(_Unwind_Context*, int*);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# include <cxxabi.h>
|
# include <cxxabi.h>
|
||||||
# include <fcntl.h>
|
# include <fcntl.h>
|
||||||
# include <link.h>
|
# include <link.h>
|
||||||
@ -221,6 +202,88 @@ extern "C" uintptr_t _Unwind_GetIPInfo(_Unwind_Context*, int*);
|
|||||||
|
|
||||||
#endif // defined(BACKWARD_SYSTEM_LINUX)
|
#endif // defined(BACKWARD_SYSTEM_LINUX)
|
||||||
|
|
||||||
|
#if defined(BACKWARD_SYSTEM_DARWIN)
|
||||||
|
// On Darwin, backtrace can back-trace or "walk" the stack using the following
|
||||||
|
// libraries:
|
||||||
|
//
|
||||||
|
// #define BACKWARD_HAS_UNWIND 1
|
||||||
|
// - unwind comes from libgcc, but I saw an equivalent inside clang itself.
|
||||||
|
// - with unwind, the stacktrace is as accurate as it can possibly be, since
|
||||||
|
// this is used by the C++ runtine in gcc/clang for stack unwinding on
|
||||||
|
// exception.
|
||||||
|
// - normally libgcc is already linked to your program by default.
|
||||||
|
//
|
||||||
|
// #define BACKWARD_HAS_BACKTRACE == 1
|
||||||
|
// - backtrace is available by default, though it does not produce as much information
|
||||||
|
// as another library might.
|
||||||
|
//
|
||||||
|
// The default is:
|
||||||
|
// #define BACKWARD_HAS_UNWIND == 1
|
||||||
|
//
|
||||||
|
// Note that only one of the define should be set to 1 at a time.
|
||||||
|
//
|
||||||
|
# if BACKWARD_HAS_UNWIND == 1
|
||||||
|
# elif BACKWARD_HAS_BACKTRACE == 1
|
||||||
|
# else
|
||||||
|
# undef BACKWARD_HAS_UNWIND
|
||||||
|
# define BACKWARD_HAS_UNWIND 1
|
||||||
|
# undef BACKWARD_HAS_BACKTRACE
|
||||||
|
# define BACKWARD_HAS_BACKTRACE 0
|
||||||
|
# endif
|
||||||
|
|
||||||
|
// On Darwin, backward can extract detailed information about a stack trace
|
||||||
|
// using one of the following libraries:
|
||||||
|
//
|
||||||
|
// #define BACKWARD_HAS_BACKTRACE_SYMBOL 1
|
||||||
|
// - backtrace provides minimal details for a stack trace:
|
||||||
|
// - object filename
|
||||||
|
// - function name
|
||||||
|
//
|
||||||
|
// The default is:
|
||||||
|
// #define BACKWARD_HAS_BACKTRACE_SYMBOL == 1
|
||||||
|
//
|
||||||
|
# if BACKWARD_HAS_BACKTRACE_SYMBOL == 1
|
||||||
|
# else
|
||||||
|
# undef BACKWARD_HAS_BACKTRACE_SYMBOL
|
||||||
|
# define BACKWARD_HAS_BACKTRACE_SYMBOL 1
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# include <cxxabi.h>
|
||||||
|
# include <fcntl.h>
|
||||||
|
# include <pthread.h>
|
||||||
|
# include <sys/stat.h>
|
||||||
|
# include <unistd.h>
|
||||||
|
# include <signal.h>
|
||||||
|
|
||||||
|
# if (BACKWARD_HAS_BACKTRACE == 1) || (BACKWARD_HAS_BACKTRACE_SYMBOL == 1)
|
||||||
|
# include <execinfo.h>
|
||||||
|
# endif
|
||||||
|
#endif // defined(BACKWARD_SYSTEM_DARWIN)
|
||||||
|
|
||||||
|
#if BACKWARD_HAS_UNWIND == 1
|
||||||
|
|
||||||
|
# include <unwind.h>
|
||||||
|
// while gcc's unwind.h defines something like that:
|
||||||
|
// extern _Unwind_Ptr _Unwind_GetIP (struct _Unwind_Context *);
|
||||||
|
// extern _Unwind_Ptr _Unwind_GetIPInfo (struct _Unwind_Context *, int *);
|
||||||
|
//
|
||||||
|
// clang's unwind.h defines something like this:
|
||||||
|
// uintptr_t _Unwind_GetIP(struct _Unwind_Context* __context);
|
||||||
|
//
|
||||||
|
// Even if the _Unwind_GetIPInfo can be linked to, it is not declared, worse we
|
||||||
|
// cannot just redeclare it because clang's unwind.h doesn't define _Unwind_Ptr
|
||||||
|
// anyway.
|
||||||
|
//
|
||||||
|
// Luckily we can play on the fact that the guard macros have a different name:
|
||||||
|
#ifdef __CLANG_UNWIND_H
|
||||||
|
// In fact, this function still comes from libgcc (on my different linux boxes,
|
||||||
|
// clang links against libgcc).
|
||||||
|
# include <inttypes.h>
|
||||||
|
extern "C" uintptr_t _Unwind_GetIPInfo(_Unwind_Context*, int*);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // BACKWARD_HAS_UNWIND == 1
|
||||||
|
|
||||||
#ifdef BACKWARD_ATLEAST_CXX11
|
#ifdef BACKWARD_ATLEAST_CXX11
|
||||||
# include <unordered_map>
|
# include <unordered_map>
|
||||||
# include <utility> // for std::swap
|
# include <utility> // for std::swap
|
||||||
@ -254,10 +317,13 @@ namespace backward {
|
|||||||
namespace system_tag {
|
namespace system_tag {
|
||||||
struct linux_tag; // seems that I cannot call that "linux" because the name
|
struct linux_tag; // seems that I cannot call that "linux" because the name
|
||||||
// is already defined... so I am adding _tag everywhere.
|
// is already defined... so I am adding _tag everywhere.
|
||||||
|
struct darwin_tag;
|
||||||
struct unknown_tag;
|
struct unknown_tag;
|
||||||
|
|
||||||
#if defined(BACKWARD_SYSTEM_LINUX)
|
#if defined(BACKWARD_SYSTEM_LINUX)
|
||||||
typedef linux_tag current_tag;
|
typedef linux_tag current_tag;
|
||||||
|
#elif defined(BACKWARD_SYSTEM_DARWIN)
|
||||||
|
typedef darwin_tag current_tag;
|
||||||
#elif defined(BACKWARD_SYSTEM_UNKNOWN)
|
#elif defined(BACKWARD_SYSTEM_UNKNOWN)
|
||||||
typedef unknown_tag current_tag;
|
typedef unknown_tag current_tag;
|
||||||
#else
|
#else
|
||||||
@ -267,21 +333,29 @@ namespace system_tag {
|
|||||||
|
|
||||||
|
|
||||||
namespace trace_resolver_tag {
|
namespace trace_resolver_tag {
|
||||||
#ifdef BACKWARD_SYSTEM_LINUX
|
#if defined(BACKWARD_SYSTEM_LINUX)
|
||||||
struct libdw;
|
struct libdw;
|
||||||
struct libbfd;
|
struct libbfd;
|
||||||
struct backtrace_symbol;
|
struct backtrace_symbol;
|
||||||
|
|
||||||
# if BACKWARD_HAS_DW == 1
|
# if BACKWARD_HAS_DW == 1
|
||||||
typedef libdw current;
|
typedef libdw current;
|
||||||
# elif BACKWARD_HAS_BFD == 1
|
# elif BACKWARD_HAS_BFD == 1
|
||||||
typedef libbfd current;
|
typedef libbfd current;
|
||||||
# elif BACKWARD_HAS_BACKTRACE_SYMBOL == 1
|
# elif BACKWARD_HAS_BACKTRACE_SYMBOL == 1
|
||||||
typedef backtrace_symbol current;
|
typedef backtrace_symbol current;
|
||||||
# else
|
# else
|
||||||
# error "You shall not pass, until you know what you want."
|
# error "You shall not pass, until you know what you want."
|
||||||
# endif
|
# endif
|
||||||
#endif // BACKWARD_SYSTEM_LINUX
|
#elif defined(BACKWARD_SYSTEM_DARWIN)
|
||||||
|
struct backtrace_symbol;
|
||||||
|
|
||||||
|
# if BACKWARD_HAS_BACKTRACE_SYMBOL == 1
|
||||||
|
typedef backtrace_symbol current;
|
||||||
|
# else
|
||||||
|
# error "You shall not pass, until you know what you want."
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
} // namespace trace_resolver_tag
|
} // namespace trace_resolver_tag
|
||||||
|
|
||||||
|
|
||||||
@ -398,7 +472,7 @@ struct demangler_impl {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef BACKWARD_SYSTEM_LINUX
|
#if defined(BACKWARD_SYSTEM_LINUX) || defined(BACKWARD_SYSTEM_DARWIN)
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct demangler_impl<system_tag::current_tag> {
|
struct demangler_impl<system_tag::current_tag> {
|
||||||
@ -420,7 +494,7 @@ private:
|
|||||||
size_t _demangle_buffer_length;
|
size_t _demangle_buffer_length;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BACKWARD_SYSTEM_LINUX
|
#endif // BACKWARD_SYSTEM_LINUX || BACKWARD_SYSTEM_DARWIN
|
||||||
|
|
||||||
struct demangler:
|
struct demangler:
|
||||||
public demangler_impl<system_tag::current_tag> {};
|
public demangler_impl<system_tag::current_tag> {};
|
||||||
@ -501,11 +575,9 @@ public:
|
|||||||
void skip_n_firsts(size_t) { }
|
void skip_n_firsts(size_t) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef BACKWARD_SYSTEM_LINUX
|
class StackTraceImplBase {
|
||||||
|
|
||||||
class StackTraceLinuxImplBase {
|
|
||||||
public:
|
public:
|
||||||
StackTraceLinuxImplBase(): _thread_id(0), _skip(0) {}
|
StackTraceImplBase(): _thread_id(0), _skip(0) {}
|
||||||
|
|
||||||
size_t thread_id() const {
|
size_t thread_id() const {
|
||||||
return _thread_id;
|
return _thread_id;
|
||||||
@ -515,12 +587,20 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void load_thread_info() {
|
void load_thread_info() {
|
||||||
|
#ifdef BACKWARD_SYSTEM_LINUX
|
||||||
_thread_id = (size_t)syscall(SYS_gettid);
|
_thread_id = (size_t)syscall(SYS_gettid);
|
||||||
if (_thread_id == (size_t) getpid()) {
|
if (_thread_id == (size_t) getpid()) {
|
||||||
// If the thread is the main one, let's hide that.
|
// If the thread is the main one, let's hide that.
|
||||||
// I like to keep little secret sometimes.
|
// I like to keep little secret sometimes.
|
||||||
_thread_id = 0;
|
_thread_id = 0;
|
||||||
}
|
}
|
||||||
|
#elif defined(BACKWARD_SYSTEM_DARWIN)
|
||||||
|
_thread_id = reinterpret_cast<size_t>(pthread_self());
|
||||||
|
if (pthread_main_np() == 1) {
|
||||||
|
// If the thread is the main one, let's hide that.
|
||||||
|
_thread_id = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t skip_n_firsts() const { return _skip; }
|
size_t skip_n_firsts() const { return _skip; }
|
||||||
@ -530,7 +610,7 @@ private:
|
|||||||
size_t _skip;
|
size_t _skip;
|
||||||
};
|
};
|
||||||
|
|
||||||
class StackTraceLinuxImplHolder: public StackTraceLinuxImplBase {
|
class StackTraceImplHolder: public StackTraceImplBase {
|
||||||
public:
|
public:
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
return _stacktrace.size() ? _stacktrace.size() - skip_n_firsts() : 0;
|
return _stacktrace.size() ? _stacktrace.size() - skip_n_firsts() : 0;
|
||||||
@ -612,7 +692,7 @@ size_t unwind(F f, size_t depth) {
|
|||||||
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
class StackTraceImpl<system_tag::linux_tag>: public StackTraceLinuxImplHolder {
|
class StackTraceImpl<system_tag::current_tag>: public StackTraceImplHolder {
|
||||||
public:
|
public:
|
||||||
__attribute__ ((noinline)) // TODO use some macro
|
__attribute__ ((noinline)) // TODO use some macro
|
||||||
size_t load_here(size_t depth=32) {
|
size_t load_here(size_t depth=32) {
|
||||||
@ -656,7 +736,7 @@ private:
|
|||||||
#else // BACKWARD_HAS_UNWIND == 0
|
#else // BACKWARD_HAS_UNWIND == 0
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
class StackTraceImpl<system_tag::linux_tag>: public StackTraceLinuxImplHolder {
|
class StackTraceImpl<system_tag::current_tag>: public StackTraceImplHolder {
|
||||||
public:
|
public:
|
||||||
__attribute__ ((noinline)) // TODO use some macro
|
__attribute__ ((noinline)) // TODO use some macro
|
||||||
size_t load_here(size_t depth=32) {
|
size_t load_here(size_t depth=32) {
|
||||||
@ -689,7 +769,6 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif // BACKWARD_HAS_UNWIND
|
#endif // BACKWARD_HAS_UNWIND
|
||||||
#endif // BACKWARD_SYSTEM_LINUX
|
|
||||||
|
|
||||||
class StackTrace:
|
class StackTrace:
|
||||||
public StackTraceImpl<system_tag::current_tag> {};
|
public StackTraceImpl<system_tag::current_tag> {};
|
||||||
@ -713,9 +792,7 @@ public:
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef BACKWARD_SYSTEM_LINUX
|
class TraceResolverImplBase {
|
||||||
|
|
||||||
class TraceResolverLinuxImplBase {
|
|
||||||
protected:
|
protected:
|
||||||
std::string demangle(const char* funcname) {
|
std::string demangle(const char* funcname) {
|
||||||
return _demangler.demangle(funcname);
|
return _demangler.demangle(funcname);
|
||||||
@ -725,6 +802,8 @@ private:
|
|||||||
details::demangler _demangler;
|
details::demangler _demangler;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef BACKWARD_SYSTEM_LINUX
|
||||||
|
|
||||||
template <typename STACKTRACE_TAG>
|
template <typename STACKTRACE_TAG>
|
||||||
class TraceResolverLinuxImpl;
|
class TraceResolverLinuxImpl;
|
||||||
|
|
||||||
@ -732,7 +811,7 @@ class TraceResolverLinuxImpl;
|
|||||||
|
|
||||||
template <>
|
template <>
|
||||||
class TraceResolverLinuxImpl<trace_resolver_tag::backtrace_symbol>:
|
class TraceResolverLinuxImpl<trace_resolver_tag::backtrace_symbol>:
|
||||||
public TraceResolverLinuxImplBase {
|
public TraceResolverImplBase {
|
||||||
public:
|
public:
|
||||||
template <class ST>
|
template <class ST>
|
||||||
void load_stacktrace(ST& st) {
|
void load_stacktrace(ST& st) {
|
||||||
@ -776,7 +855,7 @@ private:
|
|||||||
|
|
||||||
template <>
|
template <>
|
||||||
class TraceResolverLinuxImpl<trace_resolver_tag::libbfd>:
|
class TraceResolverLinuxImpl<trace_resolver_tag::libbfd>:
|
||||||
public TraceResolverLinuxImplBase {
|
public TraceResolverImplBase {
|
||||||
static std::string read_symlink(std::string const & symlink_path) {
|
static std::string read_symlink(std::string const & symlink_path) {
|
||||||
std::string path;
|
std::string path;
|
||||||
path.resize(100);
|
path.resize(100);
|
||||||
@ -1182,7 +1261,7 @@ private:
|
|||||||
|
|
||||||
template <>
|
template <>
|
||||||
class TraceResolverLinuxImpl<trace_resolver_tag::libdw>:
|
class TraceResolverLinuxImpl<trace_resolver_tag::libdw>:
|
||||||
public TraceResolverLinuxImplBase {
|
public TraceResolverImplBase {
|
||||||
public:
|
public:
|
||||||
TraceResolverLinuxImpl(): _dwfl_handle_initialized(false) {}
|
TraceResolverLinuxImpl(): _dwfl_handle_initialized(false) {}
|
||||||
|
|
||||||
@ -1520,6 +1599,83 @@ class TraceResolverImpl<system_tag::linux_tag>:
|
|||||||
|
|
||||||
#endif // BACKWARD_SYSTEM_LINUX
|
#endif // BACKWARD_SYSTEM_LINUX
|
||||||
|
|
||||||
|
#ifdef BACKWARD_SYSTEM_DARWIN
|
||||||
|
|
||||||
|
template <typename STACKTRACE_TAG>
|
||||||
|
class TraceResolverDarwinImpl;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class TraceResolverDarwinImpl<trace_resolver_tag::backtrace_symbol>:
|
||||||
|
public TraceResolverImplBase {
|
||||||
|
public:
|
||||||
|
template <class ST>
|
||||||
|
void load_stacktrace(ST& st) {
|
||||||
|
using namespace details;
|
||||||
|
if (st.size() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_symbols.reset(
|
||||||
|
backtrace_symbols(st.begin(), st.size())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ResolvedTrace resolve(ResolvedTrace trace) {
|
||||||
|
// parse:
|
||||||
|
// <n> <file> <addr> <mangled-name> + <offset>
|
||||||
|
char* filename = _symbols[trace.idx];
|
||||||
|
|
||||||
|
// skip "<n> "
|
||||||
|
while(*filename && *filename != ' ') filename++;
|
||||||
|
while(*filename == ' ') filename++;
|
||||||
|
|
||||||
|
// find start of <mangled-name> from end (<file> may contain a space)
|
||||||
|
char* p = filename + strlen(filename) - 1;
|
||||||
|
// skip to start of " + <offset>"
|
||||||
|
while(p > filename && *p != ' ') p--;
|
||||||
|
while(p > filename && *p == ' ') p--;
|
||||||
|
while(p > filename && *p != ' ') p--;
|
||||||
|
while(p > filename && *p == ' ') p--;
|
||||||
|
char *funcname_end = p + 1;
|
||||||
|
|
||||||
|
// skip to start of "<manged-name>"
|
||||||
|
while(p > filename && *p != ' ') p--;
|
||||||
|
char *funcname = p + 1;
|
||||||
|
|
||||||
|
// skip to start of " <addr> "
|
||||||
|
while(p > filename && *p == ' ') p--;
|
||||||
|
while(p > filename && *p != ' ') p--;
|
||||||
|
while(p > filename && *p == ' ') p--;
|
||||||
|
|
||||||
|
// skip "<file>", handling the case where it contains a
|
||||||
|
char* filename_end = p + 1;
|
||||||
|
if (p == filename) {
|
||||||
|
// something went wrong, give up
|
||||||
|
filename_end = filename + strlen(filename);
|
||||||
|
funcname = filename_end;
|
||||||
|
}
|
||||||
|
trace.object_filename.assign(filename, filename_end); // ok even if filename_end is the ending \0 (then we assign entire string)
|
||||||
|
|
||||||
|
if (*funcname) { // if it's not end of string
|
||||||
|
*funcname_end = '\0';
|
||||||
|
|
||||||
|
trace.object_function = this->demangle(funcname);
|
||||||
|
trace.object_function += " ";
|
||||||
|
trace.object_function += (funcname_end + 1);
|
||||||
|
trace.source.function = trace.object_function; // we cannot do better.
|
||||||
|
}
|
||||||
|
return trace;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
details::handle<char**> _symbols;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class TraceResolverImpl<system_tag::darwin_tag>:
|
||||||
|
public TraceResolverDarwinImpl<trace_resolver_tag::current> {};
|
||||||
|
|
||||||
|
#endif // BACKWARD_SYSTEM_DARWIN
|
||||||
|
|
||||||
class TraceResolver:
|
class TraceResolver:
|
||||||
public TraceResolverImpl<system_tag::current_tag> {};
|
public TraceResolverImpl<system_tag::current_tag> {};
|
||||||
|
|
||||||
@ -1904,7 +2060,7 @@ private:
|
|||||||
if (!trace.source.filename.size() || object) {
|
if (!trace.source.filename.size() || object) {
|
||||||
os << " Object \""
|
os << " Object \""
|
||||||
<< trace.object_filename
|
<< trace.object_filename
|
||||||
<< ", at "
|
<< "\", at "
|
||||||
<< trace.addr
|
<< trace.addr
|
||||||
<< ", in "
|
<< ", in "
|
||||||
<< trace.object_function
|
<< trace.object_function
|
||||||
@ -1988,7 +2144,7 @@ private:
|
|||||||
|
|
||||||
/*************** SIGNALS HANDLING ***************/
|
/*************** SIGNALS HANDLING ***************/
|
||||||
|
|
||||||
#ifdef BACKWARD_SYSTEM_LINUX
|
#if defined(BACKWARD_SYSTEM_LINUX) || defined(BACKWARD_SYSTEM_DARWIN)
|
||||||
|
|
||||||
|
|
||||||
class SignalHandling {
|
class SignalHandling {
|
||||||
@ -2007,6 +2163,9 @@ public:
|
|||||||
SIGTRAP, // Trace/breakpoint trap
|
SIGTRAP, // Trace/breakpoint trap
|
||||||
SIGXCPU, // CPU time limit exceeded (4.2BSD)
|
SIGXCPU, // CPU time limit exceeded (4.2BSD)
|
||||||
SIGXFSZ, // File size limit exceeded (4.2BSD)
|
SIGXFSZ, // File size limit exceeded (4.2BSD)
|
||||||
|
#if defined(BACKWARD_SYSTEM_DARWIN)
|
||||||
|
SIGEMT, // emulation instruction executed
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
return std::vector<int>(posix_signals, posix_signals + sizeof posix_signals / sizeof posix_signals[0] );
|
return std::vector<int>(posix_signals, posix_signals + sizeof posix_signals / sizeof posix_signals[0] );
|
||||||
}
|
}
|
||||||
@ -2064,6 +2223,8 @@ public:
|
|||||||
error_addr = reinterpret_cast<void*>(uctx->uc_mcontext.regs->nip);
|
error_addr = reinterpret_cast<void*>(uctx->uc_mcontext.regs->nip);
|
||||||
#elif defined(__s390x__)
|
#elif defined(__s390x__)
|
||||||
error_addr = reinterpret_cast<void*>(uctx->uc_mcontext.psw.addr);
|
error_addr = reinterpret_cast<void*>(uctx->uc_mcontext.psw.addr);
|
||||||
|
#elif defined(__APPLE__) && defined(__x86_64__)
|
||||||
|
error_addr = reinterpret_cast<void*>(uctx->uc_mcontext->__ss.__rip);
|
||||||
#else
|
#else
|
||||||
# warning ":/ sorry, ain't know no nothing none not of your architecture!"
|
# warning ":/ sorry, ain't know no nothing none not of your architecture!"
|
||||||
#endif
|
#endif
|
||||||
@ -2101,7 +2262,7 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BACKWARD_SYSTEM_LINUX
|
#endif // BACKWARD_SYSTEM_LINUX || BACKWARD_SYSTEM_DARWIN
|
||||||
|
|
||||||
#ifdef BACKWARD_SYSTEM_UNKNOWN
|
#ifdef BACKWARD_SYSTEM_UNKNOWN
|
||||||
|
|
||||||
|
@ -24,10 +24,35 @@
|
|||||||
#include "test.hpp"
|
#include "test.hpp"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#ifndef __APPLE__
|
||||||
#include <error.h>
|
#include <error.h>
|
||||||
|
#endif
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
void error(int status, int errnum, const char *format, ...) {
|
||||||
|
fflush(stdout);
|
||||||
|
fprintf(stderr, "%s: ", getprogname());
|
||||||
|
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
vfprintf(stderr, format, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
if (errnum != 0) {
|
||||||
|
fprintf(stderr, ": %s\n", strerror(errnum));
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
if (status != 0) {
|
||||||
|
exit(status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
test::test_registry_t test::test_registry;
|
test::test_registry_t test::test_registry;
|
||||||
using namespace test;
|
using namespace test;
|
||||||
|
|
||||||
|
@ -82,6 +82,8 @@ TEST_DIVZERO (divide_by_zero)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Darwin does not allow RLIMIT_STACK to be reduced
|
||||||
|
#ifndef __APPLE__
|
||||||
int bye_bye_stack(int i) {
|
int bye_bye_stack(int i) {
|
||||||
return bye_bye_stack(i + 1) + bye_bye_stack(i * 2);
|
return bye_bye_stack(i + 1) + bye_bye_stack(i * 2);
|
||||||
}
|
}
|
||||||
@ -94,3 +96,4 @@ TEST_SEGFAULT(stackoverflow)
|
|||||||
int r = bye_bye_stack(42);
|
int r = bye_bye_stack(42);
|
||||||
std::cout << "r=" << r << std::endl;
|
std::cout << "r=" << r << std::endl;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user