29#ifndef TTG_UTIL_MISC_BUG_H_
30#define TTG_UTIL_MISC_BUG_H_
36#include <unordered_map>
91 get_instance() = std::shared_ptr<Pool>(
new Pool(threads));
96 auto result = get_instance();
97 assert(result &&
"Pool::instance() called but Pool::initialize_instance() had not been called");
109 const auto it = pool_.find(thread);
110 assert(it != pool_.end());
112 for (
auto &watchpt_ptr : it->second) {
113 if (watchpt_ptr && watchpt_ptr->address() == addr)
return *
this;
117 auto &watchpt_ptr = it->second[dr];
120 std::make_shared<MemoryWatchpoint_x86_64>(addr,
size, cond,
static_cast<DebugRegister>(dr), thread);
132 const auto it = pool_.find(thread);
133 assert(it != pool_.end());
134 for (
auto &watchpt_ptr : it->second) {
135 if (watchpt_ptr && watchpt_ptr->address() == addr)
return watchpt_ptr.get();
144 const auto it = pool_.find(thread);
145 assert(it != pool_.end());
146 for (
auto &watchpt_ptr : it->second) {
147 if (watchpt_ptr && watchpt_ptr->address() == addr) {
156 std::unordered_map<const pthread_t *, std::vector<std::shared_ptr<MemoryWatchpoint_x86_64>>> pool_;
163 explicit Pool(
const std::vector<const pthread_t *> &threads) {
164 for (
const auto &thread : threads) {
165 assert(thread !=
nullptr);
170 static std::shared_ptr<Pool> &get_instance() {
171 static std::shared_ptr<Pool> instance_;
186 : addr_(addr), size_(
size), cond_(cond), dr_(dr), thread_(thread) {
202 const pthread_t *thread_;
206 return (state | cond << 16 |
size << 24) << (2 * reg);
213 void init(
bool create) {
214#if defined(__APPLE__) && defined(__x86_64__)
216 mach_msg_type_number_t dr_count = x86_DEBUG_STATE_COUNT;
218 mach_port_t target_mach_thread = pthread_mach_thread_np(*thread_);
221 thread_get_state(target_mach_thread, x86_DEBUG_STATE,
reinterpret_cast<thread_state_t
>(&dr), &dr_count);
223 if (create && rc != KERN_SUCCESS)
224 throw std::runtime_error(
"MemoryWatchpoint_x86_64::MemoryWatchpoint_x86_64(): thread_get_state failed");
228 dr.uds.ds64.__dr0 =
reinterpret_cast<uint64_t
>(addr_);
231 dr.uds.ds64.__dr1 =
reinterpret_cast<uint64_t
>(addr_);
234 dr.uds.ds64.__dr2 =
reinterpret_cast<uint64_t
>(addr_);
237 dr.uds.ds64.__dr3 =
reinterpret_cast<uint64_t
>(addr_);
241 dr.uds.ds64.__dr7 &= ~MakeMask(dr_);
245 rc = thread_set_state(target_mach_thread, x86_DEBUG_STATE,
reinterpret_cast<thread_state_t
>(&dr), dr_count);
247 if (create && rc != KERN_SUCCESS)
248 throw std::runtime_error(
"MemoryWatchpoint_x86_64::MemoryWatchpoint_x86_64(): thread_set_state failed");
296 static void __traceback(
const std::string &prefix,
const char *reason =
nullptr);
302 explicit Debugger(
const char *exec =
nullptr);
307 virtual void debug(
const char *reason);
315 virtual void traceback(
const char *reason);
328 virtual void handle(
int sig);
344 virtual void set_cmd(
const char *);
350 virtual void set_exec(
const char *);
362 void resolve_cmd_alias();
virtual void set_cmd(const char *)
virtual void set_prefix(const char *p)
This sets a prefix which preceeds all messages printing by Debugger.
virtual void got_signal(int sig)
Called when signal sig is received. This is mainly for internal use.
static void set_default_debugger(const std::shared_ptr< Debugger > &)
Set the global default debugger. The initial value is null.
static void __traceback(const std::string &prefix, const char *reason=nullptr)
volatile int debugger_ready_
virtual void handle_defaults()
This calls handle(int) with all of the major signals.
virtual void set_wait_for_debugger(int)
virtual void traceback(const char *reason)
static std::shared_ptr< Debugger > default_debugger()
Return the global default debugger.
virtual void default_cmd()
Calls set_cmd with a hopefully suitable default.
virtual void set_exit_on_signal(int)
Turn on or off exit after a signel. The default is on.
virtual void handle(int sig)
The Debugger will be activated when sig is caught.
virtual void debug(const char *reason)
virtual void release(int sig)
Reverts the effect of handle(sig) , i.e. the Debugger will not be activated when sig is caught.
static std::shared_ptr< Debugger > default_debugger_
virtual void set_debug_on_signal(int)
Turn on or off debugging on a signel. The default is on.
virtual void set_exec(const char *)
virtual void set_traceback_on_signal(int)
Turn on or off traceback on a signel. The default is on.
a singleton pool of MemoryWatchpoint objects
static std::shared_ptr< Pool > instance()
accesses the unique pool; asserts that the default instance has been initialized by calling initializ...
Pool & set(void *addr, Size size, Condition cond, const pthread_t *thread)
MemoryWatchpoint_x86_64 * find(void *addr, const pthread_t *thread)
static void initialize_instance(const std::vector< const pthread_t * > &threads)
Pool & clear(void *addr, const pthread_t *thread)
static constexpr const size_t nwatchpoints_per_thread
MemoryWatchpoint represents a hardware watchpoint for a memory location Implements a memory watchpoin...
MemoryWatchpoint_x86_64(void *addr, Size size, Condition cond, DebugRegister dr, const pthread_t *thread)
creates a MemoryWatchpoint watching memory window [addr,addr+size) for condition cond from threads th...
Condition condition() const
friend class MemoryWatchPool
~MemoryWatchpoint_x86_64()
DebugRegister debug_register() 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)