-
Notifications
You must be signed in to change notification settings - Fork 157
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 reading methods via "members" array #72
Conversation
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.
The architecture all looks good here. There are a couple of bugs I spotted, but my comments are mostly around naming and commit organization.
@@ -1026,6 +1026,7 @@ struct drgn_type_from_dwarf_thunk { | |||
struct drgn_type_thunk thunk; | |||
Dwarf_Die die; | |||
bool can_be_incomplete_array; | |||
uint64_t bias; |
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.
Nit, and hopefully it's not too much trouble to change this, but I think of the die
, bias
pair as one entity, so I'd prefer if bias
was immediately after die
here and in parameter lists where they're passed together.
libdrgn/object.h
Outdated
struct drgn_object *object) | ||
{ | ||
lazy_object->object = object; | ||
if (object) |
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 don't see a good reason for this to be NULL
. I'm assuming you did this because drgn_lazy_type_init_evaluated()
says it can take a NULL
type, but I think that documentation is wrong ;) it doesn't make sense for that to take NULL
either as far as I can tell.
Also, again because objects are immutable, this needs to allocate a new object and copy the passed object (which of course means that `drgn_lazy_parameter_get_object() should manually reinitialize the lazy parameter rather than calling this). I think this will only end up being needed for the Python bindings, in case someone constructs a member with an object.
libdrgn/debug_info.c
Outdated
err = drgn_compound_type_builder_add_member(builder, member, name, | ||
0, bit_field_size); | ||
if (err) | ||
goto err; | ||
return NULL; |
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.
Could you refactor this so you only need to call drgn_compound_type_builder_add_member()
in one place?
libdrgn/dwarf_index.h
Outdated
@@ -319,6 +319,8 @@ struct drgn_error *drgn_dwarf_index_get_die(struct drgn_dwarf_index_die *die, | |||
Dwarf_Die *die_ret, | |||
uint64_t *bias_ret); | |||
|
|||
bool find_definition(struct drgn_dwarf_index *dindex, uintptr_t die_addr, |
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.
Since this is being made public, it should be renamed drgn_dwarf_index_find_definition()
and given a comment.
libdrgn/type.c
Outdated
return err; | ||
struct drgn_error *err = NULL; | ||
if (!parameter.is_object) { | ||
err = drgn_lazy_type_check_prog(¶meter, builder->prog); |
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 think we need to check this in the is_object
case, too, right?
397751f
to
5e6b5fd
Compare
Since types can have object members, they must keep track of the bias variable.
if (!dwarf_flag(die, DW_AT_declaration, &decl) && decl) { | ||
Dwfl_Module *module; | ||
Dwarf_Off offset; | ||
if (drgn_dwarf_index_find_definition(&dbinfo->dindex, (uintptr_t)die->addr, &module, &offset)) { |
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.
Note to self - if we aren't able to find a declaration here, the object returned is pretty odd and can probably cause a crash if mishandled. Not sure if we should worry about that at the moment - but I have been able to generate class functions with no declarations (usually if the function was not used or defined)
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.
Didn't look at the final commit in much detail yet, but wanted to send you the comments on the lazy object handling.
drgn_type_thunk_free(lazy_parameter->thunk); | ||
} | ||
|
||
inline struct drgn_error * |
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'd just drop the inline
now that this has been moved to a .c
file.
} | ||
return NULL; | ||
} | ||
|
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.
Stray blank line.
libdrgn/lazy_parameter.h
Outdated
* Validate a @ref drgn_program matches the one in a @ref drgn_lazy_parameter. | ||
* | ||
* @param[in] lazy_parameter Lazy parameter to validate. | ||
* @param[in] prog The program to compare against.. |
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.
Extra "."
else | ||
free(lazy_parameter->object); |
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.
You also need to call drgn_object_deinit()
first.
} else | ||
if (!drgn_lazy_parameter_is_evaluated(lazy_parameter)) |
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.
Squash these to else if
.
drgn_lazy_parameter_init_object(lazy_parameter, &obj); | ||
thunk.free_fn(thunk_ptr); | ||
} | ||
drgn_object_init(ret, drgn_object_program(lazy_parameter->object)); |
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.
The convention in libdrgn is to assume that a passed object is already initialized. Rather than calling drgn_object_init()
here, the caller should do it.
} | ||
drgn_object_init(ret, drgn_object_program(lazy_parameter->object)); | ||
drgn_object_copy(ret, lazy_parameter->object); | ||
*ret = *lazy_parameter->object; |
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.
drgn_object_copy()
already effectively did this, so this shouldn't be necessary and isn't safe since the object may have an allocated buffer.
struct drgn_error *err = thunk.evaluate_fn(thunk_ptr, &obj); | ||
if (err) | ||
return err; | ||
drgn_lazy_parameter_init_object(lazy_parameter, &obj); |
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.
Using drgn_lazy_parameter_init_object()
means that you're creating a temporary object only to copy it and then discard it. I'd just malloc()
the new object directly and reinitialize the lazy parameter here.
if (!new_obj) | ||
return &drgn_enomem; | ||
drgn_object_init(new_obj, drgn_object_program(object)); | ||
drgn_object_copy(new_obj, object); |
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.
This can fail, you need to handle errors.
struct drgn_object_thunk thunk; | ||
Dwarf_Die die; | ||
uint64_t bias; | ||
const char* name; |
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.
const char *name
This will be superseded by #123, so I'm closing this in favor of exposing methods that way instead. |
This is the first step towards real "method" support (ie: reading methods like
Class::methodname
). It also adds support forinstance.method
right now, and adds the methods to the members array of object types.Here are the biggest red flags (that I would like input on):
lazy_type
andlazy_object
variable names to signify the parameter must be a type/object at that point. I could split things a little more to remove this distinction if you wish.If you have high-level suggestions for the architecture, I'm also happy to hear those as well.