Skip to content

Commit

Permalink
attach: Add breakpoints for more safe entry points
Browse files Browse the repository at this point in the history
`memray attach` needs to inject some custom code into the process it has
attached to. It does this by using `dlopen` and then calling a function
we control, but that can't be done just anywhere: we need to ensure
we're not currently in the middle of a call to `dlopen`, or in the
middle of a call to `malloc`, etc.

To work around this, we set a handful of breakpoints for known safe
(probably) places to call into our custom code, and load and call it
only when the breakpoint is hit.

Add 2 new breakpoints to our gdb script, on `PyCallable_Check` and
`PyError_CheckSignals`. Also, use `Py_AddPendingCall` to schedule a call
to `PyCallable_Check` on the main thread, in the hopes of triggering one
of our breakpoints to happen sooner.

For now, apply this only to our gdb script, and not to our lldb script.
Making the analogous changes to the lldb script results in lldb on Linux
stopping at an already-deleted breakpoint, and I haven't figured out
a workaround or fix for that yet.

Signed-off-by: Matt Wozniski <[email protected]>
  • Loading branch information
godlygeek committed May 30, 2024
1 parent 896b37d commit d7226c2
Showing 1 changed file with 9 additions and 2 deletions.
11 changes: 9 additions & 2 deletions src/memray/commands/_attach.gdb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ p PyMem_Realloc
p PyMem_Free

p "MEMRAY: Process is Python 3.7+."
set scheduler-locking on
call (int)Py_AddPendingCall(&PyCallable_Check, (void*)0)

# When updating this list, also update the "commands" call below,
# and the breakpoints hardcoded for lldb in attach.py
Expand All @@ -26,12 +28,17 @@ b PyMem_Malloc
b PyMem_Calloc
b PyMem_Realloc
b PyMem_Free
# Apply commands to all 8 breakpoints above
commands 1-8
b PyErr_CheckSignals
b PyCallable_Check
# Apply commands to all 10 breakpoints above
commands 1-10
bt
disable breakpoints
delete breakpoints
call (void*)dlopen($libpath, $rtld_now)
p (char*)dlerror()
eval "sharedlibrary %s", $libpath
p (int)memray_spawn_client($port) ? "FAILURE" : "SUCCESS"
end
set scheduler-locking off
continue

0 comments on commit d7226c2

Please sign in to comment.