Skip to content
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

Add support for more operating systems and architectures #3

Open
6 of 10 tasks
mstange opened this issue Feb 1, 2022 · 5 comments
Open
6 of 10 tasks

Add support for more operating systems and architectures #3

mstange opened this issue Feb 1, 2022 · 5 comments

Comments

@mstange
Copy link
Owner

mstange commented Feb 1, 2022

  • macOS arm64
  • macOS x86_64
  • Linux x86_64
  • Linux x86
  • Linux aarch64
  • Android 32-bit arm
  • Android aarch64
  • Windows x86_64
  • Windows x86
  • Windows aarch64
@mstange mstange changed the title Add support for more Operating Systems and architectures Add support for more operating systems and architectures Apr 2, 2022
@ishitatsuyuki
Copy link
Contributor

I might work on implementing x64 SEH (Windows) unwinding.

For the context, a few days ago I made a few tweaks to samply and I was surprised that it worked very reliably to profile Wine applications, which I routinely do for Proton/Wine related development. (Thanks for the amazing work!) Right now, I've made it to unwind through Wine DLLs through the PE DWARF debug info MinGW can generate, but using SEH we could get rid of the reliance on debug info and also unwind through most externally compiled applications as well.

I've went through https://auscitte.github.io/posts/Exception-Directory-pefile and got a grasp of how unwind codes work. After looking at real world exes I think most of the SEH opcodes should be translatable to the current cacheable rule infrastructure, with the exception of frame pointers, as I've been seeing MSVC happily putting the frame pointer in the middle of the stack:

UnwindCodes [
  0x25: SAVE_NONVOL reg=RDI, offset=0x80
  0x1E: SAVE_NONVOL reg=RSI, offset=0x78
  0x17: SAVE_NONVOL reg=RBX, offset=0x70
  0x13: SET_FPREG reg=RBP, offset=0x30
  0x0E: ALLOC_SMALL size=64
  0x0A: PUSH_NONVOL reg=R15
  0x08: PUSH_NONVOL reg=R14
  0x06: PUSH_NONVOL reg=R13
  0x04: PUSH_NONVOL reg=R12
  0x02: PUSH_NONVOL reg=RBP
]

I'll keep you updated with progresses.

@mstange
Copy link
Owner Author

mstange commented Jan 28, 2023

Excellent, that sounds great!

Also, what a fun use case! Profiling Windows binaries on Linux is certainly not something that I've anticipated, but it makes total sense. I was never sure whether it's justified to ship the PDB code in samply's Linux build, and this is an excellent justification.

You may also be interested in goblin's SEH parsing code: https://github.com/m4b/goblin/blob/master/src/pe/exception.rs
This is what symbolic / rust-minidump use. Over there, they also ran into the annoyingness of framepointers in the middle stack: rust-minidump/rust-minidump#489

I'd like to avoid the goblin dependency and would prefer an implementation which uses zerocopy parsing, like in macho-unwind-info.

@afranchuk
Copy link
Contributor

I've just created pe-unwind-info (not yet published to crates.io), which I'll work on integrating into framehop. It only supports x64 right now, but ARM64 will be pretty straightforward. AFAIK there's nothing special for windows x86, it's just hoping frame pointers weren't omitted and walking EBPs.

@ishitatsuyuki
Copy link
Contributor

FYI my previous attempt to add x64 support to framehop is at https://github.com/ishitatsuyuki/framehop/tree/seh-poc, but I didn't have time to clean it up yet.

A tricky part is that the RVAs in RUNTIME_FUNCTION can technically point to any section. My POC branch uses something called RvaMapper which is pretty much a wrapper around a mmaped view over the entire PE file. But later I realized that most of the time this data will always lie in .xdata section if it exists, and .rdata if .xdata does not exist. So getting passed a mmaped buffer of that might also work.

@afranchuk
Copy link
Contributor

Yeah, in my code I just take the entire module data as a parameter and parse the sections. In my few tests I saw that the data is usually in .rdata, but I would not be surprised to see it in .xdata since that's where it is for ARM64. But I may take a stab at integrating with what you've done so far (the higher-lever functionality overlaps with some things I provided in pe-unwind-info, but that doesn't matter much).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants