-
Notifications
You must be signed in to change notification settings - Fork 68
Allow attaching to existing macOS process #190
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Hrm. Being able to attach to newly created children seems very complicated, borderline not doable. In order to write to the environment, the magic seems to be the
Spawning a thread in the target and executing code seems like maybe more possible, especially if that code can be Given all this, I'm inclined to just not support attaching to new children when profiling a target process. It should be possible to attach to existing children, though. |
For profiling child processes, we could poll |
And for profiling system-wide, if it's even possible with acceptable overhead, we could list all processes using the |
Thanks for investigating this! I was imagining using a sudo subprocess for this, but self-signing samply is a good idea too. We could even have both. And we could have a |
samply/src/mac/process_launcher.rs
Outdated
pub fn take_task(&mut self) -> mach_port_t { | ||
mem::replace(&mut self.task, MACH_PORT_NULL) | ||
// TODO: I think it's safe to not do this mem::replace; we may need to resume the task | ||
// in start_execution() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then this method should be renamed to just task()
.
I think it's fine to not mem::replace
this for now because we never call mach_deallocate
to drop our reference to these task ports. It might be cleaner to do that; once we do, we could store an Arc<OwnedPort>
here.
let mut root_child = self.launch_child(); | ||
let mut exit_status = root_child.wait().expect("couldn't wait for child"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If samply has debugger entitlements, can we call task_for_pid
for root_child.id()
if we're launching system binaries or shell scripts? Or will those still be denied?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still denied. (Whether as root or entitled.) Anything that's protected by SIP is off the table completely I think.
I wanted to point you at Listing 12-9 from the *OS Internals Book 1, but then I found this post which has further improved on it, and one of the comments on the gist with the full code links to this implementation which is arm64 compatible. |
Yep, I was thinking
Awesome, thanks! Good to know, though I probably won't go down this route any time soon. |
I want to discourage |
Implement attaching to existing mac processes. This needs samply to be signed with the debugger entitlement:
ent.xml
:cargo build
codesign --force --options runtime --sign - --entitlements ent.xml target/debug/samply
The basic functionality works, but there is still work to do:
For 2, this might be possible to sort out if can set the dyld preload env var in the target process. I don't know if there's a simpler way to do this, but one idea is to load the preload shared library into the target (I think this is doable?) and then create a new thread in that process that calls an init function from the preload lib which will set the process env.