52 #if defined(__APPLE__) && defined(__MACH__)
57 #ifndef HAVE_FEENABLEEXCEPT
58 auto feenableexcept = [](
int excepts) ->
int {
60 const auto new_excepts = excepts & FE_ALL_EXCEPT;
62 if (fegetenv(&fenv)) {
65 #if defined(__x86_64__)
67 const unsigned int old_excepts = fenv.__control & FE_ALL_EXCEPT;
70 fenv.__control &= ~new_excepts;
71 fenv.__mxcsr &= ~(new_excepts << 7);
72 #elif defined(__arm64__)
73 if (new_excepts & FE_INVALID) fenv.__fpcr |= __fpcr_trap_invalid;
74 if (new_excepts & FE_DIVBYZERO) fenv.__fpcr |= __fpcr_trap_divbyzero;
75 if (new_excepts & FE_OVERFLOW) fenv.__fpcr |= __fpcr_trap_overflow;
76 if (new_excepts & FE_UNDERFLOW) fenv.__fpcr |= __fpcr_trap_underflow;
77 if (new_excepts & FE_INEXACT) fenv.__fpcr |= __fpcr_trap_inexact;
79 #error "MacOS on unknown architecture"
81 return fesetenv(&fenv);
83 #define HAVE_FEENABLEEXCEPT 1
86 #ifndef HAVE_FEDISABLEEXCEPT
87 auto fedisableexcept = [](
int excepts) ->
int {
89 const auto new_excepts = excepts & FE_ALL_EXCEPT;
92 if (fegetenv(&fenv)) {
95 #if defined(__x86_64__)
96 const unsigned int old_excepts = fenv.__control & FE_ALL_EXCEPT;
99 fenv.__control |= new_excepts;
100 fenv.__mxcsr |= new_excepts << 7;
101 #elif defined(__arm64__)
102 if (new_excepts & FE_INVALID) fenv.__fpcr &= ~__fpcr_trap_invalid;
103 if (new_excepts & FE_DIVBYZERO) fenv.__fpcr &= ~__fpcr_trap_divbyzero;
104 if (new_excepts & FE_OVERFLOW) fenv.__fpcr &= ~__fpcr_trap_overflow;
105 if (new_excepts & FE_UNDERFLOW) fenv.__fpcr &= ~__fpcr_trap_underflow;
106 if (new_excepts & FE_INEXACT) fenv.__fpcr &= ~__fpcr_trap_inexact;
108 #error "MacOS on unknown architecture"
111 return fesetenv(&fenv);
114 #define HAVE_FEDISABLEEXCEPT 1
118 #ifdef HAVE_FEENABLEEXCEPT
120 int enable_excepts = 0;
122 enable_excepts |= FE_DIVBYZERO;
125 enable_excepts |= FE_INVALID;
128 enable_excepts |= FE_OVERFLOW;
130 feenableexcept(enable_excepts);
133 #ifdef HAVE_FEDISABLEEXCEPT
135 int disable_excepts = 0;
137 disable_excepts |= FE_UNDERFLOW;
140 disable_excepts |= FE_INEXACT;
142 fedisableexcept(disable_excepts);
155 std::shared_ptr<Debugger> Debugger::default_debugger_(
nullptr);
157 Debugger::Debugger(
const char *exec) {
162 exit_on_signal_ =
true;
164 wait_for_debugger_ =
true;
167 handle_sigint_ =
false;
174 Debugger::~Debugger() {
175 for (
int i = 0; i <
NSIG; i++) {
176 if (mysigs_[i]) signals[i] =
nullptr;
181 void Debugger::init() {
190 wait_for_debugger_ = 1;
192 mysigs_ =
new int[
NSIG];
193 for (
int i = 0; i <
NSIG; i++) {
199 static void handler(
int sig) {
200 if (signals[sig]) signals[sig]->
got_signal(sig);
204 void Debugger::handle(
int sig) {
205 if (sig >=
NSIG)
return;
206 typedef void (*handler_type)(int);
207 signal(sig, (handler_type)handler);
212 void Debugger::release(
int sig) {
213 if (sig >=
NSIG)
return;
214 signal(sig, SIG_DFL);
215 signals[sig] =
nullptr;
219 void Debugger::handle_defaults() {
233 if (handle_sigint_) handle(SIGINT);
249 void Debugger::set_exec(
const char *exec) {
257 void Debugger::set_prefix(
const char *p) {
265 void Debugger::set_prefix(
int i) {
267 sprintf(p,
"%3d: ", i);
271 void Debugger::default_cmd() {
272 int has_x11_display = (getenv(
"DISPLAY") != 0);
274 if (has_x11_display) {
275 set_cmd(
"gdb_xterm");
281 void Debugger::resolve_cmd_alias() {
282 if (cmd_ ==
"gdb_xterm") {
283 cmd_ =
"xterm -title \"$(PREFIX)$(EXEC)\" -e gdb -ex \"set variable debugger_ready_=1\" --pid=$(PID) $(EXEC) &";
284 }
else if (cmd_ ==
"lldb_xterm") {
285 cmd_ =
"xterm -title \"$(PREFIX)$(EXEC)\" -e lldb -p $(PID) -o \"expr debugger_ready_=1\" &";
289 void Debugger::set_cmd(
const char *cmd) {
298 void Debugger::debug(
const char *reason) {
299 std::cout << prefix_ <<
"Debugger::debug: ";
303 std::cout <<
"no reason given";
309 std::string cmd = cmd_;
310 std::string::size_type pos;
311 std::string pidvar(
"$(PID)");
312 while ((pos = cmd.find(pidvar)) != std::string::npos) {
314 pidstr += std::to_string(pid);
315 cmd.replace(pos, pidvar.size(), pidstr);
317 std::string execvar(
"$(EXEC)");
318 while ((pos = cmd.find(execvar)) != std::string::npos) {
319 cmd.replace(pos, execvar.size(), exec_);
321 std::string prefixvar(
"$(PREFIX)");
322 while ((pos = cmd.find(prefixvar)) != std::string::npos) {
323 cmd.replace(pos, prefixvar.size(), prefix_);
329 std::cout << prefix_ <<
"Debugger: starting \"" << cmd <<
"\"" << endl;
331 const auto system_retvalue = system(cmd.c_str());
332 if (system_retvalue != 0) {
333 std::cout << prefix_ <<
"Failed debugger launch: system() did not succeed ..." << endl;
337 std::cout << prefix_ <<
"Sleeping " << sleep_ <<
" seconds to wait for debugger ..." << endl;
340 if (wait_for_debugger_) {
341 std::string make_ready_message;
342 if (cmd_.find(
" gdb ") != std::string::npos || cmd_.find(
" lldb ") != std::string::npos) {
344 " configure debugging session (set breakpoints/watchpoints, etc.) then type 'c' to continue running";
347 std::cout << prefix_ <<
": waiting for the user ..." << make_ready_message << endl;
348 while (!debugger_ready_)
353 std::cout << prefix_ <<
": waiting for the user to attach a debugger to process " << getpid() <<
" ... " << endl;
355 while (!debugger_ready_)
360 void Debugger::got_signal(
int sig) {
364 else if (sig == SIGFPE)
366 else if (sig == SIGHUP)
368 else if (sig == SIGINT)
370 else if (sig == SIGABRT)
373 else if (sig == SIGBUS)
376 else if (sig == SIGTRAP)
379 signame =
"UNKNOWN SIGNAL";
388 if (exit_on_signal_) {
389 std::cout << prefix_ <<
"Debugger: exiting" << endl;
392 std::cout << prefix_ <<
"Debugger: continuing" << endl;
398 void Debugger::set_debug_on_signal(
int v) { debug_ = v; }
400 void Debugger::set_traceback_on_signal(
int v) { traceback_ = v; }
402 void Debugger::set_wait_for_debugger(
int v) { wait_for_debugger_ = v; }
404 void Debugger::set_exit_on_signal(
int v) { exit_on_signal_ = v; }
406 void Debugger::set_default_debugger(
const std::shared_ptr<Debugger> &d) { default_debugger_ = d; }
408 std::shared_ptr<Debugger> Debugger::default_debugger() {
return default_debugger_; }
410 #define SIMPLE_STACK (defined(linux) && defined(i386)) || (defined(__OSF1__) && defined(i860))
412 void Debugger::traceback(
const char *reason) { Debugger::__traceback(prefix_, reason); }
414 void Debugger::__traceback(
const std::string &prefix,
const char *reason) {
416 const size_t nframes_to_skip = 2;
417 #if defined(HAVE_LIBUNWIND)
418 std::cout << prefix <<
"Debugger::traceback(using libunwind):";
419 #elif defined(HAVE_BACKTRACE)
420 std::cout << prefix <<
"Debugger::traceback(using backtrace):";
422 #if defined(SIMPLE_STACK)
423 std::cout << prefix <<
"Debugger::traceback:";
425 std::cout << prefix <<
"traceback not available for this arch" << endl;
433 std::cout <<
"no reason given";
437 std::cout << prefix <<
"backtrace returned no state information" << std::endl;
439 std::cout << result.
str(nframes_to_skip) << std::endl;
447 auto debugger = std::make_shared<Debugger>();
448 Debugger::set_default_debugger(debugger);
449 debugger->set_exec(exec_name);
450 debugger->set_prefix(
rank);
451 debugger->set_cmd(
"lldb_xterm");
452 debugger->debug(
"start");
virtual void got_signal(int sig)
Called when signal sig is received. This is mainly for internal use.
std::string str(const size_t nframes_to_skip=0) const
top-level TTG namespace contains runtime-neutral functionality
void launch_lldb(int rank, const char *exec_name)
void launch_debugger(int rank, const char *exec_name, const char *cmd)
int rank(World world=default_execution_context())
void initialize_fpe()
Initializes the floating point exceptions.
void launch_gdb(int rank, const char *exec_name)