rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
98.61k stars 12.74k forks source link

Unable to instrument rust debug software #107033

Open Yuri6037 opened 1 year ago

Yuri6037 commented 1 year ago

When trying to instrument rust software built in debug mode under macOS, the instrument tool will throw Required kernel recording resources are in use by another document. Essentially you can't do any advanced instrumentation with debug executables built by rustc because rustc is not adding the proper entitlements to the built binary. It actually needs to add the get-task-allow entitlement when building in debug.

Meta

rustc --version --verbose:

rustc 1.66.1 (90743e729 2023-01-10)
binary: rustc
commit-hash: 90743e7298aca107ddaa0c202a4d3604e29bfeb6
commit-date: 2023-01-10
host: aarch64-apple-darwin
release: 1.66.1
LLVM version: 15.0.2

Workaround

Currently it is possible to workaround the issue but it's a pain. it's not possible to integrate this in Cargo as it requires accessing zsh.

Paste the following code in a zsh terminal opened at the target directory:

codesign -s - -v -f --entitlements =(echo -n '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd"\>
<plist version="1.0">
    <dict>
        <key>com.apple.security.get-task-allow</key>
        <true/>
    </dict>
</plist>') testbin

Unfortunately you must run the same pain every time you build the software.

madsmtm commented 4 months ago

I tried this today, and this issue is still relevant (though it is not specific to Rust, a basic C file compiled with Clang outside of Xcode exhibits the same problem).

Something that really confused me is that Instruments (at least in Xcode 15.3 using the Leaks tool) seems to cache certain information related to code signing, so you might have to restart Instruments if you tried to debug the application before adding the entitlement.

Also noting that another workaround is to disable SIP (which is bad advice in general, but still, it's a possibility). I think it should be sufficient to only disable the debugging restrictions, something like csrutil disable && csrutil enable --without debug.

BlackHoleFox commented 2 months ago

Maybe this should be a cargo issue? rustc isn't the place to make aware of entitlements imo unless we end up needing to directly inject them into generated binaries. rustc is definitely not the place to become aware of checking if the user already has entitlements files, etc.

I considered fixing this late last year but got sidetracked. I wanted Cargo to generate the same debugging entitlements XCode does (like shown above) when they aren't explicitly provided for Mach-O binaries and link them in when not compiling in release mode (a per-profile setting).

madsmtm commented 2 months ago

I think it's a good idea to consider how this may be integrated into Cargo!

I'll note too that the open-source reimplementation of codesign, rcodesign, is also able to do this process (rcodesign sign --entitlements-xml-path=entitlements.xml testbin), so that might be a way forwards when doing the integration (if we want to avoid shelling out to a different binary, as well as allowing building this from non-Apple platforms).