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