fbt.c revision 254268
1245700Snwhitehorn/* 2245700Snwhitehorn * CDDL HEADER START 3245700Snwhitehorn * 4245700Snwhitehorn * The contents of this file are subject to the terms of the 5245700Snwhitehorn * Common Development and Distribution License (the "License"). 6245700Snwhitehorn * You may not use this file except in compliance with the License. 7245700Snwhitehorn * 8245700Snwhitehorn * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9245700Snwhitehorn * or http://www.opensolaris.org/os/licensing. 10245700Snwhitehorn * See the License for the specific language governing permissions 11245700Snwhitehorn * and limitations under the License. 12245700Snwhitehorn * 13245700Snwhitehorn * When distributing Covered Code, include this CDDL HEADER in each 14245700Snwhitehorn * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15245700Snwhitehorn * If applicable, add the following below this CDDL HEADER, with the 16245700Snwhitehorn * fields enclosed by brackets "[]" replaced with your own identifying 17245700Snwhitehorn * information: Portions Copyright [yyyy] [name of copyright owner] 18245700Snwhitehorn * 19245700Snwhitehorn * CDDL HEADER END 20245700Snwhitehorn * 21245700Snwhitehorn * Portions Copyright 2006-2008 John Birrell jb@freebsd.org 22245700Snwhitehorn * 23245700Snwhitehorn * $FreeBSD: head/sys/cddl/dev/fbt/fbt.c 254268 2013-08-13 03:10:39Z markj $ 24245700Snwhitehorn * 25245700Snwhitehorn */ 26245700Snwhitehorn 27245700Snwhitehorn/* 28245700Snwhitehorn * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 29245700Snwhitehorn * Use is subject to license terms. 30245700Snwhitehorn */ 31245700Snwhitehorn 32245700Snwhitehorn#include <sys/cdefs.h> 33245700Snwhitehorn#include <sys/param.h> 34245700Snwhitehorn#include <sys/systm.h> 35245700Snwhitehorn#include <sys/conf.h> 36245700Snwhitehorn#include <sys/cpuvar.h> 37245700Snwhitehorn#include <sys/fcntl.h> 38245700Snwhitehorn#include <sys/filio.h> 39245700Snwhitehorn#include <sys/kdb.h> 40245700Snwhitehorn#include <sys/kernel.h> 41245700Snwhitehorn#include <sys/kmem.h> 42245700Snwhitehorn#include <sys/kthread.h> 43245700Snwhitehorn#include <sys/limits.h> 44245700Snwhitehorn#include <sys/linker.h> 45245700Snwhitehorn#include <sys/lock.h> 46245700Snwhitehorn#include <sys/malloc.h> 47245700Snwhitehorn#include <sys/module.h> 48245700Snwhitehorn#include <sys/mutex.h> 49245700Snwhitehorn#include <sys/pcpu.h> 50245700Snwhitehorn#include <sys/poll.h> 51245700Snwhitehorn#include <sys/proc.h> 52245700Snwhitehorn#include <sys/selinfo.h> 53245700Snwhitehorn#include <sys/smp.h> 54245700Snwhitehorn#include <sys/syscall.h> 55245700Snwhitehorn#include <sys/sysent.h> 56245700Snwhitehorn#include <sys/sysproto.h> 57245700Snwhitehorn#include <sys/uio.h> 58245700Snwhitehorn#include <sys/unistd.h> 59245700Snwhitehorn#include <machine/stdarg.h> 60245700Snwhitehorn 61245700Snwhitehorn#include <sys/dtrace.h> 62245700Snwhitehorn#include <sys/dtrace_bsd.h> 63245700Snwhitehorn 64245700Snwhitehornstatic MALLOC_DEFINE(M_FBT, "fbt", "Function Boundary Tracing"); 65245700Snwhitehorn 66245700Snwhitehorn#define FBT_PUSHL_EBP 0x55 67245700Snwhitehorn#define FBT_MOVL_ESP_EBP0_V0 0x8b 68245700Snwhitehorn#define FBT_MOVL_ESP_EBP1_V0 0xec 69245700Snwhitehorn#define FBT_MOVL_ESP_EBP0_V1 0x89 70245700Snwhitehorn#define FBT_MOVL_ESP_EBP1_V1 0xe5 71245700Snwhitehorn#define FBT_REX_RSP_RBP 0x48 72245700Snwhitehorn 73245700Snwhitehorn#define FBT_POPL_EBP 0x5d 74245700Snwhitehorn#define FBT_RET 0xc3 75245700Snwhitehorn#define FBT_RET_IMM16 0xc2 76245700Snwhitehorn#define FBT_LEAVE 0xc9 77245700Snwhitehorn 78245796Snwhitehorn#ifdef __amd64__ 79245796Snwhitehorn#define FBT_PATCHVAL 0xcc 80245796Snwhitehorn#else 81245796Snwhitehorn#define FBT_PATCHVAL 0xf0 82245796Snwhitehorn#endif 83245700Snwhitehorn 84245700Snwhitehornstatic d_open_t fbt_open; 85245700Snwhitehornstatic int fbt_unload(void); 86245700Snwhitehornstatic void fbt_getargdesc(void *, dtrace_id_t, void *, dtrace_argdesc_t *); 87245700Snwhitehornstatic void fbt_provide_module(void *, modctl_t *); 88245700Snwhitehornstatic void fbt_destroy(void *, dtrace_id_t, void *); 89245700Snwhitehornstatic void fbt_enable(void *, dtrace_id_t, void *); 90245700Snwhitehornstatic void fbt_disable(void *, dtrace_id_t, void *); 91245700Snwhitehornstatic void fbt_load(void *); 92245700Snwhitehornstatic void fbt_suspend(void *, dtrace_id_t, void *); 93245700Snwhitehornstatic void fbt_resume(void *, dtrace_id_t, void *); 94245700Snwhitehorn 95245700Snwhitehorn#define FBT_ENTRY "entry" 96245700Snwhitehorn#define FBT_RETURN "return" 97245700Snwhitehorn#define FBT_ADDR2NDX(addr) ((((uintptr_t)(addr)) >> 4) & fbt_probetab_mask) 98245700Snwhitehorn#define FBT_PROBETAB_SIZE 0x8000 /* 32k entries -- 128K total */ 99245700Snwhitehorn 100245700Snwhitehornstatic struct cdevsw fbt_cdevsw = { 101245700Snwhitehorn .d_version = D_VERSION, 102245700Snwhitehorn .d_open = fbt_open, 103245700Snwhitehorn .d_name = "fbt", 104245700Snwhitehorn}; 105245700Snwhitehorn 106245700Snwhitehornstatic dtrace_pattr_t fbt_attr = { 107245700Snwhitehorn{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON }, 108245700Snwhitehorn{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN }, 109245700Snwhitehorn{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA }, 110245700Snwhitehorn{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON }, 111245701Snwhitehorn{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA }, 112273831Snwhitehorn}; 113245701Snwhitehorn 114245701Snwhitehornstatic dtrace_pops_t fbt_pops = { 115245701Snwhitehorn NULL, 116245700Snwhitehorn fbt_provide_module, 117245700Snwhitehorn fbt_enable, 118245700Snwhitehorn fbt_disable, 119245700Snwhitehorn fbt_suspend, 120245700Snwhitehorn fbt_resume, 121245700Snwhitehorn fbt_getargdesc, 122245700Snwhitehorn NULL, 123245700Snwhitehorn NULL, 124245700Snwhitehorn fbt_destroy 125245700Snwhitehorn}; 126245700Snwhitehorn 127245700Snwhitehorntypedef struct fbt_probe { 128245700Snwhitehorn struct fbt_probe *fbtp_hashnext; 129245700Snwhitehorn uint8_t *fbtp_patchpoint; 130245700Snwhitehorn int8_t fbtp_rval; 131245700Snwhitehorn uint8_t fbtp_patchval; 132245700Snwhitehorn uint8_t fbtp_savedval; 133245700Snwhitehorn uintptr_t fbtp_roffset; 134245700Snwhitehorn dtrace_id_t fbtp_id; 135245700Snwhitehorn const char *fbtp_name; 136245700Snwhitehorn modctl_t *fbtp_ctl; 137245700Snwhitehorn int fbtp_loadcnt; 138245701Snwhitehorn int fbtp_primary; 139245700Snwhitehorn int fbtp_invop_cnt; 140245700Snwhitehorn int fbtp_symindx; 141245700Snwhitehorn struct fbt_probe *fbtp_next; 142245700Snwhitehorn} fbt_probe_t; 143245700Snwhitehorn 144245700Snwhitehornstatic struct cdev *fbt_cdev; 145245700Snwhitehornstatic dtrace_provider_id_t fbt_id; 146245700Snwhitehornstatic fbt_probe_t **fbt_probetab; 147245700Snwhitehornstatic int fbt_probetab_size; 148245700Snwhitehornstatic int fbt_probetab_mask; 149245700Snwhitehornstatic int fbt_verbose = 0; 150245700Snwhitehorn 151245700Snwhitehornstatic void 152245700Snwhitehornfbt_doubletrap(void) 153245700Snwhitehorn{ 154245700Snwhitehorn fbt_probe_t *fbt; 155245700Snwhitehorn int i; 156245700Snwhitehorn 157245700Snwhitehorn for (i = 0; i < fbt_probetab_size; i++) { 158245700Snwhitehorn fbt = fbt_probetab[i]; 159245700Snwhitehorn 160245700Snwhitehorn for (; fbt != NULL; fbt = fbt->fbtp_next) 161245700Snwhitehorn *fbt->fbtp_patchpoint = fbt->fbtp_savedval; 162245700Snwhitehorn } 163245700Snwhitehorn} 164245700Snwhitehorn 165245700Snwhitehornstatic int 166245700Snwhitehornfbt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t rval) 167245700Snwhitehorn{ 168245700Snwhitehorn solaris_cpu_t *cpu = &solaris_cpu[curcpu]; 169245700Snwhitehorn uintptr_t stack0, stack1, stack2, stack3, stack4; 170245700Snwhitehorn fbt_probe_t *fbt = fbt_probetab[FBT_ADDR2NDX(addr)]; 171245700Snwhitehorn 172245700Snwhitehorn for (; fbt != NULL; fbt = fbt->fbtp_hashnext) { 173245700Snwhitehorn if ((uintptr_t)fbt->fbtp_patchpoint == addr) { 174245700Snwhitehorn fbt->fbtp_invop_cnt++; 175245700Snwhitehorn if (fbt->fbtp_roffset == 0) { 176245700Snwhitehorn int i = 0; 177245700Snwhitehorn /* 178245700Snwhitehorn * When accessing the arguments on the stack, 179245700Snwhitehorn * we must protect against accessing beyond 180245700Snwhitehorn * the stack. We can safely set NOFAULT here 181245700Snwhitehorn * -- we know that interrupts are already 182245700Snwhitehorn * disabled. 183245700Snwhitehorn */ 184245700Snwhitehorn DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); 185245796Snwhitehorn cpu->cpu_dtrace_caller = stack[i++]; 186245700Snwhitehorn stack0 = stack[i++]; 187245700Snwhitehorn stack1 = stack[i++]; 188245700Snwhitehorn stack2 = stack[i++]; 189245700Snwhitehorn stack3 = stack[i++]; 190245700Snwhitehorn stack4 = stack[i++]; 191245700Snwhitehorn DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT | 192245700Snwhitehorn CPU_DTRACE_BADADDR); 193245700Snwhitehorn 194245796Snwhitehorn dtrace_probe(fbt->fbtp_id, stack0, stack1, 195245700Snwhitehorn stack2, stack3, stack4); 196245700Snwhitehorn 197245700Snwhitehorn cpu->cpu_dtrace_caller = 0; 198245700Snwhitehorn } else { 199245700Snwhitehorn#ifdef __amd64__ 200245700Snwhitehorn /* 201245700Snwhitehorn * On amd64, we instrument the ret, not the 202245700Snwhitehorn * leave. We therefore need to set the caller 203245700Snwhitehorn * to assure that the top frame of a stack() 204245700Snwhitehorn * action is correct. 205245796Snwhitehorn */ 206245796Snwhitehorn DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); 207245796Snwhitehorn cpu->cpu_dtrace_caller = stack[0]; 208245796Snwhitehorn DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT | 209245796Snwhitehorn CPU_DTRACE_BADADDR); 210245700Snwhitehorn#endif 211245700Snwhitehorn 212245700Snwhitehorn dtrace_probe(fbt->fbtp_id, fbt->fbtp_roffset, 213245700Snwhitehorn rval, 0, 0, 0); 214 cpu->cpu_dtrace_caller = 0; 215 } 216 217 return (fbt->fbtp_rval); 218 } 219 } 220 221 return (0); 222} 223 224static int 225fbt_provide_module_function(linker_file_t lf, int symindx, 226 linker_symval_t *symval, void *opaque) 227{ 228 char *modname = opaque; 229 const char *name = symval->name; 230 fbt_probe_t *fbt, *retfbt; 231 int j; 232 int size; 233 u_int8_t *instr, *limit; 234 235 if (strncmp(name, "dtrace_", 7) == 0 && 236 strncmp(name, "dtrace_safe_", 12) != 0) { 237 /* 238 * Anything beginning with "dtrace_" may be called 239 * from probe context unless it explicitly indicates 240 * that it won't be called from probe context by 241 * using the prefix "dtrace_safe_". 242 */ 243 return (0); 244 } 245 246 if (name[0] == '_' && name[1] == '_') 247 return (0); 248 249 size = symval->size; 250 251 instr = (u_int8_t *) symval->value; 252 limit = (u_int8_t *) symval->value + symval->size; 253 254#ifdef __amd64__ 255 while (instr < limit) { 256 if (*instr == FBT_PUSHL_EBP) 257 break; 258 259 if ((size = dtrace_instr_size(instr)) <= 0) 260 break; 261 262 instr += size; 263 } 264 265 if (instr >= limit || *instr != FBT_PUSHL_EBP) { 266 /* 267 * We either don't save the frame pointer in this 268 * function, or we ran into some disassembly 269 * screw-up. Either way, we bail. 270 */ 271 return (0); 272 } 273#else 274 if (instr[0] != FBT_PUSHL_EBP) 275 return (0); 276 277 if (!(instr[1] == FBT_MOVL_ESP_EBP0_V0 && 278 instr[2] == FBT_MOVL_ESP_EBP1_V0) && 279 !(instr[1] == FBT_MOVL_ESP_EBP0_V1 && 280 instr[2] == FBT_MOVL_ESP_EBP1_V1)) 281 return (0); 282#endif 283 284 fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO); 285 fbt->fbtp_name = name; 286 fbt->fbtp_id = dtrace_probe_create(fbt_id, modname, 287 name, FBT_ENTRY, 3, fbt); 288 fbt->fbtp_patchpoint = instr; 289 fbt->fbtp_ctl = lf; 290 fbt->fbtp_loadcnt = lf->loadcnt; 291 fbt->fbtp_rval = DTRACE_INVOP_PUSHL_EBP; 292 fbt->fbtp_savedval = *instr; 293 fbt->fbtp_patchval = FBT_PATCHVAL; 294 fbt->fbtp_symindx = symindx; 295 296 fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)]; 297 fbt_probetab[FBT_ADDR2NDX(instr)] = fbt; 298 299 lf->fbt_nentries++; 300 301 retfbt = NULL; 302again: 303 if (instr >= limit) 304 return (0); 305 306 /* 307 * If this disassembly fails, then we've likely walked off into 308 * a jump table or some other unsuitable area. Bail out of the 309 * disassembly now. 310 */ 311 if ((size = dtrace_instr_size(instr)) <= 0) 312 return (0); 313 314#ifdef __amd64__ 315 /* 316 * We only instrument "ret" on amd64 -- we don't yet instrument 317 * ret imm16, largely because the compiler doesn't seem to 318 * (yet) emit them in the kernel... 319 */ 320 if (*instr != FBT_RET) { 321 instr += size; 322 goto again; 323 } 324#else 325 if (!(size == 1 && 326 (*instr == FBT_POPL_EBP || *instr == FBT_LEAVE) && 327 (*(instr + 1) == FBT_RET || 328 *(instr + 1) == FBT_RET_IMM16))) { 329 instr += size; 330 goto again; 331 } 332#endif 333 334 /* 335 * We (desperately) want to avoid erroneously instrumenting a 336 * jump table, especially given that our markers are pretty 337 * short: two bytes on x86, and just one byte on amd64. To 338 * determine if we're looking at a true instruction sequence 339 * or an inline jump table that happens to contain the same 340 * byte sequences, we resort to some heuristic sleeze: we 341 * treat this instruction as being contained within a pointer, 342 * and see if that pointer points to within the body of the 343 * function. If it does, we refuse to instrument it. 344 */ 345 for (j = 0; j < sizeof (uintptr_t); j++) { 346 caddr_t check = (caddr_t) instr - j; 347 uint8_t *ptr; 348 349 if (check < symval->value) 350 break; 351 352 if (check + sizeof (caddr_t) > (caddr_t)limit) 353 continue; 354 355 ptr = *(uint8_t **)check; 356 357 if (ptr >= (uint8_t *) symval->value && ptr < limit) { 358 instr += size; 359 goto again; 360 } 361 } 362 363 /* 364 * We have a winner! 365 */ 366 fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO); 367 fbt->fbtp_name = name; 368 369 if (retfbt == NULL) { 370 fbt->fbtp_id = dtrace_probe_create(fbt_id, modname, 371 name, FBT_RETURN, 3, fbt); 372 } else { 373 retfbt->fbtp_next = fbt; 374 fbt->fbtp_id = retfbt->fbtp_id; 375 } 376 377 retfbt = fbt; 378 fbt->fbtp_patchpoint = instr; 379 fbt->fbtp_ctl = lf; 380 fbt->fbtp_loadcnt = lf->loadcnt; 381 fbt->fbtp_symindx = symindx; 382 383#ifndef __amd64__ 384 if (*instr == FBT_POPL_EBP) { 385 fbt->fbtp_rval = DTRACE_INVOP_POPL_EBP; 386 } else { 387 ASSERT(*instr == FBT_LEAVE); 388 fbt->fbtp_rval = DTRACE_INVOP_LEAVE; 389 } 390 fbt->fbtp_roffset = 391 (uintptr_t)(instr - (uint8_t *) symval->value) + 1; 392 393#else 394 ASSERT(*instr == FBT_RET); 395 fbt->fbtp_rval = DTRACE_INVOP_RET; 396 fbt->fbtp_roffset = 397 (uintptr_t)(instr - (uint8_t *) symval->value); 398#endif 399 400 fbt->fbtp_savedval = *instr; 401 fbt->fbtp_patchval = FBT_PATCHVAL; 402 fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)]; 403 fbt_probetab[FBT_ADDR2NDX(instr)] = fbt; 404 405 lf->fbt_nentries++; 406 407 instr += size; 408 goto again; 409} 410 411static void 412fbt_provide_module(void *arg, modctl_t *lf) 413{ 414 char modname[MAXPATHLEN]; 415 int i; 416 size_t len; 417 418 strlcpy(modname, lf->filename, sizeof(modname)); 419 len = strlen(modname); 420 if (len > 3 && strcmp(modname + len - 3, ".ko") == 0) 421 modname[len - 3] = '\0'; 422 423 /* 424 * Employees of dtrace and their families are ineligible. Void 425 * where prohibited. 426 */ 427 if (strcmp(modname, "dtrace") == 0) 428 return; 429 430 /* 431 * The cyclic timer subsystem can be built as a module and DTrace 432 * depends on that, so it is ineligible too. 433 */ 434 if (strcmp(modname, "cyclic") == 0) 435 return; 436 437 /* 438 * To register with DTrace, a module must list 'dtrace' as a 439 * dependency in order for the kernel linker to resolve 440 * symbols like dtrace_register(). All modules with such a 441 * dependency are ineligible for FBT tracing. 442 */ 443 for (i = 0; i < lf->ndeps; i++) 444 if (strncmp(lf->deps[i]->filename, "dtrace", 6) == 0) 445 return; 446 447 if (lf->fbt_nentries) { 448 /* 449 * This module has some FBT entries allocated; we're afraid 450 * to screw with it. 451 */ 452 return; 453 } 454 455 /* 456 * List the functions in the module and the symbol values. 457 */ 458 (void) linker_file_function_listall(lf, fbt_provide_module_function, modname); 459} 460 461static void 462fbt_destroy(void *arg, dtrace_id_t id, void *parg) 463{ 464 fbt_probe_t *fbt = parg, *next, *hash, *last; 465 modctl_t *ctl; 466 int ndx; 467 468 do { 469 ctl = fbt->fbtp_ctl; 470 471 ctl->fbt_nentries--; 472 473 /* 474 * Now we need to remove this probe from the fbt_probetab. 475 */ 476 ndx = FBT_ADDR2NDX(fbt->fbtp_patchpoint); 477 last = NULL; 478 hash = fbt_probetab[ndx]; 479 480 while (hash != fbt) { 481 ASSERT(hash != NULL); 482 last = hash; 483 hash = hash->fbtp_hashnext; 484 } 485 486 if (last != NULL) { 487 last->fbtp_hashnext = fbt->fbtp_hashnext; 488 } else { 489 fbt_probetab[ndx] = fbt->fbtp_hashnext; 490 } 491 492 next = fbt->fbtp_next; 493 free(fbt, M_FBT); 494 495 fbt = next; 496 } while (fbt != NULL); 497} 498 499static void 500fbt_enable(void *arg, dtrace_id_t id, void *parg) 501{ 502 fbt_probe_t *fbt = parg; 503 modctl_t *ctl = fbt->fbtp_ctl; 504 505 ctl->nenabled++; 506 507 /* 508 * Now check that our modctl has the expected load count. If it 509 * doesn't, this module must have been unloaded and reloaded -- and 510 * we're not going to touch it. 511 */ 512 if (ctl->loadcnt != fbt->fbtp_loadcnt) { 513 if (fbt_verbose) { 514 printf("fbt is failing for probe %s " 515 "(module %s reloaded)", 516 fbt->fbtp_name, ctl->filename); 517 } 518 519 return; 520 } 521 522 for (; fbt != NULL; fbt = fbt->fbtp_next) { 523 *fbt->fbtp_patchpoint = fbt->fbtp_patchval; 524 } 525} 526 527static void 528fbt_disable(void *arg, dtrace_id_t id, void *parg) 529{ 530 fbt_probe_t *fbt = parg; 531 modctl_t *ctl = fbt->fbtp_ctl; 532 533 ASSERT(ctl->nenabled > 0); 534 ctl->nenabled--; 535 536 if ((ctl->loadcnt != fbt->fbtp_loadcnt)) 537 return; 538 539 for (; fbt != NULL; fbt = fbt->fbtp_next) 540 *fbt->fbtp_patchpoint = fbt->fbtp_savedval; 541} 542 543static void 544fbt_suspend(void *arg, dtrace_id_t id, void *parg) 545{ 546 fbt_probe_t *fbt = parg; 547 modctl_t *ctl = fbt->fbtp_ctl; 548 549 ASSERT(ctl->nenabled > 0); 550 551 if ((ctl->loadcnt != fbt->fbtp_loadcnt)) 552 return; 553 554 for (; fbt != NULL; fbt = fbt->fbtp_next) 555 *fbt->fbtp_patchpoint = fbt->fbtp_savedval; 556} 557 558static void 559fbt_resume(void *arg, dtrace_id_t id, void *parg) 560{ 561 fbt_probe_t *fbt = parg; 562 modctl_t *ctl = fbt->fbtp_ctl; 563 564 ASSERT(ctl->nenabled > 0); 565 566 if ((ctl->loadcnt != fbt->fbtp_loadcnt)) 567 return; 568 569 for (; fbt != NULL; fbt = fbt->fbtp_next) 570 *fbt->fbtp_patchpoint = fbt->fbtp_patchval; 571} 572 573static int 574fbt_ctfoff_init(modctl_t *lf, linker_ctf_t *lc) 575{ 576 const Elf_Sym *symp = lc->symtab;; 577 const char *name; 578 const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab; 579 const uint8_t *ctfdata = lc->ctftab + sizeof(ctf_header_t); 580 int i; 581 uint32_t *ctfoff; 582 uint32_t objtoff = hp->cth_objtoff; 583 uint32_t funcoff = hp->cth_funcoff; 584 ushort_t info; 585 ushort_t vlen; 586 587 /* Sanity check. */ 588 if (hp->cth_magic != CTF_MAGIC) { 589 printf("Bad magic value in CTF data of '%s'\n",lf->pathname); 590 return (EINVAL); 591 } 592 593 if (lc->symtab == NULL) { 594 printf("No symbol table in '%s'\n",lf->pathname); 595 return (EINVAL); 596 } 597 598 if ((ctfoff = malloc(sizeof(uint32_t) * lc->nsym, M_LINKER, M_WAITOK)) == NULL) 599 return (ENOMEM); 600 601 *lc->ctfoffp = ctfoff; 602 603 for (i = 0; i < lc->nsym; i++, ctfoff++, symp++) { 604 if (symp->st_name == 0 || symp->st_shndx == SHN_UNDEF) { 605 *ctfoff = 0xffffffff; 606 continue; 607 } 608 609 if (symp->st_name < lc->strcnt) 610 name = lc->strtab + symp->st_name; 611 else 612 name = "(?)"; 613 614 switch (ELF_ST_TYPE(symp->st_info)) { 615 case STT_OBJECT: 616 if (objtoff >= hp->cth_funcoff || 617 (symp->st_shndx == SHN_ABS && symp->st_value == 0)) { 618 *ctfoff = 0xffffffff; 619 break; 620 } 621 622 *ctfoff = objtoff; 623 objtoff += sizeof (ushort_t); 624 break; 625 626 case STT_FUNC: 627 if (funcoff >= hp->cth_typeoff) { 628 *ctfoff = 0xffffffff; 629 break; 630 } 631 632 *ctfoff = funcoff; 633 634 info = *((const ushort_t *)(ctfdata + funcoff)); 635 vlen = CTF_INFO_VLEN(info); 636 637 /* 638 * If we encounter a zero pad at the end, just skip it. 639 * Otherwise skip over the function and its return type 640 * (+2) and the argument list (vlen). 641 */ 642 if (CTF_INFO_KIND(info) == CTF_K_UNKNOWN && vlen == 0) 643 funcoff += sizeof (ushort_t); /* skip pad */ 644 else 645 funcoff += sizeof (ushort_t) * (vlen + 2); 646 break; 647 648 default: 649 *ctfoff = 0xffffffff; 650 break; 651 } 652 } 653 654 return (0); 655} 656 657static ssize_t 658fbt_get_ctt_size(uint8_t version, const ctf_type_t *tp, ssize_t *sizep, 659 ssize_t *incrementp) 660{ 661 ssize_t size, increment; 662 663 if (version > CTF_VERSION_1 && 664 tp->ctt_size == CTF_LSIZE_SENT) { 665 size = CTF_TYPE_LSIZE(tp); 666 increment = sizeof (ctf_type_t); 667 } else { 668 size = tp->ctt_size; 669 increment = sizeof (ctf_stype_t); 670 } 671 672 if (sizep) 673 *sizep = size; 674 if (incrementp) 675 *incrementp = increment; 676 677 return (size); 678} 679 680static int 681fbt_typoff_init(linker_ctf_t *lc) 682{ 683 const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab; 684 const ctf_type_t *tbuf; 685 const ctf_type_t *tend; 686 const ctf_type_t *tp; 687 const uint8_t *ctfdata = lc->ctftab + sizeof(ctf_header_t); 688 int ctf_typemax = 0; 689 uint32_t *xp; 690 ulong_t pop[CTF_K_MAX + 1] = { 0 }; 691 692 693 /* Sanity check. */ 694 if (hp->cth_magic != CTF_MAGIC) 695 return (EINVAL); 696 697 tbuf = (const ctf_type_t *) (ctfdata + hp->cth_typeoff); 698 tend = (const ctf_type_t *) (ctfdata + hp->cth_stroff); 699 700 int child = hp->cth_parname != 0; 701 702 /* 703 * We make two passes through the entire type section. In this first 704 * pass, we count the number of each type and the total number of types. 705 */ 706 for (tp = tbuf; tp < tend; ctf_typemax++) { 707 ushort_t kind = CTF_INFO_KIND(tp->ctt_info); 708 ulong_t vlen = CTF_INFO_VLEN(tp->ctt_info); 709 ssize_t size, increment; 710 711 size_t vbytes; 712 uint_t n; 713 714 (void) fbt_get_ctt_size(hp->cth_version, tp, &size, &increment); 715 716 switch (kind) { 717 case CTF_K_INTEGER: 718 case CTF_K_FLOAT: 719 vbytes = sizeof (uint_t); 720 break; 721 case CTF_K_ARRAY: 722 vbytes = sizeof (ctf_array_t); 723 break; 724 case CTF_K_FUNCTION: 725 vbytes = sizeof (ushort_t) * (vlen + (vlen & 1)); 726 break; 727 case CTF_K_STRUCT: 728 case CTF_K_UNION: 729 if (size < CTF_LSTRUCT_THRESH) { 730 ctf_member_t *mp = (ctf_member_t *) 731 ((uintptr_t)tp + increment); 732 733 vbytes = sizeof (ctf_member_t) * vlen; 734 for (n = vlen; n != 0; n--, mp++) 735 child |= CTF_TYPE_ISCHILD(mp->ctm_type); 736 } else { 737 ctf_lmember_t *lmp = (ctf_lmember_t *) 738 ((uintptr_t)tp + increment); 739 740 vbytes = sizeof (ctf_lmember_t) * vlen; 741 for (n = vlen; n != 0; n--, lmp++) 742 child |= 743 CTF_TYPE_ISCHILD(lmp->ctlm_type); 744 } 745 break; 746 case CTF_K_ENUM: 747 vbytes = sizeof (ctf_enum_t) * vlen; 748 break; 749 case CTF_K_FORWARD: 750 /* 751 * For forward declarations, ctt_type is the CTF_K_* 752 * kind for the tag, so bump that population count too. 753 * If ctt_type is unknown, treat the tag as a struct. 754 */ 755 if (tp->ctt_type == CTF_K_UNKNOWN || 756 tp->ctt_type >= CTF_K_MAX) 757 pop[CTF_K_STRUCT]++; 758 else 759 pop[tp->ctt_type]++; 760 /*FALLTHRU*/ 761 case CTF_K_UNKNOWN: 762 vbytes = 0; 763 break; 764 case CTF_K_POINTER: 765 case CTF_K_TYPEDEF: 766 case CTF_K_VOLATILE: 767 case CTF_K_CONST: 768 case CTF_K_RESTRICT: 769 child |= CTF_TYPE_ISCHILD(tp->ctt_type); 770 vbytes = 0; 771 break; 772 default: 773 printf("%s(%d): detected invalid CTF kind -- %u\n", __func__, __LINE__, kind); 774 return (EIO); 775 } 776 tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes); 777 pop[kind]++; 778 } 779 780 /* account for a sentinel value below */ 781 ctf_typemax++; 782 *lc->typlenp = ctf_typemax; 783 784 if ((xp = malloc(sizeof(uint32_t) * ctf_typemax, M_LINKER, M_ZERO | M_WAITOK)) == NULL) 785 return (ENOMEM); 786 787 *lc->typoffp = xp; 788 789 /* type id 0 is used as a sentinel value */ 790 *xp++ = 0; 791 792 /* 793 * In the second pass, fill in the type offset. 794 */ 795 for (tp = tbuf; tp < tend; xp++) { 796 ushort_t kind = CTF_INFO_KIND(tp->ctt_info); 797 ulong_t vlen = CTF_INFO_VLEN(tp->ctt_info); 798 ssize_t size, increment; 799 800 size_t vbytes; 801 uint_t n; 802 803 (void) fbt_get_ctt_size(hp->cth_version, tp, &size, &increment); 804 805 switch (kind) { 806 case CTF_K_INTEGER: 807 case CTF_K_FLOAT: 808 vbytes = sizeof (uint_t); 809 break; 810 case CTF_K_ARRAY: 811 vbytes = sizeof (ctf_array_t); 812 break; 813 case CTF_K_FUNCTION: 814 vbytes = sizeof (ushort_t) * (vlen + (vlen & 1)); 815 break; 816 case CTF_K_STRUCT: 817 case CTF_K_UNION: 818 if (size < CTF_LSTRUCT_THRESH) { 819 ctf_member_t *mp = (ctf_member_t *) 820 ((uintptr_t)tp + increment); 821 822 vbytes = sizeof (ctf_member_t) * vlen; 823 for (n = vlen; n != 0; n--, mp++) 824 child |= CTF_TYPE_ISCHILD(mp->ctm_type); 825 } else { 826 ctf_lmember_t *lmp = (ctf_lmember_t *) 827 ((uintptr_t)tp + increment); 828 829 vbytes = sizeof (ctf_lmember_t) * vlen; 830 for (n = vlen; n != 0; n--, lmp++) 831 child |= 832 CTF_TYPE_ISCHILD(lmp->ctlm_type); 833 } 834 break; 835 case CTF_K_ENUM: 836 vbytes = sizeof (ctf_enum_t) * vlen; 837 break; 838 case CTF_K_FORWARD: 839 case CTF_K_UNKNOWN: 840 vbytes = 0; 841 break; 842 case CTF_K_POINTER: 843 case CTF_K_TYPEDEF: 844 case CTF_K_VOLATILE: 845 case CTF_K_CONST: 846 case CTF_K_RESTRICT: 847 vbytes = 0; 848 break; 849 default: 850 printf("%s(%d): detected invalid CTF kind -- %u\n", __func__, __LINE__, kind); 851 return (EIO); 852 } 853 *xp = (uint32_t)((uintptr_t) tp - (uintptr_t) ctfdata); 854 tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes); 855 } 856 857 return (0); 858} 859 860/* 861 * CTF Declaration Stack 862 * 863 * In order to implement ctf_type_name(), we must convert a type graph back 864 * into a C type declaration. Unfortunately, a type graph represents a storage 865 * class ordering of the type whereas a type declaration must obey the C rules 866 * for operator precedence, and the two orderings are frequently in conflict. 867 * For example, consider these CTF type graphs and their C declarations: 868 * 869 * CTF_K_POINTER -> CTF_K_FUNCTION -> CTF_K_INTEGER : int (*)() 870 * CTF_K_POINTER -> CTF_K_ARRAY -> CTF_K_INTEGER : int (*)[] 871 * 872 * In each case, parentheses are used to raise operator * to higher lexical 873 * precedence, so the string form of the C declaration cannot be constructed by 874 * walking the type graph links and forming the string from left to right. 875 * 876 * The functions in this file build a set of stacks from the type graph nodes 877 * corresponding to the C operator precedence levels in the appropriate order. 878 * The code in ctf_type_name() can then iterate over the levels and nodes in 879 * lexical precedence order and construct the final C declaration string. 880 */ 881typedef struct ctf_list { 882 struct ctf_list *l_prev; /* previous pointer or tail pointer */ 883 struct ctf_list *l_next; /* next pointer or head pointer */ 884} ctf_list_t; 885 886#define ctf_list_prev(elem) ((void *)(((ctf_list_t *)(elem))->l_prev)) 887#define ctf_list_next(elem) ((void *)(((ctf_list_t *)(elem))->l_next)) 888 889typedef enum { 890 CTF_PREC_BASE, 891 CTF_PREC_POINTER, 892 CTF_PREC_ARRAY, 893 CTF_PREC_FUNCTION, 894 CTF_PREC_MAX 895} ctf_decl_prec_t; 896 897typedef struct ctf_decl_node { 898 ctf_list_t cd_list; /* linked list pointers */ 899 ctf_id_t cd_type; /* type identifier */ 900 uint_t cd_kind; /* type kind */ 901 uint_t cd_n; /* type dimension if array */ 902} ctf_decl_node_t; 903 904typedef struct ctf_decl { 905 ctf_list_t cd_nodes[CTF_PREC_MAX]; /* declaration node stacks */ 906 int cd_order[CTF_PREC_MAX]; /* storage order of decls */ 907 ctf_decl_prec_t cd_qualp; /* qualifier precision */ 908 ctf_decl_prec_t cd_ordp; /* ordered precision */ 909 char *cd_buf; /* buffer for output */ 910 char *cd_ptr; /* buffer location */ 911 char *cd_end; /* buffer limit */ 912 size_t cd_len; /* buffer space required */ 913 int cd_err; /* saved error value */ 914} ctf_decl_t; 915 916/* 917 * Simple doubly-linked list append routine. This implementation assumes that 918 * each list element contains an embedded ctf_list_t as the first member. 919 * An additional ctf_list_t is used to store the head (l_next) and tail 920 * (l_prev) pointers. The current head and tail list elements have their 921 * previous and next pointers set to NULL, respectively. 922 */ 923static void 924ctf_list_append(ctf_list_t *lp, void *new) 925{ 926 ctf_list_t *p = lp->l_prev; /* p = tail list element */ 927 ctf_list_t *q = new; /* q = new list element */ 928 929 lp->l_prev = q; 930 q->l_prev = p; 931 q->l_next = NULL; 932 933 if (p != NULL) 934 p->l_next = q; 935 else 936 lp->l_next = q; 937} 938 939/* 940 * Prepend the specified existing element to the given ctf_list_t. The 941 * existing pointer should be pointing at a struct with embedded ctf_list_t. 942 */ 943static void 944ctf_list_prepend(ctf_list_t *lp, void *new) 945{ 946 ctf_list_t *p = new; /* p = new list element */ 947 ctf_list_t *q = lp->l_next; /* q = head list element */ 948 949 lp->l_next = p; 950 p->l_prev = NULL; 951 p->l_next = q; 952 953 if (q != NULL) 954 q->l_prev = p; 955 else 956 lp->l_prev = p; 957} 958 959static void 960ctf_decl_init(ctf_decl_t *cd, char *buf, size_t len) 961{ 962 int i; 963 964 bzero(cd, sizeof (ctf_decl_t)); 965 966 for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++) 967 cd->cd_order[i] = CTF_PREC_BASE - 1; 968 969 cd->cd_qualp = CTF_PREC_BASE; 970 cd->cd_ordp = CTF_PREC_BASE; 971 972 cd->cd_buf = buf; 973 cd->cd_ptr = buf; 974 cd->cd_end = buf + len; 975} 976 977static void 978ctf_decl_fini(ctf_decl_t *cd) 979{ 980 ctf_decl_node_t *cdp, *ndp; 981 int i; 982 983 for (i = CTF_PREC_BASE; i < CTF_PREC_MAX; i++) { 984 for (cdp = ctf_list_next(&cd->cd_nodes[i]); 985 cdp != NULL; cdp = ndp) { 986 ndp = ctf_list_next(cdp); 987 free(cdp, M_FBT); 988 } 989 } 990} 991 992static const ctf_type_t * 993ctf_lookup_by_id(linker_ctf_t *lc, ctf_id_t type) 994{ 995 const ctf_type_t *tp; 996 uint32_t offset; 997 uint32_t *typoff = *lc->typoffp; 998 999 if (type >= *lc->typlenp) { 1000 printf("%s(%d): type %d exceeds max %ld\n",__func__,__LINE__,(int) type,*lc->typlenp); 1001 return(NULL); 1002 } 1003 1004 /* Check if the type isn't cross-referenced. */ 1005 if ((offset = typoff[type]) == 0) { 1006 printf("%s(%d): type %d isn't cross referenced\n",__func__,__LINE__, (int) type); 1007 return(NULL); 1008 } 1009 1010 tp = (const ctf_type_t *)(lc->ctftab + offset + sizeof(ctf_header_t)); 1011 1012 return (tp); 1013} 1014 1015static void 1016fbt_array_info(linker_ctf_t *lc, ctf_id_t type, ctf_arinfo_t *arp) 1017{ 1018 const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab; 1019 const ctf_type_t *tp; 1020 const ctf_array_t *ap; 1021 ssize_t increment; 1022 1023 bzero(arp, sizeof(*arp)); 1024 1025 if ((tp = ctf_lookup_by_id(lc, type)) == NULL) 1026 return; 1027 1028 if (CTF_INFO_KIND(tp->ctt_info) != CTF_K_ARRAY) 1029 return; 1030 1031 (void) fbt_get_ctt_size(hp->cth_version, tp, NULL, &increment); 1032 1033 ap = (const ctf_array_t *)((uintptr_t)tp + increment); 1034 arp->ctr_contents = ap->cta_contents; 1035 arp->ctr_index = ap->cta_index; 1036 arp->ctr_nelems = ap->cta_nelems; 1037} 1038 1039static const char * 1040ctf_strptr(linker_ctf_t *lc, int name) 1041{ 1042 const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab;; 1043 const char *strp = ""; 1044 1045 if (name < 0 || name >= hp->cth_strlen) 1046 return(strp); 1047 1048 strp = (const char *)(lc->ctftab + hp->cth_stroff + name + sizeof(ctf_header_t)); 1049 1050 return (strp); 1051} 1052 1053static void 1054ctf_decl_push(ctf_decl_t *cd, linker_ctf_t *lc, ctf_id_t type) 1055{ 1056 ctf_decl_node_t *cdp; 1057 ctf_decl_prec_t prec; 1058 uint_t kind, n = 1; 1059 int is_qual = 0; 1060 1061 const ctf_type_t *tp; 1062 ctf_arinfo_t ar; 1063 1064 if ((tp = ctf_lookup_by_id(lc, type)) == NULL) { 1065 cd->cd_err = ENOENT; 1066 return; 1067 } 1068 1069 switch (kind = CTF_INFO_KIND(tp->ctt_info)) { 1070 case CTF_K_ARRAY: 1071 fbt_array_info(lc, type, &ar); 1072 ctf_decl_push(cd, lc, ar.ctr_contents); 1073 n = ar.ctr_nelems; 1074 prec = CTF_PREC_ARRAY; 1075 break; 1076 1077 case CTF_K_TYPEDEF: 1078 if (ctf_strptr(lc, tp->ctt_name)[0] == '\0') { 1079 ctf_decl_push(cd, lc, tp->ctt_type); 1080 return; 1081 } 1082 prec = CTF_PREC_BASE; 1083 break; 1084 1085 case CTF_K_FUNCTION: 1086 ctf_decl_push(cd, lc, tp->ctt_type); 1087 prec = CTF_PREC_FUNCTION; 1088 break; 1089 1090 case CTF_K_POINTER: 1091 ctf_decl_push(cd, lc, tp->ctt_type); 1092 prec = CTF_PREC_POINTER; 1093 break; 1094 1095 case CTF_K_VOLATILE: 1096 case CTF_K_CONST: 1097 case CTF_K_RESTRICT: 1098 ctf_decl_push(cd, lc, tp->ctt_type); 1099 prec = cd->cd_qualp; 1100 is_qual++; 1101 break; 1102 1103 default: 1104 prec = CTF_PREC_BASE; 1105 } 1106 1107 if ((cdp = malloc(sizeof (ctf_decl_node_t), M_FBT, M_WAITOK)) == NULL) { 1108 cd->cd_err = EAGAIN; 1109 return; 1110 } 1111 1112 cdp->cd_type = type; 1113 cdp->cd_kind = kind; 1114 cdp->cd_n = n; 1115 1116 if (ctf_list_next(&cd->cd_nodes[prec]) == NULL) 1117 cd->cd_order[prec] = cd->cd_ordp++; 1118 1119 /* 1120 * Reset cd_qualp to the highest precedence level that we've seen so 1121 * far that can be qualified (CTF_PREC_BASE or CTF_PREC_POINTER). 1122 */ 1123 if (prec > cd->cd_qualp && prec < CTF_PREC_ARRAY) 1124 cd->cd_qualp = prec; 1125 1126 /* 1127 * C array declarators are ordered inside out so prepend them. Also by 1128 * convention qualifiers of base types precede the type specifier (e.g. 1129 * const int vs. int const) even though the two forms are equivalent. 1130 */ 1131 if (kind == CTF_K_ARRAY || (is_qual && prec == CTF_PREC_BASE)) 1132 ctf_list_prepend(&cd->cd_nodes[prec], cdp); 1133 else 1134 ctf_list_append(&cd->cd_nodes[prec], cdp); 1135} 1136 1137static void 1138ctf_decl_sprintf(ctf_decl_t *cd, const char *format, ...) 1139{ 1140 size_t len = (size_t)(cd->cd_end - cd->cd_ptr); 1141 va_list ap; 1142 size_t n; 1143 1144 va_start(ap, format); 1145 n = vsnprintf(cd->cd_ptr, len, format, ap); 1146 va_end(ap); 1147 1148 cd->cd_ptr += MIN(n, len); 1149 cd->cd_len += n; 1150} 1151 1152static ssize_t 1153fbt_type_name(linker_ctf_t *lc, ctf_id_t type, char *buf, size_t len) 1154{ 1155 ctf_decl_t cd; 1156 ctf_decl_node_t *cdp; 1157 ctf_decl_prec_t prec, lp, rp; 1158 int ptr, arr; 1159 uint_t k; 1160 1161 if (lc == NULL && type == CTF_ERR) 1162 return (-1); /* simplify caller code by permitting CTF_ERR */ 1163 1164 ctf_decl_init(&cd, buf, len); 1165 ctf_decl_push(&cd, lc, type); 1166 1167 if (cd.cd_err != 0) { 1168 ctf_decl_fini(&cd); 1169 return (-1); 1170 } 1171 1172 /* 1173 * If the type graph's order conflicts with lexical precedence order 1174 * for pointers or arrays, then we need to surround the declarations at 1175 * the corresponding lexical precedence with parentheses. This can 1176 * result in either a parenthesized pointer (*) as in int (*)() or 1177 * int (*)[], or in a parenthesized pointer and array as in int (*[])(). 1178 */ 1179 ptr = cd.cd_order[CTF_PREC_POINTER] > CTF_PREC_POINTER; 1180 arr = cd.cd_order[CTF_PREC_ARRAY] > CTF_PREC_ARRAY; 1181 1182 rp = arr ? CTF_PREC_ARRAY : ptr ? CTF_PREC_POINTER : -1; 1183 lp = ptr ? CTF_PREC_POINTER : arr ? CTF_PREC_ARRAY : -1; 1184 1185 k = CTF_K_POINTER; /* avoid leading whitespace (see below) */ 1186 1187 for (prec = CTF_PREC_BASE; prec < CTF_PREC_MAX; prec++) { 1188 for (cdp = ctf_list_next(&cd.cd_nodes[prec]); 1189 cdp != NULL; cdp = ctf_list_next(cdp)) { 1190 1191 const ctf_type_t *tp = 1192 ctf_lookup_by_id(lc, cdp->cd_type); 1193 const char *name = ctf_strptr(lc, tp->ctt_name); 1194 1195 if (k != CTF_K_POINTER && k != CTF_K_ARRAY) 1196 ctf_decl_sprintf(&cd, " "); 1197 1198 if (lp == prec) { 1199 ctf_decl_sprintf(&cd, "("); 1200 lp = -1; 1201 } 1202 1203 switch (cdp->cd_kind) { 1204 case CTF_K_INTEGER: 1205 case CTF_K_FLOAT: 1206 case CTF_K_TYPEDEF: 1207 ctf_decl_sprintf(&cd, "%s", name); 1208 break; 1209 case CTF_K_POINTER: 1210 ctf_decl_sprintf(&cd, "*"); 1211 break; 1212 case CTF_K_ARRAY: 1213 ctf_decl_sprintf(&cd, "[%u]", cdp->cd_n); 1214 break; 1215 case CTF_K_FUNCTION: 1216 ctf_decl_sprintf(&cd, "()"); 1217 break; 1218 case CTF_K_STRUCT: 1219 case CTF_K_FORWARD: 1220 ctf_decl_sprintf(&cd, "struct %s", name); 1221 break; 1222 case CTF_K_UNION: 1223 ctf_decl_sprintf(&cd, "union %s", name); 1224 break; 1225 case CTF_K_ENUM: 1226 ctf_decl_sprintf(&cd, "enum %s", name); 1227 break; 1228 case CTF_K_VOLATILE: 1229 ctf_decl_sprintf(&cd, "volatile"); 1230 break; 1231 case CTF_K_CONST: 1232 ctf_decl_sprintf(&cd, "const"); 1233 break; 1234 case CTF_K_RESTRICT: 1235 ctf_decl_sprintf(&cd, "restrict"); 1236 break; 1237 } 1238 1239 k = cdp->cd_kind; 1240 } 1241 1242 if (rp == prec) 1243 ctf_decl_sprintf(&cd, ")"); 1244 } 1245 1246 ctf_decl_fini(&cd); 1247 return (cd.cd_len); 1248} 1249 1250static void 1251fbt_getargdesc(void *arg __unused, dtrace_id_t id __unused, void *parg, dtrace_argdesc_t *desc) 1252{ 1253 const ushort_t *dp; 1254 fbt_probe_t *fbt = parg; 1255 linker_ctf_t lc; 1256 modctl_t *ctl = fbt->fbtp_ctl; 1257 int ndx = desc->dtargd_ndx; 1258 int symindx = fbt->fbtp_symindx; 1259 uint32_t *ctfoff; 1260 uint32_t offset; 1261 ushort_t info, kind, n; 1262 1263 if (fbt->fbtp_roffset != 0 && desc->dtargd_ndx == 0) { 1264 (void) strcpy(desc->dtargd_native, "int"); 1265 return; 1266 } 1267 1268 desc->dtargd_ndx = DTRACE_ARGNONE; 1269 1270 /* Get a pointer to the CTF data and it's length. */ 1271 if (linker_ctf_get(ctl, &lc) != 0) 1272 /* No CTF data? Something wrong? *shrug* */ 1273 return; 1274 1275 /* Check if this module hasn't been initialised yet. */ 1276 if (*lc.ctfoffp == NULL) { 1277 /* 1278 * Initialise the CTF object and function symindx to 1279 * byte offset array. 1280 */ 1281 if (fbt_ctfoff_init(ctl, &lc) != 0) 1282 return; 1283 1284 /* Initialise the CTF type to byte offset array. */ 1285 if (fbt_typoff_init(&lc) != 0) 1286 return; 1287 } 1288 1289 ctfoff = *lc.ctfoffp; 1290 1291 if (ctfoff == NULL || *lc.typoffp == NULL) 1292 return; 1293 1294 /* Check if the symbol index is out of range. */ 1295 if (symindx >= lc.nsym) 1296 return; 1297 1298 /* Check if the symbol isn't cross-referenced. */ 1299 if ((offset = ctfoff[symindx]) == 0xffffffff) 1300 return; 1301 1302 dp = (const ushort_t *)(lc.ctftab + offset + sizeof(ctf_header_t)); 1303 1304 info = *dp++; 1305 kind = CTF_INFO_KIND(info); 1306 n = CTF_INFO_VLEN(info); 1307 1308 if (kind == CTF_K_UNKNOWN && n == 0) { 1309 printf("%s(%d): Unknown function!\n",__func__,__LINE__); 1310 return; 1311 } 1312 1313 if (kind != CTF_K_FUNCTION) { 1314 printf("%s(%d): Expected a function!\n",__func__,__LINE__); 1315 return; 1316 } 1317 1318 if (fbt->fbtp_roffset != 0) { 1319 /* Only return type is available for args[1] in return probe. */ 1320 if (ndx > 1) 1321 return; 1322 ASSERT(ndx == 1); 1323 } else { 1324 /* Check if the requested argument doesn't exist. */ 1325 if (ndx >= n) 1326 return; 1327 1328 /* Skip the return type and arguments up to the one requested. */ 1329 dp += ndx + 1; 1330 } 1331 1332 if (fbt_type_name(&lc, *dp, desc->dtargd_native, sizeof(desc->dtargd_native)) > 0) 1333 desc->dtargd_ndx = ndx; 1334 1335 return; 1336} 1337 1338static int 1339fbt_linker_file_cb(linker_file_t lf, void *arg) 1340{ 1341 1342 fbt_provide_module(arg, lf); 1343 1344 return (0); 1345} 1346 1347static void 1348fbt_load(void *dummy) 1349{ 1350 /* Create the /dev/dtrace/fbt entry. */ 1351 fbt_cdev = make_dev(&fbt_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, 1352 "dtrace/fbt"); 1353 1354 /* Default the probe table size if not specified. */ 1355 if (fbt_probetab_size == 0) 1356 fbt_probetab_size = FBT_PROBETAB_SIZE; 1357 1358 /* Choose the hash mask for the probe table. */ 1359 fbt_probetab_mask = fbt_probetab_size - 1; 1360 1361 /* Allocate memory for the probe table. */ 1362 fbt_probetab = 1363 malloc(fbt_probetab_size * sizeof (fbt_probe_t *), M_FBT, M_WAITOK | M_ZERO); 1364 1365 dtrace_doubletrap_func = fbt_doubletrap; 1366 dtrace_invop_add(fbt_invop); 1367 1368 if (dtrace_register("fbt", &fbt_attr, DTRACE_PRIV_USER, 1369 NULL, &fbt_pops, NULL, &fbt_id) != 0) 1370 return; 1371 1372 /* Create probes for the kernel and already-loaded modules. */ 1373 linker_file_foreach(fbt_linker_file_cb, NULL); 1374} 1375 1376static int 1377fbt_unload() 1378{ 1379 int error = 0; 1380 1381 /* De-register the invalid opcode handler. */ 1382 dtrace_invop_remove(fbt_invop); 1383 1384 dtrace_doubletrap_func = NULL; 1385 1386 /* De-register this DTrace provider. */ 1387 if ((error = dtrace_unregister(fbt_id)) != 0) 1388 return (error); 1389 1390 /* Free the probe table. */ 1391 free(fbt_probetab, M_FBT); 1392 fbt_probetab = NULL; 1393 fbt_probetab_mask = 0; 1394 1395 destroy_dev(fbt_cdev); 1396 1397 return (error); 1398} 1399 1400static int 1401fbt_modevent(module_t mod __unused, int type, void *data __unused) 1402{ 1403 int error = 0; 1404 1405 switch (type) { 1406 case MOD_LOAD: 1407 break; 1408 1409 case MOD_UNLOAD: 1410 break; 1411 1412 case MOD_SHUTDOWN: 1413 break; 1414 1415 default: 1416 error = EOPNOTSUPP; 1417 break; 1418 1419 } 1420 1421 return (error); 1422} 1423 1424static int 1425fbt_open(struct cdev *dev __unused, int oflags __unused, int devtype __unused, struct thread *td __unused) 1426{ 1427 return (0); 1428} 1429 1430SYSINIT(fbt_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, fbt_load, NULL); 1431SYSUNINIT(fbt_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, fbt_unload, NULL); 1432 1433DEV_MODULE(fbt, fbt_modevent, NULL); 1434MODULE_VERSION(fbt, 1); 1435MODULE_DEPEND(fbt, dtrace, 1, 1, 1); 1436MODULE_DEPEND(fbt, opensolaris, 1, 1, 1); 1437