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