Replace readdir_r with readdir
[platform/upstream/ltrace.git] / output.c
index 0cec653..b63befe 100644 (file)
--- a/output.c
+++ b/output.c
 #include "type.h"
 #include "value.h"
 #include "value_dict.h"
+#include "filter.h"
+#include "debug.h"
+
+#if defined(HAVE_LIBDW)
+#include "dwarf_prototypes.h"
+#endif
 
 static struct process *current_proc = NULL;
 static size_t current_depth = 0;
@@ -191,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)
 {
@@ -207,6 +235,21 @@ library_get_prototype(struct library *lib, const char *name)
                         && lib->type == LT_LIBTYPE_DSO
                         && snip_period(buf));
 
+#if defined(HAVE_LIBDW)
+               // DWARF data fills in the gaps in the .conf files, so I don't
+               // check for lib->protolib==NULL here
+               if (lib->dwfl_module != NULL &&
+                   (filter_matches_library(options.plt_filter,    lib ) ||
+                    filter_matches_library(options.static_filter, lib ) ||
+                    filter_matches_library(options.export_filter, lib )))
+                       import_DWARF_prototypes(lib);
+               else
+                       debug(DEBUG_FUNCTION,
+                             "Filter didn't match prototype '%s' in lib '%s'. "
+                             "Not importing",
+                             name, lib->soname);
+#endif
+
                if (lib->protolib == NULL)
                        lib->protolib = protolib_cache_default(&g_protocache,
                                                               buf, 0);
@@ -214,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,
+                                         NULL, lookup_prototype_alias_cb,
+                                         &context);
+
+       // if found, the prototype is stored here, otherwise it's NULL
+       return context.result;
 }
 
 struct find_proto_data {
@@ -531,7 +587,7 @@ output_left(enum tof type, struct process *proc,
 
        account_output(&current_column, fprintf(options.output, "("));
 
-       struct prototype *func = lookup_symbol_prototype(proc, libsym);
+       struct prototype *func = lookup_symbol_prototype(proc->leader, libsym);
        if (func == NULL) {
        fail:
                account_output(&current_column, fprintf(options.output, "???"));