mirror of
https://github.com/python/cpython.git
synced 2026-04-14 15:50:50 +00:00
[3.14] gh-144563: Fix remote debugging with duplicate libpython mappings from ctypes (GH-144595) (#144655)
This commit is contained in:
parent
8b4210c30e
commit
616e611844
4 changed files with 95 additions and 14 deletions
|
|
@ -133,6 +133,31 @@ typedef struct {
|
|||
Py_ssize_t page_size;
|
||||
} proc_handle_t;
|
||||
|
||||
// Forward declaration for use in validation function
|
||||
static int
|
||||
_Py_RemoteDebug_ReadRemoteMemory(proc_handle_t *handle, uintptr_t remote_address, size_t len, void* dst);
|
||||
|
||||
// Optional callback to validate a candidate section address found during
|
||||
// memory map searches. Returns 1 if the address is valid, 0 to skip it.
|
||||
// This allows callers to filter out duplicate/stale mappings (e.g. from
|
||||
// ctypes dlopen) whose sections were never initialized.
|
||||
typedef int (*section_validator_t)(proc_handle_t *handle, uintptr_t address);
|
||||
|
||||
// Validate that a candidate address starts with _Py_Debug_Cookie.
|
||||
static int
|
||||
_Py_RemoteDebug_ValidatePyRuntimeCookie(proc_handle_t *handle, uintptr_t address)
|
||||
{
|
||||
if (address == 0) {
|
||||
return 0;
|
||||
}
|
||||
char buf[sizeof(_Py_Debug_Cookie) - 1];
|
||||
if (_Py_RemoteDebug_ReadRemoteMemory(handle, address, sizeof(buf), buf) != 0) {
|
||||
PyErr_Clear();
|
||||
return 0;
|
||||
}
|
||||
return memcmp(buf, _Py_Debug_Cookie, sizeof(buf)) == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_Py_RemoteDebug_FreePageCache(proc_handle_t *handle)
|
||||
{
|
||||
|
|
@ -490,7 +515,8 @@ pid_to_task(pid_t pid)
|
|||
}
|
||||
|
||||
static uintptr_t
|
||||
search_map_for_section(proc_handle_t *handle, const char* secname, const char* substr) {
|
||||
search_map_for_section(proc_handle_t *handle, const char* secname, const char* substr,
|
||||
section_validator_t validator) {
|
||||
mach_vm_address_t address = 0;
|
||||
mach_vm_size_t size = 0;
|
||||
mach_msg_type_number_t count = sizeof(vm_region_basic_info_data_64_t);
|
||||
|
|
@ -542,7 +568,9 @@ search_map_for_section(proc_handle_t *handle, const char* secname, const char* s
|
|||
if (strncmp(filename, substr, strlen(substr)) == 0) {
|
||||
uintptr_t result = search_section_in_file(
|
||||
secname, map_filename, address, size, proc_ref);
|
||||
if (result != 0) {
|
||||
if (result != 0
|
||||
&& (validator == NULL || validator(handle, result)))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -659,7 +687,8 @@ search_elf_file_for_section(
|
|||
}
|
||||
|
||||
static uintptr_t
|
||||
search_linux_map_for_section(proc_handle_t *handle, const char* secname, const char* substr)
|
||||
search_linux_map_for_section(proc_handle_t *handle, const char* secname, const char* substr,
|
||||
section_validator_t validator)
|
||||
{
|
||||
char maps_file_path[64];
|
||||
sprintf(maps_file_path, "/proc/%d/maps", handle->pid);
|
||||
|
|
@ -734,9 +763,12 @@ search_linux_map_for_section(proc_handle_t *handle, const char* secname, const c
|
|||
|
||||
if (strstr(filename, substr)) {
|
||||
retval = search_elf_file_for_section(handle, secname, start, path);
|
||||
if (retval) {
|
||||
if (retval
|
||||
&& (validator == NULL || validator(handle, retval)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
retval = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -832,7 +864,8 @@ static void* analyze_pe(const wchar_t* mod_path, BYTE* remote_base, const char*
|
|||
|
||||
|
||||
static uintptr_t
|
||||
search_windows_map_for_section(proc_handle_t* handle, const char* secname, const wchar_t* substr) {
|
||||
search_windows_map_for_section(proc_handle_t* handle, const char* secname, const wchar_t* substr,
|
||||
section_validator_t validator) {
|
||||
HANDLE hProcSnap;
|
||||
do {
|
||||
hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, handle->pid);
|
||||
|
|
@ -855,8 +888,11 @@ search_windows_map_for_section(proc_handle_t* handle, const char* secname, const
|
|||
for (BOOL hasModule = Module32FirstW(hProcSnap, &moduleEntry); hasModule; hasModule = Module32NextW(hProcSnap, &moduleEntry)) {
|
||||
// Look for either python executable or DLL
|
||||
if (wcsstr(moduleEntry.szModule, substr)) {
|
||||
runtime_addr = analyze_pe(moduleEntry.szExePath, moduleEntry.modBaseAddr, secname);
|
||||
if (runtime_addr != NULL) {
|
||||
void *candidate = analyze_pe(moduleEntry.szExePath, moduleEntry.modBaseAddr, secname);
|
||||
if (candidate != NULL
|
||||
&& (validator == NULL || validator(handle, (uintptr_t)candidate)))
|
||||
{
|
||||
runtime_addr = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -877,7 +913,8 @@ _Py_RemoteDebug_GetPyRuntimeAddress(proc_handle_t* handle)
|
|||
|
||||
#ifdef MS_WINDOWS
|
||||
// On Windows, search for 'python' in executable or DLL
|
||||
address = search_windows_map_for_section(handle, "PyRuntime", L"python");
|
||||
address = search_windows_map_for_section(handle, "PyRuntime", L"python",
|
||||
_Py_RemoteDebug_ValidatePyRuntimeCookie);
|
||||
if (address == 0) {
|
||||
// Error out: 'python' substring covers both executable and DLL
|
||||
PyObject *exc = PyErr_GetRaisedException();
|
||||
|
|
@ -888,7 +925,8 @@ _Py_RemoteDebug_GetPyRuntimeAddress(proc_handle_t* handle)
|
|||
}
|
||||
#elif defined(__linux__)
|
||||
// On Linux, search for 'python' in executable or DLL
|
||||
address = search_linux_map_for_section(handle, "PyRuntime", "python");
|
||||
address = search_linux_map_for_section(handle, "PyRuntime", "python",
|
||||
_Py_RemoteDebug_ValidatePyRuntimeCookie);
|
||||
if (address == 0) {
|
||||
// Error out: 'python' substring covers both executable and DLL
|
||||
PyObject *exc = PyErr_GetRaisedException();
|
||||
|
|
@ -902,7 +940,8 @@ _Py_RemoteDebug_GetPyRuntimeAddress(proc_handle_t* handle)
|
|||
const char* candidates[] = {"libpython", "python", "Python", NULL};
|
||||
for (const char** candidate = candidates; *candidate; candidate++) {
|
||||
PyErr_Clear();
|
||||
address = search_map_for_section(handle, "PyRuntime", *candidate);
|
||||
address = search_map_for_section(handle, "PyRuntime", *candidate,
|
||||
_Py_RemoteDebug_ValidatePyRuntimeCookie);
|
||||
if (address != 0) {
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue