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 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <sys/param.h>
27 #include <sys/systm.h>
28 #include <sys/errno.h>
29 #include <sys/stat.h>
30 #include <sys/ioctl.h>
31 #include <sys/conf.h>
32 #include <sys/fcntl.h>
33 #include <miscfs/devfs/devfs.h>
34
35 #if defined(__arm__) || defined(__arm64__)
36 #include <arm/caches_internal.h>
37 #endif /* defined(__arm__) || defined(__arm64__) */
38
39 #include <sys/dtrace.h>
40 #include <sys/dtrace_impl.h>
41
42 #include <sys/dtrace_glue.h>
43
44 #include <sys/sdt_impl.h>
45 extern int dtrace_kernel_symbol_mode;
46
47 #include <ptrauth.h>
48
49 /* #include <machine/trap.h */
50 struct savearea_t; /* Used anonymously */
51
52 #if defined(__arm__)
53 typedef kern_return_t (*perfCallback)(int, struct savearea_t *, __unused int, __unused int);
54 extern perfCallback tempDTraceTrapHook;
55 extern kern_return_t fbt_perfCallback(int, struct savearea_t *, __unused int, __unused int);
56 #define SDT_PATCHVAL 0xdefc
57 #define SDT_AFRAMES 7
58 #elif defined(__arm64__)
59 typedef kern_return_t (*perfCallback)(int, struct savearea_t *, __unused int, __unused int);
60 extern perfCallback tempDTraceTrapHook;
61 extern kern_return_t fbt_perfCallback(int, struct savearea_t *, __unused int, __unused int);
62 #define SDT_PATCHVAL 0xe7eeee7e
63 #define SDT_AFRAMES 7
64 #elif defined(__x86_64__)
65 typedef kern_return_t (*perfCallback)(int, struct savearea_t *, uintptr_t *, int);
66 extern perfCallback tempDTraceTrapHook;
67 extern kern_return_t fbt_perfCallback(int, struct savearea_t *, uintptr_t *, int);
68 #define SDT_PATCHVAL 0xf0
69 #define SDT_AFRAMES 6
70 #else
71 #error Unknown architecture
72 #endif
73
74 #define SDT_PROBETAB_SIZE 0x1000 /* 4k entries -- 16K total */
75
76 #define SDT_UNKNOWN_FUNCNAME "." /* function symbol name when not found in symbol table */
77
78
79 static int sdt_verbose = 0;
80 sdt_probe_t **sdt_probetab;
81 int sdt_probetab_size;
82 int sdt_probetab_mask;
83
84 /*ARGSUSED*/
85 static void
__sdt_provide_module(void * arg,struct modctl * ctl)86 __sdt_provide_module(void *arg, struct modctl *ctl)
87 {
88 #pragma unused(arg)
89 char *modname = ctl->mod_modname;
90 sdt_probedesc_t *sdpd;
91 sdt_probe_t *sdp, *old;
92 sdt_provider_t *prov;
93
94 /*
95 * One for all, and all for one: if we haven't yet registered all of
96 * our providers, we'll refuse to provide anything.
97 */
98 for (prov = sdt_providers; prov->sdtp_name != NULL; prov++) {
99 if (prov->sdtp_id == DTRACE_PROVNONE) {
100 return;
101 }
102 }
103
104 /* Nothing to do. Module is either invalid or we haven't found any SDT probe descriptions. */
105 if (!ctl || ctl->mod_sdtprobecnt != 0 || (sdpd = ctl->mod_sdtdesc) == NULL) {
106 return;
107 }
108
109 for (sdpd = ctl->mod_sdtdesc; sdpd != NULL; sdpd = sdpd->sdpd_next) {
110 dtrace_id_t id;
111
112 /* Validate probe's provider name. Do not provide probes for unknown providers. */
113 for (prov = sdt_providers; prov->sdtp_name != NULL; prov++) {
114 if (strcmp(prov->sdtp_prefix, sdpd->sdpd_prov) == 0) {
115 break;
116 }
117 }
118
119 if (prov->sdtp_name == NULL) {
120 printf("Ignoring probes from unsupported provider %s\n", sdpd->sdpd_prov);
121 continue;
122 }
123
124 if (sdpd->sdpd_func == NULL) {
125 /*
126 * Ignore probes for which we don't have any symbol. That's likely some problem with
127 * __sdt section processing.
128 */
129 printf("Ignoring probe %s (no symbol name)\n", sdpd->sdpd_name);
130 continue;
131 }
132
133 sdp = kmem_zalloc(sizeof(sdt_probe_t), KM_SLEEP);
134 sdp->sdp_loadcnt = ctl->mod_loadcnt;
135 sdp->sdp_ctl = ctl;
136 sdp->sdp_name = kmem_alloc(strlen(sdpd->sdpd_name) + 1, KM_SLEEP);
137 (void) strlcpy(sdp->sdp_name, sdpd->sdpd_name, strlen(sdpd->sdpd_name) + 1);
138 sdp->sdp_namelen = strlen(sdpd->sdpd_name) + 1;
139 sdp->sdp_provider = prov;
140
141 /*
142 * We have our provider. Now create the probe.
143 */
144 if ((id = dtrace_probe_lookup(prov->sdtp_id, modname,
145 sdpd->sdpd_func, sdp->sdp_name)) != DTRACE_IDNONE) {
146 old = dtrace_probe_arg(prov->sdtp_id, id);
147 ASSERT(old != NULL);
148
149 sdp->sdp_next = old->sdp_next;
150 sdp->sdp_id = id;
151 old->sdp_next = sdp;
152 } else {
153 sdp->sdp_id = dtrace_probe_create(prov->sdtp_id,
154 modname, sdpd->sdpd_func, sdp->sdp_name, SDT_AFRAMES, sdp);
155
156 ctl->mod_sdtprobecnt++;
157 }
158
159 #if 0
160 printf("__sdt_provide_module: sdpd=0x%p sdp=0x%p name=%s, id=%d\n", sdpd, sdp,
161 sdp->sdp_name, sdp->sdp_id);
162 #endif
163
164 sdp->sdp_hashnext =
165 sdt_probetab[SDT_ADDR2NDX(sdpd->sdpd_offset)];
166 sdt_probetab[SDT_ADDR2NDX(sdpd->sdpd_offset)] = sdp;
167
168 sdp->sdp_patchval = SDT_PATCHVAL;
169 sdp->sdp_patchpoint = (sdt_instr_t *)sdpd->sdpd_offset;
170 sdp->sdp_savedval = *sdp->sdp_patchpoint;
171 }
172 }
173
174 /*ARGSUSED*/
175 static void
sdt_destroy(void * arg,dtrace_id_t id,void * parg)176 sdt_destroy(void *arg, dtrace_id_t id, void *parg)
177 {
178 #pragma unused(arg,id)
179 sdt_probe_t *sdp = parg, *old, *last, *hash;
180 int ndx;
181
182 struct modctl *ctl = sdp->sdp_ctl;
183
184 /*
185 * Decrement SDT probe counts only when a probe being destroyed belongs to the
186 * currently loaded version of a module and not the stale one.
187 */
188 if (ctl != NULL && ctl->mod_loadcnt == sdp->sdp_loadcnt && ctl->mod_loaded) {
189 ctl->mod_sdtprobecnt--;
190 }
191
192 while (sdp != NULL) {
193 old = sdp;
194
195 /*
196 * Now we need to remove this probe from the sdt_probetab.
197 */
198 ndx = SDT_ADDR2NDX(sdp->sdp_patchpoint);
199 last = NULL;
200 hash = sdt_probetab[ndx];
201
202 while (hash != sdp) {
203 ASSERT(hash != NULL);
204 last = hash;
205 hash = hash->sdp_hashnext;
206 }
207
208 if (last != NULL) {
209 last->sdp_hashnext = sdp->sdp_hashnext;
210 } else {
211 sdt_probetab[ndx] = sdp->sdp_hashnext;
212 }
213
214 kmem_free(sdp->sdp_name, sdp->sdp_namelen);
215 sdp = sdp->sdp_next;
216 kmem_free(old, sizeof(sdt_probe_t));
217 }
218 }
219
220 /*ARGSUSED*/
221 static int
sdt_enable(void * arg,dtrace_id_t id,void * parg)222 sdt_enable(void *arg, dtrace_id_t id, void *parg)
223 {
224 #pragma unused(arg,id)
225 sdt_probe_t *sdp = parg;
226 struct modctl *ctl = sdp->sdp_ctl;
227
228 ctl->mod_nenabled++;
229
230 /*
231 * If this module has disappeared since we discovered its probes,
232 * refuse to enable it.
233 */
234 if (!ctl->mod_loaded) {
235 if (sdt_verbose) {
236 cmn_err(CE_NOTE, "sdt is failing for probe %s "
237 "(module %s unloaded)",
238 sdp->sdp_name, ctl->mod_modname);
239 }
240 goto err;
241 }
242
243 /*
244 * Now check that our modctl has the expected load count. If it
245 * doesn't, this module must have been unloaded and reloaded -- and
246 * we're not going to touch it.
247 */
248 if (ctl->mod_loadcnt != sdp->sdp_loadcnt) {
249 if (sdt_verbose) {
250 cmn_err(CE_NOTE, "sdt is failing for probe %s "
251 "(module %s reloaded)",
252 sdp->sdp_name, ctl->mod_modname);
253 }
254 goto err;
255 }
256
257 dtrace_casptr(&tempDTraceTrapHook, NULL, ptrauth_nop_cast(void *, &fbt_perfCallback));
258 if (tempDTraceTrapHook != (perfCallback)fbt_perfCallback) {
259 if (sdt_verbose) {
260 cmn_err(CE_NOTE, "sdt_enable is failing for probe %s "
261 "in module %s: tempDTraceTrapHook already occupied.",
262 sdp->sdp_name, ctl->mod_modname);
263 }
264 return 0;
265 }
266
267 while (sdp != NULL) {
268 (void)ml_nofault_copy((vm_offset_t)&sdp->sdp_patchval, (vm_offset_t)sdp->sdp_patchpoint,
269 (vm_size_t)sizeof(sdp->sdp_patchval));
270
271 /*
272 * Make the patched instruction visible via a data + instruction
273 * cache fush on platforms that need it
274 */
275 flush_dcache((vm_offset_t)sdp->sdp_patchpoint, (vm_size_t)sizeof(sdp->sdp_patchval), 0);
276 invalidate_icache((vm_offset_t)sdp->sdp_patchpoint, (vm_size_t)sizeof(sdp->sdp_patchval), 0);
277
278 sdp = sdp->sdp_next;
279 }
280
281 err:
282 return 0;
283 }
284
285 /*ARGSUSED*/
286 static void
sdt_disable(void * arg,dtrace_id_t id,void * parg)287 sdt_disable(void *arg, dtrace_id_t id, void *parg)
288 {
289 #pragma unused(arg,id)
290 sdt_probe_t *sdp = parg;
291 struct modctl *ctl = sdp->sdp_ctl;
292
293 ctl->mod_nenabled--;
294
295 if (!ctl->mod_loaded || ctl->mod_loadcnt != sdp->sdp_loadcnt) {
296 goto err;
297 }
298
299 while (sdp != NULL) {
300 (void)ml_nofault_copy((vm_offset_t)&sdp->sdp_savedval, (vm_offset_t)sdp->sdp_patchpoint,
301 (vm_size_t)sizeof(sdp->sdp_savedval));
302 /*
303 * Make the patched instruction visible via a data + instruction
304 * cache flush on platforms that need it
305 */
306 flush_dcache((vm_offset_t)sdp->sdp_patchpoint, (vm_size_t)sizeof(sdp->sdp_savedval), 0);
307 invalidate_icache((vm_offset_t)sdp->sdp_patchpoint, (vm_size_t)sizeof(sdp->sdp_savedval), 0);
308 sdp = sdp->sdp_next;
309 }
310
311 err:
312 ;
313 }
314
315 static dtrace_pops_t sdt_pops = {
316 .dtps_provide = NULL,
317 .dtps_provide_module = sdt_provide_module,
318 .dtps_enable = sdt_enable,
319 .dtps_disable = sdt_disable,
320 .dtps_suspend = NULL,
321 .dtps_resume = NULL,
322 .dtps_getargdesc = sdt_getargdesc,
323 .dtps_getargval = sdt_getarg,
324 .dtps_usermode = NULL,
325 .dtps_destroy = sdt_destroy,
326 };
327
328 /*ARGSUSED*/
329 static int
sdt_attach(dev_info_t * devi)330 sdt_attach(dev_info_t *devi)
331 {
332 sdt_provider_t *prov;
333
334 if (ddi_create_minor_node(devi, "sdt", S_IFCHR,
335 0, DDI_PSEUDO, 0) == DDI_FAILURE) {
336 cmn_err(CE_NOTE, "/dev/sdt couldn't create minor node");
337 ddi_remove_minor_node(devi, NULL);
338 return DDI_FAILURE;
339 }
340
341 if (sdt_probetab_size == 0) {
342 sdt_probetab_size = SDT_PROBETAB_SIZE;
343 }
344
345 sdt_probetab_mask = sdt_probetab_size - 1;
346 sdt_probetab =
347 kmem_zalloc(sdt_probetab_size * sizeof(sdt_probe_t *), KM_SLEEP);
348 dtrace_invop_add(sdt_invop);
349
350 for (prov = sdt_providers; prov->sdtp_name != NULL; prov++) {
351 if (dtrace_register(prov->sdtp_name, prov->sdtp_attr,
352 DTRACE_PRIV_KERNEL, NULL,
353 &sdt_pops, prov, &prov->sdtp_id) != 0) {
354 cmn_err(CE_WARN, "failed to register sdt provider %s",
355 prov->sdtp_name);
356 }
357 }
358
359 return DDI_SUCCESS;
360 }
361
362 /*
363 * APPLE NOTE: sdt_detach not implemented
364 */
365 #if !defined(__APPLE__)
366 /*ARGSUSED*/
367 static int
sdt_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)368 sdt_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
369 {
370 sdt_provider_t *prov;
371
372 switch (cmd) {
373 case DDI_DETACH:
374 break;
375
376 case DDI_SUSPEND:
377 return DDI_SUCCESS;
378
379 default:
380 return DDI_FAILURE;
381 }
382
383 for (prov = sdt_providers; prov->sdtp_name != NULL; prov++) {
384 if (prov->sdtp_id != DTRACE_PROVNONE) {
385 if (dtrace_unregister(prov->sdtp_id) != 0) {
386 return DDI_FAILURE;
387 }
388
389 prov->sdtp_id = DTRACE_PROVNONE;
390 }
391 }
392
393 dtrace_invop_remove(sdt_invop);
394 kmem_free(sdt_probetab, sdt_probetab_size * sizeof(sdt_probe_t *));
395
396 return DDI_SUCCESS;
397 }
398 #endif /* __APPLE__ */
399
400 d_open_t _sdt_open;
401
402 int
_sdt_open(dev_t dev,int flags,int devtype,struct proc * p)403 _sdt_open(dev_t dev, int flags, int devtype, struct proc *p)
404 {
405 #pragma unused(dev,flags,devtype,p)
406 return 0;
407 }
408
409 #define SDT_MAJOR -24 /* let the kernel pick the device number */
410
411 static const struct cdevsw sdt_cdevsw =
412 {
413 .d_open = _sdt_open,
414 .d_close = eno_opcl,
415 .d_read = eno_rdwrt,
416 .d_write = eno_rdwrt,
417 .d_ioctl = eno_ioctl,
418 .d_stop = (stop_fcn_t *)nulldev,
419 .d_reset = (reset_fcn_t *)nulldev,
420 .d_select = eno_select,
421 .d_mmap = eno_mmap,
422 .d_strategy = eno_strat,
423 .d_reserved_1 = eno_getc,
424 .d_reserved_2 = eno_putc,
425 };
426
427
428 #include <mach-o/nlist.h>
429 #include <libkern/kernel_mach_header.h>
430
431 /*
432 * Represents single record in __DATA,__sdt section.
433 */
434 typedef struct dtrace_sdt_def {
435 uintptr_t dsd_addr; /* probe site location */
436 const char *dsd_prov; /* provider's name */
437 const char *dsd_name; /* probe's name */
438 } __attribute__((__packed__)) dtrace_sdt_def_t;
439
440 /*
441 * Creates a copy of name and unescapes '-' characters.
442 */
443 static char *
sdt_strdup_name(const char * name)444 sdt_strdup_name(const char *name)
445 {
446 size_t len = strlen(name) + 1;
447 size_t i, j;
448 char *nname = kmem_alloc(len, KM_SLEEP);
449
450 for (i = 0, j = 0; name[j] != '\0'; i++) {
451 if (name[j] == '_' && name[j + 1] == '_') {
452 nname[i] = '-';
453 j += 2;
454 } else {
455 nname[i] = name[j++];
456 }
457 }
458
459 nname[i] = '\0';
460 return nname;
461 }
462
463 /*
464 * Returns Mach-O header that should be used for given modctl.
465 */
466 static kernel_mach_header_t *
sdt_get_module_mh(struct modctl * ctl)467 sdt_get_module_mh(struct modctl *ctl)
468 {
469 kernel_mach_header_t *mh = (kernel_mach_header_t *)ctl->mod_address;
470
471 /* Static KEXTs have their __sdt section merged into kernel's __sdt. */
472 if (MOD_IS_STATIC_KEXT(ctl)) {
473 mh = &_mh_execute_header;
474 }
475
476 if (mh->magic != MH_MAGIC_KERNEL) {
477 return NULL;
478 }
479
480 return mh;
481 }
482
483 /*
484 * Finds symbol table for given kernel module.
485 */
486 static uint32_t
sdt_find_symbol_table(struct modctl * ctl,kernel_nlist_t ** sym,char ** strings)487 sdt_find_symbol_table(struct modctl *ctl, kernel_nlist_t **sym, char **strings)
488 {
489 kernel_mach_header_t *mh = sdt_get_module_mh(ctl);
490 struct load_command *cmd = (struct load_command *)&mh[1];
491 kernel_segment_command_t *orig_le = NULL;
492 struct symtab_command *orig_st = NULL;
493
494 for (int i = 0; i < mh->ncmds; i++) {
495 if (cmd->cmd == LC_SEGMENT_KERNEL) {
496 kernel_segment_command_t *orig_sg = (kernel_segment_command_t *) cmd;
497
498 if (LIT_STRNEQL(orig_sg->segname, SEG_LINKEDIT)) {
499 orig_le = orig_sg;
500 }
501 } else if (cmd->cmd == LC_SYMTAB) {
502 orig_st = (struct symtab_command *) cmd;
503 }
504
505 cmd = (struct load_command *) ((uintptr_t) cmd + cmd->cmdsize);
506 }
507
508 if ((orig_st == NULL) || (orig_le == NULL)) {
509 return 0;
510 }
511
512 *sym = (kernel_nlist_t *)(orig_le->vmaddr + orig_st->symoff - orig_le->fileoff);
513 *strings = (char *)(orig_le->vmaddr + orig_st->stroff - orig_le->fileoff);
514
515 return orig_st->nsyms;
516 }
517
518 /* Last kernel address. */
519 static SECURITY_READ_ONLY_LATE(vm_address_t) kern_end = (vm_address_t)-1;
520
521 void
sdt_early_init(void)522 sdt_early_init(void)
523 {
524 kernel_mach_header_t *mh = &_mh_execute_header;
525 kernel_section_t *sec_ks = NULL;
526 kc_format_t kc_format;
527
528 if (!PE_get_primary_kc_format(&kc_format)) {
529 kc_format = KCFormatUnknown;
530 }
531
532 /*
533 * Detects end of kernel's text in static kernel cache. It is the last text address before
534 * the first kext text section start.
535 */
536 if (kc_format == KCFormatStatic) {
537 if ((sec_ks = getsectbynamefromheader(mh, "__PRELINK_INFO", "__kmod_start")) == NULL) {
538 printf("SDT: unable to find prelink info\n");
539 return;
540 }
541
542 /* find the MIN(start_address) of all kexts in this image. */
543 const uint64_t *start_addr = (const uint64_t *)sec_ks->addr;
544 for (int i = 0; i < sec_ks->size / sizeof(uint64_t); i++) {
545 if (kern_end > start_addr[i]) {
546 kern_end = start_addr[i];
547 }
548 }
549 }
550 }
551
552 /*
553 * Finds TEXT range that belongs to given module.
554 */
555 static int
sdt_find_module_text_range(struct modctl * ctl,vm_address_t * start,vm_address_t * end)556 sdt_find_module_text_range(struct modctl *ctl, vm_address_t *start, vm_address_t *end)
557 {
558 kc_format_t kc_format;
559
560 if (!PE_get_primary_kc_format(&kc_format)) {
561 kc_format = KCFormatUnknown;
562 }
563
564 /* Adjust kernel region for static kernel cache. */
565 *start = ctl->mod_address;
566
567 if (MOD_IS_MACH_KERNEL(ctl) && kc_format == KCFormatStatic) {
568 *end = kern_end;
569 } else {
570 *end = ctl->mod_address + ctl->mod_size;
571 }
572
573 return 1;
574 }
575
576 /*
577 * Processes SDT section in given Mach-O header
578 */
579 void
sdt_load_machsect(struct modctl * ctl)580 sdt_load_machsect(struct modctl *ctl)
581 {
582 kernel_mach_header_t *mh = sdt_get_module_mh(ctl);
583 kernel_section_t *sec_sdt = NULL;
584 char *strings = NULL;
585 kernel_nlist_t *sym = NULL;
586 vm_address_t text_start, text_end;
587 unsigned int len;
588 uint32_t nsyms = 0;
589
590 if (mh == NULL) {
591 return;
592 }
593
594 /* Ignore SDT definitions if we don't know where they belong. */
595 if (!sdt_find_module_text_range(ctl, &text_start, &text_end)) {
596 printf("SDT: Unable to determine text range for %s\n", ctl->mod_modname);
597 return;
598 }
599
600 /* Do not load SDTs when asked to use kernel symbols but symbol table is not available. */
601 if (MOD_HAS_KERNEL_SYMBOLS(ctl) && (nsyms = sdt_find_symbol_table(ctl, &sym, &strings)) == 0) {
602 printf("SDT: No kernel symbols for %s\n", ctl->mod_modname);
603 return;
604 }
605
606 /* Locate DTrace SDT section in the object. */
607 if ((sec_sdt = getsectbynamefromheader(mh, "__DATA", "__sdt")) == NULL) {
608 return;
609 }
610
611 /*
612 * Iterate over SDT section and establish all SDT probe descriptions.
613 */
614 dtrace_sdt_def_t *sdtdef = (dtrace_sdt_def_t *)(sec_sdt->addr);
615 for (size_t k = 0; k < sec_sdt->size / sizeof(dtrace_sdt_def_t); k++, sdtdef++) {
616 unsigned long best = 0;
617
618 #if defined(__arm__)
619 /* PR8353094 - mask off thumb-bit */
620 sdtdef->dsd_addr &= ~0x1U;
621 #elif defined(__arm64__)
622 sdtdef->dsd_addr &= ~0x1LU;
623 #endif /* __arm__ */
624
625 /*
626 * Static KEXTs share __sdt section with kernel after linking. It is required
627 * to filter out description and pick only those that belong to requested
628 * module or kernel itself.
629 */
630 if (MOD_IS_STATIC_KEXT(ctl) || MOD_IS_MACH_KERNEL(ctl)) {
631 if ((sdtdef->dsd_addr < text_start) || (sdtdef->dsd_addr > text_end)) {
632 continue;
633 }
634 } else {
635 /* Skip over probe descripton that do not belong to current module. */
636 if (!dtrace_addr_in_module((void *)sdtdef->dsd_addr, ctl)) {
637 continue;
638 }
639 }
640
641 sdt_probedesc_t *sdpd = kmem_alloc(sizeof(sdt_probedesc_t), KM_SLEEP);
642
643 /* Unescape probe name and keep a note of the size of original memory allocation. */
644 sdpd->sdpd_name = sdt_strdup_name(sdtdef->dsd_name);
645 sdpd->sdpd_namelen = strlen(sdtdef->dsd_name) + 1;
646
647 /* Used only for provider structure lookup so there is no need to make dynamic copy. */
648 sdpd->sdpd_prov = sdtdef->dsd_prov;
649
650 /*
651 * Find the symbol immediately preceding the sdt probe site just discovered,
652 * that symbol names the function containing the sdt probe.
653 */
654 sdpd->sdpd_func = NULL;
655
656 if (MOD_HAS_KERNEL_SYMBOLS(ctl)) {
657 const char *funcname = SDT_UNKNOWN_FUNCNAME;
658
659 for (int i = 0; i < nsyms; i++) {
660 uint8_t jn_type = sym[i].n_type & N_TYPE;
661 char *jname = strings + sym[i].n_un.n_strx;
662
663 if ((N_SECT != jn_type && N_ABS != jn_type)) {
664 continue;
665 }
666
667 if (0 == sym[i].n_un.n_strx) { /* iff a null, "", name. */
668 continue;
669 }
670
671 if (*jname == '_') {
672 jname += 1;
673 }
674
675 if (sdtdef->dsd_addr <= (unsigned long)sym[i].n_value) {
676 continue;
677 }
678
679 if ((unsigned long)sym[i].n_value > best) {
680 best = (unsigned long)sym[i].n_value;
681 funcname = jname;
682 }
683 }
684
685 len = strlen(funcname) + 1;
686 sdpd->sdpd_func = kmem_alloc(len, KM_SLEEP);
687 (void) strlcpy(sdpd->sdpd_func, funcname, len);
688 }
689
690 sdpd->sdpd_offset = sdtdef->dsd_addr;
691
692 sdpd->sdpd_next = (sdt_probedesc_t *)ctl->mod_sdtdesc;
693 ctl->mod_sdtdesc = sdpd;
694 }
695 }
696
697 void
sdt_init(void)698 sdt_init( void )
699 {
700 int majdevno = cdevsw_add(SDT_MAJOR, &sdt_cdevsw);
701
702 if (majdevno < 0) {
703 printf("sdt_init: failed to allocate a major number!\n");
704 return;
705 }
706
707 if (dtrace_sdt_probes_restricted()) {
708 return;
709 }
710
711 sdt_attach((dev_info_t*)(uintptr_t)majdevno);
712 }
713
714 #undef SDT_MAJOR
715
716 /*
717 * Provide SDT modules with userspace symbols.
718 *
719 * A module contains only partially filled in SDT probe descriptions because symbols were
720 * not available at the time when __sdt section was loaded. Fixup descriptons before providing
721 * the probes.
722 */
723 static void
sdt_provide_module_user_syms(void * arg,struct modctl * ctl)724 sdt_provide_module_user_syms(void *arg, struct modctl *ctl)
725 {
726 sdt_probedesc_t *sdpd;
727 dtrace_module_symbols_t *mod_sym = ctl->mod_user_symbols;
728
729 if (mod_sym == NULL) {
730 printf("DTrace missing userspace symbols for module %s\n", ctl->mod_modname);
731 return;
732 }
733
734 /* Fixup missing probe description parts. */
735 for (sdpd = ctl->mod_sdtdesc; sdpd != NULL; sdpd = sdpd->sdpd_next) {
736 ASSERT(sdpd->sdpd_func == NULL);
737 const char *funcname = SDT_UNKNOWN_FUNCNAME;
738
739 /* Look for symbol that contains SDT probe offset. */
740 for (int i = 0; i < mod_sym->dtmodsyms_count; i++) {
741 dtrace_symbol_t *symbol = &mod_sym->dtmodsyms_symbols[i];
742 char *name = symbol->dtsym_name;
743
744 /*
745 * Every function symbol gets extra '_' prepended in the Mach-O symbol table.
746 * Strip it away to make a probe's function name match source code.
747 */
748 if (*name == '_') {
749 name += 1;
750 }
751
752 if (!symbol->dtsym_addr) {
753 continue;
754 }
755
756 /* Ignore symbols that do not belong to this module. */
757 if (!dtrace_addr_in_module((void *)symbol->dtsym_addr, ctl)) {
758 continue;
759 }
760
761 /* Pick symbol name when we found match. */
762 if ((symbol->dtsym_addr <= sdpd->sdpd_offset) &&
763 (sdpd->sdpd_offset < symbol->dtsym_addr + symbol->dtsym_size)) {
764 funcname = name;
765 break;
766 }
767 }
768
769 size_t len = strlen(funcname) + 1;
770 sdpd->sdpd_func = kmem_alloc(len, KM_SLEEP);
771 (void) strlcpy(sdpd->sdpd_func, funcname, len);
772 }
773
774 /* Probe descriptionds are now fixed up. Provide them as usual. */
775 __sdt_provide_module(arg, ctl);
776 }
777
778 /*ARGSUSED*/
779 void
sdt_provide_module(void * arg,struct modctl * ctl)780 sdt_provide_module(void *arg, struct modctl *ctl)
781 {
782 ASSERT(ctl != NULL);
783 ASSERT(dtrace_kernel_symbol_mode != DTRACE_KERNEL_SYMBOLS_NEVER);
784 LCK_MTX_ASSERT(&mod_lock, LCK_MTX_ASSERT_OWNED);
785
786 if (MOD_SDT_DONE(ctl)) {
787 return;
788 }
789
790 if (MOD_HAS_KERNEL_SYMBOLS(ctl)) {
791 __sdt_provide_module(arg, ctl);
792 ctl->mod_flags |= MODCTL_SDT_PROBES_PROVIDED;
793 return;
794 }
795
796 if (MOD_HAS_USERSPACE_SYMBOLS(ctl)) {
797 sdt_provide_module_user_syms(arg, ctl);
798 ctl->mod_flags |= MODCTL_SDT_PROBES_PROVIDED;
799 return;
800 }
801
802 /*
803 * The SDT provider's module is not detachable so we don't have to re-provide SDT
804 * probes if that happens. After succesfull providing, the probe descriptions are
805 * no longer required. If module gets re-loaded it will get a new set of probe
806 * descriptions from its __sdt section.
807 */
808 if (MOD_SDT_PROBES_PROVIDED(ctl)) {
809 sdt_probedesc_t *sdpd = ctl->mod_sdtdesc;
810 while (sdpd) {
811 sdt_probedesc_t *this_sdpd = sdpd;
812 kmem_free((void *)sdpd->sdpd_name, sdpd->sdpd_namelen);
813 if (sdpd->sdpd_func) {
814 kmem_free((void *)sdpd->sdpd_func, strlen(sdpd->sdpd_func) + 1);
815 }
816 sdpd = sdpd->sdpd_next;
817 kmem_free((void *)this_sdpd, sizeof(sdt_probedesc_t));
818 }
819 ctl->mod_sdtdesc = NULL;
820 }
821 }
822