2 * This file is part of ltrace.
3 * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
4 * Copyright (C) 2001,2009 Juan Cespedes
5 * Copyright (C) 2006 Ian Wienand
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
32 #include "backend.h" // for arch_library_symbol_init, arch_library_init
34 #ifndef ARCH_HAVE_LIBRARY_DATA
36 arch_library_init(struct library *lib)
41 arch_library_destroy(struct library *lib)
46 arch_library_clone(struct library *retp, struct library *lib)
51 #ifndef ARCH_HAVE_LIBRARY_SYMBOL_DATA
53 arch_library_symbol_init(struct library_symbol *libsym)
59 arch_library_symbol_destroy(struct library_symbol *libsym)
64 arch_library_symbol_clone(struct library_symbol *retp,
65 struct library_symbol *libsym)
72 target_address_hash(const void *key)
74 /* XXX this assumes that key is passed by value. */
77 unsigned int ints[sizeof(arch_addr_t)
78 / sizeof(unsigned int)];
79 } u = { .addr = (arch_addr_t)key };
83 for (i = 0; i < sizeof(u.ints) / sizeof(*u.ints); ++i)
84 h ^= dict_key2hash_int((void *)(uintptr_t)u.ints[i]);
89 target_address_cmp(const void *key1, const void *key2)
91 /* XXX this assumes that key is passed by value. */
92 arch_addr_t addr1 = (arch_addr_t)key1;
93 arch_addr_t addr2 = (arch_addr_t)key2;
94 return addr1 < addr2 ? 1
95 : addr1 > addr2 ? -1 : 0;
98 /* If the other symbol owns the name, we need to make the copy, so
99 * that the life-times of the two symbols are not dependent on each
102 strdup_if_owned(const char **retp, const char *str, int owned)
104 if (!owned || str == NULL) {
109 return *retp != NULL ? 0 : -1;
114 private_library_symbol_init(struct library_symbol *libsym,
116 const char *name, int own_name,
117 enum toplt type_of_plt,
118 int latent, int delayed)
122 libsym->plt_type = type_of_plt;
124 libsym->own_name = own_name;
125 libsym->latent = latent;
126 libsym->delayed = delayed;
127 libsym->enter_addr = (void *)(uintptr_t)addr;
131 private_library_symbol_destroy(struct library_symbol *libsym)
133 library_symbol_set_name(libsym, NULL, 0);
137 library_symbol_init(struct library_symbol *libsym,
138 arch_addr_t addr, const char *name, int own_name,
139 enum toplt type_of_plt)
141 private_library_symbol_init(libsym, addr, name, own_name,
144 /* If arch init fails, we've already set libsym->name and
145 * own_name. But we return failure, and the client code isn't
146 * supposed to call library_symbol_destroy in such a case. */
147 return arch_library_symbol_init(libsym);
151 library_symbol_destroy(struct library_symbol *libsym)
153 if (libsym != NULL) {
154 private_library_symbol_destroy(libsym);
155 arch_library_symbol_destroy(libsym);
160 library_symbol_clone(struct library_symbol *retp, struct library_symbol *libsym)
163 if (strdup_if_owned(&name, libsym->name, libsym->own_name) < 0)
166 private_library_symbol_init(retp, libsym->enter_addr,
167 name, libsym->own_name, libsym->plt_type,
168 libsym->latent, libsym->delayed);
170 if (arch_library_symbol_clone(retp, libsym) < 0) {
171 private_library_symbol_destroy(retp);
179 library_symbol_cmp(struct library_symbol *a, struct library_symbol *b)
181 if (a->enter_addr < b->enter_addr)
183 if (a->enter_addr > b->enter_addr)
185 if (a->name != NULL && b->name != NULL)
186 return strcmp(a->name, b->name);
187 if (a->name == NULL) {
196 library_symbol_set_name(struct library_symbol *libsym,
197 const char *name, int own_name)
199 if (libsym->own_name)
200 free((char *)libsym->name);
202 libsym->own_name = own_name;
206 library_symbol_equal_cb(struct library_symbol *libsym, void *u)
208 struct library_symbol *standard = u;
209 return library_symbol_cmp(libsym, standard) == 0 ? CBS_STOP : CBS_CONT;
213 library_symbol_named_cb(struct library_symbol *libsym, void *name)
215 return strcmp(libsym->name, name) == 0 ? CBS_STOP : CBS_CONT;
219 library_symbol_delayed_cb(struct library_symbol *libsym, void *unused)
221 return libsym->delayed ? CBS_STOP : CBS_CONT;
225 private_library_init(struct library *lib, enum library_type type)
237 lib->pathname = NULL;
238 lib->own_pathname = 0;
241 lib->exported_names = NULL;
246 library_init(struct library *lib, enum library_type type)
248 private_library_init(lib, type);
249 arch_library_init(lib);
253 library_exported_name_clone(struct library_exported_name *retp,
254 struct library_exported_name *exnm)
256 char *name = exnm->own_name ? strdup(exnm->name) : (char *)exnm->name;
260 retp->own_name = exnm->own_name;
265 library_clone(struct library *retp, struct library *lib)
267 const char *soname = NULL;
268 const char *pathname;
269 if (strdup_if_owned(&soname, lib->soname, lib->own_soname) < 0
270 || strdup_if_owned(&pathname,
271 lib->pathname, lib->own_pathname) < 0) {
273 free((char *)soname);
277 private_library_init(retp, lib->type);
278 library_set_soname(retp, soname, lib->own_soname);
279 library_set_pathname(retp, pathname, lib->own_pathname);
280 arch_library_clone(retp, lib);
282 retp->key = lib->key;
286 struct library_symbol *it;
287 struct library_symbol **nsymp = &retp->symbols;
288 for (it = lib->symbols; it != NULL; it = it->next) {
289 *nsymp = malloc(sizeof(**nsymp));
291 || library_symbol_clone(*nsymp, it) < 0) {
294 /* Release what we managed to allocate. */
295 library_destroy(retp);
299 (*nsymp)->lib = retp;
300 nsymp = &(*nsymp)->next;
305 /* Clone exported names. */
307 struct library_exported_name *it;
308 struct library_exported_name **nnamep = &retp->exported_names;
309 for (it = lib->exported_names; it != NULL; it = it->next) {
310 *nnamep = malloc(sizeof(**nnamep));
312 || library_exported_name_clone(*nnamep, it) < 0) {
316 nnamep = &(*nnamep)->next;
325 library_destroy(struct library *lib)
330 arch_library_destroy(lib);
331 library_set_soname(lib, NULL, 0);
332 library_set_pathname(lib, NULL, 0);
334 struct library_symbol *sym;
335 for (sym = lib->symbols; sym != NULL; ) {
336 struct library_symbol *next = sym->next;
337 library_symbol_destroy(sym);
342 /* Release exported names. */
343 struct library_exported_name *it;
344 for (it = lib->exported_names; it != NULL; ) {
345 struct library_exported_name *next = it->next;
347 free((char *)it->name);
354 library_set_soname(struct library *lib, const char *new_name, int own_name)
357 free((char *)lib->soname);
358 lib->soname = new_name;
359 lib->own_soname = own_name;
363 library_set_pathname(struct library *lib, const char *new_name, int own_name)
365 if (lib->own_pathname)
366 free((char *)lib->pathname);
367 lib->pathname = new_name;
368 lib->own_pathname = own_name;
371 struct library_symbol *
372 library_each_symbol(struct library *lib, struct library_symbol *start_after,
373 enum callback_status (*cb)(struct library_symbol *, void *),
376 struct library_symbol *it = start_after == NULL ? lib->symbols
380 struct library_symbol *next = it->next;
382 switch ((*cb)(it, data)) {
398 library_add_symbol(struct library *lib, struct library_symbol *first)
400 struct library_symbol *last;
401 for (last = first; last != NULL; ) {
403 if (last->next != NULL)
409 assert(last->next == NULL);
410 last->next = lib->symbols;
411 lib->symbols = first;
415 library_named_cb(struct Process *proc, struct library *lib, void *name)
417 if (name == lib->soname
418 || strcmp(lib->soname, (char *)name) == 0)
425 library_with_key_cb(struct Process *proc, struct library *lib, void *keyp)
427 return lib->key == *(arch_addr_t *)keyp ? CBS_STOP : CBS_CONT;