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.
This commit is contained in:
Omar Sandoval 2019-07-23 15:32:26 -07:00
parent 0cb77b303c
commit 62ff4e1dba
6 changed files with 40 additions and 36 deletions

View File

@ -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 <tt>ret->type</tt> 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 <tt>ret->type</tt> 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,

View File

@ -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 *

View File

@ -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",

View File

@ -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);

View File

@ -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;
}

View File

@ -225,9 +225,8 @@ static void default_primitive_types_init(void)
}
/*
* Like @ref drgn_type_index_find_parsed(), but sets <tt>ret->type</tt> 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
* <tt>&drgn_error_not_found</tt> 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) {