2 * This file is part of ltrace.
3 * Copyright (C) 2011,2012,2013 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 OS_HAVE_LIBRARY_DATA
36 os_library_init(struct library *lib)
42 os_library_destroy(struct library *lib)
47 os_library_clone(struct library *retp, struct library *lib)
53 #ifndef ARCH_HAVE_LIBRARY_DATA
55 arch_library_init(struct library *lib)
61 arch_library_destroy(struct library *lib)
66 arch_library_clone(struct library *retp, struct library *lib)
72 #ifndef OS_HAVE_LIBRARY_SYMBOL_DATA
74 os_library_symbol_init(struct library_symbol *libsym)
80 os_library_symbol_destroy(struct library_symbol *libsym)
85 os_library_symbol_clone(struct library_symbol *retp,
86 struct library_symbol *libsym)
92 #ifndef ARCH_HAVE_LIBRARY_SYMBOL_DATA
94 arch_library_symbol_init(struct library_symbol *libsym)
100 arch_library_symbol_destroy(struct library_symbol *libsym)
105 arch_library_symbol_clone(struct library_symbol *retp,
106 struct library_symbol *libsym)
113 arch_addr_hash(const arch_addr_t *addr)
117 int ints[sizeof(arch_addr_t)
118 / sizeof(unsigned int)];
119 } u = { .addr = *addr };
123 for (i = 0; i < sizeof(u.ints) / sizeof(*u.ints); ++i)
124 h ^= dict_hash_int(&u.ints[i]);
129 arch_addr_eq(const arch_addr_t *addr1, const arch_addr_t *addr2)
131 return *addr1 == *addr2;
135 strdup_if(const char **retp, const char *str, int whether)
137 if (whether && str != NULL) {
148 private_library_symbol_init(struct library_symbol *libsym,
150 const char *name, int own_name,
151 enum toplt type_of_plt,
152 int latent, int delayed)
156 libsym->plt_type = type_of_plt;
158 libsym->own_name = own_name;
159 libsym->latent = latent;
160 libsym->delayed = delayed;
161 libsym->enter_addr = (void *)(uintptr_t)addr;
162 libsym->proto = NULL;
166 private_library_symbol_destroy(struct library_symbol *libsym)
168 library_symbol_set_name(libsym, NULL, 0);
172 library_symbol_init(struct library_symbol *libsym,
173 arch_addr_t addr, const char *name, int own_name,
174 enum toplt type_of_plt)
176 private_library_symbol_init(libsym, addr, name, own_name,
179 if (os_library_symbol_init(libsym) < 0)
180 /* We've already set libsym->name and own_name. But
181 * we return failure, and the client code isn't
182 * supposed to call library_symbol_destroy in such
186 if (arch_library_symbol_init(libsym) < 0) {
187 os_library_symbol_destroy(libsym);
195 library_symbol_destroy(struct library_symbol *libsym)
197 if (libsym != NULL) {
198 arch_library_symbol_destroy(libsym);
199 os_library_symbol_destroy(libsym);
200 private_library_symbol_destroy(libsym);
205 library_symbol_clone(struct library_symbol *retp, struct library_symbol *libsym)
207 /* Make lifetimes of name stored at original independent of
208 * the one at the clone. */
210 if (strdup_if(&name, libsym->name, libsym->own_name) < 0)
213 private_library_symbol_init(retp, libsym->enter_addr,
214 name, libsym->own_name, libsym->plt_type,
215 libsym->latent, libsym->delayed);
217 if (os_library_symbol_clone(retp, libsym) < 0) {
219 private_library_symbol_destroy(retp);
223 if (arch_library_symbol_clone(retp, libsym) < 0) {
224 os_library_symbol_destroy(retp);
232 library_symbol_cmp(struct library_symbol *a, struct library_symbol *b)
234 if (a->enter_addr < b->enter_addr)
236 if (a->enter_addr > b->enter_addr)
238 if (a->name != NULL && b->name != NULL)
239 return strcmp(a->name, b->name);
240 if (a->name == NULL) {
249 library_symbol_set_name(struct library_symbol *libsym,
250 const char *name, int own_name)
252 if (libsym->own_name)
253 free((char *)libsym->name);
255 libsym->own_name = own_name;
259 library_symbol_equal_cb(struct library_symbol *libsym, void *u)
261 struct library_symbol *standard = u;
262 return library_symbol_cmp(libsym, standard) == 0 ? CBS_STOP : CBS_CONT;
266 library_symbol_named_cb(struct library_symbol *libsym, void *name)
268 return strcmp(libsym->name, name) == 0 ? CBS_STOP : CBS_CONT;
272 library_symbol_delayed_cb(struct library_symbol *libsym, void *unused)
274 return libsym->delayed ? CBS_STOP : CBS_CONT;
278 private_library_init(struct library *lib, enum library_type type)
286 lib->protolib = NULL;
291 lib->pathname = NULL;
292 lib->own_pathname = 0;
295 lib->exported_names = NULL;
300 library_init(struct library *lib, enum library_type type)
302 private_library_init(lib, type);
304 if (os_library_init(lib) < 0)
307 if (arch_library_init(lib) < 0) {
308 os_library_destroy(lib);
316 library_exported_name_clone(struct library_exported_name *retp,
317 struct library_exported_name *exnm)
319 char *name = exnm->own_name ? strdup(exnm->name) : (char *)exnm->name;
323 retp->own_name = exnm->own_name;
328 library_clone(struct library *retp, struct library *lib)
330 const char *soname = NULL;
331 const char *pathname;
333 /* Make lifetimes of strings stored at original independent of
334 * those at the clone. */
335 if (strdup_if(&soname, lib->soname, lib->own_soname) < 0
336 || strdup_if(&pathname, lib->pathname, lib->own_pathname) < 0) {
338 free((char *)soname);
342 private_library_init(retp, lib->type);
343 library_set_soname(retp, soname, lib->own_soname);
344 library_set_pathname(retp, pathname, lib->own_pathname);
346 retp->key = lib->key;
350 struct library_symbol *it;
351 struct library_symbol **nsymp = &retp->symbols;
352 for (it = lib->symbols; it != NULL; it = it->next) {
353 *nsymp = malloc(sizeof(**nsymp));
355 || library_symbol_clone(*nsymp, it) < 0) {
359 /* Release what we managed to allocate. */
360 library_destroy(retp);
364 (*nsymp)->lib = retp;
365 nsymp = &(*nsymp)->next;
370 /* Clone exported names. */
372 struct library_exported_name *it;
373 struct library_exported_name **nnamep = &retp->exported_names;
374 for (it = lib->exported_names; it != NULL; it = it->next) {
375 *nnamep = malloc(sizeof(**nnamep));
377 || library_exported_name_clone(*nnamep, it) < 0) {
381 nnamep = &(*nnamep)->next;
386 if (os_library_clone(retp, lib) < 0)
389 if (arch_library_clone(retp, lib) < 0) {
390 os_library_destroy(retp);
398 library_destroy(struct library *lib)
403 arch_library_destroy(lib);
404 os_library_destroy(lib);
406 library_set_soname(lib, NULL, 0);
407 library_set_pathname(lib, NULL, 0);
409 struct library_symbol *sym;
410 for (sym = lib->symbols; sym != NULL; ) {
411 struct library_symbol *next = sym->next;
412 library_symbol_destroy(sym);
417 /* Release exported names. */
418 struct library_exported_name *it;
419 for (it = lib->exported_names; it != NULL; ) {
420 struct library_exported_name *next = it->next;
422 free((char *)it->name);
429 library_set_soname(struct library *lib, const char *new_name, int own_name)
432 free((char *)lib->soname);
433 lib->soname = new_name;
434 lib->own_soname = own_name;
438 library_set_pathname(struct library *lib, const char *new_name, int own_name)
440 if (lib->own_pathname)
441 free((char *)lib->pathname);
442 lib->pathname = new_name;
443 lib->own_pathname = own_name;
446 struct library_symbol *
447 library_each_symbol(struct library *lib, struct library_symbol *start_after,
448 enum callback_status (*cb)(struct library_symbol *, void *),
451 struct library_symbol *it = start_after == NULL ? lib->symbols
455 struct library_symbol *next = it->next;
457 switch ((*cb)(it, data)) {
473 library_add_symbol(struct library *lib, struct library_symbol *first)
475 struct library_symbol *last;
476 for (last = first; last != NULL; ) {
478 if (last->next != NULL)
484 assert(last->next == NULL);
485 last->next = lib->symbols;
486 lib->symbols = first;
490 library_named_cb(struct process *proc, struct library *lib, void *name)
492 if (name == lib->soname
493 || strcmp(lib->soname, (char *)name) == 0)
500 library_with_key_cb(struct process *proc, struct library *lib, void *keyp)
502 return lib->key == *(arch_addr_t *)keyp ? CBS_STOP : CBS_CONT;