20
20
#include <mach/mach_vm.h>
21
21
#include <mach/machine.h>
22
22
#include <libproc.h>
23
- #endif
23
+ #include <sys/proc.h>
24
+ #include <sys/sysctl.h>
25
+ #endif
24
26
25
27
#include <errno.h>
26
28
#include <fcntl.h>
31
33
#include <string.h>
32
34
#include <sys/mman.h>
33
35
#include <sys/param.h>
34
- #include <sys/proc.h>
35
36
#include <sys/stat.h>
36
- #include <sys/sysctl.h>
37
37
#include <sys/types.h>
38
38
#include <unistd.h>
39
39
@@ -166,6 +166,7 @@ static mach_port_t pid_to_task(pid_t pid) {
166
166
result = task_for_pid (mach_task_self (), pid , & task );
167
167
if (result != KERN_SUCCESS ) {
168
168
printf ("Call to task_for_pid failed on PID %d: %s" , pid , mach_error_string (result ));
169
+ PyErr_SetString (PyExc_PermissionError , "Cannot get task for PID" );
169
170
return 0 ;
170
171
}
171
172
return task ;
@@ -224,6 +225,55 @@ static void* get_py_runtime(pid_t pid) {
224
225
225
226
226
227
#ifdef __linux__
228
+ unsigned long
229
+ find_python_map_start_address (pid_t pid , char * result_filename ) {
230
+ char maps_file_path [64 ];
231
+ sprintf (maps_file_path , "/proc/%d/maps" , pid );
232
+
233
+ FILE * maps_file = fopen (maps_file_path , "r" );
234
+ if (maps_file == NULL ) {
235
+ PyErr_SetFromErrno (PyExc_OSError );
236
+ return 0 ;
237
+ }
238
+
239
+ int match_found = 0 ;
240
+
241
+ char line [256 ];
242
+ char map_filename [256 ];
243
+ unsigned long result_address = 0 ;
244
+ while (fgets (line , sizeof (line ), maps_file ) != NULL ) {
245
+ unsigned long start_address = 0 ;
246
+ sscanf (line , "%lx-%*x %*s %*s %*s %*s %s" , & start_address , map_filename );
247
+ char * filename = strrchr (map_filename , '/' );
248
+ if (filename != NULL ) {
249
+ filename ++ ; // Move past the '/'
250
+ } else {
251
+ filename = map_filename ; // No path, use the whole string
252
+ }
253
+
254
+ // Check if the filename starts with "python" or "libpython"
255
+ if (!match_found && strncmp (filename , "python" , 6 ) == 0 ) {
256
+ match_found = 1 ;
257
+ result_address = start_address ;
258
+ strcpy (result_filename , map_filename );
259
+ }
260
+ if (strncmp (filename , "libpython" , 9 ) == 0 ) {
261
+ match_found = 1 ;
262
+ result_address = start_address ;
263
+ strcpy (result_filename , map_filename );
264
+ break ;
265
+ }
266
+ }
267
+
268
+ fclose (maps_file );
269
+
270
+ if (!match_found ) {
271
+ map_filename [0 ] = '\0' ;
272
+ }
273
+
274
+ return result_address ;
275
+ }
276
+
227
277
void *
228
278
get_py_runtime (pid_t pid ) {
229
279
@@ -279,54 +329,7 @@ get_py_runtime(pid_t pid) {
279
329
return result ;
280
330
}
281
331
282
- unsigned long
283
- find_python_map_start_address (pid_t pid , char * result_filename ) {
284
- char maps_file_path [64 ];
285
- sprintf (maps_file_path , "/proc/%d/maps" , pid );
286
-
287
- FILE * maps_file = fopen (maps_file_path , "r" );
288
- if (maps_file == NULL ) {
289
- PyErr_SetFromErrno (PyExc_OSError );
290
- return 0 ;
291
- }
292
-
293
- int match_found = 0 ;
294
-
295
- char line [256 ];
296
- char map_filename [256 ];
297
- unsigned long result_address = 0 ;
298
- while (fgets (line , sizeof (line ), maps_file ) != NULL ) {
299
- unsigned long start_address = 0 ;
300
- sscanf (line , "%lx-%*x %*s %*s %*s %*s %s" , & start_address , map_filename );
301
- char * filename = strrchr (map_filename , '/' );
302
- if (filename != NULL ) {
303
- filename ++ ; // Move past the '/'
304
- } else {
305
- filename = map_filename ; // No path, use the whole string
306
- }
307
332
308
- // Check if the filename starts with "python" or "libpython"
309
- if (!match_found && strncmp (filename , "python" , 6 ) == 0 ) {
310
- match_found = 1 ;
311
- result_address = start_address ;
312
- strcpy (result_filename , map_filename );
313
- }
314
- if (strncmp (filename , "libpython" , 9 ) == 0 ) {
315
- match_found = 1 ;
316
- result_address = start_address ;
317
- strcpy (result_filename , map_filename );
318
- break ;
319
- }
320
- }
321
-
322
- fclose (maps_file );
323
-
324
- if (!match_found ) {
325
- map_filename [0 ] = '\0' ;
326
- }
327
-
328
- return result_address ;
329
- }
330
333
#endif
331
334
332
335
ssize_t
@@ -363,7 +366,7 @@ read_memory(pid_t pid, void* remote_address, ssize_t size, void* local_address)
363
366
return -1 ;
364
367
}
365
368
total_bytes_read = size ;
366
- #else
369
+ #else
367
370
return -1 ;
368
371
#endif
369
372
return total_bytes_read ;
@@ -391,8 +394,8 @@ read_string(pid_t pid, _Py_DebugOffsets *debug_offsets, void* address, char* buf
391
394
392
395
static PyObject *
393
396
get_stack_trace (PyObject * self , PyObject * args ) {
394
- #ifndef HAVE_PROCESS_VM_READV
395
- PyErr_SetString (PyExc_RuntimeError , "process_vm_readv not available on this platform" );
397
+ #if (!defined( __linux__ ) && !defined( __APPLE__ )) || (defined( __linux__ ) && ! HAVE_PROCESS_VM_READV )
398
+ PyErr_SetString (PyExc_RuntimeError , "get_strac_trace is not supported on this platform" );
396
399
return NULL ;
397
400
#endif
398
401
int pid ;
@@ -403,7 +406,9 @@ get_stack_trace(PyObject* self, PyObject* args) {
403
406
404
407
void * runtime_start_address = get_py_runtime (pid );
405
408
if (runtime_start_address == NULL ) {
406
- PyErr_SetString (PyExc_RuntimeError , "Failed to get .PyRuntime address" );
409
+ if (!PyErr_Occurred ()) {
410
+ PyErr_SetString (PyExc_RuntimeError , "Failed to get .PyRuntime address" );
411
+ }
407
412
return NULL ;
408
413
}
409
414
0 commit comments