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 new global drgn.value helper #473

Closed
septatrix opened this issue Mar 6, 2025 · 4 comments
Closed

Add new global drgn.value helper #473

septatrix opened this issue Mar 6, 2025 · 4 comments

Comments

@septatrix
Copy link
Contributor

When writing helper functions it can often be useful to both accept native python types and drgn.Object at the same time. Currently this requires writing if isinstance(input, drgn.Object): input = input.value_() all over the place. It would be very helpful if drgn would provide a util function which does this automatically such that one can just write input = drgn.value(input). For native python types it would just return them as is and for drgn.Object types it would call the value_() method as shown above.

If you think this would be a useful addition I would be more than happy to contribute a PR

@osandov
Copy link
Owner

osandov commented Mar 7, 2025

For integers, the way drgn helpers currently handle this is by using operator.index(), which has the added benefit of supporting other integer-like types. Here's a good example (note also the IntegerLike annotation):

@takes_program_or_default
def address_to_module(prog: Program, addr: IntegerLike) -> Object:
"""
Return the ``struct module *`` associated with a memory address
If the address is a text, data, or read-only data address associated with a
kernel module, then this function returns the module it is associated with.
Otherwise, returns NULL. Note that dynamic memory (e.g. slab objects)
generally can't be associated with the module that allocated it. Further,
static & dynamic per-cpu address cannot be associated with their associated
module either.
Normally, this lookup is efficient, thanks to
``CONFIG_MODULES_TREE_LOOKUP``, which provides a red-black tree of module
address ranges, and is `very commonly`__ enabled. However, on some uncommon
configurations the rbtree may not be present. In those cases, we fall back
to a linear search of each kernel module's memory regions.
.. __: https://oracle.github.io/kconfigs/?config=MODULES_TREE_LOOKUP&config=UTS_RELEASE
:param addr: memory address to lookup
:returns: the ``struct module *`` associated with the memory, or NULL
"""
addr = operator.index(addr)
try:
mod_tree = prog["mod_tree"]
except LookupError:
pass
else:
return _addrmod_tree(mod_tree, addr)
for module in for_each_module(prog):
for start, length in module_address_regions(module):
if start <= addr < start + length:
return module
return NULL(prog, "struct module *")

Do you have an immediate use case for non-integers? If so, I wouldn't be opposed to this.

@septatrix
Copy link
Contributor Author

septatrix commented Mar 7, 2025

Do you have an immediate use case for non-integers? If so, I wouldn't be opposed to this.

My current use case are IDs so __index__ works for me. I did not know that drgn supported that - maybe that should be added to docs somewhere under the API reference for Object? While looking for something like that I did not find it except now the link to IntegerLike you provided

@septatrix
Copy link
Contributor Author

And maybe use the already existing protocols from typing. I saw the comment in the docstring about the version and more sensible name but you already use typing_extensions so could import it from there for earlier versions and there is also SupportsInt if the name is important.

My suggestion:
Under Object.value_() add a small note that for integral data types __index__/SupportsIndex is supported. That should help with discoverability

@osandov
Copy link
Owner

osandov commented Mar 10, 2025

And maybe use the already existing protocols from typing. I saw the comment in the docstring about the version and more sensible name but you already use typing_extensions so could import it from there for earlier versions and there is also SupportsInt if the name is important.

We don't rely on typing_extensions at runtime, only in the type stub, so I'd rather not add that dependency. That will be a non-issue when we drop support for Python 3.6 and 3.7, but that won't be for a couple more releases. Even then, I think that IntegerLike is a much better name for casual drgn users who aren't familiar with the intricacies of Python typing. I will add a note to the IntegerLike documentation mentioning the equivalence, though.

My suggestion: Under Object.value_() add a small note that for integral data types __index__/SupportsIndex is supported. That should help with discoverability

I like that suggestion, thanks!

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