]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c
MFC r296816:
[FreeBSD/stable/9.git] / cddl / contrib / opensolaris / lib / libdtrace / common / dt_module.c
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21
22 /*
23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25
26 /*
27  * Portions Copyright 2016 Pedro Giffuni.  All rights reserved.
28  */
29
30 #include <sys/types.h>
31 #if defined(sun)
32 #include <sys/modctl.h>
33 #include <sys/kobj.h>
34 #include <sys/kobj_impl.h>
35 #include <sys/sysmacros.h>
36 #include <sys/elf.h>
37 #include <sys/task.h>
38 #else
39 #include <sys/param.h>
40 #include <sys/linker.h>
41 #include <sys/stat.h>
42 #endif
43
44 #include <unistd.h>
45 #if defined(sun)
46 #include <project.h>
47 #endif
48 #include <strings.h>
49 #include <stdlib.h>
50 #include <libelf.h>
51 #include <limits.h>
52 #include <assert.h>
53 #include <errno.h>
54 #include <dirent.h>
55 #if !defined(sun)
56 #include <fcntl.h>
57 #endif
58
59 #include <dt_strtab.h>
60 #include <dt_module.h>
61 #include <dt_impl.h>
62
63 static const char *dt_module_strtab; /* active strtab for qsort callbacks */
64
65 static void
66 dt_module_symhash_insert(dt_module_t *dmp, const char *name, uint_t id)
67 {
68         dt_sym_t *dsp = &dmp->dm_symchains[dmp->dm_symfree];
69         uint_t h;
70
71         assert(dmp->dm_symfree < dmp->dm_nsymelems + 1);
72
73         dsp->ds_symid = id;
74         h = dt_strtab_hash(name, NULL) % dmp->dm_nsymbuckets;
75         dsp->ds_next = dmp->dm_symbuckets[h];
76         dmp->dm_symbuckets[h] = dmp->dm_symfree++;
77 }
78
79 static uint_t
80 dt_module_syminit32(dt_module_t *dmp)
81 {
82 #if STT_NUM != (STT_TLS + 1)
83 #error "STT_NUM has grown. update dt_module_syminit32()"
84 #endif
85
86         Elf32_Sym *sym = dmp->dm_symtab.cts_data;
87         const char *base = dmp->dm_strtab.cts_data;
88         size_t ss_size = dmp->dm_strtab.cts_size;
89         uint_t i, n = dmp->dm_nsymelems;
90         uint_t asrsv = 0;
91
92 #if defined(__FreeBSD__)
93         GElf_Ehdr ehdr;
94         int is_elf_obj;
95
96         gelf_getehdr(dmp->dm_elf, &ehdr);
97         is_elf_obj = (ehdr.e_type == ET_REL);
98 #endif
99
100         for (i = 0; i < n; i++, sym++) {
101                 const char *name = base + sym->st_name;
102                 uchar_t type = ELF32_ST_TYPE(sym->st_info);
103
104                 if (type >= STT_NUM || type == STT_SECTION)
105                         continue; /* skip sections and unknown types */
106
107                 if (sym->st_name == 0 || sym->st_name >= ss_size)
108                         continue; /* skip null or invalid names */
109
110                 if (sym->st_value != 0 &&
111                     (ELF32_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size)) {
112                         asrsv++; /* reserve space in the address map */
113
114 #if defined(__FreeBSD__)
115                         sym->st_value += (Elf_Addr) dmp->dm_reloc_offset;
116                         if (is_elf_obj && sym->st_shndx != SHN_UNDEF &&
117                             sym->st_shndx < ehdr.e_shnum)
118                                 sym->st_value +=
119                                     dmp->dm_sec_offsets[sym->st_shndx];
120 #endif
121                 }
122
123                 dt_module_symhash_insert(dmp, name, i);
124         }
125
126         return (asrsv);
127 }
128
129 static uint_t
130 dt_module_syminit64(dt_module_t *dmp)
131 {
132 #if STT_NUM != (STT_TLS + 1)
133 #error "STT_NUM has grown. update dt_module_syminit64()"
134 #endif
135
136         Elf64_Sym *sym = dmp->dm_symtab.cts_data;
137         const char *base = dmp->dm_strtab.cts_data;
138         size_t ss_size = dmp->dm_strtab.cts_size;
139         uint_t i, n = dmp->dm_nsymelems;
140         uint_t asrsv = 0;
141
142 #if defined(__FreeBSD__)
143         GElf_Ehdr ehdr;
144         int is_elf_obj;
145
146         gelf_getehdr(dmp->dm_elf, &ehdr);
147         is_elf_obj = (ehdr.e_type == ET_REL);
148 #endif
149
150         for (i = 0; i < n; i++, sym++) {
151                 const char *name = base + sym->st_name;
152                 uchar_t type = ELF64_ST_TYPE(sym->st_info);
153
154                 if (type >= STT_NUM || type == STT_SECTION)
155                         continue; /* skip sections and unknown types */
156
157                 if (sym->st_name == 0 || sym->st_name >= ss_size)
158                         continue; /* skip null or invalid names */
159
160                 if (sym->st_value != 0 &&
161                     (ELF64_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size)) {
162                         asrsv++; /* reserve space in the address map */
163 #if defined(__FreeBSD__)
164                         sym->st_value += (Elf_Addr) dmp->dm_reloc_offset;
165                         if (is_elf_obj && sym->st_shndx != SHN_UNDEF &&
166                             sym->st_shndx < ehdr.e_shnum)
167                                 sym->st_value +=
168                                     dmp->dm_sec_offsets[sym->st_shndx];
169 #endif
170                 }
171
172                 dt_module_symhash_insert(dmp, name, i);
173         }
174
175         return (asrsv);
176 }
177
178 /*
179  * Sort comparison function for 32-bit symbol address-to-name lookups.  We sort
180  * symbols by value.  If values are equal, we prefer the symbol that is
181  * non-zero sized, typed, not weak, or lexically first, in that order.
182  */
183 static int
184 dt_module_symcomp32(const void *lp, const void *rp)
185 {
186         Elf32_Sym *lhs = *((Elf32_Sym **)lp);
187         Elf32_Sym *rhs = *((Elf32_Sym **)rp);
188
189         if (lhs->st_value != rhs->st_value)
190                 return (lhs->st_value > rhs->st_value ? 1 : -1);
191
192         if ((lhs->st_size == 0) != (rhs->st_size == 0))
193                 return (lhs->st_size == 0 ? 1 : -1);
194
195         if ((ELF32_ST_TYPE(lhs->st_info) == STT_NOTYPE) !=
196             (ELF32_ST_TYPE(rhs->st_info) == STT_NOTYPE))
197                 return (ELF32_ST_TYPE(lhs->st_info) == STT_NOTYPE ? 1 : -1);
198
199         if ((ELF32_ST_BIND(lhs->st_info) == STB_WEAK) !=
200             (ELF32_ST_BIND(rhs->st_info) == STB_WEAK))
201                 return (ELF32_ST_BIND(lhs->st_info) == STB_WEAK ? 1 : -1);
202
203         return (strcmp(dt_module_strtab + lhs->st_name,
204             dt_module_strtab + rhs->st_name));
205 }
206
207 /*
208  * Sort comparison function for 64-bit symbol address-to-name lookups.  We sort
209  * symbols by value.  If values are equal, we prefer the symbol that is
210  * non-zero sized, typed, not weak, or lexically first, in that order.
211  */
212 static int
213 dt_module_symcomp64(const void *lp, const void *rp)
214 {
215         Elf64_Sym *lhs = *((Elf64_Sym **)lp);
216         Elf64_Sym *rhs = *((Elf64_Sym **)rp);
217
218         if (lhs->st_value != rhs->st_value)
219                 return (lhs->st_value > rhs->st_value ? 1 : -1);
220
221         if ((lhs->st_size == 0) != (rhs->st_size == 0))
222                 return (lhs->st_size == 0 ? 1 : -1);
223
224         if ((ELF64_ST_TYPE(lhs->st_info) == STT_NOTYPE) !=
225             (ELF64_ST_TYPE(rhs->st_info) == STT_NOTYPE))
226                 return (ELF64_ST_TYPE(lhs->st_info) == STT_NOTYPE ? 1 : -1);
227
228         if ((ELF64_ST_BIND(lhs->st_info) == STB_WEAK) !=
229             (ELF64_ST_BIND(rhs->st_info) == STB_WEAK))
230                 return (ELF64_ST_BIND(lhs->st_info) == STB_WEAK ? 1 : -1);
231
232         return (strcmp(dt_module_strtab + lhs->st_name,
233             dt_module_strtab + rhs->st_name));
234 }
235
236 static void
237 dt_module_symsort32(dt_module_t *dmp)
238 {
239         Elf32_Sym *symtab = (Elf32_Sym *)dmp->dm_symtab.cts_data;
240         Elf32_Sym **sympp = (Elf32_Sym **)dmp->dm_asmap;
241         const dt_sym_t *dsp = dmp->dm_symchains + 1;
242         uint_t i, n = dmp->dm_symfree;
243
244         for (i = 1; i < n; i++, dsp++) {
245                 Elf32_Sym *sym = symtab + dsp->ds_symid;
246                 if (sym->st_value != 0 &&
247                     (ELF32_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size))
248                         *sympp++ = sym;
249         }
250
251         dmp->dm_aslen = (uint_t)(sympp - (Elf32_Sym **)dmp->dm_asmap);
252         assert(dmp->dm_aslen <= dmp->dm_asrsv);
253
254         dt_module_strtab = dmp->dm_strtab.cts_data;
255         qsort(dmp->dm_asmap, dmp->dm_aslen,
256             sizeof (Elf32_Sym *), dt_module_symcomp32);
257         dt_module_strtab = NULL;
258 }
259
260 static void
261 dt_module_symsort64(dt_module_t *dmp)
262 {
263         Elf64_Sym *symtab = (Elf64_Sym *)dmp->dm_symtab.cts_data;
264         Elf64_Sym **sympp = (Elf64_Sym **)dmp->dm_asmap;
265         const dt_sym_t *dsp = dmp->dm_symchains + 1;
266         uint_t i, n = dmp->dm_symfree;
267
268         for (i = 1; i < n; i++, dsp++) {
269                 Elf64_Sym *sym = symtab + dsp->ds_symid;
270                 if (sym->st_value != 0 &&
271                     (ELF64_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size))
272                         *sympp++ = sym;
273         }
274
275         dmp->dm_aslen = (uint_t)(sympp - (Elf64_Sym **)dmp->dm_asmap);
276         assert(dmp->dm_aslen <= dmp->dm_asrsv);
277
278         dt_module_strtab = dmp->dm_strtab.cts_data;
279         qsort(dmp->dm_asmap, dmp->dm_aslen,
280             sizeof (Elf64_Sym *), dt_module_symcomp64);
281         dt_module_strtab = NULL;
282 }
283
284 static GElf_Sym *
285 dt_module_symgelf32(const Elf32_Sym *src, GElf_Sym *dst)
286 {
287         if (dst != NULL) {
288                 dst->st_name = src->st_name;
289                 dst->st_info = src->st_info;
290                 dst->st_other = src->st_other;
291                 dst->st_shndx = src->st_shndx;
292                 dst->st_value = src->st_value;
293                 dst->st_size = src->st_size;
294         }
295
296         return (dst);
297 }
298
299 static GElf_Sym *
300 dt_module_symgelf64(const Elf64_Sym *src, GElf_Sym *dst)
301 {
302         if (dst != NULL)
303                 bcopy(src, dst, sizeof (GElf_Sym));
304
305         return (dst);
306 }
307
308 static GElf_Sym *
309 dt_module_symname32(dt_module_t *dmp, const char *name,
310     GElf_Sym *symp, uint_t *idp)
311 {
312         const Elf32_Sym *symtab = dmp->dm_symtab.cts_data;
313         const char *strtab = dmp->dm_strtab.cts_data;
314
315         const Elf32_Sym *sym;
316         const dt_sym_t *dsp;
317         uint_t i, h;
318
319         if (dmp->dm_nsymelems == 0)
320                 return (NULL);
321
322         h = dt_strtab_hash(name, NULL) % dmp->dm_nsymbuckets;
323
324         for (i = dmp->dm_symbuckets[h]; i != 0; i = dsp->ds_next) {
325                 dsp = &dmp->dm_symchains[i];
326                 sym = symtab + dsp->ds_symid;
327
328                 if (strcmp(name, strtab + sym->st_name) == 0) {
329                         if (idp != NULL)
330                                 *idp = dsp->ds_symid;
331                         return (dt_module_symgelf32(sym, symp));
332                 }
333         }
334
335         return (NULL);
336 }
337
338 static GElf_Sym *
339 dt_module_symname64(dt_module_t *dmp, const char *name,
340     GElf_Sym *symp, uint_t *idp)
341 {
342         const Elf64_Sym *symtab = dmp->dm_symtab.cts_data;
343         const char *strtab = dmp->dm_strtab.cts_data;
344
345         const Elf64_Sym *sym;
346         const dt_sym_t *dsp;
347         uint_t i, h;
348
349         if (dmp->dm_nsymelems == 0)
350                 return (NULL);
351
352         h = dt_strtab_hash(name, NULL) % dmp->dm_nsymbuckets;
353
354         for (i = dmp->dm_symbuckets[h]; i != 0; i = dsp->ds_next) {
355                 dsp = &dmp->dm_symchains[i];
356                 sym = symtab + dsp->ds_symid;
357
358                 if (strcmp(name, strtab + sym->st_name) == 0) {
359                         if (idp != NULL)
360                                 *idp = dsp->ds_symid;
361                         return (dt_module_symgelf64(sym, symp));
362                 }
363         }
364
365         return (NULL);
366 }
367
368 static GElf_Sym *
369 dt_module_symaddr32(dt_module_t *dmp, GElf_Addr addr,
370     GElf_Sym *symp, uint_t *idp)
371 {
372         const Elf32_Sym **asmap = (const Elf32_Sym **)dmp->dm_asmap;
373         const Elf32_Sym *symtab = dmp->dm_symtab.cts_data;
374         const Elf32_Sym *sym;
375
376         uint_t i, mid, lo = 0, hi = dmp->dm_aslen - 1;
377         Elf32_Addr v;
378
379         if (dmp->dm_aslen == 0)
380                 return (NULL);
381
382         while (hi - lo > 1) {
383                 mid = (lo + hi) / 2;
384                 if (addr >= asmap[mid]->st_value)
385                         lo = mid;
386                 else
387                         hi = mid;
388         }
389
390         i = addr < asmap[hi]->st_value ? lo : hi;
391         sym = asmap[i];
392         v = sym->st_value;
393
394         /*
395          * If the previous entry has the same value, improve our choice.  The
396          * order of equal-valued symbols is determined by the comparison func.
397          */
398         while (i-- != 0 && asmap[i]->st_value == v)
399                 sym = asmap[i];
400
401         if (addr - sym->st_value < MAX(sym->st_size, 1)) {
402                 if (idp != NULL)
403                         *idp = (uint_t)(sym - symtab);
404                 return (dt_module_symgelf32(sym, symp));
405         }
406
407         return (NULL);
408 }
409
410 static GElf_Sym *
411 dt_module_symaddr64(dt_module_t *dmp, GElf_Addr addr,
412     GElf_Sym *symp, uint_t *idp)
413 {
414         const Elf64_Sym **asmap = (const Elf64_Sym **)dmp->dm_asmap;
415         const Elf64_Sym *symtab = dmp->dm_symtab.cts_data;
416         const Elf64_Sym *sym;
417
418         uint_t i, mid, lo = 0, hi = dmp->dm_aslen - 1;
419         Elf64_Addr v;
420
421         if (dmp->dm_aslen == 0)
422                 return (NULL);
423
424         while (hi - lo > 1) {
425                 mid = (lo + hi) / 2;
426                 if (addr >= asmap[mid]->st_value)
427                         lo = mid;
428                 else
429                         hi = mid;
430         }
431
432         i = addr < asmap[hi]->st_value ? lo : hi;
433         sym = asmap[i];
434         v = sym->st_value;
435
436         /*
437          * If the previous entry has the same value, improve our choice.  The
438          * order of equal-valued symbols is determined by the comparison func.
439          */
440         while (i-- != 0 && asmap[i]->st_value == v)
441                 sym = asmap[i];
442
443         if (addr - sym->st_value < MAX(sym->st_size, 1)) {
444                 if (idp != NULL)
445                         *idp = (uint_t)(sym - symtab);
446                 return (dt_module_symgelf64(sym, symp));
447         }
448
449         return (NULL);
450 }
451
452 static const dt_modops_t dt_modops_32 = {
453         dt_module_syminit32,
454         dt_module_symsort32,
455         dt_module_symname32,
456         dt_module_symaddr32
457 };
458
459 static const dt_modops_t dt_modops_64 = {
460         dt_module_syminit64,
461         dt_module_symsort64,
462         dt_module_symname64,
463         dt_module_symaddr64
464 };
465
466 dt_module_t *
467 dt_module_create(dtrace_hdl_t *dtp, const char *name)
468 {
469         uint_t h = dt_strtab_hash(name, NULL) % dtp->dt_modbuckets;
470         dt_module_t *dmp;
471
472         for (dmp = dtp->dt_mods[h]; dmp != NULL; dmp = dmp->dm_next) {
473                 if (strcmp(dmp->dm_name, name) == 0)
474                         return (dmp);
475         }
476
477         if ((dmp = malloc(sizeof (dt_module_t))) == NULL)
478                 return (NULL); /* caller must handle allocation failure */
479
480         bzero(dmp, sizeof (dt_module_t));
481         (void) strlcpy(dmp->dm_name, name, sizeof (dmp->dm_name));
482         dt_list_append(&dtp->dt_modlist, dmp);
483         dmp->dm_next = dtp->dt_mods[h];
484         dtp->dt_mods[h] = dmp;
485         dtp->dt_nmods++;
486
487         if (dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64)
488                 dmp->dm_ops = &dt_modops_64;
489         else
490                 dmp->dm_ops = &dt_modops_32;
491
492         return (dmp);
493 }
494
495 dt_module_t *
496 dt_module_lookup_by_name(dtrace_hdl_t *dtp, const char *name)
497 {
498         uint_t h = dt_strtab_hash(name, NULL) % dtp->dt_modbuckets;
499         dt_module_t *dmp;
500
501         for (dmp = dtp->dt_mods[h]; dmp != NULL; dmp = dmp->dm_next) {
502                 if (strcmp(dmp->dm_name, name) == 0)
503                         return (dmp);
504         }
505
506         return (NULL);
507 }
508
509 /*ARGSUSED*/
510 dt_module_t *
511 dt_module_lookup_by_ctf(dtrace_hdl_t *dtp, ctf_file_t *ctfp)
512 {
513         return (ctfp ? ctf_getspecific(ctfp) : NULL);
514 }
515
516 static int
517 dt_module_load_sect(dtrace_hdl_t *dtp, dt_module_t *dmp, ctf_sect_t *ctsp)
518 {
519         const char *s;
520         size_t shstrs;
521         GElf_Shdr sh;
522         Elf_Data *dp;
523         Elf_Scn *sp;
524
525         if (elf_getshdrstrndx(dmp->dm_elf, &shstrs) == -1)
526                 return (dt_set_errno(dtp, EDT_NOTLOADED));
527
528         for (sp = NULL; (sp = elf_nextscn(dmp->dm_elf, sp)) != NULL; ) {
529                 if (gelf_getshdr(sp, &sh) == NULL || sh.sh_type == SHT_NULL ||
530                     (s = elf_strptr(dmp->dm_elf, shstrs, sh.sh_name)) == NULL)
531                         continue; /* skip any malformed sections */
532
533                 if (sh.sh_type == ctsp->cts_type &&
534                     sh.sh_entsize == ctsp->cts_entsize &&
535                     strcmp(s, ctsp->cts_name) == 0)
536                         break; /* section matches specification */
537         }
538
539         /*
540          * If the section isn't found, return success but leave cts_data set
541          * to NULL and cts_size set to zero for our caller.
542          */
543         if (sp == NULL || (dp = elf_getdata(sp, NULL)) == NULL)
544                 return (0);
545
546 #if defined(sun)
547         ctsp->cts_data = dp->d_buf;
548 #else
549         if ((ctsp->cts_data = malloc(dp->d_size)) == NULL)
550                 return (0);
551         memcpy(ctsp->cts_data, dp->d_buf, dp->d_size);
552 #endif
553         ctsp->cts_size = dp->d_size;
554
555         dt_dprintf("loaded %s [%s] (%lu bytes)\n",
556             dmp->dm_name, ctsp->cts_name, (ulong_t)ctsp->cts_size);
557
558         return (0);
559 }
560
561 int
562 dt_module_load(dtrace_hdl_t *dtp, dt_module_t *dmp)
563 {
564         if (dmp->dm_flags & DT_DM_LOADED)
565                 return (0); /* module is already loaded */
566
567         dmp->dm_ctdata.cts_name = ".SUNW_ctf";
568         dmp->dm_ctdata.cts_type = SHT_PROGBITS;
569         dmp->dm_ctdata.cts_flags = 0;
570         dmp->dm_ctdata.cts_data = NULL;
571         dmp->dm_ctdata.cts_size = 0;
572         dmp->dm_ctdata.cts_entsize = 0;
573         dmp->dm_ctdata.cts_offset = 0;
574
575         dmp->dm_symtab.cts_name = ".symtab";
576         dmp->dm_symtab.cts_type = SHT_SYMTAB;
577         dmp->dm_symtab.cts_flags = 0;
578         dmp->dm_symtab.cts_data = NULL;
579         dmp->dm_symtab.cts_size = 0;
580         dmp->dm_symtab.cts_entsize = dmp->dm_ops == &dt_modops_64 ?
581             sizeof (Elf64_Sym) : sizeof (Elf32_Sym);
582         dmp->dm_symtab.cts_offset = 0;
583
584         dmp->dm_strtab.cts_name = ".strtab";
585         dmp->dm_strtab.cts_type = SHT_STRTAB;
586         dmp->dm_strtab.cts_flags = 0;
587         dmp->dm_strtab.cts_data = NULL;
588         dmp->dm_strtab.cts_size = 0;
589         dmp->dm_strtab.cts_entsize = 0;
590         dmp->dm_strtab.cts_offset = 0;
591
592         /*
593          * Attempt to load the module's CTF section, symbol table section, and
594          * string table section.  Note that modules may not contain CTF data:
595          * this will result in a successful load_sect but data of size zero.
596          * We will then fail if dt_module_getctf() is called, as shown below.
597          */
598         if (dt_module_load_sect(dtp, dmp, &dmp->dm_ctdata) == -1 ||
599             dt_module_load_sect(dtp, dmp, &dmp->dm_symtab) == -1 ||
600             dt_module_load_sect(dtp, dmp, &dmp->dm_strtab) == -1) {
601                 dt_module_unload(dtp, dmp);
602                 return (-1); /* dt_errno is set for us */
603         }
604
605         /*
606          * Allocate the hash chains and hash buckets for symbol name lookup.
607          * This is relatively simple since the symbol table is of fixed size
608          * and is known in advance.  We allocate one extra element since we
609          * use element indices instead of pointers and zero is our sentinel.
610          */
611         dmp->dm_nsymelems =
612             dmp->dm_symtab.cts_size / dmp->dm_symtab.cts_entsize;
613
614         dmp->dm_nsymbuckets = _dtrace_strbuckets;
615         dmp->dm_symfree = 1;            /* first free element is index 1 */
616
617         dmp->dm_symbuckets = calloc(dmp->dm_nsymbuckets, sizeof (uint_t));
618         dmp->dm_symchains = calloc(dmp->dm_nsymelems + 1, sizeof (dt_sym_t));
619
620         if (dmp->dm_symbuckets == NULL || dmp->dm_symchains == NULL) {
621                 dt_module_unload(dtp, dmp);
622                 return (dt_set_errno(dtp, EDT_NOMEM));
623         }
624
625         /*
626          * Iterate over the symbol table data buffer and insert each symbol
627          * name into the name hash if the name and type are valid.  Then
628          * allocate the address map, fill it in, and sort it.
629          */
630         dmp->dm_asrsv = dmp->dm_ops->do_syminit(dmp);
631
632         dt_dprintf("hashed %s [%s] (%u symbols)\n",
633             dmp->dm_name, dmp->dm_symtab.cts_name, dmp->dm_symfree - 1);
634
635         if ((dmp->dm_asmap = malloc(sizeof (void *) * dmp->dm_asrsv)) == NULL) {
636                 dt_module_unload(dtp, dmp);
637                 return (dt_set_errno(dtp, EDT_NOMEM));
638         }
639
640         dmp->dm_ops->do_symsort(dmp);
641
642         dt_dprintf("sorted %s [%s] (%u symbols)\n",
643             dmp->dm_name, dmp->dm_symtab.cts_name, dmp->dm_aslen);
644
645         dmp->dm_flags |= DT_DM_LOADED;
646         return (0);
647 }
648
649 ctf_file_t *
650 dt_module_getctf(dtrace_hdl_t *dtp, dt_module_t *dmp)
651 {
652         const char *parent;
653         dt_module_t *pmp;
654         ctf_file_t *pfp;
655         int model;
656
657         if (dmp->dm_ctfp != NULL || dt_module_load(dtp, dmp) != 0)
658                 return (dmp->dm_ctfp);
659
660         if (dmp->dm_ops == &dt_modops_64)
661                 model = CTF_MODEL_LP64;
662         else
663                 model = CTF_MODEL_ILP32;
664
665         /*
666          * If the data model of the module does not match our program data
667          * model, then do not permit CTF from this module to be opened and
668          * returned to the compiler.  If we support mixed data models in the
669          * future for combined kernel/user tracing, this can be removed.
670          */
671         if (dtp->dt_conf.dtc_ctfmodel != model) {
672                 (void) dt_set_errno(dtp, EDT_DATAMODEL);
673                 return (NULL);
674         }
675
676         if (dmp->dm_ctdata.cts_size == 0) {
677                 (void) dt_set_errno(dtp, EDT_NOCTF);
678                 return (NULL);
679         }
680
681         dmp->dm_ctfp = ctf_bufopen(&dmp->dm_ctdata,
682             &dmp->dm_symtab, &dmp->dm_strtab, &dtp->dt_ctferr);
683
684         if (dmp->dm_ctfp == NULL) {
685                 (void) dt_set_errno(dtp, EDT_CTF);
686                 return (NULL);
687         }
688
689         (void) ctf_setmodel(dmp->dm_ctfp, model);
690         ctf_setspecific(dmp->dm_ctfp, dmp);
691
692         if ((parent = ctf_parent_name(dmp->dm_ctfp)) != NULL) {
693                 if ((pmp = dt_module_create(dtp, parent)) == NULL ||
694                     (pfp = dt_module_getctf(dtp, pmp)) == NULL) {
695                         if (pmp == NULL)
696                                 (void) dt_set_errno(dtp, EDT_NOMEM);
697                         goto err;
698                 }
699
700                 if (ctf_import(dmp->dm_ctfp, pfp) == CTF_ERR) {
701                         dtp->dt_ctferr = ctf_errno(dmp->dm_ctfp);
702                         (void) dt_set_errno(dtp, EDT_CTF);
703                         goto err;
704                 }
705         }
706
707         dt_dprintf("loaded CTF container for %s (%p)\n",
708             dmp->dm_name, (void *)dmp->dm_ctfp);
709
710         return (dmp->dm_ctfp);
711
712 err:
713         ctf_close(dmp->dm_ctfp);
714         dmp->dm_ctfp = NULL;
715         return (NULL);
716 }
717
718 /*ARGSUSED*/
719 void
720 dt_module_unload(dtrace_hdl_t *dtp, dt_module_t *dmp)
721 {
722         ctf_close(dmp->dm_ctfp);
723         dmp->dm_ctfp = NULL;
724
725 #if !defined(sun)
726         if (dmp->dm_ctdata.cts_data != NULL) {
727                 free(dmp->dm_ctdata.cts_data);
728         }
729         if (dmp->dm_symtab.cts_data != NULL) {
730                 free(dmp->dm_symtab.cts_data);
731         }
732         if (dmp->dm_strtab.cts_data != NULL) {
733                 free(dmp->dm_strtab.cts_data);
734         }
735 #endif
736
737         bzero(&dmp->dm_ctdata, sizeof (ctf_sect_t));
738         bzero(&dmp->dm_symtab, sizeof (ctf_sect_t));
739         bzero(&dmp->dm_strtab, sizeof (ctf_sect_t));
740
741         if (dmp->dm_symbuckets != NULL) {
742                 free(dmp->dm_symbuckets);
743                 dmp->dm_symbuckets = NULL;
744         }
745
746         if (dmp->dm_symchains != NULL) {
747                 free(dmp->dm_symchains);
748                 dmp->dm_symchains = NULL;
749         }
750
751         if (dmp->dm_asmap != NULL) {
752                 free(dmp->dm_asmap);
753                 dmp->dm_asmap = NULL;
754         }
755 #if defined(__FreeBSD__)
756         if (dmp->dm_sec_offsets != NULL) {
757                 free(dmp->dm_sec_offsets);
758                 dmp->dm_sec_offsets = NULL;
759         }
760 #endif
761         dmp->dm_symfree = 0;
762         dmp->dm_nsymbuckets = 0;
763         dmp->dm_nsymelems = 0;
764         dmp->dm_asrsv = 0;
765         dmp->dm_aslen = 0;
766
767         dmp->dm_text_va = 0;
768         dmp->dm_text_size = 0;
769         dmp->dm_data_va = 0;
770         dmp->dm_data_size = 0;
771         dmp->dm_bss_va = 0;
772         dmp->dm_bss_size = 0;
773
774         if (dmp->dm_extern != NULL) {
775                 dt_idhash_destroy(dmp->dm_extern);
776                 dmp->dm_extern = NULL;
777         }
778
779         (void) elf_end(dmp->dm_elf);
780         dmp->dm_elf = NULL;
781
782         dmp->dm_flags &= ~DT_DM_LOADED;
783 }
784
785 void
786 dt_module_destroy(dtrace_hdl_t *dtp, dt_module_t *dmp)
787 {
788         uint_t h = dt_strtab_hash(dmp->dm_name, NULL) % dtp->dt_modbuckets;
789         dt_module_t **dmpp = &dtp->dt_mods[h];
790
791         dt_list_delete(&dtp->dt_modlist, dmp);
792         assert(dtp->dt_nmods != 0);
793         dtp->dt_nmods--;
794
795         /*
796          * Now remove this module from its hash chain.  We expect to always
797          * find the module on its hash chain, so in this loop we assert that
798          * we don't run off the end of the list.
799          */
800         while (*dmpp != dmp) {
801                 dmpp = &((*dmpp)->dm_next);
802                 assert(*dmpp != NULL);
803         }
804
805         *dmpp = dmp->dm_next;
806
807         dt_module_unload(dtp, dmp);
808         free(dmp);
809 }
810
811 /*
812  * Insert a new external symbol reference into the specified module.  The new
813  * symbol will be marked as undefined and is assigned a symbol index beyond
814  * any existing cached symbols from this module.  We use the ident's di_data
815  * field to store a pointer to a copy of the dtrace_syminfo_t for this symbol.
816  */
817 dt_ident_t *
818 dt_module_extern(dtrace_hdl_t *dtp, dt_module_t *dmp,
819     const char *name, const dtrace_typeinfo_t *tip)
820 {
821         dtrace_syminfo_t *sip;
822         dt_ident_t *idp;
823         uint_t id;
824
825         if (dmp->dm_extern == NULL && (dmp->dm_extern = dt_idhash_create(
826             "extern", NULL, dmp->dm_nsymelems, UINT_MAX)) == NULL) {
827                 (void) dt_set_errno(dtp, EDT_NOMEM);
828                 return (NULL);
829         }
830
831         if (dt_idhash_nextid(dmp->dm_extern, &id) == -1) {
832                 (void) dt_set_errno(dtp, EDT_SYMOFLOW);
833                 return (NULL);
834         }
835
836         if ((sip = malloc(sizeof (dtrace_syminfo_t))) == NULL) {
837                 (void) dt_set_errno(dtp, EDT_NOMEM);
838                 return (NULL);
839         }
840
841         idp = dt_idhash_insert(dmp->dm_extern, name, DT_IDENT_SYMBOL, 0, id,
842             _dtrace_symattr, 0, &dt_idops_thaw, NULL, dtp->dt_gen);
843
844         if (idp == NULL) {
845                 (void) dt_set_errno(dtp, EDT_NOMEM);
846                 free(sip);
847                 return (NULL);
848         }
849
850         sip->dts_object = dmp->dm_name;
851         sip->dts_name = idp->di_name;
852         sip->dts_id = idp->di_id;
853
854         idp->di_data = sip;
855         idp->di_ctfp = tip->dtt_ctfp;
856         idp->di_type = tip->dtt_type;
857
858         return (idp);
859 }
860
861 const char *
862 dt_module_modelname(dt_module_t *dmp)
863 {
864         if (dmp->dm_ops == &dt_modops_64)
865                 return ("64-bit");
866         else
867                 return ("32-bit");
868 }
869
870 /*
871  * Update our module cache by adding an entry for the specified module 'name'.
872  * We create the dt_module_t and populate it using /system/object/<name>/.
873  *
874  * On FreeBSD, the module name is passed as the full module file name, 
875  * including the path.
876  */
877 static void
878 #if defined(sun)
879 dt_module_update(dtrace_hdl_t *dtp, const char *name)
880 #else
881 dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat)
882 #endif
883 {
884         char fname[MAXPATHLEN];
885         struct stat64 st;
886         int fd, err, bits;
887
888         dt_module_t *dmp;
889         const char *s;
890         size_t shstrs;
891         GElf_Shdr sh;
892         Elf_Data *dp;
893         Elf_Scn *sp;
894
895 #if defined(sun)
896         (void) snprintf(fname, sizeof (fname),
897             "%s/%s/object", OBJFS_ROOT, name);
898 #else
899         GElf_Ehdr ehdr;
900         GElf_Phdr ph;
901         char name[MAXPATHLEN];
902         uintptr_t mapbase, alignmask;
903         int i = 0;
904         int is_elf_obj;
905
906         (void) strlcpy(name, k_stat->name, sizeof(name));
907         (void) strlcpy(fname, k_stat->pathname, sizeof(fname));
908 #endif
909
910         if ((fd = open(fname, O_RDONLY)) == -1 || fstat64(fd, &st) == -1 ||
911             (dmp = dt_module_create(dtp, name)) == NULL) {
912                 dt_dprintf("failed to open %s: %s\n", fname, strerror(errno));
913                 (void) close(fd);
914                 return;
915         }
916
917         /*
918          * Since the module can unload out from under us (and /system/object
919          * will return ENOENT), tell libelf to cook the entire file now and
920          * then close the underlying file descriptor immediately.  If this
921          * succeeds, we know that we can continue safely using dmp->dm_elf.
922          */
923         dmp->dm_elf = elf_begin(fd, ELF_C_READ, NULL);
924         err = elf_cntl(dmp->dm_elf, ELF_C_FDREAD);
925         (void) close(fd);
926
927         if (dmp->dm_elf == NULL || err == -1 ||
928             elf_getshdrstrndx(dmp->dm_elf, &shstrs) == -1) {
929                 dt_dprintf("failed to load %s: %s\n",
930                     fname, elf_errmsg(elf_errno()));
931                 dt_module_destroy(dtp, dmp);
932                 return;
933         }
934
935         switch (gelf_getclass(dmp->dm_elf)) {
936         case ELFCLASS32:
937                 dmp->dm_ops = &dt_modops_32;
938                 bits = 32;
939                 break;
940         case ELFCLASS64:
941                 dmp->dm_ops = &dt_modops_64;
942                 bits = 64;
943                 break;
944         default:
945                 dt_dprintf("failed to load %s: unknown ELF class\n", fname);
946                 dt_module_destroy(dtp, dmp);
947                 return;
948         }
949 #if defined(__FreeBSD__)
950         mapbase = (uintptr_t)k_stat->address;
951         gelf_getehdr(dmp->dm_elf, &ehdr);
952         is_elf_obj = (ehdr.e_type == ET_REL);
953         if (is_elf_obj) {
954                 dmp->dm_sec_offsets =
955                     malloc(ehdr.e_shnum * sizeof(*dmp->dm_sec_offsets));
956                 if (dmp->dm_sec_offsets == NULL) {
957                         dt_dprintf("failed to allocate memory\n");
958                         dt_module_destroy(dtp, dmp);
959                         return;
960                 }
961         }
962 #endif
963         /*
964          * Iterate over the section headers locating various sections of
965          * interest and use their attributes to flesh out the dt_module_t.
966          */
967         for (sp = NULL; (sp = elf_nextscn(dmp->dm_elf, sp)) != NULL; ) {
968                 if (gelf_getshdr(sp, &sh) == NULL || sh.sh_type == SHT_NULL ||
969                     (s = elf_strptr(dmp->dm_elf, shstrs, sh.sh_name)) == NULL)
970                         continue; /* skip any malformed sections */
971 #if defined(__FreeBSD__)
972                 if (sh.sh_size == 0)
973                         continue;
974                 if (sh.sh_type == SHT_PROGBITS || sh.sh_type == SHT_NOBITS) {
975                         alignmask = sh.sh_addralign - 1;
976                         mapbase += alignmask;
977                         mapbase &= ~alignmask;
978                         sh.sh_addr = mapbase;
979                         if (is_elf_obj)
980                                 dmp->dm_sec_offsets[elf_ndxscn(sp)] = sh.sh_addr;
981                         mapbase += sh.sh_size;
982                 }
983 #endif
984                 if (strcmp(s, ".text") == 0) {
985                         dmp->dm_text_size = sh.sh_size;
986                         dmp->dm_text_va = sh.sh_addr;
987                 } else if (strcmp(s, ".data") == 0) {
988                         dmp->dm_data_size = sh.sh_size;
989                         dmp->dm_data_va = sh.sh_addr;
990                 } else if (strcmp(s, ".bss") == 0) {
991                         dmp->dm_bss_size = sh.sh_size;
992                         dmp->dm_bss_va = sh.sh_addr;
993                 } else if (strcmp(s, ".info") == 0 &&
994                     (dp = elf_getdata(sp, NULL)) != NULL) {
995                         bcopy(dp->d_buf, &dmp->dm_info,
996                             MIN(sh.sh_size, sizeof (dmp->dm_info)));
997                 } else if (strcmp(s, ".filename") == 0 &&
998                     (dp = elf_getdata(sp, NULL)) != NULL) {
999                         (void) strlcpy(dmp->dm_file,
1000                             dp->d_buf, sizeof (dmp->dm_file));
1001                 }
1002         }
1003
1004         dmp->dm_flags |= DT_DM_KERNEL;
1005 #if defined(sun)
1006         dmp->dm_modid = (int)OBJFS_MODID(st.st_ino);
1007 #else
1008         /*
1009          * Include .rodata and special sections into .text.
1010          * This depends on default section layout produced by GNU ld
1011          * for ELF objects and libraries:
1012          * [Text][R/O data][R/W data][Dynamic][BSS][Non loadable]
1013          */
1014         dmp->dm_text_size = dmp->dm_data_va - dmp->dm_text_va;
1015 #if defined(__i386__)
1016         /*
1017          * Find the first load section and figure out the relocation
1018          * offset for the symbols. The kernel module will not need
1019          * relocation, but the kernel linker modules will.
1020          */
1021         for (i = 0; gelf_getphdr(dmp->dm_elf, i, &ph) != NULL; i++) {
1022                 if (ph.p_type == PT_LOAD) {
1023                         dmp->dm_reloc_offset = k_stat->address - ph.p_vaddr;
1024                         break;
1025                 }
1026         }
1027 #endif
1028 #endif
1029
1030         if (dmp->dm_info.objfs_info_primary)
1031                 dmp->dm_flags |= DT_DM_PRIMARY;
1032
1033         dt_dprintf("opened %d-bit module %s (%s) [%d]\n",
1034             bits, dmp->dm_name, dmp->dm_file, dmp->dm_modid);
1035 }
1036
1037 /*
1038  * Unload all the loaded modules and then refresh the module cache with the
1039  * latest list of loaded modules and their address ranges.
1040  */
1041 void
1042 dtrace_update(dtrace_hdl_t *dtp)
1043 {
1044         dt_module_t *dmp;
1045         DIR *dirp;
1046 #if defined(__FreeBSD__)
1047         int fileid;
1048 #endif
1049
1050         for (dmp = dt_list_next(&dtp->dt_modlist);
1051             dmp != NULL; dmp = dt_list_next(dmp))
1052                 dt_module_unload(dtp, dmp);
1053
1054 #if defined(sun)
1055         /*
1056          * Open /system/object and attempt to create a libdtrace module for
1057          * each kernel module that is loaded on the current system.
1058          */
1059         if (!(dtp->dt_oflags & DTRACE_O_NOSYS) &&
1060             (dirp = opendir(OBJFS_ROOT)) != NULL) {
1061                 struct dirent *dp;
1062
1063                 while ((dp = readdir(dirp)) != NULL) {
1064                         if (dp->d_name[0] != '.')
1065                                 dt_module_update(dtp, dp->d_name);
1066                 }
1067
1068                 (void) closedir(dirp);
1069         }
1070 #elif defined(__FreeBSD__)
1071         /*
1072          * Use FreeBSD's kernel loader interface to discover what kernel
1073          * modules are loaded and create a libdtrace module for each one.
1074          */
1075         for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) {
1076                 struct kld_file_stat k_stat;
1077                 k_stat.version = sizeof(k_stat);
1078                 if (kldstat(fileid, &k_stat) == 0)
1079                         dt_module_update(dtp, &k_stat);
1080         }
1081 #endif
1082
1083         /*
1084          * Look up all the macro identifiers and set di_id to the latest value.
1085          * This code collaborates with dt_lex.l on the use of di_id.  We will
1086          * need to implement something fancier if we need to support non-ints.
1087          */
1088         dt_idhash_lookup(dtp->dt_macros, "egid")->di_id = getegid();
1089         dt_idhash_lookup(dtp->dt_macros, "euid")->di_id = geteuid();
1090         dt_idhash_lookup(dtp->dt_macros, "gid")->di_id = getgid();
1091         dt_idhash_lookup(dtp->dt_macros, "pid")->di_id = getpid();
1092         dt_idhash_lookup(dtp->dt_macros, "pgid")->di_id = getpgid(0);
1093         dt_idhash_lookup(dtp->dt_macros, "ppid")->di_id = getppid();
1094 #if defined(sun)
1095         dt_idhash_lookup(dtp->dt_macros, "projid")->di_id = getprojid();
1096 #endif
1097         dt_idhash_lookup(dtp->dt_macros, "sid")->di_id = getsid(0);
1098 #if defined(sun)
1099         dt_idhash_lookup(dtp->dt_macros, "taskid")->di_id = gettaskid();
1100 #endif
1101         dt_idhash_lookup(dtp->dt_macros, "uid")->di_id = getuid();
1102
1103         /*
1104          * Cache the pointers to the modules representing the base executable
1105          * and the run-time linker in the dtrace client handle. Note that on
1106          * x86 krtld is folded into unix, so if we don't find it, use unix
1107          * instead.
1108          */
1109         dtp->dt_exec = dt_module_lookup_by_name(dtp, "genunix");
1110         dtp->dt_rtld = dt_module_lookup_by_name(dtp, "krtld");
1111         if (dtp->dt_rtld == NULL)
1112                 dtp->dt_rtld = dt_module_lookup_by_name(dtp, "unix");
1113
1114         /*
1115          * If this is the first time we are initializing the module list,
1116          * remove the module for genunix from the module list and then move it
1117          * to the front of the module list.  We do this so that type and symbol
1118          * queries encounter genunix and thereby optimize for the common case
1119          * in dtrace_lookup_by_name() and dtrace_lookup_by_type(), below.
1120          */
1121         if (dtp->dt_exec != NULL &&
1122             dtp->dt_cdefs == NULL && dtp->dt_ddefs == NULL) {
1123                 dt_list_delete(&dtp->dt_modlist, dtp->dt_exec);
1124                 dt_list_prepend(&dtp->dt_modlist, dtp->dt_exec);
1125         }
1126 }
1127
1128 static dt_module_t *
1129 dt_module_from_object(dtrace_hdl_t *dtp, const char *object)
1130 {
1131         int err = EDT_NOMOD;
1132         dt_module_t *dmp;
1133
1134         switch ((uintptr_t)object) {
1135         case (uintptr_t)DTRACE_OBJ_EXEC:
1136                 dmp = dtp->dt_exec;
1137                 break;
1138         case (uintptr_t)DTRACE_OBJ_RTLD:
1139                 dmp = dtp->dt_rtld;
1140                 break;
1141         case (uintptr_t)DTRACE_OBJ_CDEFS:
1142                 dmp = dtp->dt_cdefs;
1143                 break;
1144         case (uintptr_t)DTRACE_OBJ_DDEFS:
1145                 dmp = dtp->dt_ddefs;
1146                 break;
1147         default:
1148                 dmp = dt_module_create(dtp, object);
1149                 err = EDT_NOMEM;
1150         }
1151
1152         if (dmp == NULL)
1153                 (void) dt_set_errno(dtp, err);
1154
1155         return (dmp);
1156 }
1157
1158 /*
1159  * Exported interface to look up a symbol by name.  We return the GElf_Sym and
1160  * complete symbol information for the matching symbol.
1161  */
1162 int
1163 dtrace_lookup_by_name(dtrace_hdl_t *dtp, const char *object, const char *name,
1164     GElf_Sym *symp, dtrace_syminfo_t *sip)
1165 {
1166         dt_module_t *dmp;
1167         dt_ident_t *idp;
1168         uint_t n, id;
1169         GElf_Sym sym;
1170
1171         uint_t mask = 0; /* mask of dt_module flags to match */
1172         uint_t bits = 0; /* flag bits that must be present */
1173
1174         if (object != DTRACE_OBJ_EVERY &&
1175             object != DTRACE_OBJ_KMODS &&
1176             object != DTRACE_OBJ_UMODS) {
1177                 if ((dmp = dt_module_from_object(dtp, object)) == NULL)
1178                         return (-1); /* dt_errno is set for us */
1179
1180                 if (dt_module_load(dtp, dmp) == -1)
1181                         return (-1); /* dt_errno is set for us */
1182                 n = 1;
1183
1184         } else {
1185                 if (object == DTRACE_OBJ_KMODS)
1186                         mask = bits = DT_DM_KERNEL;
1187                 else if (object == DTRACE_OBJ_UMODS)
1188                         mask = DT_DM_KERNEL;
1189
1190                 dmp = dt_list_next(&dtp->dt_modlist);
1191                 n = dtp->dt_nmods;
1192         }
1193
1194         if (symp == NULL)
1195                 symp = &sym;
1196
1197         for (; n > 0; n--, dmp = dt_list_next(dmp)) {
1198                 if ((dmp->dm_flags & mask) != bits)
1199                         continue; /* failed to match required attributes */
1200
1201                 if (dt_module_load(dtp, dmp) == -1)
1202                         continue; /* failed to load symbol table */
1203
1204                 if (dmp->dm_ops->do_symname(dmp, name, symp, &id) != NULL) {
1205                         if (sip != NULL) {
1206                                 sip->dts_object = dmp->dm_name;
1207                                 sip->dts_name = (const char *)
1208                                     dmp->dm_strtab.cts_data + symp->st_name;
1209                                 sip->dts_id = id;
1210                         }
1211                         return (0);
1212                 }
1213
1214                 if (dmp->dm_extern != NULL &&
1215                     (idp = dt_idhash_lookup(dmp->dm_extern, name)) != NULL) {
1216                         if (symp != &sym) {
1217                                 symp->st_name = (uintptr_t)idp->di_name;
1218                                 symp->st_info =
1219                                     GELF_ST_INFO(STB_GLOBAL, STT_NOTYPE);
1220                                 symp->st_other = 0;
1221                                 symp->st_shndx = SHN_UNDEF;
1222                                 symp->st_value = 0;
1223                                 symp->st_size =
1224                                     ctf_type_size(idp->di_ctfp, idp->di_type);
1225                         }
1226
1227                         if (sip != NULL) {
1228                                 sip->dts_object = dmp->dm_name;
1229                                 sip->dts_name = idp->di_name;
1230                                 sip->dts_id = idp->di_id;
1231                         }
1232
1233                         return (0);
1234                 }
1235         }
1236
1237         return (dt_set_errno(dtp, EDT_NOSYM));
1238 }
1239
1240 /*
1241  * Exported interface to look up a symbol by address.  We return the GElf_Sym
1242  * and complete symbol information for the matching symbol.
1243  */
1244 int
1245 dtrace_lookup_by_addr(dtrace_hdl_t *dtp, GElf_Addr addr,
1246     GElf_Sym *symp, dtrace_syminfo_t *sip)
1247 {
1248         dt_module_t *dmp;
1249         uint_t id;
1250         const dtrace_vector_t *v = dtp->dt_vector;
1251
1252         if (v != NULL)
1253                 return (v->dtv_lookup_by_addr(dtp->dt_varg, addr, symp, sip));
1254
1255         for (dmp = dt_list_next(&dtp->dt_modlist); dmp != NULL;
1256             dmp = dt_list_next(dmp)) {
1257                 if (addr - dmp->dm_text_va < dmp->dm_text_size ||
1258                     addr - dmp->dm_data_va < dmp->dm_data_size ||
1259                     addr - dmp->dm_bss_va < dmp->dm_bss_size)
1260                         break;
1261         }
1262
1263         if (dmp == NULL)
1264                 return (dt_set_errno(dtp, EDT_NOSYMADDR));
1265
1266         if (dt_module_load(dtp, dmp) == -1)
1267                 return (-1); /* dt_errno is set for us */
1268
1269         if (symp != NULL) {
1270                 if (dmp->dm_ops->do_symaddr(dmp, addr, symp, &id) == NULL)
1271                         return (dt_set_errno(dtp, EDT_NOSYMADDR));
1272         }
1273
1274         if (sip != NULL) {
1275                 sip->dts_object = dmp->dm_name;
1276
1277                 if (symp != NULL) {
1278                         sip->dts_name = (const char *)
1279                             dmp->dm_strtab.cts_data + symp->st_name;
1280                         sip->dts_id = id;
1281                 } else {
1282                         sip->dts_name = NULL;
1283                         sip->dts_id = 0;
1284                 }
1285         }
1286
1287         return (0);
1288 }
1289
1290 int
1291 dtrace_lookup_by_type(dtrace_hdl_t *dtp, const char *object, const char *name,
1292     dtrace_typeinfo_t *tip)
1293 {
1294         dtrace_typeinfo_t ti;
1295         dt_module_t *dmp;
1296         int found = 0;
1297         ctf_id_t id;
1298         uint_t n;
1299         int justone;
1300
1301         uint_t mask = 0; /* mask of dt_module flags to match */
1302         uint_t bits = 0; /* flag bits that must be present */
1303
1304         if (object != DTRACE_OBJ_EVERY &&
1305             object != DTRACE_OBJ_KMODS &&
1306             object != DTRACE_OBJ_UMODS) {
1307                 if ((dmp = dt_module_from_object(dtp, object)) == NULL)
1308                         return (-1); /* dt_errno is set for us */
1309
1310                 if (dt_module_load(dtp, dmp) == -1)
1311                         return (-1); /* dt_errno is set for us */
1312                 n = 1;
1313                 justone = 1;
1314
1315         } else {
1316                 if (object == DTRACE_OBJ_KMODS)
1317                         mask = bits = DT_DM_KERNEL;
1318                 else if (object == DTRACE_OBJ_UMODS)
1319                         mask = DT_DM_KERNEL;
1320
1321                 dmp = dt_list_next(&dtp->dt_modlist);
1322                 n = dtp->dt_nmods;
1323                 justone = 0;
1324         }
1325
1326         if (tip == NULL)
1327                 tip = &ti;
1328
1329         for (; n > 0; n--, dmp = dt_list_next(dmp)) {
1330                 if ((dmp->dm_flags & mask) != bits)
1331                         continue; /* failed to match required attributes */
1332
1333                 /*
1334                  * If we can't load the CTF container, continue on to the next
1335                  * module.  If our search was scoped to only one module then
1336                  * return immediately leaving dt_errno unmodified.
1337                  */
1338                 if (dt_module_getctf(dtp, dmp) == NULL) {
1339                         if (justone)
1340                                 return (-1);
1341                         continue;
1342                 }
1343
1344                 /*
1345                  * Look up the type in the module's CTF container.  If our
1346                  * match is a forward declaration tag, save this choice in
1347                  * 'tip' and keep going in the hope that we will locate the
1348                  * underlying structure definition.  Otherwise just return.
1349                  */
1350                 if ((id = ctf_lookup_by_name(dmp->dm_ctfp, name)) != CTF_ERR) {
1351                         tip->dtt_object = dmp->dm_name;
1352                         tip->dtt_ctfp = dmp->dm_ctfp;
1353                         tip->dtt_type = id;
1354
1355                         if (ctf_type_kind(dmp->dm_ctfp, ctf_type_resolve(
1356                             dmp->dm_ctfp, id)) != CTF_K_FORWARD)
1357                                 return (0);
1358
1359                         found++;
1360                 }
1361         }
1362
1363         if (found == 0)
1364                 return (dt_set_errno(dtp, EDT_NOTYPE));
1365
1366         return (0);
1367 }
1368
1369 int
1370 dtrace_symbol_type(dtrace_hdl_t *dtp, const GElf_Sym *symp,
1371     const dtrace_syminfo_t *sip, dtrace_typeinfo_t *tip)
1372 {
1373         dt_module_t *dmp;
1374
1375         tip->dtt_object = NULL;
1376         tip->dtt_ctfp = NULL;
1377         tip->dtt_type = CTF_ERR;
1378
1379         if ((dmp = dt_module_lookup_by_name(dtp, sip->dts_object)) == NULL)
1380                 return (dt_set_errno(dtp, EDT_NOMOD));
1381
1382         if (symp->st_shndx == SHN_UNDEF && dmp->dm_extern != NULL) {
1383                 dt_ident_t *idp =
1384                     dt_idhash_lookup(dmp->dm_extern, sip->dts_name);
1385
1386                 if (idp == NULL)
1387                         return (dt_set_errno(dtp, EDT_NOSYM));
1388
1389                 tip->dtt_ctfp = idp->di_ctfp;
1390                 tip->dtt_type = idp->di_type;
1391
1392         } else if (GELF_ST_TYPE(symp->st_info) != STT_FUNC) {
1393                 if (dt_module_getctf(dtp, dmp) == NULL)
1394                         return (-1); /* errno is set for us */
1395
1396                 tip->dtt_ctfp = dmp->dm_ctfp;
1397                 tip->dtt_type = ctf_lookup_by_symbol(dmp->dm_ctfp, sip->dts_id);
1398
1399                 if (tip->dtt_type == CTF_ERR) {
1400                         dtp->dt_ctferr = ctf_errno(tip->dtt_ctfp);
1401                         return (dt_set_errno(dtp, EDT_CTF));
1402                 }
1403
1404         } else {
1405                 tip->dtt_ctfp = DT_FPTR_CTFP(dtp);
1406                 tip->dtt_type = DT_FPTR_TYPE(dtp);
1407         }
1408
1409         tip->dtt_object = dmp->dm_name;
1410         return (0);
1411 }
1412
1413 static dtrace_objinfo_t *
1414 dt_module_info(const dt_module_t *dmp, dtrace_objinfo_t *dto)
1415 {
1416         dto->dto_name = dmp->dm_name;
1417         dto->dto_file = dmp->dm_file;
1418         dto->dto_id = dmp->dm_modid;
1419         dto->dto_flags = 0;
1420
1421         if (dmp->dm_flags & DT_DM_KERNEL)
1422                 dto->dto_flags |= DTRACE_OBJ_F_KERNEL;
1423         if (dmp->dm_flags & DT_DM_PRIMARY)
1424                 dto->dto_flags |= DTRACE_OBJ_F_PRIMARY;
1425
1426         dto->dto_text_va = dmp->dm_text_va;
1427         dto->dto_text_size = dmp->dm_text_size;
1428         dto->dto_data_va = dmp->dm_data_va;
1429         dto->dto_data_size = dmp->dm_data_size;
1430         dto->dto_bss_va = dmp->dm_bss_va;
1431         dto->dto_bss_size = dmp->dm_bss_size;
1432
1433         return (dto);
1434 }
1435
1436 int
1437 dtrace_object_iter(dtrace_hdl_t *dtp, dtrace_obj_f *func, void *data)
1438 {
1439         const dt_module_t *dmp = dt_list_next(&dtp->dt_modlist);
1440         dtrace_objinfo_t dto;
1441         int rv;
1442
1443         for (; dmp != NULL; dmp = dt_list_next(dmp)) {
1444                 if ((rv = (*func)(dtp, dt_module_info(dmp, &dto), data)) != 0)
1445                         return (rv);
1446         }
1447
1448         return (0);
1449 }
1450
1451 int
1452 dtrace_object_info(dtrace_hdl_t *dtp, const char *object, dtrace_objinfo_t *dto)
1453 {
1454         dt_module_t *dmp;
1455
1456         if (object == DTRACE_OBJ_EVERY || object == DTRACE_OBJ_KMODS ||
1457             object == DTRACE_OBJ_UMODS || dto == NULL)
1458                 return (dt_set_errno(dtp, EINVAL));
1459
1460         if ((dmp = dt_module_from_object(dtp, object)) == NULL)
1461                 return (-1); /* dt_errno is set for us */
1462
1463         if (dt_module_load(dtp, dmp) == -1)
1464                 return (-1); /* dt_errno is set for us */
1465
1466         (void) dt_module_info(dmp, dto);
1467         return (0);
1468 }