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