summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDima Kogan <dima@secretsauce.net>2014-06-25 22:22:12 -0700
committerChanho Park <chanho61.park@samsung.com>2014-08-22 20:38:26 +0900
commit2cdae45b59ef73f7128e123fa24de24941de8f26 (patch)
treedf375fecdfd4135c20f309a6bc59626e07ef126e
parent0d0ef961855b7aefa4529c49d05e1785c968131f (diff)
downloadltrace-2cdae45b59ef73f7128e123fa24de24941de8f26.tar.gz
ltrace-2cdae45b59ef73f7128e123fa24de24941de8f26.tar.bz2
ltrace-2cdae45b59ef73f7128e123fa24de24941de8f26.zip
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
-rw-r--r--library.c51
-rw-r--r--library.h36
-rw-r--r--output.c2
-rw-r--r--proc.c3
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;