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