@@ -67,6 +67,7 @@ extern "C" {
6767#include <tlhelp32.h>
6868#endif
6969
70+ #include <assert.h>
7071#include <errno.h>
7172#include <fcntl.h>
7273#include <stddef.h>
@@ -165,6 +166,7 @@ _Py_RemoteDebug_InitProcHandle(proc_handle_t *handle, pid_t pid) {
165166 handle -> task = pid_to_task (handle -> pid );
166167 if (handle -> task == 0 ) {
167168 _set_debug_exception_cause (PyExc_RuntimeError , "Failed to initialize macOS process handle" );
169+ assert (PyErr_Occurred ());
168170 return -1 ;
169171 }
170172#elif defined(MS_WINDOWS )
@@ -174,6 +176,7 @@ _Py_RemoteDebug_InitProcHandle(proc_handle_t *handle, pid_t pid) {
174176 if (handle -> hProcess == NULL ) {
175177 PyErr_SetFromWindowsErr (0 );
176178 _set_debug_exception_cause (PyExc_RuntimeError , "Failed to initialize Windows process handle" );
179+ assert (PyErr_Occurred ());
177180 return -1 ;
178181 }
179182#elif defined(__linux__ )
@@ -248,6 +251,7 @@ return_section_address64(
248251 "mach_vm_region failed while parsing 64-bit Mach-O binary "
249252 "at base address 0x%lx (kern_return_t: %d)" ,
250253 base , ret );
254+ assert (PyErr_Occurred ());
251255 return 0 ;
252256 }
253257 }
@@ -311,6 +315,7 @@ return_section_address32(
311315 "mach_vm_region failed while parsing 32-bit Mach-O binary "
312316 "at base address 0x%lx (kern_return_t: %d)" ,
313317 base , ret );
318+ assert (PyErr_Occurred ());
314319 return 0 ;
315320 }
316321 }
@@ -352,13 +357,15 @@ return_section_address_fat(
352357 "Failed to determine CPU type via sysctlbyname "
353358 "for fat binary analysis at 0x%lx: %s" ,
354359 base , strerror (errno ));
360+ assert (PyErr_Occurred ());
355361 return 0 ;
356362 }
357363 if (sysctlbyname ("hw.cpu64bit_capable" , & is_abi64 , & abi64_size , NULL , 0 ) != 0 ) {
358364 PyErr_Format (PyExc_OSError ,
359365 "Failed to determine CPU ABI capability via sysctlbyname "
360366 "for fat binary analysis at 0x%lx: %s" ,
361367 base , strerror (errno ));
368+ assert (PyErr_Occurred ());
362369 return 0 ;
363370 }
364371
@@ -403,6 +410,7 @@ return_section_address_fat(
403410 "No matching architecture found for CPU type 0x%x "
404411 "in fat binary at base 0x%lx (%u architectures examined)" ,
405412 cpu , base , nfat_arch );
413+ assert (PyErr_Occurred ());
406414 return 0 ;
407415}
408416
@@ -414,6 +422,7 @@ search_section_in_file(const char* secname, char* path, uintptr_t base, mach_vm_
414422 PyErr_Format (PyExc_OSError ,
415423 "Cannot open binary file '%s' for section '%s' search: %s" ,
416424 path , secname , strerror (errno ));
425+ assert (PyErr_Occurred ());
417426 return 0 ;
418427 }
419428
@@ -423,6 +432,7 @@ search_section_in_file(const char* secname, char* path, uintptr_t base, mach_vm_
423432 "Cannot get file size for binary '%s' during section '%s' search: %s" ,
424433 path , secname , strerror (errno ));
425434 close (fd );
435+ assert (PyErr_Occurred ());
426436 return 0 ;
427437 }
428438
@@ -432,6 +442,7 @@ search_section_in_file(const char* secname, char* path, uintptr_t base, mach_vm_
432442 "Cannot memory map binary file '%s' (size: %lld bytes) for section '%s' search: %s" ,
433443 path , (long long )fs .st_size , secname , strerror (errno ));
434444 close (fd );
445+ assert (PyErr_Occurred ());
435446 return 0 ;
436447 }
437448
@@ -455,6 +466,7 @@ search_section_in_file(const char* secname, char* path, uintptr_t base, mach_vm_
455466 PyErr_Format (PyExc_RuntimeError ,
456467 "Unrecognized Mach-O magic number 0x%x in binary file '%s' for section '%s' search" ,
457468 magic , path , secname );
469+ assert (PyErr_Occurred ());
458470 break ;
459471 }
460472
@@ -486,6 +498,7 @@ pid_to_task(pid_t pid)
486498 "Cannot get task port for PID %d (kern_return_t: %d). "
487499 "This typically requires running as root or having the 'com.apple.system-task-ports' entitlement." ,
488500 pid , result );
501+ assert (PyErr_Occurred ());
489502 return 0 ;
490503 }
491504 return task ;
@@ -506,6 +519,7 @@ search_map_for_section(proc_handle_t *handle, const char* secname, const char* s
506519 "Cannot get task port for PID %d during section search" ,
507520 handle -> pid );
508521 }
522+ assert (PyErr_Occurred ());
509523 return 0 ;
510524 }
511525
@@ -671,6 +685,7 @@ search_linux_map_for_section(proc_handle_t *handle, const char* secname, const c
671685 PyErr_Format (PyExc_OSError ,
672686 "Cannot open process memory map file '%s' for PID %d section search: %s" ,
673687 maps_file_path , handle -> pid , strerror (errno ));
688+ assert (PyErr_Occurred ());
674689 return 0 ;
675690 }
676691
@@ -762,13 +777,15 @@ static int is_process_alive(HANDLE hProcess) {
762777}
763778
764779static void * analyze_pe (const wchar_t * mod_path , BYTE * remote_base , const char * secname ) {
780+ printf ("DEBUG: analyze_pe called with mod_path=%ls, remote_base=%p, secname=%s\n" , mod_path , remote_base , secname );
765781 HANDLE hFile = CreateFileW (mod_path , GENERIC_READ , FILE_SHARE_READ , NULL , OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL , NULL );
766782 if (hFile == INVALID_HANDLE_VALUE ) {
767783 PyErr_SetFromWindowsErr (0 );
768784 DWORD error = GetLastError ();
769785 PyErr_Format (PyExc_OSError ,
770786 "Cannot open PE file for section '%s' analysis (error %lu)" ,
771787 secname , error );
788+ printf ("DEBUG: analyze_pe failed to open file, error=%lu\n" , error );
772789 return NULL ;
773790 }
774791
@@ -820,10 +837,14 @@ static void* analyze_pe(const wchar_t* mod_path, BYTE* remote_base, const char*
820837 IMAGE_SECTION_HEADER * pSection_header = (IMAGE_SECTION_HEADER * )(mapView + pDOSHeader -> e_lfanew + sizeof (IMAGE_NT_HEADERS ));
821838 void * runtime_addr = NULL ;
822839
840+ printf ("DEBUG: analyze_pe searching for section '%s', NumberOfSections=%d\n" , secname , pNTHeaders -> FileHeader .NumberOfSections );
823841 for (int i = 0 ; i < pNTHeaders -> FileHeader .NumberOfSections ; i ++ ) {
824842 const char * name = (const char * )pSection_header [i ].Name ;
843+ printf ("DEBUG: analyze_pe section[%d] name='%.8s'\n" , i , name );
825844 if (strncmp (name , secname , IMAGE_SIZEOF_SHORT_NAME ) == 0 ) {
826845 runtime_addr = remote_base + pSection_header [i ].VirtualAddress ;
846+ printf ("DEBUG: analyze_pe found matching section at virtual address=0x%x, runtime_addr=%p\n" ,
847+ pSection_header [i ].VirtualAddress , runtime_addr );
827848 break ;
828849 }
829850 }
@@ -832,12 +853,25 @@ static void* analyze_pe(const wchar_t* mod_path, BYTE* remote_base, const char*
832853 CloseHandle (hMap );
833854 CloseHandle (hFile );
834855
856+ if (runtime_addr == NULL ) {
857+ printf ("DEBUG: analyze_pe section '%s' not found, setting error\n" , secname );
858+ // PyErr_Format(PyExc_RuntimeError,
859+ // "Section '%s' not found in PE file",
860+ // secname);
861+ } else {
862+ printf ("DEBUG: analyze_pe returning runtime_addr=%p\n" , runtime_addr );
863+ }
864+
865+ /* Assert that if we're returning NULL, an exception should be set somewhere up the call stack */
866+ // assert(runtime_addr != NULL || PyErr_Occurred());
835867 return runtime_addr ;
836868}
837869
838870
839871static uintptr_t
840872search_windows_map_for_section (proc_handle_t * handle , const char * secname , const wchar_t * substr ) {
873+ printf ("DEBUG: search_windows_map_for_section called with pid=%d, secname=%s, substr=%ls\n" ,
874+ handle -> pid , secname , substr );
841875 HANDLE hProcSnap ;
842876 do {
843877 hProcSnap = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE , handle -> pid );
@@ -850,25 +884,34 @@ search_windows_map_for_section(proc_handle_t* handle, const char* secname, const
850884 "Unable to create module snapshot for PID %d section '%s' "
851885 "search (error %lu). Check permissions or PID validity" ,
852886 handle -> pid , secname , error );
887+ assert (PyErr_Occurred ());
853888 return 0 ;
854889 }
855890
856891 MODULEENTRY32W moduleEntry ;
857892 moduleEntry .dwSize = sizeof (moduleEntry );
858893 void * runtime_addr = NULL ;
859894
895+ printf ("DEBUG: search_windows_map_for_section enumerating modules\n" );
860896 for (BOOL hasModule = Module32FirstW (hProcSnap , & moduleEntry ); hasModule ; hasModule = Module32NextW (hProcSnap , & moduleEntry )) {
897+ printf ("DEBUG: search_windows_map_for_section checking module: %ls\n" , moduleEntry .szModule );
861898 // Look for either python executable or DLL
862899 if (wcsstr (moduleEntry .szModule , substr )) {
900+ printf ("DEBUG: search_windows_map_for_section found matching module: %ls, path: %ls\n" ,
901+ moduleEntry .szModule , moduleEntry .szExePath );
863902 runtime_addr = analyze_pe (moduleEntry .szExePath , moduleEntry .modBaseAddr , secname );
864903 if (runtime_addr != NULL ) {
904+ printf ("DEBUG: search_windows_map_for_section analyze_pe succeeded, runtime_addr=%p\n" , runtime_addr );
865905 break ;
906+ } else {
907+ printf ("DEBUG: search_windows_map_for_section analyze_pe failed for module %ls\n" , moduleEntry .szModule );
866908 }
867909 }
868910 }
869911
870912 CloseHandle (hProcSnap );
871913
914+ printf ("DEBUG: search_windows_map_for_section returning runtime_addr=%p\n" , runtime_addr );
872915 return (uintptr_t )runtime_addr ;
873916}
874917
@@ -878,12 +921,16 @@ search_windows_map_for_section(proc_handle_t* handle, const char* secname, const
878921static uintptr_t
879922_Py_RemoteDebug_GetPyRuntimeAddress (proc_handle_t * handle )
880923{
924+ printf ("DEBUG: _Py_RemoteDebug_GetPyRuntimeAddress called for pid=%d\n" , handle -> pid );
881925 uintptr_t address ;
882926
883927#ifdef MS_WINDOWS
884928 // On Windows, search for 'python' in executable or DLL
929+ printf ("DEBUG: _Py_RemoteDebug_GetPyRuntimeAddress calling search_windows_map_for_section\n" );
885930 address = search_windows_map_for_section (handle , "PyRuntime" , L"python" );
931+ printf ("DEBUG: _Py_RemoteDebug_GetPyRuntimeAddress search_windows_map_for_section returned address=0x%lx\n" , address );
886932 if (address == 0 ) {
933+ printf ("DEBUG: _Py_RemoteDebug_GetPyRuntimeAddress address is 0, setting error\n" );
887934 // Error out: 'python' substring covers both executable and DLL
888935 PyObject * exc = PyErr_GetRaisedException ();
889936 PyErr_Format (PyExc_RuntimeError ,
@@ -923,9 +970,11 @@ _Py_RemoteDebug_GetPyRuntimeAddress(proc_handle_t* handle)
923970#else
924971 _set_debug_exception_cause (PyExc_RuntimeError ,
925972 "Reading the PyRuntime section is not supported on this platform" );
973+ assert (PyErr_Occurred ());
926974 return 0 ;
927975#endif
928976
977+ printf ("DEBUG: _Py_RemoteDebug_GetPyRuntimeAddress returning address=0x%lx\n" , address );
929978 return address ;
930979}
931980
@@ -942,6 +991,7 @@ open_proc_mem_fd(proc_handle_t *handle)
942991 PyErr_SetFromErrno (PyExc_OSError );
943992 _set_debug_exception_cause (PyExc_OSError ,
944993 "failed to open file %s: %s" , mem_file_path , strerror (errno ));
994+ assert (PyErr_Occurred ());
945995 return -1 ;
946996 }
947997 return 0 ;
@@ -974,6 +1024,7 @@ read_remote_memory_fallback(proc_handle_t *handle, uintptr_t remote_address, siz
9741024 "preadv failed for PID %d at address 0x%lx "
9751025 "(size %zu, partial read %zd bytes): %s" ,
9761026 handle -> pid , remote_address + result , len - result , result , strerror (errno ));
1027+ assert (PyErr_Occurred ());
9771028 return -1 ;
9781029 }
9791030
@@ -998,6 +1049,7 @@ _Py_RemoteDebug_ReadRemoteMemory(proc_handle_t *handle, uintptr_t remote_address
9981049 if (!is_process_alive (handle -> hProcess )) {
9991050 _set_errno (ESRCH );
10001051 PyErr_SetFromErrno (PyExc_OSError );
1052+ assert (PyErr_Occurred ());
10011053 return -1 ;
10021054 }
10031055 PyErr_SetFromWindowsErr (0 );
@@ -1006,6 +1058,7 @@ _Py_RemoteDebug_ReadRemoteMemory(proc_handle_t *handle, uintptr_t remote_address
10061058 "ReadProcessMemory failed for PID %d at address 0x%lx "
10071059 "(size %zu, partial read %zu bytes): Windows error %lu" ,
10081060 handle -> pid , remote_address + result , len - result , result , error );
1061+ assert (PyErr_Occurred ());
10091062 return -1 ;
10101063 }
10111064 result += read_bytes ;
@@ -1033,12 +1086,14 @@ _Py_RemoteDebug_ReadRemoteMemory(proc_handle_t *handle, uintptr_t remote_address
10331086 }
10341087 PyErr_SetFromErrno (PyExc_OSError );
10351088 if (errno == ESRCH ) {
1089+ assert (PyErr_Occurred ());
10361090 return -1 ;
10371091 }
10381092 _set_debug_exception_cause (PyExc_OSError ,
10391093 "process_vm_readv failed for PID %d at address 0x%lx "
10401094 "(size %zu, partial read %zd bytes): %s" ,
10411095 handle -> pid , remote_address + result , len - result , result , strerror (errno ));
1096+ assert (PyErr_Occurred ());
10421097 return -1 ;
10431098 }
10441099
@@ -1094,6 +1149,7 @@ _Py_RemoteDebug_ReadRemoteMemory(proc_handle_t *handle, uintptr_t remote_address
10941149 "(size %zu): kern_return_t %d" ,
10951150 handle -> pid , remote_address , len , kr );
10961151 }
1152+ assert (PyErr_Occurred ());
10971153 return -1 ;
10981154 }
10991155 return 0 ;
@@ -1108,6 +1164,7 @@ _Py_RemoteDebug_PagedReadRemoteMemory(proc_handle_t *handle,
11081164 size_t size ,
11091165 void * out )
11101166{
1167+ int result = 0 ;
11111168 size_t page_size = handle -> page_size ;
11121169 uintptr_t page_base = addr & ~(page_size - 1 );
11131170 size_t offset_in_page = addr - page_base ;
@@ -1136,6 +1193,7 @@ _Py_RemoteDebug_PagedReadRemoteMemory(proc_handle_t *handle,
11361193 "Cannot allocate %zu bytes for page cache entry "
11371194 "during read from PID %d at address 0x%lx" ,
11381195 page_size , handle -> pid , addr );
1196+ assert (PyErr_Occurred ());
11391197 return -1 ;
11401198 }
11411199 }
@@ -1155,7 +1213,9 @@ _Py_RemoteDebug_PagedReadRemoteMemory(proc_handle_t *handle,
11551213
11561214fallback :
11571215 // Cache full — fallback to uncached read
1158- return _Py_RemoteDebug_ReadRemoteMemory (handle , addr , size , out );
1216+ result = _Py_RemoteDebug_ReadRemoteMemory (handle , addr , size , out );
1217+ assert (result == 0 || PyErr_Occurred ());
1218+ return result ;
11591219}
11601220
11611221static int
@@ -1172,11 +1232,13 @@ _Py_RemoteDebug_ReadDebugOffsets(
11721232 handle -> pid );
11731233 }
11741234 _set_debug_exception_cause (PyExc_RuntimeError , "PyRuntime address lookup failed during debug offsets initialization" );
1235+ assert (PyErr_Occurred ());
11751236 return -1 ;
11761237 }
11771238 size_t size = sizeof (struct _Py_DebugOffsets );
11781239 if (0 != _Py_RemoteDebug_ReadRemoteMemory (handle , * runtime_start_address , size , debug_offsets )) {
11791240 _set_debug_exception_cause (PyExc_RuntimeError , "Failed to read debug offsets structure from remote process" );
1241+ assert (PyErr_Occurred ());
11801242 return -1 ;
11811243 }
11821244 return 0 ;
0 commit comments