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

rbspy does not work with nonstandard ruby binaries #356

Open
Speak2Erase opened this issue Mar 3, 2022 · 6 comments
Open

rbspy does not work with nonstandard ruby binaries #356

Speak2Erase opened this issue Mar 3, 2022 · 6 comments

Comments

@Speak2Erase
Copy link

Okay, I should probably start off by establishing what I mean by "nonstandard ruby binary."
MRI supports being embedded inside a C/C++ program (or even rust when using ffi), and there are a couple of projects out there that make heavy use of this, namely mkxp and rutie.

Since these projects are essentially just a custom 'distribution' of ruby, I was wondering how possible it would be to get these to work with rbspy?
They're not standard at all, and the use case is very specific, so I don't want to push anyone to spend time adding in support for this unless it is trivial.
I've tried a couple of times handing rbspy a PID or path to one of these executables, and it doesn't work.
(Output)

rbspy is recording traces. Press Ctrl+C to stop.

Time since start: 1s. Press Ctrl+C to stop.
Summary of profiling data so far:
% self  % total  name
Warning: no profile samples were collected
Wrote raw data to C:\Users\Matthew\.cache\rbspy\records\rbspy-2022-03-03-q679hc9l2c.raw.gz
Wrote formatted output to C:\Users\Matthew\.cache\rbspy\records\rbspy-2022-03-03-oHvABPGEgb.flamegraph.svg
Something went wrong while rbspy was sampling the process. Here's what we know:
- initialize
- get ruby VM state
- Couldn't get ruby version: get Ruby version

Caused by:
    0: get_ruby_version_address
    1: Couldn't find ruby binary

I'd love for this to work, but again, I really don't want to push anyone to spend time on something so obscure!

@acj
Copy link
Member

acj commented Mar 18, 2022

Hey, sorry for the delay. I don't have time to work on this feature, but I'd be happy to support anyone who wants to give it a try.

The main problem to solve is how to find the embedded ruby VM in memory. When you try to profile a program, rbspy first looks at the program's exported symbols to find the addresses of a few key structures in memory. (This happens in initialize.rs.) If it can't find them, e.g. because ruby is embedded in another program, then you'll get the error you shared above.

But with some effort, I think it should be possible to get those memory addresses using the C API. I'd suggest something like this as a proof of concept:

  1. Write a small C program with an embedded ruby VM and use it to locate the key memory addresses (version, VM address, and global symbols address) with ruby's C API and print them out. If you can get a pointer to rb_vm_struct somehow, it should be straightforward to find the rest of them.
  2. Start up the program and have it run some simple ruby code in a loop. Make note of the addresses from step 1.
  3. Modify rbspy to use those addresses directly instead of trying to look them up.
  4. Try profiling the program with the modified rbspy.

I'm not sure how we would automate that so that rbspy could do it without help, but getting a valid profile would at least show that we can profile embedded ruby.

@Speak2Erase
Copy link
Author

Alright, I'll see what I can do.

@Jongy
Copy link

Jongy commented Mar 29, 2022

py-spy successfully profiles executables which were built statically with libpython, given that symbols are present. So it should be possible with ruby as well, depending on the necessary symbols existing.

@jabamaus

This comment was marked as off-topic.

@acj

This comment was marked as off-topic.

@jabamaus

This comment was marked as off-topic.

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

4 participants