@@ -116,6 +116,8 @@ typedef struct {
116
116
mach_port_t task ;
117
117
#elif defined(MS_WINDOWS )
118
118
HANDLE hProcess ;
119
+ #elif defined(__linux__ )
120
+ int memfd ;
119
121
#endif
120
122
page_cache_entry_t pages [MAX_PAGES ];
121
123
Py_ssize_t page_size ;
@@ -162,6 +164,8 @@ _Py_RemoteDebug_InitProcHandle(proc_handle_t *handle, pid_t pid) {
162
164
_set_debug_exception_cause (PyExc_RuntimeError , "Failed to initialize Windows process handle" );
163
165
return -1 ;
164
166
}
167
+ #elif defined(__linux__ )
168
+ handle -> memfd = -1 ;
165
169
#endif
166
170
handle -> page_size = get_page_size ();
167
171
for (int i = 0 ; i < MAX_PAGES ; i ++ ) {
@@ -179,6 +183,11 @@ _Py_RemoteDebug_CleanupProcHandle(proc_handle_t *handle) {
179
183
CloseHandle (handle -> hProcess );
180
184
handle -> hProcess = NULL ;
181
185
}
186
+ #elif defined(__linux__ )
187
+ if (handle -> memfd != -1 ) {
188
+ close (handle -> memfd );
189
+ handle -> memfd = -1 ;
190
+ }
182
191
#endif
183
192
handle -> pid = 0 ;
184
193
_Py_RemoteDebug_FreePageCache (handle );
@@ -907,6 +916,64 @@ _Py_RemoteDebug_GetPyRuntimeAddress(proc_handle_t* handle)
907
916
return address ;
908
917
}
909
918
919
+ #if defined(__linux__ ) && (HAVE_PREADV || HAVE_PWRITEV )
920
+ static int
921
+ open_proc_mem_fd (proc_handle_t * handle )
922
+ {
923
+ char mem_file_path [64 ];
924
+ sprintf (mem_file_path , "/proc/%d/mem" , handle -> pid );
925
+
926
+ handle -> memfd = open (mem_file_path , O_RDWR );
927
+ if (handle -> memfd == -1 ) {
928
+ PyErr_SetFromErrno (PyExc_OSError );
929
+ _set_debug_exception_cause (PyExc_OSError ,
930
+ "failed to open file %s: %s" , mem_file_path , strerror (errno ));
931
+ return -1 ;
932
+ }
933
+ return 0 ;
934
+ }
935
+ #endif // __linux__
936
+
937
+ #if defined(__linux__ )
938
+ static int
939
+ read_remote_memory_fallback (proc_handle_t * handle , uintptr_t remote_address , size_t len , void * dst )
940
+ {
941
+ #ifdef HAVE_PREADV
942
+ if (handle -> memfd == -1 ) {
943
+ if (open_proc_mem_fd (handle ) < 0 ) {
944
+ return -1 ;
945
+ }
946
+ }
947
+
948
+ struct iovec local [1 ];
949
+ Py_ssize_t result = 0 ;
950
+ Py_ssize_t read_bytes = 0 ;
951
+
952
+ do {
953
+ local [0 ].iov_base = (char * )dst + result ;
954
+ local [0 ].iov_len = len - result ;
955
+ off_t offset = remote_address + result ;
956
+
957
+ read_bytes = preadv (handle -> memfd , local , 1 , offset );
958
+ if (read_bytes < 0 ) {
959
+ PyErr_SetFromErrno (PyExc_OSError );
960
+ _set_debug_exception_cause (PyExc_OSError ,
961
+ "preadv failed for PID %d at address 0x%lx "
962
+ "(size %zu, partial read %zd bytes): %s" ,
963
+ handle -> pid , remote_address + result , len - result , result , strerror (errno ));
964
+ return -1 ;
965
+ }
966
+
967
+ result += read_bytes ;
968
+ } while ((size_t )read_bytes != local [0 ].iov_len );
969
+ return 0 ;
970
+ #else
971
+ PyErr_SetFromErrno (PyExc_OSError );
972
+ return -1 ;
973
+ #endif // HAVE_PREADV
974
+ }
975
+ #endif // __linux__
976
+
910
977
// Platform-independent memory read function
911
978
static int
912
979
_Py_RemoteDebug_ReadRemoteMemory (proc_handle_t * handle , uintptr_t remote_address , size_t len , void * dst )
@@ -928,6 +995,9 @@ _Py_RemoteDebug_ReadRemoteMemory(proc_handle_t *handle, uintptr_t remote_address
928
995
} while (result < len );
929
996
return 0 ;
930
997
#elif defined(__linux__ ) && HAVE_PROCESS_VM_READV
998
+ if (handle -> memfd != -1 ) {
999
+ return read_remote_memory_fallback (handle , remote_address , len , dst );
1000
+ }
931
1001
struct iovec local [1 ];
932
1002
struct iovec remote [1 ];
933
1003
Py_ssize_t result = 0 ;
@@ -941,6 +1011,9 @@ _Py_RemoteDebug_ReadRemoteMemory(proc_handle_t *handle, uintptr_t remote_address
941
1011
942
1012
read_bytes = process_vm_readv (handle -> pid , local , 1 , remote , 1 , 0 );
943
1013
if (read_bytes < 0 ) {
1014
+ if (errno == ENOSYS ) {
1015
+ return read_remote_memory_fallback (handle , remote_address , len , dst );
1016
+ }
944
1017
PyErr_SetFromErrno (PyExc_OSError );
945
1018
_set_debug_exception_cause (PyExc_OSError ,
946
1019
"process_vm_readv failed for PID %d at address 0x%lx "
0 commit comments