In ppc-lwarx.exp, Dwarf backend may resolve atomic_add's prototype
[platform/upstream/ltrace.git] / library.c
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 #if defined(HAVE_LIBDW)
299         lib->dwfl = NULL;
300 #endif
301 }
302
303 int
304 library_init(struct library *lib, enum library_type type)
305 {
306         private_library_init(lib, type);
307
308         if (os_library_init(lib) < 0)
309                 return -1;
310
311         if (arch_library_init(lib) < 0) {
312                 os_library_destroy(lib);
313                 return -1;
314         }
315
316         return 0;
317 }
318
319 static int
320 library_exported_name_clone(struct library_exported_name *retp,
321                             struct library_exported_name *exnm)
322 {
323         char *name = exnm->own_name ? strdup(exnm->name) : (char *)exnm->name;
324         if (name == NULL)
325                 return -1;
326         retp->name = name;
327         retp->own_name = exnm->own_name;
328         return 0;
329 }
330
331 int
332 library_clone(struct library *retp, struct library *lib)
333 {
334         const char *soname = NULL;
335         const char *pathname;
336
337         /* Make lifetimes of strings stored at original independent of
338          * those at the clone.  */
339         if (strdup_if(&soname, lib->soname, lib->own_soname) < 0
340             || strdup_if(&pathname, lib->pathname, lib->own_pathname) < 0) {
341                 if (lib->own_soname)
342                         free((char *)soname);
343                 return -1;
344         }
345
346         private_library_init(retp, lib->type);
347         library_set_soname(retp, soname, lib->own_soname);
348         library_set_pathname(retp, pathname, lib->own_pathname);
349
350         retp->key = lib->key;
351
352         /* Clone symbols.  */
353         {
354                 struct library_symbol *it;
355                 struct library_symbol **nsymp = &retp->symbols;
356                 for (it = lib->symbols; it != NULL; it = it->next) {
357                         *nsymp = malloc(sizeof(**nsymp));
358                         if (*nsymp == NULL
359                             || library_symbol_clone(*nsymp, it) < 0) {
360                                 free(*nsymp);
361                                 *nsymp = NULL;
362                         fail:
363                                 /* Release what we managed to allocate.  */
364                                 library_destroy(retp);
365                                 return -1;
366                         }
367
368                         (*nsymp)->lib = retp;
369                         nsymp = &(*nsymp)->next;
370                 }
371                 *nsymp = NULL;
372         }
373
374         /* Clone exported names.  */
375         {
376                 struct library_exported_name *it;
377                 struct library_exported_name **nnamep = &retp->exported_names;
378                 for (it = lib->exported_names; it != NULL; it = it->next) {
379                         *nnamep = malloc(sizeof(**nnamep));
380                         if (*nnamep == NULL
381                             || library_exported_name_clone(*nnamep, it) < 0) {
382                                 free(*nnamep);
383                                 goto fail;
384                         }
385                         nnamep = &(*nnamep)->next;
386                 }
387                 *nnamep = NULL;
388         }
389
390         if (os_library_clone(retp, lib) < 0)
391                 goto fail;
392
393         if (arch_library_clone(retp, lib) < 0) {
394                 os_library_destroy(retp);
395                 goto fail;
396         }
397
398         return 0;
399 }
400
401 void
402 library_destroy(struct library *lib)
403 {
404         if (lib == NULL)
405                 return;
406
407         arch_library_destroy(lib);
408         os_library_destroy(lib);
409
410         library_set_soname(lib, NULL, 0);
411         library_set_pathname(lib, NULL, 0);
412
413         struct library_symbol *sym;
414         for (sym = lib->symbols; sym != NULL; ) {
415                 struct library_symbol *next = sym->next;
416                 library_symbol_destroy(sym);
417                 free(sym);
418                 sym = next;
419         }
420
421         /* Release exported names.  */
422         struct library_exported_name *it;
423         for (it = lib->exported_names; it != NULL; ) {
424                 struct library_exported_name *next = it->next;
425                 if (it->own_name)
426                         free((char *)it->name);
427                 free(it);
428                 it = next;
429         }
430 }
431
432 void
433 library_set_soname(struct library *lib, const char *new_name, int own_name)
434 {
435         if (lib->own_soname)
436                 free((char *)lib->soname);
437         lib->soname = new_name;
438         lib->own_soname = own_name;
439 }
440
441 void
442 library_set_pathname(struct library *lib, const char *new_name, int own_name)
443 {
444         if (lib->own_pathname)
445                 free((char *)lib->pathname);
446         lib->pathname = new_name;
447         lib->own_pathname = own_name;
448 }
449
450 struct library_symbol *
451 library_each_symbol(struct library *lib, struct library_symbol *start_after,
452                     enum callback_status (*cb)(struct library_symbol *, void *),
453                     void *data)
454 {
455         struct library_symbol *it = start_after == NULL ? lib->symbols
456                 : start_after->next;
457
458         while (it != NULL) {
459                 struct library_symbol *next = it->next;
460
461                 switch ((*cb)(it, data)) {
462                 case CBS_FAIL:
463                         /* XXX handle me  */
464                 case CBS_STOP:
465                         return it;
466                 case CBS_CONT:
467                         break;
468                 }
469
470                 it = next;
471         }
472
473         return NULL;
474 }
475
476 void
477 library_add_symbol(struct library *lib, struct library_symbol *first)
478 {
479         struct library_symbol *last;
480         for (last = first; last != NULL; ) {
481                 last->lib = lib;
482                 if (last->next != NULL)
483                         last = last->next;
484                 else
485                         break;
486         }
487
488         assert(last->next == NULL);
489         last->next = lib->symbols;
490         lib->symbols = first;
491 }
492
493 enum callback_status
494 library_named_cb(struct process *proc, struct library *lib, void *name)
495 {
496         if (name == lib->soname
497             || strcmp(lib->soname, (char *)name) == 0)
498                 return CBS_STOP;
499         else
500                 return CBS_CONT;
501 }
502
503 enum callback_status
504 library_with_key_cb(struct process *proc, struct library *lib, void *keyp)
505 {
506         return lib->key == *(arch_addr_t *)keyp ? CBS_STOP : CBS_CONT;
507 }