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