From 62ff4e1dba1eb9b28e15327e560151d8a7a5e621 Mon Sep 17 00:00:00 2001 From: Omar Sandoval Date: Tue, 23 Jul 2019 15:32:26 -0700 Subject: [PATCH] libdrgn: indicate finder lookup failure with special error Currently, finders indicate a non-fatal lookup error by setting the type member to NULL. This won't work when we replace the symbol finder with an object finder (which shouldn't modify the object on failure). Instead, use a static error for this purpose. --- libdrgn/drgn.h | 24 ++++++++++++++++-------- libdrgn/dwarf_info_cache.c | 6 ++---- libdrgn/error.c | 5 +++++ libdrgn/python/program.c | 10 ++++------ libdrgn/symbol_index.c | 6 +++--- libdrgn/type_index.c | 25 ++++++++++--------------- 6 files changed, 40 insertions(+), 36 deletions(-) diff --git a/libdrgn/drgn.h b/libdrgn/drgn.h index 9853629c..fc719994 100644 --- a/libdrgn/drgn.h +++ b/libdrgn/drgn.h @@ -123,6 +123,16 @@ struct drgn_error { */ extern struct drgn_error drgn_enomem; +/** + * Non-fatal lookup @ref drgn_error. + * + * This has a code of @ref DRGN_ERROR_LOOKUP. It should be returned from a @ref + * drgn_type_find_fn() or @ref drgn_symbol_find_fn() to indicate that the entity + * in question could not be found. It does not need to be passed to @ref + * drgn_error_destroy() (but it can be). + */ +extern struct drgn_error drgn_not_found; + /** * Create a @ref drgn_error. * @@ -966,9 +976,6 @@ bool drgn_filename_matches(const char *haystack, const char *needle); /** * Callback for finding a type. * - * If the type is found, this should fill in @p ret and return @c NULL. If not, - * this should set ret->type to @c NULL and return @c NULL. - * * @param[in] kind Kind of type. * @param[in] name Name of type (or tag, for structs, unions, and enums). This * is @em not null-terminated. @@ -977,7 +984,9 @@ bool drgn_filename_matches(const char *haystack, const char *needle); * should be matched with @ref drgn_filename_matches(). * @param[in] arg Argument passed to @ref drgn_program_add_type_finder(). * @param[out] ret Returned type. - * @return @c NULL on success, non-@c NULL on error. + * @return @c NULL on success, non-@c NULL on error. In particular, if the type + * is not found, this should return &@ref drgn_not_found; any other errors are + * considered fatal. */ typedef struct drgn_error * (*drgn_type_find_fn)(enum drgn_type_kind kind, const char *name, @@ -1068,9 +1077,6 @@ struct drgn_symbol { /** * Callback for finding a symbol. * - * If the symbol is found, this should fill in @p ret and return @c NULL. If - * not, this should set ret->type to @c NULL and return @c NULL. - * * @param[in] name Name of symbol. This is @em not null-terminated. * @param[in] name_len Length of @p name. * @param[in] filename Filename containing the symbol definition or @c NULL. @@ -1078,7 +1084,9 @@ struct drgn_symbol { * @param[in] flags Flags indicating what kind of object to look for. * @param[in] arg Argument passed to @ref drgn_program_add_symbol_finder(). * @param[out] ret Returned symbol. - * @return @c NULL on success, non-@c NULL on error. + * @return @c NULL on success, non-@c NULL on error. In particular, if the + * symbol is not found, this should return &@ref drgn_not_found; any other + * errors are considered fatal. */ typedef struct drgn_error * (*drgn_symbol_find_fn)(const char *name, size_t name_len, const char *filename, diff --git a/libdrgn/dwarf_info_cache.c b/libdrgn/dwarf_info_cache.c index ab919c25..9e92f963 100644 --- a/libdrgn/dwarf_info_cache.c +++ b/libdrgn/dwarf_info_cache.c @@ -1402,8 +1402,7 @@ struct drgn_error *drgn_dwarf_type_find(enum drgn_type_kind kind, } if (err && err->code != DRGN_ERROR_STOP) return err; - ret->type = NULL; - return NULL; + return &drgn_not_found; } static struct drgn_error * @@ -1521,8 +1520,7 @@ drgn_dwarf_symbol_find(const char *name, size_t name_len, const char *filename, } if (err && err->code != DRGN_ERROR_STOP) return err; - ret->type = NULL; - return NULL; + return &drgn_not_found; } struct drgn_error * diff --git a/libdrgn/error.c b/libdrgn/error.c index 3d051f72..1a00e4f0 100644 --- a/libdrgn/error.c +++ b/libdrgn/error.c @@ -17,6 +17,11 @@ LIBDRGN_PUBLIC struct drgn_error drgn_enomem = { .message = "cannot allocate memory", }; +LIBDRGN_PUBLIC struct drgn_error drgn_not_found = { + .code = DRGN_ERROR_LOOKUP, + .message = "not found", +}; + struct drgn_error drgn_stop = { .code = DRGN_ERROR_STOP, .message = "stop iteration", diff --git a/libdrgn/python/program.c b/libdrgn/python/program.c index 94fdf8ee..ec7e8d48 100644 --- a/libdrgn/python/program.c +++ b/libdrgn/python/program.c @@ -221,8 +221,8 @@ static struct drgn_error *py_type_find_fn(enum drgn_type_kind kind, goto out_name_obj; } if (type_obj == Py_None) { - ret->type = NULL; - goto out; + err = &drgn_not_found; + goto out_type_obj; } if (!PyObject_TypeCheck(type_obj, &DrgnType_type)) { PyErr_SetString(PyExc_TypeError, @@ -238,7 +238,6 @@ static struct drgn_error *py_type_find_fn(enum drgn_type_kind kind, ret->type = ((DrgnType *)type_obj)->type; ret->qualifiers = ((DrgnType *)type_obj)->qualifiers; -out: err = NULL; out_type_obj: Py_DECREF(type_obj); @@ -311,8 +310,8 @@ static struct drgn_error *py_symbol_find_fn(const char *name, size_t name_len, goto out_flags_obj; } if (sym_obj == Py_None) { - ret->type = NULL; - goto out; + err = &drgn_not_found; + goto out_sym_obj; } if (!PyObject_TypeCheck(sym_obj, &Symbol_type)) { PyErr_SetString(PyExc_TypeError, @@ -327,7 +326,6 @@ static struct drgn_error *py_symbol_find_fn(const char *name, size_t name_len, } *ret = ((Symbol *)sym_obj)->sym; -out: err = NULL; out_sym_obj: Py_DECREF(sym_obj); diff --git a/libdrgn/symbol_index.c b/libdrgn/symbol_index.c index 6aa020c3..4d91f55b 100644 --- a/libdrgn/symbol_index.c +++ b/libdrgn/symbol_index.c @@ -91,9 +91,7 @@ struct drgn_error *drgn_symbol_index_find(struct drgn_symbol_index *sindex, while (finder) { err = finder->fn(name, name_len, filename, flags, finder->arg, ret); - if (err) - return err; - if (ret->type) { + if (!err) { if (ret->kind == DRGN_SYMBOL_ENUMERATOR || ret->kind == DRGN_SYMBOL_CONSTANT) { if (!(flags & DRGN_FIND_OBJECT_CONSTANT)) @@ -113,6 +111,8 @@ struct drgn_error *drgn_symbol_index_find(struct drgn_symbol_index *sindex, } return NULL; } + if (err != &drgn_not_found) + return err; finder = finder->next; } diff --git a/libdrgn/type_index.c b/libdrgn/type_index.c index 5efe7457..e64490a0 100644 --- a/libdrgn/type_index.c +++ b/libdrgn/type_index.c @@ -225,9 +225,8 @@ static void default_primitive_types_init(void) } /* - * Like @ref drgn_type_index_find_parsed(), but sets ret->type to NULL - * and returns @c NULL if the type is not found instead of returning a @ref - * DRGN_ERROR_LOOKUP error. + * Like @ref drgn_type_index_find_parsed(), but returns + * &drgn_error_not_found instead of a more informative error message. */ static struct drgn_error * drgn_type_index_find_parsed_internal(struct drgn_type_index *tindex, @@ -242,19 +241,18 @@ drgn_type_index_find_parsed_internal(struct drgn_type_index *tindex, while (finder) { err = finder->fn(kind, name, name_len, filename, finder->arg, ret); - if (err) - return err; - if (ret->type) { + if (!err) { if (drgn_type_kind(ret->type) != kind) { return drgn_error_create(DRGN_ERROR_TYPE, "type find callback returned wrong kind of type"); } return NULL; } + if (err != &drgn_not_found) + return err; finder = finder->next; } - ret->type = NULL; - return NULL; + return &drgn_not_found; } struct drgn_error * @@ -286,12 +284,11 @@ drgn_type_index_find_primitive(struct drgn_type_index *tindex, strlen(spellings[i]), NULL, &qualified_type); - if (err) { - return err; - } else if (qualified_type.type && - drgn_type_primitive(qualified_type.type) == type) { + if (!err && drgn_type_primitive(qualified_type.type) == type) { *ret = qualified_type.type; goto out; + } else if (err && err != &drgn_not_found) { + return err; } } @@ -373,10 +370,8 @@ drgn_type_index_find_parsed(struct drgn_type_index *tindex, err = drgn_type_index_find_parsed_internal(tindex, kind, name, name_len, filename, ret); - if (err) + if (err != &drgn_not_found) return err; - else if (ret->type) - return NULL; precision = name_len < INT_MAX ? (int)name_len : INT_MAX; if (filename) {