|
Packit |
0021fb |
/*
|
|
Packit |
0021fb |
* This file is part of ltrace.
|
|
Packit |
0021fb |
* Copyright (C) 2011,2012,2013 Petr Machata, Red Hat Inc.
|
|
Packit |
0021fb |
* Copyright (C) 2001,2009 Juan Cespedes
|
|
Packit |
0021fb |
* Copyright (C) 2006 Ian Wienand
|
|
Packit |
0021fb |
*
|
|
Packit |
0021fb |
* This program is free software; you can redistribute it and/or
|
|
Packit |
0021fb |
* modify it under the terms of the GNU General Public License as
|
|
Packit |
0021fb |
* published by the Free Software Foundation; either version 2 of the
|
|
Packit |
0021fb |
* License, or (at your option) any later version.
|
|
Packit |
0021fb |
*
|
|
Packit |
0021fb |
* This program is distributed in the hope that it will be useful, but
|
|
Packit |
0021fb |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
0021fb |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
0021fb |
* General Public License for more details.
|
|
Packit |
0021fb |
*
|
|
Packit |
0021fb |
* You should have received a copy of the GNU General Public License
|
|
Packit |
0021fb |
* along with this program; if not, write to the Free Software
|
|
Packit |
0021fb |
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
|
Packit |
0021fb |
* 02110-1301 USA
|
|
Packit |
0021fb |
*/
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
#include <stdlib.h>
|
|
Packit |
0021fb |
#include <string.h>
|
|
Packit |
0021fb |
#include <assert.h>
|
|
Packit |
0021fb |
#include <stdio.h>
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
#include "library.h"
|
|
Packit |
0021fb |
#include "callback.h"
|
|
Packit |
0021fb |
#include "debug.h"
|
|
Packit |
0021fb |
#include "dict.h"
|
|
Packit |
0021fb |
#include "backend.h" // for arch_library_symbol_init, arch_library_init
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
#ifndef OS_HAVE_LIBRARY_DATA
|
|
Packit |
0021fb |
int
|
|
Packit |
0021fb |
os_library_init(struct library *lib)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
return 0;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
void
|
|
Packit |
0021fb |
os_library_destroy(struct library *lib)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
int
|
|
Packit |
0021fb |
os_library_clone(struct library *retp, struct library *lib)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
return 0;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
#endif
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
#ifndef ARCH_HAVE_LIBRARY_DATA
|
|
Packit |
0021fb |
int
|
|
Packit |
0021fb |
arch_library_init(struct library *lib)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
return 0;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
void
|
|
Packit |
0021fb |
arch_library_destroy(struct library *lib)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
int
|
|
Packit |
0021fb |
arch_library_clone(struct library *retp, struct library *lib)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
return 0;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
#endif
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
#ifndef OS_HAVE_LIBRARY_SYMBOL_DATA
|
|
Packit |
0021fb |
int
|
|
Packit |
0021fb |
os_library_symbol_init(struct library_symbol *libsym)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
return 0;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
void
|
|
Packit |
0021fb |
os_library_symbol_destroy(struct library_symbol *libsym)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
int
|
|
Packit |
0021fb |
os_library_symbol_clone(struct library_symbol *retp,
|
|
Packit |
0021fb |
struct library_symbol *libsym)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
return 0;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
#endif
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
#ifndef ARCH_HAVE_LIBRARY_SYMBOL_DATA
|
|
Packit |
0021fb |
int
|
|
Packit |
0021fb |
arch_library_symbol_init(struct library_symbol *libsym)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
return 0;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
void
|
|
Packit |
0021fb |
arch_library_symbol_destroy(struct library_symbol *libsym)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
int
|
|
Packit |
0021fb |
arch_library_symbol_clone(struct library_symbol *retp,
|
|
Packit |
0021fb |
struct library_symbol *libsym)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
return 0;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
#endif
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
size_t
|
|
Packit |
0021fb |
arch_addr_hash(const arch_addr_t *addr)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
union {
|
|
Packit |
0021fb |
arch_addr_t addr;
|
|
Packit |
0021fb |
int ints[sizeof(arch_addr_t)
|
|
Packit |
0021fb |
/ sizeof(unsigned int)];
|
|
Packit |
0021fb |
} u = { .addr = *addr };
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
size_t i;
|
|
Packit |
0021fb |
size_t h = 0;
|
|
Packit |
0021fb |
for (i = 0; i < sizeof(u.ints) / sizeof(*u.ints); ++i)
|
|
Packit |
0021fb |
h ^= dict_hash_int(&u.ints[i]);
|
|
Packit |
0021fb |
return h;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
int
|
|
Packit |
0021fb |
arch_addr_eq(const arch_addr_t *addr1, const arch_addr_t *addr2)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
return *addr1 == *addr2;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
int
|
|
Packit |
0021fb |
strdup_if(const char **retp, const char *str, int whether)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
if (whether && str != NULL) {
|
|
Packit |
0021fb |
str = strdup(str);
|
|
Packit |
0021fb |
if (str == NULL)
|
|
Packit |
0021fb |
return -1;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
*retp = str;
|
|
Packit |
0021fb |
return 0;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
static void
|
|
Packit |
0021fb |
private_library_symbol_init(struct library_symbol *libsym,
|
|
Packit |
0021fb |
arch_addr_t addr,
|
|
Packit |
0021fb |
const char *name, int own_name,
|
|
Packit |
0021fb |
enum toplt type_of_plt,
|
|
Packit |
0021fb |
int latent, int delayed)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
libsym->next = NULL;
|
|
Packit |
0021fb |
libsym->lib = NULL;
|
|
Packit |
0021fb |
libsym->plt_type = type_of_plt;
|
|
Packit |
0021fb |
libsym->name = name;
|
|
Packit |
0021fb |
libsym->own_name = own_name;
|
|
Packit |
0021fb |
libsym->latent = latent;
|
|
Packit |
0021fb |
libsym->delayed = delayed;
|
|
Packit |
0021fb |
libsym->enter_addr = (void *)(uintptr_t)addr;
|
|
Packit |
0021fb |
libsym->proto = NULL;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
static void
|
|
Packit |
0021fb |
private_library_symbol_destroy(struct library_symbol *libsym)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
library_symbol_set_name(libsym, NULL, 0);
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
int
|
|
Packit |
0021fb |
library_symbol_init(struct library_symbol *libsym,
|
|
Packit |
0021fb |
arch_addr_t addr, const char *name, int own_name,
|
|
Packit |
0021fb |
enum toplt type_of_plt)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
private_library_symbol_init(libsym, addr, name, own_name,
|
|
Packit |
0021fb |
type_of_plt, 0, 0);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
if (os_library_symbol_init(libsym) < 0)
|
|
Packit |
0021fb |
/* We've already set libsym->name and own_name. But
|
|
Packit |
0021fb |
* we return failure, and the client code isn't
|
|
Packit |
0021fb |
* supposed to call library_symbol_destroy in such
|
|
Packit |
0021fb |
* case. */
|
|
Packit |
0021fb |
return -1;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
if (arch_library_symbol_init(libsym) < 0) {
|
|
Packit |
0021fb |
os_library_symbol_destroy(libsym);
|
|
Packit |
0021fb |
return -1;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
return 0;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
void
|
|
Packit |
0021fb |
library_symbol_destroy(struct library_symbol *libsym)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
if (libsym != NULL) {
|
|
Packit |
0021fb |
arch_library_symbol_destroy(libsym);
|
|
Packit |
0021fb |
os_library_symbol_destroy(libsym);
|
|
Packit |
0021fb |
private_library_symbol_destroy(libsym);
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
int
|
|
Packit |
0021fb |
library_symbol_clone(struct library_symbol *retp, struct library_symbol *libsym)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
/* Make lifetimes of name stored at original independent of
|
|
Packit |
0021fb |
* the one at the clone. */
|
|
Packit |
0021fb |
const char *name;
|
|
Packit |
0021fb |
if (strdup_if(&name, libsym->name, libsym->own_name) < 0)
|
|
Packit |
0021fb |
return -1;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
private_library_symbol_init(retp, libsym->enter_addr,
|
|
Packit |
0021fb |
name, libsym->own_name, libsym->plt_type,
|
|
Packit |
0021fb |
libsym->latent, libsym->delayed);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
if (os_library_symbol_clone(retp, libsym) < 0) {
|
|
Packit |
0021fb |
fail:
|
|
Packit |
0021fb |
private_library_symbol_destroy(retp);
|
|
Packit |
0021fb |
return -1;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
if (arch_library_symbol_clone(retp, libsym) < 0) {
|
|
Packit |
0021fb |
os_library_symbol_destroy(retp);
|
|
Packit |
0021fb |
goto fail;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
return 0;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
int
|
|
Packit |
0021fb |
library_symbol_cmp(struct library_symbol *a, struct library_symbol *b)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
if (a->enter_addr < b->enter_addr)
|
|
Packit |
0021fb |
return -1;
|
|
Packit |
0021fb |
if (a->enter_addr > b->enter_addr)
|
|
Packit |
0021fb |
return 1;
|
|
Packit |
0021fb |
if (a->name != NULL && b->name != NULL)
|
|
Packit |
0021fb |
return strcmp(a->name, b->name);
|
|
Packit |
0021fb |
if (a->name == NULL) {
|
|
Packit |
0021fb |
if (b->name == NULL)
|
|
Packit |
0021fb |
return 0;
|
|
Packit |
0021fb |
return -1;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
return 1;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
void
|
|
Packit |
0021fb |
library_symbol_set_name(struct library_symbol *libsym,
|
|
Packit |
0021fb |
const char *name, int own_name)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
if (libsym->own_name)
|
|
Packit |
0021fb |
free((char *)libsym->name);
|
|
Packit |
0021fb |
libsym->name = name;
|
|
Packit |
0021fb |
libsym->own_name = own_name;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
enum callback_status
|
|
Packit |
0021fb |
library_symbol_equal_cb(struct library_symbol *libsym, void *u)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
struct library_symbol *standard = u;
|
|
Packit |
0021fb |
return library_symbol_cmp(libsym, standard) == 0 ? CBS_STOP : CBS_CONT;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
enum callback_status
|
|
Packit |
0021fb |
library_symbol_named_cb(struct library_symbol *libsym, void *name)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
return strcmp(libsym->name, name) == 0 ? CBS_STOP : CBS_CONT;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
enum callback_status
|
|
Packit |
0021fb |
library_symbol_delayed_cb(struct library_symbol *libsym, void *unused)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
return libsym->delayed ? CBS_STOP : CBS_CONT;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
static void
|
|
Packit |
0021fb |
private_library_init(struct library *lib, enum library_type type)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
lib->next = NULL;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
lib->key = 0;
|
|
Packit |
0021fb |
lib->base = 0;
|
|
Packit |
0021fb |
lib->entry = 0;
|
|
Packit |
0021fb |
lib->dyn_addr = 0;
|
|
Packit |
0021fb |
lib->protolib = NULL;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
lib->soname = NULL;
|
|
Packit |
0021fb |
lib->own_soname = 0;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
lib->pathname = NULL;
|
|
Packit |
0021fb |
lib->own_pathname = 0;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
lib->symbols = NULL;
|
|
Packit |
0021fb |
lib->exported_names = NULL;
|
|
Packit |
0021fb |
lib->type = type;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
int
|
|
Packit |
0021fb |
library_init(struct library *lib, enum library_type type)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
private_library_init(lib, type);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
if (os_library_init(lib) < 0)
|
|
Packit |
0021fb |
return -1;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
if (arch_library_init(lib) < 0) {
|
|
Packit |
0021fb |
os_library_destroy(lib);
|
|
Packit |
0021fb |
return -1;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
return 0;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
static int
|
|
Packit |
0021fb |
library_exported_name_clone(struct library_exported_name *retp,
|
|
Packit |
0021fb |
struct library_exported_name *exnm)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
char *name = exnm->own_name ? strdup(exnm->name) : (char *)exnm->name;
|
|
Packit |
0021fb |
if (name == NULL)
|
|
Packit |
0021fb |
return -1;
|
|
Packit |
0021fb |
retp->name = name;
|
|
Packit |
0021fb |
retp->own_name = exnm->own_name;
|
|
Packit |
0021fb |
return 0;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
int
|
|
Packit |
0021fb |
library_clone(struct library *retp, struct library *lib)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
const char *soname = NULL;
|
|
Packit |
0021fb |
const char *pathname;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Make lifetimes of strings stored at original independent of
|
|
Packit |
0021fb |
* those at the clone. */
|
|
Packit |
0021fb |
if (strdup_if(&soname, lib->soname, lib->own_soname) < 0
|
|
Packit |
0021fb |
|| strdup_if(&pathname, lib->pathname, lib->own_pathname) < 0) {
|
|
Packit |
0021fb |
if (lib->own_soname)
|
|
Packit |
0021fb |
free((char *)soname);
|
|
Packit |
0021fb |
return -1;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
private_library_init(retp, lib->type);
|
|
Packit |
0021fb |
library_set_soname(retp, soname, lib->own_soname);
|
|
Packit |
0021fb |
library_set_pathname(retp, pathname, lib->own_pathname);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
retp->key = lib->key;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Clone symbols. */
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
struct library_symbol *it;
|
|
Packit |
0021fb |
struct library_symbol **nsymp = &retp->symbols;
|
|
Packit |
0021fb |
for (it = lib->symbols; it != NULL; it = it->next) {
|
|
Packit |
0021fb |
*nsymp = malloc(sizeof(**nsymp));
|
|
Packit |
0021fb |
if (*nsymp == NULL
|
|
Packit |
0021fb |
|| library_symbol_clone(*nsymp, it) < 0) {
|
|
Packit |
0021fb |
free(*nsymp);
|
|
Packit |
0021fb |
*nsymp = NULL;
|
|
Packit |
0021fb |
fail:
|
|
Packit |
0021fb |
/* Release what we managed to allocate. */
|
|
Packit |
0021fb |
library_destroy(retp);
|
|
Packit |
0021fb |
return -1;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
(*nsymp)->lib = retp;
|
|
Packit |
0021fb |
nsymp = &(*nsymp)->next;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
*nsymp = NULL;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Clone exported names. */
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
struct library_exported_name *it;
|
|
Packit |
0021fb |
struct library_exported_name **nnamep = &retp->exported_names;
|
|
Packit |
0021fb |
for (it = lib->exported_names; it != NULL; it = it->next) {
|
|
Packit |
0021fb |
*nnamep = malloc(sizeof(**nnamep));
|
|
Packit |
0021fb |
if (*nnamep == NULL
|
|
Packit |
0021fb |
|| library_exported_name_clone(*nnamep, it) < 0) {
|
|
Packit |
0021fb |
free(*nnamep);
|
|
Packit |
0021fb |
goto fail;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
nnamep = &(*nnamep)->next;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
*nnamep = NULL;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
if (os_library_clone(retp, lib) < 0)
|
|
Packit |
0021fb |
goto fail;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
if (arch_library_clone(retp, lib) < 0) {
|
|
Packit |
0021fb |
os_library_destroy(retp);
|
|
Packit |
0021fb |
goto fail;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
return 0;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
void
|
|
Packit |
0021fb |
library_destroy(struct library *lib)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
if (lib == NULL)
|
|
Packit |
0021fb |
return;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
arch_library_destroy(lib);
|
|
Packit |
0021fb |
os_library_destroy(lib);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
library_set_soname(lib, NULL, 0);
|
|
Packit |
0021fb |
library_set_pathname(lib, NULL, 0);
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
struct library_symbol *sym;
|
|
Packit |
0021fb |
for (sym = lib->symbols; sym != NULL; ) {
|
|
Packit |
0021fb |
struct library_symbol *next = sym->next;
|
|
Packit |
0021fb |
library_symbol_destroy(sym);
|
|
Packit |
0021fb |
free(sym);
|
|
Packit |
0021fb |
sym = next;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Release exported names. */
|
|
Packit |
0021fb |
struct library_exported_name *it;
|
|
Packit |
0021fb |
for (it = lib->exported_names; it != NULL; ) {
|
|
Packit |
0021fb |
struct library_exported_name *next = it->next;
|
|
Packit |
0021fb |
if (it->own_name)
|
|
Packit |
0021fb |
free((char *)it->name);
|
|
Packit |
0021fb |
free(it);
|
|
Packit |
0021fb |
it = next;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
void
|
|
Packit |
0021fb |
library_set_soname(struct library *lib, const char *new_name, int own_name)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
if (lib->own_soname)
|
|
Packit |
0021fb |
free((char *)lib->soname);
|
|
Packit |
0021fb |
lib->soname = new_name;
|
|
Packit |
0021fb |
lib->own_soname = own_name;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
void
|
|
Packit |
0021fb |
library_set_pathname(struct library *lib, const char *new_name, int own_name)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
if (lib->own_pathname)
|
|
Packit |
0021fb |
free((char *)lib->pathname);
|
|
Packit |
0021fb |
lib->pathname = new_name;
|
|
Packit |
0021fb |
lib->own_pathname = own_name;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
struct library_symbol *
|
|
Packit |
0021fb |
library_each_symbol(struct library *lib, struct library_symbol *start_after,
|
|
Packit |
0021fb |
enum callback_status (*cb)(struct library_symbol *, void *),
|
|
Packit |
0021fb |
void *data)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
struct library_symbol *it = start_after == NULL ? lib->symbols
|
|
Packit |
0021fb |
: start_after->next;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
while (it != NULL) {
|
|
Packit |
0021fb |
struct library_symbol *next = it->next;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
switch ((*cb)(it, data)) {
|
|
Packit |
0021fb |
case CBS_FAIL:
|
|
Packit |
0021fb |
/* XXX handle me */
|
|
Packit |
0021fb |
case CBS_STOP:
|
|
Packit |
0021fb |
return it;
|
|
Packit |
0021fb |
case CBS_CONT:
|
|
Packit |
0021fb |
break;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
it = next;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
return NULL;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
void
|
|
Packit |
0021fb |
library_add_symbol(struct library *lib, struct library_symbol *first)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
struct library_symbol *last;
|
|
Packit |
0021fb |
for (last = first; last != NULL; ) {
|
|
Packit |
0021fb |
last->lib = lib;
|
|
Packit |
0021fb |
if (last->next != NULL)
|
|
Packit |
0021fb |
last = last->next;
|
|
Packit |
0021fb |
else
|
|
Packit |
0021fb |
break;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
assert(last->next == NULL);
|
|
Packit |
0021fb |
last->next = lib->symbols;
|
|
Packit |
0021fb |
lib->symbols = first;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
enum callback_status
|
|
Packit |
0021fb |
library_named_cb(struct process *proc, struct library *lib, void *name)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
if (name == lib->soname
|
|
Packit |
0021fb |
|| strcmp(lib->soname, (char *)name) == 0)
|
|
Packit |
0021fb |
return CBS_STOP;
|
|
Packit |
0021fb |
else
|
|
Packit |
0021fb |
return CBS_CONT;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
enum callback_status
|
|
Packit |
0021fb |
library_with_key_cb(struct process *proc, struct library *lib, void *keyp)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
return lib->key == *(arch_addr_t *)keyp ? CBS_STOP : CBS_CONT;
|
|
Packit |
0021fb |
}
|