blob: 1f425e0d4da3d6d7e6c5a0cc2cd66ca4eda82ae1 [file] [log] [blame]
Petr Machata2b46cfc2012-02-18 11:17:29 +01001/*
2 * This file is part of ltrace.
Petr Machatab1ab2ae2013-01-07 18:09:32 +01003 * Copyright (C) 2011,2012,2013 Petr Machata, Red Hat Inc.
Petr Machata2b46cfc2012-02-18 11:17:29 +01004 * 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>
Petr Machata8cce1192012-03-25 01:37:19 +010025#include <assert.h>
Petr Machatafb8502c2012-10-27 19:24:35 +020026#include <stdio.h>
Petr Machata8cce1192012-03-25 01:37:19 +010027
Petr Machata2b46cfc2012-02-18 11:17:29 +010028#include "library.h"
Petr Machataa24021c2012-09-25 14:46:44 +020029#include "callback.h"
Petr Machata2b46cfc2012-02-18 11:17:29 +010030#include "debug.h"
Petr Machataa24021c2012-09-25 14:46:44 +020031#include "dict.h"
Petr Machata98d319e2012-05-04 02:22:47 +020032#include "backend.h" // for arch_library_symbol_init, arch_library_init
Petr Machata2b46cfc2012-02-18 11:17:29 +010033
Petr Machata8fdd09b2013-10-11 15:08:30 +020034#ifndef OS_HAVE_LIBRARY_DATA
35int
36os_library_init(struct library *lib)
37{
38 return 0;
39}
40
41void
42os_library_destroy(struct library *lib)
43{
44}
45
46int
47os_library_clone(struct library *retp, struct library *lib)
48{
49 return 0;
50}
51#endif
52
Petr Machata994ad6d2012-04-17 03:07:04 +020053#ifndef ARCH_HAVE_LIBRARY_DATA
Petr Machata72871662013-10-11 14:29:09 +020054int
Petr Machata994ad6d2012-04-17 03:07:04 +020055arch_library_init(struct library *lib)
56{
Petr Machata72871662013-10-11 14:29:09 +020057 return 0;
Petr Machata994ad6d2012-04-17 03:07:04 +020058}
59
60void
61arch_library_destroy(struct library *lib)
62{
63}
64
Petr Machata72871662013-10-11 14:29:09 +020065int
Petr Machata994ad6d2012-04-17 03:07:04 +020066arch_library_clone(struct library *retp, struct library *lib)
67{
Petr Machata72871662013-10-11 14:29:09 +020068 return 0;
Petr Machata994ad6d2012-04-17 03:07:04 +020069}
70#endif
71
Petr Machata8fdd09b2013-10-11 15:08:30 +020072#ifndef OS_HAVE_LIBRARY_SYMBOL_DATA
73int
74os_library_symbol_init(struct library_symbol *libsym)
75{
76 return 0;
77}
78
79void
80os_library_symbol_destroy(struct library_symbol *libsym)
81{
82}
83
84int
85os_library_symbol_clone(struct library_symbol *retp,
86 struct library_symbol *libsym)
87{
88 return 0;
89}
90#endif
91
Petr Machata994ad6d2012-04-17 03:07:04 +020092#ifndef ARCH_HAVE_LIBRARY_SYMBOL_DATA
93int
94arch_library_symbol_init(struct library_symbol *libsym)
95{
96 return 0;
97}
98
99void
100arch_library_symbol_destroy(struct library_symbol *libsym)
101{
102}
103
104int
105arch_library_symbol_clone(struct library_symbol *retp,
106 struct library_symbol *libsym)
107{
108 return 0;
109}
110#endif
111
Petr Machatad7e4ca82012-11-28 03:38:47 +0100112size_t
113arch_addr_hash(const arch_addr_t *addr)
Petr Machataecb082f2012-04-05 02:10:10 +0200114{
Petr Machataecb082f2012-04-05 02:10:10 +0200115 union {
Petr Machatabac2da52012-05-29 00:42:59 +0200116 arch_addr_t addr;
Petr Machatad7e4ca82012-11-28 03:38:47 +0100117 int ints[sizeof(arch_addr_t)
118 / sizeof(unsigned int)];
119 } u = { .addr = *addr };
Petr Machataecb082f2012-04-05 02:10:10 +0200120
121 size_t i;
Petr Machatad7e4ca82012-11-28 03:38:47 +0100122 size_t h = 0;
Petr Machataecb082f2012-04-05 02:10:10 +0200123 for (i = 0; i < sizeof(u.ints) / sizeof(*u.ints); ++i)
Petr Machatad7e4ca82012-11-28 03:38:47 +0100124 h ^= dict_hash_int(&u.ints[i]);
Petr Machataecb082f2012-04-05 02:10:10 +0200125 return h;
126}
127
128int
Petr Machatad7e4ca82012-11-28 03:38:47 +0100129arch_addr_eq(const arch_addr_t *addr1, const arch_addr_t *addr2)
Petr Machataecb082f2012-04-05 02:10:10 +0200130{
Petr Machatad7e4ca82012-11-28 03:38:47 +0100131 return *addr1 == *addr2;
Petr Machataecb082f2012-04-05 02:10:10 +0200132}
133
Petr Machatab1ab2ae2013-01-07 18:09:32 +0100134int
135strdup_if(const char **retp, const char *str, int whether)
Petr Machata2b46cfc2012-02-18 11:17:29 +0100136{
Petr Machatab1ab2ae2013-01-07 18:09:32 +0100137 if (whether && str != NULL) {
138 str = strdup(str);
139 if (str == NULL)
140 return -1;
Petr Machata2b46cfc2012-02-18 11:17:29 +0100141 }
Petr Machatab1ab2ae2013-01-07 18:09:32 +0100142
143 *retp = str;
144 return 0;
Petr Machata2b46cfc2012-02-18 11:17:29 +0100145}
146
Petr Machata24c6e9d2012-04-15 04:31:34 +0200147static void
Petr Machatae8d90762012-04-15 04:28:31 +0200148private_library_symbol_init(struct library_symbol *libsym,
Petr Machatabac2da52012-05-29 00:42:59 +0200149 arch_addr_t addr,
Petr Machatae8d90762012-04-15 04:28:31 +0200150 const char *name, int own_name,
Petr Machataef2fd272012-09-28 00:43:01 +0200151 enum toplt type_of_plt,
152 int latent, int delayed)
Petr Machata2b46cfc2012-02-18 11:17:29 +0100153{
Petr Machata29add4f2012-02-18 16:38:05 +0100154 libsym->next = NULL;
Petr Machatae6523e62012-03-24 04:54:06 +0100155 libsym->lib = NULL;
Petr Machata2b46cfc2012-02-18 11:17:29 +0100156 libsym->plt_type = type_of_plt;
157 libsym->name = name;
158 libsym->own_name = own_name;
Petr Machataef2fd272012-09-28 00:43:01 +0200159 libsym->latent = latent;
160 libsym->delayed = delayed;
Petr Machata2b46cfc2012-02-18 11:17:29 +0100161 libsym->enter_addr = (void *)(uintptr_t)addr;
Petr Machatab8f0d8b2013-10-16 14:25:45 +0200162 libsym->proto = NULL;
Petr Machata2b46cfc2012-02-18 11:17:29 +0100163}
164
Petr Machata24c6e9d2012-04-15 04:31:34 +0200165static void
166private_library_symbol_destroy(struct library_symbol *libsym)
167{
168 library_symbol_set_name(libsym, NULL, 0);
169}
170
Petr Machatae8d90762012-04-15 04:28:31 +0200171int
172library_symbol_init(struct library_symbol *libsym,
Petr Machatabac2da52012-05-29 00:42:59 +0200173 arch_addr_t addr, const char *name, int own_name,
Petr Machatae8d90762012-04-15 04:28:31 +0200174 enum toplt type_of_plt)
175{
Petr Machataef2fd272012-09-28 00:43:01 +0200176 private_library_symbol_init(libsym, addr, name, own_name,
177 type_of_plt, 0, 0);
Petr Machatae8d90762012-04-15 04:28:31 +0200178
Petr Machata8fdd09b2013-10-11 15:08:30 +0200179 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;
Petr Machatae8d90762012-04-15 04:28:31 +0200192}
193
Petr Machata2b46cfc2012-02-18 11:17:29 +0100194void
195library_symbol_destroy(struct library_symbol *libsym)
196{
Petr Machata24c6e9d2012-04-15 04:31:34 +0200197 if (libsym != NULL) {
Petr Machata24c6e9d2012-04-15 04:31:34 +0200198 arch_library_symbol_destroy(libsym);
Petr Machata8fdd09b2013-10-11 15:08:30 +0200199 os_library_symbol_destroy(libsym);
200 private_library_symbol_destroy(libsym);
Petr Machata24c6e9d2012-04-15 04:31:34 +0200201 }
Petr Machata2b46cfc2012-02-18 11:17:29 +0100202}
203
204int
205library_symbol_clone(struct library_symbol *retp, struct library_symbol *libsym)
206{
Petr Machatab1ab2ae2013-01-07 18:09:32 +0100207 /* Make lifetimes of name stored at original independent of
208 * the one at the clone. */
Petr Machata2b46cfc2012-02-18 11:17:29 +0100209 const char *name;
Petr Machatab1ab2ae2013-01-07 18:09:32 +0100210 if (strdup_if(&name, libsym->name, libsym->own_name) < 0)
Petr Machata2b46cfc2012-02-18 11:17:29 +0100211 return -1;
212
Petr Machatae8d90762012-04-15 04:28:31 +0200213 private_library_symbol_init(retp, libsym->enter_addr,
Petr Machataef2fd272012-09-28 00:43:01 +0200214 name, libsym->own_name, libsym->plt_type,
215 libsym->latent, libsym->delayed);
Petr Machata24c6e9d2012-04-15 04:31:34 +0200216
Petr Machata8fdd09b2013-10-11 15:08:30 +0200217 if (os_library_symbol_clone(retp, libsym) < 0) {
218 fail:
Petr Machata24c6e9d2012-04-15 04:31:34 +0200219 private_library_symbol_destroy(retp);
220 return -1;
221 }
222
Petr Machata8fdd09b2013-10-11 15:08:30 +0200223 if (arch_library_symbol_clone(retp, libsym) < 0) {
224 os_library_symbol_destroy(retp);
225 goto fail;
226 }
227
Petr Machata2b46cfc2012-02-18 11:17:29 +0100228 return 0;
229}
230
231int
232library_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
Petr Machata157cc4d2012-04-04 19:00:34 +0200248void
249library_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
Petr Machata2b46cfc2012-02-18 11:17:29 +0100258enum callback_status
259library_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
Petr Machata016811f2012-09-27 23:29:22 +0200265enum callback_status
266library_symbol_named_cb(struct library_symbol *libsym, void *name)
267{
268 return strcmp(libsym->name, name) == 0 ? CBS_STOP : CBS_CONT;
269}
Petr Machata994ad6d2012-04-17 03:07:04 +0200270
Petr Machataab2dab52012-11-07 16:06:33 +0100271enum callback_status
272library_symbol_delayed_cb(struct library_symbol *libsym, void *unused)
273{
274 return libsym->delayed ? CBS_STOP : CBS_CONT;
275}
276
Petr Machata994ad6d2012-04-17 03:07:04 +0200277static void
278private_library_init(struct library *lib, enum library_type type)
Petr Machata2b46cfc2012-02-18 11:17:29 +0100279{
280 lib->next = NULL;
Petr Machata8ae36732012-04-30 01:19:09 +0200281
282 lib->key = 0;
283 lib->base = 0;
284 lib->entry = 0;
285 lib->dyn_addr = 0;
Petr Machataf70074c2012-12-05 01:40:51 +0100286 lib->protolib = NULL;
Petr Machata8ae36732012-04-30 01:19:09 +0200287
Petr Machata0b55b582012-04-02 00:38:46 +0200288 lib->soname = NULL;
289 lib->own_soname = 0;
Petr Machata8ae36732012-04-30 01:19:09 +0200290
Petr Machata0b55b582012-04-02 00:38:46 +0200291 lib->pathname = NULL;
292 lib->own_pathname = 0;
Petr Machata8ae36732012-04-30 01:19:09 +0200293
Petr Machata2b46cfc2012-02-18 11:17:29 +0100294 lib->symbols = NULL;
Petr Machata4b4dff42012-09-27 23:49:49 +0200295 lib->exported_names = NULL;
Petr Machatab5f80ac2012-04-04 01:46:18 +0200296 lib->type = type;
Petr Machata2b46cfc2012-02-18 11:17:29 +0100297}
298
Petr Machata72871662013-10-11 14:29:09 +0200299int
Petr Machata994ad6d2012-04-17 03:07:04 +0200300library_init(struct library *lib, enum library_type type)
301{
302 private_library_init(lib, type);
Petr Machata8fdd09b2013-10-11 15:08:30 +0200303
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;
Petr Machata994ad6d2012-04-17 03:07:04 +0200313}
314
Petr Machata4b4dff42012-09-27 23:49:49 +0200315static int
316library_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
Petr Machata2b46cfc2012-02-18 11:17:29 +0100327int
328library_clone(struct library *retp, struct library *lib)
329{
Petr Machata0b55b582012-04-02 00:38:46 +0200330 const char *soname = NULL;
331 const char *pathname;
Petr Machatab1ab2ae2013-01-07 18:09:32 +0100332
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) {
Petr Machata0b55b582012-04-02 00:38:46 +0200337 if (lib->own_soname)
338 free((char *)soname);
Petr Machata2b46cfc2012-02-18 11:17:29 +0100339 return -1;
Petr Machata0b55b582012-04-02 00:38:46 +0200340 }
Petr Machata2b46cfc2012-02-18 11:17:29 +0100341
Petr Machata994ad6d2012-04-17 03:07:04 +0200342 private_library_init(retp, lib->type);
Petr Machatab5f80ac2012-04-04 01:46:18 +0200343 library_set_soname(retp, soname, lib->own_soname);
Petr Machatafb8502c2012-10-27 19:24:35 +0200344 library_set_pathname(retp, pathname, lib->own_pathname);
Petr Machata2b46cfc2012-02-18 11:17:29 +0100345
Petr Machatafb8502c2012-10-27 19:24:35 +0200346 retp->key = lib->key;
347
Petr Machata4b4dff42012-09-27 23:49:49 +0200348 /* 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);
Petr Machatad19b9162013-01-07 20:16:57 +0100357 *nsymp = NULL;
Petr Machata4b4dff42012-09-27 23:49:49 +0200358 fail:
359 /* Release what we managed to allocate. */
360 library_destroy(retp);
361 return -1;
362 }
Petr Machata2b46cfc2012-02-18 11:17:29 +0100363
Petr Machata4b4dff42012-09-27 23:49:49 +0200364 (*nsymp)->lib = retp;
365 nsymp = &(*nsymp)->next;
366 }
Petr Machatafb8502c2012-10-27 19:24:35 +0200367 *nsymp = NULL;
Petr Machata2b46cfc2012-02-18 11:17:29 +0100368 }
Petr Machata4b4dff42012-09-27 23:49:49 +0200369
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 }
Petr Machata23e2b592012-10-27 16:03:09 +0200383 *nnamep = NULL;
Petr Machata4b4dff42012-09-27 23:49:49 +0200384 }
385
Petr Machata8fdd09b2013-10-11 15:08:30 +0200386 if (os_library_clone(retp, lib) < 0)
Petr Machata72871662013-10-11 14:29:09 +0200387 goto fail;
388
Petr Machata8fdd09b2013-10-11 15:08:30 +0200389 if (arch_library_clone(retp, lib) < 0) {
390 os_library_destroy(retp);
391 goto fail;
392 }
393
Petr Machata2b46cfc2012-02-18 11:17:29 +0100394 return 0;
395}
396
397void
398library_destroy(struct library *lib)
399{
400 if (lib == NULL)
401 return;
Petr Machata994ad6d2012-04-17 03:07:04 +0200402
403 arch_library_destroy(lib);
Petr Machata8fdd09b2013-10-11 15:08:30 +0200404 os_library_destroy(lib);
405
Petr Machata0b55b582012-04-02 00:38:46 +0200406 library_set_soname(lib, NULL, 0);
407 library_set_pathname(lib, NULL, 0);
Petr Machata2b46cfc2012-02-18 11:17:29 +0100408
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 }
Petr Machata819fdb72012-10-27 02:36:50 +0200416
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 }
Petr Machata2b46cfc2012-02-18 11:17:29 +0100426}
427
428void
Petr Machata0b55b582012-04-02 00:38:46 +0200429library_set_soname(struct library *lib, const char *new_name, int own_name)
Petr Machata2b46cfc2012-02-18 11:17:29 +0100430{
Petr Machata0b55b582012-04-02 00:38:46 +0200431 if (lib->own_soname)
432 free((char *)lib->soname);
433 lib->soname = new_name;
434 lib->own_soname = own_name;
435}
436
437void
438library_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;
Petr Machata2b46cfc2012-02-18 11:17:29 +0100444}
445
446struct library_symbol *
Petr Machata74132a42012-03-16 02:46:18 +0100447library_each_symbol(struct library *lib, struct library_symbol *start_after,
Petr Machata2b46cfc2012-02-18 11:17:29 +0100448 enum callback_status (*cb)(struct library_symbol *, void *),
449 void *data)
450{
Petr Machata74132a42012-03-16 02:46:18 +0100451 struct library_symbol *it = start_after == NULL ? lib->symbols
452 : start_after->next;
Petr Machata2b46cfc2012-02-18 11:17:29 +0100453
454 while (it != NULL) {
455 struct library_symbol *next = it->next;
456
457 switch ((*cb)(it, data)) {
Petr Machataef7fa372012-03-28 02:05:36 +0200458 case CBS_FAIL:
459 /* XXX handle me */
Petr Machata2b46cfc2012-02-18 11:17:29 +0100460 case CBS_STOP:
461 return it;
462 case CBS_CONT:
463 break;
464 }
465
466 it = next;
467 }
468
469 return NULL;
470}
471
472void
Petr Machata8cce1192012-03-25 01:37:19 +0100473library_add_symbol(struct library *lib, struct library_symbol *first)
Petr Machata2b46cfc2012-02-18 11:17:29 +0100474{
Petr Machata8cce1192012-03-25 01:37:19 +0100475 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 }
Petr Machatae6523e62012-03-24 04:54:06 +0100483
Petr Machata8cce1192012-03-25 01:37:19 +0100484 assert(last->next == NULL);
485 last->next = lib->symbols;
486 lib->symbols = first;
Petr Machata2b46cfc2012-02-18 11:17:29 +0100487}
488
489enum callback_status
Petr Machata929bd572012-12-17 03:20:34 +0100490library_named_cb(struct process *proc, struct library *lib, void *name)
Petr Machata2b46cfc2012-02-18 11:17:29 +0100491{
Petr Machata0b55b582012-04-02 00:38:46 +0200492 if (name == lib->soname
493 || strcmp(lib->soname, (char *)name) == 0)
Petr Machata2b46cfc2012-02-18 11:17:29 +0100494 return CBS_STOP;
495 else
496 return CBS_CONT;
497}
498
499enum callback_status
Petr Machata929bd572012-12-17 03:20:34 +0100500library_with_key_cb(struct process *proc, struct library *lib, void *keyp)
Petr Machata2b46cfc2012-02-18 11:17:29 +0100501{
Petr Machatabac2da52012-05-29 00:42:59 +0200502 return lib->key == *(arch_addr_t *)keyp ? CBS_STOP : CBS_CONT;
Petr Machata2b46cfc2012-02-18 11:17:29 +0100503}