Rewrite system_calls.exp
[platform/upstream/ltrace.git] / library.c
index 594472b..1f425e0 100644 (file)
--- a/library.c
+++ b/library.c
@@ -1,6 +1,6 @@
 /*
  * This file is part of ltrace.
- * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2011,2012,2013 Petr Machata, Red Hat Inc.
  * Copyright (C) 2001,2009 Juan Cespedes
  * Copyright (C) 2006 Ian Wienand
  *
 #include "dict.h"
 #include "backend.h" // for arch_library_symbol_init, arch_library_init
 
-#ifndef ARCH_HAVE_LIBRARY_DATA
+#ifndef OS_HAVE_LIBRARY_DATA
+int
+os_library_init(struct library *lib)
+{
+       return 0;
+}
+
 void
+os_library_destroy(struct library *lib)
+{
+}
+
+int
+os_library_clone(struct library *retp, struct library *lib)
+{
+       return 0;
+}
+#endif
+
+#ifndef ARCH_HAVE_LIBRARY_DATA
+int
 arch_library_init(struct library *lib)
 {
+       return 0;
 }
 
 void
@@ -42,9 +62,30 @@ arch_library_destroy(struct library *lib)
 {
 }
 
-void
+int
 arch_library_clone(struct library *retp, struct library *lib)
 {
+       return 0;
+}
+#endif
+
+#ifndef OS_HAVE_LIBRARY_SYMBOL_DATA
+int
+os_library_symbol_init(struct library_symbol *libsym)
+{
+       return 0;
+}
+
+void
+os_library_symbol_destroy(struct library_symbol *libsym)
+{
+}
+
+int
+os_library_symbol_clone(struct library_symbol *retp,
+                       struct library_symbol *libsym)
+{
+       return 0;
 }
 #endif
 
@@ -68,46 +109,39 @@ arch_library_symbol_clone(struct library_symbol *retp,
 }
 #endif
 
-unsigned int
-target_address_hash(const void *key)
+size_t
+arch_addr_hash(const arch_addr_t *addr)
 {
-       /* XXX this assumes that key is passed by value.  */
        union {
                arch_addr_t addr;
-               unsigned int ints[sizeof(arch_addr_t)
-                                 / sizeof(unsigned int)];
-       } u = { .addr = (arch_addr_t)key };
+               int ints[sizeof(arch_addr_t)
+                        / sizeof(unsigned int)];
+       } u = { .addr = *addr };
 
        size_t i;
-       unsigned int h = 0;
+       size_t h = 0;
        for (i = 0; i < sizeof(u.ints) / sizeof(*u.ints); ++i)
-               h ^= dict_key2hash_int((void *)(uintptr_t)u.ints[i]);
+               h ^= dict_hash_int(&u.ints[i]);
        return h;
 }
 
 int
-target_address_cmp(const void *key1, const void *key2)
+arch_addr_eq(const arch_addr_t *addr1, const arch_addr_t *addr2)
 {
-       /* XXX this assumes that key is passed by value.  */
-       arch_addr_t addr1 = (arch_addr_t)key1;
-       arch_addr_t addr2 = (arch_addr_t)key2;
-       return addr1 < addr2 ? 1
-            : addr1 > addr2 ? -1 : 0;
+       return *addr1 == *addr2;
 }
 
-/* If the other symbol owns the name, we need to make the copy, so
- * that the life-times of the two symbols are not dependent on each
- * other.  */
-static int
-strdup_if_owned(const char **retp, const char *str, int owned)
-{
-       if (!owned || str == NULL) {
-               *retp = str;
-               return 0;
-       } else {
-               *retp = strdup(str);
-               return *retp != NULL ? 0 : -1;
+int
+strdup_if(const char **retp, const char *str, int whether)
+{
+       if (whether && str != NULL) {
+               str = strdup(str);
+               if (str == NULL)
+                       return -1;
        }
+
+       *retp = str;
+       return 0;
 }
 
 static void
@@ -125,6 +159,7 @@ private_library_symbol_init(struct library_symbol *libsym,
        libsym->latent = latent;
        libsym->delayed = delayed;
        libsym->enter_addr = (void *)(uintptr_t)addr;
+       libsym->proto = NULL;
 }
 
 static void
@@ -141,37 +176,55 @@ library_symbol_init(struct library_symbol *libsym,
        private_library_symbol_init(libsym, addr, name, own_name,
                                    type_of_plt, 0, 0);
 
-       /* If arch init fails, we've already set libsym->name and
-        * own_name.  But we return failure, and the client code isn't
-        * supposed to call library_symbol_destroy in such a case.  */
-       return arch_library_symbol_init(libsym);
+       if (os_library_symbol_init(libsym) < 0)
+               /* We've already set libsym->name and own_name.  But
+                * we return failure, and the client code isn't
+                * supposed to call library_symbol_destroy in such
+                * case.  */
+               return -1;
+
+       if (arch_library_symbol_init(libsym) < 0) {
+               os_library_symbol_destroy(libsym);
+               return -1;
+       }
+
+       return 0;
 }
 
 void
 library_symbol_destroy(struct library_symbol *libsym)
 {
        if (libsym != NULL) {
-               private_library_symbol_destroy(libsym);
                arch_library_symbol_destroy(libsym);
+               os_library_symbol_destroy(libsym);
+               private_library_symbol_destroy(libsym);
        }
 }
 
 int
 library_symbol_clone(struct library_symbol *retp, struct library_symbol *libsym)
 {
+       /* Make lifetimes of name stored at original independent of
+        * the one at the clone.  */
        const char *name;
-       if (strdup_if_owned(&name, libsym->name, libsym->own_name) < 0)
+       if (strdup_if(&name, libsym->name, libsym->own_name) < 0)
                return -1;
 
        private_library_symbol_init(retp, libsym->enter_addr,
                                    name, libsym->own_name, libsym->plt_type,
                                    libsym->latent, libsym->delayed);
 
-       if (arch_library_symbol_clone(retp, libsym) < 0) {
+       if (os_library_symbol_clone(retp, libsym) < 0) {
+       fail:
                private_library_symbol_destroy(retp);
                return -1;
        }
 
+       if (arch_library_symbol_clone(retp, libsym) < 0) {
+               os_library_symbol_destroy(retp);
+               goto fail;
+       }
+
        return 0;
 }
 
@@ -230,6 +283,7 @@ private_library_init(struct library *lib, enum library_type type)
        lib->base = 0;
        lib->entry = 0;
        lib->dyn_addr = 0;
+       lib->protolib = NULL;
 
        lib->soname = NULL;
        lib->own_soname = 0;
@@ -242,11 +296,20 @@ private_library_init(struct library *lib, enum library_type type)
        lib->type = type;
 }
 
-void
+int
 library_init(struct library *lib, enum library_type type)
 {
        private_library_init(lib, type);
-       arch_library_init(lib);
+
+       if (os_library_init(lib) < 0)
+               return -1;
+
+       if (arch_library_init(lib) < 0) {
+               os_library_destroy(lib);
+               return -1;
+       }
+
+       return 0;
 }
 
 static int
@@ -266,9 +329,11 @@ library_clone(struct library *retp, struct library *lib)
 {
        const char *soname = NULL;
        const char *pathname;
-       if (strdup_if_owned(&soname, lib->soname, lib->own_soname) < 0
-            || strdup_if_owned(&pathname,
-                               lib->pathname, lib->own_pathname) < 0) {
+
+       /* Make lifetimes of strings stored at original independent of
+        * those at the clone.  */
+       if (strdup_if(&soname, lib->soname, lib->own_soname) < 0
+           || strdup_if(&pathname, lib->pathname, lib->own_pathname) < 0) {
                if (lib->own_soname)
                        free((char *)soname);
                return -1;
@@ -277,7 +342,6 @@ library_clone(struct library *retp, struct library *lib)
        private_library_init(retp, lib->type);
        library_set_soname(retp, soname, lib->own_soname);
        library_set_pathname(retp, pathname, lib->own_pathname);
-       arch_library_clone(retp, lib);
 
        retp->key = lib->key;
 
@@ -290,6 +354,7 @@ library_clone(struct library *retp, struct library *lib)
                        if (*nsymp == NULL
                            || library_symbol_clone(*nsymp, it) < 0) {
                                free(*nsymp);
+                               *nsymp = NULL;
                        fail:
                                /* Release what we managed to allocate.  */
                                library_destroy(retp);
@@ -318,6 +383,14 @@ library_clone(struct library *retp, struct library *lib)
                *nnamep = NULL;
        }
 
+       if (os_library_clone(retp, lib) < 0)
+               goto fail;
+
+       if (arch_library_clone(retp, lib) < 0) {
+               os_library_destroy(retp);
+               goto fail;
+       }
+
        return 0;
 }
 
@@ -328,6 +401,8 @@ library_destroy(struct library *lib)
                return;
 
        arch_library_destroy(lib);
+       os_library_destroy(lib);
+
        library_set_soname(lib, NULL, 0);
        library_set_pathname(lib, NULL, 0);
 
@@ -412,7 +487,7 @@ library_add_symbol(struct library *lib, struct library_symbol *first)
 }
 
 enum callback_status
-library_named_cb(struct Process *proc, struct library *lib, void *name)
+library_named_cb(struct process *proc, struct library *lib, void *name)
 {
        if (name == lib->soname
            || strcmp(lib->soname, (char *)name) == 0)
@@ -422,7 +497,7 @@ library_named_cb(struct Process *proc, struct library *lib, void *name)
 }
 
 enum callback_status
-library_with_key_cb(struct Process *proc, struct library *lib, void *keyp)
+library_with_key_cb(struct process *proc, struct library *lib, void *keyp)
 {
        return lib->key == *(arch_addr_t *)keyp ? CBS_STOP : CBS_CONT;
 }