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 drgn_error_catch() - take 2 #456

Merged
merged 2 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions libdrgn/error.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,24 @@ static inline void drgn_recursion_guard_cleanup(int **guard)
__attribute__((__cleanup__(drgn_recursion_guard_cleanup), __unused__)) \
int *PP_UNIQUE(recursion_count_ptr) = &unique_recursion_count

/**
* Catch a certain kind of @ref drgn_error and free it
*
* If @a errp points to a non-@c NULL error whose code matches @a code, then the
* free the error (if necessary), replace the pointer value with @c NULL, and
* return @c true. Otherwise, return @c false, and @a err is not modified.
*/
static inline bool drgn_error_catch(struct drgn_error **errp,
enum drgn_error_code code)
{
if (*errp && (*errp)->code == code) {
drgn_error_destroy(*errp);
*errp = NULL;
return true;
}
return false;
}

/** @} */

#endif /* DRGN_ERROR_H */
29 changes: 9 additions & 20 deletions libdrgn/linux_kernel_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,9 @@ struct drgn_error *linux_helper_direct_mapping_offset(struct drgn_program *prog,
uint64_t virt_addr;
if (!err) {
err = drgn_object_read_unsigned(&tmp, &virt_addr);
} else if (err->code == DRGN_ERROR_LOOKUP) {
} else if (drgn_error_catch(&err, DRGN_ERROR_LOOKUP)) {
// Avoid a confusing error message with our arbitrary variable
// name.
drgn_error_destroy(err);
err = drgn_error_create(DRGN_ERROR_OTHER,
"could not find variable in direct mapping");
}
Expand Down Expand Up @@ -248,8 +247,7 @@ struct drgn_error *linux_helper_per_cpu_ptr(struct drgn_object *res,
drgn_object_qualified_type(ptr),
ptr_value + per_cpu_offset.uvalue,
0);
} else if (err->code == DRGN_ERROR_LOOKUP) {
drgn_error_destroy(err);
} else if (drgn_error_catch(&err, DRGN_ERROR_LOOKUP)) {
return drgn_object_copy(res, ptr);
} else {
return err;
Expand Down Expand Up @@ -299,9 +297,8 @@ struct drgn_error *linux_helper_task_thread_info(struct drgn_object *res,
if (!err) {
// CONFIG_THREAD_INFO_IN_TASK=y
return drgn_object_address_of(res, &tmp);
} else if (err->code == DRGN_ERROR_LOOKUP) {
} else if (drgn_error_catch(&err, DRGN_ERROR_LOOKUP)) {
// CONFIG_THREAD_INFO_IN_TASK=n
drgn_error_destroy(err);
err = drgn_object_member_dereference(&tmp, task, "stack");
if (err)
return err;
Expand Down Expand Up @@ -340,20 +337,17 @@ struct drgn_error *linux_helper_task_cpu(const struct drgn_object *task,
if (err)
return err;
err = drgn_object_member_dereference(&tmp, &tmp, "cpu");
if (err && err->code == DRGN_ERROR_LOOKUP) {
drgn_error_destroy(err);
if (drgn_error_catch(&err, DRGN_ERROR_LOOKUP)) {
err = drgn_object_member_dereference(&tmp, task, "cpu");
}
if (!err) {
union drgn_value value;
err = drgn_object_read_integer(&tmp, &value);
if (!err)
*ret = value.uvalue;
} else if (err->code == DRGN_ERROR_LOOKUP) {
} else if (drgn_error_catch(&err, DRGN_ERROR_LOOKUP)) {
// CONFIG_SMP=n
drgn_error_destroy(err);
*ret = 0;
err = NULL;
}
return err;
}
Expand Down Expand Up @@ -387,8 +381,7 @@ linux_helper_xa_load(struct drgn_object *res,
return err;
internal_flag = 2;
node_min = 4097;
} else if (err->code == DRGN_ERROR_LOOKUP) {
drgn_error_destroy(err);
} else if (drgn_error_catch(&err, DRGN_ERROR_LOOKUP)) {
// entry = (void *)xa->rnode
err = drgn_object_member_dereference(&entry, xa, "rnode");
if (err)
Expand Down Expand Up @@ -587,10 +580,8 @@ struct drgn_error *linux_helper_idr_find(struct drgn_object *res,
if (err)
return err;
id -= idr_base.uvalue;
} else if (err->code == DRGN_ERROR_LOOKUP) {
} else if (!drgn_error_catch(&err, DRGN_ERROR_LOOKUP)) {
/* idr_base was added in v4.16. */
drgn_error_destroy(err);
} else {
return err;
}

Expand Down Expand Up @@ -787,8 +778,7 @@ struct drgn_error *linux_helper_find_pid(struct drgn_object *res,
if (err)
return err;
return drgn_object_cast(res, qualified_type, &tmp);
} else if (err->code == DRGN_ERROR_LOOKUP) {
drgn_error_destroy(err);
} else if (drgn_error_catch(&err, DRGN_ERROR_LOOKUP)) {
err = drgn_program_find_object(drgn_object_program(res),
"pid_hash", NULL,
DRGN_FIND_OBJECT_ANY, &tmp);
Expand Down Expand Up @@ -851,8 +841,7 @@ struct drgn_error *linux_helper_pid_task(struct drgn_object *res,
+ 1];
snprintf(member, sizeof(member), PID_LINKS_FORMAT, pid_type);
err = drgn_object_container_of(res, &first, task_struct_type, member);
if (err && err->code == DRGN_ERROR_LOOKUP) {
drgn_error_destroy(err);
if (drgn_error_catch(&err, DRGN_ERROR_LOOKUP)) {
/* container_of(first, struct task_struct, pids[pid_type].node) */
snprintf(member, sizeof(member), PIDS_NODE_FORMAT, pid_type);
#undef PID_LINKS_FORMAT
Expand Down
Loading