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