1178479Sjb/*
2178479Sjb * CDDL HEADER START
3178479Sjb *
4178479Sjb * The contents of this file are subject to the terms of the
5178479Sjb * Common Development and Distribution License (the "License").
6178479Sjb * You may not use this file except in compliance with the License.
7178479Sjb *
8178479Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9178479Sjb * or http://www.opensolaris.org/os/licensing.
10178479Sjb * See the License for the specific language governing permissions
11178479Sjb * and limitations under the License.
12178479Sjb *
13178479Sjb * When distributing Covered Code, include this CDDL HEADER in each
14178479Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15178479Sjb * If applicable, add the following below this CDDL HEADER, with the
16178479Sjb * fields enclosed by brackets "[]" replaced with your own identifying
17178479Sjb * information: Portions Copyright [yyyy] [name of copyright owner]
18178479Sjb *
19178479Sjb * CDDL HEADER END
20178479Sjb */
21210767Srpaulo
22178479Sjb/*
23210767Srpaulo * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24178479Sjb */
25268578Srpaulo/*
26268578Srpaulo * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
27268578Srpaulo */
28178479Sjb
29178479Sjb#include <sys/types.h>
30178559Sjb#if defined(sun)
31178479Sjb#include <sys/modctl.h>
32178479Sjb#include <sys/kobj.h>
33178479Sjb#include <sys/kobj_impl.h>
34178479Sjb#include <sys/sysmacros.h>
35178479Sjb#include <sys/elf.h>
36178479Sjb#include <sys/task.h>
37178559Sjb#else
38178559Sjb#include <sys/param.h>
39178559Sjb#include <sys/linker.h>
40178559Sjb#include <sys/stat.h>
41178559Sjb#endif
42178479Sjb
43178479Sjb#include <unistd.h>
44178559Sjb#if defined(sun)
45178479Sjb#include <project.h>
46178559Sjb#endif
47178479Sjb#include <strings.h>
48178479Sjb#include <stdlib.h>
49178479Sjb#include <libelf.h>
50178479Sjb#include <limits.h>
51178479Sjb#include <assert.h>
52178479Sjb#include <errno.h>
53178479Sjb#include <dirent.h>
54178559Sjb#if !defined(sun)
55178559Sjb#include <fcntl.h>
56268578Srpaulo#include <libproc_compat.h>
57178559Sjb#endif
58178479Sjb
59178479Sjb#include <dt_strtab.h>
60178479Sjb#include <dt_module.h>
61178479Sjb#include <dt_impl.h>
62178479Sjb
63178479Sjbstatic const char *dt_module_strtab; /* active strtab for qsort callbacks */
64178479Sjb
65178479Sjbstatic void
66178479Sjbdt_module_symhash_insert(dt_module_t *dmp, const char *name, uint_t id)
67178479Sjb{
68178479Sjb	dt_sym_t *dsp = &dmp->dm_symchains[dmp->dm_symfree];
69178479Sjb	uint_t h;
70178479Sjb
71178479Sjb	assert(dmp->dm_symfree < dmp->dm_nsymelems + 1);
72178479Sjb
73178479Sjb	dsp->ds_symid = id;
74178479Sjb	h = dt_strtab_hash(name, NULL) % dmp->dm_nsymbuckets;
75178479Sjb	dsp->ds_next = dmp->dm_symbuckets[h];
76178479Sjb	dmp->dm_symbuckets[h] = dmp->dm_symfree++;
77178479Sjb}
78178479Sjb
79178479Sjbstatic uint_t
80178479Sjbdt_module_syminit32(dt_module_t *dmp)
81178479Sjb{
82210767Srpaulo#if STT_NUM != (STT_TLS + 1)
83210767Srpaulo#error "STT_NUM has grown. update dt_module_syminit32()"
84210767Srpaulo#endif
85210767Srpaulo
86178559Sjb	Elf32_Sym *sym = dmp->dm_symtab.cts_data;
87178479Sjb	const char *base = dmp->dm_strtab.cts_data;
88178479Sjb	size_t ss_size = dmp->dm_strtab.cts_size;
89178479Sjb	uint_t i, n = dmp->dm_nsymelems;
90178479Sjb	uint_t asrsv = 0;
91178479Sjb
92210425Savg#if defined(__FreeBSD__)
93210425Savg	GElf_Ehdr ehdr;
94210425Savg	int is_elf_obj;
95210425Savg
96210425Savg	gelf_getehdr(dmp->dm_elf, &ehdr);
97210425Savg	is_elf_obj = (ehdr.e_type == ET_REL);
98210425Savg#endif
99210425Savg
100178479Sjb	for (i = 0; i < n; i++, sym++) {
101178479Sjb		const char *name = base + sym->st_name;
102178479Sjb		uchar_t type = ELF32_ST_TYPE(sym->st_info);
103178479Sjb
104178479Sjb		if (type >= STT_NUM || type == STT_SECTION)
105178479Sjb			continue; /* skip sections and unknown types */
106178479Sjb
107178479Sjb		if (sym->st_name == 0 || sym->st_name >= ss_size)
108178479Sjb			continue; /* skip null or invalid names */
109178479Sjb
110178479Sjb		if (sym->st_value != 0 &&
111178559Sjb		    (ELF32_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size)) {
112178479Sjb			asrsv++; /* reserve space in the address map */
113178479Sjb
114210425Savg#if defined(__FreeBSD__)
115178559Sjb			sym->st_value += (Elf_Addr) dmp->dm_reloc_offset;
116210425Savg			if (is_elf_obj && sym->st_shndx != SHN_UNDEF &&
117210425Savg			    sym->st_shndx < ehdr.e_shnum)
118210425Savg				sym->st_value +=
119210425Savg				    dmp->dm_sec_offsets[sym->st_shndx];
120178559Sjb#endif
121178559Sjb		}
122178559Sjb
123178479Sjb		dt_module_symhash_insert(dmp, name, i);
124178479Sjb	}
125178479Sjb
126178479Sjb	return (asrsv);
127178479Sjb}
128178479Sjb
129178479Sjbstatic uint_t
130178479Sjbdt_module_syminit64(dt_module_t *dmp)
131178479Sjb{
132210767Srpaulo#if STT_NUM != (STT_TLS + 1)
133210767Srpaulo#error "STT_NUM has grown. update dt_module_syminit64()"
134210767Srpaulo#endif
135210767Srpaulo
136178559Sjb	Elf64_Sym *sym = dmp->dm_symtab.cts_data;
137178479Sjb	const char *base = dmp->dm_strtab.cts_data;
138178479Sjb	size_t ss_size = dmp->dm_strtab.cts_size;
139178479Sjb	uint_t i, n = dmp->dm_nsymelems;
140178479Sjb	uint_t asrsv = 0;
141178479Sjb
142210425Savg#if defined(__FreeBSD__)
143210425Savg	GElf_Ehdr ehdr;
144210425Savg	int is_elf_obj;
145210425Savg
146210425Savg	gelf_getehdr(dmp->dm_elf, &ehdr);
147210425Savg	is_elf_obj = (ehdr.e_type == ET_REL);
148210425Savg#endif
149210425Savg
150178479Sjb	for (i = 0; i < n; i++, sym++) {
151178479Sjb		const char *name = base + sym->st_name;
152178479Sjb		uchar_t type = ELF64_ST_TYPE(sym->st_info);
153178479Sjb
154178479Sjb		if (type >= STT_NUM || type == STT_SECTION)
155178479Sjb			continue; /* skip sections and unknown types */
156178479Sjb
157178479Sjb		if (sym->st_name == 0 || sym->st_name >= ss_size)
158178479Sjb			continue; /* skip null or invalid names */
159178479Sjb
160178479Sjb		if (sym->st_value != 0 &&
161178559Sjb		    (ELF64_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size)) {
162178479Sjb			asrsv++; /* reserve space in the address map */
163210425Savg#if defined(__FreeBSD__)
164178559Sjb			sym->st_value += (Elf_Addr) dmp->dm_reloc_offset;
165210425Savg			if (is_elf_obj && sym->st_shndx != SHN_UNDEF &&
166210425Savg			    sym->st_shndx < ehdr.e_shnum)
167210425Savg				sym->st_value +=
168210425Savg				    dmp->dm_sec_offsets[sym->st_shndx];
169178559Sjb#endif
170178559Sjb		}
171178559Sjb
172178479Sjb		dt_module_symhash_insert(dmp, name, i);
173178479Sjb	}
174178479Sjb
175178479Sjb	return (asrsv);
176178479Sjb}
177178479Sjb
178178479Sjb/*
179178479Sjb * Sort comparison function for 32-bit symbol address-to-name lookups.  We sort
180178479Sjb * symbols by value.  If values are equal, we prefer the symbol that is
181178479Sjb * non-zero sized, typed, not weak, or lexically first, in that order.
182178479Sjb */
183178479Sjbstatic int
184178479Sjbdt_module_symcomp32(const void *lp, const void *rp)
185178479Sjb{
186178479Sjb	Elf32_Sym *lhs = *((Elf32_Sym **)lp);
187178479Sjb	Elf32_Sym *rhs = *((Elf32_Sym **)rp);
188178479Sjb
189178479Sjb	if (lhs->st_value != rhs->st_value)
190178479Sjb		return (lhs->st_value > rhs->st_value ? 1 : -1);
191178479Sjb
192178479Sjb	if ((lhs->st_size == 0) != (rhs->st_size == 0))
193178479Sjb		return (lhs->st_size == 0 ? 1 : -1);
194178479Sjb
195178479Sjb	if ((ELF32_ST_TYPE(lhs->st_info) == STT_NOTYPE) !=
196178479Sjb	    (ELF32_ST_TYPE(rhs->st_info) == STT_NOTYPE))
197178479Sjb		return (ELF32_ST_TYPE(lhs->st_info) == STT_NOTYPE ? 1 : -1);
198178479Sjb
199178479Sjb	if ((ELF32_ST_BIND(lhs->st_info) == STB_WEAK) !=
200178479Sjb	    (ELF32_ST_BIND(rhs->st_info) == STB_WEAK))
201178479Sjb		return (ELF32_ST_BIND(lhs->st_info) == STB_WEAK ? 1 : -1);
202178479Sjb
203178479Sjb	return (strcmp(dt_module_strtab + lhs->st_name,
204178479Sjb	    dt_module_strtab + rhs->st_name));
205178479Sjb}
206178479Sjb
207178479Sjb/*
208178479Sjb * Sort comparison function for 64-bit symbol address-to-name lookups.  We sort
209178479Sjb * symbols by value.  If values are equal, we prefer the symbol that is
210178479Sjb * non-zero sized, typed, not weak, or lexically first, in that order.
211178479Sjb */
212178479Sjbstatic int
213178479Sjbdt_module_symcomp64(const void *lp, const void *rp)
214178479Sjb{
215178479Sjb	Elf64_Sym *lhs = *((Elf64_Sym **)lp);
216178479Sjb	Elf64_Sym *rhs = *((Elf64_Sym **)rp);
217178479Sjb
218178479Sjb	if (lhs->st_value != rhs->st_value)
219178479Sjb		return (lhs->st_value > rhs->st_value ? 1 : -1);
220178479Sjb
221178479Sjb	if ((lhs->st_size == 0) != (rhs->st_size == 0))
222178479Sjb		return (lhs->st_size == 0 ? 1 : -1);
223178479Sjb
224178479Sjb	if ((ELF64_ST_TYPE(lhs->st_info) == STT_NOTYPE) !=
225178479Sjb	    (ELF64_ST_TYPE(rhs->st_info) == STT_NOTYPE))
226178479Sjb		return (ELF64_ST_TYPE(lhs->st_info) == STT_NOTYPE ? 1 : -1);
227178479Sjb
228178479Sjb	if ((ELF64_ST_BIND(lhs->st_info) == STB_WEAK) !=
229178479Sjb	    (ELF64_ST_BIND(rhs->st_info) == STB_WEAK))
230178479Sjb		return (ELF64_ST_BIND(lhs->st_info) == STB_WEAK ? 1 : -1);
231178479Sjb
232178479Sjb	return (strcmp(dt_module_strtab + lhs->st_name,
233178479Sjb	    dt_module_strtab + rhs->st_name));
234178479Sjb}
235178479Sjb
236178479Sjbstatic void
237178479Sjbdt_module_symsort32(dt_module_t *dmp)
238178479Sjb{
239178479Sjb	Elf32_Sym *symtab = (Elf32_Sym *)dmp->dm_symtab.cts_data;
240178479Sjb	Elf32_Sym **sympp = (Elf32_Sym **)dmp->dm_asmap;
241178479Sjb	const dt_sym_t *dsp = dmp->dm_symchains + 1;
242178479Sjb	uint_t i, n = dmp->dm_symfree;
243178479Sjb
244178479Sjb	for (i = 1; i < n; i++, dsp++) {
245178479Sjb		Elf32_Sym *sym = symtab + dsp->ds_symid;
246178479Sjb		if (sym->st_value != 0 &&
247178479Sjb		    (ELF32_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size))
248178479Sjb			*sympp++ = sym;
249178479Sjb	}
250178479Sjb
251178479Sjb	dmp->dm_aslen = (uint_t)(sympp - (Elf32_Sym **)dmp->dm_asmap);
252178479Sjb	assert(dmp->dm_aslen <= dmp->dm_asrsv);
253178479Sjb
254178479Sjb	dt_module_strtab = dmp->dm_strtab.cts_data;
255178479Sjb	qsort(dmp->dm_asmap, dmp->dm_aslen,
256178479Sjb	    sizeof (Elf32_Sym *), dt_module_symcomp32);
257178479Sjb	dt_module_strtab = NULL;
258178479Sjb}
259178479Sjb
260178479Sjbstatic void
261178479Sjbdt_module_symsort64(dt_module_t *dmp)
262178479Sjb{
263178479Sjb	Elf64_Sym *symtab = (Elf64_Sym *)dmp->dm_symtab.cts_data;
264178479Sjb	Elf64_Sym **sympp = (Elf64_Sym **)dmp->dm_asmap;
265178479Sjb	const dt_sym_t *dsp = dmp->dm_symchains + 1;
266178479Sjb	uint_t i, n = dmp->dm_symfree;
267178479Sjb
268178479Sjb	for (i = 1; i < n; i++, dsp++) {
269178479Sjb		Elf64_Sym *sym = symtab + dsp->ds_symid;
270178479Sjb		if (sym->st_value != 0 &&
271178479Sjb		    (ELF64_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size))
272178479Sjb			*sympp++ = sym;
273178479Sjb	}
274178479Sjb
275178479Sjb	dmp->dm_aslen = (uint_t)(sympp - (Elf64_Sym **)dmp->dm_asmap);
276178479Sjb	assert(dmp->dm_aslen <= dmp->dm_asrsv);
277178479Sjb
278178479Sjb	dt_module_strtab = dmp->dm_strtab.cts_data;
279178479Sjb	qsort(dmp->dm_asmap, dmp->dm_aslen,
280178479Sjb	    sizeof (Elf64_Sym *), dt_module_symcomp64);
281178479Sjb	dt_module_strtab = NULL;
282178479Sjb}
283178479Sjb
284178479Sjbstatic GElf_Sym *
285178479Sjbdt_module_symgelf32(const Elf32_Sym *src, GElf_Sym *dst)
286178479Sjb{
287178479Sjb	if (dst != NULL) {
288178479Sjb		dst->st_name = src->st_name;
289178479Sjb		dst->st_info = src->st_info;
290178479Sjb		dst->st_other = src->st_other;
291178479Sjb		dst->st_shndx = src->st_shndx;
292178479Sjb		dst->st_value = src->st_value;
293178479Sjb		dst->st_size = src->st_size;
294178479Sjb	}
295178479Sjb
296178479Sjb	return (dst);
297178479Sjb}
298178479Sjb
299178479Sjbstatic GElf_Sym *
300178479Sjbdt_module_symgelf64(const Elf64_Sym *src, GElf_Sym *dst)
301178479Sjb{
302178479Sjb	if (dst != NULL)
303178479Sjb		bcopy(src, dst, sizeof (GElf_Sym));
304178479Sjb
305178479Sjb	return (dst);
306178479Sjb}
307178479Sjb
308178479Sjbstatic GElf_Sym *
309178479Sjbdt_module_symname32(dt_module_t *dmp, const char *name,
310178479Sjb    GElf_Sym *symp, uint_t *idp)
311178479Sjb{
312178479Sjb	const Elf32_Sym *symtab = dmp->dm_symtab.cts_data;
313178479Sjb	const char *strtab = dmp->dm_strtab.cts_data;
314178479Sjb
315178479Sjb	const Elf32_Sym *sym;
316178479Sjb	const dt_sym_t *dsp;
317178479Sjb	uint_t i, h;
318178479Sjb
319178479Sjb	if (dmp->dm_nsymelems == 0)
320178479Sjb		return (NULL);
321178479Sjb
322178479Sjb	h = dt_strtab_hash(name, NULL) % dmp->dm_nsymbuckets;
323178479Sjb
324178479Sjb	for (i = dmp->dm_symbuckets[h]; i != 0; i = dsp->ds_next) {
325178479Sjb		dsp = &dmp->dm_symchains[i];
326178479Sjb		sym = symtab + dsp->ds_symid;
327178479Sjb
328178479Sjb		if (strcmp(name, strtab + sym->st_name) == 0) {
329178479Sjb			if (idp != NULL)
330178479Sjb				*idp = dsp->ds_symid;
331178479Sjb			return (dt_module_symgelf32(sym, symp));
332178479Sjb		}
333178479Sjb	}
334178479Sjb
335178479Sjb	return (NULL);
336178479Sjb}
337178479Sjb
338178479Sjbstatic GElf_Sym *
339178479Sjbdt_module_symname64(dt_module_t *dmp, const char *name,
340178479Sjb    GElf_Sym *symp, uint_t *idp)
341178479Sjb{
342178479Sjb	const Elf64_Sym *symtab = dmp->dm_symtab.cts_data;
343178479Sjb	const char *strtab = dmp->dm_strtab.cts_data;
344178479Sjb
345178479Sjb	const Elf64_Sym *sym;
346178479Sjb	const dt_sym_t *dsp;
347178479Sjb	uint_t i, h;
348178479Sjb
349178479Sjb	if (dmp->dm_nsymelems == 0)
350178479Sjb		return (NULL);
351178479Sjb
352178479Sjb	h = dt_strtab_hash(name, NULL) % dmp->dm_nsymbuckets;
353178479Sjb
354178479Sjb	for (i = dmp->dm_symbuckets[h]; i != 0; i = dsp->ds_next) {
355178479Sjb		dsp = &dmp->dm_symchains[i];
356178479Sjb		sym = symtab + dsp->ds_symid;
357178479Sjb
358178479Sjb		if (strcmp(name, strtab + sym->st_name) == 0) {
359178479Sjb			if (idp != NULL)
360178479Sjb				*idp = dsp->ds_symid;
361178479Sjb			return (dt_module_symgelf64(sym, symp));
362178479Sjb		}
363178479Sjb	}
364178479Sjb
365178479Sjb	return (NULL);
366178479Sjb}
367178479Sjb
368178479Sjbstatic GElf_Sym *
369178479Sjbdt_module_symaddr32(dt_module_t *dmp, GElf_Addr addr,
370178479Sjb    GElf_Sym *symp, uint_t *idp)
371178479Sjb{
372178479Sjb	const Elf32_Sym **asmap = (const Elf32_Sym **)dmp->dm_asmap;
373178479Sjb	const Elf32_Sym *symtab = dmp->dm_symtab.cts_data;
374178479Sjb	const Elf32_Sym *sym;
375178479Sjb
376178479Sjb	uint_t i, mid, lo = 0, hi = dmp->dm_aslen - 1;
377178479Sjb	Elf32_Addr v;
378178479Sjb
379178479Sjb	if (dmp->dm_aslen == 0)
380178479Sjb		return (NULL);
381178479Sjb
382178479Sjb	while (hi - lo > 1) {
383178479Sjb		mid = (lo + hi) / 2;
384178479Sjb		if (addr >= asmap[mid]->st_value)
385178479Sjb			lo = mid;
386178479Sjb		else
387178479Sjb			hi = mid;
388178479Sjb	}
389178479Sjb
390178479Sjb	i = addr < asmap[hi]->st_value ? lo : hi;
391178479Sjb	sym = asmap[i];
392178479Sjb	v = sym->st_value;
393178479Sjb
394178479Sjb	/*
395178479Sjb	 * If the previous entry has the same value, improve our choice.  The
396178479Sjb	 * order of equal-valued symbols is determined by the comparison func.
397178479Sjb	 */
398178479Sjb	while (i-- != 0 && asmap[i]->st_value == v)
399178479Sjb		sym = asmap[i];
400178479Sjb
401178479Sjb	if (addr - sym->st_value < MAX(sym->st_size, 1)) {
402178479Sjb		if (idp != NULL)
403178479Sjb			*idp = (uint_t)(sym - symtab);
404178479Sjb		return (dt_module_symgelf32(sym, symp));
405178479Sjb	}
406178479Sjb
407178479Sjb	return (NULL);
408178479Sjb}
409178479Sjb
410178479Sjbstatic GElf_Sym *
411178479Sjbdt_module_symaddr64(dt_module_t *dmp, GElf_Addr addr,
412178479Sjb    GElf_Sym *symp, uint_t *idp)
413178479Sjb{
414178479Sjb	const Elf64_Sym **asmap = (const Elf64_Sym **)dmp->dm_asmap;
415178479Sjb	const Elf64_Sym *symtab = dmp->dm_symtab.cts_data;
416178479Sjb	const Elf64_Sym *sym;
417178479Sjb
418178479Sjb	uint_t i, mid, lo = 0, hi = dmp->dm_aslen - 1;
419178479Sjb	Elf64_Addr v;
420178479Sjb
421178479Sjb	if (dmp->dm_aslen == 0)
422178479Sjb		return (NULL);
423178479Sjb
424178479Sjb	while (hi - lo > 1) {
425178479Sjb		mid = (lo + hi) / 2;
426178479Sjb		if (addr >= asmap[mid]->st_value)
427178479Sjb			lo = mid;
428178479Sjb		else
429178479Sjb			hi = mid;
430178479Sjb	}
431178479Sjb
432178479Sjb	i = addr < asmap[hi]->st_value ? lo : hi;
433178479Sjb	sym = asmap[i];
434178479Sjb	v = sym->st_value;
435178479Sjb
436178479Sjb	/*
437178479Sjb	 * If the previous entry has the same value, improve our choice.  The
438178479Sjb	 * order of equal-valued symbols is determined by the comparison func.
439178479Sjb	 */
440178479Sjb	while (i-- != 0 && asmap[i]->st_value == v)
441178479Sjb		sym = asmap[i];
442178479Sjb
443178479Sjb	if (addr - sym->st_value < MAX(sym->st_size, 1)) {
444178479Sjb		if (idp != NULL)
445178479Sjb			*idp = (uint_t)(sym - symtab);
446178479Sjb		return (dt_module_symgelf64(sym, symp));
447178479Sjb	}
448178479Sjb
449178479Sjb	return (NULL);
450178479Sjb}
451178479Sjb
452178479Sjbstatic const dt_modops_t dt_modops_32 = {
453178479Sjb	dt_module_syminit32,
454178479Sjb	dt_module_symsort32,
455178479Sjb	dt_module_symname32,
456178479Sjb	dt_module_symaddr32
457178479Sjb};
458178479Sjb
459178479Sjbstatic const dt_modops_t dt_modops_64 = {
460178479Sjb	dt_module_syminit64,
461178479Sjb	dt_module_symsort64,
462178479Sjb	dt_module_symname64,
463178479Sjb	dt_module_symaddr64
464178479Sjb};
465178479Sjb
466178479Sjbdt_module_t *
467178479Sjbdt_module_create(dtrace_hdl_t *dtp, const char *name)
468178479Sjb{
469268578Srpaulo	long pid;
470268578Srpaulo	char *eptr;
471268578Srpaulo	dt_ident_t *idp;
472178479Sjb	uint_t h = dt_strtab_hash(name, NULL) % dtp->dt_modbuckets;
473178479Sjb	dt_module_t *dmp;
474178479Sjb
475178479Sjb	for (dmp = dtp->dt_mods[h]; dmp != NULL; dmp = dmp->dm_next) {
476178479Sjb		if (strcmp(dmp->dm_name, name) == 0)
477178479Sjb			return (dmp);
478178479Sjb	}
479178479Sjb
480178479Sjb	if ((dmp = malloc(sizeof (dt_module_t))) == NULL)
481178479Sjb		return (NULL); /* caller must handle allocation failure */
482178479Sjb
483178479Sjb	bzero(dmp, sizeof (dt_module_t));
484178479Sjb	(void) strlcpy(dmp->dm_name, name, sizeof (dmp->dm_name));
485178479Sjb	dt_list_append(&dtp->dt_modlist, dmp);
486178479Sjb	dmp->dm_next = dtp->dt_mods[h];
487178479Sjb	dtp->dt_mods[h] = dmp;
488178479Sjb	dtp->dt_nmods++;
489178479Sjb
490178479Sjb	if (dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64)
491178479Sjb		dmp->dm_ops = &dt_modops_64;
492178479Sjb	else
493178479Sjb		dmp->dm_ops = &dt_modops_32;
494178479Sjb
495268578Srpaulo	/*
496268578Srpaulo	 * Modules for userland processes are special. They always refer to a
497268578Srpaulo	 * specific process and have a copy of their CTF data from a specific
498268578Srpaulo	 * instant in time. Any dt_module_t that begins with 'pid' is a module
499268578Srpaulo	 * for a specific process, much like how any probe description that
500268578Srpaulo	 * begins with 'pid' is special. pid123 refers to process 123. A module
501268578Srpaulo	 * that is just 'pid' refers specifically to pid$target. This is
502268578Srpaulo	 * generally done as D does not currently allow for macros to be
503268578Srpaulo	 * evaluated when working with types.
504268578Srpaulo	 */
505268578Srpaulo	if (strncmp(dmp->dm_name, "pid", 3) == 0) {
506268578Srpaulo		errno = 0;
507268578Srpaulo		if (dmp->dm_name[3] == '\0') {
508268578Srpaulo			idp = dt_idhash_lookup(dtp->dt_macros, "target");
509268578Srpaulo			if (idp != NULL && idp->di_id != 0)
510268578Srpaulo				dmp->dm_pid = idp->di_id;
511268578Srpaulo		} else {
512268578Srpaulo			pid = strtol(dmp->dm_name + 3, &eptr, 10);
513268578Srpaulo			if (errno == 0 && *eptr == '\0')
514268578Srpaulo				dmp->dm_pid = (pid_t)pid;
515268578Srpaulo			else
516268578Srpaulo				dt_dprintf("encountered malformed pid "
517268578Srpaulo				    "module: %s\n", dmp->dm_name);
518268578Srpaulo		}
519268578Srpaulo	}
520268578Srpaulo
521178479Sjb	return (dmp);
522178479Sjb}
523178479Sjb
524178479Sjbdt_module_t *
525178479Sjbdt_module_lookup_by_name(dtrace_hdl_t *dtp, const char *name)
526178479Sjb{
527178479Sjb	uint_t h = dt_strtab_hash(name, NULL) % dtp->dt_modbuckets;
528178479Sjb	dt_module_t *dmp;
529178479Sjb
530178479Sjb	for (dmp = dtp->dt_mods[h]; dmp != NULL; dmp = dmp->dm_next) {
531178479Sjb		if (strcmp(dmp->dm_name, name) == 0)
532178479Sjb			return (dmp);
533178479Sjb	}
534178479Sjb
535178479Sjb	return (NULL);
536178479Sjb}
537178479Sjb
538178479Sjb/*ARGSUSED*/
539178479Sjbdt_module_t *
540178479Sjbdt_module_lookup_by_ctf(dtrace_hdl_t *dtp, ctf_file_t *ctfp)
541178479Sjb{
542178479Sjb	return (ctfp ? ctf_getspecific(ctfp) : NULL);
543178479Sjb}
544178479Sjb
545178479Sjbstatic int
546178479Sjbdt_module_load_sect(dtrace_hdl_t *dtp, dt_module_t *dmp, ctf_sect_t *ctsp)
547178479Sjb{
548178479Sjb	const char *s;
549178479Sjb	size_t shstrs;
550178479Sjb	GElf_Shdr sh;
551178479Sjb	Elf_Data *dp;
552178479Sjb	Elf_Scn *sp;
553178479Sjb
554210767Srpaulo	if (elf_getshdrstrndx(dmp->dm_elf, &shstrs) == -1)
555178479Sjb		return (dt_set_errno(dtp, EDT_NOTLOADED));
556178479Sjb
557178479Sjb	for (sp = NULL; (sp = elf_nextscn(dmp->dm_elf, sp)) != NULL; ) {
558178479Sjb		if (gelf_getshdr(sp, &sh) == NULL || sh.sh_type == SHT_NULL ||
559178479Sjb		    (s = elf_strptr(dmp->dm_elf, shstrs, sh.sh_name)) == NULL)
560178479Sjb			continue; /* skip any malformed sections */
561178479Sjb
562178479Sjb		if (sh.sh_type == ctsp->cts_type &&
563178479Sjb		    sh.sh_entsize == ctsp->cts_entsize &&
564178479Sjb		    strcmp(s, ctsp->cts_name) == 0)
565178479Sjb			break; /* section matches specification */
566178479Sjb	}
567178479Sjb
568178479Sjb	/*
569178479Sjb	 * If the section isn't found, return success but leave cts_data set
570178479Sjb	 * to NULL and cts_size set to zero for our caller.
571178479Sjb	 */
572178479Sjb	if (sp == NULL || (dp = elf_getdata(sp, NULL)) == NULL)
573178479Sjb		return (0);
574178479Sjb
575178559Sjb#if defined(sun)
576178479Sjb	ctsp->cts_data = dp->d_buf;
577178559Sjb#else
578178559Sjb	if ((ctsp->cts_data = malloc(dp->d_size)) == NULL)
579178559Sjb		return (0);
580178559Sjb	memcpy(ctsp->cts_data, dp->d_buf, dp->d_size);
581178559Sjb#endif
582178479Sjb	ctsp->cts_size = dp->d_size;
583178479Sjb
584178479Sjb	dt_dprintf("loaded %s [%s] (%lu bytes)\n",
585178479Sjb	    dmp->dm_name, ctsp->cts_name, (ulong_t)ctsp->cts_size);
586178479Sjb
587178479Sjb	return (0);
588178479Sjb}
589178479Sjb
590268578Srpaulotypedef struct dt_module_cb_arg {
591268578Srpaulo	struct ps_prochandle *dpa_proc;
592268578Srpaulo	dtrace_hdl_t *dpa_dtp;
593268578Srpaulo	dt_module_t *dpa_dmp;
594268578Srpaulo	uint_t dpa_count;
595268578Srpaulo} dt_module_cb_arg_t;
596268578Srpaulo
597268578Srpaulo/* ARGSUSED */
598268578Srpaulostatic int
599268578Srpaulodt_module_load_proc_count(void *arg, const prmap_t *prmap, const char *obj)
600268578Srpaulo{
601268578Srpaulo	ctf_file_t *fp;
602268578Srpaulo	dt_module_cb_arg_t *dcp = arg;
603268578Srpaulo
604268578Srpaulo	/* Try to grab a ctf container if it exists */
605268578Srpaulo	fp = Pname_to_ctf(dcp->dpa_proc, obj);
606268578Srpaulo	if (fp != NULL)
607268578Srpaulo		dcp->dpa_count++;
608268578Srpaulo	return (0);
609268578Srpaulo}
610268578Srpaulo
611268578Srpaulo/* ARGSUSED */
612268578Srpaulostatic int
613268578Srpaulodt_module_load_proc_build(void *arg, const prmap_t *prmap, const char *obj)
614268578Srpaulo{
615268578Srpaulo	ctf_file_t *fp;
616268578Srpaulo	char buf[MAXPATHLEN], *p;
617268578Srpaulo	dt_module_cb_arg_t *dcp = arg;
618268578Srpaulo	int count = dcp->dpa_count;
619268578Srpaulo	Lmid_t lmid;
620268578Srpaulo
621268578Srpaulo	fp = Pname_to_ctf(dcp->dpa_proc, obj);
622268578Srpaulo	if (fp == NULL)
623268578Srpaulo		return (0);
624268578Srpaulo	fp = ctf_dup(fp);
625268578Srpaulo	if (fp == NULL)
626268578Srpaulo		return (0);
627268578Srpaulo	dcp->dpa_dmp->dm_libctfp[count] = fp;
628268578Srpaulo	/*
629268578Srpaulo	 * While it'd be nice to simply use objname here, because of our prior
630268578Srpaulo	 * actions we'll always get a resolved object name to its on disk file.
631268578Srpaulo	 * Like the pid provider, we need to tell a bit of a lie here. The type
632268578Srpaulo	 * that the user thinks of is in terms of the libraries they requested,
633268578Srpaulo	 * eg. libc.so.1, they don't care about the fact that it's
634268578Srpaulo	 * libc_hwcap.so.1.
635268578Srpaulo	 */
636268578Srpaulo	(void) Pobjname(dcp->dpa_proc, prmap->pr_vaddr, buf, sizeof (buf));
637268578Srpaulo	if ((p = strrchr(buf, '/')) == NULL)
638268578Srpaulo		p = buf;
639268578Srpaulo	else
640268578Srpaulo		p++;
641268578Srpaulo
642268578Srpaulo	/*
643268578Srpaulo	 * If for some reason we can't find a link map id for this module, which
644268578Srpaulo	 * would be really quite weird. We instead just say the link map id is
645268578Srpaulo	 * zero.
646268578Srpaulo	 */
647268578Srpaulo	if (Plmid(dcp->dpa_proc, prmap->pr_vaddr, &lmid) != 0)
648268578Srpaulo		lmid = 0;
649268578Srpaulo
650268578Srpaulo	if (lmid == 0)
651268578Srpaulo		dcp->dpa_dmp->dm_libctfn[count] = strdup(p);
652268578Srpaulo	else
653268578Srpaulo		(void) asprintf(&dcp->dpa_dmp->dm_libctfn[count],
654268578Srpaulo		    "LM%x`%s", lmid, p);
655268578Srpaulo	if (dcp->dpa_dmp->dm_libctfn[count] == NULL)
656268578Srpaulo		return (1);
657268578Srpaulo	ctf_setspecific(fp, dcp->dpa_dmp);
658268578Srpaulo	dcp->dpa_count++;
659268578Srpaulo	return (0);
660268578Srpaulo}
661268578Srpaulo
662268578Srpaulo/*
663268578Srpaulo * We've been asked to load data that belongs to another process. As such we're
664268578Srpaulo * going to pgrab it at this instant, load everything that we might ever care
665268578Srpaulo * about, and then drive on. The reason for this is that the process that we're
666268578Srpaulo * interested in might be changing. As long as we have grabbed it, then this
667268578Srpaulo * can't be a problem for us.
668268578Srpaulo *
669268578Srpaulo * For now, we're actually going to punt on most things and just try to get CTF
670268578Srpaulo * data, nothing else. Basically this is only useful as a source of type
671268578Srpaulo * information, we can't go and do the stacktrace lookups, etc.
672268578Srpaulo */
673268578Srpaulostatic int
674268578Srpaulodt_module_load_proc(dtrace_hdl_t *dtp, dt_module_t *dmp)
675268578Srpaulo{
676268578Srpaulo	struct ps_prochandle *p;
677268578Srpaulo	dt_module_cb_arg_t arg;
678268578Srpaulo
679268578Srpaulo	/*
680268578Srpaulo	 * Note that on success we do not release this hold. We must hold this
681268578Srpaulo	 * for our life time.
682268578Srpaulo	 */
683268578Srpaulo	p = dt_proc_grab(dtp, dmp->dm_pid, 0, PGRAB_RDONLY | PGRAB_FORCE);
684268578Srpaulo	if (p == NULL) {
685268578Srpaulo		dt_dprintf("failed to grab pid: %d\n", (int)dmp->dm_pid);
686268578Srpaulo		return (dt_set_errno(dtp, EDT_CANTLOAD));
687268578Srpaulo	}
688268578Srpaulo	dt_proc_lock(dtp, p);
689268578Srpaulo
690268578Srpaulo	arg.dpa_proc = p;
691268578Srpaulo	arg.dpa_dtp = dtp;
692268578Srpaulo	arg.dpa_dmp = dmp;
693268578Srpaulo	arg.dpa_count = 0;
694268578Srpaulo	if (Pobject_iter_resolved(p, dt_module_load_proc_count, &arg) != 0) {
695268578Srpaulo		dt_dprintf("failed to iterate objects\n");
696268578Srpaulo		dt_proc_release(dtp, p);
697268578Srpaulo		return (dt_set_errno(dtp, EDT_CANTLOAD));
698268578Srpaulo	}
699268578Srpaulo
700268578Srpaulo	if (arg.dpa_count == 0) {
701268578Srpaulo		dt_dprintf("no ctf data present\n");
702268578Srpaulo		dt_proc_unlock(dtp, p);
703268578Srpaulo		dt_proc_release(dtp, p);
704268578Srpaulo		return (dt_set_errno(dtp, EDT_CANTLOAD));
705268578Srpaulo	}
706268578Srpaulo
707268578Srpaulo	dmp->dm_libctfp = malloc(sizeof (ctf_file_t *) * arg.dpa_count);
708268578Srpaulo	if (dmp->dm_libctfp == NULL) {
709268578Srpaulo		dt_proc_unlock(dtp, p);
710268578Srpaulo		dt_proc_release(dtp, p);
711268578Srpaulo		return (dt_set_errno(dtp, EDT_NOMEM));
712268578Srpaulo	}
713268578Srpaulo	bzero(dmp->dm_libctfp, sizeof (ctf_file_t *) * arg.dpa_count);
714268578Srpaulo
715268578Srpaulo	dmp->dm_libctfn = malloc(sizeof (char *) * arg.dpa_count);
716268578Srpaulo	if (dmp->dm_libctfn == NULL) {
717268578Srpaulo		free(dmp->dm_libctfp);
718268578Srpaulo		dt_proc_unlock(dtp, p);
719268578Srpaulo		dt_proc_release(dtp, p);
720268578Srpaulo		return (dt_set_errno(dtp, EDT_NOMEM));
721268578Srpaulo	}
722268578Srpaulo	bzero(dmp->dm_libctfn, sizeof (char *) * arg.dpa_count);
723268578Srpaulo
724268578Srpaulo	dmp->dm_nctflibs = arg.dpa_count;
725268578Srpaulo
726268578Srpaulo	arg.dpa_count = 0;
727268578Srpaulo	if (Pobject_iter_resolved(p, dt_module_load_proc_build, &arg) != 0) {
728268578Srpaulo		dt_proc_unlock(dtp, p);
729268578Srpaulo		dt_module_unload(dtp, dmp);
730268578Srpaulo		dt_proc_release(dtp, p);
731268578Srpaulo		return (dt_set_errno(dtp, EDT_CANTLOAD));
732268578Srpaulo	}
733268578Srpaulo	assert(arg.dpa_count == dmp->dm_nctflibs);
734268578Srpaulo	dt_dprintf("loaded %d ctf modules for pid %d\n", arg.dpa_count,
735268578Srpaulo	    (int)dmp->dm_pid);
736268578Srpaulo
737268578Srpaulo	dt_proc_unlock(dtp, p);
738268578Srpaulo	dt_proc_release(dtp, p);
739268578Srpaulo	dmp->dm_flags |= DT_DM_LOADED;
740268578Srpaulo
741268578Srpaulo	return (0);
742268578Srpaulo}
743268578Srpaulo
744178479Sjbint
745178479Sjbdt_module_load(dtrace_hdl_t *dtp, dt_module_t *dmp)
746178479Sjb{
747178479Sjb	if (dmp->dm_flags & DT_DM_LOADED)
748178479Sjb		return (0); /* module is already loaded */
749178479Sjb
750268578Srpaulo	if (dmp->dm_pid != 0)
751268578Srpaulo		return (dt_module_load_proc(dtp, dmp));
752268578Srpaulo
753178479Sjb	dmp->dm_ctdata.cts_name = ".SUNW_ctf";
754178479Sjb	dmp->dm_ctdata.cts_type = SHT_PROGBITS;
755178479Sjb	dmp->dm_ctdata.cts_flags = 0;
756178479Sjb	dmp->dm_ctdata.cts_data = NULL;
757178479Sjb	dmp->dm_ctdata.cts_size = 0;
758178479Sjb	dmp->dm_ctdata.cts_entsize = 0;
759178479Sjb	dmp->dm_ctdata.cts_offset = 0;
760178479Sjb
761178479Sjb	dmp->dm_symtab.cts_name = ".symtab";
762178479Sjb	dmp->dm_symtab.cts_type = SHT_SYMTAB;
763178479Sjb	dmp->dm_symtab.cts_flags = 0;
764178479Sjb	dmp->dm_symtab.cts_data = NULL;
765178479Sjb	dmp->dm_symtab.cts_size = 0;
766178479Sjb	dmp->dm_symtab.cts_entsize = dmp->dm_ops == &dt_modops_64 ?
767178479Sjb	    sizeof (Elf64_Sym) : sizeof (Elf32_Sym);
768178479Sjb	dmp->dm_symtab.cts_offset = 0;
769178479Sjb
770178479Sjb	dmp->dm_strtab.cts_name = ".strtab";
771178479Sjb	dmp->dm_strtab.cts_type = SHT_STRTAB;
772178479Sjb	dmp->dm_strtab.cts_flags = 0;
773178479Sjb	dmp->dm_strtab.cts_data = NULL;
774178479Sjb	dmp->dm_strtab.cts_size = 0;
775178479Sjb	dmp->dm_strtab.cts_entsize = 0;
776178479Sjb	dmp->dm_strtab.cts_offset = 0;
777178479Sjb
778178479Sjb	/*
779178479Sjb	 * Attempt to load the module's CTF section, symbol table section, and
780178479Sjb	 * string table section.  Note that modules may not contain CTF data:
781178479Sjb	 * this will result in a successful load_sect but data of size zero.
782178479Sjb	 * We will then fail if dt_module_getctf() is called, as shown below.
783178479Sjb	 */
784178479Sjb	if (dt_module_load_sect(dtp, dmp, &dmp->dm_ctdata) == -1 ||
785178479Sjb	    dt_module_load_sect(dtp, dmp, &dmp->dm_symtab) == -1 ||
786178479Sjb	    dt_module_load_sect(dtp, dmp, &dmp->dm_strtab) == -1) {
787178479Sjb		dt_module_unload(dtp, dmp);
788178479Sjb		return (-1); /* dt_errno is set for us */
789178479Sjb	}
790178479Sjb
791178479Sjb	/*
792178479Sjb	 * Allocate the hash chains and hash buckets for symbol name lookup.
793178479Sjb	 * This is relatively simple since the symbol table is of fixed size
794178479Sjb	 * and is known in advance.  We allocate one extra element since we
795178479Sjb	 * use element indices instead of pointers and zero is our sentinel.
796178479Sjb	 */
797178479Sjb	dmp->dm_nsymelems =
798178479Sjb	    dmp->dm_symtab.cts_size / dmp->dm_symtab.cts_entsize;
799178479Sjb
800178479Sjb	dmp->dm_nsymbuckets = _dtrace_strbuckets;
801178479Sjb	dmp->dm_symfree = 1;		/* first free element is index 1 */
802178479Sjb
803178479Sjb	dmp->dm_symbuckets = malloc(sizeof (uint_t) * dmp->dm_nsymbuckets);
804178479Sjb	dmp->dm_symchains = malloc(sizeof (dt_sym_t) * dmp->dm_nsymelems + 1);
805178479Sjb
806178479Sjb	if (dmp->dm_symbuckets == NULL || dmp->dm_symchains == NULL) {
807178479Sjb		dt_module_unload(dtp, dmp);
808178479Sjb		return (dt_set_errno(dtp, EDT_NOMEM));
809178479Sjb	}
810178479Sjb
811178479Sjb	bzero(dmp->dm_symbuckets, sizeof (uint_t) * dmp->dm_nsymbuckets);
812178479Sjb	bzero(dmp->dm_symchains, sizeof (dt_sym_t) * dmp->dm_nsymelems + 1);
813178479Sjb
814178479Sjb	/*
815178479Sjb	 * Iterate over the symbol table data buffer and insert each symbol
816178479Sjb	 * name into the name hash if the name and type are valid.  Then
817178479Sjb	 * allocate the address map, fill it in, and sort it.
818178479Sjb	 */
819178479Sjb	dmp->dm_asrsv = dmp->dm_ops->do_syminit(dmp);
820178479Sjb
821178479Sjb	dt_dprintf("hashed %s [%s] (%u symbols)\n",
822178479Sjb	    dmp->dm_name, dmp->dm_symtab.cts_name, dmp->dm_symfree - 1);
823178479Sjb
824178479Sjb	if ((dmp->dm_asmap = malloc(sizeof (void *) * dmp->dm_asrsv)) == NULL) {
825178479Sjb		dt_module_unload(dtp, dmp);
826178479Sjb		return (dt_set_errno(dtp, EDT_NOMEM));
827178479Sjb	}
828178479Sjb
829178479Sjb	dmp->dm_ops->do_symsort(dmp);
830178479Sjb
831178479Sjb	dt_dprintf("sorted %s [%s] (%u symbols)\n",
832178479Sjb	    dmp->dm_name, dmp->dm_symtab.cts_name, dmp->dm_aslen);
833178479Sjb
834178479Sjb	dmp->dm_flags |= DT_DM_LOADED;
835178479Sjb	return (0);
836178479Sjb}
837178479Sjb
838268578Srpauloint
839268578Srpaulodt_module_hasctf(dtrace_hdl_t *dtp, dt_module_t *dmp)
840268578Srpaulo{
841268578Srpaulo	if (dmp->dm_pid != 0 && dmp->dm_nctflibs > 0)
842268578Srpaulo		return (1);
843268578Srpaulo	return (dt_module_getctf(dtp, dmp) != NULL);
844268578Srpaulo}
845268578Srpaulo
846178479Sjbctf_file_t *
847178479Sjbdt_module_getctf(dtrace_hdl_t *dtp, dt_module_t *dmp)
848178479Sjb{
849178479Sjb	const char *parent;
850178479Sjb	dt_module_t *pmp;
851178479Sjb	ctf_file_t *pfp;
852178479Sjb	int model;
853178479Sjb
854178479Sjb	if (dmp->dm_ctfp != NULL || dt_module_load(dtp, dmp) != 0)
855178479Sjb		return (dmp->dm_ctfp);
856178479Sjb
857178479Sjb	if (dmp->dm_ops == &dt_modops_64)
858178479Sjb		model = CTF_MODEL_LP64;
859178479Sjb	else
860178479Sjb		model = CTF_MODEL_ILP32;
861178479Sjb
862178479Sjb	/*
863178479Sjb	 * If the data model of the module does not match our program data
864178479Sjb	 * model, then do not permit CTF from this module to be opened and
865178479Sjb	 * returned to the compiler.  If we support mixed data models in the
866178479Sjb	 * future for combined kernel/user tracing, this can be removed.
867178479Sjb	 */
868178479Sjb	if (dtp->dt_conf.dtc_ctfmodel != model) {
869178479Sjb		(void) dt_set_errno(dtp, EDT_DATAMODEL);
870178479Sjb		return (NULL);
871178479Sjb	}
872178479Sjb
873178479Sjb	if (dmp->dm_ctdata.cts_size == 0) {
874178479Sjb		(void) dt_set_errno(dtp, EDT_NOCTF);
875178479Sjb		return (NULL);
876178479Sjb	}
877178479Sjb
878178479Sjb	dmp->dm_ctfp = ctf_bufopen(&dmp->dm_ctdata,
879178479Sjb	    &dmp->dm_symtab, &dmp->dm_strtab, &dtp->dt_ctferr);
880178479Sjb
881178479Sjb	if (dmp->dm_ctfp == NULL) {
882178479Sjb		(void) dt_set_errno(dtp, EDT_CTF);
883178479Sjb		return (NULL);
884178479Sjb	}
885178479Sjb
886178479Sjb	(void) ctf_setmodel(dmp->dm_ctfp, model);
887178479Sjb	ctf_setspecific(dmp->dm_ctfp, dmp);
888178479Sjb
889178479Sjb	if ((parent = ctf_parent_name(dmp->dm_ctfp)) != NULL) {
890178479Sjb		if ((pmp = dt_module_create(dtp, parent)) == NULL ||
891178479Sjb		    (pfp = dt_module_getctf(dtp, pmp)) == NULL) {
892178479Sjb			if (pmp == NULL)
893178479Sjb				(void) dt_set_errno(dtp, EDT_NOMEM);
894178479Sjb			goto err;
895178479Sjb		}
896178479Sjb
897178479Sjb		if (ctf_import(dmp->dm_ctfp, pfp) == CTF_ERR) {
898178479Sjb			dtp->dt_ctferr = ctf_errno(dmp->dm_ctfp);
899178479Sjb			(void) dt_set_errno(dtp, EDT_CTF);
900178479Sjb			goto err;
901178479Sjb		}
902178479Sjb	}
903178479Sjb
904178479Sjb	dt_dprintf("loaded CTF container for %s (%p)\n",
905178479Sjb	    dmp->dm_name, (void *)dmp->dm_ctfp);
906178479Sjb
907178479Sjb	return (dmp->dm_ctfp);
908178479Sjb
909178479Sjberr:
910178479Sjb	ctf_close(dmp->dm_ctfp);
911178479Sjb	dmp->dm_ctfp = NULL;
912178479Sjb	return (NULL);
913178479Sjb}
914178479Sjb
915178479Sjb/*ARGSUSED*/
916178479Sjbvoid
917178479Sjbdt_module_unload(dtrace_hdl_t *dtp, dt_module_t *dmp)
918178479Sjb{
919268578Srpaulo	int i;
920268578Srpaulo
921178479Sjb	ctf_close(dmp->dm_ctfp);
922178479Sjb	dmp->dm_ctfp = NULL;
923178479Sjb
924178559Sjb#if !defined(sun)
925178559Sjb	if (dmp->dm_ctdata.cts_data != NULL) {
926178559Sjb		free(dmp->dm_ctdata.cts_data);
927178559Sjb	}
928178559Sjb	if (dmp->dm_symtab.cts_data != NULL) {
929178559Sjb		free(dmp->dm_symtab.cts_data);
930178559Sjb	}
931178559Sjb	if (dmp->dm_strtab.cts_data != NULL) {
932178559Sjb		free(dmp->dm_strtab.cts_data);
933178559Sjb	}
934178559Sjb#endif
935178559Sjb
936268578Srpaulo	if (dmp->dm_libctfp != NULL) {
937268578Srpaulo		for (i = 0; i < dmp->dm_nctflibs; i++) {
938268578Srpaulo			ctf_close(dmp->dm_libctfp[i]);
939268578Srpaulo			free(dmp->dm_libctfn[i]);
940268578Srpaulo		}
941268578Srpaulo		free(dmp->dm_libctfp);
942268578Srpaulo		free(dmp->dm_libctfn);
943268578Srpaulo		dmp->dm_libctfp = NULL;
944268578Srpaulo		dmp->dm_nctflibs = 0;
945268578Srpaulo	}
946268578Srpaulo
947178479Sjb	bzero(&dmp->dm_ctdata, sizeof (ctf_sect_t));
948178479Sjb	bzero(&dmp->dm_symtab, sizeof (ctf_sect_t));
949178479Sjb	bzero(&dmp->dm_strtab, sizeof (ctf_sect_t));
950178479Sjb
951178479Sjb	if (dmp->dm_symbuckets != NULL) {
952178479Sjb		free(dmp->dm_symbuckets);
953178479Sjb		dmp->dm_symbuckets = NULL;
954178479Sjb	}
955178479Sjb
956178479Sjb	if (dmp->dm_symchains != NULL) {
957178479Sjb		free(dmp->dm_symchains);
958178479Sjb		dmp->dm_symchains = NULL;
959178479Sjb	}
960178479Sjb
961178479Sjb	if (dmp->dm_asmap != NULL) {
962178479Sjb		free(dmp->dm_asmap);
963178479Sjb		dmp->dm_asmap = NULL;
964178479Sjb	}
965210425Savg#if defined(__FreeBSD__)
966210425Savg	if (dmp->dm_sec_offsets != NULL) {
967210425Savg		free(dmp->dm_sec_offsets);
968210425Savg		dmp->dm_sec_offsets = NULL;
969210425Savg	}
970210425Savg#endif
971178479Sjb	dmp->dm_symfree = 0;
972178479Sjb	dmp->dm_nsymbuckets = 0;
973178479Sjb	dmp->dm_nsymelems = 0;
974178479Sjb	dmp->dm_asrsv = 0;
975178479Sjb	dmp->dm_aslen = 0;
976178479Sjb
977178559Sjb	dmp->dm_text_va = 0;
978178479Sjb	dmp->dm_text_size = 0;
979178559Sjb	dmp->dm_data_va = 0;
980178479Sjb	dmp->dm_data_size = 0;
981178559Sjb	dmp->dm_bss_va = 0;
982178479Sjb	dmp->dm_bss_size = 0;
983178479Sjb
984178479Sjb	if (dmp->dm_extern != NULL) {
985178479Sjb		dt_idhash_destroy(dmp->dm_extern);
986178479Sjb		dmp->dm_extern = NULL;
987178479Sjb	}
988178479Sjb
989178479Sjb	(void) elf_end(dmp->dm_elf);
990178479Sjb	dmp->dm_elf = NULL;
991178479Sjb
992268578Srpaulo	dmp->dm_pid = 0;
993268578Srpaulo
994178479Sjb	dmp->dm_flags &= ~DT_DM_LOADED;
995178479Sjb}
996178479Sjb
997178479Sjbvoid
998178479Sjbdt_module_destroy(dtrace_hdl_t *dtp, dt_module_t *dmp)
999178479Sjb{
1000210767Srpaulo	uint_t h = dt_strtab_hash(dmp->dm_name, NULL) % dtp->dt_modbuckets;
1001210767Srpaulo	dt_module_t **dmpp = &dtp->dt_mods[h];
1002210767Srpaulo
1003178479Sjb	dt_list_delete(&dtp->dt_modlist, dmp);
1004178479Sjb	assert(dtp->dt_nmods != 0);
1005178479Sjb	dtp->dt_nmods--;
1006178479Sjb
1007210767Srpaulo	/*
1008210767Srpaulo	 * Now remove this module from its hash chain.  We expect to always
1009210767Srpaulo	 * find the module on its hash chain, so in this loop we assert that
1010210767Srpaulo	 * we don't run off the end of the list.
1011210767Srpaulo	 */
1012210767Srpaulo	while (*dmpp != dmp) {
1013210767Srpaulo		dmpp = &((*dmpp)->dm_next);
1014210767Srpaulo		assert(*dmpp != NULL);
1015210767Srpaulo	}
1016210767Srpaulo
1017210767Srpaulo	*dmpp = dmp->dm_next;
1018210767Srpaulo
1019178479Sjb	dt_module_unload(dtp, dmp);
1020178479Sjb	free(dmp);
1021178479Sjb}
1022178479Sjb
1023178479Sjb/*
1024178479Sjb * Insert a new external symbol reference into the specified module.  The new
1025178479Sjb * symbol will be marked as undefined and is assigned a symbol index beyond
1026178479Sjb * any existing cached symbols from this module.  We use the ident's di_data
1027178479Sjb * field to store a pointer to a copy of the dtrace_syminfo_t for this symbol.
1028178479Sjb */
1029178479Sjbdt_ident_t *
1030178479Sjbdt_module_extern(dtrace_hdl_t *dtp, dt_module_t *dmp,
1031178479Sjb    const char *name, const dtrace_typeinfo_t *tip)
1032178479Sjb{
1033178479Sjb	dtrace_syminfo_t *sip;
1034178479Sjb	dt_ident_t *idp;
1035178479Sjb	uint_t id;
1036178479Sjb
1037178479Sjb	if (dmp->dm_extern == NULL && (dmp->dm_extern = dt_idhash_create(
1038178479Sjb	    "extern", NULL, dmp->dm_nsymelems, UINT_MAX)) == NULL) {
1039178479Sjb		(void) dt_set_errno(dtp, EDT_NOMEM);
1040178479Sjb		return (NULL);
1041178479Sjb	}
1042178479Sjb
1043178479Sjb	if (dt_idhash_nextid(dmp->dm_extern, &id) == -1) {
1044178479Sjb		(void) dt_set_errno(dtp, EDT_SYMOFLOW);
1045178479Sjb		return (NULL);
1046178479Sjb	}
1047178479Sjb
1048178479Sjb	if ((sip = malloc(sizeof (dtrace_syminfo_t))) == NULL) {
1049178479Sjb		(void) dt_set_errno(dtp, EDT_NOMEM);
1050178479Sjb		return (NULL);
1051178479Sjb	}
1052178479Sjb
1053178479Sjb	idp = dt_idhash_insert(dmp->dm_extern, name, DT_IDENT_SYMBOL, 0, id,
1054178479Sjb	    _dtrace_symattr, 0, &dt_idops_thaw, NULL, dtp->dt_gen);
1055178479Sjb
1056178479Sjb	if (idp == NULL) {
1057178479Sjb		(void) dt_set_errno(dtp, EDT_NOMEM);
1058178479Sjb		free(sip);
1059178479Sjb		return (NULL);
1060178479Sjb	}
1061178479Sjb
1062178479Sjb	sip->dts_object = dmp->dm_name;
1063178479Sjb	sip->dts_name = idp->di_name;
1064178479Sjb	sip->dts_id = idp->di_id;
1065178479Sjb
1066178479Sjb	idp->di_data = sip;
1067178479Sjb	idp->di_ctfp = tip->dtt_ctfp;
1068178479Sjb	idp->di_type = tip->dtt_type;
1069178479Sjb
1070178479Sjb	return (idp);
1071178479Sjb}
1072178479Sjb
1073178479Sjbconst char *
1074178479Sjbdt_module_modelname(dt_module_t *dmp)
1075178479Sjb{
1076178479Sjb	if (dmp->dm_ops == &dt_modops_64)
1077178479Sjb		return ("64-bit");
1078178479Sjb	else
1079178479Sjb		return ("32-bit");
1080178479Sjb}
1081178479Sjb
1082268578Srpaulo/* ARGSUSED */
1083268578Srpauloint
1084268578Srpaulodt_module_getlibid(dtrace_hdl_t *dtp, dt_module_t *dmp, const ctf_file_t *fp)
1085268578Srpaulo{
1086268578Srpaulo	int i;
1087268578Srpaulo
1088268578Srpaulo	for (i = 0; i < dmp->dm_nctflibs; i++) {
1089268578Srpaulo		if (dmp->dm_libctfp[i] == fp)
1090268578Srpaulo			return (i);
1091268578Srpaulo	}
1092268578Srpaulo
1093268578Srpaulo	return (-1);
1094268578Srpaulo}
1095268578Srpaulo
1096268578Srpaulo/* ARGSUSED */
1097268578Srpauloctf_file_t *
1098268578Srpaulodt_module_getctflib(dtrace_hdl_t *dtp, dt_module_t *dmp, const char *name)
1099268578Srpaulo{
1100268578Srpaulo	int i;
1101268578Srpaulo
1102268578Srpaulo	for (i = 0; i < dmp->dm_nctflibs; i++) {
1103268578Srpaulo		if (strcmp(dmp->dm_libctfn[i], name) == 0)
1104268578Srpaulo			return (dmp->dm_libctfp[i]);
1105268578Srpaulo	}
1106268578Srpaulo
1107268578Srpaulo	return (NULL);
1108268578Srpaulo}
1109268578Srpaulo
1110178479Sjb/*
1111178479Sjb * Update our module cache by adding an entry for the specified module 'name'.
1112178479Sjb * We create the dt_module_t and populate it using /system/object/<name>/.
1113178559Sjb *
1114178559Sjb * On FreeBSD, the module name is passed as the full module file name,
1115178559Sjb * including the path.
1116178479Sjb */
1117178479Sjbstatic void
1118178559Sjb#if defined(sun)
1119178479Sjbdt_module_update(dtrace_hdl_t *dtp, const char *name)
1120178559Sjb#else
1121178559Sjbdt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat)
1122178559Sjb#endif
1123178479Sjb{
1124178479Sjb	char fname[MAXPATHLEN];
1125178479Sjb	struct stat64 st;
1126178479Sjb	int fd, err, bits;
1127178479Sjb
1128178479Sjb	dt_module_t *dmp;
1129178479Sjb	const char *s;
1130178479Sjb	size_t shstrs;
1131178479Sjb	GElf_Shdr sh;
1132178479Sjb	Elf_Data *dp;
1133178479Sjb	Elf_Scn *sp;
1134178479Sjb
1135178559Sjb#if defined(sun)
1136178479Sjb	(void) snprintf(fname, sizeof (fname),
1137178479Sjb	    "%s/%s/object", OBJFS_ROOT, name);
1138178559Sjb#else
1139210425Savg	GElf_Ehdr ehdr;
1140178559Sjb	GElf_Phdr ph;
1141178559Sjb	char name[MAXPATHLEN];
1142210425Savg	uintptr_t mapbase, alignmask;
1143178559Sjb	int i = 0;
1144210425Savg	int is_elf_obj;
1145178479Sjb
1146178559Sjb	(void) strlcpy(name, k_stat->name, sizeof(name));
1147178559Sjb	(void) strlcpy(fname, k_stat->pathname, sizeof(fname));
1148178559Sjb#endif
1149178559Sjb
1150178479Sjb	if ((fd = open(fname, O_RDONLY)) == -1 || fstat64(fd, &st) == -1 ||
1151178479Sjb	    (dmp = dt_module_create(dtp, name)) == NULL) {
1152178479Sjb		dt_dprintf("failed to open %s: %s\n", fname, strerror(errno));
1153178479Sjb		(void) close(fd);
1154178479Sjb		return;
1155178479Sjb	}
1156178479Sjb
1157178479Sjb	/*
1158178479Sjb	 * Since the module can unload out from under us (and /system/object
1159178479Sjb	 * will return ENOENT), tell libelf to cook the entire file now and
1160178479Sjb	 * then close the underlying file descriptor immediately.  If this
1161178479Sjb	 * succeeds, we know that we can continue safely using dmp->dm_elf.
1162178479Sjb	 */
1163178479Sjb	dmp->dm_elf = elf_begin(fd, ELF_C_READ, NULL);
1164178479Sjb	err = elf_cntl(dmp->dm_elf, ELF_C_FDREAD);
1165178479Sjb	(void) close(fd);
1166178479Sjb
1167178479Sjb	if (dmp->dm_elf == NULL || err == -1 ||
1168210767Srpaulo	    elf_getshdrstrndx(dmp->dm_elf, &shstrs) == -1) {
1169178479Sjb		dt_dprintf("failed to load %s: %s\n",
1170178479Sjb		    fname, elf_errmsg(elf_errno()));
1171178479Sjb		dt_module_destroy(dtp, dmp);
1172178479Sjb		return;
1173178479Sjb	}
1174178479Sjb
1175178479Sjb	switch (gelf_getclass(dmp->dm_elf)) {
1176178479Sjb	case ELFCLASS32:
1177178479Sjb		dmp->dm_ops = &dt_modops_32;
1178178479Sjb		bits = 32;
1179178479Sjb		break;
1180178479Sjb	case ELFCLASS64:
1181178479Sjb		dmp->dm_ops = &dt_modops_64;
1182178479Sjb		bits = 64;
1183178479Sjb		break;
1184178479Sjb	default:
1185178479Sjb		dt_dprintf("failed to load %s: unknown ELF class\n", fname);
1186178479Sjb		dt_module_destroy(dtp, dmp);
1187178479Sjb		return;
1188178479Sjb	}
1189210425Savg#if defined(__FreeBSD__)
1190210425Savg	mapbase = (uintptr_t)k_stat->address;
1191210425Savg	gelf_getehdr(dmp->dm_elf, &ehdr);
1192210425Savg	is_elf_obj = (ehdr.e_type == ET_REL);
1193210425Savg	if (is_elf_obj) {
1194210425Savg		dmp->dm_sec_offsets =
1195210425Savg		    malloc(ehdr.e_shnum * sizeof(*dmp->dm_sec_offsets));
1196210425Savg		if (dmp->dm_sec_offsets == NULL) {
1197210425Savg			dt_dprintf("failed to allocate memory\n");
1198210425Savg			dt_module_destroy(dtp, dmp);
1199210425Savg			return;
1200210425Savg		}
1201210425Savg	}
1202210425Savg#endif
1203178479Sjb	/*
1204178479Sjb	 * Iterate over the section headers locating various sections of
1205178479Sjb	 * interest and use their attributes to flesh out the dt_module_t.
1206178479Sjb	 */
1207178479Sjb	for (sp = NULL; (sp = elf_nextscn(dmp->dm_elf, sp)) != NULL; ) {
1208178479Sjb		if (gelf_getshdr(sp, &sh) == NULL || sh.sh_type == SHT_NULL ||
1209178479Sjb		    (s = elf_strptr(dmp->dm_elf, shstrs, sh.sh_name)) == NULL)
1210178479Sjb			continue; /* skip any malformed sections */
1211210425Savg#if defined(__FreeBSD__)
1212210425Savg		if (sh.sh_size == 0)
1213210425Savg			continue;
1214276265Smarkj		if (sh.sh_type == SHT_PROGBITS || sh.sh_type == SHT_NOBITS) {
1215210425Savg			alignmask = sh.sh_addralign - 1;
1216210425Savg			mapbase += alignmask;
1217210425Savg			mapbase &= ~alignmask;
1218210425Savg			sh.sh_addr = mapbase;
1219276265Smarkj			if (is_elf_obj)
1220276265Smarkj				dmp->dm_sec_offsets[elf_ndxscn(sp)] = sh.sh_addr;
1221210425Savg			mapbase += sh.sh_size;
1222210425Savg		}
1223210425Savg#endif
1224178479Sjb		if (strcmp(s, ".text") == 0) {
1225178479Sjb			dmp->dm_text_size = sh.sh_size;
1226178479Sjb			dmp->dm_text_va = sh.sh_addr;
1227178479Sjb		} else if (strcmp(s, ".data") == 0) {
1228178479Sjb			dmp->dm_data_size = sh.sh_size;
1229178479Sjb			dmp->dm_data_va = sh.sh_addr;
1230178479Sjb		} else if (strcmp(s, ".bss") == 0) {
1231178479Sjb			dmp->dm_bss_size = sh.sh_size;
1232178479Sjb			dmp->dm_bss_va = sh.sh_addr;
1233178479Sjb		} else if (strcmp(s, ".info") == 0 &&
1234178479Sjb		    (dp = elf_getdata(sp, NULL)) != NULL) {
1235178479Sjb			bcopy(dp->d_buf, &dmp->dm_info,
1236178479Sjb			    MIN(sh.sh_size, sizeof (dmp->dm_info)));
1237178479Sjb		} else if (strcmp(s, ".filename") == 0 &&
1238178479Sjb		    (dp = elf_getdata(sp, NULL)) != NULL) {
1239178479Sjb			(void) strlcpy(dmp->dm_file,
1240178479Sjb			    dp->d_buf, sizeof (dmp->dm_file));
1241178479Sjb		}
1242178479Sjb	}
1243178479Sjb
1244178479Sjb	dmp->dm_flags |= DT_DM_KERNEL;
1245178559Sjb#if defined(sun)
1246178479Sjb	dmp->dm_modid = (int)OBJFS_MODID(st.st_ino);
1247178559Sjb#else
1248210425Savg	/*
1249210425Savg	 * Include .rodata and special sections into .text.
1250210425Savg	 * This depends on default section layout produced by GNU ld
1251210425Savg	 * for ELF objects and libraries:
1252210425Savg	 * [Text][R/O data][R/W data][Dynamic][BSS][Non loadable]
1253210425Savg	 */
1254210425Savg	dmp->dm_text_size = dmp->dm_data_va - dmp->dm_text_va;
1255178559Sjb#if defined(__i386__)
1256178559Sjb	/*
1257178559Sjb	 * Find the first load section and figure out the relocation
1258178559Sjb	 * offset for the symbols. The kernel module will not need
1259178559Sjb	 * relocation, but the kernel linker modules will.
1260178559Sjb	 */
1261178559Sjb	for (i = 0; gelf_getphdr(dmp->dm_elf, i, &ph) != NULL; i++) {
1262178559Sjb		if (ph.p_type == PT_LOAD) {
1263178559Sjb			dmp->dm_reloc_offset = k_stat->address - ph.p_vaddr;
1264178559Sjb			break;
1265178559Sjb		}
1266178559Sjb	}
1267178559Sjb#endif
1268178559Sjb#endif
1269178479Sjb
1270178479Sjb	if (dmp->dm_info.objfs_info_primary)
1271178479Sjb		dmp->dm_flags |= DT_DM_PRIMARY;
1272178479Sjb
1273178479Sjb	dt_dprintf("opened %d-bit module %s (%s) [%d]\n",
1274178479Sjb	    bits, dmp->dm_name, dmp->dm_file, dmp->dm_modid);
1275178479Sjb}
1276178479Sjb
1277178479Sjb/*
1278178479Sjb * Unload all the loaded modules and then refresh the module cache with the
1279178479Sjb * latest list of loaded modules and their address ranges.
1280178479Sjb */
1281178479Sjbvoid
1282178479Sjbdtrace_update(dtrace_hdl_t *dtp)
1283178479Sjb{
1284178479Sjb	dt_module_t *dmp;
1285178479Sjb	DIR *dirp;
1286178559Sjb#if defined(__FreeBSD__)
1287178559Sjb	int fileid;
1288178559Sjb#endif
1289178479Sjb
1290178479Sjb	for (dmp = dt_list_next(&dtp->dt_modlist);
1291178479Sjb	    dmp != NULL; dmp = dt_list_next(dmp))
1292178479Sjb		dt_module_unload(dtp, dmp);
1293178479Sjb
1294178559Sjb#if defined(sun)
1295178479Sjb	/*
1296178479Sjb	 * Open /system/object and attempt to create a libdtrace module for
1297178479Sjb	 * each kernel module that is loaded on the current system.
1298178479Sjb	 */
1299178479Sjb	if (!(dtp->dt_oflags & DTRACE_O_NOSYS) &&
1300178479Sjb	    (dirp = opendir(OBJFS_ROOT)) != NULL) {
1301178479Sjb		struct dirent *dp;
1302178479Sjb
1303178479Sjb		while ((dp = readdir(dirp)) != NULL) {
1304178479Sjb			if (dp->d_name[0] != '.')
1305178479Sjb				dt_module_update(dtp, dp->d_name);
1306178479Sjb		}
1307178479Sjb
1308178479Sjb		(void) closedir(dirp);
1309178479Sjb	}
1310178559Sjb#elif defined(__FreeBSD__)
1311178559Sjb	/*
1312178559Sjb	 * Use FreeBSD's kernel loader interface to discover what kernel
1313178559Sjb	 * modules are loaded and create a libdtrace module for each one.
1314178559Sjb	 */
1315178559Sjb	for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) {
1316178559Sjb		struct kld_file_stat k_stat;
1317178559Sjb		k_stat.version = sizeof(k_stat);
1318178559Sjb		if (kldstat(fileid, &k_stat) == 0)
1319178559Sjb			dt_module_update(dtp, &k_stat);
1320178559Sjb	}
1321178559Sjb#endif
1322178479Sjb
1323178479Sjb	/*
1324178479Sjb	 * Look up all the macro identifiers and set di_id to the latest value.
1325178479Sjb	 * This code collaborates with dt_lex.l on the use of di_id.  We will
1326178479Sjb	 * need to implement something fancier if we need to support non-ints.
1327178479Sjb	 */
1328178479Sjb	dt_idhash_lookup(dtp->dt_macros, "egid")->di_id = getegid();
1329178479Sjb	dt_idhash_lookup(dtp->dt_macros, "euid")->di_id = geteuid();
1330178479Sjb	dt_idhash_lookup(dtp->dt_macros, "gid")->di_id = getgid();
1331178479Sjb	dt_idhash_lookup(dtp->dt_macros, "pid")->di_id = getpid();
1332178479Sjb	dt_idhash_lookup(dtp->dt_macros, "pgid")->di_id = getpgid(0);
1333178479Sjb	dt_idhash_lookup(dtp->dt_macros, "ppid")->di_id = getppid();
1334178559Sjb#if defined(sun)
1335178479Sjb	dt_idhash_lookup(dtp->dt_macros, "projid")->di_id = getprojid();
1336178559Sjb#endif
1337178479Sjb	dt_idhash_lookup(dtp->dt_macros, "sid")->di_id = getsid(0);
1338178559Sjb#if defined(sun)
1339178479Sjb	dt_idhash_lookup(dtp->dt_macros, "taskid")->di_id = gettaskid();
1340178559Sjb#endif
1341178479Sjb	dt_idhash_lookup(dtp->dt_macros, "uid")->di_id = getuid();
1342178479Sjb
1343178479Sjb	/*
1344178479Sjb	 * Cache the pointers to the modules representing the base executable
1345178479Sjb	 * and the run-time linker in the dtrace client handle. Note that on
1346178479Sjb	 * x86 krtld is folded into unix, so if we don't find it, use unix
1347178479Sjb	 * instead.
1348178479Sjb	 */
1349178479Sjb	dtp->dt_exec = dt_module_lookup_by_name(dtp, "genunix");
1350178479Sjb	dtp->dt_rtld = dt_module_lookup_by_name(dtp, "krtld");
1351178479Sjb	if (dtp->dt_rtld == NULL)
1352178479Sjb		dtp->dt_rtld = dt_module_lookup_by_name(dtp, "unix");
1353178479Sjb
1354178479Sjb	/*
1355178479Sjb	 * If this is the first time we are initializing the module list,
1356178479Sjb	 * remove the module for genunix from the module list and then move it
1357178479Sjb	 * to the front of the module list.  We do this so that type and symbol
1358178479Sjb	 * queries encounter genunix and thereby optimize for the common case
1359178479Sjb	 * in dtrace_lookup_by_name() and dtrace_lookup_by_type(), below.
1360178479Sjb	 */
1361178479Sjb	if (dtp->dt_exec != NULL &&
1362178479Sjb	    dtp->dt_cdefs == NULL && dtp->dt_ddefs == NULL) {
1363178479Sjb		dt_list_delete(&dtp->dt_modlist, dtp->dt_exec);
1364178479Sjb		dt_list_prepend(&dtp->dt_modlist, dtp->dt_exec);
1365178479Sjb	}
1366178479Sjb}
1367178479Sjb
1368178479Sjbstatic dt_module_t *
1369178479Sjbdt_module_from_object(dtrace_hdl_t *dtp, const char *object)
1370178479Sjb{
1371178479Sjb	int err = EDT_NOMOD;
1372178479Sjb	dt_module_t *dmp;
1373178479Sjb
1374178479Sjb	switch ((uintptr_t)object) {
1375178479Sjb	case (uintptr_t)DTRACE_OBJ_EXEC:
1376178479Sjb		dmp = dtp->dt_exec;
1377178479Sjb		break;
1378178479Sjb	case (uintptr_t)DTRACE_OBJ_RTLD:
1379178479Sjb		dmp = dtp->dt_rtld;
1380178479Sjb		break;
1381178479Sjb	case (uintptr_t)DTRACE_OBJ_CDEFS:
1382178479Sjb		dmp = dtp->dt_cdefs;
1383178479Sjb		break;
1384178479Sjb	case (uintptr_t)DTRACE_OBJ_DDEFS:
1385178479Sjb		dmp = dtp->dt_ddefs;
1386178479Sjb		break;
1387178479Sjb	default:
1388178479Sjb		dmp = dt_module_create(dtp, object);
1389178479Sjb		err = EDT_NOMEM;
1390178479Sjb	}
1391178479Sjb
1392178479Sjb	if (dmp == NULL)
1393178479Sjb		(void) dt_set_errno(dtp, err);
1394178479Sjb
1395178479Sjb	return (dmp);
1396178479Sjb}
1397178479Sjb
1398178479Sjb/*
1399178479Sjb * Exported interface to look up a symbol by name.  We return the GElf_Sym and
1400178479Sjb * complete symbol information for the matching symbol.
1401178479Sjb */
1402178479Sjbint
1403178479Sjbdtrace_lookup_by_name(dtrace_hdl_t *dtp, const char *object, const char *name,
1404178479Sjb    GElf_Sym *symp, dtrace_syminfo_t *sip)
1405178479Sjb{
1406178479Sjb	dt_module_t *dmp;
1407178479Sjb	dt_ident_t *idp;
1408178479Sjb	uint_t n, id;
1409178479Sjb	GElf_Sym sym;
1410178479Sjb
1411178479Sjb	uint_t mask = 0; /* mask of dt_module flags to match */
1412178479Sjb	uint_t bits = 0; /* flag bits that must be present */
1413178479Sjb
1414178479Sjb	if (object != DTRACE_OBJ_EVERY &&
1415178479Sjb	    object != DTRACE_OBJ_KMODS &&
1416178479Sjb	    object != DTRACE_OBJ_UMODS) {
1417178479Sjb		if ((dmp = dt_module_from_object(dtp, object)) == NULL)
1418178479Sjb			return (-1); /* dt_errno is set for us */
1419178479Sjb
1420178479Sjb		if (dt_module_load(dtp, dmp) == -1)
1421178479Sjb			return (-1); /* dt_errno is set for us */
1422178479Sjb		n = 1;
1423178479Sjb
1424178479Sjb	} else {
1425178479Sjb		if (object == DTRACE_OBJ_KMODS)
1426178479Sjb			mask = bits = DT_DM_KERNEL;
1427178479Sjb		else if (object == DTRACE_OBJ_UMODS)
1428178479Sjb			mask = DT_DM_KERNEL;
1429178479Sjb
1430178479Sjb		dmp = dt_list_next(&dtp->dt_modlist);
1431178479Sjb		n = dtp->dt_nmods;
1432178479Sjb	}
1433178479Sjb
1434178479Sjb	if (symp == NULL)
1435178479Sjb		symp = &sym;
1436178479Sjb
1437178479Sjb	for (; n > 0; n--, dmp = dt_list_next(dmp)) {
1438178479Sjb		if ((dmp->dm_flags & mask) != bits)
1439178479Sjb			continue; /* failed to match required attributes */
1440178479Sjb
1441178479Sjb		if (dt_module_load(dtp, dmp) == -1)
1442178479Sjb			continue; /* failed to load symbol table */
1443178479Sjb
1444178479Sjb		if (dmp->dm_ops->do_symname(dmp, name, symp, &id) != NULL) {
1445178479Sjb			if (sip != NULL) {
1446178479Sjb				sip->dts_object = dmp->dm_name;
1447178479Sjb				sip->dts_name = (const char *)
1448178479Sjb				    dmp->dm_strtab.cts_data + symp->st_name;
1449178479Sjb				sip->dts_id = id;
1450178479Sjb			}
1451178479Sjb			return (0);
1452178479Sjb		}
1453178479Sjb
1454178479Sjb		if (dmp->dm_extern != NULL &&
1455178479Sjb		    (idp = dt_idhash_lookup(dmp->dm_extern, name)) != NULL) {
1456178479Sjb			if (symp != &sym) {
1457178479Sjb				symp->st_name = (uintptr_t)idp->di_name;
1458178479Sjb				symp->st_info =
1459178479Sjb				    GELF_ST_INFO(STB_GLOBAL, STT_NOTYPE);
1460178479Sjb				symp->st_other = 0;
1461178479Sjb				symp->st_shndx = SHN_UNDEF;
1462178479Sjb				symp->st_value = 0;
1463178479Sjb				symp->st_size =
1464178479Sjb				    ctf_type_size(idp->di_ctfp, idp->di_type);
1465178479Sjb			}
1466178479Sjb
1467178479Sjb			if (sip != NULL) {
1468178479Sjb				sip->dts_object = dmp->dm_name;
1469178479Sjb				sip->dts_name = idp->di_name;
1470178479Sjb				sip->dts_id = idp->di_id;
1471178479Sjb			}
1472178479Sjb
1473178479Sjb			return (0);
1474178479Sjb		}
1475178479Sjb	}
1476178479Sjb
1477178479Sjb	return (dt_set_errno(dtp, EDT_NOSYM));
1478178479Sjb}
1479178479Sjb
1480178479Sjb/*
1481178479Sjb * Exported interface to look up a symbol by address.  We return the GElf_Sym
1482178479Sjb * and complete symbol information for the matching symbol.
1483178479Sjb */
1484178479Sjbint
1485178479Sjbdtrace_lookup_by_addr(dtrace_hdl_t *dtp, GElf_Addr addr,
1486178479Sjb    GElf_Sym *symp, dtrace_syminfo_t *sip)
1487178479Sjb{
1488178479Sjb	dt_module_t *dmp;
1489178479Sjb	uint_t id;
1490178479Sjb	const dtrace_vector_t *v = dtp->dt_vector;
1491178479Sjb
1492178479Sjb	if (v != NULL)
1493178479Sjb		return (v->dtv_lookup_by_addr(dtp->dt_varg, addr, symp, sip));
1494178479Sjb
1495178479Sjb	for (dmp = dt_list_next(&dtp->dt_modlist); dmp != NULL;
1496178479Sjb	    dmp = dt_list_next(dmp)) {
1497178479Sjb		if (addr - dmp->dm_text_va < dmp->dm_text_size ||
1498178479Sjb		    addr - dmp->dm_data_va < dmp->dm_data_size ||
1499178479Sjb		    addr - dmp->dm_bss_va < dmp->dm_bss_size)
1500178479Sjb			break;
1501178479Sjb	}
1502178479Sjb
1503178479Sjb	if (dmp == NULL)
1504178479Sjb		return (dt_set_errno(dtp, EDT_NOSYMADDR));
1505178479Sjb
1506178479Sjb	if (dt_module_load(dtp, dmp) == -1)
1507178479Sjb		return (-1); /* dt_errno is set for us */
1508178479Sjb
1509178479Sjb	if (symp != NULL) {
1510178479Sjb		if (dmp->dm_ops->do_symaddr(dmp, addr, symp, &id) == NULL)
1511178479Sjb			return (dt_set_errno(dtp, EDT_NOSYMADDR));
1512178479Sjb	}
1513178479Sjb
1514178479Sjb	if (sip != NULL) {
1515178479Sjb		sip->dts_object = dmp->dm_name;
1516178479Sjb
1517178479Sjb		if (symp != NULL) {
1518178479Sjb			sip->dts_name = (const char *)
1519178479Sjb			    dmp->dm_strtab.cts_data + symp->st_name;
1520178479Sjb			sip->dts_id = id;
1521178479Sjb		} else {
1522178479Sjb			sip->dts_name = NULL;
1523178479Sjb			sip->dts_id = 0;
1524178479Sjb		}
1525178479Sjb	}
1526178479Sjb
1527178479Sjb	return (0);
1528178479Sjb}
1529178479Sjb
1530178479Sjbint
1531178479Sjbdtrace_lookup_by_type(dtrace_hdl_t *dtp, const char *object, const char *name,
1532178479Sjb    dtrace_typeinfo_t *tip)
1533178479Sjb{
1534178479Sjb	dtrace_typeinfo_t ti;
1535178479Sjb	dt_module_t *dmp;
1536178479Sjb	int found = 0;
1537178479Sjb	ctf_id_t id;
1538268578Srpaulo	uint_t n, i;
1539178479Sjb	int justone;
1540268578Srpaulo	ctf_file_t *fp;
1541268578Srpaulo	char *buf, *p, *q;
1542178479Sjb
1543178479Sjb	uint_t mask = 0; /* mask of dt_module flags to match */
1544178479Sjb	uint_t bits = 0; /* flag bits that must be present */
1545178479Sjb
1546178479Sjb	if (object != DTRACE_OBJ_EVERY &&
1547178479Sjb	    object != DTRACE_OBJ_KMODS &&
1548178479Sjb	    object != DTRACE_OBJ_UMODS) {
1549178479Sjb		if ((dmp = dt_module_from_object(dtp, object)) == NULL)
1550178479Sjb			return (-1); /* dt_errno is set for us */
1551178479Sjb
1552178479Sjb		if (dt_module_load(dtp, dmp) == -1)
1553178479Sjb			return (-1); /* dt_errno is set for us */
1554178479Sjb		n = 1;
1555178479Sjb		justone = 1;
1556178479Sjb	} else {
1557178479Sjb		if (object == DTRACE_OBJ_KMODS)
1558178479Sjb			mask = bits = DT_DM_KERNEL;
1559178479Sjb		else if (object == DTRACE_OBJ_UMODS)
1560178479Sjb			mask = DT_DM_KERNEL;
1561178479Sjb
1562178479Sjb		dmp = dt_list_next(&dtp->dt_modlist);
1563178479Sjb		n = dtp->dt_nmods;
1564178479Sjb		justone = 0;
1565178479Sjb	}
1566178479Sjb
1567178479Sjb	if (tip == NULL)
1568178479Sjb		tip = &ti;
1569178479Sjb
1570178479Sjb	for (; n > 0; n--, dmp = dt_list_next(dmp)) {
1571178479Sjb		if ((dmp->dm_flags & mask) != bits)
1572178479Sjb			continue; /* failed to match required attributes */
1573178479Sjb
1574178479Sjb		/*
1575178479Sjb		 * If we can't load the CTF container, continue on to the next
1576178479Sjb		 * module.  If our search was scoped to only one module then
1577178479Sjb		 * return immediately leaving dt_errno unmodified.
1578178479Sjb		 */
1579268578Srpaulo		if (dt_module_hasctf(dtp, dmp) == 0) {
1580178479Sjb			if (justone)
1581178479Sjb				return (-1);
1582178479Sjb			continue;
1583178479Sjb		}
1584178479Sjb
1585178479Sjb		/*
1586178479Sjb		 * Look up the type in the module's CTF container.  If our
1587178479Sjb		 * match is a forward declaration tag, save this choice in
1588178479Sjb		 * 'tip' and keep going in the hope that we will locate the
1589178479Sjb		 * underlying structure definition.  Otherwise just return.
1590178479Sjb		 */
1591268578Srpaulo		if (dmp->dm_pid == 0) {
1592268578Srpaulo			id = ctf_lookup_by_name(dmp->dm_ctfp, name);
1593268578Srpaulo			fp = dmp->dm_ctfp;
1594268578Srpaulo		} else {
1595268578Srpaulo			if ((p = strchr(name, '`')) != NULL) {
1596268578Srpaulo				buf = strdup(name);
1597268578Srpaulo				if (buf == NULL)
1598268578Srpaulo					return (dt_set_errno(dtp, EDT_NOMEM));
1599268578Srpaulo				p = strchr(buf, '`');
1600268578Srpaulo				if ((q = strchr(p + 1, '`')) != NULL)
1601268578Srpaulo					p = q;
1602268578Srpaulo				*p = '\0';
1603268578Srpaulo				fp = dt_module_getctflib(dtp, dmp, buf);
1604268578Srpaulo				if (fp == NULL || (id = ctf_lookup_by_name(fp,
1605268578Srpaulo				    p + 1)) == CTF_ERR)
1606268578Srpaulo					id = CTF_ERR;
1607268578Srpaulo				free(buf);
1608268578Srpaulo			} else {
1609268578Srpaulo				for (i = 0; i < dmp->dm_nctflibs; i++) {
1610268578Srpaulo					fp = dmp->dm_libctfp[i];
1611268578Srpaulo					id = ctf_lookup_by_name(fp, name);
1612268578Srpaulo					if (id != CTF_ERR)
1613268578Srpaulo						break;
1614268578Srpaulo				}
1615268578Srpaulo			}
1616268578Srpaulo		}
1617268578Srpaulo		if (id != CTF_ERR) {
1618178479Sjb			tip->dtt_object = dmp->dm_name;
1619268578Srpaulo			tip->dtt_ctfp = fp;
1620178479Sjb			tip->dtt_type = id;
1621268578Srpaulo			if (ctf_type_kind(fp, ctf_type_resolve(fp, id)) !=
1622268578Srpaulo			    CTF_K_FORWARD)
1623178479Sjb				return (0);
1624178479Sjb
1625178479Sjb			found++;
1626178479Sjb		}
1627178479Sjb	}
1628178479Sjb
1629178479Sjb	if (found == 0)
1630178479Sjb		return (dt_set_errno(dtp, EDT_NOTYPE));
1631178479Sjb
1632178479Sjb	return (0);
1633178479Sjb}
1634178479Sjb
1635178479Sjbint
1636178479Sjbdtrace_symbol_type(dtrace_hdl_t *dtp, const GElf_Sym *symp,
1637178479Sjb    const dtrace_syminfo_t *sip, dtrace_typeinfo_t *tip)
1638178479Sjb{
1639178479Sjb	dt_module_t *dmp;
1640178479Sjb
1641178479Sjb	tip->dtt_object = NULL;
1642178479Sjb	tip->dtt_ctfp = NULL;
1643178479Sjb	tip->dtt_type = CTF_ERR;
1644268578Srpaulo	tip->dtt_flags = 0;
1645178479Sjb
1646178479Sjb	if ((dmp = dt_module_lookup_by_name(dtp, sip->dts_object)) == NULL)
1647178479Sjb		return (dt_set_errno(dtp, EDT_NOMOD));
1648178479Sjb
1649178479Sjb	if (symp->st_shndx == SHN_UNDEF && dmp->dm_extern != NULL) {
1650178479Sjb		dt_ident_t *idp =
1651178479Sjb		    dt_idhash_lookup(dmp->dm_extern, sip->dts_name);
1652178479Sjb
1653178479Sjb		if (idp == NULL)
1654178479Sjb			return (dt_set_errno(dtp, EDT_NOSYM));
1655178479Sjb
1656178479Sjb		tip->dtt_ctfp = idp->di_ctfp;
1657178479Sjb		tip->dtt_type = idp->di_type;
1658178479Sjb
1659178479Sjb	} else if (GELF_ST_TYPE(symp->st_info) != STT_FUNC) {
1660178479Sjb		if (dt_module_getctf(dtp, dmp) == NULL)
1661178479Sjb			return (-1); /* errno is set for us */
1662178479Sjb
1663178479Sjb		tip->dtt_ctfp = dmp->dm_ctfp;
1664178479Sjb		tip->dtt_type = ctf_lookup_by_symbol(dmp->dm_ctfp, sip->dts_id);
1665178479Sjb
1666178479Sjb		if (tip->dtt_type == CTF_ERR) {
1667178479Sjb			dtp->dt_ctferr = ctf_errno(tip->dtt_ctfp);
1668178479Sjb			return (dt_set_errno(dtp, EDT_CTF));
1669178479Sjb		}
1670178479Sjb
1671178479Sjb	} else {
1672178479Sjb		tip->dtt_ctfp = DT_FPTR_CTFP(dtp);
1673178479Sjb		tip->dtt_type = DT_FPTR_TYPE(dtp);
1674178479Sjb	}
1675178479Sjb
1676178479Sjb	tip->dtt_object = dmp->dm_name;
1677178479Sjb	return (0);
1678178479Sjb}
1679178479Sjb
1680178479Sjbstatic dtrace_objinfo_t *
1681178479Sjbdt_module_info(const dt_module_t *dmp, dtrace_objinfo_t *dto)
1682178479Sjb{
1683178479Sjb	dto->dto_name = dmp->dm_name;
1684178479Sjb	dto->dto_file = dmp->dm_file;
1685178479Sjb	dto->dto_id = dmp->dm_modid;
1686178479Sjb	dto->dto_flags = 0;
1687178479Sjb
1688178479Sjb	if (dmp->dm_flags & DT_DM_KERNEL)
1689178479Sjb		dto->dto_flags |= DTRACE_OBJ_F_KERNEL;
1690178479Sjb	if (dmp->dm_flags & DT_DM_PRIMARY)
1691178479Sjb		dto->dto_flags |= DTRACE_OBJ_F_PRIMARY;
1692178479Sjb
1693178479Sjb	dto->dto_text_va = dmp->dm_text_va;
1694178479Sjb	dto->dto_text_size = dmp->dm_text_size;
1695178479Sjb	dto->dto_data_va = dmp->dm_data_va;
1696178479Sjb	dto->dto_data_size = dmp->dm_data_size;
1697178479Sjb	dto->dto_bss_va = dmp->dm_bss_va;
1698178479Sjb	dto->dto_bss_size = dmp->dm_bss_size;
1699178479Sjb
1700178479Sjb	return (dto);
1701178479Sjb}
1702178479Sjb
1703178479Sjbint
1704178479Sjbdtrace_object_iter(dtrace_hdl_t *dtp, dtrace_obj_f *func, void *data)
1705178479Sjb{
1706178479Sjb	const dt_module_t *dmp = dt_list_next(&dtp->dt_modlist);
1707178479Sjb	dtrace_objinfo_t dto;
1708178479Sjb	int rv;
1709178479Sjb
1710178479Sjb	for (; dmp != NULL; dmp = dt_list_next(dmp)) {
1711178479Sjb		if ((rv = (*func)(dtp, dt_module_info(dmp, &dto), data)) != 0)
1712178479Sjb			return (rv);
1713178479Sjb	}
1714178479Sjb
1715178479Sjb	return (0);
1716178479Sjb}
1717178479Sjb
1718178479Sjbint
1719178479Sjbdtrace_object_info(dtrace_hdl_t *dtp, const char *object, dtrace_objinfo_t *dto)
1720178479Sjb{
1721178479Sjb	dt_module_t *dmp;
1722178479Sjb
1723178479Sjb	if (object == DTRACE_OBJ_EVERY || object == DTRACE_OBJ_KMODS ||
1724178479Sjb	    object == DTRACE_OBJ_UMODS || dto == NULL)
1725178479Sjb		return (dt_set_errno(dtp, EINVAL));
1726178479Sjb
1727178479Sjb	if ((dmp = dt_module_from_object(dtp, object)) == NULL)
1728178479Sjb		return (-1); /* dt_errno is set for us */
1729178479Sjb
1730178479Sjb	if (dt_module_load(dtp, dmp) == -1)
1731178479Sjb		return (-1); /* dt_errno is set for us */
1732178479Sjb
1733178479Sjb	(void) dt_module_info(dmp, dto);
1734178479Sjb	return (0);
1735178479Sjb}
1736