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