py-spy icon indicating copy to clipboard operation
py-spy copied to clipboard

Fix macOS version identification and improve multiple-section support

Open comex opened this issue 1 year ago • 2 comments

Fixes #726, probably.

This could use some testing.

On some builds of Python on macOS, such as my Homebrew build of Python 3.13, the version ends up in the section __DATA,__common instead of __DATA,__bss. This difference appears to be caused by the use of ThinLTO. I'm not sure exactly why LLVM does that, but for py-spy's purposes, it suffices to scan both sections.

Implement this by having Binary store a Vec of (addr, size) pairs instead of just one bss_addr and bss_size.

While I'm at it:

  • Put the pyruntime section bounds into the same Vec rather than keeping it as a separate set of fields. This was already treated like another bss section.

  • Change all three executable-format parsing routines so that duplicate sections all go into the Vec, instead of them having to pick one BSS section.

  • Since we are now scanning more sections, there will be more harmless "didn't find anything" errors. Therefore, differentiate the cases by changing the return type of Version::scan_bytes from Result<X, Error> to Result<Option<X>, Error>. "Didn't find anything" now results in Ok(None), which the callers silently ignore, but the callers warn! on all other errors.

  • Improve error handling of check_interpreter_address along similar lines. It now returns an iterator of Results, which leaves it to the caller to decide how to expose the error from each individual address. The callers expose them either as warn! (if _PyRuntime was found and we really expect this address to be valid) or just debug! (if we're brute-forcing addresses).

    Maybe this one was overkill... In brute-force mode, it does waste time formatting errors that will never be shown most of the time, but in practice this shouldn't have noticeable impact: the number of addresses being brute-forced isn't that large.

comex avatar Feb 01 '25 23:02 comex

Solves Error: Failed to find python version from target process for me on macOS 14.7.2 (23H311) with Python 3.13.1 from MacPorts (python313 @3.13.1_0+lto+optimizations). Thanks, @comex!

droe avatar Feb 03 '25 14:02 droe

fwiw - this PR https://github.com/benfred/py-spy/pull/747 should make it so that we don't need to scan the BSS section for the version in python 3.12+

benfred avatar Jul 12 '25 20:07 benfred