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