-
Notifications
You must be signed in to change notification settings - Fork 15
feat(stapsdt): Allow compiler to choose argument registers #493
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
base: master
Are you sure you want to change the base?
Conversation
ahl
left a comment
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.
I apologize, but I wasn't able to follow this change. I think it would be helpful to explain the goals and to provide examples of the changes to output.
usdt-impl/src/stapsdt.rs
Outdated
| // Use att_syntax on x86 to generate GNU Assembly Syntax for the | ||
| // registers automatically. | ||
| quote! { options(att_syntax, nomem, nostack, preserves_flags) } |
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.
this is necessary due to some change you're making to the value of in_regs?
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.
Yup: the STAPSDT ELF note's argument format expects AT&T syntax. I'll make a more explicit note of it.
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.
I still don't get it.
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.
Okay; I added a larger prose section trying to really drill down to what is going on here with the att_syntax choice and why it is made. Can you check if that works to explain the thing?
My apologies, failure of my communication :( Okay, so currently for a probe With this PR, the choice of registers in the STAPSDT case is instead left to the compiler: if asm!(
"/* {name} */",
name = in(reg) arg
);This effectively says "take argument Does this explain it any better? |
I think so--it's just very foreign to me! So--unlike DTrace--it sounds like stap/eBPF will figure out where arguments land based on ELF data; is that right? |
ahl
left a comment
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.
good progress; thanks
usdt-impl/src/common.rs
Outdated
| ( | ||
| // For STAPSDT probes, we cannot "widen" the data type at the | ||
| // interface, as we've left the register choice up to the | ||
| // compiler and the compiler doesn't like mismatched register | ||
| // classes and types for single-byte values (reg_byte vs usize). | ||
| #[cfg(usdt_backend_stapsdt)] | ||
| quote! { (*<_ as ::std::borrow::Borrow<#ty>>::borrow(&#input)) }, | ||
| #[cfg(not(usdt_backend_stapsdt))] | ||
| quote! { (*<_ as ::std::borrow::Borrow<#ty>>::borrow(&#input) as usize) }, |
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.
| ( | |
| // For STAPSDT probes, we cannot "widen" the data type at the | |
| // interface, as we've left the register choice up to the | |
| // compiler and the compiler doesn't like mismatched register | |
| // classes and types for single-byte values (reg_byte vs usize). | |
| #[cfg(usdt_backend_stapsdt)] | |
| quote! { (*<_ as ::std::borrow::Borrow<#ty>>::borrow(&#input)) }, | |
| #[cfg(not(usdt_backend_stapsdt))] | |
| quote! { (*<_ as ::std::borrow::Borrow<#ty>>::borrow(&#input) as usize) }, | |
| #[cfg(not(usdt_backend_stapsdt))] | |
| let value quote! { (*<_ as ::std::borrow::Borrow<#ty>>::borrow(&#input) as usize) }; | |
| // For STAPSDT probes, we cannot "widen" the data type at the | |
| // interface, as we've left the register choice up to the | |
| // compiler and the compiler doesn't like mismatched register | |
| // classes and types for single-byte values (reg_byte vs usize). | |
| #[cfg(usdt_backend_stapsdt)] | |
| let value = quote! { (*<_ as ::std::borrow::Borrow<#ty>>::borrow(&#input)) }; | |
| ( | |
| value |
I'd suggest reflowing to something like this to make it a little easier to parse and to separate out the stap specifics more cleanly. In general I don't love having stap-specifics in common but ... meh
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.
Would you prefer I copy out the necessary code after all? I definitely agree that the stap-specific code in common is ugly as sin.
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.
I also don't think we should have a mostly the same copy; I could imagine refactoring. Perhaps @bnaecker could weight in on structure
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.
I agree that having many cfgs in this common module seems messy. My goal is generally to keep those very narrowly-scoped (the target-arch bits) or move them to modules. For example, you could make the asm_type_convert() function backend-specific, which I think would clean a lot of this up.
usdt-impl/src/stapsdt.rs
Outdated
| // Use att_syntax on x86 to generate GNU Assembly Syntax for the | ||
| // registers automatically. | ||
| quote! { options(att_syntax, nomem, nostack, preserves_flags) } |
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.
I still don't get it.
Yup! They read the "arguments" string from the ELF header and parse it as a space-separated list of |
Co-authored-by: Adam Leventhal <[email protected]>
5ba14c8 to
8e00444
Compare
While DTrace uses the function call ABI and a list of types, STAPSDT probes define their arguments with a list of register name and type combinations. This means that the registers can be left for the compiler to choose. When I originally implemented the STAPSDT probes, I didn't realise that it was possible to do this using the
in(reg)argument format in the inline assembly block.This PR allows the compiler to choose the register it prefers for STAPSDT parameter passing. This should also work towards #490. This necessitated changing the validity test to not expect exact registers; it's not beautiful but it does pass the CI.
As a future note, STAPSDT probes can also have pointer read instructions, including "load effective address" like ones, so in the future if Rust brings in support for these (Rust for Linux wants them so they'll probably appear eventually), then the feature can be taken into use here as well. This would mean that some arguments might be read from the stack.