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

Consider using findshlibs to find mappings #15

Open
umanwizard opened this issue Aug 9, 2024 · 5 comments
Open

Consider using findshlibs to find mappings #15

umanwizard opened this issue Aug 9, 2024 · 5 comments

Comments

@umanwizard
Copy link
Collaborator

There is a crate findshlibs which does 99% the same thing as our machinery for getting the list of shared objects on Linux, except that it has cross-platform support.

This can be an avenue for quickly spinning up macOS/Windows support. However, we might need to fix a few things about this library before using it (and thus possibly depend on a fork, rather than on the upstream gimli-rs repo, until they are willing to merge our changes).

  1. It doesn't provide a way to get the file offset of a mapping, even on platforms that support it. I'm not sure if this is actually important; pprof seems to work fine if we just fill in 0 for the file offset of a mapping
  2. We need to land fix: add missing wrapping_add gimli-rs/findshlibs#81 as this will cause panics in debug mode on certain versions of Linux otherwise (see the comment here).
  3. In various places that library assumes that u64 can be cast to usize, see e.g. here . We need to either carefully audit every case of this and ensure that it is valid even on 32-bit platforms, or (my preference) ban as from the codebase and use properly checked conversions.

Alternatively, we can decide not to use this library, and just write the Windows/macOS support by hand, as we already did for Linux.

Tagging @roblabla who has expressed interest in working on Windows support.

@roblabla
Copy link
Contributor

roblabla commented Aug 9, 2024

Ah nice. I was halfway through implementing the windows version, but using findshlibs would definitely be a lot easier, along with providing a macOS implementation for free (which I'm also interested in, incidentally ^^)

@umanwizard
Copy link
Collaborator Author

There is another issue with findshlibs which is that it iterates the macOS libraries in a way that is explicitly documented to be thread-unsafe: calling _dyld_image_count to get the number of images, then requesting information for each image by its index. This is thread-unsafe because there is no way to enforce that another thread is not adding or removing dylibs at the same time.

So I'm leaning towards just using our own implementations. I'm working now on a macOS version; I don't think it should be too difficult ...

@umanwizard
Copy link
Collaborator Author

I take that back. Writing it by hand seems also problematic because although there is the _dyld_register_func_for_add_image API which avoids the thread-safety issues, it doesn't give you the name of the dylib...

So maybe we should just use findshlibs (or something like it) and just document that on macOS it's undefined behavior if you are loading or unloading dylibs while setting up this library. But that's also a bit unsatisfying.

@umanwizard
Copy link
Collaborator Author

aha, it seems there is a way to get the image name even when using _dyld_register_func_for_add_image.

@roblabla
Copy link
Contributor

I made a commit that replaces mappings with findshlibs @ roblabla@dbbfa4c

As you can see, there are some subtle differences between windows, macos and linux.

  • On linux, we iterate over all the segments, and add an entry to the mapping for each of them.
  • On macos/windows, we only have one entry per library instead of one per segment. This is what pprof expects for some reason I don't quite understand.
  • On windows, we use a different accessor than macos to get the address. This is to workaround a bug in findshlib's windows implementation where the load_addr returns the load address of the first segment, which is not necessarily the load address of the library (it can be offset by BaseOfCode bytes). Thankfully, the bias is also wrongly calculated in a way that gives us the correct value... see Wrong/confusing memory addrs on Windows gimli-rs/findshlibs#76

Also, somewhat annoyingly, upstream pprof doesn't handle buildID for PEs or MachO, I had to patch that in:

With all of these (and some patches to jemalloc to add windows support), I get something that provides correct backtraces on windows, macos and Linux, at least for my use-cases.

I don't provide the file_offset, as you've identified. This doesn't seem to impact anything, I'm not entirely sure what it's used for. I suspect it may be needed in programs that have multiple text segment, or when the text segment is not the first segment of the binary?

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

2 participants