@@ -298,6 +298,36 @@ pub fn get_python_version<P>(python_info: &PythonProcessInfo, process: &P) -> Re
298298where
299299 P : ProcessMemory ,
300300{
301+ // Try getting the Py_Version symbol (points to 32 bit encoded version)
302+ if let Some ( & addr) = python_info. get_symbol ( "Py_Version" ) {
303+ let version: u32 = process
304+ . copy_struct ( addr as usize )
305+ . context ( "Failed to copy Py_Version symbol" ) ?;
306+
307+ // decode u32 version via the _Py_PACK_FULL_VERSION logic
308+ let major: u64 = ( ( version >> 24 ) & 0xff ) . into ( ) ;
309+ let minor: u64 = ( ( version >> 16 ) & 0xff ) . into ( ) ;
310+ let patch: u64 = ( ( version >> 8 ) & 0xff ) . into ( ) ;
311+ let release_level = ( version >> 4 ) & 0xf ;
312+ let release_serial = ( version) & 0xf ;
313+ let release_flags = match release_level {
314+ 0xA => format ! ( "a{}" , release_serial) ,
315+ 0xB => format ! ( "b{}" , release_serial) ,
316+ 0xC => format ! ( "rc{}" , release_serial) ,
317+ _ => "" . to_owned ( ) ,
318+ } ;
319+
320+ let version = Version {
321+ major,
322+ minor,
323+ patch,
324+ release_flags,
325+ build_metadata : None ,
326+ } ;
327+ info ! ( "Got version {} from Py_Version symbol" , version) ;
328+ return Ok ( version) ;
329+ }
330+
301331 // If possible, grab the sys.version string from the processes memory (mac osx).
302332 if let Some ( & addr) = python_info
303333 . get_symbol ( "Py_GetVersion.version" )
0 commit comments