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