mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 17:28:07 +00:00
update logic for tracking new threads
This commit is contained in:
@@ -1430,11 +1430,9 @@ dmn_lnx_handle_not_attached(Arena *arena, DMN_EventList *events)
|
|||||||
e->error_kind = DMN_ErrorKind_NotAttached;
|
e->error_kind = DMN_ErrorKind_NotAttached;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal DMN_LNX_Entity *
|
internal void
|
||||||
dmn_lnx_handle_create_thread(Arena *arena, DMN_EventList *events, DMN_LNX_Entity *process, pid_t tid)
|
dmn_lnx_init_create_thread(Arena *arena, DMN_EventList *events, DMN_LNX_Entity *process, DMN_LNX_Entity *thread)
|
||||||
{
|
{
|
||||||
DMN_LNX_Entity *thread = dmn_lnx_entity_alloc(process, DMN_LNX_EntityKind_Thread);
|
|
||||||
thread->id = tid;
|
|
||||||
thread->arch = process->arch;
|
thread->arch = process->arch;
|
||||||
thread->reg_block = push_array(process->arena, U8, regs_block_size_from_arch(process->arch));
|
thread->reg_block = push_array(process->arena, U8, regs_block_size_from_arch(process->arch));
|
||||||
thread->thread_state = DMN_LNX_ThreadState_Stopped;
|
thread->thread_state = DMN_LNX_ThreadState_Stopped;
|
||||||
@@ -1462,7 +1460,14 @@ dmn_lnx_handle_create_thread(Arena *arena, DMN_EventList *events, DMN_LNX_Entity
|
|||||||
e->code = thread->id;
|
e->code = thread->id;
|
||||||
|
|
||||||
process->thread_count += 1;
|
process->thread_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal DMN_LNX_Entity *
|
||||||
|
dmn_lnx_handle_create_thread(Arena *arena, DMN_EventList *events, DMN_LNX_Entity *process, pid_t tid)
|
||||||
|
{
|
||||||
|
DMN_LNX_Entity *thread = dmn_lnx_entity_alloc(process, DMN_LNX_EntityKind_Thread);
|
||||||
|
thread->id = tid;
|
||||||
|
dmn_lnx_init_create_thread(arena, events, process, thread);
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1786,7 +1791,7 @@ dmn_lnx_handle_load_module(Arena *arena, DMN_EventList *events, DMN_LNX_Entity *
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
dmn_lnx_hanlde_unload_module(Arena *arena, DMN_EventList *events, DMN_LNX_Entity *process, U64 name_space_id, U64 rdebug_vaddr)
|
dmn_lnx_handle_unload_module(Arena *arena, DMN_EventList *events, DMN_LNX_Entity *process, U64 name_space_id, U64 rdebug_vaddr)
|
||||||
{
|
{
|
||||||
Temp scratch = scratch_begin(&arena, 1);
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
|
|
||||||
@@ -1917,7 +1922,7 @@ dmn_lnx_handle_breakpoint(Arena *arena, DMN_EventList *events, DMN_ActiveTrap *u
|
|||||||
if(!stap_read_arg_u(probe->args.v[0], process->arch, thread->reg_block, dmn_lnx_stap_memory_read, process, &name_space_id)) { goto unmap_complete_exit; }
|
if(!stap_read_arg_u(probe->args.v[0], process->arch, thread->reg_block, dmn_lnx_stap_memory_read, process, &name_space_id)) { goto unmap_complete_exit; }
|
||||||
if(!stap_read_arg_u(probe->args.v[1], process->arch, thread->reg_block, dmn_lnx_stap_memory_read, process, &rdebug_vaddr)) { goto unmap_complete_exit; }
|
if(!stap_read_arg_u(probe->args.v[1], process->arch, thread->reg_block, dmn_lnx_stap_memory_read, process, &rdebug_vaddr)) { goto unmap_complete_exit; }
|
||||||
|
|
||||||
dmn_lnx_hanlde_unload_module(arena, events, process, name_space_id, rdebug_vaddr);
|
dmn_lnx_handle_unload_module(arena, events, process, name_space_id, rdebug_vaddr);
|
||||||
|
|
||||||
is_unmap_completed = 1;
|
is_unmap_completed = 1;
|
||||||
unmap_complete_exit:;
|
unmap_complete_exit:;
|
||||||
@@ -2573,7 +2578,8 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
|||||||
if(wifstopped || wifsignaled || wifexited)
|
if(wifstopped || wifsignaled || wifexited)
|
||||||
{
|
{
|
||||||
DMN_LNX_Entity *thread = dmn_lnx_thread_from_pid(wait_id);
|
DMN_LNX_Entity *thread = dmn_lnx_thread_from_pid(wait_id);
|
||||||
|
if(thread->thread_state != DMN_LNX_ThreadState_PendingCreation)
|
||||||
|
{
|
||||||
// kernel may send multiple stop signals for the same thread,
|
// kernel may send multiple stop signals for the same thread,
|
||||||
// so count first stop signal and ignore subsequent signals
|
// so count first stop signal and ignore subsequent signals
|
||||||
B32 is_first_thread_to_stop = 0;
|
B32 is_first_thread_to_stop = 0;
|
||||||
@@ -2609,6 +2615,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// normal child exit via _exit or exit()
|
// normal child exit via _exit or exit()
|
||||||
if(wifexited)
|
if(wifexited)
|
||||||
@@ -2627,7 +2634,7 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
|||||||
// read thread registers
|
// read thread registers
|
||||||
{
|
{
|
||||||
DMN_LNX_Entity *thread = dmn_lnx_thread_from_pid(wait_id);
|
DMN_LNX_Entity *thread = dmn_lnx_thread_from_pid(wait_id);
|
||||||
if(thread != dmn_lnx_nil_entity)
|
if(thread != dmn_lnx_nil_entity && thread->thread_state != DMN_LNX_ThreadState_PendingCreation)
|
||||||
{
|
{
|
||||||
thread->is_reg_block_dirty = !dmn_lnx_thread_read_reg_block(thread);
|
thread->is_reg_block_dirty = !dmn_lnx_thread_read_reg_block(thread);
|
||||||
Assert(!thread->is_reg_block_dirty);
|
Assert(!thread->is_reg_block_dirty);
|
||||||
@@ -2729,12 +2736,26 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
|||||||
}break;
|
}break;
|
||||||
case PTRACE_EVENT_CLONE:
|
case PTRACE_EVENT_CLONE:
|
||||||
{
|
{
|
||||||
|
// kernel stopped the parent just before scheduling the child to
|
||||||
|
// give us a chance to prepare to trace it; next event for the child
|
||||||
|
// will be a PTRACE_EVENT_STOP
|
||||||
|
|
||||||
pid_t new_pid;
|
pid_t new_pid;
|
||||||
if(OS_LNX_RETRY_ON_EINTR(ptrace(PTRACE_GETEVENTMSG, wait_id, 0, &new_pid)) >= 0)
|
if(OS_LNX_RETRY_ON_EINTR(ptrace(PTRACE_GETEVENTMSG, wait_id, 0, &new_pid)) >= 0)
|
||||||
{
|
{
|
||||||
DMN_LNX_Entity *thread = dmn_lnx_thread_from_pid(wait_id);
|
DMN_LNX_Entity *thread = dmn_lnx_thread_from_pid(wait_id);
|
||||||
DMN_LNX_Entity *process = thread->parent;
|
DMN_LNX_Entity *process = thread->parent;
|
||||||
dmn_lnx_handle_create_thread(arena, &events, process, new_pid);
|
|
||||||
|
// create a new partially inited thread
|
||||||
|
DMN_LNX_Entity *new_thread = dmn_lnx_entity_alloc(process, DMN_LNX_EntityKind_Thread);
|
||||||
|
new_thread->id = new_pid;
|
||||||
|
new_thread->thread_state = DMN_LNX_ThreadState_PendingCreation;
|
||||||
|
|
||||||
|
// create mapping from tid -> new thread
|
||||||
|
hash_table_push_u64_raw(dmn_lnx_state->arena, dmn_lnx_state->tid_ht, new_thread->id, new_thread);
|
||||||
|
|
||||||
|
// do not exit the wait loop before new threads are inited
|
||||||
|
dmn_lnx_state->threads_pending_creation += 1;
|
||||||
}
|
}
|
||||||
else { Assert(0 && "failed to get new tid"); }
|
else { Assert(0 && "failed to get new tid"); }
|
||||||
}break;
|
}break;
|
||||||
@@ -2772,11 +2793,24 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
|||||||
{
|
{
|
||||||
DMN_LNX_Entity *thread = dmn_lnx_thread_from_pid(wait_id);
|
DMN_LNX_Entity *thread = dmn_lnx_thread_from_pid(wait_id);
|
||||||
DMN_LNX_Entity *process = thread->parent;
|
DMN_LNX_Entity *process = thread->parent;
|
||||||
|
|
||||||
|
if(thread->thread_state == DMN_LNX_ThreadState_PendingCreation)
|
||||||
|
{
|
||||||
|
// finish thread init
|
||||||
|
dmn_lnx_init_create_thread(arena, &events, process, thread);
|
||||||
|
|
||||||
|
// update global thread counter
|
||||||
|
AssertAlways(dmn_lnx_state->threads_pending_creation > 0);
|
||||||
|
dmn_lnx_state->threads_pending_creation -= 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if(process->expect_user_interrupt)
|
if(process->expect_user_interrupt)
|
||||||
{
|
{
|
||||||
process->expect_user_interrupt = 0;
|
process->expect_user_interrupt = 0;
|
||||||
dmn_lnx_handle_halt(arena, &events);
|
dmn_lnx_handle_halt(arena, &events);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}break;
|
}break;
|
||||||
default: { Assert(0 && "unexpected ptrace code"); } break;
|
default: { Assert(0 && "unexpected ptrace code"); } break;
|
||||||
}
|
}
|
||||||
@@ -2804,8 +2838,8 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls)
|
|||||||
}
|
}
|
||||||
else { Assert(0 && "unexpected stop code"); }
|
else { Assert(0 && "unexpected stop code"); }
|
||||||
|
|
||||||
// do not wait if all threads are stopped and there are no launching processes
|
// do not wait if all threads are stopped, there are no launching processes, and all threads were created
|
||||||
if(stopped_threads >= running_threads.count && dmn_lnx_state->pending_procs.count == 0)
|
if(stopped_threads >= running_threads.count && dmn_lnx_state->pending_procs.count == 0 && dmn_lnx_state->threads_pending_creation == 0)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,12 +63,13 @@ StaticAssert(sizeof(DMN_LNX_UserX64) == 912, g_dmn_lnx_user_x64_size_check);
|
|||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
typedef struct
|
typedef struct DMN_LNX_DbDesc DMN_LNX_DbDesc;
|
||||||
|
struct DMN_LNX_DbDesc
|
||||||
{
|
{
|
||||||
U32 bit_size;
|
U32 bit_size;
|
||||||
U32 count;
|
U32 count;
|
||||||
U32 offset;
|
U32 offset;
|
||||||
} DMN_LNX_DbDesc;
|
};
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ SDT Probes
|
//~ SDT Probes
|
||||||
@@ -173,6 +174,7 @@ typedef enum DMN_LNX_ThreadState
|
|||||||
DMN_LNX_ThreadState_Running,
|
DMN_LNX_ThreadState_Running,
|
||||||
DMN_LNX_ThreadState_Stopped,
|
DMN_LNX_ThreadState_Stopped,
|
||||||
DMN_LNX_ThreadState_Exited,
|
DMN_LNX_ThreadState_Exited,
|
||||||
|
DMN_LNX_ThreadState_PendingCreation,
|
||||||
} DMN_LNX_ThreadState;
|
} DMN_LNX_ThreadState;
|
||||||
|
|
||||||
typedef struct DMN_LNX_Entity DMN_LNX_Entity;
|
typedef struct DMN_LNX_Entity DMN_LNX_Entity;
|
||||||
@@ -309,6 +311,8 @@ struct DMN_LNX_State
|
|||||||
DMN_LNX_ProcessLaunchList pending_procs;
|
DMN_LNX_ProcessLaunchList pending_procs;
|
||||||
DMN_LNX_ProcessLaunchList free_pids;
|
DMN_LNX_ProcessLaunchList free_pids;
|
||||||
|
|
||||||
|
U64 threads_pending_creation;
|
||||||
|
|
||||||
// halter
|
// halter
|
||||||
Mutex halter_mutex;
|
Mutex halter_mutex;
|
||||||
pid_t halter_tid;
|
pid_t halter_tid;
|
||||||
|
|||||||
Reference in New Issue
Block a user