diff options
author | Dima Kogan <dima@secretsauce.net> | 2014-06-02 02:01:57 -0700 |
---|---|---|
committer | Chanho Park <chanho61.park@samsung.com> | 2014-08-22 20:38:26 +0900 |
commit | 5c5c38e500fd8f20bb8d6c0177948dbfe86b6fcd (patch) | |
tree | 4f05fbaf41292a7c264cbe2caedd5c78c8e24a91 /output.c | |
parent | 703e5c6363ae5d07be62c2efa0a17862ce3c1c45 (diff) | |
download | ltrace-5c5c38e500fd8f20bb8d6c0177948dbfe86b6fcd.tar.gz ltrace-5c5c38e500fd8f20bb8d6c0177948dbfe86b6fcd.tar.bz2 ltrace-5c5c38e500fd8f20bb8d6c0177948dbfe86b6fcd.zip |
We now use known prototypes for all aliased symbols (same address)
Some libraries have multiple names for the same function. Prior to this patch,
it was possible to define a prototype for a symbol, and not have ltrace use it
because it saw a different symbol be called. libc is a common source of this.
For instance (on my amd64 Debian box) it defines the nanosleep symbol as both
'nanosleep' and '__GI___nanosleep', at the same address. If a calling library
calls '__GI___nanosleep', then an ltrace prototype for 'nanosleep' would not be
used, even though it should apply to this call
Diffstat (limited to 'output.c')
-rw-r--r-- | output.c | 39 |
1 files changed, 37 insertions, 2 deletions
@@ -197,6 +197,28 @@ snip_period(char *buf) } } +struct lookup_prototype_alias_context +{ + struct library *lib; + struct prototype *result; // output +}; +static enum callback_status +lookup_prototype_alias_cb(const char *name, void *data) +{ + struct lookup_prototype_alias_context *context = + (struct lookup_prototype_alias_context*)data; + + struct library *lib = context->lib; + + context->result = + protolib_lookup_prototype(lib->protolib, name, + lib->type != LT_LIBTYPE_SYSCALL); + if (context->result != NULL) + return CBS_STOP; + + return CBS_CONT; +} + static struct prototype * library_get_prototype(struct library *lib, const char *name) { @@ -235,8 +257,21 @@ library_get_prototype(struct library *lib, const char *name) if (lib->protolib == NULL) return NULL; - return protolib_lookup_prototype(lib->protolib, name, - lib->type != LT_LIBTYPE_SYSCALL); + struct prototype *result = + protolib_lookup_prototype(lib->protolib, name, + lib->type != LT_LIBTYPE_SYSCALL); + if (result != NULL) + return result; + + // prototype not found. Is it aliased? + struct lookup_prototype_alias_context context = {.lib = lib, + .result = NULL}; + library_exported_names_each_alias(&lib->exported_names, name, + lookup_prototype_alias_cb, + &context); + + // if found, the prototype is stored here, otherwise it's NULL + return context.result; } struct find_proto_data { |