@@ -373,6 +373,52 @@ where
373373{
374374 // get the address of the main PyInterpreterState object from loaded symbols if we can
375375 // (this tends to be faster than scanning through the bss section)
376+ match get_interpreter_address_from_symbols ( python_info, process, version) {
377+ Ok ( addr) => {
378+ // Check that the symbol address is valid before returning
379+ match check_interpreter_addresses ( & [ addr] , & * python_info. maps , process, version) {
380+ Ok ( addr) => return Ok ( addr) ,
381+ Err ( _) => {
382+ warn ! ( "Interpreter address from symbol is invalid {:016x}" , addr) ;
383+ }
384+ } ;
385+ }
386+ Err ( err) => {
387+ info ! ( "Failed to get interpreter address from symbols {:?}, scanning BSS section from main binary" , err)
388+ }
389+ }
390+
391+ // try scanning the BSS section of the binary for things that might be the interpreterstate
392+ let err = if let Some ( ref pb) = python_info. python_binary {
393+ match get_interpreter_address_from_binary ( pb, & * python_info. maps , process, version) {
394+ Ok ( addr) => return Ok ( addr) ,
395+ err => Some ( err) ,
396+ }
397+ } else {
398+ None
399+ } ;
400+
401+ // Before giving up, try again if there is a libpython.so
402+ if let Some ( ref lpb) = python_info. libpython_binary {
403+ info ! ( "Failed to get interpreter from binary BSS, scanning libpython BSS" ) ;
404+ match get_interpreter_address_from_binary ( lpb, & * python_info. maps , process, version) {
405+ Ok ( addr) => Ok ( addr) ,
406+ lib_err => err. unwrap_or ( lib_err) ,
407+ }
408+ } else {
409+ err. expect ( "Both python and libpython are invalid." )
410+ }
411+ }
412+
413+ // Gets the address of the main PyInterpreterState object from loaded symbols
414+ fn get_interpreter_address_from_symbols < P > (
415+ python_info : & PythonProcessInfo ,
416+ process : & P ,
417+ version : & Version ,
418+ ) -> Result < usize , Error >
419+ where
420+ P : ProcessMemory ,
421+ {
376422 match version {
377423 Version {
378424 major : 3 ,
@@ -381,37 +427,34 @@ where
381427 } => {
382428 if let Some ( & pyruntime_addr) = python_info. get_symbol ( "_PyRuntime" ) {
383429 // figure out the interpreters_head location using the debug_offsets
384- let addr = match version {
430+ match version {
385431 Version {
386432 major : 3 ,
387433 minor : 14 ,
388434 ..
389435 } => {
390436 let debug_offsets: v3_14_0:: _Py_DebugOffsets =
391437 process. copy_struct ( pyruntime_addr as usize ) ?;
392- process. copy_struct (
393- pyruntime_addr as usize
394- + debug_offsets. runtime_state . interpreters_head as usize ,
395- ) ?
438+ return process
439+ . copy_struct (
440+ pyruntime_addr as usize
441+ + debug_offsets. runtime_state . interpreters_head as usize ,
442+ )
443+ . context (
444+ "Failed to copy py_debug_offsets.runtime_state.interpreters_head" ,
445+ ) ;
396446 }
397447 _ => {
398448 let debug_offsets: v3_13_0:: _Py_DebugOffsets =
399449 process. copy_struct ( pyruntime_addr as usize ) ?;
400- process. copy_struct (
401- pyruntime_addr as usize
402- + debug_offsets. runtime_state . interpreters_head as usize ,
403- ) ?
404- }
405- } ;
406-
407- // Make sure the interpreter addr is valid before returning
408- match check_interpreter_addresses ( & [ addr] , & * python_info. maps , process, version) {
409- Ok ( addr) => return Ok ( addr) ,
410- Err ( _) => {
411- warn ! (
412- "Interpreter address from _PyRuntime symbol is invalid {:016x}" ,
413- addr
414- ) ;
450+ return process
451+ . copy_struct (
452+ pyruntime_addr as usize
453+ + debug_offsets. runtime_state . interpreters_head as usize ,
454+ )
455+ . context (
456+ "Failed to copy py_debug_offsets.runtime_state.interpreters_head" ,
457+ ) ;
415458 }
416459 } ;
417460 }
@@ -422,57 +465,22 @@ where
422465 ..
423466 } => {
424467 if let Some ( & addr) = python_info. get_symbol ( "_PyRuntime" ) {
425- let addr = process
426- . copy_struct ( addr as usize + pyruntime:: get_interp_head_offset ( version) ) ?;
427-
428- // Make sure the interpreter addr is valid before returning
429- match check_interpreter_addresses ( & [ addr] , & * python_info. maps , process, version) {
430- Ok ( addr) => return Ok ( addr) ,
431- Err ( _) => {
432- warn ! (
433- "Interpreter address from _PyRuntime symbol is invalid {:016x}" ,
434- addr
435- ) ;
436- }
437- } ;
468+ return process
469+ . copy_struct ( addr as usize + pyruntime:: get_interp_head_offset ( version) )
470+ . context ( "Failed to copy interpreters_head" ) ;
438471 }
439472 }
440473 _ => {
441474 if let Some ( & addr) = python_info. get_symbol ( "interp_head" ) {
442- let addr = process. copy_struct ( addr as usize ) ?;
443- match check_interpreter_addresses ( & [ addr] , & * python_info. maps , process, version) {
444- Ok ( addr) => return Ok ( addr) ,
445- Err ( _) => {
446- warn ! (
447- "Interpreter address from interp_head symbol is invalid {:016x}" ,
448- addr
449- ) ;
450- }
451- } ;
475+ return process
476+ . copy_struct ( addr as usize )
477+ . context ( "Failed to copy interp_head" ) ;
452478 }
453479 }
454480 } ;
455- info ! ( "Failed to find runtime address from symbols, scanning BSS section from main binary" ) ;
456-
457- // try scanning the BSS section of the binary for things that might be the interpreterstate
458- let err = if let Some ( ref pb) = python_info. python_binary {
459- match get_interpreter_address_from_binary ( pb, & * python_info. maps , process, version) {
460- Ok ( addr) => return Ok ( addr) ,
461- err => Some ( err) ,
462- }
463- } else {
464- None
465- } ;
466- // Before giving up, try again if there is a libpython.so
467- if let Some ( ref lpb) = python_info. libpython_binary {
468- info ! ( "Failed to get interpreter from binary BSS, scanning libpython BSS" ) ;
469- match get_interpreter_address_from_binary ( lpb, & * python_info. maps , process, version) {
470- Ok ( addr) => Ok ( addr) ,
471- lib_err => err. unwrap_or ( lib_err) ,
472- }
473- } else {
474- err. expect ( "Both python and libpython are invalid." )
475- }
481+ return Err ( format_err ! (
482+ "Failed to find _PyRuntime address from symbols"
483+ ) ) ;
476484}
477485
478486fn get_interpreter_address_from_binary < P > (
0 commit comments