Home | History | Annotate | Download | only in ltrace
      1 /*
      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
      6  *
      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.
     11  *
     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.
     16  *
     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
     20  * 02110-1301 USA
     21  */
     22 
     23 #include <stdlib.h>
     24 #include <string.h>
     25 #include <assert.h>
     26 #include <stdio.h>
     27 
     28 #include "library.h"
     29 #include "callback.h"
     30 #include "debug.h"
     31 #include "dict.h"
     32 #include "backend.h" // for arch_library_symbol_init, arch_library_init
     33 
     34 #ifndef OS_HAVE_LIBRARY_DATA
     35 int
     36 os_library_init(struct library *lib)
     37 {
     38 	return 0;
     39 }
     40 
     41 void
     42 os_library_destroy(struct library *lib)
     43 {
     44 }
     45 
     46 int
     47 os_library_clone(struct library *retp, struct library *lib)
     48 {
     49 	return 0;
     50 }
     51 #endif
     52 
     53 #ifndef ARCH_HAVE_LIBRARY_DATA
     54 int
     55 arch_library_init(struct library *lib)
     56 {
     57 	return 0;
     58 }
     59 
     60 void
     61 arch_library_destroy(struct library *lib)
     62 {
     63 }
     64 
     65 int
     66 arch_library_clone(struct library *retp, struct library *lib)
     67 {
     68 	return 0;
     69 }
     70 #endif
     71 
     72 #ifndef OS_HAVE_LIBRARY_SYMBOL_DATA
     73 int
     74 os_library_symbol_init(struct library_symbol *libsym)
     75 {
     76 	return 0;
     77 }
     78 
     79 void
     80 os_library_symbol_destroy(struct library_symbol *libsym)
     81 {
     82 }
     83 
     84 int
     85 os_library_symbol_clone(struct library_symbol *retp,
     86 			struct library_symbol *libsym)
     87 {
     88 	return 0;
     89 }
     90 #endif
     91 
     92 #ifndef ARCH_HAVE_LIBRARY_SYMBOL_DATA
     93 int
     94 arch_library_symbol_init(struct library_symbol *libsym)
     95 {
     96 	return 0;
     97 }
     98 
     99 void
    100 arch_library_symbol_destroy(struct library_symbol *libsym)
    101 {
    102 }
    103 
    104 int
    105 arch_library_symbol_clone(struct library_symbol *retp,
    106 			  struct library_symbol *libsym)
    107 {
    108 	return 0;
    109 }
    110 #endif
    111 
    112 size_t
    113 arch_addr_hash(const arch_addr_t *addr)
    114 {
    115 	union {
    116 		arch_addr_t addr;
    117 		int ints[sizeof(arch_addr_t)
    118 			 / sizeof(unsigned int)];
    119 	} u = { .addr = *addr };
    120 
    121 	size_t i;
    122 	size_t h = 0;
    123 	for (i = 0; i < sizeof(u.ints) / sizeof(*u.ints); ++i)
    124 		h ^= dict_hash_int(&u.ints[i]);
    125 	return h;
    126 }
    127 
    128 int
    129 arch_addr_eq(const arch_addr_t *addr1, const arch_addr_t *addr2)
    130 {
    131 	return *addr1 == *addr2;
    132 }
    133 
    134 int
    135 strdup_if(const char **retp, const char *str, int whether)
    136 {
    137 	if (whether && str != NULL) {
    138 		str = strdup(str);
    139 		if (str == NULL)
    140 			return -1;
    141 	}
    142 
    143 	*retp = str;
    144 	return 0;
    145 }
    146 
    147 static void
    148 private_library_symbol_init(struct library_symbol *libsym,
    149 			    arch_addr_t addr,
    150 			    const char *name, int own_name,
    151 			    enum toplt type_of_plt,
    152 			    int latent, int delayed)
    153 {
    154 	libsym->next = NULL;
    155 	libsym->lib = NULL;
    156 	libsym->plt_type = type_of_plt;
    157 	libsym->name = name;
    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;
    163 }
    164 
    165 static void
    166 private_library_symbol_destroy(struct library_symbol *libsym)
    167 {
    168 	library_symbol_set_name(libsym, NULL, 0);
    169 }
    170 
    171 int
    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)
    175 {
    176 	private_library_symbol_init(libsym, addr, name, own_name,
    177 				    type_of_plt, 0, 0);
    178 
    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
    183 		 * case.  */
    184 		return -1;
    185 
    186 	if (arch_library_symbol_init(libsym) < 0) {
    187 		os_library_symbol_destroy(libsym);
    188 		return -1;
    189 	}
    190 
    191 	return 0;
    192 }
    193 
    194 void
    195 library_symbol_destroy(struct library_symbol *libsym)
    196 {
    197 	if (libsym != NULL) {
    198 		arch_library_symbol_destroy(libsym);
    199 		os_library_symbol_destroy(libsym);
    200 		private_library_symbol_destroy(libsym);
    201 	}
    202 }
    203 
    204 int
    205 library_symbol_clone(struct library_symbol *retp, struct library_symbol *libsym)
    206 {
    207 	/* Make lifetimes of name stored at original independent of
    208 	 * the one at the clone.  */
    209 	const char *name;
    210 	if (strdup_if(&name, libsym->name, libsym->own_name) < 0)
    211 		return -1;
    212 
    213 	private_library_symbol_init(retp, libsym->enter_addr,
    214 				    name, libsym->own_name, libsym->plt_type,
    215 				    libsym->latent, libsym->delayed);
    216 
    217 	if (os_library_symbol_clone(retp, libsym) < 0) {
    218 	fail:
    219 		private_library_symbol_destroy(retp);
    220 		return -1;
    221 	}
    222 
    223 	if (arch_library_symbol_clone(retp, libsym) < 0) {
    224 		os_library_symbol_destroy(retp);
    225 		goto fail;
    226 	}
    227 
    228 	return 0;
    229 }
    230 
    231 int
    232 library_symbol_cmp(struct library_symbol *a, struct library_symbol *b)
    233 {
    234 	if (a->enter_addr < b->enter_addr)
    235 		return -1;
    236 	if (a->enter_addr > b->enter_addr)
    237 		return 1;
    238 	if (a->name != NULL && b->name != NULL)
    239 		return strcmp(a->name, b->name);
    240 	if (a->name == NULL) {
    241 		if (b->name == NULL)
    242 			return 0;
    243 		return -1;
    244 	}
    245 	return 1;
    246 }
    247 
    248 void
    249 library_symbol_set_name(struct library_symbol *libsym,
    250 			const char *name, int own_name)
    251 {
    252 	if (libsym->own_name)
    253 		free((char *)libsym->name);
    254 	libsym->name = name;
    255 	libsym->own_name = own_name;
    256 }
    257 
    258 enum callback_status
    259 library_symbol_equal_cb(struct library_symbol *libsym, void *u)
    260 {
    261 	struct library_symbol *standard = u;
    262 	return library_symbol_cmp(libsym, standard) == 0 ? CBS_STOP : CBS_CONT;
    263 }
    264 
    265 enum callback_status
    266 library_symbol_named_cb(struct library_symbol *libsym, void *name)
    267 {
    268 	return strcmp(libsym->name, name) == 0 ? CBS_STOP : CBS_CONT;
    269 }
    270 
    271 enum callback_status
    272 library_symbol_delayed_cb(struct library_symbol *libsym, void *unused)
    273 {
    274 	return libsym->delayed ? CBS_STOP : CBS_CONT;
    275 }
    276 
    277 static void
    278 private_library_init(struct library *lib, enum library_type type)
    279 {
    280 	lib->next = NULL;
    281 
    282 	lib->key = 0;
    283 	lib->base = 0;
    284 	lib->entry = 0;
    285 	lib->dyn_addr = 0;
    286 	lib->protolib = NULL;
    287 
    288 	lib->soname = NULL;
    289 	lib->own_soname = 0;
    290 
    291 	lib->pathname = NULL;
    292 	lib->own_pathname = 0;
    293 
    294 	lib->symbols = NULL;
    295 	lib->exported_names = NULL;
    296 	lib->type = type;
    297 }
    298 
    299 int
    300 library_init(struct library *lib, enum library_type type)
    301 {
    302 	private_library_init(lib, type);
    303 
    304 	if (os_library_init(lib) < 0)
    305 		return -1;
    306 
    307 	if (arch_library_init(lib) < 0) {
    308 		os_library_destroy(lib);
    309 		return -1;
    310 	}
    311 
    312 	return 0;
    313 }
    314 
    315 static int
    316 library_exported_name_clone(struct library_exported_name *retp,
    317 			    struct library_exported_name *exnm)
    318 {
    319 	char *name = exnm->own_name ? strdup(exnm->name) : (char *)exnm->name;
    320 	if (name == NULL)
    321 		return -1;
    322 	retp->name = name;
    323 	retp->own_name = exnm->own_name;
    324 	return 0;
    325 }
    326 
    327 int
    328 library_clone(struct library *retp, struct library *lib)
    329 {
    330 	const char *soname = NULL;
    331 	const char *pathname;
    332 
    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) {
    337 		if (lib->own_soname)
    338 			free((char *)soname);
    339 		return -1;
    340 	}
    341 
    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);
    345 
    346 	retp->key = lib->key;
    347 
    348 	/* Clone symbols.  */
    349 	{
    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));
    354 			if (*nsymp == NULL
    355 			    || library_symbol_clone(*nsymp, it) < 0) {
    356 				free(*nsymp);
    357 				*nsymp = NULL;
    358 			fail:
    359 				/* Release what we managed to allocate.  */
    360 				library_destroy(retp);
    361 				return -1;
    362 			}
    363 
    364 			(*nsymp)->lib = retp;
    365 			nsymp = &(*nsymp)->next;
    366 		}
    367 		*nsymp = NULL;
    368 	}
    369 
    370 	/* Clone exported names.  */
    371 	{
    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));
    376 			if (*nnamep == NULL
    377 			    || library_exported_name_clone(*nnamep, it) < 0) {
    378 				free(*nnamep);
    379 				goto fail;
    380 			}
    381 			nnamep = &(*nnamep)->next;
    382 		}
    383 		*nnamep = NULL;
    384 	}
    385 
    386 	if (os_library_clone(retp, lib) < 0)
    387 		goto fail;
    388 
    389 	if (arch_library_clone(retp, lib) < 0) {
    390 		os_library_destroy(retp);
    391 		goto fail;
    392 	}
    393 
    394 	return 0;
    395 }
    396 
    397 void
    398 library_destroy(struct library *lib)
    399 {
    400 	if (lib == NULL)
    401 		return;
    402 
    403 	arch_library_destroy(lib);
    404 	os_library_destroy(lib);
    405 
    406 	library_set_soname(lib, NULL, 0);
    407 	library_set_pathname(lib, NULL, 0);
    408 
    409 	struct library_symbol *sym;
    410 	for (sym = lib->symbols; sym != NULL; ) {
    411 		struct library_symbol *next = sym->next;
    412 		library_symbol_destroy(sym);
    413 		free(sym);
    414 		sym = next;
    415 	}
    416 
    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;
    421 		if (it->own_name)
    422 			free((char *)it->name);
    423 		free(it);
    424 		it = next;
    425 	}
    426 }
    427 
    428 void
    429 library_set_soname(struct library *lib, const char *new_name, int own_name)
    430 {
    431 	if (lib->own_soname)
    432 		free((char *)lib->soname);
    433 	lib->soname = new_name;
    434 	lib->own_soname = own_name;
    435 }
    436 
    437 void
    438 library_set_pathname(struct library *lib, const char *new_name, int own_name)
    439 {
    440 	if (lib->own_pathname)
    441 		free((char *)lib->pathname);
    442 	lib->pathname = new_name;
    443 	lib->own_pathname = own_name;
    444 }
    445 
    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 *),
    449 		    void *data)
    450 {
    451 	struct library_symbol *it = start_after == NULL ? lib->symbols
    452 		: start_after->next;
    453 
    454 	while (it != NULL) {
    455 		struct library_symbol *next = it->next;
    456 
    457 		switch ((*cb)(it, data)) {
    458 		case CBS_FAIL:
    459 			/* XXX handle me  */
    460 		case CBS_STOP:
    461 			return it;
    462 		case CBS_CONT:
    463 			break;
    464 		}
    465 
    466 		it = next;
    467 	}
    468 
    469 	return NULL;
    470 }
    471 
    472 void
    473 library_add_symbol(struct library *lib, struct library_symbol *first)
    474 {
    475 	struct library_symbol *last;
    476 	for (last = first; last != NULL; ) {
    477 		last->lib = lib;
    478 		if (last->next != NULL)
    479 			last = last->next;
    480 		else
    481 			break;
    482 	}
    483 
    484 	assert(last->next == NULL);
    485 	last->next = lib->symbols;
    486 	lib->symbols = first;
    487 }
    488 
    489 enum callback_status
    490 library_named_cb(struct process *proc, struct library *lib, void *name)
    491 {
    492 	if (name == lib->soname
    493 	    || strcmp(lib->soname, (char *)name) == 0)
    494 		return CBS_STOP;
    495 	else
    496 		return CBS_CONT;
    497 }
    498 
    499 enum callback_status
    500 library_with_key_cb(struct process *proc, struct library *lib, void *keyp)
    501 {
    502 	return lib->key == *(arch_addr_t *)keyp ? CBS_STOP : CBS_CONT;
    503 }
    504