-
Notifications
You must be signed in to change notification settings - Fork 168
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
Pluggable Symbol finder API, with Python support #241
Conversation
9cdb211
to
5171962
Compare
45c555d
to
9dc4c77
Compare
9dc4c77
to
0f6ef14
Compare
159620e
to
50fd02b
Compare
@osandov I think the Symbol finder API is now ready to review! I figured I'd continue using this old PR for the branch, but I did update the description so it's all relevant. |
50fd02b
to
a1dcb87
Compare
@osandov I know you're busy, but I wanted to check if you had any initial feedback I can start working on here? Or perhaps I can break it down further into smaller chunks? |
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.
Sorry for the delay, this is looking pretty good. The biggest architectural comment I have is regarding the strdup
in Symbol_wrap
; the rest are more about the implementation or style.
Fyi, I merged the first commit in this PR ("Correct types/docs for object+type finder API"). |
a1dcb87
to
ed23e92
Compare
Ok, I went ahead and rebased this branch on top of the latest main. That did involve some changes regarding the I also tried to do a better review of my commits prior to sending them, and caught a few issues. I marked them so you could see what they were. |
ed23e92
to
14b65d3
Compare
14b65d3
to
43cf716
Compare
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'm finally getting back to this. I only re-reviewed patch 1 so far, but I just wanted to submit these before I head out for the day. Feel free to wait for me to finish looking at the rest. Thanks for your continued work on this!
8fefbaf
to
711399a
Compare
Alright, I believe I've addressed everything from your review on Github as well as our discussion. The Normally I like to keep my branches rebased on top of the latest I did do a quick compile & test for each commit in the branch to make sure all of my changes were "fixed up" into the correct commits. There are also two new commits on the branch as well: one for the |
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.
A handful of mostly aesthetic things that I missed the first time around and a bug or two, but this looks great overall, thank you!
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.
Just a couple of comments that didn't get updated, and the commit message for "libdrgn: Use Symbol Finder API in find_symbol_by_address_internal()" is also stale: "the lookup API does allow us to keep the already-determined module" is no longer true.
Other than those tiny complaints, I'm happy with this! There's a bunch of stuff currently in main
that I want to get in a release, but I'd like to give this new API a chance to sit for a bit before putting it in a release. So, my plan is to cut a new release early next week and then merge this immediately afterwards.
By using __attribute__((__packed__)), we shrink each enum from the default integer size of four bytes, down to the minimum size of one. This reduces the size of drgn_symbol from 32 bytes down to 26, with 6 bytes of padding. It doesn't have a practical benefit yet, but adding fields to struct drgn_symbol in the future may not increase the size. Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
Symbol lookup is not yet modular, like type or object lookup. However, making it modular would enable easier development and prototyping of alternative Symbol providers, such as Linux kernel module symbol tables, vmlinux kallsyms tables, and BPF function symbols. To begin with, create a modular Symbol API within libdrgn, and refactor the ELF symbol search to use it. For now, we leave drgn_program_find_symbol_by_address_internal() alone. Its conversion will require some surgery, since the new API can return errors, whereas this function cannot. Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
The following commit will modify it to use drgn_program_symbols_search(), a static function declared below. Move it underneath in preparation. No changes to the function. Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
The drgn_program_find_symbol_by_address_internal() function is used when libdrgn itself may want to lookup a symbol: in particular, when formatting stack traces or objects. It does less work by possibly already having a Dwfl_Module looked up, and by avoiding memory allocation of a symbol, and it's more convenient because it doesn't return any errors, including on lookup failure. Unfortunately, the new symbol finder API breaks all of these properties: the returned symbol is now allocated via malloc() which needs cleanup on error, and errors can be returned by any finder via the lookup API. What's more, the finder API doesn't allow specifying an already-known module. Thankfully, error handling can be improved using the cleanup API, and looking up a module for an address is usually a reasonably cheap binary tree operation. Switch the internal method over to the new finder API. The major difference now is simply that lookup failures don't result in an error: they simply result in a NULL symbol. Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
Now that the symbol finder API is created, we can move the ELF symbol implementation into the debug_info.c file, where it more logically belongs. The only change to these functions in the move is to declare elf_symbols_search as static. Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
Previously, Symbol objects could not be constructed in Python. However, in order to allow Python Symbol finders, this needs to be changed. Unfortunately, Symbol name lifetimes are tricky to manage. We introduce a lifetime enumeration to handle this. The lifetime may be "static", i.e. longer than the life of the program; "external", i.e. longer than the life of the symbol, but no guarantees beyond that; or "owned", i.e. owned by the Symbol itself. Symbol objects constructed in Python are "external". The Symbol struct owns the pointer to the drgn_symbol, and it holds a reference to the Python object keeping the name valid (either the program, or a PyUnicode object). The added complexity is justified by the fact that most symbols are from the ELF file, and thus share a lifetime with the Program. It would be a waste to constantly strdup() these strings, just to support a small number of Symbols created by Python code. Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
Expose the Symbol finder API so that Python code can be used to lookup additional symbols by name or address. Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
Specify a "fake" symbol finder and then test that its results are plumbed through the API successfully. While this is a contrived test, it helps build confidence in the plumbing of the API. Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
Thanks for the last catches, clearly I need a better find/replace workflow 😅 The release plan makes total sense, I wouldn't plop a this into a brand new release immediately if I were you. Looking forward to 0.0.26! Thanks again for the detailed review, it's a much better product as a result! |
This implements a pluggable Symbol Finder API, to complement the Object and Type finding APIs. There is also a Python binding.
I think it's a bit easier to review this by reading each commit rather than the full diff, but I don't know how easy Github makes that.
I'll highlight a few architectural points here that may merit discussion or debate.
LIFETIME_STATIC
in this new system). Strings passed from python->drgn are subject to garbage collection, so they need to be copied and drgn will manage their lifetime.The API exposesdrgn_module
as a struct forward declaration, it's unused at this time, except by the ELF symbol finder.There are added tests which do demonstrate use from Python. You can also see the current kallsyms_finder branch for an example of using the C API.
(PR description is re-edited now that I've moved this out of draft state.)