From 2cdae45b59ef73f7128e123fa24de24941de8f26 Mon Sep 17 00:00:00 2001 From: Dima Kogan Date: Wed, 25 Jun 2014 22:22:12 -0700 Subject: [PATCH] library_exported_names_each_alias(), library_exported_names_each() now restartable These function now takes a *start_after, and return a pointer to the first failing key, like the other ltrace iterators --- library.c | 51 +++++++++++++++++++++------------------------------ library.h | 36 ++++++++++++++++++++++++++++-------- output.c | 2 +- proc.c | 3 ++- 4 files changed, 52 insertions(+), 40 deletions(-) diff --git a/library.c b/library.c index 3754af1..aa23262 100644 --- a/library.c +++ b/library.c @@ -445,31 +445,28 @@ struct library_exported_names_each_context { enum callback_status (*inner_cb)(const char *, void *); void *data; - bool failure : 1; }; static enum callback_status library_exported_names_each_cb(const char **key, uint64_t *value, void *data) { struct library_exported_names_each_context *context = (struct library_exported_names_each_context*)data; - enum callback_status status = context->inner_cb(*key, context->data); - if (status == CBS_FAIL) - context->failure = true; - return status; + return context->inner_cb(*key, context->data); } -bool library_exported_names_each(const struct library_exported_names *names, - enum callback_status (*cb)(const char *, - void *), - void *data) +const char** library_exported_names_each( + const struct library_exported_names *names, + const char **name_start_after, + enum callback_status (*cb)(const char *, + void *), + void *data) { struct library_exported_names_each_context context = {.inner_cb = cb, - .data = data, - .failure = false}; - DICT_EACH(&names->names, - const char*, uint64_t, - NULL, library_exported_names_each_cb, &context); - return !context.failure; + .data = data}; + return DICT_EACH(&names->names, + const char*, uint64_t, + name_start_after, library_exported_names_each_cb, + &context); } struct library_exported_names_each_alias_context @@ -477,7 +474,6 @@ struct library_exported_names_each_alias_context enum callback_status (*inner_cb)(const char *, void *); const char *origname; void *data; - bool failure : 1; }; static enum callback_status library_exported_names_each_alias_cb(const char **name, void *data) @@ -491,15 +487,13 @@ library_exported_names_each_alias_cb(const char **name, void *data) if (strcmp(*name, context->origname) == 0) return CBS_CONT; - enum callback_status status = context->inner_cb(*name, context->data); - if (status == CBS_FAIL) - context->failure = true; - return status; + return context->inner_cb(*name, context->data); } -bool library_exported_names_each_alias( +const char** library_exported_names_each_alias( const struct library_exported_names *names, const char *aliasname, + const char **name_start_after, enum callback_status (*cb)(const char *, void *), void *data) @@ -509,22 +503,19 @@ bool library_exported_names_each_alias( uint64_t *addr = DICT_FIND_REF(&names->names, &aliasname, uint64_t); if (addr == NULL) - return false; + return NULL; // OK. I have an address. Get the list of symbols at this address struct vect **aliases = DICT_FIND_REF(&names->addrs, - addr, struct vect*); - if (aliases == NULL) - return false; + addr, struct vect*); + assert(aliases != NULL); struct library_exported_names_each_alias_context context = {.inner_cb = cb, .origname = aliasname, - .data = data, - .failure = false}; - VECT_EACH(*aliases, const char*, NULL, - library_exported_names_each_alias_cb, &context); - return true; + .data = data}; + return VECT_EACH(*aliases, const char*, name_start_after, + library_exported_names_each_alias_cb, &context); } diff --git a/library.h b/library.h index f8a5cf8..71ac4db 100644 --- a/library.h +++ b/library.h @@ -265,22 +265,42 @@ int library_exported_names_push(struct library_exported_names *names, /* Iterates through the a library's export list. The callback is called for * every symbol a library exports. Symbol aliases do not apply here. If multiple - * symbols are defined at the same address, each is reported here. Returns true - * on success. If the callback fails at any point, this returns false + * symbols are defined at the same address, each is reported here. + * + * If we want to iterate through the whole list, set name_start_after=NULL. If + * we want to start iterating immediately past a particular symbol name, pass a + * pointer to this symbol name in name_start_after. This must be a pointer in + * the internal dict, preferably returned by an earlier call to this function + * + * If the callback fails at any point, a pointer to the failing key is returned. + * On success, returns NULL. The returned pointer can be passed back to this + * function in name_start_after to resume skipping this element */ -bool library_exported_names_each(const struct library_exported_names *names, - enum callback_status (*cb)(const char *, - void *), - void *data); +const char** library_exported_names_each( + const struct library_exported_names *names, + const char **name_start_after, + enum callback_status (*cb)(const char *, + void *), + void *data); /* Iterates through the a library's export list, reporting each symbol that is * an alias of the given 'aliasname' symbol. This 'aliasname' symbol itself is * NOT reported, so if this symbol is unique, the callback is not called at all. - * Returns true on success + * + * If we want to iterate through the whole alias list, set + * name_start_after=NULL. If we want to start iterating immediately past a + * particular symbol name, pass a pointer to this symbol name in + * name_start_after. This must be a pointer in the internal dict, preferably + * returned by an earlier call to this function + * + * If the callback fails at any point, a pointer to the failing key is returned. + * On success, returns NULL. The returned pointer can be passed back to this + * function in name_start_after to resume skipping this element */ -bool library_exported_names_each_alias( +const char** library_exported_names_each_alias( const struct library_exported_names *names, const char *aliasname, + const char **name_start_after, enum callback_status (*cb)(const char *, void *), void *data); diff --git a/output.c b/output.c index 2128816..b63befe 100644 --- a/output.c +++ b/output.c @@ -267,7 +267,7 @@ library_get_prototype(struct library *lib, const char *name) struct lookup_prototype_alias_context context = {.lib = lib, .result = NULL}; library_exported_names_each_alias(&lib->exported_names, name, - lookup_prototype_alias_cb, + NULL, lookup_prototype_alias_cb, &context); // if found, the prototype is stored here, otherwise it's NULL diff --git a/proc.c b/proc.c index 6d6562f..394dad0 100644 --- a/proc.c +++ b/proc.c @@ -903,8 +903,9 @@ activate_latent_in(struct process *proc, struct library *lib, void *data) struct activate_latent_in_context context = {.proc = proc, .lib = lib}; if (library_exported_names_each(exported_names, + NULL, activate_latent_in_cb, - &context)) + &context) == NULL) return CBS_CONT; else return CBS_FAIL; -- 2.7.4