1178479Sjb/* 2178479Sjb * CDDL HEADER START 3178479Sjb * 4178479Sjb * The contents of this file are subject to the terms of the 5178479Sjb * Common Development and Distribution License (the "License"). 6178479Sjb * You may not use this file except in compliance with the License. 7178479Sjb * 8178479Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9178479Sjb * or http://www.opensolaris.org/os/licensing. 10178479Sjb * See the License for the specific language governing permissions 11178479Sjb * and limitations under the License. 12178479Sjb * 13178479Sjb * When distributing Covered Code, include this CDDL HEADER in each 14178479Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15178479Sjb * If applicable, add the following below this CDDL HEADER, with the 16178479Sjb * fields enclosed by brackets "[]" replaced with your own identifying 17178479Sjb * information: Portions Copyright [yyyy] [name of copyright owner] 18178479Sjb * 19178479Sjb * CDDL HEADER END 20178479Sjb */ 21210767Srpaulo 22178479Sjb/* 23210767Srpaulo * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 24178479Sjb */ 25268578Srpaulo/* 26268578Srpaulo * Copyright (c) 2013, Joyent, Inc. All rights reserved. 27268578Srpaulo */ 28178479Sjb 29178479Sjb#include <sys/types.h> 30178559Sjb#if defined(sun) 31178479Sjb#include <sys/modctl.h> 32178479Sjb#include <sys/kobj.h> 33178479Sjb#include <sys/kobj_impl.h> 34178479Sjb#include <sys/sysmacros.h> 35178479Sjb#include <sys/elf.h> 36178479Sjb#include <sys/task.h> 37178559Sjb#else 38178559Sjb#include <sys/param.h> 39178559Sjb#include <sys/linker.h> 40178559Sjb#include <sys/stat.h> 41178559Sjb#endif 42178479Sjb 43178479Sjb#include <unistd.h> 44178559Sjb#if defined(sun) 45178479Sjb#include <project.h> 46178559Sjb#endif 47178479Sjb#include <strings.h> 48178479Sjb#include <stdlib.h> 49178479Sjb#include <libelf.h> 50178479Sjb#include <limits.h> 51178479Sjb#include <assert.h> 52178479Sjb#include <errno.h> 53178479Sjb#include <dirent.h> 54178559Sjb#if !defined(sun) 55178559Sjb#include <fcntl.h> 56268578Srpaulo#include <libproc_compat.h> 57178559Sjb#endif 58178479Sjb 59178479Sjb#include <dt_strtab.h> 60178479Sjb#include <dt_module.h> 61178479Sjb#include <dt_impl.h> 62178479Sjb 63178479Sjbstatic const char *dt_module_strtab; /* active strtab for qsort callbacks */ 64178479Sjb 65178479Sjbstatic void 66178479Sjbdt_module_symhash_insert(dt_module_t *dmp, const char *name, uint_t id) 67178479Sjb{ 68178479Sjb dt_sym_t *dsp = &dmp->dm_symchains[dmp->dm_symfree]; 69178479Sjb uint_t h; 70178479Sjb 71178479Sjb assert(dmp->dm_symfree < dmp->dm_nsymelems + 1); 72178479Sjb 73178479Sjb dsp->ds_symid = id; 74178479Sjb h = dt_strtab_hash(name, NULL) % dmp->dm_nsymbuckets; 75178479Sjb dsp->ds_next = dmp->dm_symbuckets[h]; 76178479Sjb dmp->dm_symbuckets[h] = dmp->dm_symfree++; 77178479Sjb} 78178479Sjb 79178479Sjbstatic uint_t 80178479Sjbdt_module_syminit32(dt_module_t *dmp) 81178479Sjb{ 82210767Srpaulo#if STT_NUM != (STT_TLS + 1) 83210767Srpaulo#error "STT_NUM has grown. update dt_module_syminit32()" 84210767Srpaulo#endif 85210767Srpaulo 86178559Sjb Elf32_Sym *sym = dmp->dm_symtab.cts_data; 87178479Sjb const char *base = dmp->dm_strtab.cts_data; 88178479Sjb size_t ss_size = dmp->dm_strtab.cts_size; 89178479Sjb uint_t i, n = dmp->dm_nsymelems; 90178479Sjb uint_t asrsv = 0; 91178479Sjb 92210425Savg#if defined(__FreeBSD__) 93210425Savg GElf_Ehdr ehdr; 94210425Savg int is_elf_obj; 95210425Savg 96210425Savg gelf_getehdr(dmp->dm_elf, &ehdr); 97210425Savg is_elf_obj = (ehdr.e_type == ET_REL); 98210425Savg#endif 99210425Savg 100178479Sjb for (i = 0; i < n; i++, sym++) { 101178479Sjb const char *name = base + sym->st_name; 102178479Sjb uchar_t type = ELF32_ST_TYPE(sym->st_info); 103178479Sjb 104178479Sjb if (type >= STT_NUM || type == STT_SECTION) 105178479Sjb continue; /* skip sections and unknown types */ 106178479Sjb 107178479Sjb if (sym->st_name == 0 || sym->st_name >= ss_size) 108178479Sjb continue; /* skip null or invalid names */ 109178479Sjb 110178479Sjb if (sym->st_value != 0 && 111178559Sjb (ELF32_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size)) { 112178479Sjb asrsv++; /* reserve space in the address map */ 113178479Sjb 114210425Savg#if defined(__FreeBSD__) 115178559Sjb sym->st_value += (Elf_Addr) dmp->dm_reloc_offset; 116210425Savg if (is_elf_obj && sym->st_shndx != SHN_UNDEF && 117210425Savg sym->st_shndx < ehdr.e_shnum) 118210425Savg sym->st_value += 119210425Savg dmp->dm_sec_offsets[sym->st_shndx]; 120178559Sjb#endif 121178559Sjb } 122178559Sjb 123178479Sjb dt_module_symhash_insert(dmp, name, i); 124178479Sjb } 125178479Sjb 126178479Sjb return (asrsv); 127178479Sjb} 128178479Sjb 129178479Sjbstatic uint_t 130178479Sjbdt_module_syminit64(dt_module_t *dmp) 131178479Sjb{ 132210767Srpaulo#if STT_NUM != (STT_TLS + 1) 133210767Srpaulo#error "STT_NUM has grown. update dt_module_syminit64()" 134210767Srpaulo#endif 135210767Srpaulo 136178559Sjb Elf64_Sym *sym = dmp->dm_symtab.cts_data; 137178479Sjb const char *base = dmp->dm_strtab.cts_data; 138178479Sjb size_t ss_size = dmp->dm_strtab.cts_size; 139178479Sjb uint_t i, n = dmp->dm_nsymelems; 140178479Sjb uint_t asrsv = 0; 141178479Sjb 142210425Savg#if defined(__FreeBSD__) 143210425Savg GElf_Ehdr ehdr; 144210425Savg int is_elf_obj; 145210425Savg 146210425Savg gelf_getehdr(dmp->dm_elf, &ehdr); 147210425Savg is_elf_obj = (ehdr.e_type == ET_REL); 148210425Savg#endif 149210425Savg 150178479Sjb for (i = 0; i < n; i++, sym++) { 151178479Sjb const char *name = base + sym->st_name; 152178479Sjb uchar_t type = ELF64_ST_TYPE(sym->st_info); 153178479Sjb 154178479Sjb if (type >= STT_NUM || type == STT_SECTION) 155178479Sjb continue; /* skip sections and unknown types */ 156178479Sjb 157178479Sjb if (sym->st_name == 0 || sym->st_name >= ss_size) 158178479Sjb continue; /* skip null or invalid names */ 159178479Sjb 160178479Sjb if (sym->st_value != 0 && 161178559Sjb (ELF64_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size)) { 162178479Sjb asrsv++; /* reserve space in the address map */ 163210425Savg#if defined(__FreeBSD__) 164178559Sjb sym->st_value += (Elf_Addr) dmp->dm_reloc_offset; 165210425Savg if (is_elf_obj && sym->st_shndx != SHN_UNDEF && 166210425Savg sym->st_shndx < ehdr.e_shnum) 167210425Savg sym->st_value += 168210425Savg dmp->dm_sec_offsets[sym->st_shndx]; 169178559Sjb#endif 170178559Sjb } 171178559Sjb 172178479Sjb dt_module_symhash_insert(dmp, name, i); 173178479Sjb } 174178479Sjb 175178479Sjb return (asrsv); 176178479Sjb} 177178479Sjb 178178479Sjb/* 179178479Sjb * Sort comparison function for 32-bit symbol address-to-name lookups. We sort 180178479Sjb * symbols by value. If values are equal, we prefer the symbol that is 181178479Sjb * non-zero sized, typed, not weak, or lexically first, in that order. 182178479Sjb */ 183178479Sjbstatic int 184178479Sjbdt_module_symcomp32(const void *lp, const void *rp) 185178479Sjb{ 186178479Sjb Elf32_Sym *lhs = *((Elf32_Sym **)lp); 187178479Sjb Elf32_Sym *rhs = *((Elf32_Sym **)rp); 188178479Sjb 189178479Sjb if (lhs->st_value != rhs->st_value) 190178479Sjb return (lhs->st_value > rhs->st_value ? 1 : -1); 191178479Sjb 192178479Sjb if ((lhs->st_size == 0) != (rhs->st_size == 0)) 193178479Sjb return (lhs->st_size == 0 ? 1 : -1); 194178479Sjb 195178479Sjb if ((ELF32_ST_TYPE(lhs->st_info) == STT_NOTYPE) != 196178479Sjb (ELF32_ST_TYPE(rhs->st_info) == STT_NOTYPE)) 197178479Sjb return (ELF32_ST_TYPE(lhs->st_info) == STT_NOTYPE ? 1 : -1); 198178479Sjb 199178479Sjb if ((ELF32_ST_BIND(lhs->st_info) == STB_WEAK) != 200178479Sjb (ELF32_ST_BIND(rhs->st_info) == STB_WEAK)) 201178479Sjb return (ELF32_ST_BIND(lhs->st_info) == STB_WEAK ? 1 : -1); 202178479Sjb 203178479Sjb return (strcmp(dt_module_strtab + lhs->st_name, 204178479Sjb dt_module_strtab + rhs->st_name)); 205178479Sjb} 206178479Sjb 207178479Sjb/* 208178479Sjb * Sort comparison function for 64-bit symbol address-to-name lookups. We sort 209178479Sjb * symbols by value. If values are equal, we prefer the symbol that is 210178479Sjb * non-zero sized, typed, not weak, or lexically first, in that order. 211178479Sjb */ 212178479Sjbstatic int 213178479Sjbdt_module_symcomp64(const void *lp, const void *rp) 214178479Sjb{ 215178479Sjb Elf64_Sym *lhs = *((Elf64_Sym **)lp); 216178479Sjb Elf64_Sym *rhs = *((Elf64_Sym **)rp); 217178479Sjb 218178479Sjb if (lhs->st_value != rhs->st_value) 219178479Sjb return (lhs->st_value > rhs->st_value ? 1 : -1); 220178479Sjb 221178479Sjb if ((lhs->st_size == 0) != (rhs->st_size == 0)) 222178479Sjb return (lhs->st_size == 0 ? 1 : -1); 223178479Sjb 224178479Sjb if ((ELF64_ST_TYPE(lhs->st_info) == STT_NOTYPE) != 225178479Sjb (ELF64_ST_TYPE(rhs->st_info) == STT_NOTYPE)) 226178479Sjb return (ELF64_ST_TYPE(lhs->st_info) == STT_NOTYPE ? 1 : -1); 227178479Sjb 228178479Sjb if ((ELF64_ST_BIND(lhs->st_info) == STB_WEAK) != 229178479Sjb (ELF64_ST_BIND(rhs->st_info) == STB_WEAK)) 230178479Sjb return (ELF64_ST_BIND(lhs->st_info) == STB_WEAK ? 1 : -1); 231178479Sjb 232178479Sjb return (strcmp(dt_module_strtab + lhs->st_name, 233178479Sjb dt_module_strtab + rhs->st_name)); 234178479Sjb} 235178479Sjb 236178479Sjbstatic void 237178479Sjbdt_module_symsort32(dt_module_t *dmp) 238178479Sjb{ 239178479Sjb Elf32_Sym *symtab = (Elf32_Sym *)dmp->dm_symtab.cts_data; 240178479Sjb Elf32_Sym **sympp = (Elf32_Sym **)dmp->dm_asmap; 241178479Sjb const dt_sym_t *dsp = dmp->dm_symchains + 1; 242178479Sjb uint_t i, n = dmp->dm_symfree; 243178479Sjb 244178479Sjb for (i = 1; i < n; i++, dsp++) { 245178479Sjb Elf32_Sym *sym = symtab + dsp->ds_symid; 246178479Sjb if (sym->st_value != 0 && 247178479Sjb (ELF32_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size)) 248178479Sjb *sympp++ = sym; 249178479Sjb } 250178479Sjb 251178479Sjb dmp->dm_aslen = (uint_t)(sympp - (Elf32_Sym **)dmp->dm_asmap); 252178479Sjb assert(dmp->dm_aslen <= dmp->dm_asrsv); 253178479Sjb 254178479Sjb dt_module_strtab = dmp->dm_strtab.cts_data; 255178479Sjb qsort(dmp->dm_asmap, dmp->dm_aslen, 256178479Sjb sizeof (Elf32_Sym *), dt_module_symcomp32); 257178479Sjb dt_module_strtab = NULL; 258178479Sjb} 259178479Sjb 260178479Sjbstatic void 261178479Sjbdt_module_symsort64(dt_module_t *dmp) 262178479Sjb{ 263178479Sjb Elf64_Sym *symtab = (Elf64_Sym *)dmp->dm_symtab.cts_data; 264178479Sjb Elf64_Sym **sympp = (Elf64_Sym **)dmp->dm_asmap; 265178479Sjb const dt_sym_t *dsp = dmp->dm_symchains + 1; 266178479Sjb uint_t i, n = dmp->dm_symfree; 267178479Sjb 268178479Sjb for (i = 1; i < n; i++, dsp++) { 269178479Sjb Elf64_Sym *sym = symtab + dsp->ds_symid; 270178479Sjb if (sym->st_value != 0 && 271178479Sjb (ELF64_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size)) 272178479Sjb *sympp++ = sym; 273178479Sjb } 274178479Sjb 275178479Sjb dmp->dm_aslen = (uint_t)(sympp - (Elf64_Sym **)dmp->dm_asmap); 276178479Sjb assert(dmp->dm_aslen <= dmp->dm_asrsv); 277178479Sjb 278178479Sjb dt_module_strtab = dmp->dm_strtab.cts_data; 279178479Sjb qsort(dmp->dm_asmap, dmp->dm_aslen, 280178479Sjb sizeof (Elf64_Sym *), dt_module_symcomp64); 281178479Sjb dt_module_strtab = NULL; 282178479Sjb} 283178479Sjb 284178479Sjbstatic GElf_Sym * 285178479Sjbdt_module_symgelf32(const Elf32_Sym *src, GElf_Sym *dst) 286178479Sjb{ 287178479Sjb if (dst != NULL) { 288178479Sjb dst->st_name = src->st_name; 289178479Sjb dst->st_info = src->st_info; 290178479Sjb dst->st_other = src->st_other; 291178479Sjb dst->st_shndx = src->st_shndx; 292178479Sjb dst->st_value = src->st_value; 293178479Sjb dst->st_size = src->st_size; 294178479Sjb } 295178479Sjb 296178479Sjb return (dst); 297178479Sjb} 298178479Sjb 299178479Sjbstatic GElf_Sym * 300178479Sjbdt_module_symgelf64(const Elf64_Sym *src, GElf_Sym *dst) 301178479Sjb{ 302178479Sjb if (dst != NULL) 303178479Sjb bcopy(src, dst, sizeof (GElf_Sym)); 304178479Sjb 305178479Sjb return (dst); 306178479Sjb} 307178479Sjb 308178479Sjbstatic GElf_Sym * 309178479Sjbdt_module_symname32(dt_module_t *dmp, const char *name, 310178479Sjb GElf_Sym *symp, uint_t *idp) 311178479Sjb{ 312178479Sjb const Elf32_Sym *symtab = dmp->dm_symtab.cts_data; 313178479Sjb const char *strtab = dmp->dm_strtab.cts_data; 314178479Sjb 315178479Sjb const Elf32_Sym *sym; 316178479Sjb const dt_sym_t *dsp; 317178479Sjb uint_t i, h; 318178479Sjb 319178479Sjb if (dmp->dm_nsymelems == 0) 320178479Sjb return (NULL); 321178479Sjb 322178479Sjb h = dt_strtab_hash(name, NULL) % dmp->dm_nsymbuckets; 323178479Sjb 324178479Sjb for (i = dmp->dm_symbuckets[h]; i != 0; i = dsp->ds_next) { 325178479Sjb dsp = &dmp->dm_symchains[i]; 326178479Sjb sym = symtab + dsp->ds_symid; 327178479Sjb 328178479Sjb if (strcmp(name, strtab + sym->st_name) == 0) { 329178479Sjb if (idp != NULL) 330178479Sjb *idp = dsp->ds_symid; 331178479Sjb return (dt_module_symgelf32(sym, symp)); 332178479Sjb } 333178479Sjb } 334178479Sjb 335178479Sjb return (NULL); 336178479Sjb} 337178479Sjb 338178479Sjbstatic GElf_Sym * 339178479Sjbdt_module_symname64(dt_module_t *dmp, const char *name, 340178479Sjb GElf_Sym *symp, uint_t *idp) 341178479Sjb{ 342178479Sjb const Elf64_Sym *symtab = dmp->dm_symtab.cts_data; 343178479Sjb const char *strtab = dmp->dm_strtab.cts_data; 344178479Sjb 345178479Sjb const Elf64_Sym *sym; 346178479Sjb const dt_sym_t *dsp; 347178479Sjb uint_t i, h; 348178479Sjb 349178479Sjb if (dmp->dm_nsymelems == 0) 350178479Sjb return (NULL); 351178479Sjb 352178479Sjb h = dt_strtab_hash(name, NULL) % dmp->dm_nsymbuckets; 353178479Sjb 354178479Sjb for (i = dmp->dm_symbuckets[h]; i != 0; i = dsp->ds_next) { 355178479Sjb dsp = &dmp->dm_symchains[i]; 356178479Sjb sym = symtab + dsp->ds_symid; 357178479Sjb 358178479Sjb if (strcmp(name, strtab + sym->st_name) == 0) { 359178479Sjb if (idp != NULL) 360178479Sjb *idp = dsp->ds_symid; 361178479Sjb return (dt_module_symgelf64(sym, symp)); 362178479Sjb } 363178479Sjb } 364178479Sjb 365178479Sjb return (NULL); 366178479Sjb} 367178479Sjb 368178479Sjbstatic GElf_Sym * 369178479Sjbdt_module_symaddr32(dt_module_t *dmp, GElf_Addr addr, 370178479Sjb GElf_Sym *symp, uint_t *idp) 371178479Sjb{ 372178479Sjb const Elf32_Sym **asmap = (const Elf32_Sym **)dmp->dm_asmap; 373178479Sjb const Elf32_Sym *symtab = dmp->dm_symtab.cts_data; 374178479Sjb const Elf32_Sym *sym; 375178479Sjb 376178479Sjb uint_t i, mid, lo = 0, hi = dmp->dm_aslen - 1; 377178479Sjb Elf32_Addr v; 378178479Sjb 379178479Sjb if (dmp->dm_aslen == 0) 380178479Sjb return (NULL); 381178479Sjb 382178479Sjb while (hi - lo > 1) { 383178479Sjb mid = (lo + hi) / 2; 384178479Sjb if (addr >= asmap[mid]->st_value) 385178479Sjb lo = mid; 386178479Sjb else 387178479Sjb hi = mid; 388178479Sjb } 389178479Sjb 390178479Sjb i = addr < asmap[hi]->st_value ? lo : hi; 391178479Sjb sym = asmap[i]; 392178479Sjb v = sym->st_value; 393178479Sjb 394178479Sjb /* 395178479Sjb * If the previous entry has the same value, improve our choice. The 396178479Sjb * order of equal-valued symbols is determined by the comparison func. 397178479Sjb */ 398178479Sjb while (i-- != 0 && asmap[i]->st_value == v) 399178479Sjb sym = asmap[i]; 400178479Sjb 401178479Sjb if (addr - sym->st_value < MAX(sym->st_size, 1)) { 402178479Sjb if (idp != NULL) 403178479Sjb *idp = (uint_t)(sym - symtab); 404178479Sjb return (dt_module_symgelf32(sym, symp)); 405178479Sjb } 406178479Sjb 407178479Sjb return (NULL); 408178479Sjb} 409178479Sjb 410178479Sjbstatic GElf_Sym * 411178479Sjbdt_module_symaddr64(dt_module_t *dmp, GElf_Addr addr, 412178479Sjb GElf_Sym *symp, uint_t *idp) 413178479Sjb{ 414178479Sjb const Elf64_Sym **asmap = (const Elf64_Sym **)dmp->dm_asmap; 415178479Sjb const Elf64_Sym *symtab = dmp->dm_symtab.cts_data; 416178479Sjb const Elf64_Sym *sym; 417178479Sjb 418178479Sjb uint_t i, mid, lo = 0, hi = dmp->dm_aslen - 1; 419178479Sjb Elf64_Addr v; 420178479Sjb 421178479Sjb if (dmp->dm_aslen == 0) 422178479Sjb return (NULL); 423178479Sjb 424178479Sjb while (hi - lo > 1) { 425178479Sjb mid = (lo + hi) / 2; 426178479Sjb if (addr >= asmap[mid]->st_value) 427178479Sjb lo = mid; 428178479Sjb else 429178479Sjb hi = mid; 430178479Sjb } 431178479Sjb 432178479Sjb i = addr < asmap[hi]->st_value ? lo : hi; 433178479Sjb sym = asmap[i]; 434178479Sjb v = sym->st_value; 435178479Sjb 436178479Sjb /* 437178479Sjb * If the previous entry has the same value, improve our choice. The 438178479Sjb * order of equal-valued symbols is determined by the comparison func. 439178479Sjb */ 440178479Sjb while (i-- != 0 && asmap[i]->st_value == v) 441178479Sjb sym = asmap[i]; 442178479Sjb 443178479Sjb if (addr - sym->st_value < MAX(sym->st_size, 1)) { 444178479Sjb if (idp != NULL) 445178479Sjb *idp = (uint_t)(sym - symtab); 446178479Sjb return (dt_module_symgelf64(sym, symp)); 447178479Sjb } 448178479Sjb 449178479Sjb return (NULL); 450178479Sjb} 451178479Sjb 452178479Sjbstatic const dt_modops_t dt_modops_32 = { 453178479Sjb dt_module_syminit32, 454178479Sjb dt_module_symsort32, 455178479Sjb dt_module_symname32, 456178479Sjb dt_module_symaddr32 457178479Sjb}; 458178479Sjb 459178479Sjbstatic const dt_modops_t dt_modops_64 = { 460178479Sjb dt_module_syminit64, 461178479Sjb dt_module_symsort64, 462178479Sjb dt_module_symname64, 463178479Sjb dt_module_symaddr64 464178479Sjb}; 465178479Sjb 466178479Sjbdt_module_t * 467178479Sjbdt_module_create(dtrace_hdl_t *dtp, const char *name) 468178479Sjb{ 469268578Srpaulo long pid; 470268578Srpaulo char *eptr; 471268578Srpaulo dt_ident_t *idp; 472178479Sjb uint_t h = dt_strtab_hash(name, NULL) % dtp->dt_modbuckets; 473178479Sjb dt_module_t *dmp; 474178479Sjb 475178479Sjb for (dmp = dtp->dt_mods[h]; dmp != NULL; dmp = dmp->dm_next) { 476178479Sjb if (strcmp(dmp->dm_name, name) == 0) 477178479Sjb return (dmp); 478178479Sjb } 479178479Sjb 480178479Sjb if ((dmp = malloc(sizeof (dt_module_t))) == NULL) 481178479Sjb return (NULL); /* caller must handle allocation failure */ 482178479Sjb 483178479Sjb bzero(dmp, sizeof (dt_module_t)); 484178479Sjb (void) strlcpy(dmp->dm_name, name, sizeof (dmp->dm_name)); 485178479Sjb dt_list_append(&dtp->dt_modlist, dmp); 486178479Sjb dmp->dm_next = dtp->dt_mods[h]; 487178479Sjb dtp->dt_mods[h] = dmp; 488178479Sjb dtp->dt_nmods++; 489178479Sjb 490178479Sjb if (dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64) 491178479Sjb dmp->dm_ops = &dt_modops_64; 492178479Sjb else 493178479Sjb dmp->dm_ops = &dt_modops_32; 494178479Sjb 495268578Srpaulo /* 496268578Srpaulo * Modules for userland processes are special. They always refer to a 497268578Srpaulo * specific process and have a copy of their CTF data from a specific 498268578Srpaulo * instant in time. Any dt_module_t that begins with 'pid' is a module 499268578Srpaulo * for a specific process, much like how any probe description that 500268578Srpaulo * begins with 'pid' is special. pid123 refers to process 123. A module 501268578Srpaulo * that is just 'pid' refers specifically to pid$target. This is 502268578Srpaulo * generally done as D does not currently allow for macros to be 503268578Srpaulo * evaluated when working with types. 504268578Srpaulo */ 505268578Srpaulo if (strncmp(dmp->dm_name, "pid", 3) == 0) { 506268578Srpaulo errno = 0; 507268578Srpaulo if (dmp->dm_name[3] == '\0') { 508268578Srpaulo idp = dt_idhash_lookup(dtp->dt_macros, "target"); 509268578Srpaulo if (idp != NULL && idp->di_id != 0) 510268578Srpaulo dmp->dm_pid = idp->di_id; 511268578Srpaulo } else { 512268578Srpaulo pid = strtol(dmp->dm_name + 3, &eptr, 10); 513268578Srpaulo if (errno == 0 && *eptr == '\0') 514268578Srpaulo dmp->dm_pid = (pid_t)pid; 515268578Srpaulo else 516268578Srpaulo dt_dprintf("encountered malformed pid " 517268578Srpaulo "module: %s\n", dmp->dm_name); 518268578Srpaulo } 519268578Srpaulo } 520268578Srpaulo 521178479Sjb return (dmp); 522178479Sjb} 523178479Sjb 524178479Sjbdt_module_t * 525178479Sjbdt_module_lookup_by_name(dtrace_hdl_t *dtp, const char *name) 526178479Sjb{ 527178479Sjb uint_t h = dt_strtab_hash(name, NULL) % dtp->dt_modbuckets; 528178479Sjb dt_module_t *dmp; 529178479Sjb 530178479Sjb for (dmp = dtp->dt_mods[h]; dmp != NULL; dmp = dmp->dm_next) { 531178479Sjb if (strcmp(dmp->dm_name, name) == 0) 532178479Sjb return (dmp); 533178479Sjb } 534178479Sjb 535178479Sjb return (NULL); 536178479Sjb} 537178479Sjb 538178479Sjb/*ARGSUSED*/ 539178479Sjbdt_module_t * 540178479Sjbdt_module_lookup_by_ctf(dtrace_hdl_t *dtp, ctf_file_t *ctfp) 541178479Sjb{ 542178479Sjb return (ctfp ? ctf_getspecific(ctfp) : NULL); 543178479Sjb} 544178479Sjb 545178479Sjbstatic int 546178479Sjbdt_module_load_sect(dtrace_hdl_t *dtp, dt_module_t *dmp, ctf_sect_t *ctsp) 547178479Sjb{ 548178479Sjb const char *s; 549178479Sjb size_t shstrs; 550178479Sjb GElf_Shdr sh; 551178479Sjb Elf_Data *dp; 552178479Sjb Elf_Scn *sp; 553178479Sjb 554210767Srpaulo if (elf_getshdrstrndx(dmp->dm_elf, &shstrs) == -1) 555178479Sjb return (dt_set_errno(dtp, EDT_NOTLOADED)); 556178479Sjb 557178479Sjb for (sp = NULL; (sp = elf_nextscn(dmp->dm_elf, sp)) != NULL; ) { 558178479Sjb if (gelf_getshdr(sp, &sh) == NULL || sh.sh_type == SHT_NULL || 559178479Sjb (s = elf_strptr(dmp->dm_elf, shstrs, sh.sh_name)) == NULL) 560178479Sjb continue; /* skip any malformed sections */ 561178479Sjb 562178479Sjb if (sh.sh_type == ctsp->cts_type && 563178479Sjb sh.sh_entsize == ctsp->cts_entsize && 564178479Sjb strcmp(s, ctsp->cts_name) == 0) 565178479Sjb break; /* section matches specification */ 566178479Sjb } 567178479Sjb 568178479Sjb /* 569178479Sjb * If the section isn't found, return success but leave cts_data set 570178479Sjb * to NULL and cts_size set to zero for our caller. 571178479Sjb */ 572178479Sjb if (sp == NULL || (dp = elf_getdata(sp, NULL)) == NULL) 573178479Sjb return (0); 574178479Sjb 575178559Sjb#if defined(sun) 576178479Sjb ctsp->cts_data = dp->d_buf; 577178559Sjb#else 578178559Sjb if ((ctsp->cts_data = malloc(dp->d_size)) == NULL) 579178559Sjb return (0); 580178559Sjb memcpy(ctsp->cts_data, dp->d_buf, dp->d_size); 581178559Sjb#endif 582178479Sjb ctsp->cts_size = dp->d_size; 583178479Sjb 584178479Sjb dt_dprintf("loaded %s [%s] (%lu bytes)\n", 585178479Sjb dmp->dm_name, ctsp->cts_name, (ulong_t)ctsp->cts_size); 586178479Sjb 587178479Sjb return (0); 588178479Sjb} 589178479Sjb 590268578Srpaulotypedef struct dt_module_cb_arg { 591268578Srpaulo struct ps_prochandle *dpa_proc; 592268578Srpaulo dtrace_hdl_t *dpa_dtp; 593268578Srpaulo dt_module_t *dpa_dmp; 594268578Srpaulo uint_t dpa_count; 595268578Srpaulo} dt_module_cb_arg_t; 596268578Srpaulo 597268578Srpaulo/* ARGSUSED */ 598268578Srpaulostatic int 599268578Srpaulodt_module_load_proc_count(void *arg, const prmap_t *prmap, const char *obj) 600268578Srpaulo{ 601268578Srpaulo ctf_file_t *fp; 602268578Srpaulo dt_module_cb_arg_t *dcp = arg; 603268578Srpaulo 604268578Srpaulo /* Try to grab a ctf container if it exists */ 605268578Srpaulo fp = Pname_to_ctf(dcp->dpa_proc, obj); 606268578Srpaulo if (fp != NULL) 607268578Srpaulo dcp->dpa_count++; 608268578Srpaulo return (0); 609268578Srpaulo} 610268578Srpaulo 611268578Srpaulo/* ARGSUSED */ 612268578Srpaulostatic int 613268578Srpaulodt_module_load_proc_build(void *arg, const prmap_t *prmap, const char *obj) 614268578Srpaulo{ 615268578Srpaulo ctf_file_t *fp; 616268578Srpaulo char buf[MAXPATHLEN], *p; 617268578Srpaulo dt_module_cb_arg_t *dcp = arg; 618268578Srpaulo int count = dcp->dpa_count; 619268578Srpaulo Lmid_t lmid; 620268578Srpaulo 621268578Srpaulo fp = Pname_to_ctf(dcp->dpa_proc, obj); 622268578Srpaulo if (fp == NULL) 623268578Srpaulo return (0); 624268578Srpaulo fp = ctf_dup(fp); 625268578Srpaulo if (fp == NULL) 626268578Srpaulo return (0); 627268578Srpaulo dcp->dpa_dmp->dm_libctfp[count] = fp; 628268578Srpaulo /* 629268578Srpaulo * While it'd be nice to simply use objname here, because of our prior 630268578Srpaulo * actions we'll always get a resolved object name to its on disk file. 631268578Srpaulo * Like the pid provider, we need to tell a bit of a lie here. The type 632268578Srpaulo * that the user thinks of is in terms of the libraries they requested, 633268578Srpaulo * eg. libc.so.1, they don't care about the fact that it's 634268578Srpaulo * libc_hwcap.so.1. 635268578Srpaulo */ 636268578Srpaulo (void) Pobjname(dcp->dpa_proc, prmap->pr_vaddr, buf, sizeof (buf)); 637268578Srpaulo if ((p = strrchr(buf, '/')) == NULL) 638268578Srpaulo p = buf; 639268578Srpaulo else 640268578Srpaulo p++; 641268578Srpaulo 642268578Srpaulo /* 643268578Srpaulo * If for some reason we can't find a link map id for this module, which 644268578Srpaulo * would be really quite weird. We instead just say the link map id is 645268578Srpaulo * zero. 646268578Srpaulo */ 647268578Srpaulo if (Plmid(dcp->dpa_proc, prmap->pr_vaddr, &lmid) != 0) 648268578Srpaulo lmid = 0; 649268578Srpaulo 650268578Srpaulo if (lmid == 0) 651268578Srpaulo dcp->dpa_dmp->dm_libctfn[count] = strdup(p); 652268578Srpaulo else 653268578Srpaulo (void) asprintf(&dcp->dpa_dmp->dm_libctfn[count], 654268578Srpaulo "LM%x`%s", lmid, p); 655268578Srpaulo if (dcp->dpa_dmp->dm_libctfn[count] == NULL) 656268578Srpaulo return (1); 657268578Srpaulo ctf_setspecific(fp, dcp->dpa_dmp); 658268578Srpaulo dcp->dpa_count++; 659268578Srpaulo return (0); 660268578Srpaulo} 661268578Srpaulo 662268578Srpaulo/* 663268578Srpaulo * We've been asked to load data that belongs to another process. As such we're 664268578Srpaulo * going to pgrab it at this instant, load everything that we might ever care 665268578Srpaulo * about, and then drive on. The reason for this is that the process that we're 666268578Srpaulo * interested in might be changing. As long as we have grabbed it, then this 667268578Srpaulo * can't be a problem for us. 668268578Srpaulo * 669268578Srpaulo * For now, we're actually going to punt on most things and just try to get CTF 670268578Srpaulo * data, nothing else. Basically this is only useful as a source of type 671268578Srpaulo * information, we can't go and do the stacktrace lookups, etc. 672268578Srpaulo */ 673268578Srpaulostatic int 674268578Srpaulodt_module_load_proc(dtrace_hdl_t *dtp, dt_module_t *dmp) 675268578Srpaulo{ 676268578Srpaulo struct ps_prochandle *p; 677268578Srpaulo dt_module_cb_arg_t arg; 678268578Srpaulo 679268578Srpaulo /* 680268578Srpaulo * Note that on success we do not release this hold. We must hold this 681268578Srpaulo * for our life time. 682268578Srpaulo */ 683268578Srpaulo p = dt_proc_grab(dtp, dmp->dm_pid, 0, PGRAB_RDONLY | PGRAB_FORCE); 684268578Srpaulo if (p == NULL) { 685268578Srpaulo dt_dprintf("failed to grab pid: %d\n", (int)dmp->dm_pid); 686268578Srpaulo return (dt_set_errno(dtp, EDT_CANTLOAD)); 687268578Srpaulo } 688268578Srpaulo dt_proc_lock(dtp, p); 689268578Srpaulo 690268578Srpaulo arg.dpa_proc = p; 691268578Srpaulo arg.dpa_dtp = dtp; 692268578Srpaulo arg.dpa_dmp = dmp; 693268578Srpaulo arg.dpa_count = 0; 694268578Srpaulo if (Pobject_iter_resolved(p, dt_module_load_proc_count, &arg) != 0) { 695268578Srpaulo dt_dprintf("failed to iterate objects\n"); 696268578Srpaulo dt_proc_release(dtp, p); 697268578Srpaulo return (dt_set_errno(dtp, EDT_CANTLOAD)); 698268578Srpaulo } 699268578Srpaulo 700268578Srpaulo if (arg.dpa_count == 0) { 701268578Srpaulo dt_dprintf("no ctf data present\n"); 702268578Srpaulo dt_proc_unlock(dtp, p); 703268578Srpaulo dt_proc_release(dtp, p); 704268578Srpaulo return (dt_set_errno(dtp, EDT_CANTLOAD)); 705268578Srpaulo } 706268578Srpaulo 707268578Srpaulo dmp->dm_libctfp = malloc(sizeof (ctf_file_t *) * arg.dpa_count); 708268578Srpaulo if (dmp->dm_libctfp == NULL) { 709268578Srpaulo dt_proc_unlock(dtp, p); 710268578Srpaulo dt_proc_release(dtp, p); 711268578Srpaulo return (dt_set_errno(dtp, EDT_NOMEM)); 712268578Srpaulo } 713268578Srpaulo bzero(dmp->dm_libctfp, sizeof (ctf_file_t *) * arg.dpa_count); 714268578Srpaulo 715268578Srpaulo dmp->dm_libctfn = malloc(sizeof (char *) * arg.dpa_count); 716268578Srpaulo if (dmp->dm_libctfn == NULL) { 717268578Srpaulo free(dmp->dm_libctfp); 718268578Srpaulo dt_proc_unlock(dtp, p); 719268578Srpaulo dt_proc_release(dtp, p); 720268578Srpaulo return (dt_set_errno(dtp, EDT_NOMEM)); 721268578Srpaulo } 722268578Srpaulo bzero(dmp->dm_libctfn, sizeof (char *) * arg.dpa_count); 723268578Srpaulo 724268578Srpaulo dmp->dm_nctflibs = arg.dpa_count; 725268578Srpaulo 726268578Srpaulo arg.dpa_count = 0; 727268578Srpaulo if (Pobject_iter_resolved(p, dt_module_load_proc_build, &arg) != 0) { 728268578Srpaulo dt_proc_unlock(dtp, p); 729268578Srpaulo dt_module_unload(dtp, dmp); 730268578Srpaulo dt_proc_release(dtp, p); 731268578Srpaulo return (dt_set_errno(dtp, EDT_CANTLOAD)); 732268578Srpaulo } 733268578Srpaulo assert(arg.dpa_count == dmp->dm_nctflibs); 734268578Srpaulo dt_dprintf("loaded %d ctf modules for pid %d\n", arg.dpa_count, 735268578Srpaulo (int)dmp->dm_pid); 736268578Srpaulo 737268578Srpaulo dt_proc_unlock(dtp, p); 738268578Srpaulo dt_proc_release(dtp, p); 739268578Srpaulo dmp->dm_flags |= DT_DM_LOADED; 740268578Srpaulo 741268578Srpaulo return (0); 742268578Srpaulo} 743268578Srpaulo 744178479Sjbint 745178479Sjbdt_module_load(dtrace_hdl_t *dtp, dt_module_t *dmp) 746178479Sjb{ 747178479Sjb if (dmp->dm_flags & DT_DM_LOADED) 748178479Sjb return (0); /* module is already loaded */ 749178479Sjb 750268578Srpaulo if (dmp->dm_pid != 0) 751268578Srpaulo return (dt_module_load_proc(dtp, dmp)); 752268578Srpaulo 753178479Sjb dmp->dm_ctdata.cts_name = ".SUNW_ctf"; 754178479Sjb dmp->dm_ctdata.cts_type = SHT_PROGBITS; 755178479Sjb dmp->dm_ctdata.cts_flags = 0; 756178479Sjb dmp->dm_ctdata.cts_data = NULL; 757178479Sjb dmp->dm_ctdata.cts_size = 0; 758178479Sjb dmp->dm_ctdata.cts_entsize = 0; 759178479Sjb dmp->dm_ctdata.cts_offset = 0; 760178479Sjb 761178479Sjb dmp->dm_symtab.cts_name = ".symtab"; 762178479Sjb dmp->dm_symtab.cts_type = SHT_SYMTAB; 763178479Sjb dmp->dm_symtab.cts_flags = 0; 764178479Sjb dmp->dm_symtab.cts_data = NULL; 765178479Sjb dmp->dm_symtab.cts_size = 0; 766178479Sjb dmp->dm_symtab.cts_entsize = dmp->dm_ops == &dt_modops_64 ? 767178479Sjb sizeof (Elf64_Sym) : sizeof (Elf32_Sym); 768178479Sjb dmp->dm_symtab.cts_offset = 0; 769178479Sjb 770178479Sjb dmp->dm_strtab.cts_name = ".strtab"; 771178479Sjb dmp->dm_strtab.cts_type = SHT_STRTAB; 772178479Sjb dmp->dm_strtab.cts_flags = 0; 773178479Sjb dmp->dm_strtab.cts_data = NULL; 774178479Sjb dmp->dm_strtab.cts_size = 0; 775178479Sjb dmp->dm_strtab.cts_entsize = 0; 776178479Sjb dmp->dm_strtab.cts_offset = 0; 777178479Sjb 778178479Sjb /* 779178479Sjb * Attempt to load the module's CTF section, symbol table section, and 780178479Sjb * string table section. Note that modules may not contain CTF data: 781178479Sjb * this will result in a successful load_sect but data of size zero. 782178479Sjb * We will then fail if dt_module_getctf() is called, as shown below. 783178479Sjb */ 784178479Sjb if (dt_module_load_sect(dtp, dmp, &dmp->dm_ctdata) == -1 || 785178479Sjb dt_module_load_sect(dtp, dmp, &dmp->dm_symtab) == -1 || 786178479Sjb dt_module_load_sect(dtp, dmp, &dmp->dm_strtab) == -1) { 787178479Sjb dt_module_unload(dtp, dmp); 788178479Sjb return (-1); /* dt_errno is set for us */ 789178479Sjb } 790178479Sjb 791178479Sjb /* 792178479Sjb * Allocate the hash chains and hash buckets for symbol name lookup. 793178479Sjb * This is relatively simple since the symbol table is of fixed size 794178479Sjb * and is known in advance. We allocate one extra element since we 795178479Sjb * use element indices instead of pointers and zero is our sentinel. 796178479Sjb */ 797178479Sjb dmp->dm_nsymelems = 798178479Sjb dmp->dm_symtab.cts_size / dmp->dm_symtab.cts_entsize; 799178479Sjb 800178479Sjb dmp->dm_nsymbuckets = _dtrace_strbuckets; 801178479Sjb dmp->dm_symfree = 1; /* first free element is index 1 */ 802178479Sjb 803178479Sjb dmp->dm_symbuckets = malloc(sizeof (uint_t) * dmp->dm_nsymbuckets); 804178479Sjb dmp->dm_symchains = malloc(sizeof (dt_sym_t) * dmp->dm_nsymelems + 1); 805178479Sjb 806178479Sjb if (dmp->dm_symbuckets == NULL || dmp->dm_symchains == NULL) { 807178479Sjb dt_module_unload(dtp, dmp); 808178479Sjb return (dt_set_errno(dtp, EDT_NOMEM)); 809178479Sjb } 810178479Sjb 811178479Sjb bzero(dmp->dm_symbuckets, sizeof (uint_t) * dmp->dm_nsymbuckets); 812178479Sjb bzero(dmp->dm_symchains, sizeof (dt_sym_t) * dmp->dm_nsymelems + 1); 813178479Sjb 814178479Sjb /* 815178479Sjb * Iterate over the symbol table data buffer and insert each symbol 816178479Sjb * name into the name hash if the name and type are valid. Then 817178479Sjb * allocate the address map, fill it in, and sort it. 818178479Sjb */ 819178479Sjb dmp->dm_asrsv = dmp->dm_ops->do_syminit(dmp); 820178479Sjb 821178479Sjb dt_dprintf("hashed %s [%s] (%u symbols)\n", 822178479Sjb dmp->dm_name, dmp->dm_symtab.cts_name, dmp->dm_symfree - 1); 823178479Sjb 824178479Sjb if ((dmp->dm_asmap = malloc(sizeof (void *) * dmp->dm_asrsv)) == NULL) { 825178479Sjb dt_module_unload(dtp, dmp); 826178479Sjb return (dt_set_errno(dtp, EDT_NOMEM)); 827178479Sjb } 828178479Sjb 829178479Sjb dmp->dm_ops->do_symsort(dmp); 830178479Sjb 831178479Sjb dt_dprintf("sorted %s [%s] (%u symbols)\n", 832178479Sjb dmp->dm_name, dmp->dm_symtab.cts_name, dmp->dm_aslen); 833178479Sjb 834178479Sjb dmp->dm_flags |= DT_DM_LOADED; 835178479Sjb return (0); 836178479Sjb} 837178479Sjb 838268578Srpauloint 839268578Srpaulodt_module_hasctf(dtrace_hdl_t *dtp, dt_module_t *dmp) 840268578Srpaulo{ 841268578Srpaulo if (dmp->dm_pid != 0 && dmp->dm_nctflibs > 0) 842268578Srpaulo return (1); 843268578Srpaulo return (dt_module_getctf(dtp, dmp) != NULL); 844268578Srpaulo} 845268578Srpaulo 846178479Sjbctf_file_t * 847178479Sjbdt_module_getctf(dtrace_hdl_t *dtp, dt_module_t *dmp) 848178479Sjb{ 849178479Sjb const char *parent; 850178479Sjb dt_module_t *pmp; 851178479Sjb ctf_file_t *pfp; 852178479Sjb int model; 853178479Sjb 854178479Sjb if (dmp->dm_ctfp != NULL || dt_module_load(dtp, dmp) != 0) 855178479Sjb return (dmp->dm_ctfp); 856178479Sjb 857178479Sjb if (dmp->dm_ops == &dt_modops_64) 858178479Sjb model = CTF_MODEL_LP64; 859178479Sjb else 860178479Sjb model = CTF_MODEL_ILP32; 861178479Sjb 862178479Sjb /* 863178479Sjb * If the data model of the module does not match our program data 864178479Sjb * model, then do not permit CTF from this module to be opened and 865178479Sjb * returned to the compiler. If we support mixed data models in the 866178479Sjb * future for combined kernel/user tracing, this can be removed. 867178479Sjb */ 868178479Sjb if (dtp->dt_conf.dtc_ctfmodel != model) { 869178479Sjb (void) dt_set_errno(dtp, EDT_DATAMODEL); 870178479Sjb return (NULL); 871178479Sjb } 872178479Sjb 873178479Sjb if (dmp->dm_ctdata.cts_size == 0) { 874178479Sjb (void) dt_set_errno(dtp, EDT_NOCTF); 875178479Sjb return (NULL); 876178479Sjb } 877178479Sjb 878178479Sjb dmp->dm_ctfp = ctf_bufopen(&dmp->dm_ctdata, 879178479Sjb &dmp->dm_symtab, &dmp->dm_strtab, &dtp->dt_ctferr); 880178479Sjb 881178479Sjb if (dmp->dm_ctfp == NULL) { 882178479Sjb (void) dt_set_errno(dtp, EDT_CTF); 883178479Sjb return (NULL); 884178479Sjb } 885178479Sjb 886178479Sjb (void) ctf_setmodel(dmp->dm_ctfp, model); 887178479Sjb ctf_setspecific(dmp->dm_ctfp, dmp); 888178479Sjb 889178479Sjb if ((parent = ctf_parent_name(dmp->dm_ctfp)) != NULL) { 890178479Sjb if ((pmp = dt_module_create(dtp, parent)) == NULL || 891178479Sjb (pfp = dt_module_getctf(dtp, pmp)) == NULL) { 892178479Sjb if (pmp == NULL) 893178479Sjb (void) dt_set_errno(dtp, EDT_NOMEM); 894178479Sjb goto err; 895178479Sjb } 896178479Sjb 897178479Sjb if (ctf_import(dmp->dm_ctfp, pfp) == CTF_ERR) { 898178479Sjb dtp->dt_ctferr = ctf_errno(dmp->dm_ctfp); 899178479Sjb (void) dt_set_errno(dtp, EDT_CTF); 900178479Sjb goto err; 901178479Sjb } 902178479Sjb } 903178479Sjb 904178479Sjb dt_dprintf("loaded CTF container for %s (%p)\n", 905178479Sjb dmp->dm_name, (void *)dmp->dm_ctfp); 906178479Sjb 907178479Sjb return (dmp->dm_ctfp); 908178479Sjb 909178479Sjberr: 910178479Sjb ctf_close(dmp->dm_ctfp); 911178479Sjb dmp->dm_ctfp = NULL; 912178479Sjb return (NULL); 913178479Sjb} 914178479Sjb 915178479Sjb/*ARGSUSED*/ 916178479Sjbvoid 917178479Sjbdt_module_unload(dtrace_hdl_t *dtp, dt_module_t *dmp) 918178479Sjb{ 919268578Srpaulo int i; 920268578Srpaulo 921178479Sjb ctf_close(dmp->dm_ctfp); 922178479Sjb dmp->dm_ctfp = NULL; 923178479Sjb 924178559Sjb#if !defined(sun) 925178559Sjb if (dmp->dm_ctdata.cts_data != NULL) { 926178559Sjb free(dmp->dm_ctdata.cts_data); 927178559Sjb } 928178559Sjb if (dmp->dm_symtab.cts_data != NULL) { 929178559Sjb free(dmp->dm_symtab.cts_data); 930178559Sjb } 931178559Sjb if (dmp->dm_strtab.cts_data != NULL) { 932178559Sjb free(dmp->dm_strtab.cts_data); 933178559Sjb } 934178559Sjb#endif 935178559Sjb 936268578Srpaulo if (dmp->dm_libctfp != NULL) { 937268578Srpaulo for (i = 0; i < dmp->dm_nctflibs; i++) { 938268578Srpaulo ctf_close(dmp->dm_libctfp[i]); 939268578Srpaulo free(dmp->dm_libctfn[i]); 940268578Srpaulo } 941268578Srpaulo free(dmp->dm_libctfp); 942268578Srpaulo free(dmp->dm_libctfn); 943268578Srpaulo dmp->dm_libctfp = NULL; 944268578Srpaulo dmp->dm_nctflibs = 0; 945268578Srpaulo } 946268578Srpaulo 947178479Sjb bzero(&dmp->dm_ctdata, sizeof (ctf_sect_t)); 948178479Sjb bzero(&dmp->dm_symtab, sizeof (ctf_sect_t)); 949178479Sjb bzero(&dmp->dm_strtab, sizeof (ctf_sect_t)); 950178479Sjb 951178479Sjb if (dmp->dm_symbuckets != NULL) { 952178479Sjb free(dmp->dm_symbuckets); 953178479Sjb dmp->dm_symbuckets = NULL; 954178479Sjb } 955178479Sjb 956178479Sjb if (dmp->dm_symchains != NULL) { 957178479Sjb free(dmp->dm_symchains); 958178479Sjb dmp->dm_symchains = NULL; 959178479Sjb } 960178479Sjb 961178479Sjb if (dmp->dm_asmap != NULL) { 962178479Sjb free(dmp->dm_asmap); 963178479Sjb dmp->dm_asmap = NULL; 964178479Sjb } 965210425Savg#if defined(__FreeBSD__) 966210425Savg if (dmp->dm_sec_offsets != NULL) { 967210425Savg free(dmp->dm_sec_offsets); 968210425Savg dmp->dm_sec_offsets = NULL; 969210425Savg } 970210425Savg#endif 971178479Sjb dmp->dm_symfree = 0; 972178479Sjb dmp->dm_nsymbuckets = 0; 973178479Sjb dmp->dm_nsymelems = 0; 974178479Sjb dmp->dm_asrsv = 0; 975178479Sjb dmp->dm_aslen = 0; 976178479Sjb 977178559Sjb dmp->dm_text_va = 0; 978178479Sjb dmp->dm_text_size = 0; 979178559Sjb dmp->dm_data_va = 0; 980178479Sjb dmp->dm_data_size = 0; 981178559Sjb dmp->dm_bss_va = 0; 982178479Sjb dmp->dm_bss_size = 0; 983178479Sjb 984178479Sjb if (dmp->dm_extern != NULL) { 985178479Sjb dt_idhash_destroy(dmp->dm_extern); 986178479Sjb dmp->dm_extern = NULL; 987178479Sjb } 988178479Sjb 989178479Sjb (void) elf_end(dmp->dm_elf); 990178479Sjb dmp->dm_elf = NULL; 991178479Sjb 992268578Srpaulo dmp->dm_pid = 0; 993268578Srpaulo 994178479Sjb dmp->dm_flags &= ~DT_DM_LOADED; 995178479Sjb} 996178479Sjb 997178479Sjbvoid 998178479Sjbdt_module_destroy(dtrace_hdl_t *dtp, dt_module_t *dmp) 999178479Sjb{ 1000210767Srpaulo uint_t h = dt_strtab_hash(dmp->dm_name, NULL) % dtp->dt_modbuckets; 1001210767Srpaulo dt_module_t **dmpp = &dtp->dt_mods[h]; 1002210767Srpaulo 1003178479Sjb dt_list_delete(&dtp->dt_modlist, dmp); 1004178479Sjb assert(dtp->dt_nmods != 0); 1005178479Sjb dtp->dt_nmods--; 1006178479Sjb 1007210767Srpaulo /* 1008210767Srpaulo * Now remove this module from its hash chain. We expect to always 1009210767Srpaulo * find the module on its hash chain, so in this loop we assert that 1010210767Srpaulo * we don't run off the end of the list. 1011210767Srpaulo */ 1012210767Srpaulo while (*dmpp != dmp) { 1013210767Srpaulo dmpp = &((*dmpp)->dm_next); 1014210767Srpaulo assert(*dmpp != NULL); 1015210767Srpaulo } 1016210767Srpaulo 1017210767Srpaulo *dmpp = dmp->dm_next; 1018210767Srpaulo 1019178479Sjb dt_module_unload(dtp, dmp); 1020178479Sjb free(dmp); 1021178479Sjb} 1022178479Sjb 1023178479Sjb/* 1024178479Sjb * Insert a new external symbol reference into the specified module. The new 1025178479Sjb * symbol will be marked as undefined and is assigned a symbol index beyond 1026178479Sjb * any existing cached symbols from this module. We use the ident's di_data 1027178479Sjb * field to store a pointer to a copy of the dtrace_syminfo_t for this symbol. 1028178479Sjb */ 1029178479Sjbdt_ident_t * 1030178479Sjbdt_module_extern(dtrace_hdl_t *dtp, dt_module_t *dmp, 1031178479Sjb const char *name, const dtrace_typeinfo_t *tip) 1032178479Sjb{ 1033178479Sjb dtrace_syminfo_t *sip; 1034178479Sjb dt_ident_t *idp; 1035178479Sjb uint_t id; 1036178479Sjb 1037178479Sjb if (dmp->dm_extern == NULL && (dmp->dm_extern = dt_idhash_create( 1038178479Sjb "extern", NULL, dmp->dm_nsymelems, UINT_MAX)) == NULL) { 1039178479Sjb (void) dt_set_errno(dtp, EDT_NOMEM); 1040178479Sjb return (NULL); 1041178479Sjb } 1042178479Sjb 1043178479Sjb if (dt_idhash_nextid(dmp->dm_extern, &id) == -1) { 1044178479Sjb (void) dt_set_errno(dtp, EDT_SYMOFLOW); 1045178479Sjb return (NULL); 1046178479Sjb } 1047178479Sjb 1048178479Sjb if ((sip = malloc(sizeof (dtrace_syminfo_t))) == NULL) { 1049178479Sjb (void) dt_set_errno(dtp, EDT_NOMEM); 1050178479Sjb return (NULL); 1051178479Sjb } 1052178479Sjb 1053178479Sjb idp = dt_idhash_insert(dmp->dm_extern, name, DT_IDENT_SYMBOL, 0, id, 1054178479Sjb _dtrace_symattr, 0, &dt_idops_thaw, NULL, dtp->dt_gen); 1055178479Sjb 1056178479Sjb if (idp == NULL) { 1057178479Sjb (void) dt_set_errno(dtp, EDT_NOMEM); 1058178479Sjb free(sip); 1059178479Sjb return (NULL); 1060178479Sjb } 1061178479Sjb 1062178479Sjb sip->dts_object = dmp->dm_name; 1063178479Sjb sip->dts_name = idp->di_name; 1064178479Sjb sip->dts_id = idp->di_id; 1065178479Sjb 1066178479Sjb idp->di_data = sip; 1067178479Sjb idp->di_ctfp = tip->dtt_ctfp; 1068178479Sjb idp->di_type = tip->dtt_type; 1069178479Sjb 1070178479Sjb return (idp); 1071178479Sjb} 1072178479Sjb 1073178479Sjbconst char * 1074178479Sjbdt_module_modelname(dt_module_t *dmp) 1075178479Sjb{ 1076178479Sjb if (dmp->dm_ops == &dt_modops_64) 1077178479Sjb return ("64-bit"); 1078178479Sjb else 1079178479Sjb return ("32-bit"); 1080178479Sjb} 1081178479Sjb 1082268578Srpaulo/* ARGSUSED */ 1083268578Srpauloint 1084268578Srpaulodt_module_getlibid(dtrace_hdl_t *dtp, dt_module_t *dmp, const ctf_file_t *fp) 1085268578Srpaulo{ 1086268578Srpaulo int i; 1087268578Srpaulo 1088268578Srpaulo for (i = 0; i < dmp->dm_nctflibs; i++) { 1089268578Srpaulo if (dmp->dm_libctfp[i] == fp) 1090268578Srpaulo return (i); 1091268578Srpaulo } 1092268578Srpaulo 1093268578Srpaulo return (-1); 1094268578Srpaulo} 1095268578Srpaulo 1096268578Srpaulo/* ARGSUSED */ 1097268578Srpauloctf_file_t * 1098268578Srpaulodt_module_getctflib(dtrace_hdl_t *dtp, dt_module_t *dmp, const char *name) 1099268578Srpaulo{ 1100268578Srpaulo int i; 1101268578Srpaulo 1102268578Srpaulo for (i = 0; i < dmp->dm_nctflibs; i++) { 1103268578Srpaulo if (strcmp(dmp->dm_libctfn[i], name) == 0) 1104268578Srpaulo return (dmp->dm_libctfp[i]); 1105268578Srpaulo } 1106268578Srpaulo 1107268578Srpaulo return (NULL); 1108268578Srpaulo} 1109268578Srpaulo 1110178479Sjb/* 1111178479Sjb * Update our module cache by adding an entry for the specified module 'name'. 1112178479Sjb * We create the dt_module_t and populate it using /system/object/<name>/. 1113178559Sjb * 1114178559Sjb * On FreeBSD, the module name is passed as the full module file name, 1115178559Sjb * including the path. 1116178479Sjb */ 1117178479Sjbstatic void 1118178559Sjb#if defined(sun) 1119178479Sjbdt_module_update(dtrace_hdl_t *dtp, const char *name) 1120178559Sjb#else 1121178559Sjbdt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat) 1122178559Sjb#endif 1123178479Sjb{ 1124178479Sjb char fname[MAXPATHLEN]; 1125178479Sjb struct stat64 st; 1126178479Sjb int fd, err, bits; 1127178479Sjb 1128178479Sjb dt_module_t *dmp; 1129178479Sjb const char *s; 1130178479Sjb size_t shstrs; 1131178479Sjb GElf_Shdr sh; 1132178479Sjb Elf_Data *dp; 1133178479Sjb Elf_Scn *sp; 1134178479Sjb 1135178559Sjb#if defined(sun) 1136178479Sjb (void) snprintf(fname, sizeof (fname), 1137178479Sjb "%s/%s/object", OBJFS_ROOT, name); 1138178559Sjb#else 1139210425Savg GElf_Ehdr ehdr; 1140178559Sjb GElf_Phdr ph; 1141178559Sjb char name[MAXPATHLEN]; 1142210425Savg uintptr_t mapbase, alignmask; 1143178559Sjb int i = 0; 1144210425Savg int is_elf_obj; 1145178479Sjb 1146178559Sjb (void) strlcpy(name, k_stat->name, sizeof(name)); 1147178559Sjb (void) strlcpy(fname, k_stat->pathname, sizeof(fname)); 1148178559Sjb#endif 1149178559Sjb 1150178479Sjb if ((fd = open(fname, O_RDONLY)) == -1 || fstat64(fd, &st) == -1 || 1151178479Sjb (dmp = dt_module_create(dtp, name)) == NULL) { 1152178479Sjb dt_dprintf("failed to open %s: %s\n", fname, strerror(errno)); 1153178479Sjb (void) close(fd); 1154178479Sjb return; 1155178479Sjb } 1156178479Sjb 1157178479Sjb /* 1158178479Sjb * Since the module can unload out from under us (and /system/object 1159178479Sjb * will return ENOENT), tell libelf to cook the entire file now and 1160178479Sjb * then close the underlying file descriptor immediately. If this 1161178479Sjb * succeeds, we know that we can continue safely using dmp->dm_elf. 1162178479Sjb */ 1163178479Sjb dmp->dm_elf = elf_begin(fd, ELF_C_READ, NULL); 1164178479Sjb err = elf_cntl(dmp->dm_elf, ELF_C_FDREAD); 1165178479Sjb (void) close(fd); 1166178479Sjb 1167178479Sjb if (dmp->dm_elf == NULL || err == -1 || 1168210767Srpaulo elf_getshdrstrndx(dmp->dm_elf, &shstrs) == -1) { 1169178479Sjb dt_dprintf("failed to load %s: %s\n", 1170178479Sjb fname, elf_errmsg(elf_errno())); 1171178479Sjb dt_module_destroy(dtp, dmp); 1172178479Sjb return; 1173178479Sjb } 1174178479Sjb 1175178479Sjb switch (gelf_getclass(dmp->dm_elf)) { 1176178479Sjb case ELFCLASS32: 1177178479Sjb dmp->dm_ops = &dt_modops_32; 1178178479Sjb bits = 32; 1179178479Sjb break; 1180178479Sjb case ELFCLASS64: 1181178479Sjb dmp->dm_ops = &dt_modops_64; 1182178479Sjb bits = 64; 1183178479Sjb break; 1184178479Sjb default: 1185178479Sjb dt_dprintf("failed to load %s: unknown ELF class\n", fname); 1186178479Sjb dt_module_destroy(dtp, dmp); 1187178479Sjb return; 1188178479Sjb } 1189210425Savg#if defined(__FreeBSD__) 1190210425Savg mapbase = (uintptr_t)k_stat->address; 1191210425Savg gelf_getehdr(dmp->dm_elf, &ehdr); 1192210425Savg is_elf_obj = (ehdr.e_type == ET_REL); 1193210425Savg if (is_elf_obj) { 1194210425Savg dmp->dm_sec_offsets = 1195210425Savg malloc(ehdr.e_shnum * sizeof(*dmp->dm_sec_offsets)); 1196210425Savg if (dmp->dm_sec_offsets == NULL) { 1197210425Savg dt_dprintf("failed to allocate memory\n"); 1198210425Savg dt_module_destroy(dtp, dmp); 1199210425Savg return; 1200210425Savg } 1201210425Savg } 1202210425Savg#endif 1203178479Sjb /* 1204178479Sjb * Iterate over the section headers locating various sections of 1205178479Sjb * interest and use their attributes to flesh out the dt_module_t. 1206178479Sjb */ 1207178479Sjb for (sp = NULL; (sp = elf_nextscn(dmp->dm_elf, sp)) != NULL; ) { 1208178479Sjb if (gelf_getshdr(sp, &sh) == NULL || sh.sh_type == SHT_NULL || 1209178479Sjb (s = elf_strptr(dmp->dm_elf, shstrs, sh.sh_name)) == NULL) 1210178479Sjb continue; /* skip any malformed sections */ 1211210425Savg#if defined(__FreeBSD__) 1212210425Savg if (sh.sh_size == 0) 1213210425Savg continue; 1214276265Smarkj if (sh.sh_type == SHT_PROGBITS || sh.sh_type == SHT_NOBITS) { 1215210425Savg alignmask = sh.sh_addralign - 1; 1216210425Savg mapbase += alignmask; 1217210425Savg mapbase &= ~alignmask; 1218210425Savg sh.sh_addr = mapbase; 1219276265Smarkj if (is_elf_obj) 1220276265Smarkj dmp->dm_sec_offsets[elf_ndxscn(sp)] = sh.sh_addr; 1221210425Savg mapbase += sh.sh_size; 1222210425Savg } 1223210425Savg#endif 1224178479Sjb if (strcmp(s, ".text") == 0) { 1225178479Sjb dmp->dm_text_size = sh.sh_size; 1226178479Sjb dmp->dm_text_va = sh.sh_addr; 1227178479Sjb } else if (strcmp(s, ".data") == 0) { 1228178479Sjb dmp->dm_data_size = sh.sh_size; 1229178479Sjb dmp->dm_data_va = sh.sh_addr; 1230178479Sjb } else if (strcmp(s, ".bss") == 0) { 1231178479Sjb dmp->dm_bss_size = sh.sh_size; 1232178479Sjb dmp->dm_bss_va = sh.sh_addr; 1233178479Sjb } else if (strcmp(s, ".info") == 0 && 1234178479Sjb (dp = elf_getdata(sp, NULL)) != NULL) { 1235178479Sjb bcopy(dp->d_buf, &dmp->dm_info, 1236178479Sjb MIN(sh.sh_size, sizeof (dmp->dm_info))); 1237178479Sjb } else if (strcmp(s, ".filename") == 0 && 1238178479Sjb (dp = elf_getdata(sp, NULL)) != NULL) { 1239178479Sjb (void) strlcpy(dmp->dm_file, 1240178479Sjb dp->d_buf, sizeof (dmp->dm_file)); 1241178479Sjb } 1242178479Sjb } 1243178479Sjb 1244178479Sjb dmp->dm_flags |= DT_DM_KERNEL; 1245178559Sjb#if defined(sun) 1246178479Sjb dmp->dm_modid = (int)OBJFS_MODID(st.st_ino); 1247178559Sjb#else 1248210425Savg /* 1249210425Savg * Include .rodata and special sections into .text. 1250210425Savg * This depends on default section layout produced by GNU ld 1251210425Savg * for ELF objects and libraries: 1252210425Savg * [Text][R/O data][R/W data][Dynamic][BSS][Non loadable] 1253210425Savg */ 1254210425Savg dmp->dm_text_size = dmp->dm_data_va - dmp->dm_text_va; 1255178559Sjb#if defined(__i386__) 1256178559Sjb /* 1257178559Sjb * Find the first load section and figure out the relocation 1258178559Sjb * offset for the symbols. The kernel module will not need 1259178559Sjb * relocation, but the kernel linker modules will. 1260178559Sjb */ 1261178559Sjb for (i = 0; gelf_getphdr(dmp->dm_elf, i, &ph) != NULL; i++) { 1262178559Sjb if (ph.p_type == PT_LOAD) { 1263178559Sjb dmp->dm_reloc_offset = k_stat->address - ph.p_vaddr; 1264178559Sjb break; 1265178559Sjb } 1266178559Sjb } 1267178559Sjb#endif 1268178559Sjb#endif 1269178479Sjb 1270178479Sjb if (dmp->dm_info.objfs_info_primary) 1271178479Sjb dmp->dm_flags |= DT_DM_PRIMARY; 1272178479Sjb 1273178479Sjb dt_dprintf("opened %d-bit module %s (%s) [%d]\n", 1274178479Sjb bits, dmp->dm_name, dmp->dm_file, dmp->dm_modid); 1275178479Sjb} 1276178479Sjb 1277178479Sjb/* 1278178479Sjb * Unload all the loaded modules and then refresh the module cache with the 1279178479Sjb * latest list of loaded modules and their address ranges. 1280178479Sjb */ 1281178479Sjbvoid 1282178479Sjbdtrace_update(dtrace_hdl_t *dtp) 1283178479Sjb{ 1284178479Sjb dt_module_t *dmp; 1285178479Sjb DIR *dirp; 1286178559Sjb#if defined(__FreeBSD__) 1287178559Sjb int fileid; 1288178559Sjb#endif 1289178479Sjb 1290178479Sjb for (dmp = dt_list_next(&dtp->dt_modlist); 1291178479Sjb dmp != NULL; dmp = dt_list_next(dmp)) 1292178479Sjb dt_module_unload(dtp, dmp); 1293178479Sjb 1294178559Sjb#if defined(sun) 1295178479Sjb /* 1296178479Sjb * Open /system/object and attempt to create a libdtrace module for 1297178479Sjb * each kernel module that is loaded on the current system. 1298178479Sjb */ 1299178479Sjb if (!(dtp->dt_oflags & DTRACE_O_NOSYS) && 1300178479Sjb (dirp = opendir(OBJFS_ROOT)) != NULL) { 1301178479Sjb struct dirent *dp; 1302178479Sjb 1303178479Sjb while ((dp = readdir(dirp)) != NULL) { 1304178479Sjb if (dp->d_name[0] != '.') 1305178479Sjb dt_module_update(dtp, dp->d_name); 1306178479Sjb } 1307178479Sjb 1308178479Sjb (void) closedir(dirp); 1309178479Sjb } 1310178559Sjb#elif defined(__FreeBSD__) 1311178559Sjb /* 1312178559Sjb * Use FreeBSD's kernel loader interface to discover what kernel 1313178559Sjb * modules are loaded and create a libdtrace module for each one. 1314178559Sjb */ 1315178559Sjb for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) { 1316178559Sjb struct kld_file_stat k_stat; 1317178559Sjb k_stat.version = sizeof(k_stat); 1318178559Sjb if (kldstat(fileid, &k_stat) == 0) 1319178559Sjb dt_module_update(dtp, &k_stat); 1320178559Sjb } 1321178559Sjb#endif 1322178479Sjb 1323178479Sjb /* 1324178479Sjb * Look up all the macro identifiers and set di_id to the latest value. 1325178479Sjb * This code collaborates with dt_lex.l on the use of di_id. We will 1326178479Sjb * need to implement something fancier if we need to support non-ints. 1327178479Sjb */ 1328178479Sjb dt_idhash_lookup(dtp->dt_macros, "egid")->di_id = getegid(); 1329178479Sjb dt_idhash_lookup(dtp->dt_macros, "euid")->di_id = geteuid(); 1330178479Sjb dt_idhash_lookup(dtp->dt_macros, "gid")->di_id = getgid(); 1331178479Sjb dt_idhash_lookup(dtp->dt_macros, "pid")->di_id = getpid(); 1332178479Sjb dt_idhash_lookup(dtp->dt_macros, "pgid")->di_id = getpgid(0); 1333178479Sjb dt_idhash_lookup(dtp->dt_macros, "ppid")->di_id = getppid(); 1334178559Sjb#if defined(sun) 1335178479Sjb dt_idhash_lookup(dtp->dt_macros, "projid")->di_id = getprojid(); 1336178559Sjb#endif 1337178479Sjb dt_idhash_lookup(dtp->dt_macros, "sid")->di_id = getsid(0); 1338178559Sjb#if defined(sun) 1339178479Sjb dt_idhash_lookup(dtp->dt_macros, "taskid")->di_id = gettaskid(); 1340178559Sjb#endif 1341178479Sjb dt_idhash_lookup(dtp->dt_macros, "uid")->di_id = getuid(); 1342178479Sjb 1343178479Sjb /* 1344178479Sjb * Cache the pointers to the modules representing the base executable 1345178479Sjb * and the run-time linker in the dtrace client handle. Note that on 1346178479Sjb * x86 krtld is folded into unix, so if we don't find it, use unix 1347178479Sjb * instead. 1348178479Sjb */ 1349178479Sjb dtp->dt_exec = dt_module_lookup_by_name(dtp, "genunix"); 1350178479Sjb dtp->dt_rtld = dt_module_lookup_by_name(dtp, "krtld"); 1351178479Sjb if (dtp->dt_rtld == NULL) 1352178479Sjb dtp->dt_rtld = dt_module_lookup_by_name(dtp, "unix"); 1353178479Sjb 1354178479Sjb /* 1355178479Sjb * If this is the first time we are initializing the module list, 1356178479Sjb * remove the module for genunix from the module list and then move it 1357178479Sjb * to the front of the module list. We do this so that type and symbol 1358178479Sjb * queries encounter genunix and thereby optimize for the common case 1359178479Sjb * in dtrace_lookup_by_name() and dtrace_lookup_by_type(), below. 1360178479Sjb */ 1361178479Sjb if (dtp->dt_exec != NULL && 1362178479Sjb dtp->dt_cdefs == NULL && dtp->dt_ddefs == NULL) { 1363178479Sjb dt_list_delete(&dtp->dt_modlist, dtp->dt_exec); 1364178479Sjb dt_list_prepend(&dtp->dt_modlist, dtp->dt_exec); 1365178479Sjb } 1366178479Sjb} 1367178479Sjb 1368178479Sjbstatic dt_module_t * 1369178479Sjbdt_module_from_object(dtrace_hdl_t *dtp, const char *object) 1370178479Sjb{ 1371178479Sjb int err = EDT_NOMOD; 1372178479Sjb dt_module_t *dmp; 1373178479Sjb 1374178479Sjb switch ((uintptr_t)object) { 1375178479Sjb case (uintptr_t)DTRACE_OBJ_EXEC: 1376178479Sjb dmp = dtp->dt_exec; 1377178479Sjb break; 1378178479Sjb case (uintptr_t)DTRACE_OBJ_RTLD: 1379178479Sjb dmp = dtp->dt_rtld; 1380178479Sjb break; 1381178479Sjb case (uintptr_t)DTRACE_OBJ_CDEFS: 1382178479Sjb dmp = dtp->dt_cdefs; 1383178479Sjb break; 1384178479Sjb case (uintptr_t)DTRACE_OBJ_DDEFS: 1385178479Sjb dmp = dtp->dt_ddefs; 1386178479Sjb break; 1387178479Sjb default: 1388178479Sjb dmp = dt_module_create(dtp, object); 1389178479Sjb err = EDT_NOMEM; 1390178479Sjb } 1391178479Sjb 1392178479Sjb if (dmp == NULL) 1393178479Sjb (void) dt_set_errno(dtp, err); 1394178479Sjb 1395178479Sjb return (dmp); 1396178479Sjb} 1397178479Sjb 1398178479Sjb/* 1399178479Sjb * Exported interface to look up a symbol by name. We return the GElf_Sym and 1400178479Sjb * complete symbol information for the matching symbol. 1401178479Sjb */ 1402178479Sjbint 1403178479Sjbdtrace_lookup_by_name(dtrace_hdl_t *dtp, const char *object, const char *name, 1404178479Sjb GElf_Sym *symp, dtrace_syminfo_t *sip) 1405178479Sjb{ 1406178479Sjb dt_module_t *dmp; 1407178479Sjb dt_ident_t *idp; 1408178479Sjb uint_t n, id; 1409178479Sjb GElf_Sym sym; 1410178479Sjb 1411178479Sjb uint_t mask = 0; /* mask of dt_module flags to match */ 1412178479Sjb uint_t bits = 0; /* flag bits that must be present */ 1413178479Sjb 1414178479Sjb if (object != DTRACE_OBJ_EVERY && 1415178479Sjb object != DTRACE_OBJ_KMODS && 1416178479Sjb object != DTRACE_OBJ_UMODS) { 1417178479Sjb if ((dmp = dt_module_from_object(dtp, object)) == NULL) 1418178479Sjb return (-1); /* dt_errno is set for us */ 1419178479Sjb 1420178479Sjb if (dt_module_load(dtp, dmp) == -1) 1421178479Sjb return (-1); /* dt_errno is set for us */ 1422178479Sjb n = 1; 1423178479Sjb 1424178479Sjb } else { 1425178479Sjb if (object == DTRACE_OBJ_KMODS) 1426178479Sjb mask = bits = DT_DM_KERNEL; 1427178479Sjb else if (object == DTRACE_OBJ_UMODS) 1428178479Sjb mask = DT_DM_KERNEL; 1429178479Sjb 1430178479Sjb dmp = dt_list_next(&dtp->dt_modlist); 1431178479Sjb n = dtp->dt_nmods; 1432178479Sjb } 1433178479Sjb 1434178479Sjb if (symp == NULL) 1435178479Sjb symp = &sym; 1436178479Sjb 1437178479Sjb for (; n > 0; n--, dmp = dt_list_next(dmp)) { 1438178479Sjb if ((dmp->dm_flags & mask) != bits) 1439178479Sjb continue; /* failed to match required attributes */ 1440178479Sjb 1441178479Sjb if (dt_module_load(dtp, dmp) == -1) 1442178479Sjb continue; /* failed to load symbol table */ 1443178479Sjb 1444178479Sjb if (dmp->dm_ops->do_symname(dmp, name, symp, &id) != NULL) { 1445178479Sjb if (sip != NULL) { 1446178479Sjb sip->dts_object = dmp->dm_name; 1447178479Sjb sip->dts_name = (const char *) 1448178479Sjb dmp->dm_strtab.cts_data + symp->st_name; 1449178479Sjb sip->dts_id = id; 1450178479Sjb } 1451178479Sjb return (0); 1452178479Sjb } 1453178479Sjb 1454178479Sjb if (dmp->dm_extern != NULL && 1455178479Sjb (idp = dt_idhash_lookup(dmp->dm_extern, name)) != NULL) { 1456178479Sjb if (symp != &sym) { 1457178479Sjb symp->st_name = (uintptr_t)idp->di_name; 1458178479Sjb symp->st_info = 1459178479Sjb GELF_ST_INFO(STB_GLOBAL, STT_NOTYPE); 1460178479Sjb symp->st_other = 0; 1461178479Sjb symp->st_shndx = SHN_UNDEF; 1462178479Sjb symp->st_value = 0; 1463178479Sjb symp->st_size = 1464178479Sjb ctf_type_size(idp->di_ctfp, idp->di_type); 1465178479Sjb } 1466178479Sjb 1467178479Sjb if (sip != NULL) { 1468178479Sjb sip->dts_object = dmp->dm_name; 1469178479Sjb sip->dts_name = idp->di_name; 1470178479Sjb sip->dts_id = idp->di_id; 1471178479Sjb } 1472178479Sjb 1473178479Sjb return (0); 1474178479Sjb } 1475178479Sjb } 1476178479Sjb 1477178479Sjb return (dt_set_errno(dtp, EDT_NOSYM)); 1478178479Sjb} 1479178479Sjb 1480178479Sjb/* 1481178479Sjb * Exported interface to look up a symbol by address. We return the GElf_Sym 1482178479Sjb * and complete symbol information for the matching symbol. 1483178479Sjb */ 1484178479Sjbint 1485178479Sjbdtrace_lookup_by_addr(dtrace_hdl_t *dtp, GElf_Addr addr, 1486178479Sjb GElf_Sym *symp, dtrace_syminfo_t *sip) 1487178479Sjb{ 1488178479Sjb dt_module_t *dmp; 1489178479Sjb uint_t id; 1490178479Sjb const dtrace_vector_t *v = dtp->dt_vector; 1491178479Sjb 1492178479Sjb if (v != NULL) 1493178479Sjb return (v->dtv_lookup_by_addr(dtp->dt_varg, addr, symp, sip)); 1494178479Sjb 1495178479Sjb for (dmp = dt_list_next(&dtp->dt_modlist); dmp != NULL; 1496178479Sjb dmp = dt_list_next(dmp)) { 1497178479Sjb if (addr - dmp->dm_text_va < dmp->dm_text_size || 1498178479Sjb addr - dmp->dm_data_va < dmp->dm_data_size || 1499178479Sjb addr - dmp->dm_bss_va < dmp->dm_bss_size) 1500178479Sjb break; 1501178479Sjb } 1502178479Sjb 1503178479Sjb if (dmp == NULL) 1504178479Sjb return (dt_set_errno(dtp, EDT_NOSYMADDR)); 1505178479Sjb 1506178479Sjb if (dt_module_load(dtp, dmp) == -1) 1507178479Sjb return (-1); /* dt_errno is set for us */ 1508178479Sjb 1509178479Sjb if (symp != NULL) { 1510178479Sjb if (dmp->dm_ops->do_symaddr(dmp, addr, symp, &id) == NULL) 1511178479Sjb return (dt_set_errno(dtp, EDT_NOSYMADDR)); 1512178479Sjb } 1513178479Sjb 1514178479Sjb if (sip != NULL) { 1515178479Sjb sip->dts_object = dmp->dm_name; 1516178479Sjb 1517178479Sjb if (symp != NULL) { 1518178479Sjb sip->dts_name = (const char *) 1519178479Sjb dmp->dm_strtab.cts_data + symp->st_name; 1520178479Sjb sip->dts_id = id; 1521178479Sjb } else { 1522178479Sjb sip->dts_name = NULL; 1523178479Sjb sip->dts_id = 0; 1524178479Sjb } 1525178479Sjb } 1526178479Sjb 1527178479Sjb return (0); 1528178479Sjb} 1529178479Sjb 1530178479Sjbint 1531178479Sjbdtrace_lookup_by_type(dtrace_hdl_t *dtp, const char *object, const char *name, 1532178479Sjb dtrace_typeinfo_t *tip) 1533178479Sjb{ 1534178479Sjb dtrace_typeinfo_t ti; 1535178479Sjb dt_module_t *dmp; 1536178479Sjb int found = 0; 1537178479Sjb ctf_id_t id; 1538268578Srpaulo uint_t n, i; 1539178479Sjb int justone; 1540268578Srpaulo ctf_file_t *fp; 1541268578Srpaulo char *buf, *p, *q; 1542178479Sjb 1543178479Sjb uint_t mask = 0; /* mask of dt_module flags to match */ 1544178479Sjb uint_t bits = 0; /* flag bits that must be present */ 1545178479Sjb 1546178479Sjb if (object != DTRACE_OBJ_EVERY && 1547178479Sjb object != DTRACE_OBJ_KMODS && 1548178479Sjb object != DTRACE_OBJ_UMODS) { 1549178479Sjb if ((dmp = dt_module_from_object(dtp, object)) == NULL) 1550178479Sjb return (-1); /* dt_errno is set for us */ 1551178479Sjb 1552178479Sjb if (dt_module_load(dtp, dmp) == -1) 1553178479Sjb return (-1); /* dt_errno is set for us */ 1554178479Sjb n = 1; 1555178479Sjb justone = 1; 1556178479Sjb } else { 1557178479Sjb if (object == DTRACE_OBJ_KMODS) 1558178479Sjb mask = bits = DT_DM_KERNEL; 1559178479Sjb else if (object == DTRACE_OBJ_UMODS) 1560178479Sjb mask = DT_DM_KERNEL; 1561178479Sjb 1562178479Sjb dmp = dt_list_next(&dtp->dt_modlist); 1563178479Sjb n = dtp->dt_nmods; 1564178479Sjb justone = 0; 1565178479Sjb } 1566178479Sjb 1567178479Sjb if (tip == NULL) 1568178479Sjb tip = &ti; 1569178479Sjb 1570178479Sjb for (; n > 0; n--, dmp = dt_list_next(dmp)) { 1571178479Sjb if ((dmp->dm_flags & mask) != bits) 1572178479Sjb continue; /* failed to match required attributes */ 1573178479Sjb 1574178479Sjb /* 1575178479Sjb * If we can't load the CTF container, continue on to the next 1576178479Sjb * module. If our search was scoped to only one module then 1577178479Sjb * return immediately leaving dt_errno unmodified. 1578178479Sjb */ 1579268578Srpaulo if (dt_module_hasctf(dtp, dmp) == 0) { 1580178479Sjb if (justone) 1581178479Sjb return (-1); 1582178479Sjb continue; 1583178479Sjb } 1584178479Sjb 1585178479Sjb /* 1586178479Sjb * Look up the type in the module's CTF container. If our 1587178479Sjb * match is a forward declaration tag, save this choice in 1588178479Sjb * 'tip' and keep going in the hope that we will locate the 1589178479Sjb * underlying structure definition. Otherwise just return. 1590178479Sjb */ 1591268578Srpaulo if (dmp->dm_pid == 0) { 1592268578Srpaulo id = ctf_lookup_by_name(dmp->dm_ctfp, name); 1593268578Srpaulo fp = dmp->dm_ctfp; 1594268578Srpaulo } else { 1595268578Srpaulo if ((p = strchr(name, '`')) != NULL) { 1596268578Srpaulo buf = strdup(name); 1597268578Srpaulo if (buf == NULL) 1598268578Srpaulo return (dt_set_errno(dtp, EDT_NOMEM)); 1599268578Srpaulo p = strchr(buf, '`'); 1600268578Srpaulo if ((q = strchr(p + 1, '`')) != NULL) 1601268578Srpaulo p = q; 1602268578Srpaulo *p = '\0'; 1603268578Srpaulo fp = dt_module_getctflib(dtp, dmp, buf); 1604268578Srpaulo if (fp == NULL || (id = ctf_lookup_by_name(fp, 1605268578Srpaulo p + 1)) == CTF_ERR) 1606268578Srpaulo id = CTF_ERR; 1607268578Srpaulo free(buf); 1608268578Srpaulo } else { 1609268578Srpaulo for (i = 0; i < dmp->dm_nctflibs; i++) { 1610268578Srpaulo fp = dmp->dm_libctfp[i]; 1611268578Srpaulo id = ctf_lookup_by_name(fp, name); 1612268578Srpaulo if (id != CTF_ERR) 1613268578Srpaulo break; 1614268578Srpaulo } 1615268578Srpaulo } 1616268578Srpaulo } 1617268578Srpaulo if (id != CTF_ERR) { 1618178479Sjb tip->dtt_object = dmp->dm_name; 1619268578Srpaulo tip->dtt_ctfp = fp; 1620178479Sjb tip->dtt_type = id; 1621268578Srpaulo if (ctf_type_kind(fp, ctf_type_resolve(fp, id)) != 1622268578Srpaulo CTF_K_FORWARD) 1623178479Sjb return (0); 1624178479Sjb 1625178479Sjb found++; 1626178479Sjb } 1627178479Sjb } 1628178479Sjb 1629178479Sjb if (found == 0) 1630178479Sjb return (dt_set_errno(dtp, EDT_NOTYPE)); 1631178479Sjb 1632178479Sjb return (0); 1633178479Sjb} 1634178479Sjb 1635178479Sjbint 1636178479Sjbdtrace_symbol_type(dtrace_hdl_t *dtp, const GElf_Sym *symp, 1637178479Sjb const dtrace_syminfo_t *sip, dtrace_typeinfo_t *tip) 1638178479Sjb{ 1639178479Sjb dt_module_t *dmp; 1640178479Sjb 1641178479Sjb tip->dtt_object = NULL; 1642178479Sjb tip->dtt_ctfp = NULL; 1643178479Sjb tip->dtt_type = CTF_ERR; 1644268578Srpaulo tip->dtt_flags = 0; 1645178479Sjb 1646178479Sjb if ((dmp = dt_module_lookup_by_name(dtp, sip->dts_object)) == NULL) 1647178479Sjb return (dt_set_errno(dtp, EDT_NOMOD)); 1648178479Sjb 1649178479Sjb if (symp->st_shndx == SHN_UNDEF && dmp->dm_extern != NULL) { 1650178479Sjb dt_ident_t *idp = 1651178479Sjb dt_idhash_lookup(dmp->dm_extern, sip->dts_name); 1652178479Sjb 1653178479Sjb if (idp == NULL) 1654178479Sjb return (dt_set_errno(dtp, EDT_NOSYM)); 1655178479Sjb 1656178479Sjb tip->dtt_ctfp = idp->di_ctfp; 1657178479Sjb tip->dtt_type = idp->di_type; 1658178479Sjb 1659178479Sjb } else if (GELF_ST_TYPE(symp->st_info) != STT_FUNC) { 1660178479Sjb if (dt_module_getctf(dtp, dmp) == NULL) 1661178479Sjb return (-1); /* errno is set for us */ 1662178479Sjb 1663178479Sjb tip->dtt_ctfp = dmp->dm_ctfp; 1664178479Sjb tip->dtt_type = ctf_lookup_by_symbol(dmp->dm_ctfp, sip->dts_id); 1665178479Sjb 1666178479Sjb if (tip->dtt_type == CTF_ERR) { 1667178479Sjb dtp->dt_ctferr = ctf_errno(tip->dtt_ctfp); 1668178479Sjb return (dt_set_errno(dtp, EDT_CTF)); 1669178479Sjb } 1670178479Sjb 1671178479Sjb } else { 1672178479Sjb tip->dtt_ctfp = DT_FPTR_CTFP(dtp); 1673178479Sjb tip->dtt_type = DT_FPTR_TYPE(dtp); 1674178479Sjb } 1675178479Sjb 1676178479Sjb tip->dtt_object = dmp->dm_name; 1677178479Sjb return (0); 1678178479Sjb} 1679178479Sjb 1680178479Sjbstatic dtrace_objinfo_t * 1681178479Sjbdt_module_info(const dt_module_t *dmp, dtrace_objinfo_t *dto) 1682178479Sjb{ 1683178479Sjb dto->dto_name = dmp->dm_name; 1684178479Sjb dto->dto_file = dmp->dm_file; 1685178479Sjb dto->dto_id = dmp->dm_modid; 1686178479Sjb dto->dto_flags = 0; 1687178479Sjb 1688178479Sjb if (dmp->dm_flags & DT_DM_KERNEL) 1689178479Sjb dto->dto_flags |= DTRACE_OBJ_F_KERNEL; 1690178479Sjb if (dmp->dm_flags & DT_DM_PRIMARY) 1691178479Sjb dto->dto_flags |= DTRACE_OBJ_F_PRIMARY; 1692178479Sjb 1693178479Sjb dto->dto_text_va = dmp->dm_text_va; 1694178479Sjb dto->dto_text_size = dmp->dm_text_size; 1695178479Sjb dto->dto_data_va = dmp->dm_data_va; 1696178479Sjb dto->dto_data_size = dmp->dm_data_size; 1697178479Sjb dto->dto_bss_va = dmp->dm_bss_va; 1698178479Sjb dto->dto_bss_size = dmp->dm_bss_size; 1699178479Sjb 1700178479Sjb return (dto); 1701178479Sjb} 1702178479Sjb 1703178479Sjbint 1704178479Sjbdtrace_object_iter(dtrace_hdl_t *dtp, dtrace_obj_f *func, void *data) 1705178479Sjb{ 1706178479Sjb const dt_module_t *dmp = dt_list_next(&dtp->dt_modlist); 1707178479Sjb dtrace_objinfo_t dto; 1708178479Sjb int rv; 1709178479Sjb 1710178479Sjb for (; dmp != NULL; dmp = dt_list_next(dmp)) { 1711178479Sjb if ((rv = (*func)(dtp, dt_module_info(dmp, &dto), data)) != 0) 1712178479Sjb return (rv); 1713178479Sjb } 1714178479Sjb 1715178479Sjb return (0); 1716178479Sjb} 1717178479Sjb 1718178479Sjbint 1719178479Sjbdtrace_object_info(dtrace_hdl_t *dtp, const char *object, dtrace_objinfo_t *dto) 1720178479Sjb{ 1721178479Sjb dt_module_t *dmp; 1722178479Sjb 1723178479Sjb if (object == DTRACE_OBJ_EVERY || object == DTRACE_OBJ_KMODS || 1724178479Sjb object == DTRACE_OBJ_UMODS || dto == NULL) 1725178479Sjb return (dt_set_errno(dtp, EINVAL)); 1726178479Sjb 1727178479Sjb if ((dmp = dt_module_from_object(dtp, object)) == NULL) 1728178479Sjb return (-1); /* dt_errno is set for us */ 1729178479Sjb 1730178479Sjb if (dt_module_load(dtp, dmp) == -1) 1731178479Sjb return (-1); /* dt_errno is set for us */ 1732178479Sjb 1733178479Sjb (void) dt_module_info(dmp, dto); 1734178479Sjb return (0); 1735178479Sjb} 1736