]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libproc/proc_sym.c
Update LLDB snapshot to upstream r225923 (git 2b588ecd)
[FreeBSD/FreeBSD.git] / lib / libproc / proc_sym.c
1 /*-
2  * Copyright (c) 2010 The FreeBSD Foundation
3  * Copyright (c) 2008 John Birrell (jb@freebsd.org)
4  * All rights reserved.
5  *
6  * Portions of this software were developed by Rui Paulo under sponsorship
7  * from the FreeBSD Foundation.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include <sys/types.h>
35 #ifndef NO_CTF
36 #include <sys/ctf.h>
37 #include <sys/ctf_api.h>
38 #endif
39 #include <sys/user.h>
40
41 #include <assert.h>
42 #include <err.h>
43 #include <fcntl.h>
44 #include <libgen.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <unistd.h>
49 #ifndef NO_CTF
50 #include <libctf.h>
51 #endif
52 #include <libutil.h>
53
54 #include "_libproc.h"
55
56 #ifdef NO_CTF
57 typedef struct ctf_file ctf_file_t;
58 #endif
59
60 #ifndef NO_CXA_DEMANGLE
61 extern char *__cxa_demangle(const char *, char *, size_t *, int *);
62 #endif /* NO_CXA_DEMANGLE */
63
64 static void     proc_rdl2prmap(rd_loadobj_t *, prmap_t *);
65
66 static void
67 demangle(const char *symbol, char *buf, size_t len)
68 {
69 #ifndef NO_CXA_DEMANGLE
70         char *dembuf;
71
72         if (symbol[0] == '_' && symbol[1] == 'Z' && symbol[2]) {
73                 dembuf = __cxa_demangle(symbol, NULL, NULL, NULL);
74                 if (!dembuf)
75                         goto fail;
76                 strlcpy(buf, dembuf, len);
77                 free(dembuf);
78                 return;
79         }
80 fail:
81 #endif /* NO_CXA_DEMANGLE */
82         strlcpy(buf, symbol, len);
83 }
84
85 static void
86 proc_rdl2prmap(rd_loadobj_t *rdl, prmap_t *map)
87 {
88         map->pr_vaddr = rdl->rdl_saddr;
89         map->pr_size = rdl->rdl_eaddr - rdl->rdl_saddr;
90         map->pr_offset = rdl->rdl_offset;
91         map->pr_mflags = 0;
92         if (rdl->rdl_prot & RD_RDL_R)
93                 map->pr_mflags |= MA_READ;
94         if (rdl->rdl_prot & RD_RDL_W)
95                 map->pr_mflags |= MA_WRITE;
96         if (rdl->rdl_prot & RD_RDL_X)
97                 map->pr_mflags |= MA_EXEC;
98         strlcpy(map->pr_mapname, rdl->rdl_path,
99             sizeof(map->pr_mapname));
100 }
101
102 char *
103 proc_objname(struct proc_handle *p, uintptr_t addr, char *objname,
104     size_t objnamesz)
105 {
106         size_t i;
107         rd_loadobj_t *rdl;
108
109         for (i = 0; i < p->nobjs; i++) {
110                 rdl = &p->rdobjs[i];
111                 if (addr >= rdl->rdl_saddr && addr < rdl->rdl_eaddr) {
112                         strlcpy(objname, rdl->rdl_path, objnamesz);
113                         return (objname);
114                 }
115         }
116         return (NULL);
117 }
118
119 prmap_t *
120 proc_obj2map(struct proc_handle *p, const char *objname)
121 {
122         size_t i;
123         prmap_t *map;
124         rd_loadobj_t *rdl;
125         char path[MAXPATHLEN];
126
127         rdl = NULL;
128         for (i = 0; i < p->nobjs; i++) {
129                 basename_r(p->rdobjs[i].rdl_path, path);
130                 if (strcmp(path, objname) == 0) {
131                         rdl = &p->rdobjs[i];
132                         break;
133                 }
134         }
135         if (rdl == NULL) {
136                 if (strcmp(objname, "a.out") == 0 && p->rdexec != NULL)
137                         rdl = p->rdexec;
138                 else
139                         return (NULL);
140         }
141
142         if ((map = malloc(sizeof(*map))) == NULL)
143                 return (NULL);
144         proc_rdl2prmap(rdl, map);
145         return (map);
146 }
147
148 int
149 proc_iter_objs(struct proc_handle *p, proc_map_f *func, void *cd)
150 {
151         size_t i;
152         rd_loadobj_t *rdl;
153         prmap_t map;
154         char path[MAXPATHLEN];
155         char last[MAXPATHLEN];
156         int error;
157
158         if (p->nobjs == 0)
159                 return (-1);
160
161         error = 0;
162         memset(last, 0, sizeof(last));
163         for (i = 0; i < p->nobjs; i++) {
164                 rdl = &p->rdobjs[i];
165                 proc_rdl2prmap(rdl, &map);
166                 basename_r(rdl->rdl_path, path);
167                 /*
168                  * We shouldn't call the callback twice with the same object.
169                  * To do that we are assuming the fact that if there are
170                  * repeated object names (i.e. different mappings for the
171                  * same object) they occur next to each other.
172                  */
173                 if (strcmp(path, last) == 0)
174                         continue;
175                 if ((error = (*func)(cd, &map, path)) != 0)
176                         break;
177                 strlcpy(last, path, sizeof(last));
178         }
179         return (error);
180 }
181
182 prmap_t *
183 proc_addr2map(struct proc_handle *p, uintptr_t addr)
184 {
185         size_t i;
186         int cnt, lastvn = 0;
187         prmap_t *map;
188         rd_loadobj_t *rdl;
189         struct kinfo_vmentry *kves, *kve;
190
191         /*
192          * If we don't have a cache of listed objects, we need to query
193          * it ourselves.
194          */
195         if (p->nobjs == 0) {
196                 if ((kves = kinfo_getvmmap(p->pid, &cnt)) == NULL)
197                         return (NULL);
198                 for (i = 0; i < (size_t)cnt; i++) {
199                         kve = kves + i;
200                         if (kve->kve_type == KVME_TYPE_VNODE)
201                                 lastvn = i;
202                         if (addr >= kve->kve_start && addr < kve->kve_end) {
203                                 if ((map = malloc(sizeof(*map))) == NULL) {
204                                         free(kves);
205                                         return (NULL);
206                                 }
207                                 map->pr_vaddr = kve->kve_start;
208                                 map->pr_size = kve->kve_end - kve->kve_start;
209                                 map->pr_offset = kve->kve_offset;
210                                 map->pr_mflags = 0;
211                                 if (kve->kve_protection & KVME_PROT_READ)
212                                         map->pr_mflags |= MA_READ;
213                                 if (kve->kve_protection & KVME_PROT_WRITE)
214                                         map->pr_mflags |= MA_WRITE;
215                                 if (kve->kve_protection & KVME_PROT_EXEC)
216                                         map->pr_mflags |= MA_EXEC;
217                                 if (kve->kve_flags & KVME_FLAG_COW)
218                                         map->pr_mflags |= MA_COW;
219                                 if (kve->kve_flags & KVME_FLAG_NEEDS_COPY)
220                                         map->pr_mflags |= MA_NEEDS_COPY;
221                                 if (kve->kve_flags & KVME_FLAG_NOCOREDUMP)
222                                         map->pr_mflags |= MA_NOCOREDUMP;
223                                 strlcpy(map->pr_mapname, kves[lastvn].kve_path,
224                                     sizeof(map->pr_mapname));
225                                 free(kves);
226                                 return (map);
227                         }
228                 }
229                 free(kves);
230                 return (NULL);
231         }
232
233         for (i = 0; i < p->nobjs; i++) {
234                 rdl = &p->rdobjs[i];
235                 if (addr >= rdl->rdl_saddr && addr < rdl->rdl_eaddr) {
236                         if ((map = malloc(sizeof(*map))) == NULL)
237                                 return (NULL);
238                         proc_rdl2prmap(rdl, map);
239                         return (map);
240                 }
241         }
242         return (NULL);
243 }
244
245 /*
246  * Look up the symbol at addr, returning a copy of the symbol and its name.
247  */
248 static int
249 lookup_addr(Elf *e, Elf_Scn *scn, u_long stridx, uintptr_t off, uintptr_t addr,
250     const char **name, GElf_Sym *symcopy)
251 {
252         GElf_Sym sym;
253         Elf_Data *data;
254         const char *s;
255         uint64_t rsym;
256         int i;
257
258         if ((data = elf_getdata(scn, NULL)) == NULL) {
259                 DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
260                 return (1);
261         }
262         for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) {
263                 rsym = off + sym.st_value;
264                 if (addr >= rsym && addr < rsym + sym.st_size) {
265                         s = elf_strptr(e, stridx, sym.st_name);
266                         if (s != NULL) {
267                                 *name = s;
268                                 memcpy(symcopy, &sym, sizeof(*symcopy));
269                                 /*
270                                  * DTrace expects the st_value to contain
271                                  * only the address relative to the start of
272                                  * the function.
273                                  */
274                                 symcopy->st_value = rsym;
275                                 return (0);
276                         }
277                 }
278         }
279         return (1);
280 }
281
282 int
283 proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
284     size_t namesz, GElf_Sym *symcopy)
285 {
286         GElf_Ehdr ehdr;
287         GElf_Shdr shdr;
288         Elf *e;
289         Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL;
290         prmap_t *map;
291         const char *s;
292         uintptr_t off;
293         u_long symtabstridx = 0, dynsymstridx = 0;
294         int fd, error = -1;
295
296         if ((map = proc_addr2map(p, addr)) == NULL)
297                 return (-1);
298         if ((fd = open(map->pr_mapname, O_RDONLY, 0)) < 0) {
299                 DPRINTF("ERROR: open %s failed", map->pr_mapname);
300                 goto err0;
301         }
302         if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
303                 DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1));
304                 goto err1;
305         }
306         if (gelf_getehdr(e, &ehdr) == NULL) {
307                 DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1));
308                 goto err2;
309         }
310
311         /*
312          * Find the index of the STRTAB and SYMTAB sections to locate
313          * symbol names.
314          */
315         scn = NULL;
316         while ((scn = elf_nextscn(e, scn)) != NULL) {
317                 gelf_getshdr(scn, &shdr);
318                 switch (shdr.sh_type) {
319                 case SHT_SYMTAB:
320                         symtabscn = scn;
321                         symtabstridx = shdr.sh_link;
322                         break;
323                 case SHT_DYNSYM:
324                         dynsymscn = scn;
325                         dynsymstridx = shdr.sh_link;
326                         break;
327                 }
328         }
329
330         off = ehdr.e_type == ET_EXEC ? 0 : map->pr_vaddr;
331
332         /*
333          * First look up the symbol in the dynsymtab, and fall back to the
334          * symtab if the lookup fails.
335          */
336         error = lookup_addr(e, dynsymscn, dynsymstridx, off, addr, &s, symcopy);
337         if (error == 0)
338                 goto out;
339
340         error = lookup_addr(e, symtabscn, symtabstridx, off, addr, &s, symcopy);
341         if (error != 0)
342                 goto err2;
343
344 out:
345         demangle(s, name, namesz);
346 err2:
347         elf_end(e);
348 err1:
349         close(fd);
350 err0:
351         free(map);
352         return (error);
353 }
354
355 prmap_t *
356 proc_name2map(struct proc_handle *p, const char *name)
357 {
358         size_t i;
359         int cnt;
360         prmap_t *map = NULL;
361         char tmppath[MAXPATHLEN];
362         struct kinfo_vmentry *kves, *kve;
363         rd_loadobj_t *rdl;
364
365         /*
366          * If we haven't iterated over the list of loaded objects,
367          * librtld_db isn't yet initialized and it's very likely
368          * that librtld_db called us. We need to do the heavy
369          * lifting here to find the symbol librtld_db is looking for.
370          */
371         if (p->nobjs == 0) {
372                 if ((kves = kinfo_getvmmap(proc_getpid(p), &cnt)) == NULL)
373                         return (NULL);
374                 for (i = 0; i < (size_t)cnt; i++) {
375                         kve = kves + i;
376                         basename_r(kve->kve_path, tmppath);
377                         if (strcmp(tmppath, name) == 0) {
378                                 map = proc_addr2map(p, kve->kve_start);
379                                 break;
380                         }
381                 }
382                 free(kves);
383         } else
384                 for (i = 0; i < p->nobjs; i++) {
385                         rdl = &p->rdobjs[i];
386                         basename_r(rdl->rdl_path, tmppath);
387                         if (strcmp(tmppath, name) == 0) {
388                                 if ((map = malloc(sizeof(*map))) == NULL)
389                                         return (NULL);
390                                 proc_rdl2prmap(rdl, map);
391                                 break;
392                         }
393                 }
394
395         if (map == NULL && strcmp(name, "a.out") == 0 && p->rdexec != NULL)
396                 map = proc_addr2map(p, p->rdexec->rdl_saddr);
397
398         return (map);
399 }
400
401 /*
402  * Look up the symbol with the given name and return a copy of it.
403  */
404 static int
405 lookup_name(Elf *e, Elf_Scn *scn, u_long stridx, const char *symbol,
406     GElf_Sym *symcopy, prsyminfo_t *si)
407 {
408         GElf_Sym sym;
409         Elf_Data *data;
410         char *s;
411         int i;
412
413         if ((data = elf_getdata(scn, NULL)) == NULL) {
414                 DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
415                 return (1);
416         }
417         for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) {
418                 s = elf_strptr(e, stridx, sym.st_name);
419                 if (s != NULL && strcmp(s, symbol) == 0) {
420                         memcpy(symcopy, &sym, sizeof(*symcopy));
421                         if (si != NULL)
422                                 si->prs_id = i;
423                         return (0);
424                 }
425         }
426         return (1);
427 }
428
429 int
430 proc_name2sym(struct proc_handle *p, const char *object, const char *symbol,
431     GElf_Sym *symcopy, prsyminfo_t *si)
432 {
433         Elf *e;
434         Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL;
435         GElf_Shdr shdr;
436         GElf_Ehdr ehdr;
437         prmap_t *map;
438         uintptr_t off;
439         u_long symtabstridx = 0, dynsymstridx = 0;
440         int fd, error = -1;
441
442         if ((map = proc_name2map(p, object)) == NULL) {
443                 DPRINTFX("ERROR: couldn't find object %s", object);
444                 goto err0;
445         }
446         if ((fd = open(map->pr_mapname, O_RDONLY, 0)) < 0) {
447                 DPRINTF("ERROR: open %s failed", map->pr_mapname);
448                 goto err0;
449         }
450         if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
451                 DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1));
452                 goto err1;
453         }
454         if (gelf_getehdr(e, &ehdr) == NULL) {
455                 DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1));
456                 goto err2;
457         }
458         /*
459          * Find the index of the STRTAB and SYMTAB sections to locate
460          * symbol names.
461          */
462         scn = NULL;
463         while ((scn = elf_nextscn(e, scn)) != NULL) {
464                 gelf_getshdr(scn, &shdr);
465                 switch (shdr.sh_type) {
466                 case SHT_SYMTAB:
467                         symtabscn = scn;
468                         symtabstridx = shdr.sh_link;
469                         break;
470                 case SHT_DYNSYM:
471                         dynsymscn = scn;
472                         dynsymstridx = shdr.sh_link;
473                         break;
474                 }
475         }
476
477         /*
478          * First look up the symbol in the dynsymtab, and fall back to the
479          * symtab if the lookup fails.
480          */
481         error = lookup_name(e, dynsymscn, dynsymstridx, symbol, symcopy, si);
482         if (error == 0)
483                 goto out;
484
485         error = lookup_name(e, symtabscn, symtabstridx, symbol, symcopy, si);
486         if (error == 0)
487                 goto out;
488
489 out:
490         off = ehdr.e_type == ET_EXEC ? 0 : map->pr_vaddr;
491         symcopy->st_value += off;
492
493 err2:
494         elf_end(e);
495 err1:
496         close(fd);
497 err0:
498         free(map);
499
500         return (error);
501 }
502
503 ctf_file_t *
504 proc_name2ctf(struct proc_handle *p, const char *name)
505 {
506 #ifndef NO_CTF
507         ctf_file_t *ctf;
508         prmap_t *map;
509         int error;
510
511         if ((map = proc_name2map(p, name)) == NULL)
512                 return (NULL);
513
514         ctf = ctf_open(map->pr_mapname, &error);
515         free(map);
516         return (ctf);
517 #else
518         (void)p;
519         (void)name;
520         return (NULL);
521 #endif
522 }
523
524 int
525 proc_iter_symbyaddr(struct proc_handle *p, const char *object, int which,
526     int mask, proc_sym_f *func, void *cd)
527 {
528         Elf *e;
529         int i, fd;
530         prmap_t *map;
531         Elf_Scn *scn, *foundscn = NULL;
532         Elf_Data *data;
533         GElf_Ehdr ehdr;
534         GElf_Shdr shdr;
535         GElf_Sym sym;
536         unsigned long stridx = -1;
537         char *s;
538         int error = -1;
539
540         if ((map = proc_name2map(p, object)) == NULL)
541                 return (-1);
542         if ((fd = open(map->pr_mapname, O_RDONLY)) < 0) {
543                 DPRINTF("ERROR: open %s failed", map->pr_mapname);
544                 goto err0;
545         }
546         if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
547                 DPRINTFX("ERROR: elf_begin() failed: %s", elf_errmsg(-1));
548                 goto err1;
549         }
550         if (gelf_getehdr(e, &ehdr) == NULL) {
551                 DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1));
552                 goto err2;
553         }
554         /*
555          * Find the section we are looking for.
556          */
557         scn = NULL;
558         while ((scn = elf_nextscn(e, scn)) != NULL) {
559                 gelf_getshdr(scn, &shdr);
560                 if (which == PR_SYMTAB &&
561                     shdr.sh_type == SHT_SYMTAB) {
562                         foundscn = scn;
563                         break;
564                 } else if (which == PR_DYNSYM &&
565                     shdr.sh_type == SHT_DYNSYM) {
566                         foundscn = scn;
567                         break;
568                 }
569         }
570         if (!foundscn)
571                 return (-1);
572         stridx = shdr.sh_link;
573         if ((data = elf_getdata(foundscn, NULL)) == NULL) {
574                 DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
575                 goto err2;
576         }
577         for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) {
578                 if (GELF_ST_BIND(sym.st_info) == STB_LOCAL &&
579                     (mask & BIND_LOCAL) == 0)
580                         continue;
581                 if (GELF_ST_BIND(sym.st_info) == STB_GLOBAL &&
582                     (mask & BIND_GLOBAL) == 0)
583                         continue;
584                 if (GELF_ST_BIND(sym.st_info) == STB_WEAK &&
585                     (mask & BIND_WEAK) == 0)
586                         continue;
587                 if (GELF_ST_TYPE(sym.st_info) == STT_NOTYPE &&
588                     (mask & TYPE_NOTYPE) == 0)
589                         continue;
590                 if (GELF_ST_TYPE(sym.st_info) == STT_OBJECT &&
591                     (mask & TYPE_OBJECT) == 0)
592                         continue;
593                 if (GELF_ST_TYPE(sym.st_info) == STT_FUNC &&
594                     (mask & TYPE_FUNC) == 0)
595                         continue;
596                 if (GELF_ST_TYPE(sym.st_info) == STT_SECTION &&
597                     (mask & TYPE_SECTION) == 0)
598                         continue;
599                 if (GELF_ST_TYPE(sym.st_info) == STT_FILE &&
600                     (mask & TYPE_FILE) == 0)
601                         continue;
602                 s = elf_strptr(e, stridx, sym.st_name);
603                 if (ehdr.e_type != ET_EXEC)
604                         sym.st_value += map->pr_vaddr;
605                 if ((error = (*func)(cd, &sym, s)) != 0)
606                         goto err2;
607         }
608         error = 0;
609 err2:
610         elf_end(e);
611 err1:
612         close(fd);
613 err0:
614         free(map);
615         return (error);
616 }