summaryrefslogtreecommitdiff
path: root/library.c
diff options
context:
space:
mode:
authorChanho Park <chanho61.park@samsung.com>2014-08-22 20:34:56 +0900
committerChanho Park <chanho61.park@samsung.com>2014-08-22 20:34:56 +0900
commit517f5529d7008eba87b8b2fee5ec9ec0a5075f6e (patch)
treec71720a9b41309713c089478f921165bd2d63b25 /library.c
parent689b9dbb8d7f88ab91e7741932ed000b6e49be9a (diff)
downloadltrace-517f5529d7008eba87b8b2fee5ec9ec0a5075f6e.tar.gz
ltrace-517f5529d7008eba87b8b2fee5ec9ec0a5075f6e.tar.bz2
ltrace-517f5529d7008eba87b8b2fee5ec9ec0a5075f6e.zip
Imported Upstream version 0.7.91upstream/0.7.91upstream
Diffstat (limited to 'library.c')
-rw-r--r--library.c163
1 files changed, 119 insertions, 44 deletions
diff --git a/library.c b/library.c
index 594472b..1f425e0 100644
--- 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
*
@@ -31,10 +31,30 @@
#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;
}