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